monaco-editor11 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/dist/assets/css.worker-C7FogG4G.js +93 -0
  2. package/dist/assets/editor.worker-iXcRX1Tq.js +26 -0
  3. package/dist/assets/html.worker-C8VxctEJ.js +470 -0
  4. package/dist/assets/json.worker-CMC9kgPL.js +58 -0
  5. package/dist/assets/ts.worker-CtTJ3hNN.js +67731 -0
  6. package/dist/index.d.ts +0 -6
  7. package/dist/monaco-editor11.es.js +49 -78
  8. package/dist/monaco-editor11.umd.js +1 -50
  9. package/dist/monaco.d.ts +8 -0
  10. package/dist/workers/common/initialize.js +16 -0
  11. package/dist/workers/common/workers.js +141 -0
  12. package/dist/workers/editor/common/abstractSyntaxTokenBackend.js +128 -0
  13. package/dist/workers/editor/common/abstractText.js +89 -0
  14. package/dist/workers/editor/common/ast.js +485 -0
  15. package/dist/workers/editor/common/autoIndent.js +390 -0
  16. package/dist/workers/editor/common/beforeEditPositionMapper.js +110 -0
  17. package/dist/workers/editor/common/bracketPairsImpl.js +717 -0
  18. package/dist/workers/editor/common/bracketPairsTree.js +343 -0
  19. package/dist/workers/editor/common/brackets.js +108 -0
  20. package/dist/workers/editor/common/characterClassifier.js +59 -0
  21. package/dist/workers/editor/common/characterPair.js +40 -0
  22. package/dist/workers/editor/common/colorizedBracketPairsDecorationProvider.js +97 -0
  23. package/dist/workers/editor/common/columnRange.js +35 -0
  24. package/dist/workers/editor/common/combineTextEditInfos.js +124 -0
  25. package/dist/workers/editor/common/common.js +20 -0
  26. package/dist/workers/editor/common/computeMovedLines.js +249 -0
  27. package/dist/workers/editor/common/concat23Trees.js +192 -0
  28. package/dist/workers/editor/common/contiguousMultilineTokens.js +32 -0
  29. package/dist/workers/editor/common/contiguousMultilineTokensBuilder.js +23 -0
  30. package/dist/workers/editor/common/contiguousTokensEditing.js +128 -0
  31. package/dist/workers/editor/common/contiguousTokensStore.js +207 -0
  32. package/dist/workers/editor/common/coordinatesConverter.js +51 -0
  33. package/dist/workers/editor/common/cursor.js +899 -0
  34. package/dist/workers/editor/common/cursorAtomicMoveOperations.js +145 -0
  35. package/dist/workers/editor/common/cursorCollection.js +194 -0
  36. package/dist/workers/editor/common/cursorColumnSelection.js +93 -0
  37. package/dist/workers/editor/common/cursorColumns.js +112 -0
  38. package/dist/workers/editor/common/cursorCommon.js +250 -0
  39. package/dist/workers/editor/common/cursorContext.js +15 -0
  40. package/dist/workers/editor/common/cursorDeleteOperations.js +231 -0
  41. package/dist/workers/editor/common/cursorMoveCommands.js +676 -0
  42. package/dist/workers/editor/common/cursorMoveOperations.js +290 -0
  43. package/dist/workers/editor/common/cursorTypeEditOperations.js +968 -0
  44. package/dist/workers/editor/common/cursorTypeOperations.js +173 -0
  45. package/dist/workers/editor/common/cursorUtils.js +75 -0
  46. package/dist/workers/editor/common/cursorWordOperations.js +720 -0
  47. package/dist/workers/editor/common/defaultDocumentColorsComputer.js +138 -0
  48. package/dist/workers/editor/common/defaultLinesDiffComputer.js +188 -0
  49. package/dist/workers/editor/common/diffAlgorithm.js +139 -0
  50. package/dist/workers/editor/common/diffEditor.js +38 -0
  51. package/dist/workers/editor/common/dynamicProgrammingDiffing.js +101 -0
  52. package/dist/workers/editor/common/edit.js +183 -0
  53. package/dist/workers/editor/common/editOperation.js +36 -0
  54. package/dist/workers/editor/common/editStack.js +363 -0
  55. package/dist/workers/editor/common/editorAction.js +26 -0
  56. package/dist/workers/editor/common/editorBaseApi.js +43 -0
  57. package/dist/workers/editor/common/editorColorRegistry.js +102 -0
  58. package/dist/workers/editor/common/editorCommon.js +13 -0
  59. package/dist/workers/editor/common/editorConfigurationSchema.js +338 -0
  60. package/dist/workers/editor/common/editorContextKeys.js +84 -0
  61. package/dist/workers/editor/common/editorFeatures.js +17 -0
  62. package/dist/workers/editor/common/editorOptions.js +3440 -0
  63. package/dist/workers/editor/common/editorTheme.js +23 -0
  64. package/dist/workers/editor/common/editorWebWorker.js +299 -0
  65. package/dist/workers/editor/common/editorWorker.js +9 -0
  66. package/dist/workers/editor/common/editorWorkerHost.js +15 -0
  67. package/dist/workers/editor/common/editorZoom.js +26 -0
  68. package/dist/workers/editor/common/electricCharacter.js +55 -0
  69. package/dist/workers/editor/common/encodedTokenAttributes.js +79 -0
  70. package/dist/workers/editor/common/enterAction.js +53 -0
  71. package/dist/workers/editor/common/eolCounter.js +44 -0
  72. package/dist/workers/editor/common/findSectionHeaders.js +128 -0
  73. package/dist/workers/editor/common/fixBrackets.js +67 -0
  74. package/dist/workers/editor/common/fixedArray.js +70 -0
  75. package/dist/workers/editor/common/fontInfo.js +172 -0
  76. package/dist/workers/editor/common/fontInfoFromSettings.js +29 -0
  77. package/dist/workers/editor/common/getIconClasses.js +106 -0
  78. package/dist/workers/editor/common/getPositionOffsetTransformerFromTextModel.js +24 -0
  79. package/dist/workers/editor/common/glyphLanesModel.js +61 -0
  80. package/dist/workers/editor/common/guidesTextModelPart.js +405 -0
  81. package/dist/workers/editor/common/heuristicSequenceOptimizations.js +374 -0
  82. package/dist/workers/editor/common/indentRules.js +63 -0
  83. package/dist/workers/editor/common/indentation.js +39 -0
  84. package/dist/workers/editor/common/indentationGuesser.js +178 -0
  85. package/dist/workers/editor/common/indentationLineProcessor.js +193 -0
  86. package/dist/workers/editor/common/inlineDecorations.js +26 -0
  87. package/dist/workers/editor/common/inplaceReplaceSupport.js +87 -0
  88. package/dist/workers/editor/common/inputMode.js +22 -0
  89. package/dist/workers/editor/common/intervalTree.js +1002 -0
  90. package/dist/workers/editor/common/language.js +9 -0
  91. package/dist/workers/editor/common/languageBracketsConfiguration.js +133 -0
  92. package/dist/workers/editor/common/languageConfiguration.js +138 -0
  93. package/dist/workers/editor/common/languageConfigurationRegistry.js +361 -0
  94. package/dist/workers/editor/common/languageFeatureDebounce.js +137 -0
  95. package/dist/workers/editor/common/languageFeatureRegistry.js +180 -0
  96. package/dist/workers/editor/common/languageFeatures.js +9 -0
  97. package/dist/workers/editor/common/languageFeaturesService.js +47 -0
  98. package/dist/workers/editor/common/languageSelector.js +112 -0
  99. package/dist/workers/editor/common/languageService.js +92 -0
  100. package/dist/workers/editor/common/languages.js +522 -0
  101. package/dist/workers/editor/common/languagesAssociations.js +193 -0
  102. package/dist/workers/editor/common/languagesRegistry.js +237 -0
  103. package/dist/workers/editor/common/legacyLinesDiffComputer.js +468 -0
  104. package/dist/workers/editor/common/length.js +129 -0
  105. package/dist/workers/editor/common/lineDecorations.js +208 -0
  106. package/dist/workers/editor/common/lineEdit.js +75 -0
  107. package/dist/workers/editor/common/lineHeights.js +370 -0
  108. package/dist/workers/editor/common/linePart.js +25 -0
  109. package/dist/workers/editor/common/lineRange.js +312 -0
  110. package/dist/workers/editor/common/lineSequence.js +36 -0
  111. package/dist/workers/editor/common/lineTokens.js +405 -0
  112. package/dist/workers/editor/common/linesDiffComputer.js +29 -0
  113. package/dist/workers/editor/common/linesDiffComputers.js +13 -0
  114. package/dist/workers/editor/common/linesLayout.js +765 -0
  115. package/dist/workers/editor/common/linesSliceCharSequence.js +205 -0
  116. package/dist/workers/editor/common/linkComputer.js +269 -0
  117. package/dist/workers/editor/common/markerDecorations.js +9 -0
  118. package/dist/workers/editor/common/markerDecorationsService.js +248 -0
  119. package/dist/workers/editor/common/minimapTokensColorTracker.js +58 -0
  120. package/dist/workers/editor/common/mirrorTextModel.js +117 -0
  121. package/dist/workers/editor/common/model.js +9 -0
  122. package/dist/workers/editor/common/modelLineProjection.js +350 -0
  123. package/dist/workers/editor/common/modelLineProjectionData.js +297 -0
  124. package/dist/workers/editor/common/modelService.js +413 -0
  125. package/dist/workers/editor/common/modesRegistry.js +75 -0
  126. package/dist/workers/editor/common/monospaceLineBreaksComputer.js +473 -0
  127. package/dist/workers/editor/common/myersDiffAlgorithm.js +159 -0
  128. package/dist/workers/editor/common/nodeReader.js +127 -0
  129. package/dist/workers/editor/common/nullTokenize.js +29 -0
  130. package/dist/workers/editor/common/offsetRange.js +225 -0
  131. package/dist/workers/editor/common/onEnter.js +109 -0
  132. package/dist/workers/editor/common/oneCursor.js +117 -0
  133. package/dist/workers/editor/common/overviewZoneManager.js +176 -0
  134. package/dist/workers/editor/common/parser.js +121 -0
  135. package/dist/workers/editor/common/pieceTreeBase.js +1473 -0
  136. package/dist/workers/editor/common/pieceTreeTextBuffer.js +461 -0
  137. package/dist/workers/editor/common/pieceTreeTextBufferBuilder.js +140 -0
  138. package/dist/workers/editor/common/point.js +50 -0
  139. package/dist/workers/editor/common/position.js +142 -0
  140. package/dist/workers/editor/common/positionToOffset.js +17 -0
  141. package/dist/workers/editor/common/positionToOffsetImpl.js +98 -0
  142. package/dist/workers/editor/common/prefixSumComputer.js +226 -0
  143. package/dist/workers/editor/common/range.js +421 -0
  144. package/dist/workers/editor/common/rangeMapping.js +229 -0
  145. package/dist/workers/editor/common/rangeSingleLine.js +17 -0
  146. package/dist/workers/editor/common/rbTreeBase.js +362 -0
  147. package/dist/workers/editor/common/rect.js +163 -0
  148. package/dist/workers/editor/common/replaceCommand.js +158 -0
  149. package/dist/workers/editor/common/resolverService.js +5 -0
  150. package/dist/workers/editor/common/rgba.js +35 -0
  151. package/dist/workers/editor/common/richEditBrackets.js +356 -0
  152. package/dist/workers/editor/common/selection.js +145 -0
  153. package/dist/workers/editor/common/semanticTokensDto.js +82 -0
  154. package/dist/workers/editor/common/semanticTokensProviderStyling.js +263 -0
  155. package/dist/workers/editor/common/semanticTokensStyling.js +9 -0
  156. package/dist/workers/editor/common/semanticTokensStylingService.js +47 -0
  157. package/dist/workers/editor/common/shiftCommand.js +241 -0
  158. package/dist/workers/editor/common/smallImmutableSet.js +108 -0
  159. package/dist/workers/editor/common/sparseMultilineTokens.js +548 -0
  160. package/dist/workers/editor/common/sparseTokensStore.js +210 -0
  161. package/dist/workers/editor/common/standaloneEnums.js +1017 -0
  162. package/dist/workers/editor/common/standaloneStrings.js +42 -0
  163. package/dist/workers/editor/common/stringBuilder.js +122 -0
  164. package/dist/workers/editor/common/stringEdit.js +165 -0
  165. package/dist/workers/editor/common/supports.js +58 -0
  166. package/dist/workers/editor/common/surroundSelectionCommand.js +44 -0
  167. package/dist/workers/editor/common/textChange.js +248 -0
  168. package/dist/workers/editor/common/textEdit.js +269 -0
  169. package/dist/workers/editor/common/textLength.js +87 -0
  170. package/dist/workers/editor/common/textModel.js +2031 -0
  171. package/dist/workers/editor/common/textModelBracketPairs.js +45 -0
  172. package/dist/workers/editor/common/textModelDefaults.js +18 -0
  173. package/dist/workers/editor/common/textModelEditSource.js +166 -0
  174. package/dist/workers/editor/common/textModelEvents.js +216 -0
  175. package/dist/workers/editor/common/textModelGuides.js +40 -0
  176. package/dist/workers/editor/common/textModelPart.js +23 -0
  177. package/dist/workers/editor/common/textModelSearch.js +455 -0
  178. package/dist/workers/editor/common/textModelStringEdit.js +11 -0
  179. package/dist/workers/editor/common/textModelSync.impl.js +307 -0
  180. package/dist/workers/editor/common/textModelText.js +26 -0
  181. package/dist/workers/editor/common/textModelTokens.js +436 -0
  182. package/dist/workers/editor/common/textResourceConfiguration.js +6 -0
  183. package/dist/workers/editor/common/textToHtmlTokenizer.js +139 -0
  184. package/dist/workers/editor/common/tokenStore.js +407 -0
  185. package/dist/workers/editor/common/tokenWithTextArray.js +73 -0
  186. package/dist/workers/editor/common/tokenization.js +287 -0
  187. package/dist/workers/editor/common/tokenizationRegistry.js +123 -0
  188. package/dist/workers/editor/common/tokenizationTextModelPart.js +275 -0
  189. package/dist/workers/editor/common/tokenizer.js +301 -0
  190. package/dist/workers/editor/common/tokenizerSyntaxTokenBackend.js +261 -0
  191. package/dist/workers/editor/common/treeSitterLibraryService.js +9 -0
  192. package/dist/workers/editor/common/treeSitterSyntaxTokenBackend.js +167 -0
  193. package/dist/workers/editor/common/treeSitterThemeService.js +9 -0
  194. package/dist/workers/editor/common/treeSitterTokenizationImpl.js +713 -0
  195. package/dist/workers/editor/common/treeSitterTree.js +395 -0
  196. package/dist/workers/editor/common/treeViewsDnd.js +24 -0
  197. package/dist/workers/editor/common/treeViewsDndService.js +12 -0
  198. package/dist/workers/editor/common/trimTrailingWhitespaceCommand.js +98 -0
  199. package/dist/workers/editor/common/unicodeTextModelHighlighter.js +188 -0
  200. package/dist/workers/editor/common/utils.js +62 -0
  201. package/dist/workers/editor/common/viewContext.js +22 -0
  202. package/dist/workers/editor/common/viewEventHandler.js +186 -0
  203. package/dist/workers/editor/common/viewEvents.js +180 -0
  204. package/dist/workers/editor/common/viewLayout.js +368 -0
  205. package/dist/workers/editor/common/viewLineRenderer.js +948 -0
  206. package/dist/workers/editor/common/viewLinesViewportData.js +30 -0
  207. package/dist/workers/editor/common/viewModel.js +98 -0
  208. package/dist/workers/editor/common/viewModelDecoration.js +55 -0
  209. package/dist/workers/editor/common/viewModelDecorations.js +132 -0
  210. package/dist/workers/editor/common/viewModelEventDispatcher.js +398 -0
  211. package/dist/workers/editor/common/viewModelImpl.js +1163 -0
  212. package/dist/workers/editor/common/viewModelLines.js +938 -0
  213. package/dist/workers/editor/common/wordCharacterClassifier.js +87 -0
  214. package/dist/workers/editor/common/wordHelper.js +127 -0
  215. package/dist/workers/editor/editor.worker.js +11 -0
  216. package/dist/workers/language/css.worker.js +8 -0
  217. package/dist/workers/language/cssMode.js +198 -0
  218. package/dist/workers/language/cssWorker.js +183 -0
  219. package/dist/workers/language/html.worker.js +8 -0
  220. package/dist/workers/language/htmlMode.js +213 -0
  221. package/dist/workers/language/htmlWorker.js +126 -0
  222. package/dist/workers/language/json.worker.js +8 -0
  223. package/dist/workers/language/jsonMode.js +224 -0
  224. package/dist/workers/language/jsonWorker.js +187 -0
  225. package/dist/workers/language/languageFeatures.js +1009 -0
  226. package/dist/workers/language/lib.index.js +103 -0
  227. package/dist/workers/language/lib.js +1107 -0
  228. package/dist/workers/language/lspLanguageFeatures.js +716 -0
  229. package/dist/workers/language/monaco.contribution.js +144 -0
  230. package/dist/workers/language/tokenization.js +189 -0
  231. package/dist/workers/language/ts.worker.js +14 -0
  232. package/dist/workers/language/tsMode.js +212 -0
  233. package/dist/workers/language/tsWorker.js +352 -0
  234. package/dist/workers/language/typescriptServices.js +210154 -0
  235. package/dist/workers/language/typescriptServicesMetadata.js +3 -0
  236. package/dist/workers/language/workerManager.js +65 -0
  237. package/package.json +3 -2
@@ -0,0 +1,1473 @@
1
+ import { Position } from '../../core/position.js';
2
+ import { Range } from '../../core/range.js';
3
+ import { FindMatch } from '../../model.js';
4
+ import { SENTINEL, rbDelete, updateTreeMetadata, TreeNode, leftest, fixInsert, righttest } from './rbTreeBase.js';
5
+ import { createFindMatch, Searcher, isValidMatch } from '../textModelSearch.js';
6
+
7
+ /*---------------------------------------------------------------------------------------------
8
+ * Copyright (c) Microsoft Corporation. All rights reserved.
9
+ * Licensed under the MIT License. See License.txt in the project root for license information.
10
+ *--------------------------------------------------------------------------------------------*/
11
+ // const lfRegex = new RegExp(/\r\n|\r|\n/g);
12
+ const AverageBufferSize = 65535;
13
+ function createUintArray(arr) {
14
+ let r;
15
+ if (arr[arr.length - 1] < 65536) {
16
+ r = new Uint16Array(arr.length);
17
+ }
18
+ else {
19
+ r = new Uint32Array(arr.length);
20
+ }
21
+ r.set(arr, 0);
22
+ return r;
23
+ }
24
+ class LineStarts {
25
+ constructor(lineStarts, cr, lf, crlf, isBasicASCII) {
26
+ this.lineStarts = lineStarts;
27
+ this.cr = cr;
28
+ this.lf = lf;
29
+ this.crlf = crlf;
30
+ this.isBasicASCII = isBasicASCII;
31
+ }
32
+ }
33
+ function createLineStartsFast(str, readonly = true) {
34
+ const r = [0];
35
+ let rLength = 1;
36
+ for (let i = 0, len = str.length; i < len; i++) {
37
+ const chr = str.charCodeAt(i);
38
+ if (chr === 13 /* CharCode.CarriageReturn */) {
39
+ if (i + 1 < len && str.charCodeAt(i + 1) === 10 /* CharCode.LineFeed */) {
40
+ // \r\n... case
41
+ r[rLength++] = i + 2;
42
+ i++; // skip \n
43
+ }
44
+ else {
45
+ // \r... case
46
+ r[rLength++] = i + 1;
47
+ }
48
+ }
49
+ else if (chr === 10 /* CharCode.LineFeed */) {
50
+ r[rLength++] = i + 1;
51
+ }
52
+ }
53
+ if (readonly) {
54
+ return createUintArray(r);
55
+ }
56
+ else {
57
+ return r;
58
+ }
59
+ }
60
+ function createLineStarts(r, str) {
61
+ r.length = 0;
62
+ r[0] = 0;
63
+ let rLength = 1;
64
+ let cr = 0, lf = 0, crlf = 0;
65
+ let isBasicASCII = true;
66
+ for (let i = 0, len = str.length; i < len; i++) {
67
+ const chr = str.charCodeAt(i);
68
+ if (chr === 13 /* CharCode.CarriageReturn */) {
69
+ if (i + 1 < len && str.charCodeAt(i + 1) === 10 /* CharCode.LineFeed */) {
70
+ // \r\n... case
71
+ crlf++;
72
+ r[rLength++] = i + 2;
73
+ i++; // skip \n
74
+ }
75
+ else {
76
+ cr++;
77
+ // \r... case
78
+ r[rLength++] = i + 1;
79
+ }
80
+ }
81
+ else if (chr === 10 /* CharCode.LineFeed */) {
82
+ lf++;
83
+ r[rLength++] = i + 1;
84
+ }
85
+ else {
86
+ if (isBasicASCII) {
87
+ if (chr !== 9 /* CharCode.Tab */ && (chr < 32 || chr > 126)) {
88
+ isBasicASCII = false;
89
+ }
90
+ }
91
+ }
92
+ }
93
+ const result = new LineStarts(createUintArray(r), cr, lf, crlf, isBasicASCII);
94
+ r.length = 0;
95
+ return result;
96
+ }
97
+ class Piece {
98
+ constructor(bufferIndex, start, end, lineFeedCnt, length) {
99
+ this.bufferIndex = bufferIndex;
100
+ this.start = start;
101
+ this.end = end;
102
+ this.lineFeedCnt = lineFeedCnt;
103
+ this.length = length;
104
+ }
105
+ }
106
+ class StringBuffer {
107
+ constructor(buffer, lineStarts) {
108
+ this.buffer = buffer;
109
+ this.lineStarts = lineStarts;
110
+ }
111
+ }
112
+ /**
113
+ * Readonly snapshot for piece tree.
114
+ * In a real multiple thread environment, to make snapshot reading always work correctly, we need to
115
+ * 1. Make TreeNode.piece immutable, then reading and writing can run in parallel.
116
+ * 2. TreeNode/Buffers normalization should not happen during snapshot reading.
117
+ */
118
+ class PieceTreeSnapshot {
119
+ constructor(tree, BOM) {
120
+ this._pieces = [];
121
+ this._tree = tree;
122
+ this._BOM = BOM;
123
+ this._index = 0;
124
+ if (tree.root !== SENTINEL) {
125
+ tree.iterate(tree.root, node => {
126
+ if (node !== SENTINEL) {
127
+ this._pieces.push(node.piece);
128
+ }
129
+ return true;
130
+ });
131
+ }
132
+ }
133
+ read() {
134
+ if (this._pieces.length === 0) {
135
+ if (this._index === 0) {
136
+ this._index++;
137
+ return this._BOM;
138
+ }
139
+ else {
140
+ return null;
141
+ }
142
+ }
143
+ if (this._index > this._pieces.length - 1) {
144
+ return null;
145
+ }
146
+ if (this._index === 0) {
147
+ return this._BOM + this._tree.getPieceContent(this._pieces[this._index++]);
148
+ }
149
+ return this._tree.getPieceContent(this._pieces[this._index++]);
150
+ }
151
+ }
152
+ class PieceTreeSearchCache {
153
+ constructor(limit) {
154
+ this._limit = limit;
155
+ this._cache = [];
156
+ }
157
+ get(offset) {
158
+ for (let i = this._cache.length - 1; i >= 0; i--) {
159
+ const nodePos = this._cache[i];
160
+ if (nodePos.nodeStartOffset <= offset && nodePos.nodeStartOffset + nodePos.node.piece.length >= offset) {
161
+ return nodePos;
162
+ }
163
+ }
164
+ return null;
165
+ }
166
+ get2(lineNumber) {
167
+ for (let i = this._cache.length - 1; i >= 0; i--) {
168
+ const nodePos = this._cache[i];
169
+ if (nodePos.nodeStartLineNumber && nodePos.nodeStartLineNumber < lineNumber && nodePos.nodeStartLineNumber + nodePos.node.piece.lineFeedCnt >= lineNumber) {
170
+ return nodePos;
171
+ }
172
+ }
173
+ return null;
174
+ }
175
+ set(nodePosition) {
176
+ if (this._cache.length >= this._limit) {
177
+ this._cache.shift();
178
+ }
179
+ this._cache.push(nodePosition);
180
+ }
181
+ validate(offset) {
182
+ let hasInvalidVal = false;
183
+ const tmp = this._cache;
184
+ for (let i = 0; i < tmp.length; i++) {
185
+ const nodePos = tmp[i];
186
+ if (nodePos.node.parent === null || nodePos.nodeStartOffset >= offset) {
187
+ tmp[i] = null;
188
+ hasInvalidVal = true;
189
+ continue;
190
+ }
191
+ }
192
+ if (hasInvalidVal) {
193
+ const newArr = [];
194
+ for (const entry of tmp) {
195
+ if (entry !== null) {
196
+ newArr.push(entry);
197
+ }
198
+ }
199
+ this._cache = newArr;
200
+ }
201
+ }
202
+ }
203
+ class PieceTreeBase {
204
+ constructor(chunks, eol, eolNormalized) {
205
+ this.create(chunks, eol, eolNormalized);
206
+ }
207
+ create(chunks, eol, eolNormalized) {
208
+ this._buffers = [
209
+ new StringBuffer('', [0])
210
+ ];
211
+ this._lastChangeBufferPos = { line: 0, column: 0 };
212
+ this.root = SENTINEL;
213
+ this._lineCnt = 1;
214
+ this._length = 0;
215
+ this._EOL = eol;
216
+ this._EOLLength = eol.length;
217
+ this._EOLNormalized = eolNormalized;
218
+ let lastNode = null;
219
+ for (let i = 0, len = chunks.length; i < len; i++) {
220
+ if (chunks[i].buffer.length > 0) {
221
+ if (!chunks[i].lineStarts) {
222
+ chunks[i].lineStarts = createLineStartsFast(chunks[i].buffer);
223
+ }
224
+ const piece = new Piece(i + 1, { line: 0, column: 0 }, { line: chunks[i].lineStarts.length - 1, column: chunks[i].buffer.length - chunks[i].lineStarts[chunks[i].lineStarts.length - 1] }, chunks[i].lineStarts.length - 1, chunks[i].buffer.length);
225
+ this._buffers.push(chunks[i]);
226
+ lastNode = this.rbInsertRight(lastNode, piece);
227
+ }
228
+ }
229
+ this._searchCache = new PieceTreeSearchCache(1);
230
+ this._lastVisitedLine = { lineNumber: 0, value: '' };
231
+ this.computeBufferMetadata();
232
+ }
233
+ normalizeEOL(eol) {
234
+ const averageBufferSize = AverageBufferSize;
235
+ const min = averageBufferSize - Math.floor(averageBufferSize / 3);
236
+ const max = min * 2;
237
+ let tempChunk = '';
238
+ let tempChunkLen = 0;
239
+ const chunks = [];
240
+ this.iterate(this.root, node => {
241
+ const str = this.getNodeContent(node);
242
+ const len = str.length;
243
+ if (tempChunkLen <= min || tempChunkLen + len < max) {
244
+ tempChunk += str;
245
+ tempChunkLen += len;
246
+ return true;
247
+ }
248
+ // flush anyways
249
+ const text = tempChunk.replace(/\r\n|\r|\n/g, eol);
250
+ chunks.push(new StringBuffer(text, createLineStartsFast(text)));
251
+ tempChunk = str;
252
+ tempChunkLen = len;
253
+ return true;
254
+ });
255
+ if (tempChunkLen > 0) {
256
+ const text = tempChunk.replace(/\r\n|\r|\n/g, eol);
257
+ chunks.push(new StringBuffer(text, createLineStartsFast(text)));
258
+ }
259
+ this.create(chunks, eol, true);
260
+ }
261
+ // #region Buffer API
262
+ getEOL() {
263
+ return this._EOL;
264
+ }
265
+ setEOL(newEOL) {
266
+ this._EOL = newEOL;
267
+ this._EOLLength = this._EOL.length;
268
+ this.normalizeEOL(newEOL);
269
+ }
270
+ createSnapshot(BOM) {
271
+ return new PieceTreeSnapshot(this, BOM);
272
+ }
273
+ getOffsetAt(lineNumber, column) {
274
+ let leftLen = 0; // inorder
275
+ let x = this.root;
276
+ while (x !== SENTINEL) {
277
+ if (x.left !== SENTINEL && x.lf_left + 1 >= lineNumber) {
278
+ x = x.left;
279
+ }
280
+ else if (x.lf_left + x.piece.lineFeedCnt + 1 >= lineNumber) {
281
+ leftLen += x.size_left;
282
+ // lineNumber >= 2
283
+ const accumualtedValInCurrentIndex = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
284
+ return leftLen += accumualtedValInCurrentIndex + column - 1;
285
+ }
286
+ else {
287
+ lineNumber -= x.lf_left + x.piece.lineFeedCnt;
288
+ leftLen += x.size_left + x.piece.length;
289
+ x = x.right;
290
+ }
291
+ }
292
+ return leftLen;
293
+ }
294
+ getPositionAt(offset) {
295
+ offset = Math.floor(offset);
296
+ offset = Math.max(0, offset);
297
+ let x = this.root;
298
+ let lfCnt = 0;
299
+ const originalOffset = offset;
300
+ while (x !== SENTINEL) {
301
+ if (x.size_left !== 0 && x.size_left >= offset) {
302
+ x = x.left;
303
+ }
304
+ else if (x.size_left + x.piece.length >= offset) {
305
+ const out = this.getIndexOf(x, offset - x.size_left);
306
+ lfCnt += x.lf_left + out.index;
307
+ if (out.index === 0) {
308
+ const lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);
309
+ const column = originalOffset - lineStartOffset;
310
+ return new Position(lfCnt + 1, column + 1);
311
+ }
312
+ return new Position(lfCnt + 1, out.remainder + 1);
313
+ }
314
+ else {
315
+ offset -= x.size_left + x.piece.length;
316
+ lfCnt += x.lf_left + x.piece.lineFeedCnt;
317
+ if (x.right === SENTINEL) {
318
+ // last node
319
+ const lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);
320
+ const column = originalOffset - offset - lineStartOffset;
321
+ return new Position(lfCnt + 1, column + 1);
322
+ }
323
+ else {
324
+ x = x.right;
325
+ }
326
+ }
327
+ }
328
+ return new Position(1, 1);
329
+ }
330
+ getValueInRange(range, eol) {
331
+ if (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {
332
+ return '';
333
+ }
334
+ const startPosition = this.nodeAt2(range.startLineNumber, range.startColumn);
335
+ const endPosition = this.nodeAt2(range.endLineNumber, range.endColumn);
336
+ const value = this.getValueInRange2(startPosition, endPosition);
337
+ if (eol) {
338
+ if (eol !== this._EOL || !this._EOLNormalized) {
339
+ return value.replace(/\r\n|\r|\n/g, eol);
340
+ }
341
+ if (eol === this.getEOL() && this._EOLNormalized) {
342
+ return value;
343
+ }
344
+ return value.replace(/\r\n|\r|\n/g, eol);
345
+ }
346
+ return value;
347
+ }
348
+ getValueInRange2(startPosition, endPosition) {
349
+ if (startPosition.node === endPosition.node) {
350
+ const node = startPosition.node;
351
+ const buffer = this._buffers[node.piece.bufferIndex].buffer;
352
+ const startOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);
353
+ return buffer.substring(startOffset + startPosition.remainder, startOffset + endPosition.remainder);
354
+ }
355
+ let x = startPosition.node;
356
+ const buffer = this._buffers[x.piece.bufferIndex].buffer;
357
+ const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
358
+ let ret = buffer.substring(startOffset + startPosition.remainder, startOffset + x.piece.length);
359
+ x = x.next();
360
+ while (x !== SENTINEL) {
361
+ const buffer = this._buffers[x.piece.bufferIndex].buffer;
362
+ const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
363
+ if (x === endPosition.node) {
364
+ ret += buffer.substring(startOffset, startOffset + endPosition.remainder);
365
+ break;
366
+ }
367
+ else {
368
+ ret += buffer.substr(startOffset, x.piece.length);
369
+ }
370
+ x = x.next();
371
+ }
372
+ return ret;
373
+ }
374
+ getLinesContent() {
375
+ const lines = [];
376
+ let linesLength = 0;
377
+ let currentLine = '';
378
+ let danglingCR = false;
379
+ this.iterate(this.root, node => {
380
+ if (node === SENTINEL) {
381
+ return true;
382
+ }
383
+ const piece = node.piece;
384
+ let pieceLength = piece.length;
385
+ if (pieceLength === 0) {
386
+ return true;
387
+ }
388
+ const buffer = this._buffers[piece.bufferIndex].buffer;
389
+ const lineStarts = this._buffers[piece.bufferIndex].lineStarts;
390
+ const pieceStartLine = piece.start.line;
391
+ const pieceEndLine = piece.end.line;
392
+ let pieceStartOffset = lineStarts[pieceStartLine] + piece.start.column;
393
+ if (danglingCR) {
394
+ if (buffer.charCodeAt(pieceStartOffset) === 10 /* CharCode.LineFeed */) {
395
+ // pretend the \n was in the previous piece..
396
+ pieceStartOffset++;
397
+ pieceLength--;
398
+ }
399
+ lines[linesLength++] = currentLine;
400
+ currentLine = '';
401
+ danglingCR = false;
402
+ if (pieceLength === 0) {
403
+ return true;
404
+ }
405
+ }
406
+ if (pieceStartLine === pieceEndLine) {
407
+ // this piece has no new lines
408
+ if (!this._EOLNormalized && buffer.charCodeAt(pieceStartOffset + pieceLength - 1) === 13 /* CharCode.CarriageReturn */) {
409
+ danglingCR = true;
410
+ currentLine += buffer.substr(pieceStartOffset, pieceLength - 1);
411
+ }
412
+ else {
413
+ currentLine += buffer.substr(pieceStartOffset, pieceLength);
414
+ }
415
+ return true;
416
+ }
417
+ // add the text before the first line start in this piece
418
+ currentLine += (this._EOLNormalized
419
+ ? buffer.substring(pieceStartOffset, Math.max(pieceStartOffset, lineStarts[pieceStartLine + 1] - this._EOLLength))
420
+ : buffer.substring(pieceStartOffset, lineStarts[pieceStartLine + 1]).replace(/(\r\n|\r|\n)$/, ''));
421
+ lines[linesLength++] = currentLine;
422
+ for (let line = pieceStartLine + 1; line < pieceEndLine; line++) {
423
+ currentLine = (this._EOLNormalized
424
+ ? buffer.substring(lineStarts[line], lineStarts[line + 1] - this._EOLLength)
425
+ : buffer.substring(lineStarts[line], lineStarts[line + 1]).replace(/(\r\n|\r|\n)$/, ''));
426
+ lines[linesLength++] = currentLine;
427
+ }
428
+ if (!this._EOLNormalized && buffer.charCodeAt(lineStarts[pieceEndLine] + piece.end.column - 1) === 13 /* CharCode.CarriageReturn */) {
429
+ danglingCR = true;
430
+ if (piece.end.column === 0) {
431
+ // The last line ended with a \r, let's undo the push, it will be pushed by next iteration
432
+ linesLength--;
433
+ }
434
+ else {
435
+ currentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column - 1);
436
+ }
437
+ }
438
+ else {
439
+ currentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column);
440
+ }
441
+ return true;
442
+ });
443
+ if (danglingCR) {
444
+ lines[linesLength++] = currentLine;
445
+ currentLine = '';
446
+ }
447
+ lines[linesLength++] = currentLine;
448
+ return lines;
449
+ }
450
+ getLength() {
451
+ return this._length;
452
+ }
453
+ getLineCount() {
454
+ return this._lineCnt;
455
+ }
456
+ getLineContent(lineNumber) {
457
+ if (this._lastVisitedLine.lineNumber === lineNumber) {
458
+ return this._lastVisitedLine.value;
459
+ }
460
+ this._lastVisitedLine.lineNumber = lineNumber;
461
+ if (lineNumber === this._lineCnt) {
462
+ this._lastVisitedLine.value = this.getLineRawContent(lineNumber);
463
+ }
464
+ else if (this._EOLNormalized) {
465
+ this._lastVisitedLine.value = this.getLineRawContent(lineNumber, this._EOLLength);
466
+ }
467
+ else {
468
+ this._lastVisitedLine.value = this.getLineRawContent(lineNumber).replace(/(\r\n|\r|\n)$/, '');
469
+ }
470
+ return this._lastVisitedLine.value;
471
+ }
472
+ _getCharCode(nodePos) {
473
+ if (nodePos.remainder === nodePos.node.piece.length) {
474
+ // the char we want to fetch is at the head of next node.
475
+ const matchingNode = nodePos.node.next();
476
+ if (!matchingNode) {
477
+ return 0;
478
+ }
479
+ const buffer = this._buffers[matchingNode.piece.bufferIndex];
480
+ const startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);
481
+ return buffer.buffer.charCodeAt(startOffset);
482
+ }
483
+ else {
484
+ const buffer = this._buffers[nodePos.node.piece.bufferIndex];
485
+ const startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);
486
+ const targetOffset = startOffset + nodePos.remainder;
487
+ return buffer.buffer.charCodeAt(targetOffset);
488
+ }
489
+ }
490
+ getLineCharCode(lineNumber, index) {
491
+ const nodePos = this.nodeAt2(lineNumber, index + 1);
492
+ return this._getCharCode(nodePos);
493
+ }
494
+ getLineLength(lineNumber) {
495
+ if (lineNumber === this.getLineCount()) {
496
+ const startOffset = this.getOffsetAt(lineNumber, 1);
497
+ return this.getLength() - startOffset;
498
+ }
499
+ return this.getOffsetAt(lineNumber + 1, 1) - this.getOffsetAt(lineNumber, 1) - this._EOLLength;
500
+ }
501
+ getNearestChunk(offset) {
502
+ const nodePos = this.nodeAt(offset);
503
+ if (nodePos.remainder === nodePos.node.piece.length) {
504
+ // the offset is at the head of next node.
505
+ const matchingNode = nodePos.node.next();
506
+ if (!matchingNode || matchingNode === SENTINEL) {
507
+ return '';
508
+ }
509
+ const buffer = this._buffers[matchingNode.piece.bufferIndex];
510
+ const startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);
511
+ return buffer.buffer.substring(startOffset, startOffset + matchingNode.piece.length);
512
+ }
513
+ else {
514
+ const buffer = this._buffers[nodePos.node.piece.bufferIndex];
515
+ const startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);
516
+ const targetOffset = startOffset + nodePos.remainder;
517
+ const targetEnd = startOffset + nodePos.node.piece.length;
518
+ return buffer.buffer.substring(targetOffset, targetEnd);
519
+ }
520
+ }
521
+ findMatchesInNode(node, searcher, startLineNumber, startColumn, startCursor, endCursor, searchData, captureMatches, limitResultCount, resultLen, result) {
522
+ const buffer = this._buffers[node.piece.bufferIndex];
523
+ const startOffsetInBuffer = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);
524
+ const start = this.offsetInBuffer(node.piece.bufferIndex, startCursor);
525
+ const end = this.offsetInBuffer(node.piece.bufferIndex, endCursor);
526
+ let m;
527
+ // Reset regex to search from the beginning
528
+ const ret = { line: 0, column: 0 };
529
+ let searchText;
530
+ let offsetInBuffer;
531
+ if (searcher._wordSeparators) {
532
+ searchText = buffer.buffer.substring(start, end);
533
+ offsetInBuffer = (offset) => offset + start;
534
+ searcher.reset(0);
535
+ }
536
+ else {
537
+ searchText = buffer.buffer;
538
+ offsetInBuffer = (offset) => offset;
539
+ searcher.reset(start);
540
+ }
541
+ do {
542
+ m = searcher.next(searchText);
543
+ if (m) {
544
+ if (offsetInBuffer(m.index) >= end) {
545
+ return resultLen;
546
+ }
547
+ this.positionInBuffer(node, offsetInBuffer(m.index) - startOffsetInBuffer, ret);
548
+ const lineFeedCnt = this.getLineFeedCnt(node.piece.bufferIndex, startCursor, ret);
549
+ const retStartColumn = ret.line === startCursor.line ? ret.column - startCursor.column + startColumn : ret.column + 1;
550
+ const retEndColumn = retStartColumn + m[0].length;
551
+ result[resultLen++] = createFindMatch(new Range(startLineNumber + lineFeedCnt, retStartColumn, startLineNumber + lineFeedCnt, retEndColumn), m, captureMatches);
552
+ if (offsetInBuffer(m.index) + m[0].length >= end) {
553
+ return resultLen;
554
+ }
555
+ if (resultLen >= limitResultCount) {
556
+ return resultLen;
557
+ }
558
+ }
559
+ } while (m);
560
+ return resultLen;
561
+ }
562
+ findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount) {
563
+ const result = [];
564
+ let resultLen = 0;
565
+ const searcher = new Searcher(searchData.wordSeparators, searchData.regex);
566
+ let startPosition = this.nodeAt2(searchRange.startLineNumber, searchRange.startColumn);
567
+ if (startPosition === null) {
568
+ return [];
569
+ }
570
+ const endPosition = this.nodeAt2(searchRange.endLineNumber, searchRange.endColumn);
571
+ if (endPosition === null) {
572
+ return [];
573
+ }
574
+ let start = this.positionInBuffer(startPosition.node, startPosition.remainder);
575
+ const end = this.positionInBuffer(endPosition.node, endPosition.remainder);
576
+ if (startPosition.node === endPosition.node) {
577
+ this.findMatchesInNode(startPosition.node, searcher, searchRange.startLineNumber, searchRange.startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);
578
+ return result;
579
+ }
580
+ let startLineNumber = searchRange.startLineNumber;
581
+ let currentNode = startPosition.node;
582
+ while (currentNode !== endPosition.node) {
583
+ const lineBreakCnt = this.getLineFeedCnt(currentNode.piece.bufferIndex, start, currentNode.piece.end);
584
+ if (lineBreakCnt >= 1) {
585
+ // last line break position
586
+ const lineStarts = this._buffers[currentNode.piece.bufferIndex].lineStarts;
587
+ const startOffsetInBuffer = this.offsetInBuffer(currentNode.piece.bufferIndex, currentNode.piece.start);
588
+ const nextLineStartOffset = lineStarts[start.line + lineBreakCnt];
589
+ const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;
590
+ resultLen = this.findMatchesInNode(currentNode, searcher, startLineNumber, startColumn, start, this.positionInBuffer(currentNode, nextLineStartOffset - startOffsetInBuffer), searchData, captureMatches, limitResultCount, resultLen, result);
591
+ if (resultLen >= limitResultCount) {
592
+ return result;
593
+ }
594
+ startLineNumber += lineBreakCnt;
595
+ }
596
+ const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;
597
+ // search for the remaining content
598
+ if (startLineNumber === searchRange.endLineNumber) {
599
+ const text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);
600
+ resultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);
601
+ return result;
602
+ }
603
+ resultLen = this._findMatchesInLine(searchData, searcher, this.getLineContent(startLineNumber).substr(startColumn), startLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);
604
+ if (resultLen >= limitResultCount) {
605
+ return result;
606
+ }
607
+ startLineNumber++;
608
+ startPosition = this.nodeAt2(startLineNumber, 1);
609
+ currentNode = startPosition.node;
610
+ start = this.positionInBuffer(startPosition.node, startPosition.remainder);
611
+ }
612
+ if (startLineNumber === searchRange.endLineNumber) {
613
+ const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;
614
+ const text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);
615
+ resultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);
616
+ return result;
617
+ }
618
+ const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;
619
+ resultLen = this.findMatchesInNode(endPosition.node, searcher, startLineNumber, startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);
620
+ return result;
621
+ }
622
+ _findMatchesInLine(searchData, searcher, text, lineNumber, deltaOffset, resultLen, result, captureMatches, limitResultCount) {
623
+ const wordSeparators = searchData.wordSeparators;
624
+ if (!captureMatches && searchData.simpleSearch) {
625
+ const searchString = searchData.simpleSearch;
626
+ const searchStringLen = searchString.length;
627
+ const textLength = text.length;
628
+ let lastMatchIndex = -searchStringLen;
629
+ while ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {
630
+ if (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {
631
+ result[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);
632
+ if (resultLen >= limitResultCount) {
633
+ return resultLen;
634
+ }
635
+ }
636
+ }
637
+ return resultLen;
638
+ }
639
+ let m;
640
+ // Reset regex to search from the beginning
641
+ searcher.reset(0);
642
+ do {
643
+ m = searcher.next(text);
644
+ if (m) {
645
+ result[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);
646
+ if (resultLen >= limitResultCount) {
647
+ return resultLen;
648
+ }
649
+ }
650
+ } while (m);
651
+ return resultLen;
652
+ }
653
+ // #endregion
654
+ // #region Piece Table
655
+ insert(offset, value, eolNormalized = false) {
656
+ this._EOLNormalized = this._EOLNormalized && eolNormalized;
657
+ this._lastVisitedLine.lineNumber = 0;
658
+ this._lastVisitedLine.value = '';
659
+ if (this.root !== SENTINEL) {
660
+ const { node, remainder, nodeStartOffset } = this.nodeAt(offset);
661
+ const piece = node.piece;
662
+ const bufferIndex = piece.bufferIndex;
663
+ const insertPosInBuffer = this.positionInBuffer(node, remainder);
664
+ if (node.piece.bufferIndex === 0 &&
665
+ piece.end.line === this._lastChangeBufferPos.line &&
666
+ piece.end.column === this._lastChangeBufferPos.column &&
667
+ (nodeStartOffset + piece.length === offset) &&
668
+ value.length < AverageBufferSize) {
669
+ // changed buffer
670
+ this.appendToNode(node, value);
671
+ this.computeBufferMetadata();
672
+ return;
673
+ }
674
+ if (nodeStartOffset === offset) {
675
+ this.insertContentToNodeLeft(value, node);
676
+ this._searchCache.validate(offset);
677
+ }
678
+ else if (nodeStartOffset + node.piece.length > offset) {
679
+ // we are inserting into the middle of a node.
680
+ const nodesToDel = [];
681
+ let newRightPiece = new Piece(piece.bufferIndex, insertPosInBuffer, piece.end, this.getLineFeedCnt(piece.bufferIndex, insertPosInBuffer, piece.end), this.offsetInBuffer(bufferIndex, piece.end) - this.offsetInBuffer(bufferIndex, insertPosInBuffer));
682
+ if (this.shouldCheckCRLF() && this.endWithCR(value)) {
683
+ const headOfRight = this.nodeCharCodeAt(node, remainder);
684
+ if (headOfRight === 10 /** \n */) {
685
+ const newStart = { line: newRightPiece.start.line + 1, column: 0 };
686
+ newRightPiece = new Piece(newRightPiece.bufferIndex, newStart, newRightPiece.end, this.getLineFeedCnt(newRightPiece.bufferIndex, newStart, newRightPiece.end), newRightPiece.length - 1);
687
+ value += '\n';
688
+ }
689
+ }
690
+ // reuse node for content before insertion point.
691
+ if (this.shouldCheckCRLF() && this.startWithLF(value)) {
692
+ const tailOfLeft = this.nodeCharCodeAt(node, remainder - 1);
693
+ if (tailOfLeft === 13 /** \r */) {
694
+ const previousPos = this.positionInBuffer(node, remainder - 1);
695
+ this.deleteNodeTail(node, previousPos);
696
+ value = '\r' + value;
697
+ if (node.piece.length === 0) {
698
+ nodesToDel.push(node);
699
+ }
700
+ }
701
+ else {
702
+ this.deleteNodeTail(node, insertPosInBuffer);
703
+ }
704
+ }
705
+ else {
706
+ this.deleteNodeTail(node, insertPosInBuffer);
707
+ }
708
+ const newPieces = this.createNewPieces(value);
709
+ if (newRightPiece.length > 0) {
710
+ this.rbInsertRight(node, newRightPiece);
711
+ }
712
+ let tmpNode = node;
713
+ for (let k = 0; k < newPieces.length; k++) {
714
+ tmpNode = this.rbInsertRight(tmpNode, newPieces[k]);
715
+ }
716
+ this.deleteNodes(nodesToDel);
717
+ }
718
+ else {
719
+ this.insertContentToNodeRight(value, node);
720
+ }
721
+ }
722
+ else {
723
+ // insert new node
724
+ const pieces = this.createNewPieces(value);
725
+ let node = this.rbInsertLeft(null, pieces[0]);
726
+ for (let k = 1; k < pieces.length; k++) {
727
+ node = this.rbInsertRight(node, pieces[k]);
728
+ }
729
+ }
730
+ // todo, this is too brutal. Total line feed count should be updated the same way as lf_left.
731
+ this.computeBufferMetadata();
732
+ }
733
+ delete(offset, cnt) {
734
+ this._lastVisitedLine.lineNumber = 0;
735
+ this._lastVisitedLine.value = '';
736
+ if (cnt <= 0 || this.root === SENTINEL) {
737
+ return;
738
+ }
739
+ const startPosition = this.nodeAt(offset);
740
+ const endPosition = this.nodeAt(offset + cnt);
741
+ const startNode = startPosition.node;
742
+ const endNode = endPosition.node;
743
+ if (startNode === endNode) {
744
+ const startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);
745
+ const endSplitPosInBuffer = this.positionInBuffer(startNode, endPosition.remainder);
746
+ if (startPosition.nodeStartOffset === offset) {
747
+ if (cnt === startNode.piece.length) { // delete node
748
+ const next = startNode.next();
749
+ rbDelete(this, startNode);
750
+ this.validateCRLFWithPrevNode(next);
751
+ this.computeBufferMetadata();
752
+ return;
753
+ }
754
+ this.deleteNodeHead(startNode, endSplitPosInBuffer);
755
+ this._searchCache.validate(offset);
756
+ this.validateCRLFWithPrevNode(startNode);
757
+ this.computeBufferMetadata();
758
+ return;
759
+ }
760
+ if (startPosition.nodeStartOffset + startNode.piece.length === offset + cnt) {
761
+ this.deleteNodeTail(startNode, startSplitPosInBuffer);
762
+ this.validateCRLFWithNextNode(startNode);
763
+ this.computeBufferMetadata();
764
+ return;
765
+ }
766
+ // delete content in the middle, this node will be splitted to nodes
767
+ this.shrinkNode(startNode, startSplitPosInBuffer, endSplitPosInBuffer);
768
+ this.computeBufferMetadata();
769
+ return;
770
+ }
771
+ const nodesToDel = [];
772
+ const startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);
773
+ this.deleteNodeTail(startNode, startSplitPosInBuffer);
774
+ this._searchCache.validate(offset);
775
+ if (startNode.piece.length === 0) {
776
+ nodesToDel.push(startNode);
777
+ }
778
+ // update last touched node
779
+ const endSplitPosInBuffer = this.positionInBuffer(endNode, endPosition.remainder);
780
+ this.deleteNodeHead(endNode, endSplitPosInBuffer);
781
+ if (endNode.piece.length === 0) {
782
+ nodesToDel.push(endNode);
783
+ }
784
+ // delete nodes in between
785
+ const secondNode = startNode.next();
786
+ for (let node = secondNode; node !== SENTINEL && node !== endNode; node = node.next()) {
787
+ nodesToDel.push(node);
788
+ }
789
+ const prev = startNode.piece.length === 0 ? startNode.prev() : startNode;
790
+ this.deleteNodes(nodesToDel);
791
+ this.validateCRLFWithNextNode(prev);
792
+ this.computeBufferMetadata();
793
+ }
794
+ insertContentToNodeLeft(value, node) {
795
+ // we are inserting content to the beginning of node
796
+ const nodesToDel = [];
797
+ if (this.shouldCheckCRLF() && this.endWithCR(value) && this.startWithLF(node)) {
798
+ // move `\n` to new node.
799
+ const piece = node.piece;
800
+ const newStart = { line: piece.start.line + 1, column: 0 };
801
+ const nPiece = new Piece(piece.bufferIndex, newStart, piece.end, this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end), piece.length - 1);
802
+ node.piece = nPiece;
803
+ value += '\n';
804
+ updateTreeMetadata(this, node, -1, -1);
805
+ if (node.piece.length === 0) {
806
+ nodesToDel.push(node);
807
+ }
808
+ }
809
+ const newPieces = this.createNewPieces(value);
810
+ let newNode = this.rbInsertLeft(node, newPieces[newPieces.length - 1]);
811
+ for (let k = newPieces.length - 2; k >= 0; k--) {
812
+ newNode = this.rbInsertLeft(newNode, newPieces[k]);
813
+ }
814
+ this.validateCRLFWithPrevNode(newNode);
815
+ this.deleteNodes(nodesToDel);
816
+ }
817
+ insertContentToNodeRight(value, node) {
818
+ // we are inserting to the right of this node.
819
+ if (this.adjustCarriageReturnFromNext(value, node)) {
820
+ // move \n to the new node.
821
+ value += '\n';
822
+ }
823
+ const newPieces = this.createNewPieces(value);
824
+ const newNode = this.rbInsertRight(node, newPieces[0]);
825
+ let tmpNode = newNode;
826
+ for (let k = 1; k < newPieces.length; k++) {
827
+ tmpNode = this.rbInsertRight(tmpNode, newPieces[k]);
828
+ }
829
+ this.validateCRLFWithPrevNode(newNode);
830
+ }
831
+ positionInBuffer(node, remainder, ret) {
832
+ const piece = node.piece;
833
+ const bufferIndex = node.piece.bufferIndex;
834
+ const lineStarts = this._buffers[bufferIndex].lineStarts;
835
+ const startOffset = lineStarts[piece.start.line] + piece.start.column;
836
+ const offset = startOffset + remainder;
837
+ // binary search offset between startOffset and endOffset
838
+ let low = piece.start.line;
839
+ let high = piece.end.line;
840
+ let mid = 0;
841
+ let midStop = 0;
842
+ let midStart = 0;
843
+ while (low <= high) {
844
+ mid = low + ((high - low) / 2) | 0;
845
+ midStart = lineStarts[mid];
846
+ if (mid === high) {
847
+ break;
848
+ }
849
+ midStop = lineStarts[mid + 1];
850
+ if (offset < midStart) {
851
+ high = mid - 1;
852
+ }
853
+ else if (offset >= midStop) {
854
+ low = mid + 1;
855
+ }
856
+ else {
857
+ break;
858
+ }
859
+ }
860
+ if (ret) {
861
+ ret.line = mid;
862
+ ret.column = offset - midStart;
863
+ return null;
864
+ }
865
+ return {
866
+ line: mid,
867
+ column: offset - midStart
868
+ };
869
+ }
870
+ getLineFeedCnt(bufferIndex, start, end) {
871
+ // we don't need to worry about start: abc\r|\n, or abc|\r, or abc|\n, or abc|\r\n doesn't change the fact that, there is one line break after start.
872
+ // now let's take care of end: abc\r|\n, if end is in between \r and \n, we need to add line feed count by 1
873
+ if (end.column === 0) {
874
+ return end.line - start.line;
875
+ }
876
+ const lineStarts = this._buffers[bufferIndex].lineStarts;
877
+ if (end.line === lineStarts.length - 1) { // it means, there is no \n after end, otherwise, there will be one more lineStart.
878
+ return end.line - start.line;
879
+ }
880
+ const nextLineStartOffset = lineStarts[end.line + 1];
881
+ const endOffset = lineStarts[end.line] + end.column;
882
+ if (nextLineStartOffset > endOffset + 1) { // there are more than 1 character after end, which means it can't be \n
883
+ return end.line - start.line;
884
+ }
885
+ // endOffset + 1 === nextLineStartOffset
886
+ // character at endOffset is \n, so we check the character before first
887
+ // if character at endOffset is \r, end.column is 0 and we can't get here.
888
+ const previousCharOffset = endOffset - 1; // end.column > 0 so it's okay.
889
+ const buffer = this._buffers[bufferIndex].buffer;
890
+ if (buffer.charCodeAt(previousCharOffset) === 13) {
891
+ return end.line - start.line + 1;
892
+ }
893
+ else {
894
+ return end.line - start.line;
895
+ }
896
+ }
897
+ offsetInBuffer(bufferIndex, cursor) {
898
+ const lineStarts = this._buffers[bufferIndex].lineStarts;
899
+ return lineStarts[cursor.line] + cursor.column;
900
+ }
901
+ deleteNodes(nodes) {
902
+ for (let i = 0; i < nodes.length; i++) {
903
+ rbDelete(this, nodes[i]);
904
+ }
905
+ }
906
+ createNewPieces(text) {
907
+ if (text.length > AverageBufferSize) {
908
+ // the content is large, operations like substring, charCode becomes slow
909
+ // so here we split it into smaller chunks, just like what we did for CR/LF normalization
910
+ const newPieces = [];
911
+ while (text.length > AverageBufferSize) {
912
+ const lastChar = text.charCodeAt(AverageBufferSize - 1);
913
+ let splitText;
914
+ if (lastChar === 13 /* CharCode.CarriageReturn */ || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {
915
+ // last character is \r or a high surrogate => keep it back
916
+ splitText = text.substring(0, AverageBufferSize - 1);
917
+ text = text.substring(AverageBufferSize - 1);
918
+ }
919
+ else {
920
+ splitText = text.substring(0, AverageBufferSize);
921
+ text = text.substring(AverageBufferSize);
922
+ }
923
+ const lineStarts = createLineStartsFast(splitText);
924
+ newPieces.push(new Piece(this._buffers.length, /* buffer index */ { line: 0, column: 0 }, { line: lineStarts.length - 1, column: splitText.length - lineStarts[lineStarts.length - 1] }, lineStarts.length - 1, splitText.length));
925
+ this._buffers.push(new StringBuffer(splitText, lineStarts));
926
+ }
927
+ const lineStarts = createLineStartsFast(text);
928
+ newPieces.push(new Piece(this._buffers.length, /* buffer index */ { line: 0, column: 0 }, { line: lineStarts.length - 1, column: text.length - lineStarts[lineStarts.length - 1] }, lineStarts.length - 1, text.length));
929
+ this._buffers.push(new StringBuffer(text, lineStarts));
930
+ return newPieces;
931
+ }
932
+ let startOffset = this._buffers[0].buffer.length;
933
+ const lineStarts = createLineStartsFast(text, false);
934
+ let start = this._lastChangeBufferPos;
935
+ if (this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 1] === startOffset
936
+ && startOffset !== 0
937
+ && this.startWithLF(text)
938
+ && this.endWithCR(this._buffers[0].buffer) // todo, we can check this._lastChangeBufferPos's column as it's the last one
939
+ ) {
940
+ this._lastChangeBufferPos = { line: this._lastChangeBufferPos.line, column: this._lastChangeBufferPos.column + 1 };
941
+ start = this._lastChangeBufferPos;
942
+ for (let i = 0; i < lineStarts.length; i++) {
943
+ lineStarts[i] += startOffset + 1;
944
+ }
945
+ this._buffers[0].lineStarts = this._buffers[0].lineStarts.concat(lineStarts.slice(1));
946
+ this._buffers[0].buffer += '_' + text;
947
+ startOffset += 1;
948
+ }
949
+ else {
950
+ if (startOffset !== 0) {
951
+ for (let i = 0; i < lineStarts.length; i++) {
952
+ lineStarts[i] += startOffset;
953
+ }
954
+ }
955
+ this._buffers[0].lineStarts = this._buffers[0].lineStarts.concat(lineStarts.slice(1));
956
+ this._buffers[0].buffer += text;
957
+ }
958
+ const endOffset = this._buffers[0].buffer.length;
959
+ const endIndex = this._buffers[0].lineStarts.length - 1;
960
+ const endColumn = endOffset - this._buffers[0].lineStarts[endIndex];
961
+ const endPos = { line: endIndex, column: endColumn };
962
+ const newPiece = new Piece(0, /** todo@peng */ start, endPos, this.getLineFeedCnt(0, start, endPos), endOffset - startOffset);
963
+ this._lastChangeBufferPos = endPos;
964
+ return [newPiece];
965
+ }
966
+ getLineRawContent(lineNumber, endOffset = 0) {
967
+ let x = this.root;
968
+ let ret = '';
969
+ const cache = this._searchCache.get2(lineNumber);
970
+ if (cache) {
971
+ x = cache.node;
972
+ const prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber - 1);
973
+ const buffer = this._buffers[x.piece.bufferIndex].buffer;
974
+ const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
975
+ if (cache.nodeStartLineNumber + x.piece.lineFeedCnt === lineNumber) {
976
+ ret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);
977
+ }
978
+ else {
979
+ const accumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber);
980
+ return buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);
981
+ }
982
+ }
983
+ else {
984
+ let nodeStartOffset = 0;
985
+ const originalLineNumber = lineNumber;
986
+ while (x !== SENTINEL) {
987
+ if (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {
988
+ x = x.left;
989
+ }
990
+ else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {
991
+ const prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
992
+ const accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);
993
+ const buffer = this._buffers[x.piece.bufferIndex].buffer;
994
+ const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
995
+ nodeStartOffset += x.size_left;
996
+ this._searchCache.set({
997
+ node: x,
998
+ nodeStartOffset,
999
+ nodeStartLineNumber: originalLineNumber - (lineNumber - 1 - x.lf_left)
1000
+ });
1001
+ return buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);
1002
+ }
1003
+ else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {
1004
+ const prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
1005
+ const buffer = this._buffers[x.piece.bufferIndex].buffer;
1006
+ const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
1007
+ ret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);
1008
+ break;
1009
+ }
1010
+ else {
1011
+ lineNumber -= x.lf_left + x.piece.lineFeedCnt;
1012
+ nodeStartOffset += x.size_left + x.piece.length;
1013
+ x = x.right;
1014
+ }
1015
+ }
1016
+ }
1017
+ // search in order, to find the node contains end column
1018
+ x = x.next();
1019
+ while (x !== SENTINEL) {
1020
+ const buffer = this._buffers[x.piece.bufferIndex].buffer;
1021
+ if (x.piece.lineFeedCnt > 0) {
1022
+ const accumulatedValue = this.getAccumulatedValue(x, 0);
1023
+ const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
1024
+ ret += buffer.substring(startOffset, startOffset + accumulatedValue - endOffset);
1025
+ return ret;
1026
+ }
1027
+ else {
1028
+ const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
1029
+ ret += buffer.substr(startOffset, x.piece.length);
1030
+ }
1031
+ x = x.next();
1032
+ }
1033
+ return ret;
1034
+ }
1035
+ computeBufferMetadata() {
1036
+ let x = this.root;
1037
+ let lfCnt = 1;
1038
+ let len = 0;
1039
+ while (x !== SENTINEL) {
1040
+ lfCnt += x.lf_left + x.piece.lineFeedCnt;
1041
+ len += x.size_left + x.piece.length;
1042
+ x = x.right;
1043
+ }
1044
+ this._lineCnt = lfCnt;
1045
+ this._length = len;
1046
+ this._searchCache.validate(this._length);
1047
+ }
1048
+ // #region node operations
1049
+ getIndexOf(node, accumulatedValue) {
1050
+ const piece = node.piece;
1051
+ const pos = this.positionInBuffer(node, accumulatedValue);
1052
+ const lineCnt = pos.line - piece.start.line;
1053
+ if (this.offsetInBuffer(piece.bufferIndex, piece.end) - this.offsetInBuffer(piece.bufferIndex, piece.start) === accumulatedValue) {
1054
+ // we are checking the end of this node, so a CRLF check is necessary.
1055
+ const realLineCnt = this.getLineFeedCnt(node.piece.bufferIndex, piece.start, pos);
1056
+ if (realLineCnt !== lineCnt) {
1057
+ // aha yes, CRLF
1058
+ return { index: realLineCnt, remainder: 0 };
1059
+ }
1060
+ }
1061
+ return { index: lineCnt, remainder: pos.column };
1062
+ }
1063
+ getAccumulatedValue(node, index) {
1064
+ if (index < 0) {
1065
+ return 0;
1066
+ }
1067
+ const piece = node.piece;
1068
+ const lineStarts = this._buffers[piece.bufferIndex].lineStarts;
1069
+ const expectedLineStartIndex = piece.start.line + index + 1;
1070
+ if (expectedLineStartIndex > piece.end.line) {
1071
+ return lineStarts[piece.end.line] + piece.end.column - lineStarts[piece.start.line] - piece.start.column;
1072
+ }
1073
+ else {
1074
+ return lineStarts[expectedLineStartIndex] - lineStarts[piece.start.line] - piece.start.column;
1075
+ }
1076
+ }
1077
+ deleteNodeTail(node, pos) {
1078
+ const piece = node.piece;
1079
+ const originalLFCnt = piece.lineFeedCnt;
1080
+ const originalEndOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);
1081
+ const newEnd = pos;
1082
+ const newEndOffset = this.offsetInBuffer(piece.bufferIndex, newEnd);
1083
+ const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);
1084
+ const lf_delta = newLineFeedCnt - originalLFCnt;
1085
+ const size_delta = newEndOffset - originalEndOffset;
1086
+ const newLength = piece.length + size_delta;
1087
+ node.piece = new Piece(piece.bufferIndex, piece.start, newEnd, newLineFeedCnt, newLength);
1088
+ updateTreeMetadata(this, node, size_delta, lf_delta);
1089
+ }
1090
+ deleteNodeHead(node, pos) {
1091
+ const piece = node.piece;
1092
+ const originalLFCnt = piece.lineFeedCnt;
1093
+ const originalStartOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);
1094
+ const newStart = pos;
1095
+ const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);
1096
+ const newStartOffset = this.offsetInBuffer(piece.bufferIndex, newStart);
1097
+ const lf_delta = newLineFeedCnt - originalLFCnt;
1098
+ const size_delta = originalStartOffset - newStartOffset;
1099
+ const newLength = piece.length + size_delta;
1100
+ node.piece = new Piece(piece.bufferIndex, newStart, piece.end, newLineFeedCnt, newLength);
1101
+ updateTreeMetadata(this, node, size_delta, lf_delta);
1102
+ }
1103
+ shrinkNode(node, start, end) {
1104
+ const piece = node.piece;
1105
+ const originalStartPos = piece.start;
1106
+ const originalEndPos = piece.end;
1107
+ // old piece, originalStartPos, start
1108
+ const oldLength = piece.length;
1109
+ const oldLFCnt = piece.lineFeedCnt;
1110
+ const newEnd = start;
1111
+ const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);
1112
+ const newLength = this.offsetInBuffer(piece.bufferIndex, start) - this.offsetInBuffer(piece.bufferIndex, originalStartPos);
1113
+ node.piece = new Piece(piece.bufferIndex, piece.start, newEnd, newLineFeedCnt, newLength);
1114
+ updateTreeMetadata(this, node, newLength - oldLength, newLineFeedCnt - oldLFCnt);
1115
+ // new right piece, end, originalEndPos
1116
+ const newPiece = new Piece(piece.bufferIndex, end, originalEndPos, this.getLineFeedCnt(piece.bufferIndex, end, originalEndPos), this.offsetInBuffer(piece.bufferIndex, originalEndPos) - this.offsetInBuffer(piece.bufferIndex, end));
1117
+ const newNode = this.rbInsertRight(node, newPiece);
1118
+ this.validateCRLFWithPrevNode(newNode);
1119
+ }
1120
+ appendToNode(node, value) {
1121
+ if (this.adjustCarriageReturnFromNext(value, node)) {
1122
+ value += '\n';
1123
+ }
1124
+ const hitCRLF = this.shouldCheckCRLF() && this.startWithLF(value) && this.endWithCR(node);
1125
+ const startOffset = this._buffers[0].buffer.length;
1126
+ this._buffers[0].buffer += value;
1127
+ const lineStarts = createLineStartsFast(value, false);
1128
+ for (let i = 0; i < lineStarts.length; i++) {
1129
+ lineStarts[i] += startOffset;
1130
+ }
1131
+ if (hitCRLF) {
1132
+ const prevStartOffset = this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 2];
1133
+ this._buffers[0].lineStarts.pop();
1134
+ // _lastChangeBufferPos is already wrong
1135
+ this._lastChangeBufferPos = { line: this._lastChangeBufferPos.line - 1, column: startOffset - prevStartOffset };
1136
+ }
1137
+ this._buffers[0].lineStarts = this._buffers[0].lineStarts.concat(lineStarts.slice(1));
1138
+ const endIndex = this._buffers[0].lineStarts.length - 1;
1139
+ const endColumn = this._buffers[0].buffer.length - this._buffers[0].lineStarts[endIndex];
1140
+ const newEnd = { line: endIndex, column: endColumn };
1141
+ const newLength = node.piece.length + value.length;
1142
+ const oldLineFeedCnt = node.piece.lineFeedCnt;
1143
+ const newLineFeedCnt = this.getLineFeedCnt(0, node.piece.start, newEnd);
1144
+ const lf_delta = newLineFeedCnt - oldLineFeedCnt;
1145
+ node.piece = new Piece(node.piece.bufferIndex, node.piece.start, newEnd, newLineFeedCnt, newLength);
1146
+ this._lastChangeBufferPos = newEnd;
1147
+ updateTreeMetadata(this, node, value.length, lf_delta);
1148
+ }
1149
+ nodeAt(offset) {
1150
+ let x = this.root;
1151
+ const cache = this._searchCache.get(offset);
1152
+ if (cache) {
1153
+ return {
1154
+ node: cache.node,
1155
+ nodeStartOffset: cache.nodeStartOffset,
1156
+ remainder: offset - cache.nodeStartOffset
1157
+ };
1158
+ }
1159
+ let nodeStartOffset = 0;
1160
+ while (x !== SENTINEL) {
1161
+ if (x.size_left > offset) {
1162
+ x = x.left;
1163
+ }
1164
+ else if (x.size_left + x.piece.length >= offset) {
1165
+ nodeStartOffset += x.size_left;
1166
+ const ret = {
1167
+ node: x,
1168
+ remainder: offset - x.size_left,
1169
+ nodeStartOffset
1170
+ };
1171
+ this._searchCache.set(ret);
1172
+ return ret;
1173
+ }
1174
+ else {
1175
+ offset -= x.size_left + x.piece.length;
1176
+ nodeStartOffset += x.size_left + x.piece.length;
1177
+ x = x.right;
1178
+ }
1179
+ }
1180
+ return null;
1181
+ }
1182
+ nodeAt2(lineNumber, column) {
1183
+ let x = this.root;
1184
+ let nodeStartOffset = 0;
1185
+ while (x !== SENTINEL) {
1186
+ if (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {
1187
+ x = x.left;
1188
+ }
1189
+ else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {
1190
+ const prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
1191
+ const accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);
1192
+ nodeStartOffset += x.size_left;
1193
+ return {
1194
+ node: x,
1195
+ remainder: Math.min(prevAccumualtedValue + column - 1, accumulatedValue),
1196
+ nodeStartOffset
1197
+ };
1198
+ }
1199
+ else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {
1200
+ const prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
1201
+ if (prevAccumualtedValue + column - 1 <= x.piece.length) {
1202
+ return {
1203
+ node: x,
1204
+ remainder: prevAccumualtedValue + column - 1,
1205
+ nodeStartOffset
1206
+ };
1207
+ }
1208
+ else {
1209
+ column -= x.piece.length - prevAccumualtedValue;
1210
+ break;
1211
+ }
1212
+ }
1213
+ else {
1214
+ lineNumber -= x.lf_left + x.piece.lineFeedCnt;
1215
+ nodeStartOffset += x.size_left + x.piece.length;
1216
+ x = x.right;
1217
+ }
1218
+ }
1219
+ // search in order, to find the node contains position.column
1220
+ x = x.next();
1221
+ while (x !== SENTINEL) {
1222
+ if (x.piece.lineFeedCnt > 0) {
1223
+ const accumulatedValue = this.getAccumulatedValue(x, 0);
1224
+ const nodeStartOffset = this.offsetOfNode(x);
1225
+ return {
1226
+ node: x,
1227
+ remainder: Math.min(column - 1, accumulatedValue),
1228
+ nodeStartOffset
1229
+ };
1230
+ }
1231
+ else {
1232
+ if (x.piece.length >= column - 1) {
1233
+ const nodeStartOffset = this.offsetOfNode(x);
1234
+ return {
1235
+ node: x,
1236
+ remainder: column - 1,
1237
+ nodeStartOffset
1238
+ };
1239
+ }
1240
+ else {
1241
+ column -= x.piece.length;
1242
+ }
1243
+ }
1244
+ x = x.next();
1245
+ }
1246
+ return null;
1247
+ }
1248
+ nodeCharCodeAt(node, offset) {
1249
+ if (node.piece.lineFeedCnt < 1) {
1250
+ return -1;
1251
+ }
1252
+ const buffer = this._buffers[node.piece.bufferIndex];
1253
+ const newOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start) + offset;
1254
+ return buffer.buffer.charCodeAt(newOffset);
1255
+ }
1256
+ offsetOfNode(node) {
1257
+ if (!node) {
1258
+ return 0;
1259
+ }
1260
+ let pos = node.size_left;
1261
+ while (node !== this.root) {
1262
+ if (node.parent.right === node) {
1263
+ pos += node.parent.size_left + node.parent.piece.length;
1264
+ }
1265
+ node = node.parent;
1266
+ }
1267
+ return pos;
1268
+ }
1269
+ // #endregion
1270
+ // #region CRLF
1271
+ shouldCheckCRLF() {
1272
+ return !(this._EOLNormalized && this._EOL === '\n');
1273
+ }
1274
+ startWithLF(val) {
1275
+ if (typeof val === 'string') {
1276
+ return val.charCodeAt(0) === 10;
1277
+ }
1278
+ if (val === SENTINEL || val.piece.lineFeedCnt === 0) {
1279
+ return false;
1280
+ }
1281
+ const piece = val.piece;
1282
+ const lineStarts = this._buffers[piece.bufferIndex].lineStarts;
1283
+ const line = piece.start.line;
1284
+ const startOffset = lineStarts[line] + piece.start.column;
1285
+ if (line === lineStarts.length - 1) {
1286
+ // last line, so there is no line feed at the end of this line
1287
+ return false;
1288
+ }
1289
+ const nextLineOffset = lineStarts[line + 1];
1290
+ if (nextLineOffset > startOffset + 1) {
1291
+ return false;
1292
+ }
1293
+ return this._buffers[piece.bufferIndex].buffer.charCodeAt(startOffset) === 10;
1294
+ }
1295
+ endWithCR(val) {
1296
+ if (typeof val === 'string') {
1297
+ return val.charCodeAt(val.length - 1) === 13;
1298
+ }
1299
+ if (val === SENTINEL || val.piece.lineFeedCnt === 0) {
1300
+ return false;
1301
+ }
1302
+ return this.nodeCharCodeAt(val, val.piece.length - 1) === 13;
1303
+ }
1304
+ validateCRLFWithPrevNode(nextNode) {
1305
+ if (this.shouldCheckCRLF() && this.startWithLF(nextNode)) {
1306
+ const node = nextNode.prev();
1307
+ if (this.endWithCR(node)) {
1308
+ this.fixCRLF(node, nextNode);
1309
+ }
1310
+ }
1311
+ }
1312
+ validateCRLFWithNextNode(node) {
1313
+ if (this.shouldCheckCRLF() && this.endWithCR(node)) {
1314
+ const nextNode = node.next();
1315
+ if (this.startWithLF(nextNode)) {
1316
+ this.fixCRLF(node, nextNode);
1317
+ }
1318
+ }
1319
+ }
1320
+ fixCRLF(prev, next) {
1321
+ const nodesToDel = [];
1322
+ // update node
1323
+ const lineStarts = this._buffers[prev.piece.bufferIndex].lineStarts;
1324
+ let newEnd;
1325
+ if (prev.piece.end.column === 0) {
1326
+ // it means, last line ends with \r, not \r\n
1327
+ newEnd = { line: prev.piece.end.line - 1, column: lineStarts[prev.piece.end.line] - lineStarts[prev.piece.end.line - 1] - 1 };
1328
+ }
1329
+ else {
1330
+ // \r\n
1331
+ newEnd = { line: prev.piece.end.line, column: prev.piece.end.column - 1 };
1332
+ }
1333
+ const prevNewLength = prev.piece.length - 1;
1334
+ const prevNewLFCnt = prev.piece.lineFeedCnt - 1;
1335
+ prev.piece = new Piece(prev.piece.bufferIndex, prev.piece.start, newEnd, prevNewLFCnt, prevNewLength);
1336
+ updateTreeMetadata(this, prev, -1, -1);
1337
+ if (prev.piece.length === 0) {
1338
+ nodesToDel.push(prev);
1339
+ }
1340
+ // update nextNode
1341
+ const newStart = { line: next.piece.start.line + 1, column: 0 };
1342
+ const newLength = next.piece.length - 1;
1343
+ const newLineFeedCnt = this.getLineFeedCnt(next.piece.bufferIndex, newStart, next.piece.end);
1344
+ next.piece = new Piece(next.piece.bufferIndex, newStart, next.piece.end, newLineFeedCnt, newLength);
1345
+ updateTreeMetadata(this, next, -1, -1);
1346
+ if (next.piece.length === 0) {
1347
+ nodesToDel.push(next);
1348
+ }
1349
+ // create new piece which contains \r\n
1350
+ const pieces = this.createNewPieces('\r\n');
1351
+ this.rbInsertRight(prev, pieces[0]);
1352
+ // delete empty nodes
1353
+ for (let i = 0; i < nodesToDel.length; i++) {
1354
+ rbDelete(this, nodesToDel[i]);
1355
+ }
1356
+ }
1357
+ adjustCarriageReturnFromNext(value, node) {
1358
+ if (this.shouldCheckCRLF() && this.endWithCR(value)) {
1359
+ const nextNode = node.next();
1360
+ if (this.startWithLF(nextNode)) {
1361
+ // move `\n` forward
1362
+ value += '\n';
1363
+ if (nextNode.piece.length === 1) {
1364
+ rbDelete(this, nextNode);
1365
+ }
1366
+ else {
1367
+ const piece = nextNode.piece;
1368
+ const newStart = { line: piece.start.line + 1, column: 0 };
1369
+ const newLength = piece.length - 1;
1370
+ const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);
1371
+ nextNode.piece = new Piece(piece.bufferIndex, newStart, piece.end, newLineFeedCnt, newLength);
1372
+ updateTreeMetadata(this, nextNode, -1, -1);
1373
+ }
1374
+ return true;
1375
+ }
1376
+ }
1377
+ return false;
1378
+ }
1379
+ // #endregion
1380
+ // #endregion
1381
+ // #region Tree operations
1382
+ iterate(node, callback) {
1383
+ if (node === SENTINEL) {
1384
+ return callback(SENTINEL);
1385
+ }
1386
+ const leftRet = this.iterate(node.left, callback);
1387
+ if (!leftRet) {
1388
+ return leftRet;
1389
+ }
1390
+ return callback(node) && this.iterate(node.right, callback);
1391
+ }
1392
+ getNodeContent(node) {
1393
+ if (node === SENTINEL) {
1394
+ return '';
1395
+ }
1396
+ const buffer = this._buffers[node.piece.bufferIndex];
1397
+ const piece = node.piece;
1398
+ const startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);
1399
+ const endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);
1400
+ const currentContent = buffer.buffer.substring(startOffset, endOffset);
1401
+ return currentContent;
1402
+ }
1403
+ getPieceContent(piece) {
1404
+ const buffer = this._buffers[piece.bufferIndex];
1405
+ const startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);
1406
+ const endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);
1407
+ const currentContent = buffer.buffer.substring(startOffset, endOffset);
1408
+ return currentContent;
1409
+ }
1410
+ /**
1411
+ * node node
1412
+ * / \ / \
1413
+ * a b <---- a b
1414
+ * /
1415
+ * z
1416
+ */
1417
+ rbInsertRight(node, p) {
1418
+ const z = new TreeNode(p, 1 /* NodeColor.Red */);
1419
+ z.left = SENTINEL;
1420
+ z.right = SENTINEL;
1421
+ z.parent = SENTINEL;
1422
+ z.size_left = 0;
1423
+ z.lf_left = 0;
1424
+ const x = this.root;
1425
+ if (x === SENTINEL) {
1426
+ this.root = z;
1427
+ z.color = 0 /* NodeColor.Black */;
1428
+ }
1429
+ else if (node.right === SENTINEL) {
1430
+ node.right = z;
1431
+ z.parent = node;
1432
+ }
1433
+ else {
1434
+ const nextNode = leftest(node.right);
1435
+ nextNode.left = z;
1436
+ z.parent = nextNode;
1437
+ }
1438
+ fixInsert(this, z);
1439
+ return z;
1440
+ }
1441
+ /**
1442
+ * node node
1443
+ * / \ / \
1444
+ * a b ----> a b
1445
+ * \
1446
+ * z
1447
+ */
1448
+ rbInsertLeft(node, p) {
1449
+ const z = new TreeNode(p, 1 /* NodeColor.Red */);
1450
+ z.left = SENTINEL;
1451
+ z.right = SENTINEL;
1452
+ z.parent = SENTINEL;
1453
+ z.size_left = 0;
1454
+ z.lf_left = 0;
1455
+ if (this.root === SENTINEL) {
1456
+ this.root = z;
1457
+ z.color = 0 /* NodeColor.Black */;
1458
+ }
1459
+ else if (node.left === SENTINEL) {
1460
+ node.left = z;
1461
+ z.parent = node;
1462
+ }
1463
+ else {
1464
+ const prevNode = righttest(node.left); // a
1465
+ prevNode.right = z;
1466
+ z.parent = prevNode;
1467
+ }
1468
+ fixInsert(this, z);
1469
+ return z;
1470
+ }
1471
+ }
1472
+
1473
+ export { Piece, PieceTreeBase, StringBuffer, createLineStarts, createLineStartsFast };