Upload folder using huggingface_hub (part 15)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +2 -0
- node_modules/monaco-editor/esm/vs/editor/common/model.js +133 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/decorationProvider.js +1 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/editStack.js +359 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/fixedArray.js +67 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/guidesTextModelPart.js +402 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/indentationGuesser.js +176 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/intervalTree.js +986 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/mirrorTextModel.js +114 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.js +1452 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.js +455 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.js +137 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase.js +360 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/prefixSumComputer.js +223 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/textModel.js +1899 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/textModelPart.js +20 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/textModelSearch.js +452 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/textModelText.js +20 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/textModelTokens.js +429 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/tokenizationTextModelPart.js +530 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/tokens.js +89 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/treeSitterTokens.js +79 -0
- node_modules/monaco-editor/esm/vs/editor/common/model/utils.js +31 -0
- node_modules/monaco-editor/esm/vs/editor/common/modelLineProjectionData.js +299 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/editorBaseApi.js +40 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/editorSimpleWorker.js +351 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/editorWorker.js +6 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/editorWorkerHost.js +13 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/findSectionHeaders.js +81 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/getIconClasses.js +103 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/languageFeatureDebounce.js +135 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/languageFeatures.js +6 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/languageFeaturesService.js +45 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/languageService.js +89 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/languagesAssociations.js +190 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/languagesRegistry.js +236 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/markerDecorations.js +6 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/markerDecorationsService.js +227 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/model.js +6 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/modelService.js +418 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/resolverService.js +2 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/semanticTokensDto.js +79 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/semanticTokensProviderStyling.js +276 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/semanticTokensStyling.js +6 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/semanticTokensStylingService.js +45 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/textModelSync/textModelSync.impl.js +304 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/textModelSync/textModelSync.protocol.js +5 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/textResourceConfiguration.js +3 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/treeSitterParserService.js +2 -0
- node_modules/monaco-editor/esm/vs/editor/common/services/treeViewsDnd.js +22 -0
.gitattributes
CHANGED
|
@@ -56,3 +56,5 @@ node_modules/lightningcss-linux-x64-gnu/lightningcss.linux-x64-gnu.node filter=l
|
|
| 56 |
node_modules/lightningcss-linux-x64-musl/lightningcss.linux-x64-musl.node filter=lfs diff=lfs merge=lfs -text
|
| 57 |
node_modules/monaco-editor/dev/vs/editor/editor.main.js.map filter=lfs diff=lfs merge=lfs -text
|
| 58 |
node_modules/monaco-editor/dev/vs/language/typescript/tsWorker.js filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
| 56 |
node_modules/lightningcss-linux-x64-musl/lightningcss.linux-x64-musl.node filter=lfs diff=lfs merge=lfs -text
|
| 57 |
node_modules/monaco-editor/dev/vs/editor/editor.main.js.map filter=lfs diff=lfs merge=lfs -text
|
| 58 |
node_modules/monaco-editor/dev/vs/language/typescript/tsWorker.js filter=lfs diff=lfs merge=lfs -text
|
| 59 |
+
node_modules/monaco-editor/esm/vs/language/typescript/ts.worker.js filter=lfs diff=lfs merge=lfs -text
|
| 60 |
+
node_modules/monaco-editor/min-maps/vs/editor/editor.main.js.map filter=lfs diff=lfs merge=lfs -text
|
node_modules/monaco-editor/esm/vs/editor/common/model.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { equals } from '../../base/common/objects.js';
|
| 6 |
+
/**
|
| 7 |
+
* Vertical Lane in the overview ruler of the editor.
|
| 8 |
+
*/
|
| 9 |
+
export var OverviewRulerLane;
|
| 10 |
+
(function (OverviewRulerLane) {
|
| 11 |
+
OverviewRulerLane[OverviewRulerLane["Left"] = 1] = "Left";
|
| 12 |
+
OverviewRulerLane[OverviewRulerLane["Center"] = 2] = "Center";
|
| 13 |
+
OverviewRulerLane[OverviewRulerLane["Right"] = 4] = "Right";
|
| 14 |
+
OverviewRulerLane[OverviewRulerLane["Full"] = 7] = "Full";
|
| 15 |
+
})(OverviewRulerLane || (OverviewRulerLane = {}));
|
| 16 |
+
/**
|
| 17 |
+
* Vertical Lane in the glyph margin of the editor.
|
| 18 |
+
*/
|
| 19 |
+
export var GlyphMarginLane;
|
| 20 |
+
(function (GlyphMarginLane) {
|
| 21 |
+
GlyphMarginLane[GlyphMarginLane["Left"] = 1] = "Left";
|
| 22 |
+
GlyphMarginLane[GlyphMarginLane["Center"] = 2] = "Center";
|
| 23 |
+
GlyphMarginLane[GlyphMarginLane["Right"] = 3] = "Right";
|
| 24 |
+
})(GlyphMarginLane || (GlyphMarginLane = {}));
|
| 25 |
+
export var InjectedTextCursorStops;
|
| 26 |
+
(function (InjectedTextCursorStops) {
|
| 27 |
+
InjectedTextCursorStops[InjectedTextCursorStops["Both"] = 0] = "Both";
|
| 28 |
+
InjectedTextCursorStops[InjectedTextCursorStops["Right"] = 1] = "Right";
|
| 29 |
+
InjectedTextCursorStops[InjectedTextCursorStops["Left"] = 2] = "Left";
|
| 30 |
+
InjectedTextCursorStops[InjectedTextCursorStops["None"] = 3] = "None";
|
| 31 |
+
})(InjectedTextCursorStops || (InjectedTextCursorStops = {}));
|
| 32 |
+
export class TextModelResolvedOptions {
|
| 33 |
+
get originalIndentSize() {
|
| 34 |
+
return this._indentSizeIsTabSize ? 'tabSize' : this.indentSize;
|
| 35 |
+
}
|
| 36 |
+
/**
|
| 37 |
+
* @internal
|
| 38 |
+
*/
|
| 39 |
+
constructor(src) {
|
| 40 |
+
this._textModelResolvedOptionsBrand = undefined;
|
| 41 |
+
this.tabSize = Math.max(1, src.tabSize | 0);
|
| 42 |
+
if (src.indentSize === 'tabSize') {
|
| 43 |
+
this.indentSize = this.tabSize;
|
| 44 |
+
this._indentSizeIsTabSize = true;
|
| 45 |
+
}
|
| 46 |
+
else {
|
| 47 |
+
this.indentSize = Math.max(1, src.indentSize | 0);
|
| 48 |
+
this._indentSizeIsTabSize = false;
|
| 49 |
+
}
|
| 50 |
+
this.insertSpaces = Boolean(src.insertSpaces);
|
| 51 |
+
this.defaultEOL = src.defaultEOL | 0;
|
| 52 |
+
this.trimAutoWhitespace = Boolean(src.trimAutoWhitespace);
|
| 53 |
+
this.bracketPairColorizationOptions = src.bracketPairColorizationOptions;
|
| 54 |
+
}
|
| 55 |
+
/**
|
| 56 |
+
* @internal
|
| 57 |
+
*/
|
| 58 |
+
equals(other) {
|
| 59 |
+
return (this.tabSize === other.tabSize
|
| 60 |
+
&& this._indentSizeIsTabSize === other._indentSizeIsTabSize
|
| 61 |
+
&& this.indentSize === other.indentSize
|
| 62 |
+
&& this.insertSpaces === other.insertSpaces
|
| 63 |
+
&& this.defaultEOL === other.defaultEOL
|
| 64 |
+
&& this.trimAutoWhitespace === other.trimAutoWhitespace
|
| 65 |
+
&& equals(this.bracketPairColorizationOptions, other.bracketPairColorizationOptions));
|
| 66 |
+
}
|
| 67 |
+
/**
|
| 68 |
+
* @internal
|
| 69 |
+
*/
|
| 70 |
+
createChangeEvent(newOpts) {
|
| 71 |
+
return {
|
| 72 |
+
tabSize: this.tabSize !== newOpts.tabSize,
|
| 73 |
+
indentSize: this.indentSize !== newOpts.indentSize,
|
| 74 |
+
insertSpaces: this.insertSpaces !== newOpts.insertSpaces,
|
| 75 |
+
trimAutoWhitespace: this.trimAutoWhitespace !== newOpts.trimAutoWhitespace,
|
| 76 |
+
};
|
| 77 |
+
}
|
| 78 |
+
}
|
| 79 |
+
export class FindMatch {
|
| 80 |
+
/**
|
| 81 |
+
* @internal
|
| 82 |
+
*/
|
| 83 |
+
constructor(range, matches) {
|
| 84 |
+
this._findMatchBrand = undefined;
|
| 85 |
+
this.range = range;
|
| 86 |
+
this.matches = matches;
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
/**
|
| 90 |
+
* @internal
|
| 91 |
+
*/
|
| 92 |
+
export function isITextSnapshot(obj) {
|
| 93 |
+
return (obj && typeof obj.read === 'function');
|
| 94 |
+
}
|
| 95 |
+
/**
|
| 96 |
+
* @internal
|
| 97 |
+
*/
|
| 98 |
+
export class ValidAnnotatedEditOperation {
|
| 99 |
+
constructor(identifier, range, text, forceMoveMarkers, isAutoWhitespaceEdit, _isTracked) {
|
| 100 |
+
this.identifier = identifier;
|
| 101 |
+
this.range = range;
|
| 102 |
+
this.text = text;
|
| 103 |
+
this.forceMoveMarkers = forceMoveMarkers;
|
| 104 |
+
this.isAutoWhitespaceEdit = isAutoWhitespaceEdit;
|
| 105 |
+
this._isTracked = _isTracked;
|
| 106 |
+
}
|
| 107 |
+
}
|
| 108 |
+
/**
|
| 109 |
+
* @internal
|
| 110 |
+
*/
|
| 111 |
+
export class SearchData {
|
| 112 |
+
constructor(regex, wordSeparators, simpleSearch) {
|
| 113 |
+
this.regex = regex;
|
| 114 |
+
this.wordSeparators = wordSeparators;
|
| 115 |
+
this.simpleSearch = simpleSearch;
|
| 116 |
+
}
|
| 117 |
+
}
|
| 118 |
+
/**
|
| 119 |
+
* @internal
|
| 120 |
+
*/
|
| 121 |
+
export class ApplyEditsResult {
|
| 122 |
+
constructor(reverseEdits, changes, trimAutoWhitespaceLineNumbers) {
|
| 123 |
+
this.reverseEdits = reverseEdits;
|
| 124 |
+
this.changes = changes;
|
| 125 |
+
this.trimAutoWhitespaceLineNumbers = trimAutoWhitespaceLineNumbers;
|
| 126 |
+
}
|
| 127 |
+
}
|
| 128 |
+
/**
|
| 129 |
+
* @internal
|
| 130 |
+
*/
|
| 131 |
+
export function shouldSynchronizeModel(model) {
|
| 132 |
+
return (!model.isTooLargeForSyncing() && !model.isForSimpleWidget);
|
| 133 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/decorationProvider.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
export {};
|
node_modules/monaco-editor/esm/vs/editor/common/model/editStack.js
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import * as nls from '../../../nls.js';
|
| 6 |
+
import { onUnexpectedError } from '../../../base/common/errors.js';
|
| 7 |
+
import { Selection } from '../core/selection.js';
|
| 8 |
+
import { URI } from '../../../base/common/uri.js';
|
| 9 |
+
import { TextChange, compressConsecutiveTextChanges } from '../core/textChange.js';
|
| 10 |
+
import * as buffer from '../../../base/common/buffer.js';
|
| 11 |
+
import { basename } from '../../../base/common/resources.js';
|
| 12 |
+
function uriGetComparisonKey(resource) {
|
| 13 |
+
return resource.toString();
|
| 14 |
+
}
|
| 15 |
+
export class SingleModelEditStackData {
|
| 16 |
+
static create(model, beforeCursorState) {
|
| 17 |
+
const alternativeVersionId = model.getAlternativeVersionId();
|
| 18 |
+
const eol = getModelEOL(model);
|
| 19 |
+
return new SingleModelEditStackData(alternativeVersionId, alternativeVersionId, eol, eol, beforeCursorState, beforeCursorState, []);
|
| 20 |
+
}
|
| 21 |
+
constructor(beforeVersionId, afterVersionId, beforeEOL, afterEOL, beforeCursorState, afterCursorState, changes) {
|
| 22 |
+
this.beforeVersionId = beforeVersionId;
|
| 23 |
+
this.afterVersionId = afterVersionId;
|
| 24 |
+
this.beforeEOL = beforeEOL;
|
| 25 |
+
this.afterEOL = afterEOL;
|
| 26 |
+
this.beforeCursorState = beforeCursorState;
|
| 27 |
+
this.afterCursorState = afterCursorState;
|
| 28 |
+
this.changes = changes;
|
| 29 |
+
}
|
| 30 |
+
append(model, textChanges, afterEOL, afterVersionId, afterCursorState) {
|
| 31 |
+
if (textChanges.length > 0) {
|
| 32 |
+
this.changes = compressConsecutiveTextChanges(this.changes, textChanges);
|
| 33 |
+
}
|
| 34 |
+
this.afterEOL = afterEOL;
|
| 35 |
+
this.afterVersionId = afterVersionId;
|
| 36 |
+
this.afterCursorState = afterCursorState;
|
| 37 |
+
}
|
| 38 |
+
static _writeSelectionsSize(selections) {
|
| 39 |
+
return 4 + 4 * 4 * (selections ? selections.length : 0);
|
| 40 |
+
}
|
| 41 |
+
static _writeSelections(b, selections, offset) {
|
| 42 |
+
buffer.writeUInt32BE(b, (selections ? selections.length : 0), offset);
|
| 43 |
+
offset += 4;
|
| 44 |
+
if (selections) {
|
| 45 |
+
for (const selection of selections) {
|
| 46 |
+
buffer.writeUInt32BE(b, selection.selectionStartLineNumber, offset);
|
| 47 |
+
offset += 4;
|
| 48 |
+
buffer.writeUInt32BE(b, selection.selectionStartColumn, offset);
|
| 49 |
+
offset += 4;
|
| 50 |
+
buffer.writeUInt32BE(b, selection.positionLineNumber, offset);
|
| 51 |
+
offset += 4;
|
| 52 |
+
buffer.writeUInt32BE(b, selection.positionColumn, offset);
|
| 53 |
+
offset += 4;
|
| 54 |
+
}
|
| 55 |
+
}
|
| 56 |
+
return offset;
|
| 57 |
+
}
|
| 58 |
+
static _readSelections(b, offset, dest) {
|
| 59 |
+
const count = buffer.readUInt32BE(b, offset);
|
| 60 |
+
offset += 4;
|
| 61 |
+
for (let i = 0; i < count; i++) {
|
| 62 |
+
const selectionStartLineNumber = buffer.readUInt32BE(b, offset);
|
| 63 |
+
offset += 4;
|
| 64 |
+
const selectionStartColumn = buffer.readUInt32BE(b, offset);
|
| 65 |
+
offset += 4;
|
| 66 |
+
const positionLineNumber = buffer.readUInt32BE(b, offset);
|
| 67 |
+
offset += 4;
|
| 68 |
+
const positionColumn = buffer.readUInt32BE(b, offset);
|
| 69 |
+
offset += 4;
|
| 70 |
+
dest.push(new Selection(selectionStartLineNumber, selectionStartColumn, positionLineNumber, positionColumn));
|
| 71 |
+
}
|
| 72 |
+
return offset;
|
| 73 |
+
}
|
| 74 |
+
serialize() {
|
| 75 |
+
let necessarySize = (+4 // beforeVersionId
|
| 76 |
+
+ 4 // afterVersionId
|
| 77 |
+
+ 1 // beforeEOL
|
| 78 |
+
+ 1 // afterEOL
|
| 79 |
+
+ SingleModelEditStackData._writeSelectionsSize(this.beforeCursorState)
|
| 80 |
+
+ SingleModelEditStackData._writeSelectionsSize(this.afterCursorState)
|
| 81 |
+
+ 4 // change count
|
| 82 |
+
);
|
| 83 |
+
for (const change of this.changes) {
|
| 84 |
+
necessarySize += change.writeSize();
|
| 85 |
+
}
|
| 86 |
+
const b = new Uint8Array(necessarySize);
|
| 87 |
+
let offset = 0;
|
| 88 |
+
buffer.writeUInt32BE(b, this.beforeVersionId, offset);
|
| 89 |
+
offset += 4;
|
| 90 |
+
buffer.writeUInt32BE(b, this.afterVersionId, offset);
|
| 91 |
+
offset += 4;
|
| 92 |
+
buffer.writeUInt8(b, this.beforeEOL, offset);
|
| 93 |
+
offset += 1;
|
| 94 |
+
buffer.writeUInt8(b, this.afterEOL, offset);
|
| 95 |
+
offset += 1;
|
| 96 |
+
offset = SingleModelEditStackData._writeSelections(b, this.beforeCursorState, offset);
|
| 97 |
+
offset = SingleModelEditStackData._writeSelections(b, this.afterCursorState, offset);
|
| 98 |
+
buffer.writeUInt32BE(b, this.changes.length, offset);
|
| 99 |
+
offset += 4;
|
| 100 |
+
for (const change of this.changes) {
|
| 101 |
+
offset = change.write(b, offset);
|
| 102 |
+
}
|
| 103 |
+
return b.buffer;
|
| 104 |
+
}
|
| 105 |
+
static deserialize(source) {
|
| 106 |
+
const b = new Uint8Array(source);
|
| 107 |
+
let offset = 0;
|
| 108 |
+
const beforeVersionId = buffer.readUInt32BE(b, offset);
|
| 109 |
+
offset += 4;
|
| 110 |
+
const afterVersionId = buffer.readUInt32BE(b, offset);
|
| 111 |
+
offset += 4;
|
| 112 |
+
const beforeEOL = buffer.readUInt8(b, offset);
|
| 113 |
+
offset += 1;
|
| 114 |
+
const afterEOL = buffer.readUInt8(b, offset);
|
| 115 |
+
offset += 1;
|
| 116 |
+
const beforeCursorState = [];
|
| 117 |
+
offset = SingleModelEditStackData._readSelections(b, offset, beforeCursorState);
|
| 118 |
+
const afterCursorState = [];
|
| 119 |
+
offset = SingleModelEditStackData._readSelections(b, offset, afterCursorState);
|
| 120 |
+
const changeCount = buffer.readUInt32BE(b, offset);
|
| 121 |
+
offset += 4;
|
| 122 |
+
const changes = [];
|
| 123 |
+
for (let i = 0; i < changeCount; i++) {
|
| 124 |
+
offset = TextChange.read(b, offset, changes);
|
| 125 |
+
}
|
| 126 |
+
return new SingleModelEditStackData(beforeVersionId, afterVersionId, beforeEOL, afterEOL, beforeCursorState, afterCursorState, changes);
|
| 127 |
+
}
|
| 128 |
+
}
|
| 129 |
+
export class SingleModelEditStackElement {
|
| 130 |
+
get type() {
|
| 131 |
+
return 0 /* UndoRedoElementType.Resource */;
|
| 132 |
+
}
|
| 133 |
+
get resource() {
|
| 134 |
+
if (URI.isUri(this.model)) {
|
| 135 |
+
return this.model;
|
| 136 |
+
}
|
| 137 |
+
return this.model.uri;
|
| 138 |
+
}
|
| 139 |
+
constructor(label, code, model, beforeCursorState) {
|
| 140 |
+
this.label = label;
|
| 141 |
+
this.code = code;
|
| 142 |
+
this.model = model;
|
| 143 |
+
this._data = SingleModelEditStackData.create(model, beforeCursorState);
|
| 144 |
+
}
|
| 145 |
+
toString() {
|
| 146 |
+
const data = (this._data instanceof SingleModelEditStackData ? this._data : SingleModelEditStackData.deserialize(this._data));
|
| 147 |
+
return data.changes.map(change => change.toString()).join(', ');
|
| 148 |
+
}
|
| 149 |
+
matchesResource(resource) {
|
| 150 |
+
const uri = (URI.isUri(this.model) ? this.model : this.model.uri);
|
| 151 |
+
return (uri.toString() === resource.toString());
|
| 152 |
+
}
|
| 153 |
+
setModel(model) {
|
| 154 |
+
this.model = model;
|
| 155 |
+
}
|
| 156 |
+
canAppend(model) {
|
| 157 |
+
return (this.model === model && this._data instanceof SingleModelEditStackData);
|
| 158 |
+
}
|
| 159 |
+
append(model, textChanges, afterEOL, afterVersionId, afterCursorState) {
|
| 160 |
+
if (this._data instanceof SingleModelEditStackData) {
|
| 161 |
+
this._data.append(model, textChanges, afterEOL, afterVersionId, afterCursorState);
|
| 162 |
+
}
|
| 163 |
+
}
|
| 164 |
+
close() {
|
| 165 |
+
if (this._data instanceof SingleModelEditStackData) {
|
| 166 |
+
this._data = this._data.serialize();
|
| 167 |
+
}
|
| 168 |
+
}
|
| 169 |
+
open() {
|
| 170 |
+
if (!(this._data instanceof SingleModelEditStackData)) {
|
| 171 |
+
this._data = SingleModelEditStackData.deserialize(this._data);
|
| 172 |
+
}
|
| 173 |
+
}
|
| 174 |
+
undo() {
|
| 175 |
+
if (URI.isUri(this.model)) {
|
| 176 |
+
// don't have a model
|
| 177 |
+
throw new Error(`Invalid SingleModelEditStackElement`);
|
| 178 |
+
}
|
| 179 |
+
if (this._data instanceof SingleModelEditStackData) {
|
| 180 |
+
this._data = this._data.serialize();
|
| 181 |
+
}
|
| 182 |
+
const data = SingleModelEditStackData.deserialize(this._data);
|
| 183 |
+
this.model._applyUndo(data.changes, data.beforeEOL, data.beforeVersionId, data.beforeCursorState);
|
| 184 |
+
}
|
| 185 |
+
redo() {
|
| 186 |
+
if (URI.isUri(this.model)) {
|
| 187 |
+
// don't have a model
|
| 188 |
+
throw new Error(`Invalid SingleModelEditStackElement`);
|
| 189 |
+
}
|
| 190 |
+
if (this._data instanceof SingleModelEditStackData) {
|
| 191 |
+
this._data = this._data.serialize();
|
| 192 |
+
}
|
| 193 |
+
const data = SingleModelEditStackData.deserialize(this._data);
|
| 194 |
+
this.model._applyRedo(data.changes, data.afterEOL, data.afterVersionId, data.afterCursorState);
|
| 195 |
+
}
|
| 196 |
+
heapSize() {
|
| 197 |
+
if (this._data instanceof SingleModelEditStackData) {
|
| 198 |
+
this._data = this._data.serialize();
|
| 199 |
+
}
|
| 200 |
+
return this._data.byteLength + 168 /*heap overhead*/;
|
| 201 |
+
}
|
| 202 |
+
}
|
| 203 |
+
export class MultiModelEditStackElement {
|
| 204 |
+
get resources() {
|
| 205 |
+
return this._editStackElementsArr.map(editStackElement => editStackElement.resource);
|
| 206 |
+
}
|
| 207 |
+
constructor(label, code, editStackElements) {
|
| 208 |
+
this.label = label;
|
| 209 |
+
this.code = code;
|
| 210 |
+
this.type = 1 /* UndoRedoElementType.Workspace */;
|
| 211 |
+
this._isOpen = true;
|
| 212 |
+
this._editStackElementsArr = editStackElements.slice(0);
|
| 213 |
+
this._editStackElementsMap = new Map();
|
| 214 |
+
for (const editStackElement of this._editStackElementsArr) {
|
| 215 |
+
const key = uriGetComparisonKey(editStackElement.resource);
|
| 216 |
+
this._editStackElementsMap.set(key, editStackElement);
|
| 217 |
+
}
|
| 218 |
+
this._delegate = null;
|
| 219 |
+
}
|
| 220 |
+
prepareUndoRedo() {
|
| 221 |
+
if (this._delegate) {
|
| 222 |
+
return this._delegate.prepareUndoRedo(this);
|
| 223 |
+
}
|
| 224 |
+
}
|
| 225 |
+
matchesResource(resource) {
|
| 226 |
+
const key = uriGetComparisonKey(resource);
|
| 227 |
+
return (this._editStackElementsMap.has(key));
|
| 228 |
+
}
|
| 229 |
+
setModel(model) {
|
| 230 |
+
const key = uriGetComparisonKey(URI.isUri(model) ? model : model.uri);
|
| 231 |
+
if (this._editStackElementsMap.has(key)) {
|
| 232 |
+
this._editStackElementsMap.get(key).setModel(model);
|
| 233 |
+
}
|
| 234 |
+
}
|
| 235 |
+
canAppend(model) {
|
| 236 |
+
if (!this._isOpen) {
|
| 237 |
+
return false;
|
| 238 |
+
}
|
| 239 |
+
const key = uriGetComparisonKey(model.uri);
|
| 240 |
+
if (this._editStackElementsMap.has(key)) {
|
| 241 |
+
const editStackElement = this._editStackElementsMap.get(key);
|
| 242 |
+
return editStackElement.canAppend(model);
|
| 243 |
+
}
|
| 244 |
+
return false;
|
| 245 |
+
}
|
| 246 |
+
append(model, textChanges, afterEOL, afterVersionId, afterCursorState) {
|
| 247 |
+
const key = uriGetComparisonKey(model.uri);
|
| 248 |
+
const editStackElement = this._editStackElementsMap.get(key);
|
| 249 |
+
editStackElement.append(model, textChanges, afterEOL, afterVersionId, afterCursorState);
|
| 250 |
+
}
|
| 251 |
+
close() {
|
| 252 |
+
this._isOpen = false;
|
| 253 |
+
}
|
| 254 |
+
open() {
|
| 255 |
+
// cannot reopen
|
| 256 |
+
}
|
| 257 |
+
undo() {
|
| 258 |
+
this._isOpen = false;
|
| 259 |
+
for (const editStackElement of this._editStackElementsArr) {
|
| 260 |
+
editStackElement.undo();
|
| 261 |
+
}
|
| 262 |
+
}
|
| 263 |
+
redo() {
|
| 264 |
+
for (const editStackElement of this._editStackElementsArr) {
|
| 265 |
+
editStackElement.redo();
|
| 266 |
+
}
|
| 267 |
+
}
|
| 268 |
+
heapSize(resource) {
|
| 269 |
+
const key = uriGetComparisonKey(resource);
|
| 270 |
+
if (this._editStackElementsMap.has(key)) {
|
| 271 |
+
const editStackElement = this._editStackElementsMap.get(key);
|
| 272 |
+
return editStackElement.heapSize();
|
| 273 |
+
}
|
| 274 |
+
return 0;
|
| 275 |
+
}
|
| 276 |
+
split() {
|
| 277 |
+
return this._editStackElementsArr;
|
| 278 |
+
}
|
| 279 |
+
toString() {
|
| 280 |
+
const result = [];
|
| 281 |
+
for (const editStackElement of this._editStackElementsArr) {
|
| 282 |
+
result.push(`${basename(editStackElement.resource)}: ${editStackElement}`);
|
| 283 |
+
}
|
| 284 |
+
return `{${result.join(', ')}}`;
|
| 285 |
+
}
|
| 286 |
+
}
|
| 287 |
+
function getModelEOL(model) {
|
| 288 |
+
const eol = model.getEOL();
|
| 289 |
+
if (eol === '\n') {
|
| 290 |
+
return 0 /* EndOfLineSequence.LF */;
|
| 291 |
+
}
|
| 292 |
+
else {
|
| 293 |
+
return 1 /* EndOfLineSequence.CRLF */;
|
| 294 |
+
}
|
| 295 |
+
}
|
| 296 |
+
export function isEditStackElement(element) {
|
| 297 |
+
if (!element) {
|
| 298 |
+
return false;
|
| 299 |
+
}
|
| 300 |
+
return ((element instanceof SingleModelEditStackElement) || (element instanceof MultiModelEditStackElement));
|
| 301 |
+
}
|
| 302 |
+
export class EditStack {
|
| 303 |
+
constructor(model, undoRedoService) {
|
| 304 |
+
this._model = model;
|
| 305 |
+
this._undoRedoService = undoRedoService;
|
| 306 |
+
}
|
| 307 |
+
pushStackElement() {
|
| 308 |
+
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
|
| 309 |
+
if (isEditStackElement(lastElement)) {
|
| 310 |
+
lastElement.close();
|
| 311 |
+
}
|
| 312 |
+
}
|
| 313 |
+
popStackElement() {
|
| 314 |
+
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
|
| 315 |
+
if (isEditStackElement(lastElement)) {
|
| 316 |
+
lastElement.open();
|
| 317 |
+
}
|
| 318 |
+
}
|
| 319 |
+
clear() {
|
| 320 |
+
this._undoRedoService.removeElements(this._model.uri);
|
| 321 |
+
}
|
| 322 |
+
_getOrCreateEditStackElement(beforeCursorState, group) {
|
| 323 |
+
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
|
| 324 |
+
if (isEditStackElement(lastElement) && lastElement.canAppend(this._model)) {
|
| 325 |
+
return lastElement;
|
| 326 |
+
}
|
| 327 |
+
const newElement = new SingleModelEditStackElement(nls.localize('edit', "Typing"), 'undoredo.textBufferEdit', this._model, beforeCursorState);
|
| 328 |
+
this._undoRedoService.pushElement(newElement, group);
|
| 329 |
+
return newElement;
|
| 330 |
+
}
|
| 331 |
+
pushEOL(eol) {
|
| 332 |
+
const editStackElement = this._getOrCreateEditStackElement(null, undefined);
|
| 333 |
+
this._model.setEOL(eol);
|
| 334 |
+
editStackElement.append(this._model, [], getModelEOL(this._model), this._model.getAlternativeVersionId(), null);
|
| 335 |
+
}
|
| 336 |
+
pushEditOperation(beforeCursorState, editOperations, cursorStateComputer, group) {
|
| 337 |
+
const editStackElement = this._getOrCreateEditStackElement(beforeCursorState, group);
|
| 338 |
+
const inverseEditOperations = this._model.applyEdits(editOperations, true);
|
| 339 |
+
const afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperations);
|
| 340 |
+
const textChanges = inverseEditOperations.map((op, index) => ({ index: index, textChange: op.textChange }));
|
| 341 |
+
textChanges.sort((a, b) => {
|
| 342 |
+
if (a.textChange.oldPosition === b.textChange.oldPosition) {
|
| 343 |
+
return a.index - b.index;
|
| 344 |
+
}
|
| 345 |
+
return a.textChange.oldPosition - b.textChange.oldPosition;
|
| 346 |
+
});
|
| 347 |
+
editStackElement.append(this._model, textChanges.map(op => op.textChange), getModelEOL(this._model), this._model.getAlternativeVersionId(), afterCursorState);
|
| 348 |
+
return afterCursorState;
|
| 349 |
+
}
|
| 350 |
+
static _computeCursorState(cursorStateComputer, inverseEditOperations) {
|
| 351 |
+
try {
|
| 352 |
+
return cursorStateComputer ? cursorStateComputer(inverseEditOperations) : null;
|
| 353 |
+
}
|
| 354 |
+
catch (e) {
|
| 355 |
+
onUnexpectedError(e);
|
| 356 |
+
return null;
|
| 357 |
+
}
|
| 358 |
+
}
|
| 359 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/fixedArray.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { arrayInsert } from '../../../base/common/arrays.js';
|
| 6 |
+
/**
|
| 7 |
+
* An array that avoids being sparse by always
|
| 8 |
+
* filling up unused indices with a default value.
|
| 9 |
+
*/
|
| 10 |
+
export class FixedArray {
|
| 11 |
+
constructor(_default) {
|
| 12 |
+
this._default = _default;
|
| 13 |
+
this._store = [];
|
| 14 |
+
}
|
| 15 |
+
get(index) {
|
| 16 |
+
if (index < this._store.length) {
|
| 17 |
+
return this._store[index];
|
| 18 |
+
}
|
| 19 |
+
return this._default;
|
| 20 |
+
}
|
| 21 |
+
set(index, value) {
|
| 22 |
+
while (index >= this._store.length) {
|
| 23 |
+
this._store[this._store.length] = this._default;
|
| 24 |
+
}
|
| 25 |
+
this._store[index] = value;
|
| 26 |
+
}
|
| 27 |
+
replace(index, oldLength, newLength) {
|
| 28 |
+
if (index >= this._store.length) {
|
| 29 |
+
return;
|
| 30 |
+
}
|
| 31 |
+
if (oldLength === 0) {
|
| 32 |
+
this.insert(index, newLength);
|
| 33 |
+
return;
|
| 34 |
+
}
|
| 35 |
+
else if (newLength === 0) {
|
| 36 |
+
this.delete(index, oldLength);
|
| 37 |
+
return;
|
| 38 |
+
}
|
| 39 |
+
const before = this._store.slice(0, index);
|
| 40 |
+
const after = this._store.slice(index + oldLength);
|
| 41 |
+
const insertArr = arrayFill(newLength, this._default);
|
| 42 |
+
this._store = before.concat(insertArr, after);
|
| 43 |
+
}
|
| 44 |
+
delete(deleteIndex, deleteCount) {
|
| 45 |
+
if (deleteCount === 0 || deleteIndex >= this._store.length) {
|
| 46 |
+
return;
|
| 47 |
+
}
|
| 48 |
+
this._store.splice(deleteIndex, deleteCount);
|
| 49 |
+
}
|
| 50 |
+
insert(insertIndex, insertCount) {
|
| 51 |
+
if (insertCount === 0 || insertIndex >= this._store.length) {
|
| 52 |
+
return;
|
| 53 |
+
}
|
| 54 |
+
const arr = [];
|
| 55 |
+
for (let i = 0; i < insertCount; i++) {
|
| 56 |
+
arr[i] = this._default;
|
| 57 |
+
}
|
| 58 |
+
this._store = arrayInsert(this._store, insertIndex, arr);
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
function arrayFill(length, value) {
|
| 62 |
+
const arr = [];
|
| 63 |
+
for (let i = 0; i < length; i++) {
|
| 64 |
+
arr[i] = value;
|
| 65 |
+
}
|
| 66 |
+
return arr;
|
| 67 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/guidesTextModelPart.js
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { findLast } from '../../../base/common/arraysFind.js';
|
| 6 |
+
import * as strings from '../../../base/common/strings.js';
|
| 7 |
+
import { CursorColumns } from '../core/cursorColumns.js';
|
| 8 |
+
import { Range } from '../core/range.js';
|
| 9 |
+
import { TextModelPart } from './textModelPart.js';
|
| 10 |
+
import { computeIndentLevel } from './utils.js';
|
| 11 |
+
import { HorizontalGuidesState, IndentGuide, IndentGuideHorizontalLine } from '../textModelGuides.js';
|
| 12 |
+
import { BugIndicatingError } from '../../../base/common/errors.js';
|
| 13 |
+
export class GuidesTextModelPart extends TextModelPart {
|
| 14 |
+
constructor(textModel, languageConfigurationService) {
|
| 15 |
+
super();
|
| 16 |
+
this.textModel = textModel;
|
| 17 |
+
this.languageConfigurationService = languageConfigurationService;
|
| 18 |
+
}
|
| 19 |
+
getLanguageConfiguration(languageId) {
|
| 20 |
+
return this.languageConfigurationService.getLanguageConfiguration(languageId);
|
| 21 |
+
}
|
| 22 |
+
_computeIndentLevel(lineIndex) {
|
| 23 |
+
return computeIndentLevel(this.textModel.getLineContent(lineIndex + 1), this.textModel.getOptions().tabSize);
|
| 24 |
+
}
|
| 25 |
+
getActiveIndentGuide(lineNumber, minLineNumber, maxLineNumber) {
|
| 26 |
+
this.assertNotDisposed();
|
| 27 |
+
const lineCount = this.textModel.getLineCount();
|
| 28 |
+
if (lineNumber < 1 || lineNumber > lineCount) {
|
| 29 |
+
throw new BugIndicatingError('Illegal value for lineNumber');
|
| 30 |
+
}
|
| 31 |
+
const foldingRules = this.getLanguageConfiguration(this.textModel.getLanguageId()).foldingRules;
|
| 32 |
+
const offSide = Boolean(foldingRules && foldingRules.offSide);
|
| 33 |
+
let up_aboveContentLineIndex = -2; /* -2 is a marker for not having computed it */
|
| 34 |
+
let up_aboveContentLineIndent = -1;
|
| 35 |
+
let up_belowContentLineIndex = -2; /* -2 is a marker for not having computed it */
|
| 36 |
+
let up_belowContentLineIndent = -1;
|
| 37 |
+
const up_resolveIndents = (lineNumber) => {
|
| 38 |
+
if (up_aboveContentLineIndex !== -1 &&
|
| 39 |
+
(up_aboveContentLineIndex === -2 ||
|
| 40 |
+
up_aboveContentLineIndex > lineNumber - 1)) {
|
| 41 |
+
up_aboveContentLineIndex = -1;
|
| 42 |
+
up_aboveContentLineIndent = -1;
|
| 43 |
+
// must find previous line with content
|
| 44 |
+
for (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) {
|
| 45 |
+
const indent = this._computeIndentLevel(lineIndex);
|
| 46 |
+
if (indent >= 0) {
|
| 47 |
+
up_aboveContentLineIndex = lineIndex;
|
| 48 |
+
up_aboveContentLineIndent = indent;
|
| 49 |
+
break;
|
| 50 |
+
}
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
if (up_belowContentLineIndex === -2) {
|
| 54 |
+
up_belowContentLineIndex = -1;
|
| 55 |
+
up_belowContentLineIndent = -1;
|
| 56 |
+
// must find next line with content
|
| 57 |
+
for (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) {
|
| 58 |
+
const indent = this._computeIndentLevel(lineIndex);
|
| 59 |
+
if (indent >= 0) {
|
| 60 |
+
up_belowContentLineIndex = lineIndex;
|
| 61 |
+
up_belowContentLineIndent = indent;
|
| 62 |
+
break;
|
| 63 |
+
}
|
| 64 |
+
}
|
| 65 |
+
}
|
| 66 |
+
};
|
| 67 |
+
let down_aboveContentLineIndex = -2; /* -2 is a marker for not having computed it */
|
| 68 |
+
let down_aboveContentLineIndent = -1;
|
| 69 |
+
let down_belowContentLineIndex = -2; /* -2 is a marker for not having computed it */
|
| 70 |
+
let down_belowContentLineIndent = -1;
|
| 71 |
+
const down_resolveIndents = (lineNumber) => {
|
| 72 |
+
if (down_aboveContentLineIndex === -2) {
|
| 73 |
+
down_aboveContentLineIndex = -1;
|
| 74 |
+
down_aboveContentLineIndent = -1;
|
| 75 |
+
// must find previous line with content
|
| 76 |
+
for (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) {
|
| 77 |
+
const indent = this._computeIndentLevel(lineIndex);
|
| 78 |
+
if (indent >= 0) {
|
| 79 |
+
down_aboveContentLineIndex = lineIndex;
|
| 80 |
+
down_aboveContentLineIndent = indent;
|
| 81 |
+
break;
|
| 82 |
+
}
|
| 83 |
+
}
|
| 84 |
+
}
|
| 85 |
+
if (down_belowContentLineIndex !== -1 &&
|
| 86 |
+
(down_belowContentLineIndex === -2 ||
|
| 87 |
+
down_belowContentLineIndex < lineNumber - 1)) {
|
| 88 |
+
down_belowContentLineIndex = -1;
|
| 89 |
+
down_belowContentLineIndent = -1;
|
| 90 |
+
// must find next line with content
|
| 91 |
+
for (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) {
|
| 92 |
+
const indent = this._computeIndentLevel(lineIndex);
|
| 93 |
+
if (indent >= 0) {
|
| 94 |
+
down_belowContentLineIndex = lineIndex;
|
| 95 |
+
down_belowContentLineIndent = indent;
|
| 96 |
+
break;
|
| 97 |
+
}
|
| 98 |
+
}
|
| 99 |
+
}
|
| 100 |
+
};
|
| 101 |
+
let startLineNumber = 0;
|
| 102 |
+
let goUp = true;
|
| 103 |
+
let endLineNumber = 0;
|
| 104 |
+
let goDown = true;
|
| 105 |
+
let indent = 0;
|
| 106 |
+
let initialIndent = 0;
|
| 107 |
+
for (let distance = 0; goUp || goDown; distance++) {
|
| 108 |
+
const upLineNumber = lineNumber - distance;
|
| 109 |
+
const downLineNumber = lineNumber + distance;
|
| 110 |
+
if (distance > 1 && (upLineNumber < 1 || upLineNumber < minLineNumber)) {
|
| 111 |
+
goUp = false;
|
| 112 |
+
}
|
| 113 |
+
if (distance > 1 &&
|
| 114 |
+
(downLineNumber > lineCount || downLineNumber > maxLineNumber)) {
|
| 115 |
+
goDown = false;
|
| 116 |
+
}
|
| 117 |
+
if (distance > 50000) {
|
| 118 |
+
// stop processing
|
| 119 |
+
goUp = false;
|
| 120 |
+
goDown = false;
|
| 121 |
+
}
|
| 122 |
+
let upLineIndentLevel = -1;
|
| 123 |
+
if (goUp && upLineNumber >= 1) {
|
| 124 |
+
// compute indent level going up
|
| 125 |
+
const currentIndent = this._computeIndentLevel(upLineNumber - 1);
|
| 126 |
+
if (currentIndent >= 0) {
|
| 127 |
+
// This line has content (besides whitespace)
|
| 128 |
+
// Use the line's indent
|
| 129 |
+
up_belowContentLineIndex = upLineNumber - 1;
|
| 130 |
+
up_belowContentLineIndent = currentIndent;
|
| 131 |
+
upLineIndentLevel = Math.ceil(currentIndent / this.textModel.getOptions().indentSize);
|
| 132 |
+
}
|
| 133 |
+
else {
|
| 134 |
+
up_resolveIndents(upLineNumber);
|
| 135 |
+
upLineIndentLevel = this._getIndentLevelForWhitespaceLine(offSide, up_aboveContentLineIndent, up_belowContentLineIndent);
|
| 136 |
+
}
|
| 137 |
+
}
|
| 138 |
+
let downLineIndentLevel = -1;
|
| 139 |
+
if (goDown && downLineNumber <= lineCount) {
|
| 140 |
+
// compute indent level going down
|
| 141 |
+
const currentIndent = this._computeIndentLevel(downLineNumber - 1);
|
| 142 |
+
if (currentIndent >= 0) {
|
| 143 |
+
// This line has content (besides whitespace)
|
| 144 |
+
// Use the line's indent
|
| 145 |
+
down_aboveContentLineIndex = downLineNumber - 1;
|
| 146 |
+
down_aboveContentLineIndent = currentIndent;
|
| 147 |
+
downLineIndentLevel = Math.ceil(currentIndent / this.textModel.getOptions().indentSize);
|
| 148 |
+
}
|
| 149 |
+
else {
|
| 150 |
+
down_resolveIndents(downLineNumber);
|
| 151 |
+
downLineIndentLevel = this._getIndentLevelForWhitespaceLine(offSide, down_aboveContentLineIndent, down_belowContentLineIndent);
|
| 152 |
+
}
|
| 153 |
+
}
|
| 154 |
+
if (distance === 0) {
|
| 155 |
+
initialIndent = upLineIndentLevel;
|
| 156 |
+
continue;
|
| 157 |
+
}
|
| 158 |
+
if (distance === 1) {
|
| 159 |
+
if (downLineNumber <= lineCount &&
|
| 160 |
+
downLineIndentLevel >= 0 &&
|
| 161 |
+
initialIndent + 1 === downLineIndentLevel) {
|
| 162 |
+
// This is the beginning of a scope, we have special handling here, since we want the
|
| 163 |
+
// child scope indent to be active, not the parent scope
|
| 164 |
+
goUp = false;
|
| 165 |
+
startLineNumber = downLineNumber;
|
| 166 |
+
endLineNumber = downLineNumber;
|
| 167 |
+
indent = downLineIndentLevel;
|
| 168 |
+
continue;
|
| 169 |
+
}
|
| 170 |
+
if (upLineNumber >= 1 &&
|
| 171 |
+
upLineIndentLevel >= 0 &&
|
| 172 |
+
upLineIndentLevel - 1 === initialIndent) {
|
| 173 |
+
// This is the end of a scope, just like above
|
| 174 |
+
goDown = false;
|
| 175 |
+
startLineNumber = upLineNumber;
|
| 176 |
+
endLineNumber = upLineNumber;
|
| 177 |
+
indent = upLineIndentLevel;
|
| 178 |
+
continue;
|
| 179 |
+
}
|
| 180 |
+
startLineNumber = lineNumber;
|
| 181 |
+
endLineNumber = lineNumber;
|
| 182 |
+
indent = initialIndent;
|
| 183 |
+
if (indent === 0) {
|
| 184 |
+
// No need to continue
|
| 185 |
+
return { startLineNumber, endLineNumber, indent };
|
| 186 |
+
}
|
| 187 |
+
}
|
| 188 |
+
if (goUp) {
|
| 189 |
+
if (upLineIndentLevel >= indent) {
|
| 190 |
+
startLineNumber = upLineNumber;
|
| 191 |
+
}
|
| 192 |
+
else {
|
| 193 |
+
goUp = false;
|
| 194 |
+
}
|
| 195 |
+
}
|
| 196 |
+
if (goDown) {
|
| 197 |
+
if (downLineIndentLevel >= indent) {
|
| 198 |
+
endLineNumber = downLineNumber;
|
| 199 |
+
}
|
| 200 |
+
else {
|
| 201 |
+
goDown = false;
|
| 202 |
+
}
|
| 203 |
+
}
|
| 204 |
+
}
|
| 205 |
+
return { startLineNumber, endLineNumber, indent };
|
| 206 |
+
}
|
| 207 |
+
getLinesBracketGuides(startLineNumber, endLineNumber, activePosition, options) {
|
| 208 |
+
const result = [];
|
| 209 |
+
for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {
|
| 210 |
+
result.push([]);
|
| 211 |
+
}
|
| 212 |
+
// If requested, this could be made configurable.
|
| 213 |
+
const includeSingleLinePairs = true;
|
| 214 |
+
const bracketPairs = this.textModel.bracketPairs.getBracketPairsInRangeWithMinIndentation(new Range(startLineNumber, 1, endLineNumber, this.textModel.getLineMaxColumn(endLineNumber))).toArray();
|
| 215 |
+
let activeBracketPairRange = undefined;
|
| 216 |
+
if (activePosition && bracketPairs.length > 0) {
|
| 217 |
+
const bracketsContainingActivePosition = (startLineNumber <= activePosition.lineNumber &&
|
| 218 |
+
activePosition.lineNumber <= endLineNumber
|
| 219 |
+
// We don't need to query the brackets again if the cursor is in the viewport
|
| 220 |
+
? bracketPairs
|
| 221 |
+
: this.textModel.bracketPairs.getBracketPairsInRange(Range.fromPositions(activePosition)).toArray()).filter((bp) => Range.strictContainsPosition(bp.range, activePosition));
|
| 222 |
+
activeBracketPairRange = findLast(bracketsContainingActivePosition, (i) => includeSingleLinePairs || i.range.startLineNumber !== i.range.endLineNumber)?.range;
|
| 223 |
+
}
|
| 224 |
+
const independentColorPoolPerBracketType = this.textModel.getOptions().bracketPairColorizationOptions.independentColorPoolPerBracketType;
|
| 225 |
+
const colorProvider = new BracketPairGuidesClassNames();
|
| 226 |
+
for (const pair of bracketPairs) {
|
| 227 |
+
/*
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
{
|
| 231 |
+
|
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
{
|
| 235 |
+
|
|
| 236 |
+
----}
|
| 237 |
+
|
| 238 |
+
____{
|
| 239 |
+
|test
|
| 240 |
+
----}
|
| 241 |
+
|
| 242 |
+
renderHorizontalEndLineAtTheBottom:
|
| 243 |
+
{
|
| 244 |
+
|
|
| 245 |
+
|x}
|
| 246 |
+
--
|
| 247 |
+
renderHorizontalEndLineAtTheBottom:
|
| 248 |
+
____{
|
| 249 |
+
|test
|
| 250 |
+
| x }
|
| 251 |
+
----
|
| 252 |
+
*/
|
| 253 |
+
if (!pair.closingBracketRange) {
|
| 254 |
+
continue;
|
| 255 |
+
}
|
| 256 |
+
const isActive = activeBracketPairRange && pair.range.equalsRange(activeBracketPairRange);
|
| 257 |
+
if (!isActive && !options.includeInactive) {
|
| 258 |
+
continue;
|
| 259 |
+
}
|
| 260 |
+
const className = colorProvider.getInlineClassName(pair.nestingLevel, pair.nestingLevelOfEqualBracketType, independentColorPoolPerBracketType) +
|
| 261 |
+
(options.highlightActive && isActive
|
| 262 |
+
? ' ' + colorProvider.activeClassName
|
| 263 |
+
: '');
|
| 264 |
+
const start = pair.openingBracketRange.getStartPosition();
|
| 265 |
+
const end = pair.closingBracketRange.getStartPosition();
|
| 266 |
+
const horizontalGuides = options.horizontalGuides === HorizontalGuidesState.Enabled || (options.horizontalGuides === HorizontalGuidesState.EnabledForActive && isActive);
|
| 267 |
+
if (pair.range.startLineNumber === pair.range.endLineNumber) {
|
| 268 |
+
if (includeSingleLinePairs && horizontalGuides) {
|
| 269 |
+
result[pair.range.startLineNumber - startLineNumber].push(new IndentGuide(-1, pair.openingBracketRange.getEndPosition().column, className, new IndentGuideHorizontalLine(false, end.column), -1, -1));
|
| 270 |
+
}
|
| 271 |
+
continue;
|
| 272 |
+
}
|
| 273 |
+
const endVisibleColumn = this.getVisibleColumnFromPosition(end);
|
| 274 |
+
const startVisibleColumn = this.getVisibleColumnFromPosition(pair.openingBracketRange.getStartPosition());
|
| 275 |
+
const guideVisibleColumn = Math.min(startVisibleColumn, endVisibleColumn, pair.minVisibleColumnIndentation + 1);
|
| 276 |
+
let renderHorizontalEndLineAtTheBottom = false;
|
| 277 |
+
const firstNonWsIndex = strings.firstNonWhitespaceIndex(this.textModel.getLineContent(pair.closingBracketRange.startLineNumber));
|
| 278 |
+
const hasTextBeforeClosingBracket = firstNonWsIndex < pair.closingBracketRange.startColumn - 1;
|
| 279 |
+
if (hasTextBeforeClosingBracket) {
|
| 280 |
+
renderHorizontalEndLineAtTheBottom = true;
|
| 281 |
+
}
|
| 282 |
+
const visibleGuideStartLineNumber = Math.max(start.lineNumber, startLineNumber);
|
| 283 |
+
const visibleGuideEndLineNumber = Math.min(end.lineNumber, endLineNumber);
|
| 284 |
+
const offset = renderHorizontalEndLineAtTheBottom ? 1 : 0;
|
| 285 |
+
for (let l = visibleGuideStartLineNumber; l < visibleGuideEndLineNumber + offset; l++) {
|
| 286 |
+
result[l - startLineNumber].push(new IndentGuide(guideVisibleColumn, -1, className, null, l === start.lineNumber ? start.column : -1, l === end.lineNumber ? end.column : -1));
|
| 287 |
+
}
|
| 288 |
+
if (horizontalGuides) {
|
| 289 |
+
if (start.lineNumber >= startLineNumber && startVisibleColumn > guideVisibleColumn) {
|
| 290 |
+
result[start.lineNumber - startLineNumber].push(new IndentGuide(guideVisibleColumn, -1, className, new IndentGuideHorizontalLine(false, start.column), -1, -1));
|
| 291 |
+
}
|
| 292 |
+
if (end.lineNumber <= endLineNumber && endVisibleColumn > guideVisibleColumn) {
|
| 293 |
+
result[end.lineNumber - startLineNumber].push(new IndentGuide(guideVisibleColumn, -1, className, new IndentGuideHorizontalLine(!renderHorizontalEndLineAtTheBottom, end.column), -1, -1));
|
| 294 |
+
}
|
| 295 |
+
}
|
| 296 |
+
}
|
| 297 |
+
for (const guides of result) {
|
| 298 |
+
guides.sort((a, b) => a.visibleColumn - b.visibleColumn);
|
| 299 |
+
}
|
| 300 |
+
return result;
|
| 301 |
+
}
|
| 302 |
+
getVisibleColumnFromPosition(position) {
|
| 303 |
+
return (CursorColumns.visibleColumnFromColumn(this.textModel.getLineContent(position.lineNumber), position.column, this.textModel.getOptions().tabSize) + 1);
|
| 304 |
+
}
|
| 305 |
+
getLinesIndentGuides(startLineNumber, endLineNumber) {
|
| 306 |
+
this.assertNotDisposed();
|
| 307 |
+
const lineCount = this.textModel.getLineCount();
|
| 308 |
+
if (startLineNumber < 1 || startLineNumber > lineCount) {
|
| 309 |
+
throw new Error('Illegal value for startLineNumber');
|
| 310 |
+
}
|
| 311 |
+
if (endLineNumber < 1 || endLineNumber > lineCount) {
|
| 312 |
+
throw new Error('Illegal value for endLineNumber');
|
| 313 |
+
}
|
| 314 |
+
const options = this.textModel.getOptions();
|
| 315 |
+
const foldingRules = this.getLanguageConfiguration(this.textModel.getLanguageId()).foldingRules;
|
| 316 |
+
const offSide = Boolean(foldingRules && foldingRules.offSide);
|
| 317 |
+
const result = new Array(endLineNumber - startLineNumber + 1);
|
| 318 |
+
let aboveContentLineIndex = -2; /* -2 is a marker for not having computed it */
|
| 319 |
+
let aboveContentLineIndent = -1;
|
| 320 |
+
let belowContentLineIndex = -2; /* -2 is a marker for not having computed it */
|
| 321 |
+
let belowContentLineIndent = -1;
|
| 322 |
+
for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {
|
| 323 |
+
const resultIndex = lineNumber - startLineNumber;
|
| 324 |
+
const currentIndent = this._computeIndentLevel(lineNumber - 1);
|
| 325 |
+
if (currentIndent >= 0) {
|
| 326 |
+
// This line has content (besides whitespace)
|
| 327 |
+
// Use the line's indent
|
| 328 |
+
aboveContentLineIndex = lineNumber - 1;
|
| 329 |
+
aboveContentLineIndent = currentIndent;
|
| 330 |
+
result[resultIndex] = Math.ceil(currentIndent / options.indentSize);
|
| 331 |
+
continue;
|
| 332 |
+
}
|
| 333 |
+
if (aboveContentLineIndex === -2) {
|
| 334 |
+
aboveContentLineIndex = -1;
|
| 335 |
+
aboveContentLineIndent = -1;
|
| 336 |
+
// must find previous line with content
|
| 337 |
+
for (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) {
|
| 338 |
+
const indent = this._computeIndentLevel(lineIndex);
|
| 339 |
+
if (indent >= 0) {
|
| 340 |
+
aboveContentLineIndex = lineIndex;
|
| 341 |
+
aboveContentLineIndent = indent;
|
| 342 |
+
break;
|
| 343 |
+
}
|
| 344 |
+
}
|
| 345 |
+
}
|
| 346 |
+
if (belowContentLineIndex !== -1 &&
|
| 347 |
+
(belowContentLineIndex === -2 || belowContentLineIndex < lineNumber - 1)) {
|
| 348 |
+
belowContentLineIndex = -1;
|
| 349 |
+
belowContentLineIndent = -1;
|
| 350 |
+
// must find next line with content
|
| 351 |
+
for (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) {
|
| 352 |
+
const indent = this._computeIndentLevel(lineIndex);
|
| 353 |
+
if (indent >= 0) {
|
| 354 |
+
belowContentLineIndex = lineIndex;
|
| 355 |
+
belowContentLineIndent = indent;
|
| 356 |
+
break;
|
| 357 |
+
}
|
| 358 |
+
}
|
| 359 |
+
}
|
| 360 |
+
result[resultIndex] = this._getIndentLevelForWhitespaceLine(offSide, aboveContentLineIndent, belowContentLineIndent);
|
| 361 |
+
}
|
| 362 |
+
return result;
|
| 363 |
+
}
|
| 364 |
+
_getIndentLevelForWhitespaceLine(offSide, aboveContentLineIndent, belowContentLineIndent) {
|
| 365 |
+
const options = this.textModel.getOptions();
|
| 366 |
+
if (aboveContentLineIndent === -1 || belowContentLineIndent === -1) {
|
| 367 |
+
// At the top or bottom of the file
|
| 368 |
+
return 0;
|
| 369 |
+
}
|
| 370 |
+
else if (aboveContentLineIndent < belowContentLineIndent) {
|
| 371 |
+
// we are inside the region above
|
| 372 |
+
return 1 + Math.floor(aboveContentLineIndent / options.indentSize);
|
| 373 |
+
}
|
| 374 |
+
else if (aboveContentLineIndent === belowContentLineIndent) {
|
| 375 |
+
// we are in between two regions
|
| 376 |
+
return Math.ceil(belowContentLineIndent / options.indentSize);
|
| 377 |
+
}
|
| 378 |
+
else {
|
| 379 |
+
if (offSide) {
|
| 380 |
+
// same level as region below
|
| 381 |
+
return Math.ceil(belowContentLineIndent / options.indentSize);
|
| 382 |
+
}
|
| 383 |
+
else {
|
| 384 |
+
// we are inside the region that ends below
|
| 385 |
+
return 1 + Math.floor(belowContentLineIndent / options.indentSize);
|
| 386 |
+
}
|
| 387 |
+
}
|
| 388 |
+
}
|
| 389 |
+
}
|
| 390 |
+
export class BracketPairGuidesClassNames {
|
| 391 |
+
constructor() {
|
| 392 |
+
this.activeClassName = 'indent-active';
|
| 393 |
+
}
|
| 394 |
+
getInlineClassName(nestingLevel, nestingLevelOfEqualBracketType, independentColorPoolPerBracketType) {
|
| 395 |
+
return this.getInlineClassNameOfLevel(independentColorPoolPerBracketType ? nestingLevelOfEqualBracketType : nestingLevel);
|
| 396 |
+
}
|
| 397 |
+
getInlineClassNameOfLevel(level) {
|
| 398 |
+
// To support a dynamic amount of colors up to 6 colors,
|
| 399 |
+
// we use a number that is a lcm of all numbers from 1 to 6.
|
| 400 |
+
return `bracket-indent-guide lvl-${level % 30}`;
|
| 401 |
+
}
|
| 402 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/indentationGuesser.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
class SpacesDiffResult {
|
| 6 |
+
constructor() {
|
| 7 |
+
this.spacesDiff = 0;
|
| 8 |
+
this.looksLikeAlignment = false;
|
| 9 |
+
}
|
| 10 |
+
}
|
| 11 |
+
/**
|
| 12 |
+
* Compute the diff in spaces between two line's indentation.
|
| 13 |
+
*/
|
| 14 |
+
function spacesDiff(a, aLength, b, bLength, result) {
|
| 15 |
+
result.spacesDiff = 0;
|
| 16 |
+
result.looksLikeAlignment = false;
|
| 17 |
+
// This can go both ways (e.g.):
|
| 18 |
+
// - a: "\t"
|
| 19 |
+
// - b: "\t "
|
| 20 |
+
// => This should count 1 tab and 4 spaces
|
| 21 |
+
let i;
|
| 22 |
+
for (i = 0; i < aLength && i < bLength; i++) {
|
| 23 |
+
const aCharCode = a.charCodeAt(i);
|
| 24 |
+
const bCharCode = b.charCodeAt(i);
|
| 25 |
+
if (aCharCode !== bCharCode) {
|
| 26 |
+
break;
|
| 27 |
+
}
|
| 28 |
+
}
|
| 29 |
+
let aSpacesCnt = 0, aTabsCount = 0;
|
| 30 |
+
for (let j = i; j < aLength; j++) {
|
| 31 |
+
const aCharCode = a.charCodeAt(j);
|
| 32 |
+
if (aCharCode === 32 /* CharCode.Space */) {
|
| 33 |
+
aSpacesCnt++;
|
| 34 |
+
}
|
| 35 |
+
else {
|
| 36 |
+
aTabsCount++;
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
let bSpacesCnt = 0, bTabsCount = 0;
|
| 40 |
+
for (let j = i; j < bLength; j++) {
|
| 41 |
+
const bCharCode = b.charCodeAt(j);
|
| 42 |
+
if (bCharCode === 32 /* CharCode.Space */) {
|
| 43 |
+
bSpacesCnt++;
|
| 44 |
+
}
|
| 45 |
+
else {
|
| 46 |
+
bTabsCount++;
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
if (aSpacesCnt > 0 && aTabsCount > 0) {
|
| 50 |
+
return;
|
| 51 |
+
}
|
| 52 |
+
if (bSpacesCnt > 0 && bTabsCount > 0) {
|
| 53 |
+
return;
|
| 54 |
+
}
|
| 55 |
+
const tabsDiff = Math.abs(aTabsCount - bTabsCount);
|
| 56 |
+
const spacesDiff = Math.abs(aSpacesCnt - bSpacesCnt);
|
| 57 |
+
if (tabsDiff === 0) {
|
| 58 |
+
// check if the indentation difference might be caused by alignment reasons
|
| 59 |
+
// sometime folks like to align their code, but this should not be used as a hint
|
| 60 |
+
result.spacesDiff = spacesDiff;
|
| 61 |
+
if (spacesDiff > 0 && 0 <= bSpacesCnt - 1 && bSpacesCnt - 1 < a.length && bSpacesCnt < b.length) {
|
| 62 |
+
if (b.charCodeAt(bSpacesCnt) !== 32 /* CharCode.Space */ && a.charCodeAt(bSpacesCnt - 1) === 32 /* CharCode.Space */) {
|
| 63 |
+
if (a.charCodeAt(a.length - 1) === 44 /* CharCode.Comma */) {
|
| 64 |
+
// This looks like an alignment desire: e.g.
|
| 65 |
+
// const a = b + c,
|
| 66 |
+
// d = b - c;
|
| 67 |
+
result.looksLikeAlignment = true;
|
| 68 |
+
}
|
| 69 |
+
}
|
| 70 |
+
}
|
| 71 |
+
return;
|
| 72 |
+
}
|
| 73 |
+
if (spacesDiff % tabsDiff === 0) {
|
| 74 |
+
result.spacesDiff = spacesDiff / tabsDiff;
|
| 75 |
+
return;
|
| 76 |
+
}
|
| 77 |
+
}
|
| 78 |
+
export function guessIndentation(source, defaultTabSize, defaultInsertSpaces) {
|
| 79 |
+
// Look at most at the first 10k lines
|
| 80 |
+
const linesCount = Math.min(source.getLineCount(), 10000);
|
| 81 |
+
let linesIndentedWithTabsCount = 0; // number of lines that contain at least one tab in indentation
|
| 82 |
+
let linesIndentedWithSpacesCount = 0; // number of lines that contain only spaces in indentation
|
| 83 |
+
let previousLineText = ''; // content of latest line that contained non-whitespace chars
|
| 84 |
+
let previousLineIndentation = 0; // index at which latest line contained the first non-whitespace char
|
| 85 |
+
const ALLOWED_TAB_SIZE_GUESSES = [2, 4, 6, 8, 3, 5, 7]; // prefer even guesses for `tabSize`, limit to [2, 8].
|
| 86 |
+
const MAX_ALLOWED_TAB_SIZE_GUESS = 8; // max(ALLOWED_TAB_SIZE_GUESSES) = 8
|
| 87 |
+
const spacesDiffCount = [0, 0, 0, 0, 0, 0, 0, 0, 0]; // `tabSize` scores
|
| 88 |
+
const tmp = new SpacesDiffResult();
|
| 89 |
+
for (let lineNumber = 1; lineNumber <= linesCount; lineNumber++) {
|
| 90 |
+
const currentLineLength = source.getLineLength(lineNumber);
|
| 91 |
+
const currentLineText = source.getLineContent(lineNumber);
|
| 92 |
+
// if the text buffer is chunk based, so long lines are cons-string, v8 will flattern the string when we check charCode.
|
| 93 |
+
// checking charCode on chunks directly is cheaper.
|
| 94 |
+
const useCurrentLineText = (currentLineLength <= 65536);
|
| 95 |
+
let currentLineHasContent = false; // does `currentLineText` contain non-whitespace chars
|
| 96 |
+
let currentLineIndentation = 0; // index at which `currentLineText` contains the first non-whitespace char
|
| 97 |
+
let currentLineSpacesCount = 0; // count of spaces found in `currentLineText` indentation
|
| 98 |
+
let currentLineTabsCount = 0; // count of tabs found in `currentLineText` indentation
|
| 99 |
+
for (let j = 0, lenJ = currentLineLength; j < lenJ; j++) {
|
| 100 |
+
const charCode = (useCurrentLineText ? currentLineText.charCodeAt(j) : source.getLineCharCode(lineNumber, j));
|
| 101 |
+
if (charCode === 9 /* CharCode.Tab */) {
|
| 102 |
+
currentLineTabsCount++;
|
| 103 |
+
}
|
| 104 |
+
else if (charCode === 32 /* CharCode.Space */) {
|
| 105 |
+
currentLineSpacesCount++;
|
| 106 |
+
}
|
| 107 |
+
else {
|
| 108 |
+
// Hit non whitespace character on this line
|
| 109 |
+
currentLineHasContent = true;
|
| 110 |
+
currentLineIndentation = j;
|
| 111 |
+
break;
|
| 112 |
+
}
|
| 113 |
+
}
|
| 114 |
+
// Ignore empty or only whitespace lines
|
| 115 |
+
if (!currentLineHasContent) {
|
| 116 |
+
continue;
|
| 117 |
+
}
|
| 118 |
+
if (currentLineTabsCount > 0) {
|
| 119 |
+
linesIndentedWithTabsCount++;
|
| 120 |
+
}
|
| 121 |
+
else if (currentLineSpacesCount > 1) {
|
| 122 |
+
linesIndentedWithSpacesCount++;
|
| 123 |
+
}
|
| 124 |
+
spacesDiff(previousLineText, previousLineIndentation, currentLineText, currentLineIndentation, tmp);
|
| 125 |
+
if (tmp.looksLikeAlignment) {
|
| 126 |
+
// if defaultInsertSpaces === true && the spaces count == tabSize, we may want to count it as valid indentation
|
| 127 |
+
//
|
| 128 |
+
// - item1
|
| 129 |
+
// - item2
|
| 130 |
+
//
|
| 131 |
+
// otherwise skip this line entirely
|
| 132 |
+
//
|
| 133 |
+
// const a = 1,
|
| 134 |
+
// b = 2;
|
| 135 |
+
if (!(defaultInsertSpaces && defaultTabSize === tmp.spacesDiff)) {
|
| 136 |
+
continue;
|
| 137 |
+
}
|
| 138 |
+
}
|
| 139 |
+
const currentSpacesDiff = tmp.spacesDiff;
|
| 140 |
+
if (currentSpacesDiff <= MAX_ALLOWED_TAB_SIZE_GUESS) {
|
| 141 |
+
spacesDiffCount[currentSpacesDiff]++;
|
| 142 |
+
}
|
| 143 |
+
previousLineText = currentLineText;
|
| 144 |
+
previousLineIndentation = currentLineIndentation;
|
| 145 |
+
}
|
| 146 |
+
let insertSpaces = defaultInsertSpaces;
|
| 147 |
+
if (linesIndentedWithTabsCount !== linesIndentedWithSpacesCount) {
|
| 148 |
+
insertSpaces = (linesIndentedWithTabsCount < linesIndentedWithSpacesCount);
|
| 149 |
+
}
|
| 150 |
+
let tabSize = defaultTabSize;
|
| 151 |
+
// Guess tabSize only if inserting spaces...
|
| 152 |
+
if (insertSpaces) {
|
| 153 |
+
let tabSizeScore = (insertSpaces ? 0 : 0.1 * linesCount);
|
| 154 |
+
// console.log("score threshold: " + tabSizeScore);
|
| 155 |
+
ALLOWED_TAB_SIZE_GUESSES.forEach((possibleTabSize) => {
|
| 156 |
+
const possibleTabSizeScore = spacesDiffCount[possibleTabSize];
|
| 157 |
+
if (possibleTabSizeScore > tabSizeScore) {
|
| 158 |
+
tabSizeScore = possibleTabSizeScore;
|
| 159 |
+
tabSize = possibleTabSize;
|
| 160 |
+
}
|
| 161 |
+
});
|
| 162 |
+
// Let a tabSize of 2 win even if it is not the maximum
|
| 163 |
+
// (only in case 4 was guessed)
|
| 164 |
+
if (tabSize === 4 && spacesDiffCount[4] > 0 && spacesDiffCount[2] > 0 && spacesDiffCount[2] >= spacesDiffCount[4] / 2) {
|
| 165 |
+
tabSize = 2;
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
+
// console.log('--------------------------');
|
| 169 |
+
// console.log('linesIndentedWithTabsCount: ' + linesIndentedWithTabsCount + ', linesIndentedWithSpacesCount: ' + linesIndentedWithSpacesCount);
|
| 170 |
+
// console.log('spacesDiffCount: ' + spacesDiffCount);
|
| 171 |
+
// console.log('tabSize: ' + tabSize + ', tabSizeScore: ' + tabSizeScore);
|
| 172 |
+
return {
|
| 173 |
+
insertSpaces: insertSpaces,
|
| 174 |
+
tabSize: tabSize
|
| 175 |
+
};
|
| 176 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/intervalTree.js
ADDED
|
@@ -0,0 +1,986 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
export function getNodeColor(node) {
|
| 6 |
+
return ((node.metadata & 1 /* Constants.ColorMask */) >>> 0 /* Constants.ColorOffset */);
|
| 7 |
+
}
|
| 8 |
+
function setNodeColor(node, color) {
|
| 9 |
+
node.metadata = ((node.metadata & 254 /* Constants.ColorMaskInverse */) | (color << 0 /* Constants.ColorOffset */));
|
| 10 |
+
}
|
| 11 |
+
function getNodeIsVisited(node) {
|
| 12 |
+
return ((node.metadata & 2 /* Constants.IsVisitedMask */) >>> 1 /* Constants.IsVisitedOffset */) === 1;
|
| 13 |
+
}
|
| 14 |
+
function setNodeIsVisited(node, value) {
|
| 15 |
+
node.metadata = ((node.metadata & 253 /* Constants.IsVisitedMaskInverse */) | ((value ? 1 : 0) << 1 /* Constants.IsVisitedOffset */));
|
| 16 |
+
}
|
| 17 |
+
function getNodeIsForValidation(node) {
|
| 18 |
+
return ((node.metadata & 4 /* Constants.IsForValidationMask */) >>> 2 /* Constants.IsForValidationOffset */) === 1;
|
| 19 |
+
}
|
| 20 |
+
function setNodeIsForValidation(node, value) {
|
| 21 |
+
node.metadata = ((node.metadata & 251 /* Constants.IsForValidationMaskInverse */) | ((value ? 1 : 0) << 2 /* Constants.IsForValidationOffset */));
|
| 22 |
+
}
|
| 23 |
+
function getNodeIsInGlyphMargin(node) {
|
| 24 |
+
return ((node.metadata & 64 /* Constants.IsMarginMask */) >>> 6 /* Constants.IsMarginOffset */) === 1;
|
| 25 |
+
}
|
| 26 |
+
function setNodeIsInGlyphMargin(node, value) {
|
| 27 |
+
node.metadata = ((node.metadata & 191 /* Constants.IsMarginMaskInverse */) | ((value ? 1 : 0) << 6 /* Constants.IsMarginOffset */));
|
| 28 |
+
}
|
| 29 |
+
function getNodeStickiness(node) {
|
| 30 |
+
return ((node.metadata & 24 /* Constants.StickinessMask */) >>> 3 /* Constants.StickinessOffset */);
|
| 31 |
+
}
|
| 32 |
+
function _setNodeStickiness(node, stickiness) {
|
| 33 |
+
node.metadata = ((node.metadata & 231 /* Constants.StickinessMaskInverse */) | (stickiness << 3 /* Constants.StickinessOffset */));
|
| 34 |
+
}
|
| 35 |
+
function getCollapseOnReplaceEdit(node) {
|
| 36 |
+
return ((node.metadata & 32 /* Constants.CollapseOnReplaceEditMask */) >>> 5 /* Constants.CollapseOnReplaceEditOffset */) === 1;
|
| 37 |
+
}
|
| 38 |
+
function setCollapseOnReplaceEdit(node, value) {
|
| 39 |
+
node.metadata = ((node.metadata & 223 /* Constants.CollapseOnReplaceEditMaskInverse */) | ((value ? 1 : 0) << 5 /* Constants.CollapseOnReplaceEditOffset */));
|
| 40 |
+
}
|
| 41 |
+
export class IntervalNode {
|
| 42 |
+
constructor(id, start, end) {
|
| 43 |
+
this.metadata = 0;
|
| 44 |
+
this.parent = this;
|
| 45 |
+
this.left = this;
|
| 46 |
+
this.right = this;
|
| 47 |
+
setNodeColor(this, 1 /* NodeColor.Red */);
|
| 48 |
+
this.start = start;
|
| 49 |
+
this.end = end;
|
| 50 |
+
// FORCE_OVERFLOWING_TEST: this.delta = start;
|
| 51 |
+
this.delta = 0;
|
| 52 |
+
this.maxEnd = end;
|
| 53 |
+
this.id = id;
|
| 54 |
+
this.ownerId = 0;
|
| 55 |
+
this.options = null;
|
| 56 |
+
setNodeIsForValidation(this, false);
|
| 57 |
+
setNodeIsInGlyphMargin(this, false);
|
| 58 |
+
_setNodeStickiness(this, 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */);
|
| 59 |
+
setCollapseOnReplaceEdit(this, false);
|
| 60 |
+
this.cachedVersionId = 0;
|
| 61 |
+
this.cachedAbsoluteStart = start;
|
| 62 |
+
this.cachedAbsoluteEnd = end;
|
| 63 |
+
this.range = null;
|
| 64 |
+
setNodeIsVisited(this, false);
|
| 65 |
+
}
|
| 66 |
+
reset(versionId, start, end, range) {
|
| 67 |
+
this.start = start;
|
| 68 |
+
this.end = end;
|
| 69 |
+
this.maxEnd = end;
|
| 70 |
+
this.cachedVersionId = versionId;
|
| 71 |
+
this.cachedAbsoluteStart = start;
|
| 72 |
+
this.cachedAbsoluteEnd = end;
|
| 73 |
+
this.range = range;
|
| 74 |
+
}
|
| 75 |
+
setOptions(options) {
|
| 76 |
+
this.options = options;
|
| 77 |
+
const className = this.options.className;
|
| 78 |
+
setNodeIsForValidation(this, (className === "squiggly-error" /* ClassName.EditorErrorDecoration */
|
| 79 |
+
|| className === "squiggly-warning" /* ClassName.EditorWarningDecoration */
|
| 80 |
+
|| className === "squiggly-info" /* ClassName.EditorInfoDecoration */));
|
| 81 |
+
setNodeIsInGlyphMargin(this, this.options.glyphMarginClassName !== null);
|
| 82 |
+
_setNodeStickiness(this, this.options.stickiness);
|
| 83 |
+
setCollapseOnReplaceEdit(this, this.options.collapseOnReplaceEdit);
|
| 84 |
+
}
|
| 85 |
+
setCachedOffsets(absoluteStart, absoluteEnd, cachedVersionId) {
|
| 86 |
+
if (this.cachedVersionId !== cachedVersionId) {
|
| 87 |
+
this.range = null;
|
| 88 |
+
}
|
| 89 |
+
this.cachedVersionId = cachedVersionId;
|
| 90 |
+
this.cachedAbsoluteStart = absoluteStart;
|
| 91 |
+
this.cachedAbsoluteEnd = absoluteEnd;
|
| 92 |
+
}
|
| 93 |
+
detach() {
|
| 94 |
+
this.parent = null;
|
| 95 |
+
this.left = null;
|
| 96 |
+
this.right = null;
|
| 97 |
+
}
|
| 98 |
+
}
|
| 99 |
+
export const SENTINEL = new IntervalNode(null, 0, 0);
|
| 100 |
+
SENTINEL.parent = SENTINEL;
|
| 101 |
+
SENTINEL.left = SENTINEL;
|
| 102 |
+
SENTINEL.right = SENTINEL;
|
| 103 |
+
setNodeColor(SENTINEL, 0 /* NodeColor.Black */);
|
| 104 |
+
export class IntervalTree {
|
| 105 |
+
constructor() {
|
| 106 |
+
this.root = SENTINEL;
|
| 107 |
+
this.requestNormalizeDelta = false;
|
| 108 |
+
}
|
| 109 |
+
intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations) {
|
| 110 |
+
if (this.root === SENTINEL) {
|
| 111 |
+
return [];
|
| 112 |
+
}
|
| 113 |
+
return intervalSearch(this, start, end, filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations);
|
| 114 |
+
}
|
| 115 |
+
search(filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations) {
|
| 116 |
+
if (this.root === SENTINEL) {
|
| 117 |
+
return [];
|
| 118 |
+
}
|
| 119 |
+
return search(this, filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations);
|
| 120 |
+
}
|
| 121 |
+
/**
|
| 122 |
+
* Will not set `cachedAbsoluteStart` nor `cachedAbsoluteEnd` on the returned nodes!
|
| 123 |
+
*/
|
| 124 |
+
collectNodesFromOwner(ownerId) {
|
| 125 |
+
return collectNodesFromOwner(this, ownerId);
|
| 126 |
+
}
|
| 127 |
+
/**
|
| 128 |
+
* Will not set `cachedAbsoluteStart` nor `cachedAbsoluteEnd` on the returned nodes!
|
| 129 |
+
*/
|
| 130 |
+
collectNodesPostOrder() {
|
| 131 |
+
return collectNodesPostOrder(this);
|
| 132 |
+
}
|
| 133 |
+
insert(node) {
|
| 134 |
+
rbTreeInsert(this, node);
|
| 135 |
+
this._normalizeDeltaIfNecessary();
|
| 136 |
+
}
|
| 137 |
+
delete(node) {
|
| 138 |
+
rbTreeDelete(this, node);
|
| 139 |
+
this._normalizeDeltaIfNecessary();
|
| 140 |
+
}
|
| 141 |
+
resolveNode(node, cachedVersionId) {
|
| 142 |
+
const initialNode = node;
|
| 143 |
+
let delta = 0;
|
| 144 |
+
while (node !== this.root) {
|
| 145 |
+
if (node === node.parent.right) {
|
| 146 |
+
delta += node.parent.delta;
|
| 147 |
+
}
|
| 148 |
+
node = node.parent;
|
| 149 |
+
}
|
| 150 |
+
const nodeStart = initialNode.start + delta;
|
| 151 |
+
const nodeEnd = initialNode.end + delta;
|
| 152 |
+
initialNode.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId);
|
| 153 |
+
}
|
| 154 |
+
acceptReplace(offset, length, textLength, forceMoveMarkers) {
|
| 155 |
+
// Our strategy is to remove all directly impacted nodes, and then add them back to the tree.
|
| 156 |
+
// (1) collect all nodes that are intersecting this edit as nodes of interest
|
| 157 |
+
const nodesOfInterest = searchForEditing(this, offset, offset + length);
|
| 158 |
+
// (2) remove all nodes that are intersecting this edit
|
| 159 |
+
for (let i = 0, len = nodesOfInterest.length; i < len; i++) {
|
| 160 |
+
const node = nodesOfInterest[i];
|
| 161 |
+
rbTreeDelete(this, node);
|
| 162 |
+
}
|
| 163 |
+
this._normalizeDeltaIfNecessary();
|
| 164 |
+
// (3) edit all tree nodes except the nodes of interest
|
| 165 |
+
noOverlapReplace(this, offset, offset + length, textLength);
|
| 166 |
+
this._normalizeDeltaIfNecessary();
|
| 167 |
+
// (4) edit the nodes of interest and insert them back in the tree
|
| 168 |
+
for (let i = 0, len = nodesOfInterest.length; i < len; i++) {
|
| 169 |
+
const node = nodesOfInterest[i];
|
| 170 |
+
node.start = node.cachedAbsoluteStart;
|
| 171 |
+
node.end = node.cachedAbsoluteEnd;
|
| 172 |
+
nodeAcceptEdit(node, offset, (offset + length), textLength, forceMoveMarkers);
|
| 173 |
+
node.maxEnd = node.end;
|
| 174 |
+
rbTreeInsert(this, node);
|
| 175 |
+
}
|
| 176 |
+
this._normalizeDeltaIfNecessary();
|
| 177 |
+
}
|
| 178 |
+
_normalizeDeltaIfNecessary() {
|
| 179 |
+
if (!this.requestNormalizeDelta) {
|
| 180 |
+
return;
|
| 181 |
+
}
|
| 182 |
+
this.requestNormalizeDelta = false;
|
| 183 |
+
normalizeDelta(this);
|
| 184 |
+
}
|
| 185 |
+
}
|
| 186 |
+
//#region Delta Normalization
|
| 187 |
+
function normalizeDelta(T) {
|
| 188 |
+
let node = T.root;
|
| 189 |
+
let delta = 0;
|
| 190 |
+
while (node !== SENTINEL) {
|
| 191 |
+
if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {
|
| 192 |
+
// go left
|
| 193 |
+
node = node.left;
|
| 194 |
+
continue;
|
| 195 |
+
}
|
| 196 |
+
if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {
|
| 197 |
+
// go right
|
| 198 |
+
delta += node.delta;
|
| 199 |
+
node = node.right;
|
| 200 |
+
continue;
|
| 201 |
+
}
|
| 202 |
+
// handle current node
|
| 203 |
+
node.start = delta + node.start;
|
| 204 |
+
node.end = delta + node.end;
|
| 205 |
+
node.delta = 0;
|
| 206 |
+
recomputeMaxEnd(node);
|
| 207 |
+
setNodeIsVisited(node, true);
|
| 208 |
+
// going up from this node
|
| 209 |
+
setNodeIsVisited(node.left, false);
|
| 210 |
+
setNodeIsVisited(node.right, false);
|
| 211 |
+
if (node === node.parent.right) {
|
| 212 |
+
delta -= node.parent.delta;
|
| 213 |
+
}
|
| 214 |
+
node = node.parent;
|
| 215 |
+
}
|
| 216 |
+
setNodeIsVisited(T.root, false);
|
| 217 |
+
}
|
| 218 |
+
function adjustMarkerBeforeColumn(markerOffset, markerStickToPreviousCharacter, checkOffset, moveSemantics) {
|
| 219 |
+
if (markerOffset < checkOffset) {
|
| 220 |
+
return true;
|
| 221 |
+
}
|
| 222 |
+
if (markerOffset > checkOffset) {
|
| 223 |
+
return false;
|
| 224 |
+
}
|
| 225 |
+
if (moveSemantics === 1 /* MarkerMoveSemantics.ForceMove */) {
|
| 226 |
+
return false;
|
| 227 |
+
}
|
| 228 |
+
if (moveSemantics === 2 /* MarkerMoveSemantics.ForceStay */) {
|
| 229 |
+
return true;
|
| 230 |
+
}
|
| 231 |
+
return markerStickToPreviousCharacter;
|
| 232 |
+
}
|
| 233 |
+
/**
|
| 234 |
+
* This is a lot more complicated than strictly necessary to maintain the same behaviour
|
| 235 |
+
* as when decorations were implemented using two markers.
|
| 236 |
+
*/
|
| 237 |
+
export function nodeAcceptEdit(node, start, end, textLength, forceMoveMarkers) {
|
| 238 |
+
const nodeStickiness = getNodeStickiness(node);
|
| 239 |
+
const startStickToPreviousCharacter = (nodeStickiness === 0 /* TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges */
|
| 240 |
+
|| nodeStickiness === 2 /* TrackedRangeStickiness.GrowsOnlyWhenTypingBefore */);
|
| 241 |
+
const endStickToPreviousCharacter = (nodeStickiness === 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */
|
| 242 |
+
|| nodeStickiness === 2 /* TrackedRangeStickiness.GrowsOnlyWhenTypingBefore */);
|
| 243 |
+
const deletingCnt = (end - start);
|
| 244 |
+
const insertingCnt = textLength;
|
| 245 |
+
const commonLength = Math.min(deletingCnt, insertingCnt);
|
| 246 |
+
const nodeStart = node.start;
|
| 247 |
+
let startDone = false;
|
| 248 |
+
const nodeEnd = node.end;
|
| 249 |
+
let endDone = false;
|
| 250 |
+
if (start <= nodeStart && nodeEnd <= end && getCollapseOnReplaceEdit(node)) {
|
| 251 |
+
// This edit encompasses the entire decoration range
|
| 252 |
+
// and the decoration has asked to become collapsed
|
| 253 |
+
node.start = start;
|
| 254 |
+
startDone = true;
|
| 255 |
+
node.end = start;
|
| 256 |
+
endDone = true;
|
| 257 |
+
}
|
| 258 |
+
{
|
| 259 |
+
const moveSemantics = forceMoveMarkers ? 1 /* MarkerMoveSemantics.ForceMove */ : (deletingCnt > 0 ? 2 /* MarkerMoveSemantics.ForceStay */ : 0 /* MarkerMoveSemantics.MarkerDefined */);
|
| 260 |
+
if (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, start, moveSemantics)) {
|
| 261 |
+
startDone = true;
|
| 262 |
+
}
|
| 263 |
+
if (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, start, moveSemantics)) {
|
| 264 |
+
endDone = true;
|
| 265 |
+
}
|
| 266 |
+
}
|
| 267 |
+
if (commonLength > 0 && !forceMoveMarkers) {
|
| 268 |
+
const moveSemantics = (deletingCnt > insertingCnt ? 2 /* MarkerMoveSemantics.ForceStay */ : 0 /* MarkerMoveSemantics.MarkerDefined */);
|
| 269 |
+
if (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, start + commonLength, moveSemantics)) {
|
| 270 |
+
startDone = true;
|
| 271 |
+
}
|
| 272 |
+
if (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, start + commonLength, moveSemantics)) {
|
| 273 |
+
endDone = true;
|
| 274 |
+
}
|
| 275 |
+
}
|
| 276 |
+
{
|
| 277 |
+
const moveSemantics = forceMoveMarkers ? 1 /* MarkerMoveSemantics.ForceMove */ : 0 /* MarkerMoveSemantics.MarkerDefined */;
|
| 278 |
+
if (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, end, moveSemantics)) {
|
| 279 |
+
node.start = start + insertingCnt;
|
| 280 |
+
startDone = true;
|
| 281 |
+
}
|
| 282 |
+
if (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, end, moveSemantics)) {
|
| 283 |
+
node.end = start + insertingCnt;
|
| 284 |
+
endDone = true;
|
| 285 |
+
}
|
| 286 |
+
}
|
| 287 |
+
// Finish
|
| 288 |
+
const deltaColumn = (insertingCnt - deletingCnt);
|
| 289 |
+
if (!startDone) {
|
| 290 |
+
node.start = Math.max(0, nodeStart + deltaColumn);
|
| 291 |
+
}
|
| 292 |
+
if (!endDone) {
|
| 293 |
+
node.end = Math.max(0, nodeEnd + deltaColumn);
|
| 294 |
+
}
|
| 295 |
+
if (node.start > node.end) {
|
| 296 |
+
node.end = node.start;
|
| 297 |
+
}
|
| 298 |
+
}
|
| 299 |
+
function searchForEditing(T, start, end) {
|
| 300 |
+
// https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree
|
| 301 |
+
// Now, it is known that two intervals A and B overlap only when both
|
| 302 |
+
// A.low <= B.high and A.high >= B.low. When searching the trees for
|
| 303 |
+
// nodes overlapping with a given interval, you can immediately skip:
|
| 304 |
+
// a) all nodes to the right of nodes whose low value is past the end of the given interval.
|
| 305 |
+
// b) all nodes that have their maximum 'high' value below the start of the given interval.
|
| 306 |
+
let node = T.root;
|
| 307 |
+
let delta = 0;
|
| 308 |
+
let nodeMaxEnd = 0;
|
| 309 |
+
let nodeStart = 0;
|
| 310 |
+
let nodeEnd = 0;
|
| 311 |
+
const result = [];
|
| 312 |
+
let resultLen = 0;
|
| 313 |
+
while (node !== SENTINEL) {
|
| 314 |
+
if (getNodeIsVisited(node)) {
|
| 315 |
+
// going up from this node
|
| 316 |
+
setNodeIsVisited(node.left, false);
|
| 317 |
+
setNodeIsVisited(node.right, false);
|
| 318 |
+
if (node === node.parent.right) {
|
| 319 |
+
delta -= node.parent.delta;
|
| 320 |
+
}
|
| 321 |
+
node = node.parent;
|
| 322 |
+
continue;
|
| 323 |
+
}
|
| 324 |
+
if (!getNodeIsVisited(node.left)) {
|
| 325 |
+
// first time seeing this node
|
| 326 |
+
nodeMaxEnd = delta + node.maxEnd;
|
| 327 |
+
if (nodeMaxEnd < start) {
|
| 328 |
+
// cover case b) from above
|
| 329 |
+
// there is no need to search this node or its children
|
| 330 |
+
setNodeIsVisited(node, true);
|
| 331 |
+
continue;
|
| 332 |
+
}
|
| 333 |
+
if (node.left !== SENTINEL) {
|
| 334 |
+
// go left
|
| 335 |
+
node = node.left;
|
| 336 |
+
continue;
|
| 337 |
+
}
|
| 338 |
+
}
|
| 339 |
+
// handle current node
|
| 340 |
+
nodeStart = delta + node.start;
|
| 341 |
+
if (nodeStart > end) {
|
| 342 |
+
// cover case a) from above
|
| 343 |
+
// there is no need to search this node or its right subtree
|
| 344 |
+
setNodeIsVisited(node, true);
|
| 345 |
+
continue;
|
| 346 |
+
}
|
| 347 |
+
nodeEnd = delta + node.end;
|
| 348 |
+
if (nodeEnd >= start) {
|
| 349 |
+
node.setCachedOffsets(nodeStart, nodeEnd, 0);
|
| 350 |
+
result[resultLen++] = node;
|
| 351 |
+
}
|
| 352 |
+
setNodeIsVisited(node, true);
|
| 353 |
+
if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {
|
| 354 |
+
// go right
|
| 355 |
+
delta += node.delta;
|
| 356 |
+
node = node.right;
|
| 357 |
+
continue;
|
| 358 |
+
}
|
| 359 |
+
}
|
| 360 |
+
setNodeIsVisited(T.root, false);
|
| 361 |
+
return result;
|
| 362 |
+
}
|
| 363 |
+
function noOverlapReplace(T, start, end, textLength) {
|
| 364 |
+
// https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree
|
| 365 |
+
// Now, it is known that two intervals A and B overlap only when both
|
| 366 |
+
// A.low <= B.high and A.high >= B.low. When searching the trees for
|
| 367 |
+
// nodes overlapping with a given interval, you can immediately skip:
|
| 368 |
+
// a) all nodes to the right of nodes whose low value is past the end of the given interval.
|
| 369 |
+
// b) all nodes that have their maximum 'high' value below the start of the given interval.
|
| 370 |
+
let node = T.root;
|
| 371 |
+
let delta = 0;
|
| 372 |
+
let nodeMaxEnd = 0;
|
| 373 |
+
let nodeStart = 0;
|
| 374 |
+
const editDelta = (textLength - (end - start));
|
| 375 |
+
while (node !== SENTINEL) {
|
| 376 |
+
if (getNodeIsVisited(node)) {
|
| 377 |
+
// going up from this node
|
| 378 |
+
setNodeIsVisited(node.left, false);
|
| 379 |
+
setNodeIsVisited(node.right, false);
|
| 380 |
+
if (node === node.parent.right) {
|
| 381 |
+
delta -= node.parent.delta;
|
| 382 |
+
}
|
| 383 |
+
recomputeMaxEnd(node);
|
| 384 |
+
node = node.parent;
|
| 385 |
+
continue;
|
| 386 |
+
}
|
| 387 |
+
if (!getNodeIsVisited(node.left)) {
|
| 388 |
+
// first time seeing this node
|
| 389 |
+
nodeMaxEnd = delta + node.maxEnd;
|
| 390 |
+
if (nodeMaxEnd < start) {
|
| 391 |
+
// cover case b) from above
|
| 392 |
+
// there is no need to search this node or its children
|
| 393 |
+
setNodeIsVisited(node, true);
|
| 394 |
+
continue;
|
| 395 |
+
}
|
| 396 |
+
if (node.left !== SENTINEL) {
|
| 397 |
+
// go left
|
| 398 |
+
node = node.left;
|
| 399 |
+
continue;
|
| 400 |
+
}
|
| 401 |
+
}
|
| 402 |
+
// handle current node
|
| 403 |
+
nodeStart = delta + node.start;
|
| 404 |
+
if (nodeStart > end) {
|
| 405 |
+
node.start += editDelta;
|
| 406 |
+
node.end += editDelta;
|
| 407 |
+
node.delta += editDelta;
|
| 408 |
+
if (node.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || node.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {
|
| 409 |
+
T.requestNormalizeDelta = true;
|
| 410 |
+
}
|
| 411 |
+
// cover case a) from above
|
| 412 |
+
// there is no need to search this node or its right subtree
|
| 413 |
+
setNodeIsVisited(node, true);
|
| 414 |
+
continue;
|
| 415 |
+
}
|
| 416 |
+
setNodeIsVisited(node, true);
|
| 417 |
+
if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {
|
| 418 |
+
// go right
|
| 419 |
+
delta += node.delta;
|
| 420 |
+
node = node.right;
|
| 421 |
+
continue;
|
| 422 |
+
}
|
| 423 |
+
}
|
| 424 |
+
setNodeIsVisited(T.root, false);
|
| 425 |
+
}
|
| 426 |
+
//#endregion
|
| 427 |
+
//#region Searching
|
| 428 |
+
function collectNodesFromOwner(T, ownerId) {
|
| 429 |
+
let node = T.root;
|
| 430 |
+
const result = [];
|
| 431 |
+
let resultLen = 0;
|
| 432 |
+
while (node !== SENTINEL) {
|
| 433 |
+
if (getNodeIsVisited(node)) {
|
| 434 |
+
// going up from this node
|
| 435 |
+
setNodeIsVisited(node.left, false);
|
| 436 |
+
setNodeIsVisited(node.right, false);
|
| 437 |
+
node = node.parent;
|
| 438 |
+
continue;
|
| 439 |
+
}
|
| 440 |
+
if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {
|
| 441 |
+
// go left
|
| 442 |
+
node = node.left;
|
| 443 |
+
continue;
|
| 444 |
+
}
|
| 445 |
+
// handle current node
|
| 446 |
+
if (node.ownerId === ownerId) {
|
| 447 |
+
result[resultLen++] = node;
|
| 448 |
+
}
|
| 449 |
+
setNodeIsVisited(node, true);
|
| 450 |
+
if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {
|
| 451 |
+
// go right
|
| 452 |
+
node = node.right;
|
| 453 |
+
continue;
|
| 454 |
+
}
|
| 455 |
+
}
|
| 456 |
+
setNodeIsVisited(T.root, false);
|
| 457 |
+
return result;
|
| 458 |
+
}
|
| 459 |
+
function collectNodesPostOrder(T) {
|
| 460 |
+
let node = T.root;
|
| 461 |
+
const result = [];
|
| 462 |
+
let resultLen = 0;
|
| 463 |
+
while (node !== SENTINEL) {
|
| 464 |
+
if (getNodeIsVisited(node)) {
|
| 465 |
+
// going up from this node
|
| 466 |
+
setNodeIsVisited(node.left, false);
|
| 467 |
+
setNodeIsVisited(node.right, false);
|
| 468 |
+
node = node.parent;
|
| 469 |
+
continue;
|
| 470 |
+
}
|
| 471 |
+
if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {
|
| 472 |
+
// go left
|
| 473 |
+
node = node.left;
|
| 474 |
+
continue;
|
| 475 |
+
}
|
| 476 |
+
if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {
|
| 477 |
+
// go right
|
| 478 |
+
node = node.right;
|
| 479 |
+
continue;
|
| 480 |
+
}
|
| 481 |
+
// handle current node
|
| 482 |
+
result[resultLen++] = node;
|
| 483 |
+
setNodeIsVisited(node, true);
|
| 484 |
+
}
|
| 485 |
+
setNodeIsVisited(T.root, false);
|
| 486 |
+
return result;
|
| 487 |
+
}
|
| 488 |
+
function search(T, filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations) {
|
| 489 |
+
let node = T.root;
|
| 490 |
+
let delta = 0;
|
| 491 |
+
let nodeStart = 0;
|
| 492 |
+
let nodeEnd = 0;
|
| 493 |
+
const result = [];
|
| 494 |
+
let resultLen = 0;
|
| 495 |
+
while (node !== SENTINEL) {
|
| 496 |
+
if (getNodeIsVisited(node)) {
|
| 497 |
+
// going up from this node
|
| 498 |
+
setNodeIsVisited(node.left, false);
|
| 499 |
+
setNodeIsVisited(node.right, false);
|
| 500 |
+
if (node === node.parent.right) {
|
| 501 |
+
delta -= node.parent.delta;
|
| 502 |
+
}
|
| 503 |
+
node = node.parent;
|
| 504 |
+
continue;
|
| 505 |
+
}
|
| 506 |
+
if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {
|
| 507 |
+
// go left
|
| 508 |
+
node = node.left;
|
| 509 |
+
continue;
|
| 510 |
+
}
|
| 511 |
+
// handle current node
|
| 512 |
+
nodeStart = delta + node.start;
|
| 513 |
+
nodeEnd = delta + node.end;
|
| 514 |
+
node.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId);
|
| 515 |
+
let include = true;
|
| 516 |
+
if (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) {
|
| 517 |
+
include = false;
|
| 518 |
+
}
|
| 519 |
+
if (filterOutValidation && getNodeIsForValidation(node)) {
|
| 520 |
+
include = false;
|
| 521 |
+
}
|
| 522 |
+
if (onlyMarginDecorations && !getNodeIsInGlyphMargin(node)) {
|
| 523 |
+
include = false;
|
| 524 |
+
}
|
| 525 |
+
if (include) {
|
| 526 |
+
result[resultLen++] = node;
|
| 527 |
+
}
|
| 528 |
+
setNodeIsVisited(node, true);
|
| 529 |
+
if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {
|
| 530 |
+
// go right
|
| 531 |
+
delta += node.delta;
|
| 532 |
+
node = node.right;
|
| 533 |
+
continue;
|
| 534 |
+
}
|
| 535 |
+
}
|
| 536 |
+
setNodeIsVisited(T.root, false);
|
| 537 |
+
return result;
|
| 538 |
+
}
|
| 539 |
+
function intervalSearch(T, intervalStart, intervalEnd, filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations) {
|
| 540 |
+
// https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree
|
| 541 |
+
// Now, it is known that two intervals A and B overlap only when both
|
| 542 |
+
// A.low <= B.high and A.high >= B.low. When searching the trees for
|
| 543 |
+
// nodes overlapping with a given interval, you can immediately skip:
|
| 544 |
+
// a) all nodes to the right of nodes whose low value is past the end of the given interval.
|
| 545 |
+
// b) all nodes that have their maximum 'high' value below the start of the given interval.
|
| 546 |
+
let node = T.root;
|
| 547 |
+
let delta = 0;
|
| 548 |
+
let nodeMaxEnd = 0;
|
| 549 |
+
let nodeStart = 0;
|
| 550 |
+
let nodeEnd = 0;
|
| 551 |
+
const result = [];
|
| 552 |
+
let resultLen = 0;
|
| 553 |
+
while (node !== SENTINEL) {
|
| 554 |
+
if (getNodeIsVisited(node)) {
|
| 555 |
+
// going up from this node
|
| 556 |
+
setNodeIsVisited(node.left, false);
|
| 557 |
+
setNodeIsVisited(node.right, false);
|
| 558 |
+
if (node === node.parent.right) {
|
| 559 |
+
delta -= node.parent.delta;
|
| 560 |
+
}
|
| 561 |
+
node = node.parent;
|
| 562 |
+
continue;
|
| 563 |
+
}
|
| 564 |
+
if (!getNodeIsVisited(node.left)) {
|
| 565 |
+
// first time seeing this node
|
| 566 |
+
nodeMaxEnd = delta + node.maxEnd;
|
| 567 |
+
if (nodeMaxEnd < intervalStart) {
|
| 568 |
+
// cover case b) from above
|
| 569 |
+
// there is no need to search this node or its children
|
| 570 |
+
setNodeIsVisited(node, true);
|
| 571 |
+
continue;
|
| 572 |
+
}
|
| 573 |
+
if (node.left !== SENTINEL) {
|
| 574 |
+
// go left
|
| 575 |
+
node = node.left;
|
| 576 |
+
continue;
|
| 577 |
+
}
|
| 578 |
+
}
|
| 579 |
+
// handle current node
|
| 580 |
+
nodeStart = delta + node.start;
|
| 581 |
+
if (nodeStart > intervalEnd) {
|
| 582 |
+
// cover case a) from above
|
| 583 |
+
// there is no need to search this node or its right subtree
|
| 584 |
+
setNodeIsVisited(node, true);
|
| 585 |
+
continue;
|
| 586 |
+
}
|
| 587 |
+
nodeEnd = delta + node.end;
|
| 588 |
+
if (nodeEnd >= intervalStart) {
|
| 589 |
+
// There is overlap
|
| 590 |
+
node.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId);
|
| 591 |
+
let include = true;
|
| 592 |
+
if (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) {
|
| 593 |
+
include = false;
|
| 594 |
+
}
|
| 595 |
+
if (filterOutValidation && getNodeIsForValidation(node)) {
|
| 596 |
+
include = false;
|
| 597 |
+
}
|
| 598 |
+
if (onlyMarginDecorations && !getNodeIsInGlyphMargin(node)) {
|
| 599 |
+
include = false;
|
| 600 |
+
}
|
| 601 |
+
if (include) {
|
| 602 |
+
result[resultLen++] = node;
|
| 603 |
+
}
|
| 604 |
+
}
|
| 605 |
+
setNodeIsVisited(node, true);
|
| 606 |
+
if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {
|
| 607 |
+
// go right
|
| 608 |
+
delta += node.delta;
|
| 609 |
+
node = node.right;
|
| 610 |
+
continue;
|
| 611 |
+
}
|
| 612 |
+
}
|
| 613 |
+
setNodeIsVisited(T.root, false);
|
| 614 |
+
return result;
|
| 615 |
+
}
|
| 616 |
+
//#endregion
|
| 617 |
+
//#region Insertion
|
| 618 |
+
function rbTreeInsert(T, newNode) {
|
| 619 |
+
if (T.root === SENTINEL) {
|
| 620 |
+
newNode.parent = SENTINEL;
|
| 621 |
+
newNode.left = SENTINEL;
|
| 622 |
+
newNode.right = SENTINEL;
|
| 623 |
+
setNodeColor(newNode, 0 /* NodeColor.Black */);
|
| 624 |
+
T.root = newNode;
|
| 625 |
+
return T.root;
|
| 626 |
+
}
|
| 627 |
+
treeInsert(T, newNode);
|
| 628 |
+
recomputeMaxEndWalkToRoot(newNode.parent);
|
| 629 |
+
// repair tree
|
| 630 |
+
let x = newNode;
|
| 631 |
+
while (x !== T.root && getNodeColor(x.parent) === 1 /* NodeColor.Red */) {
|
| 632 |
+
if (x.parent === x.parent.parent.left) {
|
| 633 |
+
const y = x.parent.parent.right;
|
| 634 |
+
if (getNodeColor(y) === 1 /* NodeColor.Red */) {
|
| 635 |
+
setNodeColor(x.parent, 0 /* NodeColor.Black */);
|
| 636 |
+
setNodeColor(y, 0 /* NodeColor.Black */);
|
| 637 |
+
setNodeColor(x.parent.parent, 1 /* NodeColor.Red */);
|
| 638 |
+
x = x.parent.parent;
|
| 639 |
+
}
|
| 640 |
+
else {
|
| 641 |
+
if (x === x.parent.right) {
|
| 642 |
+
x = x.parent;
|
| 643 |
+
leftRotate(T, x);
|
| 644 |
+
}
|
| 645 |
+
setNodeColor(x.parent, 0 /* NodeColor.Black */);
|
| 646 |
+
setNodeColor(x.parent.parent, 1 /* NodeColor.Red */);
|
| 647 |
+
rightRotate(T, x.parent.parent);
|
| 648 |
+
}
|
| 649 |
+
}
|
| 650 |
+
else {
|
| 651 |
+
const y = x.parent.parent.left;
|
| 652 |
+
if (getNodeColor(y) === 1 /* NodeColor.Red */) {
|
| 653 |
+
setNodeColor(x.parent, 0 /* NodeColor.Black */);
|
| 654 |
+
setNodeColor(y, 0 /* NodeColor.Black */);
|
| 655 |
+
setNodeColor(x.parent.parent, 1 /* NodeColor.Red */);
|
| 656 |
+
x = x.parent.parent;
|
| 657 |
+
}
|
| 658 |
+
else {
|
| 659 |
+
if (x === x.parent.left) {
|
| 660 |
+
x = x.parent;
|
| 661 |
+
rightRotate(T, x);
|
| 662 |
+
}
|
| 663 |
+
setNodeColor(x.parent, 0 /* NodeColor.Black */);
|
| 664 |
+
setNodeColor(x.parent.parent, 1 /* NodeColor.Red */);
|
| 665 |
+
leftRotate(T, x.parent.parent);
|
| 666 |
+
}
|
| 667 |
+
}
|
| 668 |
+
}
|
| 669 |
+
setNodeColor(T.root, 0 /* NodeColor.Black */);
|
| 670 |
+
return newNode;
|
| 671 |
+
}
|
| 672 |
+
function treeInsert(T, z) {
|
| 673 |
+
let delta = 0;
|
| 674 |
+
let x = T.root;
|
| 675 |
+
const zAbsoluteStart = z.start;
|
| 676 |
+
const zAbsoluteEnd = z.end;
|
| 677 |
+
while (true) {
|
| 678 |
+
const cmp = intervalCompare(zAbsoluteStart, zAbsoluteEnd, x.start + delta, x.end + delta);
|
| 679 |
+
if (cmp < 0) {
|
| 680 |
+
// this node should be inserted to the left
|
| 681 |
+
// => it is not affected by the node's delta
|
| 682 |
+
if (x.left === SENTINEL) {
|
| 683 |
+
z.start -= delta;
|
| 684 |
+
z.end -= delta;
|
| 685 |
+
z.maxEnd -= delta;
|
| 686 |
+
x.left = z;
|
| 687 |
+
break;
|
| 688 |
+
}
|
| 689 |
+
else {
|
| 690 |
+
x = x.left;
|
| 691 |
+
}
|
| 692 |
+
}
|
| 693 |
+
else {
|
| 694 |
+
// this node should be inserted to the right
|
| 695 |
+
// => it is not affected by the node's delta
|
| 696 |
+
if (x.right === SENTINEL) {
|
| 697 |
+
z.start -= (delta + x.delta);
|
| 698 |
+
z.end -= (delta + x.delta);
|
| 699 |
+
z.maxEnd -= (delta + x.delta);
|
| 700 |
+
x.right = z;
|
| 701 |
+
break;
|
| 702 |
+
}
|
| 703 |
+
else {
|
| 704 |
+
delta += x.delta;
|
| 705 |
+
x = x.right;
|
| 706 |
+
}
|
| 707 |
+
}
|
| 708 |
+
}
|
| 709 |
+
z.parent = x;
|
| 710 |
+
z.left = SENTINEL;
|
| 711 |
+
z.right = SENTINEL;
|
| 712 |
+
setNodeColor(z, 1 /* NodeColor.Red */);
|
| 713 |
+
}
|
| 714 |
+
//#endregion
|
| 715 |
+
//#region Deletion
|
| 716 |
+
function rbTreeDelete(T, z) {
|
| 717 |
+
let x;
|
| 718 |
+
let y;
|
| 719 |
+
// RB-DELETE except we don't swap z and y in case c)
|
| 720 |
+
// i.e. we always delete what's pointed at by z.
|
| 721 |
+
if (z.left === SENTINEL) {
|
| 722 |
+
x = z.right;
|
| 723 |
+
y = z;
|
| 724 |
+
// x's delta is no longer influenced by z's delta
|
| 725 |
+
x.delta += z.delta;
|
| 726 |
+
if (x.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || x.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {
|
| 727 |
+
T.requestNormalizeDelta = true;
|
| 728 |
+
}
|
| 729 |
+
x.start += z.delta;
|
| 730 |
+
x.end += z.delta;
|
| 731 |
+
}
|
| 732 |
+
else if (z.right === SENTINEL) {
|
| 733 |
+
x = z.left;
|
| 734 |
+
y = z;
|
| 735 |
+
}
|
| 736 |
+
else {
|
| 737 |
+
y = leftest(z.right);
|
| 738 |
+
x = y.right;
|
| 739 |
+
// y's delta is no longer influenced by z's delta,
|
| 740 |
+
// but we don't want to walk the entire right-hand-side subtree of x.
|
| 741 |
+
// we therefore maintain z's delta in y, and adjust only x
|
| 742 |
+
x.start += y.delta;
|
| 743 |
+
x.end += y.delta;
|
| 744 |
+
x.delta += y.delta;
|
| 745 |
+
if (x.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || x.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {
|
| 746 |
+
T.requestNormalizeDelta = true;
|
| 747 |
+
}
|
| 748 |
+
y.start += z.delta;
|
| 749 |
+
y.end += z.delta;
|
| 750 |
+
y.delta = z.delta;
|
| 751 |
+
if (y.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || y.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {
|
| 752 |
+
T.requestNormalizeDelta = true;
|
| 753 |
+
}
|
| 754 |
+
}
|
| 755 |
+
if (y === T.root) {
|
| 756 |
+
T.root = x;
|
| 757 |
+
setNodeColor(x, 0 /* NodeColor.Black */);
|
| 758 |
+
z.detach();
|
| 759 |
+
resetSentinel();
|
| 760 |
+
recomputeMaxEnd(x);
|
| 761 |
+
T.root.parent = SENTINEL;
|
| 762 |
+
return;
|
| 763 |
+
}
|
| 764 |
+
const yWasRed = (getNodeColor(y) === 1 /* NodeColor.Red */);
|
| 765 |
+
if (y === y.parent.left) {
|
| 766 |
+
y.parent.left = x;
|
| 767 |
+
}
|
| 768 |
+
else {
|
| 769 |
+
y.parent.right = x;
|
| 770 |
+
}
|
| 771 |
+
if (y === z) {
|
| 772 |
+
x.parent = y.parent;
|
| 773 |
+
}
|
| 774 |
+
else {
|
| 775 |
+
if (y.parent === z) {
|
| 776 |
+
x.parent = y;
|
| 777 |
+
}
|
| 778 |
+
else {
|
| 779 |
+
x.parent = y.parent;
|
| 780 |
+
}
|
| 781 |
+
y.left = z.left;
|
| 782 |
+
y.right = z.right;
|
| 783 |
+
y.parent = z.parent;
|
| 784 |
+
setNodeColor(y, getNodeColor(z));
|
| 785 |
+
if (z === T.root) {
|
| 786 |
+
T.root = y;
|
| 787 |
+
}
|
| 788 |
+
else {
|
| 789 |
+
if (z === z.parent.left) {
|
| 790 |
+
z.parent.left = y;
|
| 791 |
+
}
|
| 792 |
+
else {
|
| 793 |
+
z.parent.right = y;
|
| 794 |
+
}
|
| 795 |
+
}
|
| 796 |
+
if (y.left !== SENTINEL) {
|
| 797 |
+
y.left.parent = y;
|
| 798 |
+
}
|
| 799 |
+
if (y.right !== SENTINEL) {
|
| 800 |
+
y.right.parent = y;
|
| 801 |
+
}
|
| 802 |
+
}
|
| 803 |
+
z.detach();
|
| 804 |
+
if (yWasRed) {
|
| 805 |
+
recomputeMaxEndWalkToRoot(x.parent);
|
| 806 |
+
if (y !== z) {
|
| 807 |
+
recomputeMaxEndWalkToRoot(y);
|
| 808 |
+
recomputeMaxEndWalkToRoot(y.parent);
|
| 809 |
+
}
|
| 810 |
+
resetSentinel();
|
| 811 |
+
return;
|
| 812 |
+
}
|
| 813 |
+
recomputeMaxEndWalkToRoot(x);
|
| 814 |
+
recomputeMaxEndWalkToRoot(x.parent);
|
| 815 |
+
if (y !== z) {
|
| 816 |
+
recomputeMaxEndWalkToRoot(y);
|
| 817 |
+
recomputeMaxEndWalkToRoot(y.parent);
|
| 818 |
+
}
|
| 819 |
+
// RB-DELETE-FIXUP
|
| 820 |
+
let w;
|
| 821 |
+
while (x !== T.root && getNodeColor(x) === 0 /* NodeColor.Black */) {
|
| 822 |
+
if (x === x.parent.left) {
|
| 823 |
+
w = x.parent.right;
|
| 824 |
+
if (getNodeColor(w) === 1 /* NodeColor.Red */) {
|
| 825 |
+
setNodeColor(w, 0 /* NodeColor.Black */);
|
| 826 |
+
setNodeColor(x.parent, 1 /* NodeColor.Red */);
|
| 827 |
+
leftRotate(T, x.parent);
|
| 828 |
+
w = x.parent.right;
|
| 829 |
+
}
|
| 830 |
+
if (getNodeColor(w.left) === 0 /* NodeColor.Black */ && getNodeColor(w.right) === 0 /* NodeColor.Black */) {
|
| 831 |
+
setNodeColor(w, 1 /* NodeColor.Red */);
|
| 832 |
+
x = x.parent;
|
| 833 |
+
}
|
| 834 |
+
else {
|
| 835 |
+
if (getNodeColor(w.right) === 0 /* NodeColor.Black */) {
|
| 836 |
+
setNodeColor(w.left, 0 /* NodeColor.Black */);
|
| 837 |
+
setNodeColor(w, 1 /* NodeColor.Red */);
|
| 838 |
+
rightRotate(T, w);
|
| 839 |
+
w = x.parent.right;
|
| 840 |
+
}
|
| 841 |
+
setNodeColor(w, getNodeColor(x.parent));
|
| 842 |
+
setNodeColor(x.parent, 0 /* NodeColor.Black */);
|
| 843 |
+
setNodeColor(w.right, 0 /* NodeColor.Black */);
|
| 844 |
+
leftRotate(T, x.parent);
|
| 845 |
+
x = T.root;
|
| 846 |
+
}
|
| 847 |
+
}
|
| 848 |
+
else {
|
| 849 |
+
w = x.parent.left;
|
| 850 |
+
if (getNodeColor(w) === 1 /* NodeColor.Red */) {
|
| 851 |
+
setNodeColor(w, 0 /* NodeColor.Black */);
|
| 852 |
+
setNodeColor(x.parent, 1 /* NodeColor.Red */);
|
| 853 |
+
rightRotate(T, x.parent);
|
| 854 |
+
w = x.parent.left;
|
| 855 |
+
}
|
| 856 |
+
if (getNodeColor(w.left) === 0 /* NodeColor.Black */ && getNodeColor(w.right) === 0 /* NodeColor.Black */) {
|
| 857 |
+
setNodeColor(w, 1 /* NodeColor.Red */);
|
| 858 |
+
x = x.parent;
|
| 859 |
+
}
|
| 860 |
+
else {
|
| 861 |
+
if (getNodeColor(w.left) === 0 /* NodeColor.Black */) {
|
| 862 |
+
setNodeColor(w.right, 0 /* NodeColor.Black */);
|
| 863 |
+
setNodeColor(w, 1 /* NodeColor.Red */);
|
| 864 |
+
leftRotate(T, w);
|
| 865 |
+
w = x.parent.left;
|
| 866 |
+
}
|
| 867 |
+
setNodeColor(w, getNodeColor(x.parent));
|
| 868 |
+
setNodeColor(x.parent, 0 /* NodeColor.Black */);
|
| 869 |
+
setNodeColor(w.left, 0 /* NodeColor.Black */);
|
| 870 |
+
rightRotate(T, x.parent);
|
| 871 |
+
x = T.root;
|
| 872 |
+
}
|
| 873 |
+
}
|
| 874 |
+
}
|
| 875 |
+
setNodeColor(x, 0 /* NodeColor.Black */);
|
| 876 |
+
resetSentinel();
|
| 877 |
+
}
|
| 878 |
+
function leftest(node) {
|
| 879 |
+
while (node.left !== SENTINEL) {
|
| 880 |
+
node = node.left;
|
| 881 |
+
}
|
| 882 |
+
return node;
|
| 883 |
+
}
|
| 884 |
+
function resetSentinel() {
|
| 885 |
+
SENTINEL.parent = SENTINEL;
|
| 886 |
+
SENTINEL.delta = 0; // optional
|
| 887 |
+
SENTINEL.start = 0; // optional
|
| 888 |
+
SENTINEL.end = 0; // optional
|
| 889 |
+
}
|
| 890 |
+
//#endregion
|
| 891 |
+
//#region Rotations
|
| 892 |
+
function leftRotate(T, x) {
|
| 893 |
+
const y = x.right; // set y.
|
| 894 |
+
y.delta += x.delta; // y's delta is no longer influenced by x's delta
|
| 895 |
+
if (y.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || y.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {
|
| 896 |
+
T.requestNormalizeDelta = true;
|
| 897 |
+
}
|
| 898 |
+
y.start += x.delta;
|
| 899 |
+
y.end += x.delta;
|
| 900 |
+
x.right = y.left; // turn y's left subtree into x's right subtree.
|
| 901 |
+
if (y.left !== SENTINEL) {
|
| 902 |
+
y.left.parent = x;
|
| 903 |
+
}
|
| 904 |
+
y.parent = x.parent; // link x's parent to y.
|
| 905 |
+
if (x.parent === SENTINEL) {
|
| 906 |
+
T.root = y;
|
| 907 |
+
}
|
| 908 |
+
else if (x === x.parent.left) {
|
| 909 |
+
x.parent.left = y;
|
| 910 |
+
}
|
| 911 |
+
else {
|
| 912 |
+
x.parent.right = y;
|
| 913 |
+
}
|
| 914 |
+
y.left = x; // put x on y's left.
|
| 915 |
+
x.parent = y;
|
| 916 |
+
recomputeMaxEnd(x);
|
| 917 |
+
recomputeMaxEnd(y);
|
| 918 |
+
}
|
| 919 |
+
function rightRotate(T, y) {
|
| 920 |
+
const x = y.left;
|
| 921 |
+
y.delta -= x.delta;
|
| 922 |
+
if (y.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || y.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {
|
| 923 |
+
T.requestNormalizeDelta = true;
|
| 924 |
+
}
|
| 925 |
+
y.start -= x.delta;
|
| 926 |
+
y.end -= x.delta;
|
| 927 |
+
y.left = x.right;
|
| 928 |
+
if (x.right !== SENTINEL) {
|
| 929 |
+
x.right.parent = y;
|
| 930 |
+
}
|
| 931 |
+
x.parent = y.parent;
|
| 932 |
+
if (y.parent === SENTINEL) {
|
| 933 |
+
T.root = x;
|
| 934 |
+
}
|
| 935 |
+
else if (y === y.parent.right) {
|
| 936 |
+
y.parent.right = x;
|
| 937 |
+
}
|
| 938 |
+
else {
|
| 939 |
+
y.parent.left = x;
|
| 940 |
+
}
|
| 941 |
+
x.right = y;
|
| 942 |
+
y.parent = x;
|
| 943 |
+
recomputeMaxEnd(y);
|
| 944 |
+
recomputeMaxEnd(x);
|
| 945 |
+
}
|
| 946 |
+
//#endregion
|
| 947 |
+
//#region max end computation
|
| 948 |
+
function computeMaxEnd(node) {
|
| 949 |
+
let maxEnd = node.end;
|
| 950 |
+
if (node.left !== SENTINEL) {
|
| 951 |
+
const leftMaxEnd = node.left.maxEnd;
|
| 952 |
+
if (leftMaxEnd > maxEnd) {
|
| 953 |
+
maxEnd = leftMaxEnd;
|
| 954 |
+
}
|
| 955 |
+
}
|
| 956 |
+
if (node.right !== SENTINEL) {
|
| 957 |
+
const rightMaxEnd = node.right.maxEnd + node.delta;
|
| 958 |
+
if (rightMaxEnd > maxEnd) {
|
| 959 |
+
maxEnd = rightMaxEnd;
|
| 960 |
+
}
|
| 961 |
+
}
|
| 962 |
+
return maxEnd;
|
| 963 |
+
}
|
| 964 |
+
export function recomputeMaxEnd(node) {
|
| 965 |
+
node.maxEnd = computeMaxEnd(node);
|
| 966 |
+
}
|
| 967 |
+
function recomputeMaxEndWalkToRoot(node) {
|
| 968 |
+
while (node !== SENTINEL) {
|
| 969 |
+
const maxEnd = computeMaxEnd(node);
|
| 970 |
+
if (node.maxEnd === maxEnd) {
|
| 971 |
+
// no need to go further
|
| 972 |
+
return;
|
| 973 |
+
}
|
| 974 |
+
node.maxEnd = maxEnd;
|
| 975 |
+
node = node.parent;
|
| 976 |
+
}
|
| 977 |
+
}
|
| 978 |
+
//#endregion
|
| 979 |
+
//#region utils
|
| 980 |
+
export function intervalCompare(aStart, aEnd, bStart, bEnd) {
|
| 981 |
+
if (aStart === bStart) {
|
| 982 |
+
return aEnd - bEnd;
|
| 983 |
+
}
|
| 984 |
+
return aStart - bStart;
|
| 985 |
+
}
|
| 986 |
+
//#endregion
|
node_modules/monaco-editor/esm/vs/editor/common/model/mirrorTextModel.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { splitLines } from '../../../base/common/strings.js';
|
| 6 |
+
import { Position } from '../core/position.js';
|
| 7 |
+
import { PrefixSumComputer } from './prefixSumComputer.js';
|
| 8 |
+
export class MirrorTextModel {
|
| 9 |
+
constructor(uri, lines, eol, versionId) {
|
| 10 |
+
this._uri = uri;
|
| 11 |
+
this._lines = lines;
|
| 12 |
+
this._eol = eol;
|
| 13 |
+
this._versionId = versionId;
|
| 14 |
+
this._lineStarts = null;
|
| 15 |
+
this._cachedTextValue = null;
|
| 16 |
+
}
|
| 17 |
+
dispose() {
|
| 18 |
+
this._lines.length = 0;
|
| 19 |
+
}
|
| 20 |
+
get version() {
|
| 21 |
+
return this._versionId;
|
| 22 |
+
}
|
| 23 |
+
getText() {
|
| 24 |
+
if (this._cachedTextValue === null) {
|
| 25 |
+
this._cachedTextValue = this._lines.join(this._eol);
|
| 26 |
+
}
|
| 27 |
+
return this._cachedTextValue;
|
| 28 |
+
}
|
| 29 |
+
onEvents(e) {
|
| 30 |
+
if (e.eol && e.eol !== this._eol) {
|
| 31 |
+
this._eol = e.eol;
|
| 32 |
+
this._lineStarts = null;
|
| 33 |
+
}
|
| 34 |
+
// Update my lines
|
| 35 |
+
const changes = e.changes;
|
| 36 |
+
for (const change of changes) {
|
| 37 |
+
this._acceptDeleteRange(change.range);
|
| 38 |
+
this._acceptInsertText(new Position(change.range.startLineNumber, change.range.startColumn), change.text);
|
| 39 |
+
}
|
| 40 |
+
this._versionId = e.versionId;
|
| 41 |
+
this._cachedTextValue = null;
|
| 42 |
+
}
|
| 43 |
+
_ensureLineStarts() {
|
| 44 |
+
if (!this._lineStarts) {
|
| 45 |
+
const eolLength = this._eol.length;
|
| 46 |
+
const linesLength = this._lines.length;
|
| 47 |
+
const lineStartValues = new Uint32Array(linesLength);
|
| 48 |
+
for (let i = 0; i < linesLength; i++) {
|
| 49 |
+
lineStartValues[i] = this._lines[i].length + eolLength;
|
| 50 |
+
}
|
| 51 |
+
this._lineStarts = new PrefixSumComputer(lineStartValues);
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
/**
|
| 55 |
+
* All changes to a line's text go through this method
|
| 56 |
+
*/
|
| 57 |
+
_setLineText(lineIndex, newValue) {
|
| 58 |
+
this._lines[lineIndex] = newValue;
|
| 59 |
+
if (this._lineStarts) {
|
| 60 |
+
// update prefix sum
|
| 61 |
+
this._lineStarts.setValue(lineIndex, this._lines[lineIndex].length + this._eol.length);
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
_acceptDeleteRange(range) {
|
| 65 |
+
if (range.startLineNumber === range.endLineNumber) {
|
| 66 |
+
if (range.startColumn === range.endColumn) {
|
| 67 |
+
// Nothing to delete
|
| 68 |
+
return;
|
| 69 |
+
}
|
| 70 |
+
// Delete text on the affected line
|
| 71 |
+
this._setLineText(range.startLineNumber - 1, this._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1)
|
| 72 |
+
+ this._lines[range.startLineNumber - 1].substring(range.endColumn - 1));
|
| 73 |
+
return;
|
| 74 |
+
}
|
| 75 |
+
// Take remaining text on last line and append it to remaining text on first line
|
| 76 |
+
this._setLineText(range.startLineNumber - 1, this._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1)
|
| 77 |
+
+ this._lines[range.endLineNumber - 1].substring(range.endColumn - 1));
|
| 78 |
+
// Delete middle lines
|
| 79 |
+
this._lines.splice(range.startLineNumber, range.endLineNumber - range.startLineNumber);
|
| 80 |
+
if (this._lineStarts) {
|
| 81 |
+
// update prefix sum
|
| 82 |
+
this._lineStarts.removeValues(range.startLineNumber, range.endLineNumber - range.startLineNumber);
|
| 83 |
+
}
|
| 84 |
+
}
|
| 85 |
+
_acceptInsertText(position, insertText) {
|
| 86 |
+
if (insertText.length === 0) {
|
| 87 |
+
// Nothing to insert
|
| 88 |
+
return;
|
| 89 |
+
}
|
| 90 |
+
const insertLines = splitLines(insertText);
|
| 91 |
+
if (insertLines.length === 1) {
|
| 92 |
+
// Inserting text on one line
|
| 93 |
+
this._setLineText(position.lineNumber - 1, this._lines[position.lineNumber - 1].substring(0, position.column - 1)
|
| 94 |
+
+ insertLines[0]
|
| 95 |
+
+ this._lines[position.lineNumber - 1].substring(position.column - 1));
|
| 96 |
+
return;
|
| 97 |
+
}
|
| 98 |
+
// Append overflowing text from first line to the end of text to insert
|
| 99 |
+
insertLines[insertLines.length - 1] += this._lines[position.lineNumber - 1].substring(position.column - 1);
|
| 100 |
+
// Delete overflowing text from first line and insert text on first line
|
| 101 |
+
this._setLineText(position.lineNumber - 1, this._lines[position.lineNumber - 1].substring(0, position.column - 1)
|
| 102 |
+
+ insertLines[0]);
|
| 103 |
+
// Insert new lines & store lengths
|
| 104 |
+
const newLengths = new Uint32Array(insertLines.length - 1);
|
| 105 |
+
for (let i = 1; i < insertLines.length; i++) {
|
| 106 |
+
this._lines.splice(position.lineNumber + i - 1, 0, insertLines[i]);
|
| 107 |
+
newLengths[i - 1] = insertLines[i].length + this._eol.length;
|
| 108 |
+
}
|
| 109 |
+
if (this._lineStarts) {
|
| 110 |
+
// update prefix sum
|
| 111 |
+
this._lineStarts.insertValues(position.lineNumber, newLengths);
|
| 112 |
+
}
|
| 113 |
+
}
|
| 114 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.js
ADDED
|
@@ -0,0 +1,1452 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { Position } from '../../core/position.js';
|
| 6 |
+
import { Range } from '../../core/range.js';
|
| 7 |
+
import { FindMatch } from '../../model.js';
|
| 8 |
+
import { SENTINEL, TreeNode, fixInsert, leftest, rbDelete, righttest, updateTreeMetadata } from './rbTreeBase.js';
|
| 9 |
+
import { Searcher, createFindMatch, isValidMatch } from '../textModelSearch.js';
|
| 10 |
+
// const lfRegex = new RegExp(/\r\n|\r|\n/g);
|
| 11 |
+
const AverageBufferSize = 65535;
|
| 12 |
+
function createUintArray(arr) {
|
| 13 |
+
let r;
|
| 14 |
+
if (arr[arr.length - 1] < 65536) {
|
| 15 |
+
r = new Uint16Array(arr.length);
|
| 16 |
+
}
|
| 17 |
+
else {
|
| 18 |
+
r = new Uint32Array(arr.length);
|
| 19 |
+
}
|
| 20 |
+
r.set(arr, 0);
|
| 21 |
+
return r;
|
| 22 |
+
}
|
| 23 |
+
class LineStarts {
|
| 24 |
+
constructor(lineStarts, cr, lf, crlf, isBasicASCII) {
|
| 25 |
+
this.lineStarts = lineStarts;
|
| 26 |
+
this.cr = cr;
|
| 27 |
+
this.lf = lf;
|
| 28 |
+
this.crlf = crlf;
|
| 29 |
+
this.isBasicASCII = isBasicASCII;
|
| 30 |
+
}
|
| 31 |
+
}
|
| 32 |
+
export function createLineStartsFast(str, readonly = true) {
|
| 33 |
+
const r = [0];
|
| 34 |
+
let rLength = 1;
|
| 35 |
+
for (let i = 0, len = str.length; i < len; i++) {
|
| 36 |
+
const chr = str.charCodeAt(i);
|
| 37 |
+
if (chr === 13 /* CharCode.CarriageReturn */) {
|
| 38 |
+
if (i + 1 < len && str.charCodeAt(i + 1) === 10 /* CharCode.LineFeed */) {
|
| 39 |
+
// \r\n... case
|
| 40 |
+
r[rLength++] = i + 2;
|
| 41 |
+
i++; // skip \n
|
| 42 |
+
}
|
| 43 |
+
else {
|
| 44 |
+
// \r... case
|
| 45 |
+
r[rLength++] = i + 1;
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
else if (chr === 10 /* CharCode.LineFeed */) {
|
| 49 |
+
r[rLength++] = i + 1;
|
| 50 |
+
}
|
| 51 |
+
}
|
| 52 |
+
if (readonly) {
|
| 53 |
+
return createUintArray(r);
|
| 54 |
+
}
|
| 55 |
+
else {
|
| 56 |
+
return r;
|
| 57 |
+
}
|
| 58 |
+
}
|
| 59 |
+
export function createLineStarts(r, str) {
|
| 60 |
+
r.length = 0;
|
| 61 |
+
r[0] = 0;
|
| 62 |
+
let rLength = 1;
|
| 63 |
+
let cr = 0, lf = 0, crlf = 0;
|
| 64 |
+
let isBasicASCII = true;
|
| 65 |
+
for (let i = 0, len = str.length; i < len; i++) {
|
| 66 |
+
const chr = str.charCodeAt(i);
|
| 67 |
+
if (chr === 13 /* CharCode.CarriageReturn */) {
|
| 68 |
+
if (i + 1 < len && str.charCodeAt(i + 1) === 10 /* CharCode.LineFeed */) {
|
| 69 |
+
// \r\n... case
|
| 70 |
+
crlf++;
|
| 71 |
+
r[rLength++] = i + 2;
|
| 72 |
+
i++; // skip \n
|
| 73 |
+
}
|
| 74 |
+
else {
|
| 75 |
+
cr++;
|
| 76 |
+
// \r... case
|
| 77 |
+
r[rLength++] = i + 1;
|
| 78 |
+
}
|
| 79 |
+
}
|
| 80 |
+
else if (chr === 10 /* CharCode.LineFeed */) {
|
| 81 |
+
lf++;
|
| 82 |
+
r[rLength++] = i + 1;
|
| 83 |
+
}
|
| 84 |
+
else {
|
| 85 |
+
if (isBasicASCII) {
|
| 86 |
+
if (chr !== 9 /* CharCode.Tab */ && (chr < 32 || chr > 126)) {
|
| 87 |
+
isBasicASCII = false;
|
| 88 |
+
}
|
| 89 |
+
}
|
| 90 |
+
}
|
| 91 |
+
}
|
| 92 |
+
const result = new LineStarts(createUintArray(r), cr, lf, crlf, isBasicASCII);
|
| 93 |
+
r.length = 0;
|
| 94 |
+
return result;
|
| 95 |
+
}
|
| 96 |
+
export class Piece {
|
| 97 |
+
constructor(bufferIndex, start, end, lineFeedCnt, length) {
|
| 98 |
+
this.bufferIndex = bufferIndex;
|
| 99 |
+
this.start = start;
|
| 100 |
+
this.end = end;
|
| 101 |
+
this.lineFeedCnt = lineFeedCnt;
|
| 102 |
+
this.length = length;
|
| 103 |
+
}
|
| 104 |
+
}
|
| 105 |
+
export class StringBuffer {
|
| 106 |
+
constructor(buffer, lineStarts) {
|
| 107 |
+
this.buffer = buffer;
|
| 108 |
+
this.lineStarts = lineStarts;
|
| 109 |
+
}
|
| 110 |
+
}
|
| 111 |
+
/**
|
| 112 |
+
* Readonly snapshot for piece tree.
|
| 113 |
+
* In a real multiple thread environment, to make snapshot reading always work correctly, we need to
|
| 114 |
+
* 1. Make TreeNode.piece immutable, then reading and writing can run in parallel.
|
| 115 |
+
* 2. TreeNode/Buffers normalization should not happen during snapshot reading.
|
| 116 |
+
*/
|
| 117 |
+
class PieceTreeSnapshot {
|
| 118 |
+
constructor(tree, BOM) {
|
| 119 |
+
this._pieces = [];
|
| 120 |
+
this._tree = tree;
|
| 121 |
+
this._BOM = BOM;
|
| 122 |
+
this._index = 0;
|
| 123 |
+
if (tree.root !== SENTINEL) {
|
| 124 |
+
tree.iterate(tree.root, node => {
|
| 125 |
+
if (node !== SENTINEL) {
|
| 126 |
+
this._pieces.push(node.piece);
|
| 127 |
+
}
|
| 128 |
+
return true;
|
| 129 |
+
});
|
| 130 |
+
}
|
| 131 |
+
}
|
| 132 |
+
read() {
|
| 133 |
+
if (this._pieces.length === 0) {
|
| 134 |
+
if (this._index === 0) {
|
| 135 |
+
this._index++;
|
| 136 |
+
return this._BOM;
|
| 137 |
+
}
|
| 138 |
+
else {
|
| 139 |
+
return null;
|
| 140 |
+
}
|
| 141 |
+
}
|
| 142 |
+
if (this._index > this._pieces.length - 1) {
|
| 143 |
+
return null;
|
| 144 |
+
}
|
| 145 |
+
if (this._index === 0) {
|
| 146 |
+
return this._BOM + this._tree.getPieceContent(this._pieces[this._index++]);
|
| 147 |
+
}
|
| 148 |
+
return this._tree.getPieceContent(this._pieces[this._index++]);
|
| 149 |
+
}
|
| 150 |
+
}
|
| 151 |
+
class PieceTreeSearchCache {
|
| 152 |
+
constructor(limit) {
|
| 153 |
+
this._limit = limit;
|
| 154 |
+
this._cache = [];
|
| 155 |
+
}
|
| 156 |
+
get(offset) {
|
| 157 |
+
for (let i = this._cache.length - 1; i >= 0; i--) {
|
| 158 |
+
const nodePos = this._cache[i];
|
| 159 |
+
if (nodePos.nodeStartOffset <= offset && nodePos.nodeStartOffset + nodePos.node.piece.length >= offset) {
|
| 160 |
+
return nodePos;
|
| 161 |
+
}
|
| 162 |
+
}
|
| 163 |
+
return null;
|
| 164 |
+
}
|
| 165 |
+
get2(lineNumber) {
|
| 166 |
+
for (let i = this._cache.length - 1; i >= 0; i--) {
|
| 167 |
+
const nodePos = this._cache[i];
|
| 168 |
+
if (nodePos.nodeStartLineNumber && nodePos.nodeStartLineNumber < lineNumber && nodePos.nodeStartLineNumber + nodePos.node.piece.lineFeedCnt >= lineNumber) {
|
| 169 |
+
return nodePos;
|
| 170 |
+
}
|
| 171 |
+
}
|
| 172 |
+
return null;
|
| 173 |
+
}
|
| 174 |
+
set(nodePosition) {
|
| 175 |
+
if (this._cache.length >= this._limit) {
|
| 176 |
+
this._cache.shift();
|
| 177 |
+
}
|
| 178 |
+
this._cache.push(nodePosition);
|
| 179 |
+
}
|
| 180 |
+
validate(offset) {
|
| 181 |
+
let hasInvalidVal = false;
|
| 182 |
+
const tmp = this._cache;
|
| 183 |
+
for (let i = 0; i < tmp.length; i++) {
|
| 184 |
+
const nodePos = tmp[i];
|
| 185 |
+
if (nodePos.node.parent === null || nodePos.nodeStartOffset >= offset) {
|
| 186 |
+
tmp[i] = null;
|
| 187 |
+
hasInvalidVal = true;
|
| 188 |
+
continue;
|
| 189 |
+
}
|
| 190 |
+
}
|
| 191 |
+
if (hasInvalidVal) {
|
| 192 |
+
const newArr = [];
|
| 193 |
+
for (const entry of tmp) {
|
| 194 |
+
if (entry !== null) {
|
| 195 |
+
newArr.push(entry);
|
| 196 |
+
}
|
| 197 |
+
}
|
| 198 |
+
this._cache = newArr;
|
| 199 |
+
}
|
| 200 |
+
}
|
| 201 |
+
}
|
| 202 |
+
export class PieceTreeBase {
|
| 203 |
+
constructor(chunks, eol, eolNormalized) {
|
| 204 |
+
this.create(chunks, eol, eolNormalized);
|
| 205 |
+
}
|
| 206 |
+
create(chunks, eol, eolNormalized) {
|
| 207 |
+
this._buffers = [
|
| 208 |
+
new StringBuffer('', [0])
|
| 209 |
+
];
|
| 210 |
+
this._lastChangeBufferPos = { line: 0, column: 0 };
|
| 211 |
+
this.root = SENTINEL;
|
| 212 |
+
this._lineCnt = 1;
|
| 213 |
+
this._length = 0;
|
| 214 |
+
this._EOL = eol;
|
| 215 |
+
this._EOLLength = eol.length;
|
| 216 |
+
this._EOLNormalized = eolNormalized;
|
| 217 |
+
let lastNode = null;
|
| 218 |
+
for (let i = 0, len = chunks.length; i < len; i++) {
|
| 219 |
+
if (chunks[i].buffer.length > 0) {
|
| 220 |
+
if (!chunks[i].lineStarts) {
|
| 221 |
+
chunks[i].lineStarts = createLineStartsFast(chunks[i].buffer);
|
| 222 |
+
}
|
| 223 |
+
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);
|
| 224 |
+
this._buffers.push(chunks[i]);
|
| 225 |
+
lastNode = this.rbInsertRight(lastNode, piece);
|
| 226 |
+
}
|
| 227 |
+
}
|
| 228 |
+
this._searchCache = new PieceTreeSearchCache(1);
|
| 229 |
+
this._lastVisitedLine = { lineNumber: 0, value: '' };
|
| 230 |
+
this.computeBufferMetadata();
|
| 231 |
+
}
|
| 232 |
+
normalizeEOL(eol) {
|
| 233 |
+
const averageBufferSize = AverageBufferSize;
|
| 234 |
+
const min = averageBufferSize - Math.floor(averageBufferSize / 3);
|
| 235 |
+
const max = min * 2;
|
| 236 |
+
let tempChunk = '';
|
| 237 |
+
let tempChunkLen = 0;
|
| 238 |
+
const chunks = [];
|
| 239 |
+
this.iterate(this.root, node => {
|
| 240 |
+
const str = this.getNodeContent(node);
|
| 241 |
+
const len = str.length;
|
| 242 |
+
if (tempChunkLen <= min || tempChunkLen + len < max) {
|
| 243 |
+
tempChunk += str;
|
| 244 |
+
tempChunkLen += len;
|
| 245 |
+
return true;
|
| 246 |
+
}
|
| 247 |
+
// flush anyways
|
| 248 |
+
const text = tempChunk.replace(/\r\n|\r|\n/g, eol);
|
| 249 |
+
chunks.push(new StringBuffer(text, createLineStartsFast(text)));
|
| 250 |
+
tempChunk = str;
|
| 251 |
+
tempChunkLen = len;
|
| 252 |
+
return true;
|
| 253 |
+
});
|
| 254 |
+
if (tempChunkLen > 0) {
|
| 255 |
+
const text = tempChunk.replace(/\r\n|\r|\n/g, eol);
|
| 256 |
+
chunks.push(new StringBuffer(text, createLineStartsFast(text)));
|
| 257 |
+
}
|
| 258 |
+
this.create(chunks, eol, true);
|
| 259 |
+
}
|
| 260 |
+
// #region Buffer API
|
| 261 |
+
getEOL() {
|
| 262 |
+
return this._EOL;
|
| 263 |
+
}
|
| 264 |
+
setEOL(newEOL) {
|
| 265 |
+
this._EOL = newEOL;
|
| 266 |
+
this._EOLLength = this._EOL.length;
|
| 267 |
+
this.normalizeEOL(newEOL);
|
| 268 |
+
}
|
| 269 |
+
createSnapshot(BOM) {
|
| 270 |
+
return new PieceTreeSnapshot(this, BOM);
|
| 271 |
+
}
|
| 272 |
+
getOffsetAt(lineNumber, column) {
|
| 273 |
+
let leftLen = 0; // inorder
|
| 274 |
+
let x = this.root;
|
| 275 |
+
while (x !== SENTINEL) {
|
| 276 |
+
if (x.left !== SENTINEL && x.lf_left + 1 >= lineNumber) {
|
| 277 |
+
x = x.left;
|
| 278 |
+
}
|
| 279 |
+
else if (x.lf_left + x.piece.lineFeedCnt + 1 >= lineNumber) {
|
| 280 |
+
leftLen += x.size_left;
|
| 281 |
+
// lineNumber >= 2
|
| 282 |
+
const accumualtedValInCurrentIndex = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
|
| 283 |
+
return leftLen += accumualtedValInCurrentIndex + column - 1;
|
| 284 |
+
}
|
| 285 |
+
else {
|
| 286 |
+
lineNumber -= x.lf_left + x.piece.lineFeedCnt;
|
| 287 |
+
leftLen += x.size_left + x.piece.length;
|
| 288 |
+
x = x.right;
|
| 289 |
+
}
|
| 290 |
+
}
|
| 291 |
+
return leftLen;
|
| 292 |
+
}
|
| 293 |
+
getPositionAt(offset) {
|
| 294 |
+
offset = Math.floor(offset);
|
| 295 |
+
offset = Math.max(0, offset);
|
| 296 |
+
let x = this.root;
|
| 297 |
+
let lfCnt = 0;
|
| 298 |
+
const originalOffset = offset;
|
| 299 |
+
while (x !== SENTINEL) {
|
| 300 |
+
if (x.size_left !== 0 && x.size_left >= offset) {
|
| 301 |
+
x = x.left;
|
| 302 |
+
}
|
| 303 |
+
else if (x.size_left + x.piece.length >= offset) {
|
| 304 |
+
const out = this.getIndexOf(x, offset - x.size_left);
|
| 305 |
+
lfCnt += x.lf_left + out.index;
|
| 306 |
+
if (out.index === 0) {
|
| 307 |
+
const lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);
|
| 308 |
+
const column = originalOffset - lineStartOffset;
|
| 309 |
+
return new Position(lfCnt + 1, column + 1);
|
| 310 |
+
}
|
| 311 |
+
return new Position(lfCnt + 1, out.remainder + 1);
|
| 312 |
+
}
|
| 313 |
+
else {
|
| 314 |
+
offset -= x.size_left + x.piece.length;
|
| 315 |
+
lfCnt += x.lf_left + x.piece.lineFeedCnt;
|
| 316 |
+
if (x.right === SENTINEL) {
|
| 317 |
+
// last node
|
| 318 |
+
const lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);
|
| 319 |
+
const column = originalOffset - offset - lineStartOffset;
|
| 320 |
+
return new Position(lfCnt + 1, column + 1);
|
| 321 |
+
}
|
| 322 |
+
else {
|
| 323 |
+
x = x.right;
|
| 324 |
+
}
|
| 325 |
+
}
|
| 326 |
+
}
|
| 327 |
+
return new Position(1, 1);
|
| 328 |
+
}
|
| 329 |
+
getValueInRange(range, eol) {
|
| 330 |
+
if (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {
|
| 331 |
+
return '';
|
| 332 |
+
}
|
| 333 |
+
const startPosition = this.nodeAt2(range.startLineNumber, range.startColumn);
|
| 334 |
+
const endPosition = this.nodeAt2(range.endLineNumber, range.endColumn);
|
| 335 |
+
const value = this.getValueInRange2(startPosition, endPosition);
|
| 336 |
+
if (eol) {
|
| 337 |
+
if (eol !== this._EOL || !this._EOLNormalized) {
|
| 338 |
+
return value.replace(/\r\n|\r|\n/g, eol);
|
| 339 |
+
}
|
| 340 |
+
if (eol === this.getEOL() && this._EOLNormalized) {
|
| 341 |
+
if (eol === '\r\n') {
|
| 342 |
+
}
|
| 343 |
+
return value;
|
| 344 |
+
}
|
| 345 |
+
return value.replace(/\r\n|\r|\n/g, eol);
|
| 346 |
+
}
|
| 347 |
+
return value;
|
| 348 |
+
}
|
| 349 |
+
getValueInRange2(startPosition, endPosition) {
|
| 350 |
+
if (startPosition.node === endPosition.node) {
|
| 351 |
+
const node = startPosition.node;
|
| 352 |
+
const buffer = this._buffers[node.piece.bufferIndex].buffer;
|
| 353 |
+
const startOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);
|
| 354 |
+
return buffer.substring(startOffset + startPosition.remainder, startOffset + endPosition.remainder);
|
| 355 |
+
}
|
| 356 |
+
let x = startPosition.node;
|
| 357 |
+
const buffer = this._buffers[x.piece.bufferIndex].buffer;
|
| 358 |
+
const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
| 359 |
+
let ret = buffer.substring(startOffset + startPosition.remainder, startOffset + x.piece.length);
|
| 360 |
+
x = x.next();
|
| 361 |
+
while (x !== SENTINEL) {
|
| 362 |
+
const buffer = this._buffers[x.piece.bufferIndex].buffer;
|
| 363 |
+
const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
| 364 |
+
if (x === endPosition.node) {
|
| 365 |
+
ret += buffer.substring(startOffset, startOffset + endPosition.remainder);
|
| 366 |
+
break;
|
| 367 |
+
}
|
| 368 |
+
else {
|
| 369 |
+
ret += buffer.substr(startOffset, x.piece.length);
|
| 370 |
+
}
|
| 371 |
+
x = x.next();
|
| 372 |
+
}
|
| 373 |
+
return ret;
|
| 374 |
+
}
|
| 375 |
+
getLinesContent() {
|
| 376 |
+
const lines = [];
|
| 377 |
+
let linesLength = 0;
|
| 378 |
+
let currentLine = '';
|
| 379 |
+
let danglingCR = false;
|
| 380 |
+
this.iterate(this.root, node => {
|
| 381 |
+
if (node === SENTINEL) {
|
| 382 |
+
return true;
|
| 383 |
+
}
|
| 384 |
+
const piece = node.piece;
|
| 385 |
+
let pieceLength = piece.length;
|
| 386 |
+
if (pieceLength === 0) {
|
| 387 |
+
return true;
|
| 388 |
+
}
|
| 389 |
+
const buffer = this._buffers[piece.bufferIndex].buffer;
|
| 390 |
+
const lineStarts = this._buffers[piece.bufferIndex].lineStarts;
|
| 391 |
+
const pieceStartLine = piece.start.line;
|
| 392 |
+
const pieceEndLine = piece.end.line;
|
| 393 |
+
let pieceStartOffset = lineStarts[pieceStartLine] + piece.start.column;
|
| 394 |
+
if (danglingCR) {
|
| 395 |
+
if (buffer.charCodeAt(pieceStartOffset) === 10 /* CharCode.LineFeed */) {
|
| 396 |
+
// pretend the \n was in the previous piece..
|
| 397 |
+
pieceStartOffset++;
|
| 398 |
+
pieceLength--;
|
| 399 |
+
}
|
| 400 |
+
lines[linesLength++] = currentLine;
|
| 401 |
+
currentLine = '';
|
| 402 |
+
danglingCR = false;
|
| 403 |
+
if (pieceLength === 0) {
|
| 404 |
+
return true;
|
| 405 |
+
}
|
| 406 |
+
}
|
| 407 |
+
if (pieceStartLine === pieceEndLine) {
|
| 408 |
+
// this piece has no new lines
|
| 409 |
+
if (!this._EOLNormalized && buffer.charCodeAt(pieceStartOffset + pieceLength - 1) === 13 /* CharCode.CarriageReturn */) {
|
| 410 |
+
danglingCR = true;
|
| 411 |
+
currentLine += buffer.substr(pieceStartOffset, pieceLength - 1);
|
| 412 |
+
}
|
| 413 |
+
else {
|
| 414 |
+
currentLine += buffer.substr(pieceStartOffset, pieceLength);
|
| 415 |
+
}
|
| 416 |
+
return true;
|
| 417 |
+
}
|
| 418 |
+
// add the text before the first line start in this piece
|
| 419 |
+
currentLine += (this._EOLNormalized
|
| 420 |
+
? buffer.substring(pieceStartOffset, Math.max(pieceStartOffset, lineStarts[pieceStartLine + 1] - this._EOLLength))
|
| 421 |
+
: buffer.substring(pieceStartOffset, lineStarts[pieceStartLine + 1]).replace(/(\r\n|\r|\n)$/, ''));
|
| 422 |
+
lines[linesLength++] = currentLine;
|
| 423 |
+
for (let line = pieceStartLine + 1; line < pieceEndLine; line++) {
|
| 424 |
+
currentLine = (this._EOLNormalized
|
| 425 |
+
? buffer.substring(lineStarts[line], lineStarts[line + 1] - this._EOLLength)
|
| 426 |
+
: buffer.substring(lineStarts[line], lineStarts[line + 1]).replace(/(\r\n|\r|\n)$/, ''));
|
| 427 |
+
lines[linesLength++] = currentLine;
|
| 428 |
+
}
|
| 429 |
+
if (!this._EOLNormalized && buffer.charCodeAt(lineStarts[pieceEndLine] + piece.end.column - 1) === 13 /* CharCode.CarriageReturn */) {
|
| 430 |
+
danglingCR = true;
|
| 431 |
+
if (piece.end.column === 0) {
|
| 432 |
+
// The last line ended with a \r, let's undo the push, it will be pushed by next iteration
|
| 433 |
+
linesLength--;
|
| 434 |
+
}
|
| 435 |
+
else {
|
| 436 |
+
currentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column - 1);
|
| 437 |
+
}
|
| 438 |
+
}
|
| 439 |
+
else {
|
| 440 |
+
currentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column);
|
| 441 |
+
}
|
| 442 |
+
return true;
|
| 443 |
+
});
|
| 444 |
+
if (danglingCR) {
|
| 445 |
+
lines[linesLength++] = currentLine;
|
| 446 |
+
currentLine = '';
|
| 447 |
+
}
|
| 448 |
+
lines[linesLength++] = currentLine;
|
| 449 |
+
return lines;
|
| 450 |
+
}
|
| 451 |
+
getLength() {
|
| 452 |
+
return this._length;
|
| 453 |
+
}
|
| 454 |
+
getLineCount() {
|
| 455 |
+
return this._lineCnt;
|
| 456 |
+
}
|
| 457 |
+
getLineContent(lineNumber) {
|
| 458 |
+
if (this._lastVisitedLine.lineNumber === lineNumber) {
|
| 459 |
+
return this._lastVisitedLine.value;
|
| 460 |
+
}
|
| 461 |
+
this._lastVisitedLine.lineNumber = lineNumber;
|
| 462 |
+
if (lineNumber === this._lineCnt) {
|
| 463 |
+
this._lastVisitedLine.value = this.getLineRawContent(lineNumber);
|
| 464 |
+
}
|
| 465 |
+
else if (this._EOLNormalized) {
|
| 466 |
+
this._lastVisitedLine.value = this.getLineRawContent(lineNumber, this._EOLLength);
|
| 467 |
+
}
|
| 468 |
+
else {
|
| 469 |
+
this._lastVisitedLine.value = this.getLineRawContent(lineNumber).replace(/(\r\n|\r|\n)$/, '');
|
| 470 |
+
}
|
| 471 |
+
return this._lastVisitedLine.value;
|
| 472 |
+
}
|
| 473 |
+
_getCharCode(nodePos) {
|
| 474 |
+
if (nodePos.remainder === nodePos.node.piece.length) {
|
| 475 |
+
// the char we want to fetch is at the head of next node.
|
| 476 |
+
const matchingNode = nodePos.node.next();
|
| 477 |
+
if (!matchingNode) {
|
| 478 |
+
return 0;
|
| 479 |
+
}
|
| 480 |
+
const buffer = this._buffers[matchingNode.piece.bufferIndex];
|
| 481 |
+
const startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);
|
| 482 |
+
return buffer.buffer.charCodeAt(startOffset);
|
| 483 |
+
}
|
| 484 |
+
else {
|
| 485 |
+
const buffer = this._buffers[nodePos.node.piece.bufferIndex];
|
| 486 |
+
const startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);
|
| 487 |
+
const targetOffset = startOffset + nodePos.remainder;
|
| 488 |
+
return buffer.buffer.charCodeAt(targetOffset);
|
| 489 |
+
}
|
| 490 |
+
}
|
| 491 |
+
getLineCharCode(lineNumber, index) {
|
| 492 |
+
const nodePos = this.nodeAt2(lineNumber, index + 1);
|
| 493 |
+
return this._getCharCode(nodePos);
|
| 494 |
+
}
|
| 495 |
+
getLineLength(lineNumber) {
|
| 496 |
+
if (lineNumber === this.getLineCount()) {
|
| 497 |
+
const startOffset = this.getOffsetAt(lineNumber, 1);
|
| 498 |
+
return this.getLength() - startOffset;
|
| 499 |
+
}
|
| 500 |
+
return this.getOffsetAt(lineNumber + 1, 1) - this.getOffsetAt(lineNumber, 1) - this._EOLLength;
|
| 501 |
+
}
|
| 502 |
+
findMatchesInNode(node, searcher, startLineNumber, startColumn, startCursor, endCursor, searchData, captureMatches, limitResultCount, resultLen, result) {
|
| 503 |
+
const buffer = this._buffers[node.piece.bufferIndex];
|
| 504 |
+
const startOffsetInBuffer = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);
|
| 505 |
+
const start = this.offsetInBuffer(node.piece.bufferIndex, startCursor);
|
| 506 |
+
const end = this.offsetInBuffer(node.piece.bufferIndex, endCursor);
|
| 507 |
+
let m;
|
| 508 |
+
// Reset regex to search from the beginning
|
| 509 |
+
const ret = { line: 0, column: 0 };
|
| 510 |
+
let searchText;
|
| 511 |
+
let offsetInBuffer;
|
| 512 |
+
if (searcher._wordSeparators) {
|
| 513 |
+
searchText = buffer.buffer.substring(start, end);
|
| 514 |
+
offsetInBuffer = (offset) => offset + start;
|
| 515 |
+
searcher.reset(0);
|
| 516 |
+
}
|
| 517 |
+
else {
|
| 518 |
+
searchText = buffer.buffer;
|
| 519 |
+
offsetInBuffer = (offset) => offset;
|
| 520 |
+
searcher.reset(start);
|
| 521 |
+
}
|
| 522 |
+
do {
|
| 523 |
+
m = searcher.next(searchText);
|
| 524 |
+
if (m) {
|
| 525 |
+
if (offsetInBuffer(m.index) >= end) {
|
| 526 |
+
return resultLen;
|
| 527 |
+
}
|
| 528 |
+
this.positionInBuffer(node, offsetInBuffer(m.index) - startOffsetInBuffer, ret);
|
| 529 |
+
const lineFeedCnt = this.getLineFeedCnt(node.piece.bufferIndex, startCursor, ret);
|
| 530 |
+
const retStartColumn = ret.line === startCursor.line ? ret.column - startCursor.column + startColumn : ret.column + 1;
|
| 531 |
+
const retEndColumn = retStartColumn + m[0].length;
|
| 532 |
+
result[resultLen++] = createFindMatch(new Range(startLineNumber + lineFeedCnt, retStartColumn, startLineNumber + lineFeedCnt, retEndColumn), m, captureMatches);
|
| 533 |
+
if (offsetInBuffer(m.index) + m[0].length >= end) {
|
| 534 |
+
return resultLen;
|
| 535 |
+
}
|
| 536 |
+
if (resultLen >= limitResultCount) {
|
| 537 |
+
return resultLen;
|
| 538 |
+
}
|
| 539 |
+
}
|
| 540 |
+
} while (m);
|
| 541 |
+
return resultLen;
|
| 542 |
+
}
|
| 543 |
+
findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount) {
|
| 544 |
+
const result = [];
|
| 545 |
+
let resultLen = 0;
|
| 546 |
+
const searcher = new Searcher(searchData.wordSeparators, searchData.regex);
|
| 547 |
+
let startPosition = this.nodeAt2(searchRange.startLineNumber, searchRange.startColumn);
|
| 548 |
+
if (startPosition === null) {
|
| 549 |
+
return [];
|
| 550 |
+
}
|
| 551 |
+
const endPosition = this.nodeAt2(searchRange.endLineNumber, searchRange.endColumn);
|
| 552 |
+
if (endPosition === null) {
|
| 553 |
+
return [];
|
| 554 |
+
}
|
| 555 |
+
let start = this.positionInBuffer(startPosition.node, startPosition.remainder);
|
| 556 |
+
const end = this.positionInBuffer(endPosition.node, endPosition.remainder);
|
| 557 |
+
if (startPosition.node === endPosition.node) {
|
| 558 |
+
this.findMatchesInNode(startPosition.node, searcher, searchRange.startLineNumber, searchRange.startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);
|
| 559 |
+
return result;
|
| 560 |
+
}
|
| 561 |
+
let startLineNumber = searchRange.startLineNumber;
|
| 562 |
+
let currentNode = startPosition.node;
|
| 563 |
+
while (currentNode !== endPosition.node) {
|
| 564 |
+
const lineBreakCnt = this.getLineFeedCnt(currentNode.piece.bufferIndex, start, currentNode.piece.end);
|
| 565 |
+
if (lineBreakCnt >= 1) {
|
| 566 |
+
// last line break position
|
| 567 |
+
const lineStarts = this._buffers[currentNode.piece.bufferIndex].lineStarts;
|
| 568 |
+
const startOffsetInBuffer = this.offsetInBuffer(currentNode.piece.bufferIndex, currentNode.piece.start);
|
| 569 |
+
const nextLineStartOffset = lineStarts[start.line + lineBreakCnt];
|
| 570 |
+
const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;
|
| 571 |
+
resultLen = this.findMatchesInNode(currentNode, searcher, startLineNumber, startColumn, start, this.positionInBuffer(currentNode, nextLineStartOffset - startOffsetInBuffer), searchData, captureMatches, limitResultCount, resultLen, result);
|
| 572 |
+
if (resultLen >= limitResultCount) {
|
| 573 |
+
return result;
|
| 574 |
+
}
|
| 575 |
+
startLineNumber += lineBreakCnt;
|
| 576 |
+
}
|
| 577 |
+
const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;
|
| 578 |
+
// search for the remaining content
|
| 579 |
+
if (startLineNumber === searchRange.endLineNumber) {
|
| 580 |
+
const text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);
|
| 581 |
+
resultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);
|
| 582 |
+
return result;
|
| 583 |
+
}
|
| 584 |
+
resultLen = this._findMatchesInLine(searchData, searcher, this.getLineContent(startLineNumber).substr(startColumn), startLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);
|
| 585 |
+
if (resultLen >= limitResultCount) {
|
| 586 |
+
return result;
|
| 587 |
+
}
|
| 588 |
+
startLineNumber++;
|
| 589 |
+
startPosition = this.nodeAt2(startLineNumber, 1);
|
| 590 |
+
currentNode = startPosition.node;
|
| 591 |
+
start = this.positionInBuffer(startPosition.node, startPosition.remainder);
|
| 592 |
+
}
|
| 593 |
+
if (startLineNumber === searchRange.endLineNumber) {
|
| 594 |
+
const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;
|
| 595 |
+
const text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);
|
| 596 |
+
resultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);
|
| 597 |
+
return result;
|
| 598 |
+
}
|
| 599 |
+
const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;
|
| 600 |
+
resultLen = this.findMatchesInNode(endPosition.node, searcher, startLineNumber, startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);
|
| 601 |
+
return result;
|
| 602 |
+
}
|
| 603 |
+
_findMatchesInLine(searchData, searcher, text, lineNumber, deltaOffset, resultLen, result, captureMatches, limitResultCount) {
|
| 604 |
+
const wordSeparators = searchData.wordSeparators;
|
| 605 |
+
if (!captureMatches && searchData.simpleSearch) {
|
| 606 |
+
const searchString = searchData.simpleSearch;
|
| 607 |
+
const searchStringLen = searchString.length;
|
| 608 |
+
const textLength = text.length;
|
| 609 |
+
let lastMatchIndex = -searchStringLen;
|
| 610 |
+
while ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {
|
| 611 |
+
if (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {
|
| 612 |
+
result[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);
|
| 613 |
+
if (resultLen >= limitResultCount) {
|
| 614 |
+
return resultLen;
|
| 615 |
+
}
|
| 616 |
+
}
|
| 617 |
+
}
|
| 618 |
+
return resultLen;
|
| 619 |
+
}
|
| 620 |
+
let m;
|
| 621 |
+
// Reset regex to search from the beginning
|
| 622 |
+
searcher.reset(0);
|
| 623 |
+
do {
|
| 624 |
+
m = searcher.next(text);
|
| 625 |
+
if (m) {
|
| 626 |
+
result[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);
|
| 627 |
+
if (resultLen >= limitResultCount) {
|
| 628 |
+
return resultLen;
|
| 629 |
+
}
|
| 630 |
+
}
|
| 631 |
+
} while (m);
|
| 632 |
+
return resultLen;
|
| 633 |
+
}
|
| 634 |
+
// #endregion
|
| 635 |
+
// #region Piece Table
|
| 636 |
+
insert(offset, value, eolNormalized = false) {
|
| 637 |
+
this._EOLNormalized = this._EOLNormalized && eolNormalized;
|
| 638 |
+
this._lastVisitedLine.lineNumber = 0;
|
| 639 |
+
this._lastVisitedLine.value = '';
|
| 640 |
+
if (this.root !== SENTINEL) {
|
| 641 |
+
const { node, remainder, nodeStartOffset } = this.nodeAt(offset);
|
| 642 |
+
const piece = node.piece;
|
| 643 |
+
const bufferIndex = piece.bufferIndex;
|
| 644 |
+
const insertPosInBuffer = this.positionInBuffer(node, remainder);
|
| 645 |
+
if (node.piece.bufferIndex === 0 &&
|
| 646 |
+
piece.end.line === this._lastChangeBufferPos.line &&
|
| 647 |
+
piece.end.column === this._lastChangeBufferPos.column &&
|
| 648 |
+
(nodeStartOffset + piece.length === offset) &&
|
| 649 |
+
value.length < AverageBufferSize) {
|
| 650 |
+
// changed buffer
|
| 651 |
+
this.appendToNode(node, value);
|
| 652 |
+
this.computeBufferMetadata();
|
| 653 |
+
return;
|
| 654 |
+
}
|
| 655 |
+
if (nodeStartOffset === offset) {
|
| 656 |
+
this.insertContentToNodeLeft(value, node);
|
| 657 |
+
this._searchCache.validate(offset);
|
| 658 |
+
}
|
| 659 |
+
else if (nodeStartOffset + node.piece.length > offset) {
|
| 660 |
+
// we are inserting into the middle of a node.
|
| 661 |
+
const nodesToDel = [];
|
| 662 |
+
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));
|
| 663 |
+
if (this.shouldCheckCRLF() && this.endWithCR(value)) {
|
| 664 |
+
const headOfRight = this.nodeCharCodeAt(node, remainder);
|
| 665 |
+
if (headOfRight === 10 /** \n */) {
|
| 666 |
+
const newStart = { line: newRightPiece.start.line + 1, column: 0 };
|
| 667 |
+
newRightPiece = new Piece(newRightPiece.bufferIndex, newStart, newRightPiece.end, this.getLineFeedCnt(newRightPiece.bufferIndex, newStart, newRightPiece.end), newRightPiece.length - 1);
|
| 668 |
+
value += '\n';
|
| 669 |
+
}
|
| 670 |
+
}
|
| 671 |
+
// reuse node for content before insertion point.
|
| 672 |
+
if (this.shouldCheckCRLF() && this.startWithLF(value)) {
|
| 673 |
+
const tailOfLeft = this.nodeCharCodeAt(node, remainder - 1);
|
| 674 |
+
if (tailOfLeft === 13 /** \r */) {
|
| 675 |
+
const previousPos = this.positionInBuffer(node, remainder - 1);
|
| 676 |
+
this.deleteNodeTail(node, previousPos);
|
| 677 |
+
value = '\r' + value;
|
| 678 |
+
if (node.piece.length === 0) {
|
| 679 |
+
nodesToDel.push(node);
|
| 680 |
+
}
|
| 681 |
+
}
|
| 682 |
+
else {
|
| 683 |
+
this.deleteNodeTail(node, insertPosInBuffer);
|
| 684 |
+
}
|
| 685 |
+
}
|
| 686 |
+
else {
|
| 687 |
+
this.deleteNodeTail(node, insertPosInBuffer);
|
| 688 |
+
}
|
| 689 |
+
const newPieces = this.createNewPieces(value);
|
| 690 |
+
if (newRightPiece.length > 0) {
|
| 691 |
+
this.rbInsertRight(node, newRightPiece);
|
| 692 |
+
}
|
| 693 |
+
let tmpNode = node;
|
| 694 |
+
for (let k = 0; k < newPieces.length; k++) {
|
| 695 |
+
tmpNode = this.rbInsertRight(tmpNode, newPieces[k]);
|
| 696 |
+
}
|
| 697 |
+
this.deleteNodes(nodesToDel);
|
| 698 |
+
}
|
| 699 |
+
else {
|
| 700 |
+
this.insertContentToNodeRight(value, node);
|
| 701 |
+
}
|
| 702 |
+
}
|
| 703 |
+
else {
|
| 704 |
+
// insert new node
|
| 705 |
+
const pieces = this.createNewPieces(value);
|
| 706 |
+
let node = this.rbInsertLeft(null, pieces[0]);
|
| 707 |
+
for (let k = 1; k < pieces.length; k++) {
|
| 708 |
+
node = this.rbInsertRight(node, pieces[k]);
|
| 709 |
+
}
|
| 710 |
+
}
|
| 711 |
+
// todo, this is too brutal. Total line feed count should be updated the same way as lf_left.
|
| 712 |
+
this.computeBufferMetadata();
|
| 713 |
+
}
|
| 714 |
+
delete(offset, cnt) {
|
| 715 |
+
this._lastVisitedLine.lineNumber = 0;
|
| 716 |
+
this._lastVisitedLine.value = '';
|
| 717 |
+
if (cnt <= 0 || this.root === SENTINEL) {
|
| 718 |
+
return;
|
| 719 |
+
}
|
| 720 |
+
const startPosition = this.nodeAt(offset);
|
| 721 |
+
const endPosition = this.nodeAt(offset + cnt);
|
| 722 |
+
const startNode = startPosition.node;
|
| 723 |
+
const endNode = endPosition.node;
|
| 724 |
+
if (startNode === endNode) {
|
| 725 |
+
const startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);
|
| 726 |
+
const endSplitPosInBuffer = this.positionInBuffer(startNode, endPosition.remainder);
|
| 727 |
+
if (startPosition.nodeStartOffset === offset) {
|
| 728 |
+
if (cnt === startNode.piece.length) { // delete node
|
| 729 |
+
const next = startNode.next();
|
| 730 |
+
rbDelete(this, startNode);
|
| 731 |
+
this.validateCRLFWithPrevNode(next);
|
| 732 |
+
this.computeBufferMetadata();
|
| 733 |
+
return;
|
| 734 |
+
}
|
| 735 |
+
this.deleteNodeHead(startNode, endSplitPosInBuffer);
|
| 736 |
+
this._searchCache.validate(offset);
|
| 737 |
+
this.validateCRLFWithPrevNode(startNode);
|
| 738 |
+
this.computeBufferMetadata();
|
| 739 |
+
return;
|
| 740 |
+
}
|
| 741 |
+
if (startPosition.nodeStartOffset + startNode.piece.length === offset + cnt) {
|
| 742 |
+
this.deleteNodeTail(startNode, startSplitPosInBuffer);
|
| 743 |
+
this.validateCRLFWithNextNode(startNode);
|
| 744 |
+
this.computeBufferMetadata();
|
| 745 |
+
return;
|
| 746 |
+
}
|
| 747 |
+
// delete content in the middle, this node will be splitted to nodes
|
| 748 |
+
this.shrinkNode(startNode, startSplitPosInBuffer, endSplitPosInBuffer);
|
| 749 |
+
this.computeBufferMetadata();
|
| 750 |
+
return;
|
| 751 |
+
}
|
| 752 |
+
const nodesToDel = [];
|
| 753 |
+
const startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);
|
| 754 |
+
this.deleteNodeTail(startNode, startSplitPosInBuffer);
|
| 755 |
+
this._searchCache.validate(offset);
|
| 756 |
+
if (startNode.piece.length === 0) {
|
| 757 |
+
nodesToDel.push(startNode);
|
| 758 |
+
}
|
| 759 |
+
// update last touched node
|
| 760 |
+
const endSplitPosInBuffer = this.positionInBuffer(endNode, endPosition.remainder);
|
| 761 |
+
this.deleteNodeHead(endNode, endSplitPosInBuffer);
|
| 762 |
+
if (endNode.piece.length === 0) {
|
| 763 |
+
nodesToDel.push(endNode);
|
| 764 |
+
}
|
| 765 |
+
// delete nodes in between
|
| 766 |
+
const secondNode = startNode.next();
|
| 767 |
+
for (let node = secondNode; node !== SENTINEL && node !== endNode; node = node.next()) {
|
| 768 |
+
nodesToDel.push(node);
|
| 769 |
+
}
|
| 770 |
+
const prev = startNode.piece.length === 0 ? startNode.prev() : startNode;
|
| 771 |
+
this.deleteNodes(nodesToDel);
|
| 772 |
+
this.validateCRLFWithNextNode(prev);
|
| 773 |
+
this.computeBufferMetadata();
|
| 774 |
+
}
|
| 775 |
+
insertContentToNodeLeft(value, node) {
|
| 776 |
+
// we are inserting content to the beginning of node
|
| 777 |
+
const nodesToDel = [];
|
| 778 |
+
if (this.shouldCheckCRLF() && this.endWithCR(value) && this.startWithLF(node)) {
|
| 779 |
+
// move `\n` to new node.
|
| 780 |
+
const piece = node.piece;
|
| 781 |
+
const newStart = { line: piece.start.line + 1, column: 0 };
|
| 782 |
+
const nPiece = new Piece(piece.bufferIndex, newStart, piece.end, this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end), piece.length - 1);
|
| 783 |
+
node.piece = nPiece;
|
| 784 |
+
value += '\n';
|
| 785 |
+
updateTreeMetadata(this, node, -1, -1);
|
| 786 |
+
if (node.piece.length === 0) {
|
| 787 |
+
nodesToDel.push(node);
|
| 788 |
+
}
|
| 789 |
+
}
|
| 790 |
+
const newPieces = this.createNewPieces(value);
|
| 791 |
+
let newNode = this.rbInsertLeft(node, newPieces[newPieces.length - 1]);
|
| 792 |
+
for (let k = newPieces.length - 2; k >= 0; k--) {
|
| 793 |
+
newNode = this.rbInsertLeft(newNode, newPieces[k]);
|
| 794 |
+
}
|
| 795 |
+
this.validateCRLFWithPrevNode(newNode);
|
| 796 |
+
this.deleteNodes(nodesToDel);
|
| 797 |
+
}
|
| 798 |
+
insertContentToNodeRight(value, node) {
|
| 799 |
+
// we are inserting to the right of this node.
|
| 800 |
+
if (this.adjustCarriageReturnFromNext(value, node)) {
|
| 801 |
+
// move \n to the new node.
|
| 802 |
+
value += '\n';
|
| 803 |
+
}
|
| 804 |
+
const newPieces = this.createNewPieces(value);
|
| 805 |
+
const newNode = this.rbInsertRight(node, newPieces[0]);
|
| 806 |
+
let tmpNode = newNode;
|
| 807 |
+
for (let k = 1; k < newPieces.length; k++) {
|
| 808 |
+
tmpNode = this.rbInsertRight(tmpNode, newPieces[k]);
|
| 809 |
+
}
|
| 810 |
+
this.validateCRLFWithPrevNode(newNode);
|
| 811 |
+
}
|
| 812 |
+
positionInBuffer(node, remainder, ret) {
|
| 813 |
+
const piece = node.piece;
|
| 814 |
+
const bufferIndex = node.piece.bufferIndex;
|
| 815 |
+
const lineStarts = this._buffers[bufferIndex].lineStarts;
|
| 816 |
+
const startOffset = lineStarts[piece.start.line] + piece.start.column;
|
| 817 |
+
const offset = startOffset + remainder;
|
| 818 |
+
// binary search offset between startOffset and endOffset
|
| 819 |
+
let low = piece.start.line;
|
| 820 |
+
let high = piece.end.line;
|
| 821 |
+
let mid = 0;
|
| 822 |
+
let midStop = 0;
|
| 823 |
+
let midStart = 0;
|
| 824 |
+
while (low <= high) {
|
| 825 |
+
mid = low + ((high - low) / 2) | 0;
|
| 826 |
+
midStart = lineStarts[mid];
|
| 827 |
+
if (mid === high) {
|
| 828 |
+
break;
|
| 829 |
+
}
|
| 830 |
+
midStop = lineStarts[mid + 1];
|
| 831 |
+
if (offset < midStart) {
|
| 832 |
+
high = mid - 1;
|
| 833 |
+
}
|
| 834 |
+
else if (offset >= midStop) {
|
| 835 |
+
low = mid + 1;
|
| 836 |
+
}
|
| 837 |
+
else {
|
| 838 |
+
break;
|
| 839 |
+
}
|
| 840 |
+
}
|
| 841 |
+
if (ret) {
|
| 842 |
+
ret.line = mid;
|
| 843 |
+
ret.column = offset - midStart;
|
| 844 |
+
return null;
|
| 845 |
+
}
|
| 846 |
+
return {
|
| 847 |
+
line: mid,
|
| 848 |
+
column: offset - midStart
|
| 849 |
+
};
|
| 850 |
+
}
|
| 851 |
+
getLineFeedCnt(bufferIndex, start, end) {
|
| 852 |
+
// 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.
|
| 853 |
+
// 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
|
| 854 |
+
if (end.column === 0) {
|
| 855 |
+
return end.line - start.line;
|
| 856 |
+
}
|
| 857 |
+
const lineStarts = this._buffers[bufferIndex].lineStarts;
|
| 858 |
+
if (end.line === lineStarts.length - 1) { // it means, there is no \n after end, otherwise, there will be one more lineStart.
|
| 859 |
+
return end.line - start.line;
|
| 860 |
+
}
|
| 861 |
+
const nextLineStartOffset = lineStarts[end.line + 1];
|
| 862 |
+
const endOffset = lineStarts[end.line] + end.column;
|
| 863 |
+
if (nextLineStartOffset > endOffset + 1) { // there are more than 1 character after end, which means it can't be \n
|
| 864 |
+
return end.line - start.line;
|
| 865 |
+
}
|
| 866 |
+
// endOffset + 1 === nextLineStartOffset
|
| 867 |
+
// character at endOffset is \n, so we check the character before first
|
| 868 |
+
// if character at endOffset is \r, end.column is 0 and we can't get here.
|
| 869 |
+
const previousCharOffset = endOffset - 1; // end.column > 0 so it's okay.
|
| 870 |
+
const buffer = this._buffers[bufferIndex].buffer;
|
| 871 |
+
if (buffer.charCodeAt(previousCharOffset) === 13) {
|
| 872 |
+
return end.line - start.line + 1;
|
| 873 |
+
}
|
| 874 |
+
else {
|
| 875 |
+
return end.line - start.line;
|
| 876 |
+
}
|
| 877 |
+
}
|
| 878 |
+
offsetInBuffer(bufferIndex, cursor) {
|
| 879 |
+
const lineStarts = this._buffers[bufferIndex].lineStarts;
|
| 880 |
+
return lineStarts[cursor.line] + cursor.column;
|
| 881 |
+
}
|
| 882 |
+
deleteNodes(nodes) {
|
| 883 |
+
for (let i = 0; i < nodes.length; i++) {
|
| 884 |
+
rbDelete(this, nodes[i]);
|
| 885 |
+
}
|
| 886 |
+
}
|
| 887 |
+
createNewPieces(text) {
|
| 888 |
+
if (text.length > AverageBufferSize) {
|
| 889 |
+
// the content is large, operations like substring, charCode becomes slow
|
| 890 |
+
// so here we split it into smaller chunks, just like what we did for CR/LF normalization
|
| 891 |
+
const newPieces = [];
|
| 892 |
+
while (text.length > AverageBufferSize) {
|
| 893 |
+
const lastChar = text.charCodeAt(AverageBufferSize - 1);
|
| 894 |
+
let splitText;
|
| 895 |
+
if (lastChar === 13 /* CharCode.CarriageReturn */ || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {
|
| 896 |
+
// last character is \r or a high surrogate => keep it back
|
| 897 |
+
splitText = text.substring(0, AverageBufferSize - 1);
|
| 898 |
+
text = text.substring(AverageBufferSize - 1);
|
| 899 |
+
}
|
| 900 |
+
else {
|
| 901 |
+
splitText = text.substring(0, AverageBufferSize);
|
| 902 |
+
text = text.substring(AverageBufferSize);
|
| 903 |
+
}
|
| 904 |
+
const lineStarts = createLineStartsFast(splitText);
|
| 905 |
+
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));
|
| 906 |
+
this._buffers.push(new StringBuffer(splitText, lineStarts));
|
| 907 |
+
}
|
| 908 |
+
const lineStarts = createLineStartsFast(text);
|
| 909 |
+
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));
|
| 910 |
+
this._buffers.push(new StringBuffer(text, lineStarts));
|
| 911 |
+
return newPieces;
|
| 912 |
+
}
|
| 913 |
+
let startOffset = this._buffers[0].buffer.length;
|
| 914 |
+
const lineStarts = createLineStartsFast(text, false);
|
| 915 |
+
let start = this._lastChangeBufferPos;
|
| 916 |
+
if (this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 1] === startOffset
|
| 917 |
+
&& startOffset !== 0
|
| 918 |
+
&& this.startWithLF(text)
|
| 919 |
+
&& this.endWithCR(this._buffers[0].buffer) // todo, we can check this._lastChangeBufferPos's column as it's the last one
|
| 920 |
+
) {
|
| 921 |
+
this._lastChangeBufferPos = { line: this._lastChangeBufferPos.line, column: this._lastChangeBufferPos.column + 1 };
|
| 922 |
+
start = this._lastChangeBufferPos;
|
| 923 |
+
for (let i = 0; i < lineStarts.length; i++) {
|
| 924 |
+
lineStarts[i] += startOffset + 1;
|
| 925 |
+
}
|
| 926 |
+
this._buffers[0].lineStarts = this._buffers[0].lineStarts.concat(lineStarts.slice(1));
|
| 927 |
+
this._buffers[0].buffer += '_' + text;
|
| 928 |
+
startOffset += 1;
|
| 929 |
+
}
|
| 930 |
+
else {
|
| 931 |
+
if (startOffset !== 0) {
|
| 932 |
+
for (let i = 0; i < lineStarts.length; i++) {
|
| 933 |
+
lineStarts[i] += startOffset;
|
| 934 |
+
}
|
| 935 |
+
}
|
| 936 |
+
this._buffers[0].lineStarts = this._buffers[0].lineStarts.concat(lineStarts.slice(1));
|
| 937 |
+
this._buffers[0].buffer += text;
|
| 938 |
+
}
|
| 939 |
+
const endOffset = this._buffers[0].buffer.length;
|
| 940 |
+
const endIndex = this._buffers[0].lineStarts.length - 1;
|
| 941 |
+
const endColumn = endOffset - this._buffers[0].lineStarts[endIndex];
|
| 942 |
+
const endPos = { line: endIndex, column: endColumn };
|
| 943 |
+
const newPiece = new Piece(0, /** todo@peng */ start, endPos, this.getLineFeedCnt(0, start, endPos), endOffset - startOffset);
|
| 944 |
+
this._lastChangeBufferPos = endPos;
|
| 945 |
+
return [newPiece];
|
| 946 |
+
}
|
| 947 |
+
getLineRawContent(lineNumber, endOffset = 0) {
|
| 948 |
+
let x = this.root;
|
| 949 |
+
let ret = '';
|
| 950 |
+
const cache = this._searchCache.get2(lineNumber);
|
| 951 |
+
if (cache) {
|
| 952 |
+
x = cache.node;
|
| 953 |
+
const prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber - 1);
|
| 954 |
+
const buffer = this._buffers[x.piece.bufferIndex].buffer;
|
| 955 |
+
const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
| 956 |
+
if (cache.nodeStartLineNumber + x.piece.lineFeedCnt === lineNumber) {
|
| 957 |
+
ret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);
|
| 958 |
+
}
|
| 959 |
+
else {
|
| 960 |
+
const accumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber);
|
| 961 |
+
return buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);
|
| 962 |
+
}
|
| 963 |
+
}
|
| 964 |
+
else {
|
| 965 |
+
let nodeStartOffset = 0;
|
| 966 |
+
const originalLineNumber = lineNumber;
|
| 967 |
+
while (x !== SENTINEL) {
|
| 968 |
+
if (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {
|
| 969 |
+
x = x.left;
|
| 970 |
+
}
|
| 971 |
+
else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {
|
| 972 |
+
const prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
|
| 973 |
+
const accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);
|
| 974 |
+
const buffer = this._buffers[x.piece.bufferIndex].buffer;
|
| 975 |
+
const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
| 976 |
+
nodeStartOffset += x.size_left;
|
| 977 |
+
this._searchCache.set({
|
| 978 |
+
node: x,
|
| 979 |
+
nodeStartOffset,
|
| 980 |
+
nodeStartLineNumber: originalLineNumber - (lineNumber - 1 - x.lf_left)
|
| 981 |
+
});
|
| 982 |
+
return buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);
|
| 983 |
+
}
|
| 984 |
+
else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {
|
| 985 |
+
const prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
|
| 986 |
+
const buffer = this._buffers[x.piece.bufferIndex].buffer;
|
| 987 |
+
const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
| 988 |
+
ret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);
|
| 989 |
+
break;
|
| 990 |
+
}
|
| 991 |
+
else {
|
| 992 |
+
lineNumber -= x.lf_left + x.piece.lineFeedCnt;
|
| 993 |
+
nodeStartOffset += x.size_left + x.piece.length;
|
| 994 |
+
x = x.right;
|
| 995 |
+
}
|
| 996 |
+
}
|
| 997 |
+
}
|
| 998 |
+
// search in order, to find the node contains end column
|
| 999 |
+
x = x.next();
|
| 1000 |
+
while (x !== SENTINEL) {
|
| 1001 |
+
const buffer = this._buffers[x.piece.bufferIndex].buffer;
|
| 1002 |
+
if (x.piece.lineFeedCnt > 0) {
|
| 1003 |
+
const accumulatedValue = this.getAccumulatedValue(x, 0);
|
| 1004 |
+
const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
| 1005 |
+
ret += buffer.substring(startOffset, startOffset + accumulatedValue - endOffset);
|
| 1006 |
+
return ret;
|
| 1007 |
+
}
|
| 1008 |
+
else {
|
| 1009 |
+
const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
| 1010 |
+
ret += buffer.substr(startOffset, x.piece.length);
|
| 1011 |
+
}
|
| 1012 |
+
x = x.next();
|
| 1013 |
+
}
|
| 1014 |
+
return ret;
|
| 1015 |
+
}
|
| 1016 |
+
computeBufferMetadata() {
|
| 1017 |
+
let x = this.root;
|
| 1018 |
+
let lfCnt = 1;
|
| 1019 |
+
let len = 0;
|
| 1020 |
+
while (x !== SENTINEL) {
|
| 1021 |
+
lfCnt += x.lf_left + x.piece.lineFeedCnt;
|
| 1022 |
+
len += x.size_left + x.piece.length;
|
| 1023 |
+
x = x.right;
|
| 1024 |
+
}
|
| 1025 |
+
this._lineCnt = lfCnt;
|
| 1026 |
+
this._length = len;
|
| 1027 |
+
this._searchCache.validate(this._length);
|
| 1028 |
+
}
|
| 1029 |
+
// #region node operations
|
| 1030 |
+
getIndexOf(node, accumulatedValue) {
|
| 1031 |
+
const piece = node.piece;
|
| 1032 |
+
const pos = this.positionInBuffer(node, accumulatedValue);
|
| 1033 |
+
const lineCnt = pos.line - piece.start.line;
|
| 1034 |
+
if (this.offsetInBuffer(piece.bufferIndex, piece.end) - this.offsetInBuffer(piece.bufferIndex, piece.start) === accumulatedValue) {
|
| 1035 |
+
// we are checking the end of this node, so a CRLF check is necessary.
|
| 1036 |
+
const realLineCnt = this.getLineFeedCnt(node.piece.bufferIndex, piece.start, pos);
|
| 1037 |
+
if (realLineCnt !== lineCnt) {
|
| 1038 |
+
// aha yes, CRLF
|
| 1039 |
+
return { index: realLineCnt, remainder: 0 };
|
| 1040 |
+
}
|
| 1041 |
+
}
|
| 1042 |
+
return { index: lineCnt, remainder: pos.column };
|
| 1043 |
+
}
|
| 1044 |
+
getAccumulatedValue(node, index) {
|
| 1045 |
+
if (index < 0) {
|
| 1046 |
+
return 0;
|
| 1047 |
+
}
|
| 1048 |
+
const piece = node.piece;
|
| 1049 |
+
const lineStarts = this._buffers[piece.bufferIndex].lineStarts;
|
| 1050 |
+
const expectedLineStartIndex = piece.start.line + index + 1;
|
| 1051 |
+
if (expectedLineStartIndex > piece.end.line) {
|
| 1052 |
+
return lineStarts[piece.end.line] + piece.end.column - lineStarts[piece.start.line] - piece.start.column;
|
| 1053 |
+
}
|
| 1054 |
+
else {
|
| 1055 |
+
return lineStarts[expectedLineStartIndex] - lineStarts[piece.start.line] - piece.start.column;
|
| 1056 |
+
}
|
| 1057 |
+
}
|
| 1058 |
+
deleteNodeTail(node, pos) {
|
| 1059 |
+
const piece = node.piece;
|
| 1060 |
+
const originalLFCnt = piece.lineFeedCnt;
|
| 1061 |
+
const originalEndOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);
|
| 1062 |
+
const newEnd = pos;
|
| 1063 |
+
const newEndOffset = this.offsetInBuffer(piece.bufferIndex, newEnd);
|
| 1064 |
+
const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);
|
| 1065 |
+
const lf_delta = newLineFeedCnt - originalLFCnt;
|
| 1066 |
+
const size_delta = newEndOffset - originalEndOffset;
|
| 1067 |
+
const newLength = piece.length + size_delta;
|
| 1068 |
+
node.piece = new Piece(piece.bufferIndex, piece.start, newEnd, newLineFeedCnt, newLength);
|
| 1069 |
+
updateTreeMetadata(this, node, size_delta, lf_delta);
|
| 1070 |
+
}
|
| 1071 |
+
deleteNodeHead(node, pos) {
|
| 1072 |
+
const piece = node.piece;
|
| 1073 |
+
const originalLFCnt = piece.lineFeedCnt;
|
| 1074 |
+
const originalStartOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);
|
| 1075 |
+
const newStart = pos;
|
| 1076 |
+
const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);
|
| 1077 |
+
const newStartOffset = this.offsetInBuffer(piece.bufferIndex, newStart);
|
| 1078 |
+
const lf_delta = newLineFeedCnt - originalLFCnt;
|
| 1079 |
+
const size_delta = originalStartOffset - newStartOffset;
|
| 1080 |
+
const newLength = piece.length + size_delta;
|
| 1081 |
+
node.piece = new Piece(piece.bufferIndex, newStart, piece.end, newLineFeedCnt, newLength);
|
| 1082 |
+
updateTreeMetadata(this, node, size_delta, lf_delta);
|
| 1083 |
+
}
|
| 1084 |
+
shrinkNode(node, start, end) {
|
| 1085 |
+
const piece = node.piece;
|
| 1086 |
+
const originalStartPos = piece.start;
|
| 1087 |
+
const originalEndPos = piece.end;
|
| 1088 |
+
// old piece, originalStartPos, start
|
| 1089 |
+
const oldLength = piece.length;
|
| 1090 |
+
const oldLFCnt = piece.lineFeedCnt;
|
| 1091 |
+
const newEnd = start;
|
| 1092 |
+
const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);
|
| 1093 |
+
const newLength = this.offsetInBuffer(piece.bufferIndex, start) - this.offsetInBuffer(piece.bufferIndex, originalStartPos);
|
| 1094 |
+
node.piece = new Piece(piece.bufferIndex, piece.start, newEnd, newLineFeedCnt, newLength);
|
| 1095 |
+
updateTreeMetadata(this, node, newLength - oldLength, newLineFeedCnt - oldLFCnt);
|
| 1096 |
+
// new right piece, end, originalEndPos
|
| 1097 |
+
const newPiece = new Piece(piece.bufferIndex, end, originalEndPos, this.getLineFeedCnt(piece.bufferIndex, end, originalEndPos), this.offsetInBuffer(piece.bufferIndex, originalEndPos) - this.offsetInBuffer(piece.bufferIndex, end));
|
| 1098 |
+
const newNode = this.rbInsertRight(node, newPiece);
|
| 1099 |
+
this.validateCRLFWithPrevNode(newNode);
|
| 1100 |
+
}
|
| 1101 |
+
appendToNode(node, value) {
|
| 1102 |
+
if (this.adjustCarriageReturnFromNext(value, node)) {
|
| 1103 |
+
value += '\n';
|
| 1104 |
+
}
|
| 1105 |
+
const hitCRLF = this.shouldCheckCRLF() && this.startWithLF(value) && this.endWithCR(node);
|
| 1106 |
+
const startOffset = this._buffers[0].buffer.length;
|
| 1107 |
+
this._buffers[0].buffer += value;
|
| 1108 |
+
const lineStarts = createLineStartsFast(value, false);
|
| 1109 |
+
for (let i = 0; i < lineStarts.length; i++) {
|
| 1110 |
+
lineStarts[i] += startOffset;
|
| 1111 |
+
}
|
| 1112 |
+
if (hitCRLF) {
|
| 1113 |
+
const prevStartOffset = this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 2];
|
| 1114 |
+
this._buffers[0].lineStarts.pop();
|
| 1115 |
+
// _lastChangeBufferPos is already wrong
|
| 1116 |
+
this._lastChangeBufferPos = { line: this._lastChangeBufferPos.line - 1, column: startOffset - prevStartOffset };
|
| 1117 |
+
}
|
| 1118 |
+
this._buffers[0].lineStarts = this._buffers[0].lineStarts.concat(lineStarts.slice(1));
|
| 1119 |
+
const endIndex = this._buffers[0].lineStarts.length - 1;
|
| 1120 |
+
const endColumn = this._buffers[0].buffer.length - this._buffers[0].lineStarts[endIndex];
|
| 1121 |
+
const newEnd = { line: endIndex, column: endColumn };
|
| 1122 |
+
const newLength = node.piece.length + value.length;
|
| 1123 |
+
const oldLineFeedCnt = node.piece.lineFeedCnt;
|
| 1124 |
+
const newLineFeedCnt = this.getLineFeedCnt(0, node.piece.start, newEnd);
|
| 1125 |
+
const lf_delta = newLineFeedCnt - oldLineFeedCnt;
|
| 1126 |
+
node.piece = new Piece(node.piece.bufferIndex, node.piece.start, newEnd, newLineFeedCnt, newLength);
|
| 1127 |
+
this._lastChangeBufferPos = newEnd;
|
| 1128 |
+
updateTreeMetadata(this, node, value.length, lf_delta);
|
| 1129 |
+
}
|
| 1130 |
+
nodeAt(offset) {
|
| 1131 |
+
let x = this.root;
|
| 1132 |
+
const cache = this._searchCache.get(offset);
|
| 1133 |
+
if (cache) {
|
| 1134 |
+
return {
|
| 1135 |
+
node: cache.node,
|
| 1136 |
+
nodeStartOffset: cache.nodeStartOffset,
|
| 1137 |
+
remainder: offset - cache.nodeStartOffset
|
| 1138 |
+
};
|
| 1139 |
+
}
|
| 1140 |
+
let nodeStartOffset = 0;
|
| 1141 |
+
while (x !== SENTINEL) {
|
| 1142 |
+
if (x.size_left > offset) {
|
| 1143 |
+
x = x.left;
|
| 1144 |
+
}
|
| 1145 |
+
else if (x.size_left + x.piece.length >= offset) {
|
| 1146 |
+
nodeStartOffset += x.size_left;
|
| 1147 |
+
const ret = {
|
| 1148 |
+
node: x,
|
| 1149 |
+
remainder: offset - x.size_left,
|
| 1150 |
+
nodeStartOffset
|
| 1151 |
+
};
|
| 1152 |
+
this._searchCache.set(ret);
|
| 1153 |
+
return ret;
|
| 1154 |
+
}
|
| 1155 |
+
else {
|
| 1156 |
+
offset -= x.size_left + x.piece.length;
|
| 1157 |
+
nodeStartOffset += x.size_left + x.piece.length;
|
| 1158 |
+
x = x.right;
|
| 1159 |
+
}
|
| 1160 |
+
}
|
| 1161 |
+
return null;
|
| 1162 |
+
}
|
| 1163 |
+
nodeAt2(lineNumber, column) {
|
| 1164 |
+
let x = this.root;
|
| 1165 |
+
let nodeStartOffset = 0;
|
| 1166 |
+
while (x !== SENTINEL) {
|
| 1167 |
+
if (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {
|
| 1168 |
+
x = x.left;
|
| 1169 |
+
}
|
| 1170 |
+
else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {
|
| 1171 |
+
const prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
|
| 1172 |
+
const accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);
|
| 1173 |
+
nodeStartOffset += x.size_left;
|
| 1174 |
+
return {
|
| 1175 |
+
node: x,
|
| 1176 |
+
remainder: Math.min(prevAccumualtedValue + column - 1, accumulatedValue),
|
| 1177 |
+
nodeStartOffset
|
| 1178 |
+
};
|
| 1179 |
+
}
|
| 1180 |
+
else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {
|
| 1181 |
+
const prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
|
| 1182 |
+
if (prevAccumualtedValue + column - 1 <= x.piece.length) {
|
| 1183 |
+
return {
|
| 1184 |
+
node: x,
|
| 1185 |
+
remainder: prevAccumualtedValue + column - 1,
|
| 1186 |
+
nodeStartOffset
|
| 1187 |
+
};
|
| 1188 |
+
}
|
| 1189 |
+
else {
|
| 1190 |
+
column -= x.piece.length - prevAccumualtedValue;
|
| 1191 |
+
break;
|
| 1192 |
+
}
|
| 1193 |
+
}
|
| 1194 |
+
else {
|
| 1195 |
+
lineNumber -= x.lf_left + x.piece.lineFeedCnt;
|
| 1196 |
+
nodeStartOffset += x.size_left + x.piece.length;
|
| 1197 |
+
x = x.right;
|
| 1198 |
+
}
|
| 1199 |
+
}
|
| 1200 |
+
// search in order, to find the node contains position.column
|
| 1201 |
+
x = x.next();
|
| 1202 |
+
while (x !== SENTINEL) {
|
| 1203 |
+
if (x.piece.lineFeedCnt > 0) {
|
| 1204 |
+
const accumulatedValue = this.getAccumulatedValue(x, 0);
|
| 1205 |
+
const nodeStartOffset = this.offsetOfNode(x);
|
| 1206 |
+
return {
|
| 1207 |
+
node: x,
|
| 1208 |
+
remainder: Math.min(column - 1, accumulatedValue),
|
| 1209 |
+
nodeStartOffset
|
| 1210 |
+
};
|
| 1211 |
+
}
|
| 1212 |
+
else {
|
| 1213 |
+
if (x.piece.length >= column - 1) {
|
| 1214 |
+
const nodeStartOffset = this.offsetOfNode(x);
|
| 1215 |
+
return {
|
| 1216 |
+
node: x,
|
| 1217 |
+
remainder: column - 1,
|
| 1218 |
+
nodeStartOffset
|
| 1219 |
+
};
|
| 1220 |
+
}
|
| 1221 |
+
else {
|
| 1222 |
+
column -= x.piece.length;
|
| 1223 |
+
}
|
| 1224 |
+
}
|
| 1225 |
+
x = x.next();
|
| 1226 |
+
}
|
| 1227 |
+
return null;
|
| 1228 |
+
}
|
| 1229 |
+
nodeCharCodeAt(node, offset) {
|
| 1230 |
+
if (node.piece.lineFeedCnt < 1) {
|
| 1231 |
+
return -1;
|
| 1232 |
+
}
|
| 1233 |
+
const buffer = this._buffers[node.piece.bufferIndex];
|
| 1234 |
+
const newOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start) + offset;
|
| 1235 |
+
return buffer.buffer.charCodeAt(newOffset);
|
| 1236 |
+
}
|
| 1237 |
+
offsetOfNode(node) {
|
| 1238 |
+
if (!node) {
|
| 1239 |
+
return 0;
|
| 1240 |
+
}
|
| 1241 |
+
let pos = node.size_left;
|
| 1242 |
+
while (node !== this.root) {
|
| 1243 |
+
if (node.parent.right === node) {
|
| 1244 |
+
pos += node.parent.size_left + node.parent.piece.length;
|
| 1245 |
+
}
|
| 1246 |
+
node = node.parent;
|
| 1247 |
+
}
|
| 1248 |
+
return pos;
|
| 1249 |
+
}
|
| 1250 |
+
// #endregion
|
| 1251 |
+
// #region CRLF
|
| 1252 |
+
shouldCheckCRLF() {
|
| 1253 |
+
return !(this._EOLNormalized && this._EOL === '\n');
|
| 1254 |
+
}
|
| 1255 |
+
startWithLF(val) {
|
| 1256 |
+
if (typeof val === 'string') {
|
| 1257 |
+
return val.charCodeAt(0) === 10;
|
| 1258 |
+
}
|
| 1259 |
+
if (val === SENTINEL || val.piece.lineFeedCnt === 0) {
|
| 1260 |
+
return false;
|
| 1261 |
+
}
|
| 1262 |
+
const piece = val.piece;
|
| 1263 |
+
const lineStarts = this._buffers[piece.bufferIndex].lineStarts;
|
| 1264 |
+
const line = piece.start.line;
|
| 1265 |
+
const startOffset = lineStarts[line] + piece.start.column;
|
| 1266 |
+
if (line === lineStarts.length - 1) {
|
| 1267 |
+
// last line, so there is no line feed at the end of this line
|
| 1268 |
+
return false;
|
| 1269 |
+
}
|
| 1270 |
+
const nextLineOffset = lineStarts[line + 1];
|
| 1271 |
+
if (nextLineOffset > startOffset + 1) {
|
| 1272 |
+
return false;
|
| 1273 |
+
}
|
| 1274 |
+
return this._buffers[piece.bufferIndex].buffer.charCodeAt(startOffset) === 10;
|
| 1275 |
+
}
|
| 1276 |
+
endWithCR(val) {
|
| 1277 |
+
if (typeof val === 'string') {
|
| 1278 |
+
return val.charCodeAt(val.length - 1) === 13;
|
| 1279 |
+
}
|
| 1280 |
+
if (val === SENTINEL || val.piece.lineFeedCnt === 0) {
|
| 1281 |
+
return false;
|
| 1282 |
+
}
|
| 1283 |
+
return this.nodeCharCodeAt(val, val.piece.length - 1) === 13;
|
| 1284 |
+
}
|
| 1285 |
+
validateCRLFWithPrevNode(nextNode) {
|
| 1286 |
+
if (this.shouldCheckCRLF() && this.startWithLF(nextNode)) {
|
| 1287 |
+
const node = nextNode.prev();
|
| 1288 |
+
if (this.endWithCR(node)) {
|
| 1289 |
+
this.fixCRLF(node, nextNode);
|
| 1290 |
+
}
|
| 1291 |
+
}
|
| 1292 |
+
}
|
| 1293 |
+
validateCRLFWithNextNode(node) {
|
| 1294 |
+
if (this.shouldCheckCRLF() && this.endWithCR(node)) {
|
| 1295 |
+
const nextNode = node.next();
|
| 1296 |
+
if (this.startWithLF(nextNode)) {
|
| 1297 |
+
this.fixCRLF(node, nextNode);
|
| 1298 |
+
}
|
| 1299 |
+
}
|
| 1300 |
+
}
|
| 1301 |
+
fixCRLF(prev, next) {
|
| 1302 |
+
const nodesToDel = [];
|
| 1303 |
+
// update node
|
| 1304 |
+
const lineStarts = this._buffers[prev.piece.bufferIndex].lineStarts;
|
| 1305 |
+
let newEnd;
|
| 1306 |
+
if (prev.piece.end.column === 0) {
|
| 1307 |
+
// it means, last line ends with \r, not \r\n
|
| 1308 |
+
newEnd = { line: prev.piece.end.line - 1, column: lineStarts[prev.piece.end.line] - lineStarts[prev.piece.end.line - 1] - 1 };
|
| 1309 |
+
}
|
| 1310 |
+
else {
|
| 1311 |
+
// \r\n
|
| 1312 |
+
newEnd = { line: prev.piece.end.line, column: prev.piece.end.column - 1 };
|
| 1313 |
+
}
|
| 1314 |
+
const prevNewLength = prev.piece.length - 1;
|
| 1315 |
+
const prevNewLFCnt = prev.piece.lineFeedCnt - 1;
|
| 1316 |
+
prev.piece = new Piece(prev.piece.bufferIndex, prev.piece.start, newEnd, prevNewLFCnt, prevNewLength);
|
| 1317 |
+
updateTreeMetadata(this, prev, -1, -1);
|
| 1318 |
+
if (prev.piece.length === 0) {
|
| 1319 |
+
nodesToDel.push(prev);
|
| 1320 |
+
}
|
| 1321 |
+
// update nextNode
|
| 1322 |
+
const newStart = { line: next.piece.start.line + 1, column: 0 };
|
| 1323 |
+
const newLength = next.piece.length - 1;
|
| 1324 |
+
const newLineFeedCnt = this.getLineFeedCnt(next.piece.bufferIndex, newStart, next.piece.end);
|
| 1325 |
+
next.piece = new Piece(next.piece.bufferIndex, newStart, next.piece.end, newLineFeedCnt, newLength);
|
| 1326 |
+
updateTreeMetadata(this, next, -1, -1);
|
| 1327 |
+
if (next.piece.length === 0) {
|
| 1328 |
+
nodesToDel.push(next);
|
| 1329 |
+
}
|
| 1330 |
+
// create new piece which contains \r\n
|
| 1331 |
+
const pieces = this.createNewPieces('\r\n');
|
| 1332 |
+
this.rbInsertRight(prev, pieces[0]);
|
| 1333 |
+
// delete empty nodes
|
| 1334 |
+
for (let i = 0; i < nodesToDel.length; i++) {
|
| 1335 |
+
rbDelete(this, nodesToDel[i]);
|
| 1336 |
+
}
|
| 1337 |
+
}
|
| 1338 |
+
adjustCarriageReturnFromNext(value, node) {
|
| 1339 |
+
if (this.shouldCheckCRLF() && this.endWithCR(value)) {
|
| 1340 |
+
const nextNode = node.next();
|
| 1341 |
+
if (this.startWithLF(nextNode)) {
|
| 1342 |
+
// move `\n` forward
|
| 1343 |
+
value += '\n';
|
| 1344 |
+
if (nextNode.piece.length === 1) {
|
| 1345 |
+
rbDelete(this, nextNode);
|
| 1346 |
+
}
|
| 1347 |
+
else {
|
| 1348 |
+
const piece = nextNode.piece;
|
| 1349 |
+
const newStart = { line: piece.start.line + 1, column: 0 };
|
| 1350 |
+
const newLength = piece.length - 1;
|
| 1351 |
+
const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);
|
| 1352 |
+
nextNode.piece = new Piece(piece.bufferIndex, newStart, piece.end, newLineFeedCnt, newLength);
|
| 1353 |
+
updateTreeMetadata(this, nextNode, -1, -1);
|
| 1354 |
+
}
|
| 1355 |
+
return true;
|
| 1356 |
+
}
|
| 1357 |
+
}
|
| 1358 |
+
return false;
|
| 1359 |
+
}
|
| 1360 |
+
// #endregion
|
| 1361 |
+
// #endregion
|
| 1362 |
+
// #region Tree operations
|
| 1363 |
+
iterate(node, callback) {
|
| 1364 |
+
if (node === SENTINEL) {
|
| 1365 |
+
return callback(SENTINEL);
|
| 1366 |
+
}
|
| 1367 |
+
const leftRet = this.iterate(node.left, callback);
|
| 1368 |
+
if (!leftRet) {
|
| 1369 |
+
return leftRet;
|
| 1370 |
+
}
|
| 1371 |
+
return callback(node) && this.iterate(node.right, callback);
|
| 1372 |
+
}
|
| 1373 |
+
getNodeContent(node) {
|
| 1374 |
+
if (node === SENTINEL) {
|
| 1375 |
+
return '';
|
| 1376 |
+
}
|
| 1377 |
+
const buffer = this._buffers[node.piece.bufferIndex];
|
| 1378 |
+
const piece = node.piece;
|
| 1379 |
+
const startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);
|
| 1380 |
+
const endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);
|
| 1381 |
+
const currentContent = buffer.buffer.substring(startOffset, endOffset);
|
| 1382 |
+
return currentContent;
|
| 1383 |
+
}
|
| 1384 |
+
getPieceContent(piece) {
|
| 1385 |
+
const buffer = this._buffers[piece.bufferIndex];
|
| 1386 |
+
const startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);
|
| 1387 |
+
const endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);
|
| 1388 |
+
const currentContent = buffer.buffer.substring(startOffset, endOffset);
|
| 1389 |
+
return currentContent;
|
| 1390 |
+
}
|
| 1391 |
+
/**
|
| 1392 |
+
* node node
|
| 1393 |
+
* / \ / \
|
| 1394 |
+
* a b <---- a b
|
| 1395 |
+
* /
|
| 1396 |
+
* z
|
| 1397 |
+
*/
|
| 1398 |
+
rbInsertRight(node, p) {
|
| 1399 |
+
const z = new TreeNode(p, 1 /* NodeColor.Red */);
|
| 1400 |
+
z.left = SENTINEL;
|
| 1401 |
+
z.right = SENTINEL;
|
| 1402 |
+
z.parent = SENTINEL;
|
| 1403 |
+
z.size_left = 0;
|
| 1404 |
+
z.lf_left = 0;
|
| 1405 |
+
const x = this.root;
|
| 1406 |
+
if (x === SENTINEL) {
|
| 1407 |
+
this.root = z;
|
| 1408 |
+
z.color = 0 /* NodeColor.Black */;
|
| 1409 |
+
}
|
| 1410 |
+
else if (node.right === SENTINEL) {
|
| 1411 |
+
node.right = z;
|
| 1412 |
+
z.parent = node;
|
| 1413 |
+
}
|
| 1414 |
+
else {
|
| 1415 |
+
const nextNode = leftest(node.right);
|
| 1416 |
+
nextNode.left = z;
|
| 1417 |
+
z.parent = nextNode;
|
| 1418 |
+
}
|
| 1419 |
+
fixInsert(this, z);
|
| 1420 |
+
return z;
|
| 1421 |
+
}
|
| 1422 |
+
/**
|
| 1423 |
+
* node node
|
| 1424 |
+
* / \ / \
|
| 1425 |
+
* a b ----> a b
|
| 1426 |
+
* \
|
| 1427 |
+
* z
|
| 1428 |
+
*/
|
| 1429 |
+
rbInsertLeft(node, p) {
|
| 1430 |
+
const z = new TreeNode(p, 1 /* NodeColor.Red */);
|
| 1431 |
+
z.left = SENTINEL;
|
| 1432 |
+
z.right = SENTINEL;
|
| 1433 |
+
z.parent = SENTINEL;
|
| 1434 |
+
z.size_left = 0;
|
| 1435 |
+
z.lf_left = 0;
|
| 1436 |
+
if (this.root === SENTINEL) {
|
| 1437 |
+
this.root = z;
|
| 1438 |
+
z.color = 0 /* NodeColor.Black */;
|
| 1439 |
+
}
|
| 1440 |
+
else if (node.left === SENTINEL) {
|
| 1441 |
+
node.left = z;
|
| 1442 |
+
z.parent = node;
|
| 1443 |
+
}
|
| 1444 |
+
else {
|
| 1445 |
+
const prevNode = righttest(node.left); // a
|
| 1446 |
+
prevNode.right = z;
|
| 1447 |
+
z.parent = prevNode;
|
| 1448 |
+
}
|
| 1449 |
+
fixInsert(this, z);
|
| 1450 |
+
return z;
|
| 1451 |
+
}
|
| 1452 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.js
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { Emitter } from '../../../../base/common/event.js';
|
| 6 |
+
import * as strings from '../../../../base/common/strings.js';
|
| 7 |
+
import { Range } from '../../core/range.js';
|
| 8 |
+
import { ApplyEditsResult } from '../../model.js';
|
| 9 |
+
import { PieceTreeBase } from './pieceTreeBase.js';
|
| 10 |
+
import { countEOL } from '../../core/eolCounter.js';
|
| 11 |
+
import { TextChange } from '../../core/textChange.js';
|
| 12 |
+
import { Disposable } from '../../../../base/common/lifecycle.js';
|
| 13 |
+
export class PieceTreeTextBuffer extends Disposable {
|
| 14 |
+
constructor(chunks, BOM, eol, containsRTL, containsUnusualLineTerminators, isBasicASCII, eolNormalized) {
|
| 15 |
+
super();
|
| 16 |
+
this._onDidChangeContent = this._register(new Emitter());
|
| 17 |
+
this._BOM = BOM;
|
| 18 |
+
this._mightContainNonBasicASCII = !isBasicASCII;
|
| 19 |
+
this._mightContainRTL = containsRTL;
|
| 20 |
+
this._mightContainUnusualLineTerminators = containsUnusualLineTerminators;
|
| 21 |
+
this._pieceTree = new PieceTreeBase(chunks, eol, eolNormalized);
|
| 22 |
+
}
|
| 23 |
+
mightContainRTL() {
|
| 24 |
+
return this._mightContainRTL;
|
| 25 |
+
}
|
| 26 |
+
mightContainUnusualLineTerminators() {
|
| 27 |
+
return this._mightContainUnusualLineTerminators;
|
| 28 |
+
}
|
| 29 |
+
resetMightContainUnusualLineTerminators() {
|
| 30 |
+
this._mightContainUnusualLineTerminators = false;
|
| 31 |
+
}
|
| 32 |
+
mightContainNonBasicASCII() {
|
| 33 |
+
return this._mightContainNonBasicASCII;
|
| 34 |
+
}
|
| 35 |
+
getBOM() {
|
| 36 |
+
return this._BOM;
|
| 37 |
+
}
|
| 38 |
+
getEOL() {
|
| 39 |
+
return this._pieceTree.getEOL();
|
| 40 |
+
}
|
| 41 |
+
createSnapshot(preserveBOM) {
|
| 42 |
+
return this._pieceTree.createSnapshot(preserveBOM ? this._BOM : '');
|
| 43 |
+
}
|
| 44 |
+
getOffsetAt(lineNumber, column) {
|
| 45 |
+
return this._pieceTree.getOffsetAt(lineNumber, column);
|
| 46 |
+
}
|
| 47 |
+
getPositionAt(offset) {
|
| 48 |
+
return this._pieceTree.getPositionAt(offset);
|
| 49 |
+
}
|
| 50 |
+
getRangeAt(start, length) {
|
| 51 |
+
const end = start + length;
|
| 52 |
+
const startPosition = this.getPositionAt(start);
|
| 53 |
+
const endPosition = this.getPositionAt(end);
|
| 54 |
+
return new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column);
|
| 55 |
+
}
|
| 56 |
+
getValueInRange(range, eol = 0 /* EndOfLinePreference.TextDefined */) {
|
| 57 |
+
if (range.isEmpty()) {
|
| 58 |
+
return '';
|
| 59 |
+
}
|
| 60 |
+
const lineEnding = this._getEndOfLine(eol);
|
| 61 |
+
return this._pieceTree.getValueInRange(range, lineEnding);
|
| 62 |
+
}
|
| 63 |
+
getValueLengthInRange(range, eol = 0 /* EndOfLinePreference.TextDefined */) {
|
| 64 |
+
if (range.isEmpty()) {
|
| 65 |
+
return 0;
|
| 66 |
+
}
|
| 67 |
+
if (range.startLineNumber === range.endLineNumber) {
|
| 68 |
+
return (range.endColumn - range.startColumn);
|
| 69 |
+
}
|
| 70 |
+
const startOffset = this.getOffsetAt(range.startLineNumber, range.startColumn);
|
| 71 |
+
const endOffset = this.getOffsetAt(range.endLineNumber, range.endColumn);
|
| 72 |
+
// offsets use the text EOL, so we need to compensate for length differences
|
| 73 |
+
// if the requested EOL doesn't match the text EOL
|
| 74 |
+
let eolOffsetCompensation = 0;
|
| 75 |
+
const desiredEOL = this._getEndOfLine(eol);
|
| 76 |
+
const actualEOL = this.getEOL();
|
| 77 |
+
if (desiredEOL.length !== actualEOL.length) {
|
| 78 |
+
const delta = desiredEOL.length - actualEOL.length;
|
| 79 |
+
const eolCount = range.endLineNumber - range.startLineNumber;
|
| 80 |
+
eolOffsetCompensation = delta * eolCount;
|
| 81 |
+
}
|
| 82 |
+
return endOffset - startOffset + eolOffsetCompensation;
|
| 83 |
+
}
|
| 84 |
+
getCharacterCountInRange(range, eol = 0 /* EndOfLinePreference.TextDefined */) {
|
| 85 |
+
if (this._mightContainNonBasicASCII) {
|
| 86 |
+
// we must count by iterating
|
| 87 |
+
let result = 0;
|
| 88 |
+
const fromLineNumber = range.startLineNumber;
|
| 89 |
+
const toLineNumber = range.endLineNumber;
|
| 90 |
+
for (let lineNumber = fromLineNumber; lineNumber <= toLineNumber; lineNumber++) {
|
| 91 |
+
const lineContent = this.getLineContent(lineNumber);
|
| 92 |
+
const fromOffset = (lineNumber === fromLineNumber ? range.startColumn - 1 : 0);
|
| 93 |
+
const toOffset = (lineNumber === toLineNumber ? range.endColumn - 1 : lineContent.length);
|
| 94 |
+
for (let offset = fromOffset; offset < toOffset; offset++) {
|
| 95 |
+
if (strings.isHighSurrogate(lineContent.charCodeAt(offset))) {
|
| 96 |
+
result = result + 1;
|
| 97 |
+
offset = offset + 1;
|
| 98 |
+
}
|
| 99 |
+
else {
|
| 100 |
+
result = result + 1;
|
| 101 |
+
}
|
| 102 |
+
}
|
| 103 |
+
}
|
| 104 |
+
result += this._getEndOfLine(eol).length * (toLineNumber - fromLineNumber);
|
| 105 |
+
return result;
|
| 106 |
+
}
|
| 107 |
+
return this.getValueLengthInRange(range, eol);
|
| 108 |
+
}
|
| 109 |
+
getLength() {
|
| 110 |
+
return this._pieceTree.getLength();
|
| 111 |
+
}
|
| 112 |
+
getLineCount() {
|
| 113 |
+
return this._pieceTree.getLineCount();
|
| 114 |
+
}
|
| 115 |
+
getLinesContent() {
|
| 116 |
+
return this._pieceTree.getLinesContent();
|
| 117 |
+
}
|
| 118 |
+
getLineContent(lineNumber) {
|
| 119 |
+
return this._pieceTree.getLineContent(lineNumber);
|
| 120 |
+
}
|
| 121 |
+
getLineCharCode(lineNumber, index) {
|
| 122 |
+
return this._pieceTree.getLineCharCode(lineNumber, index);
|
| 123 |
+
}
|
| 124 |
+
getLineLength(lineNumber) {
|
| 125 |
+
return this._pieceTree.getLineLength(lineNumber);
|
| 126 |
+
}
|
| 127 |
+
getLineFirstNonWhitespaceColumn(lineNumber) {
|
| 128 |
+
const result = strings.firstNonWhitespaceIndex(this.getLineContent(lineNumber));
|
| 129 |
+
if (result === -1) {
|
| 130 |
+
return 0;
|
| 131 |
+
}
|
| 132 |
+
return result + 1;
|
| 133 |
+
}
|
| 134 |
+
getLineLastNonWhitespaceColumn(lineNumber) {
|
| 135 |
+
const result = strings.lastNonWhitespaceIndex(this.getLineContent(lineNumber));
|
| 136 |
+
if (result === -1) {
|
| 137 |
+
return 0;
|
| 138 |
+
}
|
| 139 |
+
return result + 2;
|
| 140 |
+
}
|
| 141 |
+
_getEndOfLine(eol) {
|
| 142 |
+
switch (eol) {
|
| 143 |
+
case 1 /* EndOfLinePreference.LF */:
|
| 144 |
+
return '\n';
|
| 145 |
+
case 2 /* EndOfLinePreference.CRLF */:
|
| 146 |
+
return '\r\n';
|
| 147 |
+
case 0 /* EndOfLinePreference.TextDefined */:
|
| 148 |
+
return this.getEOL();
|
| 149 |
+
default:
|
| 150 |
+
throw new Error('Unknown EOL preference');
|
| 151 |
+
}
|
| 152 |
+
}
|
| 153 |
+
setEOL(newEOL) {
|
| 154 |
+
this._pieceTree.setEOL(newEOL);
|
| 155 |
+
}
|
| 156 |
+
applyEdits(rawOperations, recordTrimAutoWhitespace, computeUndoEdits) {
|
| 157 |
+
let mightContainRTL = this._mightContainRTL;
|
| 158 |
+
let mightContainUnusualLineTerminators = this._mightContainUnusualLineTerminators;
|
| 159 |
+
let mightContainNonBasicASCII = this._mightContainNonBasicASCII;
|
| 160 |
+
let canReduceOperations = true;
|
| 161 |
+
let operations = [];
|
| 162 |
+
for (let i = 0; i < rawOperations.length; i++) {
|
| 163 |
+
const op = rawOperations[i];
|
| 164 |
+
if (canReduceOperations && op._isTracked) {
|
| 165 |
+
canReduceOperations = false;
|
| 166 |
+
}
|
| 167 |
+
const validatedRange = op.range;
|
| 168 |
+
if (op.text) {
|
| 169 |
+
let textMightContainNonBasicASCII = true;
|
| 170 |
+
if (!mightContainNonBasicASCII) {
|
| 171 |
+
textMightContainNonBasicASCII = !strings.isBasicASCII(op.text);
|
| 172 |
+
mightContainNonBasicASCII = textMightContainNonBasicASCII;
|
| 173 |
+
}
|
| 174 |
+
if (!mightContainRTL && textMightContainNonBasicASCII) {
|
| 175 |
+
// check if the new inserted text contains RTL
|
| 176 |
+
mightContainRTL = strings.containsRTL(op.text);
|
| 177 |
+
}
|
| 178 |
+
if (!mightContainUnusualLineTerminators && textMightContainNonBasicASCII) {
|
| 179 |
+
// check if the new inserted text contains unusual line terminators
|
| 180 |
+
mightContainUnusualLineTerminators = strings.containsUnusualLineTerminators(op.text);
|
| 181 |
+
}
|
| 182 |
+
}
|
| 183 |
+
let validText = '';
|
| 184 |
+
let eolCount = 0;
|
| 185 |
+
let firstLineLength = 0;
|
| 186 |
+
let lastLineLength = 0;
|
| 187 |
+
if (op.text) {
|
| 188 |
+
let strEOL;
|
| 189 |
+
[eolCount, firstLineLength, lastLineLength, strEOL] = countEOL(op.text);
|
| 190 |
+
const bufferEOL = this.getEOL();
|
| 191 |
+
const expectedStrEOL = (bufferEOL === '\r\n' ? 2 /* StringEOL.CRLF */ : 1 /* StringEOL.LF */);
|
| 192 |
+
if (strEOL === 0 /* StringEOL.Unknown */ || strEOL === expectedStrEOL) {
|
| 193 |
+
validText = op.text;
|
| 194 |
+
}
|
| 195 |
+
else {
|
| 196 |
+
validText = op.text.replace(/\r\n|\r|\n/g, bufferEOL);
|
| 197 |
+
}
|
| 198 |
+
}
|
| 199 |
+
operations[i] = {
|
| 200 |
+
sortIndex: i,
|
| 201 |
+
identifier: op.identifier || null,
|
| 202 |
+
range: validatedRange,
|
| 203 |
+
rangeOffset: this.getOffsetAt(validatedRange.startLineNumber, validatedRange.startColumn),
|
| 204 |
+
rangeLength: this.getValueLengthInRange(validatedRange),
|
| 205 |
+
text: validText,
|
| 206 |
+
eolCount: eolCount,
|
| 207 |
+
firstLineLength: firstLineLength,
|
| 208 |
+
lastLineLength: lastLineLength,
|
| 209 |
+
forceMoveMarkers: Boolean(op.forceMoveMarkers),
|
| 210 |
+
isAutoWhitespaceEdit: op.isAutoWhitespaceEdit || false
|
| 211 |
+
};
|
| 212 |
+
}
|
| 213 |
+
// Sort operations ascending
|
| 214 |
+
operations.sort(PieceTreeTextBuffer._sortOpsAscending);
|
| 215 |
+
let hasTouchingRanges = false;
|
| 216 |
+
for (let i = 0, count = operations.length - 1; i < count; i++) {
|
| 217 |
+
const rangeEnd = operations[i].range.getEndPosition();
|
| 218 |
+
const nextRangeStart = operations[i + 1].range.getStartPosition();
|
| 219 |
+
if (nextRangeStart.isBeforeOrEqual(rangeEnd)) {
|
| 220 |
+
if (nextRangeStart.isBefore(rangeEnd)) {
|
| 221 |
+
// overlapping ranges
|
| 222 |
+
throw new Error('Overlapping ranges are not allowed!');
|
| 223 |
+
}
|
| 224 |
+
hasTouchingRanges = true;
|
| 225 |
+
}
|
| 226 |
+
}
|
| 227 |
+
if (canReduceOperations) {
|
| 228 |
+
operations = this._reduceOperations(operations);
|
| 229 |
+
}
|
| 230 |
+
// Delta encode operations
|
| 231 |
+
const reverseRanges = (computeUndoEdits || recordTrimAutoWhitespace ? PieceTreeTextBuffer._getInverseEditRanges(operations) : []);
|
| 232 |
+
const newTrimAutoWhitespaceCandidates = [];
|
| 233 |
+
if (recordTrimAutoWhitespace) {
|
| 234 |
+
for (let i = 0; i < operations.length; i++) {
|
| 235 |
+
const op = operations[i];
|
| 236 |
+
const reverseRange = reverseRanges[i];
|
| 237 |
+
if (op.isAutoWhitespaceEdit && op.range.isEmpty()) {
|
| 238 |
+
// Record already the future line numbers that might be auto whitespace removal candidates on next edit
|
| 239 |
+
for (let lineNumber = reverseRange.startLineNumber; lineNumber <= reverseRange.endLineNumber; lineNumber++) {
|
| 240 |
+
let currentLineContent = '';
|
| 241 |
+
if (lineNumber === reverseRange.startLineNumber) {
|
| 242 |
+
currentLineContent = this.getLineContent(op.range.startLineNumber);
|
| 243 |
+
if (strings.firstNonWhitespaceIndex(currentLineContent) !== -1) {
|
| 244 |
+
continue;
|
| 245 |
+
}
|
| 246 |
+
}
|
| 247 |
+
newTrimAutoWhitespaceCandidates.push({ lineNumber: lineNumber, oldContent: currentLineContent });
|
| 248 |
+
}
|
| 249 |
+
}
|
| 250 |
+
}
|
| 251 |
+
}
|
| 252 |
+
let reverseOperations = null;
|
| 253 |
+
if (computeUndoEdits) {
|
| 254 |
+
let reverseRangeDeltaOffset = 0;
|
| 255 |
+
reverseOperations = [];
|
| 256 |
+
for (let i = 0; i < operations.length; i++) {
|
| 257 |
+
const op = operations[i];
|
| 258 |
+
const reverseRange = reverseRanges[i];
|
| 259 |
+
const bufferText = this.getValueInRange(op.range);
|
| 260 |
+
const reverseRangeOffset = op.rangeOffset + reverseRangeDeltaOffset;
|
| 261 |
+
reverseRangeDeltaOffset += (op.text.length - bufferText.length);
|
| 262 |
+
reverseOperations[i] = {
|
| 263 |
+
sortIndex: op.sortIndex,
|
| 264 |
+
identifier: op.identifier,
|
| 265 |
+
range: reverseRange,
|
| 266 |
+
text: bufferText,
|
| 267 |
+
textChange: new TextChange(op.rangeOffset, bufferText, reverseRangeOffset, op.text)
|
| 268 |
+
};
|
| 269 |
+
}
|
| 270 |
+
// Can only sort reverse operations when the order is not significant
|
| 271 |
+
if (!hasTouchingRanges) {
|
| 272 |
+
reverseOperations.sort((a, b) => a.sortIndex - b.sortIndex);
|
| 273 |
+
}
|
| 274 |
+
}
|
| 275 |
+
this._mightContainRTL = mightContainRTL;
|
| 276 |
+
this._mightContainUnusualLineTerminators = mightContainUnusualLineTerminators;
|
| 277 |
+
this._mightContainNonBasicASCII = mightContainNonBasicASCII;
|
| 278 |
+
const contentChanges = this._doApplyEdits(operations);
|
| 279 |
+
let trimAutoWhitespaceLineNumbers = null;
|
| 280 |
+
if (recordTrimAutoWhitespace && newTrimAutoWhitespaceCandidates.length > 0) {
|
| 281 |
+
// sort line numbers auto whitespace removal candidates for next edit descending
|
| 282 |
+
newTrimAutoWhitespaceCandidates.sort((a, b) => b.lineNumber - a.lineNumber);
|
| 283 |
+
trimAutoWhitespaceLineNumbers = [];
|
| 284 |
+
for (let i = 0, len = newTrimAutoWhitespaceCandidates.length; i < len; i++) {
|
| 285 |
+
const lineNumber = newTrimAutoWhitespaceCandidates[i].lineNumber;
|
| 286 |
+
if (i > 0 && newTrimAutoWhitespaceCandidates[i - 1].lineNumber === lineNumber) {
|
| 287 |
+
// Do not have the same line number twice
|
| 288 |
+
continue;
|
| 289 |
+
}
|
| 290 |
+
const prevContent = newTrimAutoWhitespaceCandidates[i].oldContent;
|
| 291 |
+
const lineContent = this.getLineContent(lineNumber);
|
| 292 |
+
if (lineContent.length === 0 || lineContent === prevContent || strings.firstNonWhitespaceIndex(lineContent) !== -1) {
|
| 293 |
+
continue;
|
| 294 |
+
}
|
| 295 |
+
trimAutoWhitespaceLineNumbers.push(lineNumber);
|
| 296 |
+
}
|
| 297 |
+
}
|
| 298 |
+
this._onDidChangeContent.fire();
|
| 299 |
+
return new ApplyEditsResult(reverseOperations, contentChanges, trimAutoWhitespaceLineNumbers);
|
| 300 |
+
}
|
| 301 |
+
/**
|
| 302 |
+
* Transform operations such that they represent the same logic edit,
|
| 303 |
+
* but that they also do not cause OOM crashes.
|
| 304 |
+
*/
|
| 305 |
+
_reduceOperations(operations) {
|
| 306 |
+
if (operations.length < 1000) {
|
| 307 |
+
// We know from empirical testing that a thousand edits work fine regardless of their shape.
|
| 308 |
+
return operations;
|
| 309 |
+
}
|
| 310 |
+
// At one point, due to how events are emitted and how each operation is handled,
|
| 311 |
+
// some operations can trigger a high amount of temporary string allocations,
|
| 312 |
+
// that will immediately get edited again.
|
| 313 |
+
// e.g. a formatter inserting ridiculous ammounts of \n on a model with a single line
|
| 314 |
+
// Therefore, the strategy is to collapse all the operations into a huge single edit operation
|
| 315 |
+
return [this._toSingleEditOperation(operations)];
|
| 316 |
+
}
|
| 317 |
+
_toSingleEditOperation(operations) {
|
| 318 |
+
let forceMoveMarkers = false;
|
| 319 |
+
const firstEditRange = operations[0].range;
|
| 320 |
+
const lastEditRange = operations[operations.length - 1].range;
|
| 321 |
+
const entireEditRange = new Range(firstEditRange.startLineNumber, firstEditRange.startColumn, lastEditRange.endLineNumber, lastEditRange.endColumn);
|
| 322 |
+
let lastEndLineNumber = firstEditRange.startLineNumber;
|
| 323 |
+
let lastEndColumn = firstEditRange.startColumn;
|
| 324 |
+
const result = [];
|
| 325 |
+
for (let i = 0, len = operations.length; i < len; i++) {
|
| 326 |
+
const operation = operations[i];
|
| 327 |
+
const range = operation.range;
|
| 328 |
+
forceMoveMarkers = forceMoveMarkers || operation.forceMoveMarkers;
|
| 329 |
+
// (1) -- Push old text
|
| 330 |
+
result.push(this.getValueInRange(new Range(lastEndLineNumber, lastEndColumn, range.startLineNumber, range.startColumn)));
|
| 331 |
+
// (2) -- Push new text
|
| 332 |
+
if (operation.text.length > 0) {
|
| 333 |
+
result.push(operation.text);
|
| 334 |
+
}
|
| 335 |
+
lastEndLineNumber = range.endLineNumber;
|
| 336 |
+
lastEndColumn = range.endColumn;
|
| 337 |
+
}
|
| 338 |
+
const text = result.join('');
|
| 339 |
+
const [eolCount, firstLineLength, lastLineLength] = countEOL(text);
|
| 340 |
+
return {
|
| 341 |
+
sortIndex: 0,
|
| 342 |
+
identifier: operations[0].identifier,
|
| 343 |
+
range: entireEditRange,
|
| 344 |
+
rangeOffset: this.getOffsetAt(entireEditRange.startLineNumber, entireEditRange.startColumn),
|
| 345 |
+
rangeLength: this.getValueLengthInRange(entireEditRange, 0 /* EndOfLinePreference.TextDefined */),
|
| 346 |
+
text: text,
|
| 347 |
+
eolCount: eolCount,
|
| 348 |
+
firstLineLength: firstLineLength,
|
| 349 |
+
lastLineLength: lastLineLength,
|
| 350 |
+
forceMoveMarkers: forceMoveMarkers,
|
| 351 |
+
isAutoWhitespaceEdit: false
|
| 352 |
+
};
|
| 353 |
+
}
|
| 354 |
+
_doApplyEdits(operations) {
|
| 355 |
+
operations.sort(PieceTreeTextBuffer._sortOpsDescending);
|
| 356 |
+
const contentChanges = [];
|
| 357 |
+
// operations are from bottom to top
|
| 358 |
+
for (let i = 0; i < operations.length; i++) {
|
| 359 |
+
const op = operations[i];
|
| 360 |
+
const startLineNumber = op.range.startLineNumber;
|
| 361 |
+
const startColumn = op.range.startColumn;
|
| 362 |
+
const endLineNumber = op.range.endLineNumber;
|
| 363 |
+
const endColumn = op.range.endColumn;
|
| 364 |
+
if (startLineNumber === endLineNumber && startColumn === endColumn && op.text.length === 0) {
|
| 365 |
+
// no-op
|
| 366 |
+
continue;
|
| 367 |
+
}
|
| 368 |
+
if (op.text) {
|
| 369 |
+
// replacement
|
| 370 |
+
this._pieceTree.delete(op.rangeOffset, op.rangeLength);
|
| 371 |
+
this._pieceTree.insert(op.rangeOffset, op.text, true);
|
| 372 |
+
}
|
| 373 |
+
else {
|
| 374 |
+
// deletion
|
| 375 |
+
this._pieceTree.delete(op.rangeOffset, op.rangeLength);
|
| 376 |
+
}
|
| 377 |
+
const contentChangeRange = new Range(startLineNumber, startColumn, endLineNumber, endColumn);
|
| 378 |
+
contentChanges.push({
|
| 379 |
+
range: contentChangeRange,
|
| 380 |
+
rangeLength: op.rangeLength,
|
| 381 |
+
text: op.text,
|
| 382 |
+
rangeOffset: op.rangeOffset,
|
| 383 |
+
forceMoveMarkers: op.forceMoveMarkers
|
| 384 |
+
});
|
| 385 |
+
}
|
| 386 |
+
return contentChanges;
|
| 387 |
+
}
|
| 388 |
+
findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount) {
|
| 389 |
+
return this._pieceTree.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);
|
| 390 |
+
}
|
| 391 |
+
/**
|
| 392 |
+
* Assumes `operations` are validated and sorted ascending
|
| 393 |
+
*/
|
| 394 |
+
static _getInverseEditRanges(operations) {
|
| 395 |
+
const result = [];
|
| 396 |
+
let prevOpEndLineNumber = 0;
|
| 397 |
+
let prevOpEndColumn = 0;
|
| 398 |
+
let prevOp = null;
|
| 399 |
+
for (let i = 0, len = operations.length; i < len; i++) {
|
| 400 |
+
const op = operations[i];
|
| 401 |
+
let startLineNumber;
|
| 402 |
+
let startColumn;
|
| 403 |
+
if (prevOp) {
|
| 404 |
+
if (prevOp.range.endLineNumber === op.range.startLineNumber) {
|
| 405 |
+
startLineNumber = prevOpEndLineNumber;
|
| 406 |
+
startColumn = prevOpEndColumn + (op.range.startColumn - prevOp.range.endColumn);
|
| 407 |
+
}
|
| 408 |
+
else {
|
| 409 |
+
startLineNumber = prevOpEndLineNumber + (op.range.startLineNumber - prevOp.range.endLineNumber);
|
| 410 |
+
startColumn = op.range.startColumn;
|
| 411 |
+
}
|
| 412 |
+
}
|
| 413 |
+
else {
|
| 414 |
+
startLineNumber = op.range.startLineNumber;
|
| 415 |
+
startColumn = op.range.startColumn;
|
| 416 |
+
}
|
| 417 |
+
let resultRange;
|
| 418 |
+
if (op.text.length > 0) {
|
| 419 |
+
// the operation inserts something
|
| 420 |
+
const lineCount = op.eolCount + 1;
|
| 421 |
+
if (lineCount === 1) {
|
| 422 |
+
// single line insert
|
| 423 |
+
resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn + op.firstLineLength);
|
| 424 |
+
}
|
| 425 |
+
else {
|
| 426 |
+
// multi line insert
|
| 427 |
+
resultRange = new Range(startLineNumber, startColumn, startLineNumber + lineCount - 1, op.lastLineLength + 1);
|
| 428 |
+
}
|
| 429 |
+
}
|
| 430 |
+
else {
|
| 431 |
+
// There is nothing to insert
|
| 432 |
+
resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn);
|
| 433 |
+
}
|
| 434 |
+
prevOpEndLineNumber = resultRange.endLineNumber;
|
| 435 |
+
prevOpEndColumn = resultRange.endColumn;
|
| 436 |
+
result.push(resultRange);
|
| 437 |
+
prevOp = op;
|
| 438 |
+
}
|
| 439 |
+
return result;
|
| 440 |
+
}
|
| 441 |
+
static _sortOpsAscending(a, b) {
|
| 442 |
+
const r = Range.compareRangesUsingEnds(a.range, b.range);
|
| 443 |
+
if (r === 0) {
|
| 444 |
+
return a.sortIndex - b.sortIndex;
|
| 445 |
+
}
|
| 446 |
+
return r;
|
| 447 |
+
}
|
| 448 |
+
static _sortOpsDescending(a, b) {
|
| 449 |
+
const r = Range.compareRangesUsingEnds(a.range, b.range);
|
| 450 |
+
if (r === 0) {
|
| 451 |
+
return b.sortIndex - a.sortIndex;
|
| 452 |
+
}
|
| 453 |
+
return -r;
|
| 454 |
+
}
|
| 455 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import * as strings from '../../../../base/common/strings.js';
|
| 6 |
+
import { StringBuffer, createLineStarts, createLineStartsFast } from './pieceTreeBase.js';
|
| 7 |
+
import { PieceTreeTextBuffer } from './pieceTreeTextBuffer.js';
|
| 8 |
+
class PieceTreeTextBufferFactory {
|
| 9 |
+
constructor(_chunks, _bom, _cr, _lf, _crlf, _containsRTL, _containsUnusualLineTerminators, _isBasicASCII, _normalizeEOL) {
|
| 10 |
+
this._chunks = _chunks;
|
| 11 |
+
this._bom = _bom;
|
| 12 |
+
this._cr = _cr;
|
| 13 |
+
this._lf = _lf;
|
| 14 |
+
this._crlf = _crlf;
|
| 15 |
+
this._containsRTL = _containsRTL;
|
| 16 |
+
this._containsUnusualLineTerminators = _containsUnusualLineTerminators;
|
| 17 |
+
this._isBasicASCII = _isBasicASCII;
|
| 18 |
+
this._normalizeEOL = _normalizeEOL;
|
| 19 |
+
}
|
| 20 |
+
_getEOL(defaultEOL) {
|
| 21 |
+
const totalEOLCount = this._cr + this._lf + this._crlf;
|
| 22 |
+
const totalCRCount = this._cr + this._crlf;
|
| 23 |
+
if (totalEOLCount === 0) {
|
| 24 |
+
// This is an empty file or a file with precisely one line
|
| 25 |
+
return (defaultEOL === 1 /* DefaultEndOfLine.LF */ ? '\n' : '\r\n');
|
| 26 |
+
}
|
| 27 |
+
if (totalCRCount > totalEOLCount / 2) {
|
| 28 |
+
// More than half of the file contains \r\n ending lines
|
| 29 |
+
return '\r\n';
|
| 30 |
+
}
|
| 31 |
+
// At least one line more ends in \n
|
| 32 |
+
return '\n';
|
| 33 |
+
}
|
| 34 |
+
create(defaultEOL) {
|
| 35 |
+
const eol = this._getEOL(defaultEOL);
|
| 36 |
+
const chunks = this._chunks;
|
| 37 |
+
if (this._normalizeEOL &&
|
| 38 |
+
((eol === '\r\n' && (this._cr > 0 || this._lf > 0))
|
| 39 |
+
|| (eol === '\n' && (this._cr > 0 || this._crlf > 0)))) {
|
| 40 |
+
// Normalize pieces
|
| 41 |
+
for (let i = 0, len = chunks.length; i < len; i++) {
|
| 42 |
+
const str = chunks[i].buffer.replace(/\r\n|\r|\n/g, eol);
|
| 43 |
+
const newLineStart = createLineStartsFast(str);
|
| 44 |
+
chunks[i] = new StringBuffer(str, newLineStart);
|
| 45 |
+
}
|
| 46 |
+
}
|
| 47 |
+
const textBuffer = new PieceTreeTextBuffer(chunks, this._bom, eol, this._containsRTL, this._containsUnusualLineTerminators, this._isBasicASCII, this._normalizeEOL);
|
| 48 |
+
return { textBuffer: textBuffer, disposable: textBuffer };
|
| 49 |
+
}
|
| 50 |
+
}
|
| 51 |
+
export class PieceTreeTextBufferBuilder {
|
| 52 |
+
constructor() {
|
| 53 |
+
this.chunks = [];
|
| 54 |
+
this.BOM = '';
|
| 55 |
+
this._hasPreviousChar = false;
|
| 56 |
+
this._previousChar = 0;
|
| 57 |
+
this._tmpLineStarts = [];
|
| 58 |
+
this.cr = 0;
|
| 59 |
+
this.lf = 0;
|
| 60 |
+
this.crlf = 0;
|
| 61 |
+
this.containsRTL = false;
|
| 62 |
+
this.containsUnusualLineTerminators = false;
|
| 63 |
+
this.isBasicASCII = true;
|
| 64 |
+
}
|
| 65 |
+
acceptChunk(chunk) {
|
| 66 |
+
if (chunk.length === 0) {
|
| 67 |
+
return;
|
| 68 |
+
}
|
| 69 |
+
if (this.chunks.length === 0) {
|
| 70 |
+
if (strings.startsWithUTF8BOM(chunk)) {
|
| 71 |
+
this.BOM = strings.UTF8_BOM_CHARACTER;
|
| 72 |
+
chunk = chunk.substr(1);
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
const lastChar = chunk.charCodeAt(chunk.length - 1);
|
| 76 |
+
if (lastChar === 13 /* CharCode.CarriageReturn */ || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {
|
| 77 |
+
// last character is \r or a high surrogate => keep it back
|
| 78 |
+
this._acceptChunk1(chunk.substr(0, chunk.length - 1), false);
|
| 79 |
+
this._hasPreviousChar = true;
|
| 80 |
+
this._previousChar = lastChar;
|
| 81 |
+
}
|
| 82 |
+
else {
|
| 83 |
+
this._acceptChunk1(chunk, false);
|
| 84 |
+
this._hasPreviousChar = false;
|
| 85 |
+
this._previousChar = lastChar;
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
_acceptChunk1(chunk, allowEmptyStrings) {
|
| 89 |
+
if (!allowEmptyStrings && chunk.length === 0) {
|
| 90 |
+
// Nothing to do
|
| 91 |
+
return;
|
| 92 |
+
}
|
| 93 |
+
if (this._hasPreviousChar) {
|
| 94 |
+
this._acceptChunk2(String.fromCharCode(this._previousChar) + chunk);
|
| 95 |
+
}
|
| 96 |
+
else {
|
| 97 |
+
this._acceptChunk2(chunk);
|
| 98 |
+
}
|
| 99 |
+
}
|
| 100 |
+
_acceptChunk2(chunk) {
|
| 101 |
+
const lineStarts = createLineStarts(this._tmpLineStarts, chunk);
|
| 102 |
+
this.chunks.push(new StringBuffer(chunk, lineStarts.lineStarts));
|
| 103 |
+
this.cr += lineStarts.cr;
|
| 104 |
+
this.lf += lineStarts.lf;
|
| 105 |
+
this.crlf += lineStarts.crlf;
|
| 106 |
+
if (!lineStarts.isBasicASCII) {
|
| 107 |
+
// this chunk contains non basic ASCII characters
|
| 108 |
+
this.isBasicASCII = false;
|
| 109 |
+
if (!this.containsRTL) {
|
| 110 |
+
this.containsRTL = strings.containsRTL(chunk);
|
| 111 |
+
}
|
| 112 |
+
if (!this.containsUnusualLineTerminators) {
|
| 113 |
+
this.containsUnusualLineTerminators = strings.containsUnusualLineTerminators(chunk);
|
| 114 |
+
}
|
| 115 |
+
}
|
| 116 |
+
}
|
| 117 |
+
finish(normalizeEOL = true) {
|
| 118 |
+
this._finish();
|
| 119 |
+
return new PieceTreeTextBufferFactory(this.chunks, this.BOM, this.cr, this.lf, this.crlf, this.containsRTL, this.containsUnusualLineTerminators, this.isBasicASCII, normalizeEOL);
|
| 120 |
+
}
|
| 121 |
+
_finish() {
|
| 122 |
+
if (this.chunks.length === 0) {
|
| 123 |
+
this._acceptChunk1('', true);
|
| 124 |
+
}
|
| 125 |
+
if (this._hasPreviousChar) {
|
| 126 |
+
this._hasPreviousChar = false;
|
| 127 |
+
// recreate last chunk
|
| 128 |
+
const lastChunk = this.chunks[this.chunks.length - 1];
|
| 129 |
+
lastChunk.buffer += String.fromCharCode(this._previousChar);
|
| 130 |
+
const newLineStarts = createLineStartsFast(lastChunk.buffer);
|
| 131 |
+
lastChunk.lineStarts = newLineStarts;
|
| 132 |
+
if (this._previousChar === 13 /* CharCode.CarriageReturn */) {
|
| 133 |
+
this.cr++;
|
| 134 |
+
}
|
| 135 |
+
}
|
| 136 |
+
}
|
| 137 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase.js
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
export class TreeNode {
|
| 6 |
+
constructor(piece, color) {
|
| 7 |
+
this.piece = piece;
|
| 8 |
+
this.color = color;
|
| 9 |
+
this.size_left = 0;
|
| 10 |
+
this.lf_left = 0;
|
| 11 |
+
this.parent = this;
|
| 12 |
+
this.left = this;
|
| 13 |
+
this.right = this;
|
| 14 |
+
}
|
| 15 |
+
next() {
|
| 16 |
+
if (this.right !== SENTINEL) {
|
| 17 |
+
return leftest(this.right);
|
| 18 |
+
}
|
| 19 |
+
let node = this;
|
| 20 |
+
while (node.parent !== SENTINEL) {
|
| 21 |
+
if (node.parent.left === node) {
|
| 22 |
+
break;
|
| 23 |
+
}
|
| 24 |
+
node = node.parent;
|
| 25 |
+
}
|
| 26 |
+
if (node.parent === SENTINEL) {
|
| 27 |
+
return SENTINEL;
|
| 28 |
+
}
|
| 29 |
+
else {
|
| 30 |
+
return node.parent;
|
| 31 |
+
}
|
| 32 |
+
}
|
| 33 |
+
prev() {
|
| 34 |
+
if (this.left !== SENTINEL) {
|
| 35 |
+
return righttest(this.left);
|
| 36 |
+
}
|
| 37 |
+
let node = this;
|
| 38 |
+
while (node.parent !== SENTINEL) {
|
| 39 |
+
if (node.parent.right === node) {
|
| 40 |
+
break;
|
| 41 |
+
}
|
| 42 |
+
node = node.parent;
|
| 43 |
+
}
|
| 44 |
+
if (node.parent === SENTINEL) {
|
| 45 |
+
return SENTINEL;
|
| 46 |
+
}
|
| 47 |
+
else {
|
| 48 |
+
return node.parent;
|
| 49 |
+
}
|
| 50 |
+
}
|
| 51 |
+
detach() {
|
| 52 |
+
this.parent = null;
|
| 53 |
+
this.left = null;
|
| 54 |
+
this.right = null;
|
| 55 |
+
}
|
| 56 |
+
}
|
| 57 |
+
export const SENTINEL = new TreeNode(null, 0 /* NodeColor.Black */);
|
| 58 |
+
SENTINEL.parent = SENTINEL;
|
| 59 |
+
SENTINEL.left = SENTINEL;
|
| 60 |
+
SENTINEL.right = SENTINEL;
|
| 61 |
+
SENTINEL.color = 0 /* NodeColor.Black */;
|
| 62 |
+
export function leftest(node) {
|
| 63 |
+
while (node.left !== SENTINEL) {
|
| 64 |
+
node = node.left;
|
| 65 |
+
}
|
| 66 |
+
return node;
|
| 67 |
+
}
|
| 68 |
+
export function righttest(node) {
|
| 69 |
+
while (node.right !== SENTINEL) {
|
| 70 |
+
node = node.right;
|
| 71 |
+
}
|
| 72 |
+
return node;
|
| 73 |
+
}
|
| 74 |
+
function calculateSize(node) {
|
| 75 |
+
if (node === SENTINEL) {
|
| 76 |
+
return 0;
|
| 77 |
+
}
|
| 78 |
+
return node.size_left + node.piece.length + calculateSize(node.right);
|
| 79 |
+
}
|
| 80 |
+
function calculateLF(node) {
|
| 81 |
+
if (node === SENTINEL) {
|
| 82 |
+
return 0;
|
| 83 |
+
}
|
| 84 |
+
return node.lf_left + node.piece.lineFeedCnt + calculateLF(node.right);
|
| 85 |
+
}
|
| 86 |
+
function resetSentinel() {
|
| 87 |
+
SENTINEL.parent = SENTINEL;
|
| 88 |
+
}
|
| 89 |
+
export function leftRotate(tree, x) {
|
| 90 |
+
const y = x.right;
|
| 91 |
+
// fix size_left
|
| 92 |
+
y.size_left += x.size_left + (x.piece ? x.piece.length : 0);
|
| 93 |
+
y.lf_left += x.lf_left + (x.piece ? x.piece.lineFeedCnt : 0);
|
| 94 |
+
x.right = y.left;
|
| 95 |
+
if (y.left !== SENTINEL) {
|
| 96 |
+
y.left.parent = x;
|
| 97 |
+
}
|
| 98 |
+
y.parent = x.parent;
|
| 99 |
+
if (x.parent === SENTINEL) {
|
| 100 |
+
tree.root = y;
|
| 101 |
+
}
|
| 102 |
+
else if (x.parent.left === x) {
|
| 103 |
+
x.parent.left = y;
|
| 104 |
+
}
|
| 105 |
+
else {
|
| 106 |
+
x.parent.right = y;
|
| 107 |
+
}
|
| 108 |
+
y.left = x;
|
| 109 |
+
x.parent = y;
|
| 110 |
+
}
|
| 111 |
+
export function rightRotate(tree, y) {
|
| 112 |
+
const x = y.left;
|
| 113 |
+
y.left = x.right;
|
| 114 |
+
if (x.right !== SENTINEL) {
|
| 115 |
+
x.right.parent = y;
|
| 116 |
+
}
|
| 117 |
+
x.parent = y.parent;
|
| 118 |
+
// fix size_left
|
| 119 |
+
y.size_left -= x.size_left + (x.piece ? x.piece.length : 0);
|
| 120 |
+
y.lf_left -= x.lf_left + (x.piece ? x.piece.lineFeedCnt : 0);
|
| 121 |
+
if (y.parent === SENTINEL) {
|
| 122 |
+
tree.root = x;
|
| 123 |
+
}
|
| 124 |
+
else if (y === y.parent.right) {
|
| 125 |
+
y.parent.right = x;
|
| 126 |
+
}
|
| 127 |
+
else {
|
| 128 |
+
y.parent.left = x;
|
| 129 |
+
}
|
| 130 |
+
x.right = y;
|
| 131 |
+
y.parent = x;
|
| 132 |
+
}
|
| 133 |
+
export function rbDelete(tree, z) {
|
| 134 |
+
let x;
|
| 135 |
+
let y;
|
| 136 |
+
if (z.left === SENTINEL) {
|
| 137 |
+
y = z;
|
| 138 |
+
x = y.right;
|
| 139 |
+
}
|
| 140 |
+
else if (z.right === SENTINEL) {
|
| 141 |
+
y = z;
|
| 142 |
+
x = y.left;
|
| 143 |
+
}
|
| 144 |
+
else {
|
| 145 |
+
y = leftest(z.right);
|
| 146 |
+
x = y.right;
|
| 147 |
+
}
|
| 148 |
+
if (y === tree.root) {
|
| 149 |
+
tree.root = x;
|
| 150 |
+
// if x is null, we are removing the only node
|
| 151 |
+
x.color = 0 /* NodeColor.Black */;
|
| 152 |
+
z.detach();
|
| 153 |
+
resetSentinel();
|
| 154 |
+
tree.root.parent = SENTINEL;
|
| 155 |
+
return;
|
| 156 |
+
}
|
| 157 |
+
const yWasRed = (y.color === 1 /* NodeColor.Red */);
|
| 158 |
+
if (y === y.parent.left) {
|
| 159 |
+
y.parent.left = x;
|
| 160 |
+
}
|
| 161 |
+
else {
|
| 162 |
+
y.parent.right = x;
|
| 163 |
+
}
|
| 164 |
+
if (y === z) {
|
| 165 |
+
x.parent = y.parent;
|
| 166 |
+
recomputeTreeMetadata(tree, x);
|
| 167 |
+
}
|
| 168 |
+
else {
|
| 169 |
+
if (y.parent === z) {
|
| 170 |
+
x.parent = y;
|
| 171 |
+
}
|
| 172 |
+
else {
|
| 173 |
+
x.parent = y.parent;
|
| 174 |
+
}
|
| 175 |
+
// as we make changes to x's hierarchy, update size_left of subtree first
|
| 176 |
+
recomputeTreeMetadata(tree, x);
|
| 177 |
+
y.left = z.left;
|
| 178 |
+
y.right = z.right;
|
| 179 |
+
y.parent = z.parent;
|
| 180 |
+
y.color = z.color;
|
| 181 |
+
if (z === tree.root) {
|
| 182 |
+
tree.root = y;
|
| 183 |
+
}
|
| 184 |
+
else {
|
| 185 |
+
if (z === z.parent.left) {
|
| 186 |
+
z.parent.left = y;
|
| 187 |
+
}
|
| 188 |
+
else {
|
| 189 |
+
z.parent.right = y;
|
| 190 |
+
}
|
| 191 |
+
}
|
| 192 |
+
if (y.left !== SENTINEL) {
|
| 193 |
+
y.left.parent = y;
|
| 194 |
+
}
|
| 195 |
+
if (y.right !== SENTINEL) {
|
| 196 |
+
y.right.parent = y;
|
| 197 |
+
}
|
| 198 |
+
// update metadata
|
| 199 |
+
// we replace z with y, so in this sub tree, the length change is z.item.length
|
| 200 |
+
y.size_left = z.size_left;
|
| 201 |
+
y.lf_left = z.lf_left;
|
| 202 |
+
recomputeTreeMetadata(tree, y);
|
| 203 |
+
}
|
| 204 |
+
z.detach();
|
| 205 |
+
if (x.parent.left === x) {
|
| 206 |
+
const newSizeLeft = calculateSize(x);
|
| 207 |
+
const newLFLeft = calculateLF(x);
|
| 208 |
+
if (newSizeLeft !== x.parent.size_left || newLFLeft !== x.parent.lf_left) {
|
| 209 |
+
const delta = newSizeLeft - x.parent.size_left;
|
| 210 |
+
const lf_delta = newLFLeft - x.parent.lf_left;
|
| 211 |
+
x.parent.size_left = newSizeLeft;
|
| 212 |
+
x.parent.lf_left = newLFLeft;
|
| 213 |
+
updateTreeMetadata(tree, x.parent, delta, lf_delta);
|
| 214 |
+
}
|
| 215 |
+
}
|
| 216 |
+
recomputeTreeMetadata(tree, x.parent);
|
| 217 |
+
if (yWasRed) {
|
| 218 |
+
resetSentinel();
|
| 219 |
+
return;
|
| 220 |
+
}
|
| 221 |
+
// RB-DELETE-FIXUP
|
| 222 |
+
let w;
|
| 223 |
+
while (x !== tree.root && x.color === 0 /* NodeColor.Black */) {
|
| 224 |
+
if (x === x.parent.left) {
|
| 225 |
+
w = x.parent.right;
|
| 226 |
+
if (w.color === 1 /* NodeColor.Red */) {
|
| 227 |
+
w.color = 0 /* NodeColor.Black */;
|
| 228 |
+
x.parent.color = 1 /* NodeColor.Red */;
|
| 229 |
+
leftRotate(tree, x.parent);
|
| 230 |
+
w = x.parent.right;
|
| 231 |
+
}
|
| 232 |
+
if (w.left.color === 0 /* NodeColor.Black */ && w.right.color === 0 /* NodeColor.Black */) {
|
| 233 |
+
w.color = 1 /* NodeColor.Red */;
|
| 234 |
+
x = x.parent;
|
| 235 |
+
}
|
| 236 |
+
else {
|
| 237 |
+
if (w.right.color === 0 /* NodeColor.Black */) {
|
| 238 |
+
w.left.color = 0 /* NodeColor.Black */;
|
| 239 |
+
w.color = 1 /* NodeColor.Red */;
|
| 240 |
+
rightRotate(tree, w);
|
| 241 |
+
w = x.parent.right;
|
| 242 |
+
}
|
| 243 |
+
w.color = x.parent.color;
|
| 244 |
+
x.parent.color = 0 /* NodeColor.Black */;
|
| 245 |
+
w.right.color = 0 /* NodeColor.Black */;
|
| 246 |
+
leftRotate(tree, x.parent);
|
| 247 |
+
x = tree.root;
|
| 248 |
+
}
|
| 249 |
+
}
|
| 250 |
+
else {
|
| 251 |
+
w = x.parent.left;
|
| 252 |
+
if (w.color === 1 /* NodeColor.Red */) {
|
| 253 |
+
w.color = 0 /* NodeColor.Black */;
|
| 254 |
+
x.parent.color = 1 /* NodeColor.Red */;
|
| 255 |
+
rightRotate(tree, x.parent);
|
| 256 |
+
w = x.parent.left;
|
| 257 |
+
}
|
| 258 |
+
if (w.left.color === 0 /* NodeColor.Black */ && w.right.color === 0 /* NodeColor.Black */) {
|
| 259 |
+
w.color = 1 /* NodeColor.Red */;
|
| 260 |
+
x = x.parent;
|
| 261 |
+
}
|
| 262 |
+
else {
|
| 263 |
+
if (w.left.color === 0 /* NodeColor.Black */) {
|
| 264 |
+
w.right.color = 0 /* NodeColor.Black */;
|
| 265 |
+
w.color = 1 /* NodeColor.Red */;
|
| 266 |
+
leftRotate(tree, w);
|
| 267 |
+
w = x.parent.left;
|
| 268 |
+
}
|
| 269 |
+
w.color = x.parent.color;
|
| 270 |
+
x.parent.color = 0 /* NodeColor.Black */;
|
| 271 |
+
w.left.color = 0 /* NodeColor.Black */;
|
| 272 |
+
rightRotate(tree, x.parent);
|
| 273 |
+
x = tree.root;
|
| 274 |
+
}
|
| 275 |
+
}
|
| 276 |
+
}
|
| 277 |
+
x.color = 0 /* NodeColor.Black */;
|
| 278 |
+
resetSentinel();
|
| 279 |
+
}
|
| 280 |
+
export function fixInsert(tree, x) {
|
| 281 |
+
recomputeTreeMetadata(tree, x);
|
| 282 |
+
while (x !== tree.root && x.parent.color === 1 /* NodeColor.Red */) {
|
| 283 |
+
if (x.parent === x.parent.parent.left) {
|
| 284 |
+
const y = x.parent.parent.right;
|
| 285 |
+
if (y.color === 1 /* NodeColor.Red */) {
|
| 286 |
+
x.parent.color = 0 /* NodeColor.Black */;
|
| 287 |
+
y.color = 0 /* NodeColor.Black */;
|
| 288 |
+
x.parent.parent.color = 1 /* NodeColor.Red */;
|
| 289 |
+
x = x.parent.parent;
|
| 290 |
+
}
|
| 291 |
+
else {
|
| 292 |
+
if (x === x.parent.right) {
|
| 293 |
+
x = x.parent;
|
| 294 |
+
leftRotate(tree, x);
|
| 295 |
+
}
|
| 296 |
+
x.parent.color = 0 /* NodeColor.Black */;
|
| 297 |
+
x.parent.parent.color = 1 /* NodeColor.Red */;
|
| 298 |
+
rightRotate(tree, x.parent.parent);
|
| 299 |
+
}
|
| 300 |
+
}
|
| 301 |
+
else {
|
| 302 |
+
const y = x.parent.parent.left;
|
| 303 |
+
if (y.color === 1 /* NodeColor.Red */) {
|
| 304 |
+
x.parent.color = 0 /* NodeColor.Black */;
|
| 305 |
+
y.color = 0 /* NodeColor.Black */;
|
| 306 |
+
x.parent.parent.color = 1 /* NodeColor.Red */;
|
| 307 |
+
x = x.parent.parent;
|
| 308 |
+
}
|
| 309 |
+
else {
|
| 310 |
+
if (x === x.parent.left) {
|
| 311 |
+
x = x.parent;
|
| 312 |
+
rightRotate(tree, x);
|
| 313 |
+
}
|
| 314 |
+
x.parent.color = 0 /* NodeColor.Black */;
|
| 315 |
+
x.parent.parent.color = 1 /* NodeColor.Red */;
|
| 316 |
+
leftRotate(tree, x.parent.parent);
|
| 317 |
+
}
|
| 318 |
+
}
|
| 319 |
+
}
|
| 320 |
+
tree.root.color = 0 /* NodeColor.Black */;
|
| 321 |
+
}
|
| 322 |
+
export function updateTreeMetadata(tree, x, delta, lineFeedCntDelta) {
|
| 323 |
+
// node length change or line feed count change
|
| 324 |
+
while (x !== tree.root && x !== SENTINEL) {
|
| 325 |
+
if (x.parent.left === x) {
|
| 326 |
+
x.parent.size_left += delta;
|
| 327 |
+
x.parent.lf_left += lineFeedCntDelta;
|
| 328 |
+
}
|
| 329 |
+
x = x.parent;
|
| 330 |
+
}
|
| 331 |
+
}
|
| 332 |
+
export function recomputeTreeMetadata(tree, x) {
|
| 333 |
+
let delta = 0;
|
| 334 |
+
let lf_delta = 0;
|
| 335 |
+
if (x === tree.root) {
|
| 336 |
+
return;
|
| 337 |
+
}
|
| 338 |
+
// go upwards till the node whose left subtree is changed.
|
| 339 |
+
while (x !== tree.root && x === x.parent.right) {
|
| 340 |
+
x = x.parent;
|
| 341 |
+
}
|
| 342 |
+
if (x === tree.root) {
|
| 343 |
+
// well, it means we add a node to the end (inorder)
|
| 344 |
+
return;
|
| 345 |
+
}
|
| 346 |
+
// x is the node whose right subtree is changed.
|
| 347 |
+
x = x.parent;
|
| 348 |
+
delta = calculateSize(x.left) - x.size_left;
|
| 349 |
+
lf_delta = calculateLF(x.left) - x.lf_left;
|
| 350 |
+
x.size_left += delta;
|
| 351 |
+
x.lf_left += lf_delta;
|
| 352 |
+
// go upwards till root. O(logN)
|
| 353 |
+
while (x !== tree.root && (delta !== 0 || lf_delta !== 0)) {
|
| 354 |
+
if (x.parent.left === x) {
|
| 355 |
+
x.parent.size_left += delta;
|
| 356 |
+
x.parent.lf_left += lf_delta;
|
| 357 |
+
}
|
| 358 |
+
x = x.parent;
|
| 359 |
+
}
|
| 360 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/prefixSumComputer.js
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { arrayInsert } from '../../../base/common/arrays.js';
|
| 6 |
+
import { toUint32 } from '../../../base/common/uint.js';
|
| 7 |
+
export class PrefixSumComputer {
|
| 8 |
+
constructor(values) {
|
| 9 |
+
this.values = values;
|
| 10 |
+
this.prefixSum = new Uint32Array(values.length);
|
| 11 |
+
this.prefixSumValidIndex = new Int32Array(1);
|
| 12 |
+
this.prefixSumValidIndex[0] = -1;
|
| 13 |
+
}
|
| 14 |
+
insertValues(insertIndex, insertValues) {
|
| 15 |
+
insertIndex = toUint32(insertIndex);
|
| 16 |
+
const oldValues = this.values;
|
| 17 |
+
const oldPrefixSum = this.prefixSum;
|
| 18 |
+
const insertValuesLen = insertValues.length;
|
| 19 |
+
if (insertValuesLen === 0) {
|
| 20 |
+
return false;
|
| 21 |
+
}
|
| 22 |
+
this.values = new Uint32Array(oldValues.length + insertValuesLen);
|
| 23 |
+
this.values.set(oldValues.subarray(0, insertIndex), 0);
|
| 24 |
+
this.values.set(oldValues.subarray(insertIndex), insertIndex + insertValuesLen);
|
| 25 |
+
this.values.set(insertValues, insertIndex);
|
| 26 |
+
if (insertIndex - 1 < this.prefixSumValidIndex[0]) {
|
| 27 |
+
this.prefixSumValidIndex[0] = insertIndex - 1;
|
| 28 |
+
}
|
| 29 |
+
this.prefixSum = new Uint32Array(this.values.length);
|
| 30 |
+
if (this.prefixSumValidIndex[0] >= 0) {
|
| 31 |
+
this.prefixSum.set(oldPrefixSum.subarray(0, this.prefixSumValidIndex[0] + 1));
|
| 32 |
+
}
|
| 33 |
+
return true;
|
| 34 |
+
}
|
| 35 |
+
setValue(index, value) {
|
| 36 |
+
index = toUint32(index);
|
| 37 |
+
value = toUint32(value);
|
| 38 |
+
if (this.values[index] === value) {
|
| 39 |
+
return false;
|
| 40 |
+
}
|
| 41 |
+
this.values[index] = value;
|
| 42 |
+
if (index - 1 < this.prefixSumValidIndex[0]) {
|
| 43 |
+
this.prefixSumValidIndex[0] = index - 1;
|
| 44 |
+
}
|
| 45 |
+
return true;
|
| 46 |
+
}
|
| 47 |
+
removeValues(startIndex, count) {
|
| 48 |
+
startIndex = toUint32(startIndex);
|
| 49 |
+
count = toUint32(count);
|
| 50 |
+
const oldValues = this.values;
|
| 51 |
+
const oldPrefixSum = this.prefixSum;
|
| 52 |
+
if (startIndex >= oldValues.length) {
|
| 53 |
+
return false;
|
| 54 |
+
}
|
| 55 |
+
const maxCount = oldValues.length - startIndex;
|
| 56 |
+
if (count >= maxCount) {
|
| 57 |
+
count = maxCount;
|
| 58 |
+
}
|
| 59 |
+
if (count === 0) {
|
| 60 |
+
return false;
|
| 61 |
+
}
|
| 62 |
+
this.values = new Uint32Array(oldValues.length - count);
|
| 63 |
+
this.values.set(oldValues.subarray(0, startIndex), 0);
|
| 64 |
+
this.values.set(oldValues.subarray(startIndex + count), startIndex);
|
| 65 |
+
this.prefixSum = new Uint32Array(this.values.length);
|
| 66 |
+
if (startIndex - 1 < this.prefixSumValidIndex[0]) {
|
| 67 |
+
this.prefixSumValidIndex[0] = startIndex - 1;
|
| 68 |
+
}
|
| 69 |
+
if (this.prefixSumValidIndex[0] >= 0) {
|
| 70 |
+
this.prefixSum.set(oldPrefixSum.subarray(0, this.prefixSumValidIndex[0] + 1));
|
| 71 |
+
}
|
| 72 |
+
return true;
|
| 73 |
+
}
|
| 74 |
+
getTotalSum() {
|
| 75 |
+
if (this.values.length === 0) {
|
| 76 |
+
return 0;
|
| 77 |
+
}
|
| 78 |
+
return this._getPrefixSum(this.values.length - 1);
|
| 79 |
+
}
|
| 80 |
+
/**
|
| 81 |
+
* Returns the sum of the first `index + 1` many items.
|
| 82 |
+
* @returns `SUM(0 <= j <= index, values[j])`.
|
| 83 |
+
*/
|
| 84 |
+
getPrefixSum(index) {
|
| 85 |
+
if (index < 0) {
|
| 86 |
+
return 0;
|
| 87 |
+
}
|
| 88 |
+
index = toUint32(index);
|
| 89 |
+
return this._getPrefixSum(index);
|
| 90 |
+
}
|
| 91 |
+
_getPrefixSum(index) {
|
| 92 |
+
if (index <= this.prefixSumValidIndex[0]) {
|
| 93 |
+
return this.prefixSum[index];
|
| 94 |
+
}
|
| 95 |
+
let startIndex = this.prefixSumValidIndex[0] + 1;
|
| 96 |
+
if (startIndex === 0) {
|
| 97 |
+
this.prefixSum[0] = this.values[0];
|
| 98 |
+
startIndex++;
|
| 99 |
+
}
|
| 100 |
+
if (index >= this.values.length) {
|
| 101 |
+
index = this.values.length - 1;
|
| 102 |
+
}
|
| 103 |
+
for (let i = startIndex; i <= index; i++) {
|
| 104 |
+
this.prefixSum[i] = this.prefixSum[i - 1] + this.values[i];
|
| 105 |
+
}
|
| 106 |
+
this.prefixSumValidIndex[0] = Math.max(this.prefixSumValidIndex[0], index);
|
| 107 |
+
return this.prefixSum[index];
|
| 108 |
+
}
|
| 109 |
+
getIndexOf(sum) {
|
| 110 |
+
sum = Math.floor(sum);
|
| 111 |
+
// Compute all sums (to get a fully valid prefixSum)
|
| 112 |
+
this.getTotalSum();
|
| 113 |
+
let low = 0;
|
| 114 |
+
let high = this.values.length - 1;
|
| 115 |
+
let mid = 0;
|
| 116 |
+
let midStop = 0;
|
| 117 |
+
let midStart = 0;
|
| 118 |
+
while (low <= high) {
|
| 119 |
+
mid = low + ((high - low) / 2) | 0;
|
| 120 |
+
midStop = this.prefixSum[mid];
|
| 121 |
+
midStart = midStop - this.values[mid];
|
| 122 |
+
if (sum < midStart) {
|
| 123 |
+
high = mid - 1;
|
| 124 |
+
}
|
| 125 |
+
else if (sum >= midStop) {
|
| 126 |
+
low = mid + 1;
|
| 127 |
+
}
|
| 128 |
+
else {
|
| 129 |
+
break;
|
| 130 |
+
}
|
| 131 |
+
}
|
| 132 |
+
return new PrefixSumIndexOfResult(mid, sum - midStart);
|
| 133 |
+
}
|
| 134 |
+
}
|
| 135 |
+
/**
|
| 136 |
+
* {@link getIndexOf} has an amortized runtime complexity of O(1).
|
| 137 |
+
*
|
| 138 |
+
* ({@link PrefixSumComputer.getIndexOf} is just O(log n))
|
| 139 |
+
*/
|
| 140 |
+
export class ConstantTimePrefixSumComputer {
|
| 141 |
+
constructor(values) {
|
| 142 |
+
this._values = values;
|
| 143 |
+
this._isValid = false;
|
| 144 |
+
this._validEndIndex = -1;
|
| 145 |
+
this._prefixSum = [];
|
| 146 |
+
this._indexBySum = [];
|
| 147 |
+
}
|
| 148 |
+
/**
|
| 149 |
+
* @returns SUM(0 <= j < values.length, values[j])
|
| 150 |
+
*/
|
| 151 |
+
getTotalSum() {
|
| 152 |
+
this._ensureValid();
|
| 153 |
+
return this._indexBySum.length;
|
| 154 |
+
}
|
| 155 |
+
/**
|
| 156 |
+
* Returns the sum of the first `count` many items.
|
| 157 |
+
* @returns `SUM(0 <= j < count, values[j])`.
|
| 158 |
+
*/
|
| 159 |
+
getPrefixSum(count) {
|
| 160 |
+
this._ensureValid();
|
| 161 |
+
if (count === 0) {
|
| 162 |
+
return 0;
|
| 163 |
+
}
|
| 164 |
+
return this._prefixSum[count - 1];
|
| 165 |
+
}
|
| 166 |
+
/**
|
| 167 |
+
* @returns `result`, such that `getPrefixSum(result.index) + result.remainder = sum`
|
| 168 |
+
*/
|
| 169 |
+
getIndexOf(sum) {
|
| 170 |
+
this._ensureValid();
|
| 171 |
+
const idx = this._indexBySum[sum];
|
| 172 |
+
const viewLinesAbove = idx > 0 ? this._prefixSum[idx - 1] : 0;
|
| 173 |
+
return new PrefixSumIndexOfResult(idx, sum - viewLinesAbove);
|
| 174 |
+
}
|
| 175 |
+
removeValues(start, deleteCount) {
|
| 176 |
+
this._values.splice(start, deleteCount);
|
| 177 |
+
this._invalidate(start);
|
| 178 |
+
}
|
| 179 |
+
insertValues(insertIndex, insertArr) {
|
| 180 |
+
this._values = arrayInsert(this._values, insertIndex, insertArr);
|
| 181 |
+
this._invalidate(insertIndex);
|
| 182 |
+
}
|
| 183 |
+
_invalidate(index) {
|
| 184 |
+
this._isValid = false;
|
| 185 |
+
this._validEndIndex = Math.min(this._validEndIndex, index - 1);
|
| 186 |
+
}
|
| 187 |
+
_ensureValid() {
|
| 188 |
+
if (this._isValid) {
|
| 189 |
+
return;
|
| 190 |
+
}
|
| 191 |
+
for (let i = this._validEndIndex + 1, len = this._values.length; i < len; i++) {
|
| 192 |
+
const value = this._values[i];
|
| 193 |
+
const sumAbove = i > 0 ? this._prefixSum[i - 1] : 0;
|
| 194 |
+
this._prefixSum[i] = sumAbove + value;
|
| 195 |
+
for (let j = 0; j < value; j++) {
|
| 196 |
+
this._indexBySum[sumAbove + j] = i;
|
| 197 |
+
}
|
| 198 |
+
}
|
| 199 |
+
// trim things
|
| 200 |
+
this._prefixSum.length = this._values.length;
|
| 201 |
+
this._indexBySum.length = this._prefixSum[this._prefixSum.length - 1];
|
| 202 |
+
// mark as valid
|
| 203 |
+
this._isValid = true;
|
| 204 |
+
this._validEndIndex = this._values.length - 1;
|
| 205 |
+
}
|
| 206 |
+
setValue(index, value) {
|
| 207 |
+
if (this._values[index] === value) {
|
| 208 |
+
// no change
|
| 209 |
+
return;
|
| 210 |
+
}
|
| 211 |
+
this._values[index] = value;
|
| 212 |
+
this._invalidate(index);
|
| 213 |
+
}
|
| 214 |
+
}
|
| 215 |
+
export class PrefixSumIndexOfResult {
|
| 216 |
+
constructor(index, remainder) {
|
| 217 |
+
this.index = index;
|
| 218 |
+
this.remainder = remainder;
|
| 219 |
+
this._prefixSumIndexOfResultBrand = undefined;
|
| 220 |
+
this.index = index;
|
| 221 |
+
this.remainder = remainder;
|
| 222 |
+
}
|
| 223 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/textModel.js
ADDED
|
@@ -0,0 +1,1899 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
| 6 |
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
| 7 |
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
| 8 |
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
| 9 |
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
| 10 |
+
};
|
| 11 |
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
| 12 |
+
return function (target, key) { decorator(target, key, paramIndex); }
|
| 13 |
+
};
|
| 14 |
+
var TextModel_1;
|
| 15 |
+
import { ArrayQueue, pushMany } from '../../../base/common/arrays.js';
|
| 16 |
+
import { Color } from '../../../base/common/color.js';
|
| 17 |
+
import { BugIndicatingError, illegalArgument, onUnexpectedError } from '../../../base/common/errors.js';
|
| 18 |
+
import { Emitter } from '../../../base/common/event.js';
|
| 19 |
+
import { Disposable, MutableDisposable, combinedDisposable } from '../../../base/common/lifecycle.js';
|
| 20 |
+
import * as strings from '../../../base/common/strings.js';
|
| 21 |
+
import { URI } from '../../../base/common/uri.js';
|
| 22 |
+
import { countEOL } from '../core/eolCounter.js';
|
| 23 |
+
import { normalizeIndentation } from '../core/indentation.js';
|
| 24 |
+
import { Position } from '../core/position.js';
|
| 25 |
+
import { Range } from '../core/range.js';
|
| 26 |
+
import { Selection } from '../core/selection.js';
|
| 27 |
+
import { EDITOR_MODEL_DEFAULTS } from '../core/textModelDefaults.js';
|
| 28 |
+
import { ILanguageService } from '../languages/language.js';
|
| 29 |
+
import { ILanguageConfigurationService } from '../languages/languageConfigurationRegistry.js';
|
| 30 |
+
import * as model from '../model.js';
|
| 31 |
+
import { BracketPairsTextModelPart } from './bracketPairsTextModelPart/bracketPairsImpl.js';
|
| 32 |
+
import { ColorizedBracketPairsDecorationProvider } from './bracketPairsTextModelPart/colorizedBracketPairsDecorationProvider.js';
|
| 33 |
+
import { EditStack } from './editStack.js';
|
| 34 |
+
import { GuidesTextModelPart } from './guidesTextModelPart.js';
|
| 35 |
+
import { guessIndentation } from './indentationGuesser.js';
|
| 36 |
+
import { IntervalNode, IntervalTree, recomputeMaxEnd } from './intervalTree.js';
|
| 37 |
+
import { PieceTreeTextBuffer } from './pieceTreeTextBuffer/pieceTreeTextBuffer.js';
|
| 38 |
+
import { PieceTreeTextBufferBuilder } from './pieceTreeTextBuffer/pieceTreeTextBufferBuilder.js';
|
| 39 |
+
import { SearchParams, TextModelSearch } from './textModelSearch.js';
|
| 40 |
+
import { TokenizationTextModelPart } from './tokenizationTextModelPart.js';
|
| 41 |
+
import { AttachedViews } from './tokens.js';
|
| 42 |
+
import { InternalModelContentChangeEvent, LineInjectedText, ModelInjectedTextChangedEvent, ModelRawContentChangedEvent, ModelRawEOLChanged, ModelRawFlush, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from '../textModelEvents.js';
|
| 43 |
+
import { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';
|
| 44 |
+
import { IUndoRedoService } from '../../../platform/undoRedo/common/undoRedo.js';
|
| 45 |
+
export function createTextBufferFactory(text) {
|
| 46 |
+
const builder = new PieceTreeTextBufferBuilder();
|
| 47 |
+
builder.acceptChunk(text);
|
| 48 |
+
return builder.finish();
|
| 49 |
+
}
|
| 50 |
+
export function createTextBufferFactoryFromSnapshot(snapshot) {
|
| 51 |
+
const builder = new PieceTreeTextBufferBuilder();
|
| 52 |
+
let chunk;
|
| 53 |
+
while (typeof (chunk = snapshot.read()) === 'string') {
|
| 54 |
+
builder.acceptChunk(chunk);
|
| 55 |
+
}
|
| 56 |
+
return builder.finish();
|
| 57 |
+
}
|
| 58 |
+
export function createTextBuffer(value, defaultEOL) {
|
| 59 |
+
let factory;
|
| 60 |
+
if (typeof value === 'string') {
|
| 61 |
+
factory = createTextBufferFactory(value);
|
| 62 |
+
}
|
| 63 |
+
else if (model.isITextSnapshot(value)) {
|
| 64 |
+
factory = createTextBufferFactoryFromSnapshot(value);
|
| 65 |
+
}
|
| 66 |
+
else {
|
| 67 |
+
factory = value;
|
| 68 |
+
}
|
| 69 |
+
return factory.create(defaultEOL);
|
| 70 |
+
}
|
| 71 |
+
let MODEL_ID = 0;
|
| 72 |
+
const LIMIT_FIND_COUNT = 999;
|
| 73 |
+
const LONG_LINE_BOUNDARY = 10000;
|
| 74 |
+
class TextModelSnapshot {
|
| 75 |
+
constructor(source) {
|
| 76 |
+
this._source = source;
|
| 77 |
+
this._eos = false;
|
| 78 |
+
}
|
| 79 |
+
read() {
|
| 80 |
+
if (this._eos) {
|
| 81 |
+
return null;
|
| 82 |
+
}
|
| 83 |
+
const result = [];
|
| 84 |
+
let resultCnt = 0;
|
| 85 |
+
let resultLength = 0;
|
| 86 |
+
do {
|
| 87 |
+
const tmp = this._source.read();
|
| 88 |
+
if (tmp === null) {
|
| 89 |
+
// end-of-stream
|
| 90 |
+
this._eos = true;
|
| 91 |
+
if (resultCnt === 0) {
|
| 92 |
+
return null;
|
| 93 |
+
}
|
| 94 |
+
else {
|
| 95 |
+
return result.join('');
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
if (tmp.length > 0) {
|
| 99 |
+
result[resultCnt++] = tmp;
|
| 100 |
+
resultLength += tmp.length;
|
| 101 |
+
}
|
| 102 |
+
if (resultLength >= 64 * 1024) {
|
| 103 |
+
return result.join('');
|
| 104 |
+
}
|
| 105 |
+
} while (true);
|
| 106 |
+
}
|
| 107 |
+
}
|
| 108 |
+
const invalidFunc = () => { throw new Error(`Invalid change accessor`); };
|
| 109 |
+
let TextModel = class TextModel extends Disposable {
|
| 110 |
+
static { TextModel_1 = this; }
|
| 111 |
+
static { this._MODEL_SYNC_LIMIT = 50 * 1024 * 1024; } // 50 MB, // used in tests
|
| 112 |
+
static { this.LARGE_FILE_SIZE_THRESHOLD = 20 * 1024 * 1024; } // 20 MB;
|
| 113 |
+
static { this.LARGE_FILE_LINE_COUNT_THRESHOLD = 300 * 1000; } // 300K lines
|
| 114 |
+
static { this.LARGE_FILE_HEAP_OPERATION_THRESHOLD = 256 * 1024 * 1024; } // 256M characters, usually ~> 512MB memory usage
|
| 115 |
+
static { this.DEFAULT_CREATION_OPTIONS = {
|
| 116 |
+
isForSimpleWidget: false,
|
| 117 |
+
tabSize: EDITOR_MODEL_DEFAULTS.tabSize,
|
| 118 |
+
indentSize: EDITOR_MODEL_DEFAULTS.indentSize,
|
| 119 |
+
insertSpaces: EDITOR_MODEL_DEFAULTS.insertSpaces,
|
| 120 |
+
detectIndentation: false,
|
| 121 |
+
defaultEOL: 1 /* model.DefaultEndOfLine.LF */,
|
| 122 |
+
trimAutoWhitespace: EDITOR_MODEL_DEFAULTS.trimAutoWhitespace,
|
| 123 |
+
largeFileOptimizations: EDITOR_MODEL_DEFAULTS.largeFileOptimizations,
|
| 124 |
+
bracketPairColorizationOptions: EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions,
|
| 125 |
+
}; }
|
| 126 |
+
static resolveOptions(textBuffer, options) {
|
| 127 |
+
if (options.detectIndentation) {
|
| 128 |
+
const guessedIndentation = guessIndentation(textBuffer, options.tabSize, options.insertSpaces);
|
| 129 |
+
return new model.TextModelResolvedOptions({
|
| 130 |
+
tabSize: guessedIndentation.tabSize,
|
| 131 |
+
indentSize: 'tabSize', // TODO@Alex: guess indentSize independent of tabSize
|
| 132 |
+
insertSpaces: guessedIndentation.insertSpaces,
|
| 133 |
+
trimAutoWhitespace: options.trimAutoWhitespace,
|
| 134 |
+
defaultEOL: options.defaultEOL,
|
| 135 |
+
bracketPairColorizationOptions: options.bracketPairColorizationOptions,
|
| 136 |
+
});
|
| 137 |
+
}
|
| 138 |
+
return new model.TextModelResolvedOptions(options);
|
| 139 |
+
}
|
| 140 |
+
get onDidChangeLanguage() { return this._tokenizationTextModelPart.onDidChangeLanguage; }
|
| 141 |
+
get onDidChangeLanguageConfiguration() { return this._tokenizationTextModelPart.onDidChangeLanguageConfiguration; }
|
| 142 |
+
get onDidChangeTokens() { return this._tokenizationTextModelPart.onDidChangeTokens; }
|
| 143 |
+
onDidChangeContent(listener) {
|
| 144 |
+
return this._eventEmitter.slowEvent((e) => listener(e.contentChangedEvent));
|
| 145 |
+
}
|
| 146 |
+
onDidChangeContentOrInjectedText(listener) {
|
| 147 |
+
return combinedDisposable(this._eventEmitter.fastEvent(e => listener(e)), this._onDidChangeInjectedText.event(e => listener(e)));
|
| 148 |
+
}
|
| 149 |
+
_isDisposing() { return this.__isDisposing; }
|
| 150 |
+
get tokenization() { return this._tokenizationTextModelPart; }
|
| 151 |
+
get bracketPairs() { return this._bracketPairs; }
|
| 152 |
+
get guides() { return this._guidesTextModelPart; }
|
| 153 |
+
constructor(source, languageIdOrSelection, creationOptions, associatedResource = null, _undoRedoService, _languageService, _languageConfigurationService, instantiationService) {
|
| 154 |
+
super();
|
| 155 |
+
this._undoRedoService = _undoRedoService;
|
| 156 |
+
this._languageService = _languageService;
|
| 157 |
+
this._languageConfigurationService = _languageConfigurationService;
|
| 158 |
+
this.instantiationService = instantiationService;
|
| 159 |
+
//#region Events
|
| 160 |
+
this._onWillDispose = this._register(new Emitter());
|
| 161 |
+
this.onWillDispose = this._onWillDispose.event;
|
| 162 |
+
this._onDidChangeDecorations = this._register(new DidChangeDecorationsEmitter(affectedInjectedTextLines => this.handleBeforeFireDecorationsChangedEvent(affectedInjectedTextLines)));
|
| 163 |
+
this.onDidChangeDecorations = this._onDidChangeDecorations.event;
|
| 164 |
+
this._onDidChangeOptions = this._register(new Emitter());
|
| 165 |
+
this.onDidChangeOptions = this._onDidChangeOptions.event;
|
| 166 |
+
this._onDidChangeAttached = this._register(new Emitter());
|
| 167 |
+
this.onDidChangeAttached = this._onDidChangeAttached.event;
|
| 168 |
+
this._onDidChangeInjectedText = this._register(new Emitter());
|
| 169 |
+
this._eventEmitter = this._register(new DidChangeContentEmitter());
|
| 170 |
+
this._languageSelectionListener = this._register(new MutableDisposable());
|
| 171 |
+
this._deltaDecorationCallCnt = 0;
|
| 172 |
+
this._attachedViews = new AttachedViews();
|
| 173 |
+
// Generate a new unique model id
|
| 174 |
+
MODEL_ID++;
|
| 175 |
+
this.id = '$model' + MODEL_ID;
|
| 176 |
+
this.isForSimpleWidget = creationOptions.isForSimpleWidget;
|
| 177 |
+
if (typeof associatedResource === 'undefined' || associatedResource === null) {
|
| 178 |
+
this._associatedResource = URI.parse('inmemory://model/' + MODEL_ID);
|
| 179 |
+
}
|
| 180 |
+
else {
|
| 181 |
+
this._associatedResource = associatedResource;
|
| 182 |
+
}
|
| 183 |
+
this._attachedEditorCount = 0;
|
| 184 |
+
const { textBuffer, disposable } = createTextBuffer(source, creationOptions.defaultEOL);
|
| 185 |
+
this._buffer = textBuffer;
|
| 186 |
+
this._bufferDisposable = disposable;
|
| 187 |
+
this._options = TextModel_1.resolveOptions(this._buffer, creationOptions);
|
| 188 |
+
const languageId = (typeof languageIdOrSelection === 'string' ? languageIdOrSelection : languageIdOrSelection.languageId);
|
| 189 |
+
if (typeof languageIdOrSelection !== 'string') {
|
| 190 |
+
this._languageSelectionListener.value = languageIdOrSelection.onDidChange(() => this._setLanguage(languageIdOrSelection.languageId));
|
| 191 |
+
}
|
| 192 |
+
this._bracketPairs = this._register(new BracketPairsTextModelPart(this, this._languageConfigurationService));
|
| 193 |
+
this._guidesTextModelPart = this._register(new GuidesTextModelPart(this, this._languageConfigurationService));
|
| 194 |
+
this._decorationProvider = this._register(new ColorizedBracketPairsDecorationProvider(this));
|
| 195 |
+
this._tokenizationTextModelPart = this.instantiationService.createInstance(TokenizationTextModelPart, this, this._bracketPairs, languageId, this._attachedViews);
|
| 196 |
+
const bufferLineCount = this._buffer.getLineCount();
|
| 197 |
+
const bufferTextLength = this._buffer.getValueLengthInRange(new Range(1, 1, bufferLineCount, this._buffer.getLineLength(bufferLineCount) + 1), 0 /* model.EndOfLinePreference.TextDefined */);
|
| 198 |
+
// !!! Make a decision in the ctor and permanently respect this decision !!!
|
| 199 |
+
// If a model is too large at construction time, it will never get tokenized,
|
| 200 |
+
// under no circumstances.
|
| 201 |
+
if (creationOptions.largeFileOptimizations) {
|
| 202 |
+
this._isTooLargeForTokenization = ((bufferTextLength > TextModel_1.LARGE_FILE_SIZE_THRESHOLD)
|
| 203 |
+
|| (bufferLineCount > TextModel_1.LARGE_FILE_LINE_COUNT_THRESHOLD));
|
| 204 |
+
this._isTooLargeForHeapOperation = bufferTextLength > TextModel_1.LARGE_FILE_HEAP_OPERATION_THRESHOLD;
|
| 205 |
+
}
|
| 206 |
+
else {
|
| 207 |
+
this._isTooLargeForTokenization = false;
|
| 208 |
+
this._isTooLargeForHeapOperation = false;
|
| 209 |
+
}
|
| 210 |
+
this._isTooLargeForSyncing = (bufferTextLength > TextModel_1._MODEL_SYNC_LIMIT);
|
| 211 |
+
this._versionId = 1;
|
| 212 |
+
this._alternativeVersionId = 1;
|
| 213 |
+
this._initialUndoRedoSnapshot = null;
|
| 214 |
+
this._isDisposed = false;
|
| 215 |
+
this.__isDisposing = false;
|
| 216 |
+
this._instanceId = strings.singleLetterHash(MODEL_ID);
|
| 217 |
+
this._lastDecorationId = 0;
|
| 218 |
+
this._decorations = Object.create(null);
|
| 219 |
+
this._decorationsTree = new DecorationsTrees();
|
| 220 |
+
this._commandManager = new EditStack(this, this._undoRedoService);
|
| 221 |
+
this._isUndoing = false;
|
| 222 |
+
this._isRedoing = false;
|
| 223 |
+
this._trimAutoWhitespaceLines = null;
|
| 224 |
+
this._register(this._decorationProvider.onDidChange(() => {
|
| 225 |
+
this._onDidChangeDecorations.beginDeferredEmit();
|
| 226 |
+
this._onDidChangeDecorations.fire();
|
| 227 |
+
this._onDidChangeDecorations.endDeferredEmit();
|
| 228 |
+
}));
|
| 229 |
+
this._languageService.requestRichLanguageFeatures(languageId);
|
| 230 |
+
this._register(this._languageConfigurationService.onDidChange(e => {
|
| 231 |
+
this._bracketPairs.handleLanguageConfigurationServiceChange(e);
|
| 232 |
+
this._tokenizationTextModelPart.handleLanguageConfigurationServiceChange(e);
|
| 233 |
+
}));
|
| 234 |
+
}
|
| 235 |
+
dispose() {
|
| 236 |
+
this.__isDisposing = true;
|
| 237 |
+
this._onWillDispose.fire();
|
| 238 |
+
this._tokenizationTextModelPart.dispose();
|
| 239 |
+
this._isDisposed = true;
|
| 240 |
+
super.dispose();
|
| 241 |
+
this._bufferDisposable.dispose();
|
| 242 |
+
this.__isDisposing = false;
|
| 243 |
+
// Manually release reference to previous text buffer to avoid large leaks
|
| 244 |
+
// in case someone leaks a TextModel reference
|
| 245 |
+
const emptyDisposedTextBuffer = new PieceTreeTextBuffer([], '', '\n', false, false, true, true);
|
| 246 |
+
emptyDisposedTextBuffer.dispose();
|
| 247 |
+
this._buffer = emptyDisposedTextBuffer;
|
| 248 |
+
this._bufferDisposable = Disposable.None;
|
| 249 |
+
}
|
| 250 |
+
_assertNotDisposed() {
|
| 251 |
+
if (this._isDisposed) {
|
| 252 |
+
throw new BugIndicatingError('Model is disposed!');
|
| 253 |
+
}
|
| 254 |
+
}
|
| 255 |
+
_emitContentChangedEvent(rawChange, change) {
|
| 256 |
+
if (this.__isDisposing) {
|
| 257 |
+
// Do not confuse listeners by emitting any event after disposing
|
| 258 |
+
return;
|
| 259 |
+
}
|
| 260 |
+
this._tokenizationTextModelPart.handleDidChangeContent(change);
|
| 261 |
+
this._bracketPairs.handleDidChangeContent(change);
|
| 262 |
+
this._eventEmitter.fire(new InternalModelContentChangeEvent(rawChange, change));
|
| 263 |
+
}
|
| 264 |
+
setValue(value) {
|
| 265 |
+
this._assertNotDisposed();
|
| 266 |
+
if (value === null || value === undefined) {
|
| 267 |
+
throw illegalArgument();
|
| 268 |
+
}
|
| 269 |
+
const { textBuffer, disposable } = createTextBuffer(value, this._options.defaultEOL);
|
| 270 |
+
this._setValueFromTextBuffer(textBuffer, disposable);
|
| 271 |
+
}
|
| 272 |
+
_createContentChanged2(range, rangeOffset, rangeLength, text, isUndoing, isRedoing, isFlush, isEolChange) {
|
| 273 |
+
return {
|
| 274 |
+
changes: [{
|
| 275 |
+
range: range,
|
| 276 |
+
rangeOffset: rangeOffset,
|
| 277 |
+
rangeLength: rangeLength,
|
| 278 |
+
text: text,
|
| 279 |
+
}],
|
| 280 |
+
eol: this._buffer.getEOL(),
|
| 281 |
+
isEolChange: isEolChange,
|
| 282 |
+
versionId: this.getVersionId(),
|
| 283 |
+
isUndoing: isUndoing,
|
| 284 |
+
isRedoing: isRedoing,
|
| 285 |
+
isFlush: isFlush
|
| 286 |
+
};
|
| 287 |
+
}
|
| 288 |
+
_setValueFromTextBuffer(textBuffer, textBufferDisposable) {
|
| 289 |
+
this._assertNotDisposed();
|
| 290 |
+
const oldFullModelRange = this.getFullModelRange();
|
| 291 |
+
const oldModelValueLength = this.getValueLengthInRange(oldFullModelRange);
|
| 292 |
+
const endLineNumber = this.getLineCount();
|
| 293 |
+
const endColumn = this.getLineMaxColumn(endLineNumber);
|
| 294 |
+
this._buffer = textBuffer;
|
| 295 |
+
this._bufferDisposable.dispose();
|
| 296 |
+
this._bufferDisposable = textBufferDisposable;
|
| 297 |
+
this._increaseVersionId();
|
| 298 |
+
// Destroy all my decorations
|
| 299 |
+
this._decorations = Object.create(null);
|
| 300 |
+
this._decorationsTree = new DecorationsTrees();
|
| 301 |
+
// Destroy my edit history and settings
|
| 302 |
+
this._commandManager.clear();
|
| 303 |
+
this._trimAutoWhitespaceLines = null;
|
| 304 |
+
this._emitContentChangedEvent(new ModelRawContentChangedEvent([
|
| 305 |
+
new ModelRawFlush()
|
| 306 |
+
], this._versionId, false, false), this._createContentChanged2(new Range(1, 1, endLineNumber, endColumn), 0, oldModelValueLength, this.getValue(), false, false, true, false));
|
| 307 |
+
}
|
| 308 |
+
setEOL(eol) {
|
| 309 |
+
this._assertNotDisposed();
|
| 310 |
+
const newEOL = (eol === 1 /* model.EndOfLineSequence.CRLF */ ? '\r\n' : '\n');
|
| 311 |
+
if (this._buffer.getEOL() === newEOL) {
|
| 312 |
+
// Nothing to do
|
| 313 |
+
return;
|
| 314 |
+
}
|
| 315 |
+
const oldFullModelRange = this.getFullModelRange();
|
| 316 |
+
const oldModelValueLength = this.getValueLengthInRange(oldFullModelRange);
|
| 317 |
+
const endLineNumber = this.getLineCount();
|
| 318 |
+
const endColumn = this.getLineMaxColumn(endLineNumber);
|
| 319 |
+
this._onBeforeEOLChange();
|
| 320 |
+
this._buffer.setEOL(newEOL);
|
| 321 |
+
this._increaseVersionId();
|
| 322 |
+
this._onAfterEOLChange();
|
| 323 |
+
this._emitContentChangedEvent(new ModelRawContentChangedEvent([
|
| 324 |
+
new ModelRawEOLChanged()
|
| 325 |
+
], this._versionId, false, false), this._createContentChanged2(new Range(1, 1, endLineNumber, endColumn), 0, oldModelValueLength, this.getValue(), false, false, false, true));
|
| 326 |
+
}
|
| 327 |
+
_onBeforeEOLChange() {
|
| 328 |
+
// Ensure all decorations get their `range` set.
|
| 329 |
+
this._decorationsTree.ensureAllNodesHaveRanges(this);
|
| 330 |
+
}
|
| 331 |
+
_onAfterEOLChange() {
|
| 332 |
+
// Transform back `range` to offsets
|
| 333 |
+
const versionId = this.getVersionId();
|
| 334 |
+
const allDecorations = this._decorationsTree.collectNodesPostOrder();
|
| 335 |
+
for (let i = 0, len = allDecorations.length; i < len; i++) {
|
| 336 |
+
const node = allDecorations[i];
|
| 337 |
+
const range = node.range; // the range is defined due to `_onBeforeEOLChange`
|
| 338 |
+
const delta = node.cachedAbsoluteStart - node.start;
|
| 339 |
+
const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);
|
| 340 |
+
const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);
|
| 341 |
+
node.cachedAbsoluteStart = startOffset;
|
| 342 |
+
node.cachedAbsoluteEnd = endOffset;
|
| 343 |
+
node.cachedVersionId = versionId;
|
| 344 |
+
node.start = startOffset - delta;
|
| 345 |
+
node.end = endOffset - delta;
|
| 346 |
+
recomputeMaxEnd(node);
|
| 347 |
+
}
|
| 348 |
+
}
|
| 349 |
+
onBeforeAttached() {
|
| 350 |
+
this._attachedEditorCount++;
|
| 351 |
+
if (this._attachedEditorCount === 1) {
|
| 352 |
+
this._tokenizationTextModelPart.handleDidChangeAttached();
|
| 353 |
+
this._onDidChangeAttached.fire(undefined);
|
| 354 |
+
}
|
| 355 |
+
return this._attachedViews.attachView();
|
| 356 |
+
}
|
| 357 |
+
onBeforeDetached(view) {
|
| 358 |
+
this._attachedEditorCount--;
|
| 359 |
+
if (this._attachedEditorCount === 0) {
|
| 360 |
+
this._tokenizationTextModelPart.handleDidChangeAttached();
|
| 361 |
+
this._onDidChangeAttached.fire(undefined);
|
| 362 |
+
}
|
| 363 |
+
this._attachedViews.detachView(view);
|
| 364 |
+
}
|
| 365 |
+
isAttachedToEditor() {
|
| 366 |
+
return this._attachedEditorCount > 0;
|
| 367 |
+
}
|
| 368 |
+
getAttachedEditorCount() {
|
| 369 |
+
return this._attachedEditorCount;
|
| 370 |
+
}
|
| 371 |
+
isTooLargeForSyncing() {
|
| 372 |
+
return this._isTooLargeForSyncing;
|
| 373 |
+
}
|
| 374 |
+
isTooLargeForTokenization() {
|
| 375 |
+
return this._isTooLargeForTokenization;
|
| 376 |
+
}
|
| 377 |
+
isTooLargeForHeapOperation() {
|
| 378 |
+
return this._isTooLargeForHeapOperation;
|
| 379 |
+
}
|
| 380 |
+
isDisposed() {
|
| 381 |
+
return this._isDisposed;
|
| 382 |
+
}
|
| 383 |
+
isDominatedByLongLines() {
|
| 384 |
+
this._assertNotDisposed();
|
| 385 |
+
if (this.isTooLargeForTokenization()) {
|
| 386 |
+
// Cannot word wrap huge files anyways, so it doesn't really matter
|
| 387 |
+
return false;
|
| 388 |
+
}
|
| 389 |
+
let smallLineCharCount = 0;
|
| 390 |
+
let longLineCharCount = 0;
|
| 391 |
+
const lineCount = this._buffer.getLineCount();
|
| 392 |
+
for (let lineNumber = 1; lineNumber <= lineCount; lineNumber++) {
|
| 393 |
+
const lineLength = this._buffer.getLineLength(lineNumber);
|
| 394 |
+
if (lineLength >= LONG_LINE_BOUNDARY) {
|
| 395 |
+
longLineCharCount += lineLength;
|
| 396 |
+
}
|
| 397 |
+
else {
|
| 398 |
+
smallLineCharCount += lineLength;
|
| 399 |
+
}
|
| 400 |
+
}
|
| 401 |
+
return (longLineCharCount > smallLineCharCount);
|
| 402 |
+
}
|
| 403 |
+
get uri() {
|
| 404 |
+
return this._associatedResource;
|
| 405 |
+
}
|
| 406 |
+
//#region Options
|
| 407 |
+
getOptions() {
|
| 408 |
+
this._assertNotDisposed();
|
| 409 |
+
return this._options;
|
| 410 |
+
}
|
| 411 |
+
getFormattingOptions() {
|
| 412 |
+
return {
|
| 413 |
+
tabSize: this._options.indentSize,
|
| 414 |
+
insertSpaces: this._options.insertSpaces
|
| 415 |
+
};
|
| 416 |
+
}
|
| 417 |
+
updateOptions(_newOpts) {
|
| 418 |
+
this._assertNotDisposed();
|
| 419 |
+
const tabSize = (typeof _newOpts.tabSize !== 'undefined') ? _newOpts.tabSize : this._options.tabSize;
|
| 420 |
+
const indentSize = (typeof _newOpts.indentSize !== 'undefined') ? _newOpts.indentSize : this._options.originalIndentSize;
|
| 421 |
+
const insertSpaces = (typeof _newOpts.insertSpaces !== 'undefined') ? _newOpts.insertSpaces : this._options.insertSpaces;
|
| 422 |
+
const trimAutoWhitespace = (typeof _newOpts.trimAutoWhitespace !== 'undefined') ? _newOpts.trimAutoWhitespace : this._options.trimAutoWhitespace;
|
| 423 |
+
const bracketPairColorizationOptions = (typeof _newOpts.bracketColorizationOptions !== 'undefined') ? _newOpts.bracketColorizationOptions : this._options.bracketPairColorizationOptions;
|
| 424 |
+
const newOpts = new model.TextModelResolvedOptions({
|
| 425 |
+
tabSize: tabSize,
|
| 426 |
+
indentSize: indentSize,
|
| 427 |
+
insertSpaces: insertSpaces,
|
| 428 |
+
defaultEOL: this._options.defaultEOL,
|
| 429 |
+
trimAutoWhitespace: trimAutoWhitespace,
|
| 430 |
+
bracketPairColorizationOptions,
|
| 431 |
+
});
|
| 432 |
+
if (this._options.equals(newOpts)) {
|
| 433 |
+
return;
|
| 434 |
+
}
|
| 435 |
+
const e = this._options.createChangeEvent(newOpts);
|
| 436 |
+
this._options = newOpts;
|
| 437 |
+
this._bracketPairs.handleDidChangeOptions(e);
|
| 438 |
+
this._decorationProvider.handleDidChangeOptions(e);
|
| 439 |
+
this._onDidChangeOptions.fire(e);
|
| 440 |
+
}
|
| 441 |
+
detectIndentation(defaultInsertSpaces, defaultTabSize) {
|
| 442 |
+
this._assertNotDisposed();
|
| 443 |
+
const guessedIndentation = guessIndentation(this._buffer, defaultTabSize, defaultInsertSpaces);
|
| 444 |
+
this.updateOptions({
|
| 445 |
+
insertSpaces: guessedIndentation.insertSpaces,
|
| 446 |
+
tabSize: guessedIndentation.tabSize,
|
| 447 |
+
indentSize: guessedIndentation.tabSize, // TODO@Alex: guess indentSize independent of tabSize
|
| 448 |
+
});
|
| 449 |
+
}
|
| 450 |
+
normalizeIndentation(str) {
|
| 451 |
+
this._assertNotDisposed();
|
| 452 |
+
return normalizeIndentation(str, this._options.indentSize, this._options.insertSpaces);
|
| 453 |
+
}
|
| 454 |
+
//#endregion
|
| 455 |
+
//#region Reading
|
| 456 |
+
getVersionId() {
|
| 457 |
+
this._assertNotDisposed();
|
| 458 |
+
return this._versionId;
|
| 459 |
+
}
|
| 460 |
+
mightContainRTL() {
|
| 461 |
+
return this._buffer.mightContainRTL();
|
| 462 |
+
}
|
| 463 |
+
mightContainUnusualLineTerminators() {
|
| 464 |
+
return this._buffer.mightContainUnusualLineTerminators();
|
| 465 |
+
}
|
| 466 |
+
removeUnusualLineTerminators(selections = null) {
|
| 467 |
+
const matches = this.findMatches(strings.UNUSUAL_LINE_TERMINATORS.source, false, true, false, null, false, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */);
|
| 468 |
+
this._buffer.resetMightContainUnusualLineTerminators();
|
| 469 |
+
this.pushEditOperations(selections, matches.map(m => ({ range: m.range, text: null })), () => null);
|
| 470 |
+
}
|
| 471 |
+
mightContainNonBasicASCII() {
|
| 472 |
+
return this._buffer.mightContainNonBasicASCII();
|
| 473 |
+
}
|
| 474 |
+
getAlternativeVersionId() {
|
| 475 |
+
this._assertNotDisposed();
|
| 476 |
+
return this._alternativeVersionId;
|
| 477 |
+
}
|
| 478 |
+
getInitialUndoRedoSnapshot() {
|
| 479 |
+
this._assertNotDisposed();
|
| 480 |
+
return this._initialUndoRedoSnapshot;
|
| 481 |
+
}
|
| 482 |
+
getOffsetAt(rawPosition) {
|
| 483 |
+
this._assertNotDisposed();
|
| 484 |
+
const position = this._validatePosition(rawPosition.lineNumber, rawPosition.column, 0 /* StringOffsetValidationType.Relaxed */);
|
| 485 |
+
return this._buffer.getOffsetAt(position.lineNumber, position.column);
|
| 486 |
+
}
|
| 487 |
+
getPositionAt(rawOffset) {
|
| 488 |
+
this._assertNotDisposed();
|
| 489 |
+
const offset = (Math.min(this._buffer.getLength(), Math.max(0, rawOffset)));
|
| 490 |
+
return this._buffer.getPositionAt(offset);
|
| 491 |
+
}
|
| 492 |
+
_increaseVersionId() {
|
| 493 |
+
this._versionId = this._versionId + 1;
|
| 494 |
+
this._alternativeVersionId = this._versionId;
|
| 495 |
+
}
|
| 496 |
+
_overwriteVersionId(versionId) {
|
| 497 |
+
this._versionId = versionId;
|
| 498 |
+
}
|
| 499 |
+
_overwriteAlternativeVersionId(newAlternativeVersionId) {
|
| 500 |
+
this._alternativeVersionId = newAlternativeVersionId;
|
| 501 |
+
}
|
| 502 |
+
_overwriteInitialUndoRedoSnapshot(newInitialUndoRedoSnapshot) {
|
| 503 |
+
this._initialUndoRedoSnapshot = newInitialUndoRedoSnapshot;
|
| 504 |
+
}
|
| 505 |
+
getValue(eol, preserveBOM = false) {
|
| 506 |
+
this._assertNotDisposed();
|
| 507 |
+
if (this.isTooLargeForHeapOperation()) {
|
| 508 |
+
throw new BugIndicatingError('Operation would exceed heap memory limits');
|
| 509 |
+
}
|
| 510 |
+
const fullModelRange = this.getFullModelRange();
|
| 511 |
+
const fullModelValue = this.getValueInRange(fullModelRange, eol);
|
| 512 |
+
if (preserveBOM) {
|
| 513 |
+
return this._buffer.getBOM() + fullModelValue;
|
| 514 |
+
}
|
| 515 |
+
return fullModelValue;
|
| 516 |
+
}
|
| 517 |
+
createSnapshot(preserveBOM = false) {
|
| 518 |
+
return new TextModelSnapshot(this._buffer.createSnapshot(preserveBOM));
|
| 519 |
+
}
|
| 520 |
+
getValueLength(eol, preserveBOM = false) {
|
| 521 |
+
this._assertNotDisposed();
|
| 522 |
+
const fullModelRange = this.getFullModelRange();
|
| 523 |
+
const fullModelValue = this.getValueLengthInRange(fullModelRange, eol);
|
| 524 |
+
if (preserveBOM) {
|
| 525 |
+
return this._buffer.getBOM().length + fullModelValue;
|
| 526 |
+
}
|
| 527 |
+
return fullModelValue;
|
| 528 |
+
}
|
| 529 |
+
getValueInRange(rawRange, eol = 0 /* model.EndOfLinePreference.TextDefined */) {
|
| 530 |
+
this._assertNotDisposed();
|
| 531 |
+
return this._buffer.getValueInRange(this.validateRange(rawRange), eol);
|
| 532 |
+
}
|
| 533 |
+
getValueLengthInRange(rawRange, eol = 0 /* model.EndOfLinePreference.TextDefined */) {
|
| 534 |
+
this._assertNotDisposed();
|
| 535 |
+
return this._buffer.getValueLengthInRange(this.validateRange(rawRange), eol);
|
| 536 |
+
}
|
| 537 |
+
getCharacterCountInRange(rawRange, eol = 0 /* model.EndOfLinePreference.TextDefined */) {
|
| 538 |
+
this._assertNotDisposed();
|
| 539 |
+
return this._buffer.getCharacterCountInRange(this.validateRange(rawRange), eol);
|
| 540 |
+
}
|
| 541 |
+
getLineCount() {
|
| 542 |
+
this._assertNotDisposed();
|
| 543 |
+
return this._buffer.getLineCount();
|
| 544 |
+
}
|
| 545 |
+
getLineContent(lineNumber) {
|
| 546 |
+
this._assertNotDisposed();
|
| 547 |
+
if (lineNumber < 1 || lineNumber > this.getLineCount()) {
|
| 548 |
+
throw new BugIndicatingError('Illegal value for lineNumber');
|
| 549 |
+
}
|
| 550 |
+
return this._buffer.getLineContent(lineNumber);
|
| 551 |
+
}
|
| 552 |
+
getLineLength(lineNumber) {
|
| 553 |
+
this._assertNotDisposed();
|
| 554 |
+
if (lineNumber < 1 || lineNumber > this.getLineCount()) {
|
| 555 |
+
throw new BugIndicatingError('Illegal value for lineNumber');
|
| 556 |
+
}
|
| 557 |
+
return this._buffer.getLineLength(lineNumber);
|
| 558 |
+
}
|
| 559 |
+
getLinesContent() {
|
| 560 |
+
this._assertNotDisposed();
|
| 561 |
+
if (this.isTooLargeForHeapOperation()) {
|
| 562 |
+
throw new BugIndicatingError('Operation would exceed heap memory limits');
|
| 563 |
+
}
|
| 564 |
+
return this._buffer.getLinesContent();
|
| 565 |
+
}
|
| 566 |
+
getEOL() {
|
| 567 |
+
this._assertNotDisposed();
|
| 568 |
+
return this._buffer.getEOL();
|
| 569 |
+
}
|
| 570 |
+
getEndOfLineSequence() {
|
| 571 |
+
this._assertNotDisposed();
|
| 572 |
+
return (this._buffer.getEOL() === '\n'
|
| 573 |
+
? 0 /* model.EndOfLineSequence.LF */
|
| 574 |
+
: 1 /* model.EndOfLineSequence.CRLF */);
|
| 575 |
+
}
|
| 576 |
+
getLineMinColumn(lineNumber) {
|
| 577 |
+
this._assertNotDisposed();
|
| 578 |
+
return 1;
|
| 579 |
+
}
|
| 580 |
+
getLineMaxColumn(lineNumber) {
|
| 581 |
+
this._assertNotDisposed();
|
| 582 |
+
if (lineNumber < 1 || lineNumber > this.getLineCount()) {
|
| 583 |
+
throw new BugIndicatingError('Illegal value for lineNumber');
|
| 584 |
+
}
|
| 585 |
+
return this._buffer.getLineLength(lineNumber) + 1;
|
| 586 |
+
}
|
| 587 |
+
getLineFirstNonWhitespaceColumn(lineNumber) {
|
| 588 |
+
this._assertNotDisposed();
|
| 589 |
+
if (lineNumber < 1 || lineNumber > this.getLineCount()) {
|
| 590 |
+
throw new BugIndicatingError('Illegal value for lineNumber');
|
| 591 |
+
}
|
| 592 |
+
return this._buffer.getLineFirstNonWhitespaceColumn(lineNumber);
|
| 593 |
+
}
|
| 594 |
+
getLineLastNonWhitespaceColumn(lineNumber) {
|
| 595 |
+
this._assertNotDisposed();
|
| 596 |
+
if (lineNumber < 1 || lineNumber > this.getLineCount()) {
|
| 597 |
+
throw new BugIndicatingError('Illegal value for lineNumber');
|
| 598 |
+
}
|
| 599 |
+
return this._buffer.getLineLastNonWhitespaceColumn(lineNumber);
|
| 600 |
+
}
|
| 601 |
+
/**
|
| 602 |
+
* Validates `range` is within buffer bounds, but allows it to sit in between surrogate pairs, etc.
|
| 603 |
+
* Will try to not allocate if possible.
|
| 604 |
+
*/
|
| 605 |
+
_validateRangeRelaxedNoAllocations(range) {
|
| 606 |
+
const linesCount = this._buffer.getLineCount();
|
| 607 |
+
const initialStartLineNumber = range.startLineNumber;
|
| 608 |
+
const initialStartColumn = range.startColumn;
|
| 609 |
+
let startLineNumber = Math.floor((typeof initialStartLineNumber === 'number' && !isNaN(initialStartLineNumber)) ? initialStartLineNumber : 1);
|
| 610 |
+
let startColumn = Math.floor((typeof initialStartColumn === 'number' && !isNaN(initialStartColumn)) ? initialStartColumn : 1);
|
| 611 |
+
if (startLineNumber < 1) {
|
| 612 |
+
startLineNumber = 1;
|
| 613 |
+
startColumn = 1;
|
| 614 |
+
}
|
| 615 |
+
else if (startLineNumber > linesCount) {
|
| 616 |
+
startLineNumber = linesCount;
|
| 617 |
+
startColumn = this.getLineMaxColumn(startLineNumber);
|
| 618 |
+
}
|
| 619 |
+
else {
|
| 620 |
+
if (startColumn <= 1) {
|
| 621 |
+
startColumn = 1;
|
| 622 |
+
}
|
| 623 |
+
else {
|
| 624 |
+
const maxColumn = this.getLineMaxColumn(startLineNumber);
|
| 625 |
+
if (startColumn >= maxColumn) {
|
| 626 |
+
startColumn = maxColumn;
|
| 627 |
+
}
|
| 628 |
+
}
|
| 629 |
+
}
|
| 630 |
+
const initialEndLineNumber = range.endLineNumber;
|
| 631 |
+
const initialEndColumn = range.endColumn;
|
| 632 |
+
let endLineNumber = Math.floor((typeof initialEndLineNumber === 'number' && !isNaN(initialEndLineNumber)) ? initialEndLineNumber : 1);
|
| 633 |
+
let endColumn = Math.floor((typeof initialEndColumn === 'number' && !isNaN(initialEndColumn)) ? initialEndColumn : 1);
|
| 634 |
+
if (endLineNumber < 1) {
|
| 635 |
+
endLineNumber = 1;
|
| 636 |
+
endColumn = 1;
|
| 637 |
+
}
|
| 638 |
+
else if (endLineNumber > linesCount) {
|
| 639 |
+
endLineNumber = linesCount;
|
| 640 |
+
endColumn = this.getLineMaxColumn(endLineNumber);
|
| 641 |
+
}
|
| 642 |
+
else {
|
| 643 |
+
if (endColumn <= 1) {
|
| 644 |
+
endColumn = 1;
|
| 645 |
+
}
|
| 646 |
+
else {
|
| 647 |
+
const maxColumn = this.getLineMaxColumn(endLineNumber);
|
| 648 |
+
if (endColumn >= maxColumn) {
|
| 649 |
+
endColumn = maxColumn;
|
| 650 |
+
}
|
| 651 |
+
}
|
| 652 |
+
}
|
| 653 |
+
if (initialStartLineNumber === startLineNumber
|
| 654 |
+
&& initialStartColumn === startColumn
|
| 655 |
+
&& initialEndLineNumber === endLineNumber
|
| 656 |
+
&& initialEndColumn === endColumn
|
| 657 |
+
&& range instanceof Range
|
| 658 |
+
&& !(range instanceof Selection)) {
|
| 659 |
+
return range;
|
| 660 |
+
}
|
| 661 |
+
return new Range(startLineNumber, startColumn, endLineNumber, endColumn);
|
| 662 |
+
}
|
| 663 |
+
_isValidPosition(lineNumber, column, validationType) {
|
| 664 |
+
if (typeof lineNumber !== 'number' || typeof column !== 'number') {
|
| 665 |
+
return false;
|
| 666 |
+
}
|
| 667 |
+
if (isNaN(lineNumber) || isNaN(column)) {
|
| 668 |
+
return false;
|
| 669 |
+
}
|
| 670 |
+
if (lineNumber < 1 || column < 1) {
|
| 671 |
+
return false;
|
| 672 |
+
}
|
| 673 |
+
if ((lineNumber | 0) !== lineNumber || (column | 0) !== column) {
|
| 674 |
+
return false;
|
| 675 |
+
}
|
| 676 |
+
const lineCount = this._buffer.getLineCount();
|
| 677 |
+
if (lineNumber > lineCount) {
|
| 678 |
+
return false;
|
| 679 |
+
}
|
| 680 |
+
if (column === 1) {
|
| 681 |
+
return true;
|
| 682 |
+
}
|
| 683 |
+
const maxColumn = this.getLineMaxColumn(lineNumber);
|
| 684 |
+
if (column > maxColumn) {
|
| 685 |
+
return false;
|
| 686 |
+
}
|
| 687 |
+
if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {
|
| 688 |
+
// !!At this point, column > 1
|
| 689 |
+
const charCodeBefore = this._buffer.getLineCharCode(lineNumber, column - 2);
|
| 690 |
+
if (strings.isHighSurrogate(charCodeBefore)) {
|
| 691 |
+
return false;
|
| 692 |
+
}
|
| 693 |
+
}
|
| 694 |
+
return true;
|
| 695 |
+
}
|
| 696 |
+
_validatePosition(_lineNumber, _column, validationType) {
|
| 697 |
+
const lineNumber = Math.floor((typeof _lineNumber === 'number' && !isNaN(_lineNumber)) ? _lineNumber : 1);
|
| 698 |
+
const column = Math.floor((typeof _column === 'number' && !isNaN(_column)) ? _column : 1);
|
| 699 |
+
const lineCount = this._buffer.getLineCount();
|
| 700 |
+
if (lineNumber < 1) {
|
| 701 |
+
return new Position(1, 1);
|
| 702 |
+
}
|
| 703 |
+
if (lineNumber > lineCount) {
|
| 704 |
+
return new Position(lineCount, this.getLineMaxColumn(lineCount));
|
| 705 |
+
}
|
| 706 |
+
if (column <= 1) {
|
| 707 |
+
return new Position(lineNumber, 1);
|
| 708 |
+
}
|
| 709 |
+
const maxColumn = this.getLineMaxColumn(lineNumber);
|
| 710 |
+
if (column >= maxColumn) {
|
| 711 |
+
return new Position(lineNumber, maxColumn);
|
| 712 |
+
}
|
| 713 |
+
if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {
|
| 714 |
+
// If the position would end up in the middle of a high-low surrogate pair,
|
| 715 |
+
// we move it to before the pair
|
| 716 |
+
// !!At this point, column > 1
|
| 717 |
+
const charCodeBefore = this._buffer.getLineCharCode(lineNumber, column - 2);
|
| 718 |
+
if (strings.isHighSurrogate(charCodeBefore)) {
|
| 719 |
+
return new Position(lineNumber, column - 1);
|
| 720 |
+
}
|
| 721 |
+
}
|
| 722 |
+
return new Position(lineNumber, column);
|
| 723 |
+
}
|
| 724 |
+
validatePosition(position) {
|
| 725 |
+
const validationType = 1 /* StringOffsetValidationType.SurrogatePairs */;
|
| 726 |
+
this._assertNotDisposed();
|
| 727 |
+
// Avoid object allocation and cover most likely case
|
| 728 |
+
if (position instanceof Position) {
|
| 729 |
+
if (this._isValidPosition(position.lineNumber, position.column, validationType)) {
|
| 730 |
+
return position;
|
| 731 |
+
}
|
| 732 |
+
}
|
| 733 |
+
return this._validatePosition(position.lineNumber, position.column, validationType);
|
| 734 |
+
}
|
| 735 |
+
_isValidRange(range, validationType) {
|
| 736 |
+
const startLineNumber = range.startLineNumber;
|
| 737 |
+
const startColumn = range.startColumn;
|
| 738 |
+
const endLineNumber = range.endLineNumber;
|
| 739 |
+
const endColumn = range.endColumn;
|
| 740 |
+
if (!this._isValidPosition(startLineNumber, startColumn, 0 /* StringOffsetValidationType.Relaxed */)) {
|
| 741 |
+
return false;
|
| 742 |
+
}
|
| 743 |
+
if (!this._isValidPosition(endLineNumber, endColumn, 0 /* StringOffsetValidationType.Relaxed */)) {
|
| 744 |
+
return false;
|
| 745 |
+
}
|
| 746 |
+
if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {
|
| 747 |
+
const charCodeBeforeStart = (startColumn > 1 ? this._buffer.getLineCharCode(startLineNumber, startColumn - 2) : 0);
|
| 748 |
+
const charCodeBeforeEnd = (endColumn > 1 && endColumn <= this._buffer.getLineLength(endLineNumber) ? this._buffer.getLineCharCode(endLineNumber, endColumn - 2) : 0);
|
| 749 |
+
const startInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeStart);
|
| 750 |
+
const endInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeEnd);
|
| 751 |
+
if (!startInsideSurrogatePair && !endInsideSurrogatePair) {
|
| 752 |
+
return true;
|
| 753 |
+
}
|
| 754 |
+
return false;
|
| 755 |
+
}
|
| 756 |
+
return true;
|
| 757 |
+
}
|
| 758 |
+
validateRange(_range) {
|
| 759 |
+
const validationType = 1 /* StringOffsetValidationType.SurrogatePairs */;
|
| 760 |
+
this._assertNotDisposed();
|
| 761 |
+
// Avoid object allocation and cover most likely case
|
| 762 |
+
if ((_range instanceof Range) && !(_range instanceof Selection)) {
|
| 763 |
+
if (this._isValidRange(_range, validationType)) {
|
| 764 |
+
return _range;
|
| 765 |
+
}
|
| 766 |
+
}
|
| 767 |
+
const start = this._validatePosition(_range.startLineNumber, _range.startColumn, 0 /* StringOffsetValidationType.Relaxed */);
|
| 768 |
+
const end = this._validatePosition(_range.endLineNumber, _range.endColumn, 0 /* StringOffsetValidationType.Relaxed */);
|
| 769 |
+
const startLineNumber = start.lineNumber;
|
| 770 |
+
const startColumn = start.column;
|
| 771 |
+
const endLineNumber = end.lineNumber;
|
| 772 |
+
const endColumn = end.column;
|
| 773 |
+
if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {
|
| 774 |
+
const charCodeBeforeStart = (startColumn > 1 ? this._buffer.getLineCharCode(startLineNumber, startColumn - 2) : 0);
|
| 775 |
+
const charCodeBeforeEnd = (endColumn > 1 && endColumn <= this._buffer.getLineLength(endLineNumber) ? this._buffer.getLineCharCode(endLineNumber, endColumn - 2) : 0);
|
| 776 |
+
const startInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeStart);
|
| 777 |
+
const endInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeEnd);
|
| 778 |
+
if (!startInsideSurrogatePair && !endInsideSurrogatePair) {
|
| 779 |
+
return new Range(startLineNumber, startColumn, endLineNumber, endColumn);
|
| 780 |
+
}
|
| 781 |
+
if (startLineNumber === endLineNumber && startColumn === endColumn) {
|
| 782 |
+
// do not expand a collapsed range, simply move it to a valid location
|
| 783 |
+
return new Range(startLineNumber, startColumn - 1, endLineNumber, endColumn - 1);
|
| 784 |
+
}
|
| 785 |
+
if (startInsideSurrogatePair && endInsideSurrogatePair) {
|
| 786 |
+
// expand range at both ends
|
| 787 |
+
return new Range(startLineNumber, startColumn - 1, endLineNumber, endColumn + 1);
|
| 788 |
+
}
|
| 789 |
+
if (startInsideSurrogatePair) {
|
| 790 |
+
// only expand range at the start
|
| 791 |
+
return new Range(startLineNumber, startColumn - 1, endLineNumber, endColumn);
|
| 792 |
+
}
|
| 793 |
+
// only expand range at the end
|
| 794 |
+
return new Range(startLineNumber, startColumn, endLineNumber, endColumn + 1);
|
| 795 |
+
}
|
| 796 |
+
return new Range(startLineNumber, startColumn, endLineNumber, endColumn);
|
| 797 |
+
}
|
| 798 |
+
modifyPosition(rawPosition, offset) {
|
| 799 |
+
this._assertNotDisposed();
|
| 800 |
+
const candidate = this.getOffsetAt(rawPosition) + offset;
|
| 801 |
+
return this.getPositionAt(Math.min(this._buffer.getLength(), Math.max(0, candidate)));
|
| 802 |
+
}
|
| 803 |
+
getFullModelRange() {
|
| 804 |
+
this._assertNotDisposed();
|
| 805 |
+
const lineCount = this.getLineCount();
|
| 806 |
+
return new Range(1, 1, lineCount, this.getLineMaxColumn(lineCount));
|
| 807 |
+
}
|
| 808 |
+
findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount) {
|
| 809 |
+
return this._buffer.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);
|
| 810 |
+
}
|
| 811 |
+
findMatches(searchString, rawSearchScope, isRegex, matchCase, wordSeparators, captureMatches, limitResultCount = LIMIT_FIND_COUNT) {
|
| 812 |
+
this._assertNotDisposed();
|
| 813 |
+
let searchRanges = null;
|
| 814 |
+
if (rawSearchScope !== null) {
|
| 815 |
+
if (!Array.isArray(rawSearchScope)) {
|
| 816 |
+
rawSearchScope = [rawSearchScope];
|
| 817 |
+
}
|
| 818 |
+
if (rawSearchScope.every((searchScope) => Range.isIRange(searchScope))) {
|
| 819 |
+
searchRanges = rawSearchScope.map((searchScope) => this.validateRange(searchScope));
|
| 820 |
+
}
|
| 821 |
+
}
|
| 822 |
+
if (searchRanges === null) {
|
| 823 |
+
searchRanges = [this.getFullModelRange()];
|
| 824 |
+
}
|
| 825 |
+
searchRanges = searchRanges.sort((d1, d2) => d1.startLineNumber - d2.startLineNumber || d1.startColumn - d2.startColumn);
|
| 826 |
+
const uniqueSearchRanges = [];
|
| 827 |
+
uniqueSearchRanges.push(searchRanges.reduce((prev, curr) => {
|
| 828 |
+
if (Range.areIntersecting(prev, curr)) {
|
| 829 |
+
return prev.plusRange(curr);
|
| 830 |
+
}
|
| 831 |
+
uniqueSearchRanges.push(prev);
|
| 832 |
+
return curr;
|
| 833 |
+
}));
|
| 834 |
+
let matchMapper;
|
| 835 |
+
if (!isRegex && searchString.indexOf('\n') < 0) {
|
| 836 |
+
// not regex, not multi line
|
| 837 |
+
const searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators);
|
| 838 |
+
const searchData = searchParams.parseSearchRequest();
|
| 839 |
+
if (!searchData) {
|
| 840 |
+
return [];
|
| 841 |
+
}
|
| 842 |
+
matchMapper = (searchRange) => this.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);
|
| 843 |
+
}
|
| 844 |
+
else {
|
| 845 |
+
matchMapper = (searchRange) => TextModelSearch.findMatches(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchRange, captureMatches, limitResultCount);
|
| 846 |
+
}
|
| 847 |
+
return uniqueSearchRanges.map(matchMapper).reduce((arr, matches) => arr.concat(matches), []);
|
| 848 |
+
}
|
| 849 |
+
findNextMatch(searchString, rawSearchStart, isRegex, matchCase, wordSeparators, captureMatches) {
|
| 850 |
+
this._assertNotDisposed();
|
| 851 |
+
const searchStart = this.validatePosition(rawSearchStart);
|
| 852 |
+
if (!isRegex && searchString.indexOf('\n') < 0) {
|
| 853 |
+
const searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators);
|
| 854 |
+
const searchData = searchParams.parseSearchRequest();
|
| 855 |
+
if (!searchData) {
|
| 856 |
+
return null;
|
| 857 |
+
}
|
| 858 |
+
const lineCount = this.getLineCount();
|
| 859 |
+
let searchRange = new Range(searchStart.lineNumber, searchStart.column, lineCount, this.getLineMaxColumn(lineCount));
|
| 860 |
+
let ret = this.findMatchesLineByLine(searchRange, searchData, captureMatches, 1);
|
| 861 |
+
TextModelSearch.findNextMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches);
|
| 862 |
+
if (ret.length > 0) {
|
| 863 |
+
return ret[0];
|
| 864 |
+
}
|
| 865 |
+
searchRange = new Range(1, 1, searchStart.lineNumber, this.getLineMaxColumn(searchStart.lineNumber));
|
| 866 |
+
ret = this.findMatchesLineByLine(searchRange, searchData, captureMatches, 1);
|
| 867 |
+
if (ret.length > 0) {
|
| 868 |
+
return ret[0];
|
| 869 |
+
}
|
| 870 |
+
return null;
|
| 871 |
+
}
|
| 872 |
+
return TextModelSearch.findNextMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches);
|
| 873 |
+
}
|
| 874 |
+
findPreviousMatch(searchString, rawSearchStart, isRegex, matchCase, wordSeparators, captureMatches) {
|
| 875 |
+
this._assertNotDisposed();
|
| 876 |
+
const searchStart = this.validatePosition(rawSearchStart);
|
| 877 |
+
return TextModelSearch.findPreviousMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches);
|
| 878 |
+
}
|
| 879 |
+
//#endregion
|
| 880 |
+
//#region Editing
|
| 881 |
+
pushStackElement() {
|
| 882 |
+
this._commandManager.pushStackElement();
|
| 883 |
+
}
|
| 884 |
+
popStackElement() {
|
| 885 |
+
this._commandManager.popStackElement();
|
| 886 |
+
}
|
| 887 |
+
pushEOL(eol) {
|
| 888 |
+
const currentEOL = (this.getEOL() === '\n' ? 0 /* model.EndOfLineSequence.LF */ : 1 /* model.EndOfLineSequence.CRLF */);
|
| 889 |
+
if (currentEOL === eol) {
|
| 890 |
+
return;
|
| 891 |
+
}
|
| 892 |
+
try {
|
| 893 |
+
this._onDidChangeDecorations.beginDeferredEmit();
|
| 894 |
+
this._eventEmitter.beginDeferredEmit();
|
| 895 |
+
if (this._initialUndoRedoSnapshot === null) {
|
| 896 |
+
this._initialUndoRedoSnapshot = this._undoRedoService.createSnapshot(this.uri);
|
| 897 |
+
}
|
| 898 |
+
this._commandManager.pushEOL(eol);
|
| 899 |
+
}
|
| 900 |
+
finally {
|
| 901 |
+
this._eventEmitter.endDeferredEmit();
|
| 902 |
+
this._onDidChangeDecorations.endDeferredEmit();
|
| 903 |
+
}
|
| 904 |
+
}
|
| 905 |
+
_validateEditOperation(rawOperation) {
|
| 906 |
+
if (rawOperation instanceof model.ValidAnnotatedEditOperation) {
|
| 907 |
+
return rawOperation;
|
| 908 |
+
}
|
| 909 |
+
return new model.ValidAnnotatedEditOperation(rawOperation.identifier || null, this.validateRange(rawOperation.range), rawOperation.text, rawOperation.forceMoveMarkers || false, rawOperation.isAutoWhitespaceEdit || false, rawOperation._isTracked || false);
|
| 910 |
+
}
|
| 911 |
+
_validateEditOperations(rawOperations) {
|
| 912 |
+
const result = [];
|
| 913 |
+
for (let i = 0, len = rawOperations.length; i < len; i++) {
|
| 914 |
+
result[i] = this._validateEditOperation(rawOperations[i]);
|
| 915 |
+
}
|
| 916 |
+
return result;
|
| 917 |
+
}
|
| 918 |
+
pushEditOperations(beforeCursorState, editOperations, cursorStateComputer, group) {
|
| 919 |
+
try {
|
| 920 |
+
this._onDidChangeDecorations.beginDeferredEmit();
|
| 921 |
+
this._eventEmitter.beginDeferredEmit();
|
| 922 |
+
return this._pushEditOperations(beforeCursorState, this._validateEditOperations(editOperations), cursorStateComputer, group);
|
| 923 |
+
}
|
| 924 |
+
finally {
|
| 925 |
+
this._eventEmitter.endDeferredEmit();
|
| 926 |
+
this._onDidChangeDecorations.endDeferredEmit();
|
| 927 |
+
}
|
| 928 |
+
}
|
| 929 |
+
_pushEditOperations(beforeCursorState, editOperations, cursorStateComputer, group) {
|
| 930 |
+
if (this._options.trimAutoWhitespace && this._trimAutoWhitespaceLines) {
|
| 931 |
+
// Go through each saved line number and insert a trim whitespace edit
|
| 932 |
+
// if it is safe to do so (no conflicts with other edits).
|
| 933 |
+
const incomingEdits = editOperations.map((op) => {
|
| 934 |
+
return {
|
| 935 |
+
range: this.validateRange(op.range),
|
| 936 |
+
text: op.text
|
| 937 |
+
};
|
| 938 |
+
});
|
| 939 |
+
// Sometimes, auto-formatters change ranges automatically which can cause undesired auto whitespace trimming near the cursor
|
| 940 |
+
// We'll use the following heuristic: if the edits occur near the cursor, then it's ok to trim auto whitespace
|
| 941 |
+
let editsAreNearCursors = true;
|
| 942 |
+
if (beforeCursorState) {
|
| 943 |
+
for (let i = 0, len = beforeCursorState.length; i < len; i++) {
|
| 944 |
+
const sel = beforeCursorState[i];
|
| 945 |
+
let foundEditNearSel = false;
|
| 946 |
+
for (let j = 0, lenJ = incomingEdits.length; j < lenJ; j++) {
|
| 947 |
+
const editRange = incomingEdits[j].range;
|
| 948 |
+
const selIsAbove = editRange.startLineNumber > sel.endLineNumber;
|
| 949 |
+
const selIsBelow = sel.startLineNumber > editRange.endLineNumber;
|
| 950 |
+
if (!selIsAbove && !selIsBelow) {
|
| 951 |
+
foundEditNearSel = true;
|
| 952 |
+
break;
|
| 953 |
+
}
|
| 954 |
+
}
|
| 955 |
+
if (!foundEditNearSel) {
|
| 956 |
+
editsAreNearCursors = false;
|
| 957 |
+
break;
|
| 958 |
+
}
|
| 959 |
+
}
|
| 960 |
+
}
|
| 961 |
+
if (editsAreNearCursors) {
|
| 962 |
+
for (let i = 0, len = this._trimAutoWhitespaceLines.length; i < len; i++) {
|
| 963 |
+
const trimLineNumber = this._trimAutoWhitespaceLines[i];
|
| 964 |
+
const maxLineColumn = this.getLineMaxColumn(trimLineNumber);
|
| 965 |
+
let allowTrimLine = true;
|
| 966 |
+
for (let j = 0, lenJ = incomingEdits.length; j < lenJ; j++) {
|
| 967 |
+
const editRange = incomingEdits[j].range;
|
| 968 |
+
const editText = incomingEdits[j].text;
|
| 969 |
+
if (trimLineNumber < editRange.startLineNumber || trimLineNumber > editRange.endLineNumber) {
|
| 970 |
+
// `trimLine` is completely outside this edit
|
| 971 |
+
continue;
|
| 972 |
+
}
|
| 973 |
+
// At this point:
|
| 974 |
+
// editRange.startLineNumber <= trimLine <= editRange.endLineNumber
|
| 975 |
+
if (trimLineNumber === editRange.startLineNumber && editRange.startColumn === maxLineColumn
|
| 976 |
+
&& editRange.isEmpty() && editText && editText.length > 0 && editText.charAt(0) === '\n') {
|
| 977 |
+
// This edit inserts a new line (and maybe other text) after `trimLine`
|
| 978 |
+
continue;
|
| 979 |
+
}
|
| 980 |
+
if (trimLineNumber === editRange.startLineNumber && editRange.startColumn === 1
|
| 981 |
+
&& editRange.isEmpty() && editText && editText.length > 0 && editText.charAt(editText.length - 1) === '\n') {
|
| 982 |
+
// This edit inserts a new line (and maybe other text) before `trimLine`
|
| 983 |
+
continue;
|
| 984 |
+
}
|
| 985 |
+
// Looks like we can't trim this line as it would interfere with an incoming edit
|
| 986 |
+
allowTrimLine = false;
|
| 987 |
+
break;
|
| 988 |
+
}
|
| 989 |
+
if (allowTrimLine) {
|
| 990 |
+
const trimRange = new Range(trimLineNumber, 1, trimLineNumber, maxLineColumn);
|
| 991 |
+
editOperations.push(new model.ValidAnnotatedEditOperation(null, trimRange, null, false, false, false));
|
| 992 |
+
}
|
| 993 |
+
}
|
| 994 |
+
}
|
| 995 |
+
this._trimAutoWhitespaceLines = null;
|
| 996 |
+
}
|
| 997 |
+
if (this._initialUndoRedoSnapshot === null) {
|
| 998 |
+
this._initialUndoRedoSnapshot = this._undoRedoService.createSnapshot(this.uri);
|
| 999 |
+
}
|
| 1000 |
+
return this._commandManager.pushEditOperation(beforeCursorState, editOperations, cursorStateComputer, group);
|
| 1001 |
+
}
|
| 1002 |
+
_applyUndo(changes, eol, resultingAlternativeVersionId, resultingSelection) {
|
| 1003 |
+
const edits = changes.map((change) => {
|
| 1004 |
+
const rangeStart = this.getPositionAt(change.newPosition);
|
| 1005 |
+
const rangeEnd = this.getPositionAt(change.newEnd);
|
| 1006 |
+
return {
|
| 1007 |
+
range: new Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column),
|
| 1008 |
+
text: change.oldText
|
| 1009 |
+
};
|
| 1010 |
+
});
|
| 1011 |
+
this._applyUndoRedoEdits(edits, eol, true, false, resultingAlternativeVersionId, resultingSelection);
|
| 1012 |
+
}
|
| 1013 |
+
_applyRedo(changes, eol, resultingAlternativeVersionId, resultingSelection) {
|
| 1014 |
+
const edits = changes.map((change) => {
|
| 1015 |
+
const rangeStart = this.getPositionAt(change.oldPosition);
|
| 1016 |
+
const rangeEnd = this.getPositionAt(change.oldEnd);
|
| 1017 |
+
return {
|
| 1018 |
+
range: new Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column),
|
| 1019 |
+
text: change.newText
|
| 1020 |
+
};
|
| 1021 |
+
});
|
| 1022 |
+
this._applyUndoRedoEdits(edits, eol, false, true, resultingAlternativeVersionId, resultingSelection);
|
| 1023 |
+
}
|
| 1024 |
+
_applyUndoRedoEdits(edits, eol, isUndoing, isRedoing, resultingAlternativeVersionId, resultingSelection) {
|
| 1025 |
+
try {
|
| 1026 |
+
this._onDidChangeDecorations.beginDeferredEmit();
|
| 1027 |
+
this._eventEmitter.beginDeferredEmit();
|
| 1028 |
+
this._isUndoing = isUndoing;
|
| 1029 |
+
this._isRedoing = isRedoing;
|
| 1030 |
+
this.applyEdits(edits, false);
|
| 1031 |
+
this.setEOL(eol);
|
| 1032 |
+
this._overwriteAlternativeVersionId(resultingAlternativeVersionId);
|
| 1033 |
+
}
|
| 1034 |
+
finally {
|
| 1035 |
+
this._isUndoing = false;
|
| 1036 |
+
this._isRedoing = false;
|
| 1037 |
+
this._eventEmitter.endDeferredEmit(resultingSelection);
|
| 1038 |
+
this._onDidChangeDecorations.endDeferredEmit();
|
| 1039 |
+
}
|
| 1040 |
+
}
|
| 1041 |
+
applyEdits(rawOperations, computeUndoEdits = false) {
|
| 1042 |
+
try {
|
| 1043 |
+
this._onDidChangeDecorations.beginDeferredEmit();
|
| 1044 |
+
this._eventEmitter.beginDeferredEmit();
|
| 1045 |
+
const operations = this._validateEditOperations(rawOperations);
|
| 1046 |
+
return this._doApplyEdits(operations, computeUndoEdits);
|
| 1047 |
+
}
|
| 1048 |
+
finally {
|
| 1049 |
+
this._eventEmitter.endDeferredEmit();
|
| 1050 |
+
this._onDidChangeDecorations.endDeferredEmit();
|
| 1051 |
+
}
|
| 1052 |
+
}
|
| 1053 |
+
_doApplyEdits(rawOperations, computeUndoEdits) {
|
| 1054 |
+
const oldLineCount = this._buffer.getLineCount();
|
| 1055 |
+
const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace, computeUndoEdits);
|
| 1056 |
+
const newLineCount = this._buffer.getLineCount();
|
| 1057 |
+
const contentChanges = result.changes;
|
| 1058 |
+
this._trimAutoWhitespaceLines = result.trimAutoWhitespaceLineNumbers;
|
| 1059 |
+
if (contentChanges.length !== 0) {
|
| 1060 |
+
// We do a first pass to update decorations
|
| 1061 |
+
// because we want to read decorations in the second pass
|
| 1062 |
+
// where we will emit content change events
|
| 1063 |
+
// and we want to read the final decorations
|
| 1064 |
+
for (let i = 0, len = contentChanges.length; i < len; i++) {
|
| 1065 |
+
const change = contentChanges[i];
|
| 1066 |
+
this._decorationsTree.acceptReplace(change.rangeOffset, change.rangeLength, change.text.length, change.forceMoveMarkers);
|
| 1067 |
+
}
|
| 1068 |
+
const rawContentChanges = [];
|
| 1069 |
+
this._increaseVersionId();
|
| 1070 |
+
let lineCount = oldLineCount;
|
| 1071 |
+
for (let i = 0, len = contentChanges.length; i < len; i++) {
|
| 1072 |
+
const change = contentChanges[i];
|
| 1073 |
+
const [eolCount] = countEOL(change.text);
|
| 1074 |
+
this._onDidChangeDecorations.fire();
|
| 1075 |
+
const startLineNumber = change.range.startLineNumber;
|
| 1076 |
+
const endLineNumber = change.range.endLineNumber;
|
| 1077 |
+
const deletingLinesCnt = endLineNumber - startLineNumber;
|
| 1078 |
+
const insertingLinesCnt = eolCount;
|
| 1079 |
+
const editingLinesCnt = Math.min(deletingLinesCnt, insertingLinesCnt);
|
| 1080 |
+
const changeLineCountDelta = (insertingLinesCnt - deletingLinesCnt);
|
| 1081 |
+
const currentEditStartLineNumber = newLineCount - lineCount - changeLineCountDelta + startLineNumber;
|
| 1082 |
+
const firstEditLineNumber = currentEditStartLineNumber;
|
| 1083 |
+
const lastInsertedLineNumber = currentEditStartLineNumber + insertingLinesCnt;
|
| 1084 |
+
const decorationsWithInjectedTextInEditedRange = this._decorationsTree.getInjectedTextInInterval(this, this.getOffsetAt(new Position(firstEditLineNumber, 1)), this.getOffsetAt(new Position(lastInsertedLineNumber, this.getLineMaxColumn(lastInsertedLineNumber))), 0);
|
| 1085 |
+
const injectedTextInEditedRange = LineInjectedText.fromDecorations(decorationsWithInjectedTextInEditedRange);
|
| 1086 |
+
const injectedTextInEditedRangeQueue = new ArrayQueue(injectedTextInEditedRange);
|
| 1087 |
+
for (let j = editingLinesCnt; j >= 0; j--) {
|
| 1088 |
+
const editLineNumber = startLineNumber + j;
|
| 1089 |
+
const currentEditLineNumber = currentEditStartLineNumber + j;
|
| 1090 |
+
injectedTextInEditedRangeQueue.takeFromEndWhile(r => r.lineNumber > currentEditLineNumber);
|
| 1091 |
+
const decorationsInCurrentLine = injectedTextInEditedRangeQueue.takeFromEndWhile(r => r.lineNumber === currentEditLineNumber);
|
| 1092 |
+
rawContentChanges.push(new ModelRawLineChanged(editLineNumber, this.getLineContent(currentEditLineNumber), decorationsInCurrentLine));
|
| 1093 |
+
}
|
| 1094 |
+
if (editingLinesCnt < deletingLinesCnt) {
|
| 1095 |
+
// Must delete some lines
|
| 1096 |
+
const spliceStartLineNumber = startLineNumber + editingLinesCnt;
|
| 1097 |
+
rawContentChanges.push(new ModelRawLinesDeleted(spliceStartLineNumber + 1, endLineNumber));
|
| 1098 |
+
}
|
| 1099 |
+
if (editingLinesCnt < insertingLinesCnt) {
|
| 1100 |
+
const injectedTextInEditedRangeQueue = new ArrayQueue(injectedTextInEditedRange);
|
| 1101 |
+
// Must insert some lines
|
| 1102 |
+
const spliceLineNumber = startLineNumber + editingLinesCnt;
|
| 1103 |
+
const cnt = insertingLinesCnt - editingLinesCnt;
|
| 1104 |
+
const fromLineNumber = newLineCount - lineCount - cnt + spliceLineNumber + 1;
|
| 1105 |
+
const injectedTexts = [];
|
| 1106 |
+
const newLines = [];
|
| 1107 |
+
for (let i = 0; i < cnt; i++) {
|
| 1108 |
+
const lineNumber = fromLineNumber + i;
|
| 1109 |
+
newLines[i] = this.getLineContent(lineNumber);
|
| 1110 |
+
injectedTextInEditedRangeQueue.takeWhile(r => r.lineNumber < lineNumber);
|
| 1111 |
+
injectedTexts[i] = injectedTextInEditedRangeQueue.takeWhile(r => r.lineNumber === lineNumber);
|
| 1112 |
+
}
|
| 1113 |
+
rawContentChanges.push(new ModelRawLinesInserted(spliceLineNumber + 1, startLineNumber + insertingLinesCnt, newLines, injectedTexts));
|
| 1114 |
+
}
|
| 1115 |
+
lineCount += changeLineCountDelta;
|
| 1116 |
+
}
|
| 1117 |
+
this._emitContentChangedEvent(new ModelRawContentChangedEvent(rawContentChanges, this.getVersionId(), this._isUndoing, this._isRedoing), {
|
| 1118 |
+
changes: contentChanges,
|
| 1119 |
+
eol: this._buffer.getEOL(),
|
| 1120 |
+
isEolChange: false,
|
| 1121 |
+
versionId: this.getVersionId(),
|
| 1122 |
+
isUndoing: this._isUndoing,
|
| 1123 |
+
isRedoing: this._isRedoing,
|
| 1124 |
+
isFlush: false
|
| 1125 |
+
});
|
| 1126 |
+
}
|
| 1127 |
+
return (result.reverseEdits === null ? undefined : result.reverseEdits);
|
| 1128 |
+
}
|
| 1129 |
+
undo() {
|
| 1130 |
+
return this._undoRedoService.undo(this.uri);
|
| 1131 |
+
}
|
| 1132 |
+
canUndo() {
|
| 1133 |
+
return this._undoRedoService.canUndo(this.uri);
|
| 1134 |
+
}
|
| 1135 |
+
redo() {
|
| 1136 |
+
return this._undoRedoService.redo(this.uri);
|
| 1137 |
+
}
|
| 1138 |
+
canRedo() {
|
| 1139 |
+
return this._undoRedoService.canRedo(this.uri);
|
| 1140 |
+
}
|
| 1141 |
+
//#endregion
|
| 1142 |
+
//#region Decorations
|
| 1143 |
+
handleBeforeFireDecorationsChangedEvent(affectedInjectedTextLines) {
|
| 1144 |
+
// This is called before the decoration changed event is fired.
|
| 1145 |
+
if (affectedInjectedTextLines === null || affectedInjectedTextLines.size === 0) {
|
| 1146 |
+
return;
|
| 1147 |
+
}
|
| 1148 |
+
const affectedLines = Array.from(affectedInjectedTextLines);
|
| 1149 |
+
const lineChangeEvents = affectedLines.map(lineNumber => new ModelRawLineChanged(lineNumber, this.getLineContent(lineNumber), this._getInjectedTextInLine(lineNumber)));
|
| 1150 |
+
this._onDidChangeInjectedText.fire(new ModelInjectedTextChangedEvent(lineChangeEvents));
|
| 1151 |
+
}
|
| 1152 |
+
changeDecorations(callback, ownerId = 0) {
|
| 1153 |
+
this._assertNotDisposed();
|
| 1154 |
+
try {
|
| 1155 |
+
this._onDidChangeDecorations.beginDeferredEmit();
|
| 1156 |
+
return this._changeDecorations(ownerId, callback);
|
| 1157 |
+
}
|
| 1158 |
+
finally {
|
| 1159 |
+
this._onDidChangeDecorations.endDeferredEmit();
|
| 1160 |
+
}
|
| 1161 |
+
}
|
| 1162 |
+
_changeDecorations(ownerId, callback) {
|
| 1163 |
+
const changeAccessor = {
|
| 1164 |
+
addDecoration: (range, options) => {
|
| 1165 |
+
return this._deltaDecorationsImpl(ownerId, [], [{ range: range, options: options }])[0];
|
| 1166 |
+
},
|
| 1167 |
+
changeDecoration: (id, newRange) => {
|
| 1168 |
+
this._changeDecorationImpl(id, newRange);
|
| 1169 |
+
},
|
| 1170 |
+
changeDecorationOptions: (id, options) => {
|
| 1171 |
+
this._changeDecorationOptionsImpl(id, _normalizeOptions(options));
|
| 1172 |
+
},
|
| 1173 |
+
removeDecoration: (id) => {
|
| 1174 |
+
this._deltaDecorationsImpl(ownerId, [id], []);
|
| 1175 |
+
},
|
| 1176 |
+
deltaDecorations: (oldDecorations, newDecorations) => {
|
| 1177 |
+
if (oldDecorations.length === 0 && newDecorations.length === 0) {
|
| 1178 |
+
// nothing to do
|
| 1179 |
+
return [];
|
| 1180 |
+
}
|
| 1181 |
+
return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);
|
| 1182 |
+
}
|
| 1183 |
+
};
|
| 1184 |
+
let result = null;
|
| 1185 |
+
try {
|
| 1186 |
+
result = callback(changeAccessor);
|
| 1187 |
+
}
|
| 1188 |
+
catch (e) {
|
| 1189 |
+
onUnexpectedError(e);
|
| 1190 |
+
}
|
| 1191 |
+
// Invalidate change accessor
|
| 1192 |
+
changeAccessor.addDecoration = invalidFunc;
|
| 1193 |
+
changeAccessor.changeDecoration = invalidFunc;
|
| 1194 |
+
changeAccessor.changeDecorationOptions = invalidFunc;
|
| 1195 |
+
changeAccessor.removeDecoration = invalidFunc;
|
| 1196 |
+
changeAccessor.deltaDecorations = invalidFunc;
|
| 1197 |
+
return result;
|
| 1198 |
+
}
|
| 1199 |
+
deltaDecorations(oldDecorations, newDecorations, ownerId = 0) {
|
| 1200 |
+
this._assertNotDisposed();
|
| 1201 |
+
if (!oldDecorations) {
|
| 1202 |
+
oldDecorations = [];
|
| 1203 |
+
}
|
| 1204 |
+
if (oldDecorations.length === 0 && newDecorations.length === 0) {
|
| 1205 |
+
// nothing to do
|
| 1206 |
+
return [];
|
| 1207 |
+
}
|
| 1208 |
+
try {
|
| 1209 |
+
this._deltaDecorationCallCnt++;
|
| 1210 |
+
if (this._deltaDecorationCallCnt > 1) {
|
| 1211 |
+
console.warn(`Invoking deltaDecorations recursively could lead to leaking decorations.`);
|
| 1212 |
+
onUnexpectedError(new Error(`Invoking deltaDecorations recursively could lead to leaking decorations.`));
|
| 1213 |
+
}
|
| 1214 |
+
this._onDidChangeDecorations.beginDeferredEmit();
|
| 1215 |
+
return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);
|
| 1216 |
+
}
|
| 1217 |
+
finally {
|
| 1218 |
+
this._onDidChangeDecorations.endDeferredEmit();
|
| 1219 |
+
this._deltaDecorationCallCnt--;
|
| 1220 |
+
}
|
| 1221 |
+
}
|
| 1222 |
+
_getTrackedRange(id) {
|
| 1223 |
+
return this.getDecorationRange(id);
|
| 1224 |
+
}
|
| 1225 |
+
_setTrackedRange(id, newRange, newStickiness) {
|
| 1226 |
+
const node = (id ? this._decorations[id] : null);
|
| 1227 |
+
if (!node) {
|
| 1228 |
+
if (!newRange) {
|
| 1229 |
+
// node doesn't exist, the request is to delete => nothing to do
|
| 1230 |
+
return null;
|
| 1231 |
+
}
|
| 1232 |
+
// node doesn't exist, the request is to set => add the tracked range
|
| 1233 |
+
return this._deltaDecorationsImpl(0, [], [{ range: newRange, options: TRACKED_RANGE_OPTIONS[newStickiness] }], true)[0];
|
| 1234 |
+
}
|
| 1235 |
+
if (!newRange) {
|
| 1236 |
+
// node exists, the request is to delete => delete node
|
| 1237 |
+
this._decorationsTree.delete(node);
|
| 1238 |
+
delete this._decorations[node.id];
|
| 1239 |
+
return null;
|
| 1240 |
+
}
|
| 1241 |
+
// node exists, the request is to set => change the tracked range and its options
|
| 1242 |
+
const range = this._validateRangeRelaxedNoAllocations(newRange);
|
| 1243 |
+
const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);
|
| 1244 |
+
const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);
|
| 1245 |
+
this._decorationsTree.delete(node);
|
| 1246 |
+
node.reset(this.getVersionId(), startOffset, endOffset, range);
|
| 1247 |
+
node.setOptions(TRACKED_RANGE_OPTIONS[newStickiness]);
|
| 1248 |
+
this._decorationsTree.insert(node);
|
| 1249 |
+
return node.id;
|
| 1250 |
+
}
|
| 1251 |
+
removeAllDecorationsWithOwnerId(ownerId) {
|
| 1252 |
+
if (this._isDisposed) {
|
| 1253 |
+
return;
|
| 1254 |
+
}
|
| 1255 |
+
const nodes = this._decorationsTree.collectNodesFromOwner(ownerId);
|
| 1256 |
+
for (let i = 0, len = nodes.length; i < len; i++) {
|
| 1257 |
+
const node = nodes[i];
|
| 1258 |
+
this._decorationsTree.delete(node);
|
| 1259 |
+
delete this._decorations[node.id];
|
| 1260 |
+
}
|
| 1261 |
+
}
|
| 1262 |
+
getDecorationOptions(decorationId) {
|
| 1263 |
+
const node = this._decorations[decorationId];
|
| 1264 |
+
if (!node) {
|
| 1265 |
+
return null;
|
| 1266 |
+
}
|
| 1267 |
+
return node.options;
|
| 1268 |
+
}
|
| 1269 |
+
getDecorationRange(decorationId) {
|
| 1270 |
+
const node = this._decorations[decorationId];
|
| 1271 |
+
if (!node) {
|
| 1272 |
+
return null;
|
| 1273 |
+
}
|
| 1274 |
+
return this._decorationsTree.getNodeRange(this, node);
|
| 1275 |
+
}
|
| 1276 |
+
getLineDecorations(lineNumber, ownerId = 0, filterOutValidation = false) {
|
| 1277 |
+
if (lineNumber < 1 || lineNumber > this.getLineCount()) {
|
| 1278 |
+
return [];
|
| 1279 |
+
}
|
| 1280 |
+
return this.getLinesDecorations(lineNumber, lineNumber, ownerId, filterOutValidation);
|
| 1281 |
+
}
|
| 1282 |
+
getLinesDecorations(_startLineNumber, _endLineNumber, ownerId = 0, filterOutValidation = false, onlyMarginDecorations = false) {
|
| 1283 |
+
const lineCount = this.getLineCount();
|
| 1284 |
+
const startLineNumber = Math.min(lineCount, Math.max(1, _startLineNumber));
|
| 1285 |
+
const endLineNumber = Math.min(lineCount, Math.max(1, _endLineNumber));
|
| 1286 |
+
const endColumn = this.getLineMaxColumn(endLineNumber);
|
| 1287 |
+
const range = new Range(startLineNumber, 1, endLineNumber, endColumn);
|
| 1288 |
+
const decorations = this._getDecorationsInRange(range, ownerId, filterOutValidation, onlyMarginDecorations);
|
| 1289 |
+
pushMany(decorations, this._decorationProvider.getDecorationsInRange(range, ownerId, filterOutValidation));
|
| 1290 |
+
return decorations;
|
| 1291 |
+
}
|
| 1292 |
+
getDecorationsInRange(range, ownerId = 0, filterOutValidation = false, onlyMinimapDecorations = false, onlyMarginDecorations = false) {
|
| 1293 |
+
const validatedRange = this.validateRange(range);
|
| 1294 |
+
const decorations = this._getDecorationsInRange(validatedRange, ownerId, filterOutValidation, onlyMarginDecorations);
|
| 1295 |
+
pushMany(decorations, this._decorationProvider.getDecorationsInRange(validatedRange, ownerId, filterOutValidation, onlyMinimapDecorations));
|
| 1296 |
+
return decorations;
|
| 1297 |
+
}
|
| 1298 |
+
getOverviewRulerDecorations(ownerId = 0, filterOutValidation = false) {
|
| 1299 |
+
return this._decorationsTree.getAll(this, ownerId, filterOutValidation, true, false);
|
| 1300 |
+
}
|
| 1301 |
+
getInjectedTextDecorations(ownerId = 0) {
|
| 1302 |
+
return this._decorationsTree.getAllInjectedText(this, ownerId);
|
| 1303 |
+
}
|
| 1304 |
+
_getInjectedTextInLine(lineNumber) {
|
| 1305 |
+
const startOffset = this._buffer.getOffsetAt(lineNumber, 1);
|
| 1306 |
+
const endOffset = startOffset + this._buffer.getLineLength(lineNumber);
|
| 1307 |
+
const result = this._decorationsTree.getInjectedTextInInterval(this, startOffset, endOffset, 0);
|
| 1308 |
+
return LineInjectedText.fromDecorations(result).filter(t => t.lineNumber === lineNumber);
|
| 1309 |
+
}
|
| 1310 |
+
getAllDecorations(ownerId = 0, filterOutValidation = false) {
|
| 1311 |
+
let result = this._decorationsTree.getAll(this, ownerId, filterOutValidation, false, false);
|
| 1312 |
+
result = result.concat(this._decorationProvider.getAllDecorations(ownerId, filterOutValidation));
|
| 1313 |
+
return result;
|
| 1314 |
+
}
|
| 1315 |
+
getAllMarginDecorations(ownerId = 0) {
|
| 1316 |
+
return this._decorationsTree.getAll(this, ownerId, false, false, true);
|
| 1317 |
+
}
|
| 1318 |
+
_getDecorationsInRange(filterRange, filterOwnerId, filterOutValidation, onlyMarginDecorations) {
|
| 1319 |
+
const startOffset = this._buffer.getOffsetAt(filterRange.startLineNumber, filterRange.startColumn);
|
| 1320 |
+
const endOffset = this._buffer.getOffsetAt(filterRange.endLineNumber, filterRange.endColumn);
|
| 1321 |
+
return this._decorationsTree.getAllInInterval(this, startOffset, endOffset, filterOwnerId, filterOutValidation, onlyMarginDecorations);
|
| 1322 |
+
}
|
| 1323 |
+
getRangeAt(start, end) {
|
| 1324 |
+
return this._buffer.getRangeAt(start, end - start);
|
| 1325 |
+
}
|
| 1326 |
+
_changeDecorationImpl(decorationId, _range) {
|
| 1327 |
+
const node = this._decorations[decorationId];
|
| 1328 |
+
if (!node) {
|
| 1329 |
+
return;
|
| 1330 |
+
}
|
| 1331 |
+
if (node.options.after) {
|
| 1332 |
+
const oldRange = this.getDecorationRange(decorationId);
|
| 1333 |
+
this._onDidChangeDecorations.recordLineAffectedByInjectedText(oldRange.endLineNumber);
|
| 1334 |
+
}
|
| 1335 |
+
if (node.options.before) {
|
| 1336 |
+
const oldRange = this.getDecorationRange(decorationId);
|
| 1337 |
+
this._onDidChangeDecorations.recordLineAffectedByInjectedText(oldRange.startLineNumber);
|
| 1338 |
+
}
|
| 1339 |
+
const range = this._validateRangeRelaxedNoAllocations(_range);
|
| 1340 |
+
const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);
|
| 1341 |
+
const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);
|
| 1342 |
+
this._decorationsTree.delete(node);
|
| 1343 |
+
node.reset(this.getVersionId(), startOffset, endOffset, range);
|
| 1344 |
+
this._decorationsTree.insert(node);
|
| 1345 |
+
this._onDidChangeDecorations.checkAffectedAndFire(node.options);
|
| 1346 |
+
if (node.options.after) {
|
| 1347 |
+
this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.endLineNumber);
|
| 1348 |
+
}
|
| 1349 |
+
if (node.options.before) {
|
| 1350 |
+
this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.startLineNumber);
|
| 1351 |
+
}
|
| 1352 |
+
}
|
| 1353 |
+
_changeDecorationOptionsImpl(decorationId, options) {
|
| 1354 |
+
const node = this._decorations[decorationId];
|
| 1355 |
+
if (!node) {
|
| 1356 |
+
return;
|
| 1357 |
+
}
|
| 1358 |
+
const nodeWasInOverviewRuler = (node.options.overviewRuler && node.options.overviewRuler.color ? true : false);
|
| 1359 |
+
const nodeIsInOverviewRuler = (options.overviewRuler && options.overviewRuler.color ? true : false);
|
| 1360 |
+
this._onDidChangeDecorations.checkAffectedAndFire(node.options);
|
| 1361 |
+
this._onDidChangeDecorations.checkAffectedAndFire(options);
|
| 1362 |
+
if (node.options.after || options.after) {
|
| 1363 |
+
const nodeRange = this._decorationsTree.getNodeRange(this, node);
|
| 1364 |
+
this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.endLineNumber);
|
| 1365 |
+
}
|
| 1366 |
+
if (node.options.before || options.before) {
|
| 1367 |
+
const nodeRange = this._decorationsTree.getNodeRange(this, node);
|
| 1368 |
+
this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.startLineNumber);
|
| 1369 |
+
}
|
| 1370 |
+
const movedInOverviewRuler = nodeWasInOverviewRuler !== nodeIsInOverviewRuler;
|
| 1371 |
+
const changedWhetherInjectedText = isOptionsInjectedText(options) !== isNodeInjectedText(node);
|
| 1372 |
+
if (movedInOverviewRuler || changedWhetherInjectedText) {
|
| 1373 |
+
this._decorationsTree.delete(node);
|
| 1374 |
+
node.setOptions(options);
|
| 1375 |
+
this._decorationsTree.insert(node);
|
| 1376 |
+
}
|
| 1377 |
+
else {
|
| 1378 |
+
node.setOptions(options);
|
| 1379 |
+
}
|
| 1380 |
+
}
|
| 1381 |
+
_deltaDecorationsImpl(ownerId, oldDecorationsIds, newDecorations, suppressEvents = false) {
|
| 1382 |
+
const versionId = this.getVersionId();
|
| 1383 |
+
const oldDecorationsLen = oldDecorationsIds.length;
|
| 1384 |
+
let oldDecorationIndex = 0;
|
| 1385 |
+
const newDecorationsLen = newDecorations.length;
|
| 1386 |
+
let newDecorationIndex = 0;
|
| 1387 |
+
this._onDidChangeDecorations.beginDeferredEmit();
|
| 1388 |
+
try {
|
| 1389 |
+
const result = new Array(newDecorationsLen);
|
| 1390 |
+
while (oldDecorationIndex < oldDecorationsLen || newDecorationIndex < newDecorationsLen) {
|
| 1391 |
+
let node = null;
|
| 1392 |
+
if (oldDecorationIndex < oldDecorationsLen) {
|
| 1393 |
+
// (1) get ourselves an old node
|
| 1394 |
+
do {
|
| 1395 |
+
node = this._decorations[oldDecorationsIds[oldDecorationIndex++]];
|
| 1396 |
+
} while (!node && oldDecorationIndex < oldDecorationsLen);
|
| 1397 |
+
// (2) remove the node from the tree (if it exists)
|
| 1398 |
+
if (node) {
|
| 1399 |
+
if (node.options.after) {
|
| 1400 |
+
const nodeRange = this._decorationsTree.getNodeRange(this, node);
|
| 1401 |
+
this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.endLineNumber);
|
| 1402 |
+
}
|
| 1403 |
+
if (node.options.before) {
|
| 1404 |
+
const nodeRange = this._decorationsTree.getNodeRange(this, node);
|
| 1405 |
+
this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.startLineNumber);
|
| 1406 |
+
}
|
| 1407 |
+
this._decorationsTree.delete(node);
|
| 1408 |
+
if (!suppressEvents) {
|
| 1409 |
+
this._onDidChangeDecorations.checkAffectedAndFire(node.options);
|
| 1410 |
+
}
|
| 1411 |
+
}
|
| 1412 |
+
}
|
| 1413 |
+
if (newDecorationIndex < newDecorationsLen) {
|
| 1414 |
+
// (3) create a new node if necessary
|
| 1415 |
+
if (!node) {
|
| 1416 |
+
const internalDecorationId = (++this._lastDecorationId);
|
| 1417 |
+
const decorationId = `${this._instanceId};${internalDecorationId}`;
|
| 1418 |
+
node = new IntervalNode(decorationId, 0, 0);
|
| 1419 |
+
this._decorations[decorationId] = node;
|
| 1420 |
+
}
|
| 1421 |
+
// (4) initialize node
|
| 1422 |
+
const newDecoration = newDecorations[newDecorationIndex];
|
| 1423 |
+
const range = this._validateRangeRelaxedNoAllocations(newDecoration.range);
|
| 1424 |
+
const options = _normalizeOptions(newDecoration.options);
|
| 1425 |
+
const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);
|
| 1426 |
+
const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);
|
| 1427 |
+
node.ownerId = ownerId;
|
| 1428 |
+
node.reset(versionId, startOffset, endOffset, range);
|
| 1429 |
+
node.setOptions(options);
|
| 1430 |
+
if (node.options.after) {
|
| 1431 |
+
this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.endLineNumber);
|
| 1432 |
+
}
|
| 1433 |
+
if (node.options.before) {
|
| 1434 |
+
this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.startLineNumber);
|
| 1435 |
+
}
|
| 1436 |
+
if (!suppressEvents) {
|
| 1437 |
+
this._onDidChangeDecorations.checkAffectedAndFire(options);
|
| 1438 |
+
}
|
| 1439 |
+
this._decorationsTree.insert(node);
|
| 1440 |
+
result[newDecorationIndex] = node.id;
|
| 1441 |
+
newDecorationIndex++;
|
| 1442 |
+
}
|
| 1443 |
+
else {
|
| 1444 |
+
if (node) {
|
| 1445 |
+
delete this._decorations[node.id];
|
| 1446 |
+
}
|
| 1447 |
+
}
|
| 1448 |
+
}
|
| 1449 |
+
return result;
|
| 1450 |
+
}
|
| 1451 |
+
finally {
|
| 1452 |
+
this._onDidChangeDecorations.endDeferredEmit();
|
| 1453 |
+
}
|
| 1454 |
+
}
|
| 1455 |
+
//#endregion
|
| 1456 |
+
//#region Tokenization
|
| 1457 |
+
// TODO move them to the tokenization part.
|
| 1458 |
+
getLanguageId() {
|
| 1459 |
+
return this.tokenization.getLanguageId();
|
| 1460 |
+
}
|
| 1461 |
+
setLanguage(languageIdOrSelection, source) {
|
| 1462 |
+
if (typeof languageIdOrSelection === 'string') {
|
| 1463 |
+
this._languageSelectionListener.clear();
|
| 1464 |
+
this._setLanguage(languageIdOrSelection, source);
|
| 1465 |
+
}
|
| 1466 |
+
else {
|
| 1467 |
+
this._languageSelectionListener.value = languageIdOrSelection.onDidChange(() => this._setLanguage(languageIdOrSelection.languageId, source));
|
| 1468 |
+
this._setLanguage(languageIdOrSelection.languageId, source);
|
| 1469 |
+
}
|
| 1470 |
+
}
|
| 1471 |
+
_setLanguage(languageId, source) {
|
| 1472 |
+
this.tokenization.setLanguageId(languageId, source);
|
| 1473 |
+
this._languageService.requestRichLanguageFeatures(languageId);
|
| 1474 |
+
}
|
| 1475 |
+
getLanguageIdAtPosition(lineNumber, column) {
|
| 1476 |
+
return this.tokenization.getLanguageIdAtPosition(lineNumber, column);
|
| 1477 |
+
}
|
| 1478 |
+
getWordAtPosition(position) {
|
| 1479 |
+
return this._tokenizationTextModelPart.getWordAtPosition(position);
|
| 1480 |
+
}
|
| 1481 |
+
getWordUntilPosition(position) {
|
| 1482 |
+
return this._tokenizationTextModelPart.getWordUntilPosition(position);
|
| 1483 |
+
}
|
| 1484 |
+
//#endregion
|
| 1485 |
+
normalizePosition(position, affinity) {
|
| 1486 |
+
return position;
|
| 1487 |
+
}
|
| 1488 |
+
/**
|
| 1489 |
+
* Gets the column at which indentation stops at a given line.
|
| 1490 |
+
* @internal
|
| 1491 |
+
*/
|
| 1492 |
+
getLineIndentColumn(lineNumber) {
|
| 1493 |
+
// Columns start with 1.
|
| 1494 |
+
return indentOfLine(this.getLineContent(lineNumber)) + 1;
|
| 1495 |
+
}
|
| 1496 |
+
};
|
| 1497 |
+
TextModel = TextModel_1 = __decorate([
|
| 1498 |
+
__param(4, IUndoRedoService),
|
| 1499 |
+
__param(5, ILanguageService),
|
| 1500 |
+
__param(6, ILanguageConfigurationService),
|
| 1501 |
+
__param(7, IInstantiationService)
|
| 1502 |
+
], TextModel);
|
| 1503 |
+
export { TextModel };
|
| 1504 |
+
export function indentOfLine(line) {
|
| 1505 |
+
let indent = 0;
|
| 1506 |
+
for (const c of line) {
|
| 1507 |
+
if (c === ' ' || c === '\t') {
|
| 1508 |
+
indent++;
|
| 1509 |
+
}
|
| 1510 |
+
else {
|
| 1511 |
+
break;
|
| 1512 |
+
}
|
| 1513 |
+
}
|
| 1514 |
+
return indent;
|
| 1515 |
+
}
|
| 1516 |
+
//#region Decorations
|
| 1517 |
+
function isNodeInOverviewRuler(node) {
|
| 1518 |
+
return (node.options.overviewRuler && node.options.overviewRuler.color ? true : false);
|
| 1519 |
+
}
|
| 1520 |
+
function isOptionsInjectedText(options) {
|
| 1521 |
+
return !!options.after || !!options.before;
|
| 1522 |
+
}
|
| 1523 |
+
function isNodeInjectedText(node) {
|
| 1524 |
+
return !!node.options.after || !!node.options.before;
|
| 1525 |
+
}
|
| 1526 |
+
class DecorationsTrees {
|
| 1527 |
+
constructor() {
|
| 1528 |
+
this._decorationsTree0 = new IntervalTree();
|
| 1529 |
+
this._decorationsTree1 = new IntervalTree();
|
| 1530 |
+
this._injectedTextDecorationsTree = new IntervalTree();
|
| 1531 |
+
}
|
| 1532 |
+
ensureAllNodesHaveRanges(host) {
|
| 1533 |
+
this.getAll(host, 0, false, false, false);
|
| 1534 |
+
}
|
| 1535 |
+
_ensureNodesHaveRanges(host, nodes) {
|
| 1536 |
+
for (const node of nodes) {
|
| 1537 |
+
if (node.range === null) {
|
| 1538 |
+
node.range = host.getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd);
|
| 1539 |
+
}
|
| 1540 |
+
}
|
| 1541 |
+
return nodes;
|
| 1542 |
+
}
|
| 1543 |
+
getAllInInterval(host, start, end, filterOwnerId, filterOutValidation, onlyMarginDecorations) {
|
| 1544 |
+
const versionId = host.getVersionId();
|
| 1545 |
+
const result = this._intervalSearch(start, end, filterOwnerId, filterOutValidation, versionId, onlyMarginDecorations);
|
| 1546 |
+
return this._ensureNodesHaveRanges(host, result);
|
| 1547 |
+
}
|
| 1548 |
+
_intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations) {
|
| 1549 |
+
const r0 = this._decorationsTree0.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations);
|
| 1550 |
+
const r1 = this._decorationsTree1.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations);
|
| 1551 |
+
const r2 = this._injectedTextDecorationsTree.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations);
|
| 1552 |
+
return r0.concat(r1).concat(r2);
|
| 1553 |
+
}
|
| 1554 |
+
getInjectedTextInInterval(host, start, end, filterOwnerId) {
|
| 1555 |
+
const versionId = host.getVersionId();
|
| 1556 |
+
const result = this._injectedTextDecorationsTree.intervalSearch(start, end, filterOwnerId, false, versionId, false);
|
| 1557 |
+
return this._ensureNodesHaveRanges(host, result).filter((i) => i.options.showIfCollapsed || !i.range.isEmpty());
|
| 1558 |
+
}
|
| 1559 |
+
getAllInjectedText(host, filterOwnerId) {
|
| 1560 |
+
const versionId = host.getVersionId();
|
| 1561 |
+
const result = this._injectedTextDecorationsTree.search(filterOwnerId, false, versionId, false);
|
| 1562 |
+
return this._ensureNodesHaveRanges(host, result).filter((i) => i.options.showIfCollapsed || !i.range.isEmpty());
|
| 1563 |
+
}
|
| 1564 |
+
getAll(host, filterOwnerId, filterOutValidation, overviewRulerOnly, onlyMarginDecorations) {
|
| 1565 |
+
const versionId = host.getVersionId();
|
| 1566 |
+
const result = this._search(filterOwnerId, filterOutValidation, overviewRulerOnly, versionId, onlyMarginDecorations);
|
| 1567 |
+
return this._ensureNodesHaveRanges(host, result);
|
| 1568 |
+
}
|
| 1569 |
+
_search(filterOwnerId, filterOutValidation, overviewRulerOnly, cachedVersionId, onlyMarginDecorations) {
|
| 1570 |
+
if (overviewRulerOnly) {
|
| 1571 |
+
return this._decorationsTree1.search(filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations);
|
| 1572 |
+
}
|
| 1573 |
+
else {
|
| 1574 |
+
const r0 = this._decorationsTree0.search(filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations);
|
| 1575 |
+
const r1 = this._decorationsTree1.search(filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations);
|
| 1576 |
+
const r2 = this._injectedTextDecorationsTree.search(filterOwnerId, filterOutValidation, cachedVersionId, onlyMarginDecorations);
|
| 1577 |
+
return r0.concat(r1).concat(r2);
|
| 1578 |
+
}
|
| 1579 |
+
}
|
| 1580 |
+
collectNodesFromOwner(ownerId) {
|
| 1581 |
+
const r0 = this._decorationsTree0.collectNodesFromOwner(ownerId);
|
| 1582 |
+
const r1 = this._decorationsTree1.collectNodesFromOwner(ownerId);
|
| 1583 |
+
const r2 = this._injectedTextDecorationsTree.collectNodesFromOwner(ownerId);
|
| 1584 |
+
return r0.concat(r1).concat(r2);
|
| 1585 |
+
}
|
| 1586 |
+
collectNodesPostOrder() {
|
| 1587 |
+
const r0 = this._decorationsTree0.collectNodesPostOrder();
|
| 1588 |
+
const r1 = this._decorationsTree1.collectNodesPostOrder();
|
| 1589 |
+
const r2 = this._injectedTextDecorationsTree.collectNodesPostOrder();
|
| 1590 |
+
return r0.concat(r1).concat(r2);
|
| 1591 |
+
}
|
| 1592 |
+
insert(node) {
|
| 1593 |
+
if (isNodeInjectedText(node)) {
|
| 1594 |
+
this._injectedTextDecorationsTree.insert(node);
|
| 1595 |
+
}
|
| 1596 |
+
else if (isNodeInOverviewRuler(node)) {
|
| 1597 |
+
this._decorationsTree1.insert(node);
|
| 1598 |
+
}
|
| 1599 |
+
else {
|
| 1600 |
+
this._decorationsTree0.insert(node);
|
| 1601 |
+
}
|
| 1602 |
+
}
|
| 1603 |
+
delete(node) {
|
| 1604 |
+
if (isNodeInjectedText(node)) {
|
| 1605 |
+
this._injectedTextDecorationsTree.delete(node);
|
| 1606 |
+
}
|
| 1607 |
+
else if (isNodeInOverviewRuler(node)) {
|
| 1608 |
+
this._decorationsTree1.delete(node);
|
| 1609 |
+
}
|
| 1610 |
+
else {
|
| 1611 |
+
this._decorationsTree0.delete(node);
|
| 1612 |
+
}
|
| 1613 |
+
}
|
| 1614 |
+
getNodeRange(host, node) {
|
| 1615 |
+
const versionId = host.getVersionId();
|
| 1616 |
+
if (node.cachedVersionId !== versionId) {
|
| 1617 |
+
this._resolveNode(node, versionId);
|
| 1618 |
+
}
|
| 1619 |
+
if (node.range === null) {
|
| 1620 |
+
node.range = host.getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd);
|
| 1621 |
+
}
|
| 1622 |
+
return node.range;
|
| 1623 |
+
}
|
| 1624 |
+
_resolveNode(node, cachedVersionId) {
|
| 1625 |
+
if (isNodeInjectedText(node)) {
|
| 1626 |
+
this._injectedTextDecorationsTree.resolveNode(node, cachedVersionId);
|
| 1627 |
+
}
|
| 1628 |
+
else if (isNodeInOverviewRuler(node)) {
|
| 1629 |
+
this._decorationsTree1.resolveNode(node, cachedVersionId);
|
| 1630 |
+
}
|
| 1631 |
+
else {
|
| 1632 |
+
this._decorationsTree0.resolveNode(node, cachedVersionId);
|
| 1633 |
+
}
|
| 1634 |
+
}
|
| 1635 |
+
acceptReplace(offset, length, textLength, forceMoveMarkers) {
|
| 1636 |
+
this._decorationsTree0.acceptReplace(offset, length, textLength, forceMoveMarkers);
|
| 1637 |
+
this._decorationsTree1.acceptReplace(offset, length, textLength, forceMoveMarkers);
|
| 1638 |
+
this._injectedTextDecorationsTree.acceptReplace(offset, length, textLength, forceMoveMarkers);
|
| 1639 |
+
}
|
| 1640 |
+
}
|
| 1641 |
+
function cleanClassName(className) {
|
| 1642 |
+
return className.replace(/[^a-z0-9\-_]/gi, ' ');
|
| 1643 |
+
}
|
| 1644 |
+
class DecorationOptions {
|
| 1645 |
+
constructor(options) {
|
| 1646 |
+
this.color = options.color || '';
|
| 1647 |
+
this.darkColor = options.darkColor || '';
|
| 1648 |
+
}
|
| 1649 |
+
}
|
| 1650 |
+
export class ModelDecorationOverviewRulerOptions extends DecorationOptions {
|
| 1651 |
+
constructor(options) {
|
| 1652 |
+
super(options);
|
| 1653 |
+
this._resolvedColor = null;
|
| 1654 |
+
this.position = (typeof options.position === 'number' ? options.position : model.OverviewRulerLane.Center);
|
| 1655 |
+
}
|
| 1656 |
+
getColor(theme) {
|
| 1657 |
+
if (!this._resolvedColor) {
|
| 1658 |
+
if (theme.type !== 'light' && this.darkColor) {
|
| 1659 |
+
this._resolvedColor = this._resolveColor(this.darkColor, theme);
|
| 1660 |
+
}
|
| 1661 |
+
else {
|
| 1662 |
+
this._resolvedColor = this._resolveColor(this.color, theme);
|
| 1663 |
+
}
|
| 1664 |
+
}
|
| 1665 |
+
return this._resolvedColor;
|
| 1666 |
+
}
|
| 1667 |
+
invalidateCachedColor() {
|
| 1668 |
+
this._resolvedColor = null;
|
| 1669 |
+
}
|
| 1670 |
+
_resolveColor(color, theme) {
|
| 1671 |
+
if (typeof color === 'string') {
|
| 1672 |
+
return color;
|
| 1673 |
+
}
|
| 1674 |
+
const c = color ? theme.getColor(color.id) : null;
|
| 1675 |
+
if (!c) {
|
| 1676 |
+
return '';
|
| 1677 |
+
}
|
| 1678 |
+
return c.toString();
|
| 1679 |
+
}
|
| 1680 |
+
}
|
| 1681 |
+
export class ModelDecorationGlyphMarginOptions {
|
| 1682 |
+
constructor(options) {
|
| 1683 |
+
this.position = options?.position ?? model.GlyphMarginLane.Center;
|
| 1684 |
+
this.persistLane = options?.persistLane;
|
| 1685 |
+
}
|
| 1686 |
+
}
|
| 1687 |
+
export class ModelDecorationMinimapOptions extends DecorationOptions {
|
| 1688 |
+
constructor(options) {
|
| 1689 |
+
super(options);
|
| 1690 |
+
this.position = options.position;
|
| 1691 |
+
this.sectionHeaderStyle = options.sectionHeaderStyle ?? null;
|
| 1692 |
+
this.sectionHeaderText = options.sectionHeaderText ?? null;
|
| 1693 |
+
}
|
| 1694 |
+
getColor(theme) {
|
| 1695 |
+
if (!this._resolvedColor) {
|
| 1696 |
+
if (theme.type !== 'light' && this.darkColor) {
|
| 1697 |
+
this._resolvedColor = this._resolveColor(this.darkColor, theme);
|
| 1698 |
+
}
|
| 1699 |
+
else {
|
| 1700 |
+
this._resolvedColor = this._resolveColor(this.color, theme);
|
| 1701 |
+
}
|
| 1702 |
+
}
|
| 1703 |
+
return this._resolvedColor;
|
| 1704 |
+
}
|
| 1705 |
+
invalidateCachedColor() {
|
| 1706 |
+
this._resolvedColor = undefined;
|
| 1707 |
+
}
|
| 1708 |
+
_resolveColor(color, theme) {
|
| 1709 |
+
if (typeof color === 'string') {
|
| 1710 |
+
return Color.fromHex(color);
|
| 1711 |
+
}
|
| 1712 |
+
return theme.getColor(color.id);
|
| 1713 |
+
}
|
| 1714 |
+
}
|
| 1715 |
+
export class ModelDecorationInjectedTextOptions {
|
| 1716 |
+
static from(options) {
|
| 1717 |
+
if (options instanceof ModelDecorationInjectedTextOptions) {
|
| 1718 |
+
return options;
|
| 1719 |
+
}
|
| 1720 |
+
return new ModelDecorationInjectedTextOptions(options);
|
| 1721 |
+
}
|
| 1722 |
+
constructor(options) {
|
| 1723 |
+
this.content = options.content || '';
|
| 1724 |
+
this.inlineClassName = options.inlineClassName || null;
|
| 1725 |
+
this.inlineClassNameAffectsLetterSpacing = options.inlineClassNameAffectsLetterSpacing || false;
|
| 1726 |
+
this.attachedData = options.attachedData || null;
|
| 1727 |
+
this.cursorStops = options.cursorStops || null;
|
| 1728 |
+
}
|
| 1729 |
+
}
|
| 1730 |
+
export class ModelDecorationOptions {
|
| 1731 |
+
static register(options) {
|
| 1732 |
+
return new ModelDecorationOptions(options);
|
| 1733 |
+
}
|
| 1734 |
+
static createDynamic(options) {
|
| 1735 |
+
return new ModelDecorationOptions(options);
|
| 1736 |
+
}
|
| 1737 |
+
constructor(options) {
|
| 1738 |
+
this.description = options.description;
|
| 1739 |
+
this.blockClassName = options.blockClassName ? cleanClassName(options.blockClassName) : null;
|
| 1740 |
+
this.blockDoesNotCollapse = options.blockDoesNotCollapse ?? null;
|
| 1741 |
+
this.blockIsAfterEnd = options.blockIsAfterEnd ?? null;
|
| 1742 |
+
this.blockPadding = options.blockPadding ?? null;
|
| 1743 |
+
this.stickiness = options.stickiness || 0 /* model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges */;
|
| 1744 |
+
this.zIndex = options.zIndex || 0;
|
| 1745 |
+
this.className = options.className ? cleanClassName(options.className) : null;
|
| 1746 |
+
this.shouldFillLineOnLineBreak = options.shouldFillLineOnLineBreak ?? null;
|
| 1747 |
+
this.hoverMessage = options.hoverMessage || null;
|
| 1748 |
+
this.glyphMarginHoverMessage = options.glyphMarginHoverMessage || null;
|
| 1749 |
+
this.lineNumberHoverMessage = options.lineNumberHoverMessage || null;
|
| 1750 |
+
this.isWholeLine = options.isWholeLine || false;
|
| 1751 |
+
this.showIfCollapsed = options.showIfCollapsed || false;
|
| 1752 |
+
this.collapseOnReplaceEdit = options.collapseOnReplaceEdit || false;
|
| 1753 |
+
this.overviewRuler = options.overviewRuler ? new ModelDecorationOverviewRulerOptions(options.overviewRuler) : null;
|
| 1754 |
+
this.minimap = options.minimap ? new ModelDecorationMinimapOptions(options.minimap) : null;
|
| 1755 |
+
this.glyphMargin = options.glyphMarginClassName ? new ModelDecorationGlyphMarginOptions(options.glyphMargin) : null;
|
| 1756 |
+
this.glyphMarginClassName = options.glyphMarginClassName ? cleanClassName(options.glyphMarginClassName) : null;
|
| 1757 |
+
this.linesDecorationsClassName = options.linesDecorationsClassName ? cleanClassName(options.linesDecorationsClassName) : null;
|
| 1758 |
+
this.lineNumberClassName = options.lineNumberClassName ? cleanClassName(options.lineNumberClassName) : null;
|
| 1759 |
+
this.linesDecorationsTooltip = options.linesDecorationsTooltip ? strings.htmlAttributeEncodeValue(options.linesDecorationsTooltip) : null;
|
| 1760 |
+
this.firstLineDecorationClassName = options.firstLineDecorationClassName ? cleanClassName(options.firstLineDecorationClassName) : null;
|
| 1761 |
+
this.marginClassName = options.marginClassName ? cleanClassName(options.marginClassName) : null;
|
| 1762 |
+
this.inlineClassName = options.inlineClassName ? cleanClassName(options.inlineClassName) : null;
|
| 1763 |
+
this.inlineClassNameAffectsLetterSpacing = options.inlineClassNameAffectsLetterSpacing || false;
|
| 1764 |
+
this.beforeContentClassName = options.beforeContentClassName ? cleanClassName(options.beforeContentClassName) : null;
|
| 1765 |
+
this.afterContentClassName = options.afterContentClassName ? cleanClassName(options.afterContentClassName) : null;
|
| 1766 |
+
this.after = options.after ? ModelDecorationInjectedTextOptions.from(options.after) : null;
|
| 1767 |
+
this.before = options.before ? ModelDecorationInjectedTextOptions.from(options.before) : null;
|
| 1768 |
+
this.hideInCommentTokens = options.hideInCommentTokens ?? false;
|
| 1769 |
+
this.hideInStringTokens = options.hideInStringTokens ?? false;
|
| 1770 |
+
}
|
| 1771 |
+
}
|
| 1772 |
+
ModelDecorationOptions.EMPTY = ModelDecorationOptions.register({ description: 'empty' });
|
| 1773 |
+
/**
|
| 1774 |
+
* The order carefully matches the values of the enum.
|
| 1775 |
+
*/
|
| 1776 |
+
const TRACKED_RANGE_OPTIONS = [
|
| 1777 |
+
ModelDecorationOptions.register({ description: 'tracked-range-always-grows-when-typing-at-edges', stickiness: 0 /* model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges */ }),
|
| 1778 |
+
ModelDecorationOptions.register({ description: 'tracked-range-never-grows-when-typing-at-edges', stickiness: 1 /* model.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */ }),
|
| 1779 |
+
ModelDecorationOptions.register({ description: 'tracked-range-grows-only-when-typing-before', stickiness: 2 /* model.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore */ }),
|
| 1780 |
+
ModelDecorationOptions.register({ description: 'tracked-range-grows-only-when-typing-after', stickiness: 3 /* model.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter */ }),
|
| 1781 |
+
];
|
| 1782 |
+
function _normalizeOptions(options) {
|
| 1783 |
+
if (options instanceof ModelDecorationOptions) {
|
| 1784 |
+
return options;
|
| 1785 |
+
}
|
| 1786 |
+
return ModelDecorationOptions.createDynamic(options);
|
| 1787 |
+
}
|
| 1788 |
+
class DidChangeDecorationsEmitter extends Disposable {
|
| 1789 |
+
constructor(handleBeforeFire) {
|
| 1790 |
+
super();
|
| 1791 |
+
this.handleBeforeFire = handleBeforeFire;
|
| 1792 |
+
this._actual = this._register(new Emitter());
|
| 1793 |
+
this.event = this._actual.event;
|
| 1794 |
+
this._affectedInjectedTextLines = null;
|
| 1795 |
+
this._deferredCnt = 0;
|
| 1796 |
+
this._shouldFireDeferred = false;
|
| 1797 |
+
this._affectsMinimap = false;
|
| 1798 |
+
this._affectsOverviewRuler = false;
|
| 1799 |
+
this._affectsGlyphMargin = false;
|
| 1800 |
+
this._affectsLineNumber = false;
|
| 1801 |
+
}
|
| 1802 |
+
beginDeferredEmit() {
|
| 1803 |
+
this._deferredCnt++;
|
| 1804 |
+
}
|
| 1805 |
+
endDeferredEmit() {
|
| 1806 |
+
this._deferredCnt--;
|
| 1807 |
+
if (this._deferredCnt === 0) {
|
| 1808 |
+
if (this._shouldFireDeferred) {
|
| 1809 |
+
this.doFire();
|
| 1810 |
+
}
|
| 1811 |
+
this._affectedInjectedTextLines?.clear();
|
| 1812 |
+
this._affectedInjectedTextLines = null;
|
| 1813 |
+
}
|
| 1814 |
+
}
|
| 1815 |
+
recordLineAffectedByInjectedText(lineNumber) {
|
| 1816 |
+
if (!this._affectedInjectedTextLines) {
|
| 1817 |
+
this._affectedInjectedTextLines = new Set();
|
| 1818 |
+
}
|
| 1819 |
+
this._affectedInjectedTextLines.add(lineNumber);
|
| 1820 |
+
}
|
| 1821 |
+
checkAffectedAndFire(options) {
|
| 1822 |
+
this._affectsMinimap ||= !!options.minimap?.position;
|
| 1823 |
+
this._affectsOverviewRuler ||= !!options.overviewRuler?.color;
|
| 1824 |
+
this._affectsGlyphMargin ||= !!options.glyphMarginClassName;
|
| 1825 |
+
this._affectsLineNumber ||= !!options.lineNumberClassName;
|
| 1826 |
+
this.tryFire();
|
| 1827 |
+
}
|
| 1828 |
+
fire() {
|
| 1829 |
+
this._affectsMinimap = true;
|
| 1830 |
+
this._affectsOverviewRuler = true;
|
| 1831 |
+
this._affectsGlyphMargin = true;
|
| 1832 |
+
this.tryFire();
|
| 1833 |
+
}
|
| 1834 |
+
tryFire() {
|
| 1835 |
+
if (this._deferredCnt === 0) {
|
| 1836 |
+
this.doFire();
|
| 1837 |
+
}
|
| 1838 |
+
else {
|
| 1839 |
+
this._shouldFireDeferred = true;
|
| 1840 |
+
}
|
| 1841 |
+
}
|
| 1842 |
+
doFire() {
|
| 1843 |
+
this.handleBeforeFire(this._affectedInjectedTextLines);
|
| 1844 |
+
const event = {
|
| 1845 |
+
affectsMinimap: this._affectsMinimap,
|
| 1846 |
+
affectsOverviewRuler: this._affectsOverviewRuler,
|
| 1847 |
+
affectsGlyphMargin: this._affectsGlyphMargin,
|
| 1848 |
+
affectsLineNumber: this._affectsLineNumber,
|
| 1849 |
+
};
|
| 1850 |
+
this._shouldFireDeferred = false;
|
| 1851 |
+
this._affectsMinimap = false;
|
| 1852 |
+
this._affectsOverviewRuler = false;
|
| 1853 |
+
this._affectsGlyphMargin = false;
|
| 1854 |
+
this._actual.fire(event);
|
| 1855 |
+
}
|
| 1856 |
+
}
|
| 1857 |
+
//#endregion
|
| 1858 |
+
class DidChangeContentEmitter extends Disposable {
|
| 1859 |
+
constructor() {
|
| 1860 |
+
super();
|
| 1861 |
+
/**
|
| 1862 |
+
* Both `fastEvent` and `slowEvent` work the same way and contain the same events, but first we invoke `fastEvent` and then `slowEvent`.
|
| 1863 |
+
*/
|
| 1864 |
+
this._fastEmitter = this._register(new Emitter());
|
| 1865 |
+
this.fastEvent = this._fastEmitter.event;
|
| 1866 |
+
this._slowEmitter = this._register(new Emitter());
|
| 1867 |
+
this.slowEvent = this._slowEmitter.event;
|
| 1868 |
+
this._deferredCnt = 0;
|
| 1869 |
+
this._deferredEvent = null;
|
| 1870 |
+
}
|
| 1871 |
+
beginDeferredEmit() {
|
| 1872 |
+
this._deferredCnt++;
|
| 1873 |
+
}
|
| 1874 |
+
endDeferredEmit(resultingSelection = null) {
|
| 1875 |
+
this._deferredCnt--;
|
| 1876 |
+
if (this._deferredCnt === 0) {
|
| 1877 |
+
if (this._deferredEvent !== null) {
|
| 1878 |
+
this._deferredEvent.rawContentChangedEvent.resultingSelection = resultingSelection;
|
| 1879 |
+
const e = this._deferredEvent;
|
| 1880 |
+
this._deferredEvent = null;
|
| 1881 |
+
this._fastEmitter.fire(e);
|
| 1882 |
+
this._slowEmitter.fire(e);
|
| 1883 |
+
}
|
| 1884 |
+
}
|
| 1885 |
+
}
|
| 1886 |
+
fire(e) {
|
| 1887 |
+
if (this._deferredCnt > 0) {
|
| 1888 |
+
if (this._deferredEvent) {
|
| 1889 |
+
this._deferredEvent = this._deferredEvent.merge(e);
|
| 1890 |
+
}
|
| 1891 |
+
else {
|
| 1892 |
+
this._deferredEvent = e;
|
| 1893 |
+
}
|
| 1894 |
+
return;
|
| 1895 |
+
}
|
| 1896 |
+
this._fastEmitter.fire(e);
|
| 1897 |
+
this._slowEmitter.fire(e);
|
| 1898 |
+
}
|
| 1899 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/textModelPart.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { Disposable } from '../../../base/common/lifecycle.js';
|
| 6 |
+
export class TextModelPart extends Disposable {
|
| 7 |
+
constructor() {
|
| 8 |
+
super(...arguments);
|
| 9 |
+
this._isDisposed = false;
|
| 10 |
+
}
|
| 11 |
+
dispose() {
|
| 12 |
+
super.dispose();
|
| 13 |
+
this._isDisposed = true;
|
| 14 |
+
}
|
| 15 |
+
assertNotDisposed() {
|
| 16 |
+
if (this._isDisposed) {
|
| 17 |
+
throw new Error('TextModelPart is disposed!');
|
| 18 |
+
}
|
| 19 |
+
}
|
| 20 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/textModelSearch.js
ADDED
|
@@ -0,0 +1,452 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import * as strings from '../../../base/common/strings.js';
|
| 6 |
+
import { getMapForWordSeparators } from '../core/wordCharacterClassifier.js';
|
| 7 |
+
import { Position } from '../core/position.js';
|
| 8 |
+
import { Range } from '../core/range.js';
|
| 9 |
+
import { FindMatch, SearchData } from '../model.js';
|
| 10 |
+
const LIMIT_FIND_COUNT = 999;
|
| 11 |
+
export class SearchParams {
|
| 12 |
+
constructor(searchString, isRegex, matchCase, wordSeparators) {
|
| 13 |
+
this.searchString = searchString;
|
| 14 |
+
this.isRegex = isRegex;
|
| 15 |
+
this.matchCase = matchCase;
|
| 16 |
+
this.wordSeparators = wordSeparators;
|
| 17 |
+
}
|
| 18 |
+
parseSearchRequest() {
|
| 19 |
+
if (this.searchString === '') {
|
| 20 |
+
return null;
|
| 21 |
+
}
|
| 22 |
+
// Try to create a RegExp out of the params
|
| 23 |
+
let multiline;
|
| 24 |
+
if (this.isRegex) {
|
| 25 |
+
multiline = isMultilineRegexSource(this.searchString);
|
| 26 |
+
}
|
| 27 |
+
else {
|
| 28 |
+
multiline = (this.searchString.indexOf('\n') >= 0);
|
| 29 |
+
}
|
| 30 |
+
let regex = null;
|
| 31 |
+
try {
|
| 32 |
+
regex = strings.createRegExp(this.searchString, this.isRegex, {
|
| 33 |
+
matchCase: this.matchCase,
|
| 34 |
+
wholeWord: false,
|
| 35 |
+
multiline: multiline,
|
| 36 |
+
global: true,
|
| 37 |
+
unicode: true
|
| 38 |
+
});
|
| 39 |
+
}
|
| 40 |
+
catch (err) {
|
| 41 |
+
return null;
|
| 42 |
+
}
|
| 43 |
+
if (!regex) {
|
| 44 |
+
return null;
|
| 45 |
+
}
|
| 46 |
+
let canUseSimpleSearch = (!this.isRegex && !multiline);
|
| 47 |
+
if (canUseSimpleSearch && this.searchString.toLowerCase() !== this.searchString.toUpperCase()) {
|
| 48 |
+
// casing might make a difference
|
| 49 |
+
canUseSimpleSearch = this.matchCase;
|
| 50 |
+
}
|
| 51 |
+
return new SearchData(regex, this.wordSeparators ? getMapForWordSeparators(this.wordSeparators, []) : null, canUseSimpleSearch ? this.searchString : null);
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
export function isMultilineRegexSource(searchString) {
|
| 55 |
+
if (!searchString || searchString.length === 0) {
|
| 56 |
+
return false;
|
| 57 |
+
}
|
| 58 |
+
for (let i = 0, len = searchString.length; i < len; i++) {
|
| 59 |
+
const chCode = searchString.charCodeAt(i);
|
| 60 |
+
if (chCode === 10 /* CharCode.LineFeed */) {
|
| 61 |
+
return true;
|
| 62 |
+
}
|
| 63 |
+
if (chCode === 92 /* CharCode.Backslash */) {
|
| 64 |
+
// move to next char
|
| 65 |
+
i++;
|
| 66 |
+
if (i >= len) {
|
| 67 |
+
// string ends with a \
|
| 68 |
+
break;
|
| 69 |
+
}
|
| 70 |
+
const nextChCode = searchString.charCodeAt(i);
|
| 71 |
+
if (nextChCode === 110 /* CharCode.n */ || nextChCode === 114 /* CharCode.r */ || nextChCode === 87 /* CharCode.W */) {
|
| 72 |
+
return true;
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
}
|
| 76 |
+
return false;
|
| 77 |
+
}
|
| 78 |
+
export function createFindMatch(range, rawMatches, captureMatches) {
|
| 79 |
+
if (!captureMatches) {
|
| 80 |
+
return new FindMatch(range, null);
|
| 81 |
+
}
|
| 82 |
+
const matches = [];
|
| 83 |
+
for (let i = 0, len = rawMatches.length; i < len; i++) {
|
| 84 |
+
matches[i] = rawMatches[i];
|
| 85 |
+
}
|
| 86 |
+
return new FindMatch(range, matches);
|
| 87 |
+
}
|
| 88 |
+
class LineFeedCounter {
|
| 89 |
+
constructor(text) {
|
| 90 |
+
const lineFeedsOffsets = [];
|
| 91 |
+
let lineFeedsOffsetsLen = 0;
|
| 92 |
+
for (let i = 0, textLen = text.length; i < textLen; i++) {
|
| 93 |
+
if (text.charCodeAt(i) === 10 /* CharCode.LineFeed */) {
|
| 94 |
+
lineFeedsOffsets[lineFeedsOffsetsLen++] = i;
|
| 95 |
+
}
|
| 96 |
+
}
|
| 97 |
+
this._lineFeedsOffsets = lineFeedsOffsets;
|
| 98 |
+
}
|
| 99 |
+
findLineFeedCountBeforeOffset(offset) {
|
| 100 |
+
const lineFeedsOffsets = this._lineFeedsOffsets;
|
| 101 |
+
let min = 0;
|
| 102 |
+
let max = lineFeedsOffsets.length - 1;
|
| 103 |
+
if (max === -1) {
|
| 104 |
+
// no line feeds
|
| 105 |
+
return 0;
|
| 106 |
+
}
|
| 107 |
+
if (offset <= lineFeedsOffsets[0]) {
|
| 108 |
+
// before first line feed
|
| 109 |
+
return 0;
|
| 110 |
+
}
|
| 111 |
+
while (min < max) {
|
| 112 |
+
const mid = min + ((max - min) / 2 >> 0);
|
| 113 |
+
if (lineFeedsOffsets[mid] >= offset) {
|
| 114 |
+
max = mid - 1;
|
| 115 |
+
}
|
| 116 |
+
else {
|
| 117 |
+
if (lineFeedsOffsets[mid + 1] >= offset) {
|
| 118 |
+
// bingo!
|
| 119 |
+
min = mid;
|
| 120 |
+
max = mid;
|
| 121 |
+
}
|
| 122 |
+
else {
|
| 123 |
+
min = mid + 1;
|
| 124 |
+
}
|
| 125 |
+
}
|
| 126 |
+
}
|
| 127 |
+
return min + 1;
|
| 128 |
+
}
|
| 129 |
+
}
|
| 130 |
+
export class TextModelSearch {
|
| 131 |
+
static findMatches(model, searchParams, searchRange, captureMatches, limitResultCount) {
|
| 132 |
+
const searchData = searchParams.parseSearchRequest();
|
| 133 |
+
if (!searchData) {
|
| 134 |
+
return [];
|
| 135 |
+
}
|
| 136 |
+
if (searchData.regex.multiline) {
|
| 137 |
+
return this._doFindMatchesMultiline(model, searchRange, new Searcher(searchData.wordSeparators, searchData.regex), captureMatches, limitResultCount);
|
| 138 |
+
}
|
| 139 |
+
return this._doFindMatchesLineByLine(model, searchRange, searchData, captureMatches, limitResultCount);
|
| 140 |
+
}
|
| 141 |
+
/**
|
| 142 |
+
* Multiline search always executes on the lines concatenated with \n.
|
| 143 |
+
* We must therefore compensate for the count of \n in case the model is CRLF
|
| 144 |
+
*/
|
| 145 |
+
static _getMultilineMatchRange(model, deltaOffset, text, lfCounter, matchIndex, match0) {
|
| 146 |
+
let startOffset;
|
| 147 |
+
let lineFeedCountBeforeMatch = 0;
|
| 148 |
+
if (lfCounter) {
|
| 149 |
+
lineFeedCountBeforeMatch = lfCounter.findLineFeedCountBeforeOffset(matchIndex);
|
| 150 |
+
startOffset = deltaOffset + matchIndex + lineFeedCountBeforeMatch /* add as many \r as there were \n */;
|
| 151 |
+
}
|
| 152 |
+
else {
|
| 153 |
+
startOffset = deltaOffset + matchIndex;
|
| 154 |
+
}
|
| 155 |
+
let endOffset;
|
| 156 |
+
if (lfCounter) {
|
| 157 |
+
const lineFeedCountBeforeEndOfMatch = lfCounter.findLineFeedCountBeforeOffset(matchIndex + match0.length);
|
| 158 |
+
const lineFeedCountInMatch = lineFeedCountBeforeEndOfMatch - lineFeedCountBeforeMatch;
|
| 159 |
+
endOffset = startOffset + match0.length + lineFeedCountInMatch /* add as many \r as there were \n */;
|
| 160 |
+
}
|
| 161 |
+
else {
|
| 162 |
+
endOffset = startOffset + match0.length;
|
| 163 |
+
}
|
| 164 |
+
const startPosition = model.getPositionAt(startOffset);
|
| 165 |
+
const endPosition = model.getPositionAt(endOffset);
|
| 166 |
+
return new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column);
|
| 167 |
+
}
|
| 168 |
+
static _doFindMatchesMultiline(model, searchRange, searcher, captureMatches, limitResultCount) {
|
| 169 |
+
const deltaOffset = model.getOffsetAt(searchRange.getStartPosition());
|
| 170 |
+
// We always execute multiline search over the lines joined with \n
|
| 171 |
+
// This makes it that \n will match the EOL for both CRLF and LF models
|
| 172 |
+
// We compensate for offset errors in `_getMultilineMatchRange`
|
| 173 |
+
const text = model.getValueInRange(searchRange, 1 /* EndOfLinePreference.LF */);
|
| 174 |
+
const lfCounter = (model.getEOL() === '\r\n' ? new LineFeedCounter(text) : null);
|
| 175 |
+
const result = [];
|
| 176 |
+
let counter = 0;
|
| 177 |
+
let m;
|
| 178 |
+
searcher.reset(0);
|
| 179 |
+
while ((m = searcher.next(text))) {
|
| 180 |
+
result[counter++] = createFindMatch(this._getMultilineMatchRange(model, deltaOffset, text, lfCounter, m.index, m[0]), m, captureMatches);
|
| 181 |
+
if (counter >= limitResultCount) {
|
| 182 |
+
return result;
|
| 183 |
+
}
|
| 184 |
+
}
|
| 185 |
+
return result;
|
| 186 |
+
}
|
| 187 |
+
static _doFindMatchesLineByLine(model, searchRange, searchData, captureMatches, limitResultCount) {
|
| 188 |
+
const result = [];
|
| 189 |
+
let resultLen = 0;
|
| 190 |
+
// Early case for a search range that starts & stops on the same line number
|
| 191 |
+
if (searchRange.startLineNumber === searchRange.endLineNumber) {
|
| 192 |
+
const text = model.getLineContent(searchRange.startLineNumber).substring(searchRange.startColumn - 1, searchRange.endColumn - 1);
|
| 193 |
+
resultLen = this._findMatchesInLine(searchData, text, searchRange.startLineNumber, searchRange.startColumn - 1, resultLen, result, captureMatches, limitResultCount);
|
| 194 |
+
return result;
|
| 195 |
+
}
|
| 196 |
+
// Collect results from first line
|
| 197 |
+
const text = model.getLineContent(searchRange.startLineNumber).substring(searchRange.startColumn - 1);
|
| 198 |
+
resultLen = this._findMatchesInLine(searchData, text, searchRange.startLineNumber, searchRange.startColumn - 1, resultLen, result, captureMatches, limitResultCount);
|
| 199 |
+
// Collect results from middle lines
|
| 200 |
+
for (let lineNumber = searchRange.startLineNumber + 1; lineNumber < searchRange.endLineNumber && resultLen < limitResultCount; lineNumber++) {
|
| 201 |
+
resultLen = this._findMatchesInLine(searchData, model.getLineContent(lineNumber), lineNumber, 0, resultLen, result, captureMatches, limitResultCount);
|
| 202 |
+
}
|
| 203 |
+
// Collect results from last line
|
| 204 |
+
if (resultLen < limitResultCount) {
|
| 205 |
+
const text = model.getLineContent(searchRange.endLineNumber).substring(0, searchRange.endColumn - 1);
|
| 206 |
+
resultLen = this._findMatchesInLine(searchData, text, searchRange.endLineNumber, 0, resultLen, result, captureMatches, limitResultCount);
|
| 207 |
+
}
|
| 208 |
+
return result;
|
| 209 |
+
}
|
| 210 |
+
static _findMatchesInLine(searchData, text, lineNumber, deltaOffset, resultLen, result, captureMatches, limitResultCount) {
|
| 211 |
+
const wordSeparators = searchData.wordSeparators;
|
| 212 |
+
if (!captureMatches && searchData.simpleSearch) {
|
| 213 |
+
const searchString = searchData.simpleSearch;
|
| 214 |
+
const searchStringLen = searchString.length;
|
| 215 |
+
const textLength = text.length;
|
| 216 |
+
let lastMatchIndex = -searchStringLen;
|
| 217 |
+
while ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {
|
| 218 |
+
if (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {
|
| 219 |
+
result[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);
|
| 220 |
+
if (resultLen >= limitResultCount) {
|
| 221 |
+
return resultLen;
|
| 222 |
+
}
|
| 223 |
+
}
|
| 224 |
+
}
|
| 225 |
+
return resultLen;
|
| 226 |
+
}
|
| 227 |
+
const searcher = new Searcher(searchData.wordSeparators, searchData.regex);
|
| 228 |
+
let m;
|
| 229 |
+
// Reset regex to search from the beginning
|
| 230 |
+
searcher.reset(0);
|
| 231 |
+
do {
|
| 232 |
+
m = searcher.next(text);
|
| 233 |
+
if (m) {
|
| 234 |
+
result[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);
|
| 235 |
+
if (resultLen >= limitResultCount) {
|
| 236 |
+
return resultLen;
|
| 237 |
+
}
|
| 238 |
+
}
|
| 239 |
+
} while (m);
|
| 240 |
+
return resultLen;
|
| 241 |
+
}
|
| 242 |
+
static findNextMatch(model, searchParams, searchStart, captureMatches) {
|
| 243 |
+
const searchData = searchParams.parseSearchRequest();
|
| 244 |
+
if (!searchData) {
|
| 245 |
+
return null;
|
| 246 |
+
}
|
| 247 |
+
const searcher = new Searcher(searchData.wordSeparators, searchData.regex);
|
| 248 |
+
if (searchData.regex.multiline) {
|
| 249 |
+
return this._doFindNextMatchMultiline(model, searchStart, searcher, captureMatches);
|
| 250 |
+
}
|
| 251 |
+
return this._doFindNextMatchLineByLine(model, searchStart, searcher, captureMatches);
|
| 252 |
+
}
|
| 253 |
+
static _doFindNextMatchMultiline(model, searchStart, searcher, captureMatches) {
|
| 254 |
+
const searchTextStart = new Position(searchStart.lineNumber, 1);
|
| 255 |
+
const deltaOffset = model.getOffsetAt(searchTextStart);
|
| 256 |
+
const lineCount = model.getLineCount();
|
| 257 |
+
// We always execute multiline search over the lines joined with \n
|
| 258 |
+
// This makes it that \n will match the EOL for both CRLF and LF models
|
| 259 |
+
// We compensate for offset errors in `_getMultilineMatchRange`
|
| 260 |
+
const text = model.getValueInRange(new Range(searchTextStart.lineNumber, searchTextStart.column, lineCount, model.getLineMaxColumn(lineCount)), 1 /* EndOfLinePreference.LF */);
|
| 261 |
+
const lfCounter = (model.getEOL() === '\r\n' ? new LineFeedCounter(text) : null);
|
| 262 |
+
searcher.reset(searchStart.column - 1);
|
| 263 |
+
const m = searcher.next(text);
|
| 264 |
+
if (m) {
|
| 265 |
+
return createFindMatch(this._getMultilineMatchRange(model, deltaOffset, text, lfCounter, m.index, m[0]), m, captureMatches);
|
| 266 |
+
}
|
| 267 |
+
if (searchStart.lineNumber !== 1 || searchStart.column !== 1) {
|
| 268 |
+
// Try again from the top
|
| 269 |
+
return this._doFindNextMatchMultiline(model, new Position(1, 1), searcher, captureMatches);
|
| 270 |
+
}
|
| 271 |
+
return null;
|
| 272 |
+
}
|
| 273 |
+
static _doFindNextMatchLineByLine(model, searchStart, searcher, captureMatches) {
|
| 274 |
+
const lineCount = model.getLineCount();
|
| 275 |
+
const startLineNumber = searchStart.lineNumber;
|
| 276 |
+
// Look in first line
|
| 277 |
+
const text = model.getLineContent(startLineNumber);
|
| 278 |
+
const r = this._findFirstMatchInLine(searcher, text, startLineNumber, searchStart.column, captureMatches);
|
| 279 |
+
if (r) {
|
| 280 |
+
return r;
|
| 281 |
+
}
|
| 282 |
+
for (let i = 1; i <= lineCount; i++) {
|
| 283 |
+
const lineIndex = (startLineNumber + i - 1) % lineCount;
|
| 284 |
+
const text = model.getLineContent(lineIndex + 1);
|
| 285 |
+
const r = this._findFirstMatchInLine(searcher, text, lineIndex + 1, 1, captureMatches);
|
| 286 |
+
if (r) {
|
| 287 |
+
return r;
|
| 288 |
+
}
|
| 289 |
+
}
|
| 290 |
+
return null;
|
| 291 |
+
}
|
| 292 |
+
static _findFirstMatchInLine(searcher, text, lineNumber, fromColumn, captureMatches) {
|
| 293 |
+
// Set regex to search from column
|
| 294 |
+
searcher.reset(fromColumn - 1);
|
| 295 |
+
const m = searcher.next(text);
|
| 296 |
+
if (m) {
|
| 297 |
+
return createFindMatch(new Range(lineNumber, m.index + 1, lineNumber, m.index + 1 + m[0].length), m, captureMatches);
|
| 298 |
+
}
|
| 299 |
+
return null;
|
| 300 |
+
}
|
| 301 |
+
static findPreviousMatch(model, searchParams, searchStart, captureMatches) {
|
| 302 |
+
const searchData = searchParams.parseSearchRequest();
|
| 303 |
+
if (!searchData) {
|
| 304 |
+
return null;
|
| 305 |
+
}
|
| 306 |
+
const searcher = new Searcher(searchData.wordSeparators, searchData.regex);
|
| 307 |
+
if (searchData.regex.multiline) {
|
| 308 |
+
return this._doFindPreviousMatchMultiline(model, searchStart, searcher, captureMatches);
|
| 309 |
+
}
|
| 310 |
+
return this._doFindPreviousMatchLineByLine(model, searchStart, searcher, captureMatches);
|
| 311 |
+
}
|
| 312 |
+
static _doFindPreviousMatchMultiline(model, searchStart, searcher, captureMatches) {
|
| 313 |
+
const matches = this._doFindMatchesMultiline(model, new Range(1, 1, searchStart.lineNumber, searchStart.column), searcher, captureMatches, 10 * LIMIT_FIND_COUNT);
|
| 314 |
+
if (matches.length > 0) {
|
| 315 |
+
return matches[matches.length - 1];
|
| 316 |
+
}
|
| 317 |
+
const lineCount = model.getLineCount();
|
| 318 |
+
if (searchStart.lineNumber !== lineCount || searchStart.column !== model.getLineMaxColumn(lineCount)) {
|
| 319 |
+
// Try again with all content
|
| 320 |
+
return this._doFindPreviousMatchMultiline(model, new Position(lineCount, model.getLineMaxColumn(lineCount)), searcher, captureMatches);
|
| 321 |
+
}
|
| 322 |
+
return null;
|
| 323 |
+
}
|
| 324 |
+
static _doFindPreviousMatchLineByLine(model, searchStart, searcher, captureMatches) {
|
| 325 |
+
const lineCount = model.getLineCount();
|
| 326 |
+
const startLineNumber = searchStart.lineNumber;
|
| 327 |
+
// Look in first line
|
| 328 |
+
const text = model.getLineContent(startLineNumber).substring(0, searchStart.column - 1);
|
| 329 |
+
const r = this._findLastMatchInLine(searcher, text, startLineNumber, captureMatches);
|
| 330 |
+
if (r) {
|
| 331 |
+
return r;
|
| 332 |
+
}
|
| 333 |
+
for (let i = 1; i <= lineCount; i++) {
|
| 334 |
+
const lineIndex = (lineCount + startLineNumber - i - 1) % lineCount;
|
| 335 |
+
const text = model.getLineContent(lineIndex + 1);
|
| 336 |
+
const r = this._findLastMatchInLine(searcher, text, lineIndex + 1, captureMatches);
|
| 337 |
+
if (r) {
|
| 338 |
+
return r;
|
| 339 |
+
}
|
| 340 |
+
}
|
| 341 |
+
return null;
|
| 342 |
+
}
|
| 343 |
+
static _findLastMatchInLine(searcher, text, lineNumber, captureMatches) {
|
| 344 |
+
let bestResult = null;
|
| 345 |
+
let m;
|
| 346 |
+
searcher.reset(0);
|
| 347 |
+
while ((m = searcher.next(text))) {
|
| 348 |
+
bestResult = createFindMatch(new Range(lineNumber, m.index + 1, lineNumber, m.index + 1 + m[0].length), m, captureMatches);
|
| 349 |
+
}
|
| 350 |
+
return bestResult;
|
| 351 |
+
}
|
| 352 |
+
}
|
| 353 |
+
function leftIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength) {
|
| 354 |
+
if (matchStartIndex === 0) {
|
| 355 |
+
// Match starts at start of string
|
| 356 |
+
return true;
|
| 357 |
+
}
|
| 358 |
+
const charBefore = text.charCodeAt(matchStartIndex - 1);
|
| 359 |
+
if (wordSeparators.get(charBefore) !== 0 /* WordCharacterClass.Regular */) {
|
| 360 |
+
// The character before the match is a word separator
|
| 361 |
+
return true;
|
| 362 |
+
}
|
| 363 |
+
if (charBefore === 13 /* CharCode.CarriageReturn */ || charBefore === 10 /* CharCode.LineFeed */) {
|
| 364 |
+
// The character before the match is line break or carriage return.
|
| 365 |
+
return true;
|
| 366 |
+
}
|
| 367 |
+
if (matchLength > 0) {
|
| 368 |
+
const firstCharInMatch = text.charCodeAt(matchStartIndex);
|
| 369 |
+
if (wordSeparators.get(firstCharInMatch) !== 0 /* WordCharacterClass.Regular */) {
|
| 370 |
+
// The first character inside the match is a word separator
|
| 371 |
+
return true;
|
| 372 |
+
}
|
| 373 |
+
}
|
| 374 |
+
return false;
|
| 375 |
+
}
|
| 376 |
+
function rightIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength) {
|
| 377 |
+
if (matchStartIndex + matchLength === textLength) {
|
| 378 |
+
// Match ends at end of string
|
| 379 |
+
return true;
|
| 380 |
+
}
|
| 381 |
+
const charAfter = text.charCodeAt(matchStartIndex + matchLength);
|
| 382 |
+
if (wordSeparators.get(charAfter) !== 0 /* WordCharacterClass.Regular */) {
|
| 383 |
+
// The character after the match is a word separator
|
| 384 |
+
return true;
|
| 385 |
+
}
|
| 386 |
+
if (charAfter === 13 /* CharCode.CarriageReturn */ || charAfter === 10 /* CharCode.LineFeed */) {
|
| 387 |
+
// The character after the match is line break or carriage return.
|
| 388 |
+
return true;
|
| 389 |
+
}
|
| 390 |
+
if (matchLength > 0) {
|
| 391 |
+
const lastCharInMatch = text.charCodeAt(matchStartIndex + matchLength - 1);
|
| 392 |
+
if (wordSeparators.get(lastCharInMatch) !== 0 /* WordCharacterClass.Regular */) {
|
| 393 |
+
// The last character in the match is a word separator
|
| 394 |
+
return true;
|
| 395 |
+
}
|
| 396 |
+
}
|
| 397 |
+
return false;
|
| 398 |
+
}
|
| 399 |
+
export function isValidMatch(wordSeparators, text, textLength, matchStartIndex, matchLength) {
|
| 400 |
+
return (leftIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength)
|
| 401 |
+
&& rightIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength));
|
| 402 |
+
}
|
| 403 |
+
export class Searcher {
|
| 404 |
+
constructor(wordSeparators, searchRegex) {
|
| 405 |
+
this._wordSeparators = wordSeparators;
|
| 406 |
+
this._searchRegex = searchRegex;
|
| 407 |
+
this._prevMatchStartIndex = -1;
|
| 408 |
+
this._prevMatchLength = 0;
|
| 409 |
+
}
|
| 410 |
+
reset(lastIndex) {
|
| 411 |
+
this._searchRegex.lastIndex = lastIndex;
|
| 412 |
+
this._prevMatchStartIndex = -1;
|
| 413 |
+
this._prevMatchLength = 0;
|
| 414 |
+
}
|
| 415 |
+
next(text) {
|
| 416 |
+
const textLength = text.length;
|
| 417 |
+
let m;
|
| 418 |
+
do {
|
| 419 |
+
if (this._prevMatchStartIndex + this._prevMatchLength === textLength) {
|
| 420 |
+
// Reached the end of the line
|
| 421 |
+
return null;
|
| 422 |
+
}
|
| 423 |
+
m = this._searchRegex.exec(text);
|
| 424 |
+
if (!m) {
|
| 425 |
+
return null;
|
| 426 |
+
}
|
| 427 |
+
const matchStartIndex = m.index;
|
| 428 |
+
const matchLength = m[0].length;
|
| 429 |
+
if (matchStartIndex === this._prevMatchStartIndex && matchLength === this._prevMatchLength) {
|
| 430 |
+
if (matchLength === 0) {
|
| 431 |
+
// the search result is an empty string and won't advance `regex.lastIndex`, so `regex.exec` will stuck here
|
| 432 |
+
// we attempt to recover from that by advancing by two if surrogate pair found and by one otherwise
|
| 433 |
+
if (strings.getNextCodePoint(text, textLength, this._searchRegex.lastIndex) > 0xFFFF) {
|
| 434 |
+
this._searchRegex.lastIndex += 2;
|
| 435 |
+
}
|
| 436 |
+
else {
|
| 437 |
+
this._searchRegex.lastIndex += 1;
|
| 438 |
+
}
|
| 439 |
+
continue;
|
| 440 |
+
}
|
| 441 |
+
// Exit early if the regex matches the same range twice
|
| 442 |
+
return null;
|
| 443 |
+
}
|
| 444 |
+
this._prevMatchStartIndex = matchStartIndex;
|
| 445 |
+
this._prevMatchLength = matchLength;
|
| 446 |
+
if (!this._wordSeparators || isValidMatch(this._wordSeparators, text, textLength, matchStartIndex, matchLength)) {
|
| 447 |
+
return m;
|
| 448 |
+
}
|
| 449 |
+
} while (m);
|
| 450 |
+
return null;
|
| 451 |
+
}
|
| 452 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/textModelText.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { AbstractText } from '../core/textEdit.js';
|
| 6 |
+
import { TextLength } from '../core/textLength.js';
|
| 7 |
+
export class TextModelText extends AbstractText {
|
| 8 |
+
constructor(_textModel) {
|
| 9 |
+
super();
|
| 10 |
+
this._textModel = _textModel;
|
| 11 |
+
}
|
| 12 |
+
getValueOfRange(range) {
|
| 13 |
+
return this._textModel.getValueInRange(range);
|
| 14 |
+
}
|
| 15 |
+
get length() {
|
| 16 |
+
const lastLineNumber = this._textModel.getLineCount();
|
| 17 |
+
const lastLineLen = this._textModel.getLineLength(lastLineNumber);
|
| 18 |
+
return new TextLength(lastLineNumber - 1, lastLineLen);
|
| 19 |
+
}
|
| 20 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/textModelTokens.js
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { runWhenGlobalIdle } from '../../../base/common/async.js';
|
| 6 |
+
import { BugIndicatingError, onUnexpectedError } from '../../../base/common/errors.js';
|
| 7 |
+
import { setTimeout0 } from '../../../base/common/platform.js';
|
| 8 |
+
import { StopWatch } from '../../../base/common/stopwatch.js';
|
| 9 |
+
import { countEOL } from '../core/eolCounter.js';
|
| 10 |
+
import { LineRange } from '../core/lineRange.js';
|
| 11 |
+
import { OffsetRange } from '../core/offsetRange.js';
|
| 12 |
+
import { nullTokenizeEncoded } from '../languages/nullTokenize.js';
|
| 13 |
+
import { FixedArray } from './fixedArray.js';
|
| 14 |
+
import { ContiguousMultilineTokensBuilder } from '../tokens/contiguousMultilineTokensBuilder.js';
|
| 15 |
+
import { LineTokens } from '../tokens/lineTokens.js';
|
| 16 |
+
export class TokenizerWithStateStore {
|
| 17 |
+
constructor(lineCount, tokenizationSupport) {
|
| 18 |
+
this.tokenizationSupport = tokenizationSupport;
|
| 19 |
+
this.initialState = this.tokenizationSupport.getInitialState();
|
| 20 |
+
this.store = new TrackingTokenizationStateStore(lineCount);
|
| 21 |
+
}
|
| 22 |
+
getStartState(lineNumber) {
|
| 23 |
+
return this.store.getStartState(lineNumber, this.initialState);
|
| 24 |
+
}
|
| 25 |
+
getFirstInvalidLine() {
|
| 26 |
+
return this.store.getFirstInvalidLine(this.initialState);
|
| 27 |
+
}
|
| 28 |
+
}
|
| 29 |
+
export class TokenizerWithStateStoreAndTextModel extends TokenizerWithStateStore {
|
| 30 |
+
constructor(lineCount, tokenizationSupport, _textModel, _languageIdCodec) {
|
| 31 |
+
super(lineCount, tokenizationSupport);
|
| 32 |
+
this._textModel = _textModel;
|
| 33 |
+
this._languageIdCodec = _languageIdCodec;
|
| 34 |
+
}
|
| 35 |
+
updateTokensUntilLine(builder, lineNumber) {
|
| 36 |
+
const languageId = this._textModel.getLanguageId();
|
| 37 |
+
while (true) {
|
| 38 |
+
const lineToTokenize = this.getFirstInvalidLine();
|
| 39 |
+
if (!lineToTokenize || lineToTokenize.lineNumber > lineNumber) {
|
| 40 |
+
break;
|
| 41 |
+
}
|
| 42 |
+
const text = this._textModel.getLineContent(lineToTokenize.lineNumber);
|
| 43 |
+
const r = safeTokenize(this._languageIdCodec, languageId, this.tokenizationSupport, text, true, lineToTokenize.startState);
|
| 44 |
+
builder.add(lineToTokenize.lineNumber, r.tokens);
|
| 45 |
+
this.store.setEndState(lineToTokenize.lineNumber, r.endState);
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
/** assumes state is up to date */
|
| 49 |
+
getTokenTypeIfInsertingCharacter(position, character) {
|
| 50 |
+
// TODO@hediet: use tokenizeLineWithEdit
|
| 51 |
+
const lineStartState = this.getStartState(position.lineNumber);
|
| 52 |
+
if (!lineStartState) {
|
| 53 |
+
return 0 /* StandardTokenType.Other */;
|
| 54 |
+
}
|
| 55 |
+
const languageId = this._textModel.getLanguageId();
|
| 56 |
+
const lineContent = this._textModel.getLineContent(position.lineNumber);
|
| 57 |
+
// Create the text as if `character` was inserted
|
| 58 |
+
const text = (lineContent.substring(0, position.column - 1)
|
| 59 |
+
+ character
|
| 60 |
+
+ lineContent.substring(position.column - 1));
|
| 61 |
+
const r = safeTokenize(this._languageIdCodec, languageId, this.tokenizationSupport, text, true, lineStartState);
|
| 62 |
+
const lineTokens = new LineTokens(r.tokens, text, this._languageIdCodec);
|
| 63 |
+
if (lineTokens.getCount() === 0) {
|
| 64 |
+
return 0 /* StandardTokenType.Other */;
|
| 65 |
+
}
|
| 66 |
+
const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
|
| 67 |
+
return lineTokens.getStandardTokenType(tokenIndex);
|
| 68 |
+
}
|
| 69 |
+
/** assumes state is up to date */
|
| 70 |
+
tokenizeLineWithEdit(position, length, newText) {
|
| 71 |
+
const lineNumber = position.lineNumber;
|
| 72 |
+
const column = position.column;
|
| 73 |
+
const lineStartState = this.getStartState(lineNumber);
|
| 74 |
+
if (!lineStartState) {
|
| 75 |
+
return null;
|
| 76 |
+
}
|
| 77 |
+
const curLineContent = this._textModel.getLineContent(lineNumber);
|
| 78 |
+
const newLineContent = curLineContent.substring(0, column - 1)
|
| 79 |
+
+ newText + curLineContent.substring(column - 1 + length);
|
| 80 |
+
const languageId = this._textModel.getLanguageIdAtPosition(lineNumber, 0);
|
| 81 |
+
const result = safeTokenize(this._languageIdCodec, languageId, this.tokenizationSupport, newLineContent, true, lineStartState);
|
| 82 |
+
const lineTokens = new LineTokens(result.tokens, newLineContent, this._languageIdCodec);
|
| 83 |
+
return lineTokens;
|
| 84 |
+
}
|
| 85 |
+
hasAccurateTokensForLine(lineNumber) {
|
| 86 |
+
const firstInvalidLineNumber = this.store.getFirstInvalidEndStateLineNumberOrMax();
|
| 87 |
+
return (lineNumber < firstInvalidLineNumber);
|
| 88 |
+
}
|
| 89 |
+
isCheapToTokenize(lineNumber) {
|
| 90 |
+
const firstInvalidLineNumber = this.store.getFirstInvalidEndStateLineNumberOrMax();
|
| 91 |
+
if (lineNumber < firstInvalidLineNumber) {
|
| 92 |
+
return true;
|
| 93 |
+
}
|
| 94 |
+
if (lineNumber === firstInvalidLineNumber
|
| 95 |
+
&& this._textModel.getLineLength(lineNumber) < 2048 /* Constants.CHEAP_TOKENIZATION_LENGTH_LIMIT */) {
|
| 96 |
+
return true;
|
| 97 |
+
}
|
| 98 |
+
return false;
|
| 99 |
+
}
|
| 100 |
+
/**
|
| 101 |
+
* The result is not cached.
|
| 102 |
+
*/
|
| 103 |
+
tokenizeHeuristically(builder, startLineNumber, endLineNumber) {
|
| 104 |
+
if (endLineNumber <= this.store.getFirstInvalidEndStateLineNumberOrMax()) {
|
| 105 |
+
// nothing to do
|
| 106 |
+
return { heuristicTokens: false };
|
| 107 |
+
}
|
| 108 |
+
if (startLineNumber <= this.store.getFirstInvalidEndStateLineNumberOrMax()) {
|
| 109 |
+
// tokenization has reached the viewport start...
|
| 110 |
+
this.updateTokensUntilLine(builder, endLineNumber);
|
| 111 |
+
return { heuristicTokens: false };
|
| 112 |
+
}
|
| 113 |
+
let state = this.guessStartState(startLineNumber);
|
| 114 |
+
const languageId = this._textModel.getLanguageId();
|
| 115 |
+
for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {
|
| 116 |
+
const text = this._textModel.getLineContent(lineNumber);
|
| 117 |
+
const r = safeTokenize(this._languageIdCodec, languageId, this.tokenizationSupport, text, true, state);
|
| 118 |
+
builder.add(lineNumber, r.tokens);
|
| 119 |
+
state = r.endState;
|
| 120 |
+
}
|
| 121 |
+
return { heuristicTokens: true };
|
| 122 |
+
}
|
| 123 |
+
guessStartState(lineNumber) {
|
| 124 |
+
let nonWhitespaceColumn = this._textModel.getLineFirstNonWhitespaceColumn(lineNumber);
|
| 125 |
+
const likelyRelevantLines = [];
|
| 126 |
+
let initialState = null;
|
| 127 |
+
for (let i = lineNumber - 1; nonWhitespaceColumn > 1 && i >= 1; i--) {
|
| 128 |
+
const newNonWhitespaceIndex = this._textModel.getLineFirstNonWhitespaceColumn(i);
|
| 129 |
+
// Ignore lines full of whitespace
|
| 130 |
+
if (newNonWhitespaceIndex === 0) {
|
| 131 |
+
continue;
|
| 132 |
+
}
|
| 133 |
+
if (newNonWhitespaceIndex < nonWhitespaceColumn) {
|
| 134 |
+
likelyRelevantLines.push(this._textModel.getLineContent(i));
|
| 135 |
+
nonWhitespaceColumn = newNonWhitespaceIndex;
|
| 136 |
+
initialState = this.getStartState(i);
|
| 137 |
+
if (initialState) {
|
| 138 |
+
break;
|
| 139 |
+
}
|
| 140 |
+
}
|
| 141 |
+
}
|
| 142 |
+
if (!initialState) {
|
| 143 |
+
initialState = this.tokenizationSupport.getInitialState();
|
| 144 |
+
}
|
| 145 |
+
likelyRelevantLines.reverse();
|
| 146 |
+
const languageId = this._textModel.getLanguageId();
|
| 147 |
+
let state = initialState;
|
| 148 |
+
for (const line of likelyRelevantLines) {
|
| 149 |
+
const r = safeTokenize(this._languageIdCodec, languageId, this.tokenizationSupport, line, false, state);
|
| 150 |
+
state = r.endState;
|
| 151 |
+
}
|
| 152 |
+
return state;
|
| 153 |
+
}
|
| 154 |
+
}
|
| 155 |
+
/**
|
| 156 |
+
* **Invariant:**
|
| 157 |
+
* If the text model is retokenized from line 1 to {@link getFirstInvalidEndStateLineNumber}() - 1,
|
| 158 |
+
* then the recomputed end state for line l will be equal to {@link getEndState}(l).
|
| 159 |
+
*/
|
| 160 |
+
export class TrackingTokenizationStateStore {
|
| 161 |
+
constructor(lineCount) {
|
| 162 |
+
this.lineCount = lineCount;
|
| 163 |
+
this._tokenizationStateStore = new TokenizationStateStore();
|
| 164 |
+
this._invalidEndStatesLineNumbers = new RangePriorityQueueImpl();
|
| 165 |
+
this._invalidEndStatesLineNumbers.addRange(new OffsetRange(1, lineCount + 1));
|
| 166 |
+
}
|
| 167 |
+
getEndState(lineNumber) {
|
| 168 |
+
return this._tokenizationStateStore.getEndState(lineNumber);
|
| 169 |
+
}
|
| 170 |
+
/**
|
| 171 |
+
* @returns if the end state has changed.
|
| 172 |
+
*/
|
| 173 |
+
setEndState(lineNumber, state) {
|
| 174 |
+
if (!state) {
|
| 175 |
+
throw new BugIndicatingError('Cannot set null/undefined state');
|
| 176 |
+
}
|
| 177 |
+
this._invalidEndStatesLineNumbers.delete(lineNumber);
|
| 178 |
+
const r = this._tokenizationStateStore.setEndState(lineNumber, state);
|
| 179 |
+
if (r && lineNumber < this.lineCount) {
|
| 180 |
+
// because the state changed, we cannot trust the next state anymore and have to invalidate it.
|
| 181 |
+
this._invalidEndStatesLineNumbers.addRange(new OffsetRange(lineNumber + 1, lineNumber + 2));
|
| 182 |
+
}
|
| 183 |
+
return r;
|
| 184 |
+
}
|
| 185 |
+
acceptChange(range, newLineCount) {
|
| 186 |
+
this.lineCount += newLineCount - range.length;
|
| 187 |
+
this._tokenizationStateStore.acceptChange(range, newLineCount);
|
| 188 |
+
this._invalidEndStatesLineNumbers.addRangeAndResize(new OffsetRange(range.startLineNumber, range.endLineNumberExclusive), newLineCount);
|
| 189 |
+
}
|
| 190 |
+
acceptChanges(changes) {
|
| 191 |
+
for (const c of changes) {
|
| 192 |
+
const [eolCount] = countEOL(c.text);
|
| 193 |
+
this.acceptChange(new LineRange(c.range.startLineNumber, c.range.endLineNumber + 1), eolCount + 1);
|
| 194 |
+
}
|
| 195 |
+
}
|
| 196 |
+
invalidateEndStateRange(range) {
|
| 197 |
+
this._invalidEndStatesLineNumbers.addRange(new OffsetRange(range.startLineNumber, range.endLineNumberExclusive));
|
| 198 |
+
}
|
| 199 |
+
getFirstInvalidEndStateLineNumber() { return this._invalidEndStatesLineNumbers.min; }
|
| 200 |
+
getFirstInvalidEndStateLineNumberOrMax() {
|
| 201 |
+
return this.getFirstInvalidEndStateLineNumber() || Number.MAX_SAFE_INTEGER;
|
| 202 |
+
}
|
| 203 |
+
allStatesValid() { return this._invalidEndStatesLineNumbers.min === null; }
|
| 204 |
+
getStartState(lineNumber, initialState) {
|
| 205 |
+
if (lineNumber === 1) {
|
| 206 |
+
return initialState;
|
| 207 |
+
}
|
| 208 |
+
return this.getEndState(lineNumber - 1);
|
| 209 |
+
}
|
| 210 |
+
getFirstInvalidLine(initialState) {
|
| 211 |
+
const lineNumber = this.getFirstInvalidEndStateLineNumber();
|
| 212 |
+
if (lineNumber === null) {
|
| 213 |
+
return null;
|
| 214 |
+
}
|
| 215 |
+
const startState = this.getStartState(lineNumber, initialState);
|
| 216 |
+
if (!startState) {
|
| 217 |
+
throw new BugIndicatingError('Start state must be defined');
|
| 218 |
+
}
|
| 219 |
+
return { lineNumber, startState };
|
| 220 |
+
}
|
| 221 |
+
}
|
| 222 |
+
export class TokenizationStateStore {
|
| 223 |
+
constructor() {
|
| 224 |
+
this._lineEndStates = new FixedArray(null);
|
| 225 |
+
}
|
| 226 |
+
getEndState(lineNumber) {
|
| 227 |
+
return this._lineEndStates.get(lineNumber);
|
| 228 |
+
}
|
| 229 |
+
setEndState(lineNumber, state) {
|
| 230 |
+
const oldState = this._lineEndStates.get(lineNumber);
|
| 231 |
+
if (oldState && oldState.equals(state)) {
|
| 232 |
+
return false;
|
| 233 |
+
}
|
| 234 |
+
this._lineEndStates.set(lineNumber, state);
|
| 235 |
+
return true;
|
| 236 |
+
}
|
| 237 |
+
acceptChange(range, newLineCount) {
|
| 238 |
+
let length = range.length;
|
| 239 |
+
if (newLineCount > 0 && length > 0) {
|
| 240 |
+
// Keep the last state, even though it is unrelated.
|
| 241 |
+
// But if the new state happens to agree with this last state, then we know we can stop tokenizing.
|
| 242 |
+
length--;
|
| 243 |
+
newLineCount--;
|
| 244 |
+
}
|
| 245 |
+
this._lineEndStates.replace(range.startLineNumber, length, newLineCount);
|
| 246 |
+
}
|
| 247 |
+
}
|
| 248 |
+
export class RangePriorityQueueImpl {
|
| 249 |
+
constructor() {
|
| 250 |
+
this._ranges = [];
|
| 251 |
+
}
|
| 252 |
+
get min() {
|
| 253 |
+
if (this._ranges.length === 0) {
|
| 254 |
+
return null;
|
| 255 |
+
}
|
| 256 |
+
return this._ranges[0].start;
|
| 257 |
+
}
|
| 258 |
+
delete(value) {
|
| 259 |
+
const idx = this._ranges.findIndex(r => r.contains(value));
|
| 260 |
+
if (idx !== -1) {
|
| 261 |
+
const range = this._ranges[idx];
|
| 262 |
+
if (range.start === value) {
|
| 263 |
+
if (range.endExclusive === value + 1) {
|
| 264 |
+
this._ranges.splice(idx, 1);
|
| 265 |
+
}
|
| 266 |
+
else {
|
| 267 |
+
this._ranges[idx] = new OffsetRange(value + 1, range.endExclusive);
|
| 268 |
+
}
|
| 269 |
+
}
|
| 270 |
+
else {
|
| 271 |
+
if (range.endExclusive === value + 1) {
|
| 272 |
+
this._ranges[idx] = new OffsetRange(range.start, value);
|
| 273 |
+
}
|
| 274 |
+
else {
|
| 275 |
+
this._ranges.splice(idx, 1, new OffsetRange(range.start, value), new OffsetRange(value + 1, range.endExclusive));
|
| 276 |
+
}
|
| 277 |
+
}
|
| 278 |
+
}
|
| 279 |
+
}
|
| 280 |
+
addRange(range) {
|
| 281 |
+
OffsetRange.addRange(range, this._ranges);
|
| 282 |
+
}
|
| 283 |
+
addRangeAndResize(range, newLength) {
|
| 284 |
+
let idxFirstMightBeIntersecting = 0;
|
| 285 |
+
while (!(idxFirstMightBeIntersecting >= this._ranges.length || range.start <= this._ranges[idxFirstMightBeIntersecting].endExclusive)) {
|
| 286 |
+
idxFirstMightBeIntersecting++;
|
| 287 |
+
}
|
| 288 |
+
let idxFirstIsAfter = idxFirstMightBeIntersecting;
|
| 289 |
+
while (!(idxFirstIsAfter >= this._ranges.length || range.endExclusive < this._ranges[idxFirstIsAfter].start)) {
|
| 290 |
+
idxFirstIsAfter++;
|
| 291 |
+
}
|
| 292 |
+
const delta = newLength - range.length;
|
| 293 |
+
for (let i = idxFirstIsAfter; i < this._ranges.length; i++) {
|
| 294 |
+
this._ranges[i] = this._ranges[i].delta(delta);
|
| 295 |
+
}
|
| 296 |
+
if (idxFirstMightBeIntersecting === idxFirstIsAfter) {
|
| 297 |
+
const newRange = new OffsetRange(range.start, range.start + newLength);
|
| 298 |
+
if (!newRange.isEmpty) {
|
| 299 |
+
this._ranges.splice(idxFirstMightBeIntersecting, 0, newRange);
|
| 300 |
+
}
|
| 301 |
+
}
|
| 302 |
+
else {
|
| 303 |
+
const start = Math.min(range.start, this._ranges[idxFirstMightBeIntersecting].start);
|
| 304 |
+
const endEx = Math.max(range.endExclusive, this._ranges[idxFirstIsAfter - 1].endExclusive);
|
| 305 |
+
const newRange = new OffsetRange(start, endEx + delta);
|
| 306 |
+
if (!newRange.isEmpty) {
|
| 307 |
+
this._ranges.splice(idxFirstMightBeIntersecting, idxFirstIsAfter - idxFirstMightBeIntersecting, newRange);
|
| 308 |
+
}
|
| 309 |
+
else {
|
| 310 |
+
this._ranges.splice(idxFirstMightBeIntersecting, idxFirstIsAfter - idxFirstMightBeIntersecting);
|
| 311 |
+
}
|
| 312 |
+
}
|
| 313 |
+
}
|
| 314 |
+
toString() {
|
| 315 |
+
return this._ranges.map(r => r.toString()).join(' + ');
|
| 316 |
+
}
|
| 317 |
+
}
|
| 318 |
+
function safeTokenize(languageIdCodec, languageId, tokenizationSupport, text, hasEOL, state) {
|
| 319 |
+
let r = null;
|
| 320 |
+
if (tokenizationSupport) {
|
| 321 |
+
try {
|
| 322 |
+
r = tokenizationSupport.tokenizeEncoded(text, hasEOL, state.clone());
|
| 323 |
+
}
|
| 324 |
+
catch (e) {
|
| 325 |
+
onUnexpectedError(e);
|
| 326 |
+
}
|
| 327 |
+
}
|
| 328 |
+
if (!r) {
|
| 329 |
+
r = nullTokenizeEncoded(languageIdCodec.encodeLanguageId(languageId), state);
|
| 330 |
+
}
|
| 331 |
+
LineTokens.convertToEndOffset(r.tokens, text.length);
|
| 332 |
+
return r;
|
| 333 |
+
}
|
| 334 |
+
export class DefaultBackgroundTokenizer {
|
| 335 |
+
constructor(_tokenizerWithStateStore, _backgroundTokenStore) {
|
| 336 |
+
this._tokenizerWithStateStore = _tokenizerWithStateStore;
|
| 337 |
+
this._backgroundTokenStore = _backgroundTokenStore;
|
| 338 |
+
this._isDisposed = false;
|
| 339 |
+
this._isScheduled = false;
|
| 340 |
+
}
|
| 341 |
+
dispose() {
|
| 342 |
+
this._isDisposed = true;
|
| 343 |
+
}
|
| 344 |
+
handleChanges() {
|
| 345 |
+
this._beginBackgroundTokenization();
|
| 346 |
+
}
|
| 347 |
+
_beginBackgroundTokenization() {
|
| 348 |
+
if (this._isScheduled || !this._tokenizerWithStateStore._textModel.isAttachedToEditor() || !this._hasLinesToTokenize()) {
|
| 349 |
+
return;
|
| 350 |
+
}
|
| 351 |
+
this._isScheduled = true;
|
| 352 |
+
runWhenGlobalIdle((deadline) => {
|
| 353 |
+
this._isScheduled = false;
|
| 354 |
+
this._backgroundTokenizeWithDeadline(deadline);
|
| 355 |
+
});
|
| 356 |
+
}
|
| 357 |
+
/**
|
| 358 |
+
* Tokenize until the deadline occurs, but try to yield every 1-2ms.
|
| 359 |
+
*/
|
| 360 |
+
_backgroundTokenizeWithDeadline(deadline) {
|
| 361 |
+
// Read the time remaining from the `deadline` immediately because it is unclear
|
| 362 |
+
// if the `deadline` object will be valid after execution leaves this function.
|
| 363 |
+
const endTime = Date.now() + deadline.timeRemaining();
|
| 364 |
+
const execute = () => {
|
| 365 |
+
if (this._isDisposed || !this._tokenizerWithStateStore._textModel.isAttachedToEditor() || !this._hasLinesToTokenize()) {
|
| 366 |
+
// disposed in the meantime or detached or finished
|
| 367 |
+
return;
|
| 368 |
+
}
|
| 369 |
+
this._backgroundTokenizeForAtLeast1ms();
|
| 370 |
+
if (Date.now() < endTime) {
|
| 371 |
+
// There is still time before reaching the deadline, so yield to the browser and then
|
| 372 |
+
// continue execution
|
| 373 |
+
setTimeout0(execute);
|
| 374 |
+
}
|
| 375 |
+
else {
|
| 376 |
+
// The deadline has been reached, so schedule a new idle callback if necessary
|
| 377 |
+
this._beginBackgroundTokenization();
|
| 378 |
+
}
|
| 379 |
+
};
|
| 380 |
+
execute();
|
| 381 |
+
}
|
| 382 |
+
/**
|
| 383 |
+
* Tokenize for at least 1ms.
|
| 384 |
+
*/
|
| 385 |
+
_backgroundTokenizeForAtLeast1ms() {
|
| 386 |
+
const lineCount = this._tokenizerWithStateStore._textModel.getLineCount();
|
| 387 |
+
const builder = new ContiguousMultilineTokensBuilder();
|
| 388 |
+
const sw = StopWatch.create(false);
|
| 389 |
+
do {
|
| 390 |
+
if (sw.elapsed() > 1) {
|
| 391 |
+
// the comparison is intentionally > 1 and not >= 1 to ensure that
|
| 392 |
+
// a full millisecond has elapsed, given how microseconds are rounded
|
| 393 |
+
// to milliseconds
|
| 394 |
+
break;
|
| 395 |
+
}
|
| 396 |
+
const tokenizedLineNumber = this._tokenizeOneInvalidLine(builder);
|
| 397 |
+
if (tokenizedLineNumber >= lineCount) {
|
| 398 |
+
break;
|
| 399 |
+
}
|
| 400 |
+
} while (this._hasLinesToTokenize());
|
| 401 |
+
this._backgroundTokenStore.setTokens(builder.finalize());
|
| 402 |
+
this.checkFinished();
|
| 403 |
+
}
|
| 404 |
+
_hasLinesToTokenize() {
|
| 405 |
+
if (!this._tokenizerWithStateStore) {
|
| 406 |
+
return false;
|
| 407 |
+
}
|
| 408 |
+
return !this._tokenizerWithStateStore.store.allStatesValid();
|
| 409 |
+
}
|
| 410 |
+
_tokenizeOneInvalidLine(builder) {
|
| 411 |
+
const firstInvalidLine = this._tokenizerWithStateStore?.getFirstInvalidLine();
|
| 412 |
+
if (!firstInvalidLine) {
|
| 413 |
+
return this._tokenizerWithStateStore._textModel.getLineCount() + 1;
|
| 414 |
+
}
|
| 415 |
+
this._tokenizerWithStateStore.updateTokensUntilLine(builder, firstInvalidLine.lineNumber);
|
| 416 |
+
return firstInvalidLine.lineNumber;
|
| 417 |
+
}
|
| 418 |
+
checkFinished() {
|
| 419 |
+
if (this._isDisposed) {
|
| 420 |
+
return;
|
| 421 |
+
}
|
| 422 |
+
if (this._tokenizerWithStateStore.store.allStatesValid()) {
|
| 423 |
+
this._backgroundTokenStore.backgroundTokenizationFinished();
|
| 424 |
+
}
|
| 425 |
+
}
|
| 426 |
+
requestTokens(startLineNumber, endLineNumberExclusive) {
|
| 427 |
+
this._tokenizerWithStateStore.store.invalidateEndStateRange(new LineRange(startLineNumber, endLineNumberExclusive));
|
| 428 |
+
}
|
| 429 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/tokenizationTextModelPart.js
ADDED
|
@@ -0,0 +1,530 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
| 6 |
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
| 7 |
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
| 8 |
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
| 9 |
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
| 10 |
+
};
|
| 11 |
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
| 12 |
+
return function (target, key) { decorator(target, key, paramIndex); }
|
| 13 |
+
};
|
| 14 |
+
var TokenizationTextModelPart_1;
|
| 15 |
+
import { BugIndicatingError, onUnexpectedError } from '../../../base/common/errors.js';
|
| 16 |
+
import { Emitter, Event } from '../../../base/common/event.js';
|
| 17 |
+
import { DisposableMap, DisposableStore, MutableDisposable } from '../../../base/common/lifecycle.js';
|
| 18 |
+
import { countEOL } from '../core/eolCounter.js';
|
| 19 |
+
import { LineRange } from '../core/lineRange.js';
|
| 20 |
+
import { Position } from '../core/position.js';
|
| 21 |
+
import { getWordAtText } from '../core/wordHelper.js';
|
| 22 |
+
import { TokenizationRegistry, TreeSitterTokenizationRegistry } from '../languages.js';
|
| 23 |
+
import { ILanguageService } from '../languages/language.js';
|
| 24 |
+
import { ILanguageConfigurationService } from '../languages/languageConfigurationRegistry.js';
|
| 25 |
+
import { TextModelPart } from './textModelPart.js';
|
| 26 |
+
import { DefaultBackgroundTokenizer, TokenizerWithStateStoreAndTextModel, TrackingTokenizationStateStore } from './textModelTokens.js';
|
| 27 |
+
import { AbstractTokens, AttachedViewHandler } from './tokens.js';
|
| 28 |
+
import { TreeSitterTokens } from './treeSitterTokens.js';
|
| 29 |
+
import { ITreeSitterParserService } from '../services/treeSitterParserService.js';
|
| 30 |
+
import { ContiguousMultilineTokensBuilder } from '../tokens/contiguousMultilineTokensBuilder.js';
|
| 31 |
+
import { ContiguousTokensStore } from '../tokens/contiguousTokensStore.js';
|
| 32 |
+
import { SparseTokensStore } from '../tokens/sparseTokensStore.js';
|
| 33 |
+
let TokenizationTextModelPart = TokenizationTextModelPart_1 = class TokenizationTextModelPart extends TextModelPart {
|
| 34 |
+
constructor(_textModel, _bracketPairsTextModelPart, _languageId, _attachedViews, _languageService, _languageConfigurationService, _treeSitterService) {
|
| 35 |
+
super();
|
| 36 |
+
this._textModel = _textModel;
|
| 37 |
+
this._bracketPairsTextModelPart = _bracketPairsTextModelPart;
|
| 38 |
+
this._languageId = _languageId;
|
| 39 |
+
this._attachedViews = _attachedViews;
|
| 40 |
+
this._languageService = _languageService;
|
| 41 |
+
this._languageConfigurationService = _languageConfigurationService;
|
| 42 |
+
this._treeSitterService = _treeSitterService;
|
| 43 |
+
this._semanticTokens = new SparseTokensStore(this._languageService.languageIdCodec);
|
| 44 |
+
this._onDidChangeLanguage = this._register(new Emitter());
|
| 45 |
+
this.onDidChangeLanguage = this._onDidChangeLanguage.event;
|
| 46 |
+
this._onDidChangeLanguageConfiguration = this._register(new Emitter());
|
| 47 |
+
this.onDidChangeLanguageConfiguration = this._onDidChangeLanguageConfiguration.event;
|
| 48 |
+
this._onDidChangeTokens = this._register(new Emitter());
|
| 49 |
+
this.onDidChangeTokens = this._onDidChangeTokens.event;
|
| 50 |
+
this._tokensDisposables = this._register(new DisposableStore());
|
| 51 |
+
this._register(this._languageConfigurationService.onDidChange(e => {
|
| 52 |
+
if (e.affects(this._languageId)) {
|
| 53 |
+
this._onDidChangeLanguageConfiguration.fire({});
|
| 54 |
+
}
|
| 55 |
+
}));
|
| 56 |
+
// We just look at registry changes to determine whether to use tree sitter.
|
| 57 |
+
// This means that removing a language from the setting will not cause a switch to textmate and will require a reload.
|
| 58 |
+
// Adding a language to the setting will not need a reload, however.
|
| 59 |
+
this._register(Event.filter(TreeSitterTokenizationRegistry.onDidChange, (e) => e.changedLanguages.includes(this._languageId))(() => {
|
| 60 |
+
this.createPreferredTokenProvider();
|
| 61 |
+
}));
|
| 62 |
+
this.createPreferredTokenProvider();
|
| 63 |
+
}
|
| 64 |
+
createGrammarTokens() {
|
| 65 |
+
return this._register(new GrammarTokens(this._languageService.languageIdCodec, this._textModel, () => this._languageId, this._attachedViews));
|
| 66 |
+
}
|
| 67 |
+
createTreeSitterTokens() {
|
| 68 |
+
return this._register(new TreeSitterTokens(this._treeSitterService, this._languageService.languageIdCodec, this._textModel, () => this._languageId));
|
| 69 |
+
}
|
| 70 |
+
createTokens(useTreeSitter) {
|
| 71 |
+
const needsReset = this._tokens !== undefined;
|
| 72 |
+
this._tokens?.dispose();
|
| 73 |
+
this._tokens = useTreeSitter ? this.createTreeSitterTokens() : this.createGrammarTokens();
|
| 74 |
+
this._tokensDisposables.clear();
|
| 75 |
+
this._tokensDisposables.add(this._tokens.onDidChangeTokens(e => {
|
| 76 |
+
this._emitModelTokensChangedEvent(e);
|
| 77 |
+
}));
|
| 78 |
+
this._tokensDisposables.add(this._tokens.onDidChangeBackgroundTokenizationState(e => {
|
| 79 |
+
this._bracketPairsTextModelPart.handleDidChangeBackgroundTokenizationState();
|
| 80 |
+
}));
|
| 81 |
+
if (needsReset) {
|
| 82 |
+
// We need to reset the tokenization, as the new token provider otherwise won't have a chance to provide tokens until some action happens in the editor.
|
| 83 |
+
this._tokens.resetTokenization();
|
| 84 |
+
}
|
| 85 |
+
}
|
| 86 |
+
createPreferredTokenProvider() {
|
| 87 |
+
if (TreeSitterTokenizationRegistry.get(this._languageId)) {
|
| 88 |
+
if (!(this._tokens instanceof TreeSitterTokens)) {
|
| 89 |
+
this.createTokens(true);
|
| 90 |
+
}
|
| 91 |
+
}
|
| 92 |
+
else {
|
| 93 |
+
if (!(this._tokens instanceof GrammarTokens)) {
|
| 94 |
+
this.createTokens(false);
|
| 95 |
+
}
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
handleLanguageConfigurationServiceChange(e) {
|
| 99 |
+
if (e.affects(this._languageId)) {
|
| 100 |
+
this._onDidChangeLanguageConfiguration.fire({});
|
| 101 |
+
}
|
| 102 |
+
}
|
| 103 |
+
handleDidChangeContent(e) {
|
| 104 |
+
if (e.isFlush) {
|
| 105 |
+
this._semanticTokens.flush();
|
| 106 |
+
}
|
| 107 |
+
else if (!e.isEolChange) { // We don't have to do anything on an EOL change
|
| 108 |
+
for (const c of e.changes) {
|
| 109 |
+
const [eolCount, firstLineLength, lastLineLength] = countEOL(c.text);
|
| 110 |
+
this._semanticTokens.acceptEdit(c.range, eolCount, firstLineLength, lastLineLength, c.text.length > 0 ? c.text.charCodeAt(0) : 0 /* CharCode.Null */);
|
| 111 |
+
}
|
| 112 |
+
}
|
| 113 |
+
this._tokens.handleDidChangeContent(e);
|
| 114 |
+
}
|
| 115 |
+
handleDidChangeAttached() {
|
| 116 |
+
this._tokens.handleDidChangeAttached();
|
| 117 |
+
}
|
| 118 |
+
/**
|
| 119 |
+
* Includes grammar and semantic tokens.
|
| 120 |
+
*/
|
| 121 |
+
getLineTokens(lineNumber) {
|
| 122 |
+
this.validateLineNumber(lineNumber);
|
| 123 |
+
const syntacticTokens = this._tokens.getLineTokens(lineNumber);
|
| 124 |
+
return this._semanticTokens.addSparseTokens(lineNumber, syntacticTokens);
|
| 125 |
+
}
|
| 126 |
+
_emitModelTokensChangedEvent(e) {
|
| 127 |
+
if (!this._textModel._isDisposing()) {
|
| 128 |
+
this._bracketPairsTextModelPart.handleDidChangeTokens(e);
|
| 129 |
+
this._onDidChangeTokens.fire(e);
|
| 130 |
+
}
|
| 131 |
+
}
|
| 132 |
+
// #region Grammar Tokens
|
| 133 |
+
validateLineNumber(lineNumber) {
|
| 134 |
+
if (lineNumber < 1 || lineNumber > this._textModel.getLineCount()) {
|
| 135 |
+
throw new BugIndicatingError('Illegal value for lineNumber');
|
| 136 |
+
}
|
| 137 |
+
}
|
| 138 |
+
get hasTokens() {
|
| 139 |
+
return this._tokens.hasTokens;
|
| 140 |
+
}
|
| 141 |
+
resetTokenization() {
|
| 142 |
+
this._tokens.resetTokenization();
|
| 143 |
+
}
|
| 144 |
+
get backgroundTokenizationState() {
|
| 145 |
+
return this._tokens.backgroundTokenizationState;
|
| 146 |
+
}
|
| 147 |
+
forceTokenization(lineNumber) {
|
| 148 |
+
this.validateLineNumber(lineNumber);
|
| 149 |
+
this._tokens.forceTokenization(lineNumber);
|
| 150 |
+
}
|
| 151 |
+
hasAccurateTokensForLine(lineNumber) {
|
| 152 |
+
this.validateLineNumber(lineNumber);
|
| 153 |
+
return this._tokens.hasAccurateTokensForLine(lineNumber);
|
| 154 |
+
}
|
| 155 |
+
isCheapToTokenize(lineNumber) {
|
| 156 |
+
this.validateLineNumber(lineNumber);
|
| 157 |
+
return this._tokens.isCheapToTokenize(lineNumber);
|
| 158 |
+
}
|
| 159 |
+
tokenizeIfCheap(lineNumber) {
|
| 160 |
+
this.validateLineNumber(lineNumber);
|
| 161 |
+
this._tokens.tokenizeIfCheap(lineNumber);
|
| 162 |
+
}
|
| 163 |
+
getTokenTypeIfInsertingCharacter(lineNumber, column, character) {
|
| 164 |
+
return this._tokens.getTokenTypeIfInsertingCharacter(lineNumber, column, character);
|
| 165 |
+
}
|
| 166 |
+
tokenizeLineWithEdit(position, length, newText) {
|
| 167 |
+
return this._tokens.tokenizeLineWithEdit(position, length, newText);
|
| 168 |
+
}
|
| 169 |
+
// #endregion
|
| 170 |
+
// #region Semantic Tokens
|
| 171 |
+
setSemanticTokens(tokens, isComplete) {
|
| 172 |
+
this._semanticTokens.set(tokens, isComplete);
|
| 173 |
+
this._emitModelTokensChangedEvent({
|
| 174 |
+
semanticTokensApplied: tokens !== null,
|
| 175 |
+
ranges: [{ fromLineNumber: 1, toLineNumber: this._textModel.getLineCount() }],
|
| 176 |
+
});
|
| 177 |
+
}
|
| 178 |
+
hasCompleteSemanticTokens() {
|
| 179 |
+
return this._semanticTokens.isComplete();
|
| 180 |
+
}
|
| 181 |
+
hasSomeSemanticTokens() {
|
| 182 |
+
return !this._semanticTokens.isEmpty();
|
| 183 |
+
}
|
| 184 |
+
setPartialSemanticTokens(range, tokens) {
|
| 185 |
+
if (this.hasCompleteSemanticTokens()) {
|
| 186 |
+
return;
|
| 187 |
+
}
|
| 188 |
+
const changedRange = this._textModel.validateRange(this._semanticTokens.setPartial(range, tokens));
|
| 189 |
+
this._emitModelTokensChangedEvent({
|
| 190 |
+
semanticTokensApplied: true,
|
| 191 |
+
ranges: [
|
| 192 |
+
{
|
| 193 |
+
fromLineNumber: changedRange.startLineNumber,
|
| 194 |
+
toLineNumber: changedRange.endLineNumber,
|
| 195 |
+
},
|
| 196 |
+
],
|
| 197 |
+
});
|
| 198 |
+
}
|
| 199 |
+
// #endregion
|
| 200 |
+
// #region Utility Methods
|
| 201 |
+
getWordAtPosition(_position) {
|
| 202 |
+
this.assertNotDisposed();
|
| 203 |
+
const position = this._textModel.validatePosition(_position);
|
| 204 |
+
const lineContent = this._textModel.getLineContent(position.lineNumber);
|
| 205 |
+
const lineTokens = this.getLineTokens(position.lineNumber);
|
| 206 |
+
const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
|
| 207 |
+
// (1). First try checking right biased word
|
| 208 |
+
const [rbStartOffset, rbEndOffset] = TokenizationTextModelPart_1._findLanguageBoundaries(lineTokens, tokenIndex);
|
| 209 |
+
const rightBiasedWord = getWordAtText(position.column, this.getLanguageConfiguration(lineTokens.getLanguageId(tokenIndex)).getWordDefinition(), lineContent.substring(rbStartOffset, rbEndOffset), rbStartOffset);
|
| 210 |
+
// Make sure the result touches the original passed in position
|
| 211 |
+
if (rightBiasedWord &&
|
| 212 |
+
rightBiasedWord.startColumn <= _position.column &&
|
| 213 |
+
_position.column <= rightBiasedWord.endColumn) {
|
| 214 |
+
return rightBiasedWord;
|
| 215 |
+
}
|
| 216 |
+
// (2). Else, if we were at a language boundary, check the left biased word
|
| 217 |
+
if (tokenIndex > 0 && rbStartOffset === position.column - 1) {
|
| 218 |
+
// edge case, where `position` sits between two tokens belonging to two different languages
|
| 219 |
+
const [lbStartOffset, lbEndOffset] = TokenizationTextModelPart_1._findLanguageBoundaries(lineTokens, tokenIndex - 1);
|
| 220 |
+
const leftBiasedWord = getWordAtText(position.column, this.getLanguageConfiguration(lineTokens.getLanguageId(tokenIndex - 1)).getWordDefinition(), lineContent.substring(lbStartOffset, lbEndOffset), lbStartOffset);
|
| 221 |
+
// Make sure the result touches the original passed in position
|
| 222 |
+
if (leftBiasedWord &&
|
| 223 |
+
leftBiasedWord.startColumn <= _position.column &&
|
| 224 |
+
_position.column <= leftBiasedWord.endColumn) {
|
| 225 |
+
return leftBiasedWord;
|
| 226 |
+
}
|
| 227 |
+
}
|
| 228 |
+
return null;
|
| 229 |
+
}
|
| 230 |
+
getLanguageConfiguration(languageId) {
|
| 231 |
+
return this._languageConfigurationService.getLanguageConfiguration(languageId);
|
| 232 |
+
}
|
| 233 |
+
static _findLanguageBoundaries(lineTokens, tokenIndex) {
|
| 234 |
+
const languageId = lineTokens.getLanguageId(tokenIndex);
|
| 235 |
+
// go left until a different language is hit
|
| 236 |
+
let startOffset = 0;
|
| 237 |
+
for (let i = tokenIndex; i >= 0 && lineTokens.getLanguageId(i) === languageId; i--) {
|
| 238 |
+
startOffset = lineTokens.getStartOffset(i);
|
| 239 |
+
}
|
| 240 |
+
// go right until a different language is hit
|
| 241 |
+
let endOffset = lineTokens.getLineContent().length;
|
| 242 |
+
for (let i = tokenIndex, tokenCount = lineTokens.getCount(); i < tokenCount && lineTokens.getLanguageId(i) === languageId; i++) {
|
| 243 |
+
endOffset = lineTokens.getEndOffset(i);
|
| 244 |
+
}
|
| 245 |
+
return [startOffset, endOffset];
|
| 246 |
+
}
|
| 247 |
+
getWordUntilPosition(position) {
|
| 248 |
+
const wordAtPosition = this.getWordAtPosition(position);
|
| 249 |
+
if (!wordAtPosition) {
|
| 250 |
+
return { word: '', startColumn: position.column, endColumn: position.column, };
|
| 251 |
+
}
|
| 252 |
+
return {
|
| 253 |
+
word: wordAtPosition.word.substr(0, position.column - wordAtPosition.startColumn),
|
| 254 |
+
startColumn: wordAtPosition.startColumn,
|
| 255 |
+
endColumn: position.column,
|
| 256 |
+
};
|
| 257 |
+
}
|
| 258 |
+
// #endregion
|
| 259 |
+
// #region Language Id handling
|
| 260 |
+
getLanguageId() {
|
| 261 |
+
return this._languageId;
|
| 262 |
+
}
|
| 263 |
+
getLanguageIdAtPosition(lineNumber, column) {
|
| 264 |
+
const position = this._textModel.validatePosition(new Position(lineNumber, column));
|
| 265 |
+
const lineTokens = this.getLineTokens(position.lineNumber);
|
| 266 |
+
return lineTokens.getLanguageId(lineTokens.findTokenIndexAtOffset(position.column - 1));
|
| 267 |
+
}
|
| 268 |
+
setLanguageId(languageId, source = 'api') {
|
| 269 |
+
if (this._languageId === languageId) {
|
| 270 |
+
// There's nothing to do
|
| 271 |
+
return;
|
| 272 |
+
}
|
| 273 |
+
const e = {
|
| 274 |
+
oldLanguage: this._languageId,
|
| 275 |
+
newLanguage: languageId,
|
| 276 |
+
source
|
| 277 |
+
};
|
| 278 |
+
this._languageId = languageId;
|
| 279 |
+
this._bracketPairsTextModelPart.handleDidChangeLanguage(e);
|
| 280 |
+
this._tokens.resetTokenization();
|
| 281 |
+
this.createPreferredTokenProvider();
|
| 282 |
+
this._onDidChangeLanguage.fire(e);
|
| 283 |
+
this._onDidChangeLanguageConfiguration.fire({});
|
| 284 |
+
}
|
| 285 |
+
};
|
| 286 |
+
TokenizationTextModelPart = TokenizationTextModelPart_1 = __decorate([
|
| 287 |
+
__param(4, ILanguageService),
|
| 288 |
+
__param(5, ILanguageConfigurationService),
|
| 289 |
+
__param(6, ITreeSitterParserService)
|
| 290 |
+
], TokenizationTextModelPart);
|
| 291 |
+
export { TokenizationTextModelPart };
|
| 292 |
+
class GrammarTokens extends AbstractTokens {
|
| 293 |
+
constructor(languageIdCodec, textModel, getLanguageId, attachedViews) {
|
| 294 |
+
super(languageIdCodec, textModel, getLanguageId);
|
| 295 |
+
this._tokenizer = null;
|
| 296 |
+
this._defaultBackgroundTokenizer = null;
|
| 297 |
+
this._backgroundTokenizer = this._register(new MutableDisposable());
|
| 298 |
+
this._tokens = new ContiguousTokensStore(this._languageIdCodec);
|
| 299 |
+
this._debugBackgroundTokenizer = this._register(new MutableDisposable());
|
| 300 |
+
this._attachedViewStates = this._register(new DisposableMap());
|
| 301 |
+
this._register(TokenizationRegistry.onDidChange((e) => {
|
| 302 |
+
const languageId = this.getLanguageId();
|
| 303 |
+
if (e.changedLanguages.indexOf(languageId) === -1) {
|
| 304 |
+
return;
|
| 305 |
+
}
|
| 306 |
+
this.resetTokenization();
|
| 307 |
+
}));
|
| 308 |
+
this.resetTokenization();
|
| 309 |
+
this._register(attachedViews.onDidChangeVisibleRanges(({ view, state }) => {
|
| 310 |
+
if (state) {
|
| 311 |
+
let existing = this._attachedViewStates.get(view);
|
| 312 |
+
if (!existing) {
|
| 313 |
+
existing = new AttachedViewHandler(() => this.refreshRanges(existing.lineRanges));
|
| 314 |
+
this._attachedViewStates.set(view, existing);
|
| 315 |
+
}
|
| 316 |
+
existing.handleStateChange(state);
|
| 317 |
+
}
|
| 318 |
+
else {
|
| 319 |
+
this._attachedViewStates.deleteAndDispose(view);
|
| 320 |
+
}
|
| 321 |
+
}));
|
| 322 |
+
}
|
| 323 |
+
resetTokenization(fireTokenChangeEvent = true) {
|
| 324 |
+
this._tokens.flush();
|
| 325 |
+
this._debugBackgroundTokens?.flush();
|
| 326 |
+
if (this._debugBackgroundStates) {
|
| 327 |
+
this._debugBackgroundStates = new TrackingTokenizationStateStore(this._textModel.getLineCount());
|
| 328 |
+
}
|
| 329 |
+
if (fireTokenChangeEvent) {
|
| 330 |
+
this._onDidChangeTokens.fire({
|
| 331 |
+
semanticTokensApplied: false,
|
| 332 |
+
ranges: [
|
| 333 |
+
{
|
| 334 |
+
fromLineNumber: 1,
|
| 335 |
+
toLineNumber: this._textModel.getLineCount(),
|
| 336 |
+
},
|
| 337 |
+
],
|
| 338 |
+
});
|
| 339 |
+
}
|
| 340 |
+
const initializeTokenization = () => {
|
| 341 |
+
if (this._textModel.isTooLargeForTokenization()) {
|
| 342 |
+
return [null, null];
|
| 343 |
+
}
|
| 344 |
+
const tokenizationSupport = TokenizationRegistry.get(this.getLanguageId());
|
| 345 |
+
if (!tokenizationSupport) {
|
| 346 |
+
return [null, null];
|
| 347 |
+
}
|
| 348 |
+
let initialState;
|
| 349 |
+
try {
|
| 350 |
+
initialState = tokenizationSupport.getInitialState();
|
| 351 |
+
}
|
| 352 |
+
catch (e) {
|
| 353 |
+
onUnexpectedError(e);
|
| 354 |
+
return [null, null];
|
| 355 |
+
}
|
| 356 |
+
return [tokenizationSupport, initialState];
|
| 357 |
+
};
|
| 358 |
+
const [tokenizationSupport, initialState] = initializeTokenization();
|
| 359 |
+
if (tokenizationSupport && initialState) {
|
| 360 |
+
this._tokenizer = new TokenizerWithStateStoreAndTextModel(this._textModel.getLineCount(), tokenizationSupport, this._textModel, this._languageIdCodec);
|
| 361 |
+
}
|
| 362 |
+
else {
|
| 363 |
+
this._tokenizer = null;
|
| 364 |
+
}
|
| 365 |
+
this._backgroundTokenizer.clear();
|
| 366 |
+
this._defaultBackgroundTokenizer = null;
|
| 367 |
+
if (this._tokenizer) {
|
| 368 |
+
const b = {
|
| 369 |
+
setTokens: (tokens) => {
|
| 370 |
+
this.setTokens(tokens);
|
| 371 |
+
},
|
| 372 |
+
backgroundTokenizationFinished: () => {
|
| 373 |
+
if (this._backgroundTokenizationState === 2 /* BackgroundTokenizationState.Completed */) {
|
| 374 |
+
// We already did a full tokenization and don't go back to progressing.
|
| 375 |
+
return;
|
| 376 |
+
}
|
| 377 |
+
const newState = 2 /* BackgroundTokenizationState.Completed */;
|
| 378 |
+
this._backgroundTokenizationState = newState;
|
| 379 |
+
this._onDidChangeBackgroundTokenizationState.fire();
|
| 380 |
+
},
|
| 381 |
+
setEndState: (lineNumber, state) => {
|
| 382 |
+
if (!this._tokenizer) {
|
| 383 |
+
return;
|
| 384 |
+
}
|
| 385 |
+
const firstInvalidEndStateLineNumber = this._tokenizer.store.getFirstInvalidEndStateLineNumber();
|
| 386 |
+
// Don't accept states for definitely valid states, the renderer is ahead of the worker!
|
| 387 |
+
if (firstInvalidEndStateLineNumber !== null && lineNumber >= firstInvalidEndStateLineNumber) {
|
| 388 |
+
this._tokenizer?.store.setEndState(lineNumber, state);
|
| 389 |
+
}
|
| 390 |
+
},
|
| 391 |
+
};
|
| 392 |
+
if (tokenizationSupport && tokenizationSupport.createBackgroundTokenizer && !tokenizationSupport.backgroundTokenizerShouldOnlyVerifyTokens) {
|
| 393 |
+
this._backgroundTokenizer.value = tokenizationSupport.createBackgroundTokenizer(this._textModel, b);
|
| 394 |
+
}
|
| 395 |
+
if (!this._backgroundTokenizer.value && !this._textModel.isTooLargeForTokenization()) {
|
| 396 |
+
this._backgroundTokenizer.value = this._defaultBackgroundTokenizer =
|
| 397 |
+
new DefaultBackgroundTokenizer(this._tokenizer, b);
|
| 398 |
+
this._defaultBackgroundTokenizer.handleChanges();
|
| 399 |
+
}
|
| 400 |
+
if (tokenizationSupport?.backgroundTokenizerShouldOnlyVerifyTokens && tokenizationSupport.createBackgroundTokenizer) {
|
| 401 |
+
this._debugBackgroundTokens = new ContiguousTokensStore(this._languageIdCodec);
|
| 402 |
+
this._debugBackgroundStates = new TrackingTokenizationStateStore(this._textModel.getLineCount());
|
| 403 |
+
this._debugBackgroundTokenizer.clear();
|
| 404 |
+
this._debugBackgroundTokenizer.value = tokenizationSupport.createBackgroundTokenizer(this._textModel, {
|
| 405 |
+
setTokens: (tokens) => {
|
| 406 |
+
this._debugBackgroundTokens?.setMultilineTokens(tokens, this._textModel);
|
| 407 |
+
},
|
| 408 |
+
backgroundTokenizationFinished() {
|
| 409 |
+
// NO OP
|
| 410 |
+
},
|
| 411 |
+
setEndState: (lineNumber, state) => {
|
| 412 |
+
this._debugBackgroundStates?.setEndState(lineNumber, state);
|
| 413 |
+
},
|
| 414 |
+
});
|
| 415 |
+
}
|
| 416 |
+
else {
|
| 417 |
+
this._debugBackgroundTokens = undefined;
|
| 418 |
+
this._debugBackgroundStates = undefined;
|
| 419 |
+
this._debugBackgroundTokenizer.value = undefined;
|
| 420 |
+
}
|
| 421 |
+
}
|
| 422 |
+
this.refreshAllVisibleLineTokens();
|
| 423 |
+
}
|
| 424 |
+
handleDidChangeAttached() {
|
| 425 |
+
this._defaultBackgroundTokenizer?.handleChanges();
|
| 426 |
+
}
|
| 427 |
+
handleDidChangeContent(e) {
|
| 428 |
+
if (e.isFlush) {
|
| 429 |
+
// Don't fire the event, as the view might not have got the text change event yet
|
| 430 |
+
this.resetTokenization(false);
|
| 431 |
+
}
|
| 432 |
+
else if (!e.isEolChange) { // We don't have to do anything on an EOL change
|
| 433 |
+
for (const c of e.changes) {
|
| 434 |
+
const [eolCount, firstLineLength] = countEOL(c.text);
|
| 435 |
+
this._tokens.acceptEdit(c.range, eolCount, firstLineLength);
|
| 436 |
+
this._debugBackgroundTokens?.acceptEdit(c.range, eolCount, firstLineLength);
|
| 437 |
+
}
|
| 438 |
+
this._debugBackgroundStates?.acceptChanges(e.changes);
|
| 439 |
+
if (this._tokenizer) {
|
| 440 |
+
this._tokenizer.store.acceptChanges(e.changes);
|
| 441 |
+
}
|
| 442 |
+
this._defaultBackgroundTokenizer?.handleChanges();
|
| 443 |
+
}
|
| 444 |
+
}
|
| 445 |
+
setTokens(tokens) {
|
| 446 |
+
const { changes } = this._tokens.setMultilineTokens(tokens, this._textModel);
|
| 447 |
+
if (changes.length > 0) {
|
| 448 |
+
this._onDidChangeTokens.fire({ semanticTokensApplied: false, ranges: changes, });
|
| 449 |
+
}
|
| 450 |
+
return { changes: changes };
|
| 451 |
+
}
|
| 452 |
+
refreshAllVisibleLineTokens() {
|
| 453 |
+
const ranges = LineRange.joinMany([...this._attachedViewStates].map(([_, s]) => s.lineRanges));
|
| 454 |
+
this.refreshRanges(ranges);
|
| 455 |
+
}
|
| 456 |
+
refreshRanges(ranges) {
|
| 457 |
+
for (const range of ranges) {
|
| 458 |
+
this.refreshRange(range.startLineNumber, range.endLineNumberExclusive - 1);
|
| 459 |
+
}
|
| 460 |
+
}
|
| 461 |
+
refreshRange(startLineNumber, endLineNumber) {
|
| 462 |
+
if (!this._tokenizer) {
|
| 463 |
+
return;
|
| 464 |
+
}
|
| 465 |
+
startLineNumber = Math.max(1, Math.min(this._textModel.getLineCount(), startLineNumber));
|
| 466 |
+
endLineNumber = Math.min(this._textModel.getLineCount(), endLineNumber);
|
| 467 |
+
const builder = new ContiguousMultilineTokensBuilder();
|
| 468 |
+
const { heuristicTokens } = this._tokenizer.tokenizeHeuristically(builder, startLineNumber, endLineNumber);
|
| 469 |
+
const changedTokens = this.setTokens(builder.finalize());
|
| 470 |
+
if (heuristicTokens) {
|
| 471 |
+
// We overrode tokens with heuristically computed ones.
|
| 472 |
+
// Because old states might get reused (thus stopping invalidation),
|
| 473 |
+
// we have to explicitly request the tokens for the changed ranges again.
|
| 474 |
+
for (const c of changedTokens.changes) {
|
| 475 |
+
this._backgroundTokenizer.value?.requestTokens(c.fromLineNumber, c.toLineNumber + 1);
|
| 476 |
+
}
|
| 477 |
+
}
|
| 478 |
+
this._defaultBackgroundTokenizer?.checkFinished();
|
| 479 |
+
}
|
| 480 |
+
forceTokenization(lineNumber) {
|
| 481 |
+
const builder = new ContiguousMultilineTokensBuilder();
|
| 482 |
+
this._tokenizer?.updateTokensUntilLine(builder, lineNumber);
|
| 483 |
+
this.setTokens(builder.finalize());
|
| 484 |
+
this._defaultBackgroundTokenizer?.checkFinished();
|
| 485 |
+
}
|
| 486 |
+
hasAccurateTokensForLine(lineNumber) {
|
| 487 |
+
if (!this._tokenizer) {
|
| 488 |
+
return true;
|
| 489 |
+
}
|
| 490 |
+
return this._tokenizer.hasAccurateTokensForLine(lineNumber);
|
| 491 |
+
}
|
| 492 |
+
isCheapToTokenize(lineNumber) {
|
| 493 |
+
if (!this._tokenizer) {
|
| 494 |
+
return true;
|
| 495 |
+
}
|
| 496 |
+
return this._tokenizer.isCheapToTokenize(lineNumber);
|
| 497 |
+
}
|
| 498 |
+
getLineTokens(lineNumber) {
|
| 499 |
+
const lineText = this._textModel.getLineContent(lineNumber);
|
| 500 |
+
const result = this._tokens.getTokens(this._textModel.getLanguageId(), lineNumber - 1, lineText);
|
| 501 |
+
if (this._debugBackgroundTokens && this._debugBackgroundStates && this._tokenizer) {
|
| 502 |
+
if (this._debugBackgroundStates.getFirstInvalidEndStateLineNumberOrMax() > lineNumber && this._tokenizer.store.getFirstInvalidEndStateLineNumberOrMax() > lineNumber) {
|
| 503 |
+
const backgroundResult = this._debugBackgroundTokens.getTokens(this._textModel.getLanguageId(), lineNumber - 1, lineText);
|
| 504 |
+
if (!result.equals(backgroundResult) && this._debugBackgroundTokenizer.value?.reportMismatchingTokens) {
|
| 505 |
+
this._debugBackgroundTokenizer.value.reportMismatchingTokens(lineNumber);
|
| 506 |
+
}
|
| 507 |
+
}
|
| 508 |
+
}
|
| 509 |
+
return result;
|
| 510 |
+
}
|
| 511 |
+
getTokenTypeIfInsertingCharacter(lineNumber, column, character) {
|
| 512 |
+
if (!this._tokenizer) {
|
| 513 |
+
return 0 /* StandardTokenType.Other */;
|
| 514 |
+
}
|
| 515 |
+
const position = this._textModel.validatePosition(new Position(lineNumber, column));
|
| 516 |
+
this.forceTokenization(position.lineNumber);
|
| 517 |
+
return this._tokenizer.getTokenTypeIfInsertingCharacter(position, character);
|
| 518 |
+
}
|
| 519 |
+
tokenizeLineWithEdit(position, length, newText) {
|
| 520 |
+
if (!this._tokenizer) {
|
| 521 |
+
return null;
|
| 522 |
+
}
|
| 523 |
+
const validatedPosition = this._textModel.validatePosition(position);
|
| 524 |
+
this.forceTokenization(validatedPosition.lineNumber);
|
| 525 |
+
return this._tokenizer.tokenizeLineWithEdit(validatedPosition, length, newText);
|
| 526 |
+
}
|
| 527 |
+
get hasTokens() {
|
| 528 |
+
return this._tokens.hasTokens;
|
| 529 |
+
}
|
| 530 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/tokens.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { equals } from '../../../base/common/arrays.js';
|
| 6 |
+
import { RunOnceScheduler } from '../../../base/common/async.js';
|
| 7 |
+
import { Emitter } from '../../../base/common/event.js';
|
| 8 |
+
import { Disposable } from '../../../base/common/lifecycle.js';
|
| 9 |
+
import { LineRange } from '../core/lineRange.js';
|
| 10 |
+
/**
|
| 11 |
+
* @internal
|
| 12 |
+
*/
|
| 13 |
+
export class AttachedViews {
|
| 14 |
+
constructor() {
|
| 15 |
+
this._onDidChangeVisibleRanges = new Emitter();
|
| 16 |
+
this.onDidChangeVisibleRanges = this._onDidChangeVisibleRanges.event;
|
| 17 |
+
this._views = new Set();
|
| 18 |
+
}
|
| 19 |
+
attachView() {
|
| 20 |
+
const view = new AttachedViewImpl((state) => {
|
| 21 |
+
this._onDidChangeVisibleRanges.fire({ view, state });
|
| 22 |
+
});
|
| 23 |
+
this._views.add(view);
|
| 24 |
+
return view;
|
| 25 |
+
}
|
| 26 |
+
detachView(view) {
|
| 27 |
+
this._views.delete(view);
|
| 28 |
+
this._onDidChangeVisibleRanges.fire({ view, state: undefined });
|
| 29 |
+
}
|
| 30 |
+
}
|
| 31 |
+
class AttachedViewImpl {
|
| 32 |
+
constructor(handleStateChange) {
|
| 33 |
+
this.handleStateChange = handleStateChange;
|
| 34 |
+
}
|
| 35 |
+
setVisibleLines(visibleLines, stabilized) {
|
| 36 |
+
const visibleLineRanges = visibleLines.map((line) => new LineRange(line.startLineNumber, line.endLineNumber + 1));
|
| 37 |
+
this.handleStateChange({ visibleLineRanges, stabilized });
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
export class AttachedViewHandler extends Disposable {
|
| 41 |
+
get lineRanges() { return this._lineRanges; }
|
| 42 |
+
constructor(_refreshTokens) {
|
| 43 |
+
super();
|
| 44 |
+
this._refreshTokens = _refreshTokens;
|
| 45 |
+
this.runner = this._register(new RunOnceScheduler(() => this.update(), 50));
|
| 46 |
+
this._computedLineRanges = [];
|
| 47 |
+
this._lineRanges = [];
|
| 48 |
+
}
|
| 49 |
+
update() {
|
| 50 |
+
if (equals(this._computedLineRanges, this._lineRanges, (a, b) => a.equals(b))) {
|
| 51 |
+
return;
|
| 52 |
+
}
|
| 53 |
+
this._computedLineRanges = this._lineRanges;
|
| 54 |
+
this._refreshTokens();
|
| 55 |
+
}
|
| 56 |
+
handleStateChange(state) {
|
| 57 |
+
this._lineRanges = state.visibleLineRanges;
|
| 58 |
+
if (state.stabilized) {
|
| 59 |
+
this.runner.cancel();
|
| 60 |
+
this.update();
|
| 61 |
+
}
|
| 62 |
+
else {
|
| 63 |
+
this.runner.schedule();
|
| 64 |
+
}
|
| 65 |
+
}
|
| 66 |
+
}
|
| 67 |
+
export class AbstractTokens extends Disposable {
|
| 68 |
+
get backgroundTokenizationState() {
|
| 69 |
+
return this._backgroundTokenizationState;
|
| 70 |
+
}
|
| 71 |
+
constructor(_languageIdCodec, _textModel, getLanguageId) {
|
| 72 |
+
super();
|
| 73 |
+
this._languageIdCodec = _languageIdCodec;
|
| 74 |
+
this._textModel = _textModel;
|
| 75 |
+
this.getLanguageId = getLanguageId;
|
| 76 |
+
this._backgroundTokenizationState = 1 /* BackgroundTokenizationState.InProgress */;
|
| 77 |
+
this._onDidChangeBackgroundTokenizationState = this._register(new Emitter());
|
| 78 |
+
/** @internal, should not be exposed by the text model! */
|
| 79 |
+
this.onDidChangeBackgroundTokenizationState = this._onDidChangeBackgroundTokenizationState.event;
|
| 80 |
+
this._onDidChangeTokens = this._register(new Emitter());
|
| 81 |
+
/** @internal, should not be exposed by the text model! */
|
| 82 |
+
this.onDidChangeTokens = this._onDidChangeTokens.event;
|
| 83 |
+
}
|
| 84 |
+
tokenizeIfCheap(lineNumber) {
|
| 85 |
+
if (this.isCheapToTokenize(lineNumber)) {
|
| 86 |
+
this.forceTokenization(lineNumber);
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/treeSitterTokens.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { TreeSitterTokenizationRegistry } from '../languages.js';
|
| 6 |
+
import { LineTokens } from '../tokens/lineTokens.js';
|
| 7 |
+
import { AbstractTokens } from './tokens.js';
|
| 8 |
+
export class TreeSitterTokens extends AbstractTokens {
|
| 9 |
+
constructor(_treeSitterService, languageIdCodec, textModel, languageId) {
|
| 10 |
+
super(languageIdCodec, textModel, languageId);
|
| 11 |
+
this._treeSitterService = _treeSitterService;
|
| 12 |
+
this._tokenizationSupport = null;
|
| 13 |
+
this._initialize();
|
| 14 |
+
}
|
| 15 |
+
_initialize() {
|
| 16 |
+
const newLanguage = this.getLanguageId();
|
| 17 |
+
if (!this._tokenizationSupport || this._lastLanguageId !== newLanguage) {
|
| 18 |
+
this._lastLanguageId = newLanguage;
|
| 19 |
+
this._tokenizationSupport = TreeSitterTokenizationRegistry.get(newLanguage);
|
| 20 |
+
}
|
| 21 |
+
}
|
| 22 |
+
getLineTokens(lineNumber) {
|
| 23 |
+
const content = this._textModel.getLineContent(lineNumber);
|
| 24 |
+
if (this._tokenizationSupport) {
|
| 25 |
+
const rawTokens = this._tokenizationSupport.tokenizeEncoded(lineNumber, this._textModel);
|
| 26 |
+
if (rawTokens) {
|
| 27 |
+
return new LineTokens(rawTokens, content, this._languageIdCodec);
|
| 28 |
+
}
|
| 29 |
+
}
|
| 30 |
+
return LineTokens.createEmpty(content, this._languageIdCodec);
|
| 31 |
+
}
|
| 32 |
+
resetTokenization(fireTokenChangeEvent = true) {
|
| 33 |
+
if (fireTokenChangeEvent) {
|
| 34 |
+
this._onDidChangeTokens.fire({
|
| 35 |
+
semanticTokensApplied: false,
|
| 36 |
+
ranges: [
|
| 37 |
+
{
|
| 38 |
+
fromLineNumber: 1,
|
| 39 |
+
toLineNumber: this._textModel.getLineCount(),
|
| 40 |
+
},
|
| 41 |
+
],
|
| 42 |
+
});
|
| 43 |
+
}
|
| 44 |
+
this._initialize();
|
| 45 |
+
}
|
| 46 |
+
handleDidChangeAttached() {
|
| 47 |
+
// TODO @alexr00 implement for background tokenization
|
| 48 |
+
}
|
| 49 |
+
handleDidChangeContent(e) {
|
| 50 |
+
if (e.isFlush) {
|
| 51 |
+
// Don't fire the event, as the view might not have got the text change event yet
|
| 52 |
+
this.resetTokenization(false);
|
| 53 |
+
}
|
| 54 |
+
}
|
| 55 |
+
forceTokenization(lineNumber) {
|
| 56 |
+
// TODO @alexr00 implement
|
| 57 |
+
}
|
| 58 |
+
hasAccurateTokensForLine(lineNumber) {
|
| 59 |
+
// TODO @alexr00 update for background tokenization
|
| 60 |
+
return true;
|
| 61 |
+
}
|
| 62 |
+
isCheapToTokenize(lineNumber) {
|
| 63 |
+
// TODO @alexr00 update for background tokenization
|
| 64 |
+
return true;
|
| 65 |
+
}
|
| 66 |
+
getTokenTypeIfInsertingCharacter(lineNumber, column, character) {
|
| 67 |
+
// TODO @alexr00 implement once we have custom parsing and don't just feed in the whole text model value
|
| 68 |
+
return 0 /* StandardTokenType.Other */;
|
| 69 |
+
}
|
| 70 |
+
tokenizeLineWithEdit(position, length, newText) {
|
| 71 |
+
// TODO @alexr00 understand what this is for and implement
|
| 72 |
+
return null;
|
| 73 |
+
}
|
| 74 |
+
get hasTokens() {
|
| 75 |
+
// TODO @alexr00 once we have a token store, implement properly
|
| 76 |
+
const hasTree = this._treeSitterService.getParseResult(this._textModel) !== undefined;
|
| 77 |
+
return hasTree;
|
| 78 |
+
}
|
| 79 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/model/utils.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
/**
|
| 6 |
+
* Returns:
|
| 7 |
+
* - -1 => the line consists of whitespace
|
| 8 |
+
* - otherwise => the indent level is returned value
|
| 9 |
+
*/
|
| 10 |
+
export function computeIndentLevel(line, tabSize) {
|
| 11 |
+
let indent = 0;
|
| 12 |
+
let i = 0;
|
| 13 |
+
const len = line.length;
|
| 14 |
+
while (i < len) {
|
| 15 |
+
const chCode = line.charCodeAt(i);
|
| 16 |
+
if (chCode === 32 /* CharCode.Space */) {
|
| 17 |
+
indent++;
|
| 18 |
+
}
|
| 19 |
+
else if (chCode === 9 /* CharCode.Tab */) {
|
| 20 |
+
indent = indent - indent % tabSize + tabSize;
|
| 21 |
+
}
|
| 22 |
+
else {
|
| 23 |
+
break;
|
| 24 |
+
}
|
| 25 |
+
i++;
|
| 26 |
+
}
|
| 27 |
+
if (i === len) {
|
| 28 |
+
return -1; // line only consists of whitespace
|
| 29 |
+
}
|
| 30 |
+
return indent;
|
| 31 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/modelLineProjectionData.js
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { assertNever } from '../../base/common/assert.js';
|
| 6 |
+
import { Position } from './core/position.js';
|
| 7 |
+
import { InjectedTextCursorStops } from './model.js';
|
| 8 |
+
/**
|
| 9 |
+
* *input*:
|
| 10 |
+
* ```
|
| 11 |
+
* xxxxxxxxxxxxxxxxxxxxxxxxxxx
|
| 12 |
+
* ```
|
| 13 |
+
*
|
| 14 |
+
* -> Applying injections `[i...i]`, *inputWithInjections*:
|
| 15 |
+
* ```
|
| 16 |
+
* xxxxxx[iiiiiiiiii]xxxxxxxxxxxxxxxxx[ii]xxxx
|
| 17 |
+
* ```
|
| 18 |
+
*
|
| 19 |
+
* -> breaking at offsets `|` in `xxxxxx[iiiiiii|iii]xxxxxxxxxxx|xxxxxx[ii]xxxx|`:
|
| 20 |
+
* ```
|
| 21 |
+
* xxxxxx[iiiiiii
|
| 22 |
+
* iii]xxxxxxxxxxx
|
| 23 |
+
* xxxxxx[ii]xxxx
|
| 24 |
+
* ```
|
| 25 |
+
*
|
| 26 |
+
* -> applying wrappedTextIndentLength, *output*:
|
| 27 |
+
* ```
|
| 28 |
+
* xxxxxx[iiiiiii
|
| 29 |
+
* iii]xxxxxxxxxxx
|
| 30 |
+
* xxxxxx[ii]xxxx
|
| 31 |
+
* ```
|
| 32 |
+
*/
|
| 33 |
+
export class ModelLineProjectionData {
|
| 34 |
+
constructor(injectionOffsets,
|
| 35 |
+
/**
|
| 36 |
+
* `injectionOptions.length` must equal `injectionOffsets.length`
|
| 37 |
+
*/
|
| 38 |
+
injectionOptions,
|
| 39 |
+
/**
|
| 40 |
+
* Refers to offsets after applying injections to the source.
|
| 41 |
+
* The last break offset indicates the length of the source after applying injections.
|
| 42 |
+
*/
|
| 43 |
+
breakOffsets,
|
| 44 |
+
/**
|
| 45 |
+
* Refers to offsets after applying injections
|
| 46 |
+
*/
|
| 47 |
+
breakOffsetsVisibleColumn, wrappedTextIndentLength) {
|
| 48 |
+
this.injectionOffsets = injectionOffsets;
|
| 49 |
+
this.injectionOptions = injectionOptions;
|
| 50 |
+
this.breakOffsets = breakOffsets;
|
| 51 |
+
this.breakOffsetsVisibleColumn = breakOffsetsVisibleColumn;
|
| 52 |
+
this.wrappedTextIndentLength = wrappedTextIndentLength;
|
| 53 |
+
}
|
| 54 |
+
getOutputLineCount() {
|
| 55 |
+
return this.breakOffsets.length;
|
| 56 |
+
}
|
| 57 |
+
getMinOutputOffset(outputLineIndex) {
|
| 58 |
+
if (outputLineIndex > 0) {
|
| 59 |
+
return this.wrappedTextIndentLength;
|
| 60 |
+
}
|
| 61 |
+
return 0;
|
| 62 |
+
}
|
| 63 |
+
getLineLength(outputLineIndex) {
|
| 64 |
+
// These offsets refer to model text with injected text.
|
| 65 |
+
const startOffset = outputLineIndex > 0 ? this.breakOffsets[outputLineIndex - 1] : 0;
|
| 66 |
+
const endOffset = this.breakOffsets[outputLineIndex];
|
| 67 |
+
let lineLength = endOffset - startOffset;
|
| 68 |
+
if (outputLineIndex > 0) {
|
| 69 |
+
lineLength += this.wrappedTextIndentLength;
|
| 70 |
+
}
|
| 71 |
+
return lineLength;
|
| 72 |
+
}
|
| 73 |
+
getMaxOutputOffset(outputLineIndex) {
|
| 74 |
+
return this.getLineLength(outputLineIndex);
|
| 75 |
+
}
|
| 76 |
+
translateToInputOffset(outputLineIndex, outputOffset) {
|
| 77 |
+
if (outputLineIndex > 0) {
|
| 78 |
+
outputOffset = Math.max(0, outputOffset - this.wrappedTextIndentLength);
|
| 79 |
+
}
|
| 80 |
+
const offsetInInputWithInjection = outputLineIndex === 0 ? outputOffset : this.breakOffsets[outputLineIndex - 1] + outputOffset;
|
| 81 |
+
let offsetInInput = offsetInInputWithInjection;
|
| 82 |
+
if (this.injectionOffsets !== null) {
|
| 83 |
+
for (let i = 0; i < this.injectionOffsets.length; i++) {
|
| 84 |
+
if (offsetInInput > this.injectionOffsets[i]) {
|
| 85 |
+
if (offsetInInput < this.injectionOffsets[i] + this.injectionOptions[i].content.length) {
|
| 86 |
+
// `inputOffset` is within injected text
|
| 87 |
+
offsetInInput = this.injectionOffsets[i];
|
| 88 |
+
}
|
| 89 |
+
else {
|
| 90 |
+
offsetInInput -= this.injectionOptions[i].content.length;
|
| 91 |
+
}
|
| 92 |
+
}
|
| 93 |
+
else {
|
| 94 |
+
break;
|
| 95 |
+
}
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
return offsetInInput;
|
| 99 |
+
}
|
| 100 |
+
translateToOutputPosition(inputOffset, affinity = 2 /* PositionAffinity.None */) {
|
| 101 |
+
let inputOffsetInInputWithInjection = inputOffset;
|
| 102 |
+
if (this.injectionOffsets !== null) {
|
| 103 |
+
for (let i = 0; i < this.injectionOffsets.length; i++) {
|
| 104 |
+
if (inputOffset < this.injectionOffsets[i]) {
|
| 105 |
+
break;
|
| 106 |
+
}
|
| 107 |
+
if (affinity !== 1 /* PositionAffinity.Right */ && inputOffset === this.injectionOffsets[i]) {
|
| 108 |
+
break;
|
| 109 |
+
}
|
| 110 |
+
inputOffsetInInputWithInjection += this.injectionOptions[i].content.length;
|
| 111 |
+
}
|
| 112 |
+
}
|
| 113 |
+
return this.offsetInInputWithInjectionsToOutputPosition(inputOffsetInInputWithInjection, affinity);
|
| 114 |
+
}
|
| 115 |
+
offsetInInputWithInjectionsToOutputPosition(offsetInInputWithInjections, affinity = 2 /* PositionAffinity.None */) {
|
| 116 |
+
let low = 0;
|
| 117 |
+
let high = this.breakOffsets.length - 1;
|
| 118 |
+
let mid = 0;
|
| 119 |
+
let midStart = 0;
|
| 120 |
+
while (low <= high) {
|
| 121 |
+
mid = low + ((high - low) / 2) | 0;
|
| 122 |
+
const midStop = this.breakOffsets[mid];
|
| 123 |
+
midStart = mid > 0 ? this.breakOffsets[mid - 1] : 0;
|
| 124 |
+
if (affinity === 0 /* PositionAffinity.Left */) {
|
| 125 |
+
if (offsetInInputWithInjections <= midStart) {
|
| 126 |
+
high = mid - 1;
|
| 127 |
+
}
|
| 128 |
+
else if (offsetInInputWithInjections > midStop) {
|
| 129 |
+
low = mid + 1;
|
| 130 |
+
}
|
| 131 |
+
else {
|
| 132 |
+
break;
|
| 133 |
+
}
|
| 134 |
+
}
|
| 135 |
+
else {
|
| 136 |
+
if (offsetInInputWithInjections < midStart) {
|
| 137 |
+
high = mid - 1;
|
| 138 |
+
}
|
| 139 |
+
else if (offsetInInputWithInjections >= midStop) {
|
| 140 |
+
low = mid + 1;
|
| 141 |
+
}
|
| 142 |
+
else {
|
| 143 |
+
break;
|
| 144 |
+
}
|
| 145 |
+
}
|
| 146 |
+
}
|
| 147 |
+
let outputOffset = offsetInInputWithInjections - midStart;
|
| 148 |
+
if (mid > 0) {
|
| 149 |
+
outputOffset += this.wrappedTextIndentLength;
|
| 150 |
+
}
|
| 151 |
+
return new OutputPosition(mid, outputOffset);
|
| 152 |
+
}
|
| 153 |
+
normalizeOutputPosition(outputLineIndex, outputOffset, affinity) {
|
| 154 |
+
if (this.injectionOffsets !== null) {
|
| 155 |
+
const offsetInInputWithInjections = this.outputPositionToOffsetInInputWithInjections(outputLineIndex, outputOffset);
|
| 156 |
+
const normalizedOffsetInUnwrappedLine = this.normalizeOffsetInInputWithInjectionsAroundInjections(offsetInInputWithInjections, affinity);
|
| 157 |
+
if (normalizedOffsetInUnwrappedLine !== offsetInInputWithInjections) {
|
| 158 |
+
// injected text caused a change
|
| 159 |
+
return this.offsetInInputWithInjectionsToOutputPosition(normalizedOffsetInUnwrappedLine, affinity);
|
| 160 |
+
}
|
| 161 |
+
}
|
| 162 |
+
if (affinity === 0 /* PositionAffinity.Left */) {
|
| 163 |
+
if (outputLineIndex > 0 && outputOffset === this.getMinOutputOffset(outputLineIndex)) {
|
| 164 |
+
return new OutputPosition(outputLineIndex - 1, this.getMaxOutputOffset(outputLineIndex - 1));
|
| 165 |
+
}
|
| 166 |
+
}
|
| 167 |
+
else if (affinity === 1 /* PositionAffinity.Right */) {
|
| 168 |
+
const maxOutputLineIndex = this.getOutputLineCount() - 1;
|
| 169 |
+
if (outputLineIndex < maxOutputLineIndex && outputOffset === this.getMaxOutputOffset(outputLineIndex)) {
|
| 170 |
+
return new OutputPosition(outputLineIndex + 1, this.getMinOutputOffset(outputLineIndex + 1));
|
| 171 |
+
}
|
| 172 |
+
}
|
| 173 |
+
return new OutputPosition(outputLineIndex, outputOffset);
|
| 174 |
+
}
|
| 175 |
+
outputPositionToOffsetInInputWithInjections(outputLineIndex, outputOffset) {
|
| 176 |
+
if (outputLineIndex > 0) {
|
| 177 |
+
outputOffset = Math.max(0, outputOffset - this.wrappedTextIndentLength);
|
| 178 |
+
}
|
| 179 |
+
const result = (outputLineIndex > 0 ? this.breakOffsets[outputLineIndex - 1] : 0) + outputOffset;
|
| 180 |
+
return result;
|
| 181 |
+
}
|
| 182 |
+
normalizeOffsetInInputWithInjectionsAroundInjections(offsetInInputWithInjections, affinity) {
|
| 183 |
+
const injectedText = this.getInjectedTextAtOffset(offsetInInputWithInjections);
|
| 184 |
+
if (!injectedText) {
|
| 185 |
+
return offsetInInputWithInjections;
|
| 186 |
+
}
|
| 187 |
+
if (affinity === 2 /* PositionAffinity.None */) {
|
| 188 |
+
if (offsetInInputWithInjections === injectedText.offsetInInputWithInjections + injectedText.length
|
| 189 |
+
&& hasRightCursorStop(this.injectionOptions[injectedText.injectedTextIndex].cursorStops)) {
|
| 190 |
+
return injectedText.offsetInInputWithInjections + injectedText.length;
|
| 191 |
+
}
|
| 192 |
+
else {
|
| 193 |
+
let result = injectedText.offsetInInputWithInjections;
|
| 194 |
+
if (hasLeftCursorStop(this.injectionOptions[injectedText.injectedTextIndex].cursorStops)) {
|
| 195 |
+
return result;
|
| 196 |
+
}
|
| 197 |
+
let index = injectedText.injectedTextIndex - 1;
|
| 198 |
+
while (index >= 0 && this.injectionOffsets[index] === this.injectionOffsets[injectedText.injectedTextIndex]) {
|
| 199 |
+
if (hasRightCursorStop(this.injectionOptions[index].cursorStops)) {
|
| 200 |
+
break;
|
| 201 |
+
}
|
| 202 |
+
result -= this.injectionOptions[index].content.length;
|
| 203 |
+
if (hasLeftCursorStop(this.injectionOptions[index].cursorStops)) {
|
| 204 |
+
break;
|
| 205 |
+
}
|
| 206 |
+
index--;
|
| 207 |
+
}
|
| 208 |
+
return result;
|
| 209 |
+
}
|
| 210 |
+
}
|
| 211 |
+
else if (affinity === 1 /* PositionAffinity.Right */ || affinity === 4 /* PositionAffinity.RightOfInjectedText */) {
|
| 212 |
+
let result = injectedText.offsetInInputWithInjections + injectedText.length;
|
| 213 |
+
let index = injectedText.injectedTextIndex;
|
| 214 |
+
// traverse all injected text that touch each other
|
| 215 |
+
while (index + 1 < this.injectionOffsets.length && this.injectionOffsets[index + 1] === this.injectionOffsets[index]) {
|
| 216 |
+
result += this.injectionOptions[index + 1].content.length;
|
| 217 |
+
index++;
|
| 218 |
+
}
|
| 219 |
+
return result;
|
| 220 |
+
}
|
| 221 |
+
else if (affinity === 0 /* PositionAffinity.Left */ || affinity === 3 /* PositionAffinity.LeftOfInjectedText */) {
|
| 222 |
+
// affinity is left
|
| 223 |
+
let result = injectedText.offsetInInputWithInjections;
|
| 224 |
+
let index = injectedText.injectedTextIndex;
|
| 225 |
+
// traverse all injected text that touch each other
|
| 226 |
+
while (index - 1 >= 0 && this.injectionOffsets[index - 1] === this.injectionOffsets[index]) {
|
| 227 |
+
result -= this.injectionOptions[index - 1].content.length;
|
| 228 |
+
index--;
|
| 229 |
+
}
|
| 230 |
+
return result;
|
| 231 |
+
}
|
| 232 |
+
assertNever(affinity);
|
| 233 |
+
}
|
| 234 |
+
getInjectedText(outputLineIndex, outputOffset) {
|
| 235 |
+
const offset = this.outputPositionToOffsetInInputWithInjections(outputLineIndex, outputOffset);
|
| 236 |
+
const injectedText = this.getInjectedTextAtOffset(offset);
|
| 237 |
+
if (!injectedText) {
|
| 238 |
+
return null;
|
| 239 |
+
}
|
| 240 |
+
return {
|
| 241 |
+
options: this.injectionOptions[injectedText.injectedTextIndex]
|
| 242 |
+
};
|
| 243 |
+
}
|
| 244 |
+
getInjectedTextAtOffset(offsetInInputWithInjections) {
|
| 245 |
+
const injectionOffsets = this.injectionOffsets;
|
| 246 |
+
const injectionOptions = this.injectionOptions;
|
| 247 |
+
if (injectionOffsets !== null) {
|
| 248 |
+
let totalInjectedTextLengthBefore = 0;
|
| 249 |
+
for (let i = 0; i < injectionOffsets.length; i++) {
|
| 250 |
+
const length = injectionOptions[i].content.length;
|
| 251 |
+
const injectedTextStartOffsetInInputWithInjections = injectionOffsets[i] + totalInjectedTextLengthBefore;
|
| 252 |
+
const injectedTextEndOffsetInInputWithInjections = injectionOffsets[i] + totalInjectedTextLengthBefore + length;
|
| 253 |
+
if (injectedTextStartOffsetInInputWithInjections > offsetInInputWithInjections) {
|
| 254 |
+
// Injected text starts later.
|
| 255 |
+
break; // All later injected texts have an even larger offset.
|
| 256 |
+
}
|
| 257 |
+
if (offsetInInputWithInjections <= injectedTextEndOffsetInInputWithInjections) {
|
| 258 |
+
// Injected text ends after or with the given position (but also starts with or before it).
|
| 259 |
+
return {
|
| 260 |
+
injectedTextIndex: i,
|
| 261 |
+
offsetInInputWithInjections: injectedTextStartOffsetInInputWithInjections,
|
| 262 |
+
length
|
| 263 |
+
};
|
| 264 |
+
}
|
| 265 |
+
totalInjectedTextLengthBefore += length;
|
| 266 |
+
}
|
| 267 |
+
}
|
| 268 |
+
return undefined;
|
| 269 |
+
}
|
| 270 |
+
}
|
| 271 |
+
function hasRightCursorStop(cursorStop) {
|
| 272 |
+
if (cursorStop === null || cursorStop === undefined) {
|
| 273 |
+
return true;
|
| 274 |
+
}
|
| 275 |
+
return cursorStop === InjectedTextCursorStops.Right || cursorStop === InjectedTextCursorStops.Both;
|
| 276 |
+
}
|
| 277 |
+
function hasLeftCursorStop(cursorStop) {
|
| 278 |
+
if (cursorStop === null || cursorStop === undefined) {
|
| 279 |
+
return true;
|
| 280 |
+
}
|
| 281 |
+
return cursorStop === InjectedTextCursorStops.Left || cursorStop === InjectedTextCursorStops.Both;
|
| 282 |
+
}
|
| 283 |
+
export class InjectedText {
|
| 284 |
+
constructor(options) {
|
| 285 |
+
this.options = options;
|
| 286 |
+
}
|
| 287 |
+
}
|
| 288 |
+
export class OutputPosition {
|
| 289 |
+
constructor(outputLineIndex, outputOffset) {
|
| 290 |
+
this.outputLineIndex = outputLineIndex;
|
| 291 |
+
this.outputOffset = outputOffset;
|
| 292 |
+
}
|
| 293 |
+
toString() {
|
| 294 |
+
return `${this.outputLineIndex}:${this.outputOffset}`;
|
| 295 |
+
}
|
| 296 |
+
toPosition(baseLineNumber) {
|
| 297 |
+
return new Position(baseLineNumber + this.outputLineIndex, this.outputOffset + 1);
|
| 298 |
+
}
|
| 299 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/editorBaseApi.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { CancellationTokenSource } from '../../../base/common/cancellation.js';
|
| 6 |
+
import { Emitter } from '../../../base/common/event.js';
|
| 7 |
+
import { KeyChord } from '../../../base/common/keyCodes.js';
|
| 8 |
+
import { URI } from '../../../base/common/uri.js';
|
| 9 |
+
import { Position } from '../core/position.js';
|
| 10 |
+
import { Range } from '../core/range.js';
|
| 11 |
+
import { Selection } from '../core/selection.js';
|
| 12 |
+
import { Token } from '../languages.js';
|
| 13 |
+
import * as standaloneEnums from '../standalone/standaloneEnums.js';
|
| 14 |
+
export class KeyMod {
|
| 15 |
+
static { this.CtrlCmd = 2048 /* ConstKeyMod.CtrlCmd */; }
|
| 16 |
+
static { this.Shift = 1024 /* ConstKeyMod.Shift */; }
|
| 17 |
+
static { this.Alt = 512 /* ConstKeyMod.Alt */; }
|
| 18 |
+
static { this.WinCtrl = 256 /* ConstKeyMod.WinCtrl */; }
|
| 19 |
+
static chord(firstPart, secondPart) {
|
| 20 |
+
return KeyChord(firstPart, secondPart);
|
| 21 |
+
}
|
| 22 |
+
}
|
| 23 |
+
export function createMonacoBaseAPI() {
|
| 24 |
+
return {
|
| 25 |
+
editor: undefined, // undefined override expected here
|
| 26 |
+
languages: undefined, // undefined override expected here
|
| 27 |
+
CancellationTokenSource: CancellationTokenSource,
|
| 28 |
+
Emitter: Emitter,
|
| 29 |
+
KeyCode: standaloneEnums.KeyCode,
|
| 30 |
+
KeyMod: KeyMod,
|
| 31 |
+
Position: Position,
|
| 32 |
+
Range: Range,
|
| 33 |
+
Selection: Selection,
|
| 34 |
+
SelectionDirection: standaloneEnums.SelectionDirection,
|
| 35 |
+
MarkerSeverity: standaloneEnums.MarkerSeverity,
|
| 36 |
+
MarkerTag: standaloneEnums.MarkerTag,
|
| 37 |
+
Uri: URI,
|
| 38 |
+
Token: Token
|
| 39 |
+
};
|
| 40 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/editorSimpleWorker.js
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { stringDiff } from '../../../base/common/diff/diff.js';
|
| 6 |
+
import { Range } from '../core/range.js';
|
| 7 |
+
import { computeLinks } from '../languages/linkComputer.js';
|
| 8 |
+
import { BasicInplaceReplace } from '../languages/supports/inplaceReplaceSupport.js';
|
| 9 |
+
import { createMonacoBaseAPI } from './editorBaseApi.js';
|
| 10 |
+
import { EditorWorkerHost } from './editorWorkerHost.js';
|
| 11 |
+
import { StopWatch } from '../../../base/common/stopwatch.js';
|
| 12 |
+
import { UnicodeTextModelHighlighter } from './unicodeTextModelHighlighter.js';
|
| 13 |
+
import { linesDiffComputers } from '../diff/linesDiffComputers.js';
|
| 14 |
+
import { createProxyObject, getAllMethodNames } from '../../../base/common/objects.js';
|
| 15 |
+
import { FileAccess } from '../../../base/common/network.js';
|
| 16 |
+
import { computeDefaultDocumentColors } from '../languages/defaultDocumentColorsComputer.js';
|
| 17 |
+
import { findSectionHeaders } from './findSectionHeaders.js';
|
| 18 |
+
import { WorkerTextModelSyncServer } from './textModelSync/textModelSync.impl.js';
|
| 19 |
+
// ESM-comment-begin
|
| 20 |
+
// const isESM = false;
|
| 21 |
+
// ESM-comment-end
|
| 22 |
+
// ESM-uncomment-begin
|
| 23 |
+
const isESM = true;
|
| 24 |
+
/**
|
| 25 |
+
* @internal
|
| 26 |
+
*/
|
| 27 |
+
export class BaseEditorSimpleWorker {
|
| 28 |
+
constructor() {
|
| 29 |
+
this._workerTextModelSyncServer = new WorkerTextModelSyncServer();
|
| 30 |
+
}
|
| 31 |
+
dispose() {
|
| 32 |
+
}
|
| 33 |
+
_getModel(uri) {
|
| 34 |
+
return this._workerTextModelSyncServer.getModel(uri);
|
| 35 |
+
}
|
| 36 |
+
_getModels() {
|
| 37 |
+
return this._workerTextModelSyncServer.getModels();
|
| 38 |
+
}
|
| 39 |
+
$acceptNewModel(data) {
|
| 40 |
+
this._workerTextModelSyncServer.$acceptNewModel(data);
|
| 41 |
+
}
|
| 42 |
+
$acceptModelChanged(uri, e) {
|
| 43 |
+
this._workerTextModelSyncServer.$acceptModelChanged(uri, e);
|
| 44 |
+
}
|
| 45 |
+
$acceptRemovedModel(uri) {
|
| 46 |
+
this._workerTextModelSyncServer.$acceptRemovedModel(uri);
|
| 47 |
+
}
|
| 48 |
+
async $computeUnicodeHighlights(url, options, range) {
|
| 49 |
+
const model = this._getModel(url);
|
| 50 |
+
if (!model) {
|
| 51 |
+
return { ranges: [], hasMore: false, ambiguousCharacterCount: 0, invisibleCharacterCount: 0, nonBasicAsciiCharacterCount: 0 };
|
| 52 |
+
}
|
| 53 |
+
return UnicodeTextModelHighlighter.computeUnicodeHighlights(model, options, range);
|
| 54 |
+
}
|
| 55 |
+
async $findSectionHeaders(url, options) {
|
| 56 |
+
const model = this._getModel(url);
|
| 57 |
+
if (!model) {
|
| 58 |
+
return [];
|
| 59 |
+
}
|
| 60 |
+
return findSectionHeaders(model, options);
|
| 61 |
+
}
|
| 62 |
+
// ---- BEGIN diff --------------------------------------------------------------------------
|
| 63 |
+
async $computeDiff(originalUrl, modifiedUrl, options, algorithm) {
|
| 64 |
+
const original = this._getModel(originalUrl);
|
| 65 |
+
const modified = this._getModel(modifiedUrl);
|
| 66 |
+
if (!original || !modified) {
|
| 67 |
+
return null;
|
| 68 |
+
}
|
| 69 |
+
const result = EditorSimpleWorker.computeDiff(original, modified, options, algorithm);
|
| 70 |
+
return result;
|
| 71 |
+
}
|
| 72 |
+
static computeDiff(originalTextModel, modifiedTextModel, options, algorithm) {
|
| 73 |
+
const diffAlgorithm = algorithm === 'advanced' ? linesDiffComputers.getDefault() : linesDiffComputers.getLegacy();
|
| 74 |
+
const originalLines = originalTextModel.getLinesContent();
|
| 75 |
+
const modifiedLines = modifiedTextModel.getLinesContent();
|
| 76 |
+
const result = diffAlgorithm.computeDiff(originalLines, modifiedLines, options);
|
| 77 |
+
const identical = (result.changes.length > 0 ? false : this._modelsAreIdentical(originalTextModel, modifiedTextModel));
|
| 78 |
+
function getLineChanges(changes) {
|
| 79 |
+
return changes.map(m => ([m.original.startLineNumber, m.original.endLineNumberExclusive, m.modified.startLineNumber, m.modified.endLineNumberExclusive, m.innerChanges?.map(m => [
|
| 80 |
+
m.originalRange.startLineNumber,
|
| 81 |
+
m.originalRange.startColumn,
|
| 82 |
+
m.originalRange.endLineNumber,
|
| 83 |
+
m.originalRange.endColumn,
|
| 84 |
+
m.modifiedRange.startLineNumber,
|
| 85 |
+
m.modifiedRange.startColumn,
|
| 86 |
+
m.modifiedRange.endLineNumber,
|
| 87 |
+
m.modifiedRange.endColumn,
|
| 88 |
+
])]));
|
| 89 |
+
}
|
| 90 |
+
return {
|
| 91 |
+
identical,
|
| 92 |
+
quitEarly: result.hitTimeout,
|
| 93 |
+
changes: getLineChanges(result.changes),
|
| 94 |
+
moves: result.moves.map(m => ([
|
| 95 |
+
m.lineRangeMapping.original.startLineNumber,
|
| 96 |
+
m.lineRangeMapping.original.endLineNumberExclusive,
|
| 97 |
+
m.lineRangeMapping.modified.startLineNumber,
|
| 98 |
+
m.lineRangeMapping.modified.endLineNumberExclusive,
|
| 99 |
+
getLineChanges(m.changes)
|
| 100 |
+
])),
|
| 101 |
+
};
|
| 102 |
+
}
|
| 103 |
+
static _modelsAreIdentical(original, modified) {
|
| 104 |
+
const originalLineCount = original.getLineCount();
|
| 105 |
+
const modifiedLineCount = modified.getLineCount();
|
| 106 |
+
if (originalLineCount !== modifiedLineCount) {
|
| 107 |
+
return false;
|
| 108 |
+
}
|
| 109 |
+
for (let line = 1; line <= originalLineCount; line++) {
|
| 110 |
+
const originalLine = original.getLineContent(line);
|
| 111 |
+
const modifiedLine = modified.getLineContent(line);
|
| 112 |
+
if (originalLine !== modifiedLine) {
|
| 113 |
+
return false;
|
| 114 |
+
}
|
| 115 |
+
}
|
| 116 |
+
return true;
|
| 117 |
+
}
|
| 118 |
+
// ---- END diff --------------------------------------------------------------------------
|
| 119 |
+
// ---- BEGIN minimal edits ---------------------------------------------------------------
|
| 120 |
+
static { this._diffLimit = 100000; }
|
| 121 |
+
async $computeMoreMinimalEdits(modelUrl, edits, pretty) {
|
| 122 |
+
const model = this._getModel(modelUrl);
|
| 123 |
+
if (!model) {
|
| 124 |
+
return edits;
|
| 125 |
+
}
|
| 126 |
+
const result = [];
|
| 127 |
+
let lastEol = undefined;
|
| 128 |
+
edits = edits.slice(0).sort((a, b) => {
|
| 129 |
+
if (a.range && b.range) {
|
| 130 |
+
return Range.compareRangesUsingStarts(a.range, b.range);
|
| 131 |
+
}
|
| 132 |
+
// eol only changes should go to the end
|
| 133 |
+
const aRng = a.range ? 0 : 1;
|
| 134 |
+
const bRng = b.range ? 0 : 1;
|
| 135 |
+
return aRng - bRng;
|
| 136 |
+
});
|
| 137 |
+
// merge adjacent edits
|
| 138 |
+
let writeIndex = 0;
|
| 139 |
+
for (let readIndex = 1; readIndex < edits.length; readIndex++) {
|
| 140 |
+
if (Range.getEndPosition(edits[writeIndex].range).equals(Range.getStartPosition(edits[readIndex].range))) {
|
| 141 |
+
edits[writeIndex].range = Range.fromPositions(Range.getStartPosition(edits[writeIndex].range), Range.getEndPosition(edits[readIndex].range));
|
| 142 |
+
edits[writeIndex].text += edits[readIndex].text;
|
| 143 |
+
}
|
| 144 |
+
else {
|
| 145 |
+
writeIndex++;
|
| 146 |
+
edits[writeIndex] = edits[readIndex];
|
| 147 |
+
}
|
| 148 |
+
}
|
| 149 |
+
edits.length = writeIndex + 1;
|
| 150 |
+
for (let { range, text, eol } of edits) {
|
| 151 |
+
if (typeof eol === 'number') {
|
| 152 |
+
lastEol = eol;
|
| 153 |
+
}
|
| 154 |
+
if (Range.isEmpty(range) && !text) {
|
| 155 |
+
// empty change
|
| 156 |
+
continue;
|
| 157 |
+
}
|
| 158 |
+
const original = model.getValueInRange(range);
|
| 159 |
+
text = text.replace(/\r\n|\n|\r/g, model.eol);
|
| 160 |
+
if (original === text) {
|
| 161 |
+
// noop
|
| 162 |
+
continue;
|
| 163 |
+
}
|
| 164 |
+
// make sure diff won't take too long
|
| 165 |
+
if (Math.max(text.length, original.length) > EditorSimpleWorker._diffLimit) {
|
| 166 |
+
result.push({ range, text });
|
| 167 |
+
continue;
|
| 168 |
+
}
|
| 169 |
+
// compute diff between original and edit.text
|
| 170 |
+
const changes = stringDiff(original, text, pretty);
|
| 171 |
+
const editOffset = model.offsetAt(Range.lift(range).getStartPosition());
|
| 172 |
+
for (const change of changes) {
|
| 173 |
+
const start = model.positionAt(editOffset + change.originalStart);
|
| 174 |
+
const end = model.positionAt(editOffset + change.originalStart + change.originalLength);
|
| 175 |
+
const newEdit = {
|
| 176 |
+
text: text.substr(change.modifiedStart, change.modifiedLength),
|
| 177 |
+
range: { startLineNumber: start.lineNumber, startColumn: start.column, endLineNumber: end.lineNumber, endColumn: end.column }
|
| 178 |
+
};
|
| 179 |
+
if (model.getValueInRange(newEdit.range) !== newEdit.text) {
|
| 180 |
+
result.push(newEdit);
|
| 181 |
+
}
|
| 182 |
+
}
|
| 183 |
+
}
|
| 184 |
+
if (typeof lastEol === 'number') {
|
| 185 |
+
result.push({ eol: lastEol, text: '', range: { startLineNumber: 0, startColumn: 0, endLineNumber: 0, endColumn: 0 } });
|
| 186 |
+
}
|
| 187 |
+
return result;
|
| 188 |
+
}
|
| 189 |
+
// ---- END minimal edits ---------------------------------------------------------------
|
| 190 |
+
async $computeLinks(modelUrl) {
|
| 191 |
+
const model = this._getModel(modelUrl);
|
| 192 |
+
if (!model) {
|
| 193 |
+
return null;
|
| 194 |
+
}
|
| 195 |
+
return computeLinks(model);
|
| 196 |
+
}
|
| 197 |
+
// --- BEGIN default document colors -----------------------------------------------------------
|
| 198 |
+
async $computeDefaultDocumentColors(modelUrl) {
|
| 199 |
+
const model = this._getModel(modelUrl);
|
| 200 |
+
if (!model) {
|
| 201 |
+
return null;
|
| 202 |
+
}
|
| 203 |
+
return computeDefaultDocumentColors(model);
|
| 204 |
+
}
|
| 205 |
+
// ---- BEGIN suggest --------------------------------------------------------------------------
|
| 206 |
+
static { this._suggestionsLimit = 10000; }
|
| 207 |
+
async $textualSuggest(modelUrls, leadingWord, wordDef, wordDefFlags) {
|
| 208 |
+
const sw = new StopWatch();
|
| 209 |
+
const wordDefRegExp = new RegExp(wordDef, wordDefFlags);
|
| 210 |
+
const seen = new Set();
|
| 211 |
+
outer: for (const url of modelUrls) {
|
| 212 |
+
const model = this._getModel(url);
|
| 213 |
+
if (!model) {
|
| 214 |
+
continue;
|
| 215 |
+
}
|
| 216 |
+
for (const word of model.words(wordDefRegExp)) {
|
| 217 |
+
if (word === leadingWord || !isNaN(Number(word))) {
|
| 218 |
+
continue;
|
| 219 |
+
}
|
| 220 |
+
seen.add(word);
|
| 221 |
+
if (seen.size > EditorSimpleWorker._suggestionsLimit) {
|
| 222 |
+
break outer;
|
| 223 |
+
}
|
| 224 |
+
}
|
| 225 |
+
}
|
| 226 |
+
return { words: Array.from(seen), duration: sw.elapsed() };
|
| 227 |
+
}
|
| 228 |
+
// ---- END suggest --------------------------------------------------------------------------
|
| 229 |
+
//#region -- word ranges --
|
| 230 |
+
async $computeWordRanges(modelUrl, range, wordDef, wordDefFlags) {
|
| 231 |
+
const model = this._getModel(modelUrl);
|
| 232 |
+
if (!model) {
|
| 233 |
+
return Object.create(null);
|
| 234 |
+
}
|
| 235 |
+
const wordDefRegExp = new RegExp(wordDef, wordDefFlags);
|
| 236 |
+
const result = Object.create(null);
|
| 237 |
+
for (let line = range.startLineNumber; line < range.endLineNumber; line++) {
|
| 238 |
+
const words = model.getLineWords(line, wordDefRegExp);
|
| 239 |
+
for (const word of words) {
|
| 240 |
+
if (!isNaN(Number(word.word))) {
|
| 241 |
+
continue;
|
| 242 |
+
}
|
| 243 |
+
let array = result[word.word];
|
| 244 |
+
if (!array) {
|
| 245 |
+
array = [];
|
| 246 |
+
result[word.word] = array;
|
| 247 |
+
}
|
| 248 |
+
array.push({
|
| 249 |
+
startLineNumber: line,
|
| 250 |
+
startColumn: word.startColumn,
|
| 251 |
+
endLineNumber: line,
|
| 252 |
+
endColumn: word.endColumn
|
| 253 |
+
});
|
| 254 |
+
}
|
| 255 |
+
}
|
| 256 |
+
return result;
|
| 257 |
+
}
|
| 258 |
+
//#endregion
|
| 259 |
+
async $navigateValueSet(modelUrl, range, up, wordDef, wordDefFlags) {
|
| 260 |
+
const model = this._getModel(modelUrl);
|
| 261 |
+
if (!model) {
|
| 262 |
+
return null;
|
| 263 |
+
}
|
| 264 |
+
const wordDefRegExp = new RegExp(wordDef, wordDefFlags);
|
| 265 |
+
if (range.startColumn === range.endColumn) {
|
| 266 |
+
range = {
|
| 267 |
+
startLineNumber: range.startLineNumber,
|
| 268 |
+
startColumn: range.startColumn,
|
| 269 |
+
endLineNumber: range.endLineNumber,
|
| 270 |
+
endColumn: range.endColumn + 1
|
| 271 |
+
};
|
| 272 |
+
}
|
| 273 |
+
const selectionText = model.getValueInRange(range);
|
| 274 |
+
const wordRange = model.getWordAtPosition({ lineNumber: range.startLineNumber, column: range.startColumn }, wordDefRegExp);
|
| 275 |
+
if (!wordRange) {
|
| 276 |
+
return null;
|
| 277 |
+
}
|
| 278 |
+
const word = model.getValueInRange(wordRange);
|
| 279 |
+
const result = BasicInplaceReplace.INSTANCE.navigateValueSet(range, selectionText, wordRange, word, up);
|
| 280 |
+
return result;
|
| 281 |
+
}
|
| 282 |
+
}
|
| 283 |
+
/**
|
| 284 |
+
* @internal
|
| 285 |
+
*/
|
| 286 |
+
export class EditorSimpleWorker extends BaseEditorSimpleWorker {
|
| 287 |
+
constructor(_host, _foreignModuleFactory) {
|
| 288 |
+
super();
|
| 289 |
+
this._host = _host;
|
| 290 |
+
this._foreignModuleFactory = _foreignModuleFactory;
|
| 291 |
+
this._foreignModule = null;
|
| 292 |
+
}
|
| 293 |
+
async $ping() {
|
| 294 |
+
return 'pong';
|
| 295 |
+
}
|
| 296 |
+
// ---- BEGIN foreign module support --------------------------------------------------------------------------
|
| 297 |
+
$loadForeignModule(moduleId, createData, foreignHostMethods) {
|
| 298 |
+
const proxyMethodRequest = (method, args) => {
|
| 299 |
+
return this._host.$fhr(method, args);
|
| 300 |
+
};
|
| 301 |
+
const foreignHost = createProxyObject(foreignHostMethods, proxyMethodRequest);
|
| 302 |
+
const ctx = {
|
| 303 |
+
host: foreignHost,
|
| 304 |
+
getMirrorModels: () => {
|
| 305 |
+
return this._getModels();
|
| 306 |
+
}
|
| 307 |
+
};
|
| 308 |
+
if (this._foreignModuleFactory) {
|
| 309 |
+
this._foreignModule = this._foreignModuleFactory(ctx, createData);
|
| 310 |
+
// static foreing module
|
| 311 |
+
return Promise.resolve(getAllMethodNames(this._foreignModule));
|
| 312 |
+
}
|
| 313 |
+
return new Promise((resolve, reject) => {
|
| 314 |
+
const onModuleCallback = (foreignModule) => {
|
| 315 |
+
this._foreignModule = foreignModule.create(ctx, createData);
|
| 316 |
+
resolve(getAllMethodNames(this._foreignModule));
|
| 317 |
+
};
|
| 318 |
+
if (!isESM) {
|
| 319 |
+
require([`${moduleId}`], onModuleCallback, reject);
|
| 320 |
+
}
|
| 321 |
+
else {
|
| 322 |
+
const url = FileAccess.asBrowserUri(`${moduleId}.js`).toString(true);
|
| 323 |
+
import(`${url}`).then(onModuleCallback).catch(reject);
|
| 324 |
+
}
|
| 325 |
+
});
|
| 326 |
+
}
|
| 327 |
+
// foreign method request
|
| 328 |
+
$fmr(method, args) {
|
| 329 |
+
if (!this._foreignModule || typeof this._foreignModule[method] !== 'function') {
|
| 330 |
+
return Promise.reject(new Error('Missing requestHandler or method: ' + method));
|
| 331 |
+
}
|
| 332 |
+
try {
|
| 333 |
+
return Promise.resolve(this._foreignModule[method].apply(this._foreignModule, args));
|
| 334 |
+
}
|
| 335 |
+
catch (e) {
|
| 336 |
+
return Promise.reject(e);
|
| 337 |
+
}
|
| 338 |
+
}
|
| 339 |
+
}
|
| 340 |
+
/**
|
| 341 |
+
* Defines the worker entry point. Must be exported and named `create`.
|
| 342 |
+
* @skipMangle
|
| 343 |
+
* @internal
|
| 344 |
+
*/
|
| 345 |
+
export function create(workerServer) {
|
| 346 |
+
return new EditorSimpleWorker(EditorWorkerHost.getChannel(workerServer), null);
|
| 347 |
+
}
|
| 348 |
+
if (typeof importScripts === 'function') {
|
| 349 |
+
// Running in a web worker
|
| 350 |
+
globalThis.monaco = createMonacoBaseAPI();
|
| 351 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/editorWorker.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
|
| 6 |
+
export const IEditorWorkerService = createDecorator('editorWorkerService');
|
node_modules/monaco-editor/esm/vs/editor/common/services/editorWorkerHost.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
export class EditorWorkerHost {
|
| 6 |
+
static { this.CHANNEL_NAME = 'editorWorkerHost'; }
|
| 7 |
+
static getChannel(workerServer) {
|
| 8 |
+
return workerServer.getChannel(EditorWorkerHost.CHANNEL_NAME);
|
| 9 |
+
}
|
| 10 |
+
static setChannel(workerClient, obj) {
|
| 11 |
+
workerClient.setChannel(EditorWorkerHost.CHANNEL_NAME, obj);
|
| 12 |
+
}
|
| 13 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/findSectionHeaders.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
const markRegex = new RegExp('\\bMARK:\\s*(.*)$', 'd');
|
| 6 |
+
const trimDashesRegex = /^-+|-+$/g;
|
| 7 |
+
/**
|
| 8 |
+
* Find section headers in the model.
|
| 9 |
+
*
|
| 10 |
+
* @param model the text model to search in
|
| 11 |
+
* @param options options to search with
|
| 12 |
+
* @returns an array of section headers
|
| 13 |
+
*/
|
| 14 |
+
export function findSectionHeaders(model, options) {
|
| 15 |
+
let headers = [];
|
| 16 |
+
if (options.findRegionSectionHeaders && options.foldingRules?.markers) {
|
| 17 |
+
const regionHeaders = collectRegionHeaders(model, options);
|
| 18 |
+
headers = headers.concat(regionHeaders);
|
| 19 |
+
}
|
| 20 |
+
if (options.findMarkSectionHeaders) {
|
| 21 |
+
const markHeaders = collectMarkHeaders(model);
|
| 22 |
+
headers = headers.concat(markHeaders);
|
| 23 |
+
}
|
| 24 |
+
return headers;
|
| 25 |
+
}
|
| 26 |
+
function collectRegionHeaders(model, options) {
|
| 27 |
+
const regionHeaders = [];
|
| 28 |
+
const endLineNumber = model.getLineCount();
|
| 29 |
+
for (let lineNumber = 1; lineNumber <= endLineNumber; lineNumber++) {
|
| 30 |
+
const lineContent = model.getLineContent(lineNumber);
|
| 31 |
+
const match = lineContent.match(options.foldingRules.markers.start);
|
| 32 |
+
if (match) {
|
| 33 |
+
const range = { startLineNumber: lineNumber, startColumn: match[0].length + 1, endLineNumber: lineNumber, endColumn: lineContent.length + 1 };
|
| 34 |
+
if (range.endColumn > range.startColumn) {
|
| 35 |
+
const sectionHeader = {
|
| 36 |
+
range,
|
| 37 |
+
...getHeaderText(lineContent.substring(match[0].length)),
|
| 38 |
+
shouldBeInComments: false
|
| 39 |
+
};
|
| 40 |
+
if (sectionHeader.text || sectionHeader.hasSeparatorLine) {
|
| 41 |
+
regionHeaders.push(sectionHeader);
|
| 42 |
+
}
|
| 43 |
+
}
|
| 44 |
+
}
|
| 45 |
+
}
|
| 46 |
+
return regionHeaders;
|
| 47 |
+
}
|
| 48 |
+
function collectMarkHeaders(model) {
|
| 49 |
+
const markHeaders = [];
|
| 50 |
+
const endLineNumber = model.getLineCount();
|
| 51 |
+
for (let lineNumber = 1; lineNumber <= endLineNumber; lineNumber++) {
|
| 52 |
+
const lineContent = model.getLineContent(lineNumber);
|
| 53 |
+
addMarkHeaderIfFound(lineContent, lineNumber, markHeaders);
|
| 54 |
+
}
|
| 55 |
+
return markHeaders;
|
| 56 |
+
}
|
| 57 |
+
function addMarkHeaderIfFound(lineContent, lineNumber, sectionHeaders) {
|
| 58 |
+
markRegex.lastIndex = 0;
|
| 59 |
+
const match = markRegex.exec(lineContent);
|
| 60 |
+
if (match) {
|
| 61 |
+
const column = match.indices[1][0] + 1;
|
| 62 |
+
const endColumn = match.indices[1][1] + 1;
|
| 63 |
+
const range = { startLineNumber: lineNumber, startColumn: column, endLineNumber: lineNumber, endColumn: endColumn };
|
| 64 |
+
if (range.endColumn > range.startColumn) {
|
| 65 |
+
const sectionHeader = {
|
| 66 |
+
range,
|
| 67 |
+
...getHeaderText(match[1]),
|
| 68 |
+
shouldBeInComments: true
|
| 69 |
+
};
|
| 70 |
+
if (sectionHeader.text || sectionHeader.hasSeparatorLine) {
|
| 71 |
+
sectionHeaders.push(sectionHeader);
|
| 72 |
+
}
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
}
|
| 76 |
+
function getHeaderText(text) {
|
| 77 |
+
text = text.trim();
|
| 78 |
+
const hasSeparatorLine = text.startsWith('-');
|
| 79 |
+
text = text.replace(trimDashesRegex, '');
|
| 80 |
+
return { text, hasSeparatorLine };
|
| 81 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/getIconClasses.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { Schemas } from '../../../base/common/network.js';
|
| 6 |
+
import { DataUri } from '../../../base/common/resources.js';
|
| 7 |
+
import { URI } from '../../../base/common/uri.js';
|
| 8 |
+
import { PLAINTEXT_LANGUAGE_ID } from '../languages/modesRegistry.js';
|
| 9 |
+
import { FileKind } from '../../../platform/files/common/files.js';
|
| 10 |
+
import { ThemeIcon } from '../../../base/common/themables.js';
|
| 11 |
+
const fileIconDirectoryRegex = /(?:\/|^)(?:([^\/]+)\/)?([^\/]+)$/;
|
| 12 |
+
export function getIconClasses(modelService, languageService, resource, fileKind, icon) {
|
| 13 |
+
if (ThemeIcon.isThemeIcon(icon)) {
|
| 14 |
+
return [`codicon-${icon.id}`, 'predefined-file-icon'];
|
| 15 |
+
}
|
| 16 |
+
if (URI.isUri(icon)) {
|
| 17 |
+
return [];
|
| 18 |
+
}
|
| 19 |
+
// we always set these base classes even if we do not have a path
|
| 20 |
+
const classes = fileKind === FileKind.ROOT_FOLDER ? ['rootfolder-icon'] : fileKind === FileKind.FOLDER ? ['folder-icon'] : ['file-icon'];
|
| 21 |
+
if (resource) {
|
| 22 |
+
// Get the path and name of the resource. For data-URIs, we need to parse specially
|
| 23 |
+
let name;
|
| 24 |
+
if (resource.scheme === Schemas.data) {
|
| 25 |
+
const metadata = DataUri.parseMetaData(resource);
|
| 26 |
+
name = metadata.get(DataUri.META_DATA_LABEL);
|
| 27 |
+
}
|
| 28 |
+
else {
|
| 29 |
+
const match = resource.path.match(fileIconDirectoryRegex);
|
| 30 |
+
if (match) {
|
| 31 |
+
name = cssEscape(match[2].toLowerCase());
|
| 32 |
+
if (match[1]) {
|
| 33 |
+
classes.push(`${cssEscape(match[1].toLowerCase())}-name-dir-icon`); // parent directory
|
| 34 |
+
}
|
| 35 |
+
}
|
| 36 |
+
else {
|
| 37 |
+
name = cssEscape(resource.authority.toLowerCase());
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
// Root Folders
|
| 41 |
+
if (fileKind === FileKind.ROOT_FOLDER) {
|
| 42 |
+
classes.push(`${name}-root-name-folder-icon`);
|
| 43 |
+
}
|
| 44 |
+
// Folders
|
| 45 |
+
else if (fileKind === FileKind.FOLDER) {
|
| 46 |
+
classes.push(`${name}-name-folder-icon`);
|
| 47 |
+
}
|
| 48 |
+
// Files
|
| 49 |
+
else {
|
| 50 |
+
// Name & Extension(s)
|
| 51 |
+
if (name) {
|
| 52 |
+
classes.push(`${name}-name-file-icon`);
|
| 53 |
+
classes.push(`name-file-icon`); // extra segment to increase file-name score
|
| 54 |
+
// Avoid doing an explosive combination of extensions for very long filenames
|
| 55 |
+
// (most file systems do not allow files > 255 length) with lots of `.` characters
|
| 56 |
+
// https://github.com/microsoft/vscode/issues/116199
|
| 57 |
+
if (name.length <= 255) {
|
| 58 |
+
const dotSegments = name.split('.');
|
| 59 |
+
for (let i = 1; i < dotSegments.length; i++) {
|
| 60 |
+
classes.push(`${dotSegments.slice(i).join('.')}-ext-file-icon`); // add each combination of all found extensions if more than one
|
| 61 |
+
}
|
| 62 |
+
}
|
| 63 |
+
classes.push(`ext-file-icon`); // extra segment to increase file-ext score
|
| 64 |
+
}
|
| 65 |
+
// Detected Mode
|
| 66 |
+
const detectedLanguageId = detectLanguageId(modelService, languageService, resource);
|
| 67 |
+
if (detectedLanguageId) {
|
| 68 |
+
classes.push(`${cssEscape(detectedLanguageId)}-lang-file-icon`);
|
| 69 |
+
}
|
| 70 |
+
}
|
| 71 |
+
}
|
| 72 |
+
return classes;
|
| 73 |
+
}
|
| 74 |
+
function detectLanguageId(modelService, languageService, resource) {
|
| 75 |
+
if (!resource) {
|
| 76 |
+
return null; // we need a resource at least
|
| 77 |
+
}
|
| 78 |
+
let languageId = null;
|
| 79 |
+
// Data URI: check for encoded metadata
|
| 80 |
+
if (resource.scheme === Schemas.data) {
|
| 81 |
+
const metadata = DataUri.parseMetaData(resource);
|
| 82 |
+
const mime = metadata.get(DataUri.META_DATA_MIME);
|
| 83 |
+
if (mime) {
|
| 84 |
+
languageId = languageService.getLanguageIdByMimeType(mime);
|
| 85 |
+
}
|
| 86 |
+
}
|
| 87 |
+
// Any other URI: check for model if existing
|
| 88 |
+
else {
|
| 89 |
+
const model = modelService.getModel(resource);
|
| 90 |
+
if (model) {
|
| 91 |
+
languageId = model.getLanguageId();
|
| 92 |
+
}
|
| 93 |
+
}
|
| 94 |
+
// only take if the language id is specific (aka no just plain text)
|
| 95 |
+
if (languageId && languageId !== PLAINTEXT_LANGUAGE_ID) {
|
| 96 |
+
return languageId;
|
| 97 |
+
}
|
| 98 |
+
// otherwise fallback to path based detection
|
| 99 |
+
return languageService.guessLanguageIdByFilepathOrFirstLine(resource);
|
| 100 |
+
}
|
| 101 |
+
function cssEscape(str) {
|
| 102 |
+
return str.replace(/[\s]/g, '/'); // HTML class names can not contain certain whitespace characters (https://dom.spec.whatwg.org/#interface-domtokenlist), use / instead, which doesn't exist in file names.
|
| 103 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/languageFeatureDebounce.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
| 6 |
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
| 7 |
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
| 8 |
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
| 9 |
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
| 10 |
+
};
|
| 11 |
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
| 12 |
+
return function (target, key) { decorator(target, key, paramIndex); }
|
| 13 |
+
};
|
| 14 |
+
import { doHash } from '../../../base/common/hash.js';
|
| 15 |
+
import { LRUCache } from '../../../base/common/map.js';
|
| 16 |
+
import { clamp, MovingAverage, SlidingWindowAverage } from '../../../base/common/numbers.js';
|
| 17 |
+
import { IEnvironmentService } from '../../../platform/environment/common/environment.js';
|
| 18 |
+
import { registerSingleton } from '../../../platform/instantiation/common/extensions.js';
|
| 19 |
+
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
|
| 20 |
+
import { ILogService } from '../../../platform/log/common/log.js';
|
| 21 |
+
import { matchesScheme } from '../../../base/common/network.js';
|
| 22 |
+
export const ILanguageFeatureDebounceService = createDecorator('ILanguageFeatureDebounceService');
|
| 23 |
+
var IdentityHash;
|
| 24 |
+
(function (IdentityHash) {
|
| 25 |
+
const _hashes = new WeakMap();
|
| 26 |
+
let pool = 0;
|
| 27 |
+
function of(obj) {
|
| 28 |
+
let value = _hashes.get(obj);
|
| 29 |
+
if (value === undefined) {
|
| 30 |
+
value = ++pool;
|
| 31 |
+
_hashes.set(obj, value);
|
| 32 |
+
}
|
| 33 |
+
return value;
|
| 34 |
+
}
|
| 35 |
+
IdentityHash.of = of;
|
| 36 |
+
})(IdentityHash || (IdentityHash = {}));
|
| 37 |
+
class NullDebounceInformation {
|
| 38 |
+
constructor(_default) {
|
| 39 |
+
this._default = _default;
|
| 40 |
+
}
|
| 41 |
+
get(_model) {
|
| 42 |
+
return this._default;
|
| 43 |
+
}
|
| 44 |
+
update(_model, _value) {
|
| 45 |
+
return this._default;
|
| 46 |
+
}
|
| 47 |
+
default() {
|
| 48 |
+
return this._default;
|
| 49 |
+
}
|
| 50 |
+
}
|
| 51 |
+
class FeatureDebounceInformation {
|
| 52 |
+
constructor(_logService, _name, _registry, _default, _min, _max) {
|
| 53 |
+
this._logService = _logService;
|
| 54 |
+
this._name = _name;
|
| 55 |
+
this._registry = _registry;
|
| 56 |
+
this._default = _default;
|
| 57 |
+
this._min = _min;
|
| 58 |
+
this._max = _max;
|
| 59 |
+
this._cache = new LRUCache(50, 0.7);
|
| 60 |
+
}
|
| 61 |
+
_key(model) {
|
| 62 |
+
return model.id + this._registry.all(model).reduce((hashVal, obj) => doHash(IdentityHash.of(obj), hashVal), 0);
|
| 63 |
+
}
|
| 64 |
+
get(model) {
|
| 65 |
+
const key = this._key(model);
|
| 66 |
+
const avg = this._cache.get(key);
|
| 67 |
+
return avg
|
| 68 |
+
? clamp(avg.value, this._min, this._max)
|
| 69 |
+
: this.default();
|
| 70 |
+
}
|
| 71 |
+
update(model, value) {
|
| 72 |
+
const key = this._key(model);
|
| 73 |
+
let avg = this._cache.get(key);
|
| 74 |
+
if (!avg) {
|
| 75 |
+
avg = new SlidingWindowAverage(6);
|
| 76 |
+
this._cache.set(key, avg);
|
| 77 |
+
}
|
| 78 |
+
const newValue = clamp(avg.update(value), this._min, this._max);
|
| 79 |
+
if (!matchesScheme(model.uri, 'output')) {
|
| 80 |
+
this._logService.trace(`[DEBOUNCE: ${this._name}] for ${model.uri.toString()} is ${newValue}ms`);
|
| 81 |
+
}
|
| 82 |
+
return newValue;
|
| 83 |
+
}
|
| 84 |
+
_overall() {
|
| 85 |
+
const result = new MovingAverage();
|
| 86 |
+
for (const [, avg] of this._cache) {
|
| 87 |
+
result.update(avg.value);
|
| 88 |
+
}
|
| 89 |
+
return result.value;
|
| 90 |
+
}
|
| 91 |
+
default() {
|
| 92 |
+
const value = (this._overall() | 0) || this._default;
|
| 93 |
+
return clamp(value, this._min, this._max);
|
| 94 |
+
}
|
| 95 |
+
}
|
| 96 |
+
let LanguageFeatureDebounceService = class LanguageFeatureDebounceService {
|
| 97 |
+
constructor(_logService, envService) {
|
| 98 |
+
this._logService = _logService;
|
| 99 |
+
this._data = new Map();
|
| 100 |
+
this._isDev = envService.isExtensionDevelopment || !envService.isBuilt;
|
| 101 |
+
}
|
| 102 |
+
for(feature, name, config) {
|
| 103 |
+
const min = config?.min ?? 50;
|
| 104 |
+
const max = config?.max ?? min ** 2;
|
| 105 |
+
const extra = config?.key ?? undefined;
|
| 106 |
+
const key = `${IdentityHash.of(feature)},${min}${extra ? ',' + extra : ''}`;
|
| 107 |
+
let info = this._data.get(key);
|
| 108 |
+
if (!info) {
|
| 109 |
+
if (this._isDev) {
|
| 110 |
+
this._logService.debug(`[DEBOUNCE: ${name}] is disabled in developed mode`);
|
| 111 |
+
info = new NullDebounceInformation(min * 1.5);
|
| 112 |
+
}
|
| 113 |
+
else {
|
| 114 |
+
info = new FeatureDebounceInformation(this._logService, name, feature, (this._overallAverage() | 0) || (min * 1.5), // default is overall default or derived from min-value
|
| 115 |
+
min, max);
|
| 116 |
+
}
|
| 117 |
+
this._data.set(key, info);
|
| 118 |
+
}
|
| 119 |
+
return info;
|
| 120 |
+
}
|
| 121 |
+
_overallAverage() {
|
| 122 |
+
// Average of all language features. Not a great value but an approximation
|
| 123 |
+
const result = new MovingAverage();
|
| 124 |
+
for (const info of this._data.values()) {
|
| 125 |
+
result.update(info.default());
|
| 126 |
+
}
|
| 127 |
+
return result.value;
|
| 128 |
+
}
|
| 129 |
+
};
|
| 130 |
+
LanguageFeatureDebounceService = __decorate([
|
| 131 |
+
__param(0, ILogService),
|
| 132 |
+
__param(1, IEnvironmentService)
|
| 133 |
+
], LanguageFeatureDebounceService);
|
| 134 |
+
export { LanguageFeatureDebounceService };
|
| 135 |
+
registerSingleton(ILanguageFeatureDebounceService, LanguageFeatureDebounceService, 1 /* InstantiationType.Delayed */);
|
node_modules/monaco-editor/esm/vs/editor/common/services/languageFeatures.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
|
| 6 |
+
export const ILanguageFeaturesService = createDecorator('ILanguageFeaturesService');
|
node_modules/monaco-editor/esm/vs/editor/common/services/languageFeaturesService.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { LanguageFeatureRegistry } from '../languageFeatureRegistry.js';
|
| 6 |
+
import { ILanguageFeaturesService } from './languageFeatures.js';
|
| 7 |
+
import { registerSingleton } from '../../../platform/instantiation/common/extensions.js';
|
| 8 |
+
export class LanguageFeaturesService {
|
| 9 |
+
constructor() {
|
| 10 |
+
this.referenceProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 11 |
+
this.renameProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 12 |
+
this.newSymbolNamesProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 13 |
+
this.codeActionProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 14 |
+
this.definitionProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 15 |
+
this.typeDefinitionProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 16 |
+
this.declarationProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 17 |
+
this.implementationProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 18 |
+
this.documentSymbolProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 19 |
+
this.inlayHintsProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 20 |
+
this.colorProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 21 |
+
this.codeLensProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 22 |
+
this.documentFormattingEditProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 23 |
+
this.documentRangeFormattingEditProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 24 |
+
this.onTypeFormattingEditProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 25 |
+
this.signatureHelpProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 26 |
+
this.hoverProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 27 |
+
this.documentHighlightProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 28 |
+
this.multiDocumentHighlightProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 29 |
+
this.selectionRangeProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 30 |
+
this.foldingRangeProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 31 |
+
this.linkProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 32 |
+
this.inlineCompletionsProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 33 |
+
this.inlineEditProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 34 |
+
this.completionProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 35 |
+
this.linkedEditingRangeProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 36 |
+
this.documentRangeSemanticTokensProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 37 |
+
this.documentSemanticTokensProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 38 |
+
this.documentDropEditProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 39 |
+
this.documentPasteEditProvider = new LanguageFeatureRegistry(this._score.bind(this));
|
| 40 |
+
}
|
| 41 |
+
_score(uri) {
|
| 42 |
+
return this._notebookTypeResolver?.(uri);
|
| 43 |
+
}
|
| 44 |
+
}
|
| 45 |
+
registerSingleton(ILanguageFeaturesService, LanguageFeaturesService, 1 /* InstantiationType.Delayed */);
|
node_modules/monaco-editor/esm/vs/editor/common/services/languageService.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { Emitter, Event } from '../../../base/common/event.js';
|
| 6 |
+
import { Disposable } from '../../../base/common/lifecycle.js';
|
| 7 |
+
import { LanguagesRegistry } from './languagesRegistry.js';
|
| 8 |
+
import { firstOrDefault } from '../../../base/common/arrays.js';
|
| 9 |
+
import { TokenizationRegistry } from '../languages.js';
|
| 10 |
+
import { PLAINTEXT_LANGUAGE_ID } from '../languages/modesRegistry.js';
|
| 11 |
+
import { observableFromEvent } from '../../../base/common/observable.js';
|
| 12 |
+
export class LanguageService extends Disposable {
|
| 13 |
+
static { this.instanceCount = 0; }
|
| 14 |
+
constructor(warnOnOverwrite = false) {
|
| 15 |
+
super();
|
| 16 |
+
this._onDidRequestBasicLanguageFeatures = this._register(new Emitter());
|
| 17 |
+
this.onDidRequestBasicLanguageFeatures = this._onDidRequestBasicLanguageFeatures.event;
|
| 18 |
+
this._onDidRequestRichLanguageFeatures = this._register(new Emitter());
|
| 19 |
+
this.onDidRequestRichLanguageFeatures = this._onDidRequestRichLanguageFeatures.event;
|
| 20 |
+
this._onDidChange = this._register(new Emitter({ leakWarningThreshold: 200 /* https://github.com/microsoft/vscode/issues/119968 */ }));
|
| 21 |
+
this.onDidChange = this._onDidChange.event;
|
| 22 |
+
this._requestedBasicLanguages = new Set();
|
| 23 |
+
this._requestedRichLanguages = new Set();
|
| 24 |
+
LanguageService.instanceCount++;
|
| 25 |
+
this._registry = this._register(new LanguagesRegistry(true, warnOnOverwrite));
|
| 26 |
+
this.languageIdCodec = this._registry.languageIdCodec;
|
| 27 |
+
this._register(this._registry.onDidChange(() => this._onDidChange.fire()));
|
| 28 |
+
}
|
| 29 |
+
dispose() {
|
| 30 |
+
LanguageService.instanceCount--;
|
| 31 |
+
super.dispose();
|
| 32 |
+
}
|
| 33 |
+
isRegisteredLanguageId(languageId) {
|
| 34 |
+
return this._registry.isRegisteredLanguageId(languageId);
|
| 35 |
+
}
|
| 36 |
+
getLanguageIdByLanguageName(languageName) {
|
| 37 |
+
return this._registry.getLanguageIdByLanguageName(languageName);
|
| 38 |
+
}
|
| 39 |
+
getLanguageIdByMimeType(mimeType) {
|
| 40 |
+
return this._registry.getLanguageIdByMimeType(mimeType);
|
| 41 |
+
}
|
| 42 |
+
guessLanguageIdByFilepathOrFirstLine(resource, firstLine) {
|
| 43 |
+
const languageIds = this._registry.guessLanguageIdByFilepathOrFirstLine(resource, firstLine);
|
| 44 |
+
return firstOrDefault(languageIds, null);
|
| 45 |
+
}
|
| 46 |
+
createById(languageId) {
|
| 47 |
+
return new LanguageSelection(this.onDidChange, () => {
|
| 48 |
+
return this._createAndGetLanguageIdentifier(languageId);
|
| 49 |
+
});
|
| 50 |
+
}
|
| 51 |
+
createByFilepathOrFirstLine(resource, firstLine) {
|
| 52 |
+
return new LanguageSelection(this.onDidChange, () => {
|
| 53 |
+
const languageId = this.guessLanguageIdByFilepathOrFirstLine(resource, firstLine);
|
| 54 |
+
return this._createAndGetLanguageIdentifier(languageId);
|
| 55 |
+
});
|
| 56 |
+
}
|
| 57 |
+
_createAndGetLanguageIdentifier(languageId) {
|
| 58 |
+
if (!languageId || !this.isRegisteredLanguageId(languageId)) {
|
| 59 |
+
// Fall back to plain text if language is unknown
|
| 60 |
+
languageId = PLAINTEXT_LANGUAGE_ID;
|
| 61 |
+
}
|
| 62 |
+
return languageId;
|
| 63 |
+
}
|
| 64 |
+
requestBasicLanguageFeatures(languageId) {
|
| 65 |
+
if (!this._requestedBasicLanguages.has(languageId)) {
|
| 66 |
+
this._requestedBasicLanguages.add(languageId);
|
| 67 |
+
this._onDidRequestBasicLanguageFeatures.fire(languageId);
|
| 68 |
+
}
|
| 69 |
+
}
|
| 70 |
+
requestRichLanguageFeatures(languageId) {
|
| 71 |
+
if (!this._requestedRichLanguages.has(languageId)) {
|
| 72 |
+
this._requestedRichLanguages.add(languageId);
|
| 73 |
+
// Ensure basic features are requested
|
| 74 |
+
this.requestBasicLanguageFeatures(languageId);
|
| 75 |
+
// Ensure tokenizers are created
|
| 76 |
+
TokenizationRegistry.getOrCreate(languageId);
|
| 77 |
+
this._onDidRequestRichLanguageFeatures.fire(languageId);
|
| 78 |
+
}
|
| 79 |
+
}
|
| 80 |
+
}
|
| 81 |
+
class LanguageSelection {
|
| 82 |
+
constructor(onDidChangeLanguages, selector) {
|
| 83 |
+
this._value = observableFromEvent(this, onDidChangeLanguages, () => selector());
|
| 84 |
+
this.onDidChange = Event.fromObservable(this._value);
|
| 85 |
+
}
|
| 86 |
+
get languageId() {
|
| 87 |
+
return this._value.get();
|
| 88 |
+
}
|
| 89 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/languagesAssociations.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { parse } from '../../../base/common/glob.js';
|
| 6 |
+
import { Mimes } from '../../../base/common/mime.js';
|
| 7 |
+
import { Schemas } from '../../../base/common/network.js';
|
| 8 |
+
import { basename, posix } from '../../../base/common/path.js';
|
| 9 |
+
import { DataUri } from '../../../base/common/resources.js';
|
| 10 |
+
import { startsWithUTF8BOM } from '../../../base/common/strings.js';
|
| 11 |
+
import { PLAINTEXT_LANGUAGE_ID } from '../languages/modesRegistry.js';
|
| 12 |
+
let registeredAssociations = [];
|
| 13 |
+
let nonUserRegisteredAssociations = [];
|
| 14 |
+
let userRegisteredAssociations = [];
|
| 15 |
+
/**
|
| 16 |
+
* Associate a language to the registry (platform).
|
| 17 |
+
* * **NOTE**: This association will lose over associations registered using `registerConfiguredLanguageAssociation`.
|
| 18 |
+
* * **NOTE**: Use `clearPlatformLanguageAssociations` to remove all associations registered using this function.
|
| 19 |
+
*/
|
| 20 |
+
export function registerPlatformLanguageAssociation(association, warnOnOverwrite = false) {
|
| 21 |
+
_registerLanguageAssociation(association, false, warnOnOverwrite);
|
| 22 |
+
}
|
| 23 |
+
function _registerLanguageAssociation(association, userConfigured, warnOnOverwrite) {
|
| 24 |
+
// Register
|
| 25 |
+
const associationItem = toLanguageAssociationItem(association, userConfigured);
|
| 26 |
+
registeredAssociations.push(associationItem);
|
| 27 |
+
if (!associationItem.userConfigured) {
|
| 28 |
+
nonUserRegisteredAssociations.push(associationItem);
|
| 29 |
+
}
|
| 30 |
+
else {
|
| 31 |
+
userRegisteredAssociations.push(associationItem);
|
| 32 |
+
}
|
| 33 |
+
// Check for conflicts unless this is a user configured association
|
| 34 |
+
if (warnOnOverwrite && !associationItem.userConfigured) {
|
| 35 |
+
registeredAssociations.forEach(a => {
|
| 36 |
+
if (a.mime === associationItem.mime || a.userConfigured) {
|
| 37 |
+
return; // same mime or userConfigured is ok
|
| 38 |
+
}
|
| 39 |
+
if (associationItem.extension && a.extension === associationItem.extension) {
|
| 40 |
+
console.warn(`Overwriting extension <<${associationItem.extension}>> to now point to mime <<${associationItem.mime}>>`);
|
| 41 |
+
}
|
| 42 |
+
if (associationItem.filename && a.filename === associationItem.filename) {
|
| 43 |
+
console.warn(`Overwriting filename <<${associationItem.filename}>> to now point to mime <<${associationItem.mime}>>`);
|
| 44 |
+
}
|
| 45 |
+
if (associationItem.filepattern && a.filepattern === associationItem.filepattern) {
|
| 46 |
+
console.warn(`Overwriting filepattern <<${associationItem.filepattern}>> to now point to mime <<${associationItem.mime}>>`);
|
| 47 |
+
}
|
| 48 |
+
if (associationItem.firstline && a.firstline === associationItem.firstline) {
|
| 49 |
+
console.warn(`Overwriting firstline <<${associationItem.firstline}>> to now point to mime <<${associationItem.mime}>>`);
|
| 50 |
+
}
|
| 51 |
+
});
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
function toLanguageAssociationItem(association, userConfigured) {
|
| 55 |
+
return {
|
| 56 |
+
id: association.id,
|
| 57 |
+
mime: association.mime,
|
| 58 |
+
filename: association.filename,
|
| 59 |
+
extension: association.extension,
|
| 60 |
+
filepattern: association.filepattern,
|
| 61 |
+
firstline: association.firstline,
|
| 62 |
+
userConfigured: userConfigured,
|
| 63 |
+
filenameLowercase: association.filename ? association.filename.toLowerCase() : undefined,
|
| 64 |
+
extensionLowercase: association.extension ? association.extension.toLowerCase() : undefined,
|
| 65 |
+
filepatternLowercase: association.filepattern ? parse(association.filepattern.toLowerCase()) : undefined,
|
| 66 |
+
filepatternOnPath: association.filepattern ? association.filepattern.indexOf(posix.sep) >= 0 : false
|
| 67 |
+
};
|
| 68 |
+
}
|
| 69 |
+
/**
|
| 70 |
+
* Clear language associations from the registry (platform).
|
| 71 |
+
*/
|
| 72 |
+
export function clearPlatformLanguageAssociations() {
|
| 73 |
+
registeredAssociations = registeredAssociations.filter(a => a.userConfigured);
|
| 74 |
+
nonUserRegisteredAssociations = [];
|
| 75 |
+
}
|
| 76 |
+
/**
|
| 77 |
+
* @see `getMimeTypes`
|
| 78 |
+
*/
|
| 79 |
+
export function getLanguageIds(resource, firstLine) {
|
| 80 |
+
return getAssociations(resource, firstLine).map(item => item.id);
|
| 81 |
+
}
|
| 82 |
+
function getAssociations(resource, firstLine) {
|
| 83 |
+
let path;
|
| 84 |
+
if (resource) {
|
| 85 |
+
switch (resource.scheme) {
|
| 86 |
+
case Schemas.file:
|
| 87 |
+
path = resource.fsPath;
|
| 88 |
+
break;
|
| 89 |
+
case Schemas.data: {
|
| 90 |
+
const metadata = DataUri.parseMetaData(resource);
|
| 91 |
+
path = metadata.get(DataUri.META_DATA_LABEL);
|
| 92 |
+
break;
|
| 93 |
+
}
|
| 94 |
+
case Schemas.vscodeNotebookCell:
|
| 95 |
+
// File path not relevant for language detection of cell
|
| 96 |
+
path = undefined;
|
| 97 |
+
break;
|
| 98 |
+
default:
|
| 99 |
+
path = resource.path;
|
| 100 |
+
}
|
| 101 |
+
}
|
| 102 |
+
if (!path) {
|
| 103 |
+
return [{ id: 'unknown', mime: Mimes.unknown }];
|
| 104 |
+
}
|
| 105 |
+
path = path.toLowerCase();
|
| 106 |
+
const filename = basename(path);
|
| 107 |
+
// 1.) User configured mappings have highest priority
|
| 108 |
+
const configuredLanguage = getAssociationByPath(path, filename, userRegisteredAssociations);
|
| 109 |
+
if (configuredLanguage) {
|
| 110 |
+
return [configuredLanguage, { id: PLAINTEXT_LANGUAGE_ID, mime: Mimes.text }];
|
| 111 |
+
}
|
| 112 |
+
// 2.) Registered mappings have middle priority
|
| 113 |
+
const registeredLanguage = getAssociationByPath(path, filename, nonUserRegisteredAssociations);
|
| 114 |
+
if (registeredLanguage) {
|
| 115 |
+
return [registeredLanguage, { id: PLAINTEXT_LANGUAGE_ID, mime: Mimes.text }];
|
| 116 |
+
}
|
| 117 |
+
// 3.) Firstline has lowest priority
|
| 118 |
+
if (firstLine) {
|
| 119 |
+
const firstlineLanguage = getAssociationByFirstline(firstLine);
|
| 120 |
+
if (firstlineLanguage) {
|
| 121 |
+
return [firstlineLanguage, { id: PLAINTEXT_LANGUAGE_ID, mime: Mimes.text }];
|
| 122 |
+
}
|
| 123 |
+
}
|
| 124 |
+
return [{ id: 'unknown', mime: Mimes.unknown }];
|
| 125 |
+
}
|
| 126 |
+
function getAssociationByPath(path, filename, associations) {
|
| 127 |
+
let filenameMatch = undefined;
|
| 128 |
+
let patternMatch = undefined;
|
| 129 |
+
let extensionMatch = undefined;
|
| 130 |
+
// We want to prioritize associations based on the order they are registered so that the last registered
|
| 131 |
+
// association wins over all other. This is for https://github.com/microsoft/vscode/issues/20074
|
| 132 |
+
for (let i = associations.length - 1; i >= 0; i--) {
|
| 133 |
+
const association = associations[i];
|
| 134 |
+
// First exact name match
|
| 135 |
+
if (filename === association.filenameLowercase) {
|
| 136 |
+
filenameMatch = association;
|
| 137 |
+
break; // take it!
|
| 138 |
+
}
|
| 139 |
+
// Longest pattern match
|
| 140 |
+
if (association.filepattern) {
|
| 141 |
+
if (!patternMatch || association.filepattern.length > patternMatch.filepattern.length) {
|
| 142 |
+
const target = association.filepatternOnPath ? path : filename; // match on full path if pattern contains path separator
|
| 143 |
+
if (association.filepatternLowercase?.(target)) {
|
| 144 |
+
patternMatch = association;
|
| 145 |
+
}
|
| 146 |
+
}
|
| 147 |
+
}
|
| 148 |
+
// Longest extension match
|
| 149 |
+
if (association.extension) {
|
| 150 |
+
if (!extensionMatch || association.extension.length > extensionMatch.extension.length) {
|
| 151 |
+
if (filename.endsWith(association.extensionLowercase)) {
|
| 152 |
+
extensionMatch = association;
|
| 153 |
+
}
|
| 154 |
+
}
|
| 155 |
+
}
|
| 156 |
+
}
|
| 157 |
+
// 1.) Exact name match has second highest priority
|
| 158 |
+
if (filenameMatch) {
|
| 159 |
+
return filenameMatch;
|
| 160 |
+
}
|
| 161 |
+
// 2.) Match on pattern
|
| 162 |
+
if (patternMatch) {
|
| 163 |
+
return patternMatch;
|
| 164 |
+
}
|
| 165 |
+
// 3.) Match on extension comes next
|
| 166 |
+
if (extensionMatch) {
|
| 167 |
+
return extensionMatch;
|
| 168 |
+
}
|
| 169 |
+
return undefined;
|
| 170 |
+
}
|
| 171 |
+
function getAssociationByFirstline(firstLine) {
|
| 172 |
+
if (startsWithUTF8BOM(firstLine)) {
|
| 173 |
+
firstLine = firstLine.substr(1);
|
| 174 |
+
}
|
| 175 |
+
if (firstLine.length > 0) {
|
| 176 |
+
// We want to prioritize associations based on the order they are registered so that the last registered
|
| 177 |
+
// association wins over all other. This is for https://github.com/microsoft/vscode/issues/20074
|
| 178 |
+
for (let i = registeredAssociations.length - 1; i >= 0; i--) {
|
| 179 |
+
const association = registeredAssociations[i];
|
| 180 |
+
if (!association.firstline) {
|
| 181 |
+
continue;
|
| 182 |
+
}
|
| 183 |
+
const matches = firstLine.match(association.firstline);
|
| 184 |
+
if (matches && matches.length > 0) {
|
| 185 |
+
return association;
|
| 186 |
+
}
|
| 187 |
+
}
|
| 188 |
+
}
|
| 189 |
+
return undefined;
|
| 190 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/languagesRegistry.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { Emitter } from '../../../base/common/event.js';
|
| 6 |
+
import { Disposable } from '../../../base/common/lifecycle.js';
|
| 7 |
+
import { regExpLeadsToEndlessLoop } from '../../../base/common/strings.js';
|
| 8 |
+
import { clearPlatformLanguageAssociations, getLanguageIds, registerPlatformLanguageAssociation } from './languagesAssociations.js';
|
| 9 |
+
import { ModesRegistry, PLAINTEXT_LANGUAGE_ID } from '../languages/modesRegistry.js';
|
| 10 |
+
import { Extensions } from '../../../platform/configuration/common/configurationRegistry.js';
|
| 11 |
+
import { Registry } from '../../../platform/registry/common/platform.js';
|
| 12 |
+
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
| 13 |
+
const NULL_LANGUAGE_ID = 'vs.editor.nullLanguage';
|
| 14 |
+
export class LanguageIdCodec {
|
| 15 |
+
constructor() {
|
| 16 |
+
this._languageIdToLanguage = [];
|
| 17 |
+
this._languageToLanguageId = new Map();
|
| 18 |
+
this._register(NULL_LANGUAGE_ID, 0 /* LanguageId.Null */);
|
| 19 |
+
this._register(PLAINTEXT_LANGUAGE_ID, 1 /* LanguageId.PlainText */);
|
| 20 |
+
this._nextLanguageId = 2;
|
| 21 |
+
}
|
| 22 |
+
_register(language, languageId) {
|
| 23 |
+
this._languageIdToLanguage[languageId] = language;
|
| 24 |
+
this._languageToLanguageId.set(language, languageId);
|
| 25 |
+
}
|
| 26 |
+
register(language) {
|
| 27 |
+
if (this._languageToLanguageId.has(language)) {
|
| 28 |
+
return;
|
| 29 |
+
}
|
| 30 |
+
const languageId = this._nextLanguageId++;
|
| 31 |
+
this._register(language, languageId);
|
| 32 |
+
}
|
| 33 |
+
encodeLanguageId(languageId) {
|
| 34 |
+
return this._languageToLanguageId.get(languageId) || 0 /* LanguageId.Null */;
|
| 35 |
+
}
|
| 36 |
+
decodeLanguageId(languageId) {
|
| 37 |
+
return this._languageIdToLanguage[languageId] || NULL_LANGUAGE_ID;
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
export class LanguagesRegistry extends Disposable {
|
| 41 |
+
static { this.instanceCount = 0; }
|
| 42 |
+
constructor(useModesRegistry = true, warnOnOverwrite = false) {
|
| 43 |
+
super();
|
| 44 |
+
this._onDidChange = this._register(new Emitter());
|
| 45 |
+
this.onDidChange = this._onDidChange.event;
|
| 46 |
+
LanguagesRegistry.instanceCount++;
|
| 47 |
+
this._warnOnOverwrite = warnOnOverwrite;
|
| 48 |
+
this.languageIdCodec = new LanguageIdCodec();
|
| 49 |
+
this._dynamicLanguages = [];
|
| 50 |
+
this._languages = {};
|
| 51 |
+
this._mimeTypesMap = {};
|
| 52 |
+
this._nameMap = {};
|
| 53 |
+
this._lowercaseNameMap = {};
|
| 54 |
+
if (useModesRegistry) {
|
| 55 |
+
this._initializeFromRegistry();
|
| 56 |
+
this._register(ModesRegistry.onDidChangeLanguages((m) => {
|
| 57 |
+
this._initializeFromRegistry();
|
| 58 |
+
}));
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
dispose() {
|
| 62 |
+
LanguagesRegistry.instanceCount--;
|
| 63 |
+
super.dispose();
|
| 64 |
+
}
|
| 65 |
+
_initializeFromRegistry() {
|
| 66 |
+
this._languages = {};
|
| 67 |
+
this._mimeTypesMap = {};
|
| 68 |
+
this._nameMap = {};
|
| 69 |
+
this._lowercaseNameMap = {};
|
| 70 |
+
clearPlatformLanguageAssociations();
|
| 71 |
+
const desc = [].concat(ModesRegistry.getLanguages()).concat(this._dynamicLanguages);
|
| 72 |
+
this._registerLanguages(desc);
|
| 73 |
+
}
|
| 74 |
+
_registerLanguages(desc) {
|
| 75 |
+
for (const d of desc) {
|
| 76 |
+
this._registerLanguage(d);
|
| 77 |
+
}
|
| 78 |
+
// Rebuild fast path maps
|
| 79 |
+
this._mimeTypesMap = {};
|
| 80 |
+
this._nameMap = {};
|
| 81 |
+
this._lowercaseNameMap = {};
|
| 82 |
+
Object.keys(this._languages).forEach((langId) => {
|
| 83 |
+
const language = this._languages[langId];
|
| 84 |
+
if (language.name) {
|
| 85 |
+
this._nameMap[language.name] = language.identifier;
|
| 86 |
+
}
|
| 87 |
+
language.aliases.forEach((alias) => {
|
| 88 |
+
this._lowercaseNameMap[alias.toLowerCase()] = language.identifier;
|
| 89 |
+
});
|
| 90 |
+
language.mimetypes.forEach((mimetype) => {
|
| 91 |
+
this._mimeTypesMap[mimetype] = language.identifier;
|
| 92 |
+
});
|
| 93 |
+
});
|
| 94 |
+
Registry.as(Extensions.Configuration).registerOverrideIdentifiers(this.getRegisteredLanguageIds());
|
| 95 |
+
this._onDidChange.fire();
|
| 96 |
+
}
|
| 97 |
+
_registerLanguage(lang) {
|
| 98 |
+
const langId = lang.id;
|
| 99 |
+
let resolvedLanguage;
|
| 100 |
+
if (hasOwnProperty.call(this._languages, langId)) {
|
| 101 |
+
resolvedLanguage = this._languages[langId];
|
| 102 |
+
}
|
| 103 |
+
else {
|
| 104 |
+
this.languageIdCodec.register(langId);
|
| 105 |
+
resolvedLanguage = {
|
| 106 |
+
identifier: langId,
|
| 107 |
+
name: null,
|
| 108 |
+
mimetypes: [],
|
| 109 |
+
aliases: [],
|
| 110 |
+
extensions: [],
|
| 111 |
+
filenames: [],
|
| 112 |
+
configurationFiles: [],
|
| 113 |
+
icons: []
|
| 114 |
+
};
|
| 115 |
+
this._languages[langId] = resolvedLanguage;
|
| 116 |
+
}
|
| 117 |
+
this._mergeLanguage(resolvedLanguage, lang);
|
| 118 |
+
}
|
| 119 |
+
_mergeLanguage(resolvedLanguage, lang) {
|
| 120 |
+
const langId = lang.id;
|
| 121 |
+
let primaryMime = null;
|
| 122 |
+
if (Array.isArray(lang.mimetypes) && lang.mimetypes.length > 0) {
|
| 123 |
+
resolvedLanguage.mimetypes.push(...lang.mimetypes);
|
| 124 |
+
primaryMime = lang.mimetypes[0];
|
| 125 |
+
}
|
| 126 |
+
if (!primaryMime) {
|
| 127 |
+
primaryMime = `text/x-${langId}`;
|
| 128 |
+
resolvedLanguage.mimetypes.push(primaryMime);
|
| 129 |
+
}
|
| 130 |
+
if (Array.isArray(lang.extensions)) {
|
| 131 |
+
if (lang.configuration) {
|
| 132 |
+
// insert first as this appears to be the 'primary' language definition
|
| 133 |
+
resolvedLanguage.extensions = lang.extensions.concat(resolvedLanguage.extensions);
|
| 134 |
+
}
|
| 135 |
+
else {
|
| 136 |
+
resolvedLanguage.extensions = resolvedLanguage.extensions.concat(lang.extensions);
|
| 137 |
+
}
|
| 138 |
+
for (const extension of lang.extensions) {
|
| 139 |
+
registerPlatformLanguageAssociation({ id: langId, mime: primaryMime, extension: extension }, this._warnOnOverwrite);
|
| 140 |
+
}
|
| 141 |
+
}
|
| 142 |
+
if (Array.isArray(lang.filenames)) {
|
| 143 |
+
for (const filename of lang.filenames) {
|
| 144 |
+
registerPlatformLanguageAssociation({ id: langId, mime: primaryMime, filename: filename }, this._warnOnOverwrite);
|
| 145 |
+
resolvedLanguage.filenames.push(filename);
|
| 146 |
+
}
|
| 147 |
+
}
|
| 148 |
+
if (Array.isArray(lang.filenamePatterns)) {
|
| 149 |
+
for (const filenamePattern of lang.filenamePatterns) {
|
| 150 |
+
registerPlatformLanguageAssociation({ id: langId, mime: primaryMime, filepattern: filenamePattern }, this._warnOnOverwrite);
|
| 151 |
+
}
|
| 152 |
+
}
|
| 153 |
+
if (typeof lang.firstLine === 'string' && lang.firstLine.length > 0) {
|
| 154 |
+
let firstLineRegexStr = lang.firstLine;
|
| 155 |
+
if (firstLineRegexStr.charAt(0) !== '^') {
|
| 156 |
+
firstLineRegexStr = '^' + firstLineRegexStr;
|
| 157 |
+
}
|
| 158 |
+
try {
|
| 159 |
+
const firstLineRegex = new RegExp(firstLineRegexStr);
|
| 160 |
+
if (!regExpLeadsToEndlessLoop(firstLineRegex)) {
|
| 161 |
+
registerPlatformLanguageAssociation({ id: langId, mime: primaryMime, firstline: firstLineRegex }, this._warnOnOverwrite);
|
| 162 |
+
}
|
| 163 |
+
}
|
| 164 |
+
catch (err) {
|
| 165 |
+
// Most likely, the regex was bad
|
| 166 |
+
console.warn(`[${lang.id}]: Invalid regular expression \`${firstLineRegexStr}\`: `, err);
|
| 167 |
+
}
|
| 168 |
+
}
|
| 169 |
+
resolvedLanguage.aliases.push(langId);
|
| 170 |
+
let langAliases = null;
|
| 171 |
+
if (typeof lang.aliases !== 'undefined' && Array.isArray(lang.aliases)) {
|
| 172 |
+
if (lang.aliases.length === 0) {
|
| 173 |
+
// signal that this language should not get a name
|
| 174 |
+
langAliases = [null];
|
| 175 |
+
}
|
| 176 |
+
else {
|
| 177 |
+
langAliases = lang.aliases;
|
| 178 |
+
}
|
| 179 |
+
}
|
| 180 |
+
if (langAliases !== null) {
|
| 181 |
+
for (const langAlias of langAliases) {
|
| 182 |
+
if (!langAlias || langAlias.length === 0) {
|
| 183 |
+
continue;
|
| 184 |
+
}
|
| 185 |
+
resolvedLanguage.aliases.push(langAlias);
|
| 186 |
+
}
|
| 187 |
+
}
|
| 188 |
+
const containsAliases = (langAliases !== null && langAliases.length > 0);
|
| 189 |
+
if (containsAliases && langAliases[0] === null) {
|
| 190 |
+
// signal that this language should not get a name
|
| 191 |
+
}
|
| 192 |
+
else {
|
| 193 |
+
const bestName = (containsAliases ? langAliases[0] : null) || langId;
|
| 194 |
+
if (containsAliases || !resolvedLanguage.name) {
|
| 195 |
+
resolvedLanguage.name = bestName;
|
| 196 |
+
}
|
| 197 |
+
}
|
| 198 |
+
if (lang.configuration) {
|
| 199 |
+
resolvedLanguage.configurationFiles.push(lang.configuration);
|
| 200 |
+
}
|
| 201 |
+
if (lang.icon) {
|
| 202 |
+
resolvedLanguage.icons.push(lang.icon);
|
| 203 |
+
}
|
| 204 |
+
}
|
| 205 |
+
isRegisteredLanguageId(languageId) {
|
| 206 |
+
if (!languageId) {
|
| 207 |
+
return false;
|
| 208 |
+
}
|
| 209 |
+
return hasOwnProperty.call(this._languages, languageId);
|
| 210 |
+
}
|
| 211 |
+
getRegisteredLanguageIds() {
|
| 212 |
+
return Object.keys(this._languages);
|
| 213 |
+
}
|
| 214 |
+
getLanguageIdByLanguageName(languageName) {
|
| 215 |
+
const languageNameLower = languageName.toLowerCase();
|
| 216 |
+
if (!hasOwnProperty.call(this._lowercaseNameMap, languageNameLower)) {
|
| 217 |
+
return null;
|
| 218 |
+
}
|
| 219 |
+
return this._lowercaseNameMap[languageNameLower];
|
| 220 |
+
}
|
| 221 |
+
getLanguageIdByMimeType(mimeType) {
|
| 222 |
+
if (!mimeType) {
|
| 223 |
+
return null;
|
| 224 |
+
}
|
| 225 |
+
if (hasOwnProperty.call(this._mimeTypesMap, mimeType)) {
|
| 226 |
+
return this._mimeTypesMap[mimeType];
|
| 227 |
+
}
|
| 228 |
+
return null;
|
| 229 |
+
}
|
| 230 |
+
guessLanguageIdByFilepathOrFirstLine(resource, firstLine) {
|
| 231 |
+
if (!resource && !firstLine) {
|
| 232 |
+
return [];
|
| 233 |
+
}
|
| 234 |
+
return getLanguageIds(resource, firstLine);
|
| 235 |
+
}
|
| 236 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/markerDecorations.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
|
| 6 |
+
export const IMarkerDecorationsService = createDecorator('markerDecorationsService');
|
node_modules/monaco-editor/esm/vs/editor/common/services/markerDecorationsService.js
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
| 6 |
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
| 7 |
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
| 8 |
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
| 9 |
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
| 10 |
+
};
|
| 11 |
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
| 12 |
+
return function (target, key) { decorator(target, key, paramIndex); }
|
| 13 |
+
};
|
| 14 |
+
import { IMarkerService, MarkerSeverity } from '../../../platform/markers/common/markers.js';
|
| 15 |
+
import { Disposable, toDisposable } from '../../../base/common/lifecycle.js';
|
| 16 |
+
import { OverviewRulerLane } from '../model.js';
|
| 17 |
+
import { themeColorFromId } from '../../../platform/theme/common/themeService.js';
|
| 18 |
+
import { overviewRulerWarning, overviewRulerInfo, overviewRulerError } from '../core/editorColorRegistry.js';
|
| 19 |
+
import { IModelService } from './model.js';
|
| 20 |
+
import { Range } from '../core/range.js';
|
| 21 |
+
import { Schemas } from '../../../base/common/network.js';
|
| 22 |
+
import { Emitter } from '../../../base/common/event.js';
|
| 23 |
+
import { minimapInfo, minimapWarning, minimapError } from '../../../platform/theme/common/colorRegistry.js';
|
| 24 |
+
import { BidirectionalMap, ResourceMap } from '../../../base/common/map.js';
|
| 25 |
+
import { diffSets } from '../../../base/common/collections.js';
|
| 26 |
+
let MarkerDecorationsService = class MarkerDecorationsService extends Disposable {
|
| 27 |
+
constructor(modelService, _markerService) {
|
| 28 |
+
super();
|
| 29 |
+
this._markerService = _markerService;
|
| 30 |
+
this._onDidChangeMarker = this._register(new Emitter());
|
| 31 |
+
this._markerDecorations = new ResourceMap();
|
| 32 |
+
modelService.getModels().forEach(model => this._onModelAdded(model));
|
| 33 |
+
this._register(modelService.onModelAdded(this._onModelAdded, this));
|
| 34 |
+
this._register(modelService.onModelRemoved(this._onModelRemoved, this));
|
| 35 |
+
this._register(this._markerService.onMarkerChanged(this._handleMarkerChange, this));
|
| 36 |
+
}
|
| 37 |
+
dispose() {
|
| 38 |
+
super.dispose();
|
| 39 |
+
this._markerDecorations.forEach(value => value.dispose());
|
| 40 |
+
this._markerDecorations.clear();
|
| 41 |
+
}
|
| 42 |
+
getMarker(uri, decoration) {
|
| 43 |
+
const markerDecorations = this._markerDecorations.get(uri);
|
| 44 |
+
return markerDecorations ? (markerDecorations.getMarker(decoration) || null) : null;
|
| 45 |
+
}
|
| 46 |
+
_handleMarkerChange(changedResources) {
|
| 47 |
+
changedResources.forEach((resource) => {
|
| 48 |
+
const markerDecorations = this._markerDecorations.get(resource);
|
| 49 |
+
if (markerDecorations) {
|
| 50 |
+
this._updateDecorations(markerDecorations);
|
| 51 |
+
}
|
| 52 |
+
});
|
| 53 |
+
}
|
| 54 |
+
_onModelAdded(model) {
|
| 55 |
+
const markerDecorations = new MarkerDecorations(model);
|
| 56 |
+
this._markerDecorations.set(model.uri, markerDecorations);
|
| 57 |
+
this._updateDecorations(markerDecorations);
|
| 58 |
+
}
|
| 59 |
+
_onModelRemoved(model) {
|
| 60 |
+
const markerDecorations = this._markerDecorations.get(model.uri);
|
| 61 |
+
if (markerDecorations) {
|
| 62 |
+
markerDecorations.dispose();
|
| 63 |
+
this._markerDecorations.delete(model.uri);
|
| 64 |
+
}
|
| 65 |
+
// clean up markers for internal, transient models
|
| 66 |
+
if (model.uri.scheme === Schemas.inMemory
|
| 67 |
+
|| model.uri.scheme === Schemas.internal
|
| 68 |
+
|| model.uri.scheme === Schemas.vscode) {
|
| 69 |
+
this._markerService?.read({ resource: model.uri }).map(marker => marker.owner).forEach(owner => this._markerService.remove(owner, [model.uri]));
|
| 70 |
+
}
|
| 71 |
+
}
|
| 72 |
+
_updateDecorations(markerDecorations) {
|
| 73 |
+
// Limit to the first 500 errors/warnings
|
| 74 |
+
const markers = this._markerService.read({ resource: markerDecorations.model.uri, take: 500 });
|
| 75 |
+
if (markerDecorations.update(markers)) {
|
| 76 |
+
this._onDidChangeMarker.fire(markerDecorations.model);
|
| 77 |
+
}
|
| 78 |
+
}
|
| 79 |
+
};
|
| 80 |
+
MarkerDecorationsService = __decorate([
|
| 81 |
+
__param(0, IModelService),
|
| 82 |
+
__param(1, IMarkerService)
|
| 83 |
+
], MarkerDecorationsService);
|
| 84 |
+
export { MarkerDecorationsService };
|
| 85 |
+
class MarkerDecorations extends Disposable {
|
| 86 |
+
constructor(model) {
|
| 87 |
+
super();
|
| 88 |
+
this.model = model;
|
| 89 |
+
this._map = new BidirectionalMap();
|
| 90 |
+
this._register(toDisposable(() => {
|
| 91 |
+
this.model.deltaDecorations([...this._map.values()], []);
|
| 92 |
+
this._map.clear();
|
| 93 |
+
}));
|
| 94 |
+
}
|
| 95 |
+
update(markers) {
|
| 96 |
+
// We use the fact that marker instances are not recreated when different owners
|
| 97 |
+
// update. So we can compare references to find out what changed since the last update.
|
| 98 |
+
const { added, removed } = diffSets(new Set(this._map.keys()), new Set(markers));
|
| 99 |
+
if (added.length === 0 && removed.length === 0) {
|
| 100 |
+
return false;
|
| 101 |
+
}
|
| 102 |
+
const oldIds = removed.map(marker => this._map.get(marker));
|
| 103 |
+
const newDecorations = added.map(marker => {
|
| 104 |
+
return {
|
| 105 |
+
range: this._createDecorationRange(this.model, marker),
|
| 106 |
+
options: this._createDecorationOption(marker)
|
| 107 |
+
};
|
| 108 |
+
});
|
| 109 |
+
const ids = this.model.deltaDecorations(oldIds, newDecorations);
|
| 110 |
+
for (const removedMarker of removed) {
|
| 111 |
+
this._map.delete(removedMarker);
|
| 112 |
+
}
|
| 113 |
+
for (let index = 0; index < ids.length; index++) {
|
| 114 |
+
this._map.set(added[index], ids[index]);
|
| 115 |
+
}
|
| 116 |
+
return true;
|
| 117 |
+
}
|
| 118 |
+
getMarker(decoration) {
|
| 119 |
+
return this._map.getKey(decoration.id);
|
| 120 |
+
}
|
| 121 |
+
_createDecorationRange(model, rawMarker) {
|
| 122 |
+
let ret = Range.lift(rawMarker);
|
| 123 |
+
if (rawMarker.severity === MarkerSeverity.Hint && !this._hasMarkerTag(rawMarker, 1 /* MarkerTag.Unnecessary */) && !this._hasMarkerTag(rawMarker, 2 /* MarkerTag.Deprecated */)) {
|
| 124 |
+
// * never render hints on multiple lines
|
| 125 |
+
// * make enough space for three dots
|
| 126 |
+
ret = ret.setEndPosition(ret.startLineNumber, ret.startColumn + 2);
|
| 127 |
+
}
|
| 128 |
+
ret = model.validateRange(ret);
|
| 129 |
+
if (ret.isEmpty()) {
|
| 130 |
+
const maxColumn = model.getLineLastNonWhitespaceColumn(ret.startLineNumber) ||
|
| 131 |
+
model.getLineMaxColumn(ret.startLineNumber);
|
| 132 |
+
if (maxColumn === 1 || ret.endColumn >= maxColumn) {
|
| 133 |
+
// empty line or behind eol
|
| 134 |
+
// keep the range as is, it will be rendered 1ch wide
|
| 135 |
+
return ret;
|
| 136 |
+
}
|
| 137 |
+
const word = model.getWordAtPosition(ret.getStartPosition());
|
| 138 |
+
if (word) {
|
| 139 |
+
ret = new Range(ret.startLineNumber, word.startColumn, ret.endLineNumber, word.endColumn);
|
| 140 |
+
}
|
| 141 |
+
}
|
| 142 |
+
else if (rawMarker.endColumn === Number.MAX_VALUE && rawMarker.startColumn === 1 && ret.startLineNumber === ret.endLineNumber) {
|
| 143 |
+
const minColumn = model.getLineFirstNonWhitespaceColumn(rawMarker.startLineNumber);
|
| 144 |
+
if (minColumn < ret.endColumn) {
|
| 145 |
+
ret = new Range(ret.startLineNumber, minColumn, ret.endLineNumber, ret.endColumn);
|
| 146 |
+
rawMarker.startColumn = minColumn;
|
| 147 |
+
}
|
| 148 |
+
}
|
| 149 |
+
return ret;
|
| 150 |
+
}
|
| 151 |
+
_createDecorationOption(marker) {
|
| 152 |
+
let className;
|
| 153 |
+
let color = undefined;
|
| 154 |
+
let zIndex;
|
| 155 |
+
let inlineClassName = undefined;
|
| 156 |
+
let minimap;
|
| 157 |
+
switch (marker.severity) {
|
| 158 |
+
case MarkerSeverity.Hint:
|
| 159 |
+
if (this._hasMarkerTag(marker, 2 /* MarkerTag.Deprecated */)) {
|
| 160 |
+
className = undefined;
|
| 161 |
+
}
|
| 162 |
+
else if (this._hasMarkerTag(marker, 1 /* MarkerTag.Unnecessary */)) {
|
| 163 |
+
className = "squiggly-unnecessary" /* ClassName.EditorUnnecessaryDecoration */;
|
| 164 |
+
}
|
| 165 |
+
else {
|
| 166 |
+
className = "squiggly-hint" /* ClassName.EditorHintDecoration */;
|
| 167 |
+
}
|
| 168 |
+
zIndex = 0;
|
| 169 |
+
break;
|
| 170 |
+
case MarkerSeverity.Info:
|
| 171 |
+
className = "squiggly-info" /* ClassName.EditorInfoDecoration */;
|
| 172 |
+
color = themeColorFromId(overviewRulerInfo);
|
| 173 |
+
zIndex = 10;
|
| 174 |
+
minimap = {
|
| 175 |
+
color: themeColorFromId(minimapInfo),
|
| 176 |
+
position: 1 /* MinimapPosition.Inline */
|
| 177 |
+
};
|
| 178 |
+
break;
|
| 179 |
+
case MarkerSeverity.Warning:
|
| 180 |
+
className = "squiggly-warning" /* ClassName.EditorWarningDecoration */;
|
| 181 |
+
color = themeColorFromId(overviewRulerWarning);
|
| 182 |
+
zIndex = 20;
|
| 183 |
+
minimap = {
|
| 184 |
+
color: themeColorFromId(minimapWarning),
|
| 185 |
+
position: 1 /* MinimapPosition.Inline */
|
| 186 |
+
};
|
| 187 |
+
break;
|
| 188 |
+
case MarkerSeverity.Error:
|
| 189 |
+
default:
|
| 190 |
+
className = "squiggly-error" /* ClassName.EditorErrorDecoration */;
|
| 191 |
+
color = themeColorFromId(overviewRulerError);
|
| 192 |
+
zIndex = 30;
|
| 193 |
+
minimap = {
|
| 194 |
+
color: themeColorFromId(minimapError),
|
| 195 |
+
position: 1 /* MinimapPosition.Inline */
|
| 196 |
+
};
|
| 197 |
+
break;
|
| 198 |
+
}
|
| 199 |
+
if (marker.tags) {
|
| 200 |
+
if (marker.tags.indexOf(1 /* MarkerTag.Unnecessary */) !== -1) {
|
| 201 |
+
inlineClassName = "squiggly-inline-unnecessary" /* ClassName.EditorUnnecessaryInlineDecoration */;
|
| 202 |
+
}
|
| 203 |
+
if (marker.tags.indexOf(2 /* MarkerTag.Deprecated */) !== -1) {
|
| 204 |
+
inlineClassName = "squiggly-inline-deprecated" /* ClassName.EditorDeprecatedInlineDecoration */;
|
| 205 |
+
}
|
| 206 |
+
}
|
| 207 |
+
return {
|
| 208 |
+
description: 'marker-decoration',
|
| 209 |
+
stickiness: 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */,
|
| 210 |
+
className,
|
| 211 |
+
showIfCollapsed: true,
|
| 212 |
+
overviewRuler: {
|
| 213 |
+
color,
|
| 214 |
+
position: OverviewRulerLane.Right
|
| 215 |
+
},
|
| 216 |
+
minimap,
|
| 217 |
+
zIndex,
|
| 218 |
+
inlineClassName,
|
| 219 |
+
};
|
| 220 |
+
}
|
| 221 |
+
_hasMarkerTag(marker, tag) {
|
| 222 |
+
if (marker.tags) {
|
| 223 |
+
return marker.tags.indexOf(tag) >= 0;
|
| 224 |
+
}
|
| 225 |
+
return false;
|
| 226 |
+
}
|
| 227 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/model.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
|
| 6 |
+
export const IModelService = createDecorator('modelService');
|
node_modules/monaco-editor/esm/vs/editor/common/services/modelService.js
ADDED
|
@@ -0,0 +1,418 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
| 6 |
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
| 7 |
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
| 8 |
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
| 9 |
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
| 10 |
+
};
|
| 11 |
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
| 12 |
+
return function (target, key) { decorator(target, key, paramIndex); }
|
| 13 |
+
};
|
| 14 |
+
var ModelService_1;
|
| 15 |
+
import { Emitter } from '../../../base/common/event.js';
|
| 16 |
+
import { Disposable, DisposableStore } from '../../../base/common/lifecycle.js';
|
| 17 |
+
import * as platform from '../../../base/common/platform.js';
|
| 18 |
+
import { TextModel } from '../model/textModel.js';
|
| 19 |
+
import { EDITOR_MODEL_DEFAULTS } from '../core/textModelDefaults.js';
|
| 20 |
+
import { PLAINTEXT_LANGUAGE_ID } from '../languages/modesRegistry.js';
|
| 21 |
+
import { ITextResourcePropertiesService } from './textResourceConfiguration.js';
|
| 22 |
+
import { IConfigurationService } from '../../../platform/configuration/common/configuration.js';
|
| 23 |
+
import { IUndoRedoService } from '../../../platform/undoRedo/common/undoRedo.js';
|
| 24 |
+
import { StringSHA1 } from '../../../base/common/hash.js';
|
| 25 |
+
import { isEditStackElement } from '../model/editStack.js';
|
| 26 |
+
import { Schemas } from '../../../base/common/network.js';
|
| 27 |
+
import { equals } from '../../../base/common/objects.js';
|
| 28 |
+
import { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';
|
| 29 |
+
function MODEL_ID(resource) {
|
| 30 |
+
return resource.toString();
|
| 31 |
+
}
|
| 32 |
+
class ModelData {
|
| 33 |
+
constructor(model, onWillDispose, onDidChangeLanguage) {
|
| 34 |
+
this.model = model;
|
| 35 |
+
this._modelEventListeners = new DisposableStore();
|
| 36 |
+
this.model = model;
|
| 37 |
+
this._modelEventListeners.add(model.onWillDispose(() => onWillDispose(model)));
|
| 38 |
+
this._modelEventListeners.add(model.onDidChangeLanguage((e) => onDidChangeLanguage(model, e)));
|
| 39 |
+
}
|
| 40 |
+
dispose() {
|
| 41 |
+
this._modelEventListeners.dispose();
|
| 42 |
+
}
|
| 43 |
+
}
|
| 44 |
+
const DEFAULT_EOL = (platform.isLinux || platform.isMacintosh) ? 1 /* DefaultEndOfLine.LF */ : 2 /* DefaultEndOfLine.CRLF */;
|
| 45 |
+
class DisposedModelInfo {
|
| 46 |
+
constructor(uri, initialUndoRedoSnapshot, time, sharesUndoRedoStack, heapSize, sha1, versionId, alternativeVersionId) {
|
| 47 |
+
this.uri = uri;
|
| 48 |
+
this.initialUndoRedoSnapshot = initialUndoRedoSnapshot;
|
| 49 |
+
this.time = time;
|
| 50 |
+
this.sharesUndoRedoStack = sharesUndoRedoStack;
|
| 51 |
+
this.heapSize = heapSize;
|
| 52 |
+
this.sha1 = sha1;
|
| 53 |
+
this.versionId = versionId;
|
| 54 |
+
this.alternativeVersionId = alternativeVersionId;
|
| 55 |
+
}
|
| 56 |
+
}
|
| 57 |
+
let ModelService = class ModelService extends Disposable {
|
| 58 |
+
static { ModelService_1 = this; }
|
| 59 |
+
static { this.MAX_MEMORY_FOR_CLOSED_FILES_UNDO_STACK = 20 * 1024 * 1024; }
|
| 60 |
+
constructor(_configurationService, _resourcePropertiesService, _undoRedoService, _instantiationService) {
|
| 61 |
+
super();
|
| 62 |
+
this._configurationService = _configurationService;
|
| 63 |
+
this._resourcePropertiesService = _resourcePropertiesService;
|
| 64 |
+
this._undoRedoService = _undoRedoService;
|
| 65 |
+
this._instantiationService = _instantiationService;
|
| 66 |
+
this._onModelAdded = this._register(new Emitter());
|
| 67 |
+
this.onModelAdded = this._onModelAdded.event;
|
| 68 |
+
this._onModelRemoved = this._register(new Emitter());
|
| 69 |
+
this.onModelRemoved = this._onModelRemoved.event;
|
| 70 |
+
this._onModelModeChanged = this._register(new Emitter());
|
| 71 |
+
this.onModelLanguageChanged = this._onModelModeChanged.event;
|
| 72 |
+
this._modelCreationOptionsByLanguageAndResource = Object.create(null);
|
| 73 |
+
this._models = {};
|
| 74 |
+
this._disposedModels = new Map();
|
| 75 |
+
this._disposedModelsHeapSize = 0;
|
| 76 |
+
this._register(this._configurationService.onDidChangeConfiguration(e => this._updateModelOptions(e)));
|
| 77 |
+
this._updateModelOptions(undefined);
|
| 78 |
+
}
|
| 79 |
+
static _readModelOptions(config, isForSimpleWidget) {
|
| 80 |
+
let tabSize = EDITOR_MODEL_DEFAULTS.tabSize;
|
| 81 |
+
if (config.editor && typeof config.editor.tabSize !== 'undefined') {
|
| 82 |
+
const parsedTabSize = parseInt(config.editor.tabSize, 10);
|
| 83 |
+
if (!isNaN(parsedTabSize)) {
|
| 84 |
+
tabSize = parsedTabSize;
|
| 85 |
+
}
|
| 86 |
+
if (tabSize < 1) {
|
| 87 |
+
tabSize = 1;
|
| 88 |
+
}
|
| 89 |
+
}
|
| 90 |
+
let indentSize = 'tabSize';
|
| 91 |
+
if (config.editor && typeof config.editor.indentSize !== 'undefined' && config.editor.indentSize !== 'tabSize') {
|
| 92 |
+
const parsedIndentSize = parseInt(config.editor.indentSize, 10);
|
| 93 |
+
if (!isNaN(parsedIndentSize)) {
|
| 94 |
+
indentSize = Math.max(parsedIndentSize, 1);
|
| 95 |
+
}
|
| 96 |
+
}
|
| 97 |
+
let insertSpaces = EDITOR_MODEL_DEFAULTS.insertSpaces;
|
| 98 |
+
if (config.editor && typeof config.editor.insertSpaces !== 'undefined') {
|
| 99 |
+
insertSpaces = (config.editor.insertSpaces === 'false' ? false : Boolean(config.editor.insertSpaces));
|
| 100 |
+
}
|
| 101 |
+
let newDefaultEOL = DEFAULT_EOL;
|
| 102 |
+
const eol = config.eol;
|
| 103 |
+
if (eol === '\r\n') {
|
| 104 |
+
newDefaultEOL = 2 /* DefaultEndOfLine.CRLF */;
|
| 105 |
+
}
|
| 106 |
+
else if (eol === '\n') {
|
| 107 |
+
newDefaultEOL = 1 /* DefaultEndOfLine.LF */;
|
| 108 |
+
}
|
| 109 |
+
let trimAutoWhitespace = EDITOR_MODEL_DEFAULTS.trimAutoWhitespace;
|
| 110 |
+
if (config.editor && typeof config.editor.trimAutoWhitespace !== 'undefined') {
|
| 111 |
+
trimAutoWhitespace = (config.editor.trimAutoWhitespace === 'false' ? false : Boolean(config.editor.trimAutoWhitespace));
|
| 112 |
+
}
|
| 113 |
+
let detectIndentation = EDITOR_MODEL_DEFAULTS.detectIndentation;
|
| 114 |
+
if (config.editor && typeof config.editor.detectIndentation !== 'undefined') {
|
| 115 |
+
detectIndentation = (config.editor.detectIndentation === 'false' ? false : Boolean(config.editor.detectIndentation));
|
| 116 |
+
}
|
| 117 |
+
let largeFileOptimizations = EDITOR_MODEL_DEFAULTS.largeFileOptimizations;
|
| 118 |
+
if (config.editor && typeof config.editor.largeFileOptimizations !== 'undefined') {
|
| 119 |
+
largeFileOptimizations = (config.editor.largeFileOptimizations === 'false' ? false : Boolean(config.editor.largeFileOptimizations));
|
| 120 |
+
}
|
| 121 |
+
let bracketPairColorizationOptions = EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions;
|
| 122 |
+
if (config.editor?.bracketPairColorization && typeof config.editor.bracketPairColorization === 'object') {
|
| 123 |
+
bracketPairColorizationOptions = {
|
| 124 |
+
enabled: !!config.editor.bracketPairColorization.enabled,
|
| 125 |
+
independentColorPoolPerBracketType: !!config.editor.bracketPairColorization.independentColorPoolPerBracketType
|
| 126 |
+
};
|
| 127 |
+
}
|
| 128 |
+
return {
|
| 129 |
+
isForSimpleWidget: isForSimpleWidget,
|
| 130 |
+
tabSize: tabSize,
|
| 131 |
+
indentSize: indentSize,
|
| 132 |
+
insertSpaces: insertSpaces,
|
| 133 |
+
detectIndentation: detectIndentation,
|
| 134 |
+
defaultEOL: newDefaultEOL,
|
| 135 |
+
trimAutoWhitespace: trimAutoWhitespace,
|
| 136 |
+
largeFileOptimizations: largeFileOptimizations,
|
| 137 |
+
bracketPairColorizationOptions
|
| 138 |
+
};
|
| 139 |
+
}
|
| 140 |
+
_getEOL(resource, language) {
|
| 141 |
+
if (resource) {
|
| 142 |
+
return this._resourcePropertiesService.getEOL(resource, language);
|
| 143 |
+
}
|
| 144 |
+
const eol = this._configurationService.getValue('files.eol', { overrideIdentifier: language });
|
| 145 |
+
if (eol && typeof eol === 'string' && eol !== 'auto') {
|
| 146 |
+
return eol;
|
| 147 |
+
}
|
| 148 |
+
return platform.OS === 3 /* platform.OperatingSystem.Linux */ || platform.OS === 2 /* platform.OperatingSystem.Macintosh */ ? '\n' : '\r\n';
|
| 149 |
+
}
|
| 150 |
+
_shouldRestoreUndoStack() {
|
| 151 |
+
const result = this._configurationService.getValue('files.restoreUndoStack');
|
| 152 |
+
if (typeof result === 'boolean') {
|
| 153 |
+
return result;
|
| 154 |
+
}
|
| 155 |
+
return true;
|
| 156 |
+
}
|
| 157 |
+
getCreationOptions(languageIdOrSelection, resource, isForSimpleWidget) {
|
| 158 |
+
const language = (typeof languageIdOrSelection === 'string' ? languageIdOrSelection : languageIdOrSelection.languageId);
|
| 159 |
+
let creationOptions = this._modelCreationOptionsByLanguageAndResource[language + resource];
|
| 160 |
+
if (!creationOptions) {
|
| 161 |
+
const editor = this._configurationService.getValue('editor', { overrideIdentifier: language, resource });
|
| 162 |
+
const eol = this._getEOL(resource, language);
|
| 163 |
+
creationOptions = ModelService_1._readModelOptions({ editor, eol }, isForSimpleWidget);
|
| 164 |
+
this._modelCreationOptionsByLanguageAndResource[language + resource] = creationOptions;
|
| 165 |
+
}
|
| 166 |
+
return creationOptions;
|
| 167 |
+
}
|
| 168 |
+
_updateModelOptions(e) {
|
| 169 |
+
const oldOptionsByLanguageAndResource = this._modelCreationOptionsByLanguageAndResource;
|
| 170 |
+
this._modelCreationOptionsByLanguageAndResource = Object.create(null);
|
| 171 |
+
// Update options on all models
|
| 172 |
+
const keys = Object.keys(this._models);
|
| 173 |
+
for (let i = 0, len = keys.length; i < len; i++) {
|
| 174 |
+
const modelId = keys[i];
|
| 175 |
+
const modelData = this._models[modelId];
|
| 176 |
+
const language = modelData.model.getLanguageId();
|
| 177 |
+
const uri = modelData.model.uri;
|
| 178 |
+
if (e && !e.affectsConfiguration('editor', { overrideIdentifier: language, resource: uri }) && !e.affectsConfiguration('files.eol', { overrideIdentifier: language, resource: uri })) {
|
| 179 |
+
continue; // perf: skip if this model is not affected by configuration change
|
| 180 |
+
}
|
| 181 |
+
const oldOptions = oldOptionsByLanguageAndResource[language + uri];
|
| 182 |
+
const newOptions = this.getCreationOptions(language, uri, modelData.model.isForSimpleWidget);
|
| 183 |
+
ModelService_1._setModelOptionsForModel(modelData.model, newOptions, oldOptions);
|
| 184 |
+
}
|
| 185 |
+
}
|
| 186 |
+
static _setModelOptionsForModel(model, newOptions, currentOptions) {
|
| 187 |
+
if (currentOptions && currentOptions.defaultEOL !== newOptions.defaultEOL && model.getLineCount() === 1) {
|
| 188 |
+
model.setEOL(newOptions.defaultEOL === 1 /* DefaultEndOfLine.LF */ ? 0 /* EndOfLineSequence.LF */ : 1 /* EndOfLineSequence.CRLF */);
|
| 189 |
+
}
|
| 190 |
+
if (currentOptions
|
| 191 |
+
&& (currentOptions.detectIndentation === newOptions.detectIndentation)
|
| 192 |
+
&& (currentOptions.insertSpaces === newOptions.insertSpaces)
|
| 193 |
+
&& (currentOptions.tabSize === newOptions.tabSize)
|
| 194 |
+
&& (currentOptions.indentSize === newOptions.indentSize)
|
| 195 |
+
&& (currentOptions.trimAutoWhitespace === newOptions.trimAutoWhitespace)
|
| 196 |
+
&& equals(currentOptions.bracketPairColorizationOptions, newOptions.bracketPairColorizationOptions)) {
|
| 197 |
+
// Same indent opts, no need to touch the model
|
| 198 |
+
return;
|
| 199 |
+
}
|
| 200 |
+
if (newOptions.detectIndentation) {
|
| 201 |
+
model.detectIndentation(newOptions.insertSpaces, newOptions.tabSize);
|
| 202 |
+
model.updateOptions({
|
| 203 |
+
trimAutoWhitespace: newOptions.trimAutoWhitespace,
|
| 204 |
+
bracketColorizationOptions: newOptions.bracketPairColorizationOptions
|
| 205 |
+
});
|
| 206 |
+
}
|
| 207 |
+
else {
|
| 208 |
+
model.updateOptions({
|
| 209 |
+
insertSpaces: newOptions.insertSpaces,
|
| 210 |
+
tabSize: newOptions.tabSize,
|
| 211 |
+
indentSize: newOptions.indentSize,
|
| 212 |
+
trimAutoWhitespace: newOptions.trimAutoWhitespace,
|
| 213 |
+
bracketColorizationOptions: newOptions.bracketPairColorizationOptions
|
| 214 |
+
});
|
| 215 |
+
}
|
| 216 |
+
}
|
| 217 |
+
// --- begin IModelService
|
| 218 |
+
_insertDisposedModel(disposedModelData) {
|
| 219 |
+
this._disposedModels.set(MODEL_ID(disposedModelData.uri), disposedModelData);
|
| 220 |
+
this._disposedModelsHeapSize += disposedModelData.heapSize;
|
| 221 |
+
}
|
| 222 |
+
_removeDisposedModel(resource) {
|
| 223 |
+
const disposedModelData = this._disposedModels.get(MODEL_ID(resource));
|
| 224 |
+
if (disposedModelData) {
|
| 225 |
+
this._disposedModelsHeapSize -= disposedModelData.heapSize;
|
| 226 |
+
}
|
| 227 |
+
this._disposedModels.delete(MODEL_ID(resource));
|
| 228 |
+
return disposedModelData;
|
| 229 |
+
}
|
| 230 |
+
_ensureDisposedModelsHeapSize(maxModelsHeapSize) {
|
| 231 |
+
if (this._disposedModelsHeapSize > maxModelsHeapSize) {
|
| 232 |
+
// we must remove some old undo stack elements to free up some memory
|
| 233 |
+
const disposedModels = [];
|
| 234 |
+
this._disposedModels.forEach(entry => {
|
| 235 |
+
if (!entry.sharesUndoRedoStack) {
|
| 236 |
+
disposedModels.push(entry);
|
| 237 |
+
}
|
| 238 |
+
});
|
| 239 |
+
disposedModels.sort((a, b) => a.time - b.time);
|
| 240 |
+
while (disposedModels.length > 0 && this._disposedModelsHeapSize > maxModelsHeapSize) {
|
| 241 |
+
const disposedModel = disposedModels.shift();
|
| 242 |
+
this._removeDisposedModel(disposedModel.uri);
|
| 243 |
+
if (disposedModel.initialUndoRedoSnapshot !== null) {
|
| 244 |
+
this._undoRedoService.restoreSnapshot(disposedModel.initialUndoRedoSnapshot);
|
| 245 |
+
}
|
| 246 |
+
}
|
| 247 |
+
}
|
| 248 |
+
}
|
| 249 |
+
_createModelData(value, languageIdOrSelection, resource, isForSimpleWidget) {
|
| 250 |
+
// create & save the model
|
| 251 |
+
const options = this.getCreationOptions(languageIdOrSelection, resource, isForSimpleWidget);
|
| 252 |
+
const model = this._instantiationService.createInstance(TextModel, value, languageIdOrSelection, options, resource);
|
| 253 |
+
if (resource && this._disposedModels.has(MODEL_ID(resource))) {
|
| 254 |
+
const disposedModelData = this._removeDisposedModel(resource);
|
| 255 |
+
const elements = this._undoRedoService.getElements(resource);
|
| 256 |
+
const sha1Computer = this._getSHA1Computer();
|
| 257 |
+
const sha1IsEqual = (sha1Computer.canComputeSHA1(model)
|
| 258 |
+
? sha1Computer.computeSHA1(model) === disposedModelData.sha1
|
| 259 |
+
: false);
|
| 260 |
+
if (sha1IsEqual || disposedModelData.sharesUndoRedoStack) {
|
| 261 |
+
for (const element of elements.past) {
|
| 262 |
+
if (isEditStackElement(element) && element.matchesResource(resource)) {
|
| 263 |
+
element.setModel(model);
|
| 264 |
+
}
|
| 265 |
+
}
|
| 266 |
+
for (const element of elements.future) {
|
| 267 |
+
if (isEditStackElement(element) && element.matchesResource(resource)) {
|
| 268 |
+
element.setModel(model);
|
| 269 |
+
}
|
| 270 |
+
}
|
| 271 |
+
this._undoRedoService.setElementsValidFlag(resource, true, (element) => (isEditStackElement(element) && element.matchesResource(resource)));
|
| 272 |
+
if (sha1IsEqual) {
|
| 273 |
+
model._overwriteVersionId(disposedModelData.versionId);
|
| 274 |
+
model._overwriteAlternativeVersionId(disposedModelData.alternativeVersionId);
|
| 275 |
+
model._overwriteInitialUndoRedoSnapshot(disposedModelData.initialUndoRedoSnapshot);
|
| 276 |
+
}
|
| 277 |
+
}
|
| 278 |
+
else {
|
| 279 |
+
if (disposedModelData.initialUndoRedoSnapshot !== null) {
|
| 280 |
+
this._undoRedoService.restoreSnapshot(disposedModelData.initialUndoRedoSnapshot);
|
| 281 |
+
}
|
| 282 |
+
}
|
| 283 |
+
}
|
| 284 |
+
const modelId = MODEL_ID(model.uri);
|
| 285 |
+
if (this._models[modelId]) {
|
| 286 |
+
// There already exists a model with this id => this is a programmer error
|
| 287 |
+
throw new Error('ModelService: Cannot add model because it already exists!');
|
| 288 |
+
}
|
| 289 |
+
const modelData = new ModelData(model, (model) => this._onWillDispose(model), (model, e) => this._onDidChangeLanguage(model, e));
|
| 290 |
+
this._models[modelId] = modelData;
|
| 291 |
+
return modelData;
|
| 292 |
+
}
|
| 293 |
+
createModel(value, languageSelection, resource, isForSimpleWidget = false) {
|
| 294 |
+
let modelData;
|
| 295 |
+
if (languageSelection) {
|
| 296 |
+
modelData = this._createModelData(value, languageSelection, resource, isForSimpleWidget);
|
| 297 |
+
}
|
| 298 |
+
else {
|
| 299 |
+
modelData = this._createModelData(value, PLAINTEXT_LANGUAGE_ID, resource, isForSimpleWidget);
|
| 300 |
+
}
|
| 301 |
+
this._onModelAdded.fire(modelData.model);
|
| 302 |
+
return modelData.model;
|
| 303 |
+
}
|
| 304 |
+
getModels() {
|
| 305 |
+
const ret = [];
|
| 306 |
+
const keys = Object.keys(this._models);
|
| 307 |
+
for (let i = 0, len = keys.length; i < len; i++) {
|
| 308 |
+
const modelId = keys[i];
|
| 309 |
+
ret.push(this._models[modelId].model);
|
| 310 |
+
}
|
| 311 |
+
return ret;
|
| 312 |
+
}
|
| 313 |
+
getModel(resource) {
|
| 314 |
+
const modelId = MODEL_ID(resource);
|
| 315 |
+
const modelData = this._models[modelId];
|
| 316 |
+
if (!modelData) {
|
| 317 |
+
return null;
|
| 318 |
+
}
|
| 319 |
+
return modelData.model;
|
| 320 |
+
}
|
| 321 |
+
// --- end IModelService
|
| 322 |
+
_schemaShouldMaintainUndoRedoElements(resource) {
|
| 323 |
+
return (resource.scheme === Schemas.file
|
| 324 |
+
|| resource.scheme === Schemas.vscodeRemote
|
| 325 |
+
|| resource.scheme === Schemas.vscodeUserData
|
| 326 |
+
|| resource.scheme === Schemas.vscodeNotebookCell
|
| 327 |
+
|| resource.scheme === 'fake-fs' // for tests
|
| 328 |
+
);
|
| 329 |
+
}
|
| 330 |
+
_onWillDispose(model) {
|
| 331 |
+
const modelId = MODEL_ID(model.uri);
|
| 332 |
+
const modelData = this._models[modelId];
|
| 333 |
+
const sharesUndoRedoStack = (this._undoRedoService.getUriComparisonKey(model.uri) !== model.uri.toString());
|
| 334 |
+
let maintainUndoRedoStack = false;
|
| 335 |
+
let heapSize = 0;
|
| 336 |
+
if (sharesUndoRedoStack || (this._shouldRestoreUndoStack() && this._schemaShouldMaintainUndoRedoElements(model.uri))) {
|
| 337 |
+
const elements = this._undoRedoService.getElements(model.uri);
|
| 338 |
+
if (elements.past.length > 0 || elements.future.length > 0) {
|
| 339 |
+
for (const element of elements.past) {
|
| 340 |
+
if (isEditStackElement(element) && element.matchesResource(model.uri)) {
|
| 341 |
+
maintainUndoRedoStack = true;
|
| 342 |
+
heapSize += element.heapSize(model.uri);
|
| 343 |
+
element.setModel(model.uri); // remove reference from text buffer instance
|
| 344 |
+
}
|
| 345 |
+
}
|
| 346 |
+
for (const element of elements.future) {
|
| 347 |
+
if (isEditStackElement(element) && element.matchesResource(model.uri)) {
|
| 348 |
+
maintainUndoRedoStack = true;
|
| 349 |
+
heapSize += element.heapSize(model.uri);
|
| 350 |
+
element.setModel(model.uri); // remove reference from text buffer instance
|
| 351 |
+
}
|
| 352 |
+
}
|
| 353 |
+
}
|
| 354 |
+
}
|
| 355 |
+
const maxMemory = ModelService_1.MAX_MEMORY_FOR_CLOSED_FILES_UNDO_STACK;
|
| 356 |
+
const sha1Computer = this._getSHA1Computer();
|
| 357 |
+
if (!maintainUndoRedoStack) {
|
| 358 |
+
if (!sharesUndoRedoStack) {
|
| 359 |
+
const initialUndoRedoSnapshot = modelData.model.getInitialUndoRedoSnapshot();
|
| 360 |
+
if (initialUndoRedoSnapshot !== null) {
|
| 361 |
+
this._undoRedoService.restoreSnapshot(initialUndoRedoSnapshot);
|
| 362 |
+
}
|
| 363 |
+
}
|
| 364 |
+
}
|
| 365 |
+
else if (!sharesUndoRedoStack && (heapSize > maxMemory || !sha1Computer.canComputeSHA1(model))) {
|
| 366 |
+
// the undo stack for this file would never fit in the configured memory or the file is very large, so don't bother with it.
|
| 367 |
+
const initialUndoRedoSnapshot = modelData.model.getInitialUndoRedoSnapshot();
|
| 368 |
+
if (initialUndoRedoSnapshot !== null) {
|
| 369 |
+
this._undoRedoService.restoreSnapshot(initialUndoRedoSnapshot);
|
| 370 |
+
}
|
| 371 |
+
}
|
| 372 |
+
else {
|
| 373 |
+
this._ensureDisposedModelsHeapSize(maxMemory - heapSize);
|
| 374 |
+
// We only invalidate the elements, but they remain in the undo-redo service.
|
| 375 |
+
this._undoRedoService.setElementsValidFlag(model.uri, false, (element) => (isEditStackElement(element) && element.matchesResource(model.uri)));
|
| 376 |
+
this._insertDisposedModel(new DisposedModelInfo(model.uri, modelData.model.getInitialUndoRedoSnapshot(), Date.now(), sharesUndoRedoStack, heapSize, sha1Computer.computeSHA1(model), model.getVersionId(), model.getAlternativeVersionId()));
|
| 377 |
+
}
|
| 378 |
+
delete this._models[modelId];
|
| 379 |
+
modelData.dispose();
|
| 380 |
+
// clean up cache
|
| 381 |
+
delete this._modelCreationOptionsByLanguageAndResource[model.getLanguageId() + model.uri];
|
| 382 |
+
this._onModelRemoved.fire(model);
|
| 383 |
+
}
|
| 384 |
+
_onDidChangeLanguage(model, e) {
|
| 385 |
+
const oldLanguageId = e.oldLanguage;
|
| 386 |
+
const newLanguageId = model.getLanguageId();
|
| 387 |
+
const oldOptions = this.getCreationOptions(oldLanguageId, model.uri, model.isForSimpleWidget);
|
| 388 |
+
const newOptions = this.getCreationOptions(newLanguageId, model.uri, model.isForSimpleWidget);
|
| 389 |
+
ModelService_1._setModelOptionsForModel(model, newOptions, oldOptions);
|
| 390 |
+
this._onModelModeChanged.fire({ model, oldLanguageId: oldLanguageId });
|
| 391 |
+
}
|
| 392 |
+
_getSHA1Computer() {
|
| 393 |
+
return new DefaultModelSHA1Computer();
|
| 394 |
+
}
|
| 395 |
+
};
|
| 396 |
+
ModelService = ModelService_1 = __decorate([
|
| 397 |
+
__param(0, IConfigurationService),
|
| 398 |
+
__param(1, ITextResourcePropertiesService),
|
| 399 |
+
__param(2, IUndoRedoService),
|
| 400 |
+
__param(3, IInstantiationService)
|
| 401 |
+
], ModelService);
|
| 402 |
+
export { ModelService };
|
| 403 |
+
export class DefaultModelSHA1Computer {
|
| 404 |
+
static { this.MAX_MODEL_SIZE = 10 * 1024 * 1024; } // takes 200ms to compute a sha1 on a 10MB model on a new machine
|
| 405 |
+
canComputeSHA1(model) {
|
| 406 |
+
return (model.getValueLength() <= DefaultModelSHA1Computer.MAX_MODEL_SIZE);
|
| 407 |
+
}
|
| 408 |
+
computeSHA1(model) {
|
| 409 |
+
// compute the sha1
|
| 410 |
+
const shaComputer = new StringSHA1();
|
| 411 |
+
const snapshot = model.createSnapshot();
|
| 412 |
+
let text;
|
| 413 |
+
while ((text = snapshot.read())) {
|
| 414 |
+
shaComputer.update(text);
|
| 415 |
+
}
|
| 416 |
+
return shaComputer.digest();
|
| 417 |
+
}
|
| 418 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/resolverService.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
|
| 2 |
+
export const ITextModelService = createDecorator('textModelService');
|
node_modules/monaco-editor/esm/vs/editor/common/services/semanticTokensDto.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { VSBuffer } from '../../../base/common/buffer.js';
|
| 6 |
+
import * as platform from '../../../base/common/platform.js';
|
| 7 |
+
function reverseEndianness(arr) {
|
| 8 |
+
for (let i = 0, len = arr.length; i < len; i += 4) {
|
| 9 |
+
// flip bytes 0<->3 and 1<->2
|
| 10 |
+
const b0 = arr[i + 0];
|
| 11 |
+
const b1 = arr[i + 1];
|
| 12 |
+
const b2 = arr[i + 2];
|
| 13 |
+
const b3 = arr[i + 3];
|
| 14 |
+
arr[i + 0] = b3;
|
| 15 |
+
arr[i + 1] = b2;
|
| 16 |
+
arr[i + 2] = b1;
|
| 17 |
+
arr[i + 3] = b0;
|
| 18 |
+
}
|
| 19 |
+
}
|
| 20 |
+
function toLittleEndianBuffer(arr) {
|
| 21 |
+
const uint8Arr = new Uint8Array(arr.buffer, arr.byteOffset, arr.length * 4);
|
| 22 |
+
if (!platform.isLittleEndian()) {
|
| 23 |
+
// the byte order must be changed
|
| 24 |
+
reverseEndianness(uint8Arr);
|
| 25 |
+
}
|
| 26 |
+
return VSBuffer.wrap(uint8Arr);
|
| 27 |
+
}
|
| 28 |
+
export function encodeSemanticTokensDto(semanticTokens) {
|
| 29 |
+
const dest = new Uint32Array(encodeSemanticTokensDtoSize(semanticTokens));
|
| 30 |
+
let offset = 0;
|
| 31 |
+
dest[offset++] = semanticTokens.id;
|
| 32 |
+
if (semanticTokens.type === 'full') {
|
| 33 |
+
dest[offset++] = 1 /* EncodedSemanticTokensType.Full */;
|
| 34 |
+
dest[offset++] = semanticTokens.data.length;
|
| 35 |
+
dest.set(semanticTokens.data, offset);
|
| 36 |
+
offset += semanticTokens.data.length;
|
| 37 |
+
}
|
| 38 |
+
else {
|
| 39 |
+
dest[offset++] = 2 /* EncodedSemanticTokensType.Delta */;
|
| 40 |
+
dest[offset++] = semanticTokens.deltas.length;
|
| 41 |
+
for (const delta of semanticTokens.deltas) {
|
| 42 |
+
dest[offset++] = delta.start;
|
| 43 |
+
dest[offset++] = delta.deleteCount;
|
| 44 |
+
if (delta.data) {
|
| 45 |
+
dest[offset++] = delta.data.length;
|
| 46 |
+
dest.set(delta.data, offset);
|
| 47 |
+
offset += delta.data.length;
|
| 48 |
+
}
|
| 49 |
+
else {
|
| 50 |
+
dest[offset++] = 0;
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
return toLittleEndianBuffer(dest);
|
| 55 |
+
}
|
| 56 |
+
function encodeSemanticTokensDtoSize(semanticTokens) {
|
| 57 |
+
let result = 0;
|
| 58 |
+
result += (+1 // id
|
| 59 |
+
+ 1 // type
|
| 60 |
+
);
|
| 61 |
+
if (semanticTokens.type === 'full') {
|
| 62 |
+
result += (+1 // data length
|
| 63 |
+
+ semanticTokens.data.length);
|
| 64 |
+
}
|
| 65 |
+
else {
|
| 66 |
+
result += (+1 // delta count
|
| 67 |
+
);
|
| 68 |
+
result += (+1 // start
|
| 69 |
+
+ 1 // deleteCount
|
| 70 |
+
+ 1 // data length
|
| 71 |
+
) * semanticTokens.deltas.length;
|
| 72 |
+
for (const delta of semanticTokens.deltas) {
|
| 73 |
+
if (delta.data) {
|
| 74 |
+
result += delta.data.length;
|
| 75 |
+
}
|
| 76 |
+
}
|
| 77 |
+
}
|
| 78 |
+
return result;
|
| 79 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/semanticTokensProviderStyling.js
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
| 6 |
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
| 7 |
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
| 8 |
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
| 9 |
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
| 10 |
+
};
|
| 11 |
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
| 12 |
+
return function (target, key) { decorator(target, key, paramIndex); }
|
| 13 |
+
};
|
| 14 |
+
import { TokenMetadata } from '../encodedTokenAttributes.js';
|
| 15 |
+
import { IThemeService } from '../../../platform/theme/common/themeService.js';
|
| 16 |
+
import { ILogService, LogLevel } from '../../../platform/log/common/log.js';
|
| 17 |
+
import { SparseMultilineTokens } from '../tokens/sparseMultilineTokens.js';
|
| 18 |
+
import { ILanguageService } from '../languages/language.js';
|
| 19 |
+
const ENABLE_TRACE = false;
|
| 20 |
+
let SemanticTokensProviderStyling = class SemanticTokensProviderStyling {
|
| 21 |
+
constructor(_legend, _themeService, _languageService, _logService) {
|
| 22 |
+
this._legend = _legend;
|
| 23 |
+
this._themeService = _themeService;
|
| 24 |
+
this._languageService = _languageService;
|
| 25 |
+
this._logService = _logService;
|
| 26 |
+
this._hasWarnedOverlappingTokens = false;
|
| 27 |
+
this._hasWarnedInvalidLengthTokens = false;
|
| 28 |
+
this._hasWarnedInvalidEditStart = false;
|
| 29 |
+
this._hashTable = new HashTable();
|
| 30 |
+
}
|
| 31 |
+
getMetadata(tokenTypeIndex, tokenModifierSet, languageId) {
|
| 32 |
+
const encodedLanguageId = this._languageService.languageIdCodec.encodeLanguageId(languageId);
|
| 33 |
+
const entry = this._hashTable.get(tokenTypeIndex, tokenModifierSet, encodedLanguageId);
|
| 34 |
+
let metadata;
|
| 35 |
+
if (entry) {
|
| 36 |
+
metadata = entry.metadata;
|
| 37 |
+
if (ENABLE_TRACE && this._logService.getLevel() === LogLevel.Trace) {
|
| 38 |
+
this._logService.trace(`SemanticTokensProviderStyling [CACHED] ${tokenTypeIndex} / ${tokenModifierSet}: foreground ${TokenMetadata.getForeground(metadata)}, fontStyle ${TokenMetadata.getFontStyle(metadata).toString(2)}`);
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
else {
|
| 42 |
+
let tokenType = this._legend.tokenTypes[tokenTypeIndex];
|
| 43 |
+
const tokenModifiers = [];
|
| 44 |
+
if (tokenType) {
|
| 45 |
+
let modifierSet = tokenModifierSet;
|
| 46 |
+
for (let modifierIndex = 0; modifierSet > 0 && modifierIndex < this._legend.tokenModifiers.length; modifierIndex++) {
|
| 47 |
+
if (modifierSet & 1) {
|
| 48 |
+
tokenModifiers.push(this._legend.tokenModifiers[modifierIndex]);
|
| 49 |
+
}
|
| 50 |
+
modifierSet = modifierSet >> 1;
|
| 51 |
+
}
|
| 52 |
+
if (ENABLE_TRACE && modifierSet > 0 && this._logService.getLevel() === LogLevel.Trace) {
|
| 53 |
+
this._logService.trace(`SemanticTokensProviderStyling: unknown token modifier index: ${tokenModifierSet.toString(2)} for legend: ${JSON.stringify(this._legend.tokenModifiers)}`);
|
| 54 |
+
tokenModifiers.push('not-in-legend');
|
| 55 |
+
}
|
| 56 |
+
const tokenStyle = this._themeService.getColorTheme().getTokenStyleMetadata(tokenType, tokenModifiers, languageId);
|
| 57 |
+
if (typeof tokenStyle === 'undefined') {
|
| 58 |
+
metadata = 2147483647 /* SemanticTokensProviderStylingConstants.NO_STYLING */;
|
| 59 |
+
}
|
| 60 |
+
else {
|
| 61 |
+
metadata = 0;
|
| 62 |
+
if (typeof tokenStyle.italic !== 'undefined') {
|
| 63 |
+
const italicBit = (tokenStyle.italic ? 1 /* FontStyle.Italic */ : 0) << 11 /* MetadataConsts.FONT_STYLE_OFFSET */;
|
| 64 |
+
metadata |= italicBit | 1 /* MetadataConsts.SEMANTIC_USE_ITALIC */;
|
| 65 |
+
}
|
| 66 |
+
if (typeof tokenStyle.bold !== 'undefined') {
|
| 67 |
+
const boldBit = (tokenStyle.bold ? 2 /* FontStyle.Bold */ : 0) << 11 /* MetadataConsts.FONT_STYLE_OFFSET */;
|
| 68 |
+
metadata |= boldBit | 2 /* MetadataConsts.SEMANTIC_USE_BOLD */;
|
| 69 |
+
}
|
| 70 |
+
if (typeof tokenStyle.underline !== 'undefined') {
|
| 71 |
+
const underlineBit = (tokenStyle.underline ? 4 /* FontStyle.Underline */ : 0) << 11 /* MetadataConsts.FONT_STYLE_OFFSET */;
|
| 72 |
+
metadata |= underlineBit | 4 /* MetadataConsts.SEMANTIC_USE_UNDERLINE */;
|
| 73 |
+
}
|
| 74 |
+
if (typeof tokenStyle.strikethrough !== 'undefined') {
|
| 75 |
+
const strikethroughBit = (tokenStyle.strikethrough ? 8 /* FontStyle.Strikethrough */ : 0) << 11 /* MetadataConsts.FONT_STYLE_OFFSET */;
|
| 76 |
+
metadata |= strikethroughBit | 8 /* MetadataConsts.SEMANTIC_USE_STRIKETHROUGH */;
|
| 77 |
+
}
|
| 78 |
+
if (tokenStyle.foreground) {
|
| 79 |
+
const foregroundBits = (tokenStyle.foreground) << 15 /* MetadataConsts.FOREGROUND_OFFSET */;
|
| 80 |
+
metadata |= foregroundBits | 16 /* MetadataConsts.SEMANTIC_USE_FOREGROUND */;
|
| 81 |
+
}
|
| 82 |
+
if (metadata === 0) {
|
| 83 |
+
// Nothing!
|
| 84 |
+
metadata = 2147483647 /* SemanticTokensProviderStylingConstants.NO_STYLING */;
|
| 85 |
+
}
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
else {
|
| 89 |
+
if (ENABLE_TRACE && this._logService.getLevel() === LogLevel.Trace) {
|
| 90 |
+
this._logService.trace(`SemanticTokensProviderStyling: unknown token type index: ${tokenTypeIndex} for legend: ${JSON.stringify(this._legend.tokenTypes)}`);
|
| 91 |
+
}
|
| 92 |
+
metadata = 2147483647 /* SemanticTokensProviderStylingConstants.NO_STYLING */;
|
| 93 |
+
tokenType = 'not-in-legend';
|
| 94 |
+
}
|
| 95 |
+
this._hashTable.add(tokenTypeIndex, tokenModifierSet, encodedLanguageId, metadata);
|
| 96 |
+
if (ENABLE_TRACE && this._logService.getLevel() === LogLevel.Trace) {
|
| 97 |
+
this._logService.trace(`SemanticTokensProviderStyling ${tokenTypeIndex} (${tokenType}) / ${tokenModifierSet} (${tokenModifiers.join(' ')}): foreground ${TokenMetadata.getForeground(metadata)}, fontStyle ${TokenMetadata.getFontStyle(metadata).toString(2)}`);
|
| 98 |
+
}
|
| 99 |
+
}
|
| 100 |
+
return metadata;
|
| 101 |
+
}
|
| 102 |
+
warnOverlappingSemanticTokens(lineNumber, startColumn) {
|
| 103 |
+
if (!this._hasWarnedOverlappingTokens) {
|
| 104 |
+
this._hasWarnedOverlappingTokens = true;
|
| 105 |
+
this._logService.warn(`Overlapping semantic tokens detected at lineNumber ${lineNumber}, column ${startColumn}`);
|
| 106 |
+
}
|
| 107 |
+
}
|
| 108 |
+
warnInvalidLengthSemanticTokens(lineNumber, startColumn) {
|
| 109 |
+
if (!this._hasWarnedInvalidLengthTokens) {
|
| 110 |
+
this._hasWarnedInvalidLengthTokens = true;
|
| 111 |
+
this._logService.warn(`Semantic token with invalid length detected at lineNumber ${lineNumber}, column ${startColumn}`);
|
| 112 |
+
}
|
| 113 |
+
}
|
| 114 |
+
warnInvalidEditStart(previousResultId, resultId, editIndex, editStart, maxExpectedStart) {
|
| 115 |
+
if (!this._hasWarnedInvalidEditStart) {
|
| 116 |
+
this._hasWarnedInvalidEditStart = true;
|
| 117 |
+
this._logService.warn(`Invalid semantic tokens edit detected (previousResultId: ${previousResultId}, resultId: ${resultId}) at edit #${editIndex}: The provided start offset ${editStart} is outside the previous data (length ${maxExpectedStart}).`);
|
| 118 |
+
}
|
| 119 |
+
}
|
| 120 |
+
};
|
| 121 |
+
SemanticTokensProviderStyling = __decorate([
|
| 122 |
+
__param(1, IThemeService),
|
| 123 |
+
__param(2, ILanguageService),
|
| 124 |
+
__param(3, ILogService)
|
| 125 |
+
], SemanticTokensProviderStyling);
|
| 126 |
+
export { SemanticTokensProviderStyling };
|
| 127 |
+
export function toMultilineTokens2(tokens, styling, languageId) {
|
| 128 |
+
const srcData = tokens.data;
|
| 129 |
+
const tokenCount = (tokens.data.length / 5) | 0;
|
| 130 |
+
const tokensPerArea = Math.max(Math.ceil(tokenCount / 1024 /* SemanticColoringConstants.DesiredMaxAreas */), 400 /* SemanticColoringConstants.DesiredTokensPerArea */);
|
| 131 |
+
const result = [];
|
| 132 |
+
let tokenIndex = 0;
|
| 133 |
+
let lastLineNumber = 1;
|
| 134 |
+
let lastStartCharacter = 0;
|
| 135 |
+
while (tokenIndex < tokenCount) {
|
| 136 |
+
const tokenStartIndex = tokenIndex;
|
| 137 |
+
let tokenEndIndex = Math.min(tokenStartIndex + tokensPerArea, tokenCount);
|
| 138 |
+
// Keep tokens on the same line in the same area...
|
| 139 |
+
if (tokenEndIndex < tokenCount) {
|
| 140 |
+
let smallTokenEndIndex = tokenEndIndex;
|
| 141 |
+
while (smallTokenEndIndex - 1 > tokenStartIndex && srcData[5 * smallTokenEndIndex] === 0) {
|
| 142 |
+
smallTokenEndIndex--;
|
| 143 |
+
}
|
| 144 |
+
if (smallTokenEndIndex - 1 === tokenStartIndex) {
|
| 145 |
+
// there are so many tokens on this line that our area would be empty, we must now go right
|
| 146 |
+
let bigTokenEndIndex = tokenEndIndex;
|
| 147 |
+
while (bigTokenEndIndex + 1 < tokenCount && srcData[5 * bigTokenEndIndex] === 0) {
|
| 148 |
+
bigTokenEndIndex++;
|
| 149 |
+
}
|
| 150 |
+
tokenEndIndex = bigTokenEndIndex;
|
| 151 |
+
}
|
| 152 |
+
else {
|
| 153 |
+
tokenEndIndex = smallTokenEndIndex;
|
| 154 |
+
}
|
| 155 |
+
}
|
| 156 |
+
let destData = new Uint32Array((tokenEndIndex - tokenStartIndex) * 4);
|
| 157 |
+
let destOffset = 0;
|
| 158 |
+
let areaLine = 0;
|
| 159 |
+
let prevLineNumber = 0;
|
| 160 |
+
let prevEndCharacter = 0;
|
| 161 |
+
while (tokenIndex < tokenEndIndex) {
|
| 162 |
+
const srcOffset = 5 * tokenIndex;
|
| 163 |
+
const deltaLine = srcData[srcOffset];
|
| 164 |
+
const deltaCharacter = srcData[srcOffset + 1];
|
| 165 |
+
// Casting both `lineNumber`, `startCharacter` and `endCharacter` here to uint32 using `|0`
|
| 166 |
+
// to validate below with the actual values that will be inserted in the Uint32Array result
|
| 167 |
+
const lineNumber = (lastLineNumber + deltaLine) | 0;
|
| 168 |
+
const startCharacter = (deltaLine === 0 ? (lastStartCharacter + deltaCharacter) | 0 : deltaCharacter);
|
| 169 |
+
const length = srcData[srcOffset + 2];
|
| 170 |
+
const endCharacter = (startCharacter + length) | 0;
|
| 171 |
+
const tokenTypeIndex = srcData[srcOffset + 3];
|
| 172 |
+
const tokenModifierSet = srcData[srcOffset + 4];
|
| 173 |
+
if (endCharacter <= startCharacter) {
|
| 174 |
+
// this token is invalid (most likely a negative length casted to uint32)
|
| 175 |
+
styling.warnInvalidLengthSemanticTokens(lineNumber, startCharacter + 1);
|
| 176 |
+
}
|
| 177 |
+
else if (prevLineNumber === lineNumber && prevEndCharacter > startCharacter) {
|
| 178 |
+
// this token overlaps with the previous token
|
| 179 |
+
styling.warnOverlappingSemanticTokens(lineNumber, startCharacter + 1);
|
| 180 |
+
}
|
| 181 |
+
else {
|
| 182 |
+
const metadata = styling.getMetadata(tokenTypeIndex, tokenModifierSet, languageId);
|
| 183 |
+
if (metadata !== 2147483647 /* SemanticTokensProviderStylingConstants.NO_STYLING */) {
|
| 184 |
+
if (areaLine === 0) {
|
| 185 |
+
areaLine = lineNumber;
|
| 186 |
+
}
|
| 187 |
+
destData[destOffset] = lineNumber - areaLine;
|
| 188 |
+
destData[destOffset + 1] = startCharacter;
|
| 189 |
+
destData[destOffset + 2] = endCharacter;
|
| 190 |
+
destData[destOffset + 3] = metadata;
|
| 191 |
+
destOffset += 4;
|
| 192 |
+
prevLineNumber = lineNumber;
|
| 193 |
+
prevEndCharacter = endCharacter;
|
| 194 |
+
}
|
| 195 |
+
}
|
| 196 |
+
lastLineNumber = lineNumber;
|
| 197 |
+
lastStartCharacter = startCharacter;
|
| 198 |
+
tokenIndex++;
|
| 199 |
+
}
|
| 200 |
+
if (destOffset !== destData.length) {
|
| 201 |
+
destData = destData.subarray(0, destOffset);
|
| 202 |
+
}
|
| 203 |
+
const tokens = SparseMultilineTokens.create(areaLine, destData);
|
| 204 |
+
result.push(tokens);
|
| 205 |
+
}
|
| 206 |
+
return result;
|
| 207 |
+
}
|
| 208 |
+
class HashTableEntry {
|
| 209 |
+
constructor(tokenTypeIndex, tokenModifierSet, languageId, metadata) {
|
| 210 |
+
this.tokenTypeIndex = tokenTypeIndex;
|
| 211 |
+
this.tokenModifierSet = tokenModifierSet;
|
| 212 |
+
this.languageId = languageId;
|
| 213 |
+
this.metadata = metadata;
|
| 214 |
+
this.next = null;
|
| 215 |
+
}
|
| 216 |
+
}
|
| 217 |
+
class HashTable {
|
| 218 |
+
static { this._SIZES = [3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143]; }
|
| 219 |
+
constructor() {
|
| 220 |
+
this._elementsCount = 0;
|
| 221 |
+
this._currentLengthIndex = 0;
|
| 222 |
+
this._currentLength = HashTable._SIZES[this._currentLengthIndex];
|
| 223 |
+
this._growCount = Math.round(this._currentLengthIndex + 1 < HashTable._SIZES.length ? 2 / 3 * this._currentLength : 0);
|
| 224 |
+
this._elements = [];
|
| 225 |
+
HashTable._nullOutEntries(this._elements, this._currentLength);
|
| 226 |
+
}
|
| 227 |
+
static _nullOutEntries(entries, length) {
|
| 228 |
+
for (let i = 0; i < length; i++) {
|
| 229 |
+
entries[i] = null;
|
| 230 |
+
}
|
| 231 |
+
}
|
| 232 |
+
_hash2(n1, n2) {
|
| 233 |
+
return (((n1 << 5) - n1) + n2) | 0; // n1 * 31 + n2, keep as int32
|
| 234 |
+
}
|
| 235 |
+
_hashFunc(tokenTypeIndex, tokenModifierSet, languageId) {
|
| 236 |
+
return this._hash2(this._hash2(tokenTypeIndex, tokenModifierSet), languageId) % this._currentLength;
|
| 237 |
+
}
|
| 238 |
+
get(tokenTypeIndex, tokenModifierSet, languageId) {
|
| 239 |
+
const hash = this._hashFunc(tokenTypeIndex, tokenModifierSet, languageId);
|
| 240 |
+
let p = this._elements[hash];
|
| 241 |
+
while (p) {
|
| 242 |
+
if (p.tokenTypeIndex === tokenTypeIndex && p.tokenModifierSet === tokenModifierSet && p.languageId === languageId) {
|
| 243 |
+
return p;
|
| 244 |
+
}
|
| 245 |
+
p = p.next;
|
| 246 |
+
}
|
| 247 |
+
return null;
|
| 248 |
+
}
|
| 249 |
+
add(tokenTypeIndex, tokenModifierSet, languageId, metadata) {
|
| 250 |
+
this._elementsCount++;
|
| 251 |
+
if (this._growCount !== 0 && this._elementsCount >= this._growCount) {
|
| 252 |
+
// expand!
|
| 253 |
+
const oldElements = this._elements;
|
| 254 |
+
this._currentLengthIndex++;
|
| 255 |
+
this._currentLength = HashTable._SIZES[this._currentLengthIndex];
|
| 256 |
+
this._growCount = Math.round(this._currentLengthIndex + 1 < HashTable._SIZES.length ? 2 / 3 * this._currentLength : 0);
|
| 257 |
+
this._elements = [];
|
| 258 |
+
HashTable._nullOutEntries(this._elements, this._currentLength);
|
| 259 |
+
for (const first of oldElements) {
|
| 260 |
+
let p = first;
|
| 261 |
+
while (p) {
|
| 262 |
+
const oldNext = p.next;
|
| 263 |
+
p.next = null;
|
| 264 |
+
this._add(p);
|
| 265 |
+
p = oldNext;
|
| 266 |
+
}
|
| 267 |
+
}
|
| 268 |
+
}
|
| 269 |
+
this._add(new HashTableEntry(tokenTypeIndex, tokenModifierSet, languageId, metadata));
|
| 270 |
+
}
|
| 271 |
+
_add(element) {
|
| 272 |
+
const hash = this._hashFunc(element.tokenTypeIndex, element.tokenModifierSet, element.languageId);
|
| 273 |
+
element.next = this._elements[hash];
|
| 274 |
+
this._elements[hash] = element;
|
| 275 |
+
}
|
| 276 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/semanticTokensStyling.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
|
| 6 |
+
export const ISemanticTokensStylingService = createDecorator('semanticTokensStylingService');
|
node_modules/monaco-editor/esm/vs/editor/common/services/semanticTokensStylingService.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
| 6 |
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
| 7 |
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
| 8 |
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
| 9 |
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
| 10 |
+
};
|
| 11 |
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
| 12 |
+
return function (target, key) { decorator(target, key, paramIndex); }
|
| 13 |
+
};
|
| 14 |
+
import { Disposable } from '../../../base/common/lifecycle.js';
|
| 15 |
+
import { ILanguageService } from '../languages/language.js';
|
| 16 |
+
import { IThemeService } from '../../../platform/theme/common/themeService.js';
|
| 17 |
+
import { ILogService } from '../../../platform/log/common/log.js';
|
| 18 |
+
import { SemanticTokensProviderStyling } from './semanticTokensProviderStyling.js';
|
| 19 |
+
import { ISemanticTokensStylingService } from './semanticTokensStyling.js';
|
| 20 |
+
import { registerSingleton } from '../../../platform/instantiation/common/extensions.js';
|
| 21 |
+
let SemanticTokensStylingService = class SemanticTokensStylingService extends Disposable {
|
| 22 |
+
constructor(_themeService, _logService, _languageService) {
|
| 23 |
+
super();
|
| 24 |
+
this._themeService = _themeService;
|
| 25 |
+
this._logService = _logService;
|
| 26 |
+
this._languageService = _languageService;
|
| 27 |
+
this._caches = new WeakMap();
|
| 28 |
+
this._register(this._themeService.onDidColorThemeChange(() => {
|
| 29 |
+
this._caches = new WeakMap();
|
| 30 |
+
}));
|
| 31 |
+
}
|
| 32 |
+
getStyling(provider) {
|
| 33 |
+
if (!this._caches.has(provider)) {
|
| 34 |
+
this._caches.set(provider, new SemanticTokensProviderStyling(provider.getLegend(), this._themeService, this._languageService, this._logService));
|
| 35 |
+
}
|
| 36 |
+
return this._caches.get(provider);
|
| 37 |
+
}
|
| 38 |
+
};
|
| 39 |
+
SemanticTokensStylingService = __decorate([
|
| 40 |
+
__param(0, IThemeService),
|
| 41 |
+
__param(1, ILogService),
|
| 42 |
+
__param(2, ILanguageService)
|
| 43 |
+
], SemanticTokensStylingService);
|
| 44 |
+
export { SemanticTokensStylingService };
|
| 45 |
+
registerSingleton(ISemanticTokensStylingService, SemanticTokensStylingService, 1 /* InstantiationType.Delayed */);
|
node_modules/monaco-editor/esm/vs/editor/common/services/textModelSync/textModelSync.impl.js
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
import { IntervalTimer } from '../../../../base/common/async.js';
|
| 6 |
+
import { Disposable, DisposableStore, dispose, toDisposable } from '../../../../base/common/lifecycle.js';
|
| 7 |
+
import { URI } from '../../../../base/common/uri.js';
|
| 8 |
+
import { Position } from '../../core/position.js';
|
| 9 |
+
import { Range } from '../../core/range.js';
|
| 10 |
+
import { ensureValidWordDefinition, getWordAtText } from '../../core/wordHelper.js';
|
| 11 |
+
import { MirrorTextModel as BaseMirrorModel } from '../../model/mirrorTextModel.js';
|
| 12 |
+
/**
|
| 13 |
+
* Stop syncing a model to the worker if it was not needed for 1 min.
|
| 14 |
+
*/
|
| 15 |
+
export const STOP_SYNC_MODEL_DELTA_TIME_MS = 60 * 1000;
|
| 16 |
+
export class WorkerTextModelSyncClient extends Disposable {
|
| 17 |
+
constructor(proxy, modelService, keepIdleModels = false) {
|
| 18 |
+
super();
|
| 19 |
+
this._syncedModels = Object.create(null);
|
| 20 |
+
this._syncedModelsLastUsedTime = Object.create(null);
|
| 21 |
+
this._proxy = proxy;
|
| 22 |
+
this._modelService = modelService;
|
| 23 |
+
if (!keepIdleModels) {
|
| 24 |
+
const timer = new IntervalTimer();
|
| 25 |
+
timer.cancelAndSet(() => this._checkStopModelSync(), Math.round(STOP_SYNC_MODEL_DELTA_TIME_MS / 2));
|
| 26 |
+
this._register(timer);
|
| 27 |
+
}
|
| 28 |
+
}
|
| 29 |
+
dispose() {
|
| 30 |
+
for (const modelUrl in this._syncedModels) {
|
| 31 |
+
dispose(this._syncedModels[modelUrl]);
|
| 32 |
+
}
|
| 33 |
+
this._syncedModels = Object.create(null);
|
| 34 |
+
this._syncedModelsLastUsedTime = Object.create(null);
|
| 35 |
+
super.dispose();
|
| 36 |
+
}
|
| 37 |
+
ensureSyncedResources(resources, forceLargeModels = false) {
|
| 38 |
+
for (const resource of resources) {
|
| 39 |
+
const resourceStr = resource.toString();
|
| 40 |
+
if (!this._syncedModels[resourceStr]) {
|
| 41 |
+
this._beginModelSync(resource, forceLargeModels);
|
| 42 |
+
}
|
| 43 |
+
if (this._syncedModels[resourceStr]) {
|
| 44 |
+
this._syncedModelsLastUsedTime[resourceStr] = (new Date()).getTime();
|
| 45 |
+
}
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
_checkStopModelSync() {
|
| 49 |
+
const currentTime = (new Date()).getTime();
|
| 50 |
+
const toRemove = [];
|
| 51 |
+
for (const modelUrl in this._syncedModelsLastUsedTime) {
|
| 52 |
+
const elapsedTime = currentTime - this._syncedModelsLastUsedTime[modelUrl];
|
| 53 |
+
if (elapsedTime > STOP_SYNC_MODEL_DELTA_TIME_MS) {
|
| 54 |
+
toRemove.push(modelUrl);
|
| 55 |
+
}
|
| 56 |
+
}
|
| 57 |
+
for (const e of toRemove) {
|
| 58 |
+
this._stopModelSync(e);
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
_beginModelSync(resource, forceLargeModels) {
|
| 62 |
+
const model = this._modelService.getModel(resource);
|
| 63 |
+
if (!model) {
|
| 64 |
+
return;
|
| 65 |
+
}
|
| 66 |
+
if (!forceLargeModels && model.isTooLargeForSyncing()) {
|
| 67 |
+
return;
|
| 68 |
+
}
|
| 69 |
+
const modelUrl = resource.toString();
|
| 70 |
+
this._proxy.$acceptNewModel({
|
| 71 |
+
url: model.uri.toString(),
|
| 72 |
+
lines: model.getLinesContent(),
|
| 73 |
+
EOL: model.getEOL(),
|
| 74 |
+
versionId: model.getVersionId()
|
| 75 |
+
});
|
| 76 |
+
const toDispose = new DisposableStore();
|
| 77 |
+
toDispose.add(model.onDidChangeContent((e) => {
|
| 78 |
+
this._proxy.$acceptModelChanged(modelUrl.toString(), e);
|
| 79 |
+
}));
|
| 80 |
+
toDispose.add(model.onWillDispose(() => {
|
| 81 |
+
this._stopModelSync(modelUrl);
|
| 82 |
+
}));
|
| 83 |
+
toDispose.add(toDisposable(() => {
|
| 84 |
+
this._proxy.$acceptRemovedModel(modelUrl);
|
| 85 |
+
}));
|
| 86 |
+
this._syncedModels[modelUrl] = toDispose;
|
| 87 |
+
}
|
| 88 |
+
_stopModelSync(modelUrl) {
|
| 89 |
+
const toDispose = this._syncedModels[modelUrl];
|
| 90 |
+
delete this._syncedModels[modelUrl];
|
| 91 |
+
delete this._syncedModelsLastUsedTime[modelUrl];
|
| 92 |
+
dispose(toDispose);
|
| 93 |
+
}
|
| 94 |
+
}
|
| 95 |
+
export class WorkerTextModelSyncServer {
|
| 96 |
+
constructor() {
|
| 97 |
+
this._models = Object.create(null);
|
| 98 |
+
}
|
| 99 |
+
getModel(uri) {
|
| 100 |
+
return this._models[uri];
|
| 101 |
+
}
|
| 102 |
+
getModels() {
|
| 103 |
+
const all = [];
|
| 104 |
+
Object.keys(this._models).forEach((key) => all.push(this._models[key]));
|
| 105 |
+
return all;
|
| 106 |
+
}
|
| 107 |
+
$acceptNewModel(data) {
|
| 108 |
+
this._models[data.url] = new MirrorModel(URI.parse(data.url), data.lines, data.EOL, data.versionId);
|
| 109 |
+
}
|
| 110 |
+
$acceptModelChanged(uri, e) {
|
| 111 |
+
if (!this._models[uri]) {
|
| 112 |
+
return;
|
| 113 |
+
}
|
| 114 |
+
const model = this._models[uri];
|
| 115 |
+
model.onEvents(e);
|
| 116 |
+
}
|
| 117 |
+
$acceptRemovedModel(uri) {
|
| 118 |
+
if (!this._models[uri]) {
|
| 119 |
+
return;
|
| 120 |
+
}
|
| 121 |
+
delete this._models[uri];
|
| 122 |
+
}
|
| 123 |
+
}
|
| 124 |
+
export class MirrorModel extends BaseMirrorModel {
|
| 125 |
+
get uri() {
|
| 126 |
+
return this._uri;
|
| 127 |
+
}
|
| 128 |
+
get eol() {
|
| 129 |
+
return this._eol;
|
| 130 |
+
}
|
| 131 |
+
getValue() {
|
| 132 |
+
return this.getText();
|
| 133 |
+
}
|
| 134 |
+
findMatches(regex) {
|
| 135 |
+
const matches = [];
|
| 136 |
+
for (let i = 0; i < this._lines.length; i++) {
|
| 137 |
+
const line = this._lines[i];
|
| 138 |
+
const offsetToAdd = this.offsetAt(new Position(i + 1, 1));
|
| 139 |
+
const iteratorOverMatches = line.matchAll(regex);
|
| 140 |
+
for (const match of iteratorOverMatches) {
|
| 141 |
+
if (match.index || match.index === 0) {
|
| 142 |
+
match.index = match.index + offsetToAdd;
|
| 143 |
+
}
|
| 144 |
+
matches.push(match);
|
| 145 |
+
}
|
| 146 |
+
}
|
| 147 |
+
return matches;
|
| 148 |
+
}
|
| 149 |
+
getLinesContent() {
|
| 150 |
+
return this._lines.slice(0);
|
| 151 |
+
}
|
| 152 |
+
getLineCount() {
|
| 153 |
+
return this._lines.length;
|
| 154 |
+
}
|
| 155 |
+
getLineContent(lineNumber) {
|
| 156 |
+
return this._lines[lineNumber - 1];
|
| 157 |
+
}
|
| 158 |
+
getWordAtPosition(position, wordDefinition) {
|
| 159 |
+
const wordAtText = getWordAtText(position.column, ensureValidWordDefinition(wordDefinition), this._lines[position.lineNumber - 1], 0);
|
| 160 |
+
if (wordAtText) {
|
| 161 |
+
return new Range(position.lineNumber, wordAtText.startColumn, position.lineNumber, wordAtText.endColumn);
|
| 162 |
+
}
|
| 163 |
+
return null;
|
| 164 |
+
}
|
| 165 |
+
words(wordDefinition) {
|
| 166 |
+
const lines = this._lines;
|
| 167 |
+
const wordenize = this._wordenize.bind(this);
|
| 168 |
+
let lineNumber = 0;
|
| 169 |
+
let lineText = '';
|
| 170 |
+
let wordRangesIdx = 0;
|
| 171 |
+
let wordRanges = [];
|
| 172 |
+
return {
|
| 173 |
+
*[Symbol.iterator]() {
|
| 174 |
+
while (true) {
|
| 175 |
+
if (wordRangesIdx < wordRanges.length) {
|
| 176 |
+
const value = lineText.substring(wordRanges[wordRangesIdx].start, wordRanges[wordRangesIdx].end);
|
| 177 |
+
wordRangesIdx += 1;
|
| 178 |
+
yield value;
|
| 179 |
+
}
|
| 180 |
+
else {
|
| 181 |
+
if (lineNumber < lines.length) {
|
| 182 |
+
lineText = lines[lineNumber];
|
| 183 |
+
wordRanges = wordenize(lineText, wordDefinition);
|
| 184 |
+
wordRangesIdx = 0;
|
| 185 |
+
lineNumber += 1;
|
| 186 |
+
}
|
| 187 |
+
else {
|
| 188 |
+
break;
|
| 189 |
+
}
|
| 190 |
+
}
|
| 191 |
+
}
|
| 192 |
+
}
|
| 193 |
+
};
|
| 194 |
+
}
|
| 195 |
+
getLineWords(lineNumber, wordDefinition) {
|
| 196 |
+
const content = this._lines[lineNumber - 1];
|
| 197 |
+
const ranges = this._wordenize(content, wordDefinition);
|
| 198 |
+
const words = [];
|
| 199 |
+
for (const range of ranges) {
|
| 200 |
+
words.push({
|
| 201 |
+
word: content.substring(range.start, range.end),
|
| 202 |
+
startColumn: range.start + 1,
|
| 203 |
+
endColumn: range.end + 1
|
| 204 |
+
});
|
| 205 |
+
}
|
| 206 |
+
return words;
|
| 207 |
+
}
|
| 208 |
+
_wordenize(content, wordDefinition) {
|
| 209 |
+
const result = [];
|
| 210 |
+
let match;
|
| 211 |
+
wordDefinition.lastIndex = 0; // reset lastIndex just to be sure
|
| 212 |
+
while (match = wordDefinition.exec(content)) {
|
| 213 |
+
if (match[0].length === 0) {
|
| 214 |
+
// it did match the empty string
|
| 215 |
+
break;
|
| 216 |
+
}
|
| 217 |
+
result.push({ start: match.index, end: match.index + match[0].length });
|
| 218 |
+
}
|
| 219 |
+
return result;
|
| 220 |
+
}
|
| 221 |
+
getValueInRange(range) {
|
| 222 |
+
range = this._validateRange(range);
|
| 223 |
+
if (range.startLineNumber === range.endLineNumber) {
|
| 224 |
+
return this._lines[range.startLineNumber - 1].substring(range.startColumn - 1, range.endColumn - 1);
|
| 225 |
+
}
|
| 226 |
+
const lineEnding = this._eol;
|
| 227 |
+
const startLineIndex = range.startLineNumber - 1;
|
| 228 |
+
const endLineIndex = range.endLineNumber - 1;
|
| 229 |
+
const resultLines = [];
|
| 230 |
+
resultLines.push(this._lines[startLineIndex].substring(range.startColumn - 1));
|
| 231 |
+
for (let i = startLineIndex + 1; i < endLineIndex; i++) {
|
| 232 |
+
resultLines.push(this._lines[i]);
|
| 233 |
+
}
|
| 234 |
+
resultLines.push(this._lines[endLineIndex].substring(0, range.endColumn - 1));
|
| 235 |
+
return resultLines.join(lineEnding);
|
| 236 |
+
}
|
| 237 |
+
offsetAt(position) {
|
| 238 |
+
position = this._validatePosition(position);
|
| 239 |
+
this._ensureLineStarts();
|
| 240 |
+
return this._lineStarts.getPrefixSum(position.lineNumber - 2) + (position.column - 1);
|
| 241 |
+
}
|
| 242 |
+
positionAt(offset) {
|
| 243 |
+
offset = Math.floor(offset);
|
| 244 |
+
offset = Math.max(0, offset);
|
| 245 |
+
this._ensureLineStarts();
|
| 246 |
+
const out = this._lineStarts.getIndexOf(offset);
|
| 247 |
+
const lineLength = this._lines[out.index].length;
|
| 248 |
+
// Ensure we return a valid position
|
| 249 |
+
return {
|
| 250 |
+
lineNumber: 1 + out.index,
|
| 251 |
+
column: 1 + Math.min(out.remainder, lineLength)
|
| 252 |
+
};
|
| 253 |
+
}
|
| 254 |
+
_validateRange(range) {
|
| 255 |
+
const start = this._validatePosition({ lineNumber: range.startLineNumber, column: range.startColumn });
|
| 256 |
+
const end = this._validatePosition({ lineNumber: range.endLineNumber, column: range.endColumn });
|
| 257 |
+
if (start.lineNumber !== range.startLineNumber
|
| 258 |
+
|| start.column !== range.startColumn
|
| 259 |
+
|| end.lineNumber !== range.endLineNumber
|
| 260 |
+
|| end.column !== range.endColumn) {
|
| 261 |
+
return {
|
| 262 |
+
startLineNumber: start.lineNumber,
|
| 263 |
+
startColumn: start.column,
|
| 264 |
+
endLineNumber: end.lineNumber,
|
| 265 |
+
endColumn: end.column
|
| 266 |
+
};
|
| 267 |
+
}
|
| 268 |
+
return range;
|
| 269 |
+
}
|
| 270 |
+
_validatePosition(position) {
|
| 271 |
+
if (!Position.isIPosition(position)) {
|
| 272 |
+
throw new Error('bad position');
|
| 273 |
+
}
|
| 274 |
+
let { lineNumber, column } = position;
|
| 275 |
+
let hasChanged = false;
|
| 276 |
+
if (lineNumber < 1) {
|
| 277 |
+
lineNumber = 1;
|
| 278 |
+
column = 1;
|
| 279 |
+
hasChanged = true;
|
| 280 |
+
}
|
| 281 |
+
else if (lineNumber > this._lines.length) {
|
| 282 |
+
lineNumber = this._lines.length;
|
| 283 |
+
column = this._lines[lineNumber - 1].length + 1;
|
| 284 |
+
hasChanged = true;
|
| 285 |
+
}
|
| 286 |
+
else {
|
| 287 |
+
const maxCharacter = this._lines[lineNumber - 1].length + 1;
|
| 288 |
+
if (column < 1) {
|
| 289 |
+
column = 1;
|
| 290 |
+
hasChanged = true;
|
| 291 |
+
}
|
| 292 |
+
else if (column > maxCharacter) {
|
| 293 |
+
column = maxCharacter;
|
| 294 |
+
hasChanged = true;
|
| 295 |
+
}
|
| 296 |
+
}
|
| 297 |
+
if (!hasChanged) {
|
| 298 |
+
return position;
|
| 299 |
+
}
|
| 300 |
+
else {
|
| 301 |
+
return { lineNumber, column };
|
| 302 |
+
}
|
| 303 |
+
}
|
| 304 |
+
}
|
node_modules/monaco-editor/esm/vs/editor/common/services/textModelSync/textModelSync.protocol.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
export {};
|
node_modules/monaco-editor/esm/vs/editor/common/services/textResourceConfiguration.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
|
| 2 |
+
export const ITextResourceConfigurationService = createDecorator('textResourceConfigurationService');
|
| 3 |
+
export const ITextResourcePropertiesService = createDecorator('textResourcePropertiesService');
|
node_modules/monaco-editor/esm/vs/editor/common/services/treeSitterParserService.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
|
| 2 |
+
export const ITreeSitterParserService = createDecorator('treeSitterParserService');
|
node_modules/monaco-editor/esm/vs/editor/common/services/treeViewsDnd.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*---------------------------------------------------------------------------------------------
|
| 2 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 3 |
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
| 4 |
+
*--------------------------------------------------------------------------------------------*/
|
| 5 |
+
export class TreeViewsDnDService {
|
| 6 |
+
constructor() {
|
| 7 |
+
this._dragOperations = new Map();
|
| 8 |
+
}
|
| 9 |
+
removeDragOperationTransfer(uuid) {
|
| 10 |
+
if ((uuid && this._dragOperations.has(uuid))) {
|
| 11 |
+
const operation = this._dragOperations.get(uuid);
|
| 12 |
+
this._dragOperations.delete(uuid);
|
| 13 |
+
return operation;
|
| 14 |
+
}
|
| 15 |
+
return undefined;
|
| 16 |
+
}
|
| 17 |
+
}
|
| 18 |
+
export class DraggedTreeItemsIdentifier {
|
| 19 |
+
constructor(identifier) {
|
| 20 |
+
this.identifier = identifier;
|
| 21 |
+
}
|
| 22 |
+
}
|