monaco-editor11 1.0.9 → 1.1.0

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 (232) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/monaco-editor11.es.js +11 -16
  3. package/dist/monaco-editor11.umd.js +1 -1
  4. package/package.json +2 -2
  5. package/dist/monaco.d.ts +0 -8
  6. package/dist/workers/common/initialize.js +0 -16
  7. package/dist/workers/common/workers.js +0 -141
  8. package/dist/workers/editor/common/abstractSyntaxTokenBackend.js +0 -128
  9. package/dist/workers/editor/common/abstractText.js +0 -89
  10. package/dist/workers/editor/common/ast.js +0 -485
  11. package/dist/workers/editor/common/autoIndent.js +0 -390
  12. package/dist/workers/editor/common/beforeEditPositionMapper.js +0 -110
  13. package/dist/workers/editor/common/bracketPairsImpl.js +0 -717
  14. package/dist/workers/editor/common/bracketPairsTree.js +0 -343
  15. package/dist/workers/editor/common/brackets.js +0 -108
  16. package/dist/workers/editor/common/characterClassifier.js +0 -59
  17. package/dist/workers/editor/common/characterPair.js +0 -40
  18. package/dist/workers/editor/common/colorizedBracketPairsDecorationProvider.js +0 -97
  19. package/dist/workers/editor/common/columnRange.js +0 -35
  20. package/dist/workers/editor/common/combineTextEditInfos.js +0 -124
  21. package/dist/workers/editor/common/common.js +0 -20
  22. package/dist/workers/editor/common/computeMovedLines.js +0 -249
  23. package/dist/workers/editor/common/concat23Trees.js +0 -192
  24. package/dist/workers/editor/common/contiguousMultilineTokens.js +0 -32
  25. package/dist/workers/editor/common/contiguousMultilineTokensBuilder.js +0 -23
  26. package/dist/workers/editor/common/contiguousTokensEditing.js +0 -128
  27. package/dist/workers/editor/common/contiguousTokensStore.js +0 -207
  28. package/dist/workers/editor/common/coordinatesConverter.js +0 -51
  29. package/dist/workers/editor/common/cursor.js +0 -899
  30. package/dist/workers/editor/common/cursorAtomicMoveOperations.js +0 -145
  31. package/dist/workers/editor/common/cursorCollection.js +0 -194
  32. package/dist/workers/editor/common/cursorColumnSelection.js +0 -93
  33. package/dist/workers/editor/common/cursorColumns.js +0 -112
  34. package/dist/workers/editor/common/cursorCommon.js +0 -250
  35. package/dist/workers/editor/common/cursorContext.js +0 -15
  36. package/dist/workers/editor/common/cursorDeleteOperations.js +0 -231
  37. package/dist/workers/editor/common/cursorMoveCommands.js +0 -676
  38. package/dist/workers/editor/common/cursorMoveOperations.js +0 -290
  39. package/dist/workers/editor/common/cursorTypeEditOperations.js +0 -968
  40. package/dist/workers/editor/common/cursorTypeOperations.js +0 -173
  41. package/dist/workers/editor/common/cursorUtils.js +0 -75
  42. package/dist/workers/editor/common/cursorWordOperations.js +0 -720
  43. package/dist/workers/editor/common/defaultDocumentColorsComputer.js +0 -138
  44. package/dist/workers/editor/common/defaultLinesDiffComputer.js +0 -188
  45. package/dist/workers/editor/common/diffAlgorithm.js +0 -139
  46. package/dist/workers/editor/common/diffEditor.js +0 -38
  47. package/dist/workers/editor/common/dynamicProgrammingDiffing.js +0 -101
  48. package/dist/workers/editor/common/edit.js +0 -183
  49. package/dist/workers/editor/common/editOperation.js +0 -36
  50. package/dist/workers/editor/common/editStack.js +0 -363
  51. package/dist/workers/editor/common/editorAction.js +0 -26
  52. package/dist/workers/editor/common/editorBaseApi.js +0 -43
  53. package/dist/workers/editor/common/editorColorRegistry.js +0 -102
  54. package/dist/workers/editor/common/editorCommon.js +0 -13
  55. package/dist/workers/editor/common/editorConfigurationSchema.js +0 -338
  56. package/dist/workers/editor/common/editorContextKeys.js +0 -84
  57. package/dist/workers/editor/common/editorFeatures.js +0 -17
  58. package/dist/workers/editor/common/editorOptions.js +0 -3440
  59. package/dist/workers/editor/common/editorTheme.js +0 -23
  60. package/dist/workers/editor/common/editorWebWorker.js +0 -299
  61. package/dist/workers/editor/common/editorWorker.js +0 -9
  62. package/dist/workers/editor/common/editorWorkerHost.js +0 -15
  63. package/dist/workers/editor/common/editorZoom.js +0 -26
  64. package/dist/workers/editor/common/electricCharacter.js +0 -55
  65. package/dist/workers/editor/common/encodedTokenAttributes.js +0 -79
  66. package/dist/workers/editor/common/enterAction.js +0 -53
  67. package/dist/workers/editor/common/eolCounter.js +0 -44
  68. package/dist/workers/editor/common/findSectionHeaders.js +0 -128
  69. package/dist/workers/editor/common/fixBrackets.js +0 -67
  70. package/dist/workers/editor/common/fixedArray.js +0 -70
  71. package/dist/workers/editor/common/fontInfo.js +0 -172
  72. package/dist/workers/editor/common/fontInfoFromSettings.js +0 -29
  73. package/dist/workers/editor/common/getIconClasses.js +0 -106
  74. package/dist/workers/editor/common/getPositionOffsetTransformerFromTextModel.js +0 -24
  75. package/dist/workers/editor/common/glyphLanesModel.js +0 -61
  76. package/dist/workers/editor/common/guidesTextModelPart.js +0 -405
  77. package/dist/workers/editor/common/heuristicSequenceOptimizations.js +0 -374
  78. package/dist/workers/editor/common/indentRules.js +0 -63
  79. package/dist/workers/editor/common/indentation.js +0 -39
  80. package/dist/workers/editor/common/indentationGuesser.js +0 -178
  81. package/dist/workers/editor/common/indentationLineProcessor.js +0 -193
  82. package/dist/workers/editor/common/inlineDecorations.js +0 -26
  83. package/dist/workers/editor/common/inplaceReplaceSupport.js +0 -87
  84. package/dist/workers/editor/common/inputMode.js +0 -22
  85. package/dist/workers/editor/common/intervalTree.js +0 -1002
  86. package/dist/workers/editor/common/language.js +0 -9
  87. package/dist/workers/editor/common/languageBracketsConfiguration.js +0 -133
  88. package/dist/workers/editor/common/languageConfiguration.js +0 -138
  89. package/dist/workers/editor/common/languageConfigurationRegistry.js +0 -361
  90. package/dist/workers/editor/common/languageFeatureDebounce.js +0 -137
  91. package/dist/workers/editor/common/languageFeatureRegistry.js +0 -180
  92. package/dist/workers/editor/common/languageFeatures.js +0 -9
  93. package/dist/workers/editor/common/languageFeaturesService.js +0 -47
  94. package/dist/workers/editor/common/languageSelector.js +0 -112
  95. package/dist/workers/editor/common/languageService.js +0 -92
  96. package/dist/workers/editor/common/languages.js +0 -522
  97. package/dist/workers/editor/common/languagesAssociations.js +0 -193
  98. package/dist/workers/editor/common/languagesRegistry.js +0 -237
  99. package/dist/workers/editor/common/legacyLinesDiffComputer.js +0 -468
  100. package/dist/workers/editor/common/length.js +0 -129
  101. package/dist/workers/editor/common/lineDecorations.js +0 -208
  102. package/dist/workers/editor/common/lineEdit.js +0 -75
  103. package/dist/workers/editor/common/lineHeights.js +0 -370
  104. package/dist/workers/editor/common/linePart.js +0 -25
  105. package/dist/workers/editor/common/lineRange.js +0 -312
  106. package/dist/workers/editor/common/lineSequence.js +0 -36
  107. package/dist/workers/editor/common/lineTokens.js +0 -405
  108. package/dist/workers/editor/common/linesDiffComputer.js +0 -29
  109. package/dist/workers/editor/common/linesDiffComputers.js +0 -13
  110. package/dist/workers/editor/common/linesLayout.js +0 -765
  111. package/dist/workers/editor/common/linesSliceCharSequence.js +0 -205
  112. package/dist/workers/editor/common/linkComputer.js +0 -269
  113. package/dist/workers/editor/common/markerDecorations.js +0 -9
  114. package/dist/workers/editor/common/markerDecorationsService.js +0 -248
  115. package/dist/workers/editor/common/minimapTokensColorTracker.js +0 -58
  116. package/dist/workers/editor/common/mirrorTextModel.js +0 -117
  117. package/dist/workers/editor/common/model.js +0 -9
  118. package/dist/workers/editor/common/modelLineProjection.js +0 -350
  119. package/dist/workers/editor/common/modelLineProjectionData.js +0 -297
  120. package/dist/workers/editor/common/modelService.js +0 -413
  121. package/dist/workers/editor/common/modesRegistry.js +0 -75
  122. package/dist/workers/editor/common/monospaceLineBreaksComputer.js +0 -473
  123. package/dist/workers/editor/common/myersDiffAlgorithm.js +0 -159
  124. package/dist/workers/editor/common/nodeReader.js +0 -127
  125. package/dist/workers/editor/common/nullTokenize.js +0 -29
  126. package/dist/workers/editor/common/offsetRange.js +0 -225
  127. package/dist/workers/editor/common/onEnter.js +0 -109
  128. package/dist/workers/editor/common/oneCursor.js +0 -117
  129. package/dist/workers/editor/common/overviewZoneManager.js +0 -176
  130. package/dist/workers/editor/common/parser.js +0 -121
  131. package/dist/workers/editor/common/pieceTreeBase.js +0 -1473
  132. package/dist/workers/editor/common/pieceTreeTextBuffer.js +0 -461
  133. package/dist/workers/editor/common/pieceTreeTextBufferBuilder.js +0 -140
  134. package/dist/workers/editor/common/point.js +0 -50
  135. package/dist/workers/editor/common/position.js +0 -142
  136. package/dist/workers/editor/common/positionToOffset.js +0 -17
  137. package/dist/workers/editor/common/positionToOffsetImpl.js +0 -98
  138. package/dist/workers/editor/common/prefixSumComputer.js +0 -226
  139. package/dist/workers/editor/common/range.js +0 -421
  140. package/dist/workers/editor/common/rangeMapping.js +0 -229
  141. package/dist/workers/editor/common/rangeSingleLine.js +0 -17
  142. package/dist/workers/editor/common/rbTreeBase.js +0 -362
  143. package/dist/workers/editor/common/rect.js +0 -163
  144. package/dist/workers/editor/common/replaceCommand.js +0 -158
  145. package/dist/workers/editor/common/resolverService.js +0 -5
  146. package/dist/workers/editor/common/rgba.js +0 -35
  147. package/dist/workers/editor/common/richEditBrackets.js +0 -356
  148. package/dist/workers/editor/common/selection.js +0 -145
  149. package/dist/workers/editor/common/semanticTokensDto.js +0 -82
  150. package/dist/workers/editor/common/semanticTokensProviderStyling.js +0 -263
  151. package/dist/workers/editor/common/semanticTokensStyling.js +0 -9
  152. package/dist/workers/editor/common/semanticTokensStylingService.js +0 -47
  153. package/dist/workers/editor/common/shiftCommand.js +0 -241
  154. package/dist/workers/editor/common/smallImmutableSet.js +0 -108
  155. package/dist/workers/editor/common/sparseMultilineTokens.js +0 -548
  156. package/dist/workers/editor/common/sparseTokensStore.js +0 -210
  157. package/dist/workers/editor/common/standaloneEnums.js +0 -1017
  158. package/dist/workers/editor/common/standaloneStrings.js +0 -42
  159. package/dist/workers/editor/common/stringBuilder.js +0 -122
  160. package/dist/workers/editor/common/stringEdit.js +0 -165
  161. package/dist/workers/editor/common/supports.js +0 -58
  162. package/dist/workers/editor/common/surroundSelectionCommand.js +0 -44
  163. package/dist/workers/editor/common/textChange.js +0 -248
  164. package/dist/workers/editor/common/textEdit.js +0 -269
  165. package/dist/workers/editor/common/textLength.js +0 -87
  166. package/dist/workers/editor/common/textModel.js +0 -2031
  167. package/dist/workers/editor/common/textModelBracketPairs.js +0 -45
  168. package/dist/workers/editor/common/textModelDefaults.js +0 -18
  169. package/dist/workers/editor/common/textModelEditSource.js +0 -166
  170. package/dist/workers/editor/common/textModelEvents.js +0 -216
  171. package/dist/workers/editor/common/textModelGuides.js +0 -40
  172. package/dist/workers/editor/common/textModelPart.js +0 -23
  173. package/dist/workers/editor/common/textModelSearch.js +0 -455
  174. package/dist/workers/editor/common/textModelStringEdit.js +0 -11
  175. package/dist/workers/editor/common/textModelSync.impl.js +0 -307
  176. package/dist/workers/editor/common/textModelText.js +0 -26
  177. package/dist/workers/editor/common/textModelTokens.js +0 -436
  178. package/dist/workers/editor/common/textResourceConfiguration.js +0 -6
  179. package/dist/workers/editor/common/textToHtmlTokenizer.js +0 -139
  180. package/dist/workers/editor/common/tokenStore.js +0 -407
  181. package/dist/workers/editor/common/tokenWithTextArray.js +0 -73
  182. package/dist/workers/editor/common/tokenization.js +0 -287
  183. package/dist/workers/editor/common/tokenizationRegistry.js +0 -123
  184. package/dist/workers/editor/common/tokenizationTextModelPart.js +0 -275
  185. package/dist/workers/editor/common/tokenizer.js +0 -301
  186. package/dist/workers/editor/common/tokenizerSyntaxTokenBackend.js +0 -261
  187. package/dist/workers/editor/common/treeSitterLibraryService.js +0 -9
  188. package/dist/workers/editor/common/treeSitterSyntaxTokenBackend.js +0 -167
  189. package/dist/workers/editor/common/treeSitterThemeService.js +0 -9
  190. package/dist/workers/editor/common/treeSitterTokenizationImpl.js +0 -713
  191. package/dist/workers/editor/common/treeSitterTree.js +0 -395
  192. package/dist/workers/editor/common/treeViewsDnd.js +0 -24
  193. package/dist/workers/editor/common/treeViewsDndService.js +0 -12
  194. package/dist/workers/editor/common/trimTrailingWhitespaceCommand.js +0 -98
  195. package/dist/workers/editor/common/unicodeTextModelHighlighter.js +0 -188
  196. package/dist/workers/editor/common/utils.js +0 -62
  197. package/dist/workers/editor/common/viewContext.js +0 -22
  198. package/dist/workers/editor/common/viewEventHandler.js +0 -186
  199. package/dist/workers/editor/common/viewEvents.js +0 -180
  200. package/dist/workers/editor/common/viewLayout.js +0 -368
  201. package/dist/workers/editor/common/viewLineRenderer.js +0 -948
  202. package/dist/workers/editor/common/viewLinesViewportData.js +0 -30
  203. package/dist/workers/editor/common/viewModel.js +0 -98
  204. package/dist/workers/editor/common/viewModelDecoration.js +0 -55
  205. package/dist/workers/editor/common/viewModelDecorations.js +0 -132
  206. package/dist/workers/editor/common/viewModelEventDispatcher.js +0 -398
  207. package/dist/workers/editor/common/viewModelImpl.js +0 -1163
  208. package/dist/workers/editor/common/viewModelLines.js +0 -938
  209. package/dist/workers/editor/common/wordCharacterClassifier.js +0 -87
  210. package/dist/workers/editor/common/wordHelper.js +0 -127
  211. package/dist/workers/language/cssMode.js +0 -198
  212. package/dist/workers/language/cssWorker.js +0 -183
  213. package/dist/workers/language/htmlMode.js +0 -213
  214. package/dist/workers/language/htmlWorker.js +0 -126
  215. package/dist/workers/language/jsonMode.js +0 -224
  216. package/dist/workers/language/jsonWorker.js +0 -187
  217. package/dist/workers/language/languageFeatures.js +0 -1009
  218. package/dist/workers/language/lib.index.js +0 -103
  219. package/dist/workers/language/lib.js +0 -1107
  220. package/dist/workers/language/lspLanguageFeatures.js +0 -716
  221. package/dist/workers/language/monaco.contribution.js +0 -144
  222. package/dist/workers/language/tokenization.js +0 -189
  223. package/dist/workers/language/tsMode.js +0 -212
  224. package/dist/workers/language/tsWorker.js +0 -352
  225. package/dist/workers/language/typescriptServices.js +0 -210154
  226. package/dist/workers/language/typescriptServicesMetadata.js +0 -3
  227. package/dist/workers/language/workerManager.js +0 -65
  228. /package/dist/workers/{language/css.worker.js → css.worker.js} +0 -0
  229. /package/dist/workers/{editor/editor.worker.js → editor.worker.js} +0 -0
  230. /package/dist/workers/{language/html.worker.js → html.worker.js} +0 -0
  231. /package/dist/workers/{language/json.worker.js → json.worker.js} +0 -0
  232. /package/dist/workers/{language/ts.worker.js → ts.worker.js} +0 -0
@@ -1,1473 +0,0 @@
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 };