main.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. (function (factory) {
  2. if (typeof module === "object" && typeof module.exports === "object") {
  3. var v = factory(require, exports);
  4. if (v !== undefined) module.exports = v;
  5. }
  6. else if (typeof define === "function" && define.amd) {
  7. define(["require", "exports"], factory);
  8. }
  9. })(function (require, exports) {
  10. /* --------------------------------------------------------------------------------------------
  11. * Copyright (c) Microsoft Corporation. All rights reserved.
  12. * Licensed under the MIT License. See License.txt in the project root for license information.
  13. * ------------------------------------------------------------------------------------------ */
  14. 'use strict';
  15. Object.defineProperty(exports, "__esModule", { value: true });
  16. var FullTextDocument = /** @class */ (function () {
  17. function FullTextDocument(uri, languageId, version, content) {
  18. this._uri = uri;
  19. this._languageId = languageId;
  20. this._version = version;
  21. this._content = content;
  22. this._lineOffsets = undefined;
  23. }
  24. Object.defineProperty(FullTextDocument.prototype, "uri", {
  25. get: function () {
  26. return this._uri;
  27. },
  28. enumerable: true,
  29. configurable: true
  30. });
  31. Object.defineProperty(FullTextDocument.prototype, "languageId", {
  32. get: function () {
  33. return this._languageId;
  34. },
  35. enumerable: true,
  36. configurable: true
  37. });
  38. Object.defineProperty(FullTextDocument.prototype, "version", {
  39. get: function () {
  40. return this._version;
  41. },
  42. enumerable: true,
  43. configurable: true
  44. });
  45. FullTextDocument.prototype.getText = function (range) {
  46. if (range) {
  47. var start = this.offsetAt(range.start);
  48. var end = this.offsetAt(range.end);
  49. return this._content.substring(start, end);
  50. }
  51. return this._content;
  52. };
  53. FullTextDocument.prototype.update = function (changes, version) {
  54. for (var _i = 0, changes_1 = changes; _i < changes_1.length; _i++) {
  55. var change = changes_1[_i];
  56. if (FullTextDocument.isIncremental(change)) {
  57. // makes sure start is before end
  58. var range = getWellformedRange(change.range);
  59. // update content
  60. var startOffset = this.offsetAt(range.start);
  61. var endOffset = this.offsetAt(range.end);
  62. this._content = this._content.substring(0, startOffset) + change.text + this._content.substring(endOffset, this._content.length);
  63. // update the offsets
  64. var startLine = Math.max(range.start.line, 0);
  65. var endLine = Math.max(range.end.line, 0);
  66. var lineOffsets = this._lineOffsets;
  67. var addedLineOffsets = computeLineOffsets(change.text, false, startOffset);
  68. if (endLine - startLine === addedLineOffsets.length) {
  69. for (var i = 0, len = addedLineOffsets.length; i < len; i++) {
  70. lineOffsets[i + startLine + 1] = addedLineOffsets[i];
  71. }
  72. }
  73. else {
  74. if (addedLineOffsets.length < 10000) {
  75. lineOffsets.splice.apply(lineOffsets, [startLine + 1, endLine - startLine].concat(addedLineOffsets));
  76. }
  77. else { // avoid too many arguments for splice
  78. this._lineOffsets = lineOffsets = lineOffsets.slice(0, startLine + 1).concat(addedLineOffsets, lineOffsets.slice(endLine + 1));
  79. }
  80. }
  81. var diff = change.text.length - (endOffset - startOffset);
  82. if (diff !== 0) {
  83. for (var i = startLine + 1 + addedLineOffsets.length, len = lineOffsets.length; i < len; i++) {
  84. lineOffsets[i] = lineOffsets[i] + diff;
  85. }
  86. }
  87. }
  88. else if (FullTextDocument.isFull(change)) {
  89. this._content = change.text;
  90. this._lineOffsets = undefined;
  91. }
  92. else {
  93. throw new Error('Unknown change event received');
  94. }
  95. }
  96. this._version = version;
  97. };
  98. FullTextDocument.prototype.getLineOffsets = function () {
  99. if (this._lineOffsets === undefined) {
  100. this._lineOffsets = computeLineOffsets(this._content, true);
  101. }
  102. return this._lineOffsets;
  103. };
  104. FullTextDocument.prototype.positionAt = function (offset) {
  105. offset = Math.max(Math.min(offset, this._content.length), 0);
  106. var lineOffsets = this.getLineOffsets();
  107. var low = 0, high = lineOffsets.length;
  108. if (high === 0) {
  109. return { line: 0, character: offset };
  110. }
  111. while (low < high) {
  112. var mid = Math.floor((low + high) / 2);
  113. if (lineOffsets[mid] > offset) {
  114. high = mid;
  115. }
  116. else {
  117. low = mid + 1;
  118. }
  119. }
  120. // low is the least x for which the line offset is larger than the current offset
  121. // or array.length if no line offset is larger than the current offset
  122. var line = low - 1;
  123. return { line: line, character: offset - lineOffsets[line] };
  124. };
  125. FullTextDocument.prototype.offsetAt = function (position) {
  126. var lineOffsets = this.getLineOffsets();
  127. if (position.line >= lineOffsets.length) {
  128. return this._content.length;
  129. }
  130. else if (position.line < 0) {
  131. return 0;
  132. }
  133. var lineOffset = lineOffsets[position.line];
  134. var nextLineOffset = (position.line + 1 < lineOffsets.length) ? lineOffsets[position.line + 1] : this._content.length;
  135. return Math.max(Math.min(lineOffset + position.character, nextLineOffset), lineOffset);
  136. };
  137. Object.defineProperty(FullTextDocument.prototype, "lineCount", {
  138. get: function () {
  139. return this.getLineOffsets().length;
  140. },
  141. enumerable: true,
  142. configurable: true
  143. });
  144. FullTextDocument.isIncremental = function (event) {
  145. var candidate = event;
  146. return candidate !== undefined && candidate !== null &&
  147. typeof candidate.text === 'string' && candidate.range !== undefined &&
  148. (candidate.rangeLength === undefined || typeof candidate.rangeLength === 'number');
  149. };
  150. FullTextDocument.isFull = function (event) {
  151. var candidate = event;
  152. return candidate !== undefined && candidate !== null &&
  153. typeof candidate.text === 'string' && candidate.range === undefined && candidate.rangeLength === undefined;
  154. };
  155. return FullTextDocument;
  156. }());
  157. var TextDocument;
  158. (function (TextDocument) {
  159. /**
  160. * Creates a new text document.
  161. *
  162. * @param uri The document's uri.
  163. * @param languageId The document's language Id.
  164. * @param version The document's initial version number.
  165. * @param content The document's content.
  166. */
  167. function create(uri, languageId, version, content) {
  168. return new FullTextDocument(uri, languageId, version, content);
  169. }
  170. TextDocument.create = create;
  171. /**
  172. * Updates a TextDocument by modifing its content.
  173. *
  174. * @param document the document to update. Only documents created by TextDocument.create are valid inputs.
  175. * @param changes the changes to apply to the document.
  176. * @returns The updated TextDocument. Note: That's the same document instance passed in as first parameter.
  177. *
  178. */
  179. function update(document, changes, version) {
  180. if (document instanceof FullTextDocument) {
  181. document.update(changes, version);
  182. return document;
  183. }
  184. else {
  185. throw new Error('TextDocument.update: document must be created by TextDocument.create');
  186. }
  187. }
  188. TextDocument.update = update;
  189. function applyEdits(document, edits) {
  190. var text = document.getText();
  191. var sortedEdits = mergeSort(edits.map(getWellformedEdit), function (a, b) {
  192. var diff = a.range.start.line - b.range.start.line;
  193. if (diff === 0) {
  194. return a.range.start.character - b.range.start.character;
  195. }
  196. return diff;
  197. });
  198. var lastModifiedOffset = 0;
  199. var spans = [];
  200. for (var _i = 0, sortedEdits_1 = sortedEdits; _i < sortedEdits_1.length; _i++) {
  201. var e = sortedEdits_1[_i];
  202. var startOffset = document.offsetAt(e.range.start);
  203. if (startOffset < lastModifiedOffset) {
  204. throw new Error('Overlapping edit');
  205. }
  206. else if (startOffset > lastModifiedOffset) {
  207. spans.push(text.substring(lastModifiedOffset, startOffset));
  208. }
  209. if (e.newText.length) {
  210. spans.push(e.newText);
  211. }
  212. lastModifiedOffset = document.offsetAt(e.range.end);
  213. }
  214. spans.push(text.substr(lastModifiedOffset));
  215. return spans.join('');
  216. }
  217. TextDocument.applyEdits = applyEdits;
  218. })(TextDocument = exports.TextDocument || (exports.TextDocument = {}));
  219. function mergeSort(data, compare) {
  220. if (data.length <= 1) {
  221. // sorted
  222. return data;
  223. }
  224. var p = (data.length / 2) | 0;
  225. var left = data.slice(0, p);
  226. var right = data.slice(p);
  227. mergeSort(left, compare);
  228. mergeSort(right, compare);
  229. var leftIdx = 0;
  230. var rightIdx = 0;
  231. var i = 0;
  232. while (leftIdx < left.length && rightIdx < right.length) {
  233. var ret = compare(left[leftIdx], right[rightIdx]);
  234. if (ret <= 0) {
  235. // smaller_equal -> take left to preserve order
  236. data[i++] = left[leftIdx++];
  237. }
  238. else {
  239. // greater -> take right
  240. data[i++] = right[rightIdx++];
  241. }
  242. }
  243. while (leftIdx < left.length) {
  244. data[i++] = left[leftIdx++];
  245. }
  246. while (rightIdx < right.length) {
  247. data[i++] = right[rightIdx++];
  248. }
  249. return data;
  250. }
  251. function computeLineOffsets(text, isAtLineStart, textOffset) {
  252. if (textOffset === void 0) { textOffset = 0; }
  253. var result = isAtLineStart ? [textOffset] : [];
  254. for (var i = 0; i < text.length; i++) {
  255. var ch = text.charCodeAt(i);
  256. if (ch === 13 /* CarriageReturn */ || ch === 10 /* LineFeed */) {
  257. if (ch === 13 /* CarriageReturn */ && i + 1 < text.length && text.charCodeAt(i + 1) === 10 /* LineFeed */) {
  258. i++;
  259. }
  260. result.push(textOffset + i + 1);
  261. }
  262. }
  263. return result;
  264. }
  265. function getWellformedRange(range) {
  266. var start = range.start;
  267. var end = range.end;
  268. if (start.line > end.line || (start.line === end.line && start.character > end.character)) {
  269. return { start: end, end: start };
  270. }
  271. return range;
  272. }
  273. function getWellformedEdit(textEdit) {
  274. var range = getWellformedRange(textEdit.range);
  275. if (range !== textEdit.range) {
  276. return { newText: textEdit.newText, range: range };
  277. }
  278. return textEdit;
  279. }
  280. });