{"version":3,"sources":["out-editor/vs/editor/fake","out-editor/vs/editor/vs/css.js","out-editor/vs/editor/vs/nls.js","out-editor/vs/editor/vs/base/browser/dompurify/dompurify.js","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/fastDomNode.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/iframe.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/list/list.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/list/splice.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/scrollbar/scrollbarState.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/tree/tree.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/arrays.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/assert.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/buffer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/cache.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/codicons.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/collections.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/color.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/decorators.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/diff/diffChange.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/errors.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/functional.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/idGenerator.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/iterator.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/keyCodes.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/keybindings.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/lazy.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/lifecycle.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/linkedList.ts","out-editor/vs/editor/vs/base/common/marked/marked.js","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/mime.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/dnd.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/navigator.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/history.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/numbers.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/platform.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/process.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/path.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/range.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/list/rangeMap.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/stopwatch.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/event.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/browser.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/canIUse.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/event.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/keyboardEvent.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/mouseEvent.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/cancellation.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/async.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/comparers.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/scrollable.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/strings.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/extpath.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/hash.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/diff/diff.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/tree/indexTreeModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/tree/objectTreeModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/tree/compressedObjectTreeModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/map.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/filters.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/fuzzyScorer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/glob.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/iconLabels.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/htmlContent.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/search.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/severity.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/types.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/objects.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/uint.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/uri.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/marshalling.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/network.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/dom.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/formattedTextRenderer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/globalMouseMoveMonitor.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/touch.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/iconLabel/iconLabels.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/list/rowCache.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/widget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/resources.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/markdownRenderer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/labels.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/uuid.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/worker/simpleWorker.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/defaultWorkerFactory.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/parts/quickinput/common/quickInput.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/parts/storage/common/storage.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/aria/aria.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/button/button.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/checkbox/checkbox.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/codicons/codiconStyles.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/contextview/contextview.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/countBadge/countBadge.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/mouseCursor/mouseCursor.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/progressbar/progressbar.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/sash/sash.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/scrollbar/scrollableElement.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/hover/hoverWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/list/listView.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/list/listWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/list/listPaging.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/splitview/splitview.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/table/tableWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/parts/quickinput/browser/quickInputUtils.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/config/elementSizeObserver.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/config/migrateOptions.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/config/tabFocus.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/stableEditorScroll.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/view/renderingContext.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/view/viewUserInputEvents.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/lines/rangeUtil.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/minimap/minimapCharSheet.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/minimap/minimapCharRenderer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/minimap/minimapPreBaked.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/minimap/minimapCharRendererFactory.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/config/editorZoom.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/config/fontInfo.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/characterClassifier.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/cursorColumns.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/eolCounter.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/position.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/range.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/controller/textAreaState.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/widget/diffNavigator.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/editOperation.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/commands/trimTrailingWhitespaceCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/rgba.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/selection.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/controller/textAreaInput.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/commands/replaceCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/commands/surroundSelectionCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/stringBuilder.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/view/viewLayer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/textChange.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/textModelDefaults.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/wordCharacterClassifier.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/wordHelper.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/cursor/cursorAtomicMoveOperations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/diff/diffComputer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/editorAction.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/editorCommon.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/editorBrowser.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languageSelector.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/languageConfiguration.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/linkComputer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/supports.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/supports/characterPair.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/supports/indentRules.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/supports/inplaceReplaceSupport.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/supports/onEnter.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/supports/richEditBrackets.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/supports/electricCharacter.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/supports/tokenization.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languageFeatureRegistry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/length.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/beforeEditPositionMapper.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/nodeReader.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/smallImmutableSet.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/ast.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/concat23Trees.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/parser.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/indentationGuesser.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/intervalTree.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/prefixSumComputer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/mirrorTextModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/textModelPart.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/textModelSearch.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/unicodeTextModelHighlighter.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/utils.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/languagesAssociations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/semanticTokensDto.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/standalone/standaloneEnums.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/textModelBracketPairs.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/textModelEvents.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/textModelGuides.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/guidesTextModelPart.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/tokenizationRegistry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/nullMode.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/tokenizer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/brackets.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/bracketPairsTree.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsImpl.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/fixBrackets.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/editorBaseApi.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/editorSimpleWorker.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/tokens/contiguousMultilineTokens.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/tokens/contiguousMultilineTokensBuilder.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/tokens/lineTokens.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/textToHtmlTokenizer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/textModelTokens.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/tokens/contiguousTokensEditing.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/tokens/contiguousTokensStore.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/tokens/sparseMultilineTokens.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/tokens/sparseTokensStore.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewLayout/lineDecorations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewLayout/linesLayout.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewLayout/viewLineRenderer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewLayout/viewLinesViewportData.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/minimapTokensColorTracker.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/modelLineProjectionData.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/overviewZoneManager.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/viewContext.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/viewEventHandler.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/view/dynamicViewOverlay.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/view/viewPart.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/decorations/decorations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/linesDecorations/linesDecorations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/margin/margin.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/marginDecorations/marginDecorations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/viewZones/viewZones.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/viewEvents.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/viewModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/modelLineProjection.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/viewModelEventDispatcher.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewLayout/viewLayout.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/caretOperations/browser/moveCaretCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codeAction/browser/types.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/colorPicker/browser/colorPickerModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/comment/browser/blockCommentCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/dnd/browser/dragAndDropCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/find/browser/replaceAllCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/find/browser/replacePattern.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/folding/browser/foldingRanges.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/folding/browser/foldingModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/folding/browser/hiddenRangeModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/folding/browser/indentRangeProvider.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/folding/browser/syntaxRangeProvider.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/folding/browser/intializingRangeProvider.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/format/browser/formattingEdit.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoSymbol/browser/link/clickLinkGesture.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/hover/browser/hoverOperation.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/hover/browser/hoverTypes.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inPlaceReplace/browser/inPlaceReplaceCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/indentation/browser/indentUtils.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlayHints/browser/inlayHints.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlineCompletions/browser/consts.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlineCompletions/browser/ghostText.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionToGhostText.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlineCompletions/browser/utils.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/linesOperations/browser/copyLinesCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/linesOperations/browser/sortLinesCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/smartSelect/browser/bracketSelections.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/smartSelect/browser/wordSelections.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/snippet/browser/snippetParser.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/completionModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/resizable.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/suggestCommitCharacters.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/suggestOvertypingCapturer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/wordDistance.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/common/monarch/monarchCommon.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/common/monarch/monarchCompile.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/common/monarch/monarchLexer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/colorizer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/findinput/findInputCheckboxes.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/iconLabel/iconLabelHover.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/iconLabel/iconLabel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/tree/abstractTree.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/tree/dataTree.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/tree/objectTree.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/tree/asyncDataTree.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/actions.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/actionbar/actionViewItems.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/actionbar/actionbar.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/dropdown/dropdown.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/inputbox/inputBox.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/findinput/findInput.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/findinput/replaceInput.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/menu/menu.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/parts/quickinput/browser/quickInputBox.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/errorMessage.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/common/keybindingLabels.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/browser/ui/keybindingLabel/keybindingLabel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/parts/quickinput/browser/quickInputList.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/base/parts/quickinput/browser/quickInput.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/widget/inlineDiffMargin.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/config/editorOptions.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/config/domFontInfo.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/config/charWidthReader.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/config/fontMeasurements.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/view/domLineBreaksComputer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/view/viewOverlays.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/viewModelDecorations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/editStack.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/standaloneStrings.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoSymbol/browser/referencesModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/editor/common/editor.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/extensions/common/extensions.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/files/common/files.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/history/browser/historyWidgetKeybindingHint.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/instantiation/common/descriptors.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/instantiation/common/extensions.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/instantiation/common/graph.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/instantiation/common/instantiation.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/services/bulkEditService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/services/codeEditorService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/editorWorker.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/language.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/markerDecorations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/model.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/resolverService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/textResourceConfiguration.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/common/standaloneTheme.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/clipboard/common/clipboardService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/commands/common/commands.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/getSemanticTokens.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codelens/browser/codelens.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/colorPicker/browser/color.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/links/browser/getLinks.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/configuration/common/configuration.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/languageConfigurationRegistry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/commands/shiftCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/comment/browser/lineCommentCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/linesOperations/browser/moveLinesCommand.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/contextkey/common/contextkey.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/editorContextKeys.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/parameterHints/browser/provideSignatureHelp.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/parameterHints/browser/parameterHintsModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/suggestAlternatives.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/wordContextKey.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/accessibility/common/accessibility.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/config/editorConfiguration.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/accessibility/browser/accessibilityService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/contextkey/browser/contextKeyService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/contextkey/common/contextkeys.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/contextview/browser/contextView.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/dialogs/common/dialogs.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/instantiation/common/serviceCollection.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/instantiation/common/instantiationService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/keybinding/common/abstractKeybindingService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/keybinding/common/baseResolvedKeybinding.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/keybinding/common/keybinding.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/keybinding/common/keybindingResolver.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/keybinding/common/resolvedKeybindingItem.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/label/common/label.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/layout/browser/layoutService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/standaloneLayoutService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/contextview/browser/contextViewService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/log/common/log.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/services/editorWorkerService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/services/webWorker.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/languageFeatureDebounce.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/documentSymbols/browser/outlineModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/documentSymbols/browser/documentSymbols.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/clipboard/browser/clipboardService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/markers/common/markers.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoError/browser/markerNavigationService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/markers/common/markerService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/notification/common/notification.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/opener/common/opener.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/services/openerService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/progress/common/progress.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/quickinput/browser/pickerQuickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/quickinput/common/quickInput.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/registry/common/platform.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/configuration/common/configurationRegistry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/config/editorConfigurationSchema.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/languages/modesRegistry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/getIconClasses.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/languagesRegistry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/languageService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/markdownRenderer/browser/markdownRenderer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/hover/browser/marginHover.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/suggestWidgetDetails.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/configuration/common/configurationModels.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/keybinding/common/keybindingsRegistry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/history/browser/contextScopedHistoryWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/quickinput/common/quickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/quickinput/browser/helpQuickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/quickinput/browser/quickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/storage/common/storage.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codelens/browser/codeLensCache.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/suggestMemory.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/telemetry/common/telemetry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/quickinput/browser/commandsQuickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/quickAccess/browser/commandsQuickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/theme/common/colorRegistry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/editorDom.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/theme/common/styler.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/contextview/browser/contextMenuHandler.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/theme/common/theme.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/lines/viewLine.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/controller/mouseTarget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/controller/mouseHandler.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/controller/pointerHandler.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/lines/viewLines.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/theme/common/themeService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/services/abstractCodeEditorService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/minimap/minimap.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/selections/selections.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/core/editorColorRegistry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/controller/textAreaHandler.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/rulers/rulers.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/bracketPairsTextModelPart/colorizedBracketPairsDecorationProvider.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/markerDecorationsService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/semanticTokensProviderStyling.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codeAction/browser/lightBulbWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/colorPicker/browser/colorPickerWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoSymbol/browser/peek/referencesTree.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlineCompletions/browser/ghostTextWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/quickAccess/browser/editorNavigationQuickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/quickAccess/browser/gotoLineQuickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/quickAccess/browser/gotoSymbolQuickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/rename/browser/renameInputField.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/symbolIcons/browser/symbolIcons.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/standaloneCodeEditorService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/common/themes.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/actions/common/actions.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/editorExtensions.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/services/markerDecorations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/anchorSelect/browser/anchorSelect.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/caretOperations/browser/caretOperations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/clipboard/browser/clipboard.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/comment/browser/comment.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/contextmenu/browser/contextmenu.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/cursorUndo/browser/cursorUndo.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/editorState/browser/keybindingCancellation.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/editorState/browser/editorState.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codeAction/browser/codeAction.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codeAction/browser/codeActionMenu.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codeAction/browser/codeActionModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/fontZoom/browser/fontZoom.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/format/browser/format.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/format/browser/formatActions.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoSymbol/browser/goToSymbol.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoSymbol/browser/symbolNavigation.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/hover/browser/getHover.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/message/browser/messageController.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codeAction/browser/codeActionUi.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codeAction/browser/codeActionCommands.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codeAction/browser/codeActionContributions.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/rename/browser/rename.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/smartSelect/browser/smartSelect.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/suggest.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/toggleTabFocusMode/browser/toggleTabFocusMode.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/tokenization/browser/tokenization.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/unusualLineTerminators/browser/unusualLineTerminators.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/inspectTokens/inspectTokens.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/actions/browser/menuEntryActionViewItem.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/suggestWidgetStatus.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/actions/common/menuService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/contextview/browser/contextMenuService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/list/browser/listService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/opener/browser/link.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/quickinput/browser/quickInput.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/severityIcon/common/severityIcon.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/theme/common/iconRegistry.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/widget/diffReview.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/parameterHints/browser/parameterHints.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/suggestWidgetRenderer.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/unicodeHighlighter/browser/bannerController.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/theme/browser/iconsStyleSheet.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/standaloneThemeService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/undoRedo/common/undoRedo.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/model/textModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/cursor/cursorCommon.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/cursor/cursorColumnSelection.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/cursor/cursorMoveOperations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/cursor/cursorDeleteOperations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/cursor/cursorTypeOperations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/cursor/cursorWordOperations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/cursor/cursorMoveCommands.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/controller/coreCommands.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/view/viewController.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/view/view.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/cursor/oneCursor.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/cursor/cursorCollection.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/cursor/cursor.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/services/modelService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/viewModelLines.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/common/viewModel/viewModelImpl.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/widget/codeEditorWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/widget/diffEditorWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/bracketMatching/browser/bracketMatching.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/caretOperations/browser/transpose.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codelens/browser/codelensWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/codelens/browser/codelensController.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/colorPicker/browser/colorDetector.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/dnd/browser/dnd.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/find/browser/findDecorations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/find/browser/findModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/find/browser/findOptionsWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/find/browser/findState.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/find/browser/findWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/find/browser/findController.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/folding/browser/foldingDecorations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/folding/browser/folding.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/hover/browser/colorHoverParticipant.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inPlaceReplace/browser/inPlaceReplace.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/indentation/browser/indentation.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/lineSelection/browser/lineSelection.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/linesOperations/browser/linesOperations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/linkedEditing/browser/linkedEditing.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/links/browser/links.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/multicursor/browser/multicursor.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/suggestWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/viewportSemanticTokens/browser/viewportSemanticTokens.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/wordHighlighter/browser/wordHighlighter.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/wordOperations/browser/wordOperations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/wordPartOperations/browser/wordPartOperations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/peekView/browser/peekView.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoError/browser/gotoErrorWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoError/browser/gotoError.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoSymbol/browser/peek/referencesWidget.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoSymbol/browser/peek/referencesController.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoSymbol/browser/goToCommands.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/gotoSymbol/browser/link/goToDefinitionAtPosition.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/hover/browser/markerHoverParticipant.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlayHints/browser/inlayHintsLocations.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlayHints/browser/inlayHintsController.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlayHints/browser/inlayHintsHover.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/undoRedo/common/undoRedoService.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/workspace/common/workspace.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/workspace/common/workspaceTrust.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/standaloneServices.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/standaloneCodeEditor.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/standaloneEditor.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/standalone/browser/standaloneLanguages.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/editor.api.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/platform/workspaces/common/workspaces.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/snippet/browser/snippetVariables.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/snippet/browser/snippetSession.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/snippet/browser/snippetController2.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/suggestModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/suggest/browser/suggestController.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlineCompletions/browser/suggestWidgetInlineCompletionProvider.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlineCompletions/browser/suggestWidgetPreviewModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlineCompletions/browser/ghostTextModel.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlineCompletions/browser/ghostTextController.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsHoverParticipant.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/hover/browser/contentHover.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/hover/browser/hover.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/contrib/colorPicker/browser/colorContributions.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/editor.all.ts","out-editor/vs/editor/file:/home/runner/work/monaco-editor/monaco-editor/vscode/out-editor-src/vs/editor/editor.main.ts"],"sourcesContent":["}).call(this);","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n/*---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n * Please make sure to make edits in the .ts file at https://github.com/microsoft/vscode-loader/\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nvar CSSLoaderPlugin;\n(function (CSSLoaderPlugin) {\n /**\n * Known issue:\n * - In IE there is no way to know if the CSS file loaded successfully or not.\n */\n var BrowserCSSLoader = /** @class */ (function () {\n function BrowserCSSLoader() {\n this._pendingLoads = 0;\n }\n BrowserCSSLoader.prototype.attachListeners = function (name, linkNode, callback, errorback) {\n var unbind = function () {\n linkNode.removeEventListener('load', loadEventListener);\n linkNode.removeEventListener('error', errorEventListener);\n };\n var loadEventListener = function (e) {\n unbind();\n callback();\n };\n var errorEventListener = function (e) {\n unbind();\n errorback(e);\n };\n linkNode.addEventListener('load', loadEventListener);\n linkNode.addEventListener('error', errorEventListener);\n };\n BrowserCSSLoader.prototype._onLoad = function (name, callback) {\n this._pendingLoads--;\n callback();\n };\n BrowserCSSLoader.prototype._onLoadError = function (name, errorback, err) {\n this._pendingLoads--;\n errorback(err);\n };\n BrowserCSSLoader.prototype._insertLinkNode = function (linkNode) {\n this._pendingLoads++;\n var head = document.head || document.getElementsByTagName('head')[0];\n head.appendChild(linkNode);\n };\n BrowserCSSLoader.prototype.createLinkTag = function (name, cssUrl, externalCallback, externalErrorback) {\n var _this = this;\n var linkNode = document.createElement('link');\n linkNode.setAttribute('rel', 'stylesheet');\n linkNode.setAttribute('type', 'text/css');\n linkNode.setAttribute('data-name', name);\n var callback = function () { return _this._onLoad(name, externalCallback); };\n var errorback = function (err) { return _this._onLoadError(name, externalErrorback, err); };\n this.attachListeners(name, linkNode, callback, errorback);\n linkNode.setAttribute('href', cssUrl);\n return linkNode;\n };\n BrowserCSSLoader.prototype._linkTagExists = function (name, cssUrl) {\n var i, len, nameAttr, hrefAttr, links = document.getElementsByTagName('link');\n for (i = 0, len = links.length; i < len; i++) {\n nameAttr = links[i].getAttribute('data-name');\n hrefAttr = links[i].getAttribute('href');\n if (nameAttr === name || hrefAttr === cssUrl) {\n return true;\n }\n }\n return false;\n };\n BrowserCSSLoader.prototype.load = function (name, cssUrl, externalCallback, externalErrorback) {\n if (this._linkTagExists(name, cssUrl)) {\n externalCallback();\n return;\n }\n var linkNode = this.createLinkTag(name, cssUrl, externalCallback, externalErrorback);\n this._insertLinkNode(linkNode);\n };\n return BrowserCSSLoader;\n }());\n // ------------------------------ Finally, the plugin\n var CSSPlugin = /** @class */ (function () {\n function CSSPlugin() {\n this._cssLoader = new BrowserCSSLoader();\n }\n CSSPlugin.prototype.load = function (name, req, load, config) {\n config = config || {};\n var cssConfig = config['vs/css'] || {};\n if (cssConfig.disabled) {\n // the plugin is asked to not create any style sheets\n load({});\n return;\n }\n var cssUrl = req.toUrl(name + '.css');\n this._cssLoader.load(name, cssUrl, function (contents) {\n load({});\n }, function (err) {\n if (typeof load.error === 'function') {\n load.error('Could not find ' + cssUrl + ' or it was empty');\n }\n });\n };\n return CSSPlugin;\n }());\n CSSLoaderPlugin.CSSPlugin = CSSPlugin;\n define('vs/css', new CSSPlugin());\n})(CSSLoaderPlugin || (CSSLoaderPlugin = {}));\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n/*---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n * Please make sure to make edits in the .ts file at https://github.com/microsoft/vscode-loader/\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nvar __spreadArrays = (this && this.__spreadArrays) || function () {\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n r[k] = a[j];\n return r;\n};\nvar NLSLoaderPlugin;\n(function (NLSLoaderPlugin) {\n var Environment = /** @class */ (function () {\n function Environment() {\n this._detected = false;\n this._isPseudo = false;\n }\n Object.defineProperty(Environment.prototype, \"isPseudo\", {\n get: function () {\n this._detect();\n return this._isPseudo;\n },\n enumerable: false,\n configurable: true\n });\n Environment.prototype._detect = function () {\n if (this._detected) {\n return;\n }\n this._detected = true;\n this._isPseudo = (typeof document !== 'undefined' && document.location && document.location.hash.indexOf('pseudo=true') >= 0);\n };\n return Environment;\n }());\n function _format(message, args, env) {\n var result;\n if (args.length === 0) {\n result = message;\n }\n else {\n result = message.replace(/\\{(\\d+)\\}/g, function (match, rest) {\n var index = rest[0];\n var arg = args[index];\n var result = match;\n if (typeof arg === 'string') {\n result = arg;\n }\n else if (typeof arg === 'number' || typeof arg === 'boolean' || arg === void 0 || arg === null) {\n result = String(arg);\n }\n return result;\n });\n }\n if (env.isPseudo) {\n // FF3B and FF3D is the Unicode zenkaku representation for [ and ]\n result = '\\uFF3B' + result.replace(/[aouei]/g, '$&$&') + '\\uFF3D';\n }\n return result;\n }\n function findLanguageForModule(config, name) {\n var result = config[name];\n if (result)\n return result;\n result = config['*'];\n if (result)\n return result;\n return null;\n }\n function localize(env, data, message) {\n var args = [];\n for (var _i = 3; _i < arguments.length; _i++) {\n args[_i - 3] = arguments[_i];\n }\n return _format(message, args, env);\n }\n function createScopedLocalize(scope, env) {\n return function (idx, defaultValue) {\n var restArgs = Array.prototype.slice.call(arguments, 2);\n return _format(scope[idx], restArgs, env);\n };\n }\n var NLSPlugin = /** @class */ (function () {\n function NLSPlugin(env) {\n var _this = this;\n this._env = env;\n this.localize = function (data, message) {\n var args = [];\n for (var _i = 2; _i < arguments.length; _i++) {\n args[_i - 2] = arguments[_i];\n }\n return localize.apply(void 0, __spreadArrays([_this._env, data, message], args));\n };\n }\n NLSPlugin.prototype.setPseudoTranslation = function (value) {\n this._env._isPseudo = value;\n };\n NLSPlugin.prototype.create = function (key, data) {\n return {\n localize: createScopedLocalize(data[key], this._env)\n };\n };\n NLSPlugin.prototype.load = function (name, req, load, config) {\n var _this = this;\n config = config || {};\n if (!name || name.length === 0) {\n load({\n localize: this.localize\n });\n }\n else {\n var pluginConfig = config['vs/nls'] || {};\n var language = pluginConfig.availableLanguages ? findLanguageForModule(pluginConfig.availableLanguages, name) : null;\n var suffix = '.nls';\n if (language !== null && language !== NLSPlugin.DEFAULT_TAG) {\n suffix = suffix + '.' + language;\n }\n var messagesLoaded_1 = function (messages) {\n if (Array.isArray(messages)) {\n messages.localize = createScopedLocalize(messages, _this._env);\n }\n else {\n messages.localize = createScopedLocalize(messages[name], _this._env);\n }\n load(messages);\n };\n if (typeof pluginConfig.loadBundle === 'function') {\n pluginConfig.loadBundle(name, language, function (err, messages) {\n // We have an error. Load the English default strings to not fail\n if (err) {\n req([name + '.nls'], messagesLoaded_1);\n }\n else {\n messagesLoaded_1(messages);\n }\n });\n }\n else {\n req([name + suffix], messagesLoaded_1);\n }\n }\n };\n NLSPlugin.DEFAULT_TAG = 'i-default';\n return NLSPlugin;\n }());\n NLSLoaderPlugin.NLSPlugin = NLSPlugin;\n define('vs/nls', new NLSPlugin(new Environment()));\n})(NLSLoaderPlugin || (NLSLoaderPlugin = {}));\n","/*! @license DOMPurify 2.3.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.1/LICENSE */\n\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\nvar hasOwnProperty = Object.hasOwnProperty,\n setPrototypeOf = Object.setPrototypeOf,\n isFrozen = Object.isFrozen,\n getPrototypeOf = Object.getPrototypeOf,\n getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\nvar freeze = Object.freeze,\n seal = Object.seal,\n create = Object.create; // eslint-disable-line import/no-mutable-exports\n\nvar _ref = typeof Reflect !== 'undefined' && Reflect,\n apply = _ref.apply,\n construct = _ref.construct;\n\nif (!apply) {\n apply = function apply(fun, thisValue, args) {\n return fun.apply(thisValue, args);\n };\n}\n\nif (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n}\n\nif (!seal) {\n seal = function seal(x) {\n return x;\n };\n}\n\nif (!construct) {\n construct = function construct(Func, args) {\n return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray(args))))();\n };\n}\n\nvar arrayForEach = unapply(Array.prototype.forEach);\nvar arrayPop = unapply(Array.prototype.pop);\nvar arrayPush = unapply(Array.prototype.push);\n\nvar stringToLowerCase = unapply(String.prototype.toLowerCase);\nvar stringMatch = unapply(String.prototype.match);\nvar stringReplace = unapply(String.prototype.replace);\nvar stringIndexOf = unapply(String.prototype.indexOf);\nvar stringTrim = unapply(String.prototype.trim);\n\nvar regExpTest = unapply(RegExp.prototype.test);\n\nvar typeErrorCreate = unconstruct(TypeError);\n\nfunction unapply(func) {\n return function (thisArg) {\n for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n\n return apply(func, thisArg, args);\n };\n}\n\nfunction unconstruct(func) {\n return function () {\n for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n\n return construct(func, args);\n };\n}\n\n/* Add properties to a lookup table */\nfunction addToSet(set, array) {\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n\n var l = array.length;\n while (l--) {\n var element = array[l];\n if (typeof element === 'string') {\n var lcElement = stringToLowerCase(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n\n element = lcElement;\n }\n }\n\n set[element] = true;\n }\n\n return set;\n}\n\n/* Shallow clone an object */\nfunction clone(object) {\n var newObject = create(null);\n\n var property = void 0;\n for (property in object) {\n if (apply(hasOwnProperty, object, [property])) {\n newObject[property] = object[property];\n }\n }\n\n return newObject;\n}\n\n/* IE10 doesn't support __lookupGetter__ so lets'\n * simulate it. It also automatically checks\n * if the prop is function or getter and behaves\n * accordingly. */\nfunction lookupGetter(object, prop) {\n while (object !== null) {\n var desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n\n object = getPrototypeOf(object);\n }\n\n function fallbackValue(element) {\n console.warn('fallback value for', element);\n return null;\n }\n\n return fallbackValue;\n}\n\nvar html = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\n\n// SVG\nvar svg = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\n\nvar svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n\n// List of SVG elements that are disallowed by default.\n// We still need to know them so that we can do namespace\n// checks properly in case one wants to add them to\n// allow-list.\nvar svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', 'feimage', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\n\nvar mathMl = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);\n\n// Similarly to SVG, we want to know all MathML elements,\n// even those that we disallow by default.\nvar mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\n\nvar text = freeze(['#text']);\n\nvar html$1 = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns', 'slot']);\n\nvar svg$1 = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\n\nvar mathMl$1 = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\n\nvar xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n// eslint-disable-next-line unicorn/better-regex\nvar MUSTACHE_EXPR = seal(/\\{\\{[\\s\\S]*|[\\s\\S]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\nvar ERB_EXPR = seal(/<%[\\s\\S]*|[\\s\\S]*%>/gm);\nvar DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]/); // eslint-disable-line no-useless-escape\nvar ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\nvar IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n);\nvar IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\nvar ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n);\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nfunction _toConsumableArray$1(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\nvar getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n};\n\n/**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory.\n * @param {Document} document The document object (to determine policy name suffix)\n * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types\n * are not supported).\n */\nvar _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {\n if ((typeof trustedTypes === 'undefined' ? 'undefined' : _typeof(trustedTypes)) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n var suffix = null;\n var ATTR_NAME = 'data-tt-policy-suffix';\n if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {\n suffix = document.currentScript.getAttribute(ATTR_NAME);\n }\n\n var policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML: function createHTML(html$$1) {\n return html$$1;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n};\n\nfunction createDOMPurify() {\n var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n\n var DOMPurify = function DOMPurify(root) {\n return createDOMPurify(root);\n };\n\n /**\n * Version label, exposed for easier checks\n * if DOMPurify is up to date or not\n */\n DOMPurify.version = '2.3.1';\n\n /**\n * Array of elements that DOMPurify removed during sanitation.\n * Empty if nothing was removed.\n */\n DOMPurify.removed = [];\n\n if (!window || !window.document || window.document.nodeType !== 9) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n\n return DOMPurify;\n }\n\n var originalDocument = window.document;\n\n var document = window.document;\n var DocumentFragment = window.DocumentFragment,\n HTMLTemplateElement = window.HTMLTemplateElement,\n Node = window.Node,\n Element = window.Element,\n NodeFilter = window.NodeFilter,\n _window$NamedNodeMap = window.NamedNodeMap,\n NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,\n Text = window.Text,\n Comment = window.Comment,\n DOMParser = window.DOMParser,\n trustedTypes = window.trustedTypes;\n\n\n var ElementPrototype = Element.prototype;\n\n var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n var getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n var template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n\n var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);\n var emptyHTML = trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML('') : '';\n\n var _document = document,\n implementation = _document.implementation,\n createNodeIterator = _document.createNodeIterator,\n createDocumentFragment = _document.createDocumentFragment,\n getElementsByTagName = _document.getElementsByTagName;\n var importNode = originalDocument.importNode;\n\n\n var documentMode = {};\n try {\n documentMode = clone(document).documentMode ? document.documentMode : {};\n } catch (_) {}\n\n var hooks = {};\n\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;\n\n var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,\n ERB_EXPR$$1 = ERB_EXPR,\n DATA_ATTR$$1 = DATA_ATTR,\n ARIA_ATTR$$1 = ARIA_ATTR,\n IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;\n var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;\n\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n\n /* allowed element names */\n\n var ALLOWED_TAGS = null;\n var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray$1(html), _toConsumableArray$1(svg), _toConsumableArray$1(svgFilters), _toConsumableArray$1(mathMl), _toConsumableArray$1(text)));\n\n /* Allowed attribute names */\n var ALLOWED_ATTR = null;\n var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray$1(html$1), _toConsumableArray$1(svg$1), _toConsumableArray$1(mathMl$1), _toConsumableArray$1(xml)));\n\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n var FORBID_TAGS = null;\n\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n var FORBID_ATTR = null;\n\n /* Decide if ARIA attributes are okay */\n var ALLOW_ARIA_ATTR = true;\n\n /* Decide if custom data attributes are okay */\n var ALLOW_DATA_ATTR = true;\n\n /* Decide if unknown protocols are okay */\n var ALLOW_UNKNOWN_PROTOCOLS = false;\n\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n var SAFE_FOR_TEMPLATES = false;\n\n /* Decide if document with ... should be returned */\n var WHOLE_DOCUMENT = false;\n\n /* Track whether config is already set on this instance of DOMPurify. */\n var SET_CONFIG = false;\n\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n var FORCE_BODY = false;\n\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n var RETURN_DOM = false;\n\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n var RETURN_DOM_FRAGMENT = false;\n\n /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM\n * `Node` is imported into the current `Document`. If this flag is not enabled the\n * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by\n * DOMPurify.\n *\n * This defaults to `true` starting DOMPurify 2.2.0. Note that setting it to `false`\n * might cause XSS from attacks hidden in closed shadowroots in case the browser\n * supports Declarative Shadow: DOM https://web.dev/declarative-shadow-dom/\n */\n var RETURN_DOM_IMPORT = true;\n\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n var RETURN_TRUSTED_TYPE = false;\n\n /* Output should be free from DOM clobbering attacks? */\n var SANITIZE_DOM = true;\n\n /* Keep element content when removing element? */\n var KEEP_CONTENT = true;\n\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n var IN_PLACE = false;\n\n /* Allow usage of profiles like html, svg and mathMl */\n var USE_PROFILES = {};\n\n /* Tags to ignore content of when KEEP_CONTENT is true */\n var FORBID_CONTENTS = null;\n var DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n\n /* Tags that are safe for data: URIs */\n var DATA_URI_TAGS = null;\n var DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n\n /* Attributes safe for values like \"javascript:\" */\n var URI_SAFE_ATTRIBUTES = null;\n var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n\n var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n /* Document namespace */\n var NAMESPACE = HTML_NAMESPACE;\n var IS_EMPTY_INPUT = false;\n\n /* Keep a reference to config to pass to hooks */\n var CONFIG = null;\n\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n\n var formElement = document.createElement('form');\n\n /**\n * _parseConfig\n *\n * @param {Object} cfg optional config literal\n */\n // eslint-disable-next-line complexity\n var _parseConfig = function _parseConfig(cfg) {\n if (CONFIG && CONFIG === cfg) {\n return;\n }\n\n /* Shield configuration object from tampering */\n if (!cfg || (typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {\n cfg = {};\n }\n\n /* Shield configuration object from prototype pollution */\n cfg = clone(cfg);\n\n /* Set configuration parameters */\n ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;\n ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;\n URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;\n DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;\n FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS;\n FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};\n FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};\n USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT !== false; // Default true\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n IN_PLACE = cfg.IN_PLACE || false; // Default false\n IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;\n NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n\n /* Parse profile info */\n if (USE_PROFILES) {\n ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray$1(text)));\n ALLOWED_ATTR = [];\n if (USE_PROFILES.html === true) {\n addToSet(ALLOWED_TAGS, html);\n addToSet(ALLOWED_ATTR, html$1);\n }\n\n if (USE_PROFILES.svg === true) {\n addToSet(ALLOWED_TAGS, svg);\n addToSet(ALLOWED_ATTR, svg$1);\n addToSet(ALLOWED_ATTR, xml);\n }\n\n if (USE_PROFILES.svgFilters === true) {\n addToSet(ALLOWED_TAGS, svgFilters);\n addToSet(ALLOWED_ATTR, svg$1);\n addToSet(ALLOWED_ATTR, xml);\n }\n\n if (USE_PROFILES.mathMl === true) {\n addToSet(ALLOWED_TAGS, mathMl);\n addToSet(ALLOWED_ATTR, mathMl$1);\n addToSet(ALLOWED_ATTR, xml);\n }\n }\n\n /* Merge configuration parameters */\n if (cfg.ADD_TAGS) {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);\n }\n\n if (cfg.ADD_ATTR) {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);\n }\n\n if (cfg.ADD_URI_SAFE_ATTR) {\n addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);\n }\n\n if (cfg.FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n\n addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);\n }\n\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) {\n ALLOWED_TAGS['#text'] = true;\n }\n\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n if (WHOLE_DOCUMENT) {\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n }\n\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n if (ALLOWED_TAGS.table) {\n addToSet(ALLOWED_TAGS, ['tbody']);\n delete FORBID_TAGS.tbody;\n }\n\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (freeze) {\n freeze(cfg);\n }\n\n CONFIG = cfg;\n };\n\n var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n\n var HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']);\n\n /* Keep track of all possible SVG and MathML tags\n * so that we can perform the namespace checks\n * correctly. */\n var ALL_SVG_TAGS = addToSet({}, svg);\n addToSet(ALL_SVG_TAGS, svgFilters);\n addToSet(ALL_SVG_TAGS, svgDisallowed);\n\n var ALL_MATHML_TAGS = addToSet({}, mathMl);\n addToSet(ALL_MATHML_TAGS, mathMlDisallowed);\n\n /**\n *\n *\n * @param {Element} element a DOM element whose namespace is being checked\n * @returns {boolean} Return false if the element has a\n * namespace that a spec-compliant parser would never\n * return. Return true otherwise.\n */\n var _checkValidNamespace = function _checkValidNamespace(element) {\n var parent = getParentNode(element);\n\n // In JSDOM, if we're inside shadow DOM, then parentNode\n // can be null. We just simulate parent in this case.\n if (!parent || !parent.tagName) {\n parent = {\n namespaceURI: HTML_NAMESPACE,\n tagName: 'template'\n };\n }\n\n var tagName = stringToLowerCase(element.tagName);\n var parentTagName = stringToLowerCase(parent.tagName);\n\n if (element.namespaceURI === SVG_NAMESPACE) {\n // The only way to switch from HTML namespace to SVG\n // is via . If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'svg';\n }\n\n // The only way to switch from MathML to SVG is via\n // svg if parent is either or MathML\n // text integration points.\n if (parent.namespaceURI === MATHML_NAMESPACE) {\n return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);\n }\n\n // We only allow elements that are defined in SVG\n // spec. All others are disallowed in SVG namespace.\n return Boolean(ALL_SVG_TAGS[tagName]);\n }\n\n if (element.namespaceURI === MATHML_NAMESPACE) {\n // The only way to switch from HTML namespace to MathML\n // is via . If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'math';\n }\n\n // The only way to switch from SVG to MathML is via\n // and HTML integration points\n if (parent.namespaceURI === SVG_NAMESPACE) {\n return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];\n }\n\n // We only allow elements that are defined in MathML\n // spec. All others are disallowed in MathML namespace.\n return Boolean(ALL_MATHML_TAGS[tagName]);\n }\n\n if (element.namespaceURI === HTML_NAMESPACE) {\n // The only way to switch from SVG to HTML is via\n // HTML integration points, and from MathML to HTML\n // is via MathML text integration points\n if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n\n if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n\n // Certain elements are allowed in both SVG and HTML\n // namespace. We need to specify them explicitly\n // so that they don't get erronously deleted from\n // HTML namespace.\n var commonSvgAndHTMLElements = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n\n // We disallow tags that are specific for MathML\n // or SVG and should never appear in HTML namespace\n return !ALL_MATHML_TAGS[tagName] && (commonSvgAndHTMLElements[tagName] || !ALL_SVG_TAGS[tagName]);\n }\n\n // The code should never reach this place (this means\n // that the element somehow got namespace that is not\n // HTML, SVG or MathML). Return false just in case.\n return false;\n };\n\n /**\n * _forceRemove\n *\n * @param {Node} node a DOM node\n */\n var _forceRemove = function _forceRemove(node) {\n arrayPush(DOMPurify.removed, { element: node });\n try {\n // eslint-disable-next-line unicorn/prefer-dom-node-remove\n node.parentNode.removeChild(node);\n } catch (_) {\n try {\n node.outerHTML = emptyHTML;\n } catch (_) {\n node.remove();\n }\n }\n };\n\n /**\n * _removeAttribute\n *\n * @param {String} name an Attribute name\n * @param {Node} node a DOM node\n */\n var _removeAttribute = function _removeAttribute(name, node) {\n try {\n arrayPush(DOMPurify.removed, {\n attribute: node.getAttributeNode(name),\n from: node\n });\n } catch (_) {\n arrayPush(DOMPurify.removed, {\n attribute: null,\n from: node\n });\n }\n\n node.removeAttribute(name);\n\n // We void attribute values for unremovable \"is\"\" attributes\n if (name === 'is' && !ALLOWED_ATTR[name]) {\n if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n try {\n _forceRemove(node);\n } catch (_) {}\n } else {\n try {\n node.setAttribute(name, '');\n } catch (_) {}\n }\n }\n };\n\n /**\n * _initDocument\n *\n * @param {String} dirty a string of dirty markup\n * @return {Document} a DOM, filled with the dirty markup\n */\n var _initDocument = function _initDocument(dirty) {\n /* Create a HTML document */\n var doc = void 0;\n var leadingWhitespace = void 0;\n\n if (FORCE_BODY) {\n dirty = '' + dirty;\n } else {\n /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\n var matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\n leadingWhitespace = matches && matches[0];\n }\n\n var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;\n /*\n * Use the DOMParser API by default, fallback later if needs be\n * DOMParser not work for svg when has multiple root element.\n */\n if (NAMESPACE === HTML_NAMESPACE) {\n try {\n doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');\n } catch (_) {}\n }\n\n /* Use createHTMLDocument in case DOMParser is not available */\n if (!doc || !doc.documentElement) {\n doc = implementation.createDocument(NAMESPACE, 'template', null);\n try {\n doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;\n } catch (_) {\n // Syntax error if dirtyPayload is invalid xml\n }\n }\n\n var body = doc.body || doc.documentElement;\n\n if (dirty && leadingWhitespace) {\n body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);\n }\n\n /* Work on whole document or just its body */\n if (NAMESPACE === HTML_NAMESPACE) {\n return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n }\n\n return WHOLE_DOCUMENT ? doc.documentElement : body;\n };\n\n /**\n * _createIterator\n *\n * @param {Document} root document/fragment to create iterator for\n * @return {Iterator} iterator instance\n */\n var _createIterator = function _createIterator(root) {\n return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);\n };\n\n /**\n * _isClobbered\n *\n * @param {Node} elm element to check for clobbering attacks\n * @return {Boolean} true if clobbered, false if safe\n */\n var _isClobbered = function _isClobbered(elm) {\n if (elm instanceof Text || elm instanceof Comment) {\n return false;\n }\n\n if (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function') {\n return true;\n }\n\n return false;\n };\n\n /**\n * _isNode\n *\n * @param {Node} obj object to check whether it's a DOM node\n * @return {Boolean} true is object is a DOM node\n */\n var _isNode = function _isNode(object) {\n return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? object instanceof Node : object && (typeof object === 'undefined' ? 'undefined' : _typeof(object)) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';\n };\n\n /**\n * _executeHook\n * Execute user configurable hooks\n *\n * @param {String} entryPoint Name of the hook's entry point\n * @param {Node} currentNode node to work on with the hook\n * @param {Object} data additional hook parameters\n */\n var _executeHook = function _executeHook(entryPoint, currentNode, data) {\n if (!hooks[entryPoint]) {\n return;\n }\n\n arrayForEach(hooks[entryPoint], function (hook) {\n hook.call(DOMPurify, currentNode, data, CONFIG);\n });\n };\n\n /**\n * _sanitizeElements\n *\n * @protect nodeName\n * @protect textContent\n * @protect removeChild\n *\n * @param {Node} currentNode to check for permission to exist\n * @return {Boolean} true if node was killed, false if left alive\n */\n var _sanitizeElements = function _sanitizeElements(currentNode) {\n var content = void 0;\n\n /* Execute a hook if present */\n _executeHook('beforeSanitizeElements', currentNode, null);\n\n /* Check if element is clobbered or can clobber */\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Check if tagname contains Unicode */\n if (stringMatch(currentNode.nodeName, /[\\u0080-\\uFFFF]/)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Now let's check the element's type and name */\n var tagName = stringToLowerCase(currentNode.nodeName);\n\n /* Execute a hook if present */\n _executeHook('uponSanitizeElement', currentNode, {\n tagName: tagName,\n allowedTags: ALLOWED_TAGS\n });\n\n /* Detect mXSS attempts abusing namespace confusion */\n if (!_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\\w]/g, currentNode.innerHTML) && regExpTest(/<[/\\w]/g, currentNode.textContent)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Mitigate a problem with templates inside select */\n if (tagName === 'select' && regExpTest(/
' + (escaped ? _code : escape(_code, true)) + '
\\n';\n }\n\n return '
' + (escaped ? _code : escape(_code, true)) + '
\\n';\n };\n\n _proto.blockquote = function blockquote(quote) {\n return '
\\n' + quote + '
\\n';\n };\n\n _proto.html = function html(_html) {\n return _html;\n };\n\n _proto.heading = function heading(text, level, raw, slugger) {\n if (this.options.headerIds) {\n return '' + text + '\\n';\n } // ignore IDs\n\n\n return '' + text + '\\n';\n };\n\n _proto.hr = function hr() {\n return this.options.xhtml ? '
\\n' : '
\\n';\n };\n\n _proto.list = function list(body, ordered, start) {\n var type = ordered ? 'ol' : 'ul',\n startatt = ordered && start !== 1 ? ' start=\"' + start + '\"' : '';\n return '<' + type + startatt + '>\\n' + body + '\\n';\n };\n\n _proto.listitem = function listitem(text) {\n return '
  • ' + text + '
  • \\n';\n };\n\n _proto.checkbox = function checkbox(checked) {\n return ' ';\n };\n\n _proto.paragraph = function paragraph(text) {\n return '

    ' + text + '

    \\n';\n };\n\n _proto.table = function table(header, body) {\n if (body) body = '' + body + '';\n return '\\n' + '\\n' + header + '\\n' + body + '
    \\n';\n };\n\n _proto.tablerow = function tablerow(content) {\n return '\\n' + content + '\\n';\n };\n\n _proto.tablecell = function tablecell(content, flags) {\n var type = flags.header ? 'th' : 'td';\n var tag = flags.align ? '<' + type + ' align=\"' + flags.align + '\">' : '<' + type + '>';\n return tag + content + '\\n';\n } // span level renderer\n ;\n\n _proto.strong = function strong(text) {\n return '' + text + '';\n };\n\n _proto.em = function em(text) {\n return '' + text + '';\n };\n\n _proto.codespan = function codespan(text) {\n return '' + text + '';\n };\n\n _proto.br = function br() {\n return this.options.xhtml ? '
    ' : '
    ';\n };\n\n _proto.del = function del(text) {\n return '' + text + '';\n };\n\n _proto.link = function link(href, title, text) {\n href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);\n\n if (href === null) {\n return text;\n }\n\n var out = '';\n return out;\n };\n\n _proto.image = function image(href, title, text) {\n href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);\n\n if (href === null) {\n return text;\n }\n\n var out = '\"'' : '>';\n return out;\n };\n\n _proto.text = function text(_text) {\n return _text;\n };\n\n return Renderer;\n }();\n\n /**\n * TextRenderer\n * returns only the textual part of the token\n */\n var TextRenderer = /*#__PURE__*/function () {\n function TextRenderer() {}\n\n var _proto = TextRenderer.prototype;\n\n // no need for block level renderers\n _proto.strong = function strong(text) {\n return text;\n };\n\n _proto.em = function em(text) {\n return text;\n };\n\n _proto.codespan = function codespan(text) {\n return text;\n };\n\n _proto.del = function del(text) {\n return text;\n };\n\n _proto.html = function html(text) {\n return text;\n };\n\n _proto.text = function text(_text) {\n return _text;\n };\n\n _proto.link = function link(href, title, text) {\n return '' + text;\n };\n\n _proto.image = function image(href, title, text) {\n return '' + text;\n };\n\n _proto.br = function br() {\n return '';\n };\n\n return TextRenderer;\n }();\n\n /**\n * Slugger generates header id\n */\n var Slugger = /*#__PURE__*/function () {\n function Slugger() {\n this.seen = {};\n }\n\n var _proto = Slugger.prototype;\n\n _proto.serialize = function serialize(value) {\n return value.toLowerCase().trim() // remove html tags\n .replace(/<[!\\/a-z].*?>/ig, '') // remove unwanted chars\n .replace(/[\\u2000-\\u206F\\u2E00-\\u2E7F\\\\'!\"#$%&()*+,./:;<=>?@[\\]^`{|}~]/g, '').replace(/\\s/g, '-');\n }\n /**\n * Finds the next safe (unique) slug to use\n */\n ;\n\n _proto.getNextSafeSlug = function getNextSafeSlug(originalSlug, isDryRun) {\n var slug = originalSlug;\n var occurenceAccumulator = 0;\n\n if (this.seen.hasOwnProperty(slug)) {\n occurenceAccumulator = this.seen[originalSlug];\n\n do {\n occurenceAccumulator++;\n slug = originalSlug + '-' + occurenceAccumulator;\n } while (this.seen.hasOwnProperty(slug));\n }\n\n if (!isDryRun) {\n this.seen[originalSlug] = occurenceAccumulator;\n this.seen[slug] = 0;\n }\n\n return slug;\n }\n /**\n * Convert string to unique id\n * @param {object} options\n * @param {boolean} options.dryrun Generates the next unique slug without updating the internal accumulator.\n */\n ;\n\n _proto.slug = function slug(value, options) {\n if (options === void 0) {\n options = {};\n }\n\n var slug = this.serialize(value);\n return this.getNextSafeSlug(slug, options.dryrun);\n };\n\n return Slugger;\n }();\n\n /**\n * Parsing & Compiling\n */\n\n var Parser = /*#__PURE__*/function () {\n function Parser(options) {\n this.options = options || exports.defaults;\n this.options.renderer = this.options.renderer || new Renderer();\n this.renderer = this.options.renderer;\n this.renderer.options = this.options;\n this.textRenderer = new TextRenderer();\n this.slugger = new Slugger();\n }\n /**\n * Static Parse Method\n */\n\n\n Parser.parse = function parse(tokens, options) {\n var parser = new Parser(options);\n return parser.parse(tokens);\n }\n /**\n * Static Parse Inline Method\n */\n ;\n\n Parser.parseInline = function parseInline(tokens, options) {\n var parser = new Parser(options);\n return parser.parseInline(tokens);\n }\n /**\n * Parse Loop\n */\n ;\n\n var _proto = Parser.prototype;\n\n _proto.parse = function parse(tokens, top) {\n if (top === void 0) {\n top = true;\n }\n\n var out = '',\n i,\n j,\n k,\n l2,\n l3,\n row,\n cell,\n header,\n body,\n token,\n ordered,\n start,\n loose,\n itemBody,\n item,\n checked,\n task,\n checkbox,\n ret;\n var l = tokens.length;\n\n for (i = 0; i < l; i++) {\n token = tokens[i]; // Run any renderer extensions\n\n if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {\n ret = this.options.extensions.renderers[token.type].call({\n parser: this\n }, token);\n\n if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(token.type)) {\n out += ret || '';\n continue;\n }\n }\n\n switch (token.type) {\n case 'space':\n {\n continue;\n }\n\n case 'hr':\n {\n out += this.renderer.hr();\n continue;\n }\n\n case 'heading':\n {\n out += this.renderer.heading(this.parseInline(token.tokens), token.depth, unescape(this.parseInline(token.tokens, this.textRenderer)), this.slugger);\n continue;\n }\n\n case 'code':\n {\n out += this.renderer.code(token.text, token.lang, token.escaped);\n continue;\n }\n\n case 'table':\n {\n header = ''; // header\n\n cell = '';\n l2 = token.header.length;\n\n for (j = 0; j < l2; j++) {\n cell += this.renderer.tablecell(this.parseInline(token.header[j].tokens), {\n header: true,\n align: token.align[j]\n });\n }\n\n header += this.renderer.tablerow(cell);\n body = '';\n l2 = token.rows.length;\n\n for (j = 0; j < l2; j++) {\n row = token.rows[j];\n cell = '';\n l3 = row.length;\n\n for (k = 0; k < l3; k++) {\n cell += this.renderer.tablecell(this.parseInline(row[k].tokens), {\n header: false,\n align: token.align[k]\n });\n }\n\n body += this.renderer.tablerow(cell);\n }\n\n out += this.renderer.table(header, body);\n continue;\n }\n\n case 'blockquote':\n {\n body = this.parse(token.tokens);\n out += this.renderer.blockquote(body);\n continue;\n }\n\n case 'list':\n {\n ordered = token.ordered;\n start = token.start;\n loose = token.loose;\n l2 = token.items.length;\n body = '';\n\n for (j = 0; j < l2; j++) {\n item = token.items[j];\n checked = item.checked;\n task = item.task;\n itemBody = '';\n\n if (item.task) {\n checkbox = this.renderer.checkbox(checked);\n\n if (loose) {\n if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {\n item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;\n\n if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {\n item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;\n }\n } else {\n item.tokens.unshift({\n type: 'text',\n text: checkbox\n });\n }\n } else {\n itemBody += checkbox;\n }\n }\n\n itemBody += this.parse(item.tokens, loose);\n body += this.renderer.listitem(itemBody, task, checked);\n }\n\n out += this.renderer.list(body, ordered, start);\n continue;\n }\n\n case 'html':\n {\n // TODO parse inline content if parameter markdown=1\n out += this.renderer.html(token.text);\n continue;\n }\n\n case 'paragraph':\n {\n out += this.renderer.paragraph(this.parseInline(token.tokens));\n continue;\n }\n\n case 'text':\n {\n body = token.tokens ? this.parseInline(token.tokens) : token.text;\n\n while (i + 1 < l && tokens[i + 1].type === 'text') {\n token = tokens[++i];\n body += '\\n' + (token.tokens ? this.parseInline(token.tokens) : token.text);\n }\n\n out += top ? this.renderer.paragraph(body) : body;\n continue;\n }\n\n default:\n {\n var errMsg = 'Token with \"' + token.type + '\" type was not found.';\n\n if (this.options.silent) {\n console.error(errMsg);\n return;\n } else {\n throw new Error(errMsg);\n }\n }\n }\n }\n\n return out;\n }\n /**\n * Parse Inline Tokens\n */\n ;\n\n _proto.parseInline = function parseInline(tokens, renderer) {\n renderer = renderer || this.renderer;\n var out = '',\n i,\n token,\n ret;\n var l = tokens.length;\n\n for (i = 0; i < l; i++) {\n token = tokens[i]; // Run any renderer extensions\n\n if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {\n ret = this.options.extensions.renderers[token.type].call({\n parser: this\n }, token);\n\n if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) {\n out += ret || '';\n continue;\n }\n }\n\n switch (token.type) {\n case 'escape':\n {\n out += renderer.text(token.text);\n break;\n }\n\n case 'html':\n {\n out += renderer.html(token.text);\n break;\n }\n\n case 'link':\n {\n out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));\n break;\n }\n\n case 'image':\n {\n out += renderer.image(token.href, token.title, token.text);\n break;\n }\n\n case 'strong':\n {\n out += renderer.strong(this.parseInline(token.tokens, renderer));\n break;\n }\n\n case 'em':\n {\n out += renderer.em(this.parseInline(token.tokens, renderer));\n break;\n }\n\n case 'codespan':\n {\n out += renderer.codespan(token.text);\n break;\n }\n\n case 'br':\n {\n out += renderer.br();\n break;\n }\n\n case 'del':\n {\n out += renderer.del(this.parseInline(token.tokens, renderer));\n break;\n }\n\n case 'text':\n {\n out += renderer.text(token.text);\n break;\n }\n\n default:\n {\n var errMsg = 'Token with \"' + token.type + '\" type was not found.';\n\n if (this.options.silent) {\n console.error(errMsg);\n return;\n } else {\n throw new Error(errMsg);\n }\n }\n }\n }\n\n return out;\n };\n\n return Parser;\n }();\n\n /**\n * Marked\n */\n\n function marked(src, opt, callback) {\n // throw error in case of non string input\n if (typeof src === 'undefined' || src === null) {\n throw new Error('marked(): input parameter is undefined or null');\n }\n\n if (typeof src !== 'string') {\n throw new Error('marked(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected');\n }\n\n if (typeof opt === 'function') {\n callback = opt;\n opt = null;\n }\n\n opt = merge({}, marked.defaults, opt || {});\n checkSanitizeDeprecation(opt);\n\n if (callback) {\n var highlight = opt.highlight;\n var tokens;\n\n try {\n tokens = Lexer.lex(src, opt);\n } catch (e) {\n return callback(e);\n }\n\n var done = function done(err) {\n var out;\n\n if (!err) {\n try {\n if (opt.walkTokens) {\n marked.walkTokens(tokens, opt.walkTokens);\n }\n\n out = Parser.parse(tokens, opt);\n } catch (e) {\n err = e;\n }\n }\n\n opt.highlight = highlight;\n return err ? callback(err) : callback(null, out);\n };\n\n if (!highlight || highlight.length < 3) {\n return done();\n }\n\n delete opt.highlight;\n if (!tokens.length) return done();\n var pending = 0;\n marked.walkTokens(tokens, function (token) {\n if (token.type === 'code') {\n pending++;\n setTimeout(function () {\n highlight(token.text, token.lang, function (err, code) {\n if (err) {\n return done(err);\n }\n\n if (code != null && code !== token.text) {\n token.text = code;\n token.escaped = true;\n }\n\n pending--;\n\n if (pending === 0) {\n done();\n }\n });\n }, 0);\n }\n });\n\n if (pending === 0) {\n done();\n }\n\n return;\n }\n\n try {\n var _tokens = Lexer.lex(src, opt);\n\n if (opt.walkTokens) {\n marked.walkTokens(_tokens, opt.walkTokens);\n }\n\n return Parser.parse(_tokens, opt);\n } catch (e) {\n e.message += '\\nPlease report this to https://github.com/markedjs/marked.';\n\n if (opt.silent) {\n return '

    An error occurred:

    ' + escape(e.message + '', true) + '
    ';\n }\n\n throw e;\n }\n }\n /**\n * Options\n */\n\n marked.options = marked.setOptions = function (opt) {\n merge(marked.defaults, opt);\n changeDefaults(marked.defaults);\n return marked;\n };\n\n marked.getDefaults = getDefaults;\n marked.defaults = exports.defaults;\n /**\n * Use Extension\n */\n\n marked.use = function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n var opts = merge.apply(void 0, [{}].concat(args));\n var extensions = marked.defaults.extensions || {\n renderers: {},\n childTokens: {}\n };\n var hasExtensions;\n args.forEach(function (pack) {\n // ==-- Parse \"addon\" extensions --== //\n if (pack.extensions) {\n hasExtensions = true;\n pack.extensions.forEach(function (ext) {\n if (!ext.name) {\n throw new Error('extension name required');\n }\n\n if (ext.renderer) {\n // Renderer extensions\n var prevRenderer = extensions.renderers ? extensions.renderers[ext.name] : null;\n\n if (prevRenderer) {\n // Replace extension with func to run new extension but fall back if false\n extensions.renderers[ext.name] = function () {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n\n var ret = ext.renderer.apply(this, args);\n\n if (ret === false) {\n ret = prevRenderer.apply(this, args);\n }\n\n return ret;\n };\n } else {\n extensions.renderers[ext.name] = ext.renderer;\n }\n }\n\n if (ext.tokenizer) {\n // Tokenizer Extensions\n if (!ext.level || ext.level !== 'block' && ext.level !== 'inline') {\n throw new Error(\"extension level must be 'block' or 'inline'\");\n }\n\n if (extensions[ext.level]) {\n extensions[ext.level].unshift(ext.tokenizer);\n } else {\n extensions[ext.level] = [ext.tokenizer];\n }\n\n if (ext.start) {\n // Function to check for start of token\n if (ext.level === 'block') {\n if (extensions.startBlock) {\n extensions.startBlock.push(ext.start);\n } else {\n extensions.startBlock = [ext.start];\n }\n } else if (ext.level === 'inline') {\n if (extensions.startInline) {\n extensions.startInline.push(ext.start);\n } else {\n extensions.startInline = [ext.start];\n }\n }\n }\n }\n\n if (ext.childTokens) {\n // Child tokens to be visited by walkTokens\n extensions.childTokens[ext.name] = ext.childTokens;\n }\n });\n } // ==-- Parse \"overwrite\" extensions --== //\n\n\n if (pack.renderer) {\n (function () {\n var renderer = marked.defaults.renderer || new Renderer();\n\n var _loop = function _loop(prop) {\n var prevRenderer = renderer[prop]; // Replace renderer with func to run extension, but fall back if false\n\n renderer[prop] = function () {\n for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n args[_key3] = arguments[_key3];\n }\n\n var ret = pack.renderer[prop].apply(renderer, args);\n\n if (ret === false) {\n ret = prevRenderer.apply(renderer, args);\n }\n\n return ret;\n };\n };\n\n for (var prop in pack.renderer) {\n _loop(prop);\n }\n\n opts.renderer = renderer;\n })();\n }\n\n if (pack.tokenizer) {\n (function () {\n var tokenizer = marked.defaults.tokenizer || new Tokenizer();\n\n var _loop2 = function _loop2(prop) {\n var prevTokenizer = tokenizer[prop]; // Replace tokenizer with func to run extension, but fall back if false\n\n tokenizer[prop] = function () {\n for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n args[_key4] = arguments[_key4];\n }\n\n var ret = pack.tokenizer[prop].apply(tokenizer, args);\n\n if (ret === false) {\n ret = prevTokenizer.apply(tokenizer, args);\n }\n\n return ret;\n };\n };\n\n for (var prop in pack.tokenizer) {\n _loop2(prop);\n }\n\n opts.tokenizer = tokenizer;\n })();\n } // ==-- Parse WalkTokens extensions --== //\n\n\n if (pack.walkTokens) {\n var _walkTokens = marked.defaults.walkTokens;\n\n opts.walkTokens = function (token) {\n pack.walkTokens.call(this, token);\n\n if (_walkTokens) {\n _walkTokens.call(this, token);\n }\n };\n }\n\n if (hasExtensions) {\n opts.extensions = extensions;\n }\n\n marked.setOptions(opts);\n });\n };\n /**\n * Run callback for every token\n */\n\n\n marked.walkTokens = function (tokens, callback) {\n var _loop3 = function _loop3() {\n var token = _step.value;\n callback.call(marked, token);\n\n switch (token.type) {\n case 'table':\n {\n for (var _iterator2 = _createForOfIteratorHelperLoose(token.header), _step2; !(_step2 = _iterator2()).done;) {\n var cell = _step2.value;\n marked.walkTokens(cell.tokens, callback);\n }\n\n for (var _iterator3 = _createForOfIteratorHelperLoose(token.rows), _step3; !(_step3 = _iterator3()).done;) {\n var row = _step3.value;\n\n for (var _iterator4 = _createForOfIteratorHelperLoose(row), _step4; !(_step4 = _iterator4()).done;) {\n var _cell = _step4.value;\n marked.walkTokens(_cell.tokens, callback);\n }\n }\n\n break;\n }\n\n case 'list':\n {\n marked.walkTokens(token.items, callback);\n break;\n }\n\n default:\n {\n if (marked.defaults.extensions && marked.defaults.extensions.childTokens && marked.defaults.extensions.childTokens[token.type]) {\n // Walk any extensions\n marked.defaults.extensions.childTokens[token.type].forEach(function (childTokens) {\n marked.walkTokens(token[childTokens], callback);\n });\n } else if (token.tokens) {\n marked.walkTokens(token.tokens, callback);\n }\n }\n }\n };\n\n for (var _iterator = _createForOfIteratorHelperLoose(tokens), _step; !(_step = _iterator()).done;) {\n _loop3();\n }\n };\n /**\n * Parse Inline\n */\n\n\n marked.parseInline = function (src, opt) {\n // throw error in case of non string input\n if (typeof src === 'undefined' || src === null) {\n throw new Error('marked.parseInline(): input parameter is undefined or null');\n }\n\n if (typeof src !== 'string') {\n throw new Error('marked.parseInline(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected');\n }\n\n opt = merge({}, marked.defaults, opt || {});\n checkSanitizeDeprecation(opt);\n\n try {\n var tokens = Lexer.lexInline(src, opt);\n\n if (opt.walkTokens) {\n marked.walkTokens(tokens, opt.walkTokens);\n }\n\n return Parser.parseInline(tokens, opt);\n } catch (e) {\n e.message += '\\nPlease report this to https://github.com/markedjs/marked.';\n\n if (opt.silent) {\n return '

    An error occurred:

    ' + escape(e.message + '', true) + '
    ';\n }\n\n throw e;\n }\n };\n /**\n * Expose\n */\n\n\n marked.Parser = Parser;\n marked.parser = Parser.parse;\n marked.Renderer = Renderer;\n marked.TextRenderer = TextRenderer;\n marked.Lexer = Lexer;\n marked.lexer = Lexer.lex;\n marked.Tokenizer = Tokenizer;\n marked.Slugger = Slugger;\n marked.parse = marked;\n var options = marked.options;\n var setOptions = marked.setOptions;\n var use = marked.use;\n var walkTokens = marked.walkTokens;\n var parseInline = marked.parseInline;\n var parse = marked;\n var parser = Parser.parse;\n var lexer = Lexer.lex;\n\n exports.Lexer = Lexer;\n exports.Parser = Parser;\n exports.Renderer = Renderer;\n exports.Slugger = Slugger;\n exports.TextRenderer = TextRenderer;\n exports.Tokenizer = Tokenizer;\n exports.getDefaults = getDefaults;\n exports.lexer = lexer;\n exports.marked = marked;\n exports.options = options;\n exports.parse = parse;\n exports.parseInline = parseInline;\n exports.parser = parser;\n exports.setOptions = setOptions;\n exports.use = use;\n exports.walkTokens = walkTokens;\n\n Object.defineProperty(exports, '__esModule', { value: true });\n}));\n\n// ESM-uncomment-begin\n// })();\n// export var marked = (__marked_exports || exports);\n// ESM-uncomment-end\n","\n\nexport namespace Mimes {\n\texport const text = 'text/plain';\n\texport const binary = 'application/octet-stream';\n\texport const unknown = 'application/unknown';\n\texport const markdown = 'text/markdown';\n\texport const latex = 'text/latex';\n}\n","\nimport { Mimes } from 'vs/base/common/mime';\n\n// Common data transfers\nexport const DataTransfers = {\n\n\t/**\n\t * Application specific resource transfer type\n\t */\n\tRESOURCES: 'ResourceURLs',\n\n\t/**\n\t * Browser specific transfer type to download\n\t */\n\tDOWNLOAD_URL: 'DownloadURL',\n\n\t/**\n\t * Browser specific transfer type for files\n\t */\n\tFILES: 'Files',\n\n\t/**\n\t * Typically transfer type for copy/paste transfers.\n\t */\n\tTEXT: Mimes.text,\n\n\t/**\n\t * Application specific terminal transfer type.\n\t */\n\tTERMINALS: 'Terminals'\n};\n\nexport interface IDragAndDropData {\n\tupdate(dataTransfer: DataTransfer): void;\n\tgetData(): unknown;\n}\n\nexport class DragAndDropData implements IDragAndDropData {\n\n\tconstructor(private data: T) { }\n\n\tupdate(): void {\n\t\t// noop\n\t}\n\n\tgetData(): T {\n\t\treturn this.data;\n\t}\n}\n\nexport interface IStaticDND {\n\tCurrentDragAndDropData: IDragAndDropData | undefined;\n}\n\nexport const StaticDND: IStaticDND = {\n\tCurrentDragAndDropData: undefined\n};\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport interface INavigator {\n}\n\nexport class ArrayNavigator implements INavigator {\n\n\tconstructor(\n\t\tprivate readonly items: readonly T[],\n\t\tprotected start: number = 0,\n\t\tprotected end: number = items.length,\n\t\tprotected index = start - 1\n\t) { }\n\n\tcurrent(): T | null {\n\t\tif (this.index === this.start - 1 || this.index === this.end) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn this.items[this.index];\n\t}\n\n\tnext(): T | null {\n\t\tthis.index = Math.min(this.index + 1, this.end);\n\t\treturn this.current();\n\t}\n\n\tprevious(): T | null {\n\t\tthis.index = Math.max(this.index - 1, this.start - 1);\n\t\treturn this.current();\n\t}\n\n\tfirst(): T | null {\n\t\tthis.index = this.start;\n\t\treturn this.current();\n\t}\n\n\tlast(): T | null {\n\t\tthis.index = this.end - 1;\n\t\treturn this.current();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ArrayNavigator, INavigator } from 'vs/base/common/navigator';\n\nexport class HistoryNavigator implements INavigator {\n\n\tprivate _history!: Set;\n\tprivate _limit: number;\n\tprivate _navigator!: ArrayNavigator;\n\n\tconstructor(history: readonly T[] = [], limit: number = 10) {\n\t\tthis._initialize(history);\n\t\tthis._limit = limit;\n\t\tthis._onChange();\n\t}\n\n\tpublic getHistory(): T[] {\n\t\treturn this._elements;\n\t}\n\n\tpublic add(t: T) {\n\t\tthis._history.delete(t);\n\t\tthis._history.add(t);\n\t\tthis._onChange();\n\t}\n\n\tpublic next(): T | null {\n\t\tif (this._currentPosition() !== this._elements.length - 1) {\n\t\t\treturn this._navigator.next();\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic previous(): T | null {\n\t\tif (this._currentPosition() !== 0) {\n\t\t\treturn this._navigator.previous();\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic current(): T | null {\n\t\treturn this._navigator.current();\n\t}\n\n\tpublic first(): T | null {\n\t\treturn this._navigator.first();\n\t}\n\n\tpublic last(): T | null {\n\t\treturn this._navigator.last();\n\t}\n\n\tpublic has(t: T): boolean {\n\t\treturn this._history.has(t);\n\t}\n\n\tprivate _onChange() {\n\t\tthis._reduceToLimit();\n\t\tconst elements = this._elements;\n\t\tthis._navigator = new ArrayNavigator(elements, 0, elements.length, elements.length);\n\t}\n\n\tprivate _reduceToLimit() {\n\t\tconst data = this._elements;\n\t\tif (data.length > this._limit) {\n\t\t\tthis._initialize(data.slice(data.length - this._limit));\n\t\t}\n\t}\n\n\tprivate _currentPosition(): number {\n\t\tconst currentElement = this._navigator.current();\n\t\tif (!currentElement) {\n\t\t\treturn -1;\n\t\t}\n\n\t\treturn this._elements.indexOf(currentElement);\n\t}\n\n\tprivate _initialize(history: readonly T[]): void {\n\t\tthis._history = new Set();\n\t\tfor (const entry of history) {\n\t\t\tthis._history.add(entry);\n\t\t}\n\t}\n\n\tprivate get _elements(): T[] {\n\t\tconst elements: T[] = [];\n\t\tthis._history.forEach(e => elements.push(e));\n\t\treturn elements;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport function clamp(value: number, min: number, max: number): number {\n\treturn Math.min(Math.max(value, min), max);\n}\n\nexport class MovingAverage {\n\n\tprivate _n = 1;\n\tprivate _val = 0;\n\n\tupdate(value: number): number {\n\t\tthis._val = this._val + (value - this._val) / this._n;\n\t\tthis._n += 1;\n\t\treturn this._val;\n\t}\n\n\tget value(): number {\n\t\treturn this._val;\n\t}\n}\n\nexport class SlidingWindowAverage {\n\n\tprivate _n: number = 0;\n\tprivate _val = 0;\n\n\tprivate readonly _values: number[] = [];\n\tprivate _index: number = 0;\n\tprivate _sum = 0;\n\n\tconstructor(size: number) {\n\t\tthis._values = new Array(size);\n\t\tthis._values.fill(0, 0, size);\n\t}\n\n\tupdate(value: number): number {\n\t\tconst oldValue = this._values[this._index];\n\t\tthis._values[this._index] = value;\n\t\tthis._index = (this._index + 1) % this._values.length;\n\n\t\tthis._sum -= oldValue;\n\t\tthis._sum += value;\n\n\t\tif (this._n < this._values.length) {\n\t\t\tthis._n += 1;\n\t\t}\n\n\t\tthis._val = this._sum / this._n;\n\t\treturn this._val;\n\t}\n\n\tget value(): number {\n\t\treturn this._val;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nconst LANGUAGE_DEFAULT = 'en';\n\nlet _isWindows = false;\nlet _isMacintosh = false;\nlet _isLinux = false;\nlet _isLinuxSnap = false;\nlet _isNative = false;\nlet _isWeb = false;\nlet _isElectron = false;\nlet _isIOS = false;\nlet _locale: string | undefined = undefined;\nlet _language: string = LANGUAGE_DEFAULT;\nlet _translationsConfigFile: string | undefined = undefined;\nlet _userAgent: string | undefined = undefined;\n\ninterface NLSConfig {\n\tlocale: string;\n\tavailableLanguages: { [key: string]: string; };\n\t_translationsConfigFile: string;\n}\n\nexport interface IProcessEnvironment {\n\t[key: string]: string | undefined;\n}\n\n/**\n * This interface is intentionally not identical to node.js\n * process because it also works in sandboxed environments\n * where the process object is implemented differently. We\n * define the properties here that we need for `platform`\n * to work and nothing else.\n */\nexport interface INodeProcess {\n\tplatform: string;\n\tarch: string;\n\tenv: IProcessEnvironment;\n\tversions?: {\n\t\telectron?: string;\n\t};\n\ttype?: string;\n\tcwd: () => string;\n}\n\ndeclare const process: INodeProcess;\ndeclare const global: unknown;\ndeclare const self: unknown;\n\nexport const globals: any = (typeof self === 'object' ? self : typeof global === 'object' ? global : {});\n\nlet nodeProcess: INodeProcess | undefined = undefined;\nif (typeof globals.vscode !== 'undefined' && typeof globals.vscode.process !== 'undefined') {\n\t// Native environment (sandboxed)\n\tnodeProcess = globals.vscode.process;\n} else if (typeof process !== 'undefined') {\n\t// Native environment (non-sandboxed)\n\tnodeProcess = process;\n}\n\nconst isElectronProcess = typeof nodeProcess?.versions?.electron === 'string';\nconst isElectronRenderer = isElectronProcess && nodeProcess?.type === 'renderer';\n\ninterface INavigator {\n\tuserAgent: string;\n\tlanguage: string;\n\tmaxTouchPoints?: number;\n}\ndeclare const navigator: INavigator;\n\n// Web environment\nif (typeof navigator === 'object' && !isElectronRenderer) {\n\t_userAgent = navigator.userAgent;\n\t_isWindows = _userAgent.indexOf('Windows') >= 0;\n\t_isMacintosh = _userAgent.indexOf('Macintosh') >= 0;\n\t_isIOS = (_userAgent.indexOf('Macintosh') >= 0 || _userAgent.indexOf('iPad') >= 0 || _userAgent.indexOf('iPhone') >= 0) && !!navigator.maxTouchPoints && navigator.maxTouchPoints > 0;\n\t_isLinux = _userAgent.indexOf('Linux') >= 0;\n\t_isWeb = true;\n\t_locale = navigator.language;\n\t_language = _locale;\n}\n\n// Native environment\nelse if (typeof nodeProcess === 'object') {\n\t_isWindows = (nodeProcess.platform === 'win32');\n\t_isMacintosh = (nodeProcess.platform === 'darwin');\n\t_isLinux = (nodeProcess.platform === 'linux');\n\t_isLinuxSnap = _isLinux && !!nodeProcess.env['SNAP'] && !!nodeProcess.env['SNAP_REVISION'];\n\t_isElectron = isElectronProcess;\n\t_locale = LANGUAGE_DEFAULT;\n\t_language = LANGUAGE_DEFAULT;\n\tconst rawNlsConfig = nodeProcess.env['VSCODE_NLS_CONFIG'];\n\tif (rawNlsConfig) {\n\t\ttry {\n\t\t\tconst nlsConfig: NLSConfig = JSON.parse(rawNlsConfig);\n\t\t\tconst resolved = nlsConfig.availableLanguages['*'];\n\t\t\t_locale = nlsConfig.locale;\n\t\t\t// VSCode's default language is 'en'\n\t\t\t_language = resolved ? resolved : LANGUAGE_DEFAULT;\n\t\t\t_translationsConfigFile = nlsConfig._translationsConfigFile;\n\t\t} catch (e) {\n\t\t}\n\t}\n\t_isNative = true;\n}\n\n// Unknown environment\nelse {\n\tconsole.error('Unable to resolve platform.');\n}\n\nexport const enum Platform {\n\tWeb,\n\tMac,\n\tLinux,\n\tWindows\n}\n\nlet _platform: Platform = Platform.Web;\nif (_isMacintosh) {\n\t_platform = Platform.Mac;\n} else if (_isWindows) {\n\t_platform = Platform.Windows;\n} else if (_isLinux) {\n\t_platform = Platform.Linux;\n}\n\nexport const isWindows = _isWindows;\nexport const isMacintosh = _isMacintosh;\nexport const isLinux = _isLinux;\nexport const isNative = _isNative;\nexport const isWeb = _isWeb;\nexport const isIOS = _isIOS;\nexport const userAgent = _userAgent;\n\n/**\n * The language used for the user interface. The format of\n * the string is all lower case (e.g. zh-tw for Traditional\n * Chinese)\n */\nexport const language = _language;\n\n/**\n * See https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#:~:text=than%204%2C%20then-,set%20timeout%20to%204,-.\n *\n * Works similarly to `setTimeout(0)` but doesn't suffer from the 4ms artificial delay\n * that browsers set when the nesting level is > 5.\n */\nexport const setTimeout0 = (() => {\n\tif (typeof globals.postMessage === 'function' && !globals.importScripts) {\n\t\tinterface IQueueElement {\n\t\t\tid: number;\n\t\t\tcallback: () => void;\n\t\t}\n\t\tlet pending: IQueueElement[] = [];\n\t\tglobals.addEventListener('message', (e: MessageEvent) => {\n\t\t\tif (e.data && e.data.vscodeScheduleAsyncWork) {\n\t\t\t\tfor (let i = 0, len = pending.length; i < len; i++) {\n\t\t\t\t\tconst candidate = pending[i];\n\t\t\t\t\tif (candidate.id === e.data.vscodeScheduleAsyncWork) {\n\t\t\t\t\t\tpending.splice(i, 1);\n\t\t\t\t\t\tcandidate.callback();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tlet lastId = 0;\n\t\treturn (callback: () => void) => {\n\t\t\tconst myId = ++lastId;\n\t\t\tpending.push({\n\t\t\t\tid: myId,\n\t\t\t\tcallback: callback\n\t\t\t});\n\t\t\tglobals.postMessage({ vscodeScheduleAsyncWork: myId }, '*');\n\t\t};\n\t}\n\treturn (callback: () => void) => setTimeout(callback);\n})();\n\nexport const enum OperatingSystem {\n\tWindows = 1,\n\tMacintosh = 2,\n\tLinux = 3\n}\nexport const OS = (_isMacintosh || _isIOS ? OperatingSystem.Macintosh : (_isWindows ? OperatingSystem.Windows : OperatingSystem.Linux));\n\nlet _isLittleEndian = true;\nlet _isLittleEndianComputed = false;\nexport function isLittleEndian(): boolean {\n\tif (!_isLittleEndianComputed) {\n\t\t_isLittleEndianComputed = true;\n\t\tconst test = new Uint8Array(2);\n\t\ttest[0] = 1;\n\t\ttest[1] = 2;\n\t\tconst view = new Uint16Array(test.buffer);\n\t\t_isLittleEndian = (view[0] === (2 << 8) + 1);\n\t}\n\treturn _isLittleEndian;\n}\n\nexport const isChrome = !!(userAgent && userAgent.indexOf('Chrome') >= 0);\nexport const isFirefox = !!(userAgent && userAgent.indexOf('Firefox') >= 0);\nexport const isSafari = !!(!isChrome && (userAgent && userAgent.indexOf('Safari') >= 0));\nexport const isEdge = !!(userAgent && userAgent.indexOf('Edg/') >= 0);\nexport const isAndroid = !!(userAgent && userAgent.indexOf('Android') >= 0);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { globals, INodeProcess, isMacintosh, isWindows } from 'vs/base/common/platform';\n\nlet safeProcess: Omit & { arch: string | undefined; };\ndeclare const process: INodeProcess;\n\n// Native sandbox environment\nif (typeof globals.vscode !== 'undefined' && typeof globals.vscode.process !== 'undefined') {\n\tconst sandboxProcess: INodeProcess = globals.vscode.process;\n\tsafeProcess = {\n\t\tget platform() { return sandboxProcess.platform; },\n\t\tget arch() { return sandboxProcess.arch; },\n\t\tget env() { return sandboxProcess.env; },\n\t\tcwd() { return sandboxProcess.cwd(); }\n\t};\n}\n\n// Native node.js environment\nelse if (typeof process !== 'undefined') {\n\tsafeProcess = {\n\t\tget platform() { return process.platform; },\n\t\tget arch() { return process.arch; },\n\t\tget env() { return process.env; },\n\t\tcwd() { return process.env['VSCODE_CWD'] || process.cwd(); }\n\t};\n}\n\n// Web environment\nelse {\n\tsafeProcess = {\n\n\t\t// Supported\n\t\tget platform() { return isWindows ? 'win32' : isMacintosh ? 'darwin' : 'linux'; },\n\t\tget arch() { return undefined; /* arch is undefined in web */ },\n\n\t\t// Unsupported\n\t\tget env() { return {}; },\n\t\tcwd() { return '/'; }\n\t};\n}\n\n/**\n * Provides safe access to the `cwd` property in node.js, sandboxed or web\n * environments.\n *\n * Note: in web, this property is hardcoded to be `/`.\n */\nexport const cwd = safeProcess.cwd;\n\n/**\n * Provides safe access to the `env` property in node.js, sandboxed or web\n * environments.\n *\n * Note: in web, this property is hardcoded to be `{}`.\n */\nexport const env = safeProcess.env;\n\n/**\n * Provides safe access to the `platform` property in node.js, sandboxed or web\n * environments.\n */\nexport const platform = safeProcess.platform;\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n// NOTE: VSCode's copy of nodejs path library to be usable in common (non-node) namespace\n// Copied from: https://github.com/nodejs/node/blob/v14.16.0/lib/path.js\n\n/**\n * Copyright Joyent, Inc. and other Node contributors.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to permit\n * persons to whom the Software is furnished to do so, subject to the\n * following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n * USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\nimport * as process from 'vs/base/common/process';\n\nconst CHAR_UPPERCASE_A = 65;/* A */\nconst CHAR_LOWERCASE_A = 97; /* a */\nconst CHAR_UPPERCASE_Z = 90; /* Z */\nconst CHAR_LOWERCASE_Z = 122; /* z */\nconst CHAR_DOT = 46; /* . */\nconst CHAR_FORWARD_SLASH = 47; /* / */\nconst CHAR_BACKWARD_SLASH = 92; /* \\ */\nconst CHAR_COLON = 58; /* : */\nconst CHAR_QUESTION_MARK = 63; /* ? */\n\nclass ErrorInvalidArgType extends Error {\n\tcode: 'ERR_INVALID_ARG_TYPE';\n\tconstructor(name: string, expected: string, actual: unknown) {\n\t\t// determiner: 'must be' or 'must not be'\n\t\tlet determiner;\n\t\tif (typeof expected === 'string' && expected.indexOf('not ') === 0) {\n\t\t\tdeterminer = 'must not be';\n\t\t\texpected = expected.replace(/^not /, '');\n\t\t} else {\n\t\t\tdeterminer = 'must be';\n\t\t}\n\n\t\tconst type = name.indexOf('.') !== -1 ? 'property' : 'argument';\n\t\tlet msg = `The \"${name}\" ${type} ${determiner} of type ${expected}`;\n\n\t\tmsg += `. Received type ${typeof actual}`;\n\t\tsuper(msg);\n\n\t\tthis.code = 'ERR_INVALID_ARG_TYPE';\n\t}\n}\n\nfunction validateString(value: string, name: string) {\n\tif (typeof value !== 'string') {\n\t\tthrow new ErrorInvalidArgType(name, 'string', value);\n\t}\n}\n\nfunction isPathSeparator(code: number | undefined) {\n\treturn code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;\n}\n\nfunction isPosixPathSeparator(code: number | undefined) {\n\treturn code === CHAR_FORWARD_SLASH;\n}\n\nfunction isWindowsDeviceRoot(code: number) {\n\treturn (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) ||\n\t\t(code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z);\n}\n\n// Resolves . and .. elements in a path with directory names\nfunction normalizeString(path: string, allowAboveRoot: boolean, separator: string, isPathSeparator: (code?: number) => boolean) {\n\tlet res = '';\n\tlet lastSegmentLength = 0;\n\tlet lastSlash = -1;\n\tlet dots = 0;\n\tlet code = 0;\n\tfor (let i = 0; i <= path.length; ++i) {\n\t\tif (i < path.length) {\n\t\t\tcode = path.charCodeAt(i);\n\t\t}\n\t\telse if (isPathSeparator(code)) {\n\t\t\tbreak;\n\t\t}\n\t\telse {\n\t\t\tcode = CHAR_FORWARD_SLASH;\n\t\t}\n\n\t\tif (isPathSeparator(code)) {\n\t\t\tif (lastSlash === i - 1 || dots === 1) {\n\t\t\t\t// NOOP\n\t\t\t} else if (dots === 2) {\n\t\t\t\tif (res.length < 2 || lastSegmentLength !== 2 ||\n\t\t\t\t\tres.charCodeAt(res.length - 1) !== CHAR_DOT ||\n\t\t\t\t\tres.charCodeAt(res.length - 2) !== CHAR_DOT) {\n\t\t\t\t\tif (res.length > 2) {\n\t\t\t\t\t\tconst lastSlashIndex = res.lastIndexOf(separator);\n\t\t\t\t\t\tif (lastSlashIndex === -1) {\n\t\t\t\t\t\t\tres = '';\n\t\t\t\t\t\t\tlastSegmentLength = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tres = res.slice(0, lastSlashIndex);\n\t\t\t\t\t\t\tlastSegmentLength = res.length - 1 - res.lastIndexOf(separator);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlastSlash = i;\n\t\t\t\t\t\tdots = 0;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else if (res.length !== 0) {\n\t\t\t\t\t\tres = '';\n\t\t\t\t\t\tlastSegmentLength = 0;\n\t\t\t\t\t\tlastSlash = i;\n\t\t\t\t\t\tdots = 0;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (allowAboveRoot) {\n\t\t\t\t\tres += res.length > 0 ? `${separator}..` : '..';\n\t\t\t\t\tlastSegmentLength = 2;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (res.length > 0) {\n\t\t\t\t\tres += `${separator}${path.slice(lastSlash + 1, i)}`;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tres = path.slice(lastSlash + 1, i);\n\t\t\t\t}\n\t\t\t\tlastSegmentLength = i - lastSlash - 1;\n\t\t\t}\n\t\t\tlastSlash = i;\n\t\t\tdots = 0;\n\t\t} else if (code === CHAR_DOT && dots !== -1) {\n\t\t\t++dots;\n\t\t} else {\n\t\t\tdots = -1;\n\t\t}\n\t}\n\treturn res;\n}\n\nfunction _format(sep: string, pathObject: ParsedPath) {\n\tif (pathObject === null || typeof pathObject !== 'object') {\n\t\tthrow new ErrorInvalidArgType('pathObject', 'Object', pathObject);\n\t}\n\tconst dir = pathObject.dir || pathObject.root;\n\tconst base = pathObject.base ||\n\t\t`${pathObject.name || ''}${pathObject.ext || ''}`;\n\tif (!dir) {\n\t\treturn base;\n\t}\n\treturn dir === pathObject.root ? `${dir}${base}` : `${dir}${sep}${base}`;\n}\n\nexport interface ParsedPath {\n\troot: string;\n\tdir: string;\n\tbase: string;\n\text: string;\n\tname: string;\n}\n\nexport interface IPath {\n\tnormalize(path: string): string;\n\tisAbsolute(path: string): boolean;\n\tjoin(...paths: string[]): string;\n\tresolve(...pathSegments: string[]): string;\n\trelative(from: string, to: string): string;\n\tdirname(path: string): string;\n\tbasename(path: string, ext?: string): string;\n\textname(path: string): string;\n\tformat(pathObject: ParsedPath): string;\n\tparse(path: string): ParsedPath;\n\ttoNamespacedPath(path: string): string;\n\tsep: '\\\\' | '/';\n\tdelimiter: string;\n\twin32: IPath | null;\n\tposix: IPath | null;\n}\n\nexport const win32: IPath = {\n\t// path.resolve([from ...], to)\n\tresolve(...pathSegments: string[]): string {\n\t\tlet resolvedDevice = '';\n\t\tlet resolvedTail = '';\n\t\tlet resolvedAbsolute = false;\n\n\t\tfor (let i = pathSegments.length - 1; i >= -1; i--) {\n\t\t\tlet path;\n\t\t\tif (i >= 0) {\n\t\t\t\tpath = pathSegments[i];\n\t\t\t\tvalidateString(path, 'path');\n\n\t\t\t\t// Skip empty entries\n\t\t\t\tif (path.length === 0) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if (resolvedDevice.length === 0) {\n\t\t\t\tpath = process.cwd();\n\t\t\t} else {\n\t\t\t\t// Windows has the concept of drive-specific current working\n\t\t\t\t// directories. If we've resolved a drive letter but not yet an\n\t\t\t\t// absolute path, get cwd for that drive, or the process cwd if\n\t\t\t\t// the drive cwd is not available. We're sure the device is not\n\t\t\t\t// a UNC path at this points, because UNC paths are always absolute.\n\t\t\t\tpath = process.env[`=${resolvedDevice}`] || process.cwd();\n\n\t\t\t\t// Verify that a cwd was found and that it actually points\n\t\t\t\t// to our drive. If not, default to the drive's root.\n\t\t\t\tif (path === undefined ||\n\t\t\t\t\t(path.slice(0, 2).toLowerCase() !== resolvedDevice.toLowerCase() &&\n\t\t\t\t\t\tpath.charCodeAt(2) === CHAR_BACKWARD_SLASH)) {\n\t\t\t\t\tpath = `${resolvedDevice}\\\\`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst len = path.length;\n\t\t\tlet rootEnd = 0;\n\t\t\tlet device = '';\n\t\t\tlet isAbsolute = false;\n\t\t\tconst code = path.charCodeAt(0);\n\n\t\t\t// Try to match a root\n\t\t\tif (len === 1) {\n\t\t\t\tif (isPathSeparator(code)) {\n\t\t\t\t\t// `path` contains just a path separator\n\t\t\t\t\trootEnd = 1;\n\t\t\t\t\tisAbsolute = true;\n\t\t\t\t}\n\t\t\t} else if (isPathSeparator(code)) {\n\t\t\t\t// Possible UNC root\n\n\t\t\t\t// If we started with a separator, we know we at least have an\n\t\t\t\t// absolute path of some kind (UNC or otherwise)\n\t\t\t\tisAbsolute = true;\n\n\t\t\t\tif (isPathSeparator(path.charCodeAt(1))) {\n\t\t\t\t\t// Matched double path separator at beginning\n\t\t\t\t\tlet j = 2;\n\t\t\t\t\tlet last = j;\n\t\t\t\t\t// Match 1 or more non-path separators\n\t\t\t\t\twhile (j < len && !isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\t\tj++;\n\t\t\t\t\t}\n\t\t\t\t\tif (j < len && j !== last) {\n\t\t\t\t\t\tconst firstPart = path.slice(last, j);\n\t\t\t\t\t\t// Matched!\n\t\t\t\t\t\tlast = j;\n\t\t\t\t\t\t// Match 1 or more path separators\n\t\t\t\t\t\twhile (j < len && isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (j < len && j !== last) {\n\t\t\t\t\t\t\t// Matched!\n\t\t\t\t\t\t\tlast = j;\n\t\t\t\t\t\t\t// Match 1 or more non-path separators\n\t\t\t\t\t\t\twhile (j < len && !isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (j === len || j !== last) {\n\t\t\t\t\t\t\t\t// We matched a UNC root\n\t\t\t\t\t\t\t\tdevice = `\\\\\\\\${firstPart}\\\\${path.slice(last, j)}`;\n\t\t\t\t\t\t\t\trootEnd = j;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\trootEnd = 1;\n\t\t\t\t}\n\t\t\t} else if (isWindowsDeviceRoot(code) &&\n\t\t\t\tpath.charCodeAt(1) === CHAR_COLON) {\n\t\t\t\t// Possible device root\n\t\t\t\tdevice = path.slice(0, 2);\n\t\t\t\trootEnd = 2;\n\t\t\t\tif (len > 2 && isPathSeparator(path.charCodeAt(2))) {\n\t\t\t\t\t// Treat separator following drive name as an absolute path\n\t\t\t\t\t// indicator\n\t\t\t\t\tisAbsolute = true;\n\t\t\t\t\trootEnd = 3;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (device.length > 0) {\n\t\t\t\tif (resolvedDevice.length > 0) {\n\t\t\t\t\tif (device.toLowerCase() !== resolvedDevice.toLowerCase()) {\n\t\t\t\t\t\t// This path points to another device so it is not applicable\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresolvedDevice = device;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (resolvedAbsolute) {\n\t\t\t\tif (resolvedDevice.length > 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresolvedTail = `${path.slice(rootEnd)}\\\\${resolvedTail}`;\n\t\t\t\tresolvedAbsolute = isAbsolute;\n\t\t\t\tif (isAbsolute && resolvedDevice.length > 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// At this point the path should be resolved to a full absolute path,\n\t\t// but handle relative paths to be safe (might happen when process.cwd()\n\t\t// fails)\n\n\t\t// Normalize the tail path\n\t\tresolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\\\',\n\t\t\tisPathSeparator);\n\n\t\treturn resolvedAbsolute ?\n\t\t\t`${resolvedDevice}\\\\${resolvedTail}` :\n\t\t\t`${resolvedDevice}${resolvedTail}` || '.';\n\t},\n\n\tnormalize(path: string): string {\n\t\tvalidateString(path, 'path');\n\t\tconst len = path.length;\n\t\tif (len === 0) {\n\t\t\treturn '.';\n\t\t}\n\t\tlet rootEnd = 0;\n\t\tlet device;\n\t\tlet isAbsolute = false;\n\t\tconst code = path.charCodeAt(0);\n\n\t\t// Try to match a root\n\t\tif (len === 1) {\n\t\t\t// `path` contains just a single char, exit early to avoid\n\t\t\t// unnecessary work\n\t\t\treturn isPosixPathSeparator(code) ? '\\\\' : path;\n\t\t}\n\t\tif (isPathSeparator(code)) {\n\t\t\t// Possible UNC root\n\n\t\t\t// If we started with a separator, we know we at least have an absolute\n\t\t\t// path of some kind (UNC or otherwise)\n\t\t\tisAbsolute = true;\n\n\t\t\tif (isPathSeparator(path.charCodeAt(1))) {\n\t\t\t\t// Matched double path separator at beginning\n\t\t\t\tlet j = 2;\n\t\t\t\tlet last = j;\n\t\t\t\t// Match 1 or more non-path separators\n\t\t\t\twhile (j < len && !isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t\tif (j < len && j !== last) {\n\t\t\t\t\tconst firstPart = path.slice(last, j);\n\t\t\t\t\t// Matched!\n\t\t\t\t\tlast = j;\n\t\t\t\t\t// Match 1 or more path separators\n\t\t\t\t\twhile (j < len && isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\t\tj++;\n\t\t\t\t\t}\n\t\t\t\t\tif (j < len && j !== last) {\n\t\t\t\t\t\t// Matched!\n\t\t\t\t\t\tlast = j;\n\t\t\t\t\t\t// Match 1 or more non-path separators\n\t\t\t\t\t\twhile (j < len && !isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (j === len) {\n\t\t\t\t\t\t\t// We matched a UNC root only\n\t\t\t\t\t\t\t// Return the normalized version of the UNC root since there\n\t\t\t\t\t\t\t// is nothing left to process\n\t\t\t\t\t\t\treturn `\\\\\\\\${firstPart}\\\\${path.slice(last)}\\\\`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (j !== last) {\n\t\t\t\t\t\t\t// We matched a UNC root with leftovers\n\t\t\t\t\t\t\tdevice = `\\\\\\\\${firstPart}\\\\${path.slice(last, j)}`;\n\t\t\t\t\t\t\trootEnd = j;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trootEnd = 1;\n\t\t\t}\n\t\t} else if (isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON) {\n\t\t\t// Possible device root\n\t\t\tdevice = path.slice(0, 2);\n\t\t\trootEnd = 2;\n\t\t\tif (len > 2 && isPathSeparator(path.charCodeAt(2))) {\n\t\t\t\t// Treat separator following drive name as an absolute path\n\t\t\t\t// indicator\n\t\t\t\tisAbsolute = true;\n\t\t\t\trootEnd = 3;\n\t\t\t}\n\t\t}\n\n\t\tlet tail = rootEnd < len ?\n\t\t\tnormalizeString(path.slice(rootEnd), !isAbsolute, '\\\\', isPathSeparator) :\n\t\t\t'';\n\t\tif (tail.length === 0 && !isAbsolute) {\n\t\t\ttail = '.';\n\t\t}\n\t\tif (tail.length > 0 && isPathSeparator(path.charCodeAt(len - 1))) {\n\t\t\ttail += '\\\\';\n\t\t}\n\t\tif (device === undefined) {\n\t\t\treturn isAbsolute ? `\\\\${tail}` : tail;\n\t\t}\n\t\treturn isAbsolute ? `${device}\\\\${tail}` : `${device}${tail}`;\n\t},\n\n\tisAbsolute(path: string): boolean {\n\t\tvalidateString(path, 'path');\n\t\tconst len = path.length;\n\t\tif (len === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst code = path.charCodeAt(0);\n\t\treturn isPathSeparator(code) ||\n\t\t\t// Possible device root\n\t\t\t(len > 2 &&\n\t\t\t\tisWindowsDeviceRoot(code) &&\n\t\t\t\tpath.charCodeAt(1) === CHAR_COLON &&\n\t\t\t\tisPathSeparator(path.charCodeAt(2)));\n\t},\n\n\tjoin(...paths: string[]): string {\n\t\tif (paths.length === 0) {\n\t\t\treturn '.';\n\t\t}\n\n\t\tlet joined;\n\t\tlet firstPart: string | undefined;\n\t\tfor (let i = 0; i < paths.length; ++i) {\n\t\t\tconst arg = paths[i];\n\t\t\tvalidateString(arg, 'path');\n\t\t\tif (arg.length > 0) {\n\t\t\t\tif (joined === undefined) {\n\t\t\t\t\tjoined = firstPart = arg;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tjoined += `\\\\${arg}`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (joined === undefined) {\n\t\t\treturn '.';\n\t\t}\n\n\t\t// Make sure that the joined path doesn't start with two slashes, because\n\t\t// normalize() will mistake it for a UNC path then.\n\t\t//\n\t\t// This step is skipped when it is very clear that the user actually\n\t\t// intended to point at a UNC path. This is assumed when the first\n\t\t// non-empty string arguments starts with exactly two slashes followed by\n\t\t// at least one more non-slash character.\n\t\t//\n\t\t// Note that for normalize() to treat a path as a UNC path it needs to\n\t\t// have at least 2 components, so we don't filter for that here.\n\t\t// This means that the user can use join to construct UNC paths from\n\t\t// a server name and a share name; for example:\n\t\t// path.join('//server', 'share') -> '\\\\\\\\server\\\\share\\\\')\n\t\tlet needsReplace = true;\n\t\tlet slashCount = 0;\n\t\tif (typeof firstPart === 'string' && isPathSeparator(firstPart.charCodeAt(0))) {\n\t\t\t++slashCount;\n\t\t\tconst firstLen = firstPart.length;\n\t\t\tif (firstLen > 1 && isPathSeparator(firstPart.charCodeAt(1))) {\n\t\t\t\t++slashCount;\n\t\t\t\tif (firstLen > 2) {\n\t\t\t\t\tif (isPathSeparator(firstPart.charCodeAt(2))) {\n\t\t\t\t\t\t++slashCount;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We matched a UNC path in the first part\n\t\t\t\t\t\tneedsReplace = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (needsReplace) {\n\t\t\t// Find any more consecutive slashes we need to replace\n\t\t\twhile (slashCount < joined.length &&\n\t\t\t\tisPathSeparator(joined.charCodeAt(slashCount))) {\n\t\t\t\tslashCount++;\n\t\t\t}\n\n\t\t\t// Replace the slashes if needed\n\t\t\tif (slashCount >= 2) {\n\t\t\t\tjoined = `\\\\${joined.slice(slashCount)}`;\n\t\t\t}\n\t\t}\n\n\t\treturn win32.normalize(joined);\n\t},\n\n\n\t// It will solve the relative path from `from` to `to`, for instance:\n\t// from = 'C:\\\\orandea\\\\test\\\\aaa'\n\t// to = 'C:\\\\orandea\\\\impl\\\\bbb'\n\t// The output of the function should be: '..\\\\..\\\\impl\\\\bbb'\n\trelative(from: string, to: string): string {\n\t\tvalidateString(from, 'from');\n\t\tvalidateString(to, 'to');\n\n\t\tif (from === to) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst fromOrig = win32.resolve(from);\n\t\tconst toOrig = win32.resolve(to);\n\n\t\tif (fromOrig === toOrig) {\n\t\t\treturn '';\n\t\t}\n\n\t\tfrom = fromOrig.toLowerCase();\n\t\tto = toOrig.toLowerCase();\n\n\t\tif (from === to) {\n\t\t\treturn '';\n\t\t}\n\n\t\t// Trim any leading backslashes\n\t\tlet fromStart = 0;\n\t\twhile (fromStart < from.length &&\n\t\t\tfrom.charCodeAt(fromStart) === CHAR_BACKWARD_SLASH) {\n\t\t\tfromStart++;\n\t\t}\n\t\t// Trim trailing backslashes (applicable to UNC paths only)\n\t\tlet fromEnd = from.length;\n\t\twhile (fromEnd - 1 > fromStart &&\n\t\t\tfrom.charCodeAt(fromEnd - 1) === CHAR_BACKWARD_SLASH) {\n\t\t\tfromEnd--;\n\t\t}\n\t\tconst fromLen = fromEnd - fromStart;\n\n\t\t// Trim any leading backslashes\n\t\tlet toStart = 0;\n\t\twhile (toStart < to.length &&\n\t\t\tto.charCodeAt(toStart) === CHAR_BACKWARD_SLASH) {\n\t\t\ttoStart++;\n\t\t}\n\t\t// Trim trailing backslashes (applicable to UNC paths only)\n\t\tlet toEnd = to.length;\n\t\twhile (toEnd - 1 > toStart &&\n\t\t\tto.charCodeAt(toEnd - 1) === CHAR_BACKWARD_SLASH) {\n\t\t\ttoEnd--;\n\t\t}\n\t\tconst toLen = toEnd - toStart;\n\n\t\t// Compare paths to find the longest common path from root\n\t\tconst length = fromLen < toLen ? fromLen : toLen;\n\t\tlet lastCommonSep = -1;\n\t\tlet i = 0;\n\t\tfor (; i < length; i++) {\n\t\t\tconst fromCode = from.charCodeAt(fromStart + i);\n\t\t\tif (fromCode !== to.charCodeAt(toStart + i)) {\n\t\t\t\tbreak;\n\t\t\t} else if (fromCode === CHAR_BACKWARD_SLASH) {\n\t\t\t\tlastCommonSep = i;\n\t\t\t}\n\t\t}\n\n\t\t// We found a mismatch before the first common path separator was seen, so\n\t\t// return the original `to`.\n\t\tif (i !== length) {\n\t\t\tif (lastCommonSep === -1) {\n\t\t\t\treturn toOrig;\n\t\t\t}\n\t\t} else {\n\t\t\tif (toLen > length) {\n\t\t\t\tif (to.charCodeAt(toStart + i) === CHAR_BACKWARD_SLASH) {\n\t\t\t\t\t// We get here if `from` is the exact base path for `to`.\n\t\t\t\t\t// For example: from='C:\\\\foo\\\\bar'; to='C:\\\\foo\\\\bar\\\\baz'\n\t\t\t\t\treturn toOrig.slice(toStart + i + 1);\n\t\t\t\t}\n\t\t\t\tif (i === 2) {\n\t\t\t\t\t// We get here if `from` is the device root.\n\t\t\t\t\t// For example: from='C:\\\\'; to='C:\\\\foo'\n\t\t\t\t\treturn toOrig.slice(toStart + i);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (fromLen > length) {\n\t\t\t\tif (from.charCodeAt(fromStart + i) === CHAR_BACKWARD_SLASH) {\n\t\t\t\t\t// We get here if `to` is the exact base path for `from`.\n\t\t\t\t\t// For example: from='C:\\\\foo\\\\bar'; to='C:\\\\foo'\n\t\t\t\t\tlastCommonSep = i;\n\t\t\t\t} else if (i === 2) {\n\t\t\t\t\t// We get here if `to` is the device root.\n\t\t\t\t\t// For example: from='C:\\\\foo\\\\bar'; to='C:\\\\'\n\t\t\t\t\tlastCommonSep = 3;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (lastCommonSep === -1) {\n\t\t\t\tlastCommonSep = 0;\n\t\t\t}\n\t\t}\n\n\t\tlet out = '';\n\t\t// Generate the relative path based on the path difference between `to` and\n\t\t// `from`\n\t\tfor (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {\n\t\t\tif (i === fromEnd || from.charCodeAt(i) === CHAR_BACKWARD_SLASH) {\n\t\t\t\tout += out.length === 0 ? '..' : '\\\\..';\n\t\t\t}\n\t\t}\n\n\t\ttoStart += lastCommonSep;\n\n\t\t// Lastly, append the rest of the destination (`to`) path that comes after\n\t\t// the common path parts\n\t\tif (out.length > 0) {\n\t\t\treturn `${out}${toOrig.slice(toStart, toEnd)}`;\n\t\t}\n\n\t\tif (toOrig.charCodeAt(toStart) === CHAR_BACKWARD_SLASH) {\n\t\t\t++toStart;\n\t\t}\n\n\t\treturn toOrig.slice(toStart, toEnd);\n\t},\n\n\ttoNamespacedPath(path: string): string {\n\t\t// Note: this will *probably* throw somewhere.\n\t\tif (typeof path !== 'string') {\n\t\t\treturn path;\n\t\t}\n\n\t\tif (path.length === 0) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst resolvedPath = win32.resolve(path);\n\n\t\tif (resolvedPath.length <= 2) {\n\t\t\treturn path;\n\t\t}\n\n\t\tif (resolvedPath.charCodeAt(0) === CHAR_BACKWARD_SLASH) {\n\t\t\t// Possible UNC root\n\t\t\tif (resolvedPath.charCodeAt(1) === CHAR_BACKWARD_SLASH) {\n\t\t\t\tconst code = resolvedPath.charCodeAt(2);\n\t\t\t\tif (code !== CHAR_QUESTION_MARK && code !== CHAR_DOT) {\n\t\t\t\t\t// Matched non-long UNC root, convert the path to a long UNC path\n\t\t\t\t\treturn `\\\\\\\\?\\\\UNC\\\\${resolvedPath.slice(2)}`;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (isWindowsDeviceRoot(resolvedPath.charCodeAt(0)) &&\n\t\t\tresolvedPath.charCodeAt(1) === CHAR_COLON &&\n\t\t\tresolvedPath.charCodeAt(2) === CHAR_BACKWARD_SLASH) {\n\t\t\t// Matched device root, convert the path to a long UNC path\n\t\t\treturn `\\\\\\\\?\\\\${resolvedPath}`;\n\t\t}\n\n\t\treturn path;\n\t},\n\n\tdirname(path: string): string {\n\t\tvalidateString(path, 'path');\n\t\tconst len = path.length;\n\t\tif (len === 0) {\n\t\t\treturn '.';\n\t\t}\n\t\tlet rootEnd = -1;\n\t\tlet offset = 0;\n\t\tconst code = path.charCodeAt(0);\n\n\t\tif (len === 1) {\n\t\t\t// `path` contains just a path separator, exit early to avoid\n\t\t\t// unnecessary work or a dot.\n\t\t\treturn isPathSeparator(code) ? path : '.';\n\t\t}\n\n\t\t// Try to match a root\n\t\tif (isPathSeparator(code)) {\n\t\t\t// Possible UNC root\n\n\t\t\trootEnd = offset = 1;\n\n\t\t\tif (isPathSeparator(path.charCodeAt(1))) {\n\t\t\t\t// Matched double path separator at beginning\n\t\t\t\tlet j = 2;\n\t\t\t\tlet last = j;\n\t\t\t\t// Match 1 or more non-path separators\n\t\t\t\twhile (j < len && !isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t\tif (j < len && j !== last) {\n\t\t\t\t\t// Matched!\n\t\t\t\t\tlast = j;\n\t\t\t\t\t// Match 1 or more path separators\n\t\t\t\t\twhile (j < len && isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\t\tj++;\n\t\t\t\t\t}\n\t\t\t\t\tif (j < len && j !== last) {\n\t\t\t\t\t\t// Matched!\n\t\t\t\t\t\tlast = j;\n\t\t\t\t\t\t// Match 1 or more non-path separators\n\t\t\t\t\t\twhile (j < len && !isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (j === len) {\n\t\t\t\t\t\t\t// We matched a UNC root only\n\t\t\t\t\t\t\treturn path;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (j !== last) {\n\t\t\t\t\t\t\t// We matched a UNC root with leftovers\n\n\t\t\t\t\t\t\t// Offset by 1 to include the separator after the UNC root to\n\t\t\t\t\t\t\t// treat it as a \"normal root\" on top of a (UNC) root\n\t\t\t\t\t\t\trootEnd = offset = j + 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Possible device root\n\t\t} else if (isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON) {\n\t\t\trootEnd = len > 2 && isPathSeparator(path.charCodeAt(2)) ? 3 : 2;\n\t\t\toffset = rootEnd;\n\t\t}\n\n\t\tlet end = -1;\n\t\tlet matchedSlash = true;\n\t\tfor (let i = len - 1; i >= offset; --i) {\n\t\t\tif (isPathSeparator(path.charCodeAt(i))) {\n\t\t\t\tif (!matchedSlash) {\n\t\t\t\t\tend = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We saw the first non-path separator\n\t\t\t\tmatchedSlash = false;\n\t\t\t}\n\t\t}\n\n\t\tif (end === -1) {\n\t\t\tif (rootEnd === -1) {\n\t\t\t\treturn '.';\n\t\t\t}\n\n\t\t\tend = rootEnd;\n\t\t}\n\t\treturn path.slice(0, end);\n\t},\n\n\tbasename(path: string, ext?: string): string {\n\t\tif (ext !== undefined) {\n\t\t\tvalidateString(ext, 'ext');\n\t\t}\n\t\tvalidateString(path, 'path');\n\t\tlet start = 0;\n\t\tlet end = -1;\n\t\tlet matchedSlash = true;\n\t\tlet i;\n\n\t\t// Check for a drive letter prefix so as not to mistake the following\n\t\t// path separator as an extra separator at the end of the path that can be\n\t\t// disregarded\n\t\tif (path.length >= 2 &&\n\t\t\tisWindowsDeviceRoot(path.charCodeAt(0)) &&\n\t\t\tpath.charCodeAt(1) === CHAR_COLON) {\n\t\t\tstart = 2;\n\t\t}\n\n\t\tif (ext !== undefined && ext.length > 0 && ext.length <= path.length) {\n\t\t\tif (ext === path) {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\tlet extIdx = ext.length - 1;\n\t\t\tlet firstNonSlashEnd = -1;\n\t\t\tfor (i = path.length - 1; i >= start; --i) {\n\t\t\t\tconst code = path.charCodeAt(i);\n\t\t\t\tif (isPathSeparator(code)) {\n\t\t\t\t\t// If we reached a path separator that was not part of a set of path\n\t\t\t\t\t// separators at the end of the string, stop now\n\t\t\t\t\tif (!matchedSlash) {\n\t\t\t\t\t\tstart = i + 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (firstNonSlashEnd === -1) {\n\t\t\t\t\t\t// We saw the first non-path separator, remember this index in case\n\t\t\t\t\t\t// we need it if the extension ends up not matching\n\t\t\t\t\t\tmatchedSlash = false;\n\t\t\t\t\t\tfirstNonSlashEnd = i + 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (extIdx >= 0) {\n\t\t\t\t\t\t// Try to match the explicit extension\n\t\t\t\t\t\tif (code === ext.charCodeAt(extIdx)) {\n\t\t\t\t\t\t\tif (--extIdx === -1) {\n\t\t\t\t\t\t\t\t// We matched the extension, so mark this as the end of our path\n\t\t\t\t\t\t\t\t// component\n\t\t\t\t\t\t\t\tend = i;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Extension does not match, so our result is the entire path\n\t\t\t\t\t\t\t// component\n\t\t\t\t\t\t\textIdx = -1;\n\t\t\t\t\t\t\tend = firstNonSlashEnd;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (start === end) {\n\t\t\t\tend = firstNonSlashEnd;\n\t\t\t} else if (end === -1) {\n\t\t\t\tend = path.length;\n\t\t\t}\n\t\t\treturn path.slice(start, end);\n\t\t}\n\t\tfor (i = path.length - 1; i >= start; --i) {\n\t\t\tif (isPathSeparator(path.charCodeAt(i))) {\n\t\t\t\t// If we reached a path separator that was not part of a set of path\n\t\t\t\t// separators at the end of the string, stop now\n\t\t\t\tif (!matchedSlash) {\n\t\t\t\t\tstart = i + 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else if (end === -1) {\n\t\t\t\t// We saw the first non-path separator, mark this as the end of our\n\t\t\t\t// path component\n\t\t\t\tmatchedSlash = false;\n\t\t\t\tend = i + 1;\n\t\t\t}\n\t\t}\n\n\t\tif (end === -1) {\n\t\t\treturn '';\n\t\t}\n\t\treturn path.slice(start, end);\n\t},\n\n\textname(path: string): string {\n\t\tvalidateString(path, 'path');\n\t\tlet start = 0;\n\t\tlet startDot = -1;\n\t\tlet startPart = 0;\n\t\tlet end = -1;\n\t\tlet matchedSlash = true;\n\t\t// Track the state of characters (if any) we see before our first dot and\n\t\t// after any path separator we find\n\t\tlet preDotState = 0;\n\n\t\t// Check for a drive letter prefix so as not to mistake the following\n\t\t// path separator as an extra separator at the end of the path that can be\n\t\t// disregarded\n\n\t\tif (path.length >= 2 &&\n\t\t\tpath.charCodeAt(1) === CHAR_COLON &&\n\t\t\tisWindowsDeviceRoot(path.charCodeAt(0))) {\n\t\t\tstart = startPart = 2;\n\t\t}\n\n\t\tfor (let i = path.length - 1; i >= start; --i) {\n\t\t\tconst code = path.charCodeAt(i);\n\t\t\tif (isPathSeparator(code)) {\n\t\t\t\t// If we reached a path separator that was not part of a set of path\n\t\t\t\t// separators at the end of the string, stop now\n\t\t\t\tif (!matchedSlash) {\n\t\t\t\t\tstartPart = i + 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (end === -1) {\n\t\t\t\t// We saw the first non-path separator, mark this as the end of our\n\t\t\t\t// extension\n\t\t\t\tmatchedSlash = false;\n\t\t\t\tend = i + 1;\n\t\t\t}\n\t\t\tif (code === CHAR_DOT) {\n\t\t\t\t// If this is our first dot, mark it as the start of our extension\n\t\t\t\tif (startDot === -1) {\n\t\t\t\t\tstartDot = i;\n\t\t\t\t}\n\t\t\t\telse if (preDotState !== 1) {\n\t\t\t\t\tpreDotState = 1;\n\t\t\t\t}\n\t\t\t} else if (startDot !== -1) {\n\t\t\t\t// We saw a non-dot and non-path separator before our dot, so we should\n\t\t\t\t// have a good chance at having a non-empty extension\n\t\t\t\tpreDotState = -1;\n\t\t\t}\n\t\t}\n\n\t\tif (startDot === -1 ||\n\t\t\tend === -1 ||\n\t\t\t// We saw a non-dot character immediately before the dot\n\t\t\tpreDotState === 0 ||\n\t\t\t// The (right-most) trimmed path component is exactly '..'\n\t\t\t(preDotState === 1 &&\n\t\t\t\tstartDot === end - 1 &&\n\t\t\t\tstartDot === startPart + 1)) {\n\t\t\treturn '';\n\t\t}\n\t\treturn path.slice(startDot, end);\n\t},\n\n\tformat: _format.bind(null, '\\\\'),\n\n\tparse(path) {\n\t\tvalidateString(path, 'path');\n\n\t\tconst ret = { root: '', dir: '', base: '', ext: '', name: '' };\n\t\tif (path.length === 0) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tconst len = path.length;\n\t\tlet rootEnd = 0;\n\t\tlet code = path.charCodeAt(0);\n\n\t\tif (len === 1) {\n\t\t\tif (isPathSeparator(code)) {\n\t\t\t\t// `path` contains just a path separator, exit early to avoid\n\t\t\t\t// unnecessary work\n\t\t\t\tret.root = ret.dir = path;\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t\tret.base = ret.name = path;\n\t\t\treturn ret;\n\t\t}\n\t\t// Try to match a root\n\t\tif (isPathSeparator(code)) {\n\t\t\t// Possible UNC root\n\n\t\t\trootEnd = 1;\n\t\t\tif (isPathSeparator(path.charCodeAt(1))) {\n\t\t\t\t// Matched double path separator at beginning\n\t\t\t\tlet j = 2;\n\t\t\t\tlet last = j;\n\t\t\t\t// Match 1 or more non-path separators\n\t\t\t\twhile (j < len && !isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t\tif (j < len && j !== last) {\n\t\t\t\t\t// Matched!\n\t\t\t\t\tlast = j;\n\t\t\t\t\t// Match 1 or more path separators\n\t\t\t\t\twhile (j < len && isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\t\tj++;\n\t\t\t\t\t}\n\t\t\t\t\tif (j < len && j !== last) {\n\t\t\t\t\t\t// Matched!\n\t\t\t\t\t\tlast = j;\n\t\t\t\t\t\t// Match 1 or more non-path separators\n\t\t\t\t\t\twhile (j < len && !isPathSeparator(path.charCodeAt(j))) {\n\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (j === len) {\n\t\t\t\t\t\t\t// We matched a UNC root only\n\t\t\t\t\t\t\trootEnd = j;\n\t\t\t\t\t\t} else if (j !== last) {\n\t\t\t\t\t\t\t// We matched a UNC root with leftovers\n\t\t\t\t\t\t\trootEnd = j + 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON) {\n\t\t\t// Possible device root\n\t\t\tif (len <= 2) {\n\t\t\t\t// `path` contains just a drive root, exit early to avoid\n\t\t\t\t// unnecessary work\n\t\t\t\tret.root = ret.dir = path;\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t\trootEnd = 2;\n\t\t\tif (isPathSeparator(path.charCodeAt(2))) {\n\t\t\t\tif (len === 3) {\n\t\t\t\t\t// `path` contains just a drive root, exit early to avoid\n\t\t\t\t\t// unnecessary work\n\t\t\t\t\tret.root = ret.dir = path;\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\t\t\t\trootEnd = 3;\n\t\t\t}\n\t\t}\n\t\tif (rootEnd > 0) {\n\t\t\tret.root = path.slice(0, rootEnd);\n\t\t}\n\n\t\tlet startDot = -1;\n\t\tlet startPart = rootEnd;\n\t\tlet end = -1;\n\t\tlet matchedSlash = true;\n\t\tlet i = path.length - 1;\n\n\t\t// Track the state of characters (if any) we see before our first dot and\n\t\t// after any path separator we find\n\t\tlet preDotState = 0;\n\n\t\t// Get non-dir info\n\t\tfor (; i >= rootEnd; --i) {\n\t\t\tcode = path.charCodeAt(i);\n\t\t\tif (isPathSeparator(code)) {\n\t\t\t\t// If we reached a path separator that was not part of a set of path\n\t\t\t\t// separators at the end of the string, stop now\n\t\t\t\tif (!matchedSlash) {\n\t\t\t\t\tstartPart = i + 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (end === -1) {\n\t\t\t\t// We saw the first non-path separator, mark this as the end of our\n\t\t\t\t// extension\n\t\t\t\tmatchedSlash = false;\n\t\t\t\tend = i + 1;\n\t\t\t}\n\t\t\tif (code === CHAR_DOT) {\n\t\t\t\t// If this is our first dot, mark it as the start of our extension\n\t\t\t\tif (startDot === -1) {\n\t\t\t\t\tstartDot = i;\n\t\t\t\t} else if (preDotState !== 1) {\n\t\t\t\t\tpreDotState = 1;\n\t\t\t\t}\n\t\t\t} else if (startDot !== -1) {\n\t\t\t\t// We saw a non-dot and non-path separator before our dot, so we should\n\t\t\t\t// have a good chance at having a non-empty extension\n\t\t\t\tpreDotState = -1;\n\t\t\t}\n\t\t}\n\n\t\tif (end !== -1) {\n\t\t\tif (startDot === -1 ||\n\t\t\t\t// We saw a non-dot character immediately before the dot\n\t\t\t\tpreDotState === 0 ||\n\t\t\t\t// The (right-most) trimmed path component is exactly '..'\n\t\t\t\t(preDotState === 1 &&\n\t\t\t\t\tstartDot === end - 1 &&\n\t\t\t\t\tstartDot === startPart + 1)) {\n\t\t\t\tret.base = ret.name = path.slice(startPart, end);\n\t\t\t} else {\n\t\t\t\tret.name = path.slice(startPart, startDot);\n\t\t\t\tret.base = path.slice(startPart, end);\n\t\t\t\tret.ext = path.slice(startDot, end);\n\t\t\t}\n\t\t}\n\n\t\t// If the directory is the root, use the entire root as the `dir` including\n\t\t// the trailing slash if any (`C:\\abc` -> `C:\\`). Otherwise, strip out the\n\t\t// trailing slash (`C:\\abc\\def` -> `C:\\abc`).\n\t\tif (startPart > 0 && startPart !== rootEnd) {\n\t\t\tret.dir = path.slice(0, startPart - 1);\n\t\t} else {\n\t\t\tret.dir = ret.root;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tsep: '\\\\',\n\tdelimiter: ';',\n\twin32: null,\n\tposix: null\n};\n\nexport const posix: IPath = {\n\t// path.resolve([from ...], to)\n\tresolve(...pathSegments: string[]): string {\n\t\tlet resolvedPath = '';\n\t\tlet resolvedAbsolute = false;\n\n\t\tfor (let i = pathSegments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n\t\t\tconst path = i >= 0 ? pathSegments[i] : process.cwd();\n\n\t\t\tvalidateString(path, 'path');\n\n\t\t\t// Skip empty entries\n\t\t\tif (path.length === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tresolvedPath = `${path}/${resolvedPath}`;\n\t\t\tresolvedAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH;\n\t\t}\n\n\t\t// At this point the path should be resolved to a full absolute path, but\n\t\t// handle relative paths to be safe (might happen when process.cwd() fails)\n\n\t\t// Normalize the path\n\t\tresolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/',\n\t\t\tisPosixPathSeparator);\n\n\t\tif (resolvedAbsolute) {\n\t\t\treturn `/${resolvedPath}`;\n\t\t}\n\t\treturn resolvedPath.length > 0 ? resolvedPath : '.';\n\t},\n\n\tnormalize(path: string): string {\n\t\tvalidateString(path, 'path');\n\n\t\tif (path.length === 0) {\n\t\t\treturn '.';\n\t\t}\n\n\t\tconst isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH;\n\t\tconst trailingSeparator =\n\t\t\tpath.charCodeAt(path.length - 1) === CHAR_FORWARD_SLASH;\n\n\t\t// Normalize the path\n\t\tpath = normalizeString(path, !isAbsolute, '/', isPosixPathSeparator);\n\n\t\tif (path.length === 0) {\n\t\t\tif (isAbsolute) {\n\t\t\t\treturn '/';\n\t\t\t}\n\t\t\treturn trailingSeparator ? './' : '.';\n\t\t}\n\t\tif (trailingSeparator) {\n\t\t\tpath += '/';\n\t\t}\n\n\t\treturn isAbsolute ? `/${path}` : path;\n\t},\n\n\tisAbsolute(path: string): boolean {\n\t\tvalidateString(path, 'path');\n\t\treturn path.length > 0 && path.charCodeAt(0) === CHAR_FORWARD_SLASH;\n\t},\n\n\tjoin(...paths: string[]): string {\n\t\tif (paths.length === 0) {\n\t\t\treturn '.';\n\t\t}\n\t\tlet joined;\n\t\tfor (let i = 0; i < paths.length; ++i) {\n\t\t\tconst arg = paths[i];\n\t\t\tvalidateString(arg, 'path');\n\t\t\tif (arg.length > 0) {\n\t\t\t\tif (joined === undefined) {\n\t\t\t\t\tjoined = arg;\n\t\t\t\t} else {\n\t\t\t\t\tjoined += `/${arg}`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (joined === undefined) {\n\t\t\treturn '.';\n\t\t}\n\t\treturn posix.normalize(joined);\n\t},\n\n\trelative(from: string, to: string): string {\n\t\tvalidateString(from, 'from');\n\t\tvalidateString(to, 'to');\n\n\t\tif (from === to) {\n\t\t\treturn '';\n\t\t}\n\n\t\t// Trim leading forward slashes.\n\t\tfrom = posix.resolve(from);\n\t\tto = posix.resolve(to);\n\n\t\tif (from === to) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst fromStart = 1;\n\t\tconst fromEnd = from.length;\n\t\tconst fromLen = fromEnd - fromStart;\n\t\tconst toStart = 1;\n\t\tconst toLen = to.length - toStart;\n\n\t\t// Compare paths to find the longest common path from root\n\t\tconst length = (fromLen < toLen ? fromLen : toLen);\n\t\tlet lastCommonSep = -1;\n\t\tlet i = 0;\n\t\tfor (; i < length; i++) {\n\t\t\tconst fromCode = from.charCodeAt(fromStart + i);\n\t\t\tif (fromCode !== to.charCodeAt(toStart + i)) {\n\t\t\t\tbreak;\n\t\t\t} else if (fromCode === CHAR_FORWARD_SLASH) {\n\t\t\t\tlastCommonSep = i;\n\t\t\t}\n\t\t}\n\t\tif (i === length) {\n\t\t\tif (toLen > length) {\n\t\t\t\tif (to.charCodeAt(toStart + i) === CHAR_FORWARD_SLASH) {\n\t\t\t\t\t// We get here if `from` is the exact base path for `to`.\n\t\t\t\t\t// For example: from='/foo/bar'; to='/foo/bar/baz'\n\t\t\t\t\treturn to.slice(toStart + i + 1);\n\t\t\t\t}\n\t\t\t\tif (i === 0) {\n\t\t\t\t\t// We get here if `from` is the root\n\t\t\t\t\t// For example: from='/'; to='/foo'\n\t\t\t\t\treturn to.slice(toStart + i);\n\t\t\t\t}\n\t\t\t} else if (fromLen > length) {\n\t\t\t\tif (from.charCodeAt(fromStart + i) === CHAR_FORWARD_SLASH) {\n\t\t\t\t\t// We get here if `to` is the exact base path for `from`.\n\t\t\t\t\t// For example: from='/foo/bar/baz'; to='/foo/bar'\n\t\t\t\t\tlastCommonSep = i;\n\t\t\t\t} else if (i === 0) {\n\t\t\t\t\t// We get here if `to` is the root.\n\t\t\t\t\t// For example: from='/foo/bar'; to='/'\n\t\t\t\t\tlastCommonSep = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet out = '';\n\t\t// Generate the relative path based on the path difference between `to`\n\t\t// and `from`.\n\t\tfor (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {\n\t\t\tif (i === fromEnd || from.charCodeAt(i) === CHAR_FORWARD_SLASH) {\n\t\t\t\tout += out.length === 0 ? '..' : '/..';\n\t\t\t}\n\t\t}\n\n\t\t// Lastly, append the rest of the destination (`to`) path that comes after\n\t\t// the common path parts.\n\t\treturn `${out}${to.slice(toStart + lastCommonSep)}`;\n\t},\n\n\ttoNamespacedPath(path: string): string {\n\t\t// Non-op on posix systems\n\t\treturn path;\n\t},\n\n\tdirname(path: string): string {\n\t\tvalidateString(path, 'path');\n\t\tif (path.length === 0) {\n\t\t\treturn '.';\n\t\t}\n\t\tconst hasRoot = path.charCodeAt(0) === CHAR_FORWARD_SLASH;\n\t\tlet end = -1;\n\t\tlet matchedSlash = true;\n\t\tfor (let i = path.length - 1; i >= 1; --i) {\n\t\t\tif (path.charCodeAt(i) === CHAR_FORWARD_SLASH) {\n\t\t\t\tif (!matchedSlash) {\n\t\t\t\t\tend = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We saw the first non-path separator\n\t\t\t\tmatchedSlash = false;\n\t\t\t}\n\t\t}\n\n\t\tif (end === -1) {\n\t\t\treturn hasRoot ? '/' : '.';\n\t\t}\n\t\tif (hasRoot && end === 1) {\n\t\t\treturn '//';\n\t\t}\n\t\treturn path.slice(0, end);\n\t},\n\n\tbasename(path: string, ext?: string): string {\n\t\tif (ext !== undefined) {\n\t\t\tvalidateString(ext, 'ext');\n\t\t}\n\t\tvalidateString(path, 'path');\n\n\t\tlet start = 0;\n\t\tlet end = -1;\n\t\tlet matchedSlash = true;\n\t\tlet i;\n\n\t\tif (ext !== undefined && ext.length > 0 && ext.length <= path.length) {\n\t\t\tif (ext === path) {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\tlet extIdx = ext.length - 1;\n\t\t\tlet firstNonSlashEnd = -1;\n\t\t\tfor (i = path.length - 1; i >= 0; --i) {\n\t\t\t\tconst code = path.charCodeAt(i);\n\t\t\t\tif (code === CHAR_FORWARD_SLASH) {\n\t\t\t\t\t// If we reached a path separator that was not part of a set of path\n\t\t\t\t\t// separators at the end of the string, stop now\n\t\t\t\t\tif (!matchedSlash) {\n\t\t\t\t\t\tstart = i + 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (firstNonSlashEnd === -1) {\n\t\t\t\t\t\t// We saw the first non-path separator, remember this index in case\n\t\t\t\t\t\t// we need it if the extension ends up not matching\n\t\t\t\t\t\tmatchedSlash = false;\n\t\t\t\t\t\tfirstNonSlashEnd = i + 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (extIdx >= 0) {\n\t\t\t\t\t\t// Try to match the explicit extension\n\t\t\t\t\t\tif (code === ext.charCodeAt(extIdx)) {\n\t\t\t\t\t\t\tif (--extIdx === -1) {\n\t\t\t\t\t\t\t\t// We matched the extension, so mark this as the end of our path\n\t\t\t\t\t\t\t\t// component\n\t\t\t\t\t\t\t\tend = i;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Extension does not match, so our result is the entire path\n\t\t\t\t\t\t\t// component\n\t\t\t\t\t\t\textIdx = -1;\n\t\t\t\t\t\t\tend = firstNonSlashEnd;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (start === end) {\n\t\t\t\tend = firstNonSlashEnd;\n\t\t\t} else if (end === -1) {\n\t\t\t\tend = path.length;\n\t\t\t}\n\t\t\treturn path.slice(start, end);\n\t\t}\n\t\tfor (i = path.length - 1; i >= 0; --i) {\n\t\t\tif (path.charCodeAt(i) === CHAR_FORWARD_SLASH) {\n\t\t\t\t// If we reached a path separator that was not part of a set of path\n\t\t\t\t// separators at the end of the string, stop now\n\t\t\t\tif (!matchedSlash) {\n\t\t\t\t\tstart = i + 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else if (end === -1) {\n\t\t\t\t// We saw the first non-path separator, mark this as the end of our\n\t\t\t\t// path component\n\t\t\t\tmatchedSlash = false;\n\t\t\t\tend = i + 1;\n\t\t\t}\n\t\t}\n\n\t\tif (end === -1) {\n\t\t\treturn '';\n\t\t}\n\t\treturn path.slice(start, end);\n\t},\n\n\textname(path: string): string {\n\t\tvalidateString(path, 'path');\n\t\tlet startDot = -1;\n\t\tlet startPart = 0;\n\t\tlet end = -1;\n\t\tlet matchedSlash = true;\n\t\t// Track the state of characters (if any) we see before our first dot and\n\t\t// after any path separator we find\n\t\tlet preDotState = 0;\n\t\tfor (let i = path.length - 1; i >= 0; --i) {\n\t\t\tconst code = path.charCodeAt(i);\n\t\t\tif (code === CHAR_FORWARD_SLASH) {\n\t\t\t\t// If we reached a path separator that was not part of a set of path\n\t\t\t\t// separators at the end of the string, stop now\n\t\t\t\tif (!matchedSlash) {\n\t\t\t\t\tstartPart = i + 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (end === -1) {\n\t\t\t\t// We saw the first non-path separator, mark this as the end of our\n\t\t\t\t// extension\n\t\t\t\tmatchedSlash = false;\n\t\t\t\tend = i + 1;\n\t\t\t}\n\t\t\tif (code === CHAR_DOT) {\n\t\t\t\t// If this is our first dot, mark it as the start of our extension\n\t\t\t\tif (startDot === -1) {\n\t\t\t\t\tstartDot = i;\n\t\t\t\t}\n\t\t\t\telse if (preDotState !== 1) {\n\t\t\t\t\tpreDotState = 1;\n\t\t\t\t}\n\t\t\t} else if (startDot !== -1) {\n\t\t\t\t// We saw a non-dot and non-path separator before our dot, so we should\n\t\t\t\t// have a good chance at having a non-empty extension\n\t\t\t\tpreDotState = -1;\n\t\t\t}\n\t\t}\n\n\t\tif (startDot === -1 ||\n\t\t\tend === -1 ||\n\t\t\t// We saw a non-dot character immediately before the dot\n\t\t\tpreDotState === 0 ||\n\t\t\t// The (right-most) trimmed path component is exactly '..'\n\t\t\t(preDotState === 1 &&\n\t\t\t\tstartDot === end - 1 &&\n\t\t\t\tstartDot === startPart + 1)) {\n\t\t\treturn '';\n\t\t}\n\t\treturn path.slice(startDot, end);\n\t},\n\n\tformat: _format.bind(null, '/'),\n\n\tparse(path: string): ParsedPath {\n\t\tvalidateString(path, 'path');\n\n\t\tconst ret = { root: '', dir: '', base: '', ext: '', name: '' };\n\t\tif (path.length === 0) {\n\t\t\treturn ret;\n\t\t}\n\t\tconst isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH;\n\t\tlet start;\n\t\tif (isAbsolute) {\n\t\t\tret.root = '/';\n\t\t\tstart = 1;\n\t\t} else {\n\t\t\tstart = 0;\n\t\t}\n\t\tlet startDot = -1;\n\t\tlet startPart = 0;\n\t\tlet end = -1;\n\t\tlet matchedSlash = true;\n\t\tlet i = path.length - 1;\n\n\t\t// Track the state of characters (if any) we see before our first dot and\n\t\t// after any path separator we find\n\t\tlet preDotState = 0;\n\n\t\t// Get non-dir info\n\t\tfor (; i >= start; --i) {\n\t\t\tconst code = path.charCodeAt(i);\n\t\t\tif (code === CHAR_FORWARD_SLASH) {\n\t\t\t\t// If we reached a path separator that was not part of a set of path\n\t\t\t\t// separators at the end of the string, stop now\n\t\t\t\tif (!matchedSlash) {\n\t\t\t\t\tstartPart = i + 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (end === -1) {\n\t\t\t\t// We saw the first non-path separator, mark this as the end of our\n\t\t\t\t// extension\n\t\t\t\tmatchedSlash = false;\n\t\t\t\tend = i + 1;\n\t\t\t}\n\t\t\tif (code === CHAR_DOT) {\n\t\t\t\t// If this is our first dot, mark it as the start of our extension\n\t\t\t\tif (startDot === -1) {\n\t\t\t\t\tstartDot = i;\n\t\t\t\t} else if (preDotState !== 1) {\n\t\t\t\t\tpreDotState = 1;\n\t\t\t\t}\n\t\t\t} else if (startDot !== -1) {\n\t\t\t\t// We saw a non-dot and non-path separator before our dot, so we should\n\t\t\t\t// have a good chance at having a non-empty extension\n\t\t\t\tpreDotState = -1;\n\t\t\t}\n\t\t}\n\n\t\tif (end !== -1) {\n\t\t\tconst start = startPart === 0 && isAbsolute ? 1 : startPart;\n\t\t\tif (startDot === -1 ||\n\t\t\t\t// We saw a non-dot character immediately before the dot\n\t\t\t\tpreDotState === 0 ||\n\t\t\t\t// The (right-most) trimmed path component is exactly '..'\n\t\t\t\t(preDotState === 1 &&\n\t\t\t\t\tstartDot === end - 1 &&\n\t\t\t\t\tstartDot === startPart + 1)) {\n\t\t\t\tret.base = ret.name = path.slice(start, end);\n\t\t\t} else {\n\t\t\t\tret.name = path.slice(start, startDot);\n\t\t\t\tret.base = path.slice(start, end);\n\t\t\t\tret.ext = path.slice(startDot, end);\n\t\t\t}\n\t\t}\n\n\t\tif (startPart > 0) {\n\t\t\tret.dir = path.slice(0, startPart - 1);\n\t\t} else if (isAbsolute) {\n\t\t\tret.dir = '/';\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tsep: '/',\n\tdelimiter: ':',\n\twin32: null,\n\tposix: null\n};\n\nposix.win32 = win32.win32 = win32;\nposix.posix = win32.posix = posix;\n\nexport const normalize = (process.platform === 'win32' ? win32.normalize : posix.normalize);\nexport const resolve = (process.platform === 'win32' ? win32.resolve : posix.resolve);\nexport const relative = (process.platform === 'win32' ? win32.relative : posix.relative);\nexport const dirname = (process.platform === 'win32' ? win32.dirname : posix.dirname);\nexport const basename = (process.platform === 'win32' ? win32.basename : posix.basename);\nexport const extname = (process.platform === 'win32' ? win32.extname : posix.extname);\nexport const sep = (process.platform === 'win32' ? win32.sep : posix.sep);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport interface IRange {\n\tstart: number;\n\tend: number;\n}\n\nexport namespace Range {\n\n\t/**\n\t * Returns the intersection between two ranges as a range itself.\n\t * Returns `{ start: 0, end: 0 }` if the intersection is empty.\n\t */\n\texport function intersect(one: IRange, other: IRange): IRange {\n\t\tif (one.start >= other.end || other.start >= one.end) {\n\t\t\treturn { start: 0, end: 0 };\n\t\t}\n\n\t\tconst start = Math.max(one.start, other.start);\n\t\tconst end = Math.min(one.end, other.end);\n\n\t\tif (end - start <= 0) {\n\t\t\treturn { start: 0, end: 0 };\n\t\t}\n\n\t\treturn { start, end };\n\t}\n\n\texport function isEmpty(range: IRange): boolean {\n\t\treturn range.end - range.start <= 0;\n\t}\n\n\texport function intersects(one: IRange, other: IRange): boolean {\n\t\treturn !isEmpty(intersect(one, other));\n\t}\n\n\texport function relativeComplement(one: IRange, other: IRange): IRange[] {\n\t\tconst result: IRange[] = [];\n\t\tconst first = { start: one.start, end: Math.min(other.start, one.end) };\n\t\tconst second = { start: Math.max(other.end, one.start), end: one.end };\n\n\t\tif (!isEmpty(first)) {\n\t\t\tresult.push(first);\n\t\t}\n\n\t\tif (!isEmpty(second)) {\n\t\t\tresult.push(second);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IRange, Range } from 'vs/base/common/range';\n\nexport interface IItem {\n\tsize: number;\n}\n\nexport interface IRangedGroup {\n\trange: IRange;\n\tsize: number;\n}\n\n/**\n * Returns the intersection between a ranged group and a range.\n * Returns `[]` if the intersection is empty.\n */\nexport function groupIntersect(range: IRange, groups: IRangedGroup[]): IRangedGroup[] {\n\tconst result: IRangedGroup[] = [];\n\n\tfor (let r of groups) {\n\t\tif (range.start >= r.range.end) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (range.end < r.range.start) {\n\t\t\tbreak;\n\t\t}\n\n\t\tconst intersection = Range.intersect(range, r.range);\n\n\t\tif (Range.isEmpty(intersection)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult.push({\n\t\t\trange: intersection,\n\t\t\tsize: r.size\n\t\t});\n\t}\n\n\treturn result;\n}\n\n/**\n * Shifts a range by that `much`.\n */\nexport function shift({ start, end }: IRange, much: number): IRange {\n\treturn { start: start + much, end: end + much };\n}\n\n/**\n * Consolidates a collection of ranged groups.\n *\n * Consolidation is the process of merging consecutive ranged groups\n * that share the same `size`.\n */\nexport function consolidate(groups: IRangedGroup[]): IRangedGroup[] {\n\tconst result: IRangedGroup[] = [];\n\tlet previousGroup: IRangedGroup | null = null;\n\n\tfor (let group of groups) {\n\t\tconst start = group.range.start;\n\t\tconst end = group.range.end;\n\t\tconst size = group.size;\n\n\t\tif (previousGroup && size === previousGroup.size) {\n\t\t\tpreviousGroup.range.end = end;\n\t\t\tcontinue;\n\t\t}\n\n\t\tpreviousGroup = { range: { start, end }, size };\n\t\tresult.push(previousGroup);\n\t}\n\n\treturn result;\n}\n\n/**\n * Concatenates several collections of ranged groups into a single\n * collection.\n */\nfunction concat(...groups: IRangedGroup[][]): IRangedGroup[] {\n\treturn consolidate(groups.reduce((r, g) => r.concat(g), []));\n}\n\nexport class RangeMap {\n\n\tprivate groups: IRangedGroup[] = [];\n\tprivate _size = 0;\n\n\tsplice(index: number, deleteCount: number, items: IItem[] = []): void {\n\t\tconst diff = items.length - deleteCount;\n\t\tconst before = groupIntersect({ start: 0, end: index }, this.groups);\n\t\tconst after = groupIntersect({ start: index + deleteCount, end: Number.POSITIVE_INFINITY }, this.groups)\n\t\t\t.map(g => ({ range: shift(g.range, diff), size: g.size }));\n\n\t\tconst middle = items.map((item, i) => ({\n\t\t\trange: { start: index + i, end: index + i + 1 },\n\t\t\tsize: item.size\n\t\t}));\n\n\t\tthis.groups = concat(before, middle, after);\n\t\tthis._size = this.groups.reduce((t, g) => t + (g.size * (g.range.end - g.range.start)), 0);\n\t}\n\n\t/**\n\t * Returns the number of items in the range map.\n\t */\n\tget count(): number {\n\t\tconst len = this.groups.length;\n\n\t\tif (!len) {\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn this.groups[len - 1].range.end;\n\t}\n\n\t/**\n\t * Returns the sum of the sizes of all items in the range map.\n\t */\n\tget size(): number {\n\t\treturn this._size;\n\t}\n\n\t/**\n\t * Returns the index of the item at the given position.\n\t */\n\tindexAt(position: number): number {\n\t\tif (position < 0) {\n\t\t\treturn -1;\n\t\t}\n\n\t\tlet index = 0;\n\t\tlet size = 0;\n\n\t\tfor (let group of this.groups) {\n\t\t\tconst count = group.range.end - group.range.start;\n\t\t\tconst newSize = size + (count * group.size);\n\n\t\t\tif (position < newSize) {\n\t\t\t\treturn index + Math.floor((position - size) / group.size);\n\t\t\t}\n\n\t\t\tindex += count;\n\t\t\tsize = newSize;\n\t\t}\n\n\t\treturn index;\n\t}\n\n\t/**\n\t * Returns the index of the item right after the item at the\n\t * index of the given position.\n\t */\n\tindexAfter(position: number): number {\n\t\treturn Math.min(this.indexAt(position) + 1, this.count);\n\t}\n\n\t/**\n\t * Returns the start position of the item at the given index.\n\t */\n\tpositionAt(index: number): number {\n\t\tif (index < 0) {\n\t\t\treturn -1;\n\t\t}\n\n\t\tlet position = 0;\n\t\tlet count = 0;\n\n\t\tfor (let group of this.groups) {\n\t\t\tconst groupCount = group.range.end - group.range.start;\n\t\t\tconst newCount = count + groupCount;\n\n\t\t\tif (index < newCount) {\n\t\t\t\treturn position + ((index - count) * group.size);\n\t\t\t}\n\n\t\t\tposition += groupCount * group.size;\n\t\t\tcount = newCount;\n\t\t}\n\n\t\treturn -1;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { globals } from 'vs/base/common/platform';\n\nconst hasPerformanceNow = (globals.performance && typeof globals.performance.now === 'function');\n\nexport class StopWatch {\n\n\tprivate _highResolution: boolean;\n\tprivate _startTime: number;\n\tprivate _stopTime: number;\n\n\tpublic static create(highResolution: boolean = true): StopWatch {\n\t\treturn new StopWatch(highResolution);\n\t}\n\n\tconstructor(highResolution: boolean) {\n\t\tthis._highResolution = hasPerformanceNow && highResolution;\n\t\tthis._startTime = this._now();\n\t\tthis._stopTime = -1;\n\t}\n\n\tpublic stop(): void {\n\t\tthis._stopTime = this._now();\n\t}\n\n\tpublic elapsed(): number {\n\t\tif (this._stopTime !== -1) {\n\t\t\treturn this._stopTime - this._startTime;\n\t\t}\n\t\treturn this._now() - this._startTime;\n\t}\n\n\tprivate _now(): number {\n\t\treturn this._highResolution ? globals.performance.now() : Date.now();\n\t}\n}\n","\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport { combinedDisposable, Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { LinkedList } from 'vs/base/common/linkedList';\nimport { StopWatch } from 'vs/base/common/stopwatch';\n\n/**\n * To an event a function with one or zero parameters\n * can be subscribed. The event is the subscriber function itself.\n */\nexport interface Event {\n\t(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable;\n}\n\nexport namespace Event {\n\texport const None: Event = () => Disposable.None;\n\n\t/**\n\t * Given an event, returns another event which only fires once.\n\t */\n\texport function once(event: Event): Event {\n\t\treturn (listener, thisArgs = null, disposables?) => {\n\t\t\t// we need this, in case the event fires during the listener call\n\t\t\tlet didFire = false;\n\t\t\tlet result: IDisposable;\n\t\t\tresult = event(e => {\n\t\t\t\tif (didFire) {\n\t\t\t\t\treturn;\n\t\t\t\t} else if (result) {\n\t\t\t\t\tresult.dispose();\n\t\t\t\t} else {\n\t\t\t\t\tdidFire = true;\n\t\t\t\t}\n\n\t\t\t\treturn listener.call(thisArgs, e);\n\t\t\t}, null, disposables);\n\n\t\t\tif (didFire) {\n\t\t\t\tresult.dispose();\n\t\t\t}\n\n\t\t\treturn result;\n\t\t};\n\t}\n\n\t/**\n\t * @deprecated DO NOT use, this leaks memory\n\t */\n\texport function map(event: Event, map: (i: I) => O): Event {\n\t\treturn snapshot((listener, thisArgs = null, disposables?) => event(i => listener.call(thisArgs, map(i)), null, disposables));\n\t}\n\n\t/**\n\t * @deprecated DO NOT use, this leaks memory\n\t */\n\texport function forEach(event: Event, each: (i: I) => void): Event {\n\t\treturn snapshot((listener, thisArgs = null, disposables?) => event(i => { each(i); listener.call(thisArgs, i); }, null, disposables));\n\t}\n\n\t/**\n\t * @deprecated DO NOT use, this leaks memory\n\t */\n\texport function filter(event: Event, filter: (e: T | U) => e is T): Event;\n\texport function filter(event: Event, filter: (e: T) => boolean): Event;\n\texport function filter(event: Event, filter: (e: T | R) => e is R): Event;\n\texport function filter(event: Event, filter: (e: T) => boolean): Event {\n\t\treturn snapshot((listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables));\n\t}\n\n\t/**\n\t * Given an event, returns the same event but typed as `Event`.\n\t */\n\texport function signal(event: Event): Event {\n\t\treturn event as Event as Event;\n\t}\n\n\t/**\n\t * Given a collection of events, returns a single event which emits\n\t * whenever any of the provided events emit.\n\t */\n\texport function any(...events: Event[]): Event;\n\texport function any(...events: Event[]): Event;\n\texport function any(...events: Event[]): Event {\n\t\treturn (listener, thisArgs = null, disposables?) => combinedDisposable(...events.map(event => event(e => listener.call(thisArgs, e), null, disposables)));\n\t}\n\n\t/**\n\t * @deprecated DO NOT use, this leaks memory\n\t */\n\texport function reduce(event: Event, merge: (last: O | undefined, event: I) => O, initial?: O): Event {\n\t\tlet output: O | undefined = initial;\n\n\t\treturn map(event, e => {\n\t\t\toutput = merge(output, e);\n\t\t\treturn output;\n\t\t});\n\t}\n\n\t/**\n\t * @deprecated DO NOT use, this leaks memory\n\t */\n\tfunction snapshot(event: Event): Event {\n\t\tlet listener: IDisposable;\n\t\tconst emitter = new Emitter({\n\t\t\tonFirstListenerAdd() {\n\t\t\t\tlistener = event(emitter.fire, emitter);\n\t\t\t},\n\t\t\tonLastListenerRemove() {\n\t\t\t\tlistener.dispose();\n\t\t\t}\n\t\t});\n\n\t\treturn emitter.event;\n\t}\n\n\texport function debouncedListener(event: Event, listener: (data: O) => any, merge: (last: O | undefined, event: T) => O, delay: number = 100, leading: boolean = false): IDisposable {\n\n\t\tlet output: O | undefined = undefined;\n\t\tlet handle: any = undefined;\n\t\tlet numDebouncedCalls = 0;\n\n\t\treturn event(cur => {\n\t\t\tnumDebouncedCalls++;\n\t\t\toutput = merge(output, cur);\n\n\t\t\tif (leading && !handle) {\n\t\t\t\tlistener(output);\n\t\t\t\toutput = undefined;\n\t\t\t}\n\n\t\t\tclearTimeout(handle);\n\t\t\thandle = setTimeout(() => {\n\t\t\t\tconst _output = output;\n\t\t\t\toutput = undefined;\n\t\t\t\thandle = undefined;\n\t\t\t\tif (!leading || numDebouncedCalls > 1) {\n\t\t\t\t\tlistener(_output!);\n\t\t\t\t}\n\n\t\t\t\tnumDebouncedCalls = 0;\n\t\t\t}, delay);\n\t\t});\n\t}\n\n\t/**\n\t * @deprecated this leaks memory, {@link debouncedListener} or {@link DebounceEmitter} instead\n\t */\n\texport function debounce(event: Event, merge: (last: T | undefined, event: T) => T, delay?: number, leading?: boolean, leakWarningThreshold?: number): Event;\n\t/**\n\t * @deprecated this leaks memory, {@link debouncedListener} or {@link DebounceEmitter} instead\n\t */\n\texport function debounce(event: Event, merge: (last: O | undefined, event: I) => O, delay?: number, leading?: boolean, leakWarningThreshold?: number): Event;\n\t/**\n\t * @deprecated this leaks memory, {@link debouncedListener} or {@link DebounceEmitter} instead\n\t */\n\texport function debounce(event: Event, merge: (last: O | undefined, event: I) => O, delay: number = 100, leading = false, leakWarningThreshold?: number): Event {\n\n\t\tlet subscription: IDisposable;\n\t\tlet output: O | undefined = undefined;\n\t\tlet handle: any = undefined;\n\t\tlet numDebouncedCalls = 0;\n\n\t\tconst emitter = new Emitter({\n\t\t\tleakWarningThreshold,\n\t\t\tonFirstListenerAdd() {\n\t\t\t\tsubscription = event(cur => {\n\t\t\t\t\tnumDebouncedCalls++;\n\t\t\t\t\toutput = merge(output, cur);\n\n\t\t\t\t\tif (leading && !handle) {\n\t\t\t\t\t\temitter.fire(output);\n\t\t\t\t\t\toutput = undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tclearTimeout(handle);\n\t\t\t\t\thandle = setTimeout(() => {\n\t\t\t\t\t\tconst _output = output;\n\t\t\t\t\t\toutput = undefined;\n\t\t\t\t\t\thandle = undefined;\n\t\t\t\t\t\tif (!leading || numDebouncedCalls > 1) {\n\t\t\t\t\t\t\temitter.fire(_output!);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tnumDebouncedCalls = 0;\n\t\t\t\t\t}, delay);\n\t\t\t\t});\n\t\t\t},\n\t\t\tonLastListenerRemove() {\n\t\t\t\tsubscription.dispose();\n\t\t\t}\n\t\t});\n\n\t\treturn emitter.event;\n\t}\n\n\t/**\n\t * @deprecated DO NOT use, this leaks memory\n\t */\n\texport function latch(event: Event, equals: (a: T, b: T) => boolean = (a, b) => a === b): Event {\n\t\tlet firstCall = true;\n\t\tlet cache: T;\n\n\t\treturn filter(event, value => {\n\t\t\tconst shouldEmit = firstCall || !equals(value, cache);\n\t\t\tfirstCall = false;\n\t\t\tcache = value;\n\t\t\treturn shouldEmit;\n\t\t});\n\t}\n\n\t/**\n\t * @deprecated DO NOT use, this leaks memory\n\t */\n\texport function split(event: Event, isT: (e: T | U) => e is T): [Event, Event] {\n\t\treturn [\n\t\t\tEvent.filter(event, isT),\n\t\t\tEvent.filter(event, e => !isT(e)) as Event,\n\t\t];\n\t}\n\n\t/**\n\t * @deprecated DO NOT use, this leaks memory\n\t */\n\texport function buffer(event: Event, flushAfterTimeout = false, _buffer: T[] = []): Event {\n\t\tlet buffer: T[] | null = _buffer.slice();\n\n\t\tlet listener: IDisposable | null = event(e => {\n\t\t\tif (buffer) {\n\t\t\t\tbuffer.push(e);\n\t\t\t} else {\n\t\t\t\temitter.fire(e);\n\t\t\t}\n\t\t});\n\n\t\tconst flush = () => {\n\t\t\tif (buffer) {\n\t\t\t\tbuffer.forEach(e => emitter.fire(e));\n\t\t\t}\n\t\t\tbuffer = null;\n\t\t};\n\n\t\tconst emitter = new Emitter({\n\t\t\tonFirstListenerAdd() {\n\t\t\t\tif (!listener) {\n\t\t\t\t\tlistener = event(e => emitter.fire(e));\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tonFirstListenerDidAdd() {\n\t\t\t\tif (buffer) {\n\t\t\t\t\tif (flushAfterTimeout) {\n\t\t\t\t\t\tsetTimeout(flush);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tflush();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tonLastListenerRemove() {\n\t\t\t\tif (listener) {\n\t\t\t\t\tlistener.dispose();\n\t\t\t\t}\n\t\t\t\tlistener = null;\n\t\t\t}\n\t\t});\n\n\t\treturn emitter.event;\n\t}\n\n\texport interface IChainableEvent {\n\t\tevent: Event;\n\t\tmap(fn: (i: T) => O): IChainableEvent;\n\t\tforEach(fn: (i: T) => void): IChainableEvent;\n\t\tfilter(fn: (e: T) => boolean): IChainableEvent;\n\t\tfilter(fn: (e: T | R) => e is R): IChainableEvent;\n\t\treduce(merge: (last: R | undefined, event: T) => R, initial?: R): IChainableEvent;\n\t\tlatch(): IChainableEvent;\n\t\tdebounce(merge: (last: T | undefined, event: T) => T, delay?: number, leading?: boolean, leakWarningThreshold?: number): IChainableEvent;\n\t\tdebounce(merge: (last: R | undefined, event: T) => R, delay?: number, leading?: boolean, leakWarningThreshold?: number): IChainableEvent;\n\t\ton(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable;\n\t\tonce(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable;\n\t}\n\n\tclass ChainableEvent implements IChainableEvent {\n\n\t\tconstructor(readonly event: Event) { }\n\n\t\tmap(fn: (i: T) => O): IChainableEvent {\n\t\t\treturn new ChainableEvent(map(this.event, fn));\n\t\t}\n\n\t\tforEach(fn: (i: T) => void): IChainableEvent {\n\t\t\treturn new ChainableEvent(forEach(this.event, fn));\n\t\t}\n\n\t\tfilter(fn: (e: T) => boolean): IChainableEvent;\n\t\tfilter(fn: (e: T | R) => e is R): IChainableEvent;\n\t\tfilter(fn: (e: T) => boolean): IChainableEvent {\n\t\t\treturn new ChainableEvent(filter(this.event, fn));\n\t\t}\n\n\t\treduce(merge: (last: R | undefined, event: T) => R, initial?: R): IChainableEvent {\n\t\t\treturn new ChainableEvent(reduce(this.event, merge, initial));\n\t\t}\n\n\t\tlatch(): IChainableEvent {\n\t\t\treturn new ChainableEvent(latch(this.event));\n\t\t}\n\n\t\tdebounce(merge: (last: T | undefined, event: T) => T, delay?: number, leading?: boolean, leakWarningThreshold?: number): IChainableEvent;\n\t\tdebounce(merge: (last: R | undefined, event: T) => R, delay?: number, leading?: boolean, leakWarningThreshold?: number): IChainableEvent;\n\t\tdebounce(merge: (last: R | undefined, event: T) => R, delay: number = 100, leading = false, leakWarningThreshold?: number): IChainableEvent {\n\t\t\treturn new ChainableEvent(debounce(this.event, merge, delay, leading, leakWarningThreshold));\n\t\t}\n\n\t\ton(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[] | DisposableStore) {\n\t\t\treturn this.event(listener, thisArgs, disposables);\n\t\t}\n\n\t\tonce(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[]) {\n\t\t\treturn once(this.event)(listener, thisArgs, disposables);\n\t\t}\n\t}\n\n\t/**\n\t * @deprecated DO NOT use, this leaks memory\n\t */\n\texport function chain(event: Event): IChainableEvent {\n\t\treturn new ChainableEvent(event);\n\t}\n\n\texport interface NodeEventEmitter {\n\t\ton(event: string | symbol, listener: Function): unknown;\n\t\tremoveListener(event: string | symbol, listener: Function): unknown;\n\t}\n\n\texport function fromNodeEventEmitter(emitter: NodeEventEmitter, eventName: string, map: (...args: any[]) => T = id => id): Event {\n\t\tconst fn = (...args: any[]) => result.fire(map(...args));\n\t\tconst onFirstListenerAdd = () => emitter.on(eventName, fn);\n\t\tconst onLastListenerRemove = () => emitter.removeListener(eventName, fn);\n\t\tconst result = new Emitter({ onFirstListenerAdd, onLastListenerRemove });\n\n\t\treturn result.event;\n\t}\n\n\texport interface DOMEventEmitter {\n\t\taddEventListener(event: string | symbol, listener: Function): void;\n\t\tremoveEventListener(event: string | symbol, listener: Function): void;\n\t}\n\n\texport function fromDOMEventEmitter(emitter: DOMEventEmitter, eventName: string, map: (...args: any[]) => T = id => id): Event {\n\t\tconst fn = (...args: any[]) => result.fire(map(...args));\n\t\tconst onFirstListenerAdd = () => emitter.addEventListener(eventName, fn);\n\t\tconst onLastListenerRemove = () => emitter.removeEventListener(eventName, fn);\n\t\tconst result = new Emitter({ onFirstListenerAdd, onLastListenerRemove });\n\n\t\treturn result.event;\n\t}\n\n\texport function toPromise(event: Event): Promise {\n\t\treturn new Promise(resolve => once(event)(resolve));\n\t}\n\n\texport function runAndSubscribe(event: Event, handler: (e: T | undefined) => any): IDisposable {\n\t\thandler(undefined);\n\t\treturn event(e => handler(e));\n\t}\n\n\texport function runAndSubscribeWithStore(event: Event, handler: (e: T | undefined, disposableStore: DisposableStore) => any): IDisposable {\n\t\tlet store: DisposableStore | null = null;\n\n\t\tfunction run(e: T | undefined) {\n\t\t\tstore?.dispose();\n\t\t\tstore = new DisposableStore();\n\t\t\thandler(e, store);\n\t\t}\n\n\t\trun(undefined);\n\t\tconst disposable = event(e => run(e));\n\t\treturn toDisposable(() => {\n\t\t\tdisposable.dispose();\n\t\t\tstore?.dispose();\n\t\t});\n\t}\n}\n\nexport type Listener = [(e: T) => void, any] | ((e: T) => void);\n\nexport interface EmitterOptions {\n\tonFirstListenerAdd?: Function;\n\tonFirstListenerDidAdd?: Function;\n\tonListenerDidAdd?: Function;\n\tonLastListenerRemove?: Function;\n\tleakWarningThreshold?: number;\n\n\t/** ONLY enable this during development */\n\t_profName?: string\n}\n\n\nclass EventProfiling {\n\n\tprivate static _idPool = 0;\n\n\tprivate _name: string;\n\tprivate _stopWatch?: StopWatch;\n\tprivate _listenerCount: number = 0;\n\tprivate _invocationCount = 0;\n\tprivate _elapsedOverall = 0;\n\n\tconstructor(name: string) {\n\t\tthis._name = `${name}_${EventProfiling._idPool++}`;\n\t}\n\n\tstart(listenerCount: number): void {\n\t\tthis._stopWatch = new StopWatch(true);\n\t\tthis._listenerCount = listenerCount;\n\t}\n\n\tstop(): void {\n\t\tif (this._stopWatch) {\n\t\t\tconst elapsed = this._stopWatch.elapsed();\n\t\t\tthis._elapsedOverall += elapsed;\n\t\t\tthis._invocationCount += 1;\n\n\t\t\tconsole.info(`did FIRE ${this._name}: elapsed_ms: ${elapsed.toFixed(5)}, listener: ${this._listenerCount} (elapsed_overall: ${this._elapsedOverall.toFixed(2)}, invocations: ${this._invocationCount})`);\n\t\t\tthis._stopWatch = undefined;\n\t\t}\n\t}\n}\n\nlet _globalLeakWarningThreshold = -1;\n\nclass LeakageMonitor {\n\n\tprivate _stacks: Map | undefined;\n\tprivate _warnCountdown: number = 0;\n\n\tconstructor(\n\t\treadonly customThreshold?: number,\n\t\treadonly name: string = Math.random().toString(18).slice(2, 5),\n\t) { }\n\n\tdispose(): void {\n\t\tif (this._stacks) {\n\t\t\tthis._stacks.clear();\n\t\t}\n\t}\n\n\tcheck(listenerCount: number): undefined | (() => void) {\n\n\t\tlet threshold = _globalLeakWarningThreshold;\n\t\tif (typeof this.customThreshold === 'number') {\n\t\t\tthreshold = this.customThreshold;\n\t\t}\n\n\t\tif (threshold <= 0 || listenerCount < threshold) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (!this._stacks) {\n\t\t\tthis._stacks = new Map();\n\t\t}\n\t\tconst stack = new Error().stack!.split('\\n').slice(3).join('\\n');\n\t\tconst count = (this._stacks.get(stack) || 0);\n\t\tthis._stacks.set(stack, count + 1);\n\t\tthis._warnCountdown -= 1;\n\n\t\tif (this._warnCountdown <= 0) {\n\t\t\t// only warn on first exceed and then every time the limit\n\t\t\t// is exceeded by 50% again\n\t\t\tthis._warnCountdown = threshold * 0.5;\n\n\t\t\t// find most frequent listener and print warning\n\t\t\tlet topStack: string | undefined;\n\t\t\tlet topCount: number = 0;\n\t\t\tfor (const [stack, count] of this._stacks) {\n\t\t\t\tif (!topStack || topCount < count) {\n\t\t\t\t\ttopStack = stack;\n\t\t\t\t\ttopCount = count;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconsole.warn(`[${this.name}] potential listener LEAK detected, having ${listenerCount} listeners already. MOST frequent listener (${topCount}):`);\n\t\t\tconsole.warn(topStack!);\n\t\t}\n\n\t\treturn () => {\n\t\t\tconst count = (this._stacks!.get(stack) || 0);\n\t\t\tthis._stacks!.set(stack, count - 1);\n\t\t};\n\t}\n}\n\n/**\n * The Emitter can be used to expose an Event to the public\n * to fire it from the insides.\n * Sample:\n\tclass Document {\n\n\t\tprivate readonly _onDidChange = new Emitter<(value:string)=>any>();\n\n\t\tpublic onDidChange = this._onDidChange.event;\n\n\t\t// getter-style\n\t\t// get onDidChange(): Event<(value:string)=>any> {\n\t\t// \treturn this._onDidChange.event;\n\t\t// }\n\n\t\tprivate _doIt() {\n\t\t\t//...\n\t\t\tthis._onDidChange.fire(value);\n\t\t}\n\t}\n */\nexport class Emitter {\n\tprivate readonly _options?: EmitterOptions;\n\tprivate readonly _leakageMon?: LeakageMonitor;\n\tprivate readonly _perfMon?: EventProfiling;\n\tprivate _disposed: boolean = false;\n\tprivate _event?: Event;\n\tprivate _deliveryQueue?: LinkedList<[Listener, T]>;\n\tprotected _listeners?: LinkedList>;\n\n\tconstructor(options?: EmitterOptions) {\n\t\tthis._options = options;\n\t\tthis._leakageMon = _globalLeakWarningThreshold > 0 ? new LeakageMonitor(this._options && this._options.leakWarningThreshold) : undefined;\n\t\tthis._perfMon = this._options?._profName ? new EventProfiling(this._options._profName) : undefined;\n\t}\n\n\t/**\n\t * For the public to allow to subscribe\n\t * to events from this Emitter\n\t */\n\tget event(): Event {\n\t\tif (!this._event) {\n\t\t\tthis._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n\t\t\t\tif (!this._listeners) {\n\t\t\t\t\tthis._listeners = new LinkedList();\n\t\t\t\t}\n\n\t\t\t\tconst firstListener = this._listeners.isEmpty();\n\n\t\t\t\tif (firstListener && this._options && this._options.onFirstListenerAdd) {\n\t\t\t\t\tthis._options.onFirstListenerAdd(this);\n\t\t\t\t}\n\n\t\t\t\tconst remove = this._listeners.push(!thisArgs ? listener : [listener, thisArgs]);\n\n\t\t\t\tif (firstListener && this._options && this._options.onFirstListenerDidAdd) {\n\t\t\t\t\tthis._options.onFirstListenerDidAdd(this);\n\t\t\t\t}\n\n\t\t\t\tif (this._options && this._options.onListenerDidAdd) {\n\t\t\t\t\tthis._options.onListenerDidAdd(this, listener, thisArgs);\n\t\t\t\t}\n\n\t\t\t\t// check and record this emitter for potential leakage\n\t\t\t\tconst removeMonitor = this._leakageMon?.check(this._listeners.size);\n\n\t\t\t\tconst result = toDisposable(() => {\n\t\t\t\t\tif (removeMonitor) {\n\t\t\t\t\t\tremoveMonitor();\n\t\t\t\t\t}\n\t\t\t\t\tif (!this._disposed) {\n\t\t\t\t\t\tremove();\n\t\t\t\t\t\tif (this._options && this._options.onLastListenerRemove) {\n\t\t\t\t\t\t\tconst hasListeners = (this._listeners && !this._listeners.isEmpty());\n\t\t\t\t\t\t\tif (!hasListeners) {\n\t\t\t\t\t\t\t\tthis._options.onLastListenerRemove(this);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (disposables instanceof DisposableStore) {\n\t\t\t\t\tdisposables.add(result);\n\t\t\t\t} else if (Array.isArray(disposables)) {\n\t\t\t\t\tdisposables.push(result);\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t};\n\t\t}\n\t\treturn this._event;\n\t}\n\n\t/**\n\t * To be kept private to fire an event to\n\t * subscribers\n\t */\n\tfire(event: T): void {\n\t\tif (this._listeners) {\n\t\t\t// put all [listener,event]-pairs into delivery queue\n\t\t\t// then emit all event. an inner/nested event might be\n\t\t\t// the driver of this\n\n\t\t\tif (!this._deliveryQueue) {\n\t\t\t\tthis._deliveryQueue = new LinkedList();\n\t\t\t}\n\n\t\t\tfor (let listener of this._listeners) {\n\t\t\t\tthis._deliveryQueue.push([listener, event]);\n\t\t\t}\n\n\t\t\t// start/stop performance insight collection\n\t\t\tthis._perfMon?.start(this._deliveryQueue.size);\n\n\t\t\twhile (this._deliveryQueue.size > 0) {\n\t\t\t\tconst [listener, event] = this._deliveryQueue.shift()!;\n\t\t\t\ttry {\n\t\t\t\t\tif (typeof listener === 'function') {\n\t\t\t\t\t\tlistener.call(undefined, event);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlistener[0].call(listener[1], event);\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tonUnexpectedError(e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._perfMon?.stop();\n\t\t}\n\t}\n\n\tdispose() {\n\t\tif (!this._disposed) {\n\t\t\tthis._disposed = true;\n\t\t\tthis._listeners?.clear();\n\t\t\tthis._deliveryQueue?.clear();\n\t\t\tthis._options?.onLastListenerRemove?.();\n\t\t\tthis._leakageMon?.dispose();\n\t\t}\n\t}\n}\n\n\nexport class PauseableEmitter extends Emitter {\n\n\tprivate _isPaused = 0;\n\tprotected _eventQueue = new LinkedList();\n\tprivate _mergeFn?: (input: T[]) => T;\n\n\tconstructor(options?: EmitterOptions & { merge?: (input: T[]) => T }) {\n\t\tsuper(options);\n\t\tthis._mergeFn = options?.merge;\n\t}\n\n\tpause(): void {\n\t\tthis._isPaused++;\n\t}\n\n\tresume(): void {\n\t\tif (this._isPaused !== 0 && --this._isPaused === 0) {\n\t\t\tif (this._mergeFn) {\n\t\t\t\t// use the merge function to create a single composite\n\t\t\t\t// event. make a copy in case firing pauses this emitter\n\t\t\t\tconst events = Array.from(this._eventQueue);\n\t\t\t\tthis._eventQueue.clear();\n\t\t\t\tsuper.fire(this._mergeFn(events));\n\n\t\t\t} else {\n\t\t\t\t// no merging, fire each event individually and test\n\t\t\t\t// that this emitter isn't paused halfway through\n\t\t\t\twhile (!this._isPaused && this._eventQueue.size !== 0) {\n\t\t\t\t\tsuper.fire(this._eventQueue.shift()!);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\toverride fire(event: T): void {\n\t\tif (this._listeners) {\n\t\t\tif (this._isPaused !== 0) {\n\t\t\t\tthis._eventQueue.push(event);\n\t\t\t} else {\n\t\t\t\tsuper.fire(event);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class DebounceEmitter extends PauseableEmitter {\n\n\tprivate readonly _delay: number;\n\tprivate _handle: any | undefined;\n\n\tconstructor(options: EmitterOptions & { merge: (input: T[]) => T, delay?: number }) {\n\t\tsuper(options);\n\t\tthis._delay = options.delay ?? 100;\n\t}\n\n\toverride fire(event: T): void {\n\t\tif (!this._handle) {\n\t\t\tthis.pause();\n\t\t\tthis._handle = setTimeout(() => {\n\t\t\t\tthis._handle = undefined;\n\t\t\t\tthis.resume();\n\t\t\t}, this._delay);\n\t\t}\n\t\tsuper.fire(event);\n\t}\n}\n\n/**\n * The EventBufferer is useful in situations in which you want\n * to delay firing your events during some code.\n * You can wrap that code and be sure that the event will not\n * be fired during that wrap.\n *\n * ```\n * const emitter: Emitter;\n * const delayer = new EventDelayer();\n * const delayedEvent = delayer.wrapEvent(emitter.event);\n *\n * delayedEvent(console.log);\n *\n * delayer.bufferEvents(() => {\n * emitter.fire(); // event will not be fired yet\n * });\n *\n * // event will only be fired at this point\n * ```\n */\nexport class EventBufferer {\n\n\tprivate buffers: Function[][] = [];\n\n\twrapEvent(event: Event): Event {\n\t\treturn (listener, thisArgs?, disposables?) => {\n\t\t\treturn event(i => {\n\t\t\t\tconst buffer = this.buffers[this.buffers.length - 1];\n\n\t\t\t\tif (buffer) {\n\t\t\t\t\tbuffer.push(() => listener.call(thisArgs, i));\n\t\t\t\t} else {\n\t\t\t\t\tlistener.call(thisArgs, i);\n\t\t\t\t}\n\t\t\t}, undefined, disposables);\n\t\t};\n\t}\n\n\tbufferEvents(fn: () => R): R {\n\t\tconst buffer: Array<() => R> = [];\n\t\tthis.buffers.push(buffer);\n\t\tconst r = fn();\n\t\tthis.buffers.pop();\n\t\tbuffer.forEach(flush => flush());\n\t\treturn r;\n\t}\n}\n\n/**\n * A Relay is an event forwarder which functions as a replugabble event pipe.\n * Once created, you can connect an input event to it and it will simply forward\n * events from that input event through its own `event` property. The `input`\n * can be changed at any point in time.\n */\nexport class Relay implements IDisposable {\n\n\tprivate listening = false;\n\tprivate inputEvent: Event = Event.None;\n\tprivate inputEventListener: IDisposable = Disposable.None;\n\n\tprivate readonly emitter = new Emitter({\n\t\tonFirstListenerDidAdd: () => {\n\t\t\tthis.listening = true;\n\t\t\tthis.inputEventListener = this.inputEvent(this.emitter.fire, this.emitter);\n\t\t},\n\t\tonLastListenerRemove: () => {\n\t\t\tthis.listening = false;\n\t\t\tthis.inputEventListener.dispose();\n\t\t}\n\t});\n\n\treadonly event: Event = this.emitter.event;\n\n\tset input(event: Event) {\n\t\tthis.inputEvent = event;\n\n\t\tif (this.listening) {\n\t\t\tthis.inputEventListener.dispose();\n\t\t\tthis.inputEventListener = event(this.emitter.fire, this.emitter);\n\t\t}\n\t}\n\n\tdispose() {\n\t\tthis.inputEventListener.dispose();\n\t\tthis.emitter.dispose();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable } from 'vs/base/common/lifecycle';\n\nclass WindowManager {\n\n\tpublic static readonly INSTANCE = new WindowManager();\n\n\t// --- Zoom Factor\n\tprivate _zoomFactor: number = 1;\n\n\tpublic getZoomFactor(): number {\n\t\treturn this._zoomFactor;\n\t}\n}\n\nclass PixelRatioImpl extends Disposable {\n\n\tprivate readonly _onDidChange = this._register(new Emitter());\n\tpublic readonly onDidChange = this._onDidChange.event;\n\n\tprivate _value: number;\n\tprivate _removeListener: () => void;\n\n\tpublic get value(): number {\n\t\treturn this._value;\n\t}\n\n\tconstructor() {\n\t\tsuper();\n\n\t\tthis._value = this._getPixelRatio();\n\t\tthis._removeListener = this._installResolutionListener();\n\t}\n\n\tpublic override dispose() {\n\t\tthis._removeListener();\n\t\tsuper.dispose();\n\t}\n\n\tprivate _installResolutionListener(): () => void {\n\t\t// See https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#monitoring_screen_resolution_or_zoom_level_changes\n\t\tconst mediaQueryList = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);\n\t\tconst listener = () => this._updateValue();\n\t\tmediaQueryList.addEventListener('change', listener);\n\t\treturn () => {\n\t\t\tmediaQueryList.removeEventListener('change', listener);\n\t\t};\n\t}\n\n\tprivate _updateValue(): void {\n\t\tthis._value = this._getPixelRatio();\n\t\tthis._onDidChange.fire(this._value);\n\t\tthis._removeListener = this._installResolutionListener();\n\t}\n\n\tprivate _getPixelRatio(): number {\n\t\tconst ctx: any = document.createElement('canvas').getContext('2d');\n\t\tconst dpr = window.devicePixelRatio || 1;\n\t\tconst bsr = ctx.webkitBackingStorePixelRatio ||\n\t\t\tctx.mozBackingStorePixelRatio ||\n\t\t\tctx.msBackingStorePixelRatio ||\n\t\t\tctx.oBackingStorePixelRatio ||\n\t\t\tctx.backingStorePixelRatio || 1;\n\t\treturn dpr / bsr;\n\t}\n}\n\nclass PixelRatioFacade {\n\n\tprivate _pixelRatioMonitor: PixelRatioImpl | null = null;\n\tprivate _getOrCreatePixelRatioMonitor(): PixelRatioImpl {\n\t\tif (!this._pixelRatioMonitor) {\n\t\t\tthis._pixelRatioMonitor = new PixelRatioImpl();\n\t\t}\n\t\treturn this._pixelRatioMonitor;\n\t}\n\n\t/**\n\t * Get the current value.\n\t */\n\tpublic get value(): number {\n\t\treturn this._getOrCreatePixelRatioMonitor().value;\n\t}\n\n\t/**\n\t * Listen for changes.\n\t */\n\tpublic get onDidChange(): Event {\n\t\treturn this._getOrCreatePixelRatioMonitor().onDidChange;\n\t}\n}\n\n/**\n * Returns the pixel ratio.\n *\n * This is useful for rendering elements at native screen resolution or for being used as\n * a cache key when storing font measurements. Fonts might render differently depending on resolution\n * and any measurements need to be discarded for example when a window is moved from a monitor to another.\n */\nexport const PixelRatio = new PixelRatioFacade();\n\n/** The zoom scale for an index, e.g. 1, 1.2, 1.4 */\nexport function getZoomFactor(): number {\n\treturn WindowManager.INSTANCE.getZoomFactor();\n}\n\nconst userAgent = navigator.userAgent;\n\nexport const isFirefox = (userAgent.indexOf('Firefox') >= 0);\nexport const isWebKit = (userAgent.indexOf('AppleWebKit') >= 0);\nexport const isChrome = (userAgent.indexOf('Chrome') >= 0);\nexport const isSafari = (!isChrome && (userAgent.indexOf('Safari') >= 0));\nexport const isWebkitWebView = (!isChrome && !isSafari && isWebKit);\nexport const isEdgeLegacyWebView = (userAgent.indexOf('Edge/') >= 0) && (userAgent.indexOf('WebView/') >= 0);\nexport const isElectron = (userAgent.indexOf('Electron/') >= 0);\nexport const isAndroid = (userAgent.indexOf('Android') >= 0);\nexport const isStandalone = (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as browser from 'vs/base/browser/browser';\nimport * as platform from 'vs/base/common/platform';\n\nexport const enum KeyboardSupport {\n\tAlways,\n\tFullScreen,\n\tNone\n}\n\n/**\n * Browser feature we can support in current platform, browser and environment.\n */\nexport const BrowserFeatures = {\n\tclipboard: {\n\t\twriteText: (\n\t\t\tplatform.isNative\n\t\t\t|| (document.queryCommandSupported && document.queryCommandSupported('copy'))\n\t\t\t|| !!(navigator && navigator.clipboard && navigator.clipboard.writeText)\n\t\t),\n\t\treadText: (\n\t\t\tplatform.isNative\n\t\t\t|| !!(navigator && navigator.clipboard && navigator.clipboard.readText)\n\t\t)\n\t},\n\tkeyboard: (() => {\n\t\tif (platform.isNative || browser.isStandalone) {\n\t\t\treturn KeyboardSupport.Always;\n\t\t}\n\n\t\tif ((navigator).keyboard || browser.isSafari) {\n\t\t\treturn KeyboardSupport.FullScreen;\n\t\t}\n\n\t\treturn KeyboardSupport.None;\n\t})(),\n\n\t// 'ontouchstart' in window always evaluates to true with typescript's modern typings. This causes `window` to be\n\t// `never` later in `window.navigator`. That's why we need the explicit `window as Window` cast\n\ttouch: 'ontouchstart' in window || navigator.maxTouchPoints > 0,\n\tpointerEvents: window.PointerEvent && ('ontouchstart' in window || (window as Window).navigator.maxTouchPoints > 0 || navigator.maxTouchPoints > 0)\n};\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { GestureEvent } from 'vs/base/browser/touch';\nimport { Emitter, Event as BaseEvent } from 'vs/base/common/event';\nimport { IDisposable } from 'vs/base/common/lifecycle';\n\nexport type EventHandler = HTMLElement | HTMLDocument | Window;\n\nexport interface DOMEventMap extends HTMLElementEventMap, DocumentEventMap, WindowEventMap {\n\t'-monaco-gesturetap': GestureEvent;\n\t'-monaco-gesturechange': GestureEvent;\n\t'-monaco-gesturestart': GestureEvent;\n\t'-monaco-gesturesend': GestureEvent;\n\t'-monaco-gesturecontextmenu': GestureEvent;\n}\n\nexport class DomEmitter implements IDisposable {\n\n\tprivate emitter: Emitter;\n\n\tget event(): BaseEvent {\n\t\treturn this.emitter.event;\n\t}\n\n\tconstructor(element: Window & typeof globalThis, type: WindowEventMap, useCapture?: boolean);\n\tconstructor(element: Document, type: DocumentEventMap, useCapture?: boolean);\n\tconstructor(element: EventHandler, type: K, useCapture?: boolean);\n\tconstructor(element: EventHandler, type: K, useCapture?: boolean) {\n\t\tconst fn = (e: Event) => this.emitter.fire(e as DOMEventMap[K]);\n\t\tthis.emitter = new Emitter({\n\t\t\tonFirstListenerAdd: () => element.addEventListener(type, fn, useCapture),\n\t\t\tonLastListenerRemove: () => element.removeEventListener(type, fn, useCapture)\n\t\t});\n\t}\n\n\tdispose(): void {\n\t\tthis.emitter.dispose();\n\t}\n}\n\nexport interface CancellableEvent {\n\tpreventDefault(): void;\n\tstopPropagation(): void;\n}\n\nexport function stopEvent(event: T): T {\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn event;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as browser from 'vs/base/browser/browser';\nimport { EVENT_KEY_CODE_MAP, KeyCode, KeyCodeUtils, KeyMod } from 'vs/base/common/keyCodes';\nimport { SimpleKeybinding } from 'vs/base/common/keybindings';\nimport * as platform from 'vs/base/common/platform';\n\n\n\nfunction extractKeyCode(e: KeyboardEvent): KeyCode {\n\tif (e.charCode) {\n\t\t// \"keypress\" events mostly\n\t\tlet char = String.fromCharCode(e.charCode).toUpperCase();\n\t\treturn KeyCodeUtils.fromString(char);\n\t}\n\n\tconst keyCode = e.keyCode;\n\n\t// browser quirks\n\tif (keyCode === 3) {\n\t\treturn KeyCode.PauseBreak;\n\t} else if (browser.isFirefox) {\n\t\tif (keyCode === 59) {\n\t\t\treturn KeyCode.Semicolon;\n\t\t} else if (keyCode === 107) {\n\t\t\treturn KeyCode.Equal;\n\t\t} else if (keyCode === 109) {\n\t\t\treturn KeyCode.Minus;\n\t\t} else if (platform.isMacintosh && keyCode === 224) {\n\t\t\treturn KeyCode.Meta;\n\t\t}\n\t} else if (browser.isWebKit) {\n\t\tif (keyCode === 91) {\n\t\t\treturn KeyCode.Meta;\n\t\t} else if (platform.isMacintosh && keyCode === 93) {\n\t\t\t// the two meta keys in the Mac have different key codes (91 and 93)\n\t\t\treturn KeyCode.Meta;\n\t\t} else if (!platform.isMacintosh && keyCode === 92) {\n\t\t\treturn KeyCode.Meta;\n\t\t}\n\t}\n\n\t// cross browser keycodes:\n\treturn EVENT_KEY_CODE_MAP[keyCode] || KeyCode.Unknown;\n}\n\nexport interface IKeyboardEvent {\n\n\treadonly _standardKeyboardEventBrand: true;\n\n\treadonly browserEvent: KeyboardEvent;\n\treadonly target: HTMLElement;\n\n\treadonly ctrlKey: boolean;\n\treadonly shiftKey: boolean;\n\treadonly altKey: boolean;\n\treadonly metaKey: boolean;\n\treadonly keyCode: KeyCode;\n\treadonly code: string;\n\n\t/**\n\t * @internal\n\t */\n\ttoKeybinding(): SimpleKeybinding;\n\tequals(keybinding: number): boolean;\n\n\tpreventDefault(): void;\n\tstopPropagation(): void;\n}\n\nconst ctrlKeyMod = (platform.isMacintosh ? KeyMod.WinCtrl : KeyMod.CtrlCmd);\nconst altKeyMod = KeyMod.Alt;\nconst shiftKeyMod = KeyMod.Shift;\nconst metaKeyMod = (platform.isMacintosh ? KeyMod.CtrlCmd : KeyMod.WinCtrl);\n\nexport class StandardKeyboardEvent implements IKeyboardEvent {\n\n\treadonly _standardKeyboardEventBrand = true;\n\n\tpublic readonly browserEvent: KeyboardEvent;\n\tpublic readonly target: HTMLElement;\n\n\tpublic readonly ctrlKey: boolean;\n\tpublic readonly shiftKey: boolean;\n\tpublic readonly altKey: boolean;\n\tpublic readonly metaKey: boolean;\n\tpublic readonly keyCode: KeyCode;\n\tpublic readonly code: string;\n\n\tprivate _asKeybinding: number;\n\tprivate _asRuntimeKeybinding: SimpleKeybinding;\n\n\tconstructor(source: KeyboardEvent) {\n\t\tlet e = source;\n\n\t\tthis.browserEvent = e;\n\t\tthis.target = e.target;\n\n\t\tthis.ctrlKey = e.ctrlKey;\n\t\tthis.shiftKey = e.shiftKey;\n\t\tthis.altKey = e.altKey;\n\t\tthis.metaKey = e.metaKey;\n\t\tthis.keyCode = extractKeyCode(e);\n\t\tthis.code = e.code;\n\n\t\t// console.info(e.type + \": keyCode: \" + e.keyCode + \", which: \" + e.which + \", charCode: \" + e.charCode + \", detail: \" + e.detail + \" ====> \" + this.keyCode + ' -- ' + KeyCode[this.keyCode]);\n\n\t\tthis.ctrlKey = this.ctrlKey || this.keyCode === KeyCode.Ctrl;\n\t\tthis.altKey = this.altKey || this.keyCode === KeyCode.Alt;\n\t\tthis.shiftKey = this.shiftKey || this.keyCode === KeyCode.Shift;\n\t\tthis.metaKey = this.metaKey || this.keyCode === KeyCode.Meta;\n\n\t\tthis._asKeybinding = this._computeKeybinding();\n\t\tthis._asRuntimeKeybinding = this._computeRuntimeKeybinding();\n\n\t\t// console.log(`code: ${e.code}, keyCode: ${e.keyCode}, key: ${e.key}`);\n\t}\n\n\tpublic preventDefault(): void {\n\t\tif (this.browserEvent && this.browserEvent.preventDefault) {\n\t\t\tthis.browserEvent.preventDefault();\n\t\t}\n\t}\n\n\tpublic stopPropagation(): void {\n\t\tif (this.browserEvent && this.browserEvent.stopPropagation) {\n\t\t\tthis.browserEvent.stopPropagation();\n\t\t}\n\t}\n\n\tpublic toKeybinding(): SimpleKeybinding {\n\t\treturn this._asRuntimeKeybinding;\n\t}\n\n\tpublic equals(other: number): boolean {\n\t\treturn this._asKeybinding === other;\n\t}\n\n\tprivate _computeKeybinding(): number {\n\t\tlet key = KeyCode.Unknown;\n\t\tif (this.keyCode !== KeyCode.Ctrl && this.keyCode !== KeyCode.Shift && this.keyCode !== KeyCode.Alt && this.keyCode !== KeyCode.Meta) {\n\t\t\tkey = this.keyCode;\n\t\t}\n\n\t\tlet result = 0;\n\t\tif (this.ctrlKey) {\n\t\t\tresult |= ctrlKeyMod;\n\t\t}\n\t\tif (this.altKey) {\n\t\t\tresult |= altKeyMod;\n\t\t}\n\t\tif (this.shiftKey) {\n\t\t\tresult |= shiftKeyMod;\n\t\t}\n\t\tif (this.metaKey) {\n\t\t\tresult |= metaKeyMod;\n\t\t}\n\t\tresult |= key;\n\n\t\treturn result;\n\t}\n\n\tprivate _computeRuntimeKeybinding(): SimpleKeybinding {\n\t\tlet key = KeyCode.Unknown;\n\t\tif (this.keyCode !== KeyCode.Ctrl && this.keyCode !== KeyCode.Shift && this.keyCode !== KeyCode.Alt && this.keyCode !== KeyCode.Meta) {\n\t\t\tkey = this.keyCode;\n\t\t}\n\t\treturn new SimpleKeybinding(this.ctrlKey, this.shiftKey, this.altKey, this.metaKey, key);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as browser from 'vs/base/browser/browser';\nimport { IframeUtils } from 'vs/base/browser/iframe';\nimport * as platform from 'vs/base/common/platform';\n\nexport interface IMouseEvent {\n\treadonly browserEvent: MouseEvent;\n\treadonly leftButton: boolean;\n\treadonly middleButton: boolean;\n\treadonly rightButton: boolean;\n\treadonly buttons: number;\n\treadonly target: HTMLElement;\n\treadonly detail: number;\n\treadonly posx: number;\n\treadonly posy: number;\n\treadonly ctrlKey: boolean;\n\treadonly shiftKey: boolean;\n\treadonly altKey: boolean;\n\treadonly metaKey: boolean;\n\treadonly timestamp: number;\n\n\tpreventDefault(): void;\n\tstopPropagation(): void;\n}\n\nexport class StandardMouseEvent implements IMouseEvent {\n\n\tpublic readonly browserEvent: MouseEvent;\n\n\tpublic readonly leftButton: boolean;\n\tpublic readonly middleButton: boolean;\n\tpublic readonly rightButton: boolean;\n\tpublic readonly buttons: number;\n\tpublic readonly target: HTMLElement;\n\tpublic detail: number;\n\tpublic readonly posx: number;\n\tpublic readonly posy: number;\n\tpublic readonly ctrlKey: boolean;\n\tpublic readonly shiftKey: boolean;\n\tpublic readonly altKey: boolean;\n\tpublic readonly metaKey: boolean;\n\tpublic readonly timestamp: number;\n\n\tconstructor(e: MouseEvent) {\n\t\tthis.timestamp = Date.now();\n\t\tthis.browserEvent = e;\n\t\tthis.leftButton = e.button === 0;\n\t\tthis.middleButton = e.button === 1;\n\t\tthis.rightButton = e.button === 2;\n\t\tthis.buttons = e.buttons;\n\n\t\tthis.target = e.target;\n\n\t\tthis.detail = e.detail || 1;\n\t\tif (e.type === 'dblclick') {\n\t\t\tthis.detail = 2;\n\t\t}\n\t\tthis.ctrlKey = e.ctrlKey;\n\t\tthis.shiftKey = e.shiftKey;\n\t\tthis.altKey = e.altKey;\n\t\tthis.metaKey = e.metaKey;\n\n\t\tif (typeof e.pageX === 'number') {\n\t\t\tthis.posx = e.pageX;\n\t\t\tthis.posy = e.pageY;\n\t\t} else {\n\t\t\t// Probably hit by MSGestureEvent\n\t\t\tthis.posx = e.clientX + document.body.scrollLeft + document.documentElement!.scrollLeft;\n\t\t\tthis.posy = e.clientY + document.body.scrollTop + document.documentElement!.scrollTop;\n\t\t}\n\n\t\t// Find the position of the iframe this code is executing in relative to the iframe where the event was captured.\n\t\tlet iframeOffsets = IframeUtils.getPositionOfChildWindowRelativeToAncestorWindow(self, e.view);\n\t\tthis.posx -= iframeOffsets.left;\n\t\tthis.posy -= iframeOffsets.top;\n\t}\n\n\tpublic preventDefault(): void {\n\t\tthis.browserEvent.preventDefault();\n\t}\n\n\tpublic stopPropagation(): void {\n\t\tthis.browserEvent.stopPropagation();\n\t}\n}\n\nexport interface IMouseWheelEvent extends MouseEvent {\n\treadonly wheelDelta: number;\n\treadonly wheelDeltaX: number;\n\treadonly wheelDeltaY: number;\n\n\treadonly deltaX: number;\n\treadonly deltaY: number;\n\treadonly deltaZ: number;\n\treadonly deltaMode: number;\n}\n\ninterface IWebKitMouseWheelEvent {\n\twheelDeltaY: number;\n\twheelDeltaX: number;\n}\n\ninterface IGeckoMouseWheelEvent {\n\tHORIZONTAL_AXIS: number;\n\tVERTICAL_AXIS: number;\n\taxis: number;\n\tdetail: number;\n}\n\nexport class StandardWheelEvent {\n\n\tpublic readonly browserEvent: IMouseWheelEvent | null;\n\tpublic readonly deltaY: number;\n\tpublic readonly deltaX: number;\n\tpublic readonly target: Node;\n\n\tconstructor(e: IMouseWheelEvent | null, deltaX: number = 0, deltaY: number = 0) {\n\n\t\tthis.browserEvent = e || null;\n\t\tthis.target = e ? (e.target || (e).targetNode || e.srcElement) : null;\n\n\t\tthis.deltaY = deltaY;\n\t\tthis.deltaX = deltaX;\n\n\t\tif (e) {\n\t\t\t// Old (deprecated) wheel events\n\t\t\tlet e1 = e;\n\t\t\tlet e2 = e;\n\n\t\t\t// vertical delta scroll\n\t\t\tif (typeof e1.wheelDeltaY !== 'undefined') {\n\t\t\t\tthis.deltaY = e1.wheelDeltaY / 120;\n\t\t\t} else if (typeof e2.VERTICAL_AXIS !== 'undefined' && e2.axis === e2.VERTICAL_AXIS) {\n\t\t\t\tthis.deltaY = -e2.detail / 3;\n\t\t\t} else if (e.type === 'wheel') {\n\t\t\t\t// Modern wheel event\n\t\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent\n\t\t\t\tconst ev = e;\n\n\t\t\t\tif (ev.deltaMode === ev.DOM_DELTA_LINE) {\n\t\t\t\t\t// the deltas are expressed in lines\n\t\t\t\t\tif (browser.isFirefox && !platform.isMacintosh) {\n\t\t\t\t\t\tthis.deltaY = -e.deltaY / 3;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.deltaY = -e.deltaY;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.deltaY = -e.deltaY / 40;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// horizontal delta scroll\n\t\t\tif (typeof e1.wheelDeltaX !== 'undefined') {\n\t\t\t\tif (browser.isSafari && platform.isWindows) {\n\t\t\t\t\tthis.deltaX = - (e1.wheelDeltaX / 120);\n\t\t\t\t} else {\n\t\t\t\t\tthis.deltaX = e1.wheelDeltaX / 120;\n\t\t\t\t}\n\t\t\t} else if (typeof e2.HORIZONTAL_AXIS !== 'undefined' && e2.axis === e2.HORIZONTAL_AXIS) {\n\t\t\t\tthis.deltaX = -e.detail / 3;\n\t\t\t} else if (e.type === 'wheel') {\n\t\t\t\t// Modern wheel event\n\t\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent\n\t\t\t\tconst ev = e;\n\n\t\t\t\tif (ev.deltaMode === ev.DOM_DELTA_LINE) {\n\t\t\t\t\t// the deltas are expressed in lines\n\t\t\t\t\tif (browser.isFirefox && !platform.isMacintosh) {\n\t\t\t\t\t\tthis.deltaX = -e.deltaX / 3;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.deltaX = -e.deltaX;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.deltaX = -e.deltaX / 40;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Assume a vertical scroll if nothing else worked\n\t\t\tif (this.deltaY === 0 && this.deltaX === 0 && e.wheelDelta) {\n\t\t\t\tthis.deltaY = e.wheelDelta / 120;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic preventDefault(): void {\n\t\tif (this.browserEvent) {\n\t\t\tthis.browserEvent.preventDefault();\n\t\t}\n\t}\n\n\tpublic stopPropagation(): void {\n\t\tif (this.browserEvent) {\n\t\t\tthis.browserEvent.stopPropagation();\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { IDisposable } from 'vs/base/common/lifecycle';\n\nexport interface CancellationToken {\n\n\t/**\n\t * A flag signalling is cancellation has been requested.\n\t */\n\treadonly isCancellationRequested: boolean;\n\n\t/**\n\t * An event which fires when cancellation is requested. This event\n\t * only ever fires `once` as cancellation can only happen once. Listeners\n\t * that are registered after cancellation will be called (next event loop run),\n\t * but also only once.\n\t *\n\t * @event\n\t */\n\treadonly onCancellationRequested: (listener: (e: any) => any, thisArgs?: any, disposables?: IDisposable[]) => IDisposable;\n}\n\nconst shortcutEvent: Event = Object.freeze(function (callback, context?): IDisposable {\n\tconst handle = setTimeout(callback.bind(context), 0);\n\treturn { dispose() { clearTimeout(handle); } };\n});\n\nexport namespace CancellationToken {\n\n\texport function isCancellationToken(thing: unknown): thing is CancellationToken {\n\t\tif (thing === CancellationToken.None || thing === CancellationToken.Cancelled) {\n\t\t\treturn true;\n\t\t}\n\t\tif (thing instanceof MutableToken) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!thing || typeof thing !== 'object') {\n\t\t\treturn false;\n\t\t}\n\t\treturn typeof (thing as CancellationToken).isCancellationRequested === 'boolean'\n\t\t\t&& typeof (thing as CancellationToken).onCancellationRequested === 'function';\n\t}\n\n\n\texport const None: CancellationToken = Object.freeze({\n\t\tisCancellationRequested: false,\n\t\tonCancellationRequested: Event.None\n\t});\n\n\texport const Cancelled: CancellationToken = Object.freeze({\n\t\tisCancellationRequested: true,\n\t\tonCancellationRequested: shortcutEvent\n\t});\n}\n\nclass MutableToken implements CancellationToken {\n\n\tprivate _isCancelled: boolean = false;\n\tprivate _emitter: Emitter | null = null;\n\n\tpublic cancel() {\n\t\tif (!this._isCancelled) {\n\t\t\tthis._isCancelled = true;\n\t\t\tif (this._emitter) {\n\t\t\t\tthis._emitter.fire(undefined);\n\t\t\t\tthis.dispose();\n\t\t\t}\n\t\t}\n\t}\n\n\tget isCancellationRequested(): boolean {\n\t\treturn this._isCancelled;\n\t}\n\n\tget onCancellationRequested(): Event {\n\t\tif (this._isCancelled) {\n\t\t\treturn shortcutEvent;\n\t\t}\n\t\tif (!this._emitter) {\n\t\t\tthis._emitter = new Emitter();\n\t\t}\n\t\treturn this._emitter.event;\n\t}\n\n\tpublic dispose(): void {\n\t\tif (this._emitter) {\n\t\t\tthis._emitter.dispose();\n\t\t\tthis._emitter = null;\n\t\t}\n\t}\n}\n\nexport class CancellationTokenSource {\n\n\tprivate _token?: CancellationToken = undefined;\n\tprivate _parentListener?: IDisposable = undefined;\n\n\tconstructor(parent?: CancellationToken) {\n\t\tthis._parentListener = parent && parent.onCancellationRequested(this.cancel, this);\n\t}\n\n\tget token(): CancellationToken {\n\t\tif (!this._token) {\n\t\t\t// be lazy and create the token only when\n\t\t\t// actually needed\n\t\t\tthis._token = new MutableToken();\n\t\t}\n\t\treturn this._token;\n\t}\n\n\tcancel(): void {\n\t\tif (!this._token) {\n\t\t\t// save an object by returning the default\n\t\t\t// cancelled token when cancellation happens\n\t\t\t// before someone asks for the token\n\t\t\tthis._token = CancellationToken.Cancelled;\n\n\t\t} else if (this._token instanceof MutableToken) {\n\t\t\t// actually cancel\n\t\t\tthis._token.cancel();\n\t\t}\n\t}\n\n\tdispose(cancel: boolean = false): void {\n\t\tif (cancel) {\n\t\t\tthis.cancel();\n\t\t}\n\t\tif (this._parentListener) {\n\t\t\tthis._parentListener.dispose();\n\t\t}\n\t\tif (!this._token) {\n\t\t\t// ensure to initialize with an empty token if we had none\n\t\t\tthis._token = CancellationToken.None;\n\n\t\t} else if (this._token instanceof MutableToken) {\n\t\t\t// actually dispose\n\t\t\tthis._token.dispose();\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';\nimport { CancellationError } from 'vs/base/common/errors';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { setTimeout0 } from 'vs/base/common/platform';\n\nexport function isThenable(obj: unknown): obj is Promise {\n\treturn !!obj && typeof (obj as unknown as Promise).then === 'function';\n}\n\nexport interface CancelablePromise extends Promise {\n\tcancel(): void;\n}\n\nexport function createCancelablePromise(callback: (token: CancellationToken) => Promise): CancelablePromise {\n\tconst source = new CancellationTokenSource();\n\n\tconst thenable = callback(source.token);\n\tconst promise = new Promise((resolve, reject) => {\n\t\tconst subscription = source.token.onCancellationRequested(() => {\n\t\t\tsubscription.dispose();\n\t\t\tsource.dispose();\n\t\t\treject(new CancellationError());\n\t\t});\n\t\tPromise.resolve(thenable).then(value => {\n\t\t\tsubscription.dispose();\n\t\t\tsource.dispose();\n\t\t\tresolve(value);\n\t\t}, err => {\n\t\t\tsubscription.dispose();\n\t\t\tsource.dispose();\n\t\t\treject(err);\n\t\t});\n\t});\n\n\treturn >new class {\n\t\tcancel() {\n\t\t\tsource.cancel();\n\t\t}\n\t\tthen(resolve?: ((value: T) => TResult1 | Promise) | undefined | null, reject?: ((reason: any) => TResult2 | Promise) | undefined | null): Promise {\n\t\t\treturn promise.then(resolve, reject);\n\t\t}\n\t\tcatch(reject?: ((reason: any) => TResult | Promise) | undefined | null): Promise {\n\t\t\treturn this.then(undefined, reject);\n\t\t}\n\t\tfinally(onfinally?: (() => void) | undefined | null): Promise {\n\t\t\treturn promise.finally(onfinally);\n\t\t}\n\t};\n}\n\n/**\n * Returns a promise that resolves with `undefined` as soon as the passed token is cancelled.\n * @see {@link raceCancellationError}\n */\nexport function raceCancellation(promise: Promise, token: CancellationToken): Promise;\n\n/**\n * Returns a promise that resolves with `defaultValue` as soon as the passed token is cancelled.\n * @see {@link raceCancellationError}\n */\nexport function raceCancellation(promise: Promise, token: CancellationToken, defaultValue: T): Promise;\n\nexport function raceCancellation(promise: Promise, token: CancellationToken, defaultValue?: T): Promise {\n\treturn new Promise((resolve, reject) => {\n\t\tconst ref = token.onCancellationRequested(() => {\n\t\t\tref.dispose();\n\t\t\tresolve(defaultValue);\n\t\t});\n\t\tpromise.then(resolve, reject).finally(() => ref.dispose());\n\t});\n}\n\nexport interface ITask {\n\t(): T;\n}\n\n/**\n * A helper to prevent accumulation of sequential async tasks.\n *\n * Imagine a mail man with the sole task of delivering letters. As soon as\n * a letter submitted for delivery, he drives to the destination, delivers it\n * and returns to his base. Imagine that during the trip, N more letters were submitted.\n * When the mail man returns, he picks those N letters and delivers them all in a\n * single trip. Even though N+1 submissions occurred, only 2 deliveries were made.\n *\n * The throttler implements this via the queue() method, by providing it a task\n * factory. Following the example:\n *\n * \t\tconst throttler = new Throttler();\n * \t\tconst letters = [];\n *\n * \t\tfunction deliver() {\n * \t\t\tconst lettersToDeliver = letters;\n * \t\t\tletters = [];\n * \t\t\treturn makeTheTrip(lettersToDeliver);\n * \t\t}\n *\n * \t\tfunction onLetterReceived(l) {\n * \t\t\tletters.push(l);\n * \t\t\tthrottler.queue(deliver);\n * \t\t}\n */\nexport class Throttler {\n\n\tprivate activePromise: Promise | null;\n\tprivate queuedPromise: Promise | null;\n\tprivate queuedPromiseFactory: ITask> | null;\n\n\tconstructor() {\n\t\tthis.activePromise = null;\n\t\tthis.queuedPromise = null;\n\t\tthis.queuedPromiseFactory = null;\n\t}\n\n\tqueue(promiseFactory: ITask>): Promise {\n\t\tif (this.activePromise) {\n\t\t\tthis.queuedPromiseFactory = promiseFactory;\n\n\t\t\tif (!this.queuedPromise) {\n\t\t\t\tconst onComplete = () => {\n\t\t\t\t\tthis.queuedPromise = null;\n\n\t\t\t\t\tconst result = this.queue(this.queuedPromiseFactory!);\n\t\t\t\t\tthis.queuedPromiseFactory = null;\n\n\t\t\t\t\treturn result;\n\t\t\t\t};\n\n\t\t\t\tthis.queuedPromise = new Promise(resolve => {\n\t\t\t\t\tthis.activePromise!.then(onComplete, onComplete).then(resolve);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tthis.queuedPromise!.then(resolve, reject);\n\t\t\t});\n\t\t}\n\n\t\tthis.activePromise = promiseFactory();\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.activePromise!.then((result: T) => {\n\t\t\t\tthis.activePromise = null;\n\t\t\t\tresolve(result);\n\t\t\t}, (err: unknown) => {\n\t\t\t\tthis.activePromise = null;\n\t\t\t\treject(err);\n\t\t\t});\n\t\t});\n\t}\n}\n\ninterface IScheduledLater extends IDisposable {\n\tisTriggered(): boolean;\n}\n\nconst timeoutDeferred = (timeout: number, fn: () => void): IScheduledLater => {\n\tlet scheduled = true;\n\tconst handle = setTimeout(() => {\n\t\tscheduled = false;\n\t\tfn();\n\t}, timeout);\n\treturn {\n\t\tisTriggered: () => scheduled,\n\t\tdispose: () => {\n\t\t\tclearTimeout(handle);\n\t\t\tscheduled = false;\n\t\t},\n\t};\n};\n\nconst microtaskDeferred = (fn: () => void): IScheduledLater => {\n\tlet scheduled = true;\n\tqueueMicrotask(() => {\n\t\tif (scheduled) {\n\t\t\tscheduled = false;\n\t\t\tfn();\n\t\t}\n\t});\n\n\treturn {\n\t\tisTriggered: () => scheduled,\n\t\tdispose: () => { scheduled = false; },\n\t};\n};\n\n/** Can be passed into the Delayed to defer using a microtask */\nexport const MicrotaskDelay = Symbol('MicrotaskDelay');\n\n/**\n * A helper to delay (debounce) execution of a task that is being requested often.\n *\n * Following the throttler, now imagine the mail man wants to optimize the number of\n * trips proactively. The trip itself can be long, so he decides not to make the trip\n * as soon as a letter is submitted. Instead he waits a while, in case more\n * letters are submitted. After said waiting period, if no letters were submitted, he\n * decides to make the trip. Imagine that N more letters were submitted after the first\n * one, all within a short period of time between each other. Even though N+1\n * submissions occurred, only 1 delivery was made.\n *\n * The delayer offers this behavior via the trigger() method, into which both the task\n * to be executed and the waiting period (delay) must be passed in as arguments. Following\n * the example:\n *\n * \t\tconst delayer = new Delayer(WAITING_PERIOD);\n * \t\tconst letters = [];\n *\n * \t\tfunction letterReceived(l) {\n * \t\t\tletters.push(l);\n * \t\t\tdelayer.trigger(() => { return makeTheTrip(); });\n * \t\t}\n */\nexport class Delayer implements IDisposable {\n\n\tprivate deferred: IScheduledLater | null;\n\tprivate completionPromise: Promise | null;\n\tprivate doResolve: ((value?: any | Promise) => void) | null;\n\tprivate doReject: ((err: any) => void) | null;\n\tprivate task: ITask> | null;\n\n\tconstructor(public defaultDelay: number | typeof MicrotaskDelay) {\n\t\tthis.deferred = null;\n\t\tthis.completionPromise = null;\n\t\tthis.doResolve = null;\n\t\tthis.doReject = null;\n\t\tthis.task = null;\n\t}\n\n\ttrigger(task: ITask>, delay = this.defaultDelay): Promise {\n\t\tthis.task = task;\n\t\tthis.cancelTimeout();\n\n\t\tif (!this.completionPromise) {\n\t\t\tthis.completionPromise = new Promise((resolve, reject) => {\n\t\t\t\tthis.doResolve = resolve;\n\t\t\t\tthis.doReject = reject;\n\t\t\t}).then(() => {\n\t\t\t\tthis.completionPromise = null;\n\t\t\t\tthis.doResolve = null;\n\t\t\t\tif (this.task) {\n\t\t\t\t\tconst task = this.task;\n\t\t\t\t\tthis.task = null;\n\t\t\t\t\treturn task();\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t});\n\t\t}\n\n\t\tconst fn = () => {\n\t\t\tthis.deferred = null;\n\t\t\tthis.doResolve?.(null);\n\t\t};\n\n\t\tthis.deferred = delay === MicrotaskDelay ? microtaskDeferred(fn) : timeoutDeferred(delay, fn);\n\n\t\treturn this.completionPromise;\n\t}\n\n\tisTriggered(): boolean {\n\t\treturn !!this.deferred?.isTriggered();\n\t}\n\n\tcancel(): void {\n\t\tthis.cancelTimeout();\n\n\t\tif (this.completionPromise) {\n\t\t\tif (this.doReject) {\n\t\t\t\tthis.doReject(new CancellationError());\n\t\t\t}\n\t\t\tthis.completionPromise = null;\n\t\t}\n\t}\n\n\tprivate cancelTimeout(): void {\n\t\tthis.deferred?.dispose();\n\t\tthis.deferred = null;\n\t}\n\n\tdispose(): void {\n\t\tthis.cancel();\n\t}\n}\n\n/**\n * A helper to delay execution of a task that is being requested often, while\n * preventing accumulation of consecutive executions, while the task runs.\n *\n * The mail man is clever and waits for a certain amount of time, before going\n * out to deliver letters. While the mail man is going out, more letters arrive\n * and can only be delivered once he is back. Once he is back the mail man will\n * do one more trip to deliver the letters that have accumulated while he was out.\n */\nexport class ThrottledDelayer {\n\n\tprivate delayer: Delayer>;\n\tprivate throttler: Throttler;\n\n\tconstructor(defaultDelay: number) {\n\t\tthis.delayer = new Delayer(defaultDelay);\n\t\tthis.throttler = new Throttler();\n\t}\n\n\ttrigger(promiseFactory: ITask>, delay?: number): Promise {\n\t\treturn this.delayer.trigger(() => this.throttler.queue(promiseFactory), delay) as unknown as Promise;\n\t}\n\n\tdispose(): void {\n\t\tthis.delayer.dispose();\n\t}\n}\n\nexport function timeout(millis: number): CancelablePromise;\nexport function timeout(millis: number, token: CancellationToken): Promise;\nexport function timeout(millis: number, token?: CancellationToken): CancelablePromise | Promise {\n\tif (!token) {\n\t\treturn createCancelablePromise(token => timeout(millis, token));\n\t}\n\n\treturn new Promise((resolve, reject) => {\n\t\tconst handle = setTimeout(() => {\n\t\t\tdisposable.dispose();\n\t\t\tresolve();\n\t\t}, millis);\n\t\tconst disposable = token.onCancellationRequested(() => {\n\t\t\tclearTimeout(handle);\n\t\t\tdisposable.dispose();\n\t\t\treject(new CancellationError());\n\t\t});\n\t});\n}\n\nexport function disposableTimeout(handler: () => void, timeout = 0): IDisposable {\n\tconst timer = setTimeout(handler, timeout);\n\treturn toDisposable(() => clearTimeout(timer));\n}\n\nexport function first(promiseFactories: ITask>[], shouldStop: (t: T) => boolean = t => !!t, defaultValue: T | null = null): Promise {\n\tlet index = 0;\n\tconst len = promiseFactories.length;\n\n\tconst loop: () => Promise = () => {\n\t\tif (index >= len) {\n\t\t\treturn Promise.resolve(defaultValue);\n\t\t}\n\n\t\tconst factory = promiseFactories[index++];\n\t\tconst promise = Promise.resolve(factory());\n\n\t\treturn promise.then(result => {\n\t\t\tif (shouldStop(result)) {\n\t\t\t\treturn Promise.resolve(result);\n\t\t\t}\n\n\t\t\treturn loop();\n\t\t});\n\t};\n\n\treturn loop();\n}\n\nexport class TimeoutTimer implements IDisposable {\n\tprivate _token: any;\n\n\tconstructor();\n\tconstructor(runner: () => void, timeout: number);\n\tconstructor(runner?: () => void, timeout?: number) {\n\t\tthis._token = -1;\n\n\t\tif (typeof runner === 'function' && typeof timeout === 'number') {\n\t\t\tthis.setIfNotSet(runner, timeout);\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tthis.cancel();\n\t}\n\n\tcancel(): void {\n\t\tif (this._token !== -1) {\n\t\t\tclearTimeout(this._token);\n\t\t\tthis._token = -1;\n\t\t}\n\t}\n\n\tcancelAndSet(runner: () => void, timeout: number): void {\n\t\tthis.cancel();\n\t\tthis._token = setTimeout(() => {\n\t\t\tthis._token = -1;\n\t\t\trunner();\n\t\t}, timeout);\n\t}\n\n\tsetIfNotSet(runner: () => void, timeout: number): void {\n\t\tif (this._token !== -1) {\n\t\t\t// timer is already set\n\t\t\treturn;\n\t\t}\n\t\tthis._token = setTimeout(() => {\n\t\t\tthis._token = -1;\n\t\t\trunner();\n\t\t}, timeout);\n\t}\n}\n\nexport class IntervalTimer implements IDisposable {\n\n\tprivate _token: any;\n\n\tconstructor() {\n\t\tthis._token = -1;\n\t}\n\n\tdispose(): void {\n\t\tthis.cancel();\n\t}\n\n\tcancel(): void {\n\t\tif (this._token !== -1) {\n\t\t\tclearInterval(this._token);\n\t\t\tthis._token = -1;\n\t\t}\n\t}\n\n\tcancelAndSet(runner: () => void, interval: number): void {\n\t\tthis.cancel();\n\t\tthis._token = setInterval(() => {\n\t\t\trunner();\n\t\t}, interval);\n\t}\n}\n\nexport class RunOnceScheduler {\n\n\tprotected runner: ((...args: unknown[]) => void) | null;\n\n\tprivate timeoutToken: any;\n\tprivate timeout: number;\n\tprivate timeoutHandler: () => void;\n\n\tconstructor(runner: (...args: any[]) => void, delay: number) {\n\t\tthis.timeoutToken = -1;\n\t\tthis.runner = runner;\n\t\tthis.timeout = delay;\n\t\tthis.timeoutHandler = this.onTimeout.bind(this);\n\t}\n\n\t/**\n\t * Dispose RunOnceScheduler\n\t */\n\tdispose(): void {\n\t\tthis.cancel();\n\t\tthis.runner = null;\n\t}\n\n\t/**\n\t * Cancel current scheduled runner (if any).\n\t */\n\tcancel(): void {\n\t\tif (this.isScheduled()) {\n\t\t\tclearTimeout(this.timeoutToken);\n\t\t\tthis.timeoutToken = -1;\n\t\t}\n\t}\n\n\t/**\n\t * Cancel previous runner (if any) & schedule a new runner.\n\t */\n\tschedule(delay = this.timeout): void {\n\t\tthis.cancel();\n\t\tthis.timeoutToken = setTimeout(this.timeoutHandler, delay);\n\t}\n\n\tget delay(): number {\n\t\treturn this.timeout;\n\t}\n\n\tset delay(value: number) {\n\t\tthis.timeout = value;\n\t}\n\n\t/**\n\t * Returns true if scheduled.\n\t */\n\tisScheduled(): boolean {\n\t\treturn this.timeoutToken !== -1;\n\t}\n\n\tprivate onTimeout() {\n\t\tthis.timeoutToken = -1;\n\t\tif (this.runner) {\n\t\t\tthis.doRun();\n\t\t}\n\t}\n\n\tprotected doRun(): void {\n\t\tif (this.runner) {\n\t\t\tthis.runner();\n\t\t}\n\t}\n}\n\n//#region -- run on idle tricks ------------\n\nexport interface IdleDeadline {\n\ttimeRemaining(): number;\n}\n\n/**\n * Execute the callback the next time the browser is idle\n */\nexport let runWhenIdle: (callback: (idle: IdleDeadline) => void, timeout?: number) => IDisposable;\n\ndeclare function requestIdleCallback(callback: (args: IdleDeadline) => void, options?: { timeout: number; }): number;\ndeclare function cancelIdleCallback(handle: number): void;\n\n(function () {\n\tif (typeof requestIdleCallback !== 'function' || typeof cancelIdleCallback !== 'function') {\n\t\trunWhenIdle = (runner) => {\n\t\t\tsetTimeout0(() => {\n\t\t\t\tif (disposed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst end = Date.now() + 15; // one frame at 64fps\n\t\t\t\trunner(Object.freeze({\n\t\t\t\t\tdidTimeout: true,\n\t\t\t\t\ttimeRemaining() {\n\t\t\t\t\t\treturn Math.max(0, end - Date.now());\n\t\t\t\t\t}\n\t\t\t\t}));\n\t\t\t});\n\t\t\tlet disposed = false;\n\t\t\treturn {\n\t\t\t\tdispose() {\n\t\t\t\t\tif (disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tdisposed = true;\n\t\t\t\t}\n\t\t\t};\n\t\t};\n\t} else {\n\t\trunWhenIdle = (runner, timeout?) => {\n\t\t\tconst handle: number = requestIdleCallback(runner, typeof timeout === 'number' ? { timeout } : undefined);\n\t\t\tlet disposed = false;\n\t\t\treturn {\n\t\t\t\tdispose() {\n\t\t\t\t\tif (disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tdisposed = true;\n\t\t\t\t\tcancelIdleCallback(handle);\n\t\t\t\t}\n\t\t\t};\n\t\t};\n\t}\n})();\n\n/**\n * An implementation of the \"idle-until-urgent\"-strategy as introduced\n * here: https://philipwalton.com/articles/idle-until-urgent/\n */\nexport class IdleValue {\n\n\tprivate readonly _executor: () => void;\n\tprivate readonly _handle: IDisposable;\n\n\tprivate _didRun: boolean = false;\n\tprivate _value?: T;\n\tprivate _error: unknown;\n\n\tconstructor(executor: () => T) {\n\t\tthis._executor = () => {\n\t\t\ttry {\n\t\t\t\tthis._value = executor();\n\t\t\t} catch (err) {\n\t\t\t\tthis._error = err;\n\t\t\t} finally {\n\t\t\t\tthis._didRun = true;\n\t\t\t}\n\t\t};\n\t\tthis._handle = runWhenIdle(() => this._executor());\n\t}\n\n\tdispose(): void {\n\t\tthis._handle.dispose();\n\t}\n\n\tget value(): T {\n\t\tif (!this._didRun) {\n\t\t\tthis._handle.dispose();\n\t\t\tthis._executor();\n\t\t}\n\t\tif (this._error) {\n\t\t\tthrow this._error;\n\t\t}\n\t\treturn this._value!;\n\t}\n\n\tget isInitialized(): boolean {\n\t\treturn this._didRun;\n\t}\n}\n\n//#endregion\n\n//#region\n\nexport type ValueCallback = (value: T | Promise) => void;\n\n/**\n * Creates a promise whose resolution or rejection can be controlled imperatively.\n */\nexport class DeferredPromise {\n\n\tprivate completeCallback!: ValueCallback;\n\tprivate errorCallback!: (err: unknown) => void;\n\tprivate rejected = false;\n\tprivate resolved = false;\n\n\tpublic get isRejected() {\n\t\treturn this.rejected;\n\t}\n\n\tpublic get isSettled() {\n\t\treturn this.rejected || this.resolved;\n\t}\n\n\tpublic p: Promise;\n\n\tconstructor() {\n\t\tthis.p = new Promise((c, e) => {\n\t\t\tthis.completeCallback = c;\n\t\t\tthis.errorCallback = e;\n\t\t});\n\t}\n\n\tpublic complete(value: T) {\n\t\treturn new Promise(resolve => {\n\t\t\tthis.completeCallback(value);\n\t\t\tthis.resolved = true;\n\t\t\tresolve();\n\t\t});\n\t}\n\n\tpublic cancel() {\n\t\tnew Promise(resolve => {\n\t\t\tthis.errorCallback(new CancellationError());\n\t\t\tthis.rejected = true;\n\t\t\tresolve();\n\t\t});\n\t}\n}\n\n//#endregion\n\n//#region Promises\n\nexport namespace Promises {\n\n\t/**\n\t * A drop-in replacement for `Promise.all` with the only difference\n\t * that the method awaits every promise to either fulfill or reject.\n\t *\n\t * Similar to `Promise.all`, only the first error will be returned\n\t * if any.\n\t */\n\texport async function settled(promises: Promise[]): Promise {\n\t\tlet firstError: Error | undefined = undefined;\n\n\t\tconst result = await Promise.all(promises.map(promise => promise.then(value => value, error => {\n\t\t\tif (!firstError) {\n\t\t\t\tfirstError = error;\n\t\t\t}\n\n\t\t\treturn undefined; // do not rethrow so that other promises can settle\n\t\t})));\n\n\t\tif (typeof firstError !== 'undefined') {\n\t\t\tthrow firstError;\n\t\t}\n\n\t\treturn result as unknown as T[]; // cast is needed and protected by the `throw` above\n\t}\n\n\t/**\n\t * A helper to create a new `Promise` with a body that is a promise\n\t * itself. By default, an error that raises from the async body will\n\t * end up as a unhandled rejection, so this utility properly awaits the\n\t * body and rejects the promise as a normal promise does without async\n\t * body.\n\t *\n\t * This method should only be used in rare cases where otherwise `async`\n\t * cannot be used (e.g. when callbacks are involved that require this).\n\t */\n\texport function withAsyncBody(bodyFn: (resolve: (value: T) => unknown, reject: (error: E) => unknown) => Promise): Promise {\n\t\t// eslint-disable-next-line no-async-promise-executor\n\t\treturn new Promise(async (resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tawait bodyFn(resolve, reject);\n\t\t\t} catch (error) {\n\t\t\t\treject(error);\n\t\t\t}\n\t\t});\n\t}\n}\n\n//#endregion\n\n//#region\n\nconst enum AsyncIterableSourceState {\n\tInitial,\n\tDoneOK,\n\tDoneError,\n}\n\n/**\n * An object that allows to emit async values asynchronously or bring the iterable to an error state using `reject()`.\n * This emitter is valid only for the duration of the executor (until the promise returned by the executor settles).\n */\nexport interface AsyncIterableEmitter {\n\t/**\n\t * The value will be appended at the end.\n\t *\n\t * **NOTE** If `reject()` has already been called, this method has no effect.\n\t */\n\temitOne(value: T): void;\n\t/**\n\t * The values will be appended at the end.\n\t *\n\t * **NOTE** If `reject()` has already been called, this method has no effect.\n\t */\n\temitMany(values: T[]): void;\n\t/**\n\t * Writing an error will permanently invalidate this iterable.\n\t * The current users will receive an error thrown, as will all future users.\n\t *\n\t * **NOTE** If `reject()` have already been called, this method has no effect.\n\t */\n\treject(error: Error): void;\n}\n\n/**\n * An executor for the `AsyncIterableObject` that has access to an emitter.\n */\nexport interface AyncIterableExecutor {\n\t/**\n\t * @param emitter An object that allows to emit async values valid only for the duration of the executor.\n\t */\n\t(emitter: AsyncIterableEmitter): void | Promise;\n}\n\n/**\n * A rich implementation for an `AsyncIterable`.\n */\nexport class AsyncIterableObject implements AsyncIterable {\n\n\tpublic static fromArray(items: T[]): AsyncIterableObject {\n\t\treturn new AsyncIterableObject((writer) => {\n\t\t\twriter.emitMany(items);\n\t\t});\n\t}\n\n\tpublic static fromPromise(promise: Promise): AsyncIterableObject {\n\t\treturn new AsyncIterableObject(async (emitter) => {\n\t\t\temitter.emitMany(await promise);\n\t\t});\n\t}\n\n\tpublic static fromPromises(promises: Promise[]): AsyncIterableObject {\n\t\treturn new AsyncIterableObject(async (emitter) => {\n\t\t\tawait Promise.all(promises.map(async (p) => emitter.emitOne(await p)));\n\t\t});\n\t}\n\n\tpublic static merge(iterables: AsyncIterable[]): AsyncIterableObject {\n\t\treturn new AsyncIterableObject(async (emitter) => {\n\t\t\tawait Promise.all(iterables.map(async (iterable) => {\n\t\t\t\tfor await (const item of iterable) {\n\t\t\t\t\temitter.emitOne(item);\n\t\t\t\t}\n\t\t\t}));\n\t\t});\n\t}\n\n\tpublic static EMPTY = AsyncIterableObject.fromArray([]);\n\n\tprivate _state: AsyncIterableSourceState;\n\tprivate _results: T[];\n\tprivate _error: Error | null;\n\tprivate readonly _onStateChanged: Emitter;\n\n\tconstructor(executor: AyncIterableExecutor) {\n\t\tthis._state = AsyncIterableSourceState.Initial;\n\t\tthis._results = [];\n\t\tthis._error = null;\n\t\tthis._onStateChanged = new Emitter();\n\n\t\tqueueMicrotask(async () => {\n\t\t\tconst writer: AsyncIterableEmitter = {\n\t\t\t\temitOne: (item) => this.emitOne(item),\n\t\t\t\temitMany: (items) => this.emitMany(items),\n\t\t\t\treject: (error) => this.reject(error)\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tawait Promise.resolve(executor(writer));\n\t\t\t\tthis.resolve();\n\t\t\t} catch (err) {\n\t\t\t\tthis.reject(err);\n\t\t\t} finally {\n\t\t\t\twriter.emitOne = undefined!;\n\t\t\t\twriter.emitMany = undefined!;\n\t\t\t\twriter.reject = undefined!;\n\t\t\t}\n\t\t});\n\t}\n\n\t[Symbol.asyncIterator](): AsyncIterator {\n\t\tlet i = 0;\n\t\treturn {\n\t\t\tnext: async () => {\n\t\t\t\tdo {\n\t\t\t\t\tif (this._state === AsyncIterableSourceState.DoneError) {\n\t\t\t\t\t\tthrow this._error;\n\t\t\t\t\t}\n\t\t\t\t\tif (i < this._results.length) {\n\t\t\t\t\t\treturn { done: false, value: this._results[i++] };\n\t\t\t\t\t}\n\t\t\t\t\tif (this._state === AsyncIterableSourceState.DoneOK) {\n\t\t\t\t\t\treturn { done: true, value: undefined };\n\t\t\t\t\t}\n\t\t\t\t\tawait Event.toPromise(this._onStateChanged.event);\n\t\t\t\t} while (true);\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic static map(iterable: AsyncIterable, mapFn: (item: T) => R): AsyncIterableObject {\n\t\treturn new AsyncIterableObject(async (emitter) => {\n\t\t\tfor await (const item of iterable) {\n\t\t\t\temitter.emitOne(mapFn(item));\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic map(mapFn: (item: T) => R): AsyncIterableObject {\n\t\treturn AsyncIterableObject.map(this, mapFn);\n\t}\n\n\tpublic static filter(iterable: AsyncIterable, filterFn: (item: T) => boolean): AsyncIterableObject {\n\t\treturn new AsyncIterableObject(async (emitter) => {\n\t\t\tfor await (const item of iterable) {\n\t\t\t\tif (filterFn(item)) {\n\t\t\t\t\temitter.emitOne(item);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic filter(filterFn: (item: T) => boolean): AsyncIterableObject {\n\t\treturn AsyncIterableObject.filter(this, filterFn);\n\t}\n\n\tpublic static coalesce(iterable: AsyncIterable): AsyncIterableObject {\n\t\treturn >AsyncIterableObject.filter(iterable, item => !!item);\n\t}\n\n\tpublic coalesce(): AsyncIterableObject> {\n\t\treturn AsyncIterableObject.coalesce(this) as AsyncIterableObject>;\n\t}\n\n\tpublic static async toPromise(iterable: AsyncIterable): Promise {\n\t\tconst result: T[] = [];\n\t\tfor await (const item of iterable) {\n\t\t\tresult.push(item);\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic toPromise(): Promise {\n\t\treturn AsyncIterableObject.toPromise(this);\n\t}\n\n\t/**\n\t * The value will be appended at the end.\n\t *\n\t * **NOTE** If `resolve()` or `reject()` have already been called, this method has no effect.\n\t */\n\tprivate emitOne(value: T): void {\n\t\tif (this._state !== AsyncIterableSourceState.Initial) {\n\t\t\treturn;\n\t\t}\n\t\t// it is important to add new values at the end,\n\t\t// as we may have iterators already running on the array\n\t\tthis._results.push(value);\n\t\tthis._onStateChanged.fire();\n\t}\n\n\t/**\n\t * The values will be appended at the end.\n\t *\n\t * **NOTE** If `resolve()` or `reject()` have already been called, this method has no effect.\n\t */\n\tprivate emitMany(values: T[]): void {\n\t\tif (this._state !== AsyncIterableSourceState.Initial) {\n\t\t\treturn;\n\t\t}\n\t\t// it is important to add new values at the end,\n\t\t// as we may have iterators already running on the array\n\t\tthis._results = this._results.concat(values);\n\t\tthis._onStateChanged.fire();\n\t}\n\n\t/**\n\t * Calling `resolve()` will mark the result array as complete.\n\t *\n\t * **NOTE** `resolve()` must be called, otherwise all consumers of this iterable will hang indefinitely, similar to a non-resolved promise.\n\t * **NOTE** If `resolve()` or `reject()` have already been called, this method has no effect.\n\t */\n\tprivate resolve(): void {\n\t\tif (this._state !== AsyncIterableSourceState.Initial) {\n\t\t\treturn;\n\t\t}\n\t\tthis._state = AsyncIterableSourceState.DoneOK;\n\t\tthis._onStateChanged.fire();\n\t}\n\n\t/**\n\t * Writing an error will permanently invalidate this iterable.\n\t * The current users will receive an error thrown, as will all future users.\n\t *\n\t * **NOTE** If `resolve()` or `reject()` have already been called, this method has no effect.\n\t */\n\tprivate reject(error: Error) {\n\t\tif (this._state !== AsyncIterableSourceState.Initial) {\n\t\t\treturn;\n\t\t}\n\t\tthis._state = AsyncIterableSourceState.DoneError;\n\t\tthis._error = error;\n\t\tthis._onStateChanged.fire();\n\t}\n}\n\nexport class CancelableAsyncIterableObject extends AsyncIterableObject {\n\tconstructor(\n\t\tprivate readonly _source: CancellationTokenSource,\n\t\texecutor: AyncIterableExecutor\n\t) {\n\t\tsuper(executor);\n\t}\n\n\tcancel(): void {\n\t\tthis._source.cancel();\n\t}\n}\n\nexport function createCancelableAsyncIterable(callback: (token: CancellationToken) => AsyncIterable): CancelableAsyncIterableObject {\n\tconst source = new CancellationTokenSource();\n\tconst innerIterable = callback(source.token);\n\n\treturn new CancelableAsyncIterableObject(source, async (emitter) => {\n\t\tconst subscription = source.token.onCancellationRequested(() => {\n\t\t\tsubscription.dispose();\n\t\t\tsource.dispose();\n\t\t\temitter.reject(new CancellationError());\n\t\t});\n\t\ttry {\n\t\t\tfor await (const item of innerIterable) {\n\t\t\t\tif (source.token.isCancellationRequested) {\n\t\t\t\t\t// canceled in the meantime\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\temitter.emitOne(item);\n\t\t\t}\n\t\t\tsubscription.dispose();\n\t\t\tsource.dispose();\n\t\t} catch (err) {\n\t\t\tsubscription.dispose();\n\t\t\tsource.dispose();\n\t\t\temitter.reject(err);\n\t\t}\n\t});\n}\n\n//#endregion\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { FastDomNode } from 'vs/base/browser/fastDomNode';\nimport { TimeoutTimer } from 'vs/base/common/async';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { ScrollbarVisibility } from 'vs/base/common/scrollable';\n\nexport class ScrollbarVisibilityController extends Disposable {\n\tprivate _visibility: ScrollbarVisibility;\n\tprivate _visibleClassName: string;\n\tprivate _invisibleClassName: string;\n\tprivate _domNode: FastDomNode | null;\n\tprivate _rawShouldBeVisible: boolean;\n\tprivate _shouldBeVisible: boolean;\n\tprivate _isNeeded: boolean;\n\tprivate _isVisible: boolean;\n\tprivate _revealTimer: TimeoutTimer;\n\n\tconstructor(visibility: ScrollbarVisibility, visibleClassName: string, invisibleClassName: string) {\n\t\tsuper();\n\t\tthis._visibility = visibility;\n\t\tthis._visibleClassName = visibleClassName;\n\t\tthis._invisibleClassName = invisibleClassName;\n\t\tthis._domNode = null;\n\t\tthis._isVisible = false;\n\t\tthis._isNeeded = false;\n\t\tthis._rawShouldBeVisible = false;\n\t\tthis._shouldBeVisible = false;\n\t\tthis._revealTimer = this._register(new TimeoutTimer());\n\t}\n\n\tpublic setVisibility(visibility: ScrollbarVisibility): void {\n\t\tif (this._visibility !== visibility) {\n\t\t\tthis._visibility = visibility;\n\t\t\tthis._updateShouldBeVisible();\n\t\t}\n\t}\n\n\t// ----------------- Hide / Reveal\n\n\tpublic setShouldBeVisible(rawShouldBeVisible: boolean): void {\n\t\tthis._rawShouldBeVisible = rawShouldBeVisible;\n\t\tthis._updateShouldBeVisible();\n\t}\n\n\tprivate _applyVisibilitySetting(): boolean {\n\t\tif (this._visibility === ScrollbarVisibility.Hidden) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this._visibility === ScrollbarVisibility.Visible) {\n\t\t\treturn true;\n\t\t}\n\t\treturn this._rawShouldBeVisible;\n\t}\n\n\tprivate _updateShouldBeVisible(): void {\n\t\tconst shouldBeVisible = this._applyVisibilitySetting();\n\n\t\tif (this._shouldBeVisible !== shouldBeVisible) {\n\t\t\tthis._shouldBeVisible = shouldBeVisible;\n\t\t\tthis.ensureVisibility();\n\t\t}\n\t}\n\n\tpublic setIsNeeded(isNeeded: boolean): void {\n\t\tif (this._isNeeded !== isNeeded) {\n\t\t\tthis._isNeeded = isNeeded;\n\t\t\tthis.ensureVisibility();\n\t\t}\n\t}\n\n\tpublic setDomNode(domNode: FastDomNode): void {\n\t\tthis._domNode = domNode;\n\t\tthis._domNode.setClassName(this._invisibleClassName);\n\n\t\t// Now that the flags & the dom node are in a consistent state, ensure the Hidden/Visible configuration\n\t\tthis.setShouldBeVisible(false);\n\t}\n\n\tpublic ensureVisibility(): void {\n\n\t\tif (!this._isNeeded) {\n\t\t\t// Nothing to be rendered\n\t\t\tthis._hide(false);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this._shouldBeVisible) {\n\t\t\tthis._reveal();\n\t\t} else {\n\t\t\tthis._hide(true);\n\t\t}\n\t}\n\n\tprivate _reveal(): void {\n\t\tif (this._isVisible) {\n\t\t\treturn;\n\t\t}\n\t\tthis._isVisible = true;\n\n\t\t// The CSS animation doesn't play otherwise\n\t\tthis._revealTimer.setIfNotSet(() => {\n\t\t\tif (this._domNode) {\n\t\t\t\tthis._domNode.setClassName(this._visibleClassName);\n\t\t\t}\n\t\t}, 0);\n\t}\n\n\tprivate _hide(withFadeAway: boolean): void {\n\t\tthis._revealTimer.cancel();\n\t\tif (!this._isVisible) {\n\t\t\treturn;\n\t\t}\n\t\tthis._isVisible = false;\n\t\tif (this._domNode) {\n\t\t\tthis._domNode.setClassName(this._invisibleClassName + (withFadeAway ? ' fade' : ''));\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IdleValue } from 'vs/base/common/async';\n\n// When comparing large numbers of strings it's better for performance to create an\n// Intl.Collator object and use the function provided by its compare property\n// than it is to use String.prototype.localeCompare()\n\n// A collator with numeric sorting enabled, and no sensitivity to case, accents or diacritics.\nconst intlFileNameCollatorBaseNumeric: IdleValue<{ collator: Intl.Collator, collatorIsNumeric: boolean }> = new IdleValue(() => {\n\tconst collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });\n\treturn {\n\t\tcollator: collator,\n\t\tcollatorIsNumeric: collator.resolvedOptions().numeric\n\t};\n});\n\n// A collator with numeric sorting enabled.\nconst intlFileNameCollatorNumeric: IdleValue<{ collator: Intl.Collator }> = new IdleValue(() => {\n\tconst collator = new Intl.Collator(undefined, { numeric: true });\n\treturn {\n\t\tcollator: collator\n\t};\n});\n\n// A collator with numeric sorting enabled, and sensitivity to accents and diacritics but not case.\nconst intlFileNameCollatorNumericCaseInsensitive: IdleValue<{ collator: Intl.Collator }> = new IdleValue(() => {\n\tconst collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'accent' });\n\treturn {\n\t\tcollator: collator\n\t};\n});\n\n/** Compares filenames without distinguishing the name from the extension. Disambiguates by unicode comparison. */\nexport function compareFileNames(one: string | null, other: string | null, caseSensitive = false): number {\n\tconst a = one || '';\n\tconst b = other || '';\n\tconst result = intlFileNameCollatorBaseNumeric.value.collator.compare(a, b);\n\n\t// Using the numeric option will make compare(`foo1`, `foo01`) === 0. Disambiguate.\n\tif (intlFileNameCollatorBaseNumeric.value.collatorIsNumeric && result === 0 && a !== b) {\n\t\treturn a < b ? -1 : 1;\n\t}\n\n\treturn result;\n}\n\nexport function compareAnything(one: string, other: string, lookFor: string): number {\n\tconst elementAName = one.toLowerCase();\n\tconst elementBName = other.toLowerCase();\n\n\t// Sort prefix matches over non prefix matches\n\tconst prefixCompare = compareByPrefix(one, other, lookFor);\n\tif (prefixCompare) {\n\t\treturn prefixCompare;\n\t}\n\n\t// Sort suffix matches over non suffix matches\n\tconst elementASuffixMatch = elementAName.endsWith(lookFor);\n\tconst elementBSuffixMatch = elementBName.endsWith(lookFor);\n\tif (elementASuffixMatch !== elementBSuffixMatch) {\n\t\treturn elementASuffixMatch ? -1 : 1;\n\t}\n\n\t// Understand file names\n\tconst r = compareFileNames(elementAName, elementBName);\n\tif (r !== 0) {\n\t\treturn r;\n\t}\n\n\t// Compare by name\n\treturn elementAName.localeCompare(elementBName);\n}\n\nexport function compareByPrefix(one: string, other: string, lookFor: string): number {\n\tconst elementAName = one.toLowerCase();\n\tconst elementBName = other.toLowerCase();\n\n\t// Sort prefix matches over non prefix matches\n\tconst elementAPrefixMatch = elementAName.startsWith(lookFor);\n\tconst elementBPrefixMatch = elementBName.startsWith(lookFor);\n\tif (elementAPrefixMatch !== elementBPrefixMatch) {\n\t\treturn elementAPrefixMatch ? -1 : 1;\n\t}\n\n\t// Same prefix: Sort shorter matches to the top to have those on top that match more precisely\n\telse if (elementAPrefixMatch && elementBPrefixMatch) {\n\t\tif (elementAName.length < elementBName.length) {\n\t\t\treturn -1;\n\t\t}\n\n\t\tif (elementAName.length > elementBName.length) {\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\treturn 0;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\n\nexport const enum ScrollbarVisibility {\n\tAuto = 1,\n\tHidden = 2,\n\tVisible = 3\n}\n\nexport interface ScrollEvent {\n\tinSmoothScrolling: boolean;\n\n\toldWidth: number;\n\toldScrollWidth: number;\n\toldScrollLeft: number;\n\n\twidth: number;\n\tscrollWidth: number;\n\tscrollLeft: number;\n\n\toldHeight: number;\n\toldScrollHeight: number;\n\toldScrollTop: number;\n\n\theight: number;\n\tscrollHeight: number;\n\tscrollTop: number;\n\n\twidthChanged: boolean;\n\tscrollWidthChanged: boolean;\n\tscrollLeftChanged: boolean;\n\n\theightChanged: boolean;\n\tscrollHeightChanged: boolean;\n\tscrollTopChanged: boolean;\n}\n\nexport class ScrollState implements IScrollDimensions, IScrollPosition {\n\t_scrollStateBrand: void = undefined;\n\n\tpublic readonly rawScrollLeft: number;\n\tpublic readonly rawScrollTop: number;\n\n\tpublic readonly width: number;\n\tpublic readonly scrollWidth: number;\n\tpublic readonly scrollLeft: number;\n\tpublic readonly height: number;\n\tpublic readonly scrollHeight: number;\n\tpublic readonly scrollTop: number;\n\n\tconstructor(\n\t\tprivate readonly _forceIntegerValues: boolean,\n\t\twidth: number,\n\t\tscrollWidth: number,\n\t\tscrollLeft: number,\n\t\theight: number,\n\t\tscrollHeight: number,\n\t\tscrollTop: number\n\t) {\n\t\tif (this._forceIntegerValues) {\n\t\t\twidth = width | 0;\n\t\t\tscrollWidth = scrollWidth | 0;\n\t\t\tscrollLeft = scrollLeft | 0;\n\t\t\theight = height | 0;\n\t\t\tscrollHeight = scrollHeight | 0;\n\t\t\tscrollTop = scrollTop | 0;\n\t\t}\n\n\t\tthis.rawScrollLeft = scrollLeft; // before validation\n\t\tthis.rawScrollTop = scrollTop; // before validation\n\n\t\tif (width < 0) {\n\t\t\twidth = 0;\n\t\t}\n\t\tif (scrollLeft + width > scrollWidth) {\n\t\t\tscrollLeft = scrollWidth - width;\n\t\t}\n\t\tif (scrollLeft < 0) {\n\t\t\tscrollLeft = 0;\n\t\t}\n\n\t\tif (height < 0) {\n\t\t\theight = 0;\n\t\t}\n\t\tif (scrollTop + height > scrollHeight) {\n\t\t\tscrollTop = scrollHeight - height;\n\t\t}\n\t\tif (scrollTop < 0) {\n\t\t\tscrollTop = 0;\n\t\t}\n\n\t\tthis.width = width;\n\t\tthis.scrollWidth = scrollWidth;\n\t\tthis.scrollLeft = scrollLeft;\n\t\tthis.height = height;\n\t\tthis.scrollHeight = scrollHeight;\n\t\tthis.scrollTop = scrollTop;\n\t}\n\n\tpublic equals(other: ScrollState): boolean {\n\t\treturn (\n\t\t\tthis.rawScrollLeft === other.rawScrollLeft\n\t\t\t&& this.rawScrollTop === other.rawScrollTop\n\t\t\t&& this.width === other.width\n\t\t\t&& this.scrollWidth === other.scrollWidth\n\t\t\t&& this.scrollLeft === other.scrollLeft\n\t\t\t&& this.height === other.height\n\t\t\t&& this.scrollHeight === other.scrollHeight\n\t\t\t&& this.scrollTop === other.scrollTop\n\t\t);\n\t}\n\n\tpublic withScrollDimensions(update: INewScrollDimensions, useRawScrollPositions: boolean): ScrollState {\n\t\treturn new ScrollState(\n\t\t\tthis._forceIntegerValues,\n\t\t\t(typeof update.width !== 'undefined' ? update.width : this.width),\n\t\t\t(typeof update.scrollWidth !== 'undefined' ? update.scrollWidth : this.scrollWidth),\n\t\t\tuseRawScrollPositions ? this.rawScrollLeft : this.scrollLeft,\n\t\t\t(typeof update.height !== 'undefined' ? update.height : this.height),\n\t\t\t(typeof update.scrollHeight !== 'undefined' ? update.scrollHeight : this.scrollHeight),\n\t\t\tuseRawScrollPositions ? this.rawScrollTop : this.scrollTop\n\t\t);\n\t}\n\n\tpublic withScrollPosition(update: INewScrollPosition): ScrollState {\n\t\treturn new ScrollState(\n\t\t\tthis._forceIntegerValues,\n\t\t\tthis.width,\n\t\t\tthis.scrollWidth,\n\t\t\t(typeof update.scrollLeft !== 'undefined' ? update.scrollLeft : this.rawScrollLeft),\n\t\t\tthis.height,\n\t\t\tthis.scrollHeight,\n\t\t\t(typeof update.scrollTop !== 'undefined' ? update.scrollTop : this.rawScrollTop)\n\t\t);\n\t}\n\n\tpublic createScrollEvent(previous: ScrollState, inSmoothScrolling: boolean): ScrollEvent {\n\t\tconst widthChanged = (this.width !== previous.width);\n\t\tconst scrollWidthChanged = (this.scrollWidth !== previous.scrollWidth);\n\t\tconst scrollLeftChanged = (this.scrollLeft !== previous.scrollLeft);\n\n\t\tconst heightChanged = (this.height !== previous.height);\n\t\tconst scrollHeightChanged = (this.scrollHeight !== previous.scrollHeight);\n\t\tconst scrollTopChanged = (this.scrollTop !== previous.scrollTop);\n\n\t\treturn {\n\t\t\tinSmoothScrolling: inSmoothScrolling,\n\t\t\toldWidth: previous.width,\n\t\t\toldScrollWidth: previous.scrollWidth,\n\t\t\toldScrollLeft: previous.scrollLeft,\n\n\t\t\twidth: this.width,\n\t\t\tscrollWidth: this.scrollWidth,\n\t\t\tscrollLeft: this.scrollLeft,\n\n\t\t\toldHeight: previous.height,\n\t\t\toldScrollHeight: previous.scrollHeight,\n\t\t\toldScrollTop: previous.scrollTop,\n\n\t\t\theight: this.height,\n\t\t\tscrollHeight: this.scrollHeight,\n\t\t\tscrollTop: this.scrollTop,\n\n\t\t\twidthChanged: widthChanged,\n\t\t\tscrollWidthChanged: scrollWidthChanged,\n\t\t\tscrollLeftChanged: scrollLeftChanged,\n\n\t\t\theightChanged: heightChanged,\n\t\t\tscrollHeightChanged: scrollHeightChanged,\n\t\t\tscrollTopChanged: scrollTopChanged,\n\t\t};\n\t}\n\n}\n\nexport interface IScrollDimensions {\n\treadonly width: number;\n\treadonly scrollWidth: number;\n\treadonly height: number;\n\treadonly scrollHeight: number;\n}\nexport interface INewScrollDimensions {\n\twidth?: number;\n\tscrollWidth?: number;\n\theight?: number;\n\tscrollHeight?: number;\n}\n\nexport interface IScrollPosition {\n\treadonly scrollLeft: number;\n\treadonly scrollTop: number;\n}\nexport interface ISmoothScrollPosition {\n\treadonly scrollLeft: number;\n\treadonly scrollTop: number;\n\n\treadonly width: number;\n\treadonly height: number;\n}\nexport interface INewScrollPosition {\n\tscrollLeft?: number;\n\tscrollTop?: number;\n}\n\nexport interface IScrollableOptions {\n\t/**\n\t * Define if the scroll values should always be integers.\n\t */\n\tforceIntegerValues: boolean;\n\t/**\n\t * Set the duration (ms) used for smooth scroll animations.\n\t */\n\tsmoothScrollDuration: number;\n\t/**\n\t * A function to schedule an update at the next frame (used for smooth scroll animations).\n\t */\n\tscheduleAtNextAnimationFrame: (callback: () => void) => IDisposable;\n}\n\nexport class Scrollable extends Disposable {\n\n\t_scrollableBrand: void = undefined;\n\n\tprivate _smoothScrollDuration: number;\n\tprivate readonly _scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable;\n\tprivate _state: ScrollState;\n\tprivate _smoothScrolling: SmoothScrollingOperation | null;\n\n\tprivate _onScroll = this._register(new Emitter());\n\tpublic readonly onScroll: Event = this._onScroll.event;\n\n\tconstructor(options: IScrollableOptions) {\n\t\tsuper();\n\n\t\tthis._smoothScrollDuration = options.smoothScrollDuration;\n\t\tthis._scheduleAtNextAnimationFrame = options.scheduleAtNextAnimationFrame;\n\t\tthis._state = new ScrollState(options.forceIntegerValues, 0, 0, 0, 0, 0, 0);\n\t\tthis._smoothScrolling = null;\n\t}\n\n\tpublic override dispose(): void {\n\t\tif (this._smoothScrolling) {\n\t\t\tthis._smoothScrolling.dispose();\n\t\t\tthis._smoothScrolling = null;\n\t\t}\n\t\tsuper.dispose();\n\t}\n\n\tpublic setSmoothScrollDuration(smoothScrollDuration: number): void {\n\t\tthis._smoothScrollDuration = smoothScrollDuration;\n\t}\n\n\tpublic validateScrollPosition(scrollPosition: INewScrollPosition): IScrollPosition {\n\t\treturn this._state.withScrollPosition(scrollPosition);\n\t}\n\n\tpublic getScrollDimensions(): IScrollDimensions {\n\t\treturn this._state;\n\t}\n\n\tpublic setScrollDimensions(dimensions: INewScrollDimensions, useRawScrollPositions: boolean): void {\n\t\tconst newState = this._state.withScrollDimensions(dimensions, useRawScrollPositions);\n\t\tthis._setState(newState, Boolean(this._smoothScrolling));\n\n\t\t// Validate outstanding animated scroll position target\n\t\tif (this._smoothScrolling) {\n\t\t\tthis._smoothScrolling.acceptScrollDimensions(this._state);\n\t\t}\n\t}\n\n\t/**\n\t * Returns the final scroll position that the instance will have once the smooth scroll animation concludes.\n\t * If no scroll animation is occurring, it will return the current scroll position instead.\n\t */\n\tpublic getFutureScrollPosition(): IScrollPosition {\n\t\tif (this._smoothScrolling) {\n\t\t\treturn this._smoothScrolling.to;\n\t\t}\n\t\treturn this._state;\n\t}\n\n\t/**\n\t * Returns the current scroll position.\n\t * Note: This result might be an intermediate scroll position, as there might be an ongoing smooth scroll animation.\n\t */\n\tpublic getCurrentScrollPosition(): IScrollPosition {\n\t\treturn this._state;\n\t}\n\n\tpublic setScrollPositionNow(update: INewScrollPosition): void {\n\t\t// no smooth scrolling requested\n\t\tconst newState = this._state.withScrollPosition(update);\n\n\t\t// Terminate any outstanding smooth scrolling\n\t\tif (this._smoothScrolling) {\n\t\t\tthis._smoothScrolling.dispose();\n\t\t\tthis._smoothScrolling = null;\n\t\t}\n\n\t\tthis._setState(newState, false);\n\t}\n\n\tpublic setScrollPositionSmooth(update: INewScrollPosition, reuseAnimation?: boolean): void {\n\t\tif (this._smoothScrollDuration === 0) {\n\t\t\t// Smooth scrolling not supported.\n\t\t\treturn this.setScrollPositionNow(update);\n\t\t}\n\n\t\tif (this._smoothScrolling) {\n\t\t\t// Combine our pending scrollLeft/scrollTop with incoming scrollLeft/scrollTop\n\t\t\tupdate = {\n\t\t\t\tscrollLeft: (typeof update.scrollLeft === 'undefined' ? this._smoothScrolling.to.scrollLeft : update.scrollLeft),\n\t\t\t\tscrollTop: (typeof update.scrollTop === 'undefined' ? this._smoothScrolling.to.scrollTop : update.scrollTop)\n\t\t\t};\n\n\t\t\t// Validate `update`\n\t\t\tconst validTarget = this._state.withScrollPosition(update);\n\n\t\t\tif (this._smoothScrolling.to.scrollLeft === validTarget.scrollLeft && this._smoothScrolling.to.scrollTop === validTarget.scrollTop) {\n\t\t\t\t// No need to interrupt or extend the current animation since we're going to the same place\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet newSmoothScrolling: SmoothScrollingOperation;\n\t\t\tif (reuseAnimation) {\n\t\t\t\tnewSmoothScrolling = new SmoothScrollingOperation(this._smoothScrolling.from, validTarget, this._smoothScrolling.startTime, this._smoothScrolling.duration);\n\t\t\t} else {\n\t\t\t\tnewSmoothScrolling = this._smoothScrolling.combine(this._state, validTarget, this._smoothScrollDuration);\n\t\t\t}\n\t\t\tthis._smoothScrolling.dispose();\n\t\t\tthis._smoothScrolling = newSmoothScrolling;\n\t\t} else {\n\t\t\t// Validate `update`\n\t\t\tconst validTarget = this._state.withScrollPosition(update);\n\n\t\t\tthis._smoothScrolling = SmoothScrollingOperation.start(this._state, validTarget, this._smoothScrollDuration);\n\t\t}\n\n\t\t// Begin smooth scrolling animation\n\t\tthis._smoothScrolling.animationFrameDisposable = this._scheduleAtNextAnimationFrame(() => {\n\t\t\tif (!this._smoothScrolling) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._smoothScrolling.animationFrameDisposable = null;\n\t\t\tthis._performSmoothScrolling();\n\t\t});\n\t}\n\n\tprivate _performSmoothScrolling(): void {\n\t\tif (!this._smoothScrolling) {\n\t\t\treturn;\n\t\t}\n\t\tconst update = this._smoothScrolling.tick();\n\t\tconst newState = this._state.withScrollPosition(update);\n\n\t\tthis._setState(newState, true);\n\n\t\tif (!this._smoothScrolling) {\n\t\t\t// Looks like someone canceled the smooth scrolling\n\t\t\t// from the scroll event handler\n\t\t\treturn;\n\t\t}\n\n\t\tif (update.isDone) {\n\t\t\tthis._smoothScrolling.dispose();\n\t\t\tthis._smoothScrolling = null;\n\t\t\treturn;\n\t\t}\n\n\t\t// Continue smooth scrolling animation\n\t\tthis._smoothScrolling.animationFrameDisposable = this._scheduleAtNextAnimationFrame(() => {\n\t\t\tif (!this._smoothScrolling) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._smoothScrolling.animationFrameDisposable = null;\n\t\t\tthis._performSmoothScrolling();\n\t\t});\n\t}\n\n\tprivate _setState(newState: ScrollState, inSmoothScrolling: boolean): void {\n\t\tconst oldState = this._state;\n\t\tif (oldState.equals(newState)) {\n\t\t\t// no change\n\t\t\treturn;\n\t\t}\n\t\tthis._state = newState;\n\t\tthis._onScroll.fire(this._state.createScrollEvent(oldState, inSmoothScrolling));\n\t}\n}\n\nexport class SmoothScrollingUpdate {\n\n\tpublic readonly scrollLeft: number;\n\tpublic readonly scrollTop: number;\n\tpublic readonly isDone: boolean;\n\n\tconstructor(scrollLeft: number, scrollTop: number, isDone: boolean) {\n\t\tthis.scrollLeft = scrollLeft;\n\t\tthis.scrollTop = scrollTop;\n\t\tthis.isDone = isDone;\n\t}\n\n}\n\nexport interface IAnimation {\n\t(completion: number): number;\n}\n\nfunction createEaseOutCubic(from: number, to: number): IAnimation {\n\tconst delta = to - from;\n\treturn function (completion: number): number {\n\t\treturn from + delta * easeOutCubic(completion);\n\t};\n}\n\nfunction createComposed(a: IAnimation, b: IAnimation, cut: number): IAnimation {\n\treturn function (completion: number): number {\n\t\tif (completion < cut) {\n\t\t\treturn a(completion / cut);\n\t\t}\n\t\treturn b((completion - cut) / (1 - cut));\n\t};\n}\n\nexport class SmoothScrollingOperation {\n\n\tpublic readonly from: ISmoothScrollPosition;\n\tpublic to: ISmoothScrollPosition;\n\tpublic readonly duration: number;\n\tpublic readonly startTime: number;\n\tpublic animationFrameDisposable: IDisposable | null;\n\n\tprivate scrollLeft!: IAnimation;\n\tprivate scrollTop!: IAnimation;\n\n\tconstructor(from: ISmoothScrollPosition, to: ISmoothScrollPosition, startTime: number, duration: number) {\n\t\tthis.from = from;\n\t\tthis.to = to;\n\t\tthis.duration = duration;\n\t\tthis.startTime = startTime;\n\n\t\tthis.animationFrameDisposable = null;\n\n\t\tthis._initAnimations();\n\t}\n\n\tprivate _initAnimations(): void {\n\t\tthis.scrollLeft = this._initAnimation(this.from.scrollLeft, this.to.scrollLeft, this.to.width);\n\t\tthis.scrollTop = this._initAnimation(this.from.scrollTop, this.to.scrollTop, this.to.height);\n\t}\n\n\tprivate _initAnimation(from: number, to: number, viewportSize: number): IAnimation {\n\t\tconst delta = Math.abs(from - to);\n\t\tif (delta > 2.5 * viewportSize) {\n\t\t\tlet stop1: number, stop2: number;\n\t\t\tif (from < to) {\n\t\t\t\t// scroll to 75% of the viewportSize\n\t\t\t\tstop1 = from + 0.75 * viewportSize;\n\t\t\t\tstop2 = to - 0.75 * viewportSize;\n\t\t\t} else {\n\t\t\t\tstop1 = from - 0.75 * viewportSize;\n\t\t\t\tstop2 = to + 0.75 * viewportSize;\n\t\t\t}\n\t\t\treturn createComposed(createEaseOutCubic(from, stop1), createEaseOutCubic(stop2, to), 0.33);\n\t\t}\n\t\treturn createEaseOutCubic(from, to);\n\t}\n\n\tpublic dispose(): void {\n\t\tif (this.animationFrameDisposable !== null) {\n\t\t\tthis.animationFrameDisposable.dispose();\n\t\t\tthis.animationFrameDisposable = null;\n\t\t}\n\t}\n\n\tpublic acceptScrollDimensions(state: ScrollState): void {\n\t\tthis.to = state.withScrollPosition(this.to);\n\t\tthis._initAnimations();\n\t}\n\n\tpublic tick(): SmoothScrollingUpdate {\n\t\treturn this._tick(Date.now());\n\t}\n\n\tprotected _tick(now: number): SmoothScrollingUpdate {\n\t\tconst completion = (now - this.startTime) / this.duration;\n\n\t\tif (completion < 1) {\n\t\t\tconst newScrollLeft = this.scrollLeft(completion);\n\t\t\tconst newScrollTop = this.scrollTop(completion);\n\t\t\treturn new SmoothScrollingUpdate(newScrollLeft, newScrollTop, false);\n\t\t}\n\n\t\treturn new SmoothScrollingUpdate(this.to.scrollLeft, this.to.scrollTop, true);\n\t}\n\n\tpublic combine(from: ISmoothScrollPosition, to: ISmoothScrollPosition, duration: number): SmoothScrollingOperation {\n\t\treturn SmoothScrollingOperation.start(from, to, duration);\n\t}\n\n\tpublic static start(from: ISmoothScrollPosition, to: ISmoothScrollPosition, duration: number): SmoothScrollingOperation {\n\t\t// +10 / -10 : pretend the animation already started for a quicker response to a scroll request\n\t\tduration = duration + 10;\n\t\tconst startTime = Date.now() - 10;\n\n\t\treturn new SmoothScrollingOperation(from, to, startTime, duration);\n\t}\n}\n\nfunction easeInCubic(t: number) {\n\treturn Math.pow(t, 3);\n}\n\nfunction easeOutCubic(t: number) {\n\treturn 1 - easeInCubic(1 - t);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { LRUCachedComputed } from 'vs/base/common/cache';\nimport { CharCode } from 'vs/base/common/charCode';\nimport { Lazy } from 'vs/base/common/lazy';\nimport { Constants } from 'vs/base/common/uint';\n\nexport function isFalsyOrWhitespace(str: string | undefined): boolean {\n\tif (!str || typeof str !== 'string') {\n\t\treturn true;\n\t}\n\treturn str.trim().length === 0;\n}\n\nconst _formatRegexp = /{(\\d+)}/g;\n\n/**\n * Helper to produce a string with a variable number of arguments. Insert variable segments\n * into the string using the {n} notation where N is the index of the argument following the string.\n * @param value string to which formatting is applied\n * @param args replacements for {n}-entries\n */\nexport function format(value: string, ...args: any[]): string {\n\tif (args.length === 0) {\n\t\treturn value;\n\t}\n\treturn value.replace(_formatRegexp, function (match, group) {\n\t\tconst idx = parseInt(group, 10);\n\t\treturn isNaN(idx) || idx < 0 || idx >= args.length ?\n\t\t\tmatch :\n\t\t\targs[idx];\n\t});\n}\n\n/**\n * Converts HTML characters inside the string to use entities instead. Makes the string safe from\n * being used e.g. in HTMLElement.innerHTML.\n */\nexport function escape(html: string): string {\n\treturn html.replace(/[<>&]/g, function (match) {\n\t\tswitch (match) {\n\t\t\tcase '<': return '<';\n\t\t\tcase '>': return '>';\n\t\t\tcase '&': return '&';\n\t\t\tdefault: return match;\n\t\t}\n\t});\n}\n\n/**\n * Escapes regular expression characters in a given string\n */\nexport function escapeRegExpCharacters(value: string): string {\n\treturn value.replace(/[\\\\\\{\\}\\*\\+\\?\\|\\^\\$\\.\\[\\]\\(\\)]/g, '\\\\$&');\n}\n\n/**\n * Removes all occurrences of needle from the beginning and end of haystack.\n * @param haystack string to trim\n * @param needle the thing to trim (default is a blank)\n */\nexport function trim(haystack: string, needle: string = ' '): string {\n\tconst trimmed = ltrim(haystack, needle);\n\treturn rtrim(trimmed, needle);\n}\n\n/**\n * Removes all occurrences of needle from the beginning of haystack.\n * @param haystack string to trim\n * @param needle the thing to trim\n */\nexport function ltrim(haystack: string, needle: string): string {\n\tif (!haystack || !needle) {\n\t\treturn haystack;\n\t}\n\n\tconst needleLen = needle.length;\n\tif (needleLen === 0 || haystack.length === 0) {\n\t\treturn haystack;\n\t}\n\n\tlet offset = 0;\n\n\twhile (haystack.indexOf(needle, offset) === offset) {\n\t\toffset = offset + needleLen;\n\t}\n\treturn haystack.substring(offset);\n}\n\n/**\n * Removes all occurrences of needle from the end of haystack.\n * @param haystack string to trim\n * @param needle the thing to trim\n */\nexport function rtrim(haystack: string, needle: string): string {\n\tif (!haystack || !needle) {\n\t\treturn haystack;\n\t}\n\n\tconst needleLen = needle.length,\n\t\thaystackLen = haystack.length;\n\n\tif (needleLen === 0 || haystackLen === 0) {\n\t\treturn haystack;\n\t}\n\n\tlet offset = haystackLen,\n\t\tidx = -1;\n\n\twhile (true) {\n\t\tidx = haystack.lastIndexOf(needle, offset - 1);\n\t\tif (idx === -1 || idx + needleLen !== offset) {\n\t\t\tbreak;\n\t\t}\n\t\tif (idx === 0) {\n\t\t\treturn '';\n\t\t}\n\t\toffset = idx;\n\t}\n\n\treturn haystack.substring(0, offset);\n}\n\nexport function convertSimple2RegExpPattern(pattern: string): string {\n\treturn pattern.replace(/[\\-\\\\\\{\\}\\+\\?\\|\\^\\$\\.\\,\\[\\]\\(\\)\\#\\s]/g, '\\\\$&').replace(/[\\*]/g, '.*');\n}\n\nexport function stripWildcards(pattern: string): string {\n\treturn pattern.replace(/\\*/g, '');\n}\n\nexport interface RegExpOptions {\n\tmatchCase?: boolean;\n\twholeWord?: boolean;\n\tmultiline?: boolean;\n\tglobal?: boolean;\n\tunicode?: boolean;\n}\n\nexport function createRegExp(searchString: string, isRegex: boolean, options: RegExpOptions = {}): RegExp {\n\tif (!searchString) {\n\t\tthrow new Error('Cannot create regex from empty string');\n\t}\n\tif (!isRegex) {\n\t\tsearchString = escapeRegExpCharacters(searchString);\n\t}\n\tif (options.wholeWord) {\n\t\tif (!/\\B/.test(searchString.charAt(0))) {\n\t\t\tsearchString = '\\\\b' + searchString;\n\t\t}\n\t\tif (!/\\B/.test(searchString.charAt(searchString.length - 1))) {\n\t\t\tsearchString = searchString + '\\\\b';\n\t\t}\n\t}\n\tlet modifiers = '';\n\tif (options.global) {\n\t\tmodifiers += 'g';\n\t}\n\tif (!options.matchCase) {\n\t\tmodifiers += 'i';\n\t}\n\tif (options.multiline) {\n\t\tmodifiers += 'm';\n\t}\n\tif (options.unicode) {\n\t\tmodifiers += 'u';\n\t}\n\n\treturn new RegExp(searchString, modifiers);\n}\n\nexport function regExpLeadsToEndlessLoop(regexp: RegExp): boolean {\n\t// Exit early if it's one of these special cases which are meant to match\n\t// against an empty string\n\tif (regexp.source === '^' || regexp.source === '^$' || regexp.source === '$' || regexp.source === '^\\\\s*$') {\n\t\treturn false;\n\t}\n\n\t// We check against an empty string. If the regular expression doesn't advance\n\t// (e.g. ends in an endless loop) it will match an empty string.\n\tconst match = regexp.exec('');\n\treturn !!(match && regexp.lastIndex === 0);\n}\n\nexport function regExpFlags(regexp: RegExp): string {\n\treturn (regexp.global ? 'g' : '')\n\t\t+ (regexp.ignoreCase ? 'i' : '')\n\t\t+ (regexp.multiline ? 'm' : '')\n\t\t+ ((regexp as any /* standalone editor compilation */).unicode ? 'u' : '');\n}\n\nexport function splitLines(str: string): string[] {\n\treturn str.split(/\\r\\n|\\r|\\n/);\n}\n\n/**\n * Returns first index of the string that is not whitespace.\n * If string is empty or contains only whitespaces, returns -1\n */\nexport function firstNonWhitespaceIndex(str: string): number {\n\tfor (let i = 0, len = str.length; i < len; i++) {\n\t\tconst chCode = str.charCodeAt(i);\n\t\tif (chCode !== CharCode.Space && chCode !== CharCode.Tab) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\n\n/**\n * Returns the leading whitespace of the string.\n * If the string contains only whitespaces, returns entire string\n */\nexport function getLeadingWhitespace(str: string, start: number = 0, end: number = str.length): string {\n\tfor (let i = start; i < end; i++) {\n\t\tconst chCode = str.charCodeAt(i);\n\t\tif (chCode !== CharCode.Space && chCode !== CharCode.Tab) {\n\t\t\treturn str.substring(start, i);\n\t\t}\n\t}\n\treturn str.substring(start, end);\n}\n\n/**\n * Returns last index of the string that is not whitespace.\n * If string is empty or contains only whitespaces, returns -1\n */\nexport function lastNonWhitespaceIndex(str: string, startIndex: number = str.length - 1): number {\n\tfor (let i = startIndex; i >= 0; i--) {\n\t\tconst chCode = str.charCodeAt(i);\n\t\tif (chCode !== CharCode.Space && chCode !== CharCode.Tab) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\n\nexport function compare(a: string, b: string): number {\n\tif (a < b) {\n\t\treturn -1;\n\t} else if (a > b) {\n\t\treturn 1;\n\t} else {\n\t\treturn 0;\n\t}\n}\n\nexport function compareSubstring(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {\n\tfor (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {\n\t\tlet codeA = a.charCodeAt(aStart);\n\t\tlet codeB = b.charCodeAt(bStart);\n\t\tif (codeA < codeB) {\n\t\t\treturn -1;\n\t\t} else if (codeA > codeB) {\n\t\t\treturn 1;\n\t\t}\n\t}\n\tconst aLen = aEnd - aStart;\n\tconst bLen = bEnd - bStart;\n\tif (aLen < bLen) {\n\t\treturn -1;\n\t} else if (aLen > bLen) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nexport function compareIgnoreCase(a: string, b: string): number {\n\treturn compareSubstringIgnoreCase(a, b, 0, a.length, 0, b.length);\n}\n\nexport function compareSubstringIgnoreCase(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {\n\n\tfor (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {\n\n\t\tlet codeA = a.charCodeAt(aStart);\n\t\tlet codeB = b.charCodeAt(bStart);\n\n\t\tif (codeA === codeB) {\n\t\t\t// equal\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (codeA >= 128 || codeB >= 128) {\n\t\t\t// not ASCII letters -> fallback to lower-casing strings\n\t\t\treturn compareSubstring(a.toLowerCase(), b.toLowerCase(), aStart, aEnd, bStart, bEnd);\n\t\t}\n\n\t\t// mapper lower-case ascii letter onto upper-case varinats\n\t\t// [97-122] (lower ascii) --> [65-90] (upper ascii)\n\t\tif (isLowerAsciiLetter(codeA)) {\n\t\t\tcodeA -= 32;\n\t\t}\n\t\tif (isLowerAsciiLetter(codeB)) {\n\t\t\tcodeB -= 32;\n\t\t}\n\n\t\t// compare both code points\n\t\tconst diff = codeA - codeB;\n\t\tif (diff === 0) {\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn diff;\n\t}\n\n\tconst aLen = aEnd - aStart;\n\tconst bLen = bEnd - bStart;\n\n\tif (aLen < bLen) {\n\t\treturn -1;\n\t} else if (aLen > bLen) {\n\t\treturn 1;\n\t}\n\n\treturn 0;\n}\n\nexport function isLowerAsciiLetter(code: number): boolean {\n\treturn code >= CharCode.a && code <= CharCode.z;\n}\n\nexport function isUpperAsciiLetter(code: number): boolean {\n\treturn code >= CharCode.A && code <= CharCode.Z;\n}\n\nexport function equalsIgnoreCase(a: string, b: string): boolean {\n\treturn a.length === b.length && compareSubstringIgnoreCase(a, b) === 0;\n}\n\nexport function startsWithIgnoreCase(str: string, candidate: string): boolean {\n\tconst candidateLength = candidate.length;\n\tif (candidate.length > str.length) {\n\t\treturn false;\n\t}\n\n\treturn compareSubstringIgnoreCase(str, candidate, 0, candidateLength) === 0;\n}\n\n/**\n * @returns the length of the common prefix of the two strings.\n */\nexport function commonPrefixLength(a: string, b: string): number {\n\n\tlet i: number,\n\t\tlen = Math.min(a.length, b.length);\n\n\tfor (i = 0; i < len; i++) {\n\t\tif (a.charCodeAt(i) !== b.charCodeAt(i)) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn len;\n}\n\n/**\n * @returns the length of the common suffix of the two strings.\n */\nexport function commonSuffixLength(a: string, b: string): number {\n\n\tlet i: number,\n\t\tlen = Math.min(a.length, b.length);\n\n\tconst aLastIndex = a.length - 1;\n\tconst bLastIndex = b.length - 1;\n\n\tfor (i = 0; i < len; i++) {\n\t\tif (a.charCodeAt(aLastIndex - i) !== b.charCodeAt(bLastIndex - i)) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn len;\n}\n\n/**\n * See http://en.wikipedia.org/wiki/Surrogate_pair\n */\nexport function isHighSurrogate(charCode: number): boolean {\n\treturn (0xD800 <= charCode && charCode <= 0xDBFF);\n}\n\n/**\n * See http://en.wikipedia.org/wiki/Surrogate_pair\n */\nexport function isLowSurrogate(charCode: number): boolean {\n\treturn (0xDC00 <= charCode && charCode <= 0xDFFF);\n}\n\n/**\n * See http://en.wikipedia.org/wiki/Surrogate_pair\n */\nexport function computeCodePoint(highSurrogate: number, lowSurrogate: number): number {\n\treturn ((highSurrogate - 0xD800) << 10) + (lowSurrogate - 0xDC00) + 0x10000;\n}\n\n/**\n * get the code point that begins at offset `offset`\n */\nexport function getNextCodePoint(str: string, len: number, offset: number): number {\n\tconst charCode = str.charCodeAt(offset);\n\tif (isHighSurrogate(charCode) && offset + 1 < len) {\n\t\tconst nextCharCode = str.charCodeAt(offset + 1);\n\t\tif (isLowSurrogate(nextCharCode)) {\n\t\t\treturn computeCodePoint(charCode, nextCharCode);\n\t\t}\n\t}\n\treturn charCode;\n}\n\n/**\n * get the code point that ends right before offset `offset`\n */\nfunction getPrevCodePoint(str: string, offset: number): number {\n\tconst charCode = str.charCodeAt(offset - 1);\n\tif (isLowSurrogate(charCode) && offset > 1) {\n\t\tconst prevCharCode = str.charCodeAt(offset - 2);\n\t\tif (isHighSurrogate(prevCharCode)) {\n\t\t\treturn computeCodePoint(prevCharCode, charCode);\n\t\t}\n\t}\n\treturn charCode;\n}\n\nexport class CodePointIterator {\n\n\tprivate readonly _str: string;\n\tprivate readonly _len: number;\n\tprivate _offset: number;\n\n\tpublic get offset(): number {\n\t\treturn this._offset;\n\t}\n\n\tconstructor(str: string, offset: number = 0) {\n\t\tthis._str = str;\n\t\tthis._len = str.length;\n\t\tthis._offset = offset;\n\t}\n\n\tpublic setOffset(offset: number): void {\n\t\tthis._offset = offset;\n\t}\n\n\tpublic prevCodePoint(): number {\n\t\tconst codePoint = getPrevCodePoint(this._str, this._offset);\n\t\tthis._offset -= (codePoint >= Constants.UNICODE_SUPPLEMENTARY_PLANE_BEGIN ? 2 : 1);\n\t\treturn codePoint;\n\t}\n\n\tpublic nextCodePoint(): number {\n\t\tconst codePoint = getNextCodePoint(this._str, this._len, this._offset);\n\t\tthis._offset += (codePoint >= Constants.UNICODE_SUPPLEMENTARY_PLANE_BEGIN ? 2 : 1);\n\t\treturn codePoint;\n\t}\n\n\tpublic eol(): boolean {\n\t\treturn (this._offset >= this._len);\n\t}\n}\n\nexport class GraphemeIterator {\n\n\tprivate readonly _iterator: CodePointIterator;\n\n\tpublic get offset(): number {\n\t\treturn this._iterator.offset;\n\t}\n\n\tconstructor(str: string, offset: number = 0) {\n\t\tthis._iterator = new CodePointIterator(str, offset);\n\t}\n\n\tpublic nextGraphemeLength(): number {\n\t\tconst graphemeBreakTree = GraphemeBreakTree.getInstance();\n\t\tconst iterator = this._iterator;\n\t\tconst initialOffset = iterator.offset;\n\n\t\tlet graphemeBreakType = graphemeBreakTree.getGraphemeBreakType(iterator.nextCodePoint());\n\t\twhile (!iterator.eol()) {\n\t\t\tconst offset = iterator.offset;\n\t\t\tconst nextGraphemeBreakType = graphemeBreakTree.getGraphemeBreakType(iterator.nextCodePoint());\n\t\t\tif (breakBetweenGraphemeBreakType(graphemeBreakType, nextGraphemeBreakType)) {\n\t\t\t\t// move iterator back\n\t\t\t\titerator.setOffset(offset);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tgraphemeBreakType = nextGraphemeBreakType;\n\t\t}\n\t\treturn (iterator.offset - initialOffset);\n\t}\n\n\tpublic prevGraphemeLength(): number {\n\t\tconst graphemeBreakTree = GraphemeBreakTree.getInstance();\n\t\tconst iterator = this._iterator;\n\t\tconst initialOffset = iterator.offset;\n\n\t\tlet graphemeBreakType = graphemeBreakTree.getGraphemeBreakType(iterator.prevCodePoint());\n\t\twhile (iterator.offset > 0) {\n\t\t\tconst offset = iterator.offset;\n\t\t\tconst prevGraphemeBreakType = graphemeBreakTree.getGraphemeBreakType(iterator.prevCodePoint());\n\t\t\tif (breakBetweenGraphemeBreakType(prevGraphemeBreakType, graphemeBreakType)) {\n\t\t\t\t// move iterator back\n\t\t\t\titerator.setOffset(offset);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tgraphemeBreakType = prevGraphemeBreakType;\n\t\t}\n\t\treturn (initialOffset - iterator.offset);\n\t}\n\n\tpublic eol(): boolean {\n\t\treturn this._iterator.eol();\n\t}\n}\n\nexport function nextCharLength(str: string, initialOffset: number): number {\n\tconst iterator = new GraphemeIterator(str, initialOffset);\n\treturn iterator.nextGraphemeLength();\n}\n\nexport function prevCharLength(str: string, initialOffset: number): number {\n\tconst iterator = new GraphemeIterator(str, initialOffset);\n\treturn iterator.prevGraphemeLength();\n}\n\nexport function getCharContainingOffset(str: string, offset: number): [number, number] {\n\tif (offset > 0 && isLowSurrogate(str.charCodeAt(offset))) {\n\t\toffset--;\n\t}\n\tconst endOffset = offset + nextCharLength(str, offset);\n\tconst startOffset = endOffset - prevCharLength(str, endOffset);\n\treturn [startOffset, endOffset];\n}\n\n/**\n * Generated using https://github.com/alexdima/unicode-utils/blob/main/rtl-test.js\n */\nconst CONTAINS_RTL = /(?:[\\u05BE\\u05C0\\u05C3\\u05C6\\u05D0-\\u05F4\\u0608\\u060B\\u060D\\u061B-\\u064A\\u066D-\\u066F\\u0671-\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1-\\u07EA\\u07F4\\u07F5\\u07FA\\u07FE-\\u0815\\u081A\\u0824\\u0828\\u0830-\\u0858\\u085E-\\u088E\\u08A0-\\u08C9\\u200F\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFD3D\\uFD50-\\uFDC7\\uFDF0-\\uFDFC\\uFE70-\\uFEFC]|\\uD802[\\uDC00-\\uDD1B\\uDD20-\\uDE00\\uDE10-\\uDE35\\uDE40-\\uDEE4\\uDEEB-\\uDF35\\uDF40-\\uDFFF]|\\uD803[\\uDC00-\\uDD23\\uDE80-\\uDEA9\\uDEAD-\\uDF45\\uDF51-\\uDF81\\uDF86-\\uDFF6]|\\uD83A[\\uDC00-\\uDCCF\\uDD00-\\uDD43\\uDD4B-\\uDFFF]|\\uD83B[\\uDC00-\\uDEBB])/;\n\n/**\n * Returns true if `str` contains any Unicode character that is classified as \"R\" or \"AL\".\n */\nexport function containsRTL(str: string): boolean {\n\treturn CONTAINS_RTL.test(str);\n}\n\nconst IS_BASIC_ASCII = /^[\\t\\n\\r\\x20-\\x7E]*$/;\n/**\n * Returns true if `str` contains only basic ASCII characters in the range 32 - 126 (including 32 and 126) or \\n, \\r, \\t\n */\nexport function isBasicASCII(str: string): boolean {\n\treturn IS_BASIC_ASCII.test(str);\n}\n\nexport const UNUSUAL_LINE_TERMINATORS = /[\\u2028\\u2029]/; // LINE SEPARATOR (LS) or PARAGRAPH SEPARATOR (PS)\n/**\n * Returns true if `str` contains unusual line terminators, like LS or PS\n */\nexport function containsUnusualLineTerminators(str: string): boolean {\n\treturn UNUSUAL_LINE_TERMINATORS.test(str);\n}\n\nexport function isFullWidthCharacter(charCode: number): boolean {\n\t// Do a cheap trick to better support wrapping of wide characters, treat them as 2 columns\n\t// http://jrgraphix.net/research/unicode_blocks.php\n\t// 2E80 - 2EFF CJK Radicals Supplement\n\t// 2F00 - 2FDF Kangxi Radicals\n\t// 2FF0 - 2FFF Ideographic Description Characters\n\t// 3000 - 303F CJK Symbols and Punctuation\n\t// 3040 - 309F Hiragana\n\t// 30A0 - 30FF Katakana\n\t// 3100 - 312F Bopomofo\n\t// 3130 - 318F Hangul Compatibility Jamo\n\t// 3190 - 319F Kanbun\n\t// 31A0 - 31BF Bopomofo Extended\n\t// 31F0 - 31FF Katakana Phonetic Extensions\n\t// 3200 - 32FF Enclosed CJK Letters and Months\n\t// 3300 - 33FF CJK Compatibility\n\t// 3400 - 4DBF CJK Unified Ideographs Extension A\n\t// 4DC0 - 4DFF Yijing Hexagram Symbols\n\t// 4E00 - 9FFF CJK Unified Ideographs\n\t// A000 - A48F Yi Syllables\n\t// A490 - A4CF Yi Radicals\n\t// AC00 - D7AF Hangul Syllables\n\t// [IGNORE] D800 - DB7F High Surrogates\n\t// [IGNORE] DB80 - DBFF High Private Use Surrogates\n\t// [IGNORE] DC00 - DFFF Low Surrogates\n\t// [IGNORE] E000 - F8FF Private Use Area\n\t// F900 - FAFF CJK Compatibility Ideographs\n\t// [IGNORE] FB00 - FB4F Alphabetic Presentation Forms\n\t// [IGNORE] FB50 - FDFF Arabic Presentation Forms-A\n\t// [IGNORE] FE00 - FE0F Variation Selectors\n\t// [IGNORE] FE20 - FE2F Combining Half Marks\n\t// [IGNORE] FE30 - FE4F CJK Compatibility Forms\n\t// [IGNORE] FE50 - FE6F Small Form Variants\n\t// [IGNORE] FE70 - FEFF Arabic Presentation Forms-B\n\t// FF00 - FFEF Halfwidth and Fullwidth Forms\n\t// [https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms]\n\t// of which FF01 - FF5E fullwidth ASCII of 21 to 7E\n\t// [IGNORE] and FF65 - FFDC halfwidth of Katakana and Hangul\n\t// [IGNORE] FFF0 - FFFF Specials\n\treturn (\n\t\t(charCode >= 0x2E80 && charCode <= 0xD7AF)\n\t\t|| (charCode >= 0xF900 && charCode <= 0xFAFF)\n\t\t|| (charCode >= 0xFF01 && charCode <= 0xFF5E)\n\t);\n}\n\n/**\n * A fast function (therefore imprecise) to check if code points are emojis.\n * Generated using https://github.com/alexdima/unicode-utils/blob/main/emoji-test.js\n */\nexport function isEmojiImprecise(x: number): boolean {\n\treturn (\n\t\t(x >= 0x1F1E6 && x <= 0x1F1FF) || (x === 8986) || (x === 8987) || (x === 9200)\n\t\t|| (x === 9203) || (x >= 9728 && x <= 10175) || (x === 11088) || (x === 11093)\n\t\t|| (x >= 127744 && x <= 128591) || (x >= 128640 && x <= 128764)\n\t\t|| (x >= 128992 && x <= 129008) || (x >= 129280 && x <= 129535)\n\t\t|| (x >= 129648 && x <= 129782)\n\t);\n}\n\n// -- UTF-8 BOM\n\nexport const UTF8_BOM_CHARACTER = String.fromCharCode(CharCode.UTF8_BOM);\n\nexport function startsWithUTF8BOM(str: string): boolean {\n\treturn !!(str && str.length > 0 && str.charCodeAt(0) === CharCode.UTF8_BOM);\n}\n\nexport function containsUppercaseCharacter(target: string, ignoreEscapedChars = false): boolean {\n\tif (!target) {\n\t\treturn false;\n\t}\n\n\tif (ignoreEscapedChars) {\n\t\ttarget = target.replace(/\\\\./g, '');\n\t}\n\n\treturn target.toLowerCase() !== target;\n}\n\n/**\n * Produces 'a'-'z', followed by 'A'-'Z'... followed by 'a'-'z', etc.\n */\nexport function singleLetterHash(n: number): string {\n\tconst LETTERS_CNT = (CharCode.Z - CharCode.A + 1);\n\n\tn = n % (2 * LETTERS_CNT);\n\n\tif (n < LETTERS_CNT) {\n\t\treturn String.fromCharCode(CharCode.a + n);\n\t}\n\n\treturn String.fromCharCode(CharCode.A + n - LETTERS_CNT);\n}\n\nfunction breakBetweenGraphemeBreakType(breakTypeA: GraphemeBreakType, breakTypeB: GraphemeBreakType): boolean {\n\t// http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules\n\n\t// !!! Let's make the common case a bit faster\n\tif (breakTypeA === GraphemeBreakType.Other) {\n\t\t// see https://www.unicode.org/Public/13.0.0/ucd/auxiliary/GraphemeBreakTest-13.0.0d10.html#table\n\t\treturn (breakTypeB !== GraphemeBreakType.Extend && breakTypeB !== GraphemeBreakType.SpacingMark);\n\t}\n\n\t// Do not break between a CR and LF. Otherwise, break before and after controls.\n\t// GB3 CR × LF\n\t// GB4 (Control | CR | LF) ÷\n\t// GB5 ÷ (Control | CR | LF)\n\tif (breakTypeA === GraphemeBreakType.CR) {\n\t\tif (breakTypeB === GraphemeBreakType.LF) {\n\t\t\treturn false; // GB3\n\t\t}\n\t}\n\tif (breakTypeA === GraphemeBreakType.Control || breakTypeA === GraphemeBreakType.CR || breakTypeA === GraphemeBreakType.LF) {\n\t\treturn true; // GB4\n\t}\n\tif (breakTypeB === GraphemeBreakType.Control || breakTypeB === GraphemeBreakType.CR || breakTypeB === GraphemeBreakType.LF) {\n\t\treturn true; // GB5\n\t}\n\n\t// Do not break Hangul syllable sequences.\n\t// GB6 L × (L | V | LV | LVT)\n\t// GB7 (LV | V) × (V | T)\n\t// GB8 (LVT | T) × T\n\tif (breakTypeA === GraphemeBreakType.L) {\n\t\tif (breakTypeB === GraphemeBreakType.L || breakTypeB === GraphemeBreakType.V || breakTypeB === GraphemeBreakType.LV || breakTypeB === GraphemeBreakType.LVT) {\n\t\t\treturn false; // GB6\n\t\t}\n\t}\n\tif (breakTypeA === GraphemeBreakType.LV || breakTypeA === GraphemeBreakType.V) {\n\t\tif (breakTypeB === GraphemeBreakType.V || breakTypeB === GraphemeBreakType.T) {\n\t\t\treturn false; // GB7\n\t\t}\n\t}\n\tif (breakTypeA === GraphemeBreakType.LVT || breakTypeA === GraphemeBreakType.T) {\n\t\tif (breakTypeB === GraphemeBreakType.T) {\n\t\t\treturn false; // GB8\n\t\t}\n\t}\n\n\t// Do not break before extending characters or ZWJ.\n\t// GB9 × (Extend | ZWJ)\n\tif (breakTypeB === GraphemeBreakType.Extend || breakTypeB === GraphemeBreakType.ZWJ) {\n\t\treturn false; // GB9\n\t}\n\n\t// The GB9a and GB9b rules only apply to extended grapheme clusters:\n\t// Do not break before SpacingMarks, or after Prepend characters.\n\t// GB9a × SpacingMark\n\t// GB9b Prepend ×\n\tif (breakTypeB === GraphemeBreakType.SpacingMark) {\n\t\treturn false; // GB9a\n\t}\n\tif (breakTypeA === GraphemeBreakType.Prepend) {\n\t\treturn false; // GB9b\n\t}\n\n\t// Do not break within emoji modifier sequences or emoji zwj sequences.\n\t// GB11 \\p{Extended_Pictographic} Extend* ZWJ × \\p{Extended_Pictographic}\n\tif (breakTypeA === GraphemeBreakType.ZWJ && breakTypeB === GraphemeBreakType.Extended_Pictographic) {\n\t\t// Note: we are not implementing the rule entirely here to avoid introducing states\n\t\treturn false; // GB11\n\t}\n\n\t// GB12 sot (RI RI)* RI × RI\n\t// GB13 [^RI] (RI RI)* RI × RI\n\tif (breakTypeA === GraphemeBreakType.Regional_Indicator && breakTypeB === GraphemeBreakType.Regional_Indicator) {\n\t\t// Note: we are not implementing the rule entirely here to avoid introducing states\n\t\treturn false; // GB12 & GB13\n\t}\n\n\t// GB999 Any ÷ Any\n\treturn true;\n}\n\nexport const enum GraphemeBreakType {\n\tOther = 0,\n\tPrepend = 1,\n\tCR = 2,\n\tLF = 3,\n\tControl = 4,\n\tExtend = 5,\n\tRegional_Indicator = 6,\n\tSpacingMark = 7,\n\tL = 8,\n\tV = 9,\n\tT = 10,\n\tLV = 11,\n\tLVT = 12,\n\tZWJ = 13,\n\tExtended_Pictographic = 14\n}\n\nclass GraphemeBreakTree {\n\n\tprivate static _INSTANCE: GraphemeBreakTree | null = null;\n\tpublic static getInstance(): GraphemeBreakTree {\n\t\tif (!GraphemeBreakTree._INSTANCE) {\n\t\t\tGraphemeBreakTree._INSTANCE = new GraphemeBreakTree();\n\t\t}\n\t\treturn GraphemeBreakTree._INSTANCE;\n\t}\n\n\tprivate readonly _data: number[];\n\n\tconstructor() {\n\t\tthis._data = getGraphemeBreakRawData();\n\t}\n\n\tpublic getGraphemeBreakType(codePoint: number): GraphemeBreakType {\n\t\t// !!! Let's make 7bit ASCII a bit faster: 0..31\n\t\tif (codePoint < 32) {\n\t\t\tif (codePoint === CharCode.LineFeed) {\n\t\t\t\treturn GraphemeBreakType.LF;\n\t\t\t}\n\t\t\tif (codePoint === CharCode.CarriageReturn) {\n\t\t\t\treturn GraphemeBreakType.CR;\n\t\t\t}\n\t\t\treturn GraphemeBreakType.Control;\n\t\t}\n\t\t// !!! Let's make 7bit ASCII a bit faster: 32..126\n\t\tif (codePoint < 127) {\n\t\t\treturn GraphemeBreakType.Other;\n\t\t}\n\n\t\tconst data = this._data;\n\t\tconst nodeCount = data.length / 3;\n\t\tlet nodeIndex = 1;\n\t\twhile (nodeIndex <= nodeCount) {\n\t\t\tif (codePoint < data[3 * nodeIndex]) {\n\t\t\t\t// go left\n\t\t\t\tnodeIndex = 2 * nodeIndex;\n\t\t\t} else if (codePoint > data[3 * nodeIndex + 1]) {\n\t\t\t\t// go right\n\t\t\t\tnodeIndex = 2 * nodeIndex + 1;\n\t\t\t} else {\n\t\t\t\t// hit\n\t\t\t\treturn data[3 * nodeIndex + 2];\n\t\t\t}\n\t\t}\n\n\t\treturn GraphemeBreakType.Other;\n\t}\n}\n\nfunction getGraphemeBreakRawData(): number[] {\n\t// generated using https://github.com/alexdima/unicode-utils/blob/main/grapheme-break.js\n\treturn JSON.parse('[0,0,0,51229,51255,12,44061,44087,12,127462,127487,6,7083,7085,5,47645,47671,12,54813,54839,12,128678,128678,14,3270,3270,5,9919,9923,14,45853,45879,12,49437,49463,12,53021,53047,12,71216,71218,7,128398,128399,14,129360,129374,14,2519,2519,5,4448,4519,9,9742,9742,14,12336,12336,14,44957,44983,12,46749,46775,12,48541,48567,12,50333,50359,12,52125,52151,12,53917,53943,12,69888,69890,5,73018,73018,5,127990,127990,14,128558,128559,14,128759,128760,14,129653,129655,14,2027,2035,5,2891,2892,7,3761,3761,5,6683,6683,5,8293,8293,4,9825,9826,14,9999,9999,14,43452,43453,5,44509,44535,12,45405,45431,12,46301,46327,12,47197,47223,12,48093,48119,12,48989,49015,12,49885,49911,12,50781,50807,12,51677,51703,12,52573,52599,12,53469,53495,12,54365,54391,12,65279,65279,4,70471,70472,7,72145,72147,7,119173,119179,5,127799,127818,14,128240,128244,14,128512,128512,14,128652,128652,14,128721,128722,14,129292,129292,14,129445,129450,14,129734,129743,14,1476,1477,5,2366,2368,7,2750,2752,7,3076,3076,5,3415,3415,5,4141,4144,5,6109,6109,5,6964,6964,5,7394,7400,5,9197,9198,14,9770,9770,14,9877,9877,14,9968,9969,14,10084,10084,14,43052,43052,5,43713,43713,5,44285,44311,12,44733,44759,12,45181,45207,12,45629,45655,12,46077,46103,12,46525,46551,12,46973,46999,12,47421,47447,12,47869,47895,12,48317,48343,12,48765,48791,12,49213,49239,12,49661,49687,12,50109,50135,12,50557,50583,12,51005,51031,12,51453,51479,12,51901,51927,12,52349,52375,12,52797,52823,12,53245,53271,12,53693,53719,12,54141,54167,12,54589,54615,12,55037,55063,12,69506,69509,5,70191,70193,5,70841,70841,7,71463,71467,5,72330,72342,5,94031,94031,5,123628,123631,5,127763,127765,14,127941,127941,14,128043,128062,14,128302,128317,14,128465,128467,14,128539,128539,14,128640,128640,14,128662,128662,14,128703,128703,14,128745,128745,14,129004,129007,14,129329,129330,14,129402,129402,14,129483,129483,14,129686,129704,14,130048,131069,14,173,173,4,1757,1757,1,2200,2207,5,2434,2435,7,2631,2632,5,2817,2817,5,3008,3008,5,3201,3201,5,3387,3388,5,3542,3542,5,3902,3903,7,4190,4192,5,6002,6003,5,6439,6440,5,6765,6770,7,7019,7027,5,7154,7155,7,8205,8205,13,8505,8505,14,9654,9654,14,9757,9757,14,9792,9792,14,9852,9853,14,9890,9894,14,9937,9937,14,9981,9981,14,10035,10036,14,11035,11036,14,42654,42655,5,43346,43347,7,43587,43587,5,44006,44007,7,44173,44199,12,44397,44423,12,44621,44647,12,44845,44871,12,45069,45095,12,45293,45319,12,45517,45543,12,45741,45767,12,45965,45991,12,46189,46215,12,46413,46439,12,46637,46663,12,46861,46887,12,47085,47111,12,47309,47335,12,47533,47559,12,47757,47783,12,47981,48007,12,48205,48231,12,48429,48455,12,48653,48679,12,48877,48903,12,49101,49127,12,49325,49351,12,49549,49575,12,49773,49799,12,49997,50023,12,50221,50247,12,50445,50471,12,50669,50695,12,50893,50919,12,51117,51143,12,51341,51367,12,51565,51591,12,51789,51815,12,52013,52039,12,52237,52263,12,52461,52487,12,52685,52711,12,52909,52935,12,53133,53159,12,53357,53383,12,53581,53607,12,53805,53831,12,54029,54055,12,54253,54279,12,54477,54503,12,54701,54727,12,54925,54951,12,55149,55175,12,68101,68102,5,69762,69762,7,70067,70069,7,70371,70378,5,70720,70721,7,71087,71087,5,71341,71341,5,71995,71996,5,72249,72249,7,72850,72871,5,73109,73109,5,118576,118598,5,121505,121519,5,127245,127247,14,127568,127569,14,127777,127777,14,127872,127891,14,127956,127967,14,128015,128016,14,128110,128172,14,128259,128259,14,128367,128368,14,128424,128424,14,128488,128488,14,128530,128532,14,128550,128551,14,128566,128566,14,128647,128647,14,128656,128656,14,128667,128673,14,128691,128693,14,128715,128715,14,128728,128732,14,128752,128752,14,128765,128767,14,129096,129103,14,129311,129311,14,129344,129349,14,129394,129394,14,129413,129425,14,129466,129471,14,129511,129535,14,129664,129666,14,129719,129722,14,129760,129767,14,917536,917631,5,13,13,2,1160,1161,5,1564,1564,4,1807,1807,1,2085,2087,5,2307,2307,7,2382,2383,7,2497,2500,5,2563,2563,7,2677,2677,5,2763,2764,7,2879,2879,5,2914,2915,5,3021,3021,5,3142,3144,5,3263,3263,5,3285,3286,5,3398,3400,7,3530,3530,5,3633,3633,5,3864,3865,5,3974,3975,5,4155,4156,7,4229,4230,5,5909,5909,7,6078,6085,7,6277,6278,5,6451,6456,7,6744,6750,5,6846,6846,5,6972,6972,5,7074,7077,5,7146,7148,7,7222,7223,5,7416,7417,5,8234,8238,4,8417,8417,5,9000,9000,14,9203,9203,14,9730,9731,14,9748,9749,14,9762,9763,14,9776,9783,14,9800,9811,14,9831,9831,14,9872,9873,14,9882,9882,14,9900,9903,14,9929,9933,14,9941,9960,14,9974,9974,14,9989,9989,14,10006,10006,14,10062,10062,14,10160,10160,14,11647,11647,5,12953,12953,14,43019,43019,5,43232,43249,5,43443,43443,5,43567,43568,7,43696,43696,5,43765,43765,7,44013,44013,5,44117,44143,12,44229,44255,12,44341,44367,12,44453,44479,12,44565,44591,12,44677,44703,12,44789,44815,12,44901,44927,12,45013,45039,12,45125,45151,12,45237,45263,12,45349,45375,12,45461,45487,12,45573,45599,12,45685,45711,12,45797,45823,12,45909,45935,12,46021,46047,12,46133,46159,12,46245,46271,12,46357,46383,12,46469,46495,12,46581,46607,12,46693,46719,12,46805,46831,12,46917,46943,12,47029,47055,12,47141,47167,12,47253,47279,12,47365,47391,12,47477,47503,12,47589,47615,12,47701,47727,12,47813,47839,12,47925,47951,12,48037,48063,12,48149,48175,12,48261,48287,12,48373,48399,12,48485,48511,12,48597,48623,12,48709,48735,12,48821,48847,12,48933,48959,12,49045,49071,12,49157,49183,12,49269,49295,12,49381,49407,12,49493,49519,12,49605,49631,12,49717,49743,12,49829,49855,12,49941,49967,12,50053,50079,12,50165,50191,12,50277,50303,12,50389,50415,12,50501,50527,12,50613,50639,12,50725,50751,12,50837,50863,12,50949,50975,12,51061,51087,12,51173,51199,12,51285,51311,12,51397,51423,12,51509,51535,12,51621,51647,12,51733,51759,12,51845,51871,12,51957,51983,12,52069,52095,12,52181,52207,12,52293,52319,12,52405,52431,12,52517,52543,12,52629,52655,12,52741,52767,12,52853,52879,12,52965,52991,12,53077,53103,12,53189,53215,12,53301,53327,12,53413,53439,12,53525,53551,12,53637,53663,12,53749,53775,12,53861,53887,12,53973,53999,12,54085,54111,12,54197,54223,12,54309,54335,12,54421,54447,12,54533,54559,12,54645,54671,12,54757,54783,12,54869,54895,12,54981,55007,12,55093,55119,12,55243,55291,10,66045,66045,5,68325,68326,5,69688,69702,5,69817,69818,5,69957,69958,7,70089,70092,5,70198,70199,5,70462,70462,5,70502,70508,5,70750,70750,5,70846,70846,7,71100,71101,5,71230,71230,7,71351,71351,5,71737,71738,5,72000,72000,7,72160,72160,5,72273,72278,5,72752,72758,5,72882,72883,5,73031,73031,5,73461,73462,7,94192,94193,7,119149,119149,7,121403,121452,5,122915,122916,5,126980,126980,14,127358,127359,14,127535,127535,14,127759,127759,14,127771,127771,14,127792,127793,14,127825,127867,14,127897,127899,14,127945,127945,14,127985,127986,14,128000,128007,14,128021,128021,14,128066,128100,14,128184,128235,14,128249,128252,14,128266,128276,14,128335,128335,14,128379,128390,14,128407,128419,14,128444,128444,14,128481,128481,14,128499,128499,14,128526,128526,14,128536,128536,14,128543,128543,14,128556,128556,14,128564,128564,14,128577,128580,14,128643,128645,14,128649,128649,14,128654,128654,14,128660,128660,14,128664,128664,14,128675,128675,14,128686,128689,14,128695,128696,14,128705,128709,14,128717,128719,14,128725,128725,14,128736,128741,14,128747,128748,14,128755,128755,14,128762,128762,14,128981,128991,14,129009,129023,14,129160,129167,14,129296,129304,14,129320,129327,14,129340,129342,14,129356,129356,14,129388,129392,14,129399,129400,14,129404,129407,14,129432,129442,14,129454,129455,14,129473,129474,14,129485,129487,14,129648,129651,14,129659,129660,14,129671,129679,14,129709,129711,14,129728,129730,14,129751,129753,14,129776,129782,14,917505,917505,4,917760,917999,5,10,10,3,127,159,4,768,879,5,1471,1471,5,1536,1541,1,1648,1648,5,1767,1768,5,1840,1866,5,2070,2073,5,2137,2139,5,2274,2274,1,2363,2363,7,2377,2380,7,2402,2403,5,2494,2494,5,2507,2508,7,2558,2558,5,2622,2624,7,2641,2641,5,2691,2691,7,2759,2760,5,2786,2787,5,2876,2876,5,2881,2884,5,2901,2902,5,3006,3006,5,3014,3016,7,3072,3072,5,3134,3136,5,3157,3158,5,3260,3260,5,3266,3266,5,3274,3275,7,3328,3329,5,3391,3392,7,3405,3405,5,3457,3457,5,3536,3537,7,3551,3551,5,3636,3642,5,3764,3772,5,3895,3895,5,3967,3967,7,3993,4028,5,4146,4151,5,4182,4183,7,4226,4226,5,4253,4253,5,4957,4959,5,5940,5940,7,6070,6070,7,6087,6088,7,6158,6158,4,6432,6434,5,6448,6449,7,6679,6680,5,6742,6742,5,6754,6754,5,6783,6783,5,6912,6915,5,6966,6970,5,6978,6978,5,7042,7042,7,7080,7081,5,7143,7143,7,7150,7150,7,7212,7219,5,7380,7392,5,7412,7412,5,8203,8203,4,8232,8232,4,8265,8265,14,8400,8412,5,8421,8432,5,8617,8618,14,9167,9167,14,9200,9200,14,9410,9410,14,9723,9726,14,9733,9733,14,9745,9745,14,9752,9752,14,9760,9760,14,9766,9766,14,9774,9774,14,9786,9786,14,9794,9794,14,9823,9823,14,9828,9828,14,9833,9850,14,9855,9855,14,9875,9875,14,9880,9880,14,9885,9887,14,9896,9897,14,9906,9916,14,9926,9927,14,9935,9935,14,9939,9939,14,9962,9962,14,9972,9972,14,9978,9978,14,9986,9986,14,9997,9997,14,10002,10002,14,10017,10017,14,10055,10055,14,10071,10071,14,10133,10135,14,10548,10549,14,11093,11093,14,12330,12333,5,12441,12442,5,42608,42610,5,43010,43010,5,43045,43046,5,43188,43203,7,43302,43309,5,43392,43394,5,43446,43449,5,43493,43493,5,43571,43572,7,43597,43597,7,43703,43704,5,43756,43757,5,44003,44004,7,44009,44010,7,44033,44059,12,44089,44115,12,44145,44171,12,44201,44227,12,44257,44283,12,44313,44339,12,44369,44395,12,44425,44451,12,44481,44507,12,44537,44563,12,44593,44619,12,44649,44675,12,44705,44731,12,44761,44787,12,44817,44843,12,44873,44899,12,44929,44955,12,44985,45011,12,45041,45067,12,45097,45123,12,45153,45179,12,45209,45235,12,45265,45291,12,45321,45347,12,45377,45403,12,45433,45459,12,45489,45515,12,45545,45571,12,45601,45627,12,45657,45683,12,45713,45739,12,45769,45795,12,45825,45851,12,45881,45907,12,45937,45963,12,45993,46019,12,46049,46075,12,46105,46131,12,46161,46187,12,46217,46243,12,46273,46299,12,46329,46355,12,46385,46411,12,46441,46467,12,46497,46523,12,46553,46579,12,46609,46635,12,46665,46691,12,46721,46747,12,46777,46803,12,46833,46859,12,46889,46915,12,46945,46971,12,47001,47027,12,47057,47083,12,47113,47139,12,47169,47195,12,47225,47251,12,47281,47307,12,47337,47363,12,47393,47419,12,47449,47475,12,47505,47531,12,47561,47587,12,47617,47643,12,47673,47699,12,47729,47755,12,47785,47811,12,47841,47867,12,47897,47923,12,47953,47979,12,48009,48035,12,48065,48091,12,48121,48147,12,48177,48203,12,48233,48259,12,48289,48315,12,48345,48371,12,48401,48427,12,48457,48483,12,48513,48539,12,48569,48595,12,48625,48651,12,48681,48707,12,48737,48763,12,48793,48819,12,48849,48875,12,48905,48931,12,48961,48987,12,49017,49043,12,49073,49099,12,49129,49155,12,49185,49211,12,49241,49267,12,49297,49323,12,49353,49379,12,49409,49435,12,49465,49491,12,49521,49547,12,49577,49603,12,49633,49659,12,49689,49715,12,49745,49771,12,49801,49827,12,49857,49883,12,49913,49939,12,49969,49995,12,50025,50051,12,50081,50107,12,50137,50163,12,50193,50219,12,50249,50275,12,50305,50331,12,50361,50387,12,50417,50443,12,50473,50499,12,50529,50555,12,50585,50611,12,50641,50667,12,50697,50723,12,50753,50779,12,50809,50835,12,50865,50891,12,50921,50947,12,50977,51003,12,51033,51059,12,51089,51115,12,51145,51171,12,51201,51227,12,51257,51283,12,51313,51339,12,51369,51395,12,51425,51451,12,51481,51507,12,51537,51563,12,51593,51619,12,51649,51675,12,51705,51731,12,51761,51787,12,51817,51843,12,51873,51899,12,51929,51955,12,51985,52011,12,52041,52067,12,52097,52123,12,52153,52179,12,52209,52235,12,52265,52291,12,52321,52347,12,52377,52403,12,52433,52459,12,52489,52515,12,52545,52571,12,52601,52627,12,52657,52683,12,52713,52739,12,52769,52795,12,52825,52851,12,52881,52907,12,52937,52963,12,52993,53019,12,53049,53075,12,53105,53131,12,53161,53187,12,53217,53243,12,53273,53299,12,53329,53355,12,53385,53411,12,53441,53467,12,53497,53523,12,53553,53579,12,53609,53635,12,53665,53691,12,53721,53747,12,53777,53803,12,53833,53859,12,53889,53915,12,53945,53971,12,54001,54027,12,54057,54083,12,54113,54139,12,54169,54195,12,54225,54251,12,54281,54307,12,54337,54363,12,54393,54419,12,54449,54475,12,54505,54531,12,54561,54587,12,54617,54643,12,54673,54699,12,54729,54755,12,54785,54811,12,54841,54867,12,54897,54923,12,54953,54979,12,55009,55035,12,55065,55091,12,55121,55147,12,55177,55203,12,65024,65039,5,65520,65528,4,66422,66426,5,68152,68154,5,69291,69292,5,69633,69633,5,69747,69748,5,69811,69814,5,69826,69826,5,69932,69932,7,70016,70017,5,70079,70080,7,70095,70095,5,70196,70196,5,70367,70367,5,70402,70403,7,70464,70464,5,70487,70487,5,70709,70711,7,70725,70725,7,70833,70834,7,70843,70844,7,70849,70849,7,71090,71093,5,71103,71104,5,71227,71228,7,71339,71339,5,71344,71349,5,71458,71461,5,71727,71735,5,71985,71989,7,71998,71998,5,72002,72002,7,72154,72155,5,72193,72202,5,72251,72254,5,72281,72283,5,72344,72345,5,72766,72766,7,72874,72880,5,72885,72886,5,73023,73029,5,73104,73105,5,73111,73111,5,92912,92916,5,94095,94098,5,113824,113827,4,119142,119142,7,119155,119162,4,119362,119364,5,121476,121476,5,122888,122904,5,123184,123190,5,125252,125258,5,127183,127183,14,127340,127343,14,127377,127386,14,127491,127503,14,127548,127551,14,127744,127756,14,127761,127761,14,127769,127769,14,127773,127774,14,127780,127788,14,127796,127797,14,127820,127823,14,127869,127869,14,127894,127895,14,127902,127903,14,127943,127943,14,127947,127950,14,127972,127972,14,127988,127988,14,127992,127994,14,128009,128011,14,128019,128019,14,128023,128041,14,128064,128064,14,128102,128107,14,128174,128181,14,128238,128238,14,128246,128247,14,128254,128254,14,128264,128264,14,128278,128299,14,128329,128330,14,128348,128359,14,128371,128377,14,128392,128393,14,128401,128404,14,128421,128421,14,128433,128434,14,128450,128452,14,128476,128478,14,128483,128483,14,128495,128495,14,128506,128506,14,128519,128520,14,128528,128528,14,128534,128534,14,128538,128538,14,128540,128542,14,128544,128549,14,128552,128555,14,128557,128557,14,128560,128563,14,128565,128565,14,128567,128576,14,128581,128591,14,128641,128642,14,128646,128646,14,128648,128648,14,128650,128651,14,128653,128653,14,128655,128655,14,128657,128659,14,128661,128661,14,128663,128663,14,128665,128666,14,128674,128674,14,128676,128677,14,128679,128685,14,128690,128690,14,128694,128694,14,128697,128702,14,128704,128704,14,128710,128714,14,128716,128716,14,128720,128720,14,128723,128724,14,128726,128727,14,128733,128735,14,128742,128744,14,128746,128746,14,128749,128751,14,128753,128754,14,128756,128758,14,128761,128761,14,128763,128764,14,128884,128895,14,128992,129003,14,129008,129008,14,129036,129039,14,129114,129119,14,129198,129279,14,129293,129295,14,129305,129310,14,129312,129319,14,129328,129328,14,129331,129338,14,129343,129343,14,129351,129355,14,129357,129359,14,129375,129387,14,129393,129393,14,129395,129398,14,129401,129401,14,129403,129403,14,129408,129412,14,129426,129431,14,129443,129444,14,129451,129453,14,129456,129465,14,129472,129472,14,129475,129482,14,129484,129484,14,129488,129510,14,129536,129647,14,129652,129652,14,129656,129658,14,129661,129663,14,129667,129670,14,129680,129685,14,129705,129708,14,129712,129718,14,129723,129727,14,129731,129733,14,129744,129750,14,129754,129759,14,129768,129775,14,129783,129791,14,917504,917504,4,917506,917535,4,917632,917759,4,918000,921599,4,0,9,4,11,12,4,14,31,4,169,169,14,174,174,14,1155,1159,5,1425,1469,5,1473,1474,5,1479,1479,5,1552,1562,5,1611,1631,5,1750,1756,5,1759,1764,5,1770,1773,5,1809,1809,5,1958,1968,5,2045,2045,5,2075,2083,5,2089,2093,5,2192,2193,1,2250,2273,5,2275,2306,5,2362,2362,5,2364,2364,5,2369,2376,5,2381,2381,5,2385,2391,5,2433,2433,5,2492,2492,5,2495,2496,7,2503,2504,7,2509,2509,5,2530,2531,5,2561,2562,5,2620,2620,5,2625,2626,5,2635,2637,5,2672,2673,5,2689,2690,5,2748,2748,5,2753,2757,5,2761,2761,7,2765,2765,5,2810,2815,5,2818,2819,7,2878,2878,5,2880,2880,7,2887,2888,7,2893,2893,5,2903,2903,5,2946,2946,5,3007,3007,7,3009,3010,7,3018,3020,7,3031,3031,5,3073,3075,7,3132,3132,5,3137,3140,7,3146,3149,5,3170,3171,5,3202,3203,7,3262,3262,7,3264,3265,7,3267,3268,7,3271,3272,7,3276,3277,5,3298,3299,5,3330,3331,7,3390,3390,5,3393,3396,5,3402,3404,7,3406,3406,1,3426,3427,5,3458,3459,7,3535,3535,5,3538,3540,5,3544,3550,7,3570,3571,7,3635,3635,7,3655,3662,5,3763,3763,7,3784,3789,5,3893,3893,5,3897,3897,5,3953,3966,5,3968,3972,5,3981,3991,5,4038,4038,5,4145,4145,7,4153,4154,5,4157,4158,5,4184,4185,5,4209,4212,5,4228,4228,7,4237,4237,5,4352,4447,8,4520,4607,10,5906,5908,5,5938,5939,5,5970,5971,5,6068,6069,5,6071,6077,5,6086,6086,5,6089,6099,5,6155,6157,5,6159,6159,5,6313,6313,5,6435,6438,7,6441,6443,7,6450,6450,5,6457,6459,5,6681,6682,7,6741,6741,7,6743,6743,7,6752,6752,5,6757,6764,5,6771,6780,5,6832,6845,5,6847,6862,5,6916,6916,7,6965,6965,5,6971,6971,7,6973,6977,7,6979,6980,7,7040,7041,5,7073,7073,7,7078,7079,7,7082,7082,7,7142,7142,5,7144,7145,5,7149,7149,5,7151,7153,5,7204,7211,7,7220,7221,7,7376,7378,5,7393,7393,7,7405,7405,5,7415,7415,7,7616,7679,5,8204,8204,5,8206,8207,4,8233,8233,4,8252,8252,14,8288,8292,4,8294,8303,4,8413,8416,5,8418,8420,5,8482,8482,14,8596,8601,14,8986,8987,14,9096,9096,14,9193,9196,14,9199,9199,14,9201,9202,14,9208,9210,14,9642,9643,14,9664,9664,14,9728,9729,14,9732,9732,14,9735,9741,14,9743,9744,14,9746,9746,14,9750,9751,14,9753,9756,14,9758,9759,14,9761,9761,14,9764,9765,14,9767,9769,14,9771,9773,14,9775,9775,14,9784,9785,14,9787,9791,14,9793,9793,14,9795,9799,14,9812,9822,14,9824,9824,14,9827,9827,14,9829,9830,14,9832,9832,14,9851,9851,14,9854,9854,14,9856,9861,14,9874,9874,14,9876,9876,14,9878,9879,14,9881,9881,14,9883,9884,14,9888,9889,14,9895,9895,14,9898,9899,14,9904,9905,14,9917,9918,14,9924,9925,14,9928,9928,14,9934,9934,14,9936,9936,14,9938,9938,14,9940,9940,14,9961,9961,14,9963,9967,14,9970,9971,14,9973,9973,14,9975,9977,14,9979,9980,14,9982,9985,14,9987,9988,14,9992,9996,14,9998,9998,14,10000,10001,14,10004,10004,14,10013,10013,14,10024,10024,14,10052,10052,14,10060,10060,14,10067,10069,14,10083,10083,14,10085,10087,14,10145,10145,14,10175,10175,14,11013,11015,14,11088,11088,14,11503,11505,5,11744,11775,5,12334,12335,5,12349,12349,14,12951,12951,14,42607,42607,5,42612,42621,5,42736,42737,5,43014,43014,5,43043,43044,7,43047,43047,7,43136,43137,7,43204,43205,5,43263,43263,5,43335,43345,5,43360,43388,8,43395,43395,7,43444,43445,7,43450,43451,7,43454,43456,7,43561,43566,5,43569,43570,5,43573,43574,5,43596,43596,5,43644,43644,5,43698,43700,5,43710,43711,5,43755,43755,7,43758,43759,7,43766,43766,5,44005,44005,5,44008,44008,5,44012,44012,7,44032,44032,11,44060,44060,11,44088,44088,11,44116,44116,11,44144,44144,11,44172,44172,11,44200,44200,11,44228,44228,11,44256,44256,11,44284,44284,11,44312,44312,11,44340,44340,11,44368,44368,11,44396,44396,11,44424,44424,11,44452,44452,11,44480,44480,11,44508,44508,11,44536,44536,11,44564,44564,11,44592,44592,11,44620,44620,11,44648,44648,11,44676,44676,11,44704,44704,11,44732,44732,11,44760,44760,11,44788,44788,11,44816,44816,11,44844,44844,11,44872,44872,11,44900,44900,11,44928,44928,11,44956,44956,11,44984,44984,11,45012,45012,11,45040,45040,11,45068,45068,11,45096,45096,11,45124,45124,11,45152,45152,11,45180,45180,11,45208,45208,11,45236,45236,11,45264,45264,11,45292,45292,11,45320,45320,11,45348,45348,11,45376,45376,11,45404,45404,11,45432,45432,11,45460,45460,11,45488,45488,11,45516,45516,11,45544,45544,11,45572,45572,11,45600,45600,11,45628,45628,11,45656,45656,11,45684,45684,11,45712,45712,11,45740,45740,11,45768,45768,11,45796,45796,11,45824,45824,11,45852,45852,11,45880,45880,11,45908,45908,11,45936,45936,11,45964,45964,11,45992,45992,11,46020,46020,11,46048,46048,11,46076,46076,11,46104,46104,11,46132,46132,11,46160,46160,11,46188,46188,11,46216,46216,11,46244,46244,11,46272,46272,11,46300,46300,11,46328,46328,11,46356,46356,11,46384,46384,11,46412,46412,11,46440,46440,11,46468,46468,11,46496,46496,11,46524,46524,11,46552,46552,11,46580,46580,11,46608,46608,11,46636,46636,11,46664,46664,11,46692,46692,11,46720,46720,11,46748,46748,11,46776,46776,11,46804,46804,11,46832,46832,11,46860,46860,11,46888,46888,11,46916,46916,11,46944,46944,11,46972,46972,11,47000,47000,11,47028,47028,11,47056,47056,11,47084,47084,11,47112,47112,11,47140,47140,11,47168,47168,11,47196,47196,11,47224,47224,11,47252,47252,11,47280,47280,11,47308,47308,11,47336,47336,11,47364,47364,11,47392,47392,11,47420,47420,11,47448,47448,11,47476,47476,11,47504,47504,11,47532,47532,11,47560,47560,11,47588,47588,11,47616,47616,11,47644,47644,11,47672,47672,11,47700,47700,11,47728,47728,11,47756,47756,11,47784,47784,11,47812,47812,11,47840,47840,11,47868,47868,11,47896,47896,11,47924,47924,11,47952,47952,11,47980,47980,11,48008,48008,11,48036,48036,11,48064,48064,11,48092,48092,11,48120,48120,11,48148,48148,11,48176,48176,11,48204,48204,11,48232,48232,11,48260,48260,11,48288,48288,11,48316,48316,11,48344,48344,11,48372,48372,11,48400,48400,11,48428,48428,11,48456,48456,11,48484,48484,11,48512,48512,11,48540,48540,11,48568,48568,11,48596,48596,11,48624,48624,11,48652,48652,11,48680,48680,11,48708,48708,11,48736,48736,11,48764,48764,11,48792,48792,11,48820,48820,11,48848,48848,11,48876,48876,11,48904,48904,11,48932,48932,11,48960,48960,11,48988,48988,11,49016,49016,11,49044,49044,11,49072,49072,11,49100,49100,11,49128,49128,11,49156,49156,11,49184,49184,11,49212,49212,11,49240,49240,11,49268,49268,11,49296,49296,11,49324,49324,11,49352,49352,11,49380,49380,11,49408,49408,11,49436,49436,11,49464,49464,11,49492,49492,11,49520,49520,11,49548,49548,11,49576,49576,11,49604,49604,11,49632,49632,11,49660,49660,11,49688,49688,11,49716,49716,11,49744,49744,11,49772,49772,11,49800,49800,11,49828,49828,11,49856,49856,11,49884,49884,11,49912,49912,11,49940,49940,11,49968,49968,11,49996,49996,11,50024,50024,11,50052,50052,11,50080,50080,11,50108,50108,11,50136,50136,11,50164,50164,11,50192,50192,11,50220,50220,11,50248,50248,11,50276,50276,11,50304,50304,11,50332,50332,11,50360,50360,11,50388,50388,11,50416,50416,11,50444,50444,11,50472,50472,11,50500,50500,11,50528,50528,11,50556,50556,11,50584,50584,11,50612,50612,11,50640,50640,11,50668,50668,11,50696,50696,11,50724,50724,11,50752,50752,11,50780,50780,11,50808,50808,11,50836,50836,11,50864,50864,11,50892,50892,11,50920,50920,11,50948,50948,11,50976,50976,11,51004,51004,11,51032,51032,11,51060,51060,11,51088,51088,11,51116,51116,11,51144,51144,11,51172,51172,11,51200,51200,11,51228,51228,11,51256,51256,11,51284,51284,11,51312,51312,11,51340,51340,11,51368,51368,11,51396,51396,11,51424,51424,11,51452,51452,11,51480,51480,11,51508,51508,11,51536,51536,11,51564,51564,11,51592,51592,11,51620,51620,11,51648,51648,11,51676,51676,11,51704,51704,11,51732,51732,11,51760,51760,11,51788,51788,11,51816,51816,11,51844,51844,11,51872,51872,11,51900,51900,11,51928,51928,11,51956,51956,11,51984,51984,11,52012,52012,11,52040,52040,11,52068,52068,11,52096,52096,11,52124,52124,11,52152,52152,11,52180,52180,11,52208,52208,11,52236,52236,11,52264,52264,11,52292,52292,11,52320,52320,11,52348,52348,11,52376,52376,11,52404,52404,11,52432,52432,11,52460,52460,11,52488,52488,11,52516,52516,11,52544,52544,11,52572,52572,11,52600,52600,11,52628,52628,11,52656,52656,11,52684,52684,11,52712,52712,11,52740,52740,11,52768,52768,11,52796,52796,11,52824,52824,11,52852,52852,11,52880,52880,11,52908,52908,11,52936,52936,11,52964,52964,11,52992,52992,11,53020,53020,11,53048,53048,11,53076,53076,11,53104,53104,11,53132,53132,11,53160,53160,11,53188,53188,11,53216,53216,11,53244,53244,11,53272,53272,11,53300,53300,11,53328,53328,11,53356,53356,11,53384,53384,11,53412,53412,11,53440,53440,11,53468,53468,11,53496,53496,11,53524,53524,11,53552,53552,11,53580,53580,11,53608,53608,11,53636,53636,11,53664,53664,11,53692,53692,11,53720,53720,11,53748,53748,11,53776,53776,11,53804,53804,11,53832,53832,11,53860,53860,11,53888,53888,11,53916,53916,11,53944,53944,11,53972,53972,11,54000,54000,11,54028,54028,11,54056,54056,11,54084,54084,11,54112,54112,11,54140,54140,11,54168,54168,11,54196,54196,11,54224,54224,11,54252,54252,11,54280,54280,11,54308,54308,11,54336,54336,11,54364,54364,11,54392,54392,11,54420,54420,11,54448,54448,11,54476,54476,11,54504,54504,11,54532,54532,11,54560,54560,11,54588,54588,11,54616,54616,11,54644,54644,11,54672,54672,11,54700,54700,11,54728,54728,11,54756,54756,11,54784,54784,11,54812,54812,11,54840,54840,11,54868,54868,11,54896,54896,11,54924,54924,11,54952,54952,11,54980,54980,11,55008,55008,11,55036,55036,11,55064,55064,11,55092,55092,11,55120,55120,11,55148,55148,11,55176,55176,11,55216,55238,9,64286,64286,5,65056,65071,5,65438,65439,5,65529,65531,4,66272,66272,5,68097,68099,5,68108,68111,5,68159,68159,5,68900,68903,5,69446,69456,5,69632,69632,7,69634,69634,7,69744,69744,5,69759,69761,5,69808,69810,7,69815,69816,7,69821,69821,1,69837,69837,1,69927,69931,5,69933,69940,5,70003,70003,5,70018,70018,7,70070,70078,5,70082,70083,1,70094,70094,7,70188,70190,7,70194,70195,7,70197,70197,7,70206,70206,5,70368,70370,7,70400,70401,5,70459,70460,5,70463,70463,7,70465,70468,7,70475,70477,7,70498,70499,7,70512,70516,5,70712,70719,5,70722,70724,5,70726,70726,5,70832,70832,5,70835,70840,5,70842,70842,5,70845,70845,5,70847,70848,5,70850,70851,5,71088,71089,7,71096,71099,7,71102,71102,7,71132,71133,5,71219,71226,5,71229,71229,5,71231,71232,5,71340,71340,7,71342,71343,7,71350,71350,7,71453,71455,5,71462,71462,7,71724,71726,7,71736,71736,7,71984,71984,5,71991,71992,7,71997,71997,7,71999,71999,1,72001,72001,1,72003,72003,5,72148,72151,5,72156,72159,7,72164,72164,7,72243,72248,5,72250,72250,1,72263,72263,5,72279,72280,7,72324,72329,1,72343,72343,7,72751,72751,7,72760,72765,5,72767,72767,5,72873,72873,7,72881,72881,7,72884,72884,7,73009,73014,5,73020,73021,5,73030,73030,1,73098,73102,7,73107,73108,7,73110,73110,7,73459,73460,5,78896,78904,4,92976,92982,5,94033,94087,7,94180,94180,5,113821,113822,5,118528,118573,5,119141,119141,5,119143,119145,5,119150,119154,5,119163,119170,5,119210,119213,5,121344,121398,5,121461,121461,5,121499,121503,5,122880,122886,5,122907,122913,5,122918,122922,5,123566,123566,5,125136,125142,5,126976,126979,14,126981,127182,14,127184,127231,14,127279,127279,14,127344,127345,14,127374,127374,14,127405,127461,14,127489,127490,14,127514,127514,14,127538,127546,14,127561,127567,14,127570,127743,14,127757,127758,14,127760,127760,14,127762,127762,14,127766,127768,14,127770,127770,14,127772,127772,14,127775,127776,14,127778,127779,14,127789,127791,14,127794,127795,14,127798,127798,14,127819,127819,14,127824,127824,14,127868,127868,14,127870,127871,14,127892,127893,14,127896,127896,14,127900,127901,14,127904,127940,14,127942,127942,14,127944,127944,14,127946,127946,14,127951,127955,14,127968,127971,14,127973,127984,14,127987,127987,14,127989,127989,14,127991,127991,14,127995,127999,5,128008,128008,14,128012,128014,14,128017,128018,14,128020,128020,14,128022,128022,14,128042,128042,14,128063,128063,14,128065,128065,14,128101,128101,14,128108,128109,14,128173,128173,14,128182,128183,14,128236,128237,14,128239,128239,14,128245,128245,14,128248,128248,14,128253,128253,14,128255,128258,14,128260,128263,14,128265,128265,14,128277,128277,14,128300,128301,14,128326,128328,14,128331,128334,14,128336,128347,14,128360,128366,14,128369,128370,14,128378,128378,14,128391,128391,14,128394,128397,14,128400,128400,14,128405,128406,14,128420,128420,14,128422,128423,14,128425,128432,14,128435,128443,14,128445,128449,14,128453,128464,14,128468,128475,14,128479,128480,14,128482,128482,14,128484,128487,14,128489,128494,14,128496,128498,14,128500,128505,14,128507,128511,14,128513,128518,14,128521,128525,14,128527,128527,14,128529,128529,14,128533,128533,14,128535,128535,14,128537,128537,14]');\n}\n\n//#endregion\n\n/**\n * Computes the offset after performing a left delete on the given string,\n * while considering unicode grapheme/emoji rules.\n*/\nexport function getLeftDeleteOffset(offset: number, str: string): number {\n\tif (offset === 0) {\n\t\treturn 0;\n\t}\n\n\t// Try to delete emoji part.\n\tconst emojiOffset = getOffsetBeforeLastEmojiComponent(offset, str);\n\tif (emojiOffset !== undefined) {\n\t\treturn emojiOffset;\n\t}\n\n\t// Otherwise, just skip a single code point.\n\tconst iterator = new CodePointIterator(str, offset);\n\titerator.prevCodePoint();\n\treturn iterator.offset;\n}\n\nfunction getOffsetBeforeLastEmojiComponent(initialOffset: number, str: string): number | undefined {\n\t// See https://www.unicode.org/reports/tr51/tr51-14.html#EBNF_and_Regex for the\n\t// structure of emojis.\n\tconst iterator = new CodePointIterator(str, initialOffset);\n\tlet codePoint = iterator.prevCodePoint();\n\n\t// Skip modifiers\n\twhile ((isEmojiModifier(codePoint) || codePoint === CodePoint.emojiVariantSelector || codePoint === CodePoint.enclosingKeyCap)) {\n\t\tif (iterator.offset === 0) {\n\t\t\t// Cannot skip modifier, no preceding emoji base.\n\t\t\treturn undefined;\n\t\t}\n\t\tcodePoint = iterator.prevCodePoint();\n\t}\n\n\t// Expect base emoji\n\tif (!isEmojiImprecise(codePoint)) {\n\t\t// Unexpected code point, not a valid emoji.\n\t\treturn undefined;\n\t}\n\n\tlet resultOffset = iterator.offset;\n\n\tif (resultOffset > 0) {\n\t\t// Skip optional ZWJ code points that combine multiple emojis.\n\t\t// In theory, we should check if that ZWJ actually combines multiple emojis\n\t\t// to prevent deleting ZWJs in situations we didn't account for.\n\t\tconst optionalZwjCodePoint = iterator.prevCodePoint();\n\t\tif (optionalZwjCodePoint === CodePoint.zwj) {\n\t\t\tresultOffset = iterator.offset;\n\t\t}\n\t}\n\n\treturn resultOffset;\n}\n\nfunction isEmojiModifier(codePoint: number): boolean {\n\treturn 0x1F3FB <= codePoint && codePoint <= 0x1F3FF;\n}\n\nconst enum CodePoint {\n\tzwj = 0x200D,\n\n\t/**\n\t * Variation Selector-16 (VS16)\n\t*/\n\temojiVariantSelector = 0xFE0F,\n\n\t/**\n\t * Combining Enclosing Keycap\n\t */\n\tenclosingKeyCap = 0x20E3,\n}\n\nexport const noBreakWhitespace = '\\xa0';\n\nexport class AmbiguousCharacters {\n\tprivate static readonly ambiguousCharacterData = new Lazy<\n\t\tRecord<\n\t\t\tstring | '_common' | '_default',\n\t\t\t/* code point -> ascii code point */ number[]\n\t\t>\n\t>(() => {\n\t\t// Generated using https://github.com/hediet/vscode-unicode-data\n\t\t// Stored as key1, value1, key2, value2, ...\n\t\treturn JSON.parse(\n\t\t\t'{\\\"_common\\\":[8232,32,8233,32,5760,32,8192,32,8193,32,8194,32,8195,32,8196,32,8197,32,8198,32,8200,32,8201,32,8202,32,8287,32,8199,32,8239,32,2042,95,65101,95,65102,95,65103,95,8208,45,8209,45,8210,45,65112,45,1748,45,8259,45,727,45,8722,45,10134,45,11450,45,1549,44,1643,44,8218,44,184,44,42233,44,894,59,2307,58,2691,58,1417,58,1795,58,1796,58,5868,58,65072,58,6147,58,6153,58,8282,58,1475,58,760,58,42889,58,8758,58,720,58,42237,58,451,33,11601,33,660,63,577,63,2429,63,5038,63,42731,63,119149,46,8228,46,1793,46,1794,46,42510,46,68176,46,1632,46,1776,46,42232,46,1373,96,65287,96,8219,96,8242,96,1370,96,1523,96,8175,96,65344,96,900,96,8189,96,8125,96,8127,96,8190,96,697,96,884,96,712,96,714,96,715,96,756,96,699,96,701,96,700,96,702,96,42892,96,1497,96,2036,96,2037,96,5194,96,5836,96,94033,96,94034,96,65339,91,10088,40,10098,40,12308,40,64830,40,65341,93,10089,41,10099,41,12309,41,64831,41,10100,123,119060,123,10101,125,65342,94,8270,42,1645,42,8727,42,66335,42,5941,47,8257,47,8725,47,8260,47,9585,47,10187,47,10744,47,119354,47,12755,47,12339,47,11462,47,20031,47,12035,47,65340,92,65128,92,8726,92,10189,92,10741,92,10745,92,119311,92,119355,92,12756,92,20022,92,12034,92,42872,38,708,94,710,94,5869,43,10133,43,66203,43,8249,60,10094,60,706,60,119350,60,5176,60,5810,60,5120,61,11840,61,12448,61,42239,61,8250,62,10095,62,707,62,119351,62,5171,62,94015,62,8275,126,732,126,8128,126,8764,126,65372,124,65293,45,120784,50,120794,50,120804,50,120814,50,120824,50,130034,50,42842,50,423,50,1000,50,42564,50,5311,50,42735,50,119302,51,120785,51,120795,51,120805,51,120815,51,120825,51,130035,51,42923,51,540,51,439,51,42858,51,11468,51,1248,51,94011,51,71882,51,120786,52,120796,52,120806,52,120816,52,120826,52,130036,52,5070,52,71855,52,120787,53,120797,53,120807,53,120817,53,120827,53,130037,53,444,53,71867,53,120788,54,120798,54,120808,54,120818,54,120828,54,130038,54,11474,54,5102,54,71893,54,119314,55,120789,55,120799,55,120809,55,120819,55,120829,55,130039,55,66770,55,71878,55,2819,56,2538,56,2666,56,125131,56,120790,56,120800,56,120810,56,120820,56,120830,56,130040,56,547,56,546,56,66330,56,2663,57,2920,57,2541,57,3437,57,120791,57,120801,57,120811,57,120821,57,120831,57,130041,57,42862,57,11466,57,71884,57,71852,57,71894,57,9082,97,65345,97,119834,97,119886,97,119938,97,119990,97,120042,97,120094,97,120146,97,120198,97,120250,97,120302,97,120354,97,120406,97,120458,97,593,97,945,97,120514,97,120572,97,120630,97,120688,97,120746,97,65313,65,119808,65,119860,65,119912,65,119964,65,120016,65,120068,65,120120,65,120172,65,120224,65,120276,65,120328,65,120380,65,120432,65,913,65,120488,65,120546,65,120604,65,120662,65,120720,65,5034,65,5573,65,42222,65,94016,65,66208,65,119835,98,119887,98,119939,98,119991,98,120043,98,120095,98,120147,98,120199,98,120251,98,120303,98,120355,98,120407,98,120459,98,388,98,5071,98,5234,98,5551,98,65314,66,8492,66,119809,66,119861,66,119913,66,120017,66,120069,66,120121,66,120173,66,120225,66,120277,66,120329,66,120381,66,120433,66,42932,66,914,66,120489,66,120547,66,120605,66,120663,66,120721,66,5108,66,5623,66,42192,66,66178,66,66209,66,66305,66,65347,99,8573,99,119836,99,119888,99,119940,99,119992,99,120044,99,120096,99,120148,99,120200,99,120252,99,120304,99,120356,99,120408,99,120460,99,7428,99,1010,99,11429,99,43951,99,66621,99,128844,67,71922,67,71913,67,65315,67,8557,67,8450,67,8493,67,119810,67,119862,67,119914,67,119966,67,120018,67,120174,67,120226,67,120278,67,120330,67,120382,67,120434,67,1017,67,11428,67,5087,67,42202,67,66210,67,66306,67,66581,67,66844,67,8574,100,8518,100,119837,100,119889,100,119941,100,119993,100,120045,100,120097,100,120149,100,120201,100,120253,100,120305,100,120357,100,120409,100,120461,100,1281,100,5095,100,5231,100,42194,100,8558,68,8517,68,119811,68,119863,68,119915,68,119967,68,120019,68,120071,68,120123,68,120175,68,120227,68,120279,68,120331,68,120383,68,120435,68,5024,68,5598,68,5610,68,42195,68,8494,101,65349,101,8495,101,8519,101,119838,101,119890,101,119942,101,120046,101,120098,101,120150,101,120202,101,120254,101,120306,101,120358,101,120410,101,120462,101,43826,101,1213,101,8959,69,65317,69,8496,69,119812,69,119864,69,119916,69,120020,69,120072,69,120124,69,120176,69,120228,69,120280,69,120332,69,120384,69,120436,69,917,69,120492,69,120550,69,120608,69,120666,69,120724,69,11577,69,5036,69,42224,69,71846,69,71854,69,66182,69,119839,102,119891,102,119943,102,119995,102,120047,102,120099,102,120151,102,120203,102,120255,102,120307,102,120359,102,120411,102,120463,102,43829,102,42905,102,383,102,7837,102,1412,102,119315,70,8497,70,119813,70,119865,70,119917,70,120021,70,120073,70,120125,70,120177,70,120229,70,120281,70,120333,70,120385,70,120437,70,42904,70,988,70,120778,70,5556,70,42205,70,71874,70,71842,70,66183,70,66213,70,66853,70,65351,103,8458,103,119840,103,119892,103,119944,103,120048,103,120100,103,120152,103,120204,103,120256,103,120308,103,120360,103,120412,103,120464,103,609,103,7555,103,397,103,1409,103,119814,71,119866,71,119918,71,119970,71,120022,71,120074,71,120126,71,120178,71,120230,71,120282,71,120334,71,120386,71,120438,71,1292,71,5056,71,5107,71,42198,71,65352,104,8462,104,119841,104,119945,104,119997,104,120049,104,120101,104,120153,104,120205,104,120257,104,120309,104,120361,104,120413,104,120465,104,1211,104,1392,104,5058,104,65320,72,8459,72,8460,72,8461,72,119815,72,119867,72,119919,72,120023,72,120179,72,120231,72,120283,72,120335,72,120387,72,120439,72,919,72,120494,72,120552,72,120610,72,120668,72,120726,72,11406,72,5051,72,5500,72,42215,72,66255,72,731,105,9075,105,65353,105,8560,105,8505,105,8520,105,119842,105,119894,105,119946,105,119998,105,120050,105,120102,105,120154,105,120206,105,120258,105,120310,105,120362,105,120414,105,120466,105,120484,105,618,105,617,105,953,105,8126,105,890,105,120522,105,120580,105,120638,105,120696,105,120754,105,1110,105,42567,105,1231,105,43893,105,5029,105,71875,105,65354,106,8521,106,119843,106,119895,106,119947,106,119999,106,120051,106,120103,106,120155,106,120207,106,120259,106,120311,106,120363,106,120415,106,120467,106,1011,106,1112,106,65322,74,119817,74,119869,74,119921,74,119973,74,120025,74,120077,74,120129,74,120181,74,120233,74,120285,74,120337,74,120389,74,120441,74,42930,74,895,74,1032,74,5035,74,5261,74,42201,74,119844,107,119896,107,119948,107,120000,107,120052,107,120104,107,120156,107,120208,107,120260,107,120312,107,120364,107,120416,107,120468,107,8490,75,65323,75,119818,75,119870,75,119922,75,119974,75,120026,75,120078,75,120130,75,120182,75,120234,75,120286,75,120338,75,120390,75,120442,75,922,75,120497,75,120555,75,120613,75,120671,75,120729,75,11412,75,5094,75,5845,75,42199,75,66840,75,1472,108,8739,73,9213,73,65512,73,1633,108,1777,73,66336,108,125127,108,120783,73,120793,73,120803,73,120813,73,120823,73,130033,73,65321,73,8544,73,8464,73,8465,73,119816,73,119868,73,119920,73,120024,73,120128,73,120180,73,120232,73,120284,73,120336,73,120388,73,120440,73,65356,108,8572,73,8467,108,119845,108,119897,108,119949,108,120001,108,120053,108,120105,73,120157,73,120209,73,120261,73,120313,73,120365,73,120417,73,120469,73,448,73,120496,73,120554,73,120612,73,120670,73,120728,73,11410,73,1030,73,1216,73,1493,108,1503,108,1575,108,126464,108,126592,108,65166,108,65165,108,1994,108,11599,73,5825,73,42226,73,93992,73,66186,124,66313,124,119338,76,8556,76,8466,76,119819,76,119871,76,119923,76,120027,76,120079,76,120131,76,120183,76,120235,76,120287,76,120339,76,120391,76,120443,76,11472,76,5086,76,5290,76,42209,76,93974,76,71843,76,71858,76,66587,76,66854,76,65325,77,8559,77,8499,77,119820,77,119872,77,119924,77,120028,77,120080,77,120132,77,120184,77,120236,77,120288,77,120340,77,120392,77,120444,77,924,77,120499,77,120557,77,120615,77,120673,77,120731,77,1018,77,11416,77,5047,77,5616,77,5846,77,42207,77,66224,77,66321,77,119847,110,119899,110,119951,110,120003,110,120055,110,120107,110,120159,110,120211,110,120263,110,120315,110,120367,110,120419,110,120471,110,1400,110,1404,110,65326,78,8469,78,119821,78,119873,78,119925,78,119977,78,120029,78,120081,78,120185,78,120237,78,120289,78,120341,78,120393,78,120445,78,925,78,120500,78,120558,78,120616,78,120674,78,120732,78,11418,78,42208,78,66835,78,3074,111,3202,111,3330,111,3458,111,2406,111,2662,111,2790,111,3046,111,3174,111,3302,111,3430,111,3664,111,3792,111,4160,111,1637,111,1781,111,65359,111,8500,111,119848,111,119900,111,119952,111,120056,111,120108,111,120160,111,120212,111,120264,111,120316,111,120368,111,120420,111,120472,111,7439,111,7441,111,43837,111,959,111,120528,111,120586,111,120644,111,120702,111,120760,111,963,111,120532,111,120590,111,120648,111,120706,111,120764,111,11423,111,4351,111,1413,111,1505,111,1607,111,126500,111,126564,111,126596,111,65259,111,65260,111,65258,111,65257,111,1726,111,64428,111,64429,111,64427,111,64426,111,1729,111,64424,111,64425,111,64423,111,64422,111,1749,111,3360,111,4125,111,66794,111,71880,111,71895,111,66604,111,1984,79,2534,79,2918,79,12295,79,70864,79,71904,79,120782,79,120792,79,120802,79,120812,79,120822,79,130032,79,65327,79,119822,79,119874,79,119926,79,119978,79,120030,79,120082,79,120134,79,120186,79,120238,79,120290,79,120342,79,120394,79,120446,79,927,79,120502,79,120560,79,120618,79,120676,79,120734,79,11422,79,1365,79,11604,79,4816,79,2848,79,66754,79,42227,79,71861,79,66194,79,66219,79,66564,79,66838,79,9076,112,65360,112,119849,112,119901,112,119953,112,120005,112,120057,112,120109,112,120161,112,120213,112,120265,112,120317,112,120369,112,120421,112,120473,112,961,112,120530,112,120544,112,120588,112,120602,112,120646,112,120660,112,120704,112,120718,112,120762,112,120776,112,11427,112,65328,80,8473,80,119823,80,119875,80,119927,80,119979,80,120031,80,120083,80,120187,80,120239,80,120291,80,120343,80,120395,80,120447,80,929,80,120504,80,120562,80,120620,80,120678,80,120736,80,11426,80,5090,80,5229,80,42193,80,66197,80,119850,113,119902,113,119954,113,120006,113,120058,113,120110,113,120162,113,120214,113,120266,113,120318,113,120370,113,120422,113,120474,113,1307,113,1379,113,1382,113,8474,81,119824,81,119876,81,119928,81,119980,81,120032,81,120084,81,120188,81,120240,81,120292,81,120344,81,120396,81,120448,81,11605,81,119851,114,119903,114,119955,114,120007,114,120059,114,120111,114,120163,114,120215,114,120267,114,120319,114,120371,114,120423,114,120475,114,43847,114,43848,114,7462,114,11397,114,43905,114,119318,82,8475,82,8476,82,8477,82,119825,82,119877,82,119929,82,120033,82,120189,82,120241,82,120293,82,120345,82,120397,82,120449,82,422,82,5025,82,5074,82,66740,82,5511,82,42211,82,94005,82,65363,115,119852,115,119904,115,119956,115,120008,115,120060,115,120112,115,120164,115,120216,115,120268,115,120320,115,120372,115,120424,115,120476,115,42801,115,445,115,1109,115,43946,115,71873,115,66632,115,65331,83,119826,83,119878,83,119930,83,119982,83,120034,83,120086,83,120138,83,120190,83,120242,83,120294,83,120346,83,120398,83,120450,83,1029,83,1359,83,5077,83,5082,83,42210,83,94010,83,66198,83,66592,83,119853,116,119905,116,119957,116,120009,116,120061,116,120113,116,120165,116,120217,116,120269,116,120321,116,120373,116,120425,116,120477,116,8868,84,10201,84,128872,84,65332,84,119827,84,119879,84,119931,84,119983,84,120035,84,120087,84,120139,84,120191,84,120243,84,120295,84,120347,84,120399,84,120451,84,932,84,120507,84,120565,84,120623,84,120681,84,120739,84,11430,84,5026,84,42196,84,93962,84,71868,84,66199,84,66225,84,66325,84,119854,117,119906,117,119958,117,120010,117,120062,117,120114,117,120166,117,120218,117,120270,117,120322,117,120374,117,120426,117,120478,117,42911,117,7452,117,43854,117,43858,117,651,117,965,117,120534,117,120592,117,120650,117,120708,117,120766,117,1405,117,66806,117,71896,117,8746,85,8899,85,119828,85,119880,85,119932,85,119984,85,120036,85,120088,85,120140,85,120192,85,120244,85,120296,85,120348,85,120400,85,120452,85,1357,85,4608,85,66766,85,5196,85,42228,85,94018,85,71864,85,8744,118,8897,118,65366,118,8564,118,119855,118,119907,118,119959,118,120011,118,120063,118,120115,118,120167,118,120219,118,120271,118,120323,118,120375,118,120427,118,120479,118,7456,118,957,118,120526,118,120584,118,120642,118,120700,118,120758,118,1141,118,1496,118,71430,118,43945,118,71872,118,119309,86,1639,86,1783,86,8548,86,119829,86,119881,86,119933,86,119985,86,120037,86,120089,86,120141,86,120193,86,120245,86,120297,86,120349,86,120401,86,120453,86,1140,86,11576,86,5081,86,5167,86,42719,86,42214,86,93960,86,71840,86,66845,86,623,119,119856,119,119908,119,119960,119,120012,119,120064,119,120116,119,120168,119,120220,119,120272,119,120324,119,120376,119,120428,119,120480,119,7457,119,1121,119,1309,119,1377,119,71434,119,71438,119,71439,119,43907,119,71919,87,71910,87,119830,87,119882,87,119934,87,119986,87,120038,87,120090,87,120142,87,120194,87,120246,87,120298,87,120350,87,120402,87,120454,87,1308,87,5043,87,5076,87,42218,87,5742,120,10539,120,10540,120,10799,120,65368,120,8569,120,119857,120,119909,120,119961,120,120013,120,120065,120,120117,120,120169,120,120221,120,120273,120,120325,120,120377,120,120429,120,120481,120,5441,120,5501,120,5741,88,9587,88,66338,88,71916,88,65336,88,8553,88,119831,88,119883,88,119935,88,119987,88,120039,88,120091,88,120143,88,120195,88,120247,88,120299,88,120351,88,120403,88,120455,88,42931,88,935,88,120510,88,120568,88,120626,88,120684,88,120742,88,11436,88,11613,88,5815,88,42219,88,66192,88,66228,88,66327,88,66855,88,611,121,7564,121,65369,121,119858,121,119910,121,119962,121,120014,121,120066,121,120118,121,120170,121,120222,121,120274,121,120326,121,120378,121,120430,121,120482,121,655,121,7935,121,43866,121,947,121,8509,121,120516,121,120574,121,120632,121,120690,121,120748,121,1199,121,4327,121,71900,121,65337,89,119832,89,119884,89,119936,89,119988,89,120040,89,120092,89,120144,89,120196,89,120248,89,120300,89,120352,89,120404,89,120456,89,933,89,978,89,120508,89,120566,89,120624,89,120682,89,120740,89,11432,89,1198,89,5033,89,5053,89,42220,89,94019,89,71844,89,66226,89,119859,122,119911,122,119963,122,120015,122,120067,122,120119,122,120171,122,120223,122,120275,122,120327,122,120379,122,120431,122,120483,122,7458,122,43923,122,71876,122,66293,90,71909,90,65338,90,8484,90,8488,90,119833,90,119885,90,119937,90,119989,90,120041,90,120197,90,120249,90,120301,90,120353,90,120405,90,120457,90,918,90,120493,90,120551,90,120609,90,120667,90,120725,90,5059,90,42204,90,71849,90,65282,34,65284,36,65285,37,65286,38,65290,42,65291,43,65294,46,65295,47,65296,48,65297,49,65298,50,65299,51,65300,52,65301,53,65302,54,65303,55,65304,56,65305,57,65308,60,65309,61,65310,62,65312,64,65316,68,65318,70,65319,71,65324,76,65329,81,65330,82,65333,85,65334,86,65335,87,65343,95,65346,98,65348,100,65350,102,65355,107,65357,109,65358,110,65361,113,65362,114,65364,116,65365,117,65367,119,65370,122,65371,123,65373,125],\\\"_default\\\":[160,32,8211,45,65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"cs\\\":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"de\\\":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"es\\\":[8211,45,65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"fr\\\":[65374,126,65306,58,65281,33,8216,96,8245,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"it\\\":[160,32,8211,45,65374,126,65306,58,65281,33,8216,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"ja\\\":[8211,45,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65292,44,65307,59],\\\"ko\\\":[8211,45,65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"pl\\\":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"pt-BR\\\":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"qps-ploc\\\":[160,32,8211,45,65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"ru\\\":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,305,105,921,73,1009,112,215,120,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"tr\\\":[160,32,8211,45,65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],\\\"zh-hans\\\":[65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41],\\\"zh-hant\\\":[8211,45,65374,126,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65307,59]}'\n\t\t);\n\t});\n\n\tprivate static readonly cache = new LRUCachedComputed<\n\t\tstring[],\n\t\tAmbiguousCharacters\n\t>((locales) => {\n\t\tfunction arrayToMap(arr: number[]): Map {\n\t\t\tconst result = new Map();\n\t\t\tfor (let i = 0; i < arr.length; i += 2) {\n\t\t\t\tresult.set(arr[i], arr[i + 1]);\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tfunction mergeMaps(\n\t\t\tmap1: Map,\n\t\t\tmap2: Map\n\t\t): Map {\n\t\t\tconst result = new Map(map1);\n\t\t\tfor (const [key, value] of map2) {\n\t\t\t\tresult.set(key, value);\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tfunction intersectMaps(\n\t\t\tmap1: Map | undefined,\n\t\t\tmap2: Map\n\t\t) {\n\t\t\tif (!map1) {\n\t\t\t\treturn map2;\n\t\t\t}\n\t\t\tconst result = new Map();\n\t\t\tfor (const [key, value] of map1) {\n\t\t\t\tif (map2.has(key)) {\n\t\t\t\t\tresult.set(key, value);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tconst data = this.ambiguousCharacterData.getValue();\n\n\t\tlet filteredLocales = locales.filter(\n\t\t\t(l) => !l.startsWith('_') && l in data\n\t\t);\n\t\tif (filteredLocales.length === 0) {\n\t\t\tfilteredLocales = ['_default'];\n\t\t}\n\n\t\tlet languageSpecificMap: Map | undefined = undefined;\n\t\tfor (const locale of filteredLocales) {\n\t\t\tconst map = arrayToMap(data[locale]);\n\t\t\tlanguageSpecificMap = intersectMaps(languageSpecificMap, map);\n\t\t}\n\n\t\tconst commonMap = arrayToMap(data['_common']);\n\t\tconst map = mergeMaps(commonMap, languageSpecificMap!);\n\n\t\treturn new AmbiguousCharacters(map);\n\t});\n\n\tpublic static getInstance(locales: Set): AmbiguousCharacters {\n\t\treturn AmbiguousCharacters.cache.get(Array.from(locales));\n\t}\n\n\tprivate static _locales = new Lazy(() =>\n\t\tObject.keys(AmbiguousCharacters.ambiguousCharacterData.getValue()).filter(\n\t\t\t(k) => !k.startsWith('_')\n\t\t)\n\t);\n\tpublic static getLocales(): string[] {\n\t\treturn AmbiguousCharacters._locales.getValue();\n\t}\n\n\tprivate constructor(\n\t\tprivate readonly confusableDictionary: Map\n\t) { }\n\n\tpublic isAmbiguous(codePoint: number): boolean {\n\t\treturn this.confusableDictionary.has(codePoint);\n\t}\n\n\t/**\n\t * Returns the non basic ASCII code point that the given code point can be confused,\n\t * or undefined if such code point does note exist.\n\t */\n\tpublic getPrimaryConfusable(codePoint: number): number | undefined {\n\t\treturn this.confusableDictionary.get(codePoint);\n\t}\n\n\tpublic getConfusableCodePoints(): ReadonlySet {\n\t\treturn new Set(this.confusableDictionary.keys());\n\t}\n}\n\nexport class InvisibleCharacters {\n\tprivate static getRawData(): number[] {\n\t\t// Generated using https://github.com/hediet/vscode-unicode-data\n\t\treturn JSON.parse('[9,10,11,12,13,32,127,160,173,847,1564,4447,4448,6068,6069,6155,6156,6157,6158,7355,7356,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8234,8235,8236,8237,8238,8239,8287,8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,10240,12288,12644,65024,65025,65026,65027,65028,65029,65030,65031,65032,65033,65034,65035,65036,65037,65038,65039,65279,65440,65520,65521,65522,65523,65524,65525,65526,65527,65528,65532,78844,119155,119156,119157,119158,119159,119160,119161,119162,917504,917505,917506,917507,917508,917509,917510,917511,917512,917513,917514,917515,917516,917517,917518,917519,917520,917521,917522,917523,917524,917525,917526,917527,917528,917529,917530,917531,917532,917533,917534,917535,917536,917537,917538,917539,917540,917541,917542,917543,917544,917545,917546,917547,917548,917549,917550,917551,917552,917553,917554,917555,917556,917557,917558,917559,917560,917561,917562,917563,917564,917565,917566,917567,917568,917569,917570,917571,917572,917573,917574,917575,917576,917577,917578,917579,917580,917581,917582,917583,917584,917585,917586,917587,917588,917589,917590,917591,917592,917593,917594,917595,917596,917597,917598,917599,917600,917601,917602,917603,917604,917605,917606,917607,917608,917609,917610,917611,917612,917613,917614,917615,917616,917617,917618,917619,917620,917621,917622,917623,917624,917625,917626,917627,917628,917629,917630,917631,917760,917761,917762,917763,917764,917765,917766,917767,917768,917769,917770,917771,917772,917773,917774,917775,917776,917777,917778,917779,917780,917781,917782,917783,917784,917785,917786,917787,917788,917789,917790,917791,917792,917793,917794,917795,917796,917797,917798,917799,917800,917801,917802,917803,917804,917805,917806,917807,917808,917809,917810,917811,917812,917813,917814,917815,917816,917817,917818,917819,917820,917821,917822,917823,917824,917825,917826,917827,917828,917829,917830,917831,917832,917833,917834,917835,917836,917837,917838,917839,917840,917841,917842,917843,917844,917845,917846,917847,917848,917849,917850,917851,917852,917853,917854,917855,917856,917857,917858,917859,917860,917861,917862,917863,917864,917865,917866,917867,917868,917869,917870,917871,917872,917873,917874,917875,917876,917877,917878,917879,917880,917881,917882,917883,917884,917885,917886,917887,917888,917889,917890,917891,917892,917893,917894,917895,917896,917897,917898,917899,917900,917901,917902,917903,917904,917905,917906,917907,917908,917909,917910,917911,917912,917913,917914,917915,917916,917917,917918,917919,917920,917921,917922,917923,917924,917925,917926,917927,917928,917929,917930,917931,917932,917933,917934,917935,917936,917937,917938,917939,917940,917941,917942,917943,917944,917945,917946,917947,917948,917949,917950,917951,917952,917953,917954,917955,917956,917957,917958,917959,917960,917961,917962,917963,917964,917965,917966,917967,917968,917969,917970,917971,917972,917973,917974,917975,917976,917977,917978,917979,917980,917981,917982,917983,917984,917985,917986,917987,917988,917989,917990,917991,917992,917993,917994,917995,917996,917997,917998,917999]');\n\t}\n\n\tprivate static _data: Set | undefined = undefined;\n\n\tprivate static getData() {\n\t\tif (!this._data) {\n\t\t\tthis._data = new Set(InvisibleCharacters.getRawData());\n\t\t}\n\t\treturn this._data;\n\t}\n\n\tpublic static isInvisibleCharacter(codePoint: number): boolean {\n\t\treturn InvisibleCharacters.getData().has(codePoint);\n\t}\n\n\tpublic static get codePoints(): ReadonlySet {\n\t\treturn InvisibleCharacters.getData();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { normalize, posix, sep } from 'vs/base/common/path';\nimport { isWindows } from 'vs/base/common/platform';\nimport { startsWithIgnoreCase } from 'vs/base/common/strings';\n\nexport function isPathSeparator(code: number) {\n\treturn code === CharCode.Slash || code === CharCode.Backslash;\n}\n\n/**\n * Takes a Windows OS path and changes backward slashes to forward slashes.\n * This should only be done for OS paths from Windows (or user provided paths potentially from Windows).\n * Using it on a Linux or MaxOS path might change it.\n */\nexport function toSlashes(osPath: string) {\n\treturn osPath.replace(/[\\\\/]/g, posix.sep);\n}\n\n/**\n * Takes a Windows OS path (using backward or forward slashes) and turns it into a posix path:\n * - turns backward slashes into forward slashes\n * - makes it absolute if it starts with a drive letter\n * This should only be done for OS paths from Windows (or user provided paths potentially from Windows).\n * Using it on a Linux or MaxOS path might change it.\n */\nexport function toPosixPath(osPath: string) {\n\tif (osPath.indexOf('/') === -1) {\n\t\tosPath = toSlashes(osPath);\n\t}\n\tif (/^[a-zA-Z]:(\\/|$)/.test(osPath)) { // starts with a drive letter\n\t\tosPath = '/' + osPath;\n\t}\n\treturn osPath;\n}\n\n/**\n * Computes the _root_ this path, like `getRoot('c:\\files') === c:\\`,\n * `getRoot('files:///files/path') === files:///`,\n * or `getRoot('\\\\server\\shares\\path') === \\\\server\\shares\\`\n */\nexport function getRoot(path: string, sep: string = posix.sep): string {\n\tif (!path) {\n\t\treturn '';\n\t}\n\n\tconst len = path.length;\n\tconst firstLetter = path.charCodeAt(0);\n\tif (isPathSeparator(firstLetter)) {\n\t\tif (isPathSeparator(path.charCodeAt(1))) {\n\t\t\t// UNC candidate \\\\localhost\\shares\\ddd\n\t\t\t// ^^^^^^^^^^^^^^^^^^^\n\t\t\tif (!isPathSeparator(path.charCodeAt(2))) {\n\t\t\t\tlet pos = 3;\n\t\t\t\tconst start = pos;\n\t\t\t\tfor (; pos < len; pos++) {\n\t\t\t\t\tif (isPathSeparator(path.charCodeAt(pos))) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (start !== pos && !isPathSeparator(path.charCodeAt(pos + 1))) {\n\t\t\t\t\tpos += 1;\n\t\t\t\t\tfor (; pos < len; pos++) {\n\t\t\t\t\t\tif (isPathSeparator(path.charCodeAt(pos))) {\n\t\t\t\t\t\t\treturn path.slice(0, pos + 1) // consume this separator\n\t\t\t\t\t\t\t\t.replace(/[\\\\/]/g, sep);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// /user/far\n\t\t// ^\n\t\treturn sep;\n\n\t} else if (isWindowsDriveLetter(firstLetter)) {\n\t\t// check for windows drive letter c:\\ or c:\n\n\t\tif (path.charCodeAt(1) === CharCode.Colon) {\n\t\t\tif (isPathSeparator(path.charCodeAt(2))) {\n\t\t\t\t// C:\\fff\n\t\t\t\t// ^^^\n\t\t\t\treturn path.slice(0, 2) + sep;\n\t\t\t} else {\n\t\t\t\t// C:\n\t\t\t\t// ^^\n\t\t\t\treturn path.slice(0, 2);\n\t\t\t}\n\t\t}\n\t}\n\n\t// check for URI\n\t// scheme://authority/path\n\t// ^^^^^^^^^^^^^^^^^^^\n\tlet pos = path.indexOf('://');\n\tif (pos !== -1) {\n\t\tpos += 3; // 3 -> \"://\".length\n\t\tfor (; pos < len; pos++) {\n\t\t\tif (isPathSeparator(path.charCodeAt(pos))) {\n\t\t\t\treturn path.slice(0, pos + 1); // consume this separator\n\t\t\t}\n\t\t}\n\t}\n\n\treturn '';\n}\n\n/**\n * @deprecated please use `IUriIdentityService.extUri.isEqualOrParent` instead. If\n * you are in a context without services, consider to pass down the `extUri` from the\n * outside, or use `extUriBiasedIgnorePathCase` if you know what you are doing.\n */\nexport function isEqualOrParent(base: string, parentCandidate: string, ignoreCase?: boolean, separator = sep): boolean {\n\tif (base === parentCandidate) {\n\t\treturn true;\n\t}\n\n\tif (!base || !parentCandidate) {\n\t\treturn false;\n\t}\n\n\tif (parentCandidate.length > base.length) {\n\t\treturn false;\n\t}\n\n\tif (ignoreCase) {\n\t\tconst beginsWith = startsWithIgnoreCase(base, parentCandidate);\n\t\tif (!beginsWith) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (parentCandidate.length === base.length) {\n\t\t\treturn true; // same path, different casing\n\t\t}\n\n\t\tlet sepOffset = parentCandidate.length;\n\t\tif (parentCandidate.charAt(parentCandidate.length - 1) === separator) {\n\t\t\tsepOffset--; // adjust the expected sep offset in case our candidate already ends in separator character\n\t\t}\n\n\t\treturn base.charAt(sepOffset) === separator;\n\t}\n\n\tif (parentCandidate.charAt(parentCandidate.length - 1) !== separator) {\n\t\tparentCandidate += separator;\n\t}\n\n\treturn base.indexOf(parentCandidate) === 0;\n}\n\nexport function isWindowsDriveLetter(char0: number): boolean {\n\treturn char0 >= CharCode.A && char0 <= CharCode.Z || char0 >= CharCode.a && char0 <= CharCode.z;\n}\n\nexport function isRootOrDriveLetter(path: string): boolean {\n\tconst pathNormalized = normalize(path);\n\n\tif (isWindows) {\n\t\tif (path.length > 3) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn hasDriveLetter(pathNormalized) &&\n\t\t\t(path.length === 2 || pathNormalized.charCodeAt(2) === CharCode.Backslash);\n\t}\n\n\treturn pathNormalized === posix.sep;\n}\n\nexport function hasDriveLetter(path: string, continueAsWindows?: boolean): boolean {\n\tconst isWindowsPath: boolean = ((continueAsWindows !== undefined) ? continueAsWindows : isWindows);\n\tif (isWindowsPath) {\n\t\treturn isWindowsDriveLetter(path.charCodeAt(0)) && path.charCodeAt(1) === CharCode.Colon;\n\t}\n\n\treturn false;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as strings from 'vs/base/common/strings';\n\n/**\n * Return a hash value for an object.\n */\nexport function hash(obj: any): number {\n\treturn doHash(obj, 0);\n}\n\nexport function doHash(obj: any, hashVal: number): number {\n\tswitch (typeof obj) {\n\t\tcase 'object':\n\t\t\tif (obj === null) {\n\t\t\t\treturn numberHash(349, hashVal);\n\t\t\t} else if (Array.isArray(obj)) {\n\t\t\t\treturn arrayHash(obj, hashVal);\n\t\t\t}\n\t\t\treturn objectHash(obj, hashVal);\n\t\tcase 'string':\n\t\t\treturn stringHash(obj, hashVal);\n\t\tcase 'boolean':\n\t\t\treturn booleanHash(obj, hashVal);\n\t\tcase 'number':\n\t\t\treturn numberHash(obj, hashVal);\n\t\tcase 'undefined':\n\t\t\treturn numberHash(937, hashVal);\n\t\tdefault:\n\t\t\treturn numberHash(617, hashVal);\n\t}\n}\n\nexport function numberHash(val: number, initialHashVal: number): number {\n\treturn (((initialHashVal << 5) - initialHashVal) + val) | 0; // hashVal * 31 + ch, keep as int32\n}\n\nfunction booleanHash(b: boolean, initialHashVal: number): number {\n\treturn numberHash(b ? 433 : 863, initialHashVal);\n}\n\nexport function stringHash(s: string, hashVal: number) {\n\thashVal = numberHash(149417, hashVal);\n\tfor (let i = 0, length = s.length; i < length; i++) {\n\t\thashVal = numberHash(s.charCodeAt(i), hashVal);\n\t}\n\treturn hashVal;\n}\n\nfunction arrayHash(arr: any[], initialHashVal: number): number {\n\tinitialHashVal = numberHash(104579, initialHashVal);\n\treturn arr.reduce((hashVal, item) => doHash(item, hashVal), initialHashVal);\n}\n\nfunction objectHash(obj: any, initialHashVal: number): number {\n\tinitialHashVal = numberHash(181387, initialHashVal);\n\treturn Object.keys(obj).sort().reduce((hashVal, key) => {\n\t\thashVal = stringHash(key, hashVal);\n\t\treturn doHash(obj[key], hashVal);\n\t}, initialHashVal);\n}\n\nconst enum SHA1Constant {\n\tBLOCK_SIZE = 64, // 512 / 8\n\tUNICODE_REPLACEMENT = 0xFFFD,\n}\n\nfunction leftRotate(value: number, bits: number, totalBits: number = 32): number {\n\t// delta + bits = totalBits\n\tconst delta = totalBits - bits;\n\n\t// All ones, expect `delta` zeros aligned to the right\n\tconst mask = ~((1 << delta) - 1);\n\n\t// Join (value left-shifted `bits` bits) with (masked value right-shifted `delta` bits)\n\treturn ((value << bits) | ((mask & value) >>> delta)) >>> 0;\n}\n\nfunction fill(dest: Uint8Array, index: number = 0, count: number = dest.byteLength, value: number = 0): void {\n\tfor (let i = 0; i < count; i++) {\n\t\tdest[index + i] = value;\n\t}\n}\n\nfunction leftPad(value: string, length: number, char: string = '0'): string {\n\twhile (value.length < length) {\n\t\tvalue = char + value;\n\t}\n\treturn value;\n}\n\nexport function toHexString(buffer: ArrayBuffer): string;\nexport function toHexString(value: number, bitsize?: number): string;\nexport function toHexString(bufferOrValue: ArrayBuffer | number, bitsize: number = 32): string {\n\tif (bufferOrValue instanceof ArrayBuffer) {\n\t\treturn Array.from(new Uint8Array(bufferOrValue)).map(b => b.toString(16).padStart(2, '0')).join('');\n\t}\n\n\treturn leftPad((bufferOrValue >>> 0).toString(16), bitsize / 4);\n}\n\n/**\n * A SHA1 implementation that works with strings and does not allocate.\n */\nexport class StringSHA1 {\n\tprivate static _bigBlock32 = new DataView(new ArrayBuffer(320)); // 80 * 4 = 320\n\n\tprivate _h0 = 0x67452301;\n\tprivate _h1 = 0xEFCDAB89;\n\tprivate _h2 = 0x98BADCFE;\n\tprivate _h3 = 0x10325476;\n\tprivate _h4 = 0xC3D2E1F0;\n\n\tprivate readonly _buff: Uint8Array;\n\tprivate readonly _buffDV: DataView;\n\tprivate _buffLen: number;\n\tprivate _totalLen: number;\n\tprivate _leftoverHighSurrogate: number;\n\tprivate _finished: boolean;\n\n\tconstructor() {\n\t\tthis._buff = new Uint8Array(SHA1Constant.BLOCK_SIZE + 3 /* to fit any utf-8 */);\n\t\tthis._buffDV = new DataView(this._buff.buffer);\n\t\tthis._buffLen = 0;\n\t\tthis._totalLen = 0;\n\t\tthis._leftoverHighSurrogate = 0;\n\t\tthis._finished = false;\n\t}\n\n\tpublic update(str: string): void {\n\t\tconst strLen = str.length;\n\t\tif (strLen === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst buff = this._buff;\n\t\tlet buffLen = this._buffLen;\n\t\tlet leftoverHighSurrogate = this._leftoverHighSurrogate;\n\t\tlet charCode: number;\n\t\tlet offset: number;\n\n\t\tif (leftoverHighSurrogate !== 0) {\n\t\t\tcharCode = leftoverHighSurrogate;\n\t\t\toffset = -1;\n\t\t\tleftoverHighSurrogate = 0;\n\t\t} else {\n\t\t\tcharCode = str.charCodeAt(0);\n\t\t\toffset = 0;\n\t\t}\n\n\t\twhile (true) {\n\t\t\tlet codePoint = charCode;\n\t\t\tif (strings.isHighSurrogate(charCode)) {\n\t\t\t\tif (offset + 1 < strLen) {\n\t\t\t\t\tconst nextCharCode = str.charCodeAt(offset + 1);\n\t\t\t\t\tif (strings.isLowSurrogate(nextCharCode)) {\n\t\t\t\t\t\toffset++;\n\t\t\t\t\t\tcodePoint = strings.computeCodePoint(charCode, nextCharCode);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// illegal => unicode replacement character\n\t\t\t\t\t\tcodePoint = SHA1Constant.UNICODE_REPLACEMENT;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// last character is a surrogate pair\n\t\t\t\t\tleftoverHighSurrogate = charCode;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else if (strings.isLowSurrogate(charCode)) {\n\t\t\t\t// illegal => unicode replacement character\n\t\t\t\tcodePoint = SHA1Constant.UNICODE_REPLACEMENT;\n\t\t\t}\n\n\t\t\tbuffLen = this._push(buff, buffLen, codePoint);\n\t\t\toffset++;\n\t\t\tif (offset < strLen) {\n\t\t\t\tcharCode = str.charCodeAt(offset);\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tthis._buffLen = buffLen;\n\t\tthis._leftoverHighSurrogate = leftoverHighSurrogate;\n\t}\n\n\tprivate _push(buff: Uint8Array, buffLen: number, codePoint: number): number {\n\t\tif (codePoint < 0x0080) {\n\t\t\tbuff[buffLen++] = codePoint;\n\t\t} else if (codePoint < 0x0800) {\n\t\t\tbuff[buffLen++] = 0b11000000 | ((codePoint & 0b00000000000000000000011111000000) >>> 6);\n\t\t\tbuff[buffLen++] = 0b10000000 | ((codePoint & 0b00000000000000000000000000111111) >>> 0);\n\t\t} else if (codePoint < 0x10000) {\n\t\t\tbuff[buffLen++] = 0b11100000 | ((codePoint & 0b00000000000000001111000000000000) >>> 12);\n\t\t\tbuff[buffLen++] = 0b10000000 | ((codePoint & 0b00000000000000000000111111000000) >>> 6);\n\t\t\tbuff[buffLen++] = 0b10000000 | ((codePoint & 0b00000000000000000000000000111111) >>> 0);\n\t\t} else {\n\t\t\tbuff[buffLen++] = 0b11110000 | ((codePoint & 0b00000000000111000000000000000000) >>> 18);\n\t\t\tbuff[buffLen++] = 0b10000000 | ((codePoint & 0b00000000000000111111000000000000) >>> 12);\n\t\t\tbuff[buffLen++] = 0b10000000 | ((codePoint & 0b00000000000000000000111111000000) >>> 6);\n\t\t\tbuff[buffLen++] = 0b10000000 | ((codePoint & 0b00000000000000000000000000111111) >>> 0);\n\t\t}\n\n\t\tif (buffLen >= SHA1Constant.BLOCK_SIZE) {\n\t\t\tthis._step();\n\t\t\tbuffLen -= SHA1Constant.BLOCK_SIZE;\n\t\t\tthis._totalLen += SHA1Constant.BLOCK_SIZE;\n\t\t\t// take last 3 in case of UTF8 overflow\n\t\t\tbuff[0] = buff[SHA1Constant.BLOCK_SIZE + 0];\n\t\t\tbuff[1] = buff[SHA1Constant.BLOCK_SIZE + 1];\n\t\t\tbuff[2] = buff[SHA1Constant.BLOCK_SIZE + 2];\n\t\t}\n\n\t\treturn buffLen;\n\t}\n\n\tpublic digest(): string {\n\t\tif (!this._finished) {\n\t\t\tthis._finished = true;\n\t\t\tif (this._leftoverHighSurrogate) {\n\t\t\t\t// illegal => unicode replacement character\n\t\t\t\tthis._leftoverHighSurrogate = 0;\n\t\t\t\tthis._buffLen = this._push(this._buff, this._buffLen, SHA1Constant.UNICODE_REPLACEMENT);\n\t\t\t}\n\t\t\tthis._totalLen += this._buffLen;\n\t\t\tthis._wrapUp();\n\t\t}\n\n\t\treturn toHexString(this._h0) + toHexString(this._h1) + toHexString(this._h2) + toHexString(this._h3) + toHexString(this._h4);\n\t}\n\n\tprivate _wrapUp(): void {\n\t\tthis._buff[this._buffLen++] = 0x80;\n\t\tfill(this._buff, this._buffLen);\n\n\t\tif (this._buffLen > 56) {\n\t\t\tthis._step();\n\t\t\tfill(this._buff);\n\t\t}\n\n\t\t// this will fit because the mantissa can cover up to 52 bits\n\t\tconst ml = 8 * this._totalLen;\n\n\t\tthis._buffDV.setUint32(56, Math.floor(ml / 4294967296), false);\n\t\tthis._buffDV.setUint32(60, ml % 4294967296, false);\n\n\t\tthis._step();\n\t}\n\n\tprivate _step(): void {\n\t\tconst bigBlock32 = StringSHA1._bigBlock32;\n\t\tconst data = this._buffDV;\n\n\t\tfor (let j = 0; j < 64 /* 16*4 */; j += 4) {\n\t\t\tbigBlock32.setUint32(j, data.getUint32(j, false), false);\n\t\t}\n\n\t\tfor (let j = 64; j < 320 /* 80*4 */; j += 4) {\n\t\t\tbigBlock32.setUint32(j, leftRotate((bigBlock32.getUint32(j - 12, false) ^ bigBlock32.getUint32(j - 32, false) ^ bigBlock32.getUint32(j - 56, false) ^ bigBlock32.getUint32(j - 64, false)), 1), false);\n\t\t}\n\n\t\tlet a = this._h0;\n\t\tlet b = this._h1;\n\t\tlet c = this._h2;\n\t\tlet d = this._h3;\n\t\tlet e = this._h4;\n\n\t\tlet f: number, k: number;\n\t\tlet temp: number;\n\n\t\tfor (let j = 0; j < 80; j++) {\n\t\t\tif (j < 20) {\n\t\t\t\tf = (b & c) | ((~b) & d);\n\t\t\t\tk = 0x5A827999;\n\t\t\t} else if (j < 40) {\n\t\t\t\tf = b ^ c ^ d;\n\t\t\t\tk = 0x6ED9EBA1;\n\t\t\t} else if (j < 60) {\n\t\t\t\tf = (b & c) | (b & d) | (c & d);\n\t\t\t\tk = 0x8F1BBCDC;\n\t\t\t} else {\n\t\t\t\tf = b ^ c ^ d;\n\t\t\t\tk = 0xCA62C1D6;\n\t\t\t}\n\n\t\t\ttemp = (leftRotate(a, 5) + f + e + k + bigBlock32.getUint32(j * 4, false)) & 0xffffffff;\n\t\t\te = d;\n\t\t\td = c;\n\t\t\tc = leftRotate(b, 30);\n\t\t\tb = a;\n\t\t\ta = temp;\n\t\t}\n\n\t\tthis._h0 = (this._h0 + a) & 0xffffffff;\n\t\tthis._h1 = (this._h1 + b) & 0xffffffff;\n\t\tthis._h2 = (this._h2 + c) & 0xffffffff;\n\t\tthis._h3 = (this._h3 + d) & 0xffffffff;\n\t\tthis._h4 = (this._h4 + e) & 0xffffffff;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { DiffChange } from 'vs/base/common/diff/diffChange';\nimport { stringHash } from 'vs/base/common/hash';\nimport { Constants } from 'vs/base/common/uint';\n\nexport class StringDiffSequence implements ISequence {\n\n\tconstructor(private source: string) { }\n\n\tgetElements(): Int32Array | number[] | string[] {\n\t\tconst source = this.source;\n\t\tconst characters = new Int32Array(source.length);\n\t\tfor (let i = 0, len = source.length; i < len; i++) {\n\t\t\tcharacters[i] = source.charCodeAt(i);\n\t\t}\n\t\treturn characters;\n\t}\n}\n\nexport function stringDiff(original: string, modified: string, pretty: boolean): IDiffChange[] {\n\treturn new LcsDiff(new StringDiffSequence(original), new StringDiffSequence(modified)).ComputeDiff(pretty).changes;\n}\n\nexport interface ISequence {\n\tgetElements(): Int32Array | number[] | string[];\n\tgetStrictElement?(index: number): string;\n}\n\nexport interface IDiffChange {\n\t/**\n\t * The position of the first element in the original sequence which\n\t * this change affects.\n\t */\n\toriginalStart: number;\n\n\t/**\n\t * The number of elements from the original sequence which were\n\t * affected.\n\t */\n\toriginalLength: number;\n\n\t/**\n\t * The position of the first element in the modified sequence which\n\t * this change affects.\n\t */\n\tmodifiedStart: number;\n\n\t/**\n\t * The number of elements from the modified sequence which were\n\t * affected (added).\n\t */\n\tmodifiedLength: number;\n}\n\nexport interface IContinueProcessingPredicate {\n\t(furthestOriginalIndex: number, matchLengthOfLongest: number): boolean;\n}\n\nexport interface IDiffResult {\n\tquitEarly: boolean;\n\tchanges: IDiffChange[];\n}\n\n//\n// The code below has been ported from a C# implementation in VS\n//\n\nexport class Debug {\n\n\tpublic static Assert(condition: boolean, message: string): void {\n\t\tif (!condition) {\n\t\t\tthrow new Error(message);\n\t\t}\n\t}\n}\n\nexport class MyArray {\n\t/**\n\t * Copies a range of elements from an Array starting at the specified source index and pastes\n\t * them to another Array starting at the specified destination index. The length and the indexes\n\t * are specified as 64-bit integers.\n\t * sourceArray:\n\t *\t\tThe Array that contains the data to copy.\n\t * sourceIndex:\n\t *\t\tA 64-bit integer that represents the index in the sourceArray at which copying begins.\n\t * destinationArray:\n\t *\t\tThe Array that receives the data.\n\t * destinationIndex:\n\t *\t\tA 64-bit integer that represents the index in the destinationArray at which storing begins.\n\t * length:\n\t *\t\tA 64-bit integer that represents the number of elements to copy.\n\t */\n\tpublic static Copy(sourceArray: any[], sourceIndex: number, destinationArray: any[], destinationIndex: number, length: number) {\n\t\tfor (let i = 0; i < length; i++) {\n\t\t\tdestinationArray[destinationIndex + i] = sourceArray[sourceIndex + i];\n\t\t}\n\t}\n\tpublic static Copy2(sourceArray: Int32Array, sourceIndex: number, destinationArray: Int32Array, destinationIndex: number, length: number) {\n\t\tfor (let i = 0; i < length; i++) {\n\t\t\tdestinationArray[destinationIndex + i] = sourceArray[sourceIndex + i];\n\t\t}\n\t}\n}\n\n//*****************************************************************************\n// LcsDiff.cs\n//\n// An implementation of the difference algorithm described in\n// \"An O(ND) Difference Algorithm and its variations\" by Eugene W. Myers\n//\n// Copyright (C) 2008 Microsoft Corporation @minifier_do_not_preserve\n//*****************************************************************************\n\n// Our total memory usage for storing history is (worst-case):\n// 2 * [(MaxDifferencesHistory + 1) * (MaxDifferencesHistory + 1) - 1] * sizeof(int)\n// 2 * [1448*1448 - 1] * 4 = 16773624 = 16MB\nconst enum LocalConstants {\n\tMaxDifferencesHistory = 1447\n}\n\n/**\n * A utility class which helps to create the set of DiffChanges from\n * a difference operation. This class accepts original DiffElements and\n * modified DiffElements that are involved in a particular change. The\n * MarkNextChange() method can be called to mark the separation between\n * distinct changes. At the end, the Changes property can be called to retrieve\n * the constructed changes.\n */\nclass DiffChangeHelper {\n\n\tprivate m_changes: DiffChange[];\n\tprivate m_originalStart: number;\n\tprivate m_modifiedStart: number;\n\tprivate m_originalCount: number;\n\tprivate m_modifiedCount: number;\n\n\t/**\n\t * Constructs a new DiffChangeHelper for the given DiffSequences.\n\t */\n\tconstructor() {\n\t\tthis.m_changes = [];\n\t\tthis.m_originalStart = Constants.MAX_SAFE_SMALL_INTEGER;\n\t\tthis.m_modifiedStart = Constants.MAX_SAFE_SMALL_INTEGER;\n\t\tthis.m_originalCount = 0;\n\t\tthis.m_modifiedCount = 0;\n\t}\n\n\t/**\n\t * Marks the beginning of the next change in the set of differences.\n\t */\n\tpublic MarkNextChange(): void {\n\t\t// Only add to the list if there is something to add\n\t\tif (this.m_originalCount > 0 || this.m_modifiedCount > 0) {\n\t\t\t// Add the new change to our list\n\t\t\tthis.m_changes.push(new DiffChange(this.m_originalStart, this.m_originalCount,\n\t\t\t\tthis.m_modifiedStart, this.m_modifiedCount));\n\t\t}\n\n\t\t// Reset for the next change\n\t\tthis.m_originalCount = 0;\n\t\tthis.m_modifiedCount = 0;\n\t\tthis.m_originalStart = Constants.MAX_SAFE_SMALL_INTEGER;\n\t\tthis.m_modifiedStart = Constants.MAX_SAFE_SMALL_INTEGER;\n\t}\n\n\t/**\n\t * Adds the original element at the given position to the elements\n\t * affected by the current change. The modified index gives context\n\t * to the change position with respect to the original sequence.\n\t * @param originalIndex The index of the original element to add.\n\t * @param modifiedIndex The index of the modified element that provides corresponding position in the modified sequence.\n\t */\n\tpublic AddOriginalElement(originalIndex: number, modifiedIndex: number) {\n\t\t// The 'true' start index is the smallest of the ones we've seen\n\t\tthis.m_originalStart = Math.min(this.m_originalStart, originalIndex);\n\t\tthis.m_modifiedStart = Math.min(this.m_modifiedStart, modifiedIndex);\n\n\t\tthis.m_originalCount++;\n\t}\n\n\t/**\n\t * Adds the modified element at the given position to the elements\n\t * affected by the current change. The original index gives context\n\t * to the change position with respect to the modified sequence.\n\t * @param originalIndex The index of the original element that provides corresponding position in the original sequence.\n\t * @param modifiedIndex The index of the modified element to add.\n\t */\n\tpublic AddModifiedElement(originalIndex: number, modifiedIndex: number): void {\n\t\t// The 'true' start index is the smallest of the ones we've seen\n\t\tthis.m_originalStart = Math.min(this.m_originalStart, originalIndex);\n\t\tthis.m_modifiedStart = Math.min(this.m_modifiedStart, modifiedIndex);\n\n\t\tthis.m_modifiedCount++;\n\t}\n\n\t/**\n\t * Retrieves all of the changes marked by the class.\n\t */\n\tpublic getChanges(): DiffChange[] {\n\t\tif (this.m_originalCount > 0 || this.m_modifiedCount > 0) {\n\t\t\t// Finish up on whatever is left\n\t\t\tthis.MarkNextChange();\n\t\t}\n\n\t\treturn this.m_changes;\n\t}\n\n\t/**\n\t * Retrieves all of the changes marked by the class in the reverse order\n\t */\n\tpublic getReverseChanges(): DiffChange[] {\n\t\tif (this.m_originalCount > 0 || this.m_modifiedCount > 0) {\n\t\t\t// Finish up on whatever is left\n\t\t\tthis.MarkNextChange();\n\t\t}\n\n\t\tthis.m_changes.reverse();\n\t\treturn this.m_changes;\n\t}\n\n}\n\n/**\n * An implementation of the difference algorithm described in\n * \"An O(ND) Difference Algorithm and its variations\" by Eugene W. Myers\n */\nexport class LcsDiff {\n\n\tprivate readonly ContinueProcessingPredicate: IContinueProcessingPredicate | null;\n\n\tprivate readonly _originalSequence: ISequence;\n\tprivate readonly _modifiedSequence: ISequence;\n\tprivate readonly _hasStrings: boolean;\n\tprivate readonly _originalStringElements: string[];\n\tprivate readonly _originalElementsOrHash: Int32Array;\n\tprivate readonly _modifiedStringElements: string[];\n\tprivate readonly _modifiedElementsOrHash: Int32Array;\n\n\tprivate m_forwardHistory: Int32Array[];\n\tprivate m_reverseHistory: Int32Array[];\n\n\t/**\n\t * Constructs the DiffFinder\n\t */\n\tconstructor(originalSequence: ISequence, modifiedSequence: ISequence, continueProcessingPredicate: IContinueProcessingPredicate | null = null) {\n\t\tthis.ContinueProcessingPredicate = continueProcessingPredicate;\n\n\t\tthis._originalSequence = originalSequence;\n\t\tthis._modifiedSequence = modifiedSequence;\n\n\t\tconst [originalStringElements, originalElementsOrHash, originalHasStrings] = LcsDiff._getElements(originalSequence);\n\t\tconst [modifiedStringElements, modifiedElementsOrHash, modifiedHasStrings] = LcsDiff._getElements(modifiedSequence);\n\n\t\tthis._hasStrings = (originalHasStrings && modifiedHasStrings);\n\t\tthis._originalStringElements = originalStringElements;\n\t\tthis._originalElementsOrHash = originalElementsOrHash;\n\t\tthis._modifiedStringElements = modifiedStringElements;\n\t\tthis._modifiedElementsOrHash = modifiedElementsOrHash;\n\n\t\tthis.m_forwardHistory = [];\n\t\tthis.m_reverseHistory = [];\n\t}\n\n\tprivate static _isStringArray(arr: Int32Array | number[] | string[]): arr is string[] {\n\t\treturn (arr.length > 0 && typeof arr[0] === 'string');\n\t}\n\n\tprivate static _getElements(sequence: ISequence): [string[], Int32Array, boolean] {\n\t\tconst elements = sequence.getElements();\n\n\t\tif (LcsDiff._isStringArray(elements)) {\n\t\t\tconst hashes = new Int32Array(elements.length);\n\t\t\tfor (let i = 0, len = elements.length; i < len; i++) {\n\t\t\t\thashes[i] = stringHash(elements[i], 0);\n\t\t\t}\n\t\t\treturn [elements, hashes, true];\n\t\t}\n\n\t\tif (elements instanceof Int32Array) {\n\t\t\treturn [[], elements, false];\n\t\t}\n\n\t\treturn [[], new Int32Array(elements), false];\n\t}\n\n\tprivate ElementsAreEqual(originalIndex: number, newIndex: number): boolean {\n\t\tif (this._originalElementsOrHash[originalIndex] !== this._modifiedElementsOrHash[newIndex]) {\n\t\t\treturn false;\n\t\t}\n\t\treturn (this._hasStrings ? this._originalStringElements[originalIndex] === this._modifiedStringElements[newIndex] : true);\n\t}\n\n\tprivate ElementsAreStrictEqual(originalIndex: number, newIndex: number): boolean {\n\t\tif (!this.ElementsAreEqual(originalIndex, newIndex)) {\n\t\t\treturn false;\n\t\t}\n\t\tconst originalElement = LcsDiff._getStrictElement(this._originalSequence, originalIndex);\n\t\tconst modifiedElement = LcsDiff._getStrictElement(this._modifiedSequence, newIndex);\n\t\treturn (originalElement === modifiedElement);\n\t}\n\n\tprivate static _getStrictElement(sequence: ISequence, index: number): string | null {\n\t\tif (typeof sequence.getStrictElement === 'function') {\n\t\t\treturn sequence.getStrictElement(index);\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate OriginalElementsAreEqual(index1: number, index2: number): boolean {\n\t\tif (this._originalElementsOrHash[index1] !== this._originalElementsOrHash[index2]) {\n\t\t\treturn false;\n\t\t}\n\t\treturn (this._hasStrings ? this._originalStringElements[index1] === this._originalStringElements[index2] : true);\n\t}\n\n\tprivate ModifiedElementsAreEqual(index1: number, index2: number): boolean {\n\t\tif (this._modifiedElementsOrHash[index1] !== this._modifiedElementsOrHash[index2]) {\n\t\t\treturn false;\n\t\t}\n\t\treturn (this._hasStrings ? this._modifiedStringElements[index1] === this._modifiedStringElements[index2] : true);\n\t}\n\n\tpublic ComputeDiff(pretty: boolean): IDiffResult {\n\t\treturn this._ComputeDiff(0, this._originalElementsOrHash.length - 1, 0, this._modifiedElementsOrHash.length - 1, pretty);\n\t}\n\n\t/**\n\t * Computes the differences between the original and modified input\n\t * sequences on the bounded range.\n\t * @returns An array of the differences between the two input sequences.\n\t */\n\tprivate _ComputeDiff(originalStart: number, originalEnd: number, modifiedStart: number, modifiedEnd: number, pretty: boolean): IDiffResult {\n\t\tconst quitEarlyArr = [false];\n\t\tlet changes = this.ComputeDiffRecursive(originalStart, originalEnd, modifiedStart, modifiedEnd, quitEarlyArr);\n\n\t\tif (pretty) {\n\t\t\t// We have to clean up the computed diff to be more intuitive\n\t\t\t// but it turns out this cannot be done correctly until the entire set\n\t\t\t// of diffs have been computed\n\t\t\tchanges = this.PrettifyChanges(changes);\n\t\t}\n\n\t\treturn {\n\t\t\tquitEarly: quitEarlyArr[0],\n\t\t\tchanges: changes\n\t\t};\n\t}\n\n\t/**\n\t * Private helper method which computes the differences on the bounded range\n\t * recursively.\n\t * @returns An array of the differences between the two input sequences.\n\t */\n\tprivate ComputeDiffRecursive(originalStart: number, originalEnd: number, modifiedStart: number, modifiedEnd: number, quitEarlyArr: boolean[]): DiffChange[] {\n\t\tquitEarlyArr[0] = false;\n\n\t\t// Find the start of the differences\n\t\twhile (originalStart <= originalEnd && modifiedStart <= modifiedEnd && this.ElementsAreEqual(originalStart, modifiedStart)) {\n\t\t\toriginalStart++;\n\t\t\tmodifiedStart++;\n\t\t}\n\n\t\t// Find the end of the differences\n\t\twhile (originalEnd >= originalStart && modifiedEnd >= modifiedStart && this.ElementsAreEqual(originalEnd, modifiedEnd)) {\n\t\t\toriginalEnd--;\n\t\t\tmodifiedEnd--;\n\t\t}\n\n\t\t// In the special case where we either have all insertions or all deletions or the sequences are identical\n\t\tif (originalStart > originalEnd || modifiedStart > modifiedEnd) {\n\t\t\tlet changes: DiffChange[];\n\n\t\t\tif (modifiedStart <= modifiedEnd) {\n\t\t\t\tDebug.Assert(originalStart === originalEnd + 1, 'originalStart should only be one more than originalEnd');\n\n\t\t\t\t// All insertions\n\t\t\t\tchanges = [\n\t\t\t\t\tnew DiffChange(originalStart, 0, modifiedStart, modifiedEnd - modifiedStart + 1)\n\t\t\t\t];\n\t\t\t} else if (originalStart <= originalEnd) {\n\t\t\t\tDebug.Assert(modifiedStart === modifiedEnd + 1, 'modifiedStart should only be one more than modifiedEnd');\n\n\t\t\t\t// All deletions\n\t\t\t\tchanges = [\n\t\t\t\t\tnew DiffChange(originalStart, originalEnd - originalStart + 1, modifiedStart, 0)\n\t\t\t\t];\n\t\t\t} else {\n\t\t\t\tDebug.Assert(originalStart === originalEnd + 1, 'originalStart should only be one more than originalEnd');\n\t\t\t\tDebug.Assert(modifiedStart === modifiedEnd + 1, 'modifiedStart should only be one more than modifiedEnd');\n\n\t\t\t\t// Identical sequences - No differences\n\t\t\t\tchanges = [];\n\t\t\t}\n\n\t\t\treturn changes;\n\t\t}\n\n\t\t// This problem can be solved using the Divide-And-Conquer technique.\n\t\tconst midOriginalArr = [0];\n\t\tconst midModifiedArr = [0];\n\t\tconst result = this.ComputeRecursionPoint(originalStart, originalEnd, modifiedStart, modifiedEnd, midOriginalArr, midModifiedArr, quitEarlyArr);\n\n\t\tconst midOriginal = midOriginalArr[0];\n\t\tconst midModified = midModifiedArr[0];\n\n\t\tif (result !== null) {\n\t\t\t// Result is not-null when there was enough memory to compute the changes while\n\t\t\t// searching for the recursion point\n\t\t\treturn result;\n\t\t} else if (!quitEarlyArr[0]) {\n\t\t\t// We can break the problem down recursively by finding the changes in the\n\t\t\t// First Half: (originalStart, modifiedStart) to (midOriginal, midModified)\n\t\t\t// Second Half: (midOriginal + 1, minModified + 1) to (originalEnd, modifiedEnd)\n\t\t\t// NOTE: ComputeDiff() is inclusive, therefore the second range starts on the next point\n\n\t\t\tconst leftChanges = this.ComputeDiffRecursive(originalStart, midOriginal, modifiedStart, midModified, quitEarlyArr);\n\t\t\tlet rightChanges: DiffChange[] = [];\n\n\t\t\tif (!quitEarlyArr[0]) {\n\t\t\t\trightChanges = this.ComputeDiffRecursive(midOriginal + 1, originalEnd, midModified + 1, modifiedEnd, quitEarlyArr);\n\t\t\t} else {\n\t\t\t\t// We didn't have time to finish the first half, so we don't have time to compute this half.\n\t\t\t\t// Consider the entire rest of the sequence different.\n\t\t\t\trightChanges = [\n\t\t\t\t\tnew DiffChange(midOriginal + 1, originalEnd - (midOriginal + 1) + 1, midModified + 1, modifiedEnd - (midModified + 1) + 1)\n\t\t\t\t];\n\t\t\t}\n\n\t\t\treturn this.ConcatenateChanges(leftChanges, rightChanges);\n\t\t}\n\n\t\t// If we hit here, we quit early, and so can't return anything meaningful\n\t\treturn [\n\t\t\tnew DiffChange(originalStart, originalEnd - originalStart + 1, modifiedStart, modifiedEnd - modifiedStart + 1)\n\t\t];\n\t}\n\n\tprivate WALKTRACE(diagonalForwardBase: number, diagonalForwardStart: number, diagonalForwardEnd: number, diagonalForwardOffset: number,\n\t\tdiagonalReverseBase: number, diagonalReverseStart: number, diagonalReverseEnd: number, diagonalReverseOffset: number,\n\t\tforwardPoints: Int32Array, reversePoints: Int32Array,\n\t\toriginalIndex: number, originalEnd: number, midOriginalArr: number[],\n\t\tmodifiedIndex: number, modifiedEnd: number, midModifiedArr: number[],\n\t\tdeltaIsEven: boolean, quitEarlyArr: boolean[]\n\t): DiffChange[] {\n\t\tlet forwardChanges: DiffChange[] | null = null;\n\t\tlet reverseChanges: DiffChange[] | null = null;\n\n\t\t// First, walk backward through the forward diagonals history\n\t\tlet changeHelper = new DiffChangeHelper();\n\t\tlet diagonalMin = diagonalForwardStart;\n\t\tlet diagonalMax = diagonalForwardEnd;\n\t\tlet diagonalRelative = (midOriginalArr[0] - midModifiedArr[0]) - diagonalForwardOffset;\n\t\tlet lastOriginalIndex = Constants.MIN_SAFE_SMALL_INTEGER;\n\t\tlet historyIndex = this.m_forwardHistory.length - 1;\n\n\t\tdo {\n\t\t\t// Get the diagonal index from the relative diagonal number\n\t\t\tconst diagonal = diagonalRelative + diagonalForwardBase;\n\n\t\t\t// Figure out where we came from\n\t\t\tif (diagonal === diagonalMin || (diagonal < diagonalMax && forwardPoints[diagonal - 1] < forwardPoints[diagonal + 1])) {\n\t\t\t\t// Vertical line (the element is an insert)\n\t\t\t\toriginalIndex = forwardPoints[diagonal + 1];\n\t\t\t\tmodifiedIndex = originalIndex - diagonalRelative - diagonalForwardOffset;\n\t\t\t\tif (originalIndex < lastOriginalIndex) {\n\t\t\t\t\tchangeHelper.MarkNextChange();\n\t\t\t\t}\n\t\t\t\tlastOriginalIndex = originalIndex;\n\t\t\t\tchangeHelper.AddModifiedElement(originalIndex + 1, modifiedIndex);\n\t\t\t\tdiagonalRelative = (diagonal + 1) - diagonalForwardBase; //Setup for the next iteration\n\t\t\t} else {\n\t\t\t\t// Horizontal line (the element is a deletion)\n\t\t\t\toriginalIndex = forwardPoints[diagonal - 1] + 1;\n\t\t\t\tmodifiedIndex = originalIndex - diagonalRelative - diagonalForwardOffset;\n\t\t\t\tif (originalIndex < lastOriginalIndex) {\n\t\t\t\t\tchangeHelper.MarkNextChange();\n\t\t\t\t}\n\t\t\t\tlastOriginalIndex = originalIndex - 1;\n\t\t\t\tchangeHelper.AddOriginalElement(originalIndex, modifiedIndex + 1);\n\t\t\t\tdiagonalRelative = (diagonal - 1) - diagonalForwardBase; //Setup for the next iteration\n\t\t\t}\n\n\t\t\tif (historyIndex >= 0) {\n\t\t\t\tforwardPoints = this.m_forwardHistory[historyIndex];\n\t\t\t\tdiagonalForwardBase = forwardPoints[0]; //We stored this in the first spot\n\t\t\t\tdiagonalMin = 1;\n\t\t\t\tdiagonalMax = forwardPoints.length - 1;\n\t\t\t}\n\t\t} while (--historyIndex >= -1);\n\n\t\t// Ironically, we get the forward changes as the reverse of the\n\t\t// order we added them since we technically added them backwards\n\t\tforwardChanges = changeHelper.getReverseChanges();\n\n\t\tif (quitEarlyArr[0]) {\n\t\t\t// TODO: Calculate a partial from the reverse diagonals.\n\t\t\t// For now, just assume everything after the midOriginal/midModified point is a diff\n\n\t\t\tlet originalStartPoint = midOriginalArr[0] + 1;\n\t\t\tlet modifiedStartPoint = midModifiedArr[0] + 1;\n\n\t\t\tif (forwardChanges !== null && forwardChanges.length > 0) {\n\t\t\t\tconst lastForwardChange = forwardChanges[forwardChanges.length - 1];\n\t\t\t\toriginalStartPoint = Math.max(originalStartPoint, lastForwardChange.getOriginalEnd());\n\t\t\t\tmodifiedStartPoint = Math.max(modifiedStartPoint, lastForwardChange.getModifiedEnd());\n\t\t\t}\n\n\t\t\treverseChanges = [\n\t\t\t\tnew DiffChange(originalStartPoint, originalEnd - originalStartPoint + 1,\n\t\t\t\t\tmodifiedStartPoint, modifiedEnd - modifiedStartPoint + 1)\n\t\t\t];\n\t\t} else {\n\t\t\t// Now walk backward through the reverse diagonals history\n\t\t\tchangeHelper = new DiffChangeHelper();\n\t\t\tdiagonalMin = diagonalReverseStart;\n\t\t\tdiagonalMax = diagonalReverseEnd;\n\t\t\tdiagonalRelative = (midOriginalArr[0] - midModifiedArr[0]) - diagonalReverseOffset;\n\t\t\tlastOriginalIndex = Constants.MAX_SAFE_SMALL_INTEGER;\n\t\t\thistoryIndex = (deltaIsEven) ? this.m_reverseHistory.length - 1 : this.m_reverseHistory.length - 2;\n\n\t\t\tdo {\n\t\t\t\t// Get the diagonal index from the relative diagonal number\n\t\t\t\tconst diagonal = diagonalRelative + diagonalReverseBase;\n\n\t\t\t\t// Figure out where we came from\n\t\t\t\tif (diagonal === diagonalMin || (diagonal < diagonalMax && reversePoints[diagonal - 1] >= reversePoints[diagonal + 1])) {\n\t\t\t\t\t// Horizontal line (the element is a deletion))\n\t\t\t\t\toriginalIndex = reversePoints[diagonal + 1] - 1;\n\t\t\t\t\tmodifiedIndex = originalIndex - diagonalRelative - diagonalReverseOffset;\n\t\t\t\t\tif (originalIndex > lastOriginalIndex) {\n\t\t\t\t\t\tchangeHelper.MarkNextChange();\n\t\t\t\t\t}\n\t\t\t\t\tlastOriginalIndex = originalIndex + 1;\n\t\t\t\t\tchangeHelper.AddOriginalElement(originalIndex + 1, modifiedIndex + 1);\n\t\t\t\t\tdiagonalRelative = (diagonal + 1) - diagonalReverseBase; //Setup for the next iteration\n\t\t\t\t} else {\n\t\t\t\t\t// Vertical line (the element is an insertion)\n\t\t\t\t\toriginalIndex = reversePoints[diagonal - 1];\n\t\t\t\t\tmodifiedIndex = originalIndex - diagonalRelative - diagonalReverseOffset;\n\t\t\t\t\tif (originalIndex > lastOriginalIndex) {\n\t\t\t\t\t\tchangeHelper.MarkNextChange();\n\t\t\t\t\t}\n\t\t\t\t\tlastOriginalIndex = originalIndex;\n\t\t\t\t\tchangeHelper.AddModifiedElement(originalIndex + 1, modifiedIndex + 1);\n\t\t\t\t\tdiagonalRelative = (diagonal - 1) - diagonalReverseBase; //Setup for the next iteration\n\t\t\t\t}\n\n\t\t\t\tif (historyIndex >= 0) {\n\t\t\t\t\treversePoints = this.m_reverseHistory[historyIndex];\n\t\t\t\t\tdiagonalReverseBase = reversePoints[0]; //We stored this in the first spot\n\t\t\t\t\tdiagonalMin = 1;\n\t\t\t\t\tdiagonalMax = reversePoints.length - 1;\n\t\t\t\t}\n\t\t\t} while (--historyIndex >= -1);\n\n\t\t\t// There are cases where the reverse history will find diffs that\n\t\t\t// are correct, but not intuitive, so we need shift them.\n\t\t\treverseChanges = changeHelper.getChanges();\n\t\t}\n\n\t\treturn this.ConcatenateChanges(forwardChanges, reverseChanges);\n\t}\n\n\t/**\n\t * Given the range to compute the diff on, this method finds the point:\n\t * (midOriginal, midModified)\n\t * that exists in the middle of the LCS of the two sequences and\n\t * is the point at which the LCS problem may be broken down recursively.\n\t * This method will try to keep the LCS trace in memory. If the LCS recursion\n\t * point is calculated and the full trace is available in memory, then this method\n\t * will return the change list.\n\t * @param originalStart The start bound of the original sequence range\n\t * @param originalEnd The end bound of the original sequence range\n\t * @param modifiedStart The start bound of the modified sequence range\n\t * @param modifiedEnd The end bound of the modified sequence range\n\t * @param midOriginal The middle point of the original sequence range\n\t * @param midModified The middle point of the modified sequence range\n\t * @returns The diff changes, if available, otherwise null\n\t */\n\tprivate ComputeRecursionPoint(originalStart: number, originalEnd: number, modifiedStart: number, modifiedEnd: number, midOriginalArr: number[], midModifiedArr: number[], quitEarlyArr: boolean[]) {\n\t\tlet originalIndex = 0, modifiedIndex = 0;\n\t\tlet diagonalForwardStart = 0, diagonalForwardEnd = 0;\n\t\tlet diagonalReverseStart = 0, diagonalReverseEnd = 0;\n\n\t\t// To traverse the edit graph and produce the proper LCS, our actual\n\t\t// start position is just outside the given boundary\n\t\toriginalStart--;\n\t\tmodifiedStart--;\n\n\t\t// We set these up to make the compiler happy, but they will\n\t\t// be replaced before we return with the actual recursion point\n\t\tmidOriginalArr[0] = 0;\n\t\tmidModifiedArr[0] = 0;\n\n\t\t// Clear out the history\n\t\tthis.m_forwardHistory = [];\n\t\tthis.m_reverseHistory = [];\n\n\t\t// Each cell in the two arrays corresponds to a diagonal in the edit graph.\n\t\t// The integer value in the cell represents the originalIndex of the furthest\n\t\t// reaching point found so far that ends in that diagonal.\n\t\t// The modifiedIndex can be computed mathematically from the originalIndex and the diagonal number.\n\t\tconst maxDifferences = (originalEnd - originalStart) + (modifiedEnd - modifiedStart);\n\t\tconst numDiagonals = maxDifferences + 1;\n\t\tconst forwardPoints = new Int32Array(numDiagonals);\n\t\tconst reversePoints = new Int32Array(numDiagonals);\n\t\t// diagonalForwardBase: Index into forwardPoints of the diagonal which passes through (originalStart, modifiedStart)\n\t\t// diagonalReverseBase: Index into reversePoints of the diagonal which passes through (originalEnd, modifiedEnd)\n\t\tconst diagonalForwardBase = (modifiedEnd - modifiedStart);\n\t\tconst diagonalReverseBase = (originalEnd - originalStart);\n\t\t// diagonalForwardOffset: Geometric offset which allows modifiedIndex to be computed from originalIndex and the\n\t\t// diagonal number (relative to diagonalForwardBase)\n\t\t// diagonalReverseOffset: Geometric offset which allows modifiedIndex to be computed from originalIndex and the\n\t\t// diagonal number (relative to diagonalReverseBase)\n\t\tconst diagonalForwardOffset = (originalStart - modifiedStart);\n\t\tconst diagonalReverseOffset = (originalEnd - modifiedEnd);\n\n\t\t// delta: The difference between the end diagonal and the start diagonal. This is used to relate diagonal numbers\n\t\t// relative to the start diagonal with diagonal numbers relative to the end diagonal.\n\t\t// The Even/Oddn-ness of this delta is important for determining when we should check for overlap\n\t\tconst delta = diagonalReverseBase - diagonalForwardBase;\n\t\tconst deltaIsEven = (delta % 2 === 0);\n\n\t\t// Here we set up the start and end points as the furthest points found so far\n\t\t// in both the forward and reverse directions, respectively\n\t\tforwardPoints[diagonalForwardBase] = originalStart;\n\t\treversePoints[diagonalReverseBase] = originalEnd;\n\n\t\t// Remember if we quit early, and thus need to do a best-effort result instead of a real result.\n\t\tquitEarlyArr[0] = false;\n\n\n\n\t\t// A couple of points:\n\t\t// --With this method, we iterate on the number of differences between the two sequences.\n\t\t// The more differences there actually are, the longer this will take.\n\t\t// --Also, as the number of differences increases, we have to search on diagonals further\n\t\t// away from the reference diagonal (which is diagonalForwardBase for forward, diagonalReverseBase for reverse).\n\t\t// --We extend on even diagonals (relative to the reference diagonal) only when numDifferences\n\t\t// is even and odd diagonals only when numDifferences is odd.\n\t\tfor (let numDifferences = 1; numDifferences <= (maxDifferences / 2) + 1; numDifferences++) {\n\t\t\tlet furthestOriginalIndex = 0;\n\t\t\tlet furthestModifiedIndex = 0;\n\n\t\t\t// Run the algorithm in the forward direction\n\t\t\tdiagonalForwardStart = this.ClipDiagonalBound(diagonalForwardBase - numDifferences, numDifferences, diagonalForwardBase, numDiagonals);\n\t\t\tdiagonalForwardEnd = this.ClipDiagonalBound(diagonalForwardBase + numDifferences, numDifferences, diagonalForwardBase, numDiagonals);\n\t\t\tfor (let diagonal = diagonalForwardStart; diagonal <= diagonalForwardEnd; diagonal += 2) {\n\t\t\t\t// STEP 1: We extend the furthest reaching point in the present diagonal\n\t\t\t\t// by looking at the diagonals above and below and picking the one whose point\n\t\t\t\t// is further away from the start point (originalStart, modifiedStart)\n\t\t\t\tif (diagonal === diagonalForwardStart || (diagonal < diagonalForwardEnd && forwardPoints[diagonal - 1] < forwardPoints[diagonal + 1])) {\n\t\t\t\t\toriginalIndex = forwardPoints[diagonal + 1];\n\t\t\t\t} else {\n\t\t\t\t\toriginalIndex = forwardPoints[diagonal - 1] + 1;\n\t\t\t\t}\n\t\t\t\tmodifiedIndex = originalIndex - (diagonal - diagonalForwardBase) - diagonalForwardOffset;\n\n\t\t\t\t// Save the current originalIndex so we can test for false overlap in step 3\n\t\t\t\tconst tempOriginalIndex = originalIndex;\n\n\t\t\t\t// STEP 2: We can continue to extend the furthest reaching point in the present diagonal\n\t\t\t\t// so long as the elements are equal.\n\t\t\t\twhile (originalIndex < originalEnd && modifiedIndex < modifiedEnd && this.ElementsAreEqual(originalIndex + 1, modifiedIndex + 1)) {\n\t\t\t\t\toriginalIndex++;\n\t\t\t\t\tmodifiedIndex++;\n\t\t\t\t}\n\t\t\t\tforwardPoints[diagonal] = originalIndex;\n\n\t\t\t\tif (originalIndex + modifiedIndex > furthestOriginalIndex + furthestModifiedIndex) {\n\t\t\t\t\tfurthestOriginalIndex = originalIndex;\n\t\t\t\t\tfurthestModifiedIndex = modifiedIndex;\n\t\t\t\t}\n\n\t\t\t\t// STEP 3: If delta is odd (overlap first happens on forward when delta is odd)\n\t\t\t\t// and diagonal is in the range of reverse diagonals computed for numDifferences-1\n\t\t\t\t// (the previous iteration; we haven't computed reverse diagonals for numDifferences yet)\n\t\t\t\t// then check for overlap.\n\t\t\t\tif (!deltaIsEven && Math.abs(diagonal - diagonalReverseBase) <= (numDifferences - 1)) {\n\t\t\t\t\tif (originalIndex >= reversePoints[diagonal]) {\n\t\t\t\t\t\tmidOriginalArr[0] = originalIndex;\n\t\t\t\t\t\tmidModifiedArr[0] = modifiedIndex;\n\n\t\t\t\t\t\tif (tempOriginalIndex <= reversePoints[diagonal] && LocalConstants.MaxDifferencesHistory > 0 && numDifferences <= (LocalConstants.MaxDifferencesHistory + 1)) {\n\t\t\t\t\t\t\t// BINGO! We overlapped, and we have the full trace in memory!\n\t\t\t\t\t\t\treturn this.WALKTRACE(diagonalForwardBase, diagonalForwardStart, diagonalForwardEnd, diagonalForwardOffset,\n\t\t\t\t\t\t\t\tdiagonalReverseBase, diagonalReverseStart, diagonalReverseEnd, diagonalReverseOffset,\n\t\t\t\t\t\t\t\tforwardPoints, reversePoints,\n\t\t\t\t\t\t\t\toriginalIndex, originalEnd, midOriginalArr,\n\t\t\t\t\t\t\t\tmodifiedIndex, modifiedEnd, midModifiedArr,\n\t\t\t\t\t\t\t\tdeltaIsEven, quitEarlyArr\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Either false overlap, or we didn't have enough memory for the full trace\n\t\t\t\t\t\t\t// Just return the recursion point\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check to see if we should be quitting early, before moving on to the next iteration.\n\t\t\tconst matchLengthOfLongest = ((furthestOriginalIndex - originalStart) + (furthestModifiedIndex - modifiedStart) - numDifferences) / 2;\n\n\t\t\tif (this.ContinueProcessingPredicate !== null && !this.ContinueProcessingPredicate(furthestOriginalIndex, matchLengthOfLongest)) {\n\t\t\t\t// We can't finish, so skip ahead to generating a result from what we have.\n\t\t\t\tquitEarlyArr[0] = true;\n\n\t\t\t\t// Use the furthest distance we got in the forward direction.\n\t\t\t\tmidOriginalArr[0] = furthestOriginalIndex;\n\t\t\t\tmidModifiedArr[0] = furthestModifiedIndex;\n\n\t\t\t\tif (matchLengthOfLongest > 0 && LocalConstants.MaxDifferencesHistory > 0 && numDifferences <= (LocalConstants.MaxDifferencesHistory + 1)) {\n\t\t\t\t\t// Enough of the history is in memory to walk it backwards\n\t\t\t\t\treturn this.WALKTRACE(diagonalForwardBase, diagonalForwardStart, diagonalForwardEnd, diagonalForwardOffset,\n\t\t\t\t\t\tdiagonalReverseBase, diagonalReverseStart, diagonalReverseEnd, diagonalReverseOffset,\n\t\t\t\t\t\tforwardPoints, reversePoints,\n\t\t\t\t\t\toriginalIndex, originalEnd, midOriginalArr,\n\t\t\t\t\t\tmodifiedIndex, modifiedEnd, midModifiedArr,\n\t\t\t\t\t\tdeltaIsEven, quitEarlyArr\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// We didn't actually remember enough of the history.\n\n\t\t\t\t\t//Since we are quitting the diff early, we need to shift back the originalStart and modified start\n\t\t\t\t\t//back into the boundary limits since we decremented their value above beyond the boundary limit.\n\t\t\t\t\toriginalStart++;\n\t\t\t\t\tmodifiedStart++;\n\n\t\t\t\t\treturn [\n\t\t\t\t\t\tnew DiffChange(originalStart, originalEnd - originalStart + 1,\n\t\t\t\t\t\t\tmodifiedStart, modifiedEnd - modifiedStart + 1)\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Run the algorithm in the reverse direction\n\t\t\tdiagonalReverseStart = this.ClipDiagonalBound(diagonalReverseBase - numDifferences, numDifferences, diagonalReverseBase, numDiagonals);\n\t\t\tdiagonalReverseEnd = this.ClipDiagonalBound(diagonalReverseBase + numDifferences, numDifferences, diagonalReverseBase, numDiagonals);\n\t\t\tfor (let diagonal = diagonalReverseStart; diagonal <= diagonalReverseEnd; diagonal += 2) {\n\t\t\t\t// STEP 1: We extend the furthest reaching point in the present diagonal\n\t\t\t\t// by looking at the diagonals above and below and picking the one whose point\n\t\t\t\t// is further away from the start point (originalEnd, modifiedEnd)\n\t\t\t\tif (diagonal === diagonalReverseStart || (diagonal < diagonalReverseEnd && reversePoints[diagonal - 1] >= reversePoints[diagonal + 1])) {\n\t\t\t\t\toriginalIndex = reversePoints[diagonal + 1] - 1;\n\t\t\t\t} else {\n\t\t\t\t\toriginalIndex = reversePoints[diagonal - 1];\n\t\t\t\t}\n\t\t\t\tmodifiedIndex = originalIndex - (diagonal - diagonalReverseBase) - diagonalReverseOffset;\n\n\t\t\t\t// Save the current originalIndex so we can test for false overlap\n\t\t\t\tconst tempOriginalIndex = originalIndex;\n\n\t\t\t\t// STEP 2: We can continue to extend the furthest reaching point in the present diagonal\n\t\t\t\t// as long as the elements are equal.\n\t\t\t\twhile (originalIndex > originalStart && modifiedIndex > modifiedStart && this.ElementsAreEqual(originalIndex, modifiedIndex)) {\n\t\t\t\t\toriginalIndex--;\n\t\t\t\t\tmodifiedIndex--;\n\t\t\t\t}\n\t\t\t\treversePoints[diagonal] = originalIndex;\n\n\t\t\t\t// STEP 4: If delta is even (overlap first happens on reverse when delta is even)\n\t\t\t\t// and diagonal is in the range of forward diagonals computed for numDifferences\n\t\t\t\t// then check for overlap.\n\t\t\t\tif (deltaIsEven && Math.abs(diagonal - diagonalForwardBase) <= numDifferences) {\n\t\t\t\t\tif (originalIndex <= forwardPoints[diagonal]) {\n\t\t\t\t\t\tmidOriginalArr[0] = originalIndex;\n\t\t\t\t\t\tmidModifiedArr[0] = modifiedIndex;\n\n\t\t\t\t\t\tif (tempOriginalIndex >= forwardPoints[diagonal] && LocalConstants.MaxDifferencesHistory > 0 && numDifferences <= (LocalConstants.MaxDifferencesHistory + 1)) {\n\t\t\t\t\t\t\t// BINGO! We overlapped, and we have the full trace in memory!\n\t\t\t\t\t\t\treturn this.WALKTRACE(diagonalForwardBase, diagonalForwardStart, diagonalForwardEnd, diagonalForwardOffset,\n\t\t\t\t\t\t\t\tdiagonalReverseBase, diagonalReverseStart, diagonalReverseEnd, diagonalReverseOffset,\n\t\t\t\t\t\t\t\tforwardPoints, reversePoints,\n\t\t\t\t\t\t\t\toriginalIndex, originalEnd, midOriginalArr,\n\t\t\t\t\t\t\t\tmodifiedIndex, modifiedEnd, midModifiedArr,\n\t\t\t\t\t\t\t\tdeltaIsEven, quitEarlyArr\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Either false overlap, or we didn't have enough memory for the full trace\n\t\t\t\t\t\t\t// Just return the recursion point\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Save current vectors to history before the next iteration\n\t\t\tif (numDifferences <= LocalConstants.MaxDifferencesHistory) {\n\t\t\t\t// We are allocating space for one extra int, which we fill with\n\t\t\t\t// the index of the diagonal base index\n\t\t\t\tlet temp = new Int32Array(diagonalForwardEnd - diagonalForwardStart + 2);\n\t\t\t\ttemp[0] = diagonalForwardBase - diagonalForwardStart + 1;\n\t\t\t\tMyArray.Copy2(forwardPoints, diagonalForwardStart, temp, 1, diagonalForwardEnd - diagonalForwardStart + 1);\n\t\t\t\tthis.m_forwardHistory.push(temp);\n\n\t\t\t\ttemp = new Int32Array(diagonalReverseEnd - diagonalReverseStart + 2);\n\t\t\t\ttemp[0] = diagonalReverseBase - diagonalReverseStart + 1;\n\t\t\t\tMyArray.Copy2(reversePoints, diagonalReverseStart, temp, 1, diagonalReverseEnd - diagonalReverseStart + 1);\n\t\t\t\tthis.m_reverseHistory.push(temp);\n\t\t\t}\n\n\t\t}\n\n\t\t// If we got here, then we have the full trace in history. We just have to convert it to a change list\n\t\t// NOTE: This part is a bit messy\n\t\treturn this.WALKTRACE(diagonalForwardBase, diagonalForwardStart, diagonalForwardEnd, diagonalForwardOffset,\n\t\t\tdiagonalReverseBase, diagonalReverseStart, diagonalReverseEnd, diagonalReverseOffset,\n\t\t\tforwardPoints, reversePoints,\n\t\t\toriginalIndex, originalEnd, midOriginalArr,\n\t\t\tmodifiedIndex, modifiedEnd, midModifiedArr,\n\t\t\tdeltaIsEven, quitEarlyArr\n\t\t);\n\t}\n\n\t/**\n\t * Shifts the given changes to provide a more intuitive diff.\n\t * While the first element in a diff matches the first element after the diff,\n\t * we shift the diff down.\n\t *\n\t * @param changes The list of changes to shift\n\t * @returns The shifted changes\n\t */\n\tprivate PrettifyChanges(changes: DiffChange[]): DiffChange[] {\n\n\t\t// Shift all the changes down first\n\t\tfor (let i = 0; i < changes.length; i++) {\n\t\t\tconst change = changes[i];\n\t\t\tconst originalStop = (i < changes.length - 1) ? changes[i + 1].originalStart : this._originalElementsOrHash.length;\n\t\t\tconst modifiedStop = (i < changes.length - 1) ? changes[i + 1].modifiedStart : this._modifiedElementsOrHash.length;\n\t\t\tconst checkOriginal = change.originalLength > 0;\n\t\t\tconst checkModified = change.modifiedLength > 0;\n\n\t\t\twhile (\n\t\t\t\tchange.originalStart + change.originalLength < originalStop\n\t\t\t\t&& change.modifiedStart + change.modifiedLength < modifiedStop\n\t\t\t\t&& (!checkOriginal || this.OriginalElementsAreEqual(change.originalStart, change.originalStart + change.originalLength))\n\t\t\t\t&& (!checkModified || this.ModifiedElementsAreEqual(change.modifiedStart, change.modifiedStart + change.modifiedLength))\n\t\t\t) {\n\t\t\t\tconst startStrictEqual = this.ElementsAreStrictEqual(change.originalStart, change.modifiedStart);\n\t\t\t\tconst endStrictEqual = this.ElementsAreStrictEqual(change.originalStart + change.originalLength, change.modifiedStart + change.modifiedLength);\n\t\t\t\tif (endStrictEqual && !startStrictEqual) {\n\t\t\t\t\t// moving the change down would create an equal change, but the elements are not strict equal\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tchange.originalStart++;\n\t\t\t\tchange.modifiedStart++;\n\t\t\t}\n\n\t\t\tlet mergedChangeArr: Array = [null];\n\t\t\tif (i < changes.length - 1 && this.ChangesOverlap(changes[i], changes[i + 1], mergedChangeArr)) {\n\t\t\t\tchanges[i] = mergedChangeArr[0]!;\n\t\t\t\tchanges.splice(i + 1, 1);\n\t\t\t\ti--;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// Shift changes back up until we hit empty or whitespace-only lines\n\t\tfor (let i = changes.length - 1; i >= 0; i--) {\n\t\t\tconst change = changes[i];\n\n\t\t\tlet originalStop = 0;\n\t\t\tlet modifiedStop = 0;\n\t\t\tif (i > 0) {\n\t\t\t\tconst prevChange = changes[i - 1];\n\t\t\t\toriginalStop = prevChange.originalStart + prevChange.originalLength;\n\t\t\t\tmodifiedStop = prevChange.modifiedStart + prevChange.modifiedLength;\n\t\t\t}\n\n\t\t\tconst checkOriginal = change.originalLength > 0;\n\t\t\tconst checkModified = change.modifiedLength > 0;\n\n\t\t\tlet bestDelta = 0;\n\t\t\tlet bestScore = this._boundaryScore(change.originalStart, change.originalLength, change.modifiedStart, change.modifiedLength);\n\n\t\t\tfor (let delta = 1; ; delta++) {\n\t\t\t\tconst originalStart = change.originalStart - delta;\n\t\t\t\tconst modifiedStart = change.modifiedStart - delta;\n\n\t\t\t\tif (originalStart < originalStop || modifiedStart < modifiedStop) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (checkOriginal && !this.OriginalElementsAreEqual(originalStart, originalStart + change.originalLength)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (checkModified && !this.ModifiedElementsAreEqual(modifiedStart, modifiedStart + change.modifiedLength)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tconst touchingPreviousChange = (originalStart === originalStop && modifiedStart === modifiedStop);\n\t\t\t\tconst score = (\n\t\t\t\t\t(touchingPreviousChange ? 5 : 0)\n\t\t\t\t\t+ this._boundaryScore(originalStart, change.originalLength, modifiedStart, change.modifiedLength)\n\t\t\t\t);\n\n\t\t\t\tif (score > bestScore) {\n\t\t\t\t\tbestScore = score;\n\t\t\t\t\tbestDelta = delta;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchange.originalStart -= bestDelta;\n\t\t\tchange.modifiedStart -= bestDelta;\n\n\t\t\tconst mergedChangeArr: Array = [null];\n\t\t\tif (i > 0 && this.ChangesOverlap(changes[i - 1], changes[i], mergedChangeArr)) {\n\t\t\t\tchanges[i - 1] = mergedChangeArr[0]!;\n\t\t\t\tchanges.splice(i, 1);\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// There could be multiple longest common substrings.\n\t\t// Give preference to the ones containing longer lines\n\t\tif (this._hasStrings) {\n\t\t\tfor (let i = 1, len = changes.length; i < len; i++) {\n\t\t\t\tconst aChange = changes[i - 1];\n\t\t\t\tconst bChange = changes[i];\n\t\t\t\tconst matchedLength = bChange.originalStart - aChange.originalStart - aChange.originalLength;\n\t\t\t\tconst aOriginalStart = aChange.originalStart;\n\t\t\t\tconst bOriginalEnd = bChange.originalStart + bChange.originalLength;\n\t\t\t\tconst abOriginalLength = bOriginalEnd - aOriginalStart;\n\t\t\t\tconst aModifiedStart = aChange.modifiedStart;\n\t\t\t\tconst bModifiedEnd = bChange.modifiedStart + bChange.modifiedLength;\n\t\t\t\tconst abModifiedLength = bModifiedEnd - aModifiedStart;\n\t\t\t\t// Avoid wasting a lot of time with these searches\n\t\t\t\tif (matchedLength < 5 && abOriginalLength < 20 && abModifiedLength < 20) {\n\t\t\t\t\tconst t = this._findBetterContiguousSequence(\n\t\t\t\t\t\taOriginalStart, abOriginalLength,\n\t\t\t\t\t\taModifiedStart, abModifiedLength,\n\t\t\t\t\t\tmatchedLength\n\t\t\t\t\t);\n\t\t\t\t\tif (t) {\n\t\t\t\t\t\tconst [originalMatchStart, modifiedMatchStart] = t;\n\t\t\t\t\t\tif (originalMatchStart !== aChange.originalStart + aChange.originalLength || modifiedMatchStart !== aChange.modifiedStart + aChange.modifiedLength) {\n\t\t\t\t\t\t\t// switch to another sequence that has a better score\n\t\t\t\t\t\t\taChange.originalLength = originalMatchStart - aChange.originalStart;\n\t\t\t\t\t\t\taChange.modifiedLength = modifiedMatchStart - aChange.modifiedStart;\n\t\t\t\t\t\t\tbChange.originalStart = originalMatchStart + matchedLength;\n\t\t\t\t\t\t\tbChange.modifiedStart = modifiedMatchStart + matchedLength;\n\t\t\t\t\t\t\tbChange.originalLength = bOriginalEnd - bChange.originalStart;\n\t\t\t\t\t\t\tbChange.modifiedLength = bModifiedEnd - bChange.modifiedStart;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn changes;\n\t}\n\n\tprivate _findBetterContiguousSequence(originalStart: number, originalLength: number, modifiedStart: number, modifiedLength: number, desiredLength: number): [number, number] | null {\n\t\tif (originalLength < desiredLength || modifiedLength < desiredLength) {\n\t\t\treturn null;\n\t\t}\n\t\tconst originalMax = originalStart + originalLength - desiredLength + 1;\n\t\tconst modifiedMax = modifiedStart + modifiedLength - desiredLength + 1;\n\t\tlet bestScore = 0;\n\t\tlet bestOriginalStart = 0;\n\t\tlet bestModifiedStart = 0;\n\t\tfor (let i = originalStart; i < originalMax; i++) {\n\t\t\tfor (let j = modifiedStart; j < modifiedMax; j++) {\n\t\t\t\tconst score = this._contiguousSequenceScore(i, j, desiredLength);\n\t\t\t\tif (score > 0 && score > bestScore) {\n\t\t\t\t\tbestScore = score;\n\t\t\t\t\tbestOriginalStart = i;\n\t\t\t\t\tbestModifiedStart = j;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (bestScore > 0) {\n\t\t\treturn [bestOriginalStart, bestModifiedStart];\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate _contiguousSequenceScore(originalStart: number, modifiedStart: number, length: number): number {\n\t\tlet score = 0;\n\t\tfor (let l = 0; l < length; l++) {\n\t\t\tif (!this.ElementsAreEqual(originalStart + l, modifiedStart + l)) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tscore += this._originalStringElements[originalStart + l].length;\n\t\t}\n\t\treturn score;\n\t}\n\n\tprivate _OriginalIsBoundary(index: number): boolean {\n\t\tif (index <= 0 || index >= this._originalElementsOrHash.length - 1) {\n\t\t\treturn true;\n\t\t}\n\t\treturn (this._hasStrings && /^\\s*$/.test(this._originalStringElements[index]));\n\t}\n\n\tprivate _OriginalRegionIsBoundary(originalStart: number, originalLength: number): boolean {\n\t\tif (this._OriginalIsBoundary(originalStart) || this._OriginalIsBoundary(originalStart - 1)) {\n\t\t\treturn true;\n\t\t}\n\t\tif (originalLength > 0) {\n\t\t\tconst originalEnd = originalStart + originalLength;\n\t\t\tif (this._OriginalIsBoundary(originalEnd - 1) || this._OriginalIsBoundary(originalEnd)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate _ModifiedIsBoundary(index: number): boolean {\n\t\tif (index <= 0 || index >= this._modifiedElementsOrHash.length - 1) {\n\t\t\treturn true;\n\t\t}\n\t\treturn (this._hasStrings && /^\\s*$/.test(this._modifiedStringElements[index]));\n\t}\n\n\tprivate _ModifiedRegionIsBoundary(modifiedStart: number, modifiedLength: number): boolean {\n\t\tif (this._ModifiedIsBoundary(modifiedStart) || this._ModifiedIsBoundary(modifiedStart - 1)) {\n\t\t\treturn true;\n\t\t}\n\t\tif (modifiedLength > 0) {\n\t\t\tconst modifiedEnd = modifiedStart + modifiedLength;\n\t\t\tif (this._ModifiedIsBoundary(modifiedEnd - 1) || this._ModifiedIsBoundary(modifiedEnd)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate _boundaryScore(originalStart: number, originalLength: number, modifiedStart: number, modifiedLength: number): number {\n\t\tconst originalScore = (this._OriginalRegionIsBoundary(originalStart, originalLength) ? 1 : 0);\n\t\tconst modifiedScore = (this._ModifiedRegionIsBoundary(modifiedStart, modifiedLength) ? 1 : 0);\n\t\treturn (originalScore + modifiedScore);\n\t}\n\n\t/**\n\t * Concatenates the two input DiffChange lists and returns the resulting\n\t * list.\n\t * @param The left changes\n\t * @param The right changes\n\t * @returns The concatenated list\n\t */\n\tprivate ConcatenateChanges(left: DiffChange[], right: DiffChange[]): DiffChange[] {\n\t\tlet mergedChangeArr: DiffChange[] = [];\n\n\t\tif (left.length === 0 || right.length === 0) {\n\t\t\treturn (right.length > 0) ? right : left;\n\t\t} else if (this.ChangesOverlap(left[left.length - 1], right[0], mergedChangeArr)) {\n\t\t\t// Since we break the problem down recursively, it is possible that we\n\t\t\t// might recurse in the middle of a change thereby splitting it into\n\t\t\t// two changes. Here in the combining stage, we detect and fuse those\n\t\t\t// changes back together\n\t\t\tconst result = new Array(left.length + right.length - 1);\n\t\t\tMyArray.Copy(left, 0, result, 0, left.length - 1);\n\t\t\tresult[left.length - 1] = mergedChangeArr[0];\n\t\t\tMyArray.Copy(right, 1, result, left.length, right.length - 1);\n\n\t\t\treturn result;\n\t\t} else {\n\t\t\tconst result = new Array(left.length + right.length);\n\t\t\tMyArray.Copy(left, 0, result, 0, left.length);\n\t\t\tMyArray.Copy(right, 0, result, left.length, right.length);\n\n\t\t\treturn result;\n\t\t}\n\t}\n\n\t/**\n\t * Returns true if the two changes overlap and can be merged into a single\n\t * change\n\t * @param left The left change\n\t * @param right The right change\n\t * @param mergedChange The merged change if the two overlap, null otherwise\n\t * @returns True if the two changes overlap\n\t */\n\tprivate ChangesOverlap(left: DiffChange, right: DiffChange, mergedChangeArr: Array): boolean {\n\t\tDebug.Assert(left.originalStart <= right.originalStart, 'Left change is not less than or equal to right change');\n\t\tDebug.Assert(left.modifiedStart <= right.modifiedStart, 'Left change is not less than or equal to right change');\n\n\t\tif (left.originalStart + left.originalLength >= right.originalStart || left.modifiedStart + left.modifiedLength >= right.modifiedStart) {\n\t\t\tconst originalStart = left.originalStart;\n\t\t\tlet originalLength = left.originalLength;\n\t\t\tconst modifiedStart = left.modifiedStart;\n\t\t\tlet modifiedLength = left.modifiedLength;\n\n\t\t\tif (left.originalStart + left.originalLength >= right.originalStart) {\n\t\t\t\toriginalLength = right.originalStart + right.originalLength - left.originalStart;\n\t\t\t}\n\t\t\tif (left.modifiedStart + left.modifiedLength >= right.modifiedStart) {\n\t\t\t\tmodifiedLength = right.modifiedStart + right.modifiedLength - left.modifiedStart;\n\t\t\t}\n\n\t\t\tmergedChangeArr[0] = new DiffChange(originalStart, originalLength, modifiedStart, modifiedLength);\n\t\t\treturn true;\n\t\t} else {\n\t\t\tmergedChangeArr[0] = null;\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Helper method used to clip a diagonal index to the range of valid\n\t * diagonals. This also decides whether or not the diagonal index,\n\t * if it exceeds the boundary, should be clipped to the boundary or clipped\n\t * one inside the boundary depending on the Even/Odd status of the boundary\n\t * and numDifferences.\n\t * @param diagonal The index of the diagonal to clip.\n\t * @param numDifferences The current number of differences being iterated upon.\n\t * @param diagonalBaseIndex The base reference diagonal.\n\t * @param numDiagonals The total number of diagonals.\n\t * @returns The clipped diagonal index.\n\t */\n\tprivate ClipDiagonalBound(diagonal: number, numDifferences: number, diagonalBaseIndex: number, numDiagonals: number): number {\n\t\tif (diagonal >= 0 && diagonal < numDiagonals) {\n\t\t\t// Nothing to clip, its in range\n\t\t\treturn diagonal;\n\t\t}\n\n\t\t// diagonalsBelow: The number of diagonals below the reference diagonal\n\t\t// diagonalsAbove: The number of diagonals above the reference diagonal\n\t\tconst diagonalsBelow = diagonalBaseIndex;\n\t\tconst diagonalsAbove = numDiagonals - diagonalBaseIndex - 1;\n\t\tconst diffEven = (numDifferences % 2 === 0);\n\n\t\tif (diagonal < 0) {\n\t\t\tconst lowerBoundEven = (diagonalsBelow % 2 === 0);\n\t\t\treturn (diffEven === lowerBoundEven) ? 0 : 1;\n\t\t} else {\n\t\t\tconst upperBoundEven = (diagonalsAbove % 2 === 0);\n\t\t\treturn (diffEven === upperBoundEven) ? numDiagonals - 1 : numDiagonals - 2;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IIdentityProvider } from 'vs/base/browser/ui/list/list';\nimport { ICollapseStateChangeEvent, ITreeElement, ITreeFilter, ITreeFilterDataResult, ITreeModel, ITreeModelSpliceEvent, ITreeNode, TreeError, TreeVisibility } from 'vs/base/browser/ui/tree/tree';\nimport { splice, tail2 } from 'vs/base/common/arrays';\nimport { Delayer, MicrotaskDelay } from 'vs/base/common/async';\nimport { LcsDiff } from 'vs/base/common/diff/diff';\nimport { Emitter, Event, EventBufferer } from 'vs/base/common/event';\nimport { Iterable } from 'vs/base/common/iterator';\nimport { ISpliceable } from 'vs/base/common/sequence';\n\n// Exported for tests\nexport interface IIndexTreeNode extends ITreeNode {\n\treadonly parent: IIndexTreeNode | undefined;\n\treadonly children: IIndexTreeNode[];\n\tvisibleChildrenCount: number;\n\tvisibleChildIndex: number;\n\tcollapsible: boolean;\n\tcollapsed: boolean;\n\trenderNodeCount: number;\n\tvisibility: TreeVisibility;\n\tvisible: boolean;\n\tfilterData: TFilterData | undefined;\n\tlastDiffIds?: string[];\n}\n\nexport function isFilterResult(obj: any): obj is ITreeFilterDataResult {\n\treturn typeof obj === 'object' && 'visibility' in obj && 'data' in obj;\n}\n\nexport function getVisibleState(visibility: boolean | TreeVisibility): TreeVisibility {\n\tswitch (visibility) {\n\t\tcase true: return TreeVisibility.Visible;\n\t\tcase false: return TreeVisibility.Hidden;\n\t\tdefault: return visibility;\n\t}\n}\n\nexport interface IIndexTreeModelOptions {\n\treadonly collapseByDefault?: boolean; // defaults to false\n\treadonly filter?: ITreeFilter;\n\treadonly autoExpandSingleChildren?: boolean;\n}\n\nexport interface IIndexTreeModelSpliceOptions {\n\t/**\n\t * If set, child updates will recurse the given number of levels even if\n\t * items in the splice operation are unchanged. `Infinity` is a valid value.\n\t */\n\treadonly diffDepth?: number;\n\n\t/**\n\t * Identity provider used to optimize splice() calls in the IndexTree. If\n\t * this is not present, optimized splicing is not enabled.\n\t *\n\t * Warning: if this is present, calls to `setChildren()` will not replace\n\t * or update nodes if their identity is the same, even if the elements are\n\t * different. For this, you should call `rerender()`.\n\t */\n\treadonly diffIdentityProvider?: IIdentityProvider;\n\n\t/**\n\t * Callback for when a node is created.\n\t */\n\tonDidCreateNode?: (node: ITreeNode) => void;\n\n\t/**\n\t * Callback for when a node is deleted.\n\t */\n\tonDidDeleteNode?: (node: ITreeNode) => void\n}\n\ninterface CollapsibleStateUpdate {\n\treadonly collapsible: boolean;\n}\n\ninterface CollapsedStateUpdate {\n\treadonly collapsed: boolean;\n\treadonly recursive: boolean;\n}\n\ntype CollapseStateUpdate = CollapsibleStateUpdate | CollapsedStateUpdate;\n\nfunction isCollapsibleStateUpdate(update: CollapseStateUpdate): update is CollapsibleStateUpdate {\n\treturn typeof (update as any).collapsible === 'boolean';\n}\n\nexport interface IList extends ISpliceable {\n\tupdateElementHeight(index: number, height: number | undefined): void;\n}\n\nexport class IndexTreeModel, TFilterData = void> implements ITreeModel {\n\n\treadonly rootRef = [];\n\n\tprivate root: IIndexTreeNode;\n\tprivate eventBufferer = new EventBufferer();\n\n\tprivate readonly _onDidChangeCollapseState = new Emitter>();\n\treadonly onDidChangeCollapseState: Event> = this.eventBufferer.wrapEvent(this._onDidChangeCollapseState.event);\n\n\tprivate readonly _onDidChangeRenderNodeCount = new Emitter>();\n\treadonly onDidChangeRenderNodeCount: Event> = this.eventBufferer.wrapEvent(this._onDidChangeRenderNodeCount.event);\n\n\tprivate collapseByDefault: boolean;\n\tprivate filter?: ITreeFilter;\n\tprivate autoExpandSingleChildren: boolean;\n\n\tprivate readonly _onDidSplice = new Emitter>();\n\treadonly onDidSplice = this._onDidSplice.event;\n\n\tprivate readonly refilterDelayer = new Delayer(MicrotaskDelay);\n\n\tconstructor(\n\t\tprivate user: string,\n\t\tprivate list: IList>,\n\t\trootElement: T,\n\t\toptions: IIndexTreeModelOptions = {}\n\t) {\n\t\tthis.collapseByDefault = typeof options.collapseByDefault === 'undefined' ? false : options.collapseByDefault;\n\t\tthis.filter = options.filter;\n\t\tthis.autoExpandSingleChildren = typeof options.autoExpandSingleChildren === 'undefined' ? false : options.autoExpandSingleChildren;\n\n\t\tthis.root = {\n\t\t\tparent: undefined,\n\t\t\telement: rootElement,\n\t\t\tchildren: [],\n\t\t\tdepth: 0,\n\t\t\tvisibleChildrenCount: 0,\n\t\t\tvisibleChildIndex: -1,\n\t\t\tcollapsible: false,\n\t\t\tcollapsed: false,\n\t\t\trenderNodeCount: 0,\n\t\t\tvisibility: TreeVisibility.Visible,\n\t\t\tvisible: true,\n\t\t\tfilterData: undefined\n\t\t};\n\t}\n\n\tsplice(\n\t\tlocation: number[],\n\t\tdeleteCount: number,\n\t\ttoInsert: Iterable> = Iterable.empty(),\n\t\toptions: IIndexTreeModelSpliceOptions = {},\n\t): void {\n\t\tif (location.length === 0) {\n\t\t\tthrow new TreeError(this.user, 'Invalid tree location');\n\t\t}\n\n\t\tif (options.diffIdentityProvider) {\n\t\t\tthis.spliceSmart(options.diffIdentityProvider, location, deleteCount, toInsert, options);\n\t\t} else {\n\t\t\tthis.spliceSimple(location, deleteCount, toInsert, options);\n\t\t}\n\t}\n\n\tprivate spliceSmart(\n\t\tidentity: IIdentityProvider,\n\t\tlocation: number[],\n\t\tdeleteCount: number,\n\t\ttoInsertIterable: Iterable> = Iterable.empty(),\n\t\toptions: IIndexTreeModelSpliceOptions,\n\t\trecurseLevels = options.diffDepth ?? 0,\n\t) {\n\t\tconst { parentNode } = this.getParentNodeWithListIndex(location);\n\t\tif (!parentNode.lastDiffIds) {\n\t\t\treturn this.spliceSimple(location, deleteCount, toInsertIterable, options);\n\t\t}\n\n\t\tconst toInsert = [...toInsertIterable];\n\t\tconst index = location[location.length - 1];\n\t\tconst diff = new LcsDiff(\n\t\t\t{ getElements: () => parentNode.lastDiffIds! },\n\t\t\t{\n\t\t\t\tgetElements: () => [\n\t\t\t\t\t...parentNode.children.slice(0, index),\n\t\t\t\t\t...toInsert,\n\t\t\t\t\t...parentNode.children.slice(index + deleteCount),\n\t\t\t\t].map(e => identity.getId(e.element).toString())\n\t\t\t},\n\t\t).ComputeDiff(false);\n\n\t\t// if we were given a 'best effort' diff, use default behavior\n\t\tif (diff.quitEarly) {\n\t\t\tparentNode.lastDiffIds = undefined;\n\t\t\treturn this.spliceSimple(location, deleteCount, toInsert, options);\n\t\t}\n\n\t\tconst locationPrefix = location.slice(0, -1);\n\t\tconst recurseSplice = (fromOriginal: number, fromModified: number, count: number) => {\n\t\t\tif (recurseLevels > 0) {\n\t\t\t\tfor (let i = 0; i < count; i++) {\n\t\t\t\t\tfromOriginal--;\n\t\t\t\t\tfromModified--;\n\t\t\t\t\tthis.spliceSmart(\n\t\t\t\t\t\tidentity,\n\t\t\t\t\t\t[...locationPrefix, fromOriginal, 0],\n\t\t\t\t\t\tNumber.MAX_SAFE_INTEGER,\n\t\t\t\t\t\ttoInsert[fromModified].children,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\trecurseLevels - 1,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tlet lastStartO = Math.min(parentNode.children.length, index + deleteCount);\n\t\tlet lastStartM = toInsert.length;\n\t\tfor (const change of diff.changes.sort((a, b) => b.originalStart - a.originalStart)) {\n\t\t\trecurseSplice(lastStartO, lastStartM, lastStartO - (change.originalStart + change.originalLength));\n\t\t\tlastStartO = change.originalStart;\n\t\t\tlastStartM = change.modifiedStart - index;\n\n\t\t\tthis.spliceSimple(\n\t\t\t\t[...locationPrefix, lastStartO],\n\t\t\t\tchange.originalLength,\n\t\t\t\tIterable.slice(toInsert, lastStartM, lastStartM + change.modifiedLength),\n\t\t\t\toptions,\n\t\t\t);\n\t\t}\n\n\t\t// at this point, startO === startM === count since any remaining prefix should match\n\t\trecurseSplice(lastStartO, lastStartM, lastStartO);\n\t}\n\n\tprivate spliceSimple(\n\t\tlocation: number[],\n\t\tdeleteCount: number,\n\t\ttoInsert: Iterable> = Iterable.empty(),\n\t\t{ onDidCreateNode, onDidDeleteNode, diffIdentityProvider }: IIndexTreeModelSpliceOptions,\n\t) {\n\t\tconst { parentNode, listIndex, revealed, visible } = this.getParentNodeWithListIndex(location);\n\t\tconst treeListElementsToInsert: ITreeNode[] = [];\n\t\tconst nodesToInsertIterator = Iterable.map(toInsert, el => this.createTreeNode(el, parentNode, parentNode.visible ? TreeVisibility.Visible : TreeVisibility.Hidden, revealed, treeListElementsToInsert, onDidCreateNode));\n\n\t\tconst lastIndex = location[location.length - 1];\n\t\tconst lastHadChildren = parentNode.children.length > 0;\n\n\t\t// figure out what's the visible child start index right before the\n\t\t// splice point\n\t\tlet visibleChildStartIndex = 0;\n\n\t\tfor (let i = lastIndex; i >= 0 && i < parentNode.children.length; i--) {\n\t\t\tconst child = parentNode.children[i];\n\n\t\t\tif (child.visible) {\n\t\t\t\tvisibleChildStartIndex = child.visibleChildIndex;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tconst nodesToInsert: IIndexTreeNode[] = [];\n\t\tlet insertedVisibleChildrenCount = 0;\n\t\tlet renderNodeCount = 0;\n\n\t\tfor (const child of nodesToInsertIterator) {\n\t\t\tnodesToInsert.push(child);\n\t\t\trenderNodeCount += child.renderNodeCount;\n\n\t\t\tif (child.visible) {\n\t\t\t\tchild.visibleChildIndex = visibleChildStartIndex + insertedVisibleChildrenCount++;\n\t\t\t}\n\t\t}\n\n\t\tconst deletedNodes = splice(parentNode.children, lastIndex, deleteCount, nodesToInsert);\n\n\t\tif (!diffIdentityProvider) {\n\t\t\tparentNode.lastDiffIds = undefined;\n\t\t} else if (parentNode.lastDiffIds) {\n\t\t\tsplice(parentNode.lastDiffIds, lastIndex, deleteCount, nodesToInsert.map(n => diffIdentityProvider.getId(n.element).toString()));\n\t\t} else {\n\t\t\tparentNode.lastDiffIds = parentNode.children.map(n => diffIdentityProvider.getId(n.element).toString());\n\t\t}\n\n\t\t// figure out what is the count of deleted visible children\n\t\tlet deletedVisibleChildrenCount = 0;\n\n\t\tfor (const child of deletedNodes) {\n\t\t\tif (child.visible) {\n\t\t\t\tdeletedVisibleChildrenCount++;\n\t\t\t}\n\t\t}\n\n\t\t// and adjust for all visible children after the splice point\n\t\tif (deletedVisibleChildrenCount !== 0) {\n\t\t\tfor (let i = lastIndex + nodesToInsert.length; i < parentNode.children.length; i++) {\n\t\t\t\tconst child = parentNode.children[i];\n\n\t\t\t\tif (child.visible) {\n\t\t\t\t\tchild.visibleChildIndex -= deletedVisibleChildrenCount;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// update parent's visible children count\n\t\tparentNode.visibleChildrenCount += insertedVisibleChildrenCount - deletedVisibleChildrenCount;\n\n\t\tif (revealed && visible) {\n\t\t\tconst visibleDeleteCount = deletedNodes.reduce((r, node) => r + (node.visible ? node.renderNodeCount : 0), 0);\n\n\t\t\tthis._updateAncestorsRenderNodeCount(parentNode, renderNodeCount - visibleDeleteCount);\n\t\t\tthis.list.splice(listIndex, visibleDeleteCount, treeListElementsToInsert);\n\t\t}\n\n\t\tif (deletedNodes.length > 0 && onDidDeleteNode) {\n\t\t\tconst visit = (node: ITreeNode) => {\n\t\t\t\tonDidDeleteNode(node);\n\t\t\t\tnode.children.forEach(visit);\n\t\t\t};\n\n\t\t\tdeletedNodes.forEach(visit);\n\t\t}\n\n\t\tconst currentlyHasChildren = parentNode.children.length > 0;\n\t\tif (lastHadChildren !== currentlyHasChildren) {\n\t\t\tthis.setCollapsible(location.slice(0, -1), currentlyHasChildren);\n\t\t}\n\n\t\tthis._onDidSplice.fire({ insertedNodes: nodesToInsert, deletedNodes });\n\n\t\tlet node: IIndexTreeNode | undefined = parentNode;\n\n\t\twhile (node) {\n\t\t\tif (node.visibility === TreeVisibility.Recurse) {\n\t\t\t\t// delayed to avoid excessive refiltering, see #135941\n\t\t\t\tthis.refilterDelayer.trigger(() => this.refilter());\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tnode = node.parent;\n\t\t}\n\t}\n\n\trerender(location: number[]): void {\n\t\tif (location.length === 0) {\n\t\t\tthrow new TreeError(this.user, 'Invalid tree location');\n\t\t}\n\n\t\tconst { node, listIndex, revealed } = this.getTreeNodeWithListIndex(location);\n\n\t\tif (node.visible && revealed) {\n\t\t\tthis.list.splice(listIndex, 1, [node]);\n\t\t}\n\t}\n\n\thas(location: number[]): boolean {\n\t\treturn this.hasTreeNode(location);\n\t}\n\n\tgetListIndex(location: number[]): number {\n\t\tconst { listIndex, visible, revealed } = this.getTreeNodeWithListIndex(location);\n\t\treturn visible && revealed ? listIndex : -1;\n\t}\n\n\tgetListRenderCount(location: number[]): number {\n\t\treturn this.getTreeNode(location).renderNodeCount;\n\t}\n\n\tisCollapsible(location: number[]): boolean {\n\t\treturn this.getTreeNode(location).collapsible;\n\t}\n\n\tsetCollapsible(location: number[], collapsible?: boolean): boolean {\n\t\tconst node = this.getTreeNode(location);\n\n\t\tif (typeof collapsible === 'undefined') {\n\t\t\tcollapsible = !node.collapsible;\n\t\t}\n\n\t\tconst update: CollapsibleStateUpdate = { collapsible };\n\t\treturn this.eventBufferer.bufferEvents(() => this._setCollapseState(location, update));\n\t}\n\n\tisCollapsed(location: number[]): boolean {\n\t\treturn this.getTreeNode(location).collapsed;\n\t}\n\n\tsetCollapsed(location: number[], collapsed?: boolean, recursive?: boolean): boolean {\n\t\tconst node = this.getTreeNode(location);\n\n\t\tif (typeof collapsed === 'undefined') {\n\t\t\tcollapsed = !node.collapsed;\n\t\t}\n\n\t\tconst update: CollapsedStateUpdate = { collapsed, recursive: recursive || false };\n\t\treturn this.eventBufferer.bufferEvents(() => this._setCollapseState(location, update));\n\t}\n\n\tprivate _setCollapseState(location: number[], update: CollapseStateUpdate): boolean {\n\t\tconst { node, listIndex, revealed } = this.getTreeNodeWithListIndex(location);\n\n\t\tconst result = this._setListNodeCollapseState(node, listIndex, revealed, update);\n\n\t\tif (node !== this.root && this.autoExpandSingleChildren && result && !isCollapsibleStateUpdate(update) && node.collapsible && !node.collapsed && !update.recursive) {\n\t\t\tlet onlyVisibleChildIndex = -1;\n\n\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\tconst child = node.children[i];\n\n\t\t\t\tif (child.visible) {\n\t\t\t\t\tif (onlyVisibleChildIndex > -1) {\n\t\t\t\t\t\tonlyVisibleChildIndex = -1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tonlyVisibleChildIndex = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (onlyVisibleChildIndex > -1) {\n\t\t\t\tthis._setCollapseState([...location, onlyVisibleChildIndex], update);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate _setListNodeCollapseState(node: IIndexTreeNode, listIndex: number, revealed: boolean, update: CollapseStateUpdate): boolean {\n\t\tconst result = this._setNodeCollapseState(node, update, false);\n\n\t\tif (!revealed || !node.visible || !result) {\n\t\t\treturn result;\n\t\t}\n\n\t\tconst previousRenderNodeCount = node.renderNodeCount;\n\t\tconst toInsert = this.updateNodeAfterCollapseChange(node);\n\t\tconst deleteCount = previousRenderNodeCount - (listIndex === -1 ? 0 : 1);\n\t\tthis.list.splice(listIndex + 1, deleteCount, toInsert.slice(1));\n\n\t\treturn result;\n\t}\n\n\tprivate _setNodeCollapseState(node: IIndexTreeNode, update: CollapseStateUpdate, deep: boolean): boolean {\n\t\tlet result: boolean;\n\n\t\tif (node === this.root) {\n\t\t\tresult = false;\n\t\t} else {\n\t\t\tif (isCollapsibleStateUpdate(update)) {\n\t\t\t\tresult = node.collapsible !== update.collapsible;\n\t\t\t\tnode.collapsible = update.collapsible;\n\t\t\t} else if (!node.collapsible) {\n\t\t\t\tresult = false;\n\t\t\t} else {\n\t\t\t\tresult = node.collapsed !== update.collapsed;\n\t\t\t\tnode.collapsed = update.collapsed;\n\t\t\t}\n\n\t\t\tif (result) {\n\t\t\t\tthis._onDidChangeCollapseState.fire({ node, deep });\n\t\t\t}\n\t\t}\n\n\t\tif (!isCollapsibleStateUpdate(update) && update.recursive) {\n\t\t\tfor (const child of node.children) {\n\t\t\t\tresult = this._setNodeCollapseState(child, update, true) || result;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\texpandTo(location: number[]): void {\n\t\tthis.eventBufferer.bufferEvents(() => {\n\t\t\tlet node = this.getTreeNode(location);\n\n\t\t\twhile (node.parent) {\n\t\t\t\tnode = node.parent;\n\t\t\t\tlocation = location.slice(0, location.length - 1);\n\n\t\t\t\tif (node.collapsed) {\n\t\t\t\t\tthis._setCollapseState(location, { collapsed: false, recursive: false });\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\trefilter(): void {\n\t\tconst previousRenderNodeCount = this.root.renderNodeCount;\n\t\tconst toInsert = this.updateNodeAfterFilterChange(this.root);\n\t\tthis.list.splice(0, previousRenderNodeCount, toInsert);\n\t\tthis.refilterDelayer.cancel();\n\t}\n\n\tprivate createTreeNode(\n\t\ttreeElement: ITreeElement,\n\t\tparent: IIndexTreeNode,\n\t\tparentVisibility: TreeVisibility,\n\t\trevealed: boolean,\n\t\ttreeListElements: ITreeNode[],\n\t\tonDidCreateNode?: (node: ITreeNode) => void\n\t): IIndexTreeNode {\n\t\tconst node: IIndexTreeNode = {\n\t\t\tparent,\n\t\t\telement: treeElement.element,\n\t\t\tchildren: [],\n\t\t\tdepth: parent.depth + 1,\n\t\t\tvisibleChildrenCount: 0,\n\t\t\tvisibleChildIndex: -1,\n\t\t\tcollapsible: typeof treeElement.collapsible === 'boolean' ? treeElement.collapsible : (typeof treeElement.collapsed !== 'undefined'),\n\t\t\tcollapsed: typeof treeElement.collapsed === 'undefined' ? this.collapseByDefault : treeElement.collapsed,\n\t\t\trenderNodeCount: 1,\n\t\t\tvisibility: TreeVisibility.Visible,\n\t\t\tvisible: true,\n\t\t\tfilterData: undefined\n\t\t};\n\n\t\tconst visibility = this._filterNode(node, parentVisibility);\n\t\tnode.visibility = visibility;\n\n\t\tif (revealed) {\n\t\t\ttreeListElements.push(node);\n\t\t}\n\n\t\tconst childElements = treeElement.children || Iterable.empty();\n\t\tconst childRevealed = revealed && visibility !== TreeVisibility.Hidden && !node.collapsed;\n\t\tconst childNodes = Iterable.map(childElements, el => this.createTreeNode(el, node, visibility, childRevealed, treeListElements, onDidCreateNode));\n\n\t\tlet visibleChildrenCount = 0;\n\t\tlet renderNodeCount = 1;\n\n\t\tfor (const child of childNodes) {\n\t\t\tnode.children.push(child);\n\t\t\trenderNodeCount += child.renderNodeCount;\n\n\t\t\tif (child.visible) {\n\t\t\t\tchild.visibleChildIndex = visibleChildrenCount++;\n\t\t\t}\n\t\t}\n\n\t\tnode.collapsible = node.collapsible || node.children.length > 0;\n\t\tnode.visibleChildrenCount = visibleChildrenCount;\n\t\tnode.visible = visibility === TreeVisibility.Recurse ? visibleChildrenCount > 0 : (visibility === TreeVisibility.Visible);\n\n\t\tif (!node.visible) {\n\t\t\tnode.renderNodeCount = 0;\n\n\t\t\tif (revealed) {\n\t\t\t\ttreeListElements.pop();\n\t\t\t}\n\t\t} else if (!node.collapsed) {\n\t\t\tnode.renderNodeCount = renderNodeCount;\n\t\t}\n\n\t\tif (onDidCreateNode) {\n\t\t\tonDidCreateNode(node);\n\t\t}\n\n\t\treturn node;\n\t}\n\n\tprivate updateNodeAfterCollapseChange(node: IIndexTreeNode): ITreeNode[] {\n\t\tconst previousRenderNodeCount = node.renderNodeCount;\n\t\tconst result: ITreeNode[] = [];\n\n\t\tthis._updateNodeAfterCollapseChange(node, result);\n\t\tthis._updateAncestorsRenderNodeCount(node.parent, result.length - previousRenderNodeCount);\n\n\t\treturn result;\n\t}\n\n\tprivate _updateNodeAfterCollapseChange(node: IIndexTreeNode, result: ITreeNode[]): number {\n\t\tif (node.visible === false) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tresult.push(node);\n\t\tnode.renderNodeCount = 1;\n\n\t\tif (!node.collapsed) {\n\t\t\tfor (const child of node.children) {\n\t\t\t\tnode.renderNodeCount += this._updateNodeAfterCollapseChange(child, result);\n\t\t\t}\n\t\t}\n\n\t\tthis._onDidChangeRenderNodeCount.fire(node);\n\t\treturn node.renderNodeCount;\n\t}\n\n\tprivate updateNodeAfterFilterChange(node: IIndexTreeNode): ITreeNode[] {\n\t\tconst previousRenderNodeCount = node.renderNodeCount;\n\t\tconst result: ITreeNode[] = [];\n\n\t\tthis._updateNodeAfterFilterChange(node, node.visible ? TreeVisibility.Visible : TreeVisibility.Hidden, result);\n\t\tthis._updateAncestorsRenderNodeCount(node.parent, result.length - previousRenderNodeCount);\n\n\t\treturn result;\n\t}\n\n\tprivate _updateNodeAfterFilterChange(node: IIndexTreeNode, parentVisibility: TreeVisibility, result: ITreeNode[], revealed = true): boolean {\n\t\tlet visibility: TreeVisibility;\n\n\t\tif (node !== this.root) {\n\t\t\tvisibility = this._filterNode(node, parentVisibility);\n\n\t\t\tif (visibility === TreeVisibility.Hidden) {\n\t\t\t\tnode.visible = false;\n\t\t\t\tnode.renderNodeCount = 0;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (revealed) {\n\t\t\t\tresult.push(node);\n\t\t\t}\n\t\t}\n\n\t\tconst resultStartLength = result.length;\n\t\tnode.renderNodeCount = node === this.root ? 0 : 1;\n\n\t\tlet hasVisibleDescendants = false;\n\t\tif (!node.collapsed || visibility! !== TreeVisibility.Hidden) {\n\t\t\tlet visibleChildIndex = 0;\n\n\t\t\tfor (const child of node.children) {\n\t\t\t\thasVisibleDescendants = this._updateNodeAfterFilterChange(child, visibility!, result, revealed && !node.collapsed) || hasVisibleDescendants;\n\n\t\t\t\tif (child.visible) {\n\t\t\t\t\tchild.visibleChildIndex = visibleChildIndex++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnode.visibleChildrenCount = visibleChildIndex;\n\t\t} else {\n\t\t\tnode.visibleChildrenCount = 0;\n\t\t}\n\n\t\tif (node !== this.root) {\n\t\t\tnode.visible = visibility! === TreeVisibility.Recurse ? hasVisibleDescendants : (visibility! === TreeVisibility.Visible);\n\t\t\tnode.visibility = visibility!;\n\t\t}\n\n\t\tif (!node.visible) {\n\t\t\tnode.renderNodeCount = 0;\n\n\t\t\tif (revealed) {\n\t\t\t\tresult.pop();\n\t\t\t}\n\t\t} else if (!node.collapsed) {\n\t\t\tnode.renderNodeCount += result.length - resultStartLength;\n\t\t}\n\n\t\tthis._onDidChangeRenderNodeCount.fire(node);\n\t\treturn node.visible;\n\t}\n\n\tprivate _updateAncestorsRenderNodeCount(node: IIndexTreeNode | undefined, diff: number): void {\n\t\tif (diff === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\twhile (node) {\n\t\t\tnode.renderNodeCount += diff;\n\t\t\tthis._onDidChangeRenderNodeCount.fire(node);\n\t\t\tnode = node.parent;\n\t\t}\n\t}\n\n\tprivate _filterNode(node: IIndexTreeNode, parentVisibility: TreeVisibility): TreeVisibility {\n\t\tconst result = this.filter ? this.filter.filter(node.element, parentVisibility) : TreeVisibility.Visible;\n\n\t\tif (typeof result === 'boolean') {\n\t\t\tnode.filterData = undefined;\n\t\t\treturn result ? TreeVisibility.Visible : TreeVisibility.Hidden;\n\t\t} else if (isFilterResult(result)) {\n\t\t\tnode.filterData = result.data;\n\t\t\treturn getVisibleState(result.visibility);\n\t\t} else {\n\t\t\tnode.filterData = undefined;\n\t\t\treturn getVisibleState(result);\n\t\t}\n\t}\n\n\t// cheap\n\tprivate hasTreeNode(location: number[], node: IIndexTreeNode = this.root): boolean {\n\t\tif (!location || location.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst [index, ...rest] = location;\n\n\t\tif (index < 0 || index > node.children.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.hasTreeNode(rest, node.children[index]);\n\t}\n\n\t// cheap\n\tprivate getTreeNode(location: number[], node: IIndexTreeNode = this.root): IIndexTreeNode {\n\t\tif (!location || location.length === 0) {\n\t\t\treturn node;\n\t\t}\n\n\t\tconst [index, ...rest] = location;\n\n\t\tif (index < 0 || index > node.children.length) {\n\t\t\tthrow new TreeError(this.user, 'Invalid tree location');\n\t\t}\n\n\t\treturn this.getTreeNode(rest, node.children[index]);\n\t}\n\n\t// expensive\n\tprivate getTreeNodeWithListIndex(location: number[]): { node: IIndexTreeNode, listIndex: number, revealed: boolean, visible: boolean } {\n\t\tif (location.length === 0) {\n\t\t\treturn { node: this.root, listIndex: -1, revealed: true, visible: false };\n\t\t}\n\n\t\tconst { parentNode, listIndex, revealed, visible } = this.getParentNodeWithListIndex(location);\n\t\tconst index = location[location.length - 1];\n\n\t\tif (index < 0 || index > parentNode.children.length) {\n\t\t\tthrow new TreeError(this.user, 'Invalid tree location');\n\t\t}\n\n\t\tconst node = parentNode.children[index];\n\n\t\treturn { node, listIndex, revealed, visible: visible && node.visible };\n\t}\n\n\tprivate getParentNodeWithListIndex(location: number[], node: IIndexTreeNode = this.root, listIndex: number = 0, revealed = true, visible = true): { parentNode: IIndexTreeNode; listIndex: number; revealed: boolean; visible: boolean; } {\n\t\tconst [index, ...rest] = location;\n\n\t\tif (index < 0 || index > node.children.length) {\n\t\t\tthrow new TreeError(this.user, 'Invalid tree location');\n\t\t}\n\n\t\t// TODO@joao perf!\n\t\tfor (let i = 0; i < index; i++) {\n\t\t\tlistIndex += node.children[i].renderNodeCount;\n\t\t}\n\n\t\trevealed = revealed && !node.collapsed;\n\t\tvisible = visible && node.visible;\n\n\t\tif (rest.length === 0) {\n\t\t\treturn { parentNode: node, listIndex, revealed, visible };\n\t\t}\n\n\t\treturn this.getParentNodeWithListIndex(rest, node.children[index], listIndex + 1, revealed, visible);\n\t}\n\n\tgetNode(location: number[] = []): ITreeNode {\n\t\treturn this.getTreeNode(location);\n\t}\n\n\t// TODO@joao perf!\n\tgetNodeLocation(node: ITreeNode): number[] {\n\t\tconst location: number[] = [];\n\t\tlet indexTreeNode = node as IIndexTreeNode; // typing woes\n\n\t\twhile (indexTreeNode.parent) {\n\t\t\tlocation.push(indexTreeNode.parent.children.indexOf(indexTreeNode));\n\t\t\tindexTreeNode = indexTreeNode.parent;\n\t\t}\n\n\t\treturn location.reverse();\n\t}\n\n\tgetParentNodeLocation(location: number[]): number[] | undefined {\n\t\tif (location.length === 0) {\n\t\t\treturn undefined;\n\t\t} else if (location.length === 1) {\n\t\t\treturn [];\n\t\t} else {\n\t\t\treturn tail2(location)[0];\n\t\t}\n\t}\n\n\tgetFirstElementChild(location: number[]): T | undefined {\n\t\tconst node = this.getTreeNode(location);\n\n\t\tif (node.children.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn node.children[0].element;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IIdentityProvider } from 'vs/base/browser/ui/list/list';\nimport { IIndexTreeModelOptions, IIndexTreeModelSpliceOptions, IList, IndexTreeModel } from 'vs/base/browser/ui/tree/indexTreeModel';\nimport { ICollapseStateChangeEvent, ITreeElement, ITreeModel, ITreeModelSpliceEvent, ITreeNode, ITreeSorter, TreeError } from 'vs/base/browser/ui/tree/tree';\nimport { Event } from 'vs/base/common/event';\nimport { Iterable } from 'vs/base/common/iterator';\n\nexport interface IObjectTreeModel, TFilterData extends NonNullable = void> extends ITreeModel {\n\tsetChildren(element: T | null, children: Iterable> | undefined, options?: IObjectTreeModelSetChildrenOptions): void;\n}\n\nexport interface IObjectTreeModelSetChildrenOptions extends IIndexTreeModelSpliceOptions {\n}\n\nexport interface IObjectTreeModelOptions extends IIndexTreeModelOptions {\n\treadonly sorter?: ITreeSorter;\n\treadonly identityProvider?: IIdentityProvider;\n}\n\nexport class ObjectTreeModel, TFilterData extends NonNullable = void> implements IObjectTreeModel {\n\n\treadonly rootRef = null;\n\n\tprivate model: IndexTreeModel;\n\tprivate nodes = new Map>();\n\tprivate readonly nodesByIdentity = new Map>();\n\tprivate readonly identityProvider?: IIdentityProvider;\n\tprivate sorter?: ITreeSorter<{ element: T; }>;\n\n\treadonly onDidSplice: Event>;\n\treadonly onDidChangeCollapseState: Event>;\n\treadonly onDidChangeRenderNodeCount: Event>;\n\n\tconstructor(\n\t\tprivate user: string,\n\t\tlist: IList>,\n\t\toptions: IObjectTreeModelOptions = {}\n\t) {\n\t\tthis.model = new IndexTreeModel(user, list, null, options);\n\t\tthis.onDidSplice = this.model.onDidSplice;\n\t\tthis.onDidChangeCollapseState = this.model.onDidChangeCollapseState as Event>;\n\t\tthis.onDidChangeRenderNodeCount = this.model.onDidChangeRenderNodeCount as Event>;\n\n\t\tif (options.sorter) {\n\t\t\tthis.sorter = {\n\t\t\t\tcompare(a, b) {\n\t\t\t\t\treturn options.sorter!.compare(a.element, b.element);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tthis.identityProvider = options.identityProvider;\n\t}\n\n\tsetChildren(\n\t\telement: T | null,\n\t\tchildren: Iterable> = Iterable.empty(),\n\t\toptions: IObjectTreeModelSetChildrenOptions = {},\n\t): void {\n\t\tconst location = this.getElementLocation(element);\n\t\tthis._setChildren(location, this.preserveCollapseState(children), options);\n\t}\n\n\tprivate _setChildren(\n\t\tlocation: number[],\n\t\tchildren: Iterable> = Iterable.empty(),\n\t\toptions: IObjectTreeModelSetChildrenOptions,\n\t): void {\n\t\tconst insertedElements = new Set();\n\t\tconst insertedElementIds = new Set();\n\n\t\tconst onDidCreateNode = (node: ITreeNode) => {\n\t\t\tif (node.element === null) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst tnode = node as ITreeNode;\n\n\t\t\tinsertedElements.add(tnode.element);\n\t\t\tthis.nodes.set(tnode.element, tnode);\n\n\t\t\tif (this.identityProvider) {\n\t\t\t\tconst id = this.identityProvider.getId(tnode.element).toString();\n\t\t\t\tinsertedElementIds.add(id);\n\t\t\t\tthis.nodesByIdentity.set(id, tnode);\n\t\t\t}\n\n\t\t\toptions.onDidCreateNode?.(tnode);\n\t\t};\n\n\t\tconst onDidDeleteNode = (node: ITreeNode) => {\n\t\t\tif (node.element === null) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst tnode = node as ITreeNode;\n\n\t\t\tif (!insertedElements.has(tnode.element)) {\n\t\t\t\tthis.nodes.delete(tnode.element);\n\t\t\t}\n\n\t\t\tif (this.identityProvider) {\n\t\t\t\tconst id = this.identityProvider.getId(tnode.element).toString();\n\t\t\t\tif (!insertedElementIds.has(id)) {\n\t\t\t\t\tthis.nodesByIdentity.delete(id);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toptions.onDidDeleteNode?.(tnode);\n\t\t};\n\n\t\tthis.model.splice(\n\t\t\t[...location, 0],\n\t\t\tNumber.MAX_VALUE,\n\t\t\tchildren,\n\t\t\t{ ...options, onDidCreateNode, onDidDeleteNode }\n\t\t);\n\t}\n\n\tprivate preserveCollapseState(elements: Iterable> = Iterable.empty()): Iterable> {\n\t\tif (this.sorter) {\n\t\t\telements = [...elements].sort(this.sorter.compare.bind(this.sorter));\n\t\t}\n\n\t\treturn Iterable.map(elements, treeElement => {\n\t\t\tlet node = this.nodes.get(treeElement.element);\n\n\t\t\tif (!node && this.identityProvider) {\n\t\t\t\tconst id = this.identityProvider.getId(treeElement.element).toString();\n\t\t\t\tnode = this.nodesByIdentity.get(id);\n\t\t\t}\n\n\t\t\tif (!node) {\n\t\t\t\treturn {\n\t\t\t\t\t...treeElement,\n\t\t\t\t\tchildren: this.preserveCollapseState(treeElement.children)\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst collapsible = typeof treeElement.collapsible === 'boolean' ? treeElement.collapsible : node.collapsible;\n\t\t\tconst collapsed = typeof treeElement.collapsed !== 'undefined' ? treeElement.collapsed : node.collapsed;\n\n\t\t\treturn {\n\t\t\t\t...treeElement,\n\t\t\t\tcollapsible,\n\t\t\t\tcollapsed,\n\t\t\t\tchildren: this.preserveCollapseState(treeElement.children)\n\t\t\t};\n\t\t});\n\t}\n\n\trerender(element: T | null): void {\n\t\tconst location = this.getElementLocation(element);\n\t\tthis.model.rerender(location);\n\t}\n\n\tgetFirstElementChild(ref: T | null = null): T | null | undefined {\n\t\tconst location = this.getElementLocation(ref);\n\t\treturn this.model.getFirstElementChild(location);\n\t}\n\n\thas(element: T | null): boolean {\n\t\treturn this.nodes.has(element);\n\t}\n\n\tgetListIndex(element: T | null): number {\n\t\tconst location = this.getElementLocation(element);\n\t\treturn this.model.getListIndex(location);\n\t}\n\n\tgetListRenderCount(element: T | null): number {\n\t\tconst location = this.getElementLocation(element);\n\t\treturn this.model.getListRenderCount(location);\n\t}\n\n\tisCollapsible(element: T | null): boolean {\n\t\tconst location = this.getElementLocation(element);\n\t\treturn this.model.isCollapsible(location);\n\t}\n\n\tsetCollapsible(element: T | null, collapsible?: boolean): boolean {\n\t\tconst location = this.getElementLocation(element);\n\t\treturn this.model.setCollapsible(location, collapsible);\n\t}\n\n\tisCollapsed(element: T | null): boolean {\n\t\tconst location = this.getElementLocation(element);\n\t\treturn this.model.isCollapsed(location);\n\t}\n\n\tsetCollapsed(element: T | null, collapsed?: boolean, recursive?: boolean): boolean {\n\t\tconst location = this.getElementLocation(element);\n\t\treturn this.model.setCollapsed(location, collapsed, recursive);\n\t}\n\n\texpandTo(element: T | null): void {\n\t\tconst location = this.getElementLocation(element);\n\t\tthis.model.expandTo(location);\n\t}\n\n\trefilter(): void {\n\t\tthis.model.refilter();\n\t}\n\n\tgetNode(element: T | null = null): ITreeNode {\n\t\tif (element === null) {\n\t\t\treturn this.model.getNode(this.model.rootRef);\n\t\t}\n\n\t\tconst node = this.nodes.get(element);\n\n\t\tif (!node) {\n\t\t\tthrow new TreeError(this.user, `Tree element not found: ${element}`);\n\t\t}\n\n\t\treturn node;\n\t}\n\n\tgetNodeLocation(node: ITreeNode): T | null {\n\t\treturn node.element;\n\t}\n\n\tgetParentNodeLocation(element: T | null): T | null {\n\t\tif (element === null) {\n\t\t\tthrow new TreeError(this.user, `Invalid getParentNodeLocation call`);\n\t\t}\n\n\t\tconst node = this.nodes.get(element);\n\n\t\tif (!node) {\n\t\t\tthrow new TreeError(this.user, `Tree element not found: ${element}`);\n\t\t}\n\n\t\tconst location = this.model.getNodeLocation(node);\n\t\tconst parentLocation = this.model.getParentNodeLocation(location);\n\t\tconst parent = this.model.getNode(parentLocation);\n\n\t\treturn parent.element;\n\t}\n\n\tprivate getElementLocation(element: T | null): number[] {\n\t\tif (element === null) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst node = this.nodes.get(element);\n\n\t\tif (!node) {\n\t\t\tthrow new TreeError(this.user, `Tree element not found: ${element}`);\n\t\t}\n\n\t\treturn this.model.getNodeLocation(node);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IIdentityProvider } from 'vs/base/browser/ui/list/list';\nimport { IIndexTreeModelSpliceOptions, IList } from 'vs/base/browser/ui/tree/indexTreeModel';\nimport { IObjectTreeModel, IObjectTreeModelOptions, IObjectTreeModelSetChildrenOptions, ObjectTreeModel } from 'vs/base/browser/ui/tree/objectTreeModel';\nimport { ICollapseStateChangeEvent, ITreeElement, ITreeModel, ITreeModelSpliceEvent, ITreeNode, TreeError, TreeFilterResult, TreeVisibility, WeakMapper } from 'vs/base/browser/ui/tree/tree';\nimport { Event } from 'vs/base/common/event';\nimport { Iterable } from 'vs/base/common/iterator';\n\n// Exported only for test reasons, do not use directly\nexport interface ICompressedTreeElement extends ITreeElement {\n\treadonly children?: Iterable>;\n\treadonly incompressible?: boolean;\n}\n\n// Exported only for test reasons, do not use directly\nexport interface ICompressedTreeNode {\n\treadonly elements: T[];\n\treadonly incompressible: boolean;\n}\n\nfunction noCompress(element: ICompressedTreeElement): ITreeElement> {\n\tconst elements = [element.element];\n\tconst incompressible = element.incompressible || false;\n\n\treturn {\n\t\telement: { elements, incompressible },\n\t\tchildren: Iterable.map(Iterable.from(element.children), noCompress),\n\t\tcollapsible: element.collapsible,\n\t\tcollapsed: element.collapsed\n\t};\n}\n\n// Exported only for test reasons, do not use directly\nexport function compress(element: ICompressedTreeElement): ITreeElement> {\n\tconst elements = [element.element];\n\tconst incompressible = element.incompressible || false;\n\n\tlet childrenIterator: Iterable>;\n\tlet children: ICompressedTreeElement[];\n\n\twhile (true) {\n\t\t[children, childrenIterator] = Iterable.consume(Iterable.from(element.children), 2);\n\n\t\tif (children.length !== 1) {\n\t\t\tbreak;\n\t\t}\n\n\t\tif (children[0].incompressible) {\n\t\t\tbreak;\n\t\t}\n\n\t\telement = children[0];\n\t\telements.push(element.element);\n\t}\n\n\treturn {\n\t\telement: { elements, incompressible },\n\t\tchildren: Iterable.map(Iterable.concat(children, childrenIterator), compress),\n\t\tcollapsible: element.collapsible,\n\t\tcollapsed: element.collapsed\n\t};\n}\n\nfunction _decompress(element: ITreeElement>, index = 0): ICompressedTreeElement {\n\tlet children: Iterable>;\n\n\tif (index < element.element.elements.length - 1) {\n\t\tchildren = [_decompress(element, index + 1)];\n\t} else {\n\t\tchildren = Iterable.map(Iterable.from(element.children), el => _decompress(el, 0));\n\t}\n\n\tif (index === 0 && element.element.incompressible) {\n\t\treturn {\n\t\t\telement: element.element.elements[index],\n\t\t\tchildren,\n\t\t\tincompressible: true,\n\t\t\tcollapsible: element.collapsible,\n\t\t\tcollapsed: element.collapsed\n\t\t};\n\t}\n\n\treturn {\n\t\telement: element.element.elements[index],\n\t\tchildren,\n\t\tcollapsible: element.collapsible,\n\t\tcollapsed: element.collapsed\n\t};\n}\n\n// Exported only for test reasons, do not use directly\nexport function decompress(element: ITreeElement>): ICompressedTreeElement {\n\treturn _decompress(element, 0);\n}\n\nfunction splice(treeElement: ICompressedTreeElement, element: T, children: Iterable>): ICompressedTreeElement {\n\tif (treeElement.element === element) {\n\t\treturn { ...treeElement, children };\n\t}\n\n\treturn { ...treeElement, children: Iterable.map(Iterable.from(treeElement.children), e => splice(e, element, children)) };\n}\n\ninterface ICompressedObjectTreeModelOptions extends IObjectTreeModelOptions, TFilterData> {\n\treadonly compressionEnabled?: boolean;\n}\n\nconst wrapIdentityProvider = (base: IIdentityProvider): IIdentityProvider> => ({\n\tgetId(node) {\n\t\treturn node.elements.map(e => base.getId(e).toString()).join('\\0');\n\t}\n});\n\n// Exported only for test reasons, do not use directly\nexport class CompressedObjectTreeModel, TFilterData extends NonNullable = void> implements ITreeModel | null, TFilterData, T | null> {\n\n\treadonly rootRef = null;\n\n\tget onDidSplice(): Event | null, TFilterData>> { return this.model.onDidSplice; }\n\tget onDidChangeCollapseState(): Event, TFilterData>> { return this.model.onDidChangeCollapseState; }\n\tget onDidChangeRenderNodeCount(): Event, TFilterData>> { return this.model.onDidChangeRenderNodeCount; }\n\n\tprivate model: ObjectTreeModel, TFilterData>;\n\tprivate nodes = new Map>();\n\tprivate enabled: boolean;\n\tprivate readonly identityProvider?: IIdentityProvider>;\n\n\tconstructor(\n\t\tprivate user: string,\n\t\tlist: IList, TFilterData>>,\n\t\toptions: ICompressedObjectTreeModelOptions = {}\n\t) {\n\t\tthis.model = new ObjectTreeModel(user, list, options);\n\t\tthis.enabled = typeof options.compressionEnabled === 'undefined' ? true : options.compressionEnabled;\n\t\tthis.identityProvider = options.identityProvider;\n\t}\n\n\tsetChildren(\n\t\telement: T | null,\n\t\tchildren: Iterable> = Iterable.empty(),\n\t\toptions: IObjectTreeModelSetChildrenOptions,\n\t): void {\n\t\t// Diffs must be deem, since the compression can affect nested elements.\n\t\t// @see https://github.com/microsoft/vscode/pull/114237#issuecomment-759425034\n\n\t\tconst diffIdentityProvider = options.diffIdentityProvider && wrapIdentityProvider(options.diffIdentityProvider);\n\t\tif (element === null) {\n\t\t\tconst compressedChildren = Iterable.map(children, this.enabled ? compress : noCompress);\n\t\t\tthis._setChildren(null, compressedChildren, { diffIdentityProvider, diffDepth: Infinity });\n\t\t\treturn;\n\t\t}\n\n\t\tconst compressedNode = this.nodes.get(element);\n\n\t\tif (!compressedNode) {\n\t\t\tthrow new Error('Unknown compressed tree node');\n\t\t}\n\n\t\tconst node = this.model.getNode(compressedNode) as ITreeNode, TFilterData>;\n\t\tconst compressedParentNode = this.model.getParentNodeLocation(compressedNode);\n\t\tconst parent = this.model.getNode(compressedParentNode) as ITreeNode, TFilterData>;\n\n\t\tconst decompressedElement = decompress(node);\n\t\tconst splicedElement = splice(decompressedElement, element, children);\n\t\tconst recompressedElement = (this.enabled ? compress : noCompress)(splicedElement);\n\n\t\tconst parentChildren = parent.children\n\t\t\t.map(child => child === node ? recompressedElement : child);\n\n\t\tthis._setChildren(parent.element, parentChildren, {\n\t\t\tdiffIdentityProvider,\n\t\t\tdiffDepth: node.depth - parent.depth,\n\t\t});\n\t}\n\n\tsetCompressionEnabled(enabled: boolean): void {\n\t\tif (enabled === this.enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.enabled = enabled;\n\n\t\tconst root = this.model.getNode();\n\t\tconst rootChildren = root.children as ITreeNode>[];\n\t\tconst decompressedRootChildren = Iterable.map(rootChildren, decompress);\n\t\tconst recompressedRootChildren = Iterable.map(decompressedRootChildren, enabled ? compress : noCompress);\n\n\t\t// it should be safe to always use deep diff mode here if an identity\n\t\t// provider is available, since we know the raw nodes are unchanged.\n\t\tthis._setChildren(null, recompressedRootChildren, {\n\t\t\tdiffIdentityProvider: this.identityProvider,\n\t\t\tdiffDepth: Infinity,\n\t\t});\n\t}\n\n\tprivate _setChildren(\n\t\tnode: ICompressedTreeNode | null,\n\t\tchildren: Iterable>>,\n\t\toptions: IIndexTreeModelSpliceOptions, TFilterData>,\n\t): void {\n\t\tconst insertedElements = new Set();\n\t\tconst onDidCreateNode = (node: ITreeNode, TFilterData>) => {\n\t\t\tfor (const element of node.element.elements) {\n\t\t\t\tinsertedElements.add(element);\n\t\t\t\tthis.nodes.set(element, node.element);\n\t\t\t}\n\t\t};\n\n\t\tconst onDidDeleteNode = (node: ITreeNode, TFilterData>) => {\n\t\t\tfor (const element of node.element.elements) {\n\t\t\t\tif (!insertedElements.has(element)) {\n\t\t\t\t\tthis.nodes.delete(element);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tthis.model.setChildren(node, children, { ...options, onDidCreateNode, onDidDeleteNode });\n\t}\n\n\thas(element: T | null): boolean {\n\t\treturn this.nodes.has(element);\n\t}\n\n\tgetListIndex(location: T | null): number {\n\t\tconst node = this.getCompressedNode(location);\n\t\treturn this.model.getListIndex(node);\n\t}\n\n\tgetListRenderCount(location: T | null): number {\n\t\tconst node = this.getCompressedNode(location);\n\t\treturn this.model.getListRenderCount(node);\n\t}\n\n\tgetNode(location?: T | null | undefined): ITreeNode | null, TFilterData> {\n\t\tif (typeof location === 'undefined') {\n\t\t\treturn this.model.getNode();\n\t\t}\n\n\t\tconst node = this.getCompressedNode(location);\n\t\treturn this.model.getNode(node);\n\t}\n\n\t// TODO: review this\n\tgetNodeLocation(node: ITreeNode, TFilterData>): T | null {\n\t\tconst compressedNode = this.model.getNodeLocation(node);\n\n\t\tif (compressedNode === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn compressedNode.elements[compressedNode.elements.length - 1];\n\t}\n\n\t// TODO: review this\n\tgetParentNodeLocation(location: T | null): T | null {\n\t\tconst compressedNode = this.getCompressedNode(location);\n\t\tconst parentNode = this.model.getParentNodeLocation(compressedNode);\n\n\t\tif (parentNode === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn parentNode.elements[parentNode.elements.length - 1];\n\t}\n\n\tgetFirstElementChild(location: T | null): ICompressedTreeNode | null | undefined {\n\t\tconst compressedNode = this.getCompressedNode(location);\n\t\treturn this.model.getFirstElementChild(compressedNode);\n\t}\n\n\tisCollapsible(location: T | null): boolean {\n\t\tconst compressedNode = this.getCompressedNode(location);\n\t\treturn this.model.isCollapsible(compressedNode);\n\t}\n\n\tsetCollapsible(location: T | null, collapsible?: boolean): boolean {\n\t\tconst compressedNode = this.getCompressedNode(location);\n\t\treturn this.model.setCollapsible(compressedNode, collapsible);\n\t}\n\n\tisCollapsed(location: T | null): boolean {\n\t\tconst compressedNode = this.getCompressedNode(location);\n\t\treturn this.model.isCollapsed(compressedNode);\n\t}\n\n\tsetCollapsed(location: T | null, collapsed?: boolean | undefined, recursive?: boolean | undefined): boolean {\n\t\tconst compressedNode = this.getCompressedNode(location);\n\t\treturn this.model.setCollapsed(compressedNode, collapsed, recursive);\n\t}\n\n\texpandTo(location: T | null): void {\n\t\tconst compressedNode = this.getCompressedNode(location);\n\t\tthis.model.expandTo(compressedNode);\n\t}\n\n\trerender(location: T | null): void {\n\t\tconst compressedNode = this.getCompressedNode(location);\n\t\tthis.model.rerender(compressedNode);\n\t}\n\n\trefilter(): void {\n\t\tthis.model.refilter();\n\t}\n\n\tgetCompressedNode(element: T | null): ICompressedTreeNode | null {\n\t\tif (element === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst node = this.nodes.get(element);\n\n\t\tif (!node) {\n\t\t\tthrow new TreeError(this.user, `Tree element not found: ${element}`);\n\t\t}\n\n\t\treturn node;\n\t}\n}\n\n// Compressible Object Tree\n\nexport type ElementMapper = (elements: T[]) => T;\nexport const DefaultElementMapper: ElementMapper = elements => elements[elements.length - 1];\n\nexport type CompressedNodeUnwrapper = (node: ICompressedTreeNode) => T;\ntype CompressedNodeWeakMapper = WeakMapper | null, TFilterData>, ITreeNode>;\n\nclass CompressedTreeNodeWrapper implements ITreeNode {\n\n\tget element(): T | null { return this.node.element === null ? null : this.unwrapper(this.node.element); }\n\tget children(): ITreeNode[] { return this.node.children.map(node => new CompressedTreeNodeWrapper(this.unwrapper, node)); }\n\tget depth(): number { return this.node.depth; }\n\tget visibleChildrenCount(): number { return this.node.visibleChildrenCount; }\n\tget visibleChildIndex(): number { return this.node.visibleChildIndex; }\n\tget collapsible(): boolean { return this.node.collapsible; }\n\tget collapsed(): boolean { return this.node.collapsed; }\n\tget visible(): boolean { return this.node.visible; }\n\tget filterData(): TFilterData | undefined { return this.node.filterData; }\n\n\tconstructor(\n\t\tprivate unwrapper: CompressedNodeUnwrapper,\n\t\tprivate node: ITreeNode | null, TFilterData>\n\t) { }\n}\n\nfunction mapList(nodeMapper: CompressedNodeWeakMapper, list: IList>): IList, TFilterData>> {\n\treturn {\n\t\tsplice(start: number, deleteCount: number, toInsert: ITreeNode, TFilterData>[]): void {\n\t\t\tlist.splice(start, deleteCount, toInsert.map(node => nodeMapper.map(node)) as ITreeNode[]);\n\t\t},\n\t\tupdateElementHeight(index: number, height: number): void {\n\t\t\tlist.updateElementHeight(index, height);\n\t\t}\n\t};\n}\n\nfunction mapOptions(compressedNodeUnwrapper: CompressedNodeUnwrapper, options: ICompressibleObjectTreeModelOptions): ICompressedObjectTreeModelOptions {\n\treturn {\n\t\t...options,\n\t\tidentityProvider: options.identityProvider && {\n\t\t\tgetId(node: ICompressedTreeNode): { toString(): string; } {\n\t\t\t\treturn options.identityProvider!.getId(compressedNodeUnwrapper(node));\n\t\t\t}\n\t\t},\n\t\tsorter: options.sorter && {\n\t\t\tcompare(node: ICompressedTreeNode, otherNode: ICompressedTreeNode): number {\n\t\t\t\treturn options.sorter!.compare(node.elements[0], otherNode.elements[0]);\n\t\t\t}\n\t\t},\n\t\tfilter: options.filter && {\n\t\t\tfilter(node: ICompressedTreeNode, parentVisibility: TreeVisibility): TreeFilterResult {\n\t\t\t\treturn options.filter!.filter(compressedNodeUnwrapper(node), parentVisibility);\n\t\t\t}\n\t\t}\n\t};\n}\n\nexport interface ICompressibleObjectTreeModelOptions extends IObjectTreeModelOptions {\n\treadonly elementMapper?: ElementMapper;\n}\n\nexport class CompressibleObjectTreeModel, TFilterData extends NonNullable = void> implements IObjectTreeModel {\n\n\treadonly rootRef = null;\n\n\tget onDidSplice(): Event> {\n\t\treturn Event.map(this.model.onDidSplice, ({ insertedNodes, deletedNodes }) => ({\n\t\t\tinsertedNodes: insertedNodes.map(node => this.nodeMapper.map(node)),\n\t\t\tdeletedNodes: deletedNodes.map(node => this.nodeMapper.map(node)),\n\t\t}));\n\t}\n\n\tget onDidChangeCollapseState(): Event> {\n\t\treturn Event.map(this.model.onDidChangeCollapseState, ({ node, deep }) => ({\n\t\t\tnode: this.nodeMapper.map(node),\n\t\t\tdeep\n\t\t}));\n\t}\n\n\tget onDidChangeRenderNodeCount(): Event> {\n\t\treturn Event.map(this.model.onDidChangeRenderNodeCount, node => this.nodeMapper.map(node));\n\t}\n\n\tprivate elementMapper: ElementMapper;\n\tprivate nodeMapper: CompressedNodeWeakMapper;\n\tprivate model: CompressedObjectTreeModel;\n\n\tconstructor(\n\t\tuser: string,\n\t\tlist: IList>,\n\t\toptions: ICompressibleObjectTreeModelOptions = {}\n\t) {\n\t\tthis.elementMapper = options.elementMapper || DefaultElementMapper;\n\t\tconst compressedNodeUnwrapper: CompressedNodeUnwrapper = node => this.elementMapper(node.elements);\n\t\tthis.nodeMapper = new WeakMapper(node => new CompressedTreeNodeWrapper(compressedNodeUnwrapper, node));\n\n\t\tthis.model = new CompressedObjectTreeModel(user, mapList(this.nodeMapper, list), mapOptions(compressedNodeUnwrapper, options));\n\t}\n\n\tsetChildren(\n\t\telement: T | null,\n\t\tchildren: Iterable> = Iterable.empty(),\n\t\toptions: IObjectTreeModelSetChildrenOptions = {},\n\t): void {\n\t\tthis.model.setChildren(element, children, options);\n\t}\n\n\tsetCompressionEnabled(enabled: boolean): void {\n\t\tthis.model.setCompressionEnabled(enabled);\n\t}\n\n\thas(location: T | null): boolean {\n\t\treturn this.model.has(location);\n\t}\n\n\tgetListIndex(location: T | null): number {\n\t\treturn this.model.getListIndex(location);\n\t}\n\n\tgetListRenderCount(location: T | null): number {\n\t\treturn this.model.getListRenderCount(location);\n\t}\n\n\tgetNode(location?: T | null | undefined): ITreeNode {\n\t\treturn this.nodeMapper.map(this.model.getNode(location));\n\t}\n\n\tgetNodeLocation(node: ITreeNode): T | null {\n\t\treturn node.element;\n\t}\n\n\tgetParentNodeLocation(location: T | null): T | null {\n\t\treturn this.model.getParentNodeLocation(location);\n\t}\n\n\tgetFirstElementChild(location: T | null): T | null | undefined {\n\t\tconst result = this.model.getFirstElementChild(location);\n\n\t\tif (result === null || typeof result === 'undefined') {\n\t\t\treturn result;\n\t\t}\n\n\t\treturn this.elementMapper(result.elements);\n\t}\n\n\tisCollapsible(location: T | null): boolean {\n\t\treturn this.model.isCollapsible(location);\n\t}\n\n\tsetCollapsible(location: T | null, collapsed?: boolean): boolean {\n\t\treturn this.model.setCollapsible(location, collapsed);\n\t}\n\n\tisCollapsed(location: T | null): boolean {\n\t\treturn this.model.isCollapsed(location);\n\t}\n\n\tsetCollapsed(location: T | null, collapsed?: boolean | undefined, recursive?: boolean | undefined): boolean {\n\t\treturn this.model.setCollapsed(location, collapsed, recursive);\n\t}\n\n\texpandTo(location: T | null): void {\n\t\treturn this.model.expandTo(location);\n\t}\n\n\trerender(location: T | null): void {\n\t\treturn this.model.rerender(location);\n\t}\n\n\trefilter(): void {\n\t\treturn this.model.refilter();\n\t}\n\n\tgetCompressedTreeNode(location: T | null = null): ITreeNode | null, TFilterData> {\n\t\treturn this.model.getNode(location);\n\t}\n}\n","\nimport { CharCode } from 'vs/base/common/charCode';\nimport { compare, compareIgnoreCase, compareSubstring, compareSubstringIgnoreCase } from 'vs/base/common/strings';\nimport { URI } from 'vs/base/common/uri';\n\nexport interface IKeyIterator {\n\treset(key: K): this;\n\tnext(): this;\n\n\thasNext(): boolean;\n\tcmp(a: string): number;\n\tvalue(): string;\n}\n\nexport class StringIterator implements IKeyIterator {\n\n\tprivate _value: string = '';\n\tprivate _pos: number = 0;\n\n\treset(key: string): this {\n\t\tthis._value = key;\n\t\tthis._pos = 0;\n\t\treturn this;\n\t}\n\n\tnext(): this {\n\t\tthis._pos += 1;\n\t\treturn this;\n\t}\n\n\thasNext(): boolean {\n\t\treturn this._pos < this._value.length - 1;\n\t}\n\n\tcmp(a: string): number {\n\t\tconst aCode = a.charCodeAt(0);\n\t\tconst thisCode = this._value.charCodeAt(this._pos);\n\t\treturn aCode - thisCode;\n\t}\n\n\tvalue(): string {\n\t\treturn this._value[this._pos];\n\t}\n}\n\nexport class ConfigKeysIterator implements IKeyIterator {\n\n\tprivate _value!: string;\n\tprivate _from!: number;\n\tprivate _to!: number;\n\n\tconstructor(\n\t\tprivate readonly _caseSensitive: boolean = true\n\t) { }\n\n\treset(key: string): this {\n\t\tthis._value = key;\n\t\tthis._from = 0;\n\t\tthis._to = 0;\n\t\treturn this.next();\n\t}\n\n\thasNext(): boolean {\n\t\treturn this._to < this._value.length;\n\t}\n\n\tnext(): this {\n\t\t// this._data = key.split(/[\\\\/]/).filter(s => !!s);\n\t\tthis._from = this._to;\n\t\tlet justSeps = true;\n\t\tfor (; this._to < this._value.length; this._to++) {\n\t\t\tconst ch = this._value.charCodeAt(this._to);\n\t\t\tif (ch === CharCode.Period) {\n\t\t\t\tif (justSeps) {\n\t\t\t\t\tthis._from++;\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tjustSeps = false;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\tcmp(a: string): number {\n\t\treturn this._caseSensitive\n\t\t\t? compareSubstring(a, this._value, 0, a.length, this._from, this._to)\n\t\t\t: compareSubstringIgnoreCase(a, this._value, 0, a.length, this._from, this._to);\n\t}\n\n\tvalue(): string {\n\t\treturn this._value.substring(this._from, this._to);\n\t}\n}\n\nexport class PathIterator implements IKeyIterator {\n\n\tprivate _value!: string;\n\tprivate _valueLen!: number;\n\tprivate _from!: number;\n\tprivate _to!: number;\n\n\tconstructor(\n\t\tprivate readonly _splitOnBackslash: boolean = true,\n\t\tprivate readonly _caseSensitive: boolean = true\n\t) { }\n\n\treset(key: string): this {\n\t\tthis._from = 0;\n\t\tthis._to = 0;\n\t\tthis._value = key;\n\t\tthis._valueLen = key.length;\n\t\tfor (let pos = key.length - 1; pos >= 0; pos--, this._valueLen--) {\n\t\t\tconst ch = this._value.charCodeAt(pos);\n\t\t\tif (!(ch === CharCode.Slash || this._splitOnBackslash && ch === CharCode.Backslash)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn this.next();\n\t}\n\n\thasNext(): boolean {\n\t\treturn this._to < this._valueLen;\n\t}\n\n\tnext(): this {\n\t\t// this._data = key.split(/[\\\\/]/).filter(s => !!s);\n\t\tthis._from = this._to;\n\t\tlet justSeps = true;\n\t\tfor (; this._to < this._valueLen; this._to++) {\n\t\t\tconst ch = this._value.charCodeAt(this._to);\n\t\t\tif (ch === CharCode.Slash || this._splitOnBackslash && ch === CharCode.Backslash) {\n\t\t\t\tif (justSeps) {\n\t\t\t\t\tthis._from++;\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tjustSeps = false;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\tcmp(a: string): number {\n\t\treturn this._caseSensitive\n\t\t\t? compareSubstring(a, this._value, 0, a.length, this._from, this._to)\n\t\t\t: compareSubstringIgnoreCase(a, this._value, 0, a.length, this._from, this._to);\n\t}\n\n\tvalue(): string {\n\t\treturn this._value.substring(this._from, this._to);\n\t}\n}\n\nconst enum UriIteratorState {\n\tScheme = 1, Authority = 2, Path = 3, Query = 4, Fragment = 5\n}\n\nexport class UriIterator implements IKeyIterator {\n\n\tprivate _pathIterator!: PathIterator;\n\tprivate _value!: URI;\n\tprivate _states: UriIteratorState[] = [];\n\tprivate _stateIdx: number = 0;\n\n\tconstructor(private readonly _ignorePathCasing: (uri: URI) => boolean) { }\n\n\treset(key: URI): this {\n\t\tthis._value = key;\n\t\tthis._states = [];\n\t\tif (this._value.scheme) {\n\t\t\tthis._states.push(UriIteratorState.Scheme);\n\t\t}\n\t\tif (this._value.authority) {\n\t\t\tthis._states.push(UriIteratorState.Authority);\n\t\t}\n\t\tif (this._value.path) {\n\t\t\tthis._pathIterator = new PathIterator(false, !this._ignorePathCasing(key));\n\t\t\tthis._pathIterator.reset(key.path);\n\t\t\tif (this._pathIterator.value()) {\n\t\t\t\tthis._states.push(UriIteratorState.Path);\n\t\t\t}\n\t\t}\n\t\tif (this._value.query) {\n\t\t\tthis._states.push(UriIteratorState.Query);\n\t\t}\n\t\tif (this._value.fragment) {\n\t\t\tthis._states.push(UriIteratorState.Fragment);\n\t\t}\n\t\tthis._stateIdx = 0;\n\t\treturn this;\n\t}\n\n\tnext(): this {\n\t\tif (this._states[this._stateIdx] === UriIteratorState.Path && this._pathIterator.hasNext()) {\n\t\t\tthis._pathIterator.next();\n\t\t} else {\n\t\t\tthis._stateIdx += 1;\n\t\t}\n\t\treturn this;\n\t}\n\n\thasNext(): boolean {\n\t\treturn (this._states[this._stateIdx] === UriIteratorState.Path && this._pathIterator.hasNext())\n\t\t\t|| this._stateIdx < this._states.length - 1;\n\t}\n\n\tcmp(a: string): number {\n\t\tif (this._states[this._stateIdx] === UriIteratorState.Scheme) {\n\t\t\treturn compareIgnoreCase(a, this._value.scheme);\n\t\t} else if (this._states[this._stateIdx] === UriIteratorState.Authority) {\n\t\t\treturn compareIgnoreCase(a, this._value.authority);\n\t\t} else if (this._states[this._stateIdx] === UriIteratorState.Path) {\n\t\t\treturn this._pathIterator.cmp(a);\n\t\t} else if (this._states[this._stateIdx] === UriIteratorState.Query) {\n\t\t\treturn compare(a, this._value.query);\n\t\t} else if (this._states[this._stateIdx] === UriIteratorState.Fragment) {\n\t\t\treturn compare(a, this._value.fragment);\n\t\t}\n\t\tthrow new Error();\n\t}\n\n\tvalue(): string {\n\t\tif (this._states[this._stateIdx] === UriIteratorState.Scheme) {\n\t\t\treturn this._value.scheme;\n\t\t} else if (this._states[this._stateIdx] === UriIteratorState.Authority) {\n\t\t\treturn this._value.authority;\n\t\t} else if (this._states[this._stateIdx] === UriIteratorState.Path) {\n\t\t\treturn this._pathIterator.value();\n\t\t} else if (this._states[this._stateIdx] === UriIteratorState.Query) {\n\t\t\treturn this._value.query;\n\t\t} else if (this._states[this._stateIdx] === UriIteratorState.Fragment) {\n\t\t\treturn this._value.fragment;\n\t\t}\n\t\tthrow new Error();\n\t}\n}\n\nclass TernarySearchTreeNode {\n\theight: number = 1;\n\tsegment!: string;\n\tvalue: V | undefined;\n\tkey: K | undefined;\n\tleft: TernarySearchTreeNode | undefined;\n\tmid: TernarySearchTreeNode | undefined;\n\tright: TernarySearchTreeNode | undefined;\n\n\trotateLeft() {\n\t\tconst tmp = this.right!;\n\t\tthis.right = tmp.left;\n\t\ttmp.left = this;\n\t\tthis.updateHeight();\n\t\ttmp.updateHeight();\n\t\treturn tmp;\n\t}\n\n\trotateRight() {\n\t\tconst tmp = this.left!;\n\t\tthis.left = tmp.right;\n\t\ttmp.right = this;\n\t\tthis.updateHeight();\n\t\ttmp.updateHeight();\n\t\treturn tmp;\n\t}\n\n\tupdateHeight() {\n\t\tthis.height = 1 + Math.max(this.heightLeft, this.heightRight);\n\t}\n\n\tbalanceFactor() {\n\t\treturn this.heightRight - this.heightLeft;\n\t}\n\n\tget heightLeft() {\n\t\treturn this.left?.height ?? 0;\n\t}\n\n\tget heightRight() {\n\t\treturn this.right?.height ?? 0;\n\t}\n}\n\nconst enum Dir {\n\tLeft = -1,\n\tMid = 0,\n\tRight = 1,\n}\n\nexport class TernarySearchTree {\n\n\tstatic forUris(ignorePathCasing: (key: URI) => boolean = () => false): TernarySearchTree {\n\t\treturn new TernarySearchTree(new UriIterator(ignorePathCasing));\n\t}\n\n\tstatic forStrings(): TernarySearchTree {\n\t\treturn new TernarySearchTree(new StringIterator());\n\t}\n\n\tstatic forConfigKeys(): TernarySearchTree {\n\t\treturn new TernarySearchTree(new ConfigKeysIterator());\n\t}\n\n\tprivate _iter: IKeyIterator;\n\tprivate _root: TernarySearchTreeNode | undefined;\n\n\tconstructor(segments: IKeyIterator) {\n\t\tthis._iter = segments;\n\t}\n\n\tclear(): void {\n\t\tthis._root = undefined;\n\t}\n\n\tset(key: K, element: V): V | undefined {\n\t\tconst iter = this._iter.reset(key);\n\t\tlet node: TernarySearchTreeNode;\n\n\t\tif (!this._root) {\n\t\t\tthis._root = new TernarySearchTreeNode();\n\t\t\tthis._root.segment = iter.value();\n\t\t}\n\t\tconst stack: [Dir, TernarySearchTreeNode][] = [];\n\n\t\t// find insert_node\n\t\tnode = this._root;\n\t\twhile (true) {\n\t\t\tconst val = iter.cmp(node.segment);\n\t\t\tif (val > 0) {\n\t\t\t\t// left\n\t\t\t\tif (!node.left) {\n\t\t\t\t\tnode.left = new TernarySearchTreeNode();\n\t\t\t\t\tnode.left.segment = iter.value();\n\t\t\t\t}\n\t\t\t\tstack.push([Dir.Left, node]);\n\t\t\t\tnode = node.left;\n\n\t\t\t} else if (val < 0) {\n\t\t\t\t// right\n\t\t\t\tif (!node.right) {\n\t\t\t\t\tnode.right = new TernarySearchTreeNode();\n\t\t\t\t\tnode.right.segment = iter.value();\n\t\t\t\t}\n\t\t\t\tstack.push([Dir.Right, node]);\n\t\t\t\tnode = node.right;\n\n\t\t\t} else if (iter.hasNext()) {\n\t\t\t\t// mid\n\t\t\t\titer.next();\n\t\t\t\tif (!node.mid) {\n\t\t\t\t\tnode.mid = new TernarySearchTreeNode();\n\t\t\t\t\tnode.mid.segment = iter.value();\n\t\t\t\t}\n\t\t\t\tstack.push([Dir.Mid, node]);\n\t\t\t\tnode = node.mid;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// set value\n\t\tconst oldElement = node.value;\n\t\tnode.value = element;\n\t\tnode.key = key;\n\n\t\t// balance\n\t\tfor (let i = stack.length - 1; i >= 0; i--) {\n\t\t\tconst node = stack[i][1];\n\n\t\t\tnode.updateHeight();\n\t\t\tconst bf = node.balanceFactor();\n\n\t\t\tif (bf < -1 || bf > 1) {\n\t\t\t\t// needs rotate\n\t\t\t\tconst d1 = stack[i][0];\n\t\t\t\tconst d2 = stack[i + 1][0];\n\n\t\t\t\tif (d1 === Dir.Right && d2 === Dir.Right) {\n\t\t\t\t\t//right, right -> rotate left\n\t\t\t\t\tstack[i][1] = node.rotateLeft();\n\n\t\t\t\t} else if (d1 === Dir.Left && d2 === Dir.Left) {\n\t\t\t\t\t// left, left -> rotate right\n\t\t\t\t\tstack[i][1] = node.rotateRight();\n\n\t\t\t\t} else if (d1 === Dir.Right && d2 === Dir.Left) {\n\t\t\t\t\t// right, left -> double rotate right, left\n\t\t\t\t\tnode.right = stack[i + 1][1] = stack[i + 1][1].rotateRight();\n\t\t\t\t\tstack[i][1] = node.rotateLeft();\n\n\t\t\t\t} else if (d1 === Dir.Left && d2 === Dir.Right) {\n\t\t\t\t\t// left, right -> double rotate left, right\n\t\t\t\t\tnode.left = stack[i + 1][1] = stack[i + 1][1].rotateLeft();\n\t\t\t\t\tstack[i][1] = node.rotateRight();\n\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error();\n\t\t\t\t}\n\n\t\t\t\t// patch path to parent\n\t\t\t\tif (i > 0) {\n\t\t\t\t\tswitch (stack[i - 1][0]) {\n\t\t\t\t\t\tcase Dir.Left:\n\t\t\t\t\t\t\tstack[i - 1][1].left = stack[i][1];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase Dir.Right:\n\t\t\t\t\t\t\tstack[i - 1][1].right = stack[i][1];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase Dir.Mid:\n\t\t\t\t\t\t\tstack[i - 1][1].mid = stack[i][1];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis._root = stack[0][1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn oldElement;\n\t}\n\n\tget(key: K): V | undefined {\n\t\treturn this._getNode(key)?.value;\n\t}\n\n\tprivate _getNode(key: K) {\n\t\tconst iter = this._iter.reset(key);\n\t\tlet node = this._root;\n\t\twhile (node) {\n\t\t\tconst val = iter.cmp(node.segment);\n\t\t\tif (val > 0) {\n\t\t\t\t// left\n\t\t\t\tnode = node.left;\n\t\t\t} else if (val < 0) {\n\t\t\t\t// right\n\t\t\t\tnode = node.right;\n\t\t\t} else if (iter.hasNext()) {\n\t\t\t\t// mid\n\t\t\t\titer.next();\n\t\t\t\tnode = node.mid;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn node;\n\t}\n\n\thas(key: K): boolean {\n\t\tconst node = this._getNode(key);\n\t\treturn !(node?.value === undefined && node?.mid === undefined);\n\t}\n\n\tdelete(key: K): void {\n\t\treturn this._delete(key, false);\n\t}\n\n\tdeleteSuperstr(key: K): void {\n\t\treturn this._delete(key, true);\n\t}\n\n\tprivate _delete(key: K, superStr: boolean): void {\n\t\tconst iter = this._iter.reset(key);\n\t\tconst stack: [Dir, TernarySearchTreeNode][] = [];\n\t\tlet node = this._root;\n\n\t\t// find node\n\t\twhile (node) {\n\t\t\tconst val = iter.cmp(node.segment);\n\t\t\tif (val > 0) {\n\t\t\t\t// left\n\t\t\t\tstack.push([Dir.Left, node]);\n\t\t\t\tnode = node.left;\n\t\t\t} else if (val < 0) {\n\t\t\t\t// right\n\t\t\t\tstack.push([Dir.Right, node]);\n\t\t\t\tnode = node.right;\n\t\t\t} else if (iter.hasNext()) {\n\t\t\t\t// mid\n\t\t\t\titer.next();\n\t\t\t\tstack.push([Dir.Mid, node]);\n\t\t\t\tnode = node.mid;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!node) {\n\t\t\t// node not found\n\t\t\treturn;\n\t\t}\n\n\t\tif (superStr) {\n\t\t\t// removing children, reset height\n\t\t\tnode.left = undefined;\n\t\t\tnode.mid = undefined;\n\t\t\tnode.right = undefined;\n\t\t\tnode.height = 1;\n\t\t} else {\n\t\t\t// removing element\n\t\t\tnode.key = undefined;\n\t\t\tnode.value = undefined;\n\t\t}\n\n\t\t// BST node removal\n\t\tif (!node.mid && !node.value) {\n\t\t\tif (node.left && node.right) {\n\t\t\t\t// full node\n\t\t\t\tconst min = this._min(node.right);\n\t\t\t\tconst { key, value, segment } = min;\n\t\t\t\tthis._delete(min.key!, false);\n\t\t\t\tnode.key = key;\n\t\t\t\tnode.value = value;\n\t\t\t\tnode.segment = segment;\n\n\t\t\t} else {\n\t\t\t\t// empty or half empty\n\t\t\t\tconst newChild = node.left ?? node.right;\n\t\t\t\tif (stack.length > 0) {\n\t\t\t\t\tconst [dir, parent] = stack[stack.length - 1];\n\t\t\t\t\tswitch (dir) {\n\t\t\t\t\t\tcase Dir.Left: parent.left = newChild; break;\n\t\t\t\t\t\tcase Dir.Mid: parent.mid = newChild; break;\n\t\t\t\t\t\tcase Dir.Right: parent.right = newChild; break;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis._root = newChild;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// AVL balance\n\t\tfor (let i = stack.length - 1; i >= 0; i--) {\n\t\t\tconst node = stack[i][1];\n\n\t\t\tnode.updateHeight();\n\t\t\tconst bf = node.balanceFactor();\n\t\t\tif (bf > 1) {\n\t\t\t\t// right heavy\n\t\t\t\tif (node.right!.balanceFactor() >= 0) {\n\t\t\t\t\t// right, right -> rotate left\n\t\t\t\t\tstack[i][1] = node.rotateLeft();\n\t\t\t\t} else {\n\t\t\t\t\t// right, left -> double rotate\n\t\t\t\t\tnode.right = node.right!.rotateRight();\n\t\t\t\t\tstack[i][1] = node.rotateLeft();\n\t\t\t\t}\n\n\t\t\t} else if (bf < -1) {\n\t\t\t\t// left heavy\n\t\t\t\tif (node.left!.balanceFactor() <= 0) {\n\t\t\t\t\t// left, left -> rotate right\n\t\t\t\t\tstack[i][1] = node.rotateRight();\n\t\t\t\t} else {\n\t\t\t\t\t// left, right -> double rotate\n\t\t\t\t\tnode.left = node.left!.rotateLeft();\n\t\t\t\t\tstack[i][1] = node.rotateRight();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// patch path to parent\n\t\t\tif (i > 0) {\n\t\t\t\tswitch (stack[i - 1][0]) {\n\t\t\t\t\tcase Dir.Left:\n\t\t\t\t\t\tstack[i - 1][1].left = stack[i][1];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Dir.Right:\n\t\t\t\t\t\tstack[i - 1][1].right = stack[i][1];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Dir.Mid:\n\t\t\t\t\t\tstack[i - 1][1].mid = stack[i][1];\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis._root = stack[0][1];\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _min(node: TernarySearchTreeNode): TernarySearchTreeNode {\n\t\twhile (node.left) {\n\t\t\tnode = node.left;\n\t\t}\n\t\treturn node;\n\t}\n\n\tfindSubstr(key: K): V | undefined {\n\t\tconst iter = this._iter.reset(key);\n\t\tlet node = this._root;\n\t\tlet candidate: V | undefined = undefined;\n\t\twhile (node) {\n\t\t\tconst val = iter.cmp(node.segment);\n\t\t\tif (val > 0) {\n\t\t\t\t// left\n\t\t\t\tnode = node.left;\n\t\t\t} else if (val < 0) {\n\t\t\t\t// right\n\t\t\t\tnode = node.right;\n\t\t\t} else if (iter.hasNext()) {\n\t\t\t\t// mid\n\t\t\t\titer.next();\n\t\t\t\tcandidate = node.value || candidate;\n\t\t\t\tnode = node.mid;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn node && node.value || candidate;\n\t}\n\n\tfindSuperstr(key: K): IterableIterator<[K, V]> | undefined {\n\t\tconst iter = this._iter.reset(key);\n\t\tlet node = this._root;\n\t\twhile (node) {\n\t\t\tconst val = iter.cmp(node.segment);\n\t\t\tif (val > 0) {\n\t\t\t\t// left\n\t\t\t\tnode = node.left;\n\t\t\t} else if (val < 0) {\n\t\t\t\t// right\n\t\t\t\tnode = node.right;\n\t\t\t} else if (iter.hasNext()) {\n\t\t\t\t// mid\n\t\t\t\titer.next();\n\t\t\t\tnode = node.mid;\n\t\t\t} else {\n\t\t\t\t// collect\n\t\t\t\tif (!node.mid) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t} else {\n\t\t\t\t\treturn this._entries(node.mid);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tforEach(callback: (value: V, index: K) => any): void {\n\t\tfor (const [key, value] of this) {\n\t\t\tcallback(value, key);\n\t\t}\n\t}\n\n\t*[Symbol.iterator](): IterableIterator<[K, V]> {\n\t\tyield* this._entries(this._root);\n\t}\n\n\tprivate *_entries(node: TernarySearchTreeNode | undefined): IterableIterator<[K, V]> {\n\t\t// DFS\n\t\tif (!node) {\n\t\t\treturn;\n\t\t}\n\t\tif (node.left) {\n\t\t\tyield* this._entries(node.left);\n\t\t}\n\t\tif (node.value) {\n\t\t\tyield [node.key!, node.value];\n\t\t}\n\t\tif (node.mid) {\n\t\t\tyield* this._entries(node.mid);\n\t\t}\n\t\tif (node.right) {\n\t\t\tyield* this._entries(node.right);\n\t\t}\n\t}\n}\n\ninterface ResourceMapKeyFn {\n\t(resource: URI): string;\n}\n\nclass ResourceMapEntry {\n\tconstructor(readonly uri: URI, readonly value: T) { }\n}\n\nexport class ResourceMap implements Map {\n\n\tprivate static readonly defaultToKey = (resource: URI) => resource.toString();\n\n\treadonly [Symbol.toStringTag] = 'ResourceMap';\n\n\tprivate readonly map: Map>;\n\tprivate readonly toKey: ResourceMapKeyFn;\n\n\t/**\n\t *\n\t * @param toKey Custom uri identity function, e.g use an existing `IExtUri#getComparison`-util\n\t */\n\tconstructor(toKey?: ResourceMapKeyFn);\n\n\t/**\n\t *\n\t * @param other Another resource which this maps is created from\n\t * @param toKey Custom uri identity function, e.g use an existing `IExtUri#getComparison`-util\n\t */\n\tconstructor(other?: ResourceMap, toKey?: ResourceMapKeyFn);\n\n\tconstructor(mapOrKeyFn?: ResourceMap | ResourceMapKeyFn, toKey?: ResourceMapKeyFn) {\n\t\tif (mapOrKeyFn instanceof ResourceMap) {\n\t\t\tthis.map = new Map(mapOrKeyFn.map);\n\t\t\tthis.toKey = toKey ?? ResourceMap.defaultToKey;\n\t\t} else {\n\t\t\tthis.map = new Map();\n\t\t\tthis.toKey = mapOrKeyFn ?? ResourceMap.defaultToKey;\n\t\t}\n\t}\n\n\tset(resource: URI, value: T): this {\n\t\tthis.map.set(this.toKey(resource), new ResourceMapEntry(resource, value));\n\t\treturn this;\n\t}\n\n\tget(resource: URI): T | undefined {\n\t\treturn this.map.get(this.toKey(resource))?.value;\n\t}\n\n\thas(resource: URI): boolean {\n\t\treturn this.map.has(this.toKey(resource));\n\t}\n\n\tget size(): number {\n\t\treturn this.map.size;\n\t}\n\n\tclear(): void {\n\t\tthis.map.clear();\n\t}\n\n\tdelete(resource: URI): boolean {\n\t\treturn this.map.delete(this.toKey(resource));\n\t}\n\n\tforEach(clb: (value: T, key: URI, map: Map) => void, thisArg?: any): void {\n\t\tif (typeof thisArg !== 'undefined') {\n\t\t\tclb = clb.bind(thisArg);\n\t\t}\n\t\tfor (let [_, entry] of this.map) {\n\t\t\tclb(entry.value, entry.uri, this);\n\t\t}\n\t}\n\n\t*values(): IterableIterator {\n\t\tfor (let entry of this.map.values()) {\n\t\t\tyield entry.value;\n\t\t}\n\t}\n\n\t*keys(): IterableIterator {\n\t\tfor (let entry of this.map.values()) {\n\t\t\tyield entry.uri;\n\t\t}\n\t}\n\n\t*entries(): IterableIterator<[URI, T]> {\n\t\tfor (let entry of this.map.values()) {\n\t\t\tyield [entry.uri, entry.value];\n\t\t}\n\t}\n\n\t*[Symbol.iterator](): IterableIterator<[URI, T]> {\n\t\tfor (let [, entry] of this.map) {\n\t\t\tyield [entry.uri, entry.value];\n\t\t}\n\t}\n}\n\ninterface Item {\n\tprevious: Item | undefined;\n\tnext: Item | undefined;\n\tkey: K;\n\tvalue: V;\n}\n\nexport const enum Touch {\n\tNone = 0,\n\tAsOld = 1,\n\tAsNew = 2\n}\n\nexport class LinkedMap implements Map {\n\n\treadonly [Symbol.toStringTag] = 'LinkedMap';\n\n\tprivate _map: Map>;\n\tprivate _head: Item | undefined;\n\tprivate _tail: Item | undefined;\n\tprivate _size: number;\n\n\tprivate _state: number;\n\n\tconstructor() {\n\t\tthis._map = new Map>();\n\t\tthis._head = undefined;\n\t\tthis._tail = undefined;\n\t\tthis._size = 0;\n\t\tthis._state = 0;\n\t}\n\n\tclear(): void {\n\t\tthis._map.clear();\n\t\tthis._head = undefined;\n\t\tthis._tail = undefined;\n\t\tthis._size = 0;\n\t\tthis._state++;\n\t}\n\n\tisEmpty(): boolean {\n\t\treturn !this._head && !this._tail;\n\t}\n\n\tget size(): number {\n\t\treturn this._size;\n\t}\n\n\tget first(): V | undefined {\n\t\treturn this._head?.value;\n\t}\n\n\tget last(): V | undefined {\n\t\treturn this._tail?.value;\n\t}\n\n\thas(key: K): boolean {\n\t\treturn this._map.has(key);\n\t}\n\n\tget(key: K, touch: Touch = Touch.None): V | undefined {\n\t\tconst item = this._map.get(key);\n\t\tif (!item) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (touch !== Touch.None) {\n\t\t\tthis.touch(item, touch);\n\t\t}\n\t\treturn item.value;\n\t}\n\n\tset(key: K, value: V, touch: Touch = Touch.None): this {\n\t\tlet item = this._map.get(key);\n\t\tif (item) {\n\t\t\titem.value = value;\n\t\t\tif (touch !== Touch.None) {\n\t\t\t\tthis.touch(item, touch);\n\t\t\t}\n\t\t} else {\n\t\t\titem = { key, value, next: undefined, previous: undefined };\n\t\t\tswitch (touch) {\n\t\t\t\tcase Touch.None:\n\t\t\t\t\tthis.addItemLast(item);\n\t\t\t\t\tbreak;\n\t\t\t\tcase Touch.AsOld:\n\t\t\t\t\tthis.addItemFirst(item);\n\t\t\t\t\tbreak;\n\t\t\t\tcase Touch.AsNew:\n\t\t\t\t\tthis.addItemLast(item);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthis.addItemLast(item);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tthis._map.set(key, item);\n\t\t\tthis._size++;\n\t\t}\n\t\treturn this;\n\t}\n\n\tdelete(key: K): boolean {\n\t\treturn !!this.remove(key);\n\t}\n\n\tremove(key: K): V | undefined {\n\t\tconst item = this._map.get(key);\n\t\tif (!item) {\n\t\t\treturn undefined;\n\t\t}\n\t\tthis._map.delete(key);\n\t\tthis.removeItem(item);\n\t\tthis._size--;\n\t\treturn item.value;\n\t}\n\n\tshift(): V | undefined {\n\t\tif (!this._head && !this._tail) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (!this._head || !this._tail) {\n\t\t\tthrow new Error('Invalid list');\n\t\t}\n\t\tconst item = this._head;\n\t\tthis._map.delete(item.key);\n\t\tthis.removeItem(item);\n\t\tthis._size--;\n\t\treturn item.value;\n\t}\n\n\tforEach(callbackfn: (value: V, key: K, map: LinkedMap) => void, thisArg?: any): void {\n\t\tconst state = this._state;\n\t\tlet current = this._head;\n\t\twhile (current) {\n\t\t\tif (thisArg) {\n\t\t\t\tcallbackfn.bind(thisArg)(current.value, current.key, this);\n\t\t\t} else {\n\t\t\t\tcallbackfn(current.value, current.key, this);\n\t\t\t}\n\t\t\tif (this._state !== state) {\n\t\t\t\tthrow new Error(`LinkedMap got modified during iteration.`);\n\t\t\t}\n\t\t\tcurrent = current.next;\n\t\t}\n\t}\n\n\tkeys(): IterableIterator {\n\t\tconst map = this;\n\t\tconst state = this._state;\n\t\tlet current = this._head;\n\t\tconst iterator: IterableIterator = {\n\t\t\t[Symbol.iterator]() {\n\t\t\t\treturn iterator;\n\t\t\t},\n\t\t\tnext(): IteratorResult {\n\t\t\t\tif (map._state !== state) {\n\t\t\t\t\tthrow new Error(`LinkedMap got modified during iteration.`);\n\t\t\t\t}\n\t\t\t\tif (current) {\n\t\t\t\t\tconst result = { value: current.key, done: false };\n\t\t\t\t\tcurrent = current.next;\n\t\t\t\t\treturn result;\n\t\t\t\t} else {\n\t\t\t\t\treturn { value: undefined, done: true };\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\treturn iterator;\n\t}\n\n\tvalues(): IterableIterator {\n\t\tconst map = this;\n\t\tconst state = this._state;\n\t\tlet current = this._head;\n\t\tconst iterator: IterableIterator = {\n\t\t\t[Symbol.iterator]() {\n\t\t\t\treturn iterator;\n\t\t\t},\n\t\t\tnext(): IteratorResult {\n\t\t\t\tif (map._state !== state) {\n\t\t\t\t\tthrow new Error(`LinkedMap got modified during iteration.`);\n\t\t\t\t}\n\t\t\t\tif (current) {\n\t\t\t\t\tconst result = { value: current.value, done: false };\n\t\t\t\t\tcurrent = current.next;\n\t\t\t\t\treturn result;\n\t\t\t\t} else {\n\t\t\t\t\treturn { value: undefined, done: true };\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\treturn iterator;\n\t}\n\n\tentries(): IterableIterator<[K, V]> {\n\t\tconst map = this;\n\t\tconst state = this._state;\n\t\tlet current = this._head;\n\t\tconst iterator: IterableIterator<[K, V]> = {\n\t\t\t[Symbol.iterator]() {\n\t\t\t\treturn iterator;\n\t\t\t},\n\t\t\tnext(): IteratorResult<[K, V]> {\n\t\t\t\tif (map._state !== state) {\n\t\t\t\t\tthrow new Error(`LinkedMap got modified during iteration.`);\n\t\t\t\t}\n\t\t\t\tif (current) {\n\t\t\t\t\tconst result: IteratorResult<[K, V]> = { value: [current.key, current.value], done: false };\n\t\t\t\t\tcurrent = current.next;\n\t\t\t\t\treturn result;\n\t\t\t\t} else {\n\t\t\t\t\treturn { value: undefined, done: true };\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\treturn iterator;\n\t}\n\n\t[Symbol.iterator](): IterableIterator<[K, V]> {\n\t\treturn this.entries();\n\t}\n\n\tprotected trimOld(newSize: number) {\n\t\tif (newSize >= this.size) {\n\t\t\treturn;\n\t\t}\n\t\tif (newSize === 0) {\n\t\t\tthis.clear();\n\t\t\treturn;\n\t\t}\n\t\tlet current = this._head;\n\t\tlet currentSize = this.size;\n\t\twhile (current && currentSize > newSize) {\n\t\t\tthis._map.delete(current.key);\n\t\t\tcurrent = current.next;\n\t\t\tcurrentSize--;\n\t\t}\n\t\tthis._head = current;\n\t\tthis._size = currentSize;\n\t\tif (current) {\n\t\t\tcurrent.previous = undefined;\n\t\t}\n\t\tthis._state++;\n\t}\n\n\tprivate addItemFirst(item: Item): void {\n\t\t// First time Insert\n\t\tif (!this._head && !this._tail) {\n\t\t\tthis._tail = item;\n\t\t} else if (!this._head) {\n\t\t\tthrow new Error('Invalid list');\n\t\t} else {\n\t\t\titem.next = this._head;\n\t\t\tthis._head.previous = item;\n\t\t}\n\t\tthis._head = item;\n\t\tthis._state++;\n\t}\n\n\tprivate addItemLast(item: Item): void {\n\t\t// First time Insert\n\t\tif (!this._head && !this._tail) {\n\t\t\tthis._head = item;\n\t\t} else if (!this._tail) {\n\t\t\tthrow new Error('Invalid list');\n\t\t} else {\n\t\t\titem.previous = this._tail;\n\t\t\tthis._tail.next = item;\n\t\t}\n\t\tthis._tail = item;\n\t\tthis._state++;\n\t}\n\n\tprivate removeItem(item: Item): void {\n\t\tif (item === this._head && item === this._tail) {\n\t\t\tthis._head = undefined;\n\t\t\tthis._tail = undefined;\n\t\t}\n\t\telse if (item === this._head) {\n\t\t\t// This can only happen if size === 1 which is handled\n\t\t\t// by the case above.\n\t\t\tif (!item.next) {\n\t\t\t\tthrow new Error('Invalid list');\n\t\t\t}\n\t\t\titem.next.previous = undefined;\n\t\t\tthis._head = item.next;\n\t\t}\n\t\telse if (item === this._tail) {\n\t\t\t// This can only happen if size === 1 which is handled\n\t\t\t// by the case above.\n\t\t\tif (!item.previous) {\n\t\t\t\tthrow new Error('Invalid list');\n\t\t\t}\n\t\t\titem.previous.next = undefined;\n\t\t\tthis._tail = item.previous;\n\t\t}\n\t\telse {\n\t\t\tconst next = item.next;\n\t\t\tconst previous = item.previous;\n\t\t\tif (!next || !previous) {\n\t\t\t\tthrow new Error('Invalid list');\n\t\t\t}\n\t\t\tnext.previous = previous;\n\t\t\tprevious.next = next;\n\t\t}\n\t\titem.next = undefined;\n\t\titem.previous = undefined;\n\t\tthis._state++;\n\t}\n\n\tprivate touch(item: Item, touch: Touch): void {\n\t\tif (!this._head || !this._tail) {\n\t\t\tthrow new Error('Invalid list');\n\t\t}\n\t\tif ((touch !== Touch.AsOld && touch !== Touch.AsNew)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (touch === Touch.AsOld) {\n\t\t\tif (item === this._head) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst next = item.next;\n\t\t\tconst previous = item.previous;\n\n\t\t\t// Unlink the item\n\t\t\tif (item === this._tail) {\n\t\t\t\t// previous must be defined since item was not head but is tail\n\t\t\t\t// So there are more than on item in the map\n\t\t\t\tprevious!.next = undefined;\n\t\t\t\tthis._tail = previous;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Both next and previous are not undefined since item was neither head nor tail.\n\t\t\t\tnext!.previous = previous;\n\t\t\t\tprevious!.next = next;\n\t\t\t}\n\n\t\t\t// Insert the node at head\n\t\t\titem.previous = undefined;\n\t\t\titem.next = this._head;\n\t\t\tthis._head.previous = item;\n\t\t\tthis._head = item;\n\t\t\tthis._state++;\n\t\t} else if (touch === Touch.AsNew) {\n\t\t\tif (item === this._tail) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst next = item.next;\n\t\t\tconst previous = item.previous;\n\n\t\t\t// Unlink the item.\n\t\t\tif (item === this._head) {\n\t\t\t\t// next must be defined since item was not tail but is head\n\t\t\t\t// So there are more than on item in the map\n\t\t\t\tnext!.previous = undefined;\n\t\t\t\tthis._head = next;\n\t\t\t} else {\n\t\t\t\t// Both next and previous are not undefined since item was neither head nor tail.\n\t\t\t\tnext!.previous = previous;\n\t\t\t\tprevious!.next = next;\n\t\t\t}\n\t\t\titem.next = undefined;\n\t\t\titem.previous = this._tail;\n\t\t\tthis._tail.next = item;\n\t\t\tthis._tail = item;\n\t\t\tthis._state++;\n\t\t}\n\t}\n\n\ttoJSON(): [K, V][] {\n\t\tconst data: [K, V][] = [];\n\n\t\tthis.forEach((value, key) => {\n\t\t\tdata.push([key, value]);\n\t\t});\n\n\t\treturn data;\n\t}\n\n\tfromJSON(data: [K, V][]): void {\n\t\tthis.clear();\n\n\t\tfor (const [key, value] of data) {\n\t\t\tthis.set(key, value);\n\t\t}\n\t}\n}\n\nexport class LRUCache extends LinkedMap {\n\n\tprivate _limit: number;\n\tprivate _ratio: number;\n\n\tconstructor(limit: number, ratio: number = 1) {\n\t\tsuper();\n\t\tthis._limit = limit;\n\t\tthis._ratio = Math.min(Math.max(0, ratio), 1);\n\t}\n\n\tget limit(): number {\n\t\treturn this._limit;\n\t}\n\n\tset limit(limit: number) {\n\t\tthis._limit = limit;\n\t\tthis.checkTrim();\n\t}\n\n\toverride get(key: K, touch: Touch = Touch.AsNew): V | undefined {\n\t\treturn super.get(key, touch);\n\t}\n\n\tpeek(key: K): V | undefined {\n\t\treturn super.get(key, Touch.None);\n\t}\n\n\toverride set(key: K, value: V): this {\n\t\tsuper.set(key, value, Touch.AsNew);\n\t\tthis.checkTrim();\n\t\treturn this;\n\t}\n\n\tprivate checkTrim() {\n\t\tif (this.size > this._limit) {\n\t\t\tthis.trimOld(Math.round(this._limit * this._ratio));\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { LRUCache } from 'vs/base/common/map';\nimport * as strings from 'vs/base/common/strings';\n\nexport interface IFilter {\n\t// Returns null if word doesn't match.\n\t(word: string, wordToMatchAgainst: string): IMatch[] | null;\n}\n\nexport interface IMatch {\n\tstart: number;\n\tend: number;\n}\n\n// Combined filters\n\n/**\n * @returns A filter which combines the provided set\n * of filters with an or. The *first* filters that\n * matches defined the return value of the returned\n * filter.\n */\nexport function or(...filter: IFilter[]): IFilter {\n\treturn function (word: string, wordToMatchAgainst: string): IMatch[] | null {\n\t\tfor (let i = 0, len = filter.length; i < len; i++) {\n\t\t\tconst match = filter[i](word, wordToMatchAgainst);\n\t\t\tif (match) {\n\t\t\t\treturn match;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t};\n}\n\n// Prefix\n\nexport const matchesStrictPrefix: IFilter = _matchesPrefix.bind(undefined, false);\nexport const matchesPrefix: IFilter = _matchesPrefix.bind(undefined, true);\n\nfunction _matchesPrefix(ignoreCase: boolean, word: string, wordToMatchAgainst: string): IMatch[] | null {\n\tif (!wordToMatchAgainst || wordToMatchAgainst.length < word.length) {\n\t\treturn null;\n\t}\n\n\tlet matches: boolean;\n\tif (ignoreCase) {\n\t\tmatches = strings.startsWithIgnoreCase(wordToMatchAgainst, word);\n\t} else {\n\t\tmatches = wordToMatchAgainst.indexOf(word) === 0;\n\t}\n\n\tif (!matches) {\n\t\treturn null;\n\t}\n\n\treturn word.length > 0 ? [{ start: 0, end: word.length }] : [];\n}\n\n// Contiguous Substring\n\nexport function matchesContiguousSubString(word: string, wordToMatchAgainst: string): IMatch[] | null {\n\tconst index = wordToMatchAgainst.toLowerCase().indexOf(word.toLowerCase());\n\tif (index === -1) {\n\t\treturn null;\n\t}\n\n\treturn [{ start: index, end: index + word.length }];\n}\n\n// Substring\n\nexport function matchesSubString(word: string, wordToMatchAgainst: string): IMatch[] | null {\n\treturn _matchesSubString(word.toLowerCase(), wordToMatchAgainst.toLowerCase(), 0, 0);\n}\n\nfunction _matchesSubString(word: string, wordToMatchAgainst: string, i: number, j: number): IMatch[] | null {\n\tif (i === word.length) {\n\t\treturn [];\n\t} else if (j === wordToMatchAgainst.length) {\n\t\treturn null;\n\t} else {\n\t\tif (word[i] === wordToMatchAgainst[j]) {\n\t\t\tlet result: IMatch[] | null = null;\n\t\t\tif (result = _matchesSubString(word, wordToMatchAgainst, i + 1, j + 1)) {\n\t\t\t\treturn join({ start: j, end: j + 1 }, result);\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\treturn _matchesSubString(word, wordToMatchAgainst, i, j + 1);\n\t}\n}\n\n// CamelCase\n\nfunction isLower(code: number): boolean {\n\treturn CharCode.a <= code && code <= CharCode.z;\n}\n\nexport function isUpper(code: number): boolean {\n\treturn CharCode.A <= code && code <= CharCode.Z;\n}\n\nfunction isNumber(code: number): boolean {\n\treturn CharCode.Digit0 <= code && code <= CharCode.Digit9;\n}\n\nfunction isWhitespace(code: number): boolean {\n\treturn (\n\t\tcode === CharCode.Space\n\t\t|| code === CharCode.Tab\n\t\t|| code === CharCode.LineFeed\n\t\t|| code === CharCode.CarriageReturn\n\t);\n}\n\nconst wordSeparators = new Set();\n// These are chosen as natural word separators based on writen text.\n// It is a subset of the word separators used by the monaco editor.\n'()[]{}<>`\\'\"-/;:,.?!'\n\t.split('')\n\t.forEach(s => wordSeparators.add(s.charCodeAt(0)));\n\nfunction isWordSeparator(code: number): boolean {\n\treturn isWhitespace(code) || wordSeparators.has(code);\n}\n\nfunction charactersMatch(codeA: number, codeB: number): boolean {\n\treturn (codeA === codeB) || (isWordSeparator(codeA) && isWordSeparator(codeB));\n}\n\nfunction isAlphanumeric(code: number): boolean {\n\treturn isLower(code) || isUpper(code) || isNumber(code);\n}\n\nfunction join(head: IMatch, tail: IMatch[]): IMatch[] {\n\tif (tail.length === 0) {\n\t\ttail = [head];\n\t} else if (head.end === tail[0].start) {\n\t\ttail[0].start = head.start;\n\t} else {\n\t\ttail.unshift(head);\n\t}\n\treturn tail;\n}\n\nfunction nextAnchor(camelCaseWord: string, start: number): number {\n\tfor (let i = start; i < camelCaseWord.length; i++) {\n\t\tconst c = camelCaseWord.charCodeAt(i);\n\t\tif (isUpper(c) || isNumber(c) || (i > 0 && !isAlphanumeric(camelCaseWord.charCodeAt(i - 1)))) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn camelCaseWord.length;\n}\n\nfunction _matchesCamelCase(word: string, camelCaseWord: string, i: number, j: number): IMatch[] | null {\n\tif (i === word.length) {\n\t\treturn [];\n\t} else if (j === camelCaseWord.length) {\n\t\treturn null;\n\t} else if (word[i] !== camelCaseWord[j].toLowerCase()) {\n\t\treturn null;\n\t} else {\n\t\tlet result: IMatch[] | null = null;\n\t\tlet nextUpperIndex = j + 1;\n\t\tresult = _matchesCamelCase(word, camelCaseWord, i + 1, j + 1);\n\t\twhile (!result && (nextUpperIndex = nextAnchor(camelCaseWord, nextUpperIndex)) < camelCaseWord.length) {\n\t\t\tresult = _matchesCamelCase(word, camelCaseWord, i + 1, nextUpperIndex);\n\t\t\tnextUpperIndex++;\n\t\t}\n\t\treturn result === null ? null : join({ start: j, end: j + 1 }, result);\n\t}\n}\n\ninterface ICamelCaseAnalysis {\n\tupperPercent: number;\n\tlowerPercent: number;\n\talphaPercent: number;\n\tnumericPercent: number;\n}\n\n// Heuristic to avoid computing camel case matcher for words that don't\n// look like camelCaseWords.\nfunction analyzeCamelCaseWord(word: string): ICamelCaseAnalysis {\n\tlet upper = 0, lower = 0, alpha = 0, numeric = 0, code = 0;\n\n\tfor (let i = 0; i < word.length; i++) {\n\t\tcode = word.charCodeAt(i);\n\n\t\tif (isUpper(code)) { upper++; }\n\t\tif (isLower(code)) { lower++; }\n\t\tif (isAlphanumeric(code)) { alpha++; }\n\t\tif (isNumber(code)) { numeric++; }\n\t}\n\n\tconst upperPercent = upper / word.length;\n\tconst lowerPercent = lower / word.length;\n\tconst alphaPercent = alpha / word.length;\n\tconst numericPercent = numeric / word.length;\n\n\treturn { upperPercent, lowerPercent, alphaPercent, numericPercent };\n}\n\nfunction isUpperCaseWord(analysis: ICamelCaseAnalysis): boolean {\n\tconst { upperPercent, lowerPercent } = analysis;\n\treturn lowerPercent === 0 && upperPercent > 0.6;\n}\n\nfunction isCamelCaseWord(analysis: ICamelCaseAnalysis): boolean {\n\tconst { upperPercent, lowerPercent, alphaPercent, numericPercent } = analysis;\n\treturn lowerPercent > 0.2 && upperPercent < 0.8 && alphaPercent > 0.6 && numericPercent < 0.2;\n}\n\n// Heuristic to avoid computing camel case matcher for words that don't\n// look like camel case patterns.\nfunction isCamelCasePattern(word: string): boolean {\n\tlet upper = 0, lower = 0, code = 0, whitespace = 0;\n\n\tfor (let i = 0; i < word.length; i++) {\n\t\tcode = word.charCodeAt(i);\n\n\t\tif (isUpper(code)) { upper++; }\n\t\tif (isLower(code)) { lower++; }\n\t\tif (isWhitespace(code)) { whitespace++; }\n\t}\n\n\tif ((upper === 0 || lower === 0) && whitespace === 0) {\n\t\treturn word.length <= 30;\n\t} else {\n\t\treturn upper <= 5;\n\t}\n}\n\nexport function matchesCamelCase(word: string, camelCaseWord: string): IMatch[] | null {\n\tif (!camelCaseWord) {\n\t\treturn null;\n\t}\n\n\tcamelCaseWord = camelCaseWord.trim();\n\n\tif (camelCaseWord.length === 0) {\n\t\treturn null;\n\t}\n\n\tif (!isCamelCasePattern(word)) {\n\t\treturn null;\n\t}\n\n\tif (camelCaseWord.length > 60) {\n\t\treturn null;\n\t}\n\n\tconst analysis = analyzeCamelCaseWord(camelCaseWord);\n\n\tif (!isCamelCaseWord(analysis)) {\n\t\tif (!isUpperCaseWord(analysis)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tcamelCaseWord = camelCaseWord.toLowerCase();\n\t}\n\n\tlet result: IMatch[] | null = null;\n\tlet i = 0;\n\n\tword = word.toLowerCase();\n\twhile (i < camelCaseWord.length && (result = _matchesCamelCase(word, camelCaseWord, 0, i)) === null) {\n\t\ti = nextAnchor(camelCaseWord, i + 1);\n\t}\n\n\treturn result;\n}\n\n// Matches beginning of words supporting non-ASCII languages\n// If `contiguous` is true then matches word with beginnings of the words in the target. E.g. \"pul\" will match \"Git: Pull\"\n// Otherwise also matches sub string of the word with beginnings of the words in the target. E.g. \"gp\" or \"g p\" will match \"Git: Pull\"\n// Useful in cases where the target is words (e.g. command labels)\n\nexport function matchesWords(word: string, target: string, contiguous: boolean = false): IMatch[] | null {\n\tif (!target || target.length === 0) {\n\t\treturn null;\n\t}\n\n\tlet result: IMatch[] | null = null;\n\tlet i = 0;\n\n\tword = word.toLowerCase();\n\ttarget = target.toLowerCase();\n\twhile (i < target.length && (result = _matchesWords(word, target, 0, i, contiguous)) === null) {\n\t\ti = nextWord(target, i + 1);\n\t}\n\n\treturn result;\n}\n\nfunction _matchesWords(word: string, target: string, i: number, j: number, contiguous: boolean): IMatch[] | null {\n\tif (i === word.length) {\n\t\treturn [];\n\t} else if (j === target.length) {\n\t\treturn null;\n\t} else if (!charactersMatch(word.charCodeAt(i), target.charCodeAt(j))) {\n\t\treturn null;\n\t} else {\n\t\tlet result: IMatch[] | null = null;\n\t\tlet nextWordIndex = j + 1;\n\t\tresult = _matchesWords(word, target, i + 1, j + 1, contiguous);\n\t\tif (!contiguous) {\n\t\t\twhile (!result && (nextWordIndex = nextWord(target, nextWordIndex)) < target.length) {\n\t\t\t\tresult = _matchesWords(word, target, i + 1, nextWordIndex, contiguous);\n\t\t\t\tnextWordIndex++;\n\t\t\t}\n\t\t}\n\t\treturn result === null ? null : join({ start: j, end: j + 1 }, result);\n\t}\n}\n\nfunction nextWord(word: string, start: number): number {\n\tfor (let i = start; i < word.length; i++) {\n\t\tif (isWordSeparator(word.charCodeAt(i)) ||\n\t\t\t(i > 0 && isWordSeparator(word.charCodeAt(i - 1)))) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn word.length;\n}\n\n// Fuzzy\n\nconst fuzzyContiguousFilter = or(matchesPrefix, matchesCamelCase, matchesContiguousSubString);\nconst fuzzySeparateFilter = or(matchesPrefix, matchesCamelCase, matchesSubString);\nconst fuzzyRegExpCache = new LRUCache(10000); // bounded to 10000 elements\n\nexport function matchesFuzzy(word: string, wordToMatchAgainst: string, enableSeparateSubstringMatching = false): IMatch[] | null {\n\tif (typeof word !== 'string' || typeof wordToMatchAgainst !== 'string') {\n\t\treturn null; // return early for invalid input\n\t}\n\n\t// Form RegExp for wildcard matches\n\tlet regexp = fuzzyRegExpCache.get(word);\n\tif (!regexp) {\n\t\tregexp = new RegExp(strings.convertSimple2RegExpPattern(word), 'i');\n\t\tfuzzyRegExpCache.set(word, regexp);\n\t}\n\n\t// RegExp Filter\n\tconst match = regexp.exec(wordToMatchAgainst);\n\tif (match) {\n\t\treturn [{ start: match.index, end: match.index + match[0].length }];\n\t}\n\n\t// Default Filter\n\treturn enableSeparateSubstringMatching ? fuzzySeparateFilter(word, wordToMatchAgainst) : fuzzyContiguousFilter(word, wordToMatchAgainst);\n}\n\nexport function anyScore(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number): FuzzyScore {\n\tconst max = Math.min(13, pattern.length);\n\tfor (; patternPos < max; patternPos++) {\n\t\tconst result = fuzzyScore(pattern, lowPattern, patternPos, word, lowWord, wordPos, false);\n\t\tif (result) {\n\t\t\treturn result;\n\t\t}\n\t}\n\treturn [0, wordPos];\n}\n\n//#region --- fuzzyScore ---\n\nexport function createMatches(score: undefined | FuzzyScore): IMatch[] {\n\tif (typeof score === 'undefined') {\n\t\treturn [];\n\t}\n\tconst res: IMatch[] = [];\n\tconst wordPos = score[1];\n\tfor (let i = score.length - 1; i > 1; i--) {\n\t\tconst pos = score[i] + wordPos;\n\t\tconst last = res[res.length - 1];\n\t\tif (last && last.end === pos) {\n\t\t\tlast.end = pos + 1;\n\t\t} else {\n\t\t\tres.push({ start: pos, end: pos + 1 });\n\t\t}\n\t}\n\treturn res;\n}\n\nconst _maxLen = 128;\n\nfunction initTable() {\n\tconst table: number[][] = [];\n\tconst row: number[] = [];\n\tfor (let i = 0; i <= _maxLen; i++) {\n\t\trow[i] = 0;\n\t}\n\tfor (let i = 0; i <= _maxLen; i++) {\n\t\ttable.push(row.slice(0));\n\t}\n\treturn table;\n}\n\nfunction initArr(maxLen: number) {\n\tconst row: number[] = [];\n\tfor (let i = 0; i <= maxLen; i++) {\n\t\trow[i] = 0;\n\t}\n\treturn row;\n}\n\nconst _minWordMatchPos = initArr(2 * _maxLen); // min word position for a certain pattern position\nconst _maxWordMatchPos = initArr(2 * _maxLen); // max word position for a certain pattern position\nconst _diag = initTable(); // the length of a contiguous diagonal match\nconst _table = initTable();\nconst _arrows = initTable();\nconst _debug = false;\n\nfunction printTable(table: number[][], pattern: string, patternLen: number, word: string, wordLen: number): string {\n\tfunction pad(s: string, n: number, pad = ' ') {\n\t\twhile (s.length < n) {\n\t\t\ts = pad + s;\n\t\t}\n\t\treturn s;\n\t}\n\tlet ret = ` | |${word.split('').map(c => pad(c, 3)).join('|')}\\n`;\n\n\tfor (let i = 0; i <= patternLen; i++) {\n\t\tif (i === 0) {\n\t\t\tret += ' |';\n\t\t} else {\n\t\t\tret += `${pattern[i - 1]}|`;\n\t\t}\n\t\tret += table[i].slice(0, wordLen + 1).map(n => pad(n.toString(), 3)).join('|') + '\\n';\n\t}\n\treturn ret;\n}\n\nfunction printTables(pattern: string, patternStart: number, word: string, wordStart: number): void {\n\tpattern = pattern.substr(patternStart);\n\tword = word.substr(wordStart);\n\tconsole.log(printTable(_table, pattern, pattern.length, word, word.length));\n\tconsole.log(printTable(_arrows, pattern, pattern.length, word, word.length));\n\tconsole.log(printTable(_diag, pattern, pattern.length, word, word.length));\n}\n\nfunction isSeparatorAtPos(value: string, index: number): boolean {\n\tif (index < 0 || index >= value.length) {\n\t\treturn false;\n\t}\n\tconst code = value.codePointAt(index);\n\tswitch (code) {\n\t\tcase CharCode.Underline:\n\t\tcase CharCode.Dash:\n\t\tcase CharCode.Period:\n\t\tcase CharCode.Space:\n\t\tcase CharCode.Slash:\n\t\tcase CharCode.Backslash:\n\t\tcase CharCode.SingleQuote:\n\t\tcase CharCode.DoubleQuote:\n\t\tcase CharCode.Colon:\n\t\tcase CharCode.DollarSign:\n\t\tcase CharCode.LessThan:\n\t\tcase CharCode.OpenParen:\n\t\tcase CharCode.OpenSquareBracket:\n\t\t\treturn true;\n\t\tcase undefined:\n\t\t\treturn false;\n\t\tdefault:\n\t\t\tif (strings.isEmojiImprecise(code)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t}\n}\n\nfunction isWhitespaceAtPos(value: string, index: number): boolean {\n\tif (index < 0 || index >= value.length) {\n\t\treturn false;\n\t}\n\tconst code = value.charCodeAt(index);\n\tswitch (code) {\n\t\tcase CharCode.Space:\n\t\tcase CharCode.Tab:\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nfunction isUpperCaseAtPos(pos: number, word: string, wordLow: string): boolean {\n\treturn word[pos] !== wordLow[pos];\n}\n\nexport function isPatternInWord(patternLow: string, patternPos: number, patternLen: number, wordLow: string, wordPos: number, wordLen: number, fillMinWordPosArr = false): boolean {\n\twhile (patternPos < patternLen && wordPos < wordLen) {\n\t\tif (patternLow[patternPos] === wordLow[wordPos]) {\n\t\t\tif (fillMinWordPosArr) {\n\t\t\t\t// Remember the min word position for each pattern position\n\t\t\t\t_minWordMatchPos[patternPos] = wordPos;\n\t\t\t}\n\t\t\tpatternPos += 1;\n\t\t}\n\t\twordPos += 1;\n\t}\n\treturn patternPos === patternLen; // pattern must be exhausted\n}\n\nconst enum Arrow { Diag = 1, Left = 2, LeftLeft = 3 }\n\n/**\n * An array representing a fuzzy match.\n *\n * 0. the score\n * 1. the offset at which matching started\n * 2. ``\n * 3. ``\n * 4. `` etc\n */\nexport type FuzzyScore = [score: number, wordStart: number, ...matches: number[]];\n\nexport namespace FuzzyScore {\n\t/**\n\t * No matches and value `-100`\n\t */\n\texport const Default: FuzzyScore = ([-100, 0]);\n\n\texport function isDefault(score?: FuzzyScore): score is [-100, 0] {\n\t\treturn !score || (score.length === 2 && score[0] === -100 && score[1] === 0);\n\t}\n}\n\nexport interface FuzzyScorer {\n\t(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, firstMatchCanBeWeak: boolean): FuzzyScore | undefined;\n}\n\nexport function fuzzyScore(pattern: string, patternLow: string, patternStart: number, word: string, wordLow: string, wordStart: number, firstMatchCanBeWeak: boolean): FuzzyScore | undefined {\n\n\tconst patternLen = pattern.length > _maxLen ? _maxLen : pattern.length;\n\tconst wordLen = word.length > _maxLen ? _maxLen : word.length;\n\n\tif (patternStart >= patternLen || wordStart >= wordLen || (patternLen - patternStart) > (wordLen - wordStart)) {\n\t\treturn undefined;\n\t}\n\n\t// Run a simple check if the characters of pattern occur\n\t// (in order) at all in word. If that isn't the case we\n\t// stop because no match will be possible\n\tif (!isPatternInWord(patternLow, patternStart, patternLen, wordLow, wordStart, wordLen, true)) {\n\t\treturn undefined;\n\t}\n\n\t// Find the max matching word position for each pattern position\n\t// NOTE: the min matching word position was filled in above, in the `isPatternInWord` call\n\t_fillInMaxWordMatchPos(patternLen, wordLen, patternStart, wordStart, patternLow, wordLow);\n\n\tlet row: number = 1;\n\tlet column: number = 1;\n\tlet patternPos = patternStart;\n\tlet wordPos = wordStart;\n\n\tconst hasStrongFirstMatch = [false];\n\n\t// There will be a match, fill in tables\n\tfor (row = 1, patternPos = patternStart; patternPos < patternLen; row++, patternPos++) {\n\n\t\t// Reduce search space to possible matching word positions and to possible access from next row\n\t\tconst minWordMatchPos = _minWordMatchPos[patternPos];\n\t\tconst maxWordMatchPos = _maxWordMatchPos[patternPos];\n\t\tconst nextMaxWordMatchPos = (patternPos + 1 < patternLen ? _maxWordMatchPos[patternPos + 1] : wordLen);\n\n\t\tfor (column = minWordMatchPos - wordStart + 1, wordPos = minWordMatchPos; wordPos < nextMaxWordMatchPos; column++, wordPos++) {\n\n\t\t\tlet score = Number.MIN_SAFE_INTEGER;\n\t\t\tlet canComeDiag = false;\n\n\t\t\tif (wordPos <= maxWordMatchPos) {\n\t\t\t\tscore = _doScore(\n\t\t\t\t\tpattern, patternLow, patternPos, patternStart,\n\t\t\t\t\tword, wordLow, wordPos, wordLen, wordStart,\n\t\t\t\t\t_diag[row - 1][column - 1] === 0,\n\t\t\t\t\thasStrongFirstMatch\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet diagScore = 0;\n\t\t\tif (score !== Number.MAX_SAFE_INTEGER) {\n\t\t\t\tcanComeDiag = true;\n\t\t\t\tdiagScore = score + _table[row - 1][column - 1];\n\t\t\t}\n\n\t\t\tconst canComeLeft = wordPos > minWordMatchPos;\n\t\t\tconst leftScore = canComeLeft ? _table[row][column - 1] + (_diag[row][column - 1] > 0 ? -5 : 0) : 0; // penalty for a gap start\n\n\t\t\tconst canComeLeftLeft = wordPos > minWordMatchPos + 1 && _diag[row][column - 1] > 0;\n\t\t\tconst leftLeftScore = canComeLeftLeft ? _table[row][column - 2] + (_diag[row][column - 2] > 0 ? -5 : 0) : 0; // penalty for a gap start\n\n\t\t\tif (canComeLeftLeft && (!canComeLeft || leftLeftScore >= leftScore) && (!canComeDiag || leftLeftScore >= diagScore)) {\n\t\t\t\t// always prefer choosing left left to jump over a diagonal because that means a match is earlier in the word\n\t\t\t\t_table[row][column] = leftLeftScore;\n\t\t\t\t_arrows[row][column] = Arrow.LeftLeft;\n\t\t\t\t_diag[row][column] = 0;\n\t\t\t} else if (canComeLeft && (!canComeDiag || leftScore >= diagScore)) {\n\t\t\t\t// always prefer choosing left since that means a match is earlier in the word\n\t\t\t\t_table[row][column] = leftScore;\n\t\t\t\t_arrows[row][column] = Arrow.Left;\n\t\t\t\t_diag[row][column] = 0;\n\t\t\t} else if (canComeDiag) {\n\t\t\t\t_table[row][column] = diagScore;\n\t\t\t\t_arrows[row][column] = Arrow.Diag;\n\t\t\t\t_diag[row][column] = _diag[row - 1][column - 1] + 1;\n\t\t\t} else {\n\t\t\t\tthrow new Error(`not possible`);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (_debug) {\n\t\tprintTables(pattern, patternStart, word, wordStart);\n\t}\n\n\tif (!hasStrongFirstMatch[0] && !firstMatchCanBeWeak) {\n\t\treturn undefined;\n\t}\n\n\trow--;\n\tcolumn--;\n\n\tconst result: FuzzyScore = [_table[row][column], wordStart];\n\n\tlet backwardsDiagLength = 0;\n\tlet maxMatchColumn = 0;\n\n\twhile (row >= 1) {\n\t\t// Find the column where we go diagonally up\n\t\tlet diagColumn = column;\n\t\tdo {\n\t\t\tconst arrow = _arrows[row][diagColumn];\n\t\t\tif (arrow === Arrow.LeftLeft) {\n\t\t\t\tdiagColumn = diagColumn - 2;\n\t\t\t} else if (arrow === Arrow.Left) {\n\t\t\t\tdiagColumn = diagColumn - 1;\n\t\t\t} else {\n\t\t\t\t// found the diagonal\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} while (diagColumn >= 1);\n\n\t\t// Overturn the \"forwards\" decision if keeping the \"backwards\" diagonal would give a better match\n\t\tif (\n\t\t\tbackwardsDiagLength > 1 // only if we would have a contiguous match of 3 characters\n\t\t\t&& patternLow[patternStart + row - 1] === wordLow[wordStart + column - 1] // only if we can do a contiguous match diagonally\n\t\t\t&& !isUpperCaseAtPos(diagColumn + wordStart - 1, word, wordLow) // only if the forwards chose diagonal is not an uppercase\n\t\t\t&& backwardsDiagLength + 1 > _diag[row][diagColumn] // only if our contiguous match would be longer than the \"forwards\" contiguous match\n\t\t) {\n\t\t\tdiagColumn = column;\n\t\t}\n\n\t\tif (diagColumn === column) {\n\t\t\t// this is a contiguous match\n\t\t\tbackwardsDiagLength++;\n\t\t} else {\n\t\t\tbackwardsDiagLength = 1;\n\t\t}\n\n\t\tif (!maxMatchColumn) {\n\t\t\t// remember the last matched column\n\t\t\tmaxMatchColumn = diagColumn;\n\t\t}\n\n\t\trow--;\n\t\tcolumn = diagColumn - 1;\n\t\tresult.push(column);\n\t}\n\n\tif (wordLen === patternLen) {\n\t\t// the word matches the pattern with all characters!\n\t\t// giving the score a total match boost (to come up ahead other words)\n\t\tresult[0] += 2;\n\t}\n\n\t// Add 1 penalty for each skipped character in the word\n\tconst skippedCharsCount = maxMatchColumn - patternLen;\n\tresult[0] -= skippedCharsCount;\n\n\treturn result;\n}\n\nfunction _fillInMaxWordMatchPos(patternLen: number, wordLen: number, patternStart: number, wordStart: number, patternLow: string, wordLow: string) {\n\tlet patternPos = patternLen - 1;\n\tlet wordPos = wordLen - 1;\n\twhile (patternPos >= patternStart && wordPos >= wordStart) {\n\t\tif (patternLow[patternPos] === wordLow[wordPos]) {\n\t\t\t_maxWordMatchPos[patternPos] = wordPos;\n\t\t\tpatternPos--;\n\t\t}\n\t\twordPos--;\n\t}\n}\n\nfunction _doScore(\n\tpattern: string, patternLow: string, patternPos: number, patternStart: number,\n\tword: string, wordLow: string, wordPos: number, wordLen: number, wordStart: number,\n\tnewMatchStart: boolean,\n\toutFirstMatchStrong: boolean[],\n): number {\n\tif (patternLow[patternPos] !== wordLow[wordPos]) {\n\t\treturn Number.MIN_SAFE_INTEGER;\n\t}\n\n\tlet score = 1;\n\tlet isGapLocation = false;\n\tif (wordPos === (patternPos - patternStart)) {\n\t\t// common prefix: `foobar <-> foobaz`\n\t\t// ^^^^^\n\t\tscore = pattern[patternPos] === word[wordPos] ? 7 : 5;\n\n\t} else if (isUpperCaseAtPos(wordPos, word, wordLow) && (wordPos === 0 || !isUpperCaseAtPos(wordPos - 1, word, wordLow))) {\n\t\t// hitting upper-case: `foo <-> forOthers`\n\t\t// ^^ ^\n\t\tscore = pattern[patternPos] === word[wordPos] ? 7 : 5;\n\t\tisGapLocation = true;\n\n\t} else if (isSeparatorAtPos(wordLow, wordPos) && (wordPos === 0 || !isSeparatorAtPos(wordLow, wordPos - 1))) {\n\t\t// hitting a separator: `. <-> foo.bar`\n\t\t// ^\n\t\tscore = 5;\n\n\t} else if (isSeparatorAtPos(wordLow, wordPos - 1) || isWhitespaceAtPos(wordLow, wordPos - 1)) {\n\t\t// post separator: `foo <-> bar_foo`\n\t\t// ^^^\n\t\tscore = 5;\n\t\tisGapLocation = true;\n\t}\n\n\tif (score > 1 && patternPos === patternStart) {\n\t\toutFirstMatchStrong[0] = true;\n\t}\n\n\tif (!isGapLocation) {\n\t\tisGapLocation = isUpperCaseAtPos(wordPos, word, wordLow) || isSeparatorAtPos(wordLow, wordPos - 1) || isWhitespaceAtPos(wordLow, wordPos - 1);\n\t}\n\n\t//\n\tif (patternPos === patternStart) { // first character in pattern\n\t\tif (wordPos > wordStart) {\n\t\t\t// the first pattern character would match a word character that is not at the word start\n\t\t\t// so introduce a penalty to account for the gap preceding this match\n\t\t\tscore -= isGapLocation ? 3 : 5;\n\t\t}\n\t} else {\n\t\tif (newMatchStart) {\n\t\t\t// this would be the beginning of a new match (i.e. there would be a gap before this location)\n\t\t\tscore += isGapLocation ? 2 : 0;\n\t\t} else {\n\t\t\t// this is part of a contiguous match, so give it a slight bonus, but do so only if it would not be a preferred gap location\n\t\t\tscore += isGapLocation ? 0 : 1;\n\t\t}\n\t}\n\n\tif (wordPos + 1 === wordLen) {\n\t\t// we always penalize gaps, but this gives unfair advantages to a match that would match the last character in the word\n\t\t// so pretend there is a gap after the last character in the word to normalize things\n\t\tscore -= isGapLocation ? 3 : 5;\n\t}\n\n\treturn score;\n}\n\n//#endregion\n\n\n//#region --- graceful ---\n\nexport function fuzzyScoreGracefulAggressive(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, firstMatchCanBeWeak: boolean): FuzzyScore | undefined {\n\treturn fuzzyScoreWithPermutations(pattern, lowPattern, patternPos, word, lowWord, wordPos, true, firstMatchCanBeWeak);\n}\n\nfunction fuzzyScoreWithPermutations(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, aggressive: boolean, firstMatchCanBeWeak: boolean): FuzzyScore | undefined {\n\tlet top = fuzzyScore(pattern, lowPattern, patternPos, word, lowWord, wordPos, firstMatchCanBeWeak);\n\n\tif (top && !aggressive) {\n\t\t// when using the original pattern yield a result we`\n\t\t// return it unless we are aggressive and try to find\n\t\t// a better alignment, e.g. `cno` -> `^co^ns^ole` or `^c^o^nsole`.\n\t\treturn top;\n\t}\n\n\tif (pattern.length >= 3) {\n\t\t// When the pattern is long enough then try a few (max 7)\n\t\t// permutations of the pattern to find a better match. The\n\t\t// permutations only swap neighbouring characters, e.g\n\t\t// `cnoso` becomes `conso`, `cnsoo`, `cnoos`.\n\t\tconst tries = Math.min(7, pattern.length - 1);\n\t\tfor (let movingPatternPos = patternPos + 1; movingPatternPos < tries; movingPatternPos++) {\n\t\t\tconst newPattern = nextTypoPermutation(pattern, movingPatternPos);\n\t\t\tif (newPattern) {\n\t\t\t\tconst candidate = fuzzyScore(newPattern, newPattern.toLowerCase(), patternPos, word, lowWord, wordPos, firstMatchCanBeWeak);\n\t\t\t\tif (candidate) {\n\t\t\t\t\tcandidate[0] -= 3; // permutation penalty\n\t\t\t\t\tif (!top || candidate[0] > top[0]) {\n\t\t\t\t\t\ttop = candidate;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn top;\n}\n\nfunction nextTypoPermutation(pattern: string, patternPos: number): string | undefined {\n\n\tif (patternPos + 1 >= pattern.length) {\n\t\treturn undefined;\n\t}\n\n\tconst swap1 = pattern[patternPos];\n\tconst swap2 = pattern[patternPos + 1];\n\n\tif (swap1 === swap2) {\n\t\treturn undefined;\n\t}\n\n\treturn pattern.slice(0, patternPos)\n\t\t+ swap2\n\t\t+ swap1\n\t\t+ pattern.slice(patternPos + 2);\n}\n\n//#endregion\n","\nimport { createMatches as createFuzzyMatches, fuzzyScore, IMatch } from 'vs/base/common/filters';\nimport { sep } from 'vs/base/common/path';\nimport { isWindows } from 'vs/base/common/platform';\nimport { stripWildcards } from 'vs/base/common/strings';\n\n// function printMatrix(query: string, target: string, matches: number[], scores: number[]): void {\n// \tconsole.log('\\t' + target.split('').join('\\t'));\n// \tfor (let queryIndex = 0; queryIndex < query.length; queryIndex++) {\n// \t\tlet line = query[queryIndex] + '\\t';\n// \t\tfor (let targetIndex = 0; targetIndex < target.length; targetIndex++) {\n// \t\t\tconst currentIndex = queryIndex * target.length + targetIndex;\n// \t\t\tline = line + 'M' + matches[currentIndex] + '/' + 'S' + scores[currentIndex] + '\\t';\n// \t\t}\n\n// \t\tconsole.log(line);\n// \t}\n// }\n\n//#endregion\n\n\n//#region Alternate fuzzy scorer implementation that is e.g. used for symbols\n\nexport type FuzzyScore2 = [number | undefined /* score */, IMatch[]];\n\nconst NO_SCORE2: FuzzyScore2 = [undefined, []];\n\nexport function scoreFuzzy2(target: string, query: IPreparedQuery | IPreparedQueryPiece, patternStart = 0, wordStart = 0): FuzzyScore2 {\n\n\t// Score: multiple inputs\n\tconst preparedQuery = query as IPreparedQuery;\n\tif (preparedQuery.values && preparedQuery.values.length > 1) {\n\t\treturn doScoreFuzzy2Multiple(target, preparedQuery.values, patternStart, wordStart);\n\t}\n\n\t// Score: single input\n\treturn doScoreFuzzy2Single(target, query, patternStart, wordStart);\n}\n\nfunction doScoreFuzzy2Multiple(target: string, query: IPreparedQueryPiece[], patternStart: number, wordStart: number): FuzzyScore2 {\n\tlet totalScore = 0;\n\tconst totalMatches: IMatch[] = [];\n\n\tfor (const queryPiece of query) {\n\t\tconst [score, matches] = doScoreFuzzy2Single(target, queryPiece, patternStart, wordStart);\n\t\tif (typeof score !== 'number') {\n\t\t\t// if a single query value does not match, return with\n\t\t\t// no score entirely, we require all queries to match\n\t\t\treturn NO_SCORE2;\n\t\t}\n\n\t\ttotalScore += score;\n\t\ttotalMatches.push(...matches);\n\t}\n\n\t// if we have a score, ensure that the positions are\n\t// sorted in ascending order and distinct\n\treturn [totalScore, normalizeMatches(totalMatches)];\n}\n\nfunction doScoreFuzzy2Single(target: string, query: IPreparedQueryPiece, patternStart: number, wordStart: number): FuzzyScore2 {\n\tconst score = fuzzyScore(query.original, query.originalLowercase, patternStart, target, target.toLowerCase(), wordStart, true);\n\tif (!score) {\n\t\treturn NO_SCORE2;\n\t}\n\n\treturn [score[0], createFuzzyMatches(score)];\n}\n\n//#endregion\n\n\n//#region Item (label, description, path) scorer\n\n/**\n * Scoring on structural items that have a label and optional description.\n */\nexport interface IItemScore {\n}\n\nconst NO_ITEM_SCORE: IItemScore = Object.freeze({ score: 0 });\n\nexport interface IItemAccessor {\n}\n\nfunction normalizeMatches(matches: IMatch[]): IMatch[] {\n\n\t// sort matches by start to be able to normalize\n\tconst sortedMatches = matches.sort((matchA, matchB) => {\n\t\treturn matchA.start - matchB.start;\n\t});\n\n\t// merge matches that overlap\n\tconst normalizedMatches: IMatch[] = [];\n\tlet currentMatch: IMatch | undefined = undefined;\n\tfor (const match of sortedMatches) {\n\n\t\t// if we have no current match or the matches\n\t\t// do not overlap, we take it as is and remember\n\t\t// it for future merging\n\t\tif (!currentMatch || !matchOverlaps(currentMatch, match)) {\n\t\t\tcurrentMatch = match;\n\t\t\tnormalizedMatches.push(match);\n\t\t}\n\n\t\t// otherwise we merge the matches\n\t\telse {\n\t\t\tcurrentMatch.start = Math.min(currentMatch.start, match.start);\n\t\t\tcurrentMatch.end = Math.max(currentMatch.end, match.end);\n\t\t}\n\t}\n\n\treturn normalizedMatches;\n}\n\nfunction matchOverlaps(matchA: IMatch, matchB: IMatch): boolean {\n\tif (matchA.end < matchB.start) {\n\t\treturn false;\t// A ends before B starts\n\t}\n\n\tif (matchB.end < matchA.start) {\n\t\treturn false; // B ends before A starts\n\t}\n\n\treturn true;\n}\n\n//#endregion\n\n\n//#region Query Normalizer\n\nexport interface IPreparedQueryPiece {\n\n\t/**\n\t * The original query as provided as input.\n\t */\n\toriginal: string;\n\toriginalLowercase: string;\n\n\t/**\n\t * Original normalized to platform separators:\n\t * - Windows: \\\n\t * - Posix: /\n\t */\n\tpathNormalized: string;\n\n\t/**\n\t * In addition to the normalized path, will have\n\t * whitespace and wildcards removed.\n\t */\n\tnormalized: string;\n\tnormalizedLowercase: string;\n\n\t/**\n\t * The query is wrapped in quotes which means\n\t * this query must be a substring of the input.\n\t * In other words, no fuzzy matching is used.\n\t */\n\texpectContiguousMatch: boolean;\n}\n\nexport interface IPreparedQuery extends IPreparedQueryPiece {\n\n\t/**\n\t * Query split by spaces into pieces.\n\t */\n\tvalues: IPreparedQueryPiece[] | undefined;\n\n\t/**\n\t * Whether the query contains path separator(s) or not.\n\t */\n\tcontainsPathSeparator: boolean;\n}\n\n/*\n * If a query is wrapped in quotes, the user does not want to\n * use fuzzy search for this query.\n */\nfunction queryExpectsExactMatch(query: string) {\n\treturn query.startsWith('\"') && query.endsWith('\"');\n}\n\n/**\n * Helper function to prepare a search value for scoring by removing unwanted characters\n * and allowing to score on multiple pieces separated by whitespace character.\n */\nconst MULTIPLE_QUERY_VALUES_SEPARATOR = ' ';\nexport function prepareQuery(original: string): IPreparedQuery {\n\tif (typeof original !== 'string') {\n\t\toriginal = '';\n\t}\n\n\tconst originalLowercase = original.toLowerCase();\n\tconst { pathNormalized, normalized, normalizedLowercase } = normalizeQuery(original);\n\tconst containsPathSeparator = pathNormalized.indexOf(sep) >= 0;\n\tconst expectExactMatch = queryExpectsExactMatch(original);\n\n\tlet values: IPreparedQueryPiece[] | undefined = undefined;\n\n\tconst originalSplit = original.split(MULTIPLE_QUERY_VALUES_SEPARATOR);\n\tif (originalSplit.length > 1) {\n\t\tfor (const originalPiece of originalSplit) {\n\t\t\tconst expectExactMatchPiece = queryExpectsExactMatch(originalPiece);\n\t\t\tconst {\n\t\t\t\tpathNormalized: pathNormalizedPiece,\n\t\t\t\tnormalized: normalizedPiece,\n\t\t\t\tnormalizedLowercase: normalizedLowercasePiece\n\t\t\t} = normalizeQuery(originalPiece);\n\n\t\t\tif (normalizedPiece) {\n\t\t\t\tif (!values) {\n\t\t\t\t\tvalues = [];\n\t\t\t\t}\n\n\t\t\t\tvalues.push({\n\t\t\t\t\toriginal: originalPiece,\n\t\t\t\t\toriginalLowercase: originalPiece.toLowerCase(),\n\t\t\t\t\tpathNormalized: pathNormalizedPiece,\n\t\t\t\t\tnormalized: normalizedPiece,\n\t\t\t\t\tnormalizedLowercase: normalizedLowercasePiece,\n\t\t\t\t\texpectContiguousMatch: expectExactMatchPiece\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { original, originalLowercase, pathNormalized, normalized, normalizedLowercase, values, containsPathSeparator, expectContiguousMatch: expectExactMatch };\n}\n\nfunction normalizeQuery(original: string): { pathNormalized: string, normalized: string, normalizedLowercase: string } {\n\tlet pathNormalized: string;\n\tif (isWindows) {\n\t\tpathNormalized = original.replace(/\\//g, sep); // Help Windows users to search for paths when using slash\n\t} else {\n\t\tpathNormalized = original.replace(/\\\\/g, sep); // Help macOS/Linux users to search for paths when using backslash\n\t}\n\n\t// we remove quotes here because quotes are used for exact match search\n\tconst normalized = stripWildcards(pathNormalized).replace(/\\s|\"/g, '');\n\n\treturn {\n\t\tpathNormalized,\n\t\tnormalized,\n\t\tnormalizedLowercase: normalized.toLowerCase()\n\t};\n}\n\nexport function pieceToQuery(piece: IPreparedQueryPiece): IPreparedQuery;\nexport function pieceToQuery(pieces: IPreparedQueryPiece[]): IPreparedQuery;\nexport function pieceToQuery(arg1: IPreparedQueryPiece | IPreparedQueryPiece[]): IPreparedQuery {\n\tif (Array.isArray(arg1)) {\n\t\treturn prepareQuery(arg1.map(piece => piece.original).join(MULTIPLE_QUERY_VALUES_SEPARATOR));\n\t}\n\n\treturn prepareQuery(arg1.original);\n}\n\n//#endregion\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { isThenable } from 'vs/base/common/async';\nimport { CharCode } from 'vs/base/common/charCode';\nimport { isEqualOrParent } from 'vs/base/common/extpath';\nimport { LRUCache } from 'vs/base/common/map';\nimport { basename, extname, posix, sep } from 'vs/base/common/path';\nimport { isLinux } from 'vs/base/common/platform';\nimport { escapeRegExpCharacters } from 'vs/base/common/strings';\n\nexport interface IExpression {\n\t[pattern: string]: boolean | SiblingClause;\n}\n\nexport interface IRelativePattern {\n\n\t/**\n\t * A base file path to which this pattern will be matched against relatively.\n\t */\n\treadonly base: string;\n\n\t/**\n\t * A file glob pattern like `*.{ts,js}` that will be matched on file paths\n\t * relative to the base path.\n\t *\n\t * Example: Given a base of `/home/work/folder` and a file path of `/home/work/folder/index.js`,\n\t * the file glob pattern will match on `index.js`.\n\t */\n\treadonly pattern: string;\n}\n\nexport interface SiblingClause {\n\twhen: string;\n}\n\nexport const GLOBSTAR = '**';\nexport const GLOB_SPLIT = '/';\n\nconst PATH_REGEX = '[/\\\\\\\\]';\t\t// any slash or backslash\nconst NO_PATH_REGEX = '[^/\\\\\\\\]';\t// any non-slash and non-backslash\nconst ALL_FORWARD_SLASHES = /\\//g;\n\nfunction starsToRegExp(starCount: number): string {\n\tswitch (starCount) {\n\t\tcase 0:\n\t\t\treturn '';\n\t\tcase 1:\n\t\t\treturn `${NO_PATH_REGEX}*?`; // 1 star matches any number of characters except path separator (/ and \\) - non greedy (?)\n\t\tdefault:\n\t\t\t// Matches: (Path Sep OR Path Val followed by Path Sep OR Path Sep followed by Path Val) 0-many times\n\t\t\t// Group is non capturing because we don't need to capture at all (?:...)\n\t\t\t// Overall we use non-greedy matching because it could be that we match too much\n\t\t\treturn `(?:${PATH_REGEX}|${NO_PATH_REGEX}+${PATH_REGEX}|${PATH_REGEX}${NO_PATH_REGEX}+)*?`;\n\t}\n}\n\nexport function splitGlobAware(pattern: string, splitChar: string): string[] {\n\tif (!pattern) {\n\t\treturn [];\n\t}\n\n\tconst segments: string[] = [];\n\n\tlet inBraces = false;\n\tlet inBrackets = false;\n\n\tlet curVal = '';\n\tfor (const char of pattern) {\n\t\tswitch (char) {\n\t\t\tcase splitChar:\n\t\t\t\tif (!inBraces && !inBrackets) {\n\t\t\t\t\tsegments.push(curVal);\n\t\t\t\t\tcurVal = '';\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase '{':\n\t\t\t\tinBraces = true;\n\t\t\t\tbreak;\n\t\t\tcase '}':\n\t\t\t\tinBraces = false;\n\t\t\t\tbreak;\n\t\t\tcase '[':\n\t\t\t\tinBrackets = true;\n\t\t\t\tbreak;\n\t\t\tcase ']':\n\t\t\t\tinBrackets = false;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tcurVal += char;\n\t}\n\n\t// Tail\n\tif (curVal) {\n\t\tsegments.push(curVal);\n\t}\n\n\treturn segments;\n}\n\nfunction parseRegExp(pattern: string): string {\n\tif (!pattern) {\n\t\treturn '';\n\t}\n\n\tlet regEx = '';\n\n\t// Split up into segments for each slash found\n\tconst segments = splitGlobAware(pattern, GLOB_SPLIT);\n\n\t// Special case where we only have globstars\n\tif (segments.every(s => s === GLOBSTAR)) {\n\t\tregEx = '.*';\n\t}\n\n\t// Build regex over segments\n\telse {\n\t\tlet previousSegmentWasGlobStar = false;\n\t\tsegments.forEach((segment, index) => {\n\n\t\t\t// Globstar is special\n\t\t\tif (segment === GLOBSTAR) {\n\n\t\t\t\t// if we have more than one globstar after another, just ignore it\n\t\t\t\tif (!previousSegmentWasGlobStar) {\n\t\t\t\t\tregEx += starsToRegExp(2);\n\t\t\t\t\tpreviousSegmentWasGlobStar = true;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// States\n\t\t\tlet inBraces = false;\n\t\t\tlet braceVal = '';\n\n\t\t\tlet inBrackets = false;\n\t\t\tlet bracketVal = '';\n\n\t\t\tfor (const char of segment) {\n\t\t\t\t// Support brace expansion\n\t\t\t\tif (char !== '}' && inBraces) {\n\t\t\t\t\tbraceVal += char;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Support brackets\n\t\t\t\tif (inBrackets && (char !== ']' || !bracketVal) /* ] is literally only allowed as first character in brackets to match it */) {\n\t\t\t\t\tlet res: string;\n\n\t\t\t\t\t// range operator\n\t\t\t\t\tif (char === '-') {\n\t\t\t\t\t\tres = char;\n\t\t\t\t\t}\n\n\t\t\t\t\t// negation operator (only valid on first index in bracket)\n\t\t\t\t\telse if ((char === '^' || char === '!') && !bracketVal) {\n\t\t\t\t\t\tres = '^';\n\t\t\t\t\t}\n\n\t\t\t\t\t// glob split matching is not allowed within character ranges\n\t\t\t\t\t// see http://man7.org/linux/man-pages/man7/glob.7.html\n\t\t\t\t\telse if (char === GLOB_SPLIT) {\n\t\t\t\t\t\tres = '';\n\t\t\t\t\t}\n\n\t\t\t\t\t// anything else gets escaped\n\t\t\t\t\telse {\n\t\t\t\t\t\tres = escapeRegExpCharacters(char);\n\t\t\t\t\t}\n\n\t\t\t\t\tbracketVal += res;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tswitch (char) {\n\t\t\t\t\tcase '{':\n\t\t\t\t\t\tinBraces = true;\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\tcase '[':\n\t\t\t\t\t\tinBrackets = true;\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\tcase '}': {\n\t\t\t\t\t\tconst choices = splitGlobAware(braceVal, ',');\n\n\t\t\t\t\t\t// Converts {foo,bar} => [foo|bar]\n\t\t\t\t\t\tconst braceRegExp = `(?:${choices.map(c => parseRegExp(c)).join('|')})`;\n\n\t\t\t\t\t\tregEx += braceRegExp;\n\n\t\t\t\t\t\tinBraces = false;\n\t\t\t\t\t\tbraceVal = '';\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase ']':\n\t\t\t\t\t\tregEx += ('[' + bracketVal + ']');\n\n\t\t\t\t\t\tinBrackets = false;\n\t\t\t\t\t\tbracketVal = '';\n\n\t\t\t\t\t\tbreak;\n\n\n\t\t\t\t\tcase '?':\n\t\t\t\t\t\tregEx += NO_PATH_REGEX; // 1 ? matches any single character except path separator (/ and \\)\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\tcase '*':\n\t\t\t\t\t\tregEx += starsToRegExp(1);\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tregEx += escapeRegExpCharacters(char);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Tail: Add the slash we had split on if there is more to come and the remaining pattern is not a globstar\n\t\t\t// For example if pattern: some/**/*.js we want the \"/\" after some to be included in the RegEx to prevent\n\t\t\t// a folder called \"something\" to match as well.\n\t\t\t// However, if pattern: some/**, we tolerate that we also match on \"something\" because our globstar behaviour\n\t\t\t// is to match 0-N segments.\n\t\t\tif (index < segments.length - 1 && (segments[index + 1] !== GLOBSTAR || index + 2 < segments.length)) {\n\t\t\t\tregEx += PATH_REGEX;\n\t\t\t}\n\n\t\t\t// reset state\n\t\t\tpreviousSegmentWasGlobStar = false;\n\t\t});\n\t}\n\n\treturn regEx;\n}\n\n// regexes to check for trivial glob patterns that just check for String#endsWith\nconst T1 = /^\\*\\*\\/\\*\\.[\\w\\.-]+$/; \t\t\t\t\t\t \t\t\t\t\t\t\t\t\t// **/*.something\nconst T2 = /^\\*\\*\\/([\\w\\.-]+)\\/?$/; \t\t\t\t\t\t\t \t\t\t\t\t\t\t// **/something\nconst T3 = /^{\\*\\*\\/[\\*\\.]?[\\w\\.-]+\\/?(,\\*\\*\\/[\\*\\.]?[\\w\\.-]+\\/?)*}$/; \t\t\t\t\t\t// {**/*.something,**/*.else} or {**/package.json,**/project.json}\nconst T3_2 = /^{\\*\\*\\/[\\*\\.]?[\\w\\.-]+(\\/(\\*\\*)?)?(,\\*\\*\\/[\\*\\.]?[\\w\\.-]+(\\/(\\*\\*)?)?)*}$/; \t// Like T3, with optional trailing /**\nconst T4 = /^\\*\\*((\\/[\\w\\.-]+)+)\\/?$/; \t\t\t\t\t\t \t\t\t\t\t\t\t\t// **/something/else\nconst T5 = /^([\\w\\.-]+(\\/[\\w\\.-]+)*)\\/?$/; \t\t\t\t\t\t \t\t\t\t\t\t\t// something/else\n\nexport type ParsedPattern = (path: string, basename?: string) => boolean;\n\n// The `ParsedExpression` returns a `Promise`\n// iff `hasSibling` returns a `Promise`.\nexport type ParsedExpression = (path: string, basename?: string, hasSibling?: (name: string) => boolean | Promise) => string | null | Promise /* the matching pattern */;\n\nexport interface IGlobOptions {\n\n\t/**\n\t * Simplify patterns for use as exclusion filters during\n\t * tree traversal to skip entire subtrees. Cannot be used\n\t * outside of a tree traversal.\n\t */\n\ttrimForExclusions?: boolean;\n}\n\ninterface ParsedStringPattern {\n\t(path: string, basename?: string): string | null | Promise /* the matching pattern */;\n\tbasenames?: string[];\n\tpatterns?: string[];\n\tallBasenames?: string[];\n\tallPaths?: string[];\n}\ninterface ParsedExpressionPattern {\n\t(path: string, basename?: string, name?: string, hasSibling?: (name: string) => boolean | Promise): string | null | Promise /* the matching pattern */;\n\trequiresSiblings?: boolean;\n\tallPaths?: string[];\n}\n\nconst CACHE = new LRUCache(10000); // bounded to 10000 elements\n\nconst FALSE = function () {\n\treturn false;\n};\n\nconst NULL = function (): string | null {\n\treturn null;\n};\n\nfunction parsePattern(arg1: string | IRelativePattern, options: IGlobOptions): ParsedStringPattern {\n\tif (!arg1) {\n\t\treturn NULL;\n\t}\n\n\t// Handle IRelativePattern\n\tlet pattern: string;\n\tif (typeof arg1 !== 'string') {\n\t\tpattern = arg1.pattern;\n\t} else {\n\t\tpattern = arg1;\n\t}\n\n\t// Whitespace trimming\n\tpattern = pattern.trim();\n\n\t// Check cache\n\tconst patternKey = `${pattern}_${!!options.trimForExclusions}`;\n\tlet parsedPattern = CACHE.get(patternKey);\n\tif (parsedPattern) {\n\t\treturn wrapRelativePattern(parsedPattern, arg1);\n\t}\n\n\t// Check for Trivials\n\tlet match: RegExpExecArray | null;\n\tif (T1.test(pattern)) { // common pattern: **/*.txt just need endsWith check\n\t\tconst base = pattern.substr(4); // '**/*'.length === 4\n\t\tparsedPattern = function (path, basename) {\n\t\t\treturn typeof path === 'string' && path.endsWith(base) ? pattern : null;\n\t\t};\n\t} else if (match = T2.exec(trimForExclusions(pattern, options))) { // common pattern: **/some.txt just need basename check\n\t\tparsedPattern = trivia2(match[1], pattern);\n\t} else if ((options.trimForExclusions ? T3_2 : T3).test(pattern)) { // repetition of common patterns (see above) {**/*.txt,**/*.png}\n\t\tparsedPattern = trivia3(pattern, options);\n\t} else if (match = T4.exec(trimForExclusions(pattern, options))) { // common pattern: **/something/else just need endsWith check\n\t\tparsedPattern = trivia4and5(match[1].substr(1), pattern, true);\n\t} else if (match = T5.exec(trimForExclusions(pattern, options))) { // common pattern: something/else just need equals check\n\t\tparsedPattern = trivia4and5(match[1], pattern, false);\n\t}\n\n\t// Otherwise convert to pattern\n\telse {\n\t\tparsedPattern = toRegExp(pattern);\n\t}\n\n\t// Cache\n\tCACHE.set(patternKey, parsedPattern);\n\n\treturn wrapRelativePattern(parsedPattern, arg1);\n}\n\nfunction wrapRelativePattern(parsedPattern: ParsedStringPattern, arg2: string | IRelativePattern): ParsedStringPattern {\n\tif (typeof arg2 === 'string') {\n\t\treturn parsedPattern;\n\t}\n\n\treturn function (path, basename) {\n\t\tif (!isEqualOrParent(path, arg2.base, !isLinux)) {\n\t\t\t// skip glob matching if `base` is not a parent of `path`\n\t\t\treturn null;\n\t\t}\n\n\t\t// Given we have checked `base` being a parent of `path`,\n\t\t// we can now remove the `base` portion of the `path`\n\t\t// and only match on the remaining path components\n\t\treturn parsedPattern(path.substr(arg2.base.length + 1), basename);\n\t};\n}\n\nfunction trimForExclusions(pattern: string, options: IGlobOptions): string {\n\treturn options.trimForExclusions && pattern.endsWith('/**') ? pattern.substr(0, pattern.length - 2) : pattern; // dropping **, tailing / is dropped later\n}\n\n// common pattern: **/some.txt just need basename check\nfunction trivia2(base: string, originalPattern: string): ParsedStringPattern {\n\tconst slashBase = `/${base}`;\n\tconst backslashBase = `\\\\${base}`;\n\tconst parsedPattern: ParsedStringPattern = function (path, basename) {\n\t\tif (typeof path !== 'string') {\n\t\t\treturn null;\n\t\t}\n\t\tif (basename) {\n\t\t\treturn basename === base ? originalPattern : null;\n\t\t}\n\t\treturn path === base || path.endsWith(slashBase) || path.endsWith(backslashBase) ? originalPattern : null;\n\t};\n\tconst basenames = [base];\n\tparsedPattern.basenames = basenames;\n\tparsedPattern.patterns = [originalPattern];\n\tparsedPattern.allBasenames = basenames;\n\treturn parsedPattern;\n}\n\n// repetition of common patterns (see above) {**/*.txt,**/*.png}\nfunction trivia3(pattern: string, options: IGlobOptions): ParsedStringPattern {\n\tconst parsedPatterns = aggregateBasenameMatches(pattern.slice(1, -1).split(',')\n\t\t.map(pattern => parsePattern(pattern, options))\n\t\t.filter(pattern => pattern !== NULL), pattern);\n\tconst n = parsedPatterns.length;\n\tif (!n) {\n\t\treturn NULL;\n\t}\n\tif (n === 1) {\n\t\treturn parsedPatterns[0];\n\t}\n\tconst parsedPattern: ParsedStringPattern = function (path: string, basename?: string) {\n\t\tfor (let i = 0, n = parsedPatterns.length; i < n; i++) {\n\t\t\tif ((parsedPatterns[i])(path, basename)) {\n\t\t\t\treturn pattern;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t};\n\tconst withBasenames = parsedPatterns.find(pattern => !!(pattern).allBasenames);\n\tif (withBasenames) {\n\t\tparsedPattern.allBasenames = (withBasenames).allBasenames;\n\t}\n\tconst allPaths = parsedPatterns.reduce((all, current) => current.allPaths ? all.concat(current.allPaths) : all, []);\n\tif (allPaths.length) {\n\t\tparsedPattern.allPaths = allPaths;\n\t}\n\treturn parsedPattern;\n}\n\n// common patterns: **/something/else just need endsWith check, something/else just needs and equals check\nfunction trivia4and5(targetPath: string, pattern: string, matchPathEnds: boolean): ParsedStringPattern {\n\tconst usingPosixSep = sep === posix.sep;\n\tconst nativePath = usingPosixSep ? targetPath : targetPath.replace(ALL_FORWARD_SLASHES, sep);\n\tconst nativePathEnd = sep + nativePath;\n\tconst targetPathEnd = posix.sep + targetPath;\n\n\tconst parsedPattern: ParsedStringPattern = matchPathEnds ? function (testPath, basename) {\n\t\treturn typeof testPath === 'string' &&\n\t\t\t((testPath === nativePath || testPath.endsWith(nativePathEnd))\n\t\t\t\t|| !usingPosixSep && (testPath === targetPath || testPath.endsWith(targetPathEnd)))\n\t\t\t? pattern : null;\n\t} : function (testPath, basename) {\n\t\treturn typeof testPath === 'string' &&\n\t\t\t(testPath === nativePath\n\t\t\t\t|| (!usingPosixSep && testPath === targetPath))\n\t\t\t? pattern : null;\n\t};\n\tparsedPattern.allPaths = [(matchPathEnds ? '*/' : './') + targetPath];\n\treturn parsedPattern;\n}\n\nfunction toRegExp(pattern: string): ParsedStringPattern {\n\ttry {\n\t\tconst regExp = new RegExp(`^${parseRegExp(pattern)}$`);\n\t\treturn function (path: string) {\n\t\t\tregExp.lastIndex = 0; // reset RegExp to its initial state to reuse it!\n\t\t\treturn typeof path === 'string' && regExp.test(path) ? pattern : null;\n\t\t};\n\t} catch (error) {\n\t\treturn NULL;\n\t}\n}\n\n/**\n * Simplified glob matching. Supports a subset of glob patterns:\n * * `*` to match one or more characters in a path segment\n * * `?` to match on one character in a path segment\n * * `**` to match any number of path segments, including none\n * * `{}` to group conditions (e.g. *.{ts,js} matches all TypeScript and JavaScript files)\n * * `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)\n * * `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)\n */\nexport function match(pattern: string | IRelativePattern, path: string): boolean;\nexport function match(expression: IExpression, path: string, hasSibling?: (name: string) => boolean): string /* the matching pattern */;\nexport function match(arg1: string | IExpression | IRelativePattern, path: string, hasSibling?: (name: string) => boolean): boolean | string | null | Promise {\n\tif (!arg1 || typeof path !== 'string') {\n\t\treturn false;\n\t}\n\n\treturn parse(arg1)(path, undefined, hasSibling);\n}\n\n/**\n * Simplified glob matching. Supports a subset of glob patterns:\n * * `*` to match one or more characters in a path segment\n * * `?` to match on one character in a path segment\n * * `**` to match any number of path segments, including none\n * * `{}` to group conditions (e.g. *.{ts,js} matches all TypeScript and JavaScript files)\n * * `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)\n * * `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)\n */\nexport function parse(pattern: string | IRelativePattern, options?: IGlobOptions): ParsedPattern;\nexport function parse(expression: IExpression, options?: IGlobOptions): ParsedExpression;\nexport function parse(arg1: string | IExpression | IRelativePattern, options: IGlobOptions = {}): ParsedPattern | ParsedExpression {\n\tif (!arg1) {\n\t\treturn FALSE;\n\t}\n\n\t// Glob with String\n\tif (typeof arg1 === 'string' || isRelativePattern(arg1)) {\n\t\tconst parsedPattern = parsePattern(arg1, options);\n\t\tif (parsedPattern === NULL) {\n\t\t\treturn FALSE;\n\t\t}\n\t\tconst resultPattern: ParsedPattern & { allBasenames?: string[]; allPaths?: string[]; } = function (path: string, basename?: string) {\n\t\t\treturn !!parsedPattern(path, basename);\n\t\t};\n\t\tif (parsedPattern.allBasenames) {\n\t\t\tresultPattern.allBasenames = parsedPattern.allBasenames;\n\t\t}\n\t\tif (parsedPattern.allPaths) {\n\t\t\tresultPattern.allPaths = parsedPattern.allPaths;\n\t\t}\n\t\treturn resultPattern;\n\t}\n\n\t// Glob with Expression\n\treturn parsedExpression(arg1, options);\n}\n\nexport function isRelativePattern(obj: unknown): obj is IRelativePattern {\n\tconst rp = obj as IRelativePattern | undefined | null;\n\tif (!rp) {\n\t\treturn false;\n\t}\n\n\treturn typeof rp.base === 'string' && typeof rp.pattern === 'string';\n}\n\nfunction parsedExpression(expression: IExpression, options: IGlobOptions): ParsedExpression {\n\tconst parsedPatterns = aggregateBasenameMatches(Object.getOwnPropertyNames(expression)\n\t\t.map(pattern => parseExpressionPattern(pattern, expression[pattern], options))\n\t\t.filter(pattern => pattern !== NULL));\n\n\tconst n = parsedPatterns.length;\n\tif (!n) {\n\t\treturn NULL;\n\t}\n\n\tif (!parsedPatterns.some(parsedPattern => !!(parsedPattern).requiresSiblings)) {\n\t\tif (n === 1) {\n\t\t\treturn parsedPatterns[0];\n\t\t}\n\n\t\tconst resultExpression: ParsedStringPattern = function (path: string, basename?: string) {\n\t\t\tfor (let i = 0, n = parsedPatterns.length; i < n; i++) {\n\t\t\t\t// Pattern matches path\n\t\t\t\tconst result = (parsedPatterns[i])(path, basename);\n\t\t\t\tif (result) {\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t};\n\n\t\tconst withBasenames = parsedPatterns.find(pattern => !!(pattern).allBasenames);\n\t\tif (withBasenames) {\n\t\t\tresultExpression.allBasenames = (withBasenames).allBasenames;\n\t\t}\n\n\t\tconst allPaths = parsedPatterns.reduce((all, current) => current.allPaths ? all.concat(current.allPaths) : all, []);\n\t\tif (allPaths.length) {\n\t\t\tresultExpression.allPaths = allPaths;\n\t\t}\n\n\t\treturn resultExpression;\n\t}\n\n\tconst resultExpression: ParsedStringPattern = function (path: string, base?: string, hasSibling?: (name: string) => boolean | Promise) {\n\t\tlet name: string | undefined = undefined;\n\n\t\tfor (let i = 0, n = parsedPatterns.length; i < n; i++) {\n\t\t\t// Pattern matches path\n\t\t\tconst parsedPattern = (parsedPatterns[i]);\n\t\t\tif (parsedPattern.requiresSiblings && hasSibling) {\n\t\t\t\tif (!base) {\n\t\t\t\t\tbase = basename(path);\n\t\t\t\t}\n\t\t\t\tif (!name) {\n\t\t\t\t\tname = base.substr(0, base.length - extname(path).length);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst result = parsedPattern(path, base, name, hasSibling);\n\t\t\tif (result) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t};\n\n\tconst withBasenames = parsedPatterns.find(pattern => !!(pattern).allBasenames);\n\tif (withBasenames) {\n\t\tresultExpression.allBasenames = (withBasenames).allBasenames;\n\t}\n\n\tconst allPaths = parsedPatterns.reduce((all, current) => current.allPaths ? all.concat(current.allPaths) : all, []);\n\tif (allPaths.length) {\n\t\tresultExpression.allPaths = allPaths;\n\t}\n\n\treturn resultExpression;\n}\n\nfunction parseExpressionPattern(pattern: string, value: boolean | SiblingClause, options: IGlobOptions): (ParsedStringPattern | ParsedExpressionPattern) {\n\tif (value === false) {\n\t\treturn NULL; // pattern is disabled\n\t}\n\n\tconst parsedPattern = parsePattern(pattern, options);\n\tif (parsedPattern === NULL) {\n\t\treturn NULL;\n\t}\n\n\t// Expression Pattern is \n\tif (typeof value === 'boolean') {\n\t\treturn parsedPattern;\n\t}\n\n\t// Expression Pattern is \n\tif (value) {\n\t\tconst when = (value).when;\n\t\tif (typeof when === 'string') {\n\t\t\tconst result: ParsedExpressionPattern = (path: string, basename?: string, name?: string, hasSibling?: (name: string) => boolean | Promise) => {\n\t\t\t\tif (!hasSibling || !parsedPattern(path, basename)) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst clausePattern = when.replace('$(basename)', name!);\n\t\t\t\tconst matched = hasSibling(clausePattern);\n\t\t\t\treturn isThenable(matched) ?\n\t\t\t\t\tmatched.then(m => m ? pattern : null) :\n\t\t\t\t\tmatched ? pattern : null;\n\t\t\t};\n\t\t\tresult.requiresSiblings = true;\n\t\t\treturn result;\n\t\t}\n\t}\n\n\t// Expression is Anything\n\treturn parsedPattern;\n}\n\nfunction aggregateBasenameMatches(parsedPatterns: Array, result?: string): Array {\n\tconst basenamePatterns = parsedPatterns.filter(parsedPattern => !!(parsedPattern).basenames);\n\tif (basenamePatterns.length < 2) {\n\t\treturn parsedPatterns;\n\t}\n\n\tconst basenames = basenamePatterns.reduce((all, current) => {\n\t\tconst basenames = (current).basenames;\n\t\treturn basenames ? all.concat(basenames) : all;\n\t}, []);\n\tlet patterns: string[];\n\tif (result) {\n\t\tpatterns = [];\n\t\tfor (let i = 0, n = basenames.length; i < n; i++) {\n\t\t\tpatterns.push(result);\n\t\t}\n\t} else {\n\t\tpatterns = basenamePatterns.reduce((all, current) => {\n\t\t\tconst patterns = (current).patterns;\n\t\t\treturn patterns ? all.concat(patterns) : all;\n\t\t}, []);\n\t}\n\tconst aggregate: ParsedStringPattern = function (path, basename) {\n\t\tif (typeof path !== 'string') {\n\t\t\treturn null;\n\t\t}\n\t\tif (!basename) {\n\t\t\tlet i: number;\n\t\t\tfor (i = path.length; i > 0; i--) {\n\t\t\t\tconst ch = path.charCodeAt(i - 1);\n\t\t\t\tif (ch === CharCode.Slash || ch === CharCode.Backslash) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbasename = path.substr(i);\n\t\t}\n\t\tconst index = basenames.indexOf(basename);\n\t\treturn index !== -1 ? patterns[index] : null;\n\t};\n\taggregate.basenames = basenames;\n\taggregate.patterns = patterns;\n\taggregate.allBasenames = basenames;\n\n\tconst aggregatedPatterns = parsedPatterns.filter(parsedPattern => !(parsedPattern).basenames);\n\taggregatedPatterns.push(aggregate);\n\n\treturn aggregatedPatterns;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CSSIcon } from 'vs/base/common/codicons';\nimport { IMatch, matchesFuzzy } from 'vs/base/common/filters';\nimport { ltrim } from 'vs/base/common/strings';\n\nexport const iconStartMarker = '$(';\n\nconst iconsRegex = new RegExp(`\\\\$\\\\(${CSSIcon.iconNameExpression}(?:${CSSIcon.iconModifierExpression})?\\\\)`, 'g'); // no capturing groups\nconst iconNameCharacterRegexp = new RegExp(CSSIcon.iconNameCharacter);\n\nconst escapeIconsRegex = new RegExp(`(\\\\\\\\)?${iconsRegex.source}`, 'g');\nexport function escapeIcons(text: string): string {\n\treturn text.replace(escapeIconsRegex, (match, escaped) => escaped ? match : `\\\\${match}`);\n}\n\nconst markdownEscapedIconsRegex = new RegExp(`\\\\\\\\${iconsRegex.source}`, 'g');\nexport function markdownEscapeEscapedIcons(text: string): string {\n\t// Need to add an extra \\ for escaping in markdown\n\treturn text.replace(markdownEscapedIconsRegex, match => `\\\\${match}`);\n}\n\nconst stripIconsRegex = new RegExp(`(\\\\s)?(\\\\\\\\)?${iconsRegex.source}(\\\\s)?`, 'g');\nexport function stripIcons(text: string): string {\n\tif (text.indexOf(iconStartMarker) === -1) {\n\t\treturn text;\n\t}\n\n\treturn text.replace(stripIconsRegex, (match, preWhitespace, escaped, postWhitespace) => escaped ? match : preWhitespace || postWhitespace || '');\n}\n\n\nexport interface IParsedLabelWithIcons {\n\treadonly text: string;\n\treadonly iconOffsets?: readonly number[];\n}\n\nexport function parseLabelWithIcons(text: string): IParsedLabelWithIcons {\n\tconst firstIconIndex = text.indexOf(iconStartMarker);\n\tif (firstIconIndex === -1) {\n\t\treturn { text }; // return early if the word does not include an icon\n\t}\n\n\treturn doParseLabelWithIcons(text, firstIconIndex);\n}\n\nfunction doParseLabelWithIcons(text: string, firstIconIndex: number): IParsedLabelWithIcons {\n\tconst iconOffsets: number[] = [];\n\tlet textWithoutIcons: string = '';\n\n\tfunction appendChars(chars: string) {\n\t\tif (chars) {\n\t\t\ttextWithoutIcons += chars;\n\n\t\t\tfor (const _ of chars) {\n\t\t\t\ticonOffsets.push(iconsOffset); // make sure to fill in icon offsets\n\t\t\t}\n\t\t}\n\t}\n\n\tlet currentIconStart = -1;\n\tlet currentIconValue: string = '';\n\tlet iconsOffset = 0;\n\n\tlet char: string;\n\tlet nextChar: string;\n\n\tlet offset = firstIconIndex;\n\tconst length = text.length;\n\n\t// Append all characters until the first icon\n\tappendChars(text.substr(0, firstIconIndex));\n\n\t// example: $(file-symlink-file) my cool $(other-icon) entry\n\twhile (offset < length) {\n\t\tchar = text[offset];\n\t\tnextChar = text[offset + 1];\n\n\t\t// beginning of icon: some value $( <--\n\t\tif (char === iconStartMarker[0] && nextChar === iconStartMarker[1]) {\n\t\t\tcurrentIconStart = offset;\n\n\t\t\t// if we had a previous potential icon value without\n\t\t\t// the closing ')', it was actually not an icon and\n\t\t\t// so we have to add it to the actual value\n\t\t\tappendChars(currentIconValue);\n\n\t\t\tcurrentIconValue = iconStartMarker;\n\n\t\t\toffset++; // jump over '('\n\t\t}\n\n\t\t// end of icon: some value $(some-icon) <--\n\t\telse if (char === ')' && currentIconStart !== -1) {\n\t\t\tconst currentIconLength = offset - currentIconStart + 1; // +1 to include the closing ')'\n\t\t\ticonsOffset += currentIconLength;\n\t\t\tcurrentIconStart = -1;\n\t\t\tcurrentIconValue = '';\n\t\t}\n\n\t\t// within icon\n\t\telse if (currentIconStart !== -1) {\n\t\t\t// Make sure this is a real icon name\n\t\t\tif (iconNameCharacterRegexp.test(char)) {\n\t\t\t\tcurrentIconValue += char;\n\t\t\t} else {\n\t\t\t\t// This is not a real icon, treat it as text\n\t\t\t\tappendChars(currentIconValue);\n\n\t\t\t\tcurrentIconStart = -1;\n\t\t\t\tcurrentIconValue = '';\n\t\t\t}\n\t\t}\n\n\t\t// any value outside of icon\n\t\telse {\n\t\t\tappendChars(char);\n\t\t}\n\n\t\toffset++;\n\t}\n\n\t// if we had a previous potential icon value without\n\t// the closing ')', it was actually not an icon and\n\t// so we have to add it to the actual value\n\tappendChars(currentIconValue);\n\n\treturn { text: textWithoutIcons, iconOffsets };\n}\n\nexport function matchesFuzzyIconAware(query: string, target: IParsedLabelWithIcons, enableSeparateSubstringMatching = false): IMatch[] | null {\n\tconst { text, iconOffsets } = target;\n\n\t// Return early if there are no icon markers in the word to match against\n\tif (!iconOffsets || iconOffsets.length === 0) {\n\t\treturn matchesFuzzy(query, text, enableSeparateSubstringMatching);\n\t}\n\n\t// Trim the word to match against because it could have leading\n\t// whitespace now if the word started with an icon\n\tconst wordToMatchAgainstWithoutIconsTrimmed = ltrim(text, ' ');\n\tconst leadingWhitespaceOffset = text.length - wordToMatchAgainstWithoutIconsTrimmed.length;\n\n\t// match on value without icon\n\tconst matches = matchesFuzzy(query, wordToMatchAgainstWithoutIconsTrimmed, enableSeparateSubstringMatching);\n\n\t// Map matches back to offsets with icon and trimming\n\tif (matches) {\n\t\tfor (const match of matches) {\n\t\t\tconst iconOffset = iconOffsets[match.start + leadingWhitespaceOffset] /* icon offsets at index */ + leadingWhitespaceOffset /* overall leading whitespace offset */;\n\t\t\tmatch.start += iconOffset;\n\t\t\tmatch.end += iconOffset;\n\t\t}\n\t}\n\n\treturn matches;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { illegalArgument } from 'vs/base/common/errors';\nimport { escapeIcons } from 'vs/base/common/iconLabels';\nimport { UriComponents } from 'vs/base/common/uri';\n\nexport interface IMarkdownString {\n\treadonly value: string;\n\treadonly isTrusted?: boolean;\n\treadonly supportThemeIcons?: boolean;\n\treadonly supportHtml?: boolean;\n\turis?: { [href: string]: UriComponents };\n}\n\nexport const enum MarkdownStringTextNewlineStyle {\n\tParagraph = 0,\n\tBreak = 1,\n}\n\nexport class MarkdownString implements IMarkdownString {\n\n\tpublic value: string;\n\tpublic isTrusted?: boolean;\n\tpublic supportThemeIcons?: boolean;\n\tpublic supportHtml?: boolean;\n\n\tconstructor(\n\t\tvalue: string = '',\n\t\tisTrustedOrOptions: boolean | { isTrusted?: boolean, supportThemeIcons?: boolean, supportHtml?: boolean } = false,\n\t) {\n\t\tthis.value = value;\n\t\tif (typeof this.value !== 'string') {\n\t\t\tthrow illegalArgument('value');\n\t\t}\n\n\t\tif (typeof isTrustedOrOptions === 'boolean') {\n\t\t\tthis.isTrusted = isTrustedOrOptions;\n\t\t\tthis.supportThemeIcons = false;\n\t\t\tthis.supportHtml = false;\n\t\t}\n\t\telse {\n\t\t\tthis.isTrusted = isTrustedOrOptions.isTrusted ?? undefined;\n\t\t\tthis.supportThemeIcons = isTrustedOrOptions.supportThemeIcons ?? false;\n\t\t\tthis.supportHtml = isTrustedOrOptions.supportHtml ?? false;\n\t\t}\n\t}\n\n\tappendText(value: string, newlineStyle: MarkdownStringTextNewlineStyle = MarkdownStringTextNewlineStyle.Paragraph): MarkdownString {\n\t\tthis.value += escapeMarkdownSyntaxTokens(this.supportThemeIcons ? escapeIcons(value) : value)\n\t\t\t.replace(/([ \\t]+)/g, (_match, g1) => ' '.repeat(g1.length))\n\t\t\t.replace(/\\>/gm, '\\\\>')\n\t\t\t.replace(/\\n/g, newlineStyle === MarkdownStringTextNewlineStyle.Break ? '\\\\\\n' : '\\n\\n');\n\n\t\treturn this;\n\t}\n\n\tappendMarkdown(value: string): MarkdownString {\n\t\tthis.value += value;\n\t\treturn this;\n\t}\n\n\tappendCodeblock(langId: string, code: string): MarkdownString {\n\t\tthis.value += '\\n```';\n\t\tthis.value += langId;\n\t\tthis.value += '\\n';\n\t\tthis.value += code;\n\t\tthis.value += '\\n```\\n';\n\t\treturn this;\n\t}\n}\n\nexport function isEmptyMarkdownString(oneOrMany: IMarkdownString | IMarkdownString[] | null | undefined): boolean {\n\tif (isMarkdownString(oneOrMany)) {\n\t\treturn !oneOrMany.value;\n\t} else if (Array.isArray(oneOrMany)) {\n\t\treturn oneOrMany.every(isEmptyMarkdownString);\n\t} else {\n\t\treturn true;\n\t}\n}\n\nexport function isMarkdownString(thing: any): thing is IMarkdownString {\n\tif (thing instanceof MarkdownString) {\n\t\treturn true;\n\t} else if (thing && typeof thing === 'object') {\n\t\treturn typeof (thing).value === 'string'\n\t\t\t&& (typeof (thing).isTrusted === 'boolean' || (thing).isTrusted === undefined)\n\t\t\t&& (typeof (thing).supportThemeIcons === 'boolean' || (thing).supportThemeIcons === undefined);\n\t}\n\treturn false;\n}\n\nexport function escapeMarkdownSyntaxTokens(text: string): string {\n\t// escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash\n\treturn text.replace(/[\\\\`*_{}[\\]()#+\\-!]/g, '\\\\$&');\n}\n\nexport function removeMarkdownEscapes(text: string): string {\n\tif (!text) {\n\t\treturn text;\n\t}\n\treturn text.replace(/\\\\([\\\\`*_{}[\\]()#+\\-.!])/g, '$1');\n}\n\nexport function parseHrefAndDimensions(href: string): { href: string, dimensions: string[] } {\n\tconst dimensions: string[] = [];\n\tconst splitted = href.split('|').map(s => s.trim());\n\thref = splitted[0];\n\tconst parameters = splitted[1];\n\tif (parameters) {\n\t\tconst heightFromParams = /height=(\\d+)/.exec(parameters);\n\t\tconst widthFromParams = /width=(\\d+)/.exec(parameters);\n\t\tconst height = heightFromParams ? heightFromParams[1] : '';\n\t\tconst width = widthFromParams ? widthFromParams[1] : '';\n\t\tconst widthIsFinite = isFinite(parseInt(width));\n\t\tconst heightIsFinite = isFinite(parseInt(height));\n\t\tif (widthIsFinite) {\n\t\t\tdimensions.push(`width=\"${width}\"`);\n\t\t}\n\t\tif (heightIsFinite) {\n\t\t\tdimensions.push(`height=\"${height}\"`);\n\t\t}\n\t}\n\treturn { href, dimensions };\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as strings from './strings';\n\nexport function buildReplaceStringWithCasePreserved(matches: string[] | null, pattern: string): string {\n\tif (matches && (matches[0] !== '')) {\n\t\tconst containsHyphens = validateSpecificSpecialCharacter(matches, pattern, '-');\n\t\tconst containsUnderscores = validateSpecificSpecialCharacter(matches, pattern, '_');\n\t\tif (containsHyphens && !containsUnderscores) {\n\t\t\treturn buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '-');\n\t\t} else if (!containsHyphens && containsUnderscores) {\n\t\t\treturn buildReplaceStringForSpecificSpecialCharacter(matches, pattern, '_');\n\t\t}\n\t\tif (matches[0].toUpperCase() === matches[0]) {\n\t\t\treturn pattern.toUpperCase();\n\t\t} else if (matches[0].toLowerCase() === matches[0]) {\n\t\t\treturn pattern.toLowerCase();\n\t\t} else if (strings.containsUppercaseCharacter(matches[0][0]) && pattern.length > 0) {\n\t\t\treturn pattern[0].toUpperCase() + pattern.substr(1);\n\t\t} else if (matches[0][0].toUpperCase() !== matches[0][0] && pattern.length > 0) {\n\t\t\treturn pattern[0].toLowerCase() + pattern.substr(1);\n\t\t} else {\n\t\t\t// we don't understand its pattern yet.\n\t\t\treturn pattern;\n\t\t}\n\t} else {\n\t\treturn pattern;\n\t}\n}\n\nfunction validateSpecificSpecialCharacter(matches: string[], pattern: string, specialCharacter: string): boolean {\n\tconst doesContainSpecialCharacter = matches[0].indexOf(specialCharacter) !== -1 && pattern.indexOf(specialCharacter) !== -1;\n\treturn doesContainSpecialCharacter && matches[0].split(specialCharacter).length === pattern.split(specialCharacter).length;\n}\n\nfunction buildReplaceStringForSpecificSpecialCharacter(matches: string[], pattern: string, specialCharacter: string): string {\n\tconst splitPatternAtSpecialCharacter = pattern.split(specialCharacter);\n\tconst splitMatchAtSpecialCharacter = matches[0].split(specialCharacter);\n\tlet replaceString: string = '';\n\tsplitPatternAtSpecialCharacter.forEach((splitValue, index) => {\n\t\treplaceString += buildReplaceStringWithCasePreserved([splitMatchAtSpecialCharacter[index]], splitValue) + specialCharacter;\n\t});\n\n\treturn replaceString.slice(0, -1);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as strings from 'vs/base/common/strings';\n\nenum Severity {\n\tIgnore = 0,\n\tInfo = 1,\n\tWarning = 2,\n\tError = 3\n}\n\nnamespace Severity {\n\n\tconst _error = 'error';\n\tconst _warning = 'warning';\n\tconst _warn = 'warn';\n\tconst _info = 'info';\n\tconst _ignore = 'ignore';\n\n\t/**\n\t * Parses 'error', 'warning', 'warn', 'info' in call casings\n\t * and falls back to ignore.\n\t */\n\texport function fromValue(value: string): Severity {\n\t\tif (!value) {\n\t\t\treturn Severity.Ignore;\n\t\t}\n\n\t\tif (strings.equalsIgnoreCase(_error, value)) {\n\t\t\treturn Severity.Error;\n\t\t}\n\n\t\tif (strings.equalsIgnoreCase(_warning, value) || strings.equalsIgnoreCase(_warn, value)) {\n\t\t\treturn Severity.Warning;\n\t\t}\n\n\t\tif (strings.equalsIgnoreCase(_info, value)) {\n\t\t\treturn Severity.Info;\n\t\t}\n\t\treturn Severity.Ignore;\n\t}\n\n\texport function toString(severity: Severity): string {\n\t\tswitch (severity) {\n\t\t\tcase Severity.Error: return _error;\n\t\t\tcase Severity.Warning: return _warning;\n\t\t\tcase Severity.Info: return _info;\n\t\t\tdefault: return _ignore;\n\t\t}\n\t}\n}\n\nexport default Severity;\n","\n\n/**\n * @returns whether the provided parameter is a JavaScript Array or not.\n */\nexport function isArray(array: any): array is any[] {\n\treturn Array.isArray(array);\n}\n\n/**\n * @returns whether the provided parameter is a JavaScript String or not.\n */\nexport function isString(str: unknown): str is string {\n\treturn (typeof str === 'string');\n}\n\n/**\n *\n * @returns whether the provided parameter is of type `object` but **not**\n *\t`null`, an `array`, a `regexp`, nor a `date`.\n */\nexport function isObject(obj: unknown): obj is Object {\n\t// The method can't do a type cast since there are type (like strings) which\n\t// are subclasses of any put not positvely matched by the function. Hence type\n\t// narrowing results in wrong results.\n\treturn typeof obj === 'object'\n\t\t&& obj !== null\n\t\t&& !Array.isArray(obj)\n\t\t&& !(obj instanceof RegExp)\n\t\t&& !(obj instanceof Date);\n}\n\n/**\n * In **contrast** to just checking `typeof` this will return `false` for `NaN`.\n * @returns whether the provided parameter is a JavaScript Number or not.\n */\nexport function isNumber(obj: unknown): obj is number {\n\treturn (typeof obj === 'number' && !isNaN(obj));\n}\n\n/**\n * @returns whether the provided parameter is a JavaScript Boolean or not.\n */\nexport function isBoolean(obj: unknown): obj is boolean {\n\treturn (obj === true || obj === false);\n}\n\n/**\n * @returns whether the provided parameter is undefined.\n */\nexport function isUndefined(obj: unknown): obj is undefined {\n\treturn (typeof obj === 'undefined');\n}\n\n/**\n * @returns whether the provided parameter is defined.\n */\nexport function isDefined(arg: T | null | undefined): arg is T {\n\treturn !isUndefinedOrNull(arg);\n}\n\n/**\n * @returns whether the provided parameter is undefined or null.\n */\nexport function isUndefinedOrNull(obj: unknown): obj is undefined | null {\n\treturn (isUndefined(obj) || obj === null);\n}\n\n\nexport function assertType(condition: unknown, type?: string): asserts condition {\n\tif (!condition) {\n\t\tthrow new Error(type ? `Unexpected type, expected '${type}'` : 'Unexpected type');\n\t}\n}\n\n/**\n * Asserts that the argument passed in is neither undefined nor null.\n */\nexport function assertIsDefined(arg: T | null | undefined): T {\n\tif (isUndefinedOrNull(arg)) {\n\t\tthrow new Error('Assertion Failed: argument is undefined or null');\n\t}\n\n\treturn arg;\n}\n\n/**\n * @returns whether the provided parameter is a JavaScript Function or not.\n */\nexport function isFunction(obj: unknown): obj is Function {\n\treturn (typeof obj === 'function');\n}\n\nexport type TypeConstraint = string | Function;\n\nexport function validateConstraints(args: unknown[], constraints: Array): void {\n\tconst len = Math.min(args.length, constraints.length);\n\tfor (let i = 0; i < len; i++) {\n\t\tvalidateConstraint(args[i], constraints[i]);\n\t}\n}\n\nexport function validateConstraint(arg: unknown, constraint: TypeConstraint | undefined): void {\n\n\tif (isString(constraint)) {\n\t\tif (typeof arg !== constraint) {\n\t\t\tthrow new Error(`argument does not match constraint: typeof ${constraint}`);\n\t\t}\n\t} else if (isFunction(constraint)) {\n\t\ttry {\n\t\t\tif (arg instanceof constraint) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t\tif (!isUndefinedOrNull(arg) && (arg as any).constructor === constraint) {\n\t\t\treturn;\n\t\t}\n\t\tif (constraint.length === 1 && constraint.call(undefined, arg) === true) {\n\t\t\treturn;\n\t\t}\n\t\tthrow new Error(`argument does not match one of these constraints: arg instanceof constraint, arg.constructor === constraint, nor constraint(arg) === true`);\n\t}\n}\n\nexport function getAllPropertyNames(obj: object): string[] {\n\tlet res: string[] = [];\n\tlet proto = Object.getPrototypeOf(obj);\n\twhile (Object.prototype !== proto) {\n\t\tres = res.concat(Object.getOwnPropertyNames(proto));\n\t\tproto = Object.getPrototypeOf(proto);\n\t}\n\treturn res;\n}\n\nexport function getAllMethodNames(obj: object): string[] {\n\tconst methods: string[] = [];\n\tfor (const prop of getAllPropertyNames(obj)) {\n\t\tif (typeof (obj as any)[prop] === 'function') {\n\t\t\tmethods.push(prop);\n\t\t}\n\t}\n\treturn methods;\n}\n\nexport function createProxyObject(methodNames: string[], invoke: (method: string, args: unknown[]) => unknown): T {\n\tconst createProxyMethod = (method: string): () => unknown => {\n\t\treturn function () {\n\t\t\tconst args = Array.prototype.slice.call(arguments, 0);\n\t\t\treturn invoke(method, args);\n\t\t};\n\t};\n\n\tlet result = {} as T;\n\tfor (const methodName of methodNames) {\n\t\t(result)[methodName] = createProxyMethod(methodName);\n\t}\n\treturn result;\n}\n\n/**\n * Converts null to undefined, passes all other values through.\n */\nexport function withNullAsUndefined(x: T | null): T | undefined {\n\treturn x === null ? undefined : x;\n}\n\nexport function assertNever(value: never, message = 'Unreachable'): never {\n\tthrow new Error(message);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { isArray, isObject, isUndefinedOrNull } from 'vs/base/common/types';\n\nexport function deepClone(obj: T): T {\n\tif (!obj || typeof obj !== 'object') {\n\t\treturn obj;\n\t}\n\tif (obj instanceof RegExp) {\n\t\t// See https://github.com/microsoft/TypeScript/issues/10990\n\t\treturn obj as any;\n\t}\n\tconst result: any = Array.isArray(obj) ? [] : {};\n\tObject.keys(obj).forEach((key: string) => {\n\t\tif ((obj)[key] && typeof (obj)[key] === 'object') {\n\t\t\tresult[key] = deepClone((obj)[key]);\n\t\t} else {\n\t\t\tresult[key] = (obj)[key];\n\t\t}\n\t});\n\treturn result;\n}\n\nexport function deepFreeze(obj: T): T {\n\tif (!obj || typeof obj !== 'object') {\n\t\treturn obj;\n\t}\n\tconst stack: any[] = [obj];\n\twhile (stack.length > 0) {\n\t\tconst obj = stack.shift();\n\t\tObject.freeze(obj);\n\t\tfor (const key in obj) {\n\t\t\tif (_hasOwnProperty.call(obj, key)) {\n\t\t\t\tconst prop = obj[key];\n\t\t\t\tif (typeof prop === 'object' && !Object.isFrozen(prop)) {\n\t\t\t\t\tstack.push(prop);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn obj;\n}\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty;\n\nexport function cloneAndChange(obj: any, changer: (orig: any) => any): any {\n\treturn _cloneAndChange(obj, changer, new Set());\n}\n\nfunction _cloneAndChange(obj: any, changer: (orig: any) => any, seen: Set): any {\n\tif (isUndefinedOrNull(obj)) {\n\t\treturn obj;\n\t}\n\n\tconst changed = changer(obj);\n\tif (typeof changed !== 'undefined') {\n\t\treturn changed;\n\t}\n\n\tif (isArray(obj)) {\n\t\tconst r1: any[] = [];\n\t\tfor (const e of obj) {\n\t\t\tr1.push(_cloneAndChange(e, changer, seen));\n\t\t}\n\t\treturn r1;\n\t}\n\n\tif (isObject(obj)) {\n\t\tif (seen.has(obj)) {\n\t\t\tthrow new Error('Cannot clone recursive data-structure');\n\t\t}\n\t\tseen.add(obj);\n\t\tconst r2 = {};\n\t\tfor (let i2 in obj) {\n\t\t\tif (_hasOwnProperty.call(obj, i2)) {\n\t\t\t\t(r2 as any)[i2] = _cloneAndChange(obj[i2], changer, seen);\n\t\t\t}\n\t\t}\n\t\tseen.delete(obj);\n\t\treturn r2;\n\t}\n\n\treturn obj;\n}\n\n/**\n * Copies all properties of source into destination. The optional parameter \"overwrite\" allows to control\n * if existing properties on the destination should be overwritten or not. Defaults to true (overwrite).\n */\nexport function mixin(destination: any, source: any, overwrite: boolean = true): any {\n\tif (!isObject(destination)) {\n\t\treturn source;\n\t}\n\n\tif (isObject(source)) {\n\t\tObject.keys(source).forEach(key => {\n\t\t\tif (key in destination) {\n\t\t\t\tif (overwrite) {\n\t\t\t\t\tif (isObject(destination[key]) && isObject(source[key])) {\n\t\t\t\t\t\tmixin(destination[key], source[key], overwrite);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdestination[key] = source[key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdestination[key] = source[key];\n\t\t\t}\n\t\t});\n\t}\n\treturn destination;\n}\n\nexport function equals(one: any, other: any): boolean {\n\tif (one === other) {\n\t\treturn true;\n\t}\n\tif (one === null || one === undefined || other === null || other === undefined) {\n\t\treturn false;\n\t}\n\tif (typeof one !== typeof other) {\n\t\treturn false;\n\t}\n\tif (typeof one !== 'object') {\n\t\treturn false;\n\t}\n\tif ((Array.isArray(one)) !== (Array.isArray(other))) {\n\t\treturn false;\n\t}\n\n\tlet i: number;\n\tlet key: string;\n\n\tif (Array.isArray(one)) {\n\t\tif (one.length !== other.length) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (i = 0; i < one.length; i++) {\n\t\t\tif (!equals(one[i], other[i])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tconst oneKeys: string[] = [];\n\n\t\tfor (key in one) {\n\t\t\toneKeys.push(key);\n\t\t}\n\t\toneKeys.sort();\n\t\tconst otherKeys: string[] = [];\n\t\tfor (key in other) {\n\t\t\totherKeys.push(key);\n\t\t}\n\t\totherKeys.sort();\n\t\tif (!equals(oneKeys, otherKeys)) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (i = 0; i < oneKeys.length; i++) {\n\t\t\tif (!equals(one[oneKeys[i]], other[oneKeys[i]])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\nexport function getOrDefault(obj: T, fn: (obj: T) => R | undefined, defaultValue: R): R {\n\tconst result = fn(obj);\n\treturn typeof result === 'undefined' ? defaultValue : result;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport const enum Constants {\n\t/**\n\t * MAX SMI (SMall Integer) as defined in v8.\n\t * one bit is lost for boxing/unboxing flag.\n\t * one bit is lost for sign flag.\n\t * See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values\n\t */\n\tMAX_SAFE_SMALL_INTEGER = 1 << 30,\n\n\t/**\n\t * MIN SMI (SMall Integer) as defined in v8.\n\t * one bit is lost for boxing/unboxing flag.\n\t * one bit is lost for sign flag.\n\t * See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values\n\t */\n\tMIN_SAFE_SMALL_INTEGER = -(1 << 30),\n\n\t/**\n\t * Max unsigned integer that fits on 8 bits.\n\t */\n\tMAX_UINT_8 = 255, // 2^8 - 1\n\n\t/**\n\t * Max unsigned integer that fits on 16 bits.\n\t */\n\tMAX_UINT_16 = 65535, // 2^16 - 1\n\n\t/**\n\t * Max unsigned integer that fits on 32 bits.\n\t */\n\tMAX_UINT_32 = 4294967295, // 2^32 - 1\n\n\tUNICODE_SUPPLEMENTARY_PLANE_BEGIN = 0x010000\n}\n\nexport function toUint8(v: number): number {\n\tif (v < 0) {\n\t\treturn 0;\n\t}\n\tif (v > Constants.MAX_UINT_8) {\n\t\treturn Constants.MAX_UINT_8;\n\t}\n\treturn v | 0;\n}\n\nexport function toUint32(v: number): number {\n\tif (v < 0) {\n\t\treturn 0;\n\t}\n\tif (v > Constants.MAX_UINT_32) {\n\t\treturn Constants.MAX_UINT_32;\n\t}\n\treturn v | 0;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { MarshalledId } from 'vs/base/common/marshalling';\nimport * as paths from 'vs/base/common/path';\nimport { isWindows } from 'vs/base/common/platform';\n\nconst _schemePattern = /^\\w[\\w\\d+.-]*$/;\nconst _singleSlashStart = /^\\//;\nconst _doubleSlashStart = /^\\/\\//;\n\nfunction _validateUri(ret: URI, _strict?: boolean): void {\n\n\t// scheme, must be set\n\tif (!ret.scheme && _strict) {\n\t\tthrow new Error(`[UriError]: Scheme is missing: {scheme: \"\", authority: \"${ret.authority}\", path: \"${ret.path}\", query: \"${ret.query}\", fragment: \"${ret.fragment}\"}`);\n\t}\n\n\t// scheme, https://tools.ietf.org/html/rfc3986#section-3.1\n\t// ALPHA *( ALPHA / DIGIT / \"+\" / \"-\" / \".\" )\n\tif (ret.scheme && !_schemePattern.test(ret.scheme)) {\n\t\tthrow new Error('[UriError]: Scheme contains illegal characters.');\n\t}\n\n\t// path, http://tools.ietf.org/html/rfc3986#section-3.3\n\t// If a URI contains an authority component, then the path component\n\t// must either be empty or begin with a slash (\"/\") character. If a URI\n\t// does not contain an authority component, then the path cannot begin\n\t// with two slash characters (\"//\").\n\tif (ret.path) {\n\t\tif (ret.authority) {\n\t\t\tif (!_singleSlashStart.test(ret.path)) {\n\t\t\t\tthrow new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash (\"/\") character');\n\t\t\t}\n\t\t} else {\n\t\t\tif (_doubleSlashStart.test(ret.path)) {\n\t\t\t\tthrow new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters (\"//\")');\n\t\t\t}\n\t\t}\n\t}\n}\n\n// for a while we allowed uris *without* schemes and this is the migration\n// for them, e.g. an uri without scheme and without strict-mode warns and falls\n// back to the file-scheme. that should cause the least carnage and still be a\n// clear warning\nfunction _schemeFix(scheme: string, _strict: boolean): string {\n\tif (!scheme && !_strict) {\n\t\treturn 'file';\n\t}\n\treturn scheme;\n}\n\n// implements a bit of https://tools.ietf.org/html/rfc3986#section-5\nfunction _referenceResolution(scheme: string, path: string): string {\n\n\t// the slash-character is our 'default base' as we don't\n\t// support constructing URIs relative to other URIs. This\n\t// also means that we alter and potentially break paths.\n\t// see https://tools.ietf.org/html/rfc3986#section-5.1.4\n\tswitch (scheme) {\n\t\tcase 'https':\n\t\tcase 'http':\n\t\tcase 'file':\n\t\t\tif (!path) {\n\t\t\t\tpath = _slash;\n\t\t\t} else if (path[0] !== _slash) {\n\t\t\t\tpath = _slash + path;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\treturn path;\n}\n\nconst _empty = '';\nconst _slash = '/';\nconst _regexp = /^(([^:/?#]+?):)?(\\/\\/([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?/;\n\n/**\n * Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986.\n * This class is a simple parser which creates the basic component parts\n * (http://tools.ietf.org/html/rfc3986#section-3) with minimal validation\n * and encoding.\n *\n * ```txt\n * foo://example.com:8042/over/there?name=ferret#nose\n * \\_/ \\______________/\\_________/ \\_________/ \\__/\n * | | | | |\n * scheme authority path query fragment\n * | _____________________|__\n * / \\ / \\\n * urn:example:animal:ferret:nose\n * ```\n */\nexport class URI implements UriComponents {\n\n\tstatic isUri(thing: any): thing is URI {\n\t\tif (thing instanceof URI) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!thing) {\n\t\t\treturn false;\n\t\t}\n\t\treturn typeof (thing).authority === 'string'\n\t\t\t&& typeof (thing).fragment === 'string'\n\t\t\t&& typeof (thing).path === 'string'\n\t\t\t&& typeof (thing).query === 'string'\n\t\t\t&& typeof (thing).scheme === 'string'\n\t\t\t&& typeof (thing).fsPath === 'string'\n\t\t\t&& typeof (thing).with === 'function'\n\t\t\t&& typeof (thing).toString === 'function';\n\t}\n\n\t/**\n\t * scheme is the 'http' part of 'http://www.example.com/some/path?query#fragment'.\n\t * The part before the first colon.\n\t */\n\treadonly scheme: string;\n\n\t/**\n\t * authority is the 'www.example.com' part of 'http://www.example.com/some/path?query#fragment'.\n\t * The part between the first double slashes and the next slash.\n\t */\n\treadonly authority: string;\n\n\t/**\n\t * path is the '/some/path' part of 'http://www.example.com/some/path?query#fragment'.\n\t */\n\treadonly path: string;\n\n\t/**\n\t * query is the 'query' part of 'http://www.example.com/some/path?query#fragment'.\n\t */\n\treadonly query: string;\n\n\t/**\n\t * fragment is the 'fragment' part of 'http://www.example.com/some/path?query#fragment'.\n\t */\n\treadonly fragment: string;\n\n\t/**\n\t * @internal\n\t */\n\tprotected constructor(scheme: string, authority?: string, path?: string, query?: string, fragment?: string, _strict?: boolean);\n\n\t/**\n\t * @internal\n\t */\n\tprotected constructor(components: UriComponents);\n\n\t/**\n\t * @internal\n\t */\n\tprotected constructor(schemeOrData: string | UriComponents, authority?: string, path?: string, query?: string, fragment?: string, _strict: boolean = false) {\n\n\t\tif (typeof schemeOrData === 'object') {\n\t\t\tthis.scheme = schemeOrData.scheme || _empty;\n\t\t\tthis.authority = schemeOrData.authority || _empty;\n\t\t\tthis.path = schemeOrData.path || _empty;\n\t\t\tthis.query = schemeOrData.query || _empty;\n\t\t\tthis.fragment = schemeOrData.fragment || _empty;\n\t\t\t// no validation because it's this URI\n\t\t\t// that creates uri components.\n\t\t\t// _validateUri(this);\n\t\t} else {\n\t\t\tthis.scheme = _schemeFix(schemeOrData, _strict);\n\t\t\tthis.authority = authority || _empty;\n\t\t\tthis.path = _referenceResolution(this.scheme, path || _empty);\n\t\t\tthis.query = query || _empty;\n\t\t\tthis.fragment = fragment || _empty;\n\n\t\t\t_validateUri(this, _strict);\n\t\t}\n\t}\n\n\t// ---- filesystem path -----------------------\n\n\t/**\n\t * Returns a string representing the corresponding file system path of this URI.\n\t * Will handle UNC paths, normalizes windows drive letters to lower-case, and uses the\n\t * platform specific path separator.\n\t *\n\t * * Will *not* validate the path for invalid characters and semantics.\n\t * * Will *not* look at the scheme of this URI.\n\t * * The result shall *not* be used for display purposes but for accessing a file on disk.\n\t *\n\t *\n\t * The *difference* to `URI#path` is the use of the platform specific separator and the handling\n\t * of UNC paths. See the below sample of a file-uri with an authority (UNC path).\n\t *\n\t * ```ts\n\t\tconst u = URI.parse('file://server/c$/folder/file.txt')\n\t\tu.authority === 'server'\n\t\tu.path === '/shares/c$/file.txt'\n\t\tu.fsPath === '\\\\server\\c$\\folder\\file.txt'\n\t```\n\t *\n\t * Using `URI#path` to read a file (using fs-apis) would not be enough because parts of the path,\n\t * namely the server name, would be missing. Therefore `URI#fsPath` exists - it's sugar to ease working\n\t * with URIs that represent files on disk (`file` scheme).\n\t */\n\tget fsPath(): string {\n\t\t// if (this.scheme !== 'file') {\n\t\t// \tconsole.warn(`[UriError] calling fsPath with scheme ${this.scheme}`);\n\t\t// }\n\t\treturn uriToFsPath(this, false);\n\t}\n\n\t// ---- modify to new -------------------------\n\n\twith(change: { scheme?: string; authority?: string | null; path?: string | null; query?: string | null; fragment?: string | null }): URI {\n\n\t\tif (!change) {\n\t\t\treturn this;\n\t\t}\n\n\t\tlet { scheme, authority, path, query, fragment } = change;\n\t\tif (scheme === undefined) {\n\t\t\tscheme = this.scheme;\n\t\t} else if (scheme === null) {\n\t\t\tscheme = _empty;\n\t\t}\n\t\tif (authority === undefined) {\n\t\t\tauthority = this.authority;\n\t\t} else if (authority === null) {\n\t\t\tauthority = _empty;\n\t\t}\n\t\tif (path === undefined) {\n\t\t\tpath = this.path;\n\t\t} else if (path === null) {\n\t\t\tpath = _empty;\n\t\t}\n\t\tif (query === undefined) {\n\t\t\tquery = this.query;\n\t\t} else if (query === null) {\n\t\t\tquery = _empty;\n\t\t}\n\t\tif (fragment === undefined) {\n\t\t\tfragment = this.fragment;\n\t\t} else if (fragment === null) {\n\t\t\tfragment = _empty;\n\t\t}\n\n\t\tif (scheme === this.scheme\n\t\t\t&& authority === this.authority\n\t\t\t&& path === this.path\n\t\t\t&& query === this.query\n\t\t\t&& fragment === this.fragment) {\n\n\t\t\treturn this;\n\t\t}\n\n\t\treturn new Uri(scheme, authority, path, query, fragment);\n\t}\n\n\t// ---- parse & validate ------------------------\n\n\t/**\n\t * Creates a new URI from a string, e.g. `http://www.example.com/some/path`,\n\t * `file:///usr/home`, or `scheme:with/path`.\n\t *\n\t * @param value A string which represents an URI (see `URI#toString`).\n\t */\n\tstatic parse(value: string, _strict: boolean = false): URI {\n\t\tconst match = _regexp.exec(value);\n\t\tif (!match) {\n\t\t\treturn new Uri(_empty, _empty, _empty, _empty, _empty);\n\t\t}\n\t\treturn new Uri(\n\t\t\tmatch[2] || _empty,\n\t\t\tpercentDecode(match[4] || _empty),\n\t\t\tpercentDecode(match[5] || _empty),\n\t\t\tpercentDecode(match[7] || _empty),\n\t\t\tpercentDecode(match[9] || _empty),\n\t\t\t_strict\n\t\t);\n\t}\n\n\t/**\n\t * Creates a new URI from a file system path, e.g. `c:\\my\\files`,\n\t * `/usr/home`, or `\\\\server\\share\\some\\path`.\n\t *\n\t * The *difference* between `URI#parse` and `URI#file` is that the latter treats the argument\n\t * as path, not as stringified-uri. E.g. `URI.file(path)` is **not the same as**\n\t * `URI.parse('file://' + path)` because the path might contain characters that are\n\t * interpreted (# and ?). See the following sample:\n\t * ```ts\n\tconst good = URI.file('/coding/c#/project1');\n\tgood.scheme === 'file';\n\tgood.path === '/coding/c#/project1';\n\tgood.fragment === '';\n\tconst bad = URI.parse('file://' + '/coding/c#/project1');\n\tbad.scheme === 'file';\n\tbad.path === '/coding/c'; // path is now broken\n\tbad.fragment === '/project1';\n\t```\n\t *\n\t * @param path A file system path (see `URI#fsPath`)\n\t */\n\tstatic file(path: string): URI {\n\n\t\tlet authority = _empty;\n\n\t\t// normalize to fwd-slashes on windows,\n\t\t// on other systems bwd-slashes are valid\n\t\t// filename character, eg /f\\oo/ba\\r.txt\n\t\tif (isWindows) {\n\t\t\tpath = path.replace(/\\\\/g, _slash);\n\t\t}\n\n\t\t// check for authority as used in UNC shares\n\t\t// or use the path as given\n\t\tif (path[0] === _slash && path[1] === _slash) {\n\t\t\tconst idx = path.indexOf(_slash, 2);\n\t\t\tif (idx === -1) {\n\t\t\t\tauthority = path.substring(2);\n\t\t\t\tpath = _slash;\n\t\t\t} else {\n\t\t\t\tauthority = path.substring(2, idx);\n\t\t\t\tpath = path.substring(idx) || _slash;\n\t\t\t}\n\t\t}\n\n\t\treturn new Uri('file', authority, path, _empty, _empty);\n\t}\n\n\tstatic from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {\n\t\tconst result = new Uri(\n\t\t\tcomponents.scheme,\n\t\t\tcomponents.authority,\n\t\t\tcomponents.path,\n\t\t\tcomponents.query,\n\t\t\tcomponents.fragment,\n\t\t);\n\t\t_validateUri(result, true);\n\t\treturn result;\n\t}\n\n\t/**\n\t * Join a URI path with path fragments and normalizes the resulting path.\n\t *\n\t * @param uri The input URI.\n\t * @param pathFragment The path fragment to add to the URI path.\n\t * @returns The resulting URI.\n\t */\n\tstatic joinPath(uri: URI, ...pathFragment: string[]): URI {\n\t\tif (!uri.path) {\n\t\t\tthrow new Error(`[UriError]: cannot call joinPath on URI without path`);\n\t\t}\n\t\tlet newPath: string;\n\t\tif (isWindows && uri.scheme === 'file') {\n\t\t\tnewPath = URI.file(paths.win32.join(uriToFsPath(uri, true), ...pathFragment)).path;\n\t\t} else {\n\t\t\tnewPath = paths.posix.join(uri.path, ...pathFragment);\n\t\t}\n\t\treturn uri.with({ path: newPath });\n\t}\n\n\t// ---- printing/externalize ---------------------------\n\n\t/**\n\t * Creates a string representation for this URI. It's guaranteed that calling\n\t * `URI.parse` with the result of this function creates an URI which is equal\n\t * to this URI.\n\t *\n\t * * The result shall *not* be used for display purposes but for externalization or transport.\n\t * * The result will be encoded using the percentage encoding and encoding happens mostly\n\t * ignore the scheme-specific encoding rules.\n\t *\n\t * @param skipEncoding Do not encode the result, default is `false`\n\t */\n\ttoString(skipEncoding: boolean = false): string {\n\t\treturn _asFormatted(this, skipEncoding);\n\t}\n\n\ttoJSON(): UriComponents {\n\t\treturn this;\n\t}\n\n\tstatic revive(data: UriComponents | URI): URI;\n\tstatic revive(data: UriComponents | URI | undefined): URI | undefined;\n\tstatic revive(data: UriComponents | URI | null): URI | null;\n\tstatic revive(data: UriComponents | URI | undefined | null): URI | undefined | null;\n\tstatic revive(data: UriComponents | URI | undefined | null): URI | undefined | null {\n\t\tif (!data) {\n\t\t\treturn data;\n\t\t} else if (data instanceof URI) {\n\t\t\treturn data;\n\t\t} else {\n\t\t\tconst result = new Uri(data);\n\t\t\tresult._formatted = (data).external;\n\t\t\tresult._fsPath = (data)._sep === _pathSepMarker ? (data).fsPath : null;\n\t\t\treturn result;\n\t\t}\n\t}\n}\n\nexport interface UriComponents {\n\tscheme: string;\n\tauthority: string;\n\tpath: string;\n\tquery: string;\n\tfragment: string;\n}\n\ninterface UriState extends UriComponents {\n\t$mid: MarshalledId.Uri;\n\texternal: string;\n\tfsPath: string;\n\t_sep: 1 | undefined;\n}\n\nconst _pathSepMarker = isWindows ? 1 : undefined;\n\n// This class exists so that URI is compatible with vscode.Uri (API).\nclass Uri extends URI {\n\n\t_formatted: string | null = null;\n\t_fsPath: string | null = null;\n\n\toverride get fsPath(): string {\n\t\tif (!this._fsPath) {\n\t\t\tthis._fsPath = uriToFsPath(this, false);\n\t\t}\n\t\treturn this._fsPath;\n\t}\n\n\toverride toString(skipEncoding: boolean = false): string {\n\t\tif (!skipEncoding) {\n\t\t\tif (!this._formatted) {\n\t\t\t\tthis._formatted = _asFormatted(this, false);\n\t\t\t}\n\t\t\treturn this._formatted;\n\t\t} else {\n\t\t\t// we don't cache that\n\t\t\treturn _asFormatted(this, true);\n\t\t}\n\t}\n\n\toverride toJSON(): UriComponents {\n\t\tconst res = {\n\t\t\t$mid: MarshalledId.Uri\n\t\t};\n\t\t// cached state\n\t\tif (this._fsPath) {\n\t\t\tres.fsPath = this._fsPath;\n\t\t\tres._sep = _pathSepMarker;\n\t\t}\n\t\tif (this._formatted) {\n\t\t\tres.external = this._formatted;\n\t\t}\n\t\t// uri components\n\t\tif (this.path) {\n\t\t\tres.path = this.path;\n\t\t}\n\t\tif (this.scheme) {\n\t\t\tres.scheme = this.scheme;\n\t\t}\n\t\tif (this.authority) {\n\t\t\tres.authority = this.authority;\n\t\t}\n\t\tif (this.query) {\n\t\t\tres.query = this.query;\n\t\t}\n\t\tif (this.fragment) {\n\t\t\tres.fragment = this.fragment;\n\t\t}\n\t\treturn res;\n\t}\n}\n\n// reserved characters: https://tools.ietf.org/html/rfc3986#section-2.2\nconst encodeTable: { [ch: number]: string } = {\n\t[CharCode.Colon]: '%3A', // gen-delims\n\t[CharCode.Slash]: '%2F',\n\t[CharCode.QuestionMark]: '%3F',\n\t[CharCode.Hash]: '%23',\n\t[CharCode.OpenSquareBracket]: '%5B',\n\t[CharCode.CloseSquareBracket]: '%5D',\n\t[CharCode.AtSign]: '%40',\n\n\t[CharCode.ExclamationMark]: '%21', // sub-delims\n\t[CharCode.DollarSign]: '%24',\n\t[CharCode.Ampersand]: '%26',\n\t[CharCode.SingleQuote]: '%27',\n\t[CharCode.OpenParen]: '%28',\n\t[CharCode.CloseParen]: '%29',\n\t[CharCode.Asterisk]: '%2A',\n\t[CharCode.Plus]: '%2B',\n\t[CharCode.Comma]: '%2C',\n\t[CharCode.Semicolon]: '%3B',\n\t[CharCode.Equals]: '%3D',\n\n\t[CharCode.Space]: '%20',\n};\n\nfunction encodeURIComponentFast(uriComponent: string, allowSlash: boolean): string {\n\tlet res: string | undefined = undefined;\n\tlet nativeEncodePos = -1;\n\n\tfor (let pos = 0; pos < uriComponent.length; pos++) {\n\t\tconst code = uriComponent.charCodeAt(pos);\n\n\t\t// unreserved characters: https://tools.ietf.org/html/rfc3986#section-2.3\n\t\tif (\n\t\t\t(code >= CharCode.a && code <= CharCode.z)\n\t\t\t|| (code >= CharCode.A && code <= CharCode.Z)\n\t\t\t|| (code >= CharCode.Digit0 && code <= CharCode.Digit9)\n\t\t\t|| code === CharCode.Dash\n\t\t\t|| code === CharCode.Period\n\t\t\t|| code === CharCode.Underline\n\t\t\t|| code === CharCode.Tilde\n\t\t\t|| (allowSlash && code === CharCode.Slash)\n\t\t) {\n\t\t\t// check if we are delaying native encode\n\t\t\tif (nativeEncodePos !== -1) {\n\t\t\t\tres += encodeURIComponent(uriComponent.substring(nativeEncodePos, pos));\n\t\t\t\tnativeEncodePos = -1;\n\t\t\t}\n\t\t\t// check if we write into a new string (by default we try to return the param)\n\t\t\tif (res !== undefined) {\n\t\t\t\tres += uriComponent.charAt(pos);\n\t\t\t}\n\n\t\t} else {\n\t\t\t// encoding needed, we need to allocate a new string\n\t\t\tif (res === undefined) {\n\t\t\t\tres = uriComponent.substr(0, pos);\n\t\t\t}\n\n\t\t\t// check with default table first\n\t\t\tconst escaped = encodeTable[code];\n\t\t\tif (escaped !== undefined) {\n\n\t\t\t\t// check if we are delaying native encode\n\t\t\t\tif (nativeEncodePos !== -1) {\n\t\t\t\t\tres += encodeURIComponent(uriComponent.substring(nativeEncodePos, pos));\n\t\t\t\t\tnativeEncodePos = -1;\n\t\t\t\t}\n\n\t\t\t\t// append escaped variant to result\n\t\t\t\tres += escaped;\n\n\t\t\t} else if (nativeEncodePos === -1) {\n\t\t\t\t// use native encode only when needed\n\t\t\t\tnativeEncodePos = pos;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (nativeEncodePos !== -1) {\n\t\tres += encodeURIComponent(uriComponent.substring(nativeEncodePos));\n\t}\n\n\treturn res !== undefined ? res : uriComponent;\n}\n\nfunction encodeURIComponentMinimal(path: string): string {\n\tlet res: string | undefined = undefined;\n\tfor (let pos = 0; pos < path.length; pos++) {\n\t\tconst code = path.charCodeAt(pos);\n\t\tif (code === CharCode.Hash || code === CharCode.QuestionMark) {\n\t\t\tif (res === undefined) {\n\t\t\t\tres = path.substr(0, pos);\n\t\t\t}\n\t\t\tres += encodeTable[code];\n\t\t} else {\n\t\t\tif (res !== undefined) {\n\t\t\t\tres += path[pos];\n\t\t\t}\n\t\t}\n\t}\n\treturn res !== undefined ? res : path;\n}\n\n/**\n * Compute `fsPath` for the given uri\n */\nexport function uriToFsPath(uri: URI, keepDriveLetterCasing: boolean): string {\n\n\tlet value: string;\n\tif (uri.authority && uri.path.length > 1 && uri.scheme === 'file') {\n\t\t// unc path: file://shares/c$/far/boo\n\t\tvalue = `//${uri.authority}${uri.path}`;\n\t} else if (\n\t\turi.path.charCodeAt(0) === CharCode.Slash\n\t\t&& (uri.path.charCodeAt(1) >= CharCode.A && uri.path.charCodeAt(1) <= CharCode.Z || uri.path.charCodeAt(1) >= CharCode.a && uri.path.charCodeAt(1) <= CharCode.z)\n\t\t&& uri.path.charCodeAt(2) === CharCode.Colon\n\t) {\n\t\tif (!keepDriveLetterCasing) {\n\t\t\t// windows drive letter: file:///c:/far/boo\n\t\t\tvalue = uri.path[1].toLowerCase() + uri.path.substr(2);\n\t\t} else {\n\t\t\tvalue = uri.path.substr(1);\n\t\t}\n\t} else {\n\t\t// other path\n\t\tvalue = uri.path;\n\t}\n\tif (isWindows) {\n\t\tvalue = value.replace(/\\//g, '\\\\');\n\t}\n\treturn value;\n}\n\n/**\n * Create the external version of a uri\n */\nfunction _asFormatted(uri: URI, skipEncoding: boolean): string {\n\n\tconst encoder = !skipEncoding\n\t\t? encodeURIComponentFast\n\t\t: encodeURIComponentMinimal;\n\n\tlet res = '';\n\tlet { scheme, authority, path, query, fragment } = uri;\n\tif (scheme) {\n\t\tres += scheme;\n\t\tres += ':';\n\t}\n\tif (authority || scheme === 'file') {\n\t\tres += _slash;\n\t\tres += _slash;\n\t}\n\tif (authority) {\n\t\tlet idx = authority.indexOf('@');\n\t\tif (idx !== -1) {\n\t\t\t// @\n\t\t\tconst userinfo = authority.substr(0, idx);\n\t\t\tauthority = authority.substr(idx + 1);\n\t\t\tidx = userinfo.indexOf(':');\n\t\t\tif (idx === -1) {\n\t\t\t\tres += encoder(userinfo, false);\n\t\t\t} else {\n\t\t\t\t// :@\n\t\t\t\tres += encoder(userinfo.substr(0, idx), false);\n\t\t\t\tres += ':';\n\t\t\t\tres += encoder(userinfo.substr(idx + 1), false);\n\t\t\t}\n\t\t\tres += '@';\n\t\t}\n\t\tauthority = authority.toLowerCase();\n\t\tidx = authority.indexOf(':');\n\t\tif (idx === -1) {\n\t\t\tres += encoder(authority, false);\n\t\t} else {\n\t\t\t// :\n\t\t\tres += encoder(authority.substr(0, idx), false);\n\t\t\tres += authority.substr(idx);\n\t\t}\n\t}\n\tif (path) {\n\t\t// lower-case windows drive letters in /C:/fff or C:/fff\n\t\tif (path.length >= 3 && path.charCodeAt(0) === CharCode.Slash && path.charCodeAt(2) === CharCode.Colon) {\n\t\t\tconst code = path.charCodeAt(1);\n\t\t\tif (code >= CharCode.A && code <= CharCode.Z) {\n\t\t\t\tpath = `/${String.fromCharCode(code + 32)}:${path.substr(3)}`; // \"/c:\".length === 3\n\t\t\t}\n\t\t} else if (path.length >= 2 && path.charCodeAt(1) === CharCode.Colon) {\n\t\t\tconst code = path.charCodeAt(0);\n\t\t\tif (code >= CharCode.A && code <= CharCode.Z) {\n\t\t\t\tpath = `${String.fromCharCode(code + 32)}:${path.substr(2)}`; // \"/c:\".length === 3\n\t\t\t}\n\t\t}\n\t\t// encode the rest of the path\n\t\tres += encoder(path, true);\n\t}\n\tif (query) {\n\t\tres += '?';\n\t\tres += encoder(query, false);\n\t}\n\tif (fragment) {\n\t\tres += '#';\n\t\tres += !skipEncoding ? encodeURIComponentFast(fragment, false) : fragment;\n\t}\n\treturn res;\n}\n\n// --- decode\n\nfunction decodeURIComponentGraceful(str: string): string {\n\ttry {\n\t\treturn decodeURIComponent(str);\n\t} catch {\n\t\tif (str.length > 3) {\n\t\t\treturn str.substr(0, 3) + decodeURIComponentGraceful(str.substr(3));\n\t\t} else {\n\t\t\treturn str;\n\t\t}\n\t}\n}\n\nconst _rEncodedAsHex = /(%[0-9A-Za-z][0-9A-Za-z])+/g;\n\nfunction percentDecode(str: string): string {\n\tif (!str.match(_rEncodedAsHex)) {\n\t\treturn str;\n\t}\n\treturn str.replace(_rEncodedAsHex, (match) => decodeURIComponentGraceful(match));\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { VSBuffer } from 'vs/base/common/buffer';\nimport { URI, UriComponents } from 'vs/base/common/uri';\n\nexport function parse(text: string): any {\n\tlet data = JSON.parse(text);\n\tdata = revive(data);\n\treturn data;\n}\n\nexport const enum MarshalledId {\n\tUri = 1,\n\tRegexp,\n\tScmResource,\n\tScmResourceGroup,\n\tScmProvider,\n\tCommentController,\n\tCommentThread,\n\tCommentThreadReply,\n\tCommentNode,\n\tCommentThreadNode,\n\tTimelineActionContext,\n\tNotebookCellActionContext,\n\tTestItemContext,\n\tDate,\n}\n\nexport interface MarshalledObject {\n\t$mid: MarshalledId;\n}\n\n\ntype Deserialize = T extends UriComponents ? URI\n\t: T extends VSBuffer ? VSBuffer\n\t: T extends object\n\t? Revived\n\t: T;\n\nexport type Revived = { [K in keyof T]: Deserialize };\n\nexport function revive(obj: any, depth = 0): Revived {\n\tif (!obj || depth > 200) {\n\t\treturn obj;\n\t}\n\n\tif (typeof obj === 'object') {\n\n\t\tswitch ((obj).$mid) {\n\t\t\tcase MarshalledId.Uri: return URI.revive(obj);\n\t\t\tcase MarshalledId.Regexp: return new RegExp(obj.source, obj.flags);\n\t\t\tcase MarshalledId.Date: return new Date(obj.source);\n\t\t}\n\n\t\tif (\n\t\t\tobj instanceof VSBuffer\n\t\t\t|| obj instanceof Uint8Array\n\t\t) {\n\t\t\treturn obj;\n\t\t}\n\n\t\tif (Array.isArray(obj)) {\n\t\t\tfor (let i = 0; i < obj.length; ++i) {\n\t\t\t\tobj[i] = revive(obj[i], depth + 1);\n\t\t\t}\n\t\t} else {\n\t\t\t// walk object\n\t\t\tfor (const key in obj) {\n\t\t\t\tif (Object.hasOwnProperty.call(obj, key)) {\n\t\t\t\t\tobj[key] = revive(obj[key], depth + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn obj;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as platform from 'vs/base/common/platform';\nimport { URI } from 'vs/base/common/uri';\n\nexport namespace Schemas {\n\n\t/**\n\t * A schema that is used for models that exist in memory\n\t * only and that have no correspondence on a server or such.\n\t */\n\texport const inMemory = 'inmemory';\n\n\t/**\n\t * A schema that is used for setting files\n\t */\n\texport const vscode = 'vscode';\n\n\t/**\n\t * A schema that is used for internal private files\n\t */\n\texport const internal = 'private';\n\n\t/**\n\t * A walk-through document.\n\t */\n\texport const walkThrough = 'walkThrough';\n\n\t/**\n\t * An embedded code snippet.\n\t */\n\texport const walkThroughSnippet = 'walkThroughSnippet';\n\n\texport const http = 'http';\n\n\texport const https = 'https';\n\n\texport const file = 'file';\n\n\texport const mailto = 'mailto';\n\n\texport const untitled = 'untitled';\n\n\texport const data = 'data';\n\n\texport const command = 'command';\n\n\texport const vscodeRemote = 'vscode-remote';\n\n\texport const vscodeRemoteResource = 'vscode-remote-resource';\n\n\texport const userData = 'vscode-userdata';\n\n\texport const vscodeCustomEditor = 'vscode-custom-editor';\n\n\texport const vscodeNotebook = 'vscode-notebook';\n\n\texport const vscodeNotebookCell = 'vscode-notebook-cell';\n\n\texport const vscodeNotebookCellMetadata = 'vscode-notebook-cell-metadata';\n\texport const vscodeNotebookCellOutput = 'vscode-notebook-cell-output';\n\texport const vscodeInteractive = 'vscode-interactive';\n\texport const vscodeInteractiveInput = 'vscode-interactive-input';\n\n\texport const vscodeSettings = 'vscode-settings';\n\n\texport const vscodeWorkspaceTrust = 'vscode-workspace-trust';\n\n\texport const vscodeTerminal = 'vscode-terminal';\n\n\t/**\n\t * Scheme used internally for webviews that aren't linked to a resource (i.e. not custom editors)\n\t */\n\texport const webviewPanel = 'webview-panel';\n\n\t/**\n\t * Scheme used for loading the wrapper html and script in webviews.\n\t */\n\texport const vscodeWebview = 'vscode-webview';\n\n\t/**\n\t * Scheme used for extension pages\n\t */\n\texport const extension = 'extension';\n\n\t/**\n\t * Scheme used as a replacement of `file` scheme to load\n\t * files with our custom protocol handler (desktop only).\n\t */\n\texport const vscodeFileResource = 'vscode-file';\n\n\t/**\n\t * Scheme used for temporary resources\n\t */\n\texport const tmp = 'tmp';\n\n\t/**\n\t * Scheme used vs live share\n\t */\n\texport const vsls = 'vsls';\n}\nexport const connectionTokenQueryName = 'tkn';\n\nclass RemoteAuthoritiesImpl {\n\tprivate readonly _hosts: { [authority: string]: string | undefined; } = Object.create(null);\n\tprivate readonly _ports: { [authority: string]: number | undefined; } = Object.create(null);\n\tprivate readonly _connectionTokens: { [authority: string]: string | undefined; } = Object.create(null);\n\tprivate _preferredWebSchema: 'http' | 'https' = 'http';\n\tprivate _delegate: ((uri: URI) => URI) | null = null;\n\n\tsetPreferredWebSchema(schema: 'http' | 'https') {\n\t\tthis._preferredWebSchema = schema;\n\t}\n\n\trewrite(uri: URI): URI {\n\t\tif (this._delegate) {\n\t\t\treturn this._delegate(uri);\n\t\t}\n\t\tconst authority = uri.authority;\n\t\tlet host = this._hosts[authority];\n\t\tif (host && host.indexOf(':') !== -1) {\n\t\t\thost = `[${host}]`;\n\t\t}\n\t\tconst port = this._ports[authority];\n\t\tconst connectionToken = this._connectionTokens[authority];\n\t\tlet query = `path=${encodeURIComponent(uri.path)}`;\n\t\tif (typeof connectionToken === 'string') {\n\t\t\tquery += `&${connectionTokenQueryName}=${encodeURIComponent(connectionToken)}`;\n\t\t}\n\t\treturn URI.from({\n\t\t\tscheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,\n\t\t\tauthority: `${host}:${port}`,\n\t\t\tpath: `/vscode-remote-resource`,\n\t\t\tquery\n\t\t});\n\t}\n}\n\nexport const RemoteAuthorities = new RemoteAuthoritiesImpl();\n\nclass FileAccessImpl {\n\n\tprivate static readonly FALLBACK_AUTHORITY = 'vscode-app';\n\n\t/**\n\t * Returns a URI to use in contexts where the browser is responsible\n\t * for loading (e.g. fetch()) or when used within the DOM.\n\t *\n\t * **Note:** use `dom.ts#asCSSUrl` whenever the URL is to be used in CSS context.\n\t */\n\tasBrowserUri(uri: URI): URI;\n\tasBrowserUri(moduleId: string, moduleIdToUrl: { toUrl(moduleId: string): string }): URI;\n\tasBrowserUri(uriOrModule: URI | string, moduleIdToUrl?: { toUrl(moduleId: string): string }): URI {\n\t\tconst uri = this.toUri(uriOrModule, moduleIdToUrl);\n\n\t\t// Handle remote URIs via `RemoteAuthorities`\n\t\tif (uri.scheme === Schemas.vscodeRemote) {\n\t\t\treturn RemoteAuthorities.rewrite(uri);\n\t\t}\n\n\t\t// Convert to `vscode-file` resource..\n\t\tif (\n\t\t\t// ...only ever for `file` resources\n\t\t\turi.scheme === Schemas.file &&\n\t\t\t(\n\t\t\t\t// ...and we run in native environments\n\t\t\t\tplatform.isNative ||\n\t\t\t\t// ...or web worker extensions on desktop\n\t\t\t\t(typeof platform.globals.importScripts === 'function' && platform.globals.origin === `${Schemas.vscodeFileResource}://${FileAccessImpl.FALLBACK_AUTHORITY}`)\n\t\t\t)\n\t\t) {\n\t\t\treturn uri.with({\n\t\t\t\tscheme: Schemas.vscodeFileResource,\n\t\t\t\t// We need to provide an authority here so that it can serve\n\t\t\t\t// as origin for network and loading matters in chromium.\n\t\t\t\t// If the URI is not coming with an authority already, we\n\t\t\t\t// add our own\n\t\t\t\tauthority: uri.authority || FileAccessImpl.FALLBACK_AUTHORITY,\n\t\t\t\tquery: null,\n\t\t\t\tfragment: null\n\t\t\t});\n\t\t}\n\n\t\treturn uri;\n\t}\n\n\tprivate toUri(uriOrModule: URI | string, moduleIdToUrl?: { toUrl(moduleId: string): string }): URI {\n\t\tif (URI.isUri(uriOrModule)) {\n\t\t\treturn uriOrModule;\n\t\t}\n\n\t\treturn URI.parse(moduleIdToUrl!.toUrl(uriOrModule));\n\t}\n}\n\nexport const FileAccess = new FileAccessImpl();\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as browser from 'vs/base/browser/browser';\nimport { BrowserFeatures } from 'vs/base/browser/canIUse';\nimport { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { TimeoutTimer } from 'vs/base/common/async';\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { FileAccess, RemoteAuthorities } from 'vs/base/common/network';\nimport * as platform from 'vs/base/common/platform';\nimport { URI } from 'vs/base/common/uri';\n\nexport function clearNode(node: HTMLElement): void {\n\twhile (node.firstChild) {\n\t\tnode.firstChild.remove();\n\t}\n}\n\n/**\n * @deprecated Use node.isConnected directly\n */\nexport function isInDOM(node: Node | null): boolean {\n\treturn node?.isConnected ?? false;\n}\n\nclass DomListener implements IDisposable {\n\n\tprivate _handler: (e: any) => void;\n\tprivate _node: EventTarget;\n\tprivate readonly _type: string;\n\tprivate readonly _options: boolean | AddEventListenerOptions;\n\n\tconstructor(node: EventTarget, type: string, handler: (e: any) => void, options?: boolean | AddEventListenerOptions) {\n\t\tthis._node = node;\n\t\tthis._type = type;\n\t\tthis._handler = handler;\n\t\tthis._options = (options || false);\n\t\tthis._node.addEventListener(this._type, this._handler, this._options);\n\t}\n\n\tpublic dispose(): void {\n\t\tif (!this._handler) {\n\t\t\t// Already disposed\n\t\t\treturn;\n\t\t}\n\n\t\tthis._node.removeEventListener(this._type, this._handler, this._options);\n\n\t\t// Prevent leakers from holding on to the dom or handler func\n\t\tthis._node = null!;\n\t\tthis._handler = null!;\n\t}\n}\n\nexport function addDisposableListener(node: EventTarget, type: K, handler: (event: GlobalEventHandlersEventMap[K]) => void, useCapture?: boolean): IDisposable;\nexport function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable;\nexport function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, options: AddEventListenerOptions): IDisposable;\nexport function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, useCaptureOrOptions?: boolean | AddEventListenerOptions): IDisposable {\n\treturn new DomListener(node, type, handler, useCaptureOrOptions);\n}\n\nexport interface IAddStandardDisposableListenerSignature {\n\t(node: HTMLElement, type: 'click', handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable;\n\t(node: HTMLElement, type: 'mousedown', handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable;\n\t(node: HTMLElement, type: 'keydown', handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable;\n\t(node: HTMLElement, type: 'keypress', handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable;\n\t(node: HTMLElement, type: 'keyup', handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable;\n\t(node: HTMLElement, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable;\n}\nfunction _wrapAsStandardMouseEvent(handler: (e: IMouseEvent) => void): (e: MouseEvent) => void {\n\treturn function (e: MouseEvent) {\n\t\treturn handler(new StandardMouseEvent(e));\n\t};\n}\nfunction _wrapAsStandardKeyboardEvent(handler: (e: IKeyboardEvent) => void): (e: KeyboardEvent) => void {\n\treturn function (e: KeyboardEvent) {\n\t\treturn handler(new StandardKeyboardEvent(e));\n\t};\n}\nexport let addStandardDisposableListener: IAddStandardDisposableListenerSignature = function addStandardDisposableListener(node: HTMLElement, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable {\n\tlet wrapHandler = handler;\n\n\tif (type === 'click' || type === 'mousedown') {\n\t\twrapHandler = _wrapAsStandardMouseEvent(handler);\n\t} else if (type === 'keydown' || type === 'keypress' || type === 'keyup') {\n\t\twrapHandler = _wrapAsStandardKeyboardEvent(handler);\n\t}\n\n\treturn addDisposableListener(node, type, wrapHandler, useCapture);\n};\n\nexport let addStandardDisposableGenericMouseDownListner = function addStandardDisposableListener(node: HTMLElement, handler: (event: any) => void, useCapture?: boolean): IDisposable {\n\tlet wrapHandler = _wrapAsStandardMouseEvent(handler);\n\n\treturn addDisposableGenericMouseDownListner(node, wrapHandler, useCapture);\n};\n\nexport let addStandardDisposableGenericMouseUpListner = function addStandardDisposableListener(node: HTMLElement, handler: (event: any) => void, useCapture?: boolean): IDisposable {\n\tlet wrapHandler = _wrapAsStandardMouseEvent(handler);\n\n\treturn addDisposableGenericMouseUpListner(node, wrapHandler, useCapture);\n};\nexport function addDisposableGenericMouseDownListner(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable {\n\treturn addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_DOWN : EventType.MOUSE_DOWN, handler, useCapture);\n}\n\nexport function addDisposableGenericMouseUpListner(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable {\n\treturn addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_UP : EventType.MOUSE_UP, handler, useCapture);\n}\nexport function addDisposableNonBubblingMouseOutListener(node: Element, handler: (event: MouseEvent) => void): IDisposable {\n\treturn addDisposableListener(node, 'mouseout', (e: MouseEvent) => {\n\t\t// Mouse out bubbles, so this is an attempt to ignore faux mouse outs coming from children elements\n\t\tlet toElement: Node | null = (e.relatedTarget);\n\t\twhile (toElement && toElement !== node) {\n\t\t\ttoElement = toElement.parentNode;\n\t\t}\n\t\tif (toElement === node) {\n\t\t\treturn;\n\t\t}\n\n\t\thandler(e);\n\t});\n}\n\nexport function addDisposableNonBubblingPointerOutListener(node: Element, handler: (event: MouseEvent) => void): IDisposable {\n\treturn addDisposableListener(node, 'pointerout', (e: MouseEvent) => {\n\t\t// Mouse out bubbles, so this is an attempt to ignore faux mouse outs coming from children elements\n\t\tlet toElement: Node | null = (e.relatedTarget);\n\t\twhile (toElement && toElement !== node) {\n\t\t\ttoElement = toElement.parentNode;\n\t\t}\n\t\tif (toElement === node) {\n\t\t\treturn;\n\t\t}\n\n\t\thandler(e);\n\t});\n}\n\nexport function createEventEmitter(target: HTMLElement, type: K, options?: boolean | AddEventListenerOptions): Emitter {\n\tlet domListener: DomListener | null = null;\n\tconst handler = (e: HTMLElementEventMap[K]) => result.fire(e);\n\tconst onFirstListenerAdd = () => {\n\t\tif (!domListener) {\n\t\t\tdomListener = new DomListener(target, type, handler, options);\n\t\t}\n\t};\n\tconst onLastListenerRemove = () => {\n\t\tif (domListener) {\n\t\t\tdomListener.dispose();\n\t\t\tdomListener = null;\n\t\t}\n\t};\n\tconst result = new Emitter({ onFirstListenerAdd, onLastListenerRemove });\n\treturn result;\n}\n\ninterface IRequestAnimationFrame {\n\t(callback: (time: number) => void): number;\n}\nlet _animationFrame: IRequestAnimationFrame | null = null;\nfunction doRequestAnimationFrame(callback: (time: number) => void): number {\n\tif (!_animationFrame) {\n\t\tconst emulatedRequestAnimationFrame = (callback: (time: number) => void): any => {\n\t\t\treturn setTimeout(() => callback(new Date().getTime()), 0);\n\t\t};\n\t\t_animationFrame = (\n\t\t\tself.requestAnimationFrame\n\t\t\t|| (self).msRequestAnimationFrame\n\t\t\t|| (self).webkitRequestAnimationFrame\n\t\t\t|| (self).mozRequestAnimationFrame\n\t\t\t|| (self).oRequestAnimationFrame\n\t\t\t|| emulatedRequestAnimationFrame\n\t\t);\n\t}\n\treturn _animationFrame.call(self, callback);\n}\n\n/**\n * Schedule a callback to be run at the next animation frame.\n * This allows multiple parties to register callbacks that should run at the next animation frame.\n * If currently in an animation frame, `runner` will be executed immediately.\n * @return token that can be used to cancel the scheduled runner (only if `runner` was not executed immediately).\n */\nexport let runAtThisOrScheduleAtNextAnimationFrame: (runner: () => void, priority?: number) => IDisposable;\n/**\n * Schedule a callback to be run at the next animation frame.\n * This allows multiple parties to register callbacks that should run at the next animation frame.\n * If currently in an animation frame, `runner` will be executed at the next animation frame.\n * @return token that can be used to cancel the scheduled runner.\n */\nexport let scheduleAtNextAnimationFrame: (runner: () => void, priority?: number) => IDisposable;\n\nclass AnimationFrameQueueItem implements IDisposable {\n\n\tprivate _runner: () => void;\n\tpublic priority: number;\n\tprivate _canceled: boolean;\n\n\tconstructor(runner: () => void, priority: number = 0) {\n\t\tthis._runner = runner;\n\t\tthis.priority = priority;\n\t\tthis._canceled = false;\n\t}\n\n\tpublic dispose(): void {\n\t\tthis._canceled = true;\n\t}\n\n\tpublic execute(): void {\n\t\tif (this._canceled) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis._runner();\n\t\t} catch (e) {\n\t\t\tonUnexpectedError(e);\n\t\t}\n\t}\n\n\t// Sort by priority (largest to lowest)\n\tpublic static sort(a: AnimationFrameQueueItem, b: AnimationFrameQueueItem): number {\n\t\treturn b.priority - a.priority;\n\t}\n}\n\n(function () {\n\t/**\n\t * The runners scheduled at the next animation frame\n\t */\n\tlet NEXT_QUEUE: AnimationFrameQueueItem[] = [];\n\t/**\n\t * The runners scheduled at the current animation frame\n\t */\n\tlet CURRENT_QUEUE: AnimationFrameQueueItem[] | null = null;\n\t/**\n\t * A flag to keep track if the native requestAnimationFrame was already called\n\t */\n\tlet animFrameRequested = false;\n\t/**\n\t * A flag to indicate if currently handling a native requestAnimationFrame callback\n\t */\n\tlet inAnimationFrameRunner = false;\n\n\tlet animationFrameRunner = () => {\n\t\tanimFrameRequested = false;\n\n\t\tCURRENT_QUEUE = NEXT_QUEUE;\n\t\tNEXT_QUEUE = [];\n\n\t\tinAnimationFrameRunner = true;\n\t\twhile (CURRENT_QUEUE.length > 0) {\n\t\t\tCURRENT_QUEUE.sort(AnimationFrameQueueItem.sort);\n\t\t\tlet top = CURRENT_QUEUE.shift()!;\n\t\t\ttop.execute();\n\t\t}\n\t\tinAnimationFrameRunner = false;\n\t};\n\n\tscheduleAtNextAnimationFrame = (runner: () => void, priority: number = 0) => {\n\t\tlet item = new AnimationFrameQueueItem(runner, priority);\n\t\tNEXT_QUEUE.push(item);\n\n\t\tif (!animFrameRequested) {\n\t\t\tanimFrameRequested = true;\n\t\t\tdoRequestAnimationFrame(animationFrameRunner);\n\t\t}\n\n\t\treturn item;\n\t};\n\n\trunAtThisOrScheduleAtNextAnimationFrame = (runner: () => void, priority?: number) => {\n\t\tif (inAnimationFrameRunner) {\n\t\t\tlet item = new AnimationFrameQueueItem(runner, priority);\n\t\t\tCURRENT_QUEUE!.push(item);\n\t\t\treturn item;\n\t\t} else {\n\t\t\treturn scheduleAtNextAnimationFrame(runner, priority);\n\t\t}\n\t};\n})();\n\n/**\n * Add a throttled listener. `handler` is fired at most every 8.33333ms or with the next animation frame (if browser supports it).\n */\nexport interface IEventMerger {\n\t(lastEvent: R | null, currentEvent: E): R;\n}\n\nexport interface DOMEvent {\n}\n\nconst MINIMUM_TIME_MS = 8;\nconst DEFAULT_EVENT_MERGER: IEventMerger = function (lastEvent: DOMEvent | null, currentEvent: DOMEvent) {\n\treturn currentEvent;\n};\n\nclass TimeoutThrottledDomListener extends Disposable {\n\n\tconstructor(node: any, type: string, handler: (event: R) => void, eventMerger: IEventMerger = DEFAULT_EVENT_MERGER, minimumTimeMs: number = MINIMUM_TIME_MS) {\n\t\tsuper();\n\n\t\tlet lastEvent: R | null = null;\n\t\tlet lastHandlerTime = 0;\n\t\tlet timeout = this._register(new TimeoutTimer());\n\n\t\tlet invokeHandler = () => {\n\t\t\tlastHandlerTime = (new Date()).getTime();\n\t\t\thandler(lastEvent);\n\t\t\tlastEvent = null;\n\t\t};\n\n\t\tthis._register(addDisposableListener(node, type, (e) => {\n\n\t\t\tlastEvent = eventMerger(lastEvent, e);\n\t\t\tlet elapsedTime = (new Date()).getTime() - lastHandlerTime;\n\n\t\t\tif (elapsedTime >= minimumTimeMs) {\n\t\t\t\ttimeout.cancel();\n\t\t\t\tinvokeHandler();\n\t\t\t} else {\n\t\t\t\ttimeout.setIfNotSet(invokeHandler, minimumTimeMs - elapsedTime);\n\t\t\t}\n\t\t}));\n\t}\n}\n\nexport function addDisposableThrottledListener(node: any, type: string, handler: (event: R) => void, eventMerger?: IEventMerger, minimumTimeMs?: number): IDisposable {\n\treturn new TimeoutThrottledDomListener(node, type, handler, eventMerger, minimumTimeMs);\n}\n\nexport function getComputedStyle(el: HTMLElement): CSSStyleDeclaration {\n\treturn document.defaultView!.getComputedStyle(el, null);\n}\n\nexport function getClientArea(element: HTMLElement): Dimension {\n\n\t// Try with DOM clientWidth / clientHeight\n\tif (element !== document.body) {\n\t\treturn new Dimension(element.clientWidth, element.clientHeight);\n\t}\n\n\t// If visual view port exits and it's on mobile, it should be used instead of window innerWidth / innerHeight, or document.body.clientWidth / document.body.clientHeight\n\tif (platform.isIOS && window.visualViewport) {\n\t\treturn new Dimension(window.visualViewport.width, window.visualViewport.height);\n\t}\n\n\t// Try innerWidth / innerHeight\n\tif (window.innerWidth && window.innerHeight) {\n\t\treturn new Dimension(window.innerWidth, window.innerHeight);\n\t}\n\n\t// Try with document.body.clientWidth / document.body.clientHeight\n\tif (document.body && document.body.clientWidth && document.body.clientHeight) {\n\t\treturn new Dimension(document.body.clientWidth, document.body.clientHeight);\n\t}\n\n\t// Try with document.documentElement.clientWidth / document.documentElement.clientHeight\n\tif (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientHeight) {\n\t\treturn new Dimension(document.documentElement.clientWidth, document.documentElement.clientHeight);\n\t}\n\n\tthrow new Error('Unable to figure out browser width and height');\n}\n\nclass SizeUtils {\n\t// Adapted from WinJS\n\t// Converts a CSS positioning string for the specified element to pixels.\n\tprivate static convertToPixels(element: HTMLElement, value: string): number {\n\t\treturn parseFloat(value) || 0;\n\t}\n\n\tprivate static getDimension(element: HTMLElement, cssPropertyName: string, jsPropertyName: string): number {\n\t\tlet computedStyle: CSSStyleDeclaration = getComputedStyle(element);\n\t\tlet value = '0';\n\t\tif (computedStyle) {\n\t\t\tif (computedStyle.getPropertyValue) {\n\t\t\t\tvalue = computedStyle.getPropertyValue(cssPropertyName);\n\t\t\t} else {\n\t\t\t\t// IE8\n\t\t\t\tvalue = (computedStyle).getAttribute(jsPropertyName);\n\t\t\t}\n\t\t}\n\t\treturn SizeUtils.convertToPixels(element, value);\n\t}\n\n\tstatic getBorderLeftWidth(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'border-left-width', 'borderLeftWidth');\n\t}\n\tstatic getBorderRightWidth(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'border-right-width', 'borderRightWidth');\n\t}\n\tstatic getBorderTopWidth(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'border-top-width', 'borderTopWidth');\n\t}\n\tstatic getBorderBottomWidth(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'border-bottom-width', 'borderBottomWidth');\n\t}\n\n\tstatic getPaddingLeft(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'padding-left', 'paddingLeft');\n\t}\n\tstatic getPaddingRight(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'padding-right', 'paddingRight');\n\t}\n\tstatic getPaddingTop(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'padding-top', 'paddingTop');\n\t}\n\tstatic getPaddingBottom(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'padding-bottom', 'paddingBottom');\n\t}\n\n\tstatic getMarginLeft(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'margin-left', 'marginLeft');\n\t}\n\tstatic getMarginTop(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'margin-top', 'marginTop');\n\t}\n\tstatic getMarginRight(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'margin-right', 'marginRight');\n\t}\n\tstatic getMarginBottom(element: HTMLElement): number {\n\t\treturn SizeUtils.getDimension(element, 'margin-bottom', 'marginBottom');\n\t}\n}\n\n// ----------------------------------------------------------------------------------------\n// Position & Dimension\n\nexport interface IDimension {\n\treadonly width: number;\n\treadonly height: number;\n}\n\nexport class Dimension implements IDimension {\n\n\tstatic readonly None = new Dimension(0, 0);\n\n\tconstructor(\n\t\tpublic readonly width: number,\n\t\tpublic readonly height: number,\n\t) { }\n\n\twith(width: number = this.width, height: number = this.height): Dimension {\n\t\tif (width !== this.width || height !== this.height) {\n\t\t\treturn new Dimension(width, height);\n\t\t} else {\n\t\t\treturn this;\n\t\t}\n\t}\n\n\tstatic is(obj: unknown): obj is IDimension {\n\t\treturn typeof obj === 'object' && typeof (obj).height === 'number' && typeof (obj).width === 'number';\n\t}\n\n\tstatic lift(obj: IDimension): Dimension {\n\t\tif (obj instanceof Dimension) {\n\t\t\treturn obj;\n\t\t} else {\n\t\t\treturn new Dimension(obj.width, obj.height);\n\t\t}\n\t}\n\n\tstatic equals(a: Dimension | undefined, b: Dimension | undefined): boolean {\n\t\tif (a === b) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!a || !b) {\n\t\t\treturn false;\n\t\t}\n\t\treturn a.width === b.width && a.height === b.height;\n\t}\n}\n\nexport function getTopLeftOffset(element: HTMLElement): { left: number; top: number; } {\n\t// Adapted from WinJS.Utilities.getPosition\n\t// and added borders to the mix\n\n\tlet offsetParent = element.offsetParent;\n\tlet top = element.offsetTop;\n\tlet left = element.offsetLeft;\n\n\twhile (\n\t\t(element = element.parentNode) !== null\n\t\t&& element !== document.body\n\t\t&& element !== document.documentElement\n\t) {\n\t\ttop -= element.scrollTop;\n\t\tconst c = isShadowRoot(element) ? null : getComputedStyle(element);\n\t\tif (c) {\n\t\t\tleft -= c.direction !== 'rtl' ? element.scrollLeft : -element.scrollLeft;\n\t\t}\n\n\t\tif (element === offsetParent) {\n\t\t\tleft += SizeUtils.getBorderLeftWidth(element);\n\t\t\ttop += SizeUtils.getBorderTopWidth(element);\n\t\t\ttop += element.offsetTop;\n\t\t\tleft += element.offsetLeft;\n\t\t\toffsetParent = element.offsetParent;\n\t\t}\n\t}\n\n\treturn {\n\t\tleft: left,\n\t\ttop: top\n\t};\n}\n\nexport interface IDomNodePagePosition {\n\tleft: number;\n\ttop: number;\n\twidth: number;\n\theight: number;\n}\n\nexport function size(element: HTMLElement, width: number | null, height: number | null): void {\n\tif (typeof width === 'number') {\n\t\telement.style.width = `${width}px`;\n\t}\n\n\tif (typeof height === 'number') {\n\t\telement.style.height = `${height}px`;\n\t}\n}\n\n/**\n * Returns the position of a dom node relative to the entire page.\n */\nexport function getDomNodePagePosition(domNode: HTMLElement): IDomNodePagePosition {\n\tlet bb = domNode.getBoundingClientRect();\n\treturn {\n\t\tleft: bb.left + StandardWindow.scrollX,\n\t\ttop: bb.top + StandardWindow.scrollY,\n\t\twidth: bb.width,\n\t\theight: bb.height\n\t};\n}\n\nexport interface IStandardWindow {\n\treadonly scrollX: number;\n\treadonly scrollY: number;\n}\n\nexport const StandardWindow: IStandardWindow = new class implements IStandardWindow {\n\tget scrollX(): number {\n\t\tif (typeof window.scrollX === 'number') {\n\t\t\t// modern browsers\n\t\t\treturn window.scrollX;\n\t\t} else {\n\t\t\treturn document.body.scrollLeft + document.documentElement!.scrollLeft;\n\t\t}\n\t}\n\n\tget scrollY(): number {\n\t\tif (typeof window.scrollY === 'number') {\n\t\t\t// modern browsers\n\t\t\treturn window.scrollY;\n\t\t} else {\n\t\t\treturn document.body.scrollTop + document.documentElement!.scrollTop;\n\t\t}\n\t}\n};\n\n// Adapted from WinJS\n// Gets the width of the element, including margins.\nexport function getTotalWidth(element: HTMLElement): number {\n\tlet margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element);\n\treturn element.offsetWidth + margin;\n}\n\nexport function getContentWidth(element: HTMLElement): number {\n\tlet border = SizeUtils.getBorderLeftWidth(element) + SizeUtils.getBorderRightWidth(element);\n\tlet padding = SizeUtils.getPaddingLeft(element) + SizeUtils.getPaddingRight(element);\n\treturn element.offsetWidth - border - padding;\n}\n\n// Adapted from WinJS\n// Gets the height of the content of the specified element. The content height does not include borders or padding.\nexport function getContentHeight(element: HTMLElement): number {\n\tlet border = SizeUtils.getBorderTopWidth(element) + SizeUtils.getBorderBottomWidth(element);\n\tlet padding = SizeUtils.getPaddingTop(element) + SizeUtils.getPaddingBottom(element);\n\treturn element.offsetHeight - border - padding;\n}\n\n// Adapted from WinJS\n// Gets the height of the element, including its margins.\nexport function getTotalHeight(element: HTMLElement): number {\n\tlet margin = SizeUtils.getMarginTop(element) + SizeUtils.getMarginBottom(element);\n\treturn element.offsetHeight + margin;\n}\n\n// ----------------------------------------------------------------------------------------\n\nexport function isAncestor(testChild: Node | null, testAncestor: Node | null): boolean {\n\twhile (testChild) {\n\t\tif (testChild === testAncestor) {\n\t\t\treturn true;\n\t\t}\n\t\ttestChild = testChild.parentNode;\n\t}\n\n\treturn false;\n}\n\nexport function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement | null {\n\twhile (node && node.nodeType === node.ELEMENT_NODE) {\n\t\tif (node.classList.contains(clazz)) {\n\t\t\treturn node;\n\t\t}\n\n\t\tif (stopAtClazzOrNode) {\n\t\t\tif (typeof stopAtClazzOrNode === 'string') {\n\t\t\t\tif (node.classList.contains(stopAtClazzOrNode)) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (node === stopAtClazzOrNode) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tnode = node.parentNode;\n\t}\n\n\treturn null;\n}\n\nexport function hasParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): boolean {\n\treturn !!findParentWithClass(node, clazz, stopAtClazzOrNode);\n}\n\nexport function isShadowRoot(node: Node): node is ShadowRoot {\n\treturn (\n\t\tnode && !!(node).host && !!(node).mode\n\t);\n}\n\nexport function isInShadowDOM(domNode: Node): boolean {\n\treturn !!getShadowRoot(domNode);\n}\n\nexport function getShadowRoot(domNode: Node): ShadowRoot | null {\n\twhile (domNode.parentNode) {\n\t\tif (domNode === document.body) {\n\t\t\t// reached the body\n\t\t\treturn null;\n\t\t}\n\t\tdomNode = domNode.parentNode;\n\t}\n\treturn isShadowRoot(domNode) ? domNode : null;\n}\n\nexport function getActiveElement(): Element | null {\n\tlet result = document.activeElement;\n\n\twhile (result?.shadowRoot) {\n\t\tresult = result.shadowRoot.activeElement;\n\t}\n\n\treturn result;\n}\n\nexport function createStyleSheet(container: HTMLElement = document.getElementsByTagName('head')[0]): HTMLStyleElement {\n\tlet style = document.createElement('style');\n\tstyle.type = 'text/css';\n\tstyle.media = 'screen';\n\tcontainer.appendChild(style);\n\treturn style;\n}\n\nlet _sharedStyleSheet: HTMLStyleElement | null = null;\nfunction getSharedStyleSheet(): HTMLStyleElement {\n\tif (!_sharedStyleSheet) {\n\t\t_sharedStyleSheet = createStyleSheet();\n\t}\n\treturn _sharedStyleSheet;\n}\n\nfunction getDynamicStyleSheetRules(style: any) {\n\tif (style?.sheet?.rules) {\n\t\t// Chrome, IE\n\t\treturn style.sheet.rules;\n\t}\n\tif (style?.sheet?.cssRules) {\n\t\t// FF\n\t\treturn style.sheet.cssRules;\n\t}\n\treturn [];\n}\n\nexport function createCSSRule(selector: string, cssText: string, style: HTMLStyleElement = getSharedStyleSheet()): void {\n\tif (!style || !cssText) {\n\t\treturn;\n\t}\n\n\t(style.sheet).insertRule(selector + '{' + cssText + '}', 0);\n}\n\nexport function removeCSSRulesContainingSelector(ruleName: string, style: HTMLStyleElement = getSharedStyleSheet()): void {\n\tif (!style) {\n\t\treturn;\n\t}\n\n\tlet rules = getDynamicStyleSheetRules(style);\n\tlet toDelete: number[] = [];\n\tfor (let i = 0; i < rules.length; i++) {\n\t\tlet rule = rules[i];\n\t\tif (rule.selectorText.indexOf(ruleName) !== -1) {\n\t\t\ttoDelete.push(i);\n\t\t}\n\t}\n\n\tfor (let i = toDelete.length - 1; i >= 0; i--) {\n\t\t(style.sheet).deleteRule(toDelete[i]);\n\t}\n}\n\nexport function isHTMLElement(o: any): o is HTMLElement {\n\tif (typeof HTMLElement === 'object') {\n\t\treturn o instanceof HTMLElement;\n\t}\n\treturn o && typeof o === 'object' && o.nodeType === 1 && typeof o.nodeName === 'string';\n}\n\nexport const EventType = {\n\t// Mouse\n\tCLICK: 'click',\n\tAUXCLICK: 'auxclick',\n\tDBLCLICK: 'dblclick',\n\tMOUSE_UP: 'mouseup',\n\tMOUSE_DOWN: 'mousedown',\n\tMOUSE_OVER: 'mouseover',\n\tMOUSE_MOVE: 'mousemove',\n\tMOUSE_OUT: 'mouseout',\n\tMOUSE_ENTER: 'mouseenter',\n\tMOUSE_LEAVE: 'mouseleave',\n\tMOUSE_WHEEL: 'wheel',\n\tPOINTER_UP: 'pointerup',\n\tPOINTER_DOWN: 'pointerdown',\n\tPOINTER_MOVE: 'pointermove',\n\tCONTEXT_MENU: 'contextmenu',\n\tWHEEL: 'wheel',\n\t// Keyboard\n\tKEY_DOWN: 'keydown',\n\tKEY_PRESS: 'keypress',\n\tKEY_UP: 'keyup',\n\t// HTML Document\n\tLOAD: 'load',\n\tBEFORE_UNLOAD: 'beforeunload',\n\tUNLOAD: 'unload',\n\tPAGE_SHOW: 'pageshow',\n\tPAGE_HIDE: 'pagehide',\n\tABORT: 'abort',\n\tERROR: 'error',\n\tRESIZE: 'resize',\n\tSCROLL: 'scroll',\n\tFULLSCREEN_CHANGE: 'fullscreenchange',\n\tWK_FULLSCREEN_CHANGE: 'webkitfullscreenchange',\n\t// Form\n\tSELECT: 'select',\n\tCHANGE: 'change',\n\tSUBMIT: 'submit',\n\tRESET: 'reset',\n\tFOCUS: 'focus',\n\tFOCUS_IN: 'focusin',\n\tFOCUS_OUT: 'focusout',\n\tBLUR: 'blur',\n\tINPUT: 'input',\n\t// Local Storage\n\tSTORAGE: 'storage',\n\t// Drag\n\tDRAG_START: 'dragstart',\n\tDRAG: 'drag',\n\tDRAG_ENTER: 'dragenter',\n\tDRAG_LEAVE: 'dragleave',\n\tDRAG_OVER: 'dragover',\n\tDROP: 'drop',\n\tDRAG_END: 'dragend',\n\t// Animation\n\tANIMATION_START: browser.isWebKit ? 'webkitAnimationStart' : 'animationstart',\n\tANIMATION_END: browser.isWebKit ? 'webkitAnimationEnd' : 'animationend',\n\tANIMATION_ITERATION: browser.isWebKit ? 'webkitAnimationIteration' : 'animationiteration'\n} as const;\n\nexport interface EventLike {\n\tpreventDefault(): void;\n\tstopPropagation(): void;\n}\n\nexport const EventHelper = {\n\tstop: function (e: EventLike, cancelBubble?: boolean) {\n\t\tif (e.preventDefault) {\n\t\t\te.preventDefault();\n\t\t} else {\n\t\t\t// IE8\n\t\t\t(e).returnValue = false;\n\t\t}\n\n\t\tif (cancelBubble) {\n\t\t\tif (e.stopPropagation) {\n\t\t\t\te.stopPropagation();\n\t\t\t} else {\n\t\t\t\t// IE8\n\t\t\t\t(e).cancelBubble = true;\n\t\t\t}\n\t\t}\n\t}\n};\n\nexport interface IFocusTracker extends Disposable {\n\tonDidFocus: Event;\n\tonDidBlur: Event;\n}\n\nexport function saveParentsScrollTop(node: Element): number[] {\n\tlet r: number[] = [];\n\tfor (let i = 0; node && node.nodeType === node.ELEMENT_NODE; i++) {\n\t\tr[i] = node.scrollTop;\n\t\tnode = node.parentNode;\n\t}\n\treturn r;\n}\n\nexport function restoreParentsScrollTop(node: Element, state: number[]): void {\n\tfor (let i = 0; node && node.nodeType === node.ELEMENT_NODE; i++) {\n\t\tif (node.scrollTop !== state[i]) {\n\t\t\tnode.scrollTop = state[i];\n\t\t}\n\t\tnode = node.parentNode;\n\t}\n}\n\nclass FocusTracker extends Disposable implements IFocusTracker {\n\n\tprivate readonly _onDidFocus = this._register(new Emitter());\n\tpublic readonly onDidFocus: Event = this._onDidFocus.event;\n\n\tprivate readonly _onDidBlur = this._register(new Emitter());\n\tpublic readonly onDidBlur: Event = this._onDidBlur.event;\n\n\tprivate _refreshStateHandler: () => void;\n\n\tprivate static hasFocusWithin(element: HTMLElement): boolean {\n\t\tconst shadowRoot = getShadowRoot(element);\n\t\tconst activeElement = (shadowRoot ? shadowRoot.activeElement : document.activeElement);\n\t\treturn isAncestor(activeElement, element);\n\t}\n\n\tconstructor(element: HTMLElement | Window) {\n\t\tsuper();\n\t\tlet hasFocus = FocusTracker.hasFocusWithin(element);\n\t\tlet loosingFocus = false;\n\n\t\tconst onFocus = () => {\n\t\t\tloosingFocus = false;\n\t\t\tif (!hasFocus) {\n\t\t\t\thasFocus = true;\n\t\t\t\tthis._onDidFocus.fire();\n\t\t\t}\n\t\t};\n\n\t\tconst onBlur = () => {\n\t\t\tif (hasFocus) {\n\t\t\t\tloosingFocus = true;\n\t\t\t\twindow.setTimeout(() => {\n\t\t\t\t\tif (loosingFocus) {\n\t\t\t\t\t\tloosingFocus = false;\n\t\t\t\t\t\thasFocus = false;\n\t\t\t\t\t\tthis._onDidBlur.fire();\n\t\t\t\t\t}\n\t\t\t\t}, 0);\n\t\t\t}\n\t\t};\n\n\t\tthis._refreshStateHandler = () => {\n\t\t\tlet currentNodeHasFocus = FocusTracker.hasFocusWithin(element);\n\t\t\tif (currentNodeHasFocus !== hasFocus) {\n\t\t\t\tif (hasFocus) {\n\t\t\t\t\tonBlur();\n\t\t\t\t} else {\n\t\t\t\t\tonFocus();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tthis._register(addDisposableListener(element, EventType.FOCUS, onFocus, true));\n\t\tthis._register(addDisposableListener(element, EventType.BLUR, onBlur, true));\n\t\tthis._register(addDisposableListener(element, EventType.FOCUS_IN, () => this._refreshStateHandler()));\n\t\tthis._register(addDisposableListener(element, EventType.FOCUS_OUT, () => this._refreshStateHandler()));\n\t}\n}\n\nexport function trackFocus(element: HTMLElement | Window): IFocusTracker {\n\treturn new FocusTracker(element);\n}\n\nexport function append(parent: HTMLElement, child: T): T;\nexport function append(parent: HTMLElement, ...children: (T | string)[]): void;\nexport function append(parent: HTMLElement, ...children: (T | string)[]): T | void {\n\tparent.append(...children);\n\tif (children.length === 1 && typeof children[0] !== 'string') {\n\t\treturn children[0];\n\t}\n}\n\nexport function prepend(parent: HTMLElement, child: T): T {\n\tparent.insertBefore(child, parent.firstChild);\n\treturn child;\n}\n\n/**\n * Removes all children from `parent` and appends `children`\n */\nexport function reset(parent: HTMLElement, ...children: Array): void {\n\tparent.innerText = '';\n\tappend(parent, ...children);\n}\n\nconst SELECTOR_REGEX = /([\\w\\-]+)?(#([\\w\\-]+))?((\\.([\\w\\-]+))*)/;\n\nexport enum Namespace {\n\tHTML = 'http://www.w3.org/1999/xhtml',\n\tSVG = 'http://www.w3.org/2000/svg'\n}\n\nfunction _$(namespace: Namespace, description: string, attrs?: { [key: string]: any; }, ...children: Array): T {\n\tlet match = SELECTOR_REGEX.exec(description);\n\n\tif (!match) {\n\t\tthrow new Error('Bad use of emmet');\n\t}\n\n\tattrs = { ...(attrs || {}) };\n\n\tlet tagName = match[1] || 'div';\n\tlet result: T;\n\n\tif (namespace !== Namespace.HTML) {\n\t\tresult = document.createElementNS(namespace as string, tagName) as T;\n\t} else {\n\t\tresult = document.createElement(tagName) as unknown as T;\n\t}\n\n\tif (match[3]) {\n\t\tresult.id = match[3];\n\t}\n\tif (match[4]) {\n\t\tresult.className = match[4].replace(/\\./g, ' ').trim();\n\t}\n\n\tObject.keys(attrs).forEach(name => {\n\t\tconst value = attrs![name];\n\n\t\tif (typeof value === 'undefined') {\n\t\t\treturn;\n\t\t}\n\n\t\tif (/^on\\w+$/.test(name)) {\n\t\t\t(result)[name] = value;\n\t\t} else if (name === 'selected') {\n\t\t\tif (value) {\n\t\t\t\tresult.setAttribute(name, 'true');\n\t\t\t}\n\n\t\t} else {\n\t\t\tresult.setAttribute(name, value);\n\t\t}\n\t});\n\n\tresult.append(...children);\n\n\treturn result as T;\n}\n\nexport function $(description: string, attrs?: { [key: string]: any; }, ...children: Array): T {\n\treturn _$(Namespace.HTML, description, attrs, ...children);\n}\n\n$.SVG = function (description: string, attrs?: { [key: string]: any; }, ...children: Array): T {\n\treturn _$(Namespace.SVG, description, attrs, ...children);\n};\n\nexport function show(...elements: HTMLElement[]): void {\n\tfor (let element of elements) {\n\t\telement.style.display = '';\n\t\telement.removeAttribute('aria-hidden');\n\t}\n}\n\nexport function hide(...elements: HTMLElement[]): void {\n\tfor (let element of elements) {\n\t\telement.style.display = 'none';\n\t\telement.setAttribute('aria-hidden', 'true');\n\t}\n}\n\nexport function getElementsByTagName(tag: string): HTMLElement[] {\n\treturn Array.prototype.slice.call(document.getElementsByTagName(tag), 0);\n}\n\n/**\n * Find a value usable for a dom node size such that the likelihood that it would be\n * displayed with constant screen pixels size is as high as possible.\n *\n * e.g. We would desire for the cursors to be 2px (CSS px) wide. Under a devicePixelRatio\n * of 1.25, the cursor will be 2.5 screen pixels wide. Depending on how the dom node aligns/\"snaps\"\n * with the screen pixels, it will sometimes be rendered with 2 screen pixels, and sometimes with 3 screen pixels.\n */\nexport function computeScreenAwareSize(cssPx: number): number {\n\tconst screenPx = window.devicePixelRatio * cssPx;\n\treturn Math.max(1, Math.floor(screenPx)) / window.devicePixelRatio;\n}\n\n/**\n * Open safely a new window. This is the best way to do so, but you cannot tell\n * if the window was opened or if it was blocked by the browser's popup blocker.\n * If you want to tell if the browser blocked the new window, use {@link windowOpenWithSuccess}.\n *\n * See https://github.com/microsoft/monaco-editor/issues/601\n * To protect against malicious code in the linked site, particularly phishing attempts,\n * the window.opener should be set to null to prevent the linked site from having access\n * to change the location of the current page.\n * See https://mathiasbynens.github.io/rel-noopener/\n */\nexport function windowOpenNoOpener(url: string): void {\n\t// By using 'noopener' in the `windowFeatures` argument, the newly created window will\n\t// not be able to use `window.opener` to reach back to the current page.\n\t// See https://stackoverflow.com/a/46958731\n\t// See https://developer.mozilla.org/en-US/docs/Web/API/Window/open#noopener\n\t// However, this also doesn't allow us to realize if the browser blocked\n\t// the creation of the window.\n\twindow.open(url, '_blank', 'noopener');\n}\n\nexport function animate(fn: () => void): IDisposable {\n\tconst step = () => {\n\t\tfn();\n\t\tstepDisposable = scheduleAtNextAnimationFrame(step);\n\t};\n\n\tlet stepDisposable = scheduleAtNextAnimationFrame(step);\n\treturn toDisposable(() => stepDisposable.dispose());\n}\n\nRemoteAuthorities.setPreferredWebSchema(/^https:/.test(window.location.href) ? 'https' : 'http');\n\n/**\n * returns url('...')\n */\nexport function asCSSUrl(uri: URI): string {\n\tif (!uri) {\n\t\treturn `url('')`;\n\t}\n\treturn `url('${FileAccess.asBrowserUri(uri).toString(true).replace(/'/g, '%27')}')`;\n}\n\nexport function asCSSPropertyValue(value: string) {\n\treturn `'${value.replace(/'/g, '%27')}'`;\n}\n\ntype ModifierKey = 'alt' | 'ctrl' | 'shift' | 'meta';\n\nexport interface IModifierKeyStatus {\n\taltKey: boolean;\n\tshiftKey: boolean;\n\tctrlKey: boolean;\n\tmetaKey: boolean;\n\tlastKeyPressed?: ModifierKey;\n\tlastKeyReleased?: ModifierKey;\n\tevent?: KeyboardEvent;\n}\n\nexport class ModifierKeyEmitter extends Emitter {\n\n\tprivate readonly _subscriptions = new DisposableStore();\n\tprivate _keyStatus: IModifierKeyStatus;\n\tprivate static instance: ModifierKeyEmitter;\n\n\tprivate constructor() {\n\t\tsuper();\n\n\t\tthis._keyStatus = {\n\t\t\taltKey: false,\n\t\t\tshiftKey: false,\n\t\t\tctrlKey: false,\n\t\t\tmetaKey: false\n\t\t};\n\n\t\tthis._subscriptions.add(addDisposableListener(window, 'keydown', e => {\n\t\t\tif (e.defaultPrevented) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst event = new StandardKeyboardEvent(e);\n\t\t\t// If Alt-key keydown event is repeated, ignore it #112347\n\t\t\t// Only known to be necessary for Alt-Key at the moment #115810\n\t\t\tif (event.keyCode === KeyCode.Alt && e.repeat) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (e.altKey && !this._keyStatus.altKey) {\n\t\t\t\tthis._keyStatus.lastKeyPressed = 'alt';\n\t\t\t} else if (e.ctrlKey && !this._keyStatus.ctrlKey) {\n\t\t\t\tthis._keyStatus.lastKeyPressed = 'ctrl';\n\t\t\t} else if (e.metaKey && !this._keyStatus.metaKey) {\n\t\t\t\tthis._keyStatus.lastKeyPressed = 'meta';\n\t\t\t} else if (e.shiftKey && !this._keyStatus.shiftKey) {\n\t\t\t\tthis._keyStatus.lastKeyPressed = 'shift';\n\t\t\t} else if (event.keyCode !== KeyCode.Alt) {\n\t\t\t\tthis._keyStatus.lastKeyPressed = undefined;\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._keyStatus.altKey = e.altKey;\n\t\t\tthis._keyStatus.ctrlKey = e.ctrlKey;\n\t\t\tthis._keyStatus.metaKey = e.metaKey;\n\t\t\tthis._keyStatus.shiftKey = e.shiftKey;\n\n\t\t\tif (this._keyStatus.lastKeyPressed) {\n\t\t\t\tthis._keyStatus.event = e;\n\t\t\t\tthis.fire(this._keyStatus);\n\t\t\t}\n\t\t}, true));\n\n\t\tthis._subscriptions.add(addDisposableListener(window, 'keyup', e => {\n\t\t\tif (e.defaultPrevented) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!e.altKey && this._keyStatus.altKey) {\n\t\t\t\tthis._keyStatus.lastKeyReleased = 'alt';\n\t\t\t} else if (!e.ctrlKey && this._keyStatus.ctrlKey) {\n\t\t\t\tthis._keyStatus.lastKeyReleased = 'ctrl';\n\t\t\t} else if (!e.metaKey && this._keyStatus.metaKey) {\n\t\t\t\tthis._keyStatus.lastKeyReleased = 'meta';\n\t\t\t} else if (!e.shiftKey && this._keyStatus.shiftKey) {\n\t\t\t\tthis._keyStatus.lastKeyReleased = 'shift';\n\t\t\t} else {\n\t\t\t\tthis._keyStatus.lastKeyReleased = undefined;\n\t\t\t}\n\n\t\t\tif (this._keyStatus.lastKeyPressed !== this._keyStatus.lastKeyReleased) {\n\t\t\t\tthis._keyStatus.lastKeyPressed = undefined;\n\t\t\t}\n\n\t\t\tthis._keyStatus.altKey = e.altKey;\n\t\t\tthis._keyStatus.ctrlKey = e.ctrlKey;\n\t\t\tthis._keyStatus.metaKey = e.metaKey;\n\t\t\tthis._keyStatus.shiftKey = e.shiftKey;\n\n\t\t\tif (this._keyStatus.lastKeyReleased) {\n\t\t\t\tthis._keyStatus.event = e;\n\t\t\t\tthis.fire(this._keyStatus);\n\t\t\t}\n\t\t}, true));\n\n\t\tthis._subscriptions.add(addDisposableListener(document.body, 'mousedown', () => {\n\t\t\tthis._keyStatus.lastKeyPressed = undefined;\n\t\t}, true));\n\n\t\tthis._subscriptions.add(addDisposableListener(document.body, 'mouseup', () => {\n\t\t\tthis._keyStatus.lastKeyPressed = undefined;\n\t\t}, true));\n\n\t\tthis._subscriptions.add(addDisposableListener(document.body, 'mousemove', e => {\n\t\t\tif (e.buttons) {\n\t\t\t\tthis._keyStatus.lastKeyPressed = undefined;\n\t\t\t}\n\t\t}, true));\n\n\t\tthis._subscriptions.add(addDisposableListener(window, 'blur', () => {\n\t\t\tthis.resetKeyStatus();\n\t\t}));\n\t}\n\n\tget keyStatus(): IModifierKeyStatus {\n\t\treturn this._keyStatus;\n\t}\n\n\t/**\n\t * Allows to explicitly reset the key status based on more knowledge (#109062)\n\t */\n\tresetKeyStatus(): void {\n\t\tthis.doResetKeyStatus();\n\t\tthis.fire(this._keyStatus);\n\t}\n\n\tprivate doResetKeyStatus(): void {\n\t\tthis._keyStatus = {\n\t\t\taltKey: false,\n\t\t\tshiftKey: false,\n\t\t\tctrlKey: false,\n\t\t\tmetaKey: false\n\t\t};\n\t}\n\n\tstatic getInstance() {\n\t\tif (!ModifierKeyEmitter.instance) {\n\t\t\tModifierKeyEmitter.instance = new ModifierKeyEmitter();\n\t\t}\n\n\t\treturn ModifierKeyEmitter.instance;\n\t}\n\n\toverride dispose() {\n\t\tsuper.dispose();\n\t\tthis._subscriptions.dispose();\n\t}\n}\n\nexport function addMatchMediaChangeListener(query: string, callback: () => void): void {\n\tconst mediaQueryList = window.matchMedia(query);\n\tmediaQueryList.addEventListener('change', callback);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as DOM from 'vs/base/browser/dom';\nimport { IMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\n\nexport interface IContentActionHandler {\n\tcallback: (content: string, event?: IMouseEvent) => void;\n\treadonly disposables: DisposableStore;\n}\n\nexport interface FormattedTextRenderOptions {\n\treadonly className?: string;\n\treadonly inline?: boolean;\n\treadonly actionHandler?: IContentActionHandler;\n\treadonly renderCodeSegments?: boolean;\n}\n\nexport function renderText(text: string, options: FormattedTextRenderOptions = {}): HTMLElement {\n\tconst element = createElement(options);\n\telement.textContent = text;\n\treturn element;\n}\n\nexport function renderFormattedText(formattedText: string, options: FormattedTextRenderOptions = {}): HTMLElement {\n\tconst element = createElement(options);\n\t_renderFormattedText(element, parseFormattedText(formattedText, !!options.renderCodeSegments), options.actionHandler, options.renderCodeSegments);\n\treturn element;\n}\n\nexport function createElement(options: FormattedTextRenderOptions): HTMLElement {\n\tconst tagName = options.inline ? 'span' : 'div';\n\tconst element = document.createElement(tagName);\n\tif (options.className) {\n\t\telement.className = options.className;\n\t}\n\treturn element;\n}\n\nclass StringStream {\n\tprivate source: string;\n\tprivate index: number;\n\n\tconstructor(source: string) {\n\t\tthis.source = source;\n\t\tthis.index = 0;\n\t}\n\n\tpublic eos(): boolean {\n\t\treturn this.index >= this.source.length;\n\t}\n\n\tpublic next(): string {\n\t\tconst next = this.peek();\n\t\tthis.advance();\n\t\treturn next;\n\t}\n\n\tpublic peek(): string {\n\t\treturn this.source[this.index];\n\t}\n\n\tpublic advance(): void {\n\t\tthis.index++;\n\t}\n}\n\nconst enum FormatType {\n\tInvalid,\n\tRoot,\n\tText,\n\tBold,\n\tItalics,\n\tAction,\n\tActionClose,\n\tCode,\n\tNewLine\n}\n\ninterface IFormatParseTree {\n\ttype: FormatType;\n\tcontent?: string;\n\tindex?: number;\n\tchildren?: IFormatParseTree[];\n}\n\nfunction _renderFormattedText(element: Node, treeNode: IFormatParseTree, actionHandler?: IContentActionHandler, renderCodeSegments?: boolean) {\n\tlet child: Node | undefined;\n\n\tif (treeNode.type === FormatType.Text) {\n\t\tchild = document.createTextNode(treeNode.content || '');\n\t} else if (treeNode.type === FormatType.Bold) {\n\t\tchild = document.createElement('b');\n\t} else if (treeNode.type === FormatType.Italics) {\n\t\tchild = document.createElement('i');\n\t} else if (treeNode.type === FormatType.Code && renderCodeSegments) {\n\t\tchild = document.createElement('code');\n\t} else if (treeNode.type === FormatType.Action && actionHandler) {\n\t\tconst a = document.createElement('a');\n\t\tactionHandler.disposables.add(DOM.addStandardDisposableListener(a, 'click', (event) => {\n\t\t\tactionHandler.callback(String(treeNode.index), event);\n\t\t}));\n\n\t\tchild = a;\n\t} else if (treeNode.type === FormatType.NewLine) {\n\t\tchild = document.createElement('br');\n\t} else if (treeNode.type === FormatType.Root) {\n\t\tchild = element;\n\t}\n\n\tif (child && element !== child) {\n\t\telement.appendChild(child);\n\t}\n\n\tif (child && Array.isArray(treeNode.children)) {\n\t\ttreeNode.children.forEach((nodeChild) => {\n\t\t\t_renderFormattedText(child!, nodeChild, actionHandler, renderCodeSegments);\n\t\t});\n\t}\n}\n\nfunction parseFormattedText(content: string, parseCodeSegments: boolean): IFormatParseTree {\n\n\tconst root: IFormatParseTree = {\n\t\ttype: FormatType.Root,\n\t\tchildren: []\n\t};\n\n\tlet actionViewItemIndex = 0;\n\tlet current = root;\n\tconst stack: IFormatParseTree[] = [];\n\tconst stream = new StringStream(content);\n\n\twhile (!stream.eos()) {\n\t\tlet next = stream.next();\n\n\t\tconst isEscapedFormatType = (next === '\\\\' && formatTagType(stream.peek(), parseCodeSegments) !== FormatType.Invalid);\n\t\tif (isEscapedFormatType) {\n\t\t\tnext = stream.next(); // unread the backslash if it escapes a format tag type\n\t\t}\n\n\t\tif (!isEscapedFormatType && isFormatTag(next, parseCodeSegments) && next === stream.peek()) {\n\t\t\tstream.advance();\n\n\t\t\tif (current.type === FormatType.Text) {\n\t\t\t\tcurrent = stack.pop()!;\n\t\t\t}\n\n\t\t\tconst type = formatTagType(next, parseCodeSegments);\n\t\t\tif (current.type === type || (current.type === FormatType.Action && type === FormatType.ActionClose)) {\n\t\t\t\tcurrent = stack.pop()!;\n\t\t\t} else {\n\t\t\t\tconst newCurrent: IFormatParseTree = {\n\t\t\t\t\ttype: type,\n\t\t\t\t\tchildren: []\n\t\t\t\t};\n\n\t\t\t\tif (type === FormatType.Action) {\n\t\t\t\t\tnewCurrent.index = actionViewItemIndex;\n\t\t\t\t\tactionViewItemIndex++;\n\t\t\t\t}\n\n\t\t\t\tcurrent.children!.push(newCurrent);\n\t\t\t\tstack.push(current);\n\t\t\t\tcurrent = newCurrent;\n\t\t\t}\n\t\t} else if (next === '\\n') {\n\t\t\tif (current.type === FormatType.Text) {\n\t\t\t\tcurrent = stack.pop()!;\n\t\t\t}\n\n\t\t\tcurrent.children!.push({\n\t\t\t\ttype: FormatType.NewLine\n\t\t\t});\n\n\t\t} else {\n\t\t\tif (current.type !== FormatType.Text) {\n\t\t\t\tconst textCurrent: IFormatParseTree = {\n\t\t\t\t\ttype: FormatType.Text,\n\t\t\t\t\tcontent: next\n\t\t\t\t};\n\t\t\t\tcurrent.children!.push(textCurrent);\n\t\t\t\tstack.push(current);\n\t\t\t\tcurrent = textCurrent;\n\n\t\t\t} else {\n\t\t\t\tcurrent.content += next;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (current.type === FormatType.Text) {\n\t\tcurrent = stack.pop()!;\n\t}\n\n\tif (stack.length) {\n\t\t// incorrectly formatted string literal\n\t}\n\n\treturn root;\n}\n\nfunction isFormatTag(char: string, supportCodeSegments: boolean): boolean {\n\treturn formatTagType(char, supportCodeSegments) !== FormatType.Invalid;\n}\n\nfunction formatTagType(char: string, supportCodeSegments: boolean): FormatType {\n\tswitch (char) {\n\t\tcase '*':\n\t\t\treturn FormatType.Bold;\n\t\tcase '_':\n\t\t\treturn FormatType.Italics;\n\t\tcase '[':\n\t\t\treturn FormatType.Action;\n\t\tcase ']':\n\t\t\treturn FormatType.ActionClose;\n\t\tcase '`':\n\t\t\treturn supportCodeSegments ? FormatType.Code : FormatType.Invalid;\n\t\tdefault:\n\t\t\treturn FormatType.Invalid;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { IframeUtils } from 'vs/base/browser/iframe';\nimport { StandardMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';\nimport { isIOS } from 'vs/base/common/platform';\n\nexport interface IStandardMouseMoveEventData {\n\tleftButton: boolean;\n\tbuttons: number;\n\tposx: number;\n\tposy: number;\n}\n\nexport interface IEventMerger {\n\t(lastEvent: R | null, currentEvent: MouseEvent): R;\n}\n\nexport interface IMouseMoveCallback {\n\t(mouseMoveData: R): void;\n}\n\nexport interface IOnStopCallback {\n\t(browserEvent?: MouseEvent | KeyboardEvent): void;\n}\n\nexport function standardMouseMoveMerger(lastEvent: IStandardMouseMoveEventData | null, currentEvent: MouseEvent): IStandardMouseMoveEventData {\n\tlet ev = new StandardMouseEvent(currentEvent);\n\tev.preventDefault();\n\treturn {\n\t\tleftButton: ev.leftButton,\n\t\tbuttons: ev.buttons,\n\t\tposx: ev.posx,\n\t\tposy: ev.posy\n\t};\n}\n\nexport class GlobalMouseMoveMonitor implements IDisposable {\n\n\tprivate readonly _hooks = new DisposableStore();\n\tprivate _mouseMoveEventMerger: IEventMerger | null = null;\n\tprivate _mouseMoveCallback: IMouseMoveCallback | null = null;\n\tprivate _onStopCallback: IOnStopCallback | null = null;\n\n\tpublic dispose(): void {\n\t\tthis.stopMonitoring(false);\n\t\tthis._hooks.dispose();\n\t}\n\n\tpublic stopMonitoring(invokeStopCallback: boolean, browserEvent?: MouseEvent | KeyboardEvent): void {\n\t\tif (!this.isMonitoring()) {\n\t\t\t// Not monitoring\n\t\t\treturn;\n\t\t}\n\n\t\t// Unhook\n\t\tthis._hooks.clear();\n\t\tthis._mouseMoveEventMerger = null;\n\t\tthis._mouseMoveCallback = null;\n\t\tconst onStopCallback = this._onStopCallback;\n\t\tthis._onStopCallback = null;\n\n\t\tif (invokeStopCallback && onStopCallback) {\n\t\t\tonStopCallback(browserEvent);\n\t\t}\n\t}\n\n\tpublic isMonitoring(): boolean {\n\t\treturn !!this._mouseMoveEventMerger;\n\t}\n\n\tpublic startMonitoring(\n\t\tinitialElement: HTMLElement,\n\t\tinitialButtons: number,\n\t\tmouseMoveEventMerger: IEventMerger,\n\t\tmouseMoveCallback: IMouseMoveCallback,\n\t\tonStopCallback: IOnStopCallback\n\t): void {\n\t\tif (this.isMonitoring()) {\n\t\t\t// I am already hooked\n\t\t\treturn;\n\t\t}\n\t\tthis._mouseMoveEventMerger = mouseMoveEventMerger;\n\t\tthis._mouseMoveCallback = mouseMoveCallback;\n\t\tthis._onStopCallback = onStopCallback;\n\n\t\tconst windowChain = IframeUtils.getSameOriginWindowChain();\n\t\tconst mouseMove = isIOS ? 'pointermove' : 'mousemove'; // Safari sends wrong event, workaround for #122653\n\t\tconst mouseUp = 'mouseup';\n\n\t\tconst listenTo: (Document | ShadowRoot)[] = windowChain.map(element => element.window.document);\n\t\tconst shadowRoot = dom.getShadowRoot(initialElement);\n\t\tif (shadowRoot) {\n\t\t\tlistenTo.unshift(shadowRoot);\n\t\t}\n\n\t\tfor (const element of listenTo) {\n\t\t\tthis._hooks.add(dom.addDisposableThrottledListener(element, mouseMove,\n\t\t\t\t(data: R) => {\n\t\t\t\t\tif (data.buttons !== initialButtons) {\n\t\t\t\t\t\t// Buttons state has changed in the meantime\n\t\t\t\t\t\tthis.stopMonitoring(true);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis._mouseMoveCallback!(data);\n\t\t\t\t},\n\t\t\t\t(lastEvent: R | null, currentEvent) => this._mouseMoveEventMerger!(lastEvent, currentEvent as MouseEvent)\n\t\t\t));\n\t\t\tthis._hooks.add(dom.addDisposableListener(element, mouseUp, (e: MouseEvent) => this.stopMonitoring(true)));\n\t\t}\n\n\t\tif (IframeUtils.hasDifferentOriginAncestor()) {\n\t\t\tlet lastSameOriginAncestor = windowChain[windowChain.length - 1];\n\t\t\t// We might miss a mouse up if it happens outside the iframe\n\t\t\t// This one is for Chrome\n\t\t\tthis._hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document, 'mouseout', (browserEvent: MouseEvent) => {\n\t\t\t\tlet e = new StandardMouseEvent(browserEvent);\n\t\t\t\tif (e.target.tagName.toLowerCase() === 'html') {\n\t\t\t\t\tthis.stopMonitoring(true);\n\t\t\t\t}\n\t\t\t}));\n\t\t\t// This one is for FF\n\t\t\tthis._hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document, 'mouseover', (browserEvent: MouseEvent) => {\n\t\t\t\tlet e = new StandardMouseEvent(browserEvent);\n\t\t\t\tif (e.target.tagName.toLowerCase() === 'html') {\n\t\t\t\t\tthis.stopMonitoring(true);\n\t\t\t\t}\n\t\t\t}));\n\t\t\t// This one is for IE\n\t\t\tthis._hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document.body, 'mouseleave', (browserEvent: MouseEvent) => {\n\t\t\t\tthis.stopMonitoring(true);\n\t\t\t}));\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as DomUtils from 'vs/base/browser/dom';\nimport * as arrays from 'vs/base/common/arrays';\nimport { memoize } from 'vs/base/common/decorators';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\n\nexport namespace EventType {\n\texport const Tap = '-monaco-gesturetap';\n\texport const Change = '-monaco-gesturechange';\n\texport const Start = '-monaco-gesturestart';\n\texport const End = '-monaco-gesturesend';\n\texport const Contextmenu = '-monaco-gesturecontextmenu';\n}\n\ninterface TouchData {\n\tid: number;\n\tinitialTarget: EventTarget;\n\tinitialTimeStamp: number;\n\tinitialPageX: number;\n\tinitialPageY: number;\n\trollingTimestamps: number[];\n\trollingPageX: number[];\n\trollingPageY: number[];\n}\n\nexport interface GestureEvent extends MouseEvent {\n\tinitialTarget: EventTarget | undefined;\n\ttranslationX: number;\n\ttranslationY: number;\n\tpageX: number;\n\tpageY: number;\n\ttapCount: number;\n}\n\ninterface Touch {\n\tidentifier: number;\n\tpageX: number;\n\tpageY: number;\n\ttarget: Element;\n}\n\ninterface TouchList {\n\t[i: number]: Touch;\n\tlength: number;\n\titem(index: number): Touch;\n}\n\ninterface TouchEvent extends Event {\n\ttouches: TouchList;\n\ttargetTouches: TouchList;\n\tchangedTouches: TouchList;\n}\n\nexport class Gesture extends Disposable {\n\n\tprivate static readonly SCROLL_FRICTION = -0.005;\n\tprivate static INSTANCE: Gesture;\n\tprivate static readonly HOLD_DELAY = 700;\n\n\tprivate dispatched = false;\n\tprivate targets: HTMLElement[];\n\tprivate ignoreTargets: HTMLElement[];\n\tprivate handle: IDisposable | null;\n\n\tprivate activeTouches: { [id: number]: TouchData; };\n\n\tprivate _lastSetTapCountTime: number;\n\n\tprivate static readonly CLEAR_TAP_COUNT_TIME = 400; // ms\n\n\n\tprivate constructor() {\n\t\tsuper();\n\n\t\tthis.activeTouches = {};\n\t\tthis.handle = null;\n\t\tthis.targets = [];\n\t\tthis.ignoreTargets = [];\n\t\tthis._lastSetTapCountTime = 0;\n\t\tthis._register(DomUtils.addDisposableListener(document, 'touchstart', (e: TouchEvent) => this.onTouchStart(e), { passive: false }));\n\t\tthis._register(DomUtils.addDisposableListener(document, 'touchend', (e: TouchEvent) => this.onTouchEnd(e)));\n\t\tthis._register(DomUtils.addDisposableListener(document, 'touchmove', (e: TouchEvent) => this.onTouchMove(e), { passive: false }));\n\t}\n\n\tpublic static addTarget(element: HTMLElement): IDisposable {\n\t\tif (!Gesture.isTouchDevice()) {\n\t\t\treturn Disposable.None;\n\t\t}\n\t\tif (!Gesture.INSTANCE) {\n\t\t\tGesture.INSTANCE = new Gesture();\n\t\t}\n\n\t\tGesture.INSTANCE.targets.push(element);\n\n\t\treturn {\n\t\t\tdispose: () => {\n\t\t\t\tGesture.INSTANCE.targets = Gesture.INSTANCE.targets.filter(t => t !== element);\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic static ignoreTarget(element: HTMLElement): IDisposable {\n\t\tif (!Gesture.isTouchDevice()) {\n\t\t\treturn Disposable.None;\n\t\t}\n\t\tif (!Gesture.INSTANCE) {\n\t\t\tGesture.INSTANCE = new Gesture();\n\t\t}\n\n\t\tGesture.INSTANCE.ignoreTargets.push(element);\n\n\t\treturn {\n\t\t\tdispose: () => {\n\t\t\t\tGesture.INSTANCE.ignoreTargets = Gesture.INSTANCE.ignoreTargets.filter(t => t !== element);\n\t\t\t}\n\t\t};\n\t}\n\n\t@memoize\n\tstatic isTouchDevice(): boolean {\n\t\t// `'ontouchstart' in window` always evaluates to true with typescript's modern typings. This causes `window` to be\n\t\t// `never` later in `window.navigator`. That's why we need the explicit `window as Window` cast\n\t\treturn 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n\t}\n\n\tpublic override dispose(): void {\n\t\tif (this.handle) {\n\t\t\tthis.handle.dispose();\n\t\t\tthis.handle = null;\n\t\t}\n\n\t\tsuper.dispose();\n\t}\n\n\tprivate onTouchStart(e: TouchEvent): void {\n\t\tlet timestamp = Date.now(); // use Date.now() because on FF e.timeStamp is not epoch based.\n\n\t\tif (this.handle) {\n\t\t\tthis.handle.dispose();\n\t\t\tthis.handle = null;\n\t\t}\n\n\t\tfor (let i = 0, len = e.targetTouches.length; i < len; i++) {\n\t\t\tlet touch = e.targetTouches.item(i);\n\n\t\t\tthis.activeTouches[touch.identifier] = {\n\t\t\t\tid: touch.identifier,\n\t\t\t\tinitialTarget: touch.target,\n\t\t\t\tinitialTimeStamp: timestamp,\n\t\t\t\tinitialPageX: touch.pageX,\n\t\t\t\tinitialPageY: touch.pageY,\n\t\t\t\trollingTimestamps: [timestamp],\n\t\t\t\trollingPageX: [touch.pageX],\n\t\t\t\trollingPageY: [touch.pageY]\n\t\t\t};\n\n\t\t\tlet evt = this.newGestureEvent(EventType.Start, touch.target);\n\t\t\tevt.pageX = touch.pageX;\n\t\t\tevt.pageY = touch.pageY;\n\t\t\tthis.dispatchEvent(evt);\n\t\t}\n\n\t\tif (this.dispatched) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tthis.dispatched = false;\n\t\t}\n\t}\n\n\tprivate onTouchEnd(e: TouchEvent): void {\n\t\tlet timestamp = Date.now(); // use Date.now() because on FF e.timeStamp is not epoch based.\n\n\t\tlet activeTouchCount = Object.keys(this.activeTouches).length;\n\n\t\tfor (let i = 0, len = e.changedTouches.length; i < len; i++) {\n\n\t\t\tlet touch = e.changedTouches.item(i);\n\n\t\t\tif (!this.activeTouches.hasOwnProperty(String(touch.identifier))) {\n\t\t\t\tconsole.warn('move of an UNKNOWN touch', touch);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet data = this.activeTouches[touch.identifier],\n\t\t\t\tholdTime = Date.now() - data.initialTimeStamp;\n\n\t\t\tif (holdTime < Gesture.HOLD_DELAY\n\t\t\t\t&& Math.abs(data.initialPageX - arrays.tail(data.rollingPageX)) < 30\n\t\t\t\t&& Math.abs(data.initialPageY - arrays.tail(data.rollingPageY)) < 30) {\n\n\t\t\t\tlet evt = this.newGestureEvent(EventType.Tap, data.initialTarget);\n\t\t\t\tevt.pageX = arrays.tail(data.rollingPageX);\n\t\t\t\tevt.pageY = arrays.tail(data.rollingPageY);\n\t\t\t\tthis.dispatchEvent(evt);\n\n\t\t\t} else if (holdTime >= Gesture.HOLD_DELAY\n\t\t\t\t&& Math.abs(data.initialPageX - arrays.tail(data.rollingPageX)) < 30\n\t\t\t\t&& Math.abs(data.initialPageY - arrays.tail(data.rollingPageY)) < 30) {\n\n\t\t\t\tlet evt = this.newGestureEvent(EventType.Contextmenu, data.initialTarget);\n\t\t\t\tevt.pageX = arrays.tail(data.rollingPageX);\n\t\t\t\tevt.pageY = arrays.tail(data.rollingPageY);\n\t\t\t\tthis.dispatchEvent(evt);\n\n\t\t\t} else if (activeTouchCount === 1) {\n\t\t\t\tlet finalX = arrays.tail(data.rollingPageX);\n\t\t\t\tlet finalY = arrays.tail(data.rollingPageY);\n\n\t\t\t\tlet deltaT = arrays.tail(data.rollingTimestamps) - data.rollingTimestamps[0];\n\t\t\t\tlet deltaX = finalX - data.rollingPageX[0];\n\t\t\t\tlet deltaY = finalY - data.rollingPageY[0];\n\n\t\t\t\t// We need to get all the dispatch targets on the start of the inertia event\n\t\t\t\tconst dispatchTo = this.targets.filter(t => data.initialTarget instanceof Node && t.contains(data.initialTarget));\n\t\t\t\tthis.inertia(dispatchTo, timestamp,\t\t// time now\n\t\t\t\t\tMath.abs(deltaX) / deltaT,\t// speed\n\t\t\t\t\tdeltaX > 0 ? 1 : -1,\t\t// x direction\n\t\t\t\t\tfinalX,\t\t\t\t\t\t// x now\n\t\t\t\t\tMath.abs(deltaY) / deltaT, // y speed\n\t\t\t\t\tdeltaY > 0 ? 1 : -1,\t\t// y direction\n\t\t\t\t\tfinalY\t\t\t\t\t\t// y now\n\t\t\t\t);\n\t\t\t}\n\n\n\t\t\tthis.dispatchEvent(this.newGestureEvent(EventType.End, data.initialTarget));\n\t\t\t// forget about this touch\n\t\t\tdelete this.activeTouches[touch.identifier];\n\t\t}\n\n\t\tif (this.dispatched) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tthis.dispatched = false;\n\t\t}\n\t}\n\n\tprivate newGestureEvent(type: string, initialTarget?: EventTarget): GestureEvent {\n\t\tlet event = document.createEvent('CustomEvent') as unknown as GestureEvent;\n\t\tevent.initEvent(type, false, true);\n\t\tevent.initialTarget = initialTarget;\n\t\tevent.tapCount = 0;\n\t\treturn event;\n\t}\n\n\tprivate dispatchEvent(event: GestureEvent): void {\n\t\tif (event.type === EventType.Tap) {\n\t\t\tconst currentTime = (new Date()).getTime();\n\t\t\tlet setTapCount = 0;\n\t\t\tif (currentTime - this._lastSetTapCountTime > Gesture.CLEAR_TAP_COUNT_TIME) {\n\t\t\t\tsetTapCount = 1;\n\t\t\t} else {\n\t\t\t\tsetTapCount = 2;\n\t\t\t}\n\n\t\t\tthis._lastSetTapCountTime = currentTime;\n\t\t\tevent.tapCount = setTapCount;\n\t\t} else if (event.type === EventType.Change || event.type === EventType.Contextmenu) {\n\t\t\t// tap is canceled by scrolling or context menu\n\t\t\tthis._lastSetTapCountTime = 0;\n\t\t}\n\n\t\tfor (let i = 0; i < this.ignoreTargets.length; i++) {\n\t\t\tif (event.initialTarget instanceof Node && this.ignoreTargets[i].contains(event.initialTarget)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.targets.forEach(target => {\n\t\t\tif (event.initialTarget instanceof Node && target.contains(event.initialTarget)) {\n\t\t\t\ttarget.dispatchEvent(event);\n\t\t\t\tthis.dispatched = true;\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate inertia(dispatchTo: EventTarget[], t1: number, vX: number, dirX: number, x: number, vY: number, dirY: number, y: number): void {\n\t\tthis.handle = DomUtils.scheduleAtNextAnimationFrame(() => {\n\t\t\tlet now = Date.now();\n\n\t\t\t// velocity: old speed + accel_over_time\n\t\t\tlet deltaT = now - t1,\n\t\t\t\tdelta_pos_x = 0, delta_pos_y = 0,\n\t\t\t\tstopped = true;\n\n\t\t\tvX += Gesture.SCROLL_FRICTION * deltaT;\n\t\t\tvY += Gesture.SCROLL_FRICTION * deltaT;\n\n\t\t\tif (vX > 0) {\n\t\t\t\tstopped = false;\n\t\t\t\tdelta_pos_x = dirX * vX * deltaT;\n\t\t\t}\n\n\t\t\tif (vY > 0) {\n\t\t\t\tstopped = false;\n\t\t\t\tdelta_pos_y = dirY * vY * deltaT;\n\t\t\t}\n\n\t\t\t// dispatch translation event\n\t\t\tlet evt = this.newGestureEvent(EventType.Change);\n\t\t\tevt.translationX = delta_pos_x;\n\t\t\tevt.translationY = delta_pos_y;\n\t\t\tdispatchTo.forEach(d => d.dispatchEvent(evt));\n\n\t\t\tif (!stopped) {\n\t\t\t\tthis.inertia(dispatchTo, now, vX, dirX, x + delta_pos_x, vY, dirY, y + delta_pos_y);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate onTouchMove(e: TouchEvent): void {\n\t\tlet timestamp = Date.now(); // use Date.now() because on FF e.timeStamp is not epoch based.\n\n\t\tfor (let i = 0, len = e.changedTouches.length; i < len; i++) {\n\n\t\t\tlet touch = e.changedTouches.item(i);\n\n\t\t\tif (!this.activeTouches.hasOwnProperty(String(touch.identifier))) {\n\t\t\t\tconsole.warn('end of an UNKNOWN touch', touch);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet data = this.activeTouches[touch.identifier];\n\n\t\t\tlet evt = this.newGestureEvent(EventType.Change, data.initialTarget);\n\t\t\tevt.translationX = touch.pageX - arrays.tail(data.rollingPageX);\n\t\t\tevt.translationY = touch.pageY - arrays.tail(data.rollingPageY);\n\t\t\tevt.pageX = touch.pageX;\n\t\t\tevt.pageY = touch.pageY;\n\t\t\tthis.dispatchEvent(evt);\n\n\t\t\t// only keep a few data points, to average the final speed\n\t\t\tif (data.rollingPageX.length > 3) {\n\t\t\t\tdata.rollingPageX.shift();\n\t\t\t\tdata.rollingPageY.shift();\n\t\t\t\tdata.rollingTimestamps.shift();\n\t\t\t}\n\n\t\t\tdata.rollingPageX.push(touch.pageX);\n\t\t\tdata.rollingPageY.push(touch.pageY);\n\t\t\tdata.rollingTimestamps.push(timestamp);\n\t\t}\n\n\t\tif (this.dispatched) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tthis.dispatched = false;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { CSSIcon } from 'vs/base/common/codicons';\n\nconst labelWithIconsRegex = new RegExp(`(\\\\\\\\)?\\\\$\\\\((${CSSIcon.iconNameExpression}(?:${CSSIcon.iconModifierExpression})?)\\\\)`, 'g');\nexport function renderLabelWithIcons(text: string): Array {\n\tconst elements = new Array();\n\tlet match: RegExpMatchArray | null;\n\n\tlet textStart = 0, textStop = 0;\n\twhile ((match = labelWithIconsRegex.exec(text)) !== null) {\n\t\ttextStop = match.index || 0;\n\t\telements.push(text.substring(textStart, textStop));\n\t\ttextStart = (match.index || 0) + match[0].length;\n\n\t\tconst [, escaped, codicon] = match;\n\t\telements.push(escaped ? `$(${codicon})` : renderIcon({ id: codicon }));\n\t}\n\n\tif (textStart < text.length) {\n\t\telements.push(text.substring(textStart));\n\t}\n\treturn elements;\n}\n\nexport function renderIcon(icon: CSSIcon): HTMLSpanElement {\n\tconst node = dom.$(`span`);\n\tnode.classList.add(...CSSIcon.asClassNameArray(icon));\n\treturn node;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';\nimport * as objects from 'vs/base/common/objects';\n\n/**\n * A range to be highlighted.\n */\nexport interface IHighlight {\n\tstart: number;\n\tend: number;\n\textraClasses?: string[];\n}\n\nexport interface IOptions {\n\n\t/**\n\t * Whether\n\t */\n\treadonly supportIcons?: boolean;\n}\n\n/**\n * A widget which can render a label with substring highlights, often\n * originating from a filter function like the fuzzy matcher.\n */\nexport class HighlightedLabel {\n\n\tprivate readonly domNode: HTMLElement;\n\tprivate text: string = '';\n\tprivate title: string = '';\n\tprivate highlights: IHighlight[] = [];\n\tprivate supportIcons: boolean;\n\tprivate didEverRender: boolean = false;\n\n\t/**\n\t * Create a new {@link HighlightedLabel}.\n\t *\n\t * @param container The parent container to append to.\n\t */\n\tconstructor(container: HTMLElement, options?: IOptions) {\n\t\tthis.supportIcons = options?.supportIcons ?? false;\n\t\tthis.domNode = dom.append(container, dom.$('span.monaco-highlighted-label'));\n\t}\n\n\t/**\n\t * The label's DOM node.\n\t */\n\tget element(): HTMLElement {\n\t\treturn this.domNode;\n\t}\n\n\t/**\n\t * Set the label and highlights.\n\t *\n\t * @param text The label to display.\n\t * @param highlights The ranges to highlight.\n\t * @param title An optional title for the hover tooltip.\n\t * @param escapeNewLines Whether to escape new lines.\n\t * @returns\n\t */\n\tset(text: string | undefined, highlights: IHighlight[] = [], title: string = '', escapeNewLines?: boolean) {\n\t\tif (!text) {\n\t\t\ttext = '';\n\t\t}\n\n\t\tif (escapeNewLines) {\n\t\t\t// adjusts highlights inplace\n\t\t\ttext = HighlightedLabel.escapeNewLines(text, highlights);\n\t\t}\n\n\t\tif (this.didEverRender && this.text === text && this.title === title && objects.equals(this.highlights, highlights)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.text = text;\n\t\tthis.title = title;\n\t\tthis.highlights = highlights;\n\t\tthis.render();\n\t}\n\n\tprivate render(): void {\n\n\t\tconst children: HTMLSpanElement[] = [];\n\t\tlet pos = 0;\n\n\t\tfor (const highlight of this.highlights) {\n\t\t\tif (highlight.end === highlight.start) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (pos < highlight.start) {\n\t\t\t\tconst substring = this.text.substring(pos, highlight.start);\n\t\t\t\tchildren.push(dom.$('span', undefined, ...this.supportIcons ? renderLabelWithIcons(substring) : [substring]));\n\t\t\t\tpos = highlight.end;\n\t\t\t}\n\n\t\t\tconst substring = this.text.substring(highlight.start, highlight.end);\n\t\t\tconst element = dom.$('span.highlight', undefined, ...this.supportIcons ? renderLabelWithIcons(substring) : [substring]);\n\n\t\t\tif (highlight.extraClasses) {\n\t\t\t\telement.classList.add(...highlight.extraClasses);\n\t\t\t}\n\n\t\t\tchildren.push(element);\n\t\t\tpos = highlight.end;\n\t\t}\n\n\t\tif (pos < this.text.length) {\n\t\t\tconst substring = this.text.substring(pos,);\n\t\t\tchildren.push(dom.$('span', undefined, ...this.supportIcons ? renderLabelWithIcons(substring) : [substring]));\n\t\t}\n\n\t\tdom.reset(this.domNode, ...children);\n\n\t\tif (this.title) {\n\t\t\tthis.domNode.title = this.title;\n\t\t} else {\n\t\t\tthis.domNode.removeAttribute('title');\n\t\t}\n\n\t\tthis.didEverRender = true;\n\t}\n\n\tstatic escapeNewLines(text: string, highlights: IHighlight[]): string {\n\t\tlet total = 0;\n\t\tlet extra = 0;\n\n\t\treturn text.replace(/\\r\\n|\\r|\\n/g, (match, offset) => {\n\t\t\textra = match === '\\r\\n' ? -1 : 0;\n\t\t\toffset += total;\n\n\t\t\tfor (const highlight of highlights) {\n\t\t\t\tif (highlight.end <= offset) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (highlight.start >= offset) {\n\t\t\t\t\thighlight.start += extra;\n\t\t\t\t}\n\t\t\t\tif (highlight.end >= offset) {\n\t\t\t\t\thighlight.end += extra;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttotal += extra;\n\t\t\treturn '\\u23CE';\n\t\t});\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { $ } from 'vs/base/browser/dom';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { IListRenderer } from './list';\n\nexport interface IRow {\n\tdomNode: HTMLElement;\n\ttemplateId: string;\n\ttemplateData: any;\n}\n\nfunction removeFromParent(element: HTMLElement): void {\n\ttry {\n\t\tif (element.parentElement) {\n\t\t\telement.parentElement.removeChild(element);\n\t\t}\n\t} catch (e) {\n\t\t// this will throw if this happens due to a blur event, nasty business\n\t}\n}\n\nexport class RowCache implements IDisposable {\n\n\tprivate cache = new Map();\n\n\tconstructor(private renderers: Map>) { }\n\n\t/**\n\t * Returns a row either by creating a new one or reusing\n\t * a previously released row which shares the same templateId.\n\t */\n\talloc(templateId: string): IRow {\n\t\tlet result = this.getTemplateCache(templateId).pop();\n\n\t\tif (!result) {\n\t\t\tconst domNode = $('.monaco-list-row');\n\t\t\tconst renderer = this.getRenderer(templateId);\n\t\t\tconst templateData = renderer.renderTemplate(domNode);\n\t\t\tresult = { domNode, templateId, templateData };\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Releases the row for eventual reuse.\n\t */\n\trelease(row: IRow): void {\n\t\tif (!row) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.releaseRow(row);\n\t}\n\n\tprivate releaseRow(row: IRow): void {\n\t\tconst { domNode, templateId } = row;\n\t\tif (domNode) {\n\t\t\tdomNode.classList.remove('scrolling');\n\t\t\tremoveFromParent(domNode);\n\t\t}\n\n\t\tconst cache = this.getTemplateCache(templateId);\n\t\tcache.push(row);\n\t}\n\n\tprivate getTemplateCache(templateId: string): IRow[] {\n\t\tlet result = this.cache.get(templateId);\n\n\t\tif (!result) {\n\t\t\tresult = [];\n\t\t\tthis.cache.set(templateId, result);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tdispose(): void {\n\t\tthis.cache.forEach((cachedRows, templateId) => {\n\t\t\tfor (const cachedRow of cachedRows) {\n\t\t\t\tconst renderer = this.getRenderer(templateId);\n\t\t\t\trenderer.disposeTemplate(cachedRow.templateData);\n\t\t\t\tcachedRow.templateData = null;\n\t\t\t}\n\t\t});\n\n\t\tthis.cache.clear();\n\t}\n\n\tprivate getRenderer(templateId: string): IListRenderer {\n\t\tconst renderer = this.renderers.get(templateId);\n\t\tif (!renderer) {\n\t\t\tthrow new Error(`No renderer found for ${templateId}`);\n\t\t}\n\t\treturn renderer;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { Gesture } from 'vs/base/browser/touch';\nimport { Disposable } from 'vs/base/common/lifecycle';\n\nexport abstract class Widget extends Disposable {\n\n\tprotected onclick(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void {\n\t\tthis._register(dom.addDisposableListener(domNode, dom.EventType.CLICK, (e: MouseEvent) => listener(new StandardMouseEvent(e))));\n\t}\n\n\tprotected onmousedown(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void {\n\t\tthis._register(dom.addDisposableListener(domNode, dom.EventType.MOUSE_DOWN, (e: MouseEvent) => listener(new StandardMouseEvent(e))));\n\t}\n\n\tprotected onmouseover(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void {\n\t\tthis._register(dom.addDisposableListener(domNode, dom.EventType.MOUSE_OVER, (e: MouseEvent) => listener(new StandardMouseEvent(e))));\n\t}\n\n\tprotected onnonbubblingmouseout(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void {\n\t\tthis._register(dom.addDisposableNonBubblingMouseOutListener(domNode, (e: MouseEvent) => listener(new StandardMouseEvent(e))));\n\t}\n\n\tprotected onkeydown(domNode: HTMLElement, listener: (e: IKeyboardEvent) => void): void {\n\t\tthis._register(dom.addDisposableListener(domNode, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => listener(new StandardKeyboardEvent(e))));\n\t}\n\n\tprotected onkeyup(domNode: HTMLElement, listener: (e: IKeyboardEvent) => void): void {\n\t\tthis._register(dom.addDisposableListener(domNode, dom.EventType.KEY_UP, (e: KeyboardEvent) => listener(new StandardKeyboardEvent(e))));\n\t}\n\n\tprotected oninput(domNode: HTMLElement, listener: (e: Event) => void): void {\n\t\tthis._register(dom.addDisposableListener(domNode, dom.EventType.INPUT, listener));\n\t}\n\n\tprotected onblur(domNode: HTMLElement, listener: (e: Event) => void): void {\n\t\tthis._register(dom.addDisposableListener(domNode, dom.EventType.BLUR, listener));\n\t}\n\n\tprotected onfocus(domNode: HTMLElement, listener: (e: Event) => void): void {\n\t\tthis._register(dom.addDisposableListener(domNode, dom.EventType.FOCUS, listener));\n\t}\n\n\tprotected ignoreGesture(domNode: HTMLElement): void {\n\t\tGesture.ignoreTarget(domNode);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveMerger } from 'vs/base/browser/globalMouseMoveMonitor';\nimport { IMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { Widget } from 'vs/base/browser/ui/widget';\nimport { IntervalTimer, TimeoutTimer } from 'vs/base/common/async';\nimport { Codicon } from 'vs/base/common/codicons';\n\n/**\n * The arrow image size.\n */\nexport const ARROW_IMG_SIZE = 11;\n\nexport interface ScrollbarArrowOptions {\n\tonActivate: () => void;\n\tclassName: string;\n\ticon: Codicon;\n\n\tbgWidth: number;\n\tbgHeight: number;\n\n\ttop?: number;\n\tleft?: number;\n\tbottom?: number;\n\tright?: number;\n}\n\nexport class ScrollbarArrow extends Widget {\n\n\tprivate _onActivate: () => void;\n\tpublic bgDomNode: HTMLElement;\n\tpublic domNode: HTMLElement;\n\tprivate _mousedownRepeatTimer: IntervalTimer;\n\tprivate _mousedownScheduleRepeatTimer: TimeoutTimer;\n\tprivate _mouseMoveMonitor: GlobalMouseMoveMonitor;\n\n\tconstructor(opts: ScrollbarArrowOptions) {\n\t\tsuper();\n\t\tthis._onActivate = opts.onActivate;\n\n\t\tthis.bgDomNode = document.createElement('div');\n\t\tthis.bgDomNode.className = 'arrow-background';\n\t\tthis.bgDomNode.style.position = 'absolute';\n\t\tthis.bgDomNode.style.width = opts.bgWidth + 'px';\n\t\tthis.bgDomNode.style.height = opts.bgHeight + 'px';\n\t\tif (typeof opts.top !== 'undefined') {\n\t\t\tthis.bgDomNode.style.top = '0px';\n\t\t}\n\t\tif (typeof opts.left !== 'undefined') {\n\t\t\tthis.bgDomNode.style.left = '0px';\n\t\t}\n\t\tif (typeof opts.bottom !== 'undefined') {\n\t\t\tthis.bgDomNode.style.bottom = '0px';\n\t\t}\n\t\tif (typeof opts.right !== 'undefined') {\n\t\t\tthis.bgDomNode.style.right = '0px';\n\t\t}\n\n\t\tthis.domNode = document.createElement('div');\n\t\tthis.domNode.className = opts.className;\n\t\tthis.domNode.classList.add(...opts.icon.classNamesArray);\n\n\t\tthis.domNode.style.position = 'absolute';\n\t\tthis.domNode.style.width = ARROW_IMG_SIZE + 'px';\n\t\tthis.domNode.style.height = ARROW_IMG_SIZE + 'px';\n\t\tif (typeof opts.top !== 'undefined') {\n\t\t\tthis.domNode.style.top = opts.top + 'px';\n\t\t}\n\t\tif (typeof opts.left !== 'undefined') {\n\t\t\tthis.domNode.style.left = opts.left + 'px';\n\t\t}\n\t\tif (typeof opts.bottom !== 'undefined') {\n\t\t\tthis.domNode.style.bottom = opts.bottom + 'px';\n\t\t}\n\t\tif (typeof opts.right !== 'undefined') {\n\t\t\tthis.domNode.style.right = opts.right + 'px';\n\t\t}\n\n\t\tthis._mouseMoveMonitor = this._register(new GlobalMouseMoveMonitor());\n\t\tthis.onmousedown(this.bgDomNode, (e) => this._arrowMouseDown(e));\n\t\tthis.onmousedown(this.domNode, (e) => this._arrowMouseDown(e));\n\n\t\tthis._mousedownRepeatTimer = this._register(new IntervalTimer());\n\t\tthis._mousedownScheduleRepeatTimer = this._register(new TimeoutTimer());\n\t}\n\n\tprivate _arrowMouseDown(e: IMouseEvent): void {\n\t\tconst scheduleRepeater = () => {\n\t\t\tthis._mousedownRepeatTimer.cancelAndSet(() => this._onActivate(), 1000 / 24);\n\t\t};\n\n\t\tthis._onActivate();\n\t\tthis._mousedownRepeatTimer.cancel();\n\t\tthis._mousedownScheduleRepeatTimer.cancelAndSet(scheduleRepeater, 200);\n\n\t\tthis._mouseMoveMonitor.startMonitoring(\n\t\t\te.target,\n\t\t\te.buttons,\n\t\t\tstandardMouseMoveMerger,\n\t\t\t(mouseMoveData: IStandardMouseMoveEventData) => {\n\t\t\t\t/* Intentional empty */\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tthis._mousedownRepeatTimer.cancel();\n\t\t\t\tthis._mousedownScheduleRepeatTimer.cancel();\n\t\t\t}\n\t\t);\n\n\t\te.preventDefault();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { createFastDomNode, FastDomNode } from 'vs/base/browser/fastDomNode';\nimport { GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveMerger } from 'vs/base/browser/globalMouseMoveMonitor';\nimport { IMouseEvent, StandardWheelEvent } from 'vs/base/browser/mouseEvent';\nimport { ScrollbarArrow, ScrollbarArrowOptions } from 'vs/base/browser/ui/scrollbar/scrollbarArrow';\nimport { ScrollbarState } from 'vs/base/browser/ui/scrollbar/scrollbarState';\nimport { ScrollbarVisibilityController } from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController';\nimport { Widget } from 'vs/base/browser/ui/widget';\nimport * as platform from 'vs/base/common/platform';\nimport { INewScrollPosition, Scrollable, ScrollbarVisibility } from 'vs/base/common/scrollable';\n\n/**\n * The orthogonal distance to the slider at which dragging \"resets\". This implements \"snapping\"\n */\nconst MOUSE_DRAG_RESET_DISTANCE = 140;\n\nexport interface ISimplifiedMouseEvent {\n\tposx: number;\n\tposy: number;\n}\n\nexport interface ScrollbarHost {\n\tonMouseWheel(mouseWheelEvent: StandardWheelEvent): void;\n\tonDragStart(): void;\n\tonDragEnd(): void;\n}\n\nexport interface AbstractScrollbarOptions {\n\tlazyRender: boolean;\n\thost: ScrollbarHost;\n\tscrollbarState: ScrollbarState;\n\tvisibility: ScrollbarVisibility;\n\textraScrollbarClassName: string;\n\tscrollable: Scrollable;\n\tscrollByPage: boolean;\n}\n\nexport abstract class AbstractScrollbar extends Widget {\n\n\tprotected _host: ScrollbarHost;\n\tprotected _scrollable: Scrollable;\n\tprotected _scrollByPage: boolean;\n\tprivate _lazyRender: boolean;\n\tprotected _scrollbarState: ScrollbarState;\n\tprotected _visibilityController: ScrollbarVisibilityController;\n\tprivate _mouseMoveMonitor: GlobalMouseMoveMonitor;\n\n\tpublic domNode: FastDomNode;\n\tpublic slider!: FastDomNode;\n\n\tprotected _shouldRender: boolean;\n\n\tconstructor(opts: AbstractScrollbarOptions) {\n\t\tsuper();\n\t\tthis._lazyRender = opts.lazyRender;\n\t\tthis._host = opts.host;\n\t\tthis._scrollable = opts.scrollable;\n\t\tthis._scrollByPage = opts.scrollByPage;\n\t\tthis._scrollbarState = opts.scrollbarState;\n\t\tthis._visibilityController = this._register(new ScrollbarVisibilityController(opts.visibility, 'visible scrollbar ' + opts.extraScrollbarClassName, 'invisible scrollbar ' + opts.extraScrollbarClassName));\n\t\tthis._visibilityController.setIsNeeded(this._scrollbarState.isNeeded());\n\t\tthis._mouseMoveMonitor = this._register(new GlobalMouseMoveMonitor());\n\t\tthis._shouldRender = true;\n\t\tthis.domNode = createFastDomNode(document.createElement('div'));\n\t\tthis.domNode.setAttribute('role', 'presentation');\n\t\tthis.domNode.setAttribute('aria-hidden', 'true');\n\n\t\tthis._visibilityController.setDomNode(this.domNode);\n\t\tthis.domNode.setPosition('absolute');\n\n\t\tthis.onmousedown(this.domNode.domNode, (e) => this._domNodeMouseDown(e));\n\t}\n\n\t// ----------------- creation\n\n\t/**\n\t * Creates the dom node for an arrow & adds it to the container\n\t */\n\tprotected _createArrow(opts: ScrollbarArrowOptions): void {\n\t\tconst arrow = this._register(new ScrollbarArrow(opts));\n\t\tthis.domNode.domNode.appendChild(arrow.bgDomNode);\n\t\tthis.domNode.domNode.appendChild(arrow.domNode);\n\t}\n\n\t/**\n\t * Creates the slider dom node, adds it to the container & hooks up the events\n\t */\n\tprotected _createSlider(top: number, left: number, width: number | undefined, height: number | undefined): void {\n\t\tthis.slider = createFastDomNode(document.createElement('div'));\n\t\tthis.slider.setClassName('slider');\n\t\tthis.slider.setPosition('absolute');\n\t\tthis.slider.setTop(top);\n\t\tthis.slider.setLeft(left);\n\t\tif (typeof width === 'number') {\n\t\t\tthis.slider.setWidth(width);\n\t\t}\n\t\tif (typeof height === 'number') {\n\t\t\tthis.slider.setHeight(height);\n\t\t}\n\t\tthis.slider.setLayerHinting(true);\n\t\tthis.slider.setContain('strict');\n\n\t\tthis.domNode.domNode.appendChild(this.slider.domNode);\n\n\t\tthis.onmousedown(this.slider.domNode, (e) => {\n\t\t\tif (e.leftButton) {\n\t\t\t\te.preventDefault();\n\t\t\t\tthis._sliderMouseDown(e, () => { /*nothing to do*/ });\n\t\t\t}\n\t\t});\n\n\t\tthis.onclick(this.slider.domNode, e => {\n\t\t\tif (e.leftButton) {\n\t\t\t\te.stopPropagation();\n\t\t\t}\n\t\t});\n\t}\n\n\t// ----------------- Update state\n\n\tprotected _onElementSize(visibleSize: number): boolean {\n\t\tif (this._scrollbarState.setVisibleSize(visibleSize)) {\n\t\t\tthis._visibilityController.setIsNeeded(this._scrollbarState.isNeeded());\n\t\t\tthis._shouldRender = true;\n\t\t\tif (!this._lazyRender) {\n\t\t\t\tthis.render();\n\t\t\t}\n\t\t}\n\t\treturn this._shouldRender;\n\t}\n\n\tprotected _onElementScrollSize(elementScrollSize: number): boolean {\n\t\tif (this._scrollbarState.setScrollSize(elementScrollSize)) {\n\t\t\tthis._visibilityController.setIsNeeded(this._scrollbarState.isNeeded());\n\t\t\tthis._shouldRender = true;\n\t\t\tif (!this._lazyRender) {\n\t\t\t\tthis.render();\n\t\t\t}\n\t\t}\n\t\treturn this._shouldRender;\n\t}\n\n\tprotected _onElementScrollPosition(elementScrollPosition: number): boolean {\n\t\tif (this._scrollbarState.setScrollPosition(elementScrollPosition)) {\n\t\t\tthis._visibilityController.setIsNeeded(this._scrollbarState.isNeeded());\n\t\t\tthis._shouldRender = true;\n\t\t\tif (!this._lazyRender) {\n\t\t\t\tthis.render();\n\t\t\t}\n\t\t}\n\t\treturn this._shouldRender;\n\t}\n\n\t// ----------------- rendering\n\n\tpublic beginReveal(): void {\n\t\tthis._visibilityController.setShouldBeVisible(true);\n\t}\n\n\tpublic beginHide(): void {\n\t\tthis._visibilityController.setShouldBeVisible(false);\n\t}\n\n\tpublic render(): void {\n\t\tif (!this._shouldRender) {\n\t\t\treturn;\n\t\t}\n\t\tthis._shouldRender = false;\n\n\t\tthis._renderDomNode(this._scrollbarState.getRectangleLargeSize(), this._scrollbarState.getRectangleSmallSize());\n\t\tthis._updateSlider(this._scrollbarState.getSliderSize(), this._scrollbarState.getArrowSize() + this._scrollbarState.getSliderPosition());\n\t}\n\t// ----------------- DOM events\n\n\tprivate _domNodeMouseDown(e: IMouseEvent): void {\n\t\tif (e.target !== this.domNode.domNode) {\n\t\t\treturn;\n\t\t}\n\t\tthis._onMouseDown(e);\n\t}\n\n\tpublic delegateMouseDown(e: IMouseEvent): void {\n\t\tconst domTop = this.domNode.domNode.getClientRects()[0].top;\n\t\tconst sliderStart = domTop + this._scrollbarState.getSliderPosition();\n\t\tconst sliderStop = domTop + this._scrollbarState.getSliderPosition() + this._scrollbarState.getSliderSize();\n\t\tconst mousePos = this._sliderMousePosition(e);\n\t\tif (sliderStart <= mousePos && mousePos <= sliderStop) {\n\t\t\t// Act as if it was a mouse down on the slider\n\t\t\tif (e.leftButton) {\n\t\t\t\te.preventDefault();\n\t\t\t\tthis._sliderMouseDown(e, () => { /*nothing to do*/ });\n\t\t\t}\n\t\t} else {\n\t\t\t// Act as if it was a mouse down on the scrollbar\n\t\t\tthis._onMouseDown(e);\n\t\t}\n\t}\n\n\tprivate _onMouseDown(e: IMouseEvent): void {\n\t\tlet offsetX: number;\n\t\tlet offsetY: number;\n\t\tif (e.target === this.domNode.domNode && typeof e.browserEvent.offsetX === 'number' && typeof e.browserEvent.offsetY === 'number') {\n\t\t\toffsetX = e.browserEvent.offsetX;\n\t\t\toffsetY = e.browserEvent.offsetY;\n\t\t} else {\n\t\t\tconst domNodePosition = dom.getDomNodePagePosition(this.domNode.domNode);\n\t\t\toffsetX = e.posx - domNodePosition.left;\n\t\t\toffsetY = e.posy - domNodePosition.top;\n\t\t}\n\n\t\tconst offset = this._mouseDownRelativePosition(offsetX, offsetY);\n\t\tthis._setDesiredScrollPositionNow(\n\t\t\tthis._scrollByPage\n\t\t\t\t? this._scrollbarState.getDesiredScrollPositionFromOffsetPaged(offset)\n\t\t\t\t: this._scrollbarState.getDesiredScrollPositionFromOffset(offset)\n\t\t);\n\n\t\tif (e.leftButton) {\n\t\t\te.preventDefault();\n\t\t\tthis._sliderMouseDown(e, () => { /*nothing to do*/ });\n\t\t}\n\t}\n\n\tprivate _sliderMouseDown(e: IMouseEvent, onDragFinished: () => void): void {\n\t\tconst initialMousePosition = this._sliderMousePosition(e);\n\t\tconst initialMouseOrthogonalPosition = this._sliderOrthogonalMousePosition(e);\n\t\tconst initialScrollbarState = this._scrollbarState.clone();\n\t\tthis.slider.toggleClassName('active', true);\n\n\t\tthis._mouseMoveMonitor.startMonitoring(\n\t\t\te.target,\n\t\t\te.buttons,\n\t\t\tstandardMouseMoveMerger,\n\t\t\t(mouseMoveData: IStandardMouseMoveEventData) => {\n\t\t\t\tconst mouseOrthogonalPosition = this._sliderOrthogonalMousePosition(mouseMoveData);\n\t\t\t\tconst mouseOrthogonalDelta = Math.abs(mouseOrthogonalPosition - initialMouseOrthogonalPosition);\n\n\t\t\t\tif (platform.isWindows && mouseOrthogonalDelta > MOUSE_DRAG_RESET_DISTANCE) {\n\t\t\t\t\t// The mouse has wondered away from the scrollbar => reset dragging\n\t\t\t\t\tthis._setDesiredScrollPositionNow(initialScrollbarState.getScrollPosition());\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst mousePosition = this._sliderMousePosition(mouseMoveData);\n\t\t\t\tconst mouseDelta = mousePosition - initialMousePosition;\n\t\t\t\tthis._setDesiredScrollPositionNow(initialScrollbarState.getDesiredScrollPositionFromDelta(mouseDelta));\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tthis.slider.toggleClassName('active', false);\n\t\t\t\tthis._host.onDragEnd();\n\t\t\t\tonDragFinished();\n\t\t\t}\n\t\t);\n\n\t\tthis._host.onDragStart();\n\t}\n\n\tprivate _setDesiredScrollPositionNow(_desiredScrollPosition: number): void {\n\n\t\tconst desiredScrollPosition: INewScrollPosition = {};\n\t\tthis.writeScrollPosition(desiredScrollPosition, _desiredScrollPosition);\n\n\t\tthis._scrollable.setScrollPositionNow(desiredScrollPosition);\n\t}\n\n\tpublic updateScrollbarSize(scrollbarSize: number): void {\n\t\tthis._updateScrollbarSize(scrollbarSize);\n\t\tthis._scrollbarState.setScrollbarSize(scrollbarSize);\n\t\tthis._shouldRender = true;\n\t\tif (!this._lazyRender) {\n\t\t\tthis.render();\n\t\t}\n\t}\n\n\tpublic isNeeded(): boolean {\n\t\treturn this._scrollbarState.isNeeded();\n\t}\n\n\t// ----------------- Overwrite these\n\n\tprotected abstract _renderDomNode(largeSize: number, smallSize: number): void;\n\tprotected abstract _updateSlider(sliderSize: number, sliderPosition: number): void;\n\n\tprotected abstract _mouseDownRelativePosition(offsetX: number, offsetY: number): number;\n\tprotected abstract _sliderMousePosition(e: ISimplifiedMouseEvent): number;\n\tprotected abstract _sliderOrthogonalMousePosition(e: ISimplifiedMouseEvent): number;\n\tprotected abstract _updateScrollbarSize(size: number): void;\n\n\tpublic abstract writeScrollPosition(target: INewScrollPosition, scrollPosition: number): void;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { StandardWheelEvent } from 'vs/base/browser/mouseEvent';\nimport { AbstractScrollbar, ISimplifiedMouseEvent, ScrollbarHost } from 'vs/base/browser/ui/scrollbar/abstractScrollbar';\nimport { ScrollableElementResolvedOptions } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';\nimport { ARROW_IMG_SIZE } from 'vs/base/browser/ui/scrollbar/scrollbarArrow';\nimport { ScrollbarState } from 'vs/base/browser/ui/scrollbar/scrollbarState';\nimport { Codicon } from 'vs/base/common/codicons';\nimport { INewScrollPosition, Scrollable, ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';\n\n\n\n\nexport class HorizontalScrollbar extends AbstractScrollbar {\n\n\tconstructor(scrollable: Scrollable, options: ScrollableElementResolvedOptions, host: ScrollbarHost) {\n\t\tconst scrollDimensions = scrollable.getScrollDimensions();\n\t\tconst scrollPosition = scrollable.getCurrentScrollPosition();\n\t\tsuper({\n\t\t\tlazyRender: options.lazyRender,\n\t\t\thost: host,\n\t\t\tscrollbarState: new ScrollbarState(\n\t\t\t\t(options.horizontalHasArrows ? options.arrowSize : 0),\n\t\t\t\t(options.horizontal === ScrollbarVisibility.Hidden ? 0 : options.horizontalScrollbarSize),\n\t\t\t\t(options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize),\n\t\t\t\tscrollDimensions.width,\n\t\t\t\tscrollDimensions.scrollWidth,\n\t\t\t\tscrollPosition.scrollLeft\n\t\t\t),\n\t\t\tvisibility: options.horizontal,\n\t\t\textraScrollbarClassName: 'horizontal',\n\t\t\tscrollable: scrollable,\n\t\t\tscrollByPage: options.scrollByPage\n\t\t});\n\n\t\tif (options.horizontalHasArrows) {\n\t\t\tconst arrowDelta = (options.arrowSize - ARROW_IMG_SIZE) / 2;\n\t\t\tconst scrollbarDelta = (options.horizontalScrollbarSize - ARROW_IMG_SIZE) / 2;\n\n\t\t\tthis._createArrow({\n\t\t\t\tclassName: 'scra',\n\t\t\t\ticon: Codicon.scrollbarButtonLeft,\n\t\t\t\ttop: scrollbarDelta,\n\t\t\t\tleft: arrowDelta,\n\t\t\t\tbottom: undefined,\n\t\t\t\tright: undefined,\n\t\t\t\tbgWidth: options.arrowSize,\n\t\t\t\tbgHeight: options.horizontalScrollbarSize,\n\t\t\t\tonActivate: () => this._host.onMouseWheel(new StandardWheelEvent(null, 1, 0)),\n\t\t\t});\n\n\t\t\tthis._createArrow({\n\t\t\t\tclassName: 'scra',\n\t\t\t\ticon: Codicon.scrollbarButtonRight,\n\t\t\t\ttop: scrollbarDelta,\n\t\t\t\tleft: undefined,\n\t\t\t\tbottom: undefined,\n\t\t\t\tright: arrowDelta,\n\t\t\t\tbgWidth: options.arrowSize,\n\t\t\t\tbgHeight: options.horizontalScrollbarSize,\n\t\t\t\tonActivate: () => this._host.onMouseWheel(new StandardWheelEvent(null, -1, 0)),\n\t\t\t});\n\t\t}\n\n\t\tthis._createSlider(Math.floor((options.horizontalScrollbarSize - options.horizontalSliderSize) / 2), 0, undefined, options.horizontalSliderSize);\n\t}\n\n\tprotected _updateSlider(sliderSize: number, sliderPosition: number): void {\n\t\tthis.slider.setWidth(sliderSize);\n\t\tthis.slider.setLeft(sliderPosition);\n\t}\n\n\tprotected _renderDomNode(largeSize: number, smallSize: number): void {\n\t\tthis.domNode.setWidth(largeSize);\n\t\tthis.domNode.setHeight(smallSize);\n\t\tthis.domNode.setLeft(0);\n\t\tthis.domNode.setBottom(0);\n\t}\n\n\tpublic onDidScroll(e: ScrollEvent): boolean {\n\t\tthis._shouldRender = this._onElementScrollSize(e.scrollWidth) || this._shouldRender;\n\t\tthis._shouldRender = this._onElementScrollPosition(e.scrollLeft) || this._shouldRender;\n\t\tthis._shouldRender = this._onElementSize(e.width) || this._shouldRender;\n\t\treturn this._shouldRender;\n\t}\n\n\tprotected _mouseDownRelativePosition(offsetX: number, offsetY: number): number {\n\t\treturn offsetX;\n\t}\n\n\tprotected _sliderMousePosition(e: ISimplifiedMouseEvent): number {\n\t\treturn e.posx;\n\t}\n\n\tprotected _sliderOrthogonalMousePosition(e: ISimplifiedMouseEvent): number {\n\t\treturn e.posy;\n\t}\n\n\tprotected _updateScrollbarSize(size: number): void {\n\t\tthis.slider.setHeight(size);\n\t}\n\n\tpublic writeScrollPosition(target: INewScrollPosition, scrollPosition: number): void {\n\t\ttarget.scrollLeft = scrollPosition;\n\t}\n\n\tpublic updateOptions(options: ScrollableElementResolvedOptions): void {\n\t\tthis.updateScrollbarSize(options.horizontal === ScrollbarVisibility.Hidden ? 0 : options.horizontalScrollbarSize);\n\t\tthis._scrollbarState.setOppositeScrollbarSize(options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize);\n\t\tthis._visibilityController.setVisibility(options.horizontal);\n\t\tthis._scrollByPage = options.scrollByPage;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { StandardWheelEvent } from 'vs/base/browser/mouseEvent';\nimport { AbstractScrollbar, ISimplifiedMouseEvent, ScrollbarHost } from 'vs/base/browser/ui/scrollbar/abstractScrollbar';\nimport { ScrollableElementResolvedOptions } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';\nimport { ARROW_IMG_SIZE } from 'vs/base/browser/ui/scrollbar/scrollbarArrow';\nimport { ScrollbarState } from 'vs/base/browser/ui/scrollbar/scrollbarState';\nimport { Codicon } from 'vs/base/common/codicons';\nimport { INewScrollPosition, Scrollable, ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';\n\n\n\nexport class VerticalScrollbar extends AbstractScrollbar {\n\n\tconstructor(scrollable: Scrollable, options: ScrollableElementResolvedOptions, host: ScrollbarHost) {\n\t\tconst scrollDimensions = scrollable.getScrollDimensions();\n\t\tconst scrollPosition = scrollable.getCurrentScrollPosition();\n\t\tsuper({\n\t\t\tlazyRender: options.lazyRender,\n\t\t\thost: host,\n\t\t\tscrollbarState: new ScrollbarState(\n\t\t\t\t(options.verticalHasArrows ? options.arrowSize : 0),\n\t\t\t\t(options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize),\n\t\t\t\t// give priority to vertical scroll bar over horizontal and let it scroll all the way to the bottom\n\t\t\t\t0,\n\t\t\t\tscrollDimensions.height,\n\t\t\t\tscrollDimensions.scrollHeight,\n\t\t\t\tscrollPosition.scrollTop\n\t\t\t),\n\t\t\tvisibility: options.vertical,\n\t\t\textraScrollbarClassName: 'vertical',\n\t\t\tscrollable: scrollable,\n\t\t\tscrollByPage: options.scrollByPage\n\t\t});\n\n\t\tif (options.verticalHasArrows) {\n\t\t\tconst arrowDelta = (options.arrowSize - ARROW_IMG_SIZE) / 2;\n\t\t\tconst scrollbarDelta = (options.verticalScrollbarSize - ARROW_IMG_SIZE) / 2;\n\n\t\t\tthis._createArrow({\n\t\t\t\tclassName: 'scra',\n\t\t\t\ticon: Codicon.scrollbarButtonUp,\n\t\t\t\ttop: arrowDelta,\n\t\t\t\tleft: scrollbarDelta,\n\t\t\t\tbottom: undefined,\n\t\t\t\tright: undefined,\n\t\t\t\tbgWidth: options.verticalScrollbarSize,\n\t\t\t\tbgHeight: options.arrowSize,\n\t\t\t\tonActivate: () => this._host.onMouseWheel(new StandardWheelEvent(null, 0, 1)),\n\t\t\t});\n\n\t\t\tthis._createArrow({\n\t\t\t\tclassName: 'scra',\n\t\t\t\ticon: Codicon.scrollbarButtonDown,\n\t\t\t\ttop: undefined,\n\t\t\t\tleft: scrollbarDelta,\n\t\t\t\tbottom: arrowDelta,\n\t\t\t\tright: undefined,\n\t\t\t\tbgWidth: options.verticalScrollbarSize,\n\t\t\t\tbgHeight: options.arrowSize,\n\t\t\t\tonActivate: () => this._host.onMouseWheel(new StandardWheelEvent(null, 0, -1)),\n\t\t\t});\n\t\t}\n\n\t\tthis._createSlider(0, Math.floor((options.verticalScrollbarSize - options.verticalSliderSize) / 2), options.verticalSliderSize, undefined);\n\t}\n\n\tprotected _updateSlider(sliderSize: number, sliderPosition: number): void {\n\t\tthis.slider.setHeight(sliderSize);\n\t\tthis.slider.setTop(sliderPosition);\n\t}\n\n\tprotected _renderDomNode(largeSize: number, smallSize: number): void {\n\t\tthis.domNode.setWidth(smallSize);\n\t\tthis.domNode.setHeight(largeSize);\n\t\tthis.domNode.setRight(0);\n\t\tthis.domNode.setTop(0);\n\t}\n\n\tpublic onDidScroll(e: ScrollEvent): boolean {\n\t\tthis._shouldRender = this._onElementScrollSize(e.scrollHeight) || this._shouldRender;\n\t\tthis._shouldRender = this._onElementScrollPosition(e.scrollTop) || this._shouldRender;\n\t\tthis._shouldRender = this._onElementSize(e.height) || this._shouldRender;\n\t\treturn this._shouldRender;\n\t}\n\n\tprotected _mouseDownRelativePosition(offsetX: number, offsetY: number): number {\n\t\treturn offsetY;\n\t}\n\n\tprotected _sliderMousePosition(e: ISimplifiedMouseEvent): number {\n\t\treturn e.posy;\n\t}\n\n\tprotected _sliderOrthogonalMousePosition(e: ISimplifiedMouseEvent): number {\n\t\treturn e.posx;\n\t}\n\n\tprotected _updateScrollbarSize(size: number): void {\n\t\tthis.slider.setWidth(size);\n\t}\n\n\tpublic writeScrollPosition(target: INewScrollPosition, scrollPosition: number): void {\n\t\ttarget.scrollTop = scrollPosition;\n\t}\n\n\tpublic updateOptions(options: ScrollableElementResolvedOptions): void {\n\t\tthis.updateScrollbarSize(options.vertical === ScrollbarVisibility.Hidden ? 0 : options.verticalScrollbarSize);\n\t\t// give priority to vertical scroll bar over horizontal and let it scroll all the way to the bottom\n\t\tthis._scrollbarState.setOppositeScrollbarSize(0);\n\t\tthis._visibilityController.setVisibility(options.vertical);\n\t\tthis._scrollByPage = options.scrollByPage;\n\t}\n\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport * as extpath from 'vs/base/common/extpath';\nimport { Schemas } from 'vs/base/common/network';\nimport * as paths from 'vs/base/common/path';\nimport { isLinux, isWindows } from 'vs/base/common/platform';\nimport { compare as strCompare, equalsIgnoreCase } from 'vs/base/common/strings';\nimport { URI, uriToFsPath } from 'vs/base/common/uri';\n\nexport function originalFSPath(uri: URI): string {\n\treturn uriToFsPath(uri, true);\n}\n\n//#region IExtUri\n\nexport interface IExtUri {\n}\n\nexport class ExtUri implements IExtUri {\n\n\tconstructor(private _ignorePathCasing: (uri: URI) => boolean) { }\n\n\tcompare(uri1: URI, uri2: URI, ignoreFragment: boolean = false): number {\n\t\tif (uri1 === uri2) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn strCompare(this.getComparisonKey(uri1, ignoreFragment), this.getComparisonKey(uri2, ignoreFragment));\n\t}\n\n\tisEqual(uri1: URI | undefined, uri2: URI | undefined, ignoreFragment: boolean = false): boolean {\n\t\tif (uri1 === uri2) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!uri1 || !uri2) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.getComparisonKey(uri1, ignoreFragment) === this.getComparisonKey(uri2, ignoreFragment);\n\t}\n\n\tgetComparisonKey(uri: URI, ignoreFragment: boolean = false): string {\n\t\treturn uri.with({\n\t\t\tpath: this._ignorePathCasing(uri) ? uri.path.toLowerCase() : undefined,\n\t\t\tfragment: ignoreFragment ? null : undefined\n\t\t}).toString();\n\t}\n\n\tisEqualOrParent(base: URI, parentCandidate: URI, ignoreFragment: boolean = false): boolean {\n\t\tif (base.scheme === parentCandidate.scheme) {\n\t\t\tif (base.scheme === Schemas.file) {\n\t\t\t\treturn extpath.isEqualOrParent(originalFSPath(base), originalFSPath(parentCandidate), this._ignorePathCasing(base)) && base.query === parentCandidate.query && (ignoreFragment || base.fragment === parentCandidate.fragment);\n\t\t\t}\n\t\t\tif (isEqualAuthority(base.authority, parentCandidate.authority)) {\n\t\t\t\treturn extpath.isEqualOrParent(base.path, parentCandidate.path, this._ignorePathCasing(base), '/') && base.query === parentCandidate.query && (ignoreFragment || base.fragment === parentCandidate.fragment);\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t// --- path math\n\n\tjoinPath(resource: URI, ...pathFragment: string[]): URI {\n\t\treturn URI.joinPath(resource, ...pathFragment);\n\t}\n\n\tbasenameOrAuthority(resource: URI): string {\n\t\treturn basename(resource) || resource.authority;\n\t}\n\n\tbasename(resource: URI): string {\n\t\treturn paths.posix.basename(resource.path);\n\t}\n\n\textname(resource: URI): string {\n\t\treturn paths.posix.extname(resource.path);\n\t}\n\n\tdirname(resource: URI): URI {\n\t\tif (resource.path.length === 0) {\n\t\t\treturn resource;\n\t\t}\n\t\tlet dirname;\n\t\tif (resource.scheme === Schemas.file) {\n\t\t\tdirname = URI.file(paths.dirname(originalFSPath(resource))).path;\n\t\t} else {\n\t\t\tdirname = paths.posix.dirname(resource.path);\n\t\t\tif (resource.authority && dirname.length && dirname.charCodeAt(0) !== CharCode.Slash) {\n\t\t\t\tconsole.error(`dirname(\"${resource.toString})) resulted in a relative path`);\n\t\t\t\tdirname = '/'; // If a URI contains an authority component, then the path component must either be empty or begin with a CharCode.Slash (\"/\") character\n\t\t\t}\n\t\t}\n\t\treturn resource.with({\n\t\t\tpath: dirname\n\t\t});\n\t}\n\n\tnormalizePath(resource: URI): URI {\n\t\tif (!resource.path.length) {\n\t\t\treturn resource;\n\t\t}\n\t\tlet normalizedPath: string;\n\t\tif (resource.scheme === Schemas.file) {\n\t\t\tnormalizedPath = URI.file(paths.normalize(originalFSPath(resource))).path;\n\t\t} else {\n\t\t\tnormalizedPath = paths.posix.normalize(resource.path);\n\t\t}\n\t\treturn resource.with({\n\t\t\tpath: normalizedPath\n\t\t});\n\t}\n\n\trelativePath(from: URI, to: URI): string | undefined {\n\t\tif (from.scheme !== to.scheme || !isEqualAuthority(from.authority, to.authority)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (from.scheme === Schemas.file) {\n\t\t\tconst relativePath = paths.relative(originalFSPath(from), originalFSPath(to));\n\t\t\treturn isWindows ? extpath.toSlashes(relativePath) : relativePath;\n\t\t}\n\t\tlet fromPath = from.path || '/', toPath = to.path || '/';\n\t\tif (this._ignorePathCasing(from)) {\n\t\t\t// make casing of fromPath match toPath\n\t\t\tlet i = 0;\n\t\t\tfor (const len = Math.min(fromPath.length, toPath.length); i < len; i++) {\n\t\t\t\tif (fromPath.charCodeAt(i) !== toPath.charCodeAt(i)) {\n\t\t\t\t\tif (fromPath.charAt(i).toLowerCase() !== toPath.charAt(i).toLowerCase()) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfromPath = toPath.substr(0, i) + fromPath.substr(i);\n\t\t}\n\t\treturn paths.posix.relative(fromPath, toPath);\n\t}\n\n\tresolvePath(base: URI, path: string): URI {\n\t\tif (base.scheme === Schemas.file) {\n\t\t\tconst newURI = URI.file(paths.resolve(originalFSPath(base), path));\n\t\t\treturn base.with({\n\t\t\t\tauthority: newURI.authority,\n\t\t\t\tpath: newURI.path\n\t\t\t});\n\t\t}\n\t\tpath = extpath.toPosixPath(path); // we allow path to be a windows path\n\t\treturn base.with({\n\t\t\tpath: paths.posix.resolve(base.path, path)\n\t\t});\n\t}\n\n\t// --- misc\n\n\tisAbsolutePath(resource: URI): boolean {\n\t\treturn !!resource.path && resource.path[0] === '/';\n\t}\n\n\tisEqualAuthority(a1: string | undefined, a2: string | undefined) {\n\t\treturn a1 === a2 || (a1 !== undefined && a2 !== undefined && equalsIgnoreCase(a1, a2));\n\t}\n\n\thasTrailingPathSeparator(resource: URI, sep: string = paths.sep): boolean {\n\t\tif (resource.scheme === Schemas.file) {\n\t\t\tconst fsp = originalFSPath(resource);\n\t\t\treturn fsp.length > extpath.getRoot(fsp).length && fsp[fsp.length - 1] === sep;\n\t\t} else {\n\t\t\tconst p = resource.path;\n\t\t\treturn (p.length > 1 && p.charCodeAt(p.length - 1) === CharCode.Slash) && !(/^[a-zA-Z]:(\\/$|\\\\$)/.test(resource.fsPath)); // ignore the slash at offset 0\n\t\t}\n\t}\n\n\tremoveTrailingPathSeparator(resource: URI, sep: string = paths.sep): URI {\n\t\t// Make sure that the path isn't a drive letter. A trailing separator there is not removable.\n\t\tif (hasTrailingPathSeparator(resource, sep)) {\n\t\t\treturn resource.with({ path: resource.path.substr(0, resource.path.length - 1) });\n\t\t}\n\t\treturn resource;\n\t}\n\n\taddTrailingPathSeparator(resource: URI, sep: string = paths.sep): URI {\n\t\tlet isRootSep: boolean = false;\n\t\tif (resource.scheme === Schemas.file) {\n\t\t\tconst fsp = originalFSPath(resource);\n\t\t\tisRootSep = ((fsp !== undefined) && (fsp.length === extpath.getRoot(fsp).length) && (fsp[fsp.length - 1] === sep));\n\t\t} else {\n\t\t\tsep = '/';\n\t\t\tconst p = resource.path;\n\t\t\tisRootSep = p.length === 1 && p.charCodeAt(p.length - 1) === CharCode.Slash;\n\t\t}\n\t\tif (!isRootSep && !hasTrailingPathSeparator(resource, sep)) {\n\t\t\treturn resource.with({ path: resource.path + '/' });\n\t\t}\n\t\treturn resource;\n\t}\n}\n\n\n/**\n * Unbiased utility that takes uris \"as they are\". This means it can be interchanged with\n * uri#toString() usages. The following is true\n * ```\n * assertEqual(aUri.toString() === bUri.toString(), exturi.isEqual(aUri, bUri))\n * ```\n */\nexport const extUri = new ExtUri(() => false);\n\n/**\n * BIASED utility that _mostly_ ignored the case of urs paths. ONLY use this util if you\n * understand what you are doing.\n *\n * This utility is INCOMPATIBLE with `uri.toString()`-usages and both CANNOT be used interchanged.\n *\n * When dealing with uris from files or documents, `extUri` (the unbiased friend)is sufficient\n * because those uris come from a \"trustworthy source\". When creating unknown uris it's always\n * better to use `IUriIdentityService` which exposes an `IExtUri`-instance which knows when path\n * casing matters.\n */\nexport const extUriBiasedIgnorePathCase = new ExtUri(uri => {\n\t// A file scheme resource is in the same platform as code, so ignore case for non linux platforms\n\t// Resource can be from another platform. Lowering the case as an hack. Should come from File system provider\n\treturn uri.scheme === Schemas.file ? !isLinux : true;\n});\n\n\n/**\n * BIASED utility that always ignores the casing of uris paths. ONLY use this util if you\n * understand what you are doing.\n *\n * This utility is INCOMPATIBLE with `uri.toString()`-usages and both CANNOT be used interchanged.\n *\n * When dealing with uris from files or documents, `extUri` (the unbiased friend)is sufficient\n * because those uris come from a \"trustworthy source\". When creating unknown uris it's always\n * better to use `IUriIdentityService` which exposes an `IExtUri`-instance which knows when path\n * casing matters.\n */\nexport const extUriIgnorePathCase = new ExtUri(_ => true);\n\nexport const isEqual = extUri.isEqual.bind(extUri);\nexport const isEqualOrParent = extUri.isEqualOrParent.bind(extUri);\nexport const getComparisonKey = extUri.getComparisonKey.bind(extUri);\nexport const basenameOrAuthority = extUri.basenameOrAuthority.bind(extUri);\nexport const basename = extUri.basename.bind(extUri);\nexport const extname = extUri.extname.bind(extUri);\nexport const dirname = extUri.dirname.bind(extUri);\nexport const joinPath = extUri.joinPath.bind(extUri);\nexport const normalizePath = extUri.normalizePath.bind(extUri);\nexport const relativePath = extUri.relativePath.bind(extUri);\nexport const resolvePath = extUri.resolvePath.bind(extUri);\nexport const isAbsolutePath = extUri.isAbsolutePath.bind(extUri);\nexport const isEqualAuthority = extUri.isEqualAuthority.bind(extUri);\nexport const hasTrailingPathSeparator = extUri.hasTrailingPathSeparator.bind(extUri);\nexport const removeTrailingPathSeparator = extUri.removeTrailingPathSeparator.bind(extUri);\nexport const addTrailingPathSeparator = extUri.addTrailingPathSeparator.bind(extUri);\n\n/**\n * Data URI related helpers.\n */\nexport namespace DataUri {\n\n\texport const META_DATA_LABEL = 'label';\n\texport const META_DATA_DESCRIPTION = 'description';\n\texport const META_DATA_SIZE = 'size';\n\texport const META_DATA_MIME = 'mime';\n\n\texport function parseMetaData(dataUri: URI): Map {\n\t\tconst metadata = new Map();\n\n\t\t// Given a URI of: data:image/png;size:2313;label:SomeLabel;description:SomeDescription;base64,77+9UE5...\n\t\t// the metadata is: size:2313;label:SomeLabel;description:SomeDescription\n\t\tconst meta = dataUri.path.substring(dataUri.path.indexOf(';') + 1, dataUri.path.lastIndexOf(';'));\n\t\tmeta.split(';').forEach(property => {\n\t\t\tconst [key, value] = property.split(':');\n\t\t\tif (key && value) {\n\t\t\t\tmetadata.set(key, value);\n\t\t\t}\n\t\t});\n\n\t\t// Given a URI of: data:image/png;size:2313;label:SomeLabel;description:SomeDescription;base64,77+9UE5...\n\t\t// the mime is: image/png\n\t\tconst mime = dataUri.path.substring(0, dataUri.path.indexOf(';'));\n\t\tif (mime) {\n\t\t\tmetadata.set(META_DATA_MIME, mime);\n\t\t}\n\n\t\treturn metadata;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as DOM from 'vs/base/browser/dom';\nimport * as dompurify from 'vs/base/browser/dompurify/dompurify';\nimport { DomEmitter } from 'vs/base/browser/event';\nimport { createElement, FormattedTextRenderOptions } from 'vs/base/browser/formattedTextRenderer';\nimport { StandardMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';\nimport { raceCancellation } from 'vs/base/common/async';\nimport { CancellationTokenSource } from 'vs/base/common/cancellation';\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport { Event } from 'vs/base/common/event';\nimport { IMarkdownString, parseHrefAndDimensions, removeMarkdownEscapes } from 'vs/base/common/htmlContent';\nimport { markdownEscapeEscapedIcons } from 'vs/base/common/iconLabels';\nimport { defaultGenerator } from 'vs/base/common/idGenerator';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\nimport { marked } from 'vs/base/common/marked/marked';\nimport { parse } from 'vs/base/common/marshalling';\nimport { FileAccess, Schemas } from 'vs/base/common/network';\nimport { cloneAndChange } from 'vs/base/common/objects';\nimport { resolvePath } from 'vs/base/common/resources';\nimport { escape } from 'vs/base/common/strings';\nimport { URI } from 'vs/base/common/uri';\n\nexport interface MarkedOptions extends marked.MarkedOptions {\n}\n\nexport interface MarkdownRenderOptions extends FormattedTextRenderOptions {\n\tcodeBlockRenderer?: (languageId: string, value: string) => Promise;\n\tasyncRenderCallback?: () => void;\n\tbaseUrl?: URI;\n}\n\n/**\n * Low-level way create a html element from a markdown string.\n *\n * **Note** that for most cases you should be using [`MarkdownRenderer`](./src/vs/editor/browser/core/markdownRenderer.ts)\n * which comes with support for pretty code block rendering and which uses the default way of handling links.\n */\nexport function renderMarkdown(markdown: IMarkdownString, options: MarkdownRenderOptions = {}, markedOptions: MarkedOptions = {}): { element: HTMLElement, dispose: () => void } {\n\tconst disposables = new DisposableStore();\n\tlet isDisposed = false;\n\n\tconst cts = disposables.add(new CancellationTokenSource());\n\n\tconst element = createElement(options);\n\n\tconst _uriMassage = function (part: string): string {\n\t\tlet data: any;\n\t\ttry {\n\t\t\tdata = parse(decodeURIComponent(part));\n\t\t} catch (e) {\n\t\t\t// ignore\n\t\t}\n\t\tif (!data) {\n\t\t\treturn part;\n\t\t}\n\t\tdata = cloneAndChange(data, value => {\n\t\t\tif (markdown.uris && markdown.uris[value]) {\n\t\t\t\treturn URI.revive(markdown.uris[value]);\n\t\t\t} else {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t});\n\t\treturn encodeURIComponent(JSON.stringify(data));\n\t};\n\n\tconst _href = function (href: string, isDomUri: boolean): string {\n\t\tconst data = markdown.uris && markdown.uris[href];\n\t\tlet uri = URI.revive(data);\n\t\tif (isDomUri) {\n\t\t\tif (href.startsWith(Schemas.data + ':')) {\n\t\t\t\treturn href;\n\t\t\t}\n\t\t\tif (!uri) {\n\t\t\t\turi = URI.parse(href);\n\t\t\t}\n\t\t\t// this URI will end up as \"src\"-attribute of a dom node\n\t\t\t// and because of that special rewriting needs to be done\n\t\t\t// so that the URI uses a protocol that's understood by\n\t\t\t// browsers (like http or https)\n\t\t\treturn FileAccess.asBrowserUri(uri).toString(true);\n\t\t}\n\t\tif (!uri) {\n\t\t\treturn href;\n\t\t}\n\t\tif (URI.parse(href).toString() === uri.toString()) {\n\t\t\treturn href; // no transformation performed\n\t\t}\n\t\tif (uri.query) {\n\t\t\turi = uri.with({ query: _uriMassage(uri.query) });\n\t\t}\n\t\treturn uri.toString();\n\t};\n\n\t// signal to code-block render that the\n\t// element has been created\n\tlet signalInnerHTML: () => void;\n\tconst withInnerHTML = new Promise(c => signalInnerHTML = c);\n\n\tconst renderer = new marked.Renderer();\n\n\trenderer.image = (href: string, title: string, text: string) => {\n\t\tlet dimensions: string[] = [];\n\t\tlet attributes: string[] = [];\n\t\tif (href) {\n\t\t\t({ href, dimensions } = parseHrefAndDimensions(href));\n\t\t\tattributes.push(`src=\"${href}\"`);\n\t\t}\n\t\tif (text) {\n\t\t\tattributes.push(`alt=\"${text}\"`);\n\t\t}\n\t\tif (title) {\n\t\t\tattributes.push(`title=\"${title}\"`);\n\t\t}\n\t\tif (dimensions.length) {\n\t\t\tattributes = attributes.concat(dimensions);\n\t\t}\n\t\treturn '';\n\t};\n\trenderer.link = (href, title, text): string => {\n\t\tif (typeof href !== 'string') {\n\t\t\treturn '';\n\t\t}\n\n\t\t// Remove markdown escapes. Workaround for https://github.com/chjj/marked/issues/829\n\t\tif (href === text) { // raw link case\n\t\t\ttext = removeMarkdownEscapes(text);\n\t\t}\n\t\thref = _href(href, false);\n\t\tif (options.baseUrl) {\n\t\t\tconst hasScheme = /^\\w[\\w\\d+.-]*:/.test(href);\n\t\t\tif (!hasScheme) {\n\t\t\t\thref = resolvePath(options.baseUrl, href).toString();\n\t\t\t}\n\t\t}\n\t\ttitle = typeof title === 'string' ? removeMarkdownEscapes(title) : '';\n\t\thref = removeMarkdownEscapes(href);\n\t\tif (\n\t\t\t!href\n\t\t\t|| href.match(/^data:|javascript:/i)\n\t\t\t|| (href.match(/^command:/i) && !markdown.isTrusted)\n\t\t\t|| href.match(/^command:(\\/\\/\\/)?_workbench\\.downloadResource/i)\n\t\t) {\n\t\t\t// drop the link\n\t\t\treturn text;\n\n\t\t} else {\n\t\t\t// HTML Encode href\n\t\t\thref = href.replace(/&/g, '&')\n\t\t\t\t.replace(//g, '>')\n\t\t\t\t.replace(/\"/g, '"')\n\t\t\t\t.replace(/'/g, ''');\n\t\t\treturn `
    ${text}`;\n\t\t}\n\t};\n\trenderer.paragraph = (text): string => {\n\t\treturn `

    ${text}

    `;\n\t};\n\n\tif (options.codeBlockRenderer) {\n\t\trenderer.code = (code, lang) => {\n\t\t\tif (typeof lang !== 'string') {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tconst value = options.codeBlockRenderer!(lang, code);\n\t\t\t// when code-block rendering is async we return sync\n\t\t\t// but update the node with the real result later.\n\t\t\tconst id = defaultGenerator.nextId();\n\t\t\traceCancellation(Promise.all([value, withInnerHTML]), cts.token).then(values => {\n\t\t\t\tif (!isDisposed && values) {\n\t\t\t\t\tconst span = element.querySelector(`div[data-code=\"${id}\"]`);\n\t\t\t\t\tif (span) {\n\t\t\t\t\t\tDOM.reset(span, values[0]);\n\t\t\t\t\t}\n\t\t\t\t\toptions.asyncRenderCallback?.();\n\t\t\t\t}\n\t\t\t}).catch(() => {\n\t\t\t\t// ignore\n\t\t\t});\n\n\t\t\treturn `
    ${escape(code)}
    `;\n\t\t};\n\t}\n\n\tif (options.actionHandler) {\n\t\tconst onClick = options.actionHandler.disposables.add(new DomEmitter(element, 'click'));\n\t\tconst onAuxClick = options.actionHandler.disposables.add(new DomEmitter(element, 'auxclick'));\n\t\toptions.actionHandler.disposables.add(Event.any(onClick.event, onAuxClick.event)(e => {\n\t\t\tconst mouseEvent = new StandardMouseEvent(e);\n\t\t\tif (!mouseEvent.leftButton && !mouseEvent.middleButton) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet target: HTMLElement | null = mouseEvent.target;\n\t\t\tif (target.tagName !== 'A') {\n\t\t\t\ttarget = target.parentElement;\n\t\t\t\tif (!target || target.tagName !== 'A') {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst href = target.dataset['href'];\n\t\t\t\tif (href) {\n\t\t\t\t\toptions.actionHandler!.callback(href, mouseEvent);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tonUnexpectedError(err);\n\t\t\t} finally {\n\t\t\t\tmouseEvent.preventDefault();\n\t\t\t}\n\t\t}));\n\t}\n\n\tif (!markdown.supportHtml) {\n\t\t// TODO: Can we deprecated this in favor of 'supportHtml'?\n\n\t\t// Use our own sanitizer so that we can let through only spans.\n\t\t// Otherwise, we'd be letting all html be rendered.\n\t\t// If we want to allow markdown permitted tags, then we can delete sanitizer and sanitize.\n\t\t// We always pass the output through dompurify after this so that we don't rely on\n\t\t// marked for sanitization.\n\t\tmarkedOptions.sanitizer = (html: string): string => {\n\t\t\tconst match = markdown.isTrusted ? html.match(/^(]+>)|(<\\/\\s*span>)$/) : undefined;\n\t\t\treturn match ? html : '';\n\t\t};\n\t\tmarkedOptions.sanitize = true;\n\t\tmarkedOptions.silent = true;\n\t}\n\n\tmarkedOptions.renderer = renderer;\n\n\t// values that are too long will freeze the UI\n\tlet value = markdown.value ?? '';\n\tif (value.length > 100_000) {\n\t\tvalue = `${value.substr(0, 100_000)}…`;\n\t}\n\t// escape theme icons\n\tif (markdown.supportThemeIcons) {\n\t\tvalue = markdownEscapeEscapedIcons(value);\n\t}\n\n\tlet renderedMarkdown = marked.parse(value, markedOptions);\n\n\t// Rewrite theme icons\n\tif (markdown.supportThemeIcons) {\n\t\tconst elements = renderLabelWithIcons(renderedMarkdown);\n\t\trenderedMarkdown = elements.map(e => typeof e === 'string' ? e : e.outerHTML).join('');\n\t}\n\n\tconst htmlParser = new DOMParser();\n\tconst markdownHtmlDoc = htmlParser.parseFromString(sanitizeRenderedMarkdown(markdown, renderedMarkdown) as unknown as string, 'text/html');\n\n\tmarkdownHtmlDoc.body.querySelectorAll('img')\n\t\t.forEach(img => {\n\t\t\tif (img.src) {\n\t\t\t\tlet href = _href(img.src, true);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst hrefAsUri = URI.parse(href);\n\t\t\t\t\tif (options.baseUrl && hrefAsUri.scheme === Schemas.file) { // absolute or relative local path, or file: uri\n\t\t\t\t\t\thref = resolvePath(options.baseUrl, href).toString();\n\t\t\t\t\t}\n\t\t\t\t} catch (err) { }\n\n\t\t\t\timg.src = href;\n\t\t\t}\n\t\t});\n\n\telement.innerHTML = sanitizeRenderedMarkdown(markdown, markdownHtmlDoc.body.innerHTML) as unknown as string;\n\n\t// signal that async code blocks can be now be inserted\n\tsignalInnerHTML!();\n\n\t// signal size changes for image tags\n\tif (options.asyncRenderCallback) {\n\t\tfor (const img of element.getElementsByTagName('img')) {\n\t\t\tconst listener = disposables.add(DOM.addDisposableListener(img, 'load', () => {\n\t\t\t\tlistener.dispose();\n\t\t\t\toptions.asyncRenderCallback!();\n\t\t\t}));\n\t\t}\n\t}\n\n\treturn {\n\t\telement,\n\t\tdispose: () => {\n\t\t\tisDisposed = true;\n\t\t\tcts.cancel();\n\t\t\tdisposables.dispose();\n\t\t}\n\t};\n}\n\nfunction sanitizeRenderedMarkdown(\n\toptions: { isTrusted?: boolean },\n\trenderedMarkdown: string,\n): TrustedHTML {\n\tconst { config, allowedSchemes } = getSanitizerOptions(options);\n\tdompurify.addHook('uponSanitizeAttribute', (element, e) => {\n\t\tif (e.attrName === 'style' || e.attrName === 'class') {\n\t\t\tif (element.tagName === 'SPAN') {\n\t\t\t\tif (e.attrName === 'style') {\n\t\t\t\t\te.keepAttr = /^(color\\:#[0-9a-fA-F]+;)?(background-color\\:#[0-9a-fA-F]+;)?$/.test(e.attrValue);\n\t\t\t\t\treturn;\n\t\t\t\t} else if (e.attrName === 'class') {\n\t\t\t\t\te.keepAttr = /^codicon codicon-[a-z\\-]+( codicon-modifier-[a-z\\-]+)?$/.test(e.attrValue);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\te.keepAttr = false;\n\t\t\treturn;\n\t\t}\n\t});\n\n\t// build an anchor to map URLs to\n\tconst anchor = document.createElement('a');\n\n\t// https://github.com/cure53/DOMPurify/blob/main/demos/hooks-scheme-allowlist.html\n\tdompurify.addHook('afterSanitizeAttributes', (node) => {\n\t\t// check all href/src attributes for validity\n\t\tfor (const attr of ['href', 'src']) {\n\t\t\tif (node.hasAttribute(attr)) {\n\t\t\t\tanchor.href = node.getAttribute(attr) as string;\n\t\t\t\tif (!allowedSchemes.includes(anchor.protocol.replace(/:$/, ''))) {\n\t\t\t\t\tnode.removeAttribute(attr);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\ttry {\n\t\treturn dompurify.sanitize(renderedMarkdown, { ...config, RETURN_TRUSTED_TYPE: true });\n\t} finally {\n\t\tdompurify.removeHook('uponSanitizeAttribute');\n\t\tdompurify.removeHook('afterSanitizeAttributes');\n\t}\n}\n\nfunction getSanitizerOptions(options: { readonly isTrusted?: boolean }): { config: dompurify.Config, allowedSchemes: string[] } {\n\tconst allowedSchemes = [\n\t\tSchemas.http,\n\t\tSchemas.https,\n\t\tSchemas.mailto,\n\t\tSchemas.data,\n\t\tSchemas.file,\n\t\tSchemas.vscodeFileResource,\n\t\tSchemas.vscodeRemote,\n\t\tSchemas.vscodeRemoteResource,\n\t];\n\n\tif (options.isTrusted) {\n\t\tallowedSchemes.push(Schemas.command);\n\t}\n\n\treturn {\n\t\tconfig: {\n\t\t\t// allowedTags should included everything that markdown renders to.\n\t\t\t// Since we have our own sanitize function for marked, it's possible we missed some tag so let dompurify make sure.\n\t\t\t// HTML tags that can result from markdown are from reading https://spec.commonmark.org/0.29/\n\t\t\t// HTML table tags that can result from markdown are from https://github.github.com/gfm/#tables-extension-\n\t\t\tALLOWED_TAGS: ['ul', 'li', 'p', 'b', 'i', 'code', 'blockquote', 'ol', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'em', 'pre', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'div', 'del', 'a', 'strong', 'br', 'img', 'span'],\n\t\t\tALLOWED_ATTR: ['href', 'data-href', 'target', 'title', 'src', 'alt', 'class', 'style', 'data-code', 'width', 'height', 'align'],\n\t\t\tALLOW_UNKNOWN_PROTOCOLS: true,\n\t\t},\n\t\tallowedSchemes\n\t};\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { hasDriveLetter, isRootOrDriveLetter } from 'vs/base/common/extpath';\nimport { Schemas } from 'vs/base/common/network';\nimport { isWindows } from 'vs/base/common/platform';\nimport { basename } from 'vs/base/common/resources';\nimport { URI } from 'vs/base/common/uri';\n\nexport interface IWorkspaceFolderProvider {\n}\n\nexport function getBaseLabel(resource: URI | string): string;\nexport function getBaseLabel(resource: URI | string | undefined): string | undefined;\nexport function getBaseLabel(resource: URI | string | undefined): string | undefined {\n\tif (!resource) {\n\t\treturn undefined;\n\t}\n\n\tif (typeof resource === 'string') {\n\t\tresource = URI.file(resource);\n\t}\n\n\tconst base = basename(resource) || (resource.scheme === Schemas.file ? resource.fsPath : resource.path) /* can be empty string if '/' is passed in */;\n\n\t// convert c: => C:\n\tif (isWindows && isRootOrDriveLetter(base)) {\n\t\treturn normalizeDriveLetter(base);\n\t}\n\n\treturn base;\n}\n\nexport function normalizeDriveLetter(path: string, continueAsWindows?: boolean): string {\n\tif (hasDriveLetter(path, continueAsWindows)) {\n\t\treturn path.charAt(0).toUpperCase() + path.slice(1);\n\t}\n\n\treturn path;\n}\n\nlet normalizedUserHomeCached: { original: string; normalized: string; } = Object.create(null);\n","\n\n// prep-work\nconst _data = new Uint8Array(16);\nconst _hex: string[] = [];\nfor (let i = 0; i < 256; i++) {\n\t_hex.push(i.toString(16).padStart(2, '0'));\n}\n\n// todo@jrieken - with node@15 crypto#getRandomBytes is available everywhere, https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#browser_compatibility\nlet _fillRandomValues: (bucket: Uint8Array) => Uint8Array;\n\ndeclare const crypto: undefined | { getRandomValues(data: Uint8Array): Uint8Array };\n\nif (typeof crypto === 'object' && typeof crypto.getRandomValues === 'function') {\n\t// browser\n\t_fillRandomValues = crypto.getRandomValues.bind(crypto);\n\n} else {\n\t_fillRandomValues = function (bucket: Uint8Array): Uint8Array {\n\t\tfor (let i = 0; i < bucket.length; i++) {\n\t\t\tbucket[i] = Math.floor(Math.random() * 256);\n\t\t}\n\t\treturn bucket;\n\t};\n}\n\nexport function generateUuid(): string {\n\t// get data\n\t_fillRandomValues(_data);\n\n\t// set version bits\n\t_data[6] = (_data[6] & 0x0f) | 0x40;\n\t_data[8] = (_data[8] & 0x3f) | 0x80;\n\n\t// print as string\n\tlet i = 0;\n\tlet result = '';\n\tresult += _hex[_data[i++]];\n\tresult += _hex[_data[i++]];\n\tresult += _hex[_data[i++]];\n\tresult += _hex[_data[i++]];\n\tresult += '-';\n\tresult += _hex[_data[i++]];\n\tresult += _hex[_data[i++]];\n\tresult += '-';\n\tresult += _hex[_data[i++]];\n\tresult += _hex[_data[i++]];\n\tresult += '-';\n\tresult += _hex[_data[i++]];\n\tresult += _hex[_data[i++]];\n\tresult += '-';\n\tresult += _hex[_data[i++]];\n\tresult += _hex[_data[i++]];\n\tresult += _hex[_data[i++]];\n\tresult += _hex[_data[i++]];\n\tresult += _hex[_data[i++]];\n\tresult += _hex[_data[i++]];\n\treturn result;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { transformErrorForSerialization } from 'vs/base/common/errors';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport { globals, isWeb } from 'vs/base/common/platform';\nimport * as types from 'vs/base/common/types';\nimport * as strings from 'vs/base/common/strings';\n\nconst INITIALIZE = '$initialize';\n\nexport interface IWorker extends IDisposable {\n\tgetId(): number;\n\tpostMessage(message: Message, transfer: ArrayBuffer[]): void;\n}\n\nexport interface IWorkerCallback {\n\t(message: Message): void;\n}\n\nexport interface IWorkerFactory {\n\tcreate(moduleId: string, callback: IWorkerCallback, onErrorCallback: (err: any) => void): IWorker;\n}\n\nlet webWorkerWarningLogged = false;\nexport function logOnceWebWorkerWarning(err: any): void {\n\tif (!isWeb) {\n\t\t// running tests\n\t\treturn;\n\t}\n\tif (!webWorkerWarningLogged) {\n\t\twebWorkerWarningLogged = true;\n\t\tconsole.warn('Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/microsoft/monaco-editor#faq');\n\t}\n\tconsole.warn(err.message);\n}\n\nconst enum MessageType {\n\tRequest,\n\tReply,\n\tSubscribeEvent,\n\tEvent,\n\tUnsubscribeEvent\n}\nclass RequestMessage {\n\tpublic readonly type = MessageType.Request;\n\tconstructor(\n\t\tpublic readonly vsWorker: number,\n\t\tpublic readonly req: string,\n\t\tpublic readonly method: string,\n\t\tpublic readonly args: any[]\n\t) { }\n}\nclass ReplyMessage {\n\tpublic readonly type = MessageType.Reply;\n\tconstructor(\n\t\tpublic readonly vsWorker: number,\n\t\tpublic readonly seq: string,\n\t\tpublic readonly res: any,\n\t\tpublic readonly err: any\n\t) { }\n}\nclass SubscribeEventMessage {\n\tpublic readonly type = MessageType.SubscribeEvent;\n\tconstructor(\n\t\tpublic readonly vsWorker: number,\n\t\tpublic readonly req: string,\n\t\tpublic readonly eventName: string,\n\t\tpublic readonly arg: any\n\t) { }\n}\nclass EventMessage {\n\tpublic readonly type = MessageType.Event;\n\tconstructor(\n\t\tpublic readonly vsWorker: number,\n\t\tpublic readonly req: string,\n\t\tpublic readonly event: any\n\t) { }\n}\nclass UnsubscribeEventMessage {\n\tpublic readonly type = MessageType.UnsubscribeEvent;\n\tconstructor(\n\t\tpublic readonly vsWorker: number,\n\t\tpublic readonly req: string\n\t) { }\n}\ntype Message = RequestMessage | ReplyMessage | SubscribeEventMessage | EventMessage | UnsubscribeEventMessage;\n\ninterface IMessageReply {\n\tresolve: (value?: any) => void;\n\treject: (error?: any) => void;\n}\n\ninterface IMessageHandler {\n\tsendMessage(msg: any, transfer?: ArrayBuffer[]): void;\n\thandleMessage(method: string, args: any[]): Promise;\n\thandleEvent(eventName: string, arg: any): Event;\n}\n\nclass SimpleWorkerProtocol {\n\n\tprivate _workerId: number;\n\tprivate _lastSentReq: number;\n\tprivate _pendingReplies: { [req: string]: IMessageReply; };\n\tprivate _pendingEmitters: Map>;\n\tprivate _pendingEvents: Map;\n\tprivate _handler: IMessageHandler;\n\n\tconstructor(handler: IMessageHandler) {\n\t\tthis._workerId = -1;\n\t\tthis._handler = handler;\n\t\tthis._lastSentReq = 0;\n\t\tthis._pendingReplies = Object.create(null);\n\t\tthis._pendingEmitters = new Map>();\n\t\tthis._pendingEvents = new Map();\n\t}\n\n\tpublic setWorkerId(workerId: number): void {\n\t\tthis._workerId = workerId;\n\t}\n\n\tpublic sendMessage(method: string, args: any[]): Promise {\n\t\tconst req = String(++this._lastSentReq);\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis._pendingReplies[req] = {\n\t\t\t\tresolve: resolve,\n\t\t\t\treject: reject\n\t\t\t};\n\t\t\tthis._send(new RequestMessage(this._workerId, req, method, args));\n\t\t});\n\t}\n\n\tpublic listen(eventName: string, arg: any): Event {\n\t\tlet req: string | null = null;\n\t\tconst emitter = new Emitter({\n\t\t\tonFirstListenerAdd: () => {\n\t\t\t\treq = String(++this._lastSentReq);\n\t\t\t\tthis._pendingEmitters.set(req, emitter);\n\t\t\t\tthis._send(new SubscribeEventMessage(this._workerId, req, eventName, arg));\n\t\t\t},\n\t\t\tonLastListenerRemove: () => {\n\t\t\t\tthis._pendingEmitters.delete(req!);\n\t\t\t\tthis._send(new UnsubscribeEventMessage(this._workerId, req!));\n\t\t\t\treq = null;\n\t\t\t}\n\t\t});\n\t\treturn emitter.event;\n\t}\n\n\tpublic handleMessage(message: Message): void {\n\t\tif (!message || !message.vsWorker) {\n\t\t\treturn;\n\t\t}\n\t\tif (this._workerId !== -1 && message.vsWorker !== this._workerId) {\n\t\t\treturn;\n\t\t}\n\t\tthis._handleMessage(message);\n\t}\n\n\tprivate _handleMessage(msg: Message): void {\n\t\tswitch (msg.type) {\n\t\t\tcase MessageType.Reply:\n\t\t\t\treturn this._handleReplyMessage(msg);\n\t\t\tcase MessageType.Request:\n\t\t\t\treturn this._handleRequestMessage(msg);\n\t\t\tcase MessageType.SubscribeEvent:\n\t\t\t\treturn this._handleSubscribeEventMessage(msg);\n\t\t\tcase MessageType.Event:\n\t\t\t\treturn this._handleEventMessage(msg);\n\t\t\tcase MessageType.UnsubscribeEvent:\n\t\t\t\treturn this._handleUnsubscribeEventMessage(msg);\n\t\t}\n\t}\n\n\tprivate _handleReplyMessage(replyMessage: ReplyMessage): void {\n\t\tif (!this._pendingReplies[replyMessage.seq]) {\n\t\t\tconsole.warn('Got reply to unknown seq');\n\t\t\treturn;\n\t\t}\n\n\t\tlet reply = this._pendingReplies[replyMessage.seq];\n\t\tdelete this._pendingReplies[replyMessage.seq];\n\n\t\tif (replyMessage.err) {\n\t\t\tlet err = replyMessage.err;\n\t\t\tif (replyMessage.err.$isError) {\n\t\t\t\terr = new Error();\n\t\t\t\terr.name = replyMessage.err.name;\n\t\t\t\terr.message = replyMessage.err.message;\n\t\t\t\terr.stack = replyMessage.err.stack;\n\t\t\t}\n\t\t\treply.reject(err);\n\t\t\treturn;\n\t\t}\n\n\t\treply.resolve(replyMessage.res);\n\t}\n\n\tprivate _handleRequestMessage(requestMessage: RequestMessage): void {\n\t\tlet req = requestMessage.req;\n\t\tlet result = this._handler.handleMessage(requestMessage.method, requestMessage.args);\n\t\tresult.then((r) => {\n\t\t\tthis._send(new ReplyMessage(this._workerId, req, r, undefined));\n\t\t}, (e) => {\n\t\t\tif (e.detail instanceof Error) {\n\t\t\t\t// Loading errors have a detail property that points to the actual error\n\t\t\t\te.detail = transformErrorForSerialization(e.detail);\n\t\t\t}\n\t\t\tthis._send(new ReplyMessage(this._workerId, req, undefined, transformErrorForSerialization(e)));\n\t\t});\n\t}\n\n\tprivate _handleSubscribeEventMessage(msg: SubscribeEventMessage): void {\n\t\tconst req = msg.req;\n\t\tconst disposable = this._handler.handleEvent(msg.eventName, msg.arg)((event) => {\n\t\t\tthis._send(new EventMessage(this._workerId, req, event));\n\t\t});\n\t\tthis._pendingEvents.set(req, disposable);\n\t}\n\n\tprivate _handleEventMessage(msg: EventMessage): void {\n\t\tif (!this._pendingEmitters.has(msg.req)) {\n\t\t\tconsole.warn('Got event for unknown req');\n\t\t\treturn;\n\t\t}\n\t\tthis._pendingEmitters.get(msg.req)!.fire(msg.event);\n\t}\n\n\tprivate _handleUnsubscribeEventMessage(msg: UnsubscribeEventMessage): void {\n\t\tif (!this._pendingEvents.has(msg.req)) {\n\t\t\tconsole.warn('Got unsubscribe for unknown req');\n\t\t\treturn;\n\t\t}\n\t\tthis._pendingEvents.get(msg.req)!.dispose();\n\t\tthis._pendingEvents.delete(msg.req);\n\t}\n\n\tprivate _send(msg: Message): void {\n\t\tlet transfer: ArrayBuffer[] = [];\n\t\tif (msg.type === MessageType.Request) {\n\t\t\tfor (let i = 0; i < msg.args.length; i++) {\n\t\t\t\tif (msg.args[i] instanceof ArrayBuffer) {\n\t\t\t\t\ttransfer.push(msg.args[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (msg.type === MessageType.Reply) {\n\t\t\tif (msg.res instanceof ArrayBuffer) {\n\t\t\t\ttransfer.push(msg.res);\n\t\t\t}\n\t\t}\n\t\tthis._handler.sendMessage(msg, transfer);\n\t}\n}\n\nexport interface IWorkerClient {\n\tgetProxyObject(): Promise;\n\tdispose(): void;\n}\n\n/**\n * Main thread side\n */\nexport class SimpleWorkerClient extends Disposable implements IWorkerClient {\n\n\tprivate readonly _worker: IWorker;\n\tprivate readonly _onModuleLoaded: Promise;\n\tprivate readonly _protocol: SimpleWorkerProtocol;\n\tprivate readonly _lazyProxy: Promise;\n\n\tconstructor(workerFactory: IWorkerFactory, moduleId: string, host: H) {\n\t\tsuper();\n\n\t\tlet lazyProxyReject: ((err: any) => void) | null = null;\n\n\t\tthis._worker = this._register(workerFactory.create(\n\t\t\t'vs/base/common/worker/simpleWorker',\n\t\t\t(msg: Message) => {\n\t\t\t\tthis._protocol.handleMessage(msg);\n\t\t\t},\n\t\t\t(err: any) => {\n\t\t\t\t// in Firefox, web workers fail lazily :(\n\t\t\t\t// we will reject the proxy\n\t\t\t\tif (lazyProxyReject) {\n\t\t\t\t\tlazyProxyReject(err);\n\t\t\t\t}\n\t\t\t}\n\t\t));\n\n\t\tthis._protocol = new SimpleWorkerProtocol({\n\t\t\tsendMessage: (msg: any, transfer: ArrayBuffer[]): void => {\n\t\t\t\tthis._worker.postMessage(msg, transfer);\n\t\t\t},\n\t\t\thandleMessage: (method: string, args: any[]): Promise => {\n\t\t\t\tif (typeof (host as any)[method] !== 'function') {\n\t\t\t\t\treturn Promise.reject(new Error('Missing method ' + method + ' on main thread host.'));\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\treturn Promise.resolve((host as any)[method].apply(host, args));\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn Promise.reject(e);\n\t\t\t\t}\n\t\t\t},\n\t\t\thandleEvent: (eventName: string, arg: any): Event => {\n\t\t\t\tif (propertyIsDynamicEvent(eventName)) {\n\t\t\t\t\tconst event = (host as any)[eventName].call(host, arg);\n\t\t\t\t\tif (typeof event !== 'function') {\n\t\t\t\t\t\tthrow new Error(`Missing dynamic event ${eventName} on main thread host.`);\n\t\t\t\t\t}\n\t\t\t\t\treturn event;\n\t\t\t\t}\n\t\t\t\tif (propertyIsEvent(eventName)) {\n\t\t\t\t\tconst event = (host as any)[eventName];\n\t\t\t\t\tif (typeof event !== 'function') {\n\t\t\t\t\t\tthrow new Error(`Missing event ${eventName} on main thread host.`);\n\t\t\t\t\t}\n\t\t\t\t\treturn event;\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Malformed event name ${eventName}`);\n\t\t\t}\n\t\t});\n\t\tthis._protocol.setWorkerId(this._worker.getId());\n\n\t\t// Gather loader configuration\n\t\tlet loaderConfiguration: any = null;\n\t\tif (typeof globals.require !== 'undefined' && typeof globals.require.getConfig === 'function') {\n\t\t\t// Get the configuration from the Monaco AMD Loader\n\t\t\tloaderConfiguration = globals.require.getConfig();\n\t\t} else if (typeof globals.requirejs !== 'undefined') {\n\t\t\t// Get the configuration from requirejs\n\t\t\tloaderConfiguration = globals.requirejs.s.contexts._.config;\n\t\t}\n\n\t\tconst hostMethods = types.getAllMethodNames(host);\n\n\t\t// Send initialize message\n\t\tthis._onModuleLoaded = this._protocol.sendMessage(INITIALIZE, [\n\t\t\tthis._worker.getId(),\n\t\t\tJSON.parse(JSON.stringify(loaderConfiguration)),\n\t\t\tmoduleId,\n\t\t\thostMethods,\n\t\t]);\n\n\t\t// Create proxy to loaded code\n\t\tconst proxyMethodRequest = (method: string, args: any[]): Promise => {\n\t\t\treturn this._request(method, args);\n\t\t};\n\t\tconst proxyListen = (eventName: string, arg: any): Event => {\n\t\t\treturn this._protocol.listen(eventName, arg);\n\t\t};\n\n\t\tthis._lazyProxy = new Promise((resolve, reject) => {\n\t\t\tlazyProxyReject = reject;\n\t\t\tthis._onModuleLoaded.then((availableMethods: string[]) => {\n\t\t\t\tresolve(createProxyObject(availableMethods, proxyMethodRequest, proxyListen));\n\t\t\t}, (e) => {\n\t\t\t\treject(e);\n\t\t\t\tthis._onError('Worker failed to load ' + moduleId, e);\n\t\t\t});\n\t\t});\n\t}\n\n\tpublic getProxyObject(): Promise {\n\t\treturn this._lazyProxy;\n\t}\n\n\tprivate _request(method: string, args: any[]): Promise {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis._onModuleLoaded.then(() => {\n\t\t\t\tthis._protocol.sendMessage(method, args).then(resolve, reject);\n\t\t\t}, reject);\n\t\t});\n\t}\n\n\tprivate _onError(message: string, error?: any): void {\n\t\tconsole.error(message);\n\t\tconsole.info(error);\n\t}\n}\n\nfunction propertyIsEvent(name: string): boolean {\n\t// Assume a property is an event if it has a form of \"onSomething\"\n\treturn name[0] === 'o' && name[1] === 'n' && strings.isUpperAsciiLetter(name.charCodeAt(2));\n}\n\nfunction propertyIsDynamicEvent(name: string): boolean {\n\t// Assume a property is a dynamic event (a method that returns an event) if it has a form of \"onDynamicSomething\"\n\treturn /^onDynamic/.test(name) && strings.isUpperAsciiLetter(name.charCodeAt(9));\n}\n\nfunction createProxyObject(\n\tmethodNames: string[],\n\tinvoke: (method: string, args: unknown[]) => unknown,\n\tproxyListen: (eventName: string, arg: any) => Event\n): T {\n\tconst createProxyMethod = (method: string): () => unknown => {\n\t\treturn function () {\n\t\t\tconst args = Array.prototype.slice.call(arguments, 0);\n\t\t\treturn invoke(method, args);\n\t\t};\n\t};\n\tconst createProxyDynamicEvent = (eventName: string): (arg: any) => Event => {\n\t\treturn function (arg) {\n\t\t\treturn proxyListen(eventName, arg);\n\t\t};\n\t};\n\n\tlet result = {} as T;\n\tfor (const methodName of methodNames) {\n\t\tif (propertyIsDynamicEvent(methodName)) {\n\t\t\t(result)[methodName] = createProxyDynamicEvent(methodName);\n\t\t\tcontinue;\n\t\t}\n\t\tif (propertyIsEvent(methodName)) {\n\t\t\t(result)[methodName] = proxyListen(methodName, undefined);\n\t\t\tcontinue;\n\t\t}\n\t\t(result)[methodName] = createProxyMethod(methodName);\n\t}\n\treturn result;\n}\n\nexport interface IRequestHandler {\n\t_requestHandlerBrand: any;\n\t[prop: string]: any;\n}\n\nexport interface IRequestHandlerFactory {\n\t(host: H): IRequestHandler;\n}\n\n/**\n * Worker side\n */\nexport class SimpleWorkerServer {\n\n\tprivate _requestHandlerFactory: IRequestHandlerFactory | null;\n\tprivate _requestHandler: IRequestHandler | null;\n\tprivate _protocol: SimpleWorkerProtocol;\n\n\tconstructor(postMessage: (msg: Message, transfer?: ArrayBuffer[]) => void, requestHandlerFactory: IRequestHandlerFactory | null) {\n\t\tthis._requestHandlerFactory = requestHandlerFactory;\n\t\tthis._requestHandler = null;\n\t\tthis._protocol = new SimpleWorkerProtocol({\n\t\t\tsendMessage: (msg: any, transfer: ArrayBuffer[]): void => {\n\t\t\t\tpostMessage(msg, transfer);\n\t\t\t},\n\t\t\thandleMessage: (method: string, args: any[]): Promise => this._handleMessage(method, args),\n\t\t\thandleEvent: (eventName: string, arg: any): Event => this._handleEvent(eventName, arg)\n\t\t});\n\t}\n\n\tpublic onmessage(msg: any): void {\n\t\tthis._protocol.handleMessage(msg);\n\t}\n\n\tprivate _handleMessage(method: string, args: any[]): Promise {\n\t\tif (method === INITIALIZE) {\n\t\t\treturn this.initialize(args[0], args[1], args[2], args[3]);\n\t\t}\n\n\t\tif (!this._requestHandler || typeof this._requestHandler[method] !== 'function') {\n\t\t\treturn Promise.reject(new Error('Missing requestHandler or method: ' + method));\n\t\t}\n\n\t\ttry {\n\t\t\treturn Promise.resolve(this._requestHandler[method].apply(this._requestHandler, args));\n\t\t} catch (e) {\n\t\t\treturn Promise.reject(e);\n\t\t}\n\t}\n\n\tprivate _handleEvent(eventName: string, arg: any): Event {\n\t\tif (!this._requestHandler) {\n\t\t\tthrow new Error(`Missing requestHandler`);\n\t\t}\n\t\tif (propertyIsDynamicEvent(eventName)) {\n\t\t\tconst event = (this._requestHandler as any)[eventName].call(this._requestHandler, arg);\n\t\t\tif (typeof event !== 'function') {\n\t\t\t\tthrow new Error(`Missing dynamic event ${eventName} on request handler.`);\n\t\t\t}\n\t\t\treturn event;\n\t\t}\n\t\tif (propertyIsEvent(eventName)) {\n\t\t\tconst event = (this._requestHandler as any)[eventName];\n\t\t\tif (typeof event !== 'function') {\n\t\t\t\tthrow new Error(`Missing event ${eventName} on request handler.`);\n\t\t\t}\n\t\t\treturn event;\n\t\t}\n\t\tthrow new Error(`Malformed event name ${eventName}`);\n\t}\n\n\tprivate initialize(workerId: number, loaderConfig: any, moduleId: string, hostMethods: string[]): Promise {\n\t\tthis._protocol.setWorkerId(workerId);\n\n\t\tconst proxyMethodRequest = (method: string, args: any[]): Promise => {\n\t\t\treturn this._protocol.sendMessage(method, args);\n\t\t};\n\t\tconst proxyListen = (eventName: string, arg: any): Event => {\n\t\t\treturn this._protocol.listen(eventName, arg);\n\t\t};\n\n\t\tconst hostProxy = createProxyObject(hostMethods, proxyMethodRequest, proxyListen);\n\n\t\tif (this._requestHandlerFactory) {\n\t\t\t// static request handler\n\t\t\tthis._requestHandler = this._requestHandlerFactory(hostProxy);\n\t\t\treturn Promise.resolve(types.getAllMethodNames(this._requestHandler));\n\t\t}\n\n\t\tif (loaderConfig) {\n\t\t\t// Remove 'baseUrl', handling it is beyond scope for now\n\t\t\tif (typeof loaderConfig.baseUrl !== 'undefined') {\n\t\t\t\tdelete loaderConfig['baseUrl'];\n\t\t\t}\n\t\t\tif (typeof loaderConfig.paths !== 'undefined') {\n\t\t\t\tif (typeof loaderConfig.paths.vs !== 'undefined') {\n\t\t\t\t\tdelete loaderConfig.paths['vs'];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (typeof loaderConfig.trustedTypesPolicy !== undefined) {\n\t\t\t\t// don't use, it has been destroyed during serialize\n\t\t\t\tdelete loaderConfig['trustedTypesPolicy'];\n\t\t\t}\n\n\t\t\t// Since this is in a web worker, enable catching errors\n\t\t\tloaderConfig.catchError = true;\n\t\t\tglobals.require.config(loaderConfig);\n\t\t}\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t// Use the global require to be sure to get the global config\n\n\t\t\t// ESM-comment-begin\n\t\t\tconst req = (globals.require || require);\n\t\t\t// ESM-comment-end\n\t\t\t// ESM-uncomment-begin\n\t\t\t// const req = globals.require;\n\t\t\t// ESM-uncomment-end\n\n\t\t\treq([moduleId], (module: { create: IRequestHandlerFactory }) => {\n\t\t\t\tthis._requestHandler = module.create(hostProxy);\n\n\t\t\t\tif (!this._requestHandler) {\n\t\t\t\t\treject(new Error(`No RequestHandler!`));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tresolve(types.getAllMethodNames(this._requestHandler));\n\t\t\t}, reject);\n\t\t});\n\t}\n}\n\n/**\n * Called on the worker side\n */\nexport function create(postMessage: (msg: Message, transfer?: ArrayBuffer[]) => void): SimpleWorkerServer {\n\treturn new SimpleWorkerServer(postMessage, null);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { globals } from 'vs/base/common/platform';\nimport { IWorker, IWorkerCallback, IWorkerFactory, logOnceWebWorkerWarning } from 'vs/base/common/worker/simpleWorker';\n\nconst ttPolicy = window.trustedTypes?.createPolicy('defaultWorkerFactory', { createScriptURL: value => value });\n\nfunction getWorker(label: string): Worker | Promise {\n\t// Option for hosts to overwrite the worker script (used in the standalone editor)\n\tif (globals.MonacoEnvironment) {\n\t\tif (typeof globals.MonacoEnvironment.getWorker === 'function') {\n\t\t\treturn globals.MonacoEnvironment.getWorker('workerMain.js', label);\n\t\t}\n\t\tif (typeof globals.MonacoEnvironment.getWorkerUrl === 'function') {\n\t\t\tconst workerUrl = globals.MonacoEnvironment.getWorkerUrl('workerMain.js', label);\n\t\t\treturn new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label });\n\t\t}\n\t}\n\t// ESM-comment-begin\n\tif (typeof require === 'function') {\n\t\t// check if the JS lives on a different origin\n\t\tconst workerMain = require.toUrl('vs/base/worker/workerMain.js'); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321\n\t\tconst workerUrl = getWorkerBootstrapUrl(workerMain, label);\n\t\treturn new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label });\n\t}\n\t// ESM-comment-end\n\tthrow new Error(`You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker`);\n}\n\n// ESM-comment-begin\nexport function getWorkerBootstrapUrl(scriptPath: string, label: string): string {\n\tif (/^((http:)|(https:)|(file:))/.test(scriptPath) && scriptPath.substring(0, self.origin.length) !== self.origin) {\n\t\t// this is the cross-origin case\n\t\t// i.e. the webpage is running at a different origin than where the scripts are loaded from\n\t\tconst myPath = 'vs/base/worker/defaultWorkerFactory.js';\n\t\tconst workerBaseUrl = require.toUrl(myPath).slice(0, -myPath.length); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321\n\t\tconst js = `/*${label}*/self.MonacoEnvironment={baseUrl: '${workerBaseUrl}'};const ttPolicy = self.trustedTypes?.createPolicy('defaultWorkerFactory', { createScriptURL: value => value });importScripts(ttPolicy?.createScriptURL('${scriptPath}') ?? '${scriptPath}');/*${label}*/`;\n\t\tconst blob = new Blob([js], { type: 'application/javascript' });\n\t\treturn URL.createObjectURL(blob);\n\t}\n\treturn scriptPath + '#' + label;\n}\n// ESM-comment-end\n\nfunction isPromiseLike(obj: any): obj is PromiseLike {\n\tif (typeof obj.then === 'function') {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * A worker that uses HTML5 web workers so that is has\n * its own global scope and its own thread.\n */\nclass WebWorker implements IWorker {\n\n\tprivate id: number;\n\tprivate worker: Promise | null;\n\n\tconstructor(moduleId: string, id: number, label: string, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void) {\n\t\tthis.id = id;\n\t\tconst workerOrPromise = getWorker(label);\n\t\tif (isPromiseLike(workerOrPromise)) {\n\t\t\tthis.worker = workerOrPromise;\n\t\t} else {\n\t\t\tthis.worker = Promise.resolve(workerOrPromise);\n\t\t}\n\t\tthis.postMessage(moduleId, []);\n\t\tthis.worker.then((w) => {\n\t\t\tw.onmessage = function (ev) {\n\t\t\t\tonMessageCallback(ev.data);\n\t\t\t};\n\t\t\tw.onmessageerror = onErrorCallback;\n\t\t\tif (typeof w.addEventListener === 'function') {\n\t\t\t\tw.addEventListener('error', onErrorCallback);\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic getId(): number {\n\t\treturn this.id;\n\t}\n\n\tpublic postMessage(message: any, transfer: Transferable[]): void {\n\t\tif (this.worker) {\n\t\t\tthis.worker.then(w => w.postMessage(message, transfer));\n\t\t}\n\t}\n\n\tpublic dispose(): void {\n\t\tif (this.worker) {\n\t\t\tthis.worker.then(w => w.terminate());\n\t\t}\n\t\tthis.worker = null;\n\t}\n}\n\nexport class DefaultWorkerFactory implements IWorkerFactory {\n\n\tprivate static LAST_WORKER_ID = 0;\n\n\tprivate _label: string | undefined;\n\tprivate _webWorkerFailedBeforeError: any;\n\n\tconstructor(label: string | undefined) {\n\t\tthis._label = label;\n\t\tthis._webWorkerFailedBeforeError = false;\n\t}\n\n\tpublic create(moduleId: string, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void): IWorker {\n\t\tlet workerId = (++DefaultWorkerFactory.LAST_WORKER_ID);\n\n\t\tif (this._webWorkerFailedBeforeError) {\n\t\t\tthrow this._webWorkerFailedBeforeError;\n\t\t}\n\n\t\treturn new WebWorker(moduleId, workerId, this._label || 'anonymous' + workerId, onMessageCallback, (err) => {\n\t\t\tlogOnceWebWorkerWarning(err);\n\t\t\tthis._webWorkerFailedBeforeError = err;\n\t\t\tonErrorCallback(err);\n\t\t});\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport { IMatch } from 'vs/base/common/filters';\nimport { IItemAccessor } from 'vs/base/common/fuzzyScorer';\nimport { ResolvedKeybinding } from 'vs/base/common/keybindings';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { URI } from 'vs/base/common/uri';\n\nexport interface IQuickPickItemHighlights {\n\tlabel?: IMatch[];\n\tdescription?: IMatch[];\n\tdetail?: IMatch[];\n}\n\nexport interface IQuickPickItem {\n\ttype?: 'item';\n\tlabel: string;\n\tmeta?: string;\n\tariaLabel?: string;\n\tdescription?: string;\n\tdetail?: string;\n\t/**\n\t * Allows to show a keybinding next to the item to indicate\n\t * how the item can be triggered outside of the picker using\n\t * keyboard shortcut.\n\t */\n\tkeybinding?: ResolvedKeybinding;\n\ticonClasses?: string[];\n\titalic?: boolean;\n\tstrikethrough?: boolean;\n\thighlights?: IQuickPickItemHighlights;\n\tbuttons?: IQuickInputButton[];\n\tpicked?: boolean;\n\talwaysShow?: boolean;\n}\n\nexport interface IQuickPickSeparator {\n\ttype: 'separator';\n\tlabel?: string;\n}\n\nexport interface IKeyMods {\n\treadonly ctrlCmd: boolean;\n\treadonly alt: boolean;\n}\n\nexport const NO_KEY_MODS: IKeyMods = { ctrlCmd: false, alt: false };\n\nexport interface IQuickNavigateConfiguration {\n\tkeybindings: ResolvedKeybinding[];\n}\n\nexport interface IPickOptions {\n\n\t/**\n\t * an optional string to show as the title of the quick input\n\t */\n\ttitle?: string;\n\n\t/**\n\t * an optional string to show as placeholder in the input box to guide the user what she picks on\n\t */\n\tplaceHolder?: string;\n\n\t/**\n\t * an optional flag to include the description when filtering the picks\n\t */\n\tmatchOnDescription?: boolean;\n\n\t/**\n\t * an optional flag to include the detail when filtering the picks\n\t */\n\tmatchOnDetail?: boolean;\n\n\t/**\n\t * an optional flag to filter the picks based on label. Defaults to true.\n\t */\n\tmatchOnLabel?: boolean;\n\n\t/**\n\t * an option flag to control whether focus is always automatically brought to a list item. Defaults to true.\n\t */\n\tautoFocusOnList?: boolean;\n\n\t/**\n\t * an optional flag to not close the picker on focus lost\n\t */\n\tignoreFocusLost?: boolean;\n\n\t/**\n\t * an optional flag to make this picker multi-select\n\t */\n\tcanPickMany?: boolean;\n\n\t/**\n\t * enables quick navigate in the picker to open an element without typing\n\t */\n\tquickNavigate?: IQuickNavigateConfiguration;\n\n\t/**\n\t * a context key to set when this picker is active\n\t */\n\tcontextKey?: string;\n\n\t/**\n\t * an optional property for the item to focus initially.\n\t */\n\tactiveItem?: Promise | T;\n\n\tonKeyMods?: (keyMods: IKeyMods) => void;\n\tonDidFocus?: (entry: T) => void;\n\tonDidTriggerItemButton?: (context: IQuickPickItemButtonContext) => void;\n}\n\nexport enum QuickInputHideReason {\n\n\t/**\n\t * Focus moved away from the quick input.\n\t */\n\tBlur = 1,\n\n\t/**\n\t * An explicit user gesture, e.g. pressing Escape key.\n\t */\n\tGesture,\n\n\t/**\n\t * Anything else.\n\t */\n\tOther\n}\n\nexport interface IQuickInputHideEvent {\n\treason: QuickInputHideReason;\n}\n\nexport interface IQuickInput extends IDisposable {\n\n\treadonly onDidHide: Event;\n\n\ttitle: string | undefined;\n\n\tcontextKey: string | undefined;\n\n\tbusy: boolean;\n\n\tignoreFocusOut: boolean;\n\n\tshow(): void;\n\n\thide(): void;\n}\n\nexport interface IQuickPickWillAcceptEvent {\n\n\t/**\n\t * Allows to disable the default accept handling\n\t * of the picker. If `veto` is called, the picker\n\t * will not trigger the `onDidAccept` event.\n\t */\n\tveto(): void;\n}\n\nexport interface IQuickPickDidAcceptEvent {\n\n\t/**\n\t * Signals if the picker item is to be accepted\n\t * in the background while keeping the picker open.\n\t */\n\tinBackground: boolean;\n}\n\nexport enum ItemActivation {\n\tNONE,\n\tFIRST,\n\tSECOND,\n\tLAST\n}\n\nexport interface IQuickPick extends IQuickInput {\n\n\tvalue: string;\n\n\t/**\n\t * A method that allows to massage the value used\n\t * for filtering, e.g, to remove certain parts.\n\t */\n\tfilterValue: (value: string) => string;\n\n\tariaLabel: string | undefined;\n\n\tplaceholder: string | undefined;\n\n\treadonly onDidChangeValue: Event;\n\n\treadonly onWillAccept: Event;\n\treadonly onDidAccept: Event;\n\n\t/**\n\t * If enabled, will fire the `onDidAccept` event when\n\t * pressing the arrow-right key with the idea of accepting\n\t * the selected item without closing the picker.\n\t */\n\tcanAcceptInBackground: boolean;\n\n\treadonly onDidTriggerItemButton: Event>;\n\n\titems: ReadonlyArray;\n\n\tcanSelectMany: boolean;\n\n\tmatchOnDescription: boolean;\n\n\tmatchOnDetail: boolean;\n\n\tmatchOnLabel: boolean;\n\n\tsortByLabel: boolean;\n\n\tautoFocusOnList: boolean;\n\n\tkeepScrollPosition: boolean;\n\n\tquickNavigate: IQuickNavigateConfiguration | undefined;\n\n\tactiveItems: ReadonlyArray;\n\n\treadonly onDidChangeActive: Event;\n\n\t/**\n\t * Allows to control which entry should be activated by default.\n\t */\n\titemActivation: ItemActivation;\n\n\tselectedItems: ReadonlyArray;\n\n\treadonly onDidChangeSelection: Event;\n\n\treadonly keyMods: IKeyMods;\n\n\tvalueSelection: Readonly<[number, number]> | undefined;\n\n\t/**\n\t * Hides the input box from the picker UI. This is typically used\n\t * in combination with quick-navigation where no search UI should\n\t * be presented.\n\t */\n\thideInput: boolean;\n}\n\nexport interface IQuickInputButton {\n\t/** iconPath or iconClass required */\n\ticonPath?: { dark: URI; light?: URI; };\n\t/** iconPath or iconClass required */\n\ticonClass?: string;\n\ttooltip?: string;\n\t/**\n\t * Whether to always show the button. By default buttons\n\t * are only visible when hovering over them with the mouse\n\t */\n\talwaysVisible?: boolean;\n}\n\nexport interface IQuickPickItemButtonEvent {\n\tbutton: IQuickInputButton;\n\titem: T;\n}\n\nexport interface IQuickPickItemButtonContext extends IQuickPickItemButtonEvent {\n\tremoveItem(): void;\n}\n\nexport type QuickPickInput = T | IQuickPickSeparator;\n\n\n//#region Fuzzy Scorer Support\n\nexport type IQuickPickItemWithResource = IQuickPickItem & { resource?: URI };\n\nexport class QuickPickItemScorerAccessor implements IItemAccessor {\n\n\tconstructor(private options?: { skipDescription?: boolean, skipPath?: boolean }) { }\n}\n\nexport const quickPickItemScorerAccessor = new QuickPickItemScorerAccessor();\n\n//#endregion\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ThrottledDelayer } from 'vs/base/common/async';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport { isUndefinedOrNull } from 'vs/base/common/types';\n\nexport interface IStorageOptions {\n}\n\nexport interface IUpdateRequest {\n\treadonly insert?: Map;\n\treadonly delete?: Set;\n}\n\nexport interface IStorageItemsChangeEvent {\n\treadonly changed?: Map;\n\treadonly deleted?: Set;\n}\n\nexport interface IStorageDatabase {\n\n\treadonly onDidChangeItemsExternal: Event;\n\tupdateItems(request: IUpdateRequest): Promise;\n}\n\nexport interface IStorage extends IDisposable {\n\n\tget(key: string, fallbackValue: string): string;\n\tget(key: string, fallbackValue?: string): string | undefined;\n\n\tgetBoolean(key: string, fallbackValue: boolean): boolean;\n\tgetBoolean(key: string, fallbackValue?: boolean): boolean | undefined;\n\n\tgetNumber(key: string, fallbackValue: number): number;\n\tgetNumber(key: string, fallbackValue?: number): number | undefined;\n\n\tset(key: string, value: string | boolean | number | undefined | null): Promise;\n\tdelete(key: string): Promise;\n}\n\nenum StorageState {\n\tNone,\n\tInitialized,\n\tClosed\n}\n\nexport class Storage extends Disposable implements IStorage {\n\n\tprivate static readonly DEFAULT_FLUSH_DELAY = 100;\n\n\tprivate readonly _onDidChangeStorage = this._register(new Emitter());\n\treadonly onDidChangeStorage = this._onDidChangeStorage.event;\n\n\tprivate state = StorageState.None;\n\n\tprivate cache = new Map();\n\n\tprivate readonly flushDelayer = new ThrottledDelayer(Storage.DEFAULT_FLUSH_DELAY);\n\n\tprivate pendingDeletes = new Set();\n\tprivate pendingInserts = new Map();\n\n\tprivate readonly whenFlushedCallbacks: Function[] = [];\n\n\tconstructor(\n\t\tprotected readonly database: IStorageDatabase,\n\t\tprivate readonly options: IStorageOptions = Object.create(null)\n\t) {\n\t\tsuper();\n\n\t\tthis.registerListeners();\n\t}\n\n\tprivate registerListeners(): void {\n\t\tthis._register(this.database.onDidChangeItemsExternal(e => this.onDidChangeItemsExternal(e)));\n\t}\n\n\tprivate onDidChangeItemsExternal(e: IStorageItemsChangeEvent): void {\n\t\t// items that change external require us to update our\n\t\t// caches with the values. we just accept the value and\n\t\t// emit an event if there is a change.\n\t\te.changed?.forEach((value, key) => this.accept(key, value));\n\t\te.deleted?.forEach(key => this.accept(key, undefined));\n\t}\n\n\tprivate accept(key: string, value: string | undefined): void {\n\t\tif (this.state === StorageState.Closed) {\n\t\t\treturn; // Return early if we are already closed\n\t\t}\n\n\t\tlet changed = false;\n\n\t\t// Item got removed, check for deletion\n\t\tif (isUndefinedOrNull(value)) {\n\t\t\tchanged = this.cache.delete(key);\n\t\t}\n\n\t\t// Item got updated, check for change\n\t\telse {\n\t\t\tconst currentValue = this.cache.get(key);\n\t\t\tif (currentValue !== value) {\n\t\t\t\tthis.cache.set(key, value);\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\n\t\t// Signal to outside listeners\n\t\tif (changed) {\n\t\t\tthis._onDidChangeStorage.fire(key);\n\t\t}\n\t}\n\n\tget(key: string, fallbackValue: string): string;\n\tget(key: string, fallbackValue?: string): string | undefined;\n\tget(key: string, fallbackValue?: string): string | undefined {\n\t\tconst value = this.cache.get(key);\n\n\t\tif (isUndefinedOrNull(value)) {\n\t\t\treturn fallbackValue;\n\t\t}\n\n\t\treturn value;\n\t}\n\n\tgetBoolean(key: string, fallbackValue: boolean): boolean;\n\tgetBoolean(key: string, fallbackValue?: boolean): boolean | undefined;\n\tgetBoolean(key: string, fallbackValue?: boolean): boolean | undefined {\n\t\tconst value = this.get(key);\n\n\t\tif (isUndefinedOrNull(value)) {\n\t\t\treturn fallbackValue;\n\t\t}\n\n\t\treturn value === 'true';\n\t}\n\n\tgetNumber(key: string, fallbackValue: number): number;\n\tgetNumber(key: string, fallbackValue?: number): number | undefined;\n\tgetNumber(key: string, fallbackValue?: number): number | undefined {\n\t\tconst value = this.get(key);\n\n\t\tif (isUndefinedOrNull(value)) {\n\t\t\treturn fallbackValue;\n\t\t}\n\n\t\treturn parseInt(value, 10);\n\t}\n\n\tasync set(key: string, value: string | boolean | number | null | undefined): Promise {\n\t\tif (this.state === StorageState.Closed) {\n\t\t\treturn; // Return early if we are already closed\n\t\t}\n\n\t\t// We remove the key for undefined/null values\n\t\tif (isUndefinedOrNull(value)) {\n\t\t\treturn this.delete(key);\n\t\t}\n\n\t\t// Otherwise, convert to String and store\n\t\tconst valueStr = String(value);\n\n\t\t// Return early if value already set\n\t\tconst currentValue = this.cache.get(key);\n\t\tif (currentValue === valueStr) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Update in cache and pending\n\t\tthis.cache.set(key, valueStr);\n\t\tthis.pendingInserts.set(key, valueStr);\n\t\tthis.pendingDeletes.delete(key);\n\n\t\t// Event\n\t\tthis._onDidChangeStorage.fire(key);\n\n\t\t// Accumulate work by scheduling after timeout\n\t\treturn this.doFlush();\n\t}\n\n\tasync delete(key: string): Promise {\n\t\tif (this.state === StorageState.Closed) {\n\t\t\treturn; // Return early if we are already closed\n\t\t}\n\n\t\t// Remove from cache and add to pending\n\t\tconst wasDeleted = this.cache.delete(key);\n\t\tif (!wasDeleted) {\n\t\t\treturn; // Return early if value already deleted\n\t\t}\n\n\t\tif (!this.pendingDeletes.has(key)) {\n\t\t\tthis.pendingDeletes.add(key);\n\t\t}\n\n\t\tthis.pendingInserts.delete(key);\n\n\t\t// Event\n\t\tthis._onDidChangeStorage.fire(key);\n\n\t\t// Accumulate work by scheduling after timeout\n\t\treturn this.doFlush();\n\t}\n\n\tprivate get hasPending() {\n\t\treturn this.pendingInserts.size > 0 || this.pendingDeletes.size > 0;\n\t}\n\n\tprivate async flushPending(): Promise {\n\t\tif (!this.hasPending) {\n\t\t\treturn; // return early if nothing to do\n\t\t}\n\n\t\t// Get pending data\n\t\tconst updateRequest: IUpdateRequest = { insert: this.pendingInserts, delete: this.pendingDeletes };\n\n\t\t// Reset pending data for next run\n\t\tthis.pendingDeletes = new Set();\n\t\tthis.pendingInserts = new Map();\n\n\t\t// Update in storage and release any\n\t\t// waiters we have once done\n\t\treturn this.database.updateItems(updateRequest).finally(() => {\n\t\t\tif (!this.hasPending) {\n\t\t\t\twhile (this.whenFlushedCallbacks.length) {\n\t\t\t\t\tthis.whenFlushedCallbacks.pop()?.();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate async doFlush(delay?: number): Promise {\n\t\treturn this.flushDelayer.trigger(() => this.flushPending(), delay);\n\t}\n\n\toverride dispose(): void {\n\t\tthis.flushDelayer.dispose();\n\n\t\tsuper.dispose();\n\t}\n}\n\nexport class InMemoryStorageDatabase implements IStorageDatabase {\n\n\treadonly onDidChangeItemsExternal = Event.None;\n\n\tprivate readonly items = new Map();\n\n\tasync updateItems(request: IUpdateRequest): Promise {\n\t\tif (request.insert) {\n\t\t\trequest.insert.forEach((value, key) => this.items.set(key, value));\n\t\t}\n\n\t\tif (request.delete) {\n\t\t\trequest.delete.forEach(key => this.items.delete(key));\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { isMacintosh } from 'vs/base/common/platform';\nimport 'vs/css!./aria';\n\n// Use a max length since we are inserting the whole msg in the DOM and that can cause browsers to freeze for long messages #94233\nconst MAX_MESSAGE_LENGTH = 20000;\nlet ariaContainer: HTMLElement;\nlet alertContainer: HTMLElement;\nlet alertContainer2: HTMLElement;\nlet statusContainer: HTMLElement;\nlet statusContainer2: HTMLElement;\nexport function setARIAContainer(parent: HTMLElement) {\n\tariaContainer = document.createElement('div');\n\tariaContainer.className = 'monaco-aria-container';\n\n\tconst createAlertContainer = () => {\n\t\tconst element = document.createElement('div');\n\t\telement.className = 'monaco-alert';\n\t\telement.setAttribute('role', 'alert');\n\t\telement.setAttribute('aria-atomic', 'true');\n\t\tariaContainer.appendChild(element);\n\t\treturn element;\n\t};\n\talertContainer = createAlertContainer();\n\talertContainer2 = createAlertContainer();\n\n\tconst createStatusContainer = () => {\n\t\tconst element = document.createElement('div');\n\t\telement.className = 'monaco-status';\n\t\telement.setAttribute('role', 'complementary');\n\t\telement.setAttribute('aria-live', 'polite');\n\t\telement.setAttribute('aria-atomic', 'true');\n\t\tariaContainer.appendChild(element);\n\t\treturn element;\n\t};\n\tstatusContainer = createStatusContainer();\n\tstatusContainer2 = createStatusContainer();\n\n\tparent.appendChild(ariaContainer);\n}\n/**\n * Given the provided message, will make sure that it is read as alert to screen readers.\n */\nexport function alert(msg: string): void {\n\tif (!ariaContainer) {\n\t\treturn;\n\t}\n\n\t// Use alternate containers such that duplicated messages get read out by screen readers #99466\n\tif (alertContainer.textContent !== msg) {\n\t\tdom.clearNode(alertContainer2);\n\t\tinsertMessage(alertContainer, msg);\n\t} else {\n\t\tdom.clearNode(alertContainer);\n\t\tinsertMessage(alertContainer2, msg);\n\t}\n}\n\n/**\n * Given the provided message, will make sure that it is read as status to screen readers.\n */\nexport function status(msg: string): void {\n\tif (!ariaContainer) {\n\t\treturn;\n\t}\n\n\tif (isMacintosh) {\n\t\talert(msg); // VoiceOver does not seem to support status role\n\t} else {\n\t\tif (statusContainer.textContent !== msg) {\n\t\t\tdom.clearNode(statusContainer2);\n\t\t\tinsertMessage(statusContainer, msg);\n\t\t} else {\n\t\t\tdom.clearNode(statusContainer);\n\t\t\tinsertMessage(statusContainer2, msg);\n\t\t}\n\t}\n}\n\nfunction insertMessage(target: HTMLElement, msg: string): void {\n\tdom.clearNode(target);\n\tif (msg.length > MAX_MESSAGE_LENGTH) {\n\t\tmsg = msg.substr(0, MAX_MESSAGE_LENGTH);\n\t}\n\ttarget.textContent = msg;\n\n\t// See https://www.paciellogroup.com/blog/2012/06/html5-accessibility-chops-aria-rolealert-browser-support/\n\ttarget.style.visibility = 'hidden';\n\ttarget.style.visibility = 'visible';\n}\n","\nimport { addDisposableListener, EventHelper, EventType, IFocusTracker, reset, trackFocus } from 'vs/base/browser/dom';\nimport { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { EventType as TouchEventType, Gesture } from 'vs/base/browser/touch';\nimport { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';\nimport { Color } from 'vs/base/common/color';\nimport { Emitter, Event as BaseEvent } from 'vs/base/common/event';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport { mixin } from 'vs/base/common/objects';\nimport 'vs/css!./button';\n\nexport interface IButtonOptions extends IButtonStyles {\n\treadonly title?: boolean | string;\n\treadonly supportIcons?: boolean;\n\treadonly secondary?: boolean;\n}\n\nexport interface IButtonStyles {\n\tbuttonBackground?: Color;\n\tbuttonHoverBackground?: Color;\n\tbuttonForeground?: Color;\n\tbuttonSecondaryBackground?: Color;\n\tbuttonSecondaryHoverBackground?: Color;\n\tbuttonSecondaryForeground?: Color;\n\tbuttonBorder?: Color;\n}\n\nconst defaultOptions: IButtonStyles = {\n\tbuttonBackground: Color.fromHex('#0E639C'),\n\tbuttonHoverBackground: Color.fromHex('#006BB3'),\n\tbuttonForeground: Color.white\n};\n\nexport interface IButton extends IDisposable {\n}\n\nexport class Button extends Disposable implements IButton {\n\n\tprotected _element: HTMLElement;\n\tprotected options: IButtonOptions;\n\n\tprivate buttonBackground: Color | undefined;\n\tprivate buttonHoverBackground: Color | undefined;\n\tprivate buttonForeground: Color | undefined;\n\tprivate buttonSecondaryBackground: Color | undefined;\n\tprivate buttonSecondaryHoverBackground: Color | undefined;\n\tprivate buttonSecondaryForeground: Color | undefined;\n\tprivate buttonBorder: Color | undefined;\n\n\tprivate _onDidClick = this._register(new Emitter());\n\tget onDidClick(): BaseEvent { return this._onDidClick.event; }\n\n\tprivate focusTracker: IFocusTracker;\n\n\tconstructor(container: HTMLElement, options?: IButtonOptions) {\n\t\tsuper();\n\n\t\tthis.options = options || Object.create(null);\n\t\tmixin(this.options, defaultOptions, false);\n\n\t\tthis.buttonForeground = this.options.buttonForeground;\n\t\tthis.buttonBackground = this.options.buttonBackground;\n\t\tthis.buttonHoverBackground = this.options.buttonHoverBackground;\n\n\t\tthis.buttonSecondaryForeground = this.options.buttonSecondaryForeground;\n\t\tthis.buttonSecondaryBackground = this.options.buttonSecondaryBackground;\n\t\tthis.buttonSecondaryHoverBackground = this.options.buttonSecondaryHoverBackground;\n\n\t\tthis.buttonBorder = this.options.buttonBorder;\n\n\t\tthis._element = document.createElement('a');\n\t\tthis._element.classList.add('monaco-button');\n\t\tthis._element.tabIndex = 0;\n\t\tthis._element.setAttribute('role', 'button');\n\n\t\tcontainer.appendChild(this._element);\n\n\t\tthis._register(Gesture.addTarget(this._element));\n\n\t\t[EventType.CLICK, TouchEventType.Tap].forEach(eventType => {\n\t\t\tthis._register(addDisposableListener(this._element, eventType, e => {\n\t\t\t\tif (!this.enabled) {\n\t\t\t\t\tEventHelper.stop(e);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis._onDidClick.fire(e);\n\t\t\t}));\n\t\t});\n\n\t\tthis._register(addDisposableListener(this._element, EventType.KEY_DOWN, e => {\n\t\t\tconst event = new StandardKeyboardEvent(e);\n\t\t\tlet eventHandled = false;\n\t\t\tif (this.enabled && (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space))) {\n\t\t\t\tthis._onDidClick.fire(e);\n\t\t\t\teventHandled = true;\n\t\t\t} else if (event.equals(KeyCode.Escape)) {\n\t\t\t\tthis._element.blur();\n\t\t\t\teventHandled = true;\n\t\t\t}\n\n\t\t\tif (eventHandled) {\n\t\t\t\tEventHelper.stop(event, true);\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(addDisposableListener(this._element, EventType.MOUSE_OVER, e => {\n\t\t\tif (!this._element.classList.contains('disabled')) {\n\t\t\t\tthis.setHoverBackground();\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(addDisposableListener(this._element, EventType.MOUSE_OUT, e => {\n\t\t\tthis.applyStyles(); // restore standard styles\n\t\t}));\n\n\t\t// Also set hover background when button is focused for feedback\n\t\tthis.focusTracker = this._register(trackFocus(this._element));\n\t\tthis._register(this.focusTracker.onDidFocus(() => this.setHoverBackground()));\n\t\tthis._register(this.focusTracker.onDidBlur(() => this.applyStyles())); // restore standard styles\n\n\t\tthis.applyStyles();\n\t}\n\n\tprivate setHoverBackground(): void {\n\t\tlet hoverBackground;\n\t\tif (this.options.secondary) {\n\t\t\thoverBackground = this.buttonSecondaryHoverBackground ? this.buttonSecondaryHoverBackground.toString() : null;\n\t\t} else {\n\t\t\thoverBackground = this.buttonHoverBackground ? this.buttonHoverBackground.toString() : null;\n\t\t}\n\t\tif (hoverBackground) {\n\t\t\tthis._element.style.backgroundColor = hoverBackground;\n\t\t}\n\t}\n\n\tstyle(styles: IButtonStyles): void {\n\t\tthis.buttonForeground = styles.buttonForeground;\n\t\tthis.buttonBackground = styles.buttonBackground;\n\t\tthis.buttonHoverBackground = styles.buttonHoverBackground;\n\t\tthis.buttonSecondaryForeground = styles.buttonSecondaryForeground;\n\t\tthis.buttonSecondaryBackground = styles.buttonSecondaryBackground;\n\t\tthis.buttonSecondaryHoverBackground = styles.buttonSecondaryHoverBackground;\n\t\tthis.buttonBorder = styles.buttonBorder;\n\n\t\tthis.applyStyles();\n\t}\n\n\tprivate applyStyles(): void {\n\t\tif (this._element) {\n\t\t\tlet background, foreground;\n\t\t\tif (this.options.secondary) {\n\t\t\t\tforeground = this.buttonSecondaryForeground ? this.buttonSecondaryForeground.toString() : '';\n\t\t\t\tbackground = this.buttonSecondaryBackground ? this.buttonSecondaryBackground.toString() : '';\n\t\t\t} else {\n\t\t\t\tforeground = this.buttonForeground ? this.buttonForeground.toString() : '';\n\t\t\t\tbackground = this.buttonBackground ? this.buttonBackground.toString() : '';\n\t\t\t}\n\n\t\t\tconst border = this.buttonBorder ? this.buttonBorder.toString() : '';\n\n\t\t\tthis._element.style.color = foreground;\n\t\t\tthis._element.style.backgroundColor = background;\n\n\t\t\tthis._element.style.borderWidth = border ? '1px' : '';\n\t\t\tthis._element.style.borderStyle = border ? 'solid' : '';\n\t\t\tthis._element.style.borderColor = border;\n\t\t}\n\t}\n\n\tget element(): HTMLElement {\n\t\treturn this._element;\n\t}\n\n\tset label(value: string) {\n\t\tthis._element.classList.add('monaco-text-button');\n\t\tif (this.options.supportIcons) {\n\t\t\treset(this._element, ...renderLabelWithIcons(value));\n\t\t} else {\n\t\t\tthis._element.textContent = value;\n\t\t}\n\t\tif (typeof this.options.title === 'string') {\n\t\t\tthis._element.title = this.options.title;\n\t\t} else if (this.options.title) {\n\t\t\tthis._element.title = value;\n\t\t}\n\t}\n\n\tset enabled(value: boolean) {\n\t\tif (value) {\n\t\t\tthis._element.classList.remove('disabled');\n\t\t\tthis._element.setAttribute('aria-disabled', String(false));\n\t\t\tthis._element.tabIndex = 0;\n\t\t} else {\n\t\t\tthis._element.classList.add('disabled');\n\t\t\tthis._element.setAttribute('aria-disabled', String(true));\n\t\t}\n\t}\n\n\tget enabled() {\n\t\treturn !this._element.classList.contains('disabled');\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { Widget } from 'vs/base/browser/ui/widget';\nimport { CSSIcon } from 'vs/base/common/codicons';\nimport { Color } from 'vs/base/common/color';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport 'vs/css!./checkbox';\n\nexport interface ICheckboxOpts extends ICheckboxStyles {\n\treadonly actionClassName?: string;\n\treadonly icon?: CSSIcon;\n\treadonly title: string;\n\treadonly isChecked: boolean;\n\treadonly notFocusable?: boolean;\n}\n\nexport interface ICheckboxStyles {\n\tinputActiveOptionBorder?: Color;\n\tinputActiveOptionForeground?: Color;\n\tinputActiveOptionBackground?: Color;\n}\n\nconst defaultOpts = {\n\tinputActiveOptionBorder: Color.fromHex('#007ACC00'),\n\tinputActiveOptionForeground: Color.fromHex('#FFFFFF'),\n\tinputActiveOptionBackground: Color.fromHex('#0E639C50')\n};\n\nexport class Checkbox extends Widget {\n\n\tprivate readonly _onChange = this._register(new Emitter());\n\treadonly onChange: Event = this._onChange.event;\n\n\tprivate readonly _onKeyDown = this._register(new Emitter());\n\treadonly onKeyDown: Event = this._onKeyDown.event;\n\n\tprivate readonly _opts: ICheckboxOpts;\n\treadonly domNode: HTMLElement;\n\n\tprivate _checked: boolean;\n\n\tconstructor(opts: ICheckboxOpts) {\n\t\tsuper();\n\n\t\tthis._opts = { ...defaultOpts, ...opts };\n\t\tthis._checked = this._opts.isChecked;\n\n\t\tconst classes = ['monaco-custom-checkbox'];\n\t\tif (this._opts.icon) {\n\t\t\tclasses.push(...CSSIcon.asClassNameArray(this._opts.icon));\n\t\t}\n\t\tif (this._opts.actionClassName) {\n\t\t\tclasses.push(...this._opts.actionClassName.split(' '));\n\t\t}\n\t\tif (this._checked) {\n\t\t\tclasses.push('checked');\n\t\t}\n\n\t\tthis.domNode = document.createElement('div');\n\t\tthis.domNode.title = this._opts.title;\n\t\tthis.domNode.classList.add(...classes);\n\t\tif (!this._opts.notFocusable) {\n\t\t\tthis.domNode.tabIndex = 0;\n\t\t}\n\t\tthis.domNode.setAttribute('role', 'checkbox');\n\t\tthis.domNode.setAttribute('aria-checked', String(this._checked));\n\t\tthis.domNode.setAttribute('aria-label', this._opts.title);\n\n\t\tthis.applyStyles();\n\n\t\tthis.onclick(this.domNode, (ev) => {\n\t\t\tif (this.enabled) {\n\t\t\t\tthis.checked = !this._checked;\n\t\t\t\tthis._onChange.fire(false);\n\t\t\t\tev.preventDefault();\n\t\t\t}\n\t\t});\n\n\t\tthis.ignoreGesture(this.domNode);\n\n\t\tthis.onkeydown(this.domNode, (keyboardEvent) => {\n\t\t\tif (keyboardEvent.keyCode === KeyCode.Space || keyboardEvent.keyCode === KeyCode.Enter) {\n\t\t\t\tthis.checked = !this._checked;\n\t\t\t\tthis._onChange.fire(true);\n\t\t\t\tkeyboardEvent.preventDefault();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._onKeyDown.fire(keyboardEvent);\n\t\t});\n\t}\n\n\tget enabled(): boolean {\n\t\treturn this.domNode.getAttribute('aria-disabled') !== 'true';\n\t}\n\n\tfocus(): void {\n\t\tthis.domNode.focus();\n\t}\n\n\tget checked(): boolean {\n\t\treturn this._checked;\n\t}\n\n\tset checked(newIsChecked: boolean) {\n\t\tthis._checked = newIsChecked;\n\n\t\tthis.domNode.setAttribute('aria-checked', String(this._checked));\n\t\tthis.domNode.classList.toggle('checked', this._checked);\n\n\t\tthis.applyStyles();\n\t}\n\n\twidth(): number {\n\t\treturn 2 /*margin left*/ + 2 /*border*/ + 2 /*padding*/ + 16 /* icon width */;\n\t}\n\n\tstyle(styles: ICheckboxStyles): void {\n\t\tif (styles.inputActiveOptionBorder) {\n\t\t\tthis._opts.inputActiveOptionBorder = styles.inputActiveOptionBorder;\n\t\t}\n\t\tif (styles.inputActiveOptionForeground) {\n\t\t\tthis._opts.inputActiveOptionForeground = styles.inputActiveOptionForeground;\n\t\t}\n\t\tif (styles.inputActiveOptionBackground) {\n\t\t\tthis._opts.inputActiveOptionBackground = styles.inputActiveOptionBackground;\n\t\t}\n\t\tthis.applyStyles();\n\t}\n\n\tprotected applyStyles(): void {\n\t\tif (this.domNode) {\n\t\t\tthis.domNode.style.borderColor = this._checked && this._opts.inputActiveOptionBorder ? this._opts.inputActiveOptionBorder.toString() : '';\n\t\t\tthis.domNode.style.color = this._checked && this._opts.inputActiveOptionForeground ? this._opts.inputActiveOptionForeground.toString() : 'inherit';\n\t\t\tthis.domNode.style.backgroundColor = this._checked && this._opts.inputActiveOptionBackground ? this._opts.inputActiveOptionBackground.toString() : '';\n\t\t}\n\t}\n\n\tenable(): void {\n\t\tthis.domNode.setAttribute('aria-disabled', String(false));\n\t}\n\n\tdisable(): void {\n\t\tthis.domNode.setAttribute('aria-disabled', String(true));\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Codicon } from 'vs/base/common/codicons';\nimport 'vs/css!./codicon/codicon';\nimport 'vs/css!./codicon/codicon-modifiers';\n\n\nexport function formatRule(c: Codicon) {\n\tlet def = c.definition;\n\twhile (def instanceof Codicon) {\n\t\tdef = def.definition;\n\t}\n\treturn `.codicon-${c.id}:before { content: '${def.fontCharacter}'; }`;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { BrowserFeatures } from 'vs/base/browser/canIUse';\nimport * as DOM from 'vs/base/browser/dom';\nimport { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport * as platform from 'vs/base/common/platform';\nimport { Range } from 'vs/base/common/range';\nimport 'vs/css!./contextview';\n\nexport const enum ContextViewDOMPosition {\n\tABSOLUTE = 1,\n\tFIXED,\n\tFIXED_SHADOW\n}\n\nexport interface IAnchor {\n\tx: number;\n\ty: number;\n\twidth?: number;\n\theight?: number;\n}\n\nexport const enum AnchorAlignment {\n\tLEFT, RIGHT\n}\n\nexport const enum AnchorPosition {\n\tBELOW, ABOVE\n}\n\nexport const enum AnchorAxisAlignment {\n\tVERTICAL, HORIZONTAL\n}\n\nexport interface IDelegate {\n\tgetAnchor(): HTMLElement | IAnchor;\n\trender(container: HTMLElement): IDisposable | null;\n\tfocus?(): void;\n\tlayout?(): void;\n\tanchorAlignment?: AnchorAlignment; // default: left\n\tanchorPosition?: AnchorPosition; // default: below\n\tanchorAxisAlignment?: AnchorAxisAlignment; // default: vertical\n\tcanRelayout?: boolean; // default: true\n\tonDOMEvent?(e: Event, activeElement: HTMLElement): void;\n\tonHide?(data?: unknown): void;\n}\n\nexport interface IContextViewProvider {\n\tshowContextView(delegate: IDelegate, container?: HTMLElement): void;\n\thideContextView(): void;\n\tlayout(): void;\n}\n\nexport interface IPosition {\n\ttop: number;\n\tleft: number;\n}\n\nexport interface ISize {\n\twidth: number;\n\theight: number;\n}\n\nexport interface IView extends IPosition, ISize { }\n\nexport const enum LayoutAnchorPosition {\n\tBefore,\n\tAfter\n}\n\nexport enum LayoutAnchorMode {\n\tAVOID,\n\tALIGN\n}\n\nexport interface ILayoutAnchor {\n\toffset: number;\n\tsize: number;\n\tmode?: LayoutAnchorMode; // default: AVOID\n\tposition: LayoutAnchorPosition;\n}\n\n/**\n * Lays out a one dimensional view next to an anchor in a viewport.\n *\n * @returns The view offset within the viewport.\n */\nexport function layout(viewportSize: number, viewSize: number, anchor: ILayoutAnchor): number {\n\tconst layoutAfterAnchorBoundary = anchor.mode === LayoutAnchorMode.ALIGN ? anchor.offset : anchor.offset + anchor.size;\n\tconst layoutBeforeAnchorBoundary = anchor.mode === LayoutAnchorMode.ALIGN ? anchor.offset + anchor.size : anchor.offset;\n\n\tif (anchor.position === LayoutAnchorPosition.Before) {\n\t\tif (viewSize <= viewportSize - layoutAfterAnchorBoundary) {\n\t\t\treturn layoutAfterAnchorBoundary; // happy case, lay it out after the anchor\n\t\t}\n\n\t\tif (viewSize <= layoutBeforeAnchorBoundary) {\n\t\t\treturn layoutBeforeAnchorBoundary - viewSize; // ok case, lay it out before the anchor\n\t\t}\n\n\t\treturn Math.max(viewportSize - viewSize, 0); // sad case, lay it over the anchor\n\t} else {\n\t\tif (viewSize <= layoutBeforeAnchorBoundary) {\n\t\t\treturn layoutBeforeAnchorBoundary - viewSize; // happy case, lay it out before the anchor\n\t\t}\n\n\t\tif (viewSize <= viewportSize - layoutAfterAnchorBoundary) {\n\t\t\treturn layoutAfterAnchorBoundary; // ok case, lay it out after the anchor\n\t\t}\n\n\t\treturn 0; // sad case, lay it over the anchor\n\t}\n}\n\nexport class ContextView extends Disposable {\n\n\tprivate static readonly BUBBLE_UP_EVENTS = ['click', 'keydown', 'focus', 'blur'];\n\tprivate static readonly BUBBLE_DOWN_EVENTS = ['click'];\n\n\tprivate container: HTMLElement | null = null;\n\tprivate view: HTMLElement;\n\tprivate useFixedPosition: boolean;\n\tprivate useShadowDOM: boolean;\n\tprivate delegate: IDelegate | null = null;\n\tprivate toDisposeOnClean: IDisposable = Disposable.None;\n\tprivate toDisposeOnSetContainer: IDisposable = Disposable.None;\n\tprivate shadowRoot: ShadowRoot | null = null;\n\tprivate shadowRootHostElement: HTMLElement | null = null;\n\n\tconstructor(container: HTMLElement | null, domPosition: ContextViewDOMPosition) {\n\t\tsuper();\n\n\t\tthis.view = DOM.$('.context-view');\n\t\tthis.useFixedPosition = false;\n\t\tthis.useShadowDOM = false;\n\n\t\tDOM.hide(this.view);\n\n\t\tthis.setContainer(container, domPosition);\n\n\t\tthis._register(toDisposable(() => this.setContainer(null, ContextViewDOMPosition.ABSOLUTE)));\n\t}\n\n\tsetContainer(container: HTMLElement | null, domPosition: ContextViewDOMPosition): void {\n\t\tif (this.container) {\n\t\t\tthis.toDisposeOnSetContainer.dispose();\n\n\t\t\tif (this.shadowRoot) {\n\t\t\t\tthis.shadowRoot.removeChild(this.view);\n\t\t\t\tthis.shadowRoot = null;\n\t\t\t\tthis.shadowRootHostElement?.remove();\n\t\t\t\tthis.shadowRootHostElement = null;\n\t\t\t} else {\n\t\t\t\tthis.container.removeChild(this.view);\n\t\t\t}\n\n\t\t\tthis.container = null;\n\t\t}\n\t\tif (container) {\n\t\t\tthis.container = container;\n\n\t\t\tthis.useFixedPosition = domPosition !== ContextViewDOMPosition.ABSOLUTE;\n\t\t\tthis.useShadowDOM = domPosition === ContextViewDOMPosition.FIXED_SHADOW;\n\n\t\t\tif (this.useShadowDOM) {\n\t\t\t\tthis.shadowRootHostElement = DOM.$('.shadow-root-host');\n\t\t\t\tthis.container.appendChild(this.shadowRootHostElement);\n\t\t\t\tthis.shadowRoot = this.shadowRootHostElement.attachShadow({ mode: 'open' });\n\t\t\t\tconst style = document.createElement('style');\n\t\t\t\tstyle.textContent = SHADOW_ROOT_CSS;\n\t\t\t\tthis.shadowRoot.appendChild(style);\n\t\t\t\tthis.shadowRoot.appendChild(this.view);\n\t\t\t\tthis.shadowRoot.appendChild(DOM.$('slot'));\n\t\t\t} else {\n\t\t\t\tthis.container.appendChild(this.view);\n\t\t\t}\n\n\t\t\tconst toDisposeOnSetContainer = new DisposableStore();\n\n\t\t\tContextView.BUBBLE_UP_EVENTS.forEach(event => {\n\t\t\t\ttoDisposeOnSetContainer.add(DOM.addStandardDisposableListener(this.container!, event, (e: Event) => {\n\t\t\t\t\tthis.onDOMEvent(e, false);\n\t\t\t\t}));\n\t\t\t});\n\n\t\t\tContextView.BUBBLE_DOWN_EVENTS.forEach(event => {\n\t\t\t\ttoDisposeOnSetContainer.add(DOM.addStandardDisposableListener(this.container!, event, (e: Event) => {\n\t\t\t\t\tthis.onDOMEvent(e, true);\n\t\t\t\t}, true));\n\t\t\t});\n\n\t\t\tthis.toDisposeOnSetContainer = toDisposeOnSetContainer;\n\t\t}\n\t}\n\n\tshow(delegate: IDelegate): void {\n\t\tif (this.isVisible()) {\n\t\t\tthis.hide();\n\t\t}\n\n\t\t// Show static box\n\t\tDOM.clearNode(this.view);\n\t\tthis.view.className = 'context-view';\n\t\tthis.view.style.top = '0px';\n\t\tthis.view.style.left = '0px';\n\t\tthis.view.style.zIndex = '2500';\n\t\tthis.view.style.position = this.useFixedPosition ? 'fixed' : 'absolute';\n\t\tDOM.show(this.view);\n\n\t\t// Render content\n\t\tthis.toDisposeOnClean = delegate.render(this.view) || Disposable.None;\n\n\t\t// Set active delegate\n\t\tthis.delegate = delegate;\n\n\t\t// Layout\n\t\tthis.doLayout();\n\n\t\t// Focus\n\t\tif (this.delegate.focus) {\n\t\t\tthis.delegate.focus();\n\t\t}\n\t}\n\n\tgetViewElement(): HTMLElement {\n\t\treturn this.view;\n\t}\n\n\tlayout(): void {\n\t\tif (!this.isVisible()) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.delegate!.canRelayout === false && !(platform.isIOS && BrowserFeatures.pointerEvents)) {\n\t\t\tthis.hide();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.delegate!.layout) {\n\t\t\tthis.delegate!.layout!();\n\t\t}\n\n\t\tthis.doLayout();\n\t}\n\n\tprivate doLayout(): void {\n\t\t// Check that we still have a delegate - this.delegate.layout may have hidden\n\t\tif (!this.isVisible()) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Get anchor\n\t\tlet anchor = this.delegate!.getAnchor();\n\n\t\t// Compute around\n\t\tlet around: IView;\n\n\t\t// Get the element's position and size (to anchor the view)\n\t\tif (DOM.isHTMLElement(anchor)) {\n\t\t\tlet elementPosition = DOM.getDomNodePagePosition(anchor);\n\n\t\t\taround = {\n\t\t\t\ttop: elementPosition.top,\n\t\t\t\tleft: elementPosition.left,\n\t\t\t\twidth: elementPosition.width,\n\t\t\t\theight: elementPosition.height\n\t\t\t};\n\t\t} else {\n\t\t\taround = {\n\t\t\t\ttop: anchor.y,\n\t\t\t\tleft: anchor.x,\n\t\t\t\twidth: anchor.width || 1,\n\t\t\t\theight: anchor.height || 2\n\t\t\t};\n\t\t}\n\n\t\tconst viewSizeWidth = DOM.getTotalWidth(this.view);\n\t\tconst viewSizeHeight = DOM.getTotalHeight(this.view);\n\n\t\tconst anchorPosition = this.delegate!.anchorPosition || AnchorPosition.BELOW;\n\t\tconst anchorAlignment = this.delegate!.anchorAlignment || AnchorAlignment.LEFT;\n\t\tconst anchorAxisAlignment = this.delegate!.anchorAxisAlignment || AnchorAxisAlignment.VERTICAL;\n\n\t\tlet top: number;\n\t\tlet left: number;\n\n\t\tif (anchorAxisAlignment === AnchorAxisAlignment.VERTICAL) {\n\t\t\tconst verticalAnchor: ILayoutAnchor = { offset: around.top - window.pageYOffset, size: around.height, position: anchorPosition === AnchorPosition.BELOW ? LayoutAnchorPosition.Before : LayoutAnchorPosition.After };\n\t\t\tconst horizontalAnchor: ILayoutAnchor = { offset: around.left, size: around.width, position: anchorAlignment === AnchorAlignment.LEFT ? LayoutAnchorPosition.Before : LayoutAnchorPosition.After, mode: LayoutAnchorMode.ALIGN };\n\n\t\t\ttop = layout(window.innerHeight, viewSizeHeight, verticalAnchor) + window.pageYOffset;\n\n\t\t\t// if view intersects vertically with anchor, we must avoid the anchor\n\t\t\tif (Range.intersects({ start: top, end: top + viewSizeHeight }, { start: verticalAnchor.offset, end: verticalAnchor.offset + verticalAnchor.size })) {\n\t\t\t\thorizontalAnchor.mode = LayoutAnchorMode.AVOID;\n\t\t\t}\n\n\t\t\tleft = layout(window.innerWidth, viewSizeWidth, horizontalAnchor);\n\t\t} else {\n\t\t\tconst horizontalAnchor: ILayoutAnchor = { offset: around.left, size: around.width, position: anchorAlignment === AnchorAlignment.LEFT ? LayoutAnchorPosition.Before : LayoutAnchorPosition.After };\n\t\t\tconst verticalAnchor: ILayoutAnchor = { offset: around.top, size: around.height, position: anchorPosition === AnchorPosition.BELOW ? LayoutAnchorPosition.Before : LayoutAnchorPosition.After, mode: LayoutAnchorMode.ALIGN };\n\n\t\t\tleft = layout(window.innerWidth, viewSizeWidth, horizontalAnchor);\n\n\t\t\t// if view intersects horizontally with anchor, we must avoid the anchor\n\t\t\tif (Range.intersects({ start: left, end: left + viewSizeWidth }, { start: horizontalAnchor.offset, end: horizontalAnchor.offset + horizontalAnchor.size })) {\n\t\t\t\tverticalAnchor.mode = LayoutAnchorMode.AVOID;\n\t\t\t}\n\n\t\t\ttop = layout(window.innerHeight, viewSizeHeight, verticalAnchor) + window.pageYOffset;\n\t\t}\n\n\t\tthis.view.classList.remove('top', 'bottom', 'left', 'right');\n\t\tthis.view.classList.add(anchorPosition === AnchorPosition.BELOW ? 'bottom' : 'top');\n\t\tthis.view.classList.add(anchorAlignment === AnchorAlignment.LEFT ? 'left' : 'right');\n\t\tthis.view.classList.toggle('fixed', this.useFixedPosition);\n\n\t\tconst containerPosition = DOM.getDomNodePagePosition(this.container!);\n\t\tthis.view.style.top = `${top - (this.useFixedPosition ? DOM.getDomNodePagePosition(this.view).top : containerPosition.top)}px`;\n\t\tthis.view.style.left = `${left - (this.useFixedPosition ? DOM.getDomNodePagePosition(this.view).left : containerPosition.left)}px`;\n\t\tthis.view.style.width = 'initial';\n\t}\n\n\thide(data?: unknown): void {\n\t\tconst delegate = this.delegate;\n\t\tthis.delegate = null;\n\n\t\tif (delegate?.onHide) {\n\t\t\tdelegate.onHide(data);\n\t\t}\n\n\t\tthis.toDisposeOnClean.dispose();\n\n\t\tDOM.hide(this.view);\n\t}\n\n\tprivate isVisible(): boolean {\n\t\treturn !!this.delegate;\n\t}\n\n\tprivate onDOMEvent(e: Event, onCapture: boolean): void {\n\t\tif (this.delegate) {\n\t\t\tif (this.delegate.onDOMEvent) {\n\t\t\t\tthis.delegate.onDOMEvent(e, document.activeElement);\n\t\t\t} else if (onCapture && !DOM.isAncestor(e.target, this.container)) {\n\t\t\t\tthis.hide();\n\t\t\t}\n\t\t}\n\t}\n\n\toverride dispose(): void {\n\t\tthis.hide();\n\n\t\tsuper.dispose();\n\t}\n}\n\nlet SHADOW_ROOT_CSS = /* css */ `\n\t:host {\n\t\tall: initial; /* 1st rule so subsequent properties are reset. */\n\t}\n\n\t@font-face {\n\t\tfont-family: \"codicon\";\n\t\tfont-display: block;\n\t\tsrc: url(\"./codicon.ttf?5d4d76ab2ce5108968ad644d591a16a6\") format(\"truetype\");\n\t}\n\n\t.codicon[class*='codicon-'] {\n\t\tfont: normal normal normal 16px/1 codicon;\n\t\tdisplay: inline-block;\n\t\ttext-decoration: none;\n\t\ttext-rendering: auto;\n\t\ttext-align: center;\n\t\t-webkit-font-smoothing: antialiased;\n\t\t-moz-osx-font-smoothing: grayscale;\n\t\tuser-select: none;\n\t\t-webkit-user-select: none;\n\t\t-ms-user-select: none;\n\t}\n\n\t:host {\n\t\tfont-family: -apple-system, BlinkMacSystemFont, \"Segoe WPC\", \"Segoe UI\", \"HelveticaNeue-Light\", system-ui, \"Ubuntu\", \"Droid Sans\", sans-serif;\n\t}\n\n\t:host-context(.mac) { font-family: -apple-system, BlinkMacSystemFont, sans-serif; }\n\t:host-context(.mac:lang(zh-Hans)) { font-family: -apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Hiragino Sans GB\", sans-serif; }\n\t:host-context(.mac:lang(zh-Hant)) { font-family: -apple-system, BlinkMacSystemFont, \"PingFang TC\", sans-serif; }\n\t:host-context(.mac:lang(ja)) { font-family: -apple-system, BlinkMacSystemFont, \"Hiragino Kaku Gothic Pro\", sans-serif; }\n\t:host-context(.mac:lang(ko)) { font-family: -apple-system, BlinkMacSystemFont, \"Nanum Gothic\", \"Apple SD Gothic Neo\", \"AppleGothic\", sans-serif; }\n\n\t:host-context(.windows) { font-family: \"Segoe WPC\", \"Segoe UI\", sans-serif; }\n\t:host-context(.windows:lang(zh-Hans)) { font-family: \"Segoe WPC\", \"Segoe UI\", \"Microsoft YaHei\", sans-serif; }\n\t:host-context(.windows:lang(zh-Hant)) { font-family: \"Segoe WPC\", \"Segoe UI\", \"Microsoft Jhenghei\", sans-serif; }\n\t:host-context(.windows:lang(ja)) { font-family: \"Segoe WPC\", \"Segoe UI\", \"Yu Gothic UI\", \"Meiryo UI\", sans-serif; }\n\t:host-context(.windows:lang(ko)) { font-family: \"Segoe WPC\", \"Segoe UI\", \"Malgun Gothic\", \"Dotom\", sans-serif; }\n\n\t:host-context(.linux) { font-family: system-ui, \"Ubuntu\", \"Droid Sans\", sans-serif; }\n\t:host-context(.linux:lang(zh-Hans)) { font-family: system-ui, \"Ubuntu\", \"Droid Sans\", \"Source Han Sans SC\", \"Source Han Sans CN\", \"Source Han Sans\", sans-serif; }\n\t:host-context(.linux:lang(zh-Hant)) { font-family: system-ui, \"Ubuntu\", \"Droid Sans\", \"Source Han Sans TC\", \"Source Han Sans TW\", \"Source Han Sans\", sans-serif; }\n\t:host-context(.linux:lang(ja)) { font-family: system-ui, \"Ubuntu\", \"Droid Sans\", \"Source Han Sans J\", \"Source Han Sans JP\", \"Source Han Sans\", sans-serif; }\n\t:host-context(.linux:lang(ko)) { font-family: system-ui, \"Ubuntu\", \"Droid Sans\", \"Source Han Sans K\", \"Source Han Sans JR\", \"Source Han Sans\", \"UnDotum\", \"FBaekmuk Gulim\", sans-serif; }\n`;\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { $, append } from 'vs/base/browser/dom';\nimport { Color } from 'vs/base/common/color';\nimport { mixin } from 'vs/base/common/objects';\nimport { format } from 'vs/base/common/strings';\nimport { IThemable } from 'vs/base/common/styler';\nimport 'vs/css!./countBadge';\n\nexport interface ICountBadgeOptions extends ICountBadgetyles {\n\tcount?: number;\n\tcountFormat?: string;\n\ttitleFormat?: string;\n}\n\nexport interface ICountBadgetyles {\n\tbadgeBackground?: Color;\n\tbadgeForeground?: Color;\n\tbadgeBorder?: Color;\n}\n\nconst defaultOpts = {\n\tbadgeBackground: Color.fromHex('#4D4D4D'),\n\tbadgeForeground: Color.fromHex('#FFFFFF')\n};\n\nexport class CountBadge implements IThemable {\n\n\tprivate element: HTMLElement;\n\tprivate count: number = 0;\n\tprivate countFormat: string;\n\tprivate titleFormat: string;\n\n\tprivate badgeBackground: Color | undefined;\n\tprivate badgeForeground: Color | undefined;\n\tprivate badgeBorder: Color | undefined;\n\n\tprivate options: ICountBadgeOptions;\n\n\tconstructor(container: HTMLElement, options?: ICountBadgeOptions) {\n\t\tthis.options = options || Object.create(null);\n\t\tmixin(this.options, defaultOpts, false);\n\n\t\tthis.badgeBackground = this.options.badgeBackground;\n\t\tthis.badgeForeground = this.options.badgeForeground;\n\t\tthis.badgeBorder = this.options.badgeBorder;\n\n\t\tthis.element = append(container, $('.monaco-count-badge'));\n\t\tthis.countFormat = this.options.countFormat || '{0}';\n\t\tthis.titleFormat = this.options.titleFormat || '';\n\t\tthis.setCount(this.options.count || 0);\n\t}\n\n\tsetCount(count: number) {\n\t\tthis.count = count;\n\t\tthis.render();\n\t}\n\n\tsetTitleFormat(titleFormat: string) {\n\t\tthis.titleFormat = titleFormat;\n\t\tthis.render();\n\t}\n\n\tprivate render() {\n\t\tthis.element.textContent = format(this.countFormat, this.count);\n\t\tthis.element.title = format(this.titleFormat, this.count);\n\n\t\tthis.applyStyles();\n\t}\n\n\tstyle(styles: ICountBadgetyles): void {\n\t\tthis.badgeBackground = styles.badgeBackground;\n\t\tthis.badgeForeground = styles.badgeForeground;\n\t\tthis.badgeBorder = styles.badgeBorder;\n\n\t\tthis.applyStyles();\n\t}\n\n\tprivate applyStyles(): void {\n\t\tif (this.element) {\n\t\t\tconst background = this.badgeBackground ? this.badgeBackground.toString() : '';\n\t\t\tconst foreground = this.badgeForeground ? this.badgeForeground.toString() : '';\n\t\t\tconst border = this.badgeBorder ? this.badgeBorder.toString() : '';\n\n\t\t\tthis.element.style.backgroundColor = background;\n\t\t\tthis.element.style.color = foreground;\n\n\t\t\tthis.element.style.borderWidth = border ? '1px' : '';\n\t\t\tthis.element.style.borderStyle = border ? 'solid' : '';\n\t\t\tthis.element.style.borderColor = border;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport 'vs/css!./mouseCursor';\n\nexport const MOUSE_CURSOR_TEXT_CSS_CLASS_NAME = `monaco-mouse-cursor-text`;\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { show } from 'vs/base/browser/dom';\nimport { RunOnceScheduler } from 'vs/base/common/async';\nimport { Color } from 'vs/base/common/color';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { mixin } from 'vs/base/common/objects';\nimport 'vs/css!./progressbar';\n\nconst CSS_DONE = 'done';\nconst CSS_ACTIVE = 'active';\nconst CSS_INFINITE = 'infinite';\nconst CSS_INFINITE_LONG_RUNNING = 'infinite-long-running';\nconst CSS_DISCRETE = 'discrete';\n\nexport interface IProgressBarOptions extends IProgressBarStyles {\n}\n\nexport interface IProgressBarStyles {\n\tprogressBarBackground?: Color;\n}\n\nconst defaultOpts = {\n\tprogressBarBackground: Color.fromHex('#0E70C0')\n};\n\n/**\n * A progress bar with support for infinite or discrete progress.\n */\nexport class ProgressBar extends Disposable {\n\n\t/**\n\t * After a certain time of showing the progress bar, switch\n\t * to long-running mode and throttle animations to reduce\n\t * the pressure on the GPU process.\n\t *\n\t * https://github.com/microsoft/vscode/issues/97900\n\t * https://github.com/microsoft/vscode/issues/138396\n\t */\n\tprivate static readonly LONG_RUNNING_INFINITE_THRESHOLD = 10000;\n\n\tprivate options: IProgressBarOptions;\n\tprivate workedVal: number;\n\tprivate element!: HTMLElement;\n\tprivate bit!: HTMLElement;\n\tprivate totalWork: number | undefined;\n\tprivate progressBarBackground: Color | undefined;\n\tprivate showDelayedScheduler: RunOnceScheduler;\n\tprivate longRunningScheduler: RunOnceScheduler;\n\n\tconstructor(container: HTMLElement, options?: IProgressBarOptions) {\n\t\tsuper();\n\n\t\tthis.options = options || Object.create(null);\n\t\tmixin(this.options, defaultOpts, false);\n\n\t\tthis.workedVal = 0;\n\n\t\tthis.progressBarBackground = this.options.progressBarBackground;\n\n\t\tthis.showDelayedScheduler = this._register(new RunOnceScheduler(() => show(this.element), 0));\n\t\tthis.longRunningScheduler = this._register(new RunOnceScheduler(() => this.infiniteLongRunning(), ProgressBar.LONG_RUNNING_INFINITE_THRESHOLD));\n\n\t\tthis.create(container);\n\t}\n\n\tprivate create(container: HTMLElement): void {\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.classList.add('monaco-progress-container');\n\t\tthis.element.setAttribute('role', 'progressbar');\n\t\tthis.element.setAttribute('aria-valuemin', '0');\n\t\tcontainer.appendChild(this.element);\n\n\t\tthis.bit = document.createElement('div');\n\t\tthis.bit.classList.add('progress-bit');\n\t\tthis.element.appendChild(this.bit);\n\n\t\tthis.applyStyles();\n\t}\n\n\tprivate off(): void {\n\t\tthis.bit.style.width = 'inherit';\n\t\tthis.bit.style.opacity = '1';\n\t\tthis.element.classList.remove(CSS_ACTIVE, CSS_INFINITE, CSS_INFINITE_LONG_RUNNING, CSS_DISCRETE);\n\n\t\tthis.workedVal = 0;\n\t\tthis.totalWork = undefined;\n\n\t\tthis.longRunningScheduler.cancel();\n\t}\n\n\t/**\n\t * Stops the progressbar from showing any progress instantly without fading out.\n\t */\n\tstop(): ProgressBar {\n\t\treturn this.doDone(false);\n\t}\n\n\tprivate doDone(delayed: boolean): ProgressBar {\n\t\tthis.element.classList.add(CSS_DONE);\n\n\t\t// discrete: let it grow to 100% width and hide afterwards\n\t\tif (!this.element.classList.contains(CSS_INFINITE)) {\n\t\t\tthis.bit.style.width = 'inherit';\n\n\t\t\tif (delayed) {\n\t\t\t\tsetTimeout(() => this.off(), 200);\n\t\t\t} else {\n\t\t\t\tthis.off();\n\t\t\t}\n\t\t}\n\n\t\t// infinite: let it fade out and hide afterwards\n\t\telse {\n\t\t\tthis.bit.style.opacity = '0';\n\t\t\tif (delayed) {\n\t\t\t\tsetTimeout(() => this.off(), 200);\n\t\t\t} else {\n\t\t\t\tthis.off();\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Use this mode to indicate progress that has no total number of work units.\n\t */\n\tinfinite(): ProgressBar {\n\t\tthis.bit.style.width = '2%';\n\t\tthis.bit.style.opacity = '1';\n\n\t\tthis.element.classList.remove(CSS_DISCRETE, CSS_DONE, CSS_INFINITE_LONG_RUNNING);\n\t\tthis.element.classList.add(CSS_ACTIVE, CSS_INFINITE);\n\n\t\tthis.longRunningScheduler.schedule();\n\n\t\treturn this;\n\t}\n\n\tprivate infiniteLongRunning(): void {\n\t\tthis.element.classList.add(CSS_INFINITE_LONG_RUNNING);\n\t}\n\n\tgetContainer(): HTMLElement {\n\t\treturn this.element;\n\t}\n\n\tstyle(styles: IProgressBarStyles): void {\n\t\tthis.progressBarBackground = styles.progressBarBackground;\n\n\t\tthis.applyStyles();\n\t}\n\n\tprotected applyStyles(): void {\n\t\tif (this.bit) {\n\t\t\tconst background = this.progressBarBackground ? this.progressBarBackground.toString() : '';\n\n\t\t\tthis.bit.style.backgroundColor = background;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { $, append, createStyleSheet, EventHelper, EventLike, getElementsByTagName } from 'vs/base/browser/dom';\nimport { DomEmitter } from 'vs/base/browser/event';\nimport { EventType, Gesture, GestureEvent } from 'vs/base/browser/touch';\nimport { Delayer } from 'vs/base/common/async';\nimport { memoize } from 'vs/base/common/decorators';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';\nimport { isMacintosh } from 'vs/base/common/platform';\nimport 'vs/css!./sash';\n\n/**\n * Allow the sashes to be visible at runtime.\n * @remark Use for development purposes only.\n */\nlet DEBUG = false;\n// DEBUG = Boolean(\"true\"); // done \"weirdly\" so that a lint warning prevents you from pushing this\n\n/**\n * A vertical sash layout provider provides position and height for a sash.\n */\nexport interface IVerticalSashLayoutProvider {\n\tgetVerticalSashLeft(sash: Sash): number;\n\tgetVerticalSashTop?(sash: Sash): number;\n\tgetVerticalSashHeight?(sash: Sash): number;\n}\n\n/**\n * A vertical sash layout provider provides position and width for a sash.\n */\nexport interface IHorizontalSashLayoutProvider {\n\tgetHorizontalSashTop(sash: Sash): number;\n\tgetHorizontalSashLeft?(sash: Sash): number;\n\tgetHorizontalSashWidth?(sash: Sash): number;\n}\n\ntype ISashLayoutProvider = IVerticalSashLayoutProvider | IHorizontalSashLayoutProvider;\n\nexport interface ISashEvent {\n\treadonly startX: number;\n\treadonly currentX: number;\n\treadonly startY: number;\n\treadonly currentY: number;\n\treadonly altKey: boolean;\n}\n\nexport enum OrthogonalEdge {\n\tNorth = 'north',\n\tSouth = 'south',\n\tEast = 'east',\n\tWest = 'west'\n}\n\nexport interface ISashOptions {\n\n\t/**\n\t * Whether a sash is horizontal or vertical.\n\t */\n\treadonly orientation: Orientation;\n\n\t/**\n\t * The width or height of a vertical or horizontal sash, respectively.\n\t */\n\treadonly size?: number;\n\n\t/**\n\t * A reference to another sash, perpendicular to this one, which\n\t * aligns at the start of this one. A corner sash will be created\n\t * automatically at that location.\n\t *\n\t * The start of a horizontal sash is its left-most position.\n\t * The start of a vertical sash is its top-most position.\n\t */\n\treadonly orthogonalStartSash?: Sash;\n\n\t/**\n\t * A reference to another sash, perpendicular to this one, which\n\t * aligns at the end of this one. A corner sash will be created\n\t * automatically at that location.\n\t *\n\t * The end of a horizontal sash is its right-most position.\n\t * The end of a vertical sash is its bottom-most position.\n\t */\n\treadonly orthogonalEndSash?: Sash;\n\n\t/**\n\t * Provides a hint as to what mouse cursor to use whenever the user\n\t * hovers over a corner sash provided by this and an orthogonal sash.\n\t */\n\treadonly orthogonalEdge?: OrthogonalEdge;\n}\n\nexport interface IVerticalSashOptions extends ISashOptions {\n\treadonly orientation: Orientation.VERTICAL;\n}\n\nexport interface IHorizontalSashOptions extends ISashOptions {\n\treadonly orientation: Orientation.HORIZONTAL;\n}\n\nexport const enum Orientation {\n\tVERTICAL,\n\tHORIZONTAL\n}\n\nexport const enum SashState {\n\n\t/**\n\t * Disable any UI interaction.\n\t */\n\tDisabled,\n\n\t/**\n\t * Allow dragging down or to the right, depending on the sash orientation.\n\t *\n\t * Some OSs allow customizing the mouse cursor differently whenever\n\t * some resizable component can't be any smaller, but can be larger.\n\t */\n\tAtMinimum,\n\n\t/**\n\t * Allow dragging up or to the left, depending on the sash orientation.\n\t *\n\t * Some OSs allow customizing the mouse cursor differently whenever\n\t * some resizable component can't be any larger, but can be smaller.\n\t */\n\tAtMaximum,\n\n\t/**\n\t * Enable dragging.\n\t */\n\tEnabled\n}\n\nlet globalSize = 4;\nconst onDidChangeGlobalSize = new Emitter();\n\nlet globalHoverDelay = 300;\nconst onDidChangeHoverDelay = new Emitter();\n\ninterface PointerEvent extends EventLike {\n\treadonly pageX: number;\n\treadonly pageY: number;\n\treadonly altKey: boolean;\n\treadonly target: EventTarget | null;\n}\n\ninterface IPointerEventFactory {\n\treadonly onPointerMove: Event;\n\treadonly onPointerUp: Event;\n\tdispose(): void;\n}\n\nclass MouseEventFactory implements IPointerEventFactory {\n\n\tprivate disposables = new DisposableStore();\n\n\t@memoize\n\tget onPointerMove(): Event {\n\t\treturn this.disposables.add(new DomEmitter(window, 'mousemove')).event;\n\t}\n\n\t@memoize\n\tget onPointerUp(): Event {\n\t\treturn this.disposables.add(new DomEmitter(window, 'mouseup')).event;\n\t}\n\n\tdispose(): void {\n\t\tthis.disposables.dispose();\n\t}\n}\n\nclass GestureEventFactory implements IPointerEventFactory {\n\n\tprivate disposables = new DisposableStore();\n\n\t@memoize\n\tget onPointerMove(): Event {\n\t\treturn this.disposables.add(new DomEmitter(this.el, EventType.Change)).event;\n\t}\n\n\t@memoize\n\tget onPointerUp(): Event {\n\t\treturn this.disposables.add(new DomEmitter(this.el, EventType.End)).event;\n\t}\n\n\tconstructor(private el: HTMLElement) { }\n\n\tdispose(): void {\n\t\tthis.disposables.dispose();\n\t}\n}\n\nclass OrthogonalPointerEventFactory implements IPointerEventFactory {\n\n\t@memoize\n\tget onPointerMove(): Event {\n\t\treturn this.factory.onPointerMove;\n\t}\n\n\t@memoize\n\tget onPointerUp(): Event {\n\t\treturn this.factory.onPointerUp;\n\t}\n\n\tconstructor(private factory: IPointerEventFactory) { }\n\n\tdispose(): void {\n\t\t// noop\n\t}\n}\n\nconst PointerEventsDisabledCssClass = 'pointer-events-disabled';\n\n/**\n * The {@link Sash} is the UI component which allows the user to resize other\n * components. It's usually an invisible horizontal or vertical line which, when\n * hovered, becomes highlighted and can be dragged along the perpendicular dimension\n * to its direction.\n *\n * Features:\n * - Touch event handling\n * - Corner sash support\n * - Hover with different mouse cursor support\n * - Configurable hover size\n * - Linked sash support, for 2x2 corner sashes\n */\nexport class Sash extends Disposable {\n\n\tprivate el: HTMLElement;\n\tprivate layoutProvider: ISashLayoutProvider;\n\tprivate orientation: Orientation;\n\tprivate size: number;\n\tprivate hoverDelay = globalHoverDelay;\n\tprivate hoverDelayer = this._register(new Delayer(this.hoverDelay));\n\n\tprivate _state: SashState = SashState.Enabled;\n\tprivate readonly onDidEnablementChange = this._register(new Emitter());\n\tprivate readonly _onDidStart = this._register(new Emitter());\n\tprivate readonly _onDidChange = this._register(new Emitter());\n\tprivate readonly _onDidReset = this._register(new Emitter());\n\tprivate readonly _onDidEnd = this._register(new Emitter());\n\tprivate readonly orthogonalStartSashDisposables = this._register(new DisposableStore());\n\tprivate _orthogonalStartSash: Sash | undefined;\n\tprivate readonly orthogonalStartDragHandleDisposables = this._register(new DisposableStore());\n\tprivate _orthogonalStartDragHandle: HTMLElement | undefined;\n\tprivate readonly orthogonalEndSashDisposables = this._register(new DisposableStore());\n\tprivate _orthogonalEndSash: Sash | undefined;\n\tprivate readonly orthogonalEndDragHandleDisposables = this._register(new DisposableStore());\n\tprivate _orthogonalEndDragHandle: HTMLElement | undefined;\n\n\tget state(): SashState { return this._state; }\n\tget orthogonalStartSash(): Sash | undefined { return this._orthogonalStartSash; }\n\tget orthogonalEndSash(): Sash | undefined { return this._orthogonalEndSash; }\n\n\t/**\n\t * The state of a sash defines whether it can be interacted with by the user\n\t * as well as what mouse cursor to use, when hovered.\n\t */\n\tset state(state: SashState) {\n\t\tif (this._state === state) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.el.classList.toggle('disabled', state === SashState.Disabled);\n\t\tthis.el.classList.toggle('minimum', state === SashState.AtMinimum);\n\t\tthis.el.classList.toggle('maximum', state === SashState.AtMaximum);\n\n\t\tthis._state = state;\n\t\tthis.onDidEnablementChange.fire(state);\n\t}\n\n\t/**\n\t * An event which fires whenever the user starts dragging this sash.\n\t */\n\treadonly onDidStart: Event = this._onDidStart.event;\n\n\t/**\n\t * An event which fires whenever the user moves the mouse while\n\t * dragging this sash.\n\t */\n\treadonly onDidChange: Event = this._onDidChange.event;\n\n\t/**\n\t * An event which fires whenever the user double clicks this sash.\n\t */\n\treadonly onDidReset: Event = this._onDidReset.event;\n\n\t/**\n\t * An event which fires whenever the user stops dragging this sash.\n\t */\n\treadonly onDidEnd: Event = this._onDidEnd.event;\n\n\t/**\n\t * A linked sash will be forwarded the same user interactions and events\n\t * so it moves exactly the same way as this sash.\n\t *\n\t * Useful in 2x2 grids. Not meant for widespread usage.\n\t */\n\tlinkedSash: Sash | undefined = undefined;\n\n\t/**\n\t * A reference to another sash, perpendicular to this one, which\n\t * aligns at the start of this one. A corner sash will be created\n\t * automatically at that location.\n\t *\n\t * The start of a horizontal sash is its left-most position.\n\t * The start of a vertical sash is its top-most position.\n\t */\n\tset orthogonalStartSash(sash: Sash | undefined) {\n\t\tthis.orthogonalStartDragHandleDisposables.clear();\n\t\tthis.orthogonalStartSashDisposables.clear();\n\n\t\tif (sash) {\n\t\t\tconst onChange = (state: SashState) => {\n\t\t\t\tthis.orthogonalStartDragHandleDisposables.clear();\n\n\t\t\t\tif (state !== SashState.Disabled) {\n\t\t\t\t\tthis._orthogonalStartDragHandle = append(this.el, $('.orthogonal-drag-handle.start'));\n\t\t\t\t\tthis.orthogonalStartDragHandleDisposables.add(toDisposable(() => this._orthogonalStartDragHandle!.remove()));\n\t\t\t\t\tthis.orthogonalStartDragHandleDisposables.add(new DomEmitter(this._orthogonalStartDragHandle, 'mouseenter')).event\n\t\t\t\t\t\t(() => Sash.onMouseEnter(sash), undefined, this.orthogonalStartDragHandleDisposables);\n\t\t\t\t\tthis.orthogonalStartDragHandleDisposables.add(new DomEmitter(this._orthogonalStartDragHandle, 'mouseleave')).event\n\t\t\t\t\t\t(() => Sash.onMouseLeave(sash), undefined, this.orthogonalStartDragHandleDisposables);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.orthogonalStartSashDisposables.add(sash.onDidEnablementChange.event(onChange, this));\n\t\t\tonChange(sash.state);\n\t\t}\n\n\t\tthis._orthogonalStartSash = sash;\n\t}\n\n\t/**\n\t * A reference to another sash, perpendicular to this one, which\n\t * aligns at the end of this one. A corner sash will be created\n\t * automatically at that location.\n\t *\n\t * The end of a horizontal sash is its right-most position.\n\t * The end of a vertical sash is its bottom-most position.\n\t */\n\n\tset orthogonalEndSash(sash: Sash | undefined) {\n\t\tthis.orthogonalEndDragHandleDisposables.clear();\n\t\tthis.orthogonalEndSashDisposables.clear();\n\n\t\tif (sash) {\n\t\t\tconst onChange = (state: SashState) => {\n\t\t\t\tthis.orthogonalEndDragHandleDisposables.clear();\n\n\t\t\t\tif (state !== SashState.Disabled) {\n\t\t\t\t\tthis._orthogonalEndDragHandle = append(this.el, $('.orthogonal-drag-handle.end'));\n\t\t\t\t\tthis.orthogonalEndDragHandleDisposables.add(toDisposable(() => this._orthogonalEndDragHandle!.remove()));\n\t\t\t\t\tthis.orthogonalEndDragHandleDisposables.add(new DomEmitter(this._orthogonalEndDragHandle, 'mouseenter')).event\n\t\t\t\t\t\t(() => Sash.onMouseEnter(sash), undefined, this.orthogonalEndDragHandleDisposables);\n\t\t\t\t\tthis.orthogonalEndDragHandleDisposables.add(new DomEmitter(this._orthogonalEndDragHandle, 'mouseleave')).event\n\t\t\t\t\t\t(() => Sash.onMouseLeave(sash), undefined, this.orthogonalEndDragHandleDisposables);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.orthogonalEndSashDisposables.add(sash.onDidEnablementChange.event(onChange, this));\n\t\t\tonChange(sash.state);\n\t\t}\n\n\t\tthis._orthogonalEndSash = sash;\n\t}\n\n\t/**\n\t * Create a new vertical sash.\n\t *\n\t * @param container A DOM node to append the sash to.\n\t * @param verticalLayoutProvider A vertical layout provider.\n\t * @param options The options.\n\t */\n\tconstructor(container: HTMLElement, verticalLayoutProvider: IVerticalSashLayoutProvider, options: IVerticalSashOptions);\n\n\t/**\n\t * Create a new horizontal sash.\n\t *\n\t * @param container A DOM node to append the sash to.\n\t * @param horizontalLayoutProvider A horizontal layout provider.\n\t * @param options The options.\n\t */\n\tconstructor(container: HTMLElement, horizontalLayoutProvider: IHorizontalSashLayoutProvider, options: IHorizontalSashOptions);\n\tconstructor(container: HTMLElement, layoutProvider: ISashLayoutProvider, options: ISashOptions) {\n\t\tsuper();\n\n\t\tthis.el = append(container, $('.monaco-sash'));\n\n\t\tif (options.orthogonalEdge) {\n\t\t\tthis.el.classList.add(`orthogonal-edge-${options.orthogonalEdge}`);\n\t\t}\n\n\t\tif (isMacintosh) {\n\t\t\tthis.el.classList.add('mac');\n\t\t}\n\n\t\tconst onMouseDown = this._register(new DomEmitter(this.el, 'mousedown')).event;\n\t\tthis._register(onMouseDown(e => this.onPointerStart(e, new MouseEventFactory()), this));\n\t\tconst onMouseDoubleClick = this._register(new DomEmitter(this.el, 'dblclick')).event;\n\t\tthis._register(onMouseDoubleClick(this.onPointerDoublePress, this));\n\t\tconst onMouseEnter = this._register(new DomEmitter(this.el, 'mouseenter')).event;\n\t\tthis._register(onMouseEnter(() => Sash.onMouseEnter(this)));\n\t\tconst onMouseLeave = this._register(new DomEmitter(this.el, 'mouseleave')).event;\n\t\tthis._register(onMouseLeave(() => Sash.onMouseLeave(this)));\n\n\t\tthis._register(Gesture.addTarget(this.el));\n\n\t\tconst onTouchStart = Event.map(this._register(new DomEmitter(this.el, EventType.Start)).event, e => ({ ...e, target: e.initialTarget ?? null }));\n\t\tthis._register(onTouchStart(e => this.onPointerStart(e, new GestureEventFactory(this.el)), this));\n\t\tconst onTap = this._register(new DomEmitter(this.el, EventType.Tap)).event;\n\t\tconst onDoubleTap = Event.map(\n\t\t\tEvent.filter(\n\t\t\t\tEvent.debounce(onTap, (res, event) => ({ event, count: (res?.count ?? 0) + 1 }), 250),\n\t\t\t\t({ count }) => count === 2\n\t\t\t),\n\t\t\t({ event }) => ({ ...event, target: event.initialTarget ?? null })\n\t\t);\n\t\tthis._register(onDoubleTap(this.onPointerDoublePress, this));\n\n\t\tif (typeof options.size === 'number') {\n\t\t\tthis.size = options.size;\n\n\t\t\tif (options.orientation === Orientation.VERTICAL) {\n\t\t\t\tthis.el.style.width = `${this.size}px`;\n\t\t\t} else {\n\t\t\t\tthis.el.style.height = `${this.size}px`;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.size = globalSize;\n\t\t\tthis._register(onDidChangeGlobalSize.event(size => {\n\t\t\t\tthis.size = size;\n\t\t\t\tthis.layout();\n\t\t\t}));\n\t\t}\n\n\t\tthis._register(onDidChangeHoverDelay.event(delay => this.hoverDelay = delay));\n\n\t\tthis.layoutProvider = layoutProvider;\n\n\t\tthis.orthogonalStartSash = options.orthogonalStartSash;\n\t\tthis.orthogonalEndSash = options.orthogonalEndSash;\n\n\t\tthis.orientation = options.orientation || Orientation.VERTICAL;\n\n\t\tif (this.orientation === Orientation.HORIZONTAL) {\n\t\t\tthis.el.classList.add('horizontal');\n\t\t\tthis.el.classList.remove('vertical');\n\t\t} else {\n\t\t\tthis.el.classList.remove('horizontal');\n\t\t\tthis.el.classList.add('vertical');\n\t\t}\n\n\t\tthis.el.classList.toggle('debug', DEBUG);\n\n\t\tthis.layout();\n\t}\n\n\tprivate onPointerStart(event: PointerEvent, pointerEventFactory: IPointerEventFactory): void {\n\t\tEventHelper.stop(event);\n\n\t\tlet isMultisashResize = false;\n\n\t\tif (!(event as any).__orthogonalSashEvent) {\n\t\t\tconst orthogonalSash = this.getOrthogonalSash(event);\n\n\t\t\tif (orthogonalSash) {\n\t\t\t\tisMultisashResize = true;\n\t\t\t\t(event as any).__orthogonalSashEvent = true;\n\t\t\t\torthogonalSash.onPointerStart(event, new OrthogonalPointerEventFactory(pointerEventFactory));\n\t\t\t}\n\t\t}\n\n\t\tif (this.linkedSash && !(event as any).__linkedSashEvent) {\n\t\t\t(event as any).__linkedSashEvent = true;\n\t\t\tthis.linkedSash.onPointerStart(event, new OrthogonalPointerEventFactory(pointerEventFactory));\n\t\t}\n\n\t\tif (!this.state) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst iframes = getElementsByTagName('iframe');\n\t\tfor (const iframe of iframes) {\n\t\t\tiframe.classList.add(PointerEventsDisabledCssClass); // disable mouse events on iframes as long as we drag the sash\n\t\t}\n\n\t\tconst startX = event.pageX;\n\t\tconst startY = event.pageY;\n\t\tconst altKey = event.altKey;\n\t\tconst startEvent: ISashEvent = { startX, currentX: startX, startY, currentY: startY, altKey };\n\n\t\tthis.el.classList.add('active');\n\t\tthis._onDidStart.fire(startEvent);\n\n\t\t// fix https://github.com/microsoft/vscode/issues/21675\n\t\tconst style = createStyleSheet(this.el);\n\t\tconst updateStyle = () => {\n\t\t\tlet cursor = '';\n\n\t\t\tif (isMultisashResize) {\n\t\t\t\tcursor = 'all-scroll';\n\t\t\t} else if (this.orientation === Orientation.HORIZONTAL) {\n\t\t\t\tif (this.state === SashState.AtMinimum) {\n\t\t\t\t\tcursor = 's-resize';\n\t\t\t\t} else if (this.state === SashState.AtMaximum) {\n\t\t\t\t\tcursor = 'n-resize';\n\t\t\t\t} else {\n\t\t\t\t\tcursor = isMacintosh ? 'row-resize' : 'ns-resize';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (this.state === SashState.AtMinimum) {\n\t\t\t\t\tcursor = 'e-resize';\n\t\t\t\t} else if (this.state === SashState.AtMaximum) {\n\t\t\t\t\tcursor = 'w-resize';\n\t\t\t\t} else {\n\t\t\t\t\tcursor = isMacintosh ? 'col-resize' : 'ew-resize';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstyle.textContent = `* { cursor: ${cursor} !important; }`;\n\t\t};\n\n\t\tconst disposables = new DisposableStore();\n\n\t\tupdateStyle();\n\n\t\tif (!isMultisashResize) {\n\t\t\tthis.onDidEnablementChange.event(updateStyle, null, disposables);\n\t\t}\n\n\t\tconst onPointerMove = (e: PointerEvent) => {\n\t\t\tEventHelper.stop(e, false);\n\t\t\tconst event: ISashEvent = { startX, currentX: e.pageX, startY, currentY: e.pageY, altKey };\n\n\t\t\tthis._onDidChange.fire(event);\n\t\t};\n\n\t\tconst onPointerUp = (e: PointerEvent) => {\n\t\t\tEventHelper.stop(e, false);\n\n\t\t\tthis.el.removeChild(style);\n\n\t\t\tthis.el.classList.remove('active');\n\t\t\tthis._onDidEnd.fire();\n\n\t\t\tdisposables.dispose();\n\n\t\t\tfor (const iframe of iframes) {\n\t\t\t\tiframe.classList.remove(PointerEventsDisabledCssClass);\n\t\t\t}\n\t\t};\n\n\t\tpointerEventFactory.onPointerMove(onPointerMove, null, disposables);\n\t\tpointerEventFactory.onPointerUp(onPointerUp, null, disposables);\n\t\tdisposables.add(pointerEventFactory);\n\t}\n\n\tprivate onPointerDoublePress(e: MouseEvent): void {\n\t\tconst orthogonalSash = this.getOrthogonalSash(e);\n\n\t\tif (orthogonalSash) {\n\t\t\torthogonalSash._onDidReset.fire();\n\t\t}\n\n\t\tif (this.linkedSash) {\n\t\t\tthis.linkedSash._onDidReset.fire();\n\t\t}\n\n\t\tthis._onDidReset.fire();\n\t}\n\n\tprivate static onMouseEnter(sash: Sash, fromLinkedSash: boolean = false): void {\n\t\tif (sash.el.classList.contains('active')) {\n\t\t\tsash.hoverDelayer.cancel();\n\t\t\tsash.el.classList.add('hover');\n\t\t} else {\n\t\t\tsash.hoverDelayer.trigger(() => sash.el.classList.add('hover'), sash.hoverDelay).then(undefined, () => { });\n\t\t}\n\n\t\tif (!fromLinkedSash && sash.linkedSash) {\n\t\t\tSash.onMouseEnter(sash.linkedSash, true);\n\t\t}\n\t}\n\n\tprivate static onMouseLeave(sash: Sash, fromLinkedSash: boolean = false): void {\n\t\tsash.hoverDelayer.cancel();\n\t\tsash.el.classList.remove('hover');\n\n\t\tif (!fromLinkedSash && sash.linkedSash) {\n\t\t\tSash.onMouseLeave(sash.linkedSash, true);\n\t\t}\n\t}\n\n\t/**\n\t * Forcefully stop any user interactions with this sash.\n\t * Useful when hiding a parent component, while the user is still\n\t * interacting with the sash.\n\t */\n\tclearSashHoverState(): void {\n\t\tSash.onMouseLeave(this);\n\t}\n\n\t/**\n\t * Layout the sash. The sash will size and position itself\n\t * based on its provided {@link ISashLayoutProvider layout provider}.\n\t */\n\tlayout(): void {\n\t\tif (this.orientation === Orientation.VERTICAL) {\n\t\t\tconst verticalProvider = (this.layoutProvider);\n\t\t\tthis.el.style.left = verticalProvider.getVerticalSashLeft(this) - (this.size / 2) + 'px';\n\n\t\t\tif (verticalProvider.getVerticalSashTop) {\n\t\t\t\tthis.el.style.top = verticalProvider.getVerticalSashTop(this) + 'px';\n\t\t\t}\n\n\t\t\tif (verticalProvider.getVerticalSashHeight) {\n\t\t\t\tthis.el.style.height = verticalProvider.getVerticalSashHeight(this) + 'px';\n\t\t\t}\n\t\t} else {\n\t\t\tconst horizontalProvider = (this.layoutProvider);\n\t\t\tthis.el.style.top = horizontalProvider.getHorizontalSashTop(this) - (this.size / 2) + 'px';\n\n\t\t\tif (horizontalProvider.getHorizontalSashLeft) {\n\t\t\t\tthis.el.style.left = horizontalProvider.getHorizontalSashLeft(this) + 'px';\n\t\t\t}\n\n\t\t\tif (horizontalProvider.getHorizontalSashWidth) {\n\t\t\t\tthis.el.style.width = horizontalProvider.getHorizontalSashWidth(this) + 'px';\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getOrthogonalSash(e: PointerEvent): Sash | undefined {\n\t\tif (!e.target || !(e.target instanceof HTMLElement)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (e.target.classList.contains('orthogonal-drag-handle')) {\n\t\t\treturn e.target.classList.contains('start') ? this.orthogonalStartSash : this.orthogonalEndSash;\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tthis.el.remove();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { getZoomFactor } from 'vs/base/browser/browser';\nimport * as dom from 'vs/base/browser/dom';\nimport { createFastDomNode, FastDomNode } from 'vs/base/browser/fastDomNode';\nimport { IMouseEvent, IMouseWheelEvent, StandardWheelEvent } from 'vs/base/browser/mouseEvent';\nimport { ScrollbarHost } from 'vs/base/browser/ui/scrollbar/abstractScrollbar';\nimport { HorizontalScrollbar } from 'vs/base/browser/ui/scrollbar/horizontalScrollbar';\nimport { ScrollableElementChangeOptions, ScrollableElementCreationOptions, ScrollableElementResolvedOptions } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';\nimport { VerticalScrollbar } from 'vs/base/browser/ui/scrollbar/verticalScrollbar';\nimport { Widget } from 'vs/base/browser/ui/widget';\nimport { TimeoutTimer } from 'vs/base/common/async';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { dispose, IDisposable } from 'vs/base/common/lifecycle';\nimport * as platform from 'vs/base/common/platform';\nimport { INewScrollDimensions, INewScrollPosition, IScrollDimensions, IScrollPosition, Scrollable, ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';\nimport 'vs/css!./media/scrollbars';\n\nconst HIDE_TIMEOUT = 500;\nconst SCROLL_WHEEL_SENSITIVITY = 50;\nconst SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED = true;\n\nexport interface IOverviewRulerLayoutInfo {\n\tparent: HTMLElement;\n\tinsertBefore: HTMLElement;\n}\n\nclass MouseWheelClassifierItem {\n\tpublic timestamp: number;\n\tpublic deltaX: number;\n\tpublic deltaY: number;\n\tpublic score: number;\n\n\tconstructor(timestamp: number, deltaX: number, deltaY: number) {\n\t\tthis.timestamp = timestamp;\n\t\tthis.deltaX = deltaX;\n\t\tthis.deltaY = deltaY;\n\t\tthis.score = 0;\n\t}\n}\n\nexport class MouseWheelClassifier {\n\n\tpublic static readonly INSTANCE = new MouseWheelClassifier();\n\n\tprivate readonly _capacity: number;\n\tprivate _memory: MouseWheelClassifierItem[];\n\tprivate _front: number;\n\tprivate _rear: number;\n\n\tconstructor() {\n\t\tthis._capacity = 5;\n\t\tthis._memory = [];\n\t\tthis._front = -1;\n\t\tthis._rear = -1;\n\t}\n\n\tpublic isPhysicalMouseWheel(): boolean {\n\t\tif (this._front === -1 && this._rear === -1) {\n\t\t\t// no elements\n\t\t\treturn false;\n\t\t}\n\n\t\t// 0.5 * last + 0.25 * 2nd last + 0.125 * 3rd last + ...\n\t\tlet remainingInfluence = 1;\n\t\tlet score = 0;\n\t\tlet iteration = 1;\n\n\t\tlet index = this._rear;\n\t\tdo {\n\t\t\tconst influence = (index === this._front ? remainingInfluence : Math.pow(2, -iteration));\n\t\t\tremainingInfluence -= influence;\n\t\t\tscore += this._memory[index].score * influence;\n\n\t\t\tif (index === this._front) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tindex = (this._capacity + index - 1) % this._capacity;\n\t\t\titeration++;\n\t\t} while (true);\n\n\t\treturn (score <= 0.5);\n\t}\n\n\tpublic accept(timestamp: number, deltaX: number, deltaY: number): void {\n\t\tconst item = new MouseWheelClassifierItem(timestamp, deltaX, deltaY);\n\t\titem.score = this._computeScore(item);\n\n\t\tif (this._front === -1 && this._rear === -1) {\n\t\t\tthis._memory[0] = item;\n\t\t\tthis._front = 0;\n\t\t\tthis._rear = 0;\n\t\t} else {\n\t\t\tthis._rear = (this._rear + 1) % this._capacity;\n\t\t\tif (this._rear === this._front) {\n\t\t\t\t// Drop oldest\n\t\t\t\tthis._front = (this._front + 1) % this._capacity;\n\t\t\t}\n\t\t\tthis._memory[this._rear] = item;\n\t\t}\n\t}\n\n\t/**\n\t * A score between 0 and 1 for `item`.\n\t * - a score towards 0 indicates that the source appears to be a physical mouse wheel\n\t * - a score towards 1 indicates that the source appears to be a touchpad or magic mouse, etc.\n\t */\n\tprivate _computeScore(item: MouseWheelClassifierItem): number {\n\n\t\tif (Math.abs(item.deltaX) > 0 && Math.abs(item.deltaY) > 0) {\n\t\t\t// both axes exercised => definitely not a physical mouse wheel\n\t\t\treturn 1;\n\t\t}\n\n\t\tlet score: number = 0.5;\n\t\tconst prev = (this._front === -1 && this._rear === -1 ? null : this._memory[this._rear]);\n\t\tif (prev) {\n\t\t\t// const deltaT = item.timestamp - prev.timestamp;\n\t\t\t// if (deltaT < 1000 / 30) {\n\t\t\t// \t// sooner than X times per second => indicator that this is not a physical mouse wheel\n\t\t\t// \tscore += 0.25;\n\t\t\t// }\n\n\t\t\t// if (item.deltaX === prev.deltaX && item.deltaY === prev.deltaY) {\n\t\t\t// \t// equal amplitude => indicator that this is a physical mouse wheel\n\t\t\t// \tscore -= 0.25;\n\t\t\t// }\n\t\t}\n\n\t\tif (!this._isAlmostInt(item.deltaX) || !this._isAlmostInt(item.deltaY)) {\n\t\t\t// non-integer deltas => indicator that this is not a physical mouse wheel\n\t\t\tscore += 0.25;\n\t\t}\n\n\t\treturn Math.min(Math.max(score, 0), 1);\n\t}\n\n\tprivate _isAlmostInt(value: number): boolean {\n\t\tconst delta = Math.abs(Math.round(value) - value);\n\t\treturn (delta < 0.01);\n\t}\n}\n\nexport abstract class AbstractScrollableElement extends Widget {\n\n\tprivate readonly _options: ScrollableElementResolvedOptions;\n\tprotected readonly _scrollable: Scrollable;\n\tprivate readonly _verticalScrollbar: VerticalScrollbar;\n\tprivate readonly _horizontalScrollbar: HorizontalScrollbar;\n\tprivate readonly _domNode: HTMLElement;\n\n\tprivate readonly _leftShadowDomNode: FastDomNode | null;\n\tprivate readonly _topShadowDomNode: FastDomNode | null;\n\tprivate readonly _topLeftShadowDomNode: FastDomNode | null;\n\n\tprivate readonly _listenOnDomNode: HTMLElement;\n\n\tprivate _mouseWheelToDispose: IDisposable[];\n\n\tprivate _isDragging: boolean;\n\tprivate _mouseIsOver: boolean;\n\n\tprivate readonly _hideTimeout: TimeoutTimer;\n\tprivate _shouldRender: boolean;\n\n\tprivate _revealOnScroll: boolean;\n\n\tprivate readonly _onScroll = this._register(new Emitter());\n\tpublic readonly onScroll: Event = this._onScroll.event;\n\n\tprivate readonly _onWillScroll = this._register(new Emitter());\n\n\tpublic get options(): Readonly {\n\t\treturn this._options;\n\t}\n\n\tprotected constructor(element: HTMLElement, options: ScrollableElementCreationOptions, scrollable: Scrollable) {\n\t\tsuper();\n\t\telement.style.overflow = 'hidden';\n\t\tthis._options = resolveOptions(options);\n\t\tthis._scrollable = scrollable;\n\n\t\tthis._register(this._scrollable.onScroll((e) => {\n\t\t\tthis._onWillScroll.fire(e);\n\t\t\tthis._onDidScroll(e);\n\t\t\tthis._onScroll.fire(e);\n\t\t}));\n\n\t\tconst scrollbarHost: ScrollbarHost = {\n\t\t\tonMouseWheel: (mouseWheelEvent: StandardWheelEvent) => this._onMouseWheel(mouseWheelEvent),\n\t\t\tonDragStart: () => this._onDragStart(),\n\t\t\tonDragEnd: () => this._onDragEnd(),\n\t\t};\n\t\tthis._verticalScrollbar = this._register(new VerticalScrollbar(this._scrollable, this._options, scrollbarHost));\n\t\tthis._horizontalScrollbar = this._register(new HorizontalScrollbar(this._scrollable, this._options, scrollbarHost));\n\n\t\tthis._domNode = document.createElement('div');\n\t\tthis._domNode.className = 'monaco-scrollable-element ' + this._options.className;\n\t\tthis._domNode.setAttribute('role', 'presentation');\n\t\tthis._domNode.style.position = 'relative';\n\t\tthis._domNode.style.overflow = 'hidden';\n\t\tthis._domNode.appendChild(element);\n\t\tthis._domNode.appendChild(this._horizontalScrollbar.domNode.domNode);\n\t\tthis._domNode.appendChild(this._verticalScrollbar.domNode.domNode);\n\n\t\tif (this._options.useShadows) {\n\t\t\tthis._leftShadowDomNode = createFastDomNode(document.createElement('div'));\n\t\t\tthis._leftShadowDomNode.setClassName('shadow');\n\t\t\tthis._domNode.appendChild(this._leftShadowDomNode.domNode);\n\n\t\t\tthis._topShadowDomNode = createFastDomNode(document.createElement('div'));\n\t\t\tthis._topShadowDomNode.setClassName('shadow');\n\t\t\tthis._domNode.appendChild(this._topShadowDomNode.domNode);\n\n\t\t\tthis._topLeftShadowDomNode = createFastDomNode(document.createElement('div'));\n\t\t\tthis._topLeftShadowDomNode.setClassName('shadow');\n\t\t\tthis._domNode.appendChild(this._topLeftShadowDomNode.domNode);\n\t\t} else {\n\t\t\tthis._leftShadowDomNode = null;\n\t\t\tthis._topShadowDomNode = null;\n\t\t\tthis._topLeftShadowDomNode = null;\n\t\t}\n\n\t\tthis._listenOnDomNode = this._options.listenOnDomNode || this._domNode;\n\n\t\tthis._mouseWheelToDispose = [];\n\t\tthis._setListeningToMouseWheel(this._options.handleMouseWheel);\n\n\t\tthis.onmouseover(this._listenOnDomNode, (e) => this._onMouseOver(e));\n\t\tthis.onnonbubblingmouseout(this._listenOnDomNode, (e) => this._onMouseOut(e));\n\n\t\tthis._hideTimeout = this._register(new TimeoutTimer());\n\t\tthis._isDragging = false;\n\t\tthis._mouseIsOver = false;\n\n\t\tthis._shouldRender = true;\n\n\t\tthis._revealOnScroll = true;\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._mouseWheelToDispose = dispose(this._mouseWheelToDispose);\n\t\tsuper.dispose();\n\t}\n\n\t/**\n\t * Get the generated 'scrollable' dom node\n\t */\n\tpublic getDomNode(): HTMLElement {\n\t\treturn this._domNode;\n\t}\n\n\tpublic getOverviewRulerLayoutInfo(): IOverviewRulerLayoutInfo {\n\t\treturn {\n\t\t\tparent: this._domNode,\n\t\t\tinsertBefore: this._verticalScrollbar.domNode.domNode,\n\t\t};\n\t}\n\n\t/**\n\t * Delegate a mouse down event to the vertical scrollbar.\n\t * This is to help with clicking somewhere else and having the scrollbar react.\n\t */\n\tpublic delegateVerticalScrollbarMouseDown(browserEvent: IMouseEvent): void {\n\t\tthis._verticalScrollbar.delegateMouseDown(browserEvent);\n\t}\n\n\tpublic getScrollDimensions(): IScrollDimensions {\n\t\treturn this._scrollable.getScrollDimensions();\n\t}\n\n\tpublic setScrollDimensions(dimensions: INewScrollDimensions): void {\n\t\tthis._scrollable.setScrollDimensions(dimensions, false);\n\t}\n\n\t/**\n\t * Update the class name of the scrollable element.\n\t */\n\tpublic updateClassName(newClassName: string): void {\n\t\tthis._options.className = newClassName;\n\t\t// Defaults are different on Macs\n\t\tif (platform.isMacintosh) {\n\t\t\tthis._options.className += ' mac';\n\t\t}\n\t\tthis._domNode.className = 'monaco-scrollable-element ' + this._options.className;\n\t}\n\n\t/**\n\t * Update configuration options for the scrollbar.\n\t */\n\tpublic updateOptions(newOptions: ScrollableElementChangeOptions): void {\n\t\tif (typeof newOptions.handleMouseWheel !== 'undefined') {\n\t\t\tthis._options.handleMouseWheel = newOptions.handleMouseWheel;\n\t\t\tthis._setListeningToMouseWheel(this._options.handleMouseWheel);\n\t\t}\n\t\tif (typeof newOptions.mouseWheelScrollSensitivity !== 'undefined') {\n\t\t\tthis._options.mouseWheelScrollSensitivity = newOptions.mouseWheelScrollSensitivity;\n\t\t}\n\t\tif (typeof newOptions.fastScrollSensitivity !== 'undefined') {\n\t\t\tthis._options.fastScrollSensitivity = newOptions.fastScrollSensitivity;\n\t\t}\n\t\tif (typeof newOptions.scrollPredominantAxis !== 'undefined') {\n\t\t\tthis._options.scrollPredominantAxis = newOptions.scrollPredominantAxis;\n\t\t}\n\t\tif (typeof newOptions.horizontal !== 'undefined') {\n\t\t\tthis._options.horizontal = newOptions.horizontal;\n\t\t}\n\t\tif (typeof newOptions.vertical !== 'undefined') {\n\t\t\tthis._options.vertical = newOptions.vertical;\n\t\t}\n\t\tif (typeof newOptions.horizontalScrollbarSize !== 'undefined') {\n\t\t\tthis._options.horizontalScrollbarSize = newOptions.horizontalScrollbarSize;\n\t\t}\n\t\tif (typeof newOptions.verticalScrollbarSize !== 'undefined') {\n\t\t\tthis._options.verticalScrollbarSize = newOptions.verticalScrollbarSize;\n\t\t}\n\t\tif (typeof newOptions.scrollByPage !== 'undefined') {\n\t\t\tthis._options.scrollByPage = newOptions.scrollByPage;\n\t\t}\n\t\tthis._horizontalScrollbar.updateOptions(this._options);\n\t\tthis._verticalScrollbar.updateOptions(this._options);\n\n\t\tif (!this._options.lazyRender) {\n\t\t\tthis._render();\n\t\t}\n\t}\n\n\t// -------------------- mouse wheel scrolling --------------------\n\n\tprivate _setListeningToMouseWheel(shouldListen: boolean): void {\n\t\tconst isListening = (this._mouseWheelToDispose.length > 0);\n\n\t\tif (isListening === shouldListen) {\n\t\t\t// No change\n\t\t\treturn;\n\t\t}\n\n\t\t// Stop listening (if necessary)\n\t\tthis._mouseWheelToDispose = dispose(this._mouseWheelToDispose);\n\n\t\t// Start listening (if necessary)\n\t\tif (shouldListen) {\n\t\t\tconst onMouseWheel = (browserEvent: IMouseWheelEvent) => {\n\t\t\t\tthis._onMouseWheel(new StandardWheelEvent(browserEvent));\n\t\t\t};\n\n\t\t\tthis._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, dom.EventType.MOUSE_WHEEL, onMouseWheel, { passive: false }));\n\t\t}\n\t}\n\n\tprivate _onMouseWheel(e: StandardWheelEvent): void {\n\n\t\tconst classifier = MouseWheelClassifier.INSTANCE;\n\t\tif (SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED) {\n\t\t\tconst osZoomFactor = window.devicePixelRatio / getZoomFactor();\n\t\t\tif (platform.isWindows || platform.isLinux) {\n\t\t\t\t// On Windows and Linux, the incoming delta events are multiplied with the OS zoom factor.\n\t\t\t\t// The OS zoom factor can be reverse engineered by using the device pixel ratio and the configured zoom factor into account.\n\t\t\t\tclassifier.accept(Date.now(), e.deltaX / osZoomFactor, e.deltaY / osZoomFactor);\n\t\t\t} else {\n\t\t\t\tclassifier.accept(Date.now(), e.deltaX, e.deltaY);\n\t\t\t}\n\t\t}\n\n\t\t// console.log(`${Date.now()}, ${e.deltaY}, ${e.deltaX}`);\n\n\t\tlet didScroll = false;\n\n\t\tif (e.deltaY || e.deltaX) {\n\t\t\tlet deltaY = e.deltaY * this._options.mouseWheelScrollSensitivity;\n\t\t\tlet deltaX = e.deltaX * this._options.mouseWheelScrollSensitivity;\n\n\t\t\tif (this._options.scrollPredominantAxis) {\n\t\t\t\tif (Math.abs(deltaY) >= Math.abs(deltaX)) {\n\t\t\t\t\tdeltaX = 0;\n\t\t\t\t} else {\n\t\t\t\t\tdeltaY = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this._options.flipAxes) {\n\t\t\t\t[deltaY, deltaX] = [deltaX, deltaY];\n\t\t\t}\n\n\t\t\t// Convert vertical scrolling to horizontal if shift is held, this\n\t\t\t// is handled at a higher level on Mac\n\t\t\tconst shiftConvert = !platform.isMacintosh && e.browserEvent && e.browserEvent.shiftKey;\n\t\t\tif ((this._options.scrollYToX || shiftConvert) && !deltaX) {\n\t\t\t\tdeltaX = deltaY;\n\t\t\t\tdeltaY = 0;\n\t\t\t}\n\n\t\t\tif (e.browserEvent && e.browserEvent.altKey) {\n\t\t\t\t// fastScrolling\n\t\t\t\tdeltaX = deltaX * this._options.fastScrollSensitivity;\n\t\t\t\tdeltaY = deltaY * this._options.fastScrollSensitivity;\n\t\t\t}\n\n\t\t\tconst futureScrollPosition = this._scrollable.getFutureScrollPosition();\n\n\t\t\tlet desiredScrollPosition: INewScrollPosition = {};\n\t\t\tif (deltaY) {\n\t\t\t\tconst deltaScrollTop = SCROLL_WHEEL_SENSITIVITY * deltaY;\n\t\t\t\t// Here we convert values such as -0.3 to -1 or 0.3 to 1, otherwise low speed scrolling will never scroll\n\t\t\t\tconst desiredScrollTop = futureScrollPosition.scrollTop - (deltaScrollTop < 0 ? Math.floor(deltaScrollTop) : Math.ceil(deltaScrollTop));\n\t\t\t\tthis._verticalScrollbar.writeScrollPosition(desiredScrollPosition, desiredScrollTop);\n\t\t\t}\n\t\t\tif (deltaX) {\n\t\t\t\tconst deltaScrollLeft = SCROLL_WHEEL_SENSITIVITY * deltaX;\n\t\t\t\t// Here we convert values such as -0.3 to -1 or 0.3 to 1, otherwise low speed scrolling will never scroll\n\t\t\t\tconst desiredScrollLeft = futureScrollPosition.scrollLeft - (deltaScrollLeft < 0 ? Math.floor(deltaScrollLeft) : Math.ceil(deltaScrollLeft));\n\t\t\t\tthis._horizontalScrollbar.writeScrollPosition(desiredScrollPosition, desiredScrollLeft);\n\t\t\t}\n\n\t\t\t// Check that we are scrolling towards a location which is valid\n\t\t\tdesiredScrollPosition = this._scrollable.validateScrollPosition(desiredScrollPosition);\n\n\t\t\tif (futureScrollPosition.scrollLeft !== desiredScrollPosition.scrollLeft || futureScrollPosition.scrollTop !== desiredScrollPosition.scrollTop) {\n\n\t\t\t\tconst canPerformSmoothScroll = (\n\t\t\t\t\tSCROLL_WHEEL_SMOOTH_SCROLL_ENABLED\n\t\t\t\t\t&& this._options.mouseWheelSmoothScroll\n\t\t\t\t\t&& classifier.isPhysicalMouseWheel()\n\t\t\t\t);\n\n\t\t\t\tif (canPerformSmoothScroll) {\n\t\t\t\t\tthis._scrollable.setScrollPositionSmooth(desiredScrollPosition);\n\t\t\t\t} else {\n\t\t\t\t\tthis._scrollable.setScrollPositionNow(desiredScrollPosition);\n\t\t\t\t}\n\n\t\t\t\tdidScroll = true;\n\t\t\t}\n\t\t}\n\n\t\tlet consumeMouseWheel = didScroll;\n\t\tif (!consumeMouseWheel && this._options.alwaysConsumeMouseWheel) {\n\t\t\tconsumeMouseWheel = true;\n\t\t}\n\t\tif (!consumeMouseWheel && this._options.consumeMouseWheelIfScrollbarIsNeeded && (this._verticalScrollbar.isNeeded() || this._horizontalScrollbar.isNeeded())) {\n\t\t\tconsumeMouseWheel = true;\n\t\t}\n\n\t\tif (consumeMouseWheel) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t}\n\t}\n\n\tprivate _onDidScroll(e: ScrollEvent): void {\n\t\tthis._shouldRender = this._horizontalScrollbar.onDidScroll(e) || this._shouldRender;\n\t\tthis._shouldRender = this._verticalScrollbar.onDidScroll(e) || this._shouldRender;\n\n\t\tif (this._options.useShadows) {\n\t\t\tthis._shouldRender = true;\n\t\t}\n\n\t\tif (this._revealOnScroll) {\n\t\t\tthis._reveal();\n\t\t}\n\n\t\tif (!this._options.lazyRender) {\n\t\t\tthis._render();\n\t\t}\n\t}\n\n\t/**\n\t * Render / mutate the DOM now.\n\t * Should be used together with the ctor option `lazyRender`.\n\t */\n\tpublic renderNow(): void {\n\t\tif (!this._options.lazyRender) {\n\t\t\tthrow new Error('Please use `lazyRender` together with `renderNow`!');\n\t\t}\n\n\t\tthis._render();\n\t}\n\n\tprivate _render(): void {\n\t\tif (!this._shouldRender) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._shouldRender = false;\n\n\t\tthis._horizontalScrollbar.render();\n\t\tthis._verticalScrollbar.render();\n\n\t\tif (this._options.useShadows) {\n\t\t\tconst scrollState = this._scrollable.getCurrentScrollPosition();\n\t\t\tconst enableTop = scrollState.scrollTop > 0;\n\t\t\tconst enableLeft = scrollState.scrollLeft > 0;\n\n\t\t\tconst leftClassName = (enableLeft ? ' left' : '');\n\t\t\tconst topClassName = (enableTop ? ' top' : '');\n\t\t\tconst topLeftClassName = (enableLeft || enableTop ? ' top-left-corner' : '');\n\t\t\tthis._leftShadowDomNode!.setClassName(`shadow${leftClassName}`);\n\t\t\tthis._topShadowDomNode!.setClassName(`shadow${topClassName}`);\n\t\t\tthis._topLeftShadowDomNode!.setClassName(`shadow${topLeftClassName}${topClassName}${leftClassName}`);\n\t\t}\n\t}\n\n\t// -------------------- fade in / fade out --------------------\n\n\tprivate _onDragStart(): void {\n\t\tthis._isDragging = true;\n\t\tthis._reveal();\n\t}\n\n\tprivate _onDragEnd(): void {\n\t\tthis._isDragging = false;\n\t\tthis._hide();\n\t}\n\n\tprivate _onMouseOut(e: IMouseEvent): void {\n\t\tthis._mouseIsOver = false;\n\t\tthis._hide();\n\t}\n\n\tprivate _onMouseOver(e: IMouseEvent): void {\n\t\tthis._mouseIsOver = true;\n\t\tthis._reveal();\n\t}\n\n\tprivate _reveal(): void {\n\t\tthis._verticalScrollbar.beginReveal();\n\t\tthis._horizontalScrollbar.beginReveal();\n\t\tthis._scheduleHide();\n\t}\n\n\tprivate _hide(): void {\n\t\tif (!this._mouseIsOver && !this._isDragging) {\n\t\t\tthis._verticalScrollbar.beginHide();\n\t\t\tthis._horizontalScrollbar.beginHide();\n\t\t}\n\t}\n\n\tprivate _scheduleHide(): void {\n\t\tif (!this._mouseIsOver && !this._isDragging) {\n\t\t\tthis._hideTimeout.cancelAndSet(() => this._hide(), HIDE_TIMEOUT);\n\t\t}\n\t}\n}\n\nexport class ScrollableElement extends AbstractScrollableElement {\n\n\tconstructor(element: HTMLElement, options: ScrollableElementCreationOptions) {\n\t\toptions = options || {};\n\t\toptions.mouseWheelSmoothScroll = false;\n\t\tconst scrollable = new Scrollable({\n\t\t\tforceIntegerValues: true,\n\t\t\tsmoothScrollDuration: 0,\n\t\t\tscheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback)\n\t\t});\n\t\tsuper(element, options, scrollable);\n\t\tthis._register(scrollable);\n\t}\n\n\tpublic setScrollPosition(update: INewScrollPosition): void {\n\t\tthis._scrollable.setScrollPositionNow(update);\n\t}\n}\n\nexport class SmoothScrollableElement extends AbstractScrollableElement {\n\n\tconstructor(element: HTMLElement, options: ScrollableElementCreationOptions, scrollable: Scrollable) {\n\t\tsuper(element, options, scrollable);\n\t}\n\n\tpublic setScrollPosition(update: INewScrollPosition & { reuseAnimation?: boolean }): void {\n\t\tif (update.reuseAnimation) {\n\t\t\tthis._scrollable.setScrollPositionSmooth(update, update.reuseAnimation);\n\t\t} else {\n\t\t\tthis._scrollable.setScrollPositionNow(update);\n\t\t}\n\t}\n\n\tpublic getScrollPosition(): IScrollPosition {\n\t\treturn this._scrollable.getCurrentScrollPosition();\n\t}\n\n}\n\nexport class DomScrollableElement extends AbstractScrollableElement {\n\n\tprivate _element: HTMLElement;\n\n\tconstructor(element: HTMLElement, options: ScrollableElementCreationOptions) {\n\t\toptions = options || {};\n\t\toptions.mouseWheelSmoothScroll = false;\n\t\tconst scrollable = new Scrollable({\n\t\t\tforceIntegerValues: false, // See https://github.com/microsoft/vscode/issues/139877\n\t\t\tsmoothScrollDuration: 0,\n\t\t\tscheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback)\n\t\t});\n\t\tsuper(element, options, scrollable);\n\t\tthis._register(scrollable);\n\t\tthis._element = element;\n\t\tthis.onScroll((e) => {\n\t\t\tif (e.scrollTopChanged) {\n\t\t\t\tthis._element.scrollTop = e.scrollTop;\n\t\t\t}\n\t\t\tif (e.scrollLeftChanged) {\n\t\t\t\tthis._element.scrollLeft = e.scrollLeft;\n\t\t\t}\n\t\t});\n\t\tthis.scanDomNode();\n\t}\n\n\tpublic setScrollPosition(update: INewScrollPosition): void {\n\t\tthis._scrollable.setScrollPositionNow(update);\n\t}\n\n\tpublic getScrollPosition(): IScrollPosition {\n\t\treturn this._scrollable.getCurrentScrollPosition();\n\t}\n\n\tpublic scanDomNode(): void {\n\t\t// width, scrollLeft, scrollWidth, height, scrollTop, scrollHeight\n\t\tthis.setScrollDimensions({\n\t\t\twidth: this._element.clientWidth,\n\t\t\tscrollWidth: this._element.scrollWidth,\n\t\t\theight: this._element.clientHeight,\n\t\t\tscrollHeight: this._element.scrollHeight\n\t\t});\n\t\tthis.setScrollPosition({\n\t\t\tscrollLeft: this._element.scrollLeft,\n\t\t\tscrollTop: this._element.scrollTop,\n\t\t});\n\t}\n}\n\nfunction resolveOptions(opts: ScrollableElementCreationOptions): ScrollableElementResolvedOptions {\n\tconst result: ScrollableElementResolvedOptions = {\n\t\tlazyRender: (typeof opts.lazyRender !== 'undefined' ? opts.lazyRender : false),\n\t\tclassName: (typeof opts.className !== 'undefined' ? opts.className : ''),\n\t\tuseShadows: (typeof opts.useShadows !== 'undefined' ? opts.useShadows : true),\n\t\thandleMouseWheel: (typeof opts.handleMouseWheel !== 'undefined' ? opts.handleMouseWheel : true),\n\t\tflipAxes: (typeof opts.flipAxes !== 'undefined' ? opts.flipAxes : false),\n\t\tconsumeMouseWheelIfScrollbarIsNeeded: (typeof opts.consumeMouseWheelIfScrollbarIsNeeded !== 'undefined' ? opts.consumeMouseWheelIfScrollbarIsNeeded : false),\n\t\talwaysConsumeMouseWheel: (typeof opts.alwaysConsumeMouseWheel !== 'undefined' ? opts.alwaysConsumeMouseWheel : false),\n\t\tscrollYToX: (typeof opts.scrollYToX !== 'undefined' ? opts.scrollYToX : false),\n\t\tmouseWheelScrollSensitivity: (typeof opts.mouseWheelScrollSensitivity !== 'undefined' ? opts.mouseWheelScrollSensitivity : 1),\n\t\tfastScrollSensitivity: (typeof opts.fastScrollSensitivity !== 'undefined' ? opts.fastScrollSensitivity : 5),\n\t\tscrollPredominantAxis: (typeof opts.scrollPredominantAxis !== 'undefined' ? opts.scrollPredominantAxis : true),\n\t\tmouseWheelSmoothScroll: (typeof opts.mouseWheelSmoothScroll !== 'undefined' ? opts.mouseWheelSmoothScroll : true),\n\t\tarrowSize: (typeof opts.arrowSize !== 'undefined' ? opts.arrowSize : 11),\n\n\t\tlistenOnDomNode: (typeof opts.listenOnDomNode !== 'undefined' ? opts.listenOnDomNode : null),\n\n\t\thorizontal: (typeof opts.horizontal !== 'undefined' ? opts.horizontal : ScrollbarVisibility.Auto),\n\t\thorizontalScrollbarSize: (typeof opts.horizontalScrollbarSize !== 'undefined' ? opts.horizontalScrollbarSize : 10),\n\t\thorizontalSliderSize: (typeof opts.horizontalSliderSize !== 'undefined' ? opts.horizontalSliderSize : 0),\n\t\thorizontalHasArrows: (typeof opts.horizontalHasArrows !== 'undefined' ? opts.horizontalHasArrows : false),\n\n\t\tvertical: (typeof opts.vertical !== 'undefined' ? opts.vertical : ScrollbarVisibility.Auto),\n\t\tverticalScrollbarSize: (typeof opts.verticalScrollbarSize !== 'undefined' ? opts.verticalScrollbarSize : 10),\n\t\tverticalHasArrows: (typeof opts.verticalHasArrows !== 'undefined' ? opts.verticalHasArrows : false),\n\t\tverticalSliderSize: (typeof opts.verticalSliderSize !== 'undefined' ? opts.verticalSliderSize : 0),\n\n\t\tscrollByPage: (typeof opts.scrollByPage !== 'undefined' ? opts.scrollByPage : false)\n\t};\n\n\tresult.horizontalSliderSize = (typeof opts.horizontalSliderSize !== 'undefined' ? opts.horizontalSliderSize : result.horizontalScrollbarSize);\n\tresult.verticalSliderSize = (typeof opts.verticalSliderSize !== 'undefined' ? opts.verticalSliderSize : result.verticalScrollbarSize);\n\n\t// Defaults are different on Macs\n\tif (platform.isMacintosh) {\n\t\tresult.className += ' mac';\n\t}\n\n\treturn result;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport 'vs/css!./hover';\n\nconst $ = dom.$;\n\nexport const enum HoverPosition {\n\tLEFT, RIGHT, BELOW, ABOVE\n}\n\nexport class HoverWidget extends Disposable {\n\n\tpublic readonly containerDomNode: HTMLElement;\n\tpublic readonly contentsDomNode: HTMLElement;\n\tpublic readonly scrollbar: DomScrollableElement;\n\n\tconstructor() {\n\t\tsuper();\n\n\t\tthis.containerDomNode = document.createElement('div');\n\t\tthis.containerDomNode.className = 'monaco-hover';\n\t\tthis.containerDomNode.tabIndex = 0;\n\t\tthis.containerDomNode.setAttribute('role', 'tooltip');\n\n\t\tthis.contentsDomNode = document.createElement('div');\n\t\tthis.contentsDomNode.className = 'monaco-hover-content';\n\n\t\tthis.scrollbar = this._register(new DomScrollableElement(this.contentsDomNode, {\n\t\t\tconsumeMouseWheelIfScrollbarIsNeeded: true\n\t\t}));\n\t\tthis.containerDomNode.appendChild(this.scrollbar.getDomNode());\n\t}\n\n\tpublic onContentsChanged(): void {\n\t\tthis.scrollbar.scanDomNode();\n\t}\n}\n\nexport class HoverAction extends Disposable {\n\tpublic static render(parent: HTMLElement, actionOptions: { label: string, iconClass?: string, run: (target: HTMLElement) => void, commandId: string }, keybindingLabel: string | null) {\n\t\treturn new HoverAction(parent, actionOptions, keybindingLabel);\n\t}\n\n\tprivate readonly actionContainer: HTMLElement;\n\tprivate readonly action: HTMLElement;\n\n\tprivate constructor(parent: HTMLElement, actionOptions: { label: string, iconClass?: string, run: (target: HTMLElement) => void, commandId: string }, keybindingLabel: string | null) {\n\t\tsuper();\n\n\t\tthis.actionContainer = dom.append(parent, $('div.action-container'));\n\t\tthis.action = dom.append(this.actionContainer, $('a.action'));\n\t\tthis.action.setAttribute('role', 'button');\n\t\tif (actionOptions.iconClass) {\n\t\t\tdom.append(this.action, $(`span.icon.${actionOptions.iconClass}`));\n\t\t}\n\t\tconst label = dom.append(this.action, $('span'));\n\t\tlabel.textContent = keybindingLabel ? `${actionOptions.label} (${keybindingLabel})` : actionOptions.label;\n\n\t\tthis._register(dom.addDisposableListener(this.actionContainer, dom.EventType.MOUSE_DOWN, e => {\n\t\t\te.stopPropagation();\n\t\t\te.preventDefault();\n\t\t\tactionOptions.run(this.actionContainer);\n\t\t}));\n\n\t\tthis.setEnabled(true);\n\t}\n\n\tpublic setEnabled(enabled: boolean): void {\n\t\tif (enabled) {\n\t\t\tthis.actionContainer.classList.remove('disabled');\n\t\t\tthis.actionContainer.removeAttribute('aria-disabled');\n\t\t} else {\n\t\t\tthis.actionContainer.classList.add('disabled');\n\t\t\tthis.actionContainer.setAttribute('aria-disabled', 'true');\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { isFirefox } from 'vs/base/browser/browser';\nimport { DataTransfers, IDragAndDropData, StaticDND } from 'vs/base/browser/dnd';\nimport { $, addDisposableListener, animate, getContentHeight, getContentWidth, getTopLeftOffset, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';\nimport { DomEmitter } from 'vs/base/browser/event';\nimport { EventType as TouchEventType, Gesture, GestureEvent } from 'vs/base/browser/touch';\nimport { SmoothScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';\nimport { distinct, equals } from 'vs/base/common/arrays';\nimport { Delayer, disposableTimeout } from 'vs/base/common/async';\nimport { memoize } from 'vs/base/common/decorators';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable, DisposableStore, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { getOrDefault } from 'vs/base/common/objects';\nimport { IRange, Range } from 'vs/base/common/range';\nimport { INewScrollDimensions, Scrollable, ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';\nimport { ISpliceable } from 'vs/base/common/sequence';\nimport { IListDragAndDrop, IListDragEvent, IListGestureEvent, IListMouseEvent, IListRenderer, IListTouchEvent, IListVirtualDelegate, ListDragOverEffect } from 'vs/base/browser/ui/list/list';\nimport { RangeMap, shift } from 'vs/base/browser/ui/list/rangeMap';\nimport { IRow, RowCache } from 'vs/base/browser/ui/list/rowCache';\n\ninterface IItem {\n\treadonly id: string;\n\treadonly element: T;\n\treadonly templateId: string;\n\trow: IRow | null;\n\tsize: number;\n\twidth: number | undefined;\n\thasDynamicHeight: boolean;\n\tlastDynamicHeightWidth: number | undefined;\n\turi: string | undefined;\n\tdropTarget: boolean;\n\tdragStartDisposable: IDisposable;\n}\n\nexport interface IListViewDragAndDrop extends IListDragAndDrop {\n\tgetDragElements(element: T): T[];\n}\n\nexport interface IListViewAccessibilityProvider {\n\tgetSetSize?(element: T, index: number, listLength: number): number;\n\tgetPosInSet?(element: T, index: number): number;\n\tgetRole?(element: T): string | undefined;\n\tisChecked?(element: T): boolean | undefined;\n}\n\nexport interface IListViewOptionsUpdate {\n\treadonly additionalScrollHeight?: number;\n\treadonly smoothScrolling?: boolean;\n\treadonly horizontalScrolling?: boolean;\n\treadonly mouseWheelScrollSensitivity?: number;\n\treadonly fastScrollSensitivity?: number;\n}\n\nexport interface IListViewOptions extends IListViewOptionsUpdate {\n\treadonly dnd?: IListViewDragAndDrop;\n\treadonly useShadows?: boolean;\n\treadonly verticalScrollMode?: ScrollbarVisibility;\n\treadonly setRowLineHeight?: boolean;\n\treadonly setRowHeight?: boolean;\n\treadonly supportDynamicHeights?: boolean;\n\treadonly mouseSupport?: boolean;\n\treadonly accessibilityProvider?: IListViewAccessibilityProvider;\n\treadonly transformOptimization?: boolean;\n\treadonly alwaysConsumeMouseWheel?: boolean;\n}\n\nconst DefaultOptions = {\n\tuseShadows: true,\n\tverticalScrollMode: ScrollbarVisibility.Auto,\n\tsetRowLineHeight: true,\n\tsetRowHeight: true,\n\tsupportDynamicHeights: false,\n\tdnd: {\n\t\tgetDragElements(e: T) { return [e]; },\n\t\tgetDragURI() { return null; },\n\t\tonDragStart(): void { },\n\t\tonDragOver() { return false; },\n\t\tdrop() { }\n\t},\n\thorizontalScrolling: false,\n\ttransformOptimization: true,\n\talwaysConsumeMouseWheel: true,\n};\n\nexport class ElementsDragAndDropData implements IDragAndDropData {\n\n\treadonly elements: T[];\n\n\tconstructor(elements: T[]) {\n\t\tthis.elements = elements;\n\t}\n\n\tupdate(): void { }\n\n\tgetData(): T[] {\n\t\treturn this.elements;\n\t}\n}\n\nexport class ExternalElementsDragAndDropData implements IDragAndDropData {\n\n\treadonly elements: T[];\n\n\tconstructor(elements: T[]) {\n\t\tthis.elements = elements;\n\t}\n\n\tupdate(): void { }\n\n\tgetData(): T[] {\n\t\treturn this.elements;\n\t}\n}\n\nexport class NativeDragAndDropData implements IDragAndDropData {\n\n\treadonly types: any[];\n\treadonly files: any[];\n\n\tconstructor() {\n\t\tthis.types = [];\n\t\tthis.files = [];\n\t}\n\n\tupdate(dataTransfer: DataTransfer): void {\n\t\tif (dataTransfer.types) {\n\t\t\tthis.types.splice(0, this.types.length, ...dataTransfer.types);\n\t\t}\n\n\t\tif (dataTransfer.files) {\n\t\t\tthis.files.splice(0, this.files.length);\n\n\t\t\tfor (let i = 0; i < dataTransfer.files.length; i++) {\n\t\t\t\tconst file = dataTransfer.files.item(i);\n\n\t\t\t\tif (file && (file.size || file.type)) {\n\t\t\t\t\tthis.files.push(file);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tgetData(): any {\n\t\treturn {\n\t\t\ttypes: this.types,\n\t\t\tfiles: this.files\n\t\t};\n\t}\n}\n\nfunction equalsDragFeedback(f1: number[] | undefined, f2: number[] | undefined): boolean {\n\tif (Array.isArray(f1) && Array.isArray(f2)) {\n\t\treturn equals(f1, f2!);\n\t}\n\n\treturn f1 === f2;\n}\n\nclass ListViewAccessibilityProvider implements Required> {\n\n\treadonly getSetSize: (element: any, index: number, listLength: number) => number;\n\treadonly getPosInSet: (element: any, index: number) => number;\n\treadonly getRole: (element: T) => string | undefined;\n\treadonly isChecked: (element: T) => boolean | undefined;\n\n\tconstructor(accessibilityProvider?: IListViewAccessibilityProvider) {\n\t\tif (accessibilityProvider?.getSetSize) {\n\t\t\tthis.getSetSize = accessibilityProvider.getSetSize.bind(accessibilityProvider);\n\t\t} else {\n\t\t\tthis.getSetSize = (e, i, l) => l;\n\t\t}\n\n\t\tif (accessibilityProvider?.getPosInSet) {\n\t\t\tthis.getPosInSet = accessibilityProvider.getPosInSet.bind(accessibilityProvider);\n\t\t} else {\n\t\t\tthis.getPosInSet = (e, i) => i + 1;\n\t\t}\n\n\t\tif (accessibilityProvider?.getRole) {\n\t\t\tthis.getRole = accessibilityProvider.getRole.bind(accessibilityProvider);\n\t\t} else {\n\t\t\tthis.getRole = _ => 'listitem';\n\t\t}\n\n\t\tif (accessibilityProvider?.isChecked) {\n\t\t\tthis.isChecked = accessibilityProvider.isChecked.bind(accessibilityProvider);\n\t\t} else {\n\t\t\tthis.isChecked = _ => undefined;\n\t\t}\n\t}\n}\n\n/**\n * The {@link ListView} is a virtual scrolling engine.\n *\n * Given that it only renders elements within its viewport, it can hold large\n * collections of elements and stay very performant. The performance bottleneck\n * usually lies within the user's rendering code for each element.\n *\n * @remarks It is a low-level widget, not meant to be used directly. Refer to the\n * List widget instead.\n */\nexport class ListView implements ISpliceable, IDisposable {\n\n\tprivate static InstanceCount = 0;\n\treadonly domId = `list_id_${++ListView.InstanceCount}`;\n\n\treadonly domNode: HTMLElement;\n\n\tprivate items: IItem[];\n\tprivate itemId: number;\n\tprivate rangeMap: RangeMap;\n\tprivate cache: RowCache;\n\tprivate renderers = new Map>();\n\tprivate lastRenderTop: number;\n\tprivate lastRenderHeight: number;\n\tprivate renderWidth = 0;\n\tprivate rowsContainer: HTMLElement;\n\tprivate scrollable: Scrollable;\n\tprivate scrollableElement: SmoothScrollableElement;\n\tprivate _scrollHeight: number = 0;\n\tprivate scrollableElementUpdateDisposable: IDisposable | null = null;\n\tprivate scrollableElementWidthDelayer = new Delayer(50);\n\tprivate splicing = false;\n\tprivate dragOverAnimationDisposable: IDisposable | undefined;\n\tprivate dragOverAnimationStopDisposable: IDisposable = Disposable.None;\n\tprivate dragOverMouseY: number = 0;\n\tprivate setRowLineHeight: boolean;\n\tprivate setRowHeight: boolean;\n\tprivate supportDynamicHeights: boolean;\n\tprivate additionalScrollHeight: number;\n\tprivate accessibilityProvider: ListViewAccessibilityProvider;\n\tprivate scrollWidth: number | undefined;\n\n\tprivate dnd: IListViewDragAndDrop;\n\tprivate canDrop: boolean = false;\n\tprivate currentDragData: IDragAndDropData | undefined;\n\tprivate currentDragFeedback: number[] | undefined;\n\tprivate currentDragFeedbackDisposable: IDisposable = Disposable.None;\n\tprivate onDragLeaveTimeout: IDisposable = Disposable.None;\n\n\tprivate readonly disposables: DisposableStore = new DisposableStore();\n\n\tprivate readonly _onDidChangeContentHeight = new Emitter();\n\tget contentHeight(): number { return this.rangeMap.size; }\n\n\tprivate _horizontalScrolling: boolean = false;\n\tprivate get horizontalScrolling(): boolean { return this._horizontalScrolling; }\n\tprivate set horizontalScrolling(value: boolean) {\n\t\tif (value === this._horizontalScrolling) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (value && this.supportDynamicHeights) {\n\t\t\tthrow new Error('Horizontal scrolling and dynamic heights not supported simultaneously');\n\t\t}\n\n\t\tthis._horizontalScrolling = value;\n\t\tthis.domNode.classList.toggle('horizontal-scrolling', this._horizontalScrolling);\n\n\t\tif (this._horizontalScrolling) {\n\t\t\tfor (const item of this.items) {\n\t\t\t\tthis.measureItemWidth(item);\n\t\t\t}\n\n\t\t\tthis.updateScrollWidth();\n\t\t\tthis.scrollableElement.setScrollDimensions({ width: getContentWidth(this.domNode) });\n\t\t\tthis.rowsContainer.style.width = `${Math.max(this.scrollWidth || 0, this.renderWidth)}px`;\n\t\t} else {\n\t\t\tthis.scrollableElementWidthDelayer.cancel();\n\t\t\tthis.scrollableElement.setScrollDimensions({ width: this.renderWidth, scrollWidth: this.renderWidth });\n\t\t\tthis.rowsContainer.style.width = '';\n\t\t}\n\t}\n\n\tconstructor(\n\t\tcontainer: HTMLElement,\n\t\tprivate virtualDelegate: IListVirtualDelegate,\n\t\trenderers: IListRenderer[],\n\t\toptions: IListViewOptions = DefaultOptions as IListViewOptions\n\t) {\n\t\tif (options.horizontalScrolling && options.supportDynamicHeights) {\n\t\t\tthrow new Error('Horizontal scrolling and dynamic heights not supported simultaneously');\n\t\t}\n\n\t\tthis.items = [];\n\t\tthis.itemId = 0;\n\t\tthis.rangeMap = new RangeMap();\n\n\t\tfor (const renderer of renderers) {\n\t\t\tthis.renderers.set(renderer.templateId, renderer);\n\t\t}\n\n\t\tthis.cache = this.disposables.add(new RowCache(this.renderers));\n\n\t\tthis.lastRenderTop = 0;\n\t\tthis.lastRenderHeight = 0;\n\n\t\tthis.domNode = document.createElement('div');\n\t\tthis.domNode.className = 'monaco-list';\n\n\t\tthis.domNode.classList.add(this.domId);\n\t\tthis.domNode.tabIndex = 0;\n\n\t\tthis.domNode.classList.toggle('mouse-support', typeof options.mouseSupport === 'boolean' ? options.mouseSupport : true);\n\n\t\tthis._horizontalScrolling = getOrDefault(options, o => o.horizontalScrolling, DefaultOptions.horizontalScrolling);\n\t\tthis.domNode.classList.toggle('horizontal-scrolling', this._horizontalScrolling);\n\n\t\tthis.additionalScrollHeight = typeof options.additionalScrollHeight === 'undefined' ? 0 : options.additionalScrollHeight;\n\n\t\tthis.accessibilityProvider = new ListViewAccessibilityProvider(options.accessibilityProvider);\n\n\t\tthis.rowsContainer = document.createElement('div');\n\t\tthis.rowsContainer.className = 'monaco-list-rows';\n\n\t\tconst transformOptimization = getOrDefault(options, o => o.transformOptimization, DefaultOptions.transformOptimization);\n\t\tif (transformOptimization) {\n\t\t\tthis.rowsContainer.style.transform = 'translate3d(0px, 0px, 0px)';\n\t\t}\n\n\t\tthis.disposables.add(Gesture.addTarget(this.rowsContainer));\n\n\t\tthis.scrollable = new Scrollable({\n\t\t\tforceIntegerValues: true,\n\t\t\tsmoothScrollDuration: getOrDefault(options, o => o.smoothScrolling, false) ? 125 : 0,\n\t\t\tscheduleAtNextAnimationFrame: cb => scheduleAtNextAnimationFrame(cb)\n\t\t});\n\t\tthis.scrollableElement = this.disposables.add(new SmoothScrollableElement(this.rowsContainer, {\n\t\t\talwaysConsumeMouseWheel: getOrDefault(options, o => o.alwaysConsumeMouseWheel, DefaultOptions.alwaysConsumeMouseWheel),\n\t\t\thorizontal: ScrollbarVisibility.Auto,\n\t\t\tvertical: getOrDefault(options, o => o.verticalScrollMode, DefaultOptions.verticalScrollMode),\n\t\t\tuseShadows: getOrDefault(options, o => o.useShadows, DefaultOptions.useShadows),\n\t\t\tmouseWheelScrollSensitivity: options.mouseWheelScrollSensitivity,\n\t\t\tfastScrollSensitivity: options.fastScrollSensitivity\n\t\t}, this.scrollable));\n\n\t\tthis.domNode.appendChild(this.scrollableElement.getDomNode());\n\t\tcontainer.appendChild(this.domNode);\n\n\t\tthis.scrollableElement.onScroll(this.onScroll, this, this.disposables);\n\t\tthis.disposables.add(addDisposableListener(this.rowsContainer, TouchEventType.Change, e => this.onTouchChange(e as GestureEvent)));\n\n\t\t// Prevent the monaco-scrollable-element from scrolling\n\t\t// https://github.com/microsoft/vscode/issues/44181\n\t\tthis.disposables.add(addDisposableListener(this.scrollableElement.getDomNode(), 'scroll', e => (e.target as HTMLElement).scrollTop = 0));\n\n\t\tthis.disposables.add(addDisposableListener(this.domNode, 'dragover', e => this.onDragOver(this.toDragEvent(e))));\n\t\tthis.disposables.add(addDisposableListener(this.domNode, 'drop', e => this.onDrop(this.toDragEvent(e))));\n\t\tthis.disposables.add(addDisposableListener(this.domNode, 'dragleave', e => this.onDragLeave(this.toDragEvent(e))));\n\t\tthis.disposables.add(addDisposableListener(this.domNode, 'dragend', e => this.onDragEnd(e)));\n\n\t\tthis.setRowLineHeight = getOrDefault(options, o => o.setRowLineHeight, DefaultOptions.setRowLineHeight);\n\t\tthis.setRowHeight = getOrDefault(options, o => o.setRowHeight, DefaultOptions.setRowHeight);\n\t\tthis.supportDynamicHeights = getOrDefault(options, o => o.supportDynamicHeights, DefaultOptions.supportDynamicHeights);\n\t\tthis.dnd = getOrDefault, IListViewDragAndDrop>(options, o => o.dnd, DefaultOptions.dnd);\n\n\t\tthis.layout();\n\t}\n\n\tupdateOptions(options: IListViewOptionsUpdate) {\n\t\tif (options.additionalScrollHeight !== undefined) {\n\t\t\tthis.additionalScrollHeight = options.additionalScrollHeight;\n\t\t\tthis.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight });\n\t\t}\n\n\t\tif (options.smoothScrolling !== undefined) {\n\t\t\tthis.scrollable.setSmoothScrollDuration(options.smoothScrolling ? 125 : 0);\n\t\t}\n\n\t\tif (options.horizontalScrolling !== undefined) {\n\t\t\tthis.horizontalScrolling = options.horizontalScrolling;\n\t\t}\n\n\t\tif (options.mouseWheelScrollSensitivity !== undefined) {\n\t\t\tthis.scrollableElement.updateOptions({ mouseWheelScrollSensitivity: options.mouseWheelScrollSensitivity });\n\t\t}\n\n\t\tif (options.fastScrollSensitivity !== undefined) {\n\t\t\tthis.scrollableElement.updateOptions({ fastScrollSensitivity: options.fastScrollSensitivity });\n\t\t}\n\t}\n\n\tsplice(start: number, deleteCount: number, elements: T[] = []): T[] {\n\t\tif (this.splicing) {\n\t\t\tthrow new Error('Can\\'t run recursive splices.');\n\t\t}\n\n\t\tthis.splicing = true;\n\n\t\ttry {\n\t\t\treturn this._splice(start, deleteCount, elements);\n\t\t} finally {\n\t\t\tthis.splicing = false;\n\t\t\tthis._onDidChangeContentHeight.fire(this.contentHeight);\n\t\t}\n\t}\n\n\tprivate _splice(start: number, deleteCount: number, elements: T[] = []): T[] {\n\t\tconst previousRenderRange = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight);\n\t\tconst deleteRange = { start, end: start + deleteCount };\n\t\tconst removeRange = Range.intersect(previousRenderRange, deleteRange);\n\n\t\t// try to reuse rows, avoid removing them from DOM\n\t\tconst rowsToDispose = new Map();\n\t\tfor (let i = removeRange.end - 1; i >= removeRange.start; i--) {\n\t\t\tconst item = this.items[i];\n\t\t\titem.dragStartDisposable.dispose();\n\n\t\t\tif (item.row) {\n\t\t\t\tlet rows = rowsToDispose.get(item.templateId);\n\n\t\t\t\tif (!rows) {\n\t\t\t\t\trows = [];\n\t\t\t\t\trowsToDispose.set(item.templateId, rows);\n\t\t\t\t}\n\n\t\t\t\tconst renderer = this.renderers.get(item.templateId);\n\n\t\t\t\tif (renderer && renderer.disposeElement) {\n\t\t\t\t\trenderer.disposeElement(item.element, i, item.row.templateData, item.size);\n\t\t\t\t}\n\n\t\t\t\trows.push(item.row);\n\t\t\t}\n\n\t\t\titem.row = null;\n\t\t}\n\n\t\tconst previousRestRange: IRange = { start: start + deleteCount, end: this.items.length };\n\t\tconst previousRenderedRestRange = Range.intersect(previousRestRange, previousRenderRange);\n\t\tconst previousUnrenderedRestRanges = Range.relativeComplement(previousRestRange, previousRenderRange);\n\n\t\tconst inserted = elements.map>(element => ({\n\t\t\tid: String(this.itemId++),\n\t\t\telement,\n\t\t\ttemplateId: this.virtualDelegate.getTemplateId(element),\n\t\t\tsize: this.virtualDelegate.getHeight(element),\n\t\t\twidth: undefined,\n\t\t\thasDynamicHeight: !!this.virtualDelegate.hasDynamicHeight && this.virtualDelegate.hasDynamicHeight(element),\n\t\t\tlastDynamicHeightWidth: undefined,\n\t\t\trow: null,\n\t\t\turi: undefined,\n\t\t\tdropTarget: false,\n\t\t\tdragStartDisposable: Disposable.None\n\t\t}));\n\n\t\tlet deleted: IItem[];\n\n\t\t// TODO@joao: improve this optimization to catch even more cases\n\t\tif (start === 0 && deleteCount >= this.items.length) {\n\t\t\tthis.rangeMap = new RangeMap();\n\t\t\tthis.rangeMap.splice(0, 0, inserted);\n\t\t\tdeleted = this.items;\n\t\t\tthis.items = inserted;\n\t\t} else {\n\t\t\tthis.rangeMap.splice(start, deleteCount, inserted);\n\t\t\tdeleted = this.items.splice(start, deleteCount, ...inserted);\n\t\t}\n\n\t\tconst delta = elements.length - deleteCount;\n\t\tconst renderRange = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight);\n\t\tconst renderedRestRange = shift(previousRenderedRestRange, delta);\n\t\tconst updateRange = Range.intersect(renderRange, renderedRestRange);\n\n\t\tfor (let i = updateRange.start; i < updateRange.end; i++) {\n\t\t\tthis.updateItemInDOM(this.items[i], i);\n\t\t}\n\n\t\tconst removeRanges = Range.relativeComplement(renderedRestRange, renderRange);\n\n\t\tfor (const range of removeRanges) {\n\t\t\tfor (let i = range.start; i < range.end; i++) {\n\t\t\t\tthis.removeItemFromDOM(i);\n\t\t\t}\n\t\t}\n\n\t\tconst unrenderedRestRanges = previousUnrenderedRestRanges.map(r => shift(r, delta));\n\t\tconst elementsRange = { start, end: start + elements.length };\n\t\tconst insertRanges = [elementsRange, ...unrenderedRestRanges].map(r => Range.intersect(renderRange, r));\n\t\tconst beforeElement = this.getNextToLastElement(insertRanges);\n\n\t\tfor (const range of insertRanges) {\n\t\t\tfor (let i = range.start; i < range.end; i++) {\n\t\t\t\tconst item = this.items[i];\n\t\t\t\tconst rows = rowsToDispose.get(item.templateId);\n\t\t\t\tconst row = rows?.pop();\n\t\t\t\tthis.insertItemInDOM(i, beforeElement, row);\n\t\t\t}\n\t\t}\n\n\t\tfor (const rows of rowsToDispose.values()) {\n\t\t\tfor (const row of rows) {\n\t\t\t\tthis.cache.release(row);\n\t\t\t}\n\t\t}\n\n\t\tthis.eventuallyUpdateScrollDimensions();\n\n\t\tif (this.supportDynamicHeights) {\n\t\t\tthis._rerender(this.scrollTop, this.renderHeight);\n\t\t}\n\n\t\treturn deleted.map(i => i.element);\n\t}\n\n\tprivate eventuallyUpdateScrollDimensions(): void {\n\t\tthis._scrollHeight = this.contentHeight;\n\t\tthis.rowsContainer.style.height = `${this._scrollHeight}px`;\n\n\t\tif (!this.scrollableElementUpdateDisposable) {\n\t\t\tthis.scrollableElementUpdateDisposable = scheduleAtNextAnimationFrame(() => {\n\t\t\t\tthis.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight });\n\t\t\t\tthis.updateScrollWidth();\n\t\t\t\tthis.scrollableElementUpdateDisposable = null;\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate eventuallyUpdateScrollWidth(): void {\n\t\tif (!this.horizontalScrolling) {\n\t\t\tthis.scrollableElementWidthDelayer.cancel();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.scrollableElementWidthDelayer.trigger(() => this.updateScrollWidth());\n\t}\n\n\tprivate updateScrollWidth(): void {\n\t\tif (!this.horizontalScrolling) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet scrollWidth = 0;\n\n\t\tfor (const item of this.items) {\n\t\t\tif (typeof item.width !== 'undefined') {\n\t\t\t\tscrollWidth = Math.max(scrollWidth, item.width);\n\t\t\t}\n\t\t}\n\n\t\tthis.scrollWidth = scrollWidth;\n\t\tthis.scrollableElement.setScrollDimensions({ scrollWidth: scrollWidth === 0 ? 0 : (scrollWidth + 10) });\n\t}\n\n\trerender(): void {\n\t\tif (!this.supportDynamicHeights) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const item of this.items) {\n\t\t\titem.lastDynamicHeightWidth = undefined;\n\t\t}\n\n\t\tthis._rerender(this.lastRenderTop, this.lastRenderHeight);\n\t}\n\n\tget length(): number {\n\t\treturn this.items.length;\n\t}\n\n\tget renderHeight(): number {\n\t\tconst scrollDimensions = this.scrollableElement.getScrollDimensions();\n\t\treturn scrollDimensions.height;\n\t}\n\n\telement(index: number): T {\n\t\treturn this.items[index].element;\n\t}\n\n\tdomElement(index: number): HTMLElement | null {\n\t\tconst row = this.items[index].row;\n\t\treturn row && row.domNode;\n\t}\n\n\telementHeight(index: number): number {\n\t\treturn this.items[index].size;\n\t}\n\n\telementTop(index: number): number {\n\t\treturn this.rangeMap.positionAt(index);\n\t}\n\n\tindexAt(position: number): number {\n\t\treturn this.rangeMap.indexAt(position);\n\t}\n\n\tindexAfter(position: number): number {\n\t\treturn this.rangeMap.indexAfter(position);\n\t}\n\n\tlayout(height?: number, width?: number): void {\n\t\tlet scrollDimensions: INewScrollDimensions = {\n\t\t\theight: typeof height === 'number' ? height : getContentHeight(this.domNode)\n\t\t};\n\n\t\tif (this.scrollableElementUpdateDisposable) {\n\t\t\tthis.scrollableElementUpdateDisposable.dispose();\n\t\t\tthis.scrollableElementUpdateDisposable = null;\n\t\t\tscrollDimensions.scrollHeight = this.scrollHeight;\n\t\t}\n\n\t\tthis.scrollableElement.setScrollDimensions(scrollDimensions);\n\n\t\tif (typeof width !== 'undefined') {\n\t\t\tthis.renderWidth = width;\n\n\t\t\tif (this.supportDynamicHeights) {\n\t\t\t\tthis._rerender(this.scrollTop, this.renderHeight);\n\t\t\t}\n\t\t}\n\n\t\tif (this.horizontalScrolling) {\n\t\t\tthis.scrollableElement.setScrollDimensions({\n\t\t\t\twidth: typeof width === 'number' ? width : getContentWidth(this.domNode)\n\t\t\t});\n\t\t}\n\t}\n\n\t// Render\n\n\tprivate render(previousRenderRange: IRange, renderTop: number, renderHeight: number, renderLeft: number | undefined, scrollWidth: number | undefined, updateItemsInDOM: boolean = false): void {\n\t\tconst renderRange = this.getRenderRange(renderTop, renderHeight);\n\n\t\tconst rangesToInsert = Range.relativeComplement(renderRange, previousRenderRange);\n\t\tconst rangesToRemove = Range.relativeComplement(previousRenderRange, renderRange);\n\t\tconst beforeElement = this.getNextToLastElement(rangesToInsert);\n\n\t\tif (updateItemsInDOM) {\n\t\t\tconst rangesToUpdate = Range.intersect(previousRenderRange, renderRange);\n\n\t\t\tfor (let i = rangesToUpdate.start; i < rangesToUpdate.end; i++) {\n\t\t\t\tthis.updateItemInDOM(this.items[i], i);\n\t\t\t}\n\t\t}\n\n\t\tfor (const range of rangesToInsert) {\n\t\t\tfor (let i = range.start; i < range.end; i++) {\n\t\t\t\tthis.insertItemInDOM(i, beforeElement);\n\t\t\t}\n\t\t}\n\n\t\tfor (const range of rangesToRemove) {\n\t\t\tfor (let i = range.start; i < range.end; i++) {\n\t\t\t\tthis.removeItemFromDOM(i);\n\t\t\t}\n\t\t}\n\n\t\tif (renderLeft !== undefined) {\n\t\t\tthis.rowsContainer.style.left = `-${renderLeft}px`;\n\t\t}\n\n\t\tthis.rowsContainer.style.top = `-${renderTop}px`;\n\n\t\tif (this.horizontalScrolling && scrollWidth !== undefined) {\n\t\t\tthis.rowsContainer.style.width = `${Math.max(scrollWidth, this.renderWidth)}px`;\n\t\t}\n\n\t\tthis.lastRenderTop = renderTop;\n\t\tthis.lastRenderHeight = renderHeight;\n\t}\n\n\t// DOM operations\n\n\tprivate insertItemInDOM(index: number, beforeElement: HTMLElement | null, row?: IRow): void {\n\t\tconst item = this.items[index];\n\n\t\tif (!item.row) {\n\t\t\titem.row = row ?? this.cache.alloc(item.templateId);\n\t\t}\n\n\t\tconst role = this.accessibilityProvider.getRole(item.element) || 'listitem';\n\t\titem.row.domNode.setAttribute('role', role);\n\n\t\tconst checked = this.accessibilityProvider.isChecked(item.element);\n\t\tif (typeof checked !== 'undefined') {\n\t\t\titem.row.domNode.setAttribute('aria-checked', String(!!checked));\n\t\t}\n\n\t\tif (!item.row.domNode.parentElement) {\n\t\t\tif (beforeElement) {\n\t\t\t\tthis.rowsContainer.insertBefore(item.row.domNode, beforeElement);\n\t\t\t} else {\n\t\t\t\tthis.rowsContainer.appendChild(item.row.domNode);\n\t\t\t}\n\t\t}\n\n\t\tthis.updateItemInDOM(item, index);\n\n\t\tconst renderer = this.renderers.get(item.templateId);\n\n\t\tif (!renderer) {\n\t\t\tthrow new Error(`No renderer found for template id ${item.templateId}`);\n\t\t}\n\n\t\tif (renderer) {\n\t\t\trenderer.renderElement(item.element, index, item.row.templateData, item.size);\n\t\t}\n\n\t\tconst uri = this.dnd.getDragURI(item.element);\n\t\titem.dragStartDisposable.dispose();\n\t\titem.row.domNode.draggable = !!uri;\n\n\t\tif (uri) {\n\t\t\titem.dragStartDisposable = addDisposableListener(item.row.domNode, 'dragstart', event => this.onDragStart(item.element, uri, event));\n\t\t}\n\n\t\tif (this.horizontalScrolling) {\n\t\t\tthis.measureItemWidth(item);\n\t\t\tthis.eventuallyUpdateScrollWidth();\n\t\t}\n\t}\n\n\tprivate measureItemWidth(item: IItem): void {\n\t\tif (!item.row || !item.row.domNode) {\n\t\t\treturn;\n\t\t}\n\n\t\titem.row.domNode.style.width = isFirefox ? '-moz-fit-content' : 'fit-content';\n\t\titem.width = getContentWidth(item.row.domNode);\n\t\tconst style = window.getComputedStyle(item.row.domNode);\n\n\t\tif (style.paddingLeft) {\n\t\t\titem.width += parseFloat(style.paddingLeft);\n\t\t}\n\n\t\tif (style.paddingRight) {\n\t\t\titem.width += parseFloat(style.paddingRight);\n\t\t}\n\n\t\titem.row.domNode.style.width = '';\n\t}\n\n\tprivate updateItemInDOM(item: IItem, index: number): void {\n\t\titem.row!.domNode.style.top = `${this.elementTop(index)}px`;\n\n\t\tif (this.setRowHeight) {\n\t\t\titem.row!.domNode.style.height = `${item.size}px`;\n\t\t}\n\n\t\tif (this.setRowLineHeight) {\n\t\t\titem.row!.domNode.style.lineHeight = `${item.size}px`;\n\t\t}\n\n\t\titem.row!.domNode.setAttribute('data-index', `${index}`);\n\t\titem.row!.domNode.setAttribute('data-last-element', index === this.length - 1 ? 'true' : 'false');\n\t\titem.row!.domNode.setAttribute('data-parity', index % 2 === 0 ? 'even' : 'odd');\n\t\titem.row!.domNode.setAttribute('aria-setsize', String(this.accessibilityProvider.getSetSize(item.element, index, this.length)));\n\t\titem.row!.domNode.setAttribute('aria-posinset', String(this.accessibilityProvider.getPosInSet(item.element, index)));\n\t\titem.row!.domNode.setAttribute('id', this.getElementDomId(index));\n\n\t\titem.row!.domNode.classList.toggle('drop-target', item.dropTarget);\n\t}\n\n\tprivate removeItemFromDOM(index: number): void {\n\t\tconst item = this.items[index];\n\t\titem.dragStartDisposable.dispose();\n\n\t\tif (item.row) {\n\t\t\tconst renderer = this.renderers.get(item.templateId);\n\n\t\t\tif (renderer && renderer.disposeElement) {\n\t\t\t\trenderer.disposeElement(item.element, index, item.row.templateData, item.size);\n\t\t\t}\n\n\t\t\tthis.cache.release(item.row);\n\t\t\titem.row = null;\n\t\t}\n\n\t\tif (this.horizontalScrolling) {\n\t\t\tthis.eventuallyUpdateScrollWidth();\n\t\t}\n\t}\n\n\tgetScrollTop(): number {\n\t\tconst scrollPosition = this.scrollableElement.getScrollPosition();\n\t\treturn scrollPosition.scrollTop;\n\t}\n\n\tsetScrollTop(scrollTop: number, reuseAnimation?: boolean): void {\n\t\tif (this.scrollableElementUpdateDisposable) {\n\t\t\tthis.scrollableElementUpdateDisposable.dispose();\n\t\t\tthis.scrollableElementUpdateDisposable = null;\n\t\t\tthis.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight });\n\t\t}\n\n\t\tthis.scrollableElement.setScrollPosition({ scrollTop, reuseAnimation });\n\t}\n\n\n\tget scrollTop(): number {\n\t\treturn this.getScrollTop();\n\t}\n\n\tset scrollTop(scrollTop: number) {\n\t\tthis.setScrollTop(scrollTop);\n\t}\n\n\tget scrollHeight(): number {\n\t\treturn this._scrollHeight + (this.horizontalScrolling ? 10 : 0) + this.additionalScrollHeight;\n\t}\n\n\t// Events\n\n\t@memoize get onMouseClick(): Event> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'click')).event, e => this.toMouseEvent(e)); }\n\t@memoize get onMouseDblClick(): Event> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'dblclick')).event, e => this.toMouseEvent(e)); }\n\t@memoize get onMouseMiddleClick(): Event> { return Event.filter(Event.map(this.disposables.add(new DomEmitter(this.domNode, 'auxclick')).event, e => this.toMouseEvent(e as MouseEvent)), e => e.browserEvent.button === 1); }\n\t@memoize get onMouseDown(): Event> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'mousedown')).event, e => this.toMouseEvent(e)); }\n\t@memoize get onContextMenu(): Event | IListGestureEvent> { return Event.any(Event.map(this.disposables.add(new DomEmitter(this.domNode, 'contextmenu')).event, e => this.toMouseEvent(e)), Event.map(this.disposables.add(new DomEmitter(this.domNode, TouchEventType.Contextmenu)).event as Event, e => this.toGestureEvent(e))); }\n\t@memoize get onTouchStart(): Event> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'touchstart')).event, e => this.toTouchEvent(e)); }\n\t@memoize get onTap(): Event> { return Event.map(this.disposables.add(new DomEmitter(this.rowsContainer, TouchEventType.Tap)).event, e => this.toGestureEvent(e as GestureEvent)); }\n\n\tprivate toMouseEvent(browserEvent: MouseEvent): IListMouseEvent {\n\t\tconst index = this.getItemIndexFromEventTarget(browserEvent.target || null);\n\t\tconst item = typeof index === 'undefined' ? undefined : this.items[index];\n\t\tconst element = item && item.element;\n\t\treturn { browserEvent, index, element };\n\t}\n\n\tprivate toTouchEvent(browserEvent: TouchEvent): IListTouchEvent {\n\t\tconst index = this.getItemIndexFromEventTarget(browserEvent.target || null);\n\t\tconst item = typeof index === 'undefined' ? undefined : this.items[index];\n\t\tconst element = item && item.element;\n\t\treturn { browserEvent, index, element };\n\t}\n\n\tprivate toGestureEvent(browserEvent: GestureEvent): IListGestureEvent {\n\t\tconst index = this.getItemIndexFromEventTarget(browserEvent.initialTarget || null);\n\t\tconst item = typeof index === 'undefined' ? undefined : this.items[index];\n\t\tconst element = item && item.element;\n\t\treturn { browserEvent, index, element };\n\t}\n\n\tprivate toDragEvent(browserEvent: DragEvent): IListDragEvent {\n\t\tconst index = this.getItemIndexFromEventTarget(browserEvent.target || null);\n\t\tconst item = typeof index === 'undefined' ? undefined : this.items[index];\n\t\tconst element = item && item.element;\n\t\treturn { browserEvent, index, element };\n\t}\n\n\tprivate onScroll(e: ScrollEvent): void {\n\t\ttry {\n\t\t\tconst previousRenderRange = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight);\n\t\t\tthis.render(previousRenderRange, e.scrollTop, e.height, e.scrollLeft, e.scrollWidth);\n\n\t\t\tif (this.supportDynamicHeights) {\n\t\t\t\tthis._rerender(e.scrollTop, e.height, e.inSmoothScrolling);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error('Got bad scroll event:', e);\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tprivate onTouchChange(event: GestureEvent): void {\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tthis.scrollTop -= event.translationY;\n\t}\n\n\t// DND\n\n\tprivate onDragStart(element: T, uri: string, event: DragEvent): void {\n\t\tif (!event.dataTransfer) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst elements = this.dnd.getDragElements(element);\n\n\t\tevent.dataTransfer.effectAllowed = 'copyMove';\n\t\tevent.dataTransfer.setData(DataTransfers.TEXT, uri);\n\n\t\tif (event.dataTransfer.setDragImage) {\n\t\t\tlet label: string | undefined;\n\n\t\t\tif (this.dnd.getDragLabel) {\n\t\t\t\tlabel = this.dnd.getDragLabel(elements, event);\n\t\t\t}\n\n\t\t\tif (typeof label === 'undefined') {\n\t\t\t\tlabel = String(elements.length);\n\t\t\t}\n\n\t\t\tconst dragImage = $('.monaco-drag-image');\n\t\t\tdragImage.textContent = label;\n\t\t\tdocument.body.appendChild(dragImage);\n\t\t\tevent.dataTransfer.setDragImage(dragImage, -10, -10);\n\t\t\tsetTimeout(() => document.body.removeChild(dragImage), 0);\n\t\t}\n\n\t\tthis.currentDragData = new ElementsDragAndDropData(elements);\n\t\tStaticDND.CurrentDragAndDropData = new ExternalElementsDragAndDropData(elements);\n\n\t\tif (this.dnd.onDragStart) {\n\t\t\tthis.dnd.onDragStart(this.currentDragData, event);\n\t\t}\n\t}\n\n\tprivate onDragOver(event: IListDragEvent): boolean {\n\t\tevent.browserEvent.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)\n\n\t\tthis.onDragLeaveTimeout.dispose();\n\n\t\tif (StaticDND.CurrentDragAndDropData && StaticDND.CurrentDragAndDropData.getData() === 'vscode-ui') {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.setupDragAndDropScrollTopAnimation(event.browserEvent);\n\n\t\tif (!event.browserEvent.dataTransfer) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Drag over from outside\n\t\tif (!this.currentDragData) {\n\t\t\tif (StaticDND.CurrentDragAndDropData) {\n\t\t\t\t// Drag over from another list\n\t\t\t\tthis.currentDragData = StaticDND.CurrentDragAndDropData;\n\n\t\t\t} else {\n\t\t\t\t// Drag over from the desktop\n\t\t\t\tif (!event.browserEvent.dataTransfer.types) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tthis.currentDragData = new NativeDragAndDropData();\n\t\t\t}\n\t\t}\n\n\t\tconst result = this.dnd.onDragOver(this.currentDragData, event.element, event.index, event.browserEvent);\n\t\tthis.canDrop = typeof result === 'boolean' ? result : result.accept;\n\n\t\tif (!this.canDrop) {\n\t\t\tthis.currentDragFeedback = undefined;\n\t\t\tthis.currentDragFeedbackDisposable.dispose();\n\t\t\treturn false;\n\t\t}\n\n\t\tevent.browserEvent.dataTransfer.dropEffect = (typeof result !== 'boolean' && result.effect === ListDragOverEffect.Copy) ? 'copy' : 'move';\n\n\t\tlet feedback: number[];\n\n\t\tif (typeof result !== 'boolean' && result.feedback) {\n\t\t\tfeedback = result.feedback;\n\t\t} else {\n\t\t\tif (typeof event.index === 'undefined') {\n\t\t\t\tfeedback = [-1];\n\t\t\t} else {\n\t\t\t\tfeedback = [event.index];\n\t\t\t}\n\t\t}\n\n\t\t// sanitize feedback list\n\t\tfeedback = distinct(feedback).filter(i => i >= -1 && i < this.length).sort((a, b) => a - b);\n\t\tfeedback = feedback[0] === -1 ? [-1] : feedback;\n\n\t\tif (equalsDragFeedback(this.currentDragFeedback, feedback)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tthis.currentDragFeedback = feedback;\n\t\tthis.currentDragFeedbackDisposable.dispose();\n\n\t\tif (feedback[0] === -1) { // entire list feedback\n\t\t\tthis.domNode.classList.add('drop-target');\n\t\t\tthis.rowsContainer.classList.add('drop-target');\n\t\t\tthis.currentDragFeedbackDisposable = toDisposable(() => {\n\t\t\t\tthis.domNode.classList.remove('drop-target');\n\t\t\t\tthis.rowsContainer.classList.remove('drop-target');\n\t\t\t});\n\t\t} else {\n\t\t\tfor (const index of feedback) {\n\t\t\t\tconst item = this.items[index]!;\n\t\t\t\titem.dropTarget = true;\n\n\t\t\t\tif (item.row) {\n\t\t\t\t\titem.row.domNode.classList.add('drop-target');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.currentDragFeedbackDisposable = toDisposable(() => {\n\t\t\t\tfor (const index of feedback) {\n\t\t\t\t\tconst item = this.items[index]!;\n\t\t\t\t\titem.dropTarget = false;\n\n\t\t\t\t\tif (item.row) {\n\t\t\t\t\t\titem.row.domNode.classList.remove('drop-target');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate onDragLeave(event: IListDragEvent): void {\n\t\tthis.onDragLeaveTimeout.dispose();\n\t\tthis.onDragLeaveTimeout = disposableTimeout(() => this.clearDragOverFeedback(), 100);\n\t\tif (this.currentDragData) {\n\t\t\tthis.dnd.onDragLeave?.(this.currentDragData, event.element, event.index, event.browserEvent);\n\t\t}\n\t}\n\n\tprivate onDrop(event: IListDragEvent): void {\n\t\tif (!this.canDrop) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst dragData = this.currentDragData;\n\t\tthis.teardownDragAndDropScrollTopAnimation();\n\t\tthis.clearDragOverFeedback();\n\t\tthis.currentDragData = undefined;\n\t\tStaticDND.CurrentDragAndDropData = undefined;\n\n\t\tif (!dragData || !event.browserEvent.dataTransfer) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.browserEvent.preventDefault();\n\t\tdragData.update(event.browserEvent.dataTransfer);\n\t\tthis.dnd.drop(dragData, event.element, event.index, event.browserEvent);\n\t}\n\n\tprivate onDragEnd(event: DragEvent): void {\n\t\tthis.canDrop = false;\n\t\tthis.teardownDragAndDropScrollTopAnimation();\n\t\tthis.clearDragOverFeedback();\n\t\tthis.currentDragData = undefined;\n\t\tStaticDND.CurrentDragAndDropData = undefined;\n\n\t\tif (this.dnd.onDragEnd) {\n\t\t\tthis.dnd.onDragEnd(event);\n\t\t}\n\t}\n\n\tprivate clearDragOverFeedback(): void {\n\t\tthis.currentDragFeedback = undefined;\n\t\tthis.currentDragFeedbackDisposable.dispose();\n\t\tthis.currentDragFeedbackDisposable = Disposable.None;\n\t}\n\n\t// DND scroll top animation\n\n\tprivate setupDragAndDropScrollTopAnimation(event: DragEvent): void {\n\t\tif (!this.dragOverAnimationDisposable) {\n\t\t\tconst viewTop = getTopLeftOffset(this.domNode).top;\n\t\t\tthis.dragOverAnimationDisposable = animate(this.animateDragAndDropScrollTop.bind(this, viewTop));\n\t\t}\n\n\t\tthis.dragOverAnimationStopDisposable.dispose();\n\t\tthis.dragOverAnimationStopDisposable = disposableTimeout(() => {\n\t\t\tif (this.dragOverAnimationDisposable) {\n\t\t\t\tthis.dragOverAnimationDisposable.dispose();\n\t\t\t\tthis.dragOverAnimationDisposable = undefined;\n\t\t\t}\n\t\t}, 1000);\n\n\t\tthis.dragOverMouseY = event.pageY;\n\t}\n\n\tprivate animateDragAndDropScrollTop(viewTop: number): void {\n\t\tif (this.dragOverMouseY === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst diff = this.dragOverMouseY - viewTop;\n\t\tconst upperLimit = this.renderHeight - 35;\n\n\t\tif (diff < 35) {\n\t\t\tthis.scrollTop += Math.max(-14, Math.floor(0.3 * (diff - 35)));\n\t\t} else if (diff > upperLimit) {\n\t\t\tthis.scrollTop += Math.min(14, Math.floor(0.3 * (diff - upperLimit)));\n\t\t}\n\t}\n\n\tprivate teardownDragAndDropScrollTopAnimation(): void {\n\t\tthis.dragOverAnimationStopDisposable.dispose();\n\n\t\tif (this.dragOverAnimationDisposable) {\n\t\t\tthis.dragOverAnimationDisposable.dispose();\n\t\t\tthis.dragOverAnimationDisposable = undefined;\n\t\t}\n\t}\n\n\t// Util\n\n\tprivate getItemIndexFromEventTarget(target: EventTarget | null): number | undefined {\n\t\tconst scrollableElement = this.scrollableElement.getDomNode();\n\t\tlet element: HTMLElement | null = target as (HTMLElement | null);\n\n\t\twhile (element instanceof HTMLElement && element !== this.rowsContainer && scrollableElement.contains(element)) {\n\t\t\tconst rawIndex = element.getAttribute('data-index');\n\n\t\t\tif (rawIndex) {\n\t\t\t\tconst index = Number(rawIndex);\n\n\t\t\t\tif (!isNaN(index)) {\n\t\t\t\t\treturn index;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\telement = element.parentElement;\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tprivate getRenderRange(renderTop: number, renderHeight: number): IRange {\n\t\treturn {\n\t\t\tstart: this.rangeMap.indexAt(renderTop),\n\t\t\tend: this.rangeMap.indexAfter(renderTop + renderHeight - 1)\n\t\t};\n\t}\n\n\t/**\n\t * Given a stable rendered state, checks every rendered element whether it needs\n\t * to be probed for dynamic height. Adjusts scroll height and top if necessary.\n\t */\n\tprivate _rerender(renderTop: number, renderHeight: number, inSmoothScrolling?: boolean): void {\n\t\tconst previousRenderRange = this.getRenderRange(renderTop, renderHeight);\n\n\t\t// Let's remember the second element's position, this helps in scrolling up\n\t\t// and preserving a linear upwards scroll movement\n\t\tlet anchorElementIndex: number | undefined;\n\t\tlet anchorElementTopDelta: number | undefined;\n\n\t\tif (renderTop === this.elementTop(previousRenderRange.start)) {\n\t\t\tanchorElementIndex = previousRenderRange.start;\n\t\t\tanchorElementTopDelta = 0;\n\t\t} else if (previousRenderRange.end - previousRenderRange.start > 1) {\n\t\t\tanchorElementIndex = previousRenderRange.start + 1;\n\t\t\tanchorElementTopDelta = this.elementTop(anchorElementIndex) - renderTop;\n\t\t}\n\n\t\tlet heightDiff = 0;\n\n\t\twhile (true) {\n\t\t\tconst renderRange = this.getRenderRange(renderTop, renderHeight);\n\n\t\t\tlet didChange = false;\n\n\t\t\tfor (let i = renderRange.start; i < renderRange.end; i++) {\n\t\t\t\tconst diff = this.probeDynamicHeight(i);\n\n\t\t\t\tif (diff !== 0) {\n\t\t\t\t\tthis.rangeMap.splice(i, 1, [this.items[i]]);\n\t\t\t\t}\n\n\t\t\t\theightDiff += diff;\n\t\t\t\tdidChange = didChange || diff !== 0;\n\t\t\t}\n\n\t\t\tif (!didChange) {\n\t\t\t\tif (heightDiff !== 0) {\n\t\t\t\t\tthis.eventuallyUpdateScrollDimensions();\n\t\t\t\t}\n\n\t\t\t\tconst unrenderRanges = Range.relativeComplement(previousRenderRange, renderRange);\n\n\t\t\t\tfor (const range of unrenderRanges) {\n\t\t\t\t\tfor (let i = range.start; i < range.end; i++) {\n\t\t\t\t\t\tif (this.items[i].row) {\n\t\t\t\t\t\t\tthis.removeItemFromDOM(i);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst renderRanges = Range.relativeComplement(renderRange, previousRenderRange);\n\n\t\t\t\tfor (const range of renderRanges) {\n\t\t\t\t\tfor (let i = range.start; i < range.end; i++) {\n\t\t\t\t\t\tconst afterIndex = i + 1;\n\t\t\t\t\t\tconst beforeRow = afterIndex < this.items.length ? this.items[afterIndex].row : null;\n\t\t\t\t\t\tconst beforeElement = beforeRow ? beforeRow.domNode : null;\n\t\t\t\t\t\tthis.insertItemInDOM(i, beforeElement);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (let i = renderRange.start; i < renderRange.end; i++) {\n\t\t\t\t\tif (this.items[i].row) {\n\t\t\t\t\t\tthis.updateItemInDOM(this.items[i], i);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (typeof anchorElementIndex === 'number') {\n\t\t\t\t\t// To compute a destination scroll top, we need to take into account the current smooth scrolling\n\t\t\t\t\t// animation, and then reuse it with a new target (to avoid prolonging the scroll)\n\t\t\t\t\t// See https://github.com/microsoft/vscode/issues/104144\n\t\t\t\t\t// See https://github.com/microsoft/vscode/pull/104284\n\t\t\t\t\t// See https://github.com/microsoft/vscode/issues/107704\n\t\t\t\t\tconst deltaScrollTop = this.scrollable.getFutureScrollPosition().scrollTop - renderTop;\n\t\t\t\t\tconst newScrollTop = this.elementTop(anchorElementIndex) - anchorElementTopDelta! + deltaScrollTop;\n\t\t\t\t\tthis.setScrollTop(newScrollTop, inSmoothScrolling);\n\t\t\t\t}\n\n\t\t\t\tthis._onDidChangeContentHeight.fire(this.contentHeight);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate probeDynamicHeight(index: number): number {\n\t\tconst item = this.items[index];\n\n\t\tif (!!this.virtualDelegate.getDynamicHeight) {\n\t\t\tconst newSize = this.virtualDelegate.getDynamicHeight(item.element);\n\t\t\tif (newSize !== null) {\n\t\t\t\tconst size = item.size;\n\t\t\t\titem.size = newSize;\n\t\t\t\titem.lastDynamicHeightWidth = this.renderWidth;\n\t\t\t\treturn newSize - size;\n\t\t\t}\n\t\t}\n\n\t\tif (!item.hasDynamicHeight || item.lastDynamicHeightWidth === this.renderWidth) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tif (!!this.virtualDelegate.hasDynamicHeight && !this.virtualDelegate.hasDynamicHeight(item.element)) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst size = item.size;\n\n\t\tif (!this.setRowHeight && item.row) {\n\t\t\tlet newSize = item.row.domNode.offsetHeight;\n\t\t\titem.size = newSize;\n\t\t\titem.lastDynamicHeightWidth = this.renderWidth;\n\t\t\treturn newSize - size;\n\t\t}\n\n\t\tconst row = this.cache.alloc(item.templateId);\n\n\t\trow.domNode.style.height = '';\n\t\tthis.rowsContainer.appendChild(row.domNode);\n\n\t\tconst renderer = this.renderers.get(item.templateId);\n\t\tif (renderer) {\n\t\t\trenderer.renderElement(item.element, index, row.templateData, undefined);\n\n\t\t\tif (renderer.disposeElement) {\n\t\t\t\trenderer.disposeElement(item.element, index, row.templateData, undefined);\n\t\t\t}\n\t\t}\n\n\t\titem.size = row.domNode.offsetHeight;\n\n\t\tif (this.virtualDelegate.setDynamicHeight) {\n\t\t\tthis.virtualDelegate.setDynamicHeight(item.element, item.size);\n\t\t}\n\n\t\titem.lastDynamicHeightWidth = this.renderWidth;\n\t\tthis.rowsContainer.removeChild(row.domNode);\n\t\tthis.cache.release(row);\n\n\t\treturn item.size - size;\n\t}\n\n\tprivate getNextToLastElement(ranges: IRange[]): HTMLElement | null {\n\t\tconst lastRange = ranges[ranges.length - 1];\n\n\t\tif (!lastRange) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst nextToLastItem = this.items[lastRange.end];\n\n\t\tif (!nextToLastItem) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (!nextToLastItem.row) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn nextToLastItem.row.domNode;\n\t}\n\n\tgetElementDomId(index: number): string {\n\t\treturn `${this.domId}_${index}`;\n\t}\n\n\t// Dispose\n\n\tdispose() {\n\t\tif (this.items) {\n\t\t\tfor (const item of this.items) {\n\t\t\t\tif (item.row) {\n\t\t\t\t\tconst renderer = this.renderers.get(item.row.templateId);\n\t\t\t\t\tif (renderer) {\n\t\t\t\t\t\tif (renderer.disposeElement) {\n\t\t\t\t\t\t\trenderer.disposeElement(item.element, -1, item.row.templateData, undefined);\n\t\t\t\t\t\t}\n\t\t\t\t\t\trenderer.disposeTemplate(item.row.templateData);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.items = [];\n\t\t}\n\n\t\tif (this.domNode && this.domNode.parentNode) {\n\t\t\tthis.domNode.parentNode.removeChild(this.domNode);\n\t\t}\n\n\t\tdispose(this.disposables);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDragAndDropData } from 'vs/base/browser/dnd';\nimport { createStyleSheet } from 'vs/base/browser/dom';\nimport { DomEmitter, stopEvent } from 'vs/base/browser/event';\nimport { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { Gesture } from 'vs/base/browser/touch';\nimport { alert } from 'vs/base/browser/ui/aria/aria';\nimport { CombinedSpliceable } from 'vs/base/browser/ui/list/splice';\nimport { binarySearch, firstOrDefault, range } from 'vs/base/common/arrays';\nimport { timeout } from 'vs/base/common/async';\nimport { Color } from 'vs/base/common/color';\nimport { memoize } from 'vs/base/common/decorators';\nimport { Emitter, Event, EventBufferer } from 'vs/base/common/event';\nimport { matchesPrefix } from 'vs/base/common/filters';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';\nimport { clamp } from 'vs/base/common/numbers';\nimport { mixin } from 'vs/base/common/objects';\nimport * as platform from 'vs/base/common/platform';\nimport { ISpliceable } from 'vs/base/common/sequence';\nimport { IThemable } from 'vs/base/common/styler';\nimport { isNumber } from 'vs/base/common/types';\nimport 'vs/css!./list';\nimport { IIdentityProvider, IKeyboardNavigationDelegate, IKeyboardNavigationLabelProvider, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IListEvent, IListGestureEvent, IListMouseEvent, IListRenderer, IListTouchEvent, IListVirtualDelegate, ListError } from './list';\nimport { IListViewAccessibilityProvider, IListViewDragAndDrop, IListViewOptions, IListViewOptionsUpdate, ListView } from './listView';\n\ninterface ITraitChangeEvent {\n\tindexes: number[];\n\tbrowserEvent?: UIEvent;\n}\n\ntype ITraitTemplateData = HTMLElement;\n\ninterface IRenderedContainer {\n\ttemplateData: ITraitTemplateData;\n\tindex: number;\n}\n\nclass TraitRenderer implements IListRenderer\n{\n\tprivate renderedElements: IRenderedContainer[] = [];\n\n\tconstructor(private trait: Trait) { }\n\n\tget templateId(): string {\n\t\treturn `template:${this.trait.trait}`;\n\t}\n\n\trenderTemplate(container: HTMLElement): ITraitTemplateData {\n\t\treturn container;\n\t}\n\n\trenderElement(element: T, index: number, templateData: ITraitTemplateData): void {\n\t\tconst renderedElementIndex = this.renderedElements.findIndex(el => el.templateData === templateData);\n\n\t\tif (renderedElementIndex >= 0) {\n\t\t\tconst rendered = this.renderedElements[renderedElementIndex];\n\t\t\tthis.trait.unrender(templateData);\n\t\t\trendered.index = index;\n\t\t} else {\n\t\t\tconst rendered = { index, templateData };\n\t\t\tthis.renderedElements.push(rendered);\n\t\t}\n\n\t\tthis.trait.renderIndex(index, templateData);\n\t}\n\n\tsplice(start: number, deleteCount: number, insertCount: number): void {\n\t\tconst rendered: IRenderedContainer[] = [];\n\n\t\tfor (const renderedElement of this.renderedElements) {\n\n\t\t\tif (renderedElement.index < start) {\n\t\t\t\trendered.push(renderedElement);\n\t\t\t} else if (renderedElement.index >= start + deleteCount) {\n\t\t\t\trendered.push({\n\t\t\t\t\tindex: renderedElement.index + insertCount - deleteCount,\n\t\t\t\t\ttemplateData: renderedElement.templateData\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tthis.renderedElements = rendered;\n\t}\n\n\trenderIndexes(indexes: number[]): void {\n\t\tfor (const { index, templateData } of this.renderedElements) {\n\t\t\tif (indexes.indexOf(index) > -1) {\n\t\t\t\tthis.trait.renderIndex(index, templateData);\n\t\t\t}\n\t\t}\n\t}\n\n\tdisposeTemplate(templateData: ITraitTemplateData): void {\n\t\tconst index = this.renderedElements.findIndex(el => el.templateData === templateData);\n\n\t\tif (index < 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.renderedElements.splice(index, 1);\n\t}\n}\n\nclass Trait implements ISpliceable, IDisposable {\n\n\tprivate length = 0;\n\tprivate indexes: number[] = [];\n\tprivate sortedIndexes: number[] = [];\n\n\tprivate readonly _onChange = new Emitter();\n\treadonly onChange: Event = this._onChange.event;\n\n\tget trait(): string { return this._trait; }\n\n\t@memoize\n\tget renderer(): TraitRenderer {\n\t\treturn new TraitRenderer(this);\n\t}\n\n\tconstructor(private _trait: string) { }\n\n\tsplice(start: number, deleteCount: number, elements: boolean[]): void {\n\t\tdeleteCount = Math.max(0, Math.min(deleteCount, this.length - start));\n\n\t\tconst diff = elements.length - deleteCount;\n\t\tconst end = start + deleteCount;\n\t\tconst sortedIndexes = [\n\t\t\t...this.sortedIndexes.filter(i => i < start),\n\t\t\t...elements.map((hasTrait, i) => hasTrait ? i + start : -1).filter(i => i !== -1),\n\t\t\t...this.sortedIndexes.filter(i => i >= end).map(i => i + diff)\n\t\t];\n\n\t\tconst length = this.length + diff;\n\n\t\tif (this.sortedIndexes.length > 0 && sortedIndexes.length === 0 && length > 0) {\n\t\t\tconst first = this.sortedIndexes.find(index => index >= start) ?? length - 1;\n\t\t\tsortedIndexes.push(Math.min(first, length - 1));\n\t\t}\n\n\t\tthis.renderer.splice(start, deleteCount, elements.length);\n\t\tthis._set(sortedIndexes, sortedIndexes);\n\t\tthis.length = length;\n\t}\n\n\trenderIndex(index: number, container: HTMLElement): void {\n\t\tcontainer.classList.toggle(this._trait, this.contains(index));\n\t}\n\n\tunrender(container: HTMLElement): void {\n\t\tcontainer.classList.remove(this._trait);\n\t}\n\n\t/**\n\t * Sets the indexes which should have this trait.\n\t *\n\t * @param indexes Indexes which should have this trait.\n\t * @return The old indexes which had this trait.\n\t */\n\tset(indexes: number[], browserEvent?: UIEvent): number[] {\n\t\treturn this._set(indexes, [...indexes].sort(numericSort), browserEvent);\n\t}\n\n\tprivate _set(indexes: number[], sortedIndexes: number[], browserEvent?: UIEvent): number[] {\n\t\tconst result = this.indexes;\n\t\tconst sortedResult = this.sortedIndexes;\n\n\t\tthis.indexes = indexes;\n\t\tthis.sortedIndexes = sortedIndexes;\n\n\t\tconst toRender = disjunction(sortedResult, indexes);\n\t\tthis.renderer.renderIndexes(toRender);\n\n\t\tthis._onChange.fire({ indexes, browserEvent });\n\t\treturn result;\n\t}\n\n\tget(): number[] {\n\t\treturn this.indexes;\n\t}\n\n\tcontains(index: number): boolean {\n\t\treturn binarySearch(this.sortedIndexes, index, numericSort) >= 0;\n\t}\n\n\tdispose() {\n\t\tdispose(this._onChange);\n\t}\n}\n\nclass SelectionTrait extends Trait {\n\n\tconstructor(private setAriaSelected: boolean) {\n\t\tsuper('selected');\n\t}\n\n\toverride renderIndex(index: number, container: HTMLElement): void {\n\t\tsuper.renderIndex(index, container);\n\n\t\tif (this.setAriaSelected) {\n\t\t\tif (this.contains(index)) {\n\t\t\t\tcontainer.setAttribute('aria-selected', 'true');\n\t\t\t} else {\n\t\t\t\tcontainer.setAttribute('aria-selected', 'false');\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * The TraitSpliceable is used as a util class to be able\n * to preserve traits across splice calls, given an identity\n * provider.\n */\nclass TraitSpliceable implements ISpliceable {\n\n\tconstructor(\n\t\tprivate trait: Trait,\n\t\tprivate view: ListView,\n\t\tprivate identityProvider?: IIdentityProvider\n\t) { }\n\n\tsplice(start: number, deleteCount: number, elements: T[]): void {\n\t\tif (!this.identityProvider) {\n\t\t\treturn this.trait.splice(start, deleteCount, elements.map(() => false));\n\t\t}\n\n\t\tconst pastElementsWithTrait = this.trait.get().map(i => this.identityProvider!.getId(this.view.element(i)).toString());\n\t\tconst elementsWithTrait = elements.map(e => pastElementsWithTrait.indexOf(this.identityProvider!.getId(e).toString()) > -1);\n\n\t\tthis.trait.splice(start, deleteCount, elementsWithTrait);\n\t}\n}\n\nexport function isInputElement(e: HTMLElement): boolean {\n\treturn e.tagName === 'INPUT' || e.tagName === 'TEXTAREA';\n}\n\nexport function isMonacoEditor(e: HTMLElement): boolean {\n\tif (e.classList.contains('monaco-editor')) {\n\t\treturn true;\n\t}\n\n\tif (e.classList.contains('monaco-list')) {\n\t\treturn false;\n\t}\n\n\tif (!e.parentElement) {\n\t\treturn false;\n\t}\n\n\treturn isMonacoEditor(e.parentElement);\n}\n\nclass KeyboardController implements IDisposable {\n\n\tprivate readonly disposables = new DisposableStore();\n\tprivate readonly multipleSelectionDisposables = new DisposableStore();\n\n\t@memoize\n\tprivate get onKeyDown(): Event.IChainableEvent {\n\t\treturn Event.chain(this.disposables.add(new DomEmitter(this.view.domNode, 'keydown')).event)\n\t\t\t.filter(e => !isInputElement(e.target as HTMLElement))\n\t\t\t.map(e => new StandardKeyboardEvent(e));\n\t}\n\n\tconstructor(\n\t\tprivate list: List,\n\t\tprivate view: ListView,\n\t\toptions: IListOptions\n\t) {\n\t\tthis.onKeyDown.filter(e => e.keyCode === KeyCode.Enter).on(this.onEnter, this, this.disposables);\n\t\tthis.onKeyDown.filter(e => e.keyCode === KeyCode.UpArrow).on(this.onUpArrow, this, this.disposables);\n\t\tthis.onKeyDown.filter(e => e.keyCode === KeyCode.DownArrow).on(this.onDownArrow, this, this.disposables);\n\t\tthis.onKeyDown.filter(e => e.keyCode === KeyCode.PageUp).on(this.onPageUpArrow, this, this.disposables);\n\t\tthis.onKeyDown.filter(e => e.keyCode === KeyCode.PageDown).on(this.onPageDownArrow, this, this.disposables);\n\t\tthis.onKeyDown.filter(e => e.keyCode === KeyCode.Escape).on(this.onEscape, this, this.disposables);\n\n\t\tif (options.multipleSelectionSupport !== false) {\n\t\t\tthis.onKeyDown.filter(e => (platform.isMacintosh ? e.metaKey : e.ctrlKey) && e.keyCode === KeyCode.KeyA).on(this.onCtrlA, this, this.multipleSelectionDisposables);\n\t\t}\n\t}\n\n\tupdateOptions(optionsUpdate: IListOptionsUpdate): void {\n\t\tif (optionsUpdate.multipleSelectionSupport !== undefined) {\n\t\t\tthis.multipleSelectionDisposables.clear();\n\n\t\t\tif (optionsUpdate.multipleSelectionSupport) {\n\t\t\t\tthis.onKeyDown.filter(e => (platform.isMacintosh ? e.metaKey : e.ctrlKey) && e.keyCode === KeyCode.KeyA).on(this.onCtrlA, this, this.multipleSelectionDisposables);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onEnter(e: StandardKeyboardEvent): void {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tthis.list.setSelection(this.list.getFocus(), e.browserEvent);\n\t}\n\n\tprivate onUpArrow(e: StandardKeyboardEvent): void {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tthis.list.focusPrevious(1, false, e.browserEvent);\n\t\tconst el = this.list.getFocus()[0];\n\t\tthis.list.setAnchor(el);\n\t\tthis.list.reveal(el);\n\t\tthis.view.domNode.focus();\n\t}\n\n\tprivate onDownArrow(e: StandardKeyboardEvent): void {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tthis.list.focusNext(1, false, e.browserEvent);\n\t\tconst el = this.list.getFocus()[0];\n\t\tthis.list.setAnchor(el);\n\t\tthis.list.reveal(el);\n\t\tthis.view.domNode.focus();\n\t}\n\n\tprivate onPageUpArrow(e: StandardKeyboardEvent): void {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tthis.list.focusPreviousPage(e.browserEvent);\n\t\tconst el = this.list.getFocus()[0];\n\t\tthis.list.setAnchor(el);\n\t\tthis.list.reveal(el);\n\t\tthis.view.domNode.focus();\n\t}\n\n\tprivate onPageDownArrow(e: StandardKeyboardEvent): void {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tthis.list.focusNextPage(e.browserEvent);\n\t\tconst el = this.list.getFocus()[0];\n\t\tthis.list.setAnchor(el);\n\t\tthis.list.reveal(el);\n\t\tthis.view.domNode.focus();\n\t}\n\n\tprivate onCtrlA(e: StandardKeyboardEvent): void {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tthis.list.setSelection(range(this.list.length), e.browserEvent);\n\t\tthis.list.setAnchor(undefined);\n\t\tthis.view.domNode.focus();\n\t}\n\n\tprivate onEscape(e: StandardKeyboardEvent): void {\n\t\tif (this.list.getSelection().length) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tthis.list.setSelection([], e.browserEvent);\n\t\t\tthis.list.setAnchor(undefined);\n\t\t\tthis.view.domNode.focus();\n\t\t}\n\t}\n\n\tdispose() {\n\t\tthis.disposables.dispose();\n\t\tthis.multipleSelectionDisposables.dispose();\n\t}\n}\n\nenum TypeLabelControllerState {\n\tIdle,\n\tTyping\n}\n\nexport const DefaultKeyboardNavigationDelegate = new class implements IKeyboardNavigationDelegate {\n\tmightProducePrintableCharacter(event: IKeyboardEvent): boolean {\n\t\tif (event.ctrlKey || event.metaKey || event.altKey) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn (event.keyCode >= KeyCode.KeyA && event.keyCode <= KeyCode.KeyZ)\n\t\t\t|| (event.keyCode >= KeyCode.Digit0 && event.keyCode <= KeyCode.Digit9)\n\t\t\t|| (event.keyCode >= KeyCode.Numpad0 && event.keyCode <= KeyCode.Numpad9)\n\t\t\t|| (event.keyCode >= KeyCode.Semicolon && event.keyCode <= KeyCode.Quote);\n\t}\n};\n\nclass TypeLabelController implements IDisposable {\n\n\tprivate enabled = false;\n\tprivate state: TypeLabelControllerState = TypeLabelControllerState.Idle;\n\n\tprivate automaticKeyboardNavigation = true;\n\tprivate triggered = false;\n\tprivate previouslyFocused = -1;\n\n\tprivate readonly enabledDisposables = new DisposableStore();\n\tprivate readonly disposables = new DisposableStore();\n\n\tconstructor(\n\t\tprivate list: List,\n\t\tprivate view: ListView,\n\t\tprivate keyboardNavigationLabelProvider: IKeyboardNavigationLabelProvider,\n\t\tprivate delegate: IKeyboardNavigationDelegate\n\t) {\n\t\tthis.updateOptions(list.options);\n\t}\n\n\tupdateOptions(options: IListOptions): void {\n\t\tconst enableKeyboardNavigation = typeof options.enableKeyboardNavigation === 'undefined' ? true : !!options.enableKeyboardNavigation;\n\n\t\tif (enableKeyboardNavigation) {\n\t\t\tthis.enable();\n\t\t} else {\n\t\t\tthis.disable();\n\t\t}\n\n\t\tif (typeof options.automaticKeyboardNavigation !== 'undefined') {\n\t\t\tthis.automaticKeyboardNavigation = options.automaticKeyboardNavigation;\n\t\t}\n\t}\n\n\tprivate enable(): void {\n\t\tif (this.enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst onChar = Event.chain(this.enabledDisposables.add(new DomEmitter(this.view.domNode, 'keydown')).event)\n\t\t\t.filter(e => !isInputElement(e.target as HTMLElement))\n\t\t\t.filter(() => this.automaticKeyboardNavigation || this.triggered)\n\t\t\t.map(event => new StandardKeyboardEvent(event))\n\t\t\t.filter(e => this.delegate.mightProducePrintableCharacter(e))\n\t\t\t.forEach(e => e.preventDefault())\n\t\t\t.map(event => event.browserEvent.key)\n\t\t\t.event;\n\n\t\tconst onClear = Event.debounce(onChar, () => null, 800);\n\t\tconst onInput = Event.reduce(Event.any(onChar, onClear), (r, i) => i === null ? null : ((r || '') + i));\n\n\t\tonInput(this.onInput, this, this.enabledDisposables);\n\t\tonClear(this.onClear, this, this.enabledDisposables);\n\n\t\tthis.enabled = true;\n\t\tthis.triggered = false;\n\t}\n\n\tprivate disable(): void {\n\t\tif (!this.enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.enabledDisposables.clear();\n\t\tthis.enabled = false;\n\t\tthis.triggered = false;\n\t}\n\n\tprivate onClear(): void {\n\t\tconst focus = this.list.getFocus();\n\t\tif (focus.length > 0 && focus[0] === this.previouslyFocused) {\n\t\t\t// List: re-announce element on typing end since typed keys will interrupt aria label of focused element\n\t\t\t// Do not announce if there was a focus change at the end to prevent duplication https://github.com/microsoft/vscode/issues/95961\n\t\t\tconst ariaLabel = this.list.options.accessibilityProvider?.getAriaLabel(this.list.element(focus[0]));\n\t\t\tif (ariaLabel) {\n\t\t\t\talert(ariaLabel);\n\t\t\t}\n\t\t}\n\t\tthis.previouslyFocused = -1;\n\t}\n\n\tprivate onInput(word: string | null): void {\n\t\tif (!word) {\n\t\t\tthis.state = TypeLabelControllerState.Idle;\n\t\t\tthis.triggered = false;\n\t\t\treturn;\n\t\t}\n\n\t\tconst focus = this.list.getFocus();\n\t\tconst start = focus.length > 0 ? focus[0] : 0;\n\t\tconst delta = this.state === TypeLabelControllerState.Idle ? 1 : 0;\n\t\tthis.state = TypeLabelControllerState.Typing;\n\n\t\tfor (let i = 0; i < this.list.length; i++) {\n\t\t\tconst index = (start + i + delta) % this.list.length;\n\t\t\tconst label = this.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(this.view.element(index));\n\t\t\tconst labelStr = label && label.toString();\n\n\t\t\tif (typeof labelStr === 'undefined' || matchesPrefix(word, labelStr)) {\n\t\t\t\tthis.previouslyFocused = start;\n\t\t\t\tthis.list.setFocus([index]);\n\t\t\t\tthis.list.reveal(index);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tdispose() {\n\t\tthis.disable();\n\t\tthis.enabledDisposables.dispose();\n\t\tthis.disposables.dispose();\n\t}\n}\n\nclass DOMFocusController implements IDisposable {\n\n\tprivate readonly disposables = new DisposableStore();\n\n\tconstructor(\n\t\tprivate list: List,\n\t\tprivate view: ListView\n\t) {\n\t\tconst onKeyDown = Event.chain(this.disposables.add(new DomEmitter(view.domNode, 'keydown')).event)\n\t\t\t.filter(e => !isInputElement(e.target as HTMLElement))\n\t\t\t.map(e => new StandardKeyboardEvent(e));\n\n\t\tonKeyDown.filter(e => e.keyCode === KeyCode.Tab && !e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey)\n\t\t\t.on(this.onTab, this, this.disposables);\n\t}\n\n\tprivate onTab(e: StandardKeyboardEvent): void {\n\t\tif (e.target !== this.view.domNode) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst focus = this.list.getFocus();\n\n\t\tif (focus.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst focusedDomElement = this.view.domElement(focus[0]);\n\n\t\tif (!focusedDomElement) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst tabIndexElement = focusedDomElement.querySelector('[tabIndex]');\n\n\t\tif (!tabIndexElement || !(tabIndexElement instanceof HTMLElement) || tabIndexElement.tabIndex === -1) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst style = window.getComputedStyle(tabIndexElement);\n\t\tif (style.visibility === 'hidden' || style.display === 'none') {\n\t\t\treturn;\n\t\t}\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\ttabIndexElement.focus();\n\t}\n\n\tdispose() {\n\t\tthis.disposables.dispose();\n\t}\n}\n\nexport function isSelectionSingleChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean {\n\treturn platform.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey;\n}\n\nexport function isSelectionRangeChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean {\n\treturn event.browserEvent.shiftKey;\n}\n\nfunction isMouseRightClick(event: UIEvent): boolean {\n\treturn event instanceof MouseEvent && event.button === 2;\n}\n\nconst DefaultMultipleSelectionController = {\n\tisSelectionSingleChangeEvent,\n\tisSelectionRangeChangeEvent\n};\n\nexport class MouseController implements IDisposable {\n\n\tprivate multipleSelectionController: IMultipleSelectionController | undefined;\n\tprivate mouseSupport: boolean;\n\tprivate readonly disposables = new DisposableStore();\n\n\tprivate _onPointer = new Emitter>();\n\treadonly onPointer: Event> = this._onPointer.event;\n\n\tconstructor(protected list: List) {\n\t\tif (list.options.multipleSelectionSupport !== false) {\n\t\t\tthis.multipleSelectionController = this.list.options.multipleSelectionController || DefaultMultipleSelectionController;\n\t\t}\n\n\t\tthis.mouseSupport = typeof list.options.mouseSupport === 'undefined' || !!list.options.mouseSupport;\n\n\t\tif (this.mouseSupport) {\n\t\t\tlist.onMouseDown(this.onMouseDown, this, this.disposables);\n\t\t\tlist.onContextMenu(this.onContextMenu, this, this.disposables);\n\t\t\tlist.onMouseDblClick(this.onDoubleClick, this, this.disposables);\n\t\t\tlist.onTouchStart(this.onMouseDown, this, this.disposables);\n\t\t\tthis.disposables.add(Gesture.addTarget(list.getHTMLElement()));\n\t\t}\n\n\t\tEvent.any(list.onMouseClick, list.onMouseMiddleClick, list.onTap)(this.onViewPointer, this, this.disposables);\n\t}\n\n\tupdateOptions(optionsUpdate: IListOptionsUpdate): void {\n\t\tif (optionsUpdate.multipleSelectionSupport !== undefined) {\n\t\t\tthis.multipleSelectionController = undefined;\n\n\t\t\tif (optionsUpdate.multipleSelectionSupport) {\n\t\t\t\tthis.multipleSelectionController = this.list.options.multipleSelectionController || DefaultMultipleSelectionController;\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected isSelectionSingleChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean {\n\t\tif (!this.multipleSelectionController) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.multipleSelectionController.isSelectionSingleChangeEvent(event);\n\t}\n\n\tprotected isSelectionRangeChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean {\n\t\tif (!this.multipleSelectionController) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.multipleSelectionController.isSelectionRangeChangeEvent(event);\n\t}\n\n\tprivate isSelectionChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean {\n\t\treturn this.isSelectionSingleChangeEvent(event) || this.isSelectionRangeChangeEvent(event);\n\t}\n\n\tprivate onMouseDown(e: IListMouseEvent | IListTouchEvent): void {\n\t\tif (isMonacoEditor(e.browserEvent.target as HTMLElement)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (document.activeElement !== e.browserEvent.target) {\n\t\t\tthis.list.domFocus();\n\t\t}\n\t}\n\n\tprivate onContextMenu(e: IListContextMenuEvent): void {\n\t\tif (isMonacoEditor(e.browserEvent.target as HTMLElement)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst focus = typeof e.index === 'undefined' ? [] : [e.index];\n\t\tthis.list.setFocus(focus, e.browserEvent);\n\t}\n\n\tprotected onViewPointer(e: IListMouseEvent): void {\n\t\tif (!this.mouseSupport) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (isInputElement(e.browserEvent.target as HTMLElement) || isMonacoEditor(e.browserEvent.target as HTMLElement)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst focus = e.index;\n\n\t\tif (typeof focus === 'undefined') {\n\t\t\tthis.list.setFocus([], e.browserEvent);\n\t\t\tthis.list.setSelection([], e.browserEvent);\n\t\t\tthis.list.setAnchor(undefined);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.isSelectionRangeChangeEvent(e)) {\n\t\t\treturn this.changeSelection(e);\n\t\t}\n\n\t\tif (this.isSelectionChangeEvent(e)) {\n\t\t\treturn this.changeSelection(e);\n\t\t}\n\n\t\tthis.list.setFocus([focus], e.browserEvent);\n\t\tthis.list.setAnchor(focus);\n\n\t\tif (!isMouseRightClick(e.browserEvent)) {\n\t\t\tthis.list.setSelection([focus], e.browserEvent);\n\t\t}\n\n\t\tthis._onPointer.fire(e);\n\t}\n\n\tprotected onDoubleClick(e: IListMouseEvent): void {\n\t\tif (isInputElement(e.browserEvent.target as HTMLElement) || isMonacoEditor(e.browserEvent.target as HTMLElement)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.isSelectionChangeEvent(e)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst focus = this.list.getFocus();\n\t\tthis.list.setSelection(focus, e.browserEvent);\n\t}\n\n\tprivate changeSelection(e: IListMouseEvent | IListTouchEvent): void {\n\t\tconst focus = e.index!;\n\t\tlet anchor = this.list.getAnchor();\n\n\t\tif (this.isSelectionRangeChangeEvent(e)) {\n\t\t\tif (typeof anchor === 'undefined') {\n\t\t\t\tconst currentFocus = this.list.getFocus()[0];\n\t\t\t\tanchor = currentFocus ?? focus;\n\t\t\t\tthis.list.setAnchor(anchor);\n\t\t\t}\n\n\t\t\tconst min = Math.min(anchor, focus);\n\t\t\tconst max = Math.max(anchor, focus);\n\t\t\tconst rangeSelection = range(min, max + 1);\n\t\t\tconst selection = this.list.getSelection();\n\t\t\tconst contiguousRange = getContiguousRangeContaining(disjunction(selection, [anchor]), anchor);\n\n\t\t\tif (contiguousRange.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst newSelection = disjunction(rangeSelection, relativeComplement(selection, contiguousRange));\n\t\t\tthis.list.setSelection(newSelection, e.browserEvent);\n\t\t\tthis.list.setFocus([focus], e.browserEvent);\n\n\t\t} else if (this.isSelectionSingleChangeEvent(e)) {\n\t\t\tconst selection = this.list.getSelection();\n\t\t\tconst newSelection = selection.filter(i => i !== focus);\n\n\t\t\tthis.list.setFocus([focus]);\n\t\t\tthis.list.setAnchor(focus);\n\n\t\t\tif (selection.length === newSelection.length) {\n\t\t\t\tthis.list.setSelection([...newSelection, focus], e.browserEvent);\n\t\t\t} else {\n\t\t\t\tthis.list.setSelection(newSelection, e.browserEvent);\n\t\t\t}\n\t\t}\n\t}\n\n\tdispose() {\n\t\tthis.disposables.dispose();\n\t}\n}\n\nexport interface IMultipleSelectionController {\n\tisSelectionSingleChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean;\n\tisSelectionRangeChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean;\n}\n\nexport interface IStyleController {\n\tstyle(styles: IListStyles): void;\n}\n\nexport interface IListAccessibilityProvider extends IListViewAccessibilityProvider {\n\tgetAriaLabel(element: T): string | null;\n\tgetWidgetAriaLabel(): string;\n\tgetWidgetRole?(): string;\n\tgetAriaLevel?(element: T): number | undefined;\n\tonDidChangeActiveDescendant?: Event;\n\tgetActiveDescendantId?(element: T): string | undefined;\n}\n\nexport class DefaultStyleController implements IStyleController {\n\n\tconstructor(private styleElement: HTMLStyleElement, private selectorSuffix: string) { }\n\n\tstyle(styles: IListStyles): void {\n\t\tconst suffix = this.selectorSuffix && `.${this.selectorSuffix}`;\n\t\tconst content: string[] = [];\n\n\t\tif (styles.listBackground) {\n\t\t\tif (styles.listBackground.isOpaque()) {\n\t\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-rows { background: ${styles.listBackground}; }`);\n\t\t\t} else if (!platform.isMacintosh) { // subpixel AA doesn't exist in macOS\n\t\t\t\tconsole.warn(`List with id '${this.selectorSuffix}' was styled with a non-opaque background color. This will break sub-pixel antialiasing.`);\n\t\t\t}\n\t\t}\n\n\t\tif (styles.listFocusBackground) {\n\t\t\tcontent.push(`.monaco-list${suffix}:focus .monaco-list-row.focused { background-color: ${styles.listFocusBackground}; }`);\n\t\t\tcontent.push(`.monaco-list${suffix}:focus .monaco-list-row.focused:hover { background-color: ${styles.listFocusBackground}; }`); // overwrite :hover style in this case!\n\t\t}\n\n\t\tif (styles.listFocusForeground) {\n\t\t\tcontent.push(`.monaco-list${suffix}:focus .monaco-list-row.focused { color: ${styles.listFocusForeground}; }`);\n\t\t}\n\n\t\tif (styles.listActiveSelectionBackground) {\n\t\t\tcontent.push(`.monaco-list${suffix}:focus .monaco-list-row.selected { background-color: ${styles.listActiveSelectionBackground}; }`);\n\t\t\tcontent.push(`.monaco-list${suffix}:focus .monaco-list-row.selected:hover { background-color: ${styles.listActiveSelectionBackground}; }`); // overwrite :hover style in this case!\n\t\t}\n\n\t\tif (styles.listActiveSelectionForeground) {\n\t\t\tcontent.push(`.monaco-list${suffix}:focus .monaco-list-row.selected { color: ${styles.listActiveSelectionForeground}; }`);\n\t\t}\n\n\t\tif (styles.listActiveSelectionIconForeground) {\n\t\t\tcontent.push(`.monaco-list${suffix}:focus .monaco-list-row.selected .codicon { color: ${styles.listActiveSelectionIconForeground}; }`);\n\t\t}\n\n\t\tif (styles.listFocusAndSelectionBackground) {\n\t\t\tcontent.push(`\n\t\t\t\t.monaco-drag-image,\n\t\t\t\t.monaco-list${suffix}:focus .monaco-list-row.selected.focused { background-color: ${styles.listFocusAndSelectionBackground}; }\n\t\t\t`);\n\t\t}\n\n\t\tif (styles.listFocusAndSelectionForeground) {\n\t\t\tcontent.push(`\n\t\t\t\t.monaco-drag-image,\n\t\t\t\t.monaco-list${suffix}:focus .monaco-list-row.selected.focused { color: ${styles.listFocusAndSelectionForeground}; }\n\t\t\t`);\n\t\t}\n\n\t\tif (styles.listInactiveFocusForeground) {\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row.focused { color: ${styles.listInactiveFocusForeground}; }`);\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row.focused:hover { color: ${styles.listInactiveFocusForeground}; }`); // overwrite :hover style in this case!\n\t\t}\n\n\t\tif (styles.listInactiveSelectionIconForeground) {\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row.focused .codicon { color: ${styles.listInactiveSelectionIconForeground}; }`);\n\t\t}\n\n\t\tif (styles.listInactiveFocusBackground) {\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row.focused { background-color: ${styles.listInactiveFocusBackground}; }`);\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row.focused:hover { background-color: ${styles.listInactiveFocusBackground}; }`); // overwrite :hover style in this case!\n\t\t}\n\n\t\tif (styles.listInactiveSelectionBackground) {\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row.selected { background-color: ${styles.listInactiveSelectionBackground}; }`);\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row.selected:hover { background-color: ${styles.listInactiveSelectionBackground}; }`); // overwrite :hover style in this case!\n\t\t}\n\n\t\tif (styles.listInactiveSelectionForeground) {\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row.selected { color: ${styles.listInactiveSelectionForeground}; }`);\n\t\t}\n\n\t\tif (styles.listHoverBackground) {\n\t\t\tcontent.push(`.monaco-list${suffix}:not(.drop-target) .monaco-list-row:hover:not(.selected):not(.focused) { background-color: ${styles.listHoverBackground}; }`);\n\t\t}\n\n\t\tif (styles.listHoverForeground) {\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row:hover:not(.selected):not(.focused) { color: ${styles.listHoverForeground}; }`);\n\t\t}\n\n\t\tif (styles.listSelectionOutline) {\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row.selected { outline: 1px dotted ${styles.listSelectionOutline}; outline-offset: -1px; }`);\n\t\t}\n\n\t\tif (styles.listFocusOutline) {\n\t\t\tcontent.push(`\n\t\t\t\t.monaco-drag-image,\n\t\t\t\t.monaco-list${suffix}:focus .monaco-list-row.focused { outline: 1px solid ${styles.listFocusOutline}; outline-offset: -1px; }\n\t\t\t\t.monaco-workbench.context-menu-visible .monaco-list${suffix}.last-focused .monaco-list-row.focused { outline: 1px solid ${styles.listFocusOutline}; outline-offset: -1px; }\n\t\t\t`);\n\t\t}\n\n\t\tif (styles.listInactiveFocusOutline) {\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row.focused { outline: 1px dotted ${styles.listInactiveFocusOutline}; outline-offset: -1px; }`);\n\t\t}\n\n\t\tif (styles.listHoverOutline) {\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-list-row:hover { outline: 1px dashed ${styles.listHoverOutline}; outline-offset: -1px; }`);\n\t\t}\n\n\t\tif (styles.listDropBackground) {\n\t\t\tcontent.push(`\n\t\t\t\t.monaco-list${suffix}.drop-target,\n\t\t\t\t.monaco-list${suffix} .monaco-list-rows.drop-target,\n\t\t\t\t.monaco-list${suffix} .monaco-list-row.drop-target { background-color: ${styles.listDropBackground} !important; color: inherit !important; }\n\t\t\t`);\n\t\t}\n\n\t\tif (styles.listFilterWidgetBackground) {\n\t\t\tcontent.push(`.monaco-list-type-filter { background-color: ${styles.listFilterWidgetBackground} }`);\n\t\t}\n\n\t\tif (styles.listFilterWidgetOutline) {\n\t\t\tcontent.push(`.monaco-list-type-filter { border: 1px solid ${styles.listFilterWidgetOutline}; }`);\n\t\t}\n\n\t\tif (styles.listFilterWidgetNoMatchesOutline) {\n\t\t\tcontent.push(`.monaco-list-type-filter.no-matches { border: 1px solid ${styles.listFilterWidgetNoMatchesOutline}; }`);\n\t\t}\n\n\t\tif (styles.listMatchesShadow) {\n\t\t\tcontent.push(`.monaco-list-type-filter { box-shadow: 1px 1px 1px ${styles.listMatchesShadow}; }`);\n\t\t}\n\n\t\tif (styles.tableColumnsBorder) {\n\t\t\tcontent.push(`\n\t\t\t\t.monaco-table:hover > .monaco-split-view2,\n\t\t\t\t.monaco-table:hover > .monaco-split-view2 .monaco-sash.vertical::before {\n\t\t\t\t\tborder-color: ${styles.tableColumnsBorder};\n\t\t\t}`);\n\t\t}\n\n\t\tif (styles.tableOddRowsBackgroundColor) {\n\t\t\tcontent.push(`\n\t\t\t\t.monaco-table .monaco-list-row[data-parity=odd]:not(.focused):not(.selected):not(:hover) .monaco-table-tr,\n\t\t\t\t.monaco-table .monaco-list:not(:focus) .monaco-list-row[data-parity=odd].focused:not(.selected):not(:hover) .monaco-table-tr,\n\t\t\t\t.monaco-table .monaco-list:not(.focused) .monaco-list-row[data-parity=odd].focused:not(.selected):not(:hover) .monaco-table-tr {\n\t\t\t\t\tbackground-color: ${styles.tableOddRowsBackgroundColor};\n\t\t\t\t}\n\t\t\t`);\n\t\t}\n\n\t\tthis.styleElement.textContent = content.join('\\n');\n\t}\n}\n\nexport interface IListOptionsUpdate extends IListViewOptionsUpdate {\n\treadonly enableKeyboardNavigation?: boolean;\n\treadonly automaticKeyboardNavigation?: boolean;\n\treadonly multipleSelectionSupport?: boolean;\n}\n\nexport interface IListOptions extends IListOptionsUpdate {\n\treadonly identityProvider?: IIdentityProvider;\n\treadonly dnd?: IListDragAndDrop;\n\treadonly keyboardNavigationLabelProvider?: IKeyboardNavigationLabelProvider;\n\treadonly keyboardNavigationDelegate?: IKeyboardNavigationDelegate;\n\treadonly keyboardSupport?: boolean;\n\treadonly multipleSelectionController?: IMultipleSelectionController;\n\treadonly styleController?: (suffix: string) => IStyleController;\n\treadonly accessibilityProvider?: IListAccessibilityProvider;\n\n\t// list view options\n\treadonly useShadows?: boolean;\n\treadonly setRowLineHeight?: boolean;\n\treadonly mouseSupport?: boolean;\n\treadonly horizontalScrolling?: boolean;\n\treadonly smoothScrolling?: boolean;\n\treadonly alwaysConsumeMouseWheel?: boolean;\n}\n\nexport interface IListStyles {\n\tlistBackground?: Color;\n\tlistFocusBackground?: Color;\n\tlistFocusForeground?: Color;\n\tlistActiveSelectionBackground?: Color;\n\tlistActiveSelectionForeground?: Color;\n\tlistActiveSelectionIconForeground?: Color;\n\tlistFocusAndSelectionBackground?: Color;\n\tlistFocusAndSelectionForeground?: Color;\n\tlistInactiveSelectionBackground?: Color;\n\tlistInactiveSelectionIconForeground?: Color;\n\tlistInactiveSelectionForeground?: Color;\n\tlistInactiveFocusForeground?: Color;\n\tlistInactiveFocusBackground?: Color;\n\tlistHoverBackground?: Color;\n\tlistHoverForeground?: Color;\n\tlistDropBackground?: Color;\n\tlistFocusOutline?: Color;\n\tlistInactiveFocusOutline?: Color;\n\tlistSelectionOutline?: Color;\n\tlistHoverOutline?: Color;\n\tlistFilterWidgetBackground?: Color;\n\tlistFilterWidgetOutline?: Color;\n\tlistFilterWidgetNoMatchesOutline?: Color;\n\tlistMatchesShadow?: Color;\n\ttreeIndentGuidesStroke?: Color;\n\ttableColumnsBorder?: Color;\n\ttableOddRowsBackgroundColor?: Color;\n}\n\nconst defaultStyles: IListStyles = {\n\tlistFocusBackground: Color.fromHex('#7FB0D0'),\n\tlistActiveSelectionBackground: Color.fromHex('#0E639C'),\n\tlistActiveSelectionForeground: Color.fromHex('#FFFFFF'),\n\tlistActiveSelectionIconForeground: Color.fromHex('#FFFFFF'),\n\tlistFocusAndSelectionBackground: Color.fromHex('#094771'),\n\tlistFocusAndSelectionForeground: Color.fromHex('#FFFFFF'),\n\tlistInactiveSelectionBackground: Color.fromHex('#3F3F46'),\n\tlistInactiveSelectionIconForeground: Color.fromHex('#FFFFFF'),\n\tlistHoverBackground: Color.fromHex('#2A2D2E'),\n\tlistDropBackground: Color.fromHex('#383B3D'),\n\ttreeIndentGuidesStroke: Color.fromHex('#a9a9a9'),\n\ttableColumnsBorder: Color.fromHex('#cccccc').transparent(0.2),\n\ttableOddRowsBackgroundColor: Color.fromHex('#cccccc').transparent(0.04)\n};\n\nconst DefaultOptions: IListOptions = {\n\tkeyboardSupport: true,\n\tmouseSupport: true,\n\tmultipleSelectionSupport: true,\n\tdnd: {\n\t\tgetDragURI() { return null; },\n\t\tonDragStart(): void { },\n\t\tonDragOver() { return false; },\n\t\tdrop() { }\n\t}\n};\n\n// TODO@Joao: move these utils into a SortedArray class\n\nfunction getContiguousRangeContaining(range: number[], value: number): number[] {\n\tconst index = range.indexOf(value);\n\n\tif (index === -1) {\n\t\treturn [];\n\t}\n\n\tconst result: number[] = [];\n\tlet i = index - 1;\n\twhile (i >= 0 && range[i] === value - (index - i)) {\n\t\tresult.push(range[i--]);\n\t}\n\n\tresult.reverse();\n\ti = index;\n\twhile (i < range.length && range[i] === value + (i - index)) {\n\t\tresult.push(range[i++]);\n\t}\n\n\treturn result;\n}\n\n/**\n * Given two sorted collections of numbers, returns the intersection\n * between them (OR).\n */\nfunction disjunction(one: number[], other: number[]): number[] {\n\tconst result: number[] = [];\n\tlet i = 0, j = 0;\n\n\twhile (i < one.length || j < other.length) {\n\t\tif (i >= one.length) {\n\t\t\tresult.push(other[j++]);\n\t\t} else if (j >= other.length) {\n\t\t\tresult.push(one[i++]);\n\t\t} else if (one[i] === other[j]) {\n\t\t\tresult.push(one[i]);\n\t\t\ti++;\n\t\t\tj++;\n\t\t\tcontinue;\n\t\t} else if (one[i] < other[j]) {\n\t\t\tresult.push(one[i++]);\n\t\t} else {\n\t\t\tresult.push(other[j++]);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Given two sorted collections of numbers, returns the relative\n * complement between them (XOR).\n */\nfunction relativeComplement(one: number[], other: number[]): number[] {\n\tconst result: number[] = [];\n\tlet i = 0, j = 0;\n\n\twhile (i < one.length || j < other.length) {\n\t\tif (i >= one.length) {\n\t\t\tresult.push(other[j++]);\n\t\t} else if (j >= other.length) {\n\t\t\tresult.push(one[i++]);\n\t\t} else if (one[i] === other[j]) {\n\t\t\ti++;\n\t\t\tj++;\n\t\t\tcontinue;\n\t\t} else if (one[i] < other[j]) {\n\t\t\tresult.push(one[i++]);\n\t\t} else {\n\t\t\tj++;\n\t\t}\n\t}\n\n\treturn result;\n}\n\nconst numericSort = (a: number, b: number) => a - b;\n\nclass PipelineRenderer implements IListRenderer {\n\n\tconstructor(\n\t\tprivate _templateId: string,\n\t\tprivate renderers: IListRenderer[]\n\t) { }\n\n\tget templateId(): string {\n\t\treturn this._templateId;\n\t}\n\n\trenderTemplate(container: HTMLElement): any[] {\n\t\treturn this.renderers.map(r => r.renderTemplate(container));\n\t}\n\n\trenderElement(element: T, index: number, templateData: any[], height: number | undefined): void {\n\t\tlet i = 0;\n\n\t\tfor (const renderer of this.renderers) {\n\t\t\trenderer.renderElement(element, index, templateData[i++], height);\n\t\t}\n\t}\n\n\tdisposeElement(element: T, index: number, templateData: any[], height: number | undefined): void {\n\t\tlet i = 0;\n\n\t\tfor (const renderer of this.renderers) {\n\t\t\tif (renderer.disposeElement) {\n\t\t\t\trenderer.disposeElement(element, index, templateData[i], height);\n\t\t\t}\n\n\t\t\ti += 1;\n\t\t}\n\t}\n\n\tdisposeTemplate(templateData: any[]): void {\n\t\tlet i = 0;\n\n\t\tfor (const renderer of this.renderers) {\n\t\t\trenderer.disposeTemplate(templateData[i++]);\n\t\t}\n\t}\n}\n\nclass AccessibiltyRenderer implements IListRenderer {\n\n\ttemplateId: string = 'a18n';\n\n\tconstructor(private accessibilityProvider: IListAccessibilityProvider) { }\n\n\trenderTemplate(container: HTMLElement): HTMLElement {\n\t\treturn container;\n\t}\n\n\trenderElement(element: T, index: number, container: HTMLElement): void {\n\t\tconst ariaLabel = this.accessibilityProvider.getAriaLabel(element);\n\n\t\tif (ariaLabel) {\n\t\t\tcontainer.setAttribute('aria-label', ariaLabel);\n\t\t} else {\n\t\t\tcontainer.removeAttribute('aria-label');\n\t\t}\n\n\t\tconst ariaLevel = this.accessibilityProvider.getAriaLevel && this.accessibilityProvider.getAriaLevel(element);\n\n\t\tif (typeof ariaLevel === 'number') {\n\t\t\tcontainer.setAttribute('aria-level', `${ariaLevel}`);\n\t\t} else {\n\t\t\tcontainer.removeAttribute('aria-level');\n\t\t}\n\t}\n\n\tdisposeTemplate(templateData: any): void {\n\t\t// noop\n\t}\n}\n\nclass ListViewDragAndDrop implements IListViewDragAndDrop {\n\n\tconstructor(private list: List, private dnd: IListDragAndDrop) { }\n\n\tgetDragElements(element: T): T[] {\n\t\tconst selection = this.list.getSelectedElements();\n\t\tconst elements = selection.indexOf(element) > -1 ? selection : [element];\n\t\treturn elements;\n\t}\n\n\tgetDragURI(element: T): string | null {\n\t\treturn this.dnd.getDragURI(element);\n\t}\n\n\tgetDragLabel?(elements: T[], originalEvent: DragEvent): string | undefined {\n\t\tif (this.dnd.getDragLabel) {\n\t\t\treturn this.dnd.getDragLabel(elements, originalEvent);\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tonDragStart(data: IDragAndDropData, originalEvent: DragEvent): void {\n\t\tif (this.dnd.onDragStart) {\n\t\t\tthis.dnd.onDragStart(data, originalEvent);\n\t\t}\n\t}\n\n\tonDragOver(data: IDragAndDropData, targetElement: T, targetIndex: number, originalEvent: DragEvent): boolean | IListDragOverReaction {\n\t\treturn this.dnd.onDragOver(data, targetElement, targetIndex, originalEvent);\n\t}\n\n\tonDragLeave(data: IDragAndDropData, targetElement: T, targetIndex: number, originalEvent: DragEvent): void {\n\t\tthis.dnd.onDragLeave?.(data, targetElement, targetIndex, originalEvent);\n\t}\n\n\tonDragEnd(originalEvent: DragEvent): void {\n\t\tif (this.dnd.onDragEnd) {\n\t\t\tthis.dnd.onDragEnd(originalEvent);\n\t\t}\n\t}\n\n\tdrop(data: IDragAndDropData, targetElement: T, targetIndex: number, originalEvent: DragEvent): void {\n\t\tthis.dnd.drop(data, targetElement, targetIndex, originalEvent);\n\t}\n}\n\n/**\n * The {@link List} is a virtual scrolling widget, built on top of the {@link ListView}\n * widget.\n *\n * Features:\n * - Customizable keyboard and mouse support\n * - Element traits: focus, selection, achor\n * - Accessibility support\n * - Touch support\n * - Performant template-based rendering\n * - Horizontal scrolling\n * - Variable element height support\n * - Dynamic element height support\n * - Drag-and-drop support\n */\nexport class List implements ISpliceable, IThemable, IDisposable {\n\n\tprivate focus = new Trait('focused');\n\tprivate selection: Trait;\n\tprivate anchor = new Trait('anchor');\n\tprivate eventBufferer = new EventBufferer();\n\tprotected view: ListView;\n\tprivate spliceable: ISpliceable;\n\tprivate styleController: IStyleController;\n\tprivate typeLabelController?: TypeLabelController;\n\tprivate accessibilityProvider?: IListAccessibilityProvider;\n\tprivate keyboardController: KeyboardController | undefined;\n\tprivate mouseController: MouseController;\n\tprivate _ariaLabel: string = '';\n\n\tprotected readonly disposables = new DisposableStore();\n\n\t@memoize get onDidChangeFocus(): Event> {\n\t\treturn Event.map(this.eventBufferer.wrapEvent(this.focus.onChange), e => this.toListEvent(e));\n\t}\n\n\t@memoize get onDidChangeSelection(): Event> {\n\t\treturn Event.map(this.eventBufferer.wrapEvent(this.selection.onChange), e => this.toListEvent(e));\n\t}\n\n\tget domId(): string { return this.view.domId; }\n\tget onMouseClick(): Event> { return this.view.onMouseClick; }\n\tget onMouseDblClick(): Event> { return this.view.onMouseDblClick; }\n\tget onMouseMiddleClick(): Event> { return this.view.onMouseMiddleClick; }\n\tget onPointer(): Event> { return this.mouseController.onPointer; }\n\tget onMouseDown(): Event> { return this.view.onMouseDown; }\n\tget onTouchStart(): Event> { return this.view.onTouchStart; }\n\tget onTap(): Event> { return this.view.onTap; }\n\n\t/**\n\t * Possible context menu trigger events:\n\t * - ContextMenu key\n\t * - Shift F10\n\t * - Ctrl Option Shift M (macOS with VoiceOver)\n\t * - Mouse right click\n\t */\n\t@memoize get onContextMenu(): Event> {\n\t\tlet didJustPressContextMenuKey = false;\n\n\t\tconst fromKeyDown = Event.chain(this.disposables.add(new DomEmitter(this.view.domNode, 'keydown')).event)\n\t\t\t.map(e => new StandardKeyboardEvent(e))\n\t\t\t.filter(e => didJustPressContextMenuKey = e.keyCode === KeyCode.ContextMenu || (e.shiftKey && e.keyCode === KeyCode.F10))\n\t\t\t.map(stopEvent)\n\t\t\t.filter(() => false)\n\t\t\t.event as Event;\n\n\t\tconst fromKeyUp = Event.chain(this.disposables.add(new DomEmitter(this.view.domNode, 'keyup')).event)\n\t\t\t.forEach(() => didJustPressContextMenuKey = false)\n\t\t\t.map(e => new StandardKeyboardEvent(e))\n\t\t\t.filter(e => e.keyCode === KeyCode.ContextMenu || (e.shiftKey && e.keyCode === KeyCode.F10))\n\t\t\t.map(stopEvent)\n\t\t\t.map(({ browserEvent }) => {\n\t\t\t\tconst focus = this.getFocus();\n\t\t\t\tconst index = focus.length ? focus[0] : undefined;\n\t\t\t\tconst element = typeof index !== 'undefined' ? this.view.element(index) : undefined;\n\t\t\t\tconst anchor = typeof index !== 'undefined' ? this.view.domElement(index) as HTMLElement : this.view.domNode;\n\t\t\t\treturn { index, element, anchor, browserEvent };\n\t\t\t})\n\t\t\t.event;\n\n\t\tconst fromMouse = Event.chain(this.view.onContextMenu)\n\t\t\t.filter(_ => !didJustPressContextMenuKey)\n\t\t\t.map(({ element, index, browserEvent }) => ({ element, index, anchor: { x: browserEvent.pageX + 1, y: browserEvent.pageY }, browserEvent }))\n\t\t\t.event;\n\n\t\treturn Event.any>(fromKeyDown, fromKeyUp, fromMouse);\n\t}\n\n\t@memoize get onKeyDown(): Event { return this.disposables.add(new DomEmitter(this.view.domNode, 'keydown')).event; }\n\n\t@memoize get onDidFocus(): Event { return Event.signal(this.disposables.add(new DomEmitter(this.view.domNode, 'focus', true)).event); }\n\n\tprivate readonly _onDidDispose = new Emitter();\n\treadonly onDidDispose: Event = this._onDidDispose.event;\n\n\tconstructor(\n\t\tprivate user: string,\n\t\tcontainer: HTMLElement,\n\t\tvirtualDelegate: IListVirtualDelegate,\n\t\trenderers: IListRenderer[],\n\t\tprivate _options: IListOptions = DefaultOptions\n\t) {\n\t\tconst role = this._options.accessibilityProvider && this._options.accessibilityProvider.getWidgetRole ? this._options.accessibilityProvider?.getWidgetRole() : 'list';\n\t\tthis.selection = new SelectionTrait(role !== 'listbox');\n\n\t\tmixin(_options, defaultStyles, false);\n\n\t\tconst baseRenderers: IListRenderer[] = [this.focus.renderer, this.selection.renderer];\n\n\t\tthis.accessibilityProvider = _options.accessibilityProvider;\n\n\t\tif (this.accessibilityProvider) {\n\t\t\tbaseRenderers.push(new AccessibiltyRenderer(this.accessibilityProvider));\n\n\t\t\tif (this.accessibilityProvider.onDidChangeActiveDescendant) {\n\t\t\t\tthis.accessibilityProvider.onDidChangeActiveDescendant(this.onDidChangeActiveDescendant, this, this.disposables);\n\t\t\t}\n\t\t}\n\n\t\trenderers = renderers.map(r => new PipelineRenderer(r.templateId, [...baseRenderers, r]));\n\n\t\tconst viewOptions: IListViewOptions = {\n\t\t\t..._options,\n\t\t\tdnd: _options.dnd && new ListViewDragAndDrop(this, _options.dnd)\n\t\t};\n\n\t\tthis.view = new ListView(container, virtualDelegate, renderers, viewOptions);\n\t\tthis.view.domNode.setAttribute('role', role);\n\n\t\tif (_options.styleController) {\n\t\t\tthis.styleController = _options.styleController(this.view.domId);\n\t\t} else {\n\t\t\tconst styleElement = createStyleSheet(this.view.domNode);\n\t\t\tthis.styleController = new DefaultStyleController(styleElement, this.view.domId);\n\t\t}\n\n\t\tthis.spliceable = new CombinedSpliceable([\n\t\t\tnew TraitSpliceable(this.focus, this.view, _options.identityProvider),\n\t\t\tnew TraitSpliceable(this.selection, this.view, _options.identityProvider),\n\t\t\tnew TraitSpliceable(this.anchor, this.view, _options.identityProvider),\n\t\t\tthis.view\n\t\t]);\n\n\t\tthis.disposables.add(this.focus);\n\t\tthis.disposables.add(this.selection);\n\t\tthis.disposables.add(this.anchor);\n\t\tthis.disposables.add(this.view);\n\t\tthis.disposables.add(this._onDidDispose);\n\n\t\tthis.disposables.add(new DOMFocusController(this, this.view));\n\n\t\tif (typeof _options.keyboardSupport !== 'boolean' || _options.keyboardSupport) {\n\t\t\tthis.keyboardController = new KeyboardController(this, this.view, _options);\n\t\t\tthis.disposables.add(this.keyboardController);\n\t\t}\n\n\t\tif (_options.keyboardNavigationLabelProvider) {\n\t\t\tconst delegate = _options.keyboardNavigationDelegate || DefaultKeyboardNavigationDelegate;\n\t\t\tthis.typeLabelController = new TypeLabelController(this, this.view, _options.keyboardNavigationLabelProvider, delegate);\n\t\t\tthis.disposables.add(this.typeLabelController);\n\t\t}\n\n\t\tthis.mouseController = this.createMouseController(_options);\n\t\tthis.disposables.add(this.mouseController);\n\n\t\tthis.onDidChangeFocus(this._onFocusChange, this, this.disposables);\n\t\tthis.onDidChangeSelection(this._onSelectionChange, this, this.disposables);\n\n\t\tif (this.accessibilityProvider) {\n\t\t\tthis.ariaLabel = this.accessibilityProvider.getWidgetAriaLabel();\n\t\t}\n\n\t\tif (this._options.multipleSelectionSupport !== false) {\n\t\t\tthis.view.domNode.setAttribute('aria-multiselectable', 'true');\n\t\t}\n\t}\n\n\tprotected createMouseController(options: IListOptions): MouseController {\n\t\treturn new MouseController(this);\n\t}\n\n\tupdateOptions(optionsUpdate: IListOptionsUpdate = {}): void {\n\t\tthis._options = { ...this._options, ...optionsUpdate };\n\n\t\tif (this.typeLabelController) {\n\t\t\tthis.typeLabelController.updateOptions(this._options);\n\t\t}\n\n\t\tif (this._options.multipleSelectionController !== undefined) {\n\t\t\tif (this._options.multipleSelectionSupport) {\n\t\t\t\tthis.view.domNode.setAttribute('aria-multiselectable', 'true');\n\t\t\t} else {\n\t\t\t\tthis.view.domNode.removeAttribute('aria-multiselectable');\n\t\t\t}\n\t\t}\n\n\t\tthis.mouseController.updateOptions(optionsUpdate);\n\t\tthis.keyboardController?.updateOptions(optionsUpdate);\n\t\tthis.view.updateOptions(optionsUpdate);\n\t}\n\n\tget options(): IListOptions {\n\t\treturn this._options;\n\t}\n\n\tsplice(start: number, deleteCount: number, elements: T[] = []): void {\n\t\tif (start < 0 || start > this.view.length) {\n\t\t\tthrow new ListError(this.user, `Invalid start index: ${start}`);\n\t\t}\n\n\t\tif (deleteCount < 0) {\n\t\t\tthrow new ListError(this.user, `Invalid delete count: ${deleteCount}`);\n\t\t}\n\n\t\tif (deleteCount === 0 && elements.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.eventBufferer.bufferEvents(() => this.spliceable.splice(start, deleteCount, elements));\n\t}\n\n\trerender(): void {\n\t\tthis.view.rerender();\n\t}\n\n\telement(index: number): T {\n\t\treturn this.view.element(index);\n\t}\n\n\tget length(): number {\n\t\treturn this.view.length;\n\t}\n\n\tget contentHeight(): number {\n\t\treturn this.view.contentHeight;\n\t}\n\n\tget scrollTop(): number {\n\t\treturn this.view.getScrollTop();\n\t}\n\n\tset scrollTop(scrollTop: number) {\n\t\tthis.view.setScrollTop(scrollTop);\n\t}\n\n\tget ariaLabel(): string {\n\t\treturn this._ariaLabel;\n\t}\n\n\tset ariaLabel(value: string) {\n\t\tthis._ariaLabel = value;\n\t\tthis.view.domNode.setAttribute('aria-label', value);\n\t}\n\n\tdomFocus(): void {\n\t\tthis.view.domNode.focus({ preventScroll: true });\n\t}\n\n\tlayout(height?: number, width?: number): void {\n\t\tthis.view.layout(height, width);\n\t}\n\n\tsetSelection(indexes: number[], browserEvent?: UIEvent): void {\n\t\tfor (const index of indexes) {\n\t\t\tif (index < 0 || index >= this.length) {\n\t\t\t\tthrow new ListError(this.user, `Invalid index ${index}`);\n\t\t\t}\n\t\t}\n\n\t\tthis.selection.set(indexes, browserEvent);\n\t}\n\n\tgetSelection(): number[] {\n\t\treturn this.selection.get();\n\t}\n\n\tgetSelectedElements(): T[] {\n\t\treturn this.getSelection().map(i => this.view.element(i));\n\t}\n\n\tsetAnchor(index: number | undefined): void {\n\t\tif (typeof index === 'undefined') {\n\t\t\tthis.anchor.set([]);\n\t\t\treturn;\n\t\t}\n\n\t\tif (index < 0 || index >= this.length) {\n\t\t\tthrow new ListError(this.user, `Invalid index ${index}`);\n\t\t}\n\n\t\tthis.anchor.set([index]);\n\t}\n\n\tgetAnchor(): number | undefined {\n\t\treturn firstOrDefault(this.anchor.get(), undefined);\n\t}\n\n\tgetAnchorElement(): T | undefined {\n\t\tconst anchor = this.getAnchor();\n\t\treturn typeof anchor === 'undefined' ? undefined : this.element(anchor);\n\t}\n\n\tsetFocus(indexes: number[], browserEvent?: UIEvent): void {\n\t\tfor (const index of indexes) {\n\t\t\tif (index < 0 || index >= this.length) {\n\t\t\t\tthrow new ListError(this.user, `Invalid index ${index}`);\n\t\t\t}\n\t\t}\n\n\t\tthis.focus.set(indexes, browserEvent);\n\t}\n\n\tfocusNext(n = 1, loop = false, browserEvent?: UIEvent, filter?: (element: T) => boolean): void {\n\t\tif (this.length === 0) { return; }\n\n\t\tconst focus = this.focus.get();\n\t\tconst index = this.findNextIndex(focus.length > 0 ? focus[0] + n : 0, loop, filter);\n\n\t\tif (index > -1) {\n\t\t\tthis.setFocus([index], browserEvent);\n\t\t}\n\t}\n\n\tfocusPrevious(n = 1, loop = false, browserEvent?: UIEvent, filter?: (element: T) => boolean): void {\n\t\tif (this.length === 0) { return; }\n\n\t\tconst focus = this.focus.get();\n\t\tconst index = this.findPreviousIndex(focus.length > 0 ? focus[0] - n : 0, loop, filter);\n\n\t\tif (index > -1) {\n\t\t\tthis.setFocus([index], browserEvent);\n\t\t}\n\t}\n\n\tasync focusNextPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): Promise {\n\t\tlet lastPageIndex = this.view.indexAt(this.view.getScrollTop() + this.view.renderHeight);\n\t\tlastPageIndex = lastPageIndex === 0 ? 0 : lastPageIndex - 1;\n\t\tconst lastPageElement = this.view.element(lastPageIndex);\n\t\tconst currentlyFocusedElement = this.getFocusedElements()[0];\n\n\t\tif (currentlyFocusedElement !== lastPageElement) {\n\t\t\tconst lastGoodPageIndex = this.findPreviousIndex(lastPageIndex, false, filter);\n\n\t\t\tif (lastGoodPageIndex > -1 && currentlyFocusedElement !== this.view.element(lastGoodPageIndex)) {\n\t\t\t\tthis.setFocus([lastGoodPageIndex], browserEvent);\n\t\t\t} else {\n\t\t\t\tthis.setFocus([lastPageIndex], browserEvent);\n\t\t\t}\n\t\t} else {\n\t\t\tconst previousScrollTop = this.view.getScrollTop();\n\t\t\tthis.view.setScrollTop(previousScrollTop + this.view.renderHeight - this.view.elementHeight(lastPageIndex));\n\n\t\t\tif (this.view.getScrollTop() !== previousScrollTop) {\n\t\t\t\tthis.setFocus([]);\n\n\t\t\t\t// Let the scroll event listener run\n\t\t\t\tawait timeout(0);\n\t\t\t\tawait this.focusNextPage(browserEvent, filter);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync focusPreviousPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): Promise {\n\t\tlet firstPageIndex: number;\n\t\tconst scrollTop = this.view.getScrollTop();\n\n\t\tif (scrollTop === 0) {\n\t\t\tfirstPageIndex = this.view.indexAt(scrollTop);\n\t\t} else {\n\t\t\tfirstPageIndex = this.view.indexAfter(scrollTop - 1);\n\t\t}\n\n\t\tconst firstPageElement = this.view.element(firstPageIndex);\n\t\tconst currentlyFocusedElement = this.getFocusedElements()[0];\n\n\t\tif (currentlyFocusedElement !== firstPageElement) {\n\t\t\tconst firstGoodPageIndex = this.findNextIndex(firstPageIndex, false, filter);\n\n\t\t\tif (firstGoodPageIndex > -1 && currentlyFocusedElement !== this.view.element(firstGoodPageIndex)) {\n\t\t\t\tthis.setFocus([firstGoodPageIndex], browserEvent);\n\t\t\t} else {\n\t\t\t\tthis.setFocus([firstPageIndex], browserEvent);\n\t\t\t}\n\t\t} else {\n\t\t\tconst previousScrollTop = scrollTop;\n\t\t\tthis.view.setScrollTop(scrollTop - this.view.renderHeight);\n\n\t\t\tif (this.view.getScrollTop() !== previousScrollTop) {\n\t\t\t\tthis.setFocus([]);\n\n\t\t\t\t// Let the scroll event listener run\n\t\t\t\tawait timeout(0);\n\t\t\t\tawait this.focusPreviousPage(browserEvent, filter);\n\t\t\t}\n\t\t}\n\t}\n\n\tfocusLast(browserEvent?: UIEvent, filter?: (element: T) => boolean): void {\n\t\tif (this.length === 0) { return; }\n\n\t\tconst index = this.findPreviousIndex(this.length - 1, false, filter);\n\n\t\tif (index > -1) {\n\t\t\tthis.setFocus([index], browserEvent);\n\t\t}\n\t}\n\n\tfocusFirst(browserEvent?: UIEvent, filter?: (element: T) => boolean): void {\n\t\tthis.focusNth(0, browserEvent, filter);\n\t}\n\n\tfocusNth(n: number, browserEvent?: UIEvent, filter?: (element: T) => boolean): void {\n\t\tif (this.length === 0) { return; }\n\n\t\tconst index = this.findNextIndex(n, false, filter);\n\n\t\tif (index > -1) {\n\t\t\tthis.setFocus([index], browserEvent);\n\t\t}\n\t}\n\n\tprivate findNextIndex(index: number, loop = false, filter?: (element: T) => boolean): number {\n\t\tfor (let i = 0; i < this.length; i++) {\n\t\t\tif (index >= this.length && !loop) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tindex = index % this.length;\n\n\t\t\tif (!filter || filter(this.element(index))) {\n\t\t\t\treturn index;\n\t\t\t}\n\n\t\t\tindex++;\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\tprivate findPreviousIndex(index: number, loop = false, filter?: (element: T) => boolean): number {\n\t\tfor (let i = 0; i < this.length; i++) {\n\t\t\tif (index < 0 && !loop) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tindex = (this.length + (index % this.length)) % this.length;\n\n\t\t\tif (!filter || filter(this.element(index))) {\n\t\t\t\treturn index;\n\t\t\t}\n\n\t\t\tindex--;\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\tgetFocus(): number[] {\n\t\treturn this.focus.get();\n\t}\n\n\tgetFocusedElements(): T[] {\n\t\treturn this.getFocus().map(i => this.view.element(i));\n\t}\n\n\treveal(index: number, relativeTop?: number): void {\n\t\tif (index < 0 || index >= this.length) {\n\t\t\tthrow new ListError(this.user, `Invalid index ${index}`);\n\t\t}\n\n\t\tconst scrollTop = this.view.getScrollTop();\n\t\tconst elementTop = this.view.elementTop(index);\n\t\tconst elementHeight = this.view.elementHeight(index);\n\n\t\tif (isNumber(relativeTop)) {\n\t\t\t// y = mx + b\n\t\t\tconst m = elementHeight - this.view.renderHeight;\n\t\t\tthis.view.setScrollTop(m * clamp(relativeTop, 0, 1) + elementTop);\n\t\t} else {\n\t\t\tconst viewItemBottom = elementTop + elementHeight;\n\t\t\tconst scrollBottom = scrollTop + this.view.renderHeight;\n\n\t\t\tif (elementTop < scrollTop && viewItemBottom >= scrollBottom) {\n\t\t\t\t// The element is already overflowing the viewport, no-op\n\t\t\t} else if (elementTop < scrollTop || (viewItemBottom >= scrollBottom && elementHeight >= this.view.renderHeight)) {\n\t\t\t\tthis.view.setScrollTop(elementTop);\n\t\t\t} else if (viewItemBottom >= scrollBottom) {\n\t\t\t\tthis.view.setScrollTop(viewItemBottom - this.view.renderHeight);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns the relative position of an element rendered in the list.\n\t * Returns `null` if the element isn't *entirely* in the visible viewport.\n\t */\n\tgetRelativeTop(index: number): number | null {\n\t\tif (index < 0 || index >= this.length) {\n\t\t\tthrow new ListError(this.user, `Invalid index ${index}`);\n\t\t}\n\n\t\tconst scrollTop = this.view.getScrollTop();\n\t\tconst elementTop = this.view.elementTop(index);\n\t\tconst elementHeight = this.view.elementHeight(index);\n\n\t\tif (elementTop < scrollTop || elementTop + elementHeight > scrollTop + this.view.renderHeight) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// y = mx + b\n\t\tconst m = elementHeight - this.view.renderHeight;\n\t\treturn Math.abs((scrollTop - elementTop) / m);\n\t}\n\n\tgetHTMLElement(): HTMLElement {\n\t\treturn this.view.domNode;\n\t}\n\n\tstyle(styles: IListStyles): void {\n\t\tthis.styleController.style(styles);\n\t}\n\n\tprivate toListEvent({ indexes, browserEvent }: ITraitChangeEvent) {\n\t\treturn { indexes, elements: indexes.map(i => this.view.element(i)), browserEvent };\n\t}\n\n\tprivate _onFocusChange(): void {\n\t\tconst focus = this.focus.get();\n\t\tthis.view.domNode.classList.toggle('element-focused', focus.length > 0);\n\t\tthis.onDidChangeActiveDescendant();\n\t}\n\n\tprivate onDidChangeActiveDescendant(): void {\n\t\tconst focus = this.focus.get();\n\n\t\tif (focus.length > 0) {\n\t\t\tlet id: string | undefined;\n\n\t\t\tif (this.accessibilityProvider?.getActiveDescendantId) {\n\t\t\t\tid = this.accessibilityProvider.getActiveDescendantId(this.view.element(focus[0]));\n\t\t\t}\n\n\t\t\tthis.view.domNode.setAttribute('aria-activedescendant', id || this.view.getElementDomId(focus[0]));\n\t\t} else {\n\t\t\tthis.view.domNode.removeAttribute('aria-activedescendant');\n\t\t}\n\t}\n\n\tprivate _onSelectionChange(): void {\n\t\tconst selection = this.selection.get();\n\n\t\tthis.view.domNode.classList.toggle('selection-none', selection.length === 0);\n\t\tthis.view.domNode.classList.toggle('selection-single', selection.length === 1);\n\t\tthis.view.domNode.classList.toggle('selection-multiple', selection.length > 1);\n\t}\n\n\tdispose(): void {\n\t\tthis._onDidDispose.fire();\n\t\tthis.disposables.dispose();\n\n\t\tthis._onDidDispose.dispose();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { range } from 'vs/base/common/arrays';\nimport { CancellationTokenSource } from 'vs/base/common/cancellation';\nimport { Event } from 'vs/base/common/event';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport { IPagedModel } from 'vs/base/common/paging';\nimport { IThemable } from 'vs/base/common/styler';\nimport 'vs/css!./list';\nimport { IListEvent, IListMouseEvent, IListRenderer, IListVirtualDelegate } from './list';\nimport { IListAccessibilityProvider, IListOptions, IListOptionsUpdate, IListStyles, List } from './listWidget';\n\nexport interface IPagedRenderer extends IListRenderer {\n\trenderPlaceholder(index: number, templateData: TTemplateData): void;\n}\n\nexport interface ITemplateData {\n\tdata?: T;\n\tdisposable?: IDisposable;\n}\n\nclass PagedRenderer implements IListRenderer> {\n\n\tget templateId(): string { return this.renderer.templateId; }\n\n\tconstructor(\n\t\tprivate renderer: IPagedRenderer,\n\t\tprivate modelProvider: () => IPagedModel\n\t) { }\n\n\trenderTemplate(container: HTMLElement): ITemplateData {\n\t\tconst data = this.renderer.renderTemplate(container);\n\t\treturn { data, disposable: Disposable.None };\n\t}\n\n\trenderElement(index: number, _: number, data: ITemplateData, height: number | undefined): void {\n\t\tif (data.disposable) {\n\t\t\tdata.disposable.dispose();\n\t\t}\n\n\t\tif (!data.data) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst model = this.modelProvider();\n\n\t\tif (model.isResolved(index)) {\n\t\t\treturn this.renderer.renderElement(model.get(index), index, data.data, height);\n\t\t}\n\n\t\tconst cts = new CancellationTokenSource();\n\t\tconst promise = model.resolve(index, cts.token);\n\t\tdata.disposable = { dispose: () => cts.cancel() };\n\n\t\tthis.renderer.renderPlaceholder(index, data.data);\n\t\tpromise.then(entry => this.renderer.renderElement(entry, index, data.data!, height));\n\t}\n\n\tdisposeTemplate(data: ITemplateData): void {\n\t\tif (data.disposable) {\n\t\t\tdata.disposable.dispose();\n\t\t\tdata.disposable = undefined;\n\t\t}\n\t\tif (data.data) {\n\t\t\tthis.renderer.disposeTemplate(data.data);\n\t\t\tdata.data = undefined;\n\t\t}\n\t}\n}\n\nclass PagedAccessibilityProvider implements IListAccessibilityProvider {\n\n\tconstructor(\n\t\tprivate modelProvider: () => IPagedModel,\n\t\tprivate accessibilityProvider: IListAccessibilityProvider\n\t) { }\n\n\tgetWidgetAriaLabel(): string {\n\t\treturn this.accessibilityProvider.getWidgetAriaLabel();\n\t}\n\n\tgetAriaLabel(index: number): string | null {\n\t\tconst model = this.modelProvider();\n\n\t\tif (!model.isResolved(index)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn this.accessibilityProvider.getAriaLabel(model.get(index));\n\t}\n}\n\nexport interface IPagedListOptions {\n\treadonly keyboardSupport?: boolean;\n\treadonly accessibilityProvider?: IListAccessibilityProvider;\n\treadonly horizontalScrolling?: boolean;\n}\n\nfunction fromPagedListOptions(modelProvider: () => IPagedModel, options: IPagedListOptions): IListOptions {\n\treturn {\n\t\t...options,\n\t\taccessibilityProvider: options.accessibilityProvider && new PagedAccessibilityProvider(modelProvider, options.accessibilityProvider)\n\t};\n}\n\nexport class PagedList implements IThemable, IDisposable {\n\n\tprivate list: List;\n\tprivate _model!: IPagedModel;\n\n\tconstructor(\n\t\tuser: string,\n\t\tcontainer: HTMLElement,\n\t\tvirtualDelegate: IListVirtualDelegate,\n\t\trenderers: IPagedRenderer[],\n\t\toptions: IPagedListOptions = {}\n\t) {\n\t\tconst modelProvider = () => this.model;\n\t\tconst pagedRenderers = renderers.map(r => new PagedRenderer>(r, modelProvider));\n\t\tthis.list = new List(user, container, virtualDelegate, pagedRenderers, fromPagedListOptions(modelProvider, options));\n\t}\n\n\tupdateOptions(options: IListOptionsUpdate) {\n\t\tthis.list.updateOptions(options);\n\t}\n\n\tgetHTMLElement(): HTMLElement {\n\t\treturn this.list.getHTMLElement();\n\t}\n\n\tget onDidFocus(): Event {\n\t\treturn this.list.onDidFocus;\n\t}\n\n\tget onDidDispose(): Event {\n\t\treturn this.list.onDidDispose;\n\t}\n\n\tget onMouseDblClick(): Event> {\n\t\treturn Event.map(this.list.onMouseDblClick, ({ element, index, browserEvent }) => ({ element: element === undefined ? undefined : this._model.get(element), index, browserEvent }));\n\t}\n\n\tget onPointer(): Event> {\n\t\treturn Event.map(this.list.onPointer, ({ element, index, browserEvent }) => ({ element: element === undefined ? undefined : this._model.get(element), index, browserEvent }));\n\t}\n\n\tget onDidChangeSelection(): Event> {\n\t\treturn Event.map(this.list.onDidChangeSelection, ({ elements, indexes, browserEvent }) => ({ elements: elements.map(e => this._model.get(e)), indexes, browserEvent }));\n\t}\n\n\tget model(): IPagedModel {\n\t\treturn this._model;\n\t}\n\n\tset model(model: IPagedModel) {\n\t\tthis._model = model;\n\t\tthis.list.splice(0, this.list.length, range(model.length));\n\t}\n\n\tgetFocus(): number[] {\n\t\treturn this.list.getFocus();\n\t}\n\n\tgetSelection(): number[] {\n\t\treturn this.list.getSelection();\n\t}\n\n\tgetSelectedElements(): T[] {\n\t\treturn this.getSelection().map(i => this.model.get(i));\n\t}\n\n\tstyle(styles: IListStyles): void {\n\t\tthis.list.style(styles);\n\t}\n\n\tdispose(): void {\n\t\tthis.list.dispose();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { $, addDisposableListener, append, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';\nimport { ISashEvent as IBaseSashEvent, Orientation, Sash, SashState } from 'vs/base/browser/ui/sash/sash';\nimport { SmoothScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';\nimport { pushToEnd, pushToStart, range } from 'vs/base/common/arrays';\nimport { Color } from 'vs/base/common/color';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { combinedDisposable, Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { clamp } from 'vs/base/common/numbers';\nimport { Scrollable, ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';\nimport * as types from 'vs/base/common/types';\nimport 'vs/css!./splitview';\nexport { Orientation } from 'vs/base/browser/ui/sash/sash';\n\nexport interface ISplitViewStyles {\n\treadonly separatorBorder: Color;\n}\n\nconst defaultStyles: ISplitViewStyles = {\n\tseparatorBorder: Color.transparent\n};\n\nexport const enum LayoutPriority {\n\tNormal,\n\tLow,\n\tHigh\n}\n\n/**\n * The interface to implement for views within a {@link SplitView}.\n *\n * An optional {@link TLayoutContext layout context type} may be used in order to\n * pass along layout contextual data from the {@link SplitView.layout} method down\n * to each view's {@link IView.layout} calls.\n */\nexport interface IView {\n\n\t/**\n\t * The DOM element for this view.\n\t */\n\treadonly element: HTMLElement;\n\n\t/**\n\t * A minimum size for this view.\n\t *\n\t * @remarks If none, set it to `0`.\n\t */\n\treadonly minimumSize: number;\n\n\t/**\n\t * A minimum size for this view.\n\t *\n\t * @remarks If none, set it to `Number.POSITIVE_INFINITY`.\n\t */\n\treadonly maximumSize: number;\n\n\t/**\n\t * The priority of the view when the {@link SplitView.resize layout} algorithm\n\t * runs. Views with higher priority will be resized first.\n\t *\n\t * @remarks Only used when `proportionalLayout` is false.\n\t */\n\treadonly priority?: LayoutPriority;\n\n\t/**\n\t * Whether the view will snap whenever the user reaches its minimum size or\n\t * attempts to grow it beyond the minimum size.\n\t *\n\t * @defaultValue `false`\n\t */\n\treadonly snap?: boolean;\n\n\t/**\n\t * View instances are supposed to fire the {@link IView.onDidChange} event whenever\n\t * any of the constraint properties have changed:\n\t *\n\t * - {@link IView.minimumSize}\n\t * - {@link IView.maximumSize}\n\t * - {@link IView.priority}\n\t * - {@link IView.snap}\n\t *\n\t * The SplitView will relayout whenever that happens. The event can optionally emit\n\t * the view's preferred size for that relayout.\n\t */\n\treadonly onDidChange: Event;\n\n\t/**\n\t * This will be called by the {@link SplitView} during layout. A view meant to\n\t * pass along the layout information down to its descendants.\n\t *\n\t * @param size The size of this view, in pixels.\n\t * @param offset The offset of this view, relative to the start of the {@link SplitView}.\n\t * @param context The optional {@link IView layout context} passed to {@link SplitView.layout}.\n\t */\n\tlayout(size: number, offset: number, context: TLayoutContext | undefined): void;\n\n\t/**\n\t * This will be called by the {@link SplitView} whenever this view is made\n\t * visible or hidden.\n\t *\n\t * @param visible Whether the view becomes visible.\n\t */\n\tsetVisible?(visible: boolean): void;\n}\n\n/**\n * A descriptor for a {@link SplitView} instance.\n */\nexport interface ISplitViewDescriptor {\n\n\t/**\n\t * The layout size of the {@link SplitView}.\n\t */\n\treadonly size: number;\n\n\t/**\n\t * Descriptors for each {@link IView view}.\n\t */\n\treadonly views: {\n\n\t\t/**\n\t\t * Whether the {@link IView view} is visible.\n\t\t *\n\t\t * @defaultValue `true`\n\t\t */\n\t\treadonly visible?: boolean;\n\n\t\t/**\n\t\t * The size of the {@link IView view}.\n\t\t *\n\t\t * @defaultValue `true`\n\t\t */\n\t\treadonly size: number;\n\n\t\t/**\n\t\t * The size of the {@link IView view}.\n\t\t *\n\t\t * @defaultValue `true`\n\t\t */\n\t\treadonly view: IView;\n\t}[];\n}\n\nexport interface ISplitViewOptions {\n\n\t/**\n\t * Which axis the views align on.\n\t *\n\t * @defaultValue `Orientation.VERTICAL`\n\t */\n\treadonly orientation?: Orientation;\n\n\t/**\n\t * Styles overriding the {@link defaultStyles default ones}.\n\t */\n\treadonly styles?: ISplitViewStyles;\n\n\t/**\n\t * Make Alt-drag the default drag operation.\n\t */\n\treadonly inverseAltBehavior?: boolean;\n\n\t/**\n\t * Resize each view proportionally when resizing the SplitView.\n\t *\n\t * @defaultValue `true`\n\t */\n\treadonly proportionalLayout?: boolean;\n\n\t/**\n\t * An initial description of this {@link SplitView} instance, allowing\n\t * to initialze all views within the ctor.\n\t */\n\treadonly descriptor?: ISplitViewDescriptor;\n\n\t/**\n\t * The scrollbar visibility setting for whenever the views within\n\t * the {@link SplitView} overflow.\n\t */\n\treadonly scrollbarVisibility?: ScrollbarVisibility;\n\n\t/**\n\t * Override the orthogonal size of sashes.\n\t */\n\treadonly getSashOrthogonalSize?: () => number;\n}\n\ninterface ISashEvent {\n\treadonly sash: Sash;\n\treadonly start: number;\n\treadonly current: number;\n\treadonly alt: boolean;\n}\n\ntype ViewItemSize = number | { cachedVisibleSize: number };\n\nabstract class ViewItem {\n\n\tprivate _size: number;\n\tset size(size: number) {\n\t\tthis._size = size;\n\t}\n\n\tget size(): number {\n\t\treturn this._size;\n\t}\n\n\tprivate _cachedVisibleSize: number | undefined = undefined;\n\n\tget visible(): boolean {\n\t\treturn typeof this._cachedVisibleSize === 'undefined';\n\t}\n\n\tsetVisible(visible: boolean, size?: number): void {\n\t\tif (visible === this.visible) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (visible) {\n\t\t\tthis.size = clamp(this._cachedVisibleSize!, this.viewMinimumSize, this.viewMaximumSize);\n\t\t\tthis._cachedVisibleSize = undefined;\n\t\t} else {\n\t\t\tthis._cachedVisibleSize = typeof size === 'number' ? size : this.size;\n\t\t\tthis.size = 0;\n\t\t}\n\n\t\tthis.container.classList.toggle('visible', visible);\n\n\t\tif (this.view.setVisible) {\n\t\t\tthis.view.setVisible(visible);\n\t\t}\n\t}\n\n\tget minimumSize(): number { return this.visible ? this.view.minimumSize : 0; }\n\tget viewMinimumSize(): number { return this.view.minimumSize; }\n\n\tget maximumSize(): number { return this.visible ? this.view.maximumSize : 0; }\n\tget viewMaximumSize(): number { return this.view.maximumSize; }\n\n\tget priority(): LayoutPriority | undefined { return this.view.priority; }\n\tget snap(): boolean { return !!this.view.snap; }\n\n\tset enabled(enabled: boolean) {\n\t\tthis.container.style.pointerEvents = enabled ? '' : 'none';\n\t}\n\n\tconstructor(\n\t\tprotected container: HTMLElement,\n\t\tprivate view: IView,\n\t\tsize: ViewItemSize,\n\t\tprivate disposable: IDisposable\n\t) {\n\t\tif (typeof size === 'number') {\n\t\t\tthis._size = size;\n\t\t\tthis._cachedVisibleSize = undefined;\n\t\t\tcontainer.classList.add('visible');\n\t\t} else {\n\t\t\tthis._size = 0;\n\t\t\tthis._cachedVisibleSize = size.cachedVisibleSize;\n\t\t}\n\t}\n\n\tlayout(offset: number, layoutContext: TLayoutContext | undefined): void {\n\t\tthis.layoutContainer(offset);\n\t\tthis.view.layout(this.size, offset, layoutContext);\n\t}\n\n\tabstract layoutContainer(offset: number): void;\n\n\tdispose(): IView {\n\t\tthis.disposable.dispose();\n\t\treturn this.view;\n\t}\n}\n\nclass VerticalViewItem extends ViewItem {\n\n\tlayoutContainer(offset: number): void {\n\t\tthis.container.style.top = `${offset}px`;\n\t\tthis.container.style.height = `${this.size}px`;\n\t}\n}\n\nclass HorizontalViewItem extends ViewItem {\n\n\tlayoutContainer(offset: number): void {\n\t\tthis.container.style.left = `${offset}px`;\n\t\tthis.container.style.width = `${this.size}px`;\n\t}\n}\n\ninterface ISashItem {\n\tsash: Sash;\n\tdisposable: IDisposable;\n}\n\ninterface ISashDragSnapState {\n\treadonly index: number;\n\treadonly limitDelta: number;\n\treadonly size: number;\n}\n\ninterface ISashDragState {\n\tindex: number;\n\tstart: number;\n\tcurrent: number;\n\tsizes: number[];\n\tminDelta: number;\n\tmaxDelta: number;\n\talt: boolean;\n\tsnapBefore: ISashDragSnapState | undefined;\n\tsnapAfter: ISashDragSnapState | undefined;\n\tdisposable: IDisposable;\n}\n\nenum State {\n\tIdle,\n\tBusy\n}\n\n/**\n * When adding or removing views, distribute the delta space among\n * all other views.\n */\nexport type DistributeSizing = { type: 'distribute' };\n\n/**\n * When adding or removing views, split the delta space with another\n * specific view, indexed by the provided `index`.\n */\nexport type SplitSizing = { type: 'split', index: number };\n\n/**\n * When adding or removing views, assume the view is invisible.\n */\nexport type InvisibleSizing = { type: 'invisible', cachedVisibleSize: number };\n\n/**\n * When adding or removing views, the sizing provides fine grained\n * control over how other views get resized.\n */\nexport type Sizing = DistributeSizing | SplitSizing | InvisibleSizing;\n\nexport namespace Sizing {\n\n\t/**\n\t * When adding or removing views, distribute the delta space among\n\t * all other views.\n\t */\n\texport const Distribute: DistributeSizing = { type: 'distribute' };\n\n\t/**\n\t * When adding or removing views, split the delta space with another\n\t * specific view, indexed by the provided `index`.\n\t */\n\texport function Split(index: number): SplitSizing { return { type: 'split', index }; }\n\n\t/**\n\t * When adding or removing views, assume the view is invisible.\n\t */\n\texport function Invisible(cachedVisibleSize: number): InvisibleSizing { return { type: 'invisible', cachedVisibleSize }; }\n}\n\n/**\n * The {@link SplitView} is the UI component which implements a one dimensional\n * flex-like layout algorithm for a collection of {@link IView} instances, which\n * are essentially HTMLElement instances with the following size constraints:\n *\n * - {@link IView.minimumSize}\n * - {@link IView.maximumSize}\n * - {@link IView.priority}\n * - {@link IView.snap}\n *\n * In case the SplitView doesn't have enough size to fit all views, it will overflow\n * its content with a scrollbar.\n *\n * In between each pair of views there will be a {@link Sash} allowing the user\n * to resize the views, making sure the constraints are respected.\n *\n * An optional {@link TLayoutContext layout context type} may be used in order to\n * pass along layout contextual data from the {@link SplitView.layout} method down\n * to each view's {@link IView.layout} calls.\n *\n * Features:\n * - Flex-like layout algorithm\n * - Snap support\n * - Orthogonal sash support, for corner sashes\n * - View hide/show support\n * - View swap/move support\n * - Alt key modifier behavior, macOS style\n */\nexport class SplitView extends Disposable {\n\n\t/**\n\t * This {@link SplitView}'s orientation.\n\t */\n\treadonly orientation: Orientation;\n\n\t/**\n\t * The DOM element representing this {@link SplitView}.\n\t */\n\treadonly el: HTMLElement;\n\n\tprivate sashContainer: HTMLElement;\n\tprivate viewContainer: HTMLElement;\n\tprivate scrollable: Scrollable;\n\tprivate scrollableElement: SmoothScrollableElement;\n\tprivate size = 0;\n\tprivate layoutContext: TLayoutContext | undefined;\n\tprivate contentSize = 0;\n\tprivate proportions: undefined | number[] = undefined;\n\tprivate viewItems: ViewItem[] = [];\n\tprivate sashItems: ISashItem[] = [];\n\tprivate sashDragState: ISashDragState | undefined;\n\tprivate state: State = State.Idle;\n\tprivate inverseAltBehavior: boolean;\n\tprivate proportionalLayout: boolean;\n\tprivate readonly getSashOrthogonalSize: { (): number } | undefined;\n\n\tprivate _onDidSashChange = this._register(new Emitter());\n\tprivate _onDidSashReset = this._register(new Emitter());\n\tprivate _orthogonalStartSash: Sash | undefined;\n\tprivate _orthogonalEndSash: Sash | undefined;\n\tprivate _startSnappingEnabled = true;\n\tprivate _endSnappingEnabled = true;\n\n\t/**\n\t * Fires whenever the user resizes a {@link Sash sash}.\n\t */\n\treadonly onDidSashChange = this._onDidSashChange.event;\n\n\t/**\n\t * Fires whenever the user double clicks a {@link Sash sash}.\n\t */\n\treadonly onDidSashReset = this._onDidSashReset.event;\n\n\t/**\n\t * Fires whenever the split view is scrolled.\n\t */\n\treadonly onDidScroll: Event;\n\n\tget orthogonalStartSash(): Sash | undefined { return this._orthogonalStartSash; }\n\tget orthogonalEndSash(): Sash | undefined { return this._orthogonalEndSash; }\n\tget startSnappingEnabled(): boolean { return this._startSnappingEnabled; }\n\tget endSnappingEnabled(): boolean { return this._endSnappingEnabled; }\n\n\t/**\n\t * A reference to a sash, perpendicular to all sashes in this {@link SplitView},\n\t * located at the left- or top-most side of the SplitView.\n\t * Corner sashes will be created automatically at the intersections.\n\t */\n\tset orthogonalStartSash(sash: Sash | undefined) {\n\t\tfor (const sashItem of this.sashItems) {\n\t\t\tsashItem.sash.orthogonalStartSash = sash;\n\t\t}\n\n\t\tthis._orthogonalStartSash = sash;\n\t}\n\n\t/**\n\t * A reference to a sash, perpendicular to all sashes in this {@link SplitView},\n\t * located at the right- or bottom-most side of the SplitView.\n\t * Corner sashes will be created automatically at the intersections.\n\t */\n\tset orthogonalEndSash(sash: Sash | undefined) {\n\t\tfor (const sashItem of this.sashItems) {\n\t\t\tsashItem.sash.orthogonalEndSash = sash;\n\t\t}\n\n\t\tthis._orthogonalEndSash = sash;\n\t}\n\n\t/**\n\t * Enable/disable snapping at the beginning of this {@link SplitView}.\n\t */\n\tset startSnappingEnabled(startSnappingEnabled: boolean) {\n\t\tif (this._startSnappingEnabled === startSnappingEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._startSnappingEnabled = startSnappingEnabled;\n\t\tthis.updateSashEnablement();\n\t}\n\n\t/**\n\t * Enable/disable snapping at the end of this {@link SplitView}.\n\t */\n\tset endSnappingEnabled(endSnappingEnabled: boolean) {\n\t\tif (this._endSnappingEnabled === endSnappingEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._endSnappingEnabled = endSnappingEnabled;\n\t\tthis.updateSashEnablement();\n\t}\n\n\t/**\n\t * Create a new {@link SplitView} instance.\n\t */\n\tconstructor(container: HTMLElement, options: ISplitViewOptions = {}) {\n\t\tsuper();\n\n\t\tthis.orientation = options.orientation ?? Orientation.VERTICAL;\n\t\tthis.inverseAltBehavior = options.inverseAltBehavior ?? false;\n\t\tthis.proportionalLayout = options.proportionalLayout ?? true;\n\t\tthis.getSashOrthogonalSize = options.getSashOrthogonalSize;\n\n\t\tthis.el = document.createElement('div');\n\t\tthis.el.classList.add('monaco-split-view2');\n\t\tthis.el.classList.add(this.orientation === Orientation.VERTICAL ? 'vertical' : 'horizontal');\n\t\tcontainer.appendChild(this.el);\n\n\t\tthis.sashContainer = append(this.el, $('.sash-container'));\n\t\tthis.viewContainer = $('.split-view-container');\n\n\t\tthis.scrollable = new Scrollable({\n\t\t\tforceIntegerValues: true,\n\t\t\tsmoothScrollDuration: 125,\n\t\t\tscheduleAtNextAnimationFrame\n\t\t});\n\t\tthis.scrollableElement = this._register(new SmoothScrollableElement(this.viewContainer, {\n\t\t\tvertical: this.orientation === Orientation.VERTICAL ? (options.scrollbarVisibility ?? ScrollbarVisibility.Auto) : ScrollbarVisibility.Hidden,\n\t\t\thorizontal: this.orientation === Orientation.HORIZONTAL ? (options.scrollbarVisibility ?? ScrollbarVisibility.Auto) : ScrollbarVisibility.Hidden\n\t\t}, this.scrollable));\n\n\t\tthis.onDidScroll = this.scrollableElement.onScroll;\n\t\tthis._register(this.onDidScroll(e => {\n\t\t\tthis.viewContainer.scrollTop = e.scrollTop;\n\t\t\tthis.viewContainer.scrollLeft = e.scrollLeft;\n\t\t}));\n\n\t\tappend(this.el, this.scrollableElement.getDomNode());\n\n\t\tthis.style(options.styles || defaultStyles);\n\n\t\t// We have an existing set of view, add them now\n\t\tif (options.descriptor) {\n\t\t\tthis.size = options.descriptor.size;\n\t\t\toptions.descriptor.views.forEach((viewDescriptor, index) => {\n\t\t\t\tconst sizing = types.isUndefined(viewDescriptor.visible) || viewDescriptor.visible ? viewDescriptor.size : { type: 'invisible', cachedVisibleSize: viewDescriptor.size } as InvisibleSizing;\n\n\t\t\t\tconst view = viewDescriptor.view;\n\t\t\t\tthis.doAddView(view, sizing, index, true);\n\t\t\t});\n\n\t\t\t// Initialize content size and proportions for first layout\n\t\t\tthis.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);\n\t\t\tthis.saveProportions();\n\t\t}\n\t}\n\n\tstyle(styles: ISplitViewStyles): void {\n\t\tif (styles.separatorBorder.isTransparent()) {\n\t\t\tthis.el.classList.remove('separator-border');\n\t\t\tthis.el.style.removeProperty('--separator-border');\n\t\t} else {\n\t\t\tthis.el.classList.add('separator-border');\n\t\t\tthis.el.style.setProperty('--separator-border', styles.separatorBorder.toString());\n\t\t}\n\t}\n\n\t/**\n\t * Add a {@link IView view} to this {@link SplitView}.\n\t *\n\t * @param view The view to add.\n\t * @param size Either a fixed size, or a dynamic {@link Sizing} strategy.\n\t * @param index The index to insert the view on.\n\t * @param skipLayout Whether layout should be skipped.\n\t */\n\taddView(view: IView, size: number | Sizing, index = this.viewItems.length, skipLayout?: boolean): void {\n\t\tthis.doAddView(view, size, index, skipLayout);\n\t}\n\n\t/**\n\t * Layout the {@link SplitView}.\n\t *\n\t * @param size The entire size of the {@link SplitView}.\n\t * @param layoutContext An optional layout context to pass along to {@link IView views}.\n\t */\n\tlayout(size: number, layoutContext?: TLayoutContext): void {\n\t\tconst previousSize = Math.max(this.size, this.contentSize);\n\t\tthis.size = size;\n\t\tthis.layoutContext = layoutContext;\n\n\t\tif (!this.proportions) {\n\t\t\tconst indexes = range(this.viewItems.length);\n\t\t\tconst lowPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.Low);\n\t\t\tconst highPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.High);\n\n\t\t\tthis.resize(this.viewItems.length - 1, size - previousSize, undefined, lowPriorityIndexes, highPriorityIndexes);\n\t\t} else {\n\t\t\tfor (let i = 0; i < this.viewItems.length; i++) {\n\t\t\t\tconst item = this.viewItems[i];\n\t\t\t\titem.size = clamp(Math.round(this.proportions[i] * size), item.minimumSize, item.maximumSize);\n\t\t\t}\n\t\t}\n\n\t\tthis.distributeEmptySpace();\n\t\tthis.layoutViews();\n\t}\n\n\tprivate saveProportions(): void {\n\t\tif (this.proportionalLayout && this.contentSize > 0) {\n\t\t\tthis.proportions = this.viewItems.map(i => i.size / this.contentSize);\n\t\t}\n\t}\n\n\tprivate onSashStart({ sash, start, alt }: ISashEvent): void {\n\t\tfor (const item of this.viewItems) {\n\t\t\titem.enabled = false;\n\t\t}\n\n\t\tconst index = this.sashItems.findIndex(item => item.sash === sash);\n\n\t\t// This way, we can press Alt while we resize a sash, macOS style!\n\t\tconst disposable = combinedDisposable(\n\t\t\taddDisposableListener(document.body, 'keydown', e => resetSashDragState(this.sashDragState!.current, e.altKey)),\n\t\t\taddDisposableListener(document.body, 'keyup', () => resetSashDragState(this.sashDragState!.current, false))\n\t\t);\n\n\t\tconst resetSashDragState = (start: number, alt: boolean) => {\n\t\t\tconst sizes = this.viewItems.map(i => i.size);\n\t\t\tlet minDelta = Number.NEGATIVE_INFINITY;\n\t\t\tlet maxDelta = Number.POSITIVE_INFINITY;\n\n\t\t\tif (this.inverseAltBehavior) {\n\t\t\t\talt = !alt;\n\t\t\t}\n\n\t\t\tif (alt) {\n\t\t\t\t// When we're using the last sash with Alt, we're resizing\n\t\t\t\t// the view to the left/up, instead of right/down as usual\n\t\t\t\t// Thus, we must do the inverse of the usual\n\t\t\t\tconst isLastSash = index === this.sashItems.length - 1;\n\n\t\t\t\tif (isLastSash) {\n\t\t\t\t\tconst viewItem = this.viewItems[index];\n\t\t\t\t\tminDelta = (viewItem.minimumSize - viewItem.size) / 2;\n\t\t\t\t\tmaxDelta = (viewItem.maximumSize - viewItem.size) / 2;\n\t\t\t\t} else {\n\t\t\t\t\tconst viewItem = this.viewItems[index + 1];\n\t\t\t\t\tminDelta = (viewItem.size - viewItem.maximumSize) / 2;\n\t\t\t\t\tmaxDelta = (viewItem.size - viewItem.minimumSize) / 2;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet snapBefore: ISashDragSnapState | undefined;\n\t\t\tlet snapAfter: ISashDragSnapState | undefined;\n\n\t\t\tif (!alt) {\n\t\t\t\tconst upIndexes = range(index, -1);\n\t\t\t\tconst downIndexes = range(index + 1, this.viewItems.length);\n\t\t\t\tconst minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].minimumSize - sizes[i]), 0);\n\t\t\t\tconst maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].viewMaximumSize - sizes[i]), 0);\n\t\t\t\tconst maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].minimumSize), 0);\n\t\t\t\tconst minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].viewMaximumSize), 0);\n\t\t\t\tconst minDelta = Math.max(minDeltaUp, minDeltaDown);\n\t\t\t\tconst maxDelta = Math.min(maxDeltaDown, maxDeltaUp);\n\t\t\t\tconst snapBeforeIndex = this.findFirstSnapIndex(upIndexes);\n\t\t\t\tconst snapAfterIndex = this.findFirstSnapIndex(downIndexes);\n\n\t\t\t\tif (typeof snapBeforeIndex === 'number') {\n\t\t\t\t\tconst viewItem = this.viewItems[snapBeforeIndex];\n\t\t\t\t\tconst halfSize = Math.floor(viewItem.viewMinimumSize / 2);\n\n\t\t\t\t\tsnapBefore = {\n\t\t\t\t\t\tindex: snapBeforeIndex,\n\t\t\t\t\t\tlimitDelta: viewItem.visible ? minDelta - halfSize : minDelta + halfSize,\n\t\t\t\t\t\tsize: viewItem.size\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (typeof snapAfterIndex === 'number') {\n\t\t\t\t\tconst viewItem = this.viewItems[snapAfterIndex];\n\t\t\t\t\tconst halfSize = Math.floor(viewItem.viewMinimumSize / 2);\n\n\t\t\t\t\tsnapAfter = {\n\t\t\t\t\t\tindex: snapAfterIndex,\n\t\t\t\t\t\tlimitDelta: viewItem.visible ? maxDelta + halfSize : maxDelta - halfSize,\n\t\t\t\t\t\tsize: viewItem.size\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.sashDragState = { start, current: start, index, sizes, minDelta, maxDelta, alt, snapBefore, snapAfter, disposable };\n\t\t};\n\n\t\tresetSashDragState(start, alt);\n\t}\n\n\tprivate onSashChange({ current }: ISashEvent): void {\n\t\tconst { index, start, sizes, alt, minDelta, maxDelta, snapBefore, snapAfter } = this.sashDragState!;\n\t\tthis.sashDragState!.current = current;\n\n\t\tconst delta = current - start;\n\t\tconst newDelta = this.resize(index, delta, sizes, undefined, undefined, minDelta, maxDelta, snapBefore, snapAfter);\n\n\t\tif (alt) {\n\t\t\tconst isLastSash = index === this.sashItems.length - 1;\n\t\t\tconst newSizes = this.viewItems.map(i => i.size);\n\t\t\tconst viewItemIndex = isLastSash ? index : index + 1;\n\t\t\tconst viewItem = this.viewItems[viewItemIndex];\n\t\t\tconst newMinDelta = viewItem.size - viewItem.maximumSize;\n\t\t\tconst newMaxDelta = viewItem.size - viewItem.minimumSize;\n\t\t\tconst resizeIndex = isLastSash ? index - 1 : index + 1;\n\n\t\t\tthis.resize(resizeIndex, -newDelta, newSizes, undefined, undefined, newMinDelta, newMaxDelta);\n\t\t}\n\n\t\tthis.distributeEmptySpace();\n\t\tthis.layoutViews();\n\t}\n\n\tprivate onSashEnd(index: number): void {\n\t\tthis._onDidSashChange.fire(index);\n\t\tthis.sashDragState!.disposable.dispose();\n\t\tthis.saveProportions();\n\n\t\tfor (const item of this.viewItems) {\n\t\t\titem.enabled = true;\n\t\t}\n\t}\n\n\tprivate onViewChange(item: ViewItem, size: number | undefined): void {\n\t\tconst index = this.viewItems.indexOf(item);\n\n\t\tif (index < 0 || index >= this.viewItems.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tsize = typeof size === 'number' ? size : item.size;\n\t\tsize = clamp(size, item.minimumSize, item.maximumSize);\n\n\t\tif (this.inverseAltBehavior && index > 0) {\n\t\t\t// In this case, we want the view to grow or shrink both sides equally\n\t\t\t// so we just resize the \"left\" side by half and let `resize` do the clamping magic\n\t\t\tthis.resize(index - 1, Math.floor((item.size - size) / 2));\n\t\t\tthis.distributeEmptySpace();\n\t\t\tthis.layoutViews();\n\t\t} else {\n\t\t\titem.size = size;\n\t\t\tthis.relayout([index], undefined);\n\t\t}\n\t}\n\n\t/**\n\t * Resize a {@link IView view} within the {@link SplitView}.\n\t *\n\t * @param index The {@link IView view} index.\n\t * @param size The {@link IView view} size.\n\t */\n\tresizeView(index: number, size: number): void {\n\t\tif (this.state !== State.Idle) {\n\t\t\tthrow new Error('Cant modify splitview');\n\t\t}\n\n\t\tthis.state = State.Busy;\n\n\t\tif (index < 0 || index >= this.viewItems.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst indexes = range(this.viewItems.length).filter(i => i !== index);\n\t\tconst lowPriorityIndexes = [...indexes.filter(i => this.viewItems[i].priority === LayoutPriority.Low), index];\n\t\tconst highPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.High);\n\n\t\tconst item = this.viewItems[index];\n\t\tsize = Math.round(size);\n\t\tsize = clamp(size, item.minimumSize, Math.min(item.maximumSize, this.size));\n\n\t\titem.size = size;\n\t\tthis.relayout(lowPriorityIndexes, highPriorityIndexes);\n\t\tthis.state = State.Idle;\n\t}\n\n\t/**\n\t * Distribute the entire {@link SplitView} size among all {@link IView views}.\n\t */\n\tdistributeViewSizes(): void {\n\t\tconst flexibleViewItems: ViewItem[] = [];\n\t\tlet flexibleSize = 0;\n\n\t\tfor (const item of this.viewItems) {\n\t\t\tif (item.maximumSize - item.minimumSize > 0) {\n\t\t\t\tflexibleViewItems.push(item);\n\t\t\t\tflexibleSize += item.size;\n\t\t\t}\n\t\t}\n\n\t\tconst size = Math.floor(flexibleSize / flexibleViewItems.length);\n\n\t\tfor (const item of flexibleViewItems) {\n\t\t\titem.size = clamp(size, item.minimumSize, item.maximumSize);\n\t\t}\n\n\t\tconst indexes = range(this.viewItems.length);\n\t\tconst lowPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.Low);\n\t\tconst highPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.High);\n\n\t\tthis.relayout(lowPriorityIndexes, highPriorityIndexes);\n\t}\n\n\t/**\n\t * Returns the size of a {@link IView view}.\n\t */\n\tgetViewSize(index: number): number {\n\t\tif (index < 0 || index >= this.viewItems.length) {\n\t\t\treturn -1;\n\t\t}\n\n\t\treturn this.viewItems[index].size;\n\t}\n\n\tprivate doAddView(view: IView, size: number | Sizing, index = this.viewItems.length, skipLayout?: boolean): void {\n\t\tif (this.state !== State.Idle) {\n\t\t\tthrow new Error('Cant modify splitview');\n\t\t}\n\n\t\tthis.state = State.Busy;\n\n\t\t// Add view\n\t\tconst container = $('.split-view-view');\n\n\t\tif (index === this.viewItems.length) {\n\t\t\tthis.viewContainer.appendChild(container);\n\t\t} else {\n\t\t\tthis.viewContainer.insertBefore(container, this.viewContainer.children.item(index));\n\t\t}\n\n\t\tconst onChangeDisposable = view.onDidChange(size => this.onViewChange(item, size));\n\t\tconst containerDisposable = toDisposable(() => this.viewContainer.removeChild(container));\n\t\tconst disposable = combinedDisposable(onChangeDisposable, containerDisposable);\n\n\t\tlet viewSize: ViewItemSize;\n\n\t\tif (typeof size === 'number') {\n\t\t\tviewSize = size;\n\t\t} else if (size.type === 'split') {\n\t\t\tviewSize = this.getViewSize(size.index) / 2;\n\t\t} else if (size.type === 'invisible') {\n\t\t\tviewSize = { cachedVisibleSize: size.cachedVisibleSize };\n\t\t} else {\n\t\t\tviewSize = view.minimumSize;\n\t\t}\n\n\t\tconst item = this.orientation === Orientation.VERTICAL\n\t\t\t? new VerticalViewItem(container, view, viewSize, disposable)\n\t\t\t: new HorizontalViewItem(container, view, viewSize, disposable);\n\n\t\tthis.viewItems.splice(index, 0, item);\n\n\t\t// Add sash\n\t\tif (this.viewItems.length > 1) {\n\t\t\tlet opts = { orthogonalStartSash: this.orthogonalStartSash, orthogonalEndSash: this.orthogonalEndSash };\n\n\t\t\tconst sash = this.orientation === Orientation.VERTICAL\n\t\t\t\t? new Sash(this.sashContainer, { getHorizontalSashTop: s => this.getSashPosition(s), getHorizontalSashWidth: this.getSashOrthogonalSize }, { ...opts, orientation: Orientation.HORIZONTAL })\n\t\t\t\t: new Sash(this.sashContainer, { getVerticalSashLeft: s => this.getSashPosition(s), getVerticalSashHeight: this.getSashOrthogonalSize }, { ...opts, orientation: Orientation.VERTICAL });\n\n\t\t\tconst sashEventMapper = this.orientation === Orientation.VERTICAL\n\t\t\t\t? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey })\n\t\t\t\t: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX, alt: e.altKey });\n\n\t\t\tconst onStart = Event.map(sash.onDidStart, sashEventMapper);\n\t\t\tconst onStartDisposable = onStart(this.onSashStart, this);\n\t\t\tconst onChange = Event.map(sash.onDidChange, sashEventMapper);\n\t\t\tconst onChangeDisposable = onChange(this.onSashChange, this);\n\t\t\tconst onEnd = Event.map(sash.onDidEnd, () => this.sashItems.findIndex(item => item.sash === sash));\n\t\t\tconst onEndDisposable = onEnd(this.onSashEnd, this);\n\n\t\t\tconst onDidResetDisposable = sash.onDidReset(() => {\n\t\t\t\tconst index = this.sashItems.findIndex(item => item.sash === sash);\n\t\t\t\tconst upIndexes = range(index, -1);\n\t\t\t\tconst downIndexes = range(index + 1, this.viewItems.length);\n\t\t\t\tconst snapBeforeIndex = this.findFirstSnapIndex(upIndexes);\n\t\t\t\tconst snapAfterIndex = this.findFirstSnapIndex(downIndexes);\n\n\t\t\t\tif (typeof snapBeforeIndex === 'number' && !this.viewItems[snapBeforeIndex].visible) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (typeof snapAfterIndex === 'number' && !this.viewItems[snapAfterIndex].visible) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis._onDidSashReset.fire(index);\n\t\t\t});\n\n\t\t\tconst disposable = combinedDisposable(onStartDisposable, onChangeDisposable, onEndDisposable, onDidResetDisposable, sash);\n\t\t\tconst sashItem: ISashItem = { sash, disposable };\n\n\t\t\tthis.sashItems.splice(index - 1, 0, sashItem);\n\t\t}\n\n\t\tcontainer.appendChild(view.element);\n\n\t\tlet highPriorityIndexes: number[] | undefined;\n\n\t\tif (typeof size !== 'number' && size.type === 'split') {\n\t\t\thighPriorityIndexes = [size.index];\n\t\t}\n\n\t\tif (!skipLayout) {\n\t\t\tthis.relayout([index], highPriorityIndexes);\n\t\t}\n\n\t\tthis.state = State.Idle;\n\n\t\tif (!skipLayout && typeof size !== 'number' && size.type === 'distribute') {\n\t\t\tthis.distributeViewSizes();\n\t\t}\n\t}\n\n\tprivate relayout(lowPriorityIndexes?: number[], highPriorityIndexes?: number[]): void {\n\t\tconst contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);\n\n\t\tthis.resize(this.viewItems.length - 1, this.size - contentSize, undefined, lowPriorityIndexes, highPriorityIndexes);\n\t\tthis.distributeEmptySpace();\n\t\tthis.layoutViews();\n\t\tthis.saveProportions();\n\t}\n\n\tprivate resize(\n\t\tindex: number,\n\t\tdelta: number,\n\t\tsizes = this.viewItems.map(i => i.size),\n\t\tlowPriorityIndexes?: number[],\n\t\thighPriorityIndexes?: number[],\n\t\toverloadMinDelta: number = Number.NEGATIVE_INFINITY,\n\t\toverloadMaxDelta: number = Number.POSITIVE_INFINITY,\n\t\tsnapBefore?: ISashDragSnapState,\n\t\tsnapAfter?: ISashDragSnapState\n\t): number {\n\t\tif (index < 0 || index >= this.viewItems.length) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst upIndexes = range(index, -1);\n\t\tconst downIndexes = range(index + 1, this.viewItems.length);\n\n\t\tif (highPriorityIndexes) {\n\t\t\tfor (const index of highPriorityIndexes) {\n\t\t\t\tpushToStart(upIndexes, index);\n\t\t\t\tpushToStart(downIndexes, index);\n\t\t\t}\n\t\t}\n\n\t\tif (lowPriorityIndexes) {\n\t\t\tfor (const index of lowPriorityIndexes) {\n\t\t\t\tpushToEnd(upIndexes, index);\n\t\t\t\tpushToEnd(downIndexes, index);\n\t\t\t}\n\t\t}\n\n\t\tconst upItems = upIndexes.map(i => this.viewItems[i]);\n\t\tconst upSizes = upIndexes.map(i => sizes[i]);\n\n\t\tconst downItems = downIndexes.map(i => this.viewItems[i]);\n\t\tconst downSizes = downIndexes.map(i => sizes[i]);\n\n\t\tconst minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].minimumSize - sizes[i]), 0);\n\t\tconst maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].maximumSize - sizes[i]), 0);\n\t\tconst maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].minimumSize), 0);\n\t\tconst minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].maximumSize), 0);\n\t\tconst minDelta = Math.max(minDeltaUp, minDeltaDown, overloadMinDelta);\n\t\tconst maxDelta = Math.min(maxDeltaDown, maxDeltaUp, overloadMaxDelta);\n\n\t\tlet snapped = false;\n\n\t\tif (snapBefore) {\n\t\t\tconst snapView = this.viewItems[snapBefore.index];\n\t\t\tconst visible = delta >= snapBefore.limitDelta;\n\t\t\tsnapped = visible !== snapView.visible;\n\t\t\tsnapView.setVisible(visible, snapBefore.size);\n\t\t}\n\n\t\tif (!snapped && snapAfter) {\n\t\t\tconst snapView = this.viewItems[snapAfter.index];\n\t\t\tconst visible = delta < snapAfter.limitDelta;\n\t\t\tsnapped = visible !== snapView.visible;\n\t\t\tsnapView.setVisible(visible, snapAfter.size);\n\t\t}\n\n\t\tif (snapped) {\n\t\t\treturn this.resize(index, delta, sizes, lowPriorityIndexes, highPriorityIndexes, overloadMinDelta, overloadMaxDelta);\n\t\t}\n\n\t\tdelta = clamp(delta, minDelta, maxDelta);\n\n\t\tfor (let i = 0, deltaUp = delta; i < upItems.length; i++) {\n\t\t\tconst item = upItems[i];\n\t\t\tconst size = clamp(upSizes[i] + deltaUp, item.minimumSize, item.maximumSize);\n\t\t\tconst viewDelta = size - upSizes[i];\n\n\t\t\tdeltaUp -= viewDelta;\n\t\t\titem.size = size;\n\t\t}\n\n\t\tfor (let i = 0, deltaDown = delta; i < downItems.length; i++) {\n\t\t\tconst item = downItems[i];\n\t\t\tconst size = clamp(downSizes[i] - deltaDown, item.minimumSize, item.maximumSize);\n\t\t\tconst viewDelta = size - downSizes[i];\n\n\t\t\tdeltaDown += viewDelta;\n\t\t\titem.size = size;\n\t\t}\n\n\t\treturn delta;\n\t}\n\n\tprivate distributeEmptySpace(lowPriorityIndex?: number): void {\n\t\tconst contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);\n\t\tlet emptyDelta = this.size - contentSize;\n\n\t\tconst indexes = range(this.viewItems.length - 1, -1);\n\t\tconst lowPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.Low);\n\t\tconst highPriorityIndexes = indexes.filter(i => this.viewItems[i].priority === LayoutPriority.High);\n\n\t\tfor (const index of highPriorityIndexes) {\n\t\t\tpushToStart(indexes, index);\n\t\t}\n\n\t\tfor (const index of lowPriorityIndexes) {\n\t\t\tpushToEnd(indexes, index);\n\t\t}\n\n\t\tif (typeof lowPriorityIndex === 'number') {\n\t\t\tpushToEnd(indexes, lowPriorityIndex);\n\t\t}\n\n\t\tfor (let i = 0; emptyDelta !== 0 && i < indexes.length; i++) {\n\t\t\tconst item = this.viewItems[indexes[i]];\n\t\t\tconst size = clamp(item.size + emptyDelta, item.minimumSize, item.maximumSize);\n\t\t\tconst viewDelta = size - item.size;\n\n\t\t\temptyDelta -= viewDelta;\n\t\t\titem.size = size;\n\t\t}\n\t}\n\n\tprivate layoutViews(): void {\n\t\t// Save new content size\n\t\tthis.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);\n\n\t\t// Layout views\n\t\tlet offset = 0;\n\n\t\tfor (const viewItem of this.viewItems) {\n\t\t\tviewItem.layout(offset, this.layoutContext);\n\t\t\toffset += viewItem.size;\n\t\t}\n\n\t\t// Layout sashes\n\t\tthis.sashItems.forEach(item => item.sash.layout());\n\t\tthis.updateSashEnablement();\n\t\tthis.updateScrollableElement();\n\t}\n\n\tprivate updateScrollableElement(): void {\n\t\tif (this.orientation === Orientation.VERTICAL) {\n\t\t\tthis.scrollableElement.setScrollDimensions({\n\t\t\t\theight: this.size,\n\t\t\t\tscrollHeight: this.contentSize\n\t\t\t});\n\t\t} else {\n\t\t\tthis.scrollableElement.setScrollDimensions({\n\t\t\t\twidth: this.size,\n\t\t\t\tscrollWidth: this.contentSize\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate updateSashEnablement(): void {\n\t\tlet previous = false;\n\t\tconst collapsesDown = this.viewItems.map(i => previous = (i.size - i.minimumSize > 0) || previous);\n\n\t\tprevious = false;\n\t\tconst expandsDown = this.viewItems.map(i => previous = (i.maximumSize - i.size > 0) || previous);\n\n\t\tconst reverseViews = [...this.viewItems].reverse();\n\t\tprevious = false;\n\t\tconst collapsesUp = reverseViews.map(i => previous = (i.size - i.minimumSize > 0) || previous).reverse();\n\n\t\tprevious = false;\n\t\tconst expandsUp = reverseViews.map(i => previous = (i.maximumSize - i.size > 0) || previous).reverse();\n\n\t\tlet position = 0;\n\t\tfor (let index = 0; index < this.sashItems.length; index++) {\n\t\t\tconst { sash } = this.sashItems[index];\n\t\t\tconst viewItem = this.viewItems[index];\n\t\t\tposition += viewItem.size;\n\n\t\t\tconst min = !(collapsesDown[index] && expandsUp[index + 1]);\n\t\t\tconst max = !(expandsDown[index] && collapsesUp[index + 1]);\n\n\t\t\tif (min && max) {\n\t\t\t\tconst upIndexes = range(index, -1);\n\t\t\t\tconst downIndexes = range(index + 1, this.viewItems.length);\n\t\t\t\tconst snapBeforeIndex = this.findFirstSnapIndex(upIndexes);\n\t\t\t\tconst snapAfterIndex = this.findFirstSnapIndex(downIndexes);\n\n\t\t\t\tconst snappedBefore = typeof snapBeforeIndex === 'number' && !this.viewItems[snapBeforeIndex].visible;\n\t\t\t\tconst snappedAfter = typeof snapAfterIndex === 'number' && !this.viewItems[snapAfterIndex].visible;\n\n\t\t\t\tif (snappedBefore && collapsesUp[index] && (position > 0 || this.startSnappingEnabled)) {\n\t\t\t\t\tsash.state = SashState.AtMinimum;\n\t\t\t\t} else if (snappedAfter && collapsesDown[index] && (position < this.contentSize || this.endSnappingEnabled)) {\n\t\t\t\t\tsash.state = SashState.AtMaximum;\n\t\t\t\t} else {\n\t\t\t\t\tsash.state = SashState.Disabled;\n\t\t\t\t}\n\t\t\t} else if (min && !max) {\n\t\t\t\tsash.state = SashState.AtMinimum;\n\t\t\t} else if (!min && max) {\n\t\t\t\tsash.state = SashState.AtMaximum;\n\t\t\t} else {\n\t\t\t\tsash.state = SashState.Enabled;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getSashPosition(sash: Sash): number {\n\t\tlet position = 0;\n\n\t\tfor (let i = 0; i < this.sashItems.length; i++) {\n\t\t\tposition += this.viewItems[i].size;\n\n\t\t\tif (this.sashItems[i].sash === sash) {\n\t\t\t\treturn position;\n\t\t\t}\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\tprivate findFirstSnapIndex(indexes: number[]): number | undefined {\n\t\t// visible views first\n\t\tfor (const index of indexes) {\n\t\t\tconst viewItem = this.viewItems[index];\n\n\t\t\tif (!viewItem.visible) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (viewItem.snap) {\n\t\t\t\treturn index;\n\t\t\t}\n\t\t}\n\n\t\t// then, hidden views\n\t\tfor (const index of indexes) {\n\t\t\tconst viewItem = this.viewItems[index];\n\n\t\t\tif (viewItem.visible && viewItem.maximumSize - viewItem.minimumSize > 0) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tif (!viewItem.visible && viewItem.snap) {\n\t\t\t\treturn index;\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\n\t\tthis.viewItems.forEach(i => i.dispose());\n\t\tthis.viewItems = [];\n\n\t\tthis.sashItems.forEach(i => i.disposable.dispose());\n\t\tthis.sashItems = [];\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { $, append, clearNode, createStyleSheet } from 'vs/base/browser/dom';\nimport { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';\nimport { IListOptions, IListOptionsUpdate, IListStyles, List } from 'vs/base/browser/ui/list/listWidget';\nimport { ISplitViewDescriptor, IView, Orientation, SplitView } from 'vs/base/browser/ui/splitview/splitview';\nimport { ITableColumn, ITableEvent, ITableMouseEvent, ITableRenderer, ITableVirtualDelegate } from 'vs/base/browser/ui/table/table';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';\nimport { ScrollbarVisibility } from 'vs/base/common/scrollable';\nimport { ISpliceable } from 'vs/base/common/sequence';\nimport { IThemable } from 'vs/base/common/styler';\nimport 'vs/css!./table';\n\n// TODO@joao\ntype TCell = any;\n\ninterface RowTemplateData {\n\treadonly container: HTMLElement;\n\treadonly cellContainers: HTMLElement[];\n\treadonly cellTemplateData: unknown[];\n}\n\nclass TableListRenderer implements IListRenderer {\n\n\tstatic TemplateId = 'row';\n\treadonly templateId = TableListRenderer.TemplateId;\n\tprivate renderers: ITableRenderer[];\n\tprivate renderedTemplates = new Set();\n\n\tconstructor(\n\t\tprivate columns: ITableColumn[],\n\t\trenderers: ITableRenderer[],\n\t\tprivate getColumnSize: (index: number) => number\n\t) {\n\t\tconst rendererMap = new Map(renderers.map(r => [r.templateId, r]));\n\t\tthis.renderers = [];\n\n\t\tfor (const column of columns) {\n\t\t\tconst renderer = rendererMap.get(column.templateId);\n\n\t\t\tif (!renderer) {\n\t\t\t\tthrow new Error(`Table cell renderer for template id ${column.templateId} not found.`);\n\t\t\t}\n\n\t\t\tthis.renderers.push(renderer);\n\t\t}\n\t}\n\n\trenderTemplate(container: HTMLElement) {\n\t\tconst rowContainer = append(container, $('.monaco-table-tr'));\n\t\tconst cellContainers: HTMLElement[] = [];\n\t\tconst cellTemplateData: unknown[] = [];\n\n\t\tfor (let i = 0; i < this.columns.length; i++) {\n\t\t\tconst renderer = this.renderers[i];\n\t\t\tconst cellContainer = append(rowContainer, $('.monaco-table-td', { 'data-col-index': i }));\n\n\t\t\tcellContainer.style.width = `${this.getColumnSize(i)}px`;\n\t\t\tcellContainers.push(cellContainer);\n\t\t\tcellTemplateData.push(renderer.renderTemplate(cellContainer));\n\t\t}\n\n\t\tconst result = { container, cellContainers, cellTemplateData };\n\t\tthis.renderedTemplates.add(result);\n\n\t\treturn result;\n\t}\n\n\trenderElement(element: TRow, index: number, templateData: RowTemplateData, height: number | undefined): void {\n\t\tfor (let i = 0; i < this.columns.length; i++) {\n\t\t\tconst column = this.columns[i];\n\t\t\tconst cell = column.project(element);\n\t\t\tconst renderer = this.renderers[i];\n\t\t\trenderer.renderElement(cell, index, templateData.cellTemplateData[i], height);\n\t\t}\n\t}\n\n\tdisposeElement(element: TRow, index: number, templateData: RowTemplateData, height: number | undefined): void {\n\t\tfor (let i = 0; i < this.columns.length; i++) {\n\t\t\tconst renderer = this.renderers[i];\n\n\t\t\tif (renderer.disposeElement) {\n\t\t\t\tconst column = this.columns[i];\n\t\t\t\tconst cell = column.project(element);\n\n\t\t\t\trenderer.disposeElement(cell, index, templateData.cellTemplateData[i], height);\n\t\t\t}\n\t\t}\n\t}\n\n\tdisposeTemplate(templateData: RowTemplateData): void {\n\t\tfor (let i = 0; i < this.columns.length; i++) {\n\t\t\tconst renderer = this.renderers[i];\n\t\t\trenderer.disposeTemplate(templateData.cellTemplateData[i]);\n\t\t}\n\n\t\tclearNode(templateData.container);\n\t\tthis.renderedTemplates.delete(templateData);\n\t}\n\n\tlayoutColumn(index: number, size: number): void {\n\t\tfor (const { cellContainers } of this.renderedTemplates) {\n\t\t\tcellContainers[index].style.width = `${size}px`;\n\t\t}\n\t}\n}\n\nfunction asListVirtualDelegate(delegate: ITableVirtualDelegate): IListVirtualDelegate {\n\treturn {\n\t\tgetHeight(row) { return delegate.getHeight(row); },\n\t\tgetTemplateId() { return TableListRenderer.TemplateId; },\n\t};\n}\n\nclass ColumnHeader implements IView {\n\n\treadonly element: HTMLElement;\n\n\tget minimumSize() { return this.column.minimumWidth ?? 120; }\n\tget maximumSize() { return this.column.maximumWidth ?? Number.POSITIVE_INFINITY; }\n\tget onDidChange() { return this.column.onDidChangeWidthConstraints ?? Event.None; }\n\n\tprivate _onDidLayout = new Emitter<[number, number]>();\n\treadonly onDidLayout = this._onDidLayout.event;\n\n\tconstructor(readonly column: ITableColumn, private index: number) {\n\t\tthis.element = $('.monaco-table-th', { 'data-col-index': index, title: column.tooltip }, column.label);\n\t}\n\n\tlayout(size: number): void {\n\t\tthis._onDidLayout.fire([this.index, size]);\n\t}\n}\n\nexport interface ITableOptions extends IListOptions { }\nexport interface ITableOptionsUpdate extends IListOptionsUpdate { }\nexport interface ITableStyles extends IListStyles { }\n\nexport class Table implements ISpliceable, IThemable, IDisposable {\n\n\tprivate static InstanceCount = 0;\n\treadonly domId = `table_id_${++Table.InstanceCount}`;\n\n\treadonly domNode: HTMLElement;\n\tprivate splitview: SplitView;\n\tprivate list: List;\n\tprivate styleElement: HTMLStyleElement;\n\tprotected readonly disposables = new DisposableStore();\n\n\tprivate cachedWidth: number = 0;\n\tprivate cachedHeight: number = 0;\n\n\tget onDidChangeFocus(): Event> { return this.list.onDidChangeFocus; }\n\tget onDidChangeSelection(): Event> { return this.list.onDidChangeSelection; }\n\tget onMouseDblClick(): Event> { return this.list.onMouseDblClick; }\n\tget onPointer(): Event> { return this.list.onPointer; }\n\n\tget onDidFocus(): Event { return this.list.onDidFocus; }\n\tget onDidDispose(): Event { return this.list.onDidDispose; }\n\n\tconstructor(\n\t\tuser: string,\n\t\tcontainer: HTMLElement,\n\t\tprivate virtualDelegate: ITableVirtualDelegate,\n\t\tcolumns: ITableColumn[],\n\t\trenderers: ITableRenderer[],\n\t\t_options?: ITableOptions\n\t) {\n\t\tthis.domNode = append(container, $(`.monaco-table.${this.domId}`));\n\n\t\tconst headers = columns.map((c, i) => new ColumnHeader(c, i));\n\t\tconst descriptor: ISplitViewDescriptor = {\n\t\t\tsize: headers.reduce((a, b) => a + b.column.weight, 0),\n\t\t\tviews: headers.map(view => ({ size: view.column.weight, view }))\n\t\t};\n\n\t\tthis.splitview = this.disposables.add(new SplitView(this.domNode, {\n\t\t\torientation: Orientation.HORIZONTAL,\n\t\t\tscrollbarVisibility: ScrollbarVisibility.Hidden,\n\t\t\tgetSashOrthogonalSize: () => this.cachedHeight,\n\t\t\tdescriptor\n\t\t}));\n\n\t\tthis.splitview.el.style.height = `${virtualDelegate.headerRowHeight}px`;\n\t\tthis.splitview.el.style.lineHeight = `${virtualDelegate.headerRowHeight}px`;\n\n\t\tconst renderer = new TableListRenderer(columns, renderers, i => this.splitview.getViewSize(i));\n\t\tthis.list = this.disposables.add(new List(user, this.domNode, asListVirtualDelegate(virtualDelegate), [renderer], _options));\n\n\t\tEvent.any(...headers.map(h => h.onDidLayout))\n\t\t\t(([index, size]) => renderer.layoutColumn(index, size), null, this.disposables);\n\n\t\tthis.splitview.onDidSashReset(index => {\n\t\t\tconst totalWeight = columns.reduce((r, c) => r + c.weight, 0);\n\t\t\tconst size = columns[index].weight / totalWeight * this.cachedWidth;\n\t\t\tthis.splitview.resizeView(index, size);\n\t\t}, null, this.disposables);\n\n\t\tthis.styleElement = createStyleSheet(this.domNode);\n\t\tthis.style({});\n\t}\n\n\tupdateOptions(options: ITableOptionsUpdate): void {\n\t\tthis.list.updateOptions(options);\n\t}\n\n\tsplice(start: number, deleteCount: number, elements: TRow[] = []): void {\n\t\tthis.list.splice(start, deleteCount, elements);\n\t}\n\n\tgetHTMLElement(): HTMLElement {\n\t\treturn this.domNode;\n\t}\n\n\tstyle(styles: ITableStyles): void {\n\t\tconst content: string[] = [];\n\n\t\tcontent.push(`.monaco-table.${this.domId} > .monaco-split-view2 .monaco-sash.vertical::before {\n\t\t\ttop: ${this.virtualDelegate.headerRowHeight + 1}px;\n\t\t\theight: calc(100% - ${this.virtualDelegate.headerRowHeight}px);\n\t\t}`);\n\n\t\tthis.styleElement.textContent = content.join('\\n');\n\t\tthis.list.style(styles);\n\t}\n\n\tgetSelectedElements(): TRow[] {\n\t\treturn this.list.getSelectedElements();\n\t}\n\n\tgetSelection(): number[] {\n\t\treturn this.list.getSelection();\n\t}\n\n\tgetFocus(): number[] {\n\t\treturn this.list.getFocus();\n\t}\n\n\tdispose(): void {\n\t\tthis.disposables.dispose();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { IdGenerator } from 'vs/base/common/idGenerator';\nimport { URI } from 'vs/base/common/uri';\nimport 'vs/css!./media/quickInput';\n\nconst iconPathToClass: Record = {};\nconst iconClassGenerator = new IdGenerator('quick-input-button-icon-');\n\nexport function getIconClass(iconPath: { dark: URI; light?: URI; } | undefined): string | undefined {\n\tif (!iconPath) {\n\t\treturn undefined;\n\t}\n\tlet iconClass: string;\n\n\tconst key = iconPath.dark.toString();\n\tif (iconPathToClass[key]) {\n\t\ticonClass = iconPathToClass[key];\n\t} else {\n\t\ticonClass = iconClassGenerator.nextId();\n\t\tdom.createCSSRule(`.${iconClass}`, `background-image: ${dom.asCSSUrl(iconPath.light || iconPath.dark)}`);\n\t\tdom.createCSSRule(`.vs-dark .${iconClass}, .hc-black .${iconClass}`, `background-image: ${dom.asCSSUrl(iconPath.dark)}`);\n\t\ticonPathToClass[key] = iconClass;\n\t}\n\n\treturn iconClass;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { IDimension } from 'vs/editor/common/core/dimension';\nimport { Emitter, Event } from 'vs/base/common/event';\n\nexport class ElementSizeObserver extends Disposable {\n\n\tprivate _onDidChange = this._register(new Emitter());\n\tpublic readonly onDidChange: Event = this._onDidChange.event;\n\n\tprivate readonly _referenceDomElement: HTMLElement | null;\n\tprivate _width: number;\n\tprivate _height: number;\n\tprivate _resizeObserver: ResizeObserver | null;\n\n\tconstructor(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined) {\n\t\tsuper();\n\t\tthis._referenceDomElement = referenceDomElement;\n\t\tthis._width = -1;\n\t\tthis._height = -1;\n\t\tthis._resizeObserver = null;\n\t\tthis.measureReferenceDomElement(false, dimension);\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis.stopObserving();\n\t\tsuper.dispose();\n\t}\n\n\tpublic getWidth(): number {\n\t\treturn this._width;\n\t}\n\n\tpublic getHeight(): number {\n\t\treturn this._height;\n\t}\n\n\tpublic startObserving(): void {\n\t\tif (!this._resizeObserver && this._referenceDomElement) {\n\t\t\tthis._resizeObserver = new ResizeObserver((entries) => {\n\t\t\t\tif (entries && entries[0] && entries[0].contentRect) {\n\t\t\t\t\tthis.observe({ width: entries[0].contentRect.width, height: entries[0].contentRect.height });\n\t\t\t\t} else {\n\t\t\t\t\tthis.observe();\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis._resizeObserver.observe(this._referenceDomElement);\n\t\t}\n\t}\n\n\tpublic stopObserving(): void {\n\t\tif (this._resizeObserver) {\n\t\t\tthis._resizeObserver.disconnect();\n\t\t\tthis._resizeObserver = null;\n\t\t}\n\t}\n\n\tpublic observe(dimension?: IDimension): void {\n\t\tthis.measureReferenceDomElement(true, dimension);\n\t}\n\n\tprivate measureReferenceDomElement(emitEvent: boolean, dimension?: IDimension): void {\n\t\tlet observedWidth = 0;\n\t\tlet observedHeight = 0;\n\t\tif (dimension) {\n\t\t\tobservedWidth = dimension.width;\n\t\t\tobservedHeight = dimension.height;\n\t\t} else if (this._referenceDomElement) {\n\t\t\tobservedWidth = this._referenceDomElement.clientWidth;\n\t\t\tobservedHeight = this._referenceDomElement.clientHeight;\n\t\t}\n\t\tobservedWidth = Math.max(5, observedWidth);\n\t\tobservedHeight = Math.max(5, observedHeight);\n\t\tif (this._width !== observedWidth || this._height !== observedHeight) {\n\t\t\tthis._width = observedWidth;\n\t\t\tthis._height = observedHeight;\n\t\t\tif (emitEvent) {\n\t\t\t\tthis._onDidChange.fire();\n\t\t\t}\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { forEach } from 'vs/base/common/collections';\nimport { IEditorOptions } from 'vs/editor/common/config/editorOptions';\n\n/**\n * Compatibility with old options\n */\nexport function migrateOptions(options: IEditorOptions): void {\n\tconst wordWrap = options.wordWrap;\n\tif (wordWrap === true) {\n\t\toptions.wordWrap = 'on';\n\t} else if (wordWrap === false) {\n\t\toptions.wordWrap = 'off';\n\t}\n\n\tconst lineNumbers = options.lineNumbers;\n\tif (lineNumbers === true) {\n\t\toptions.lineNumbers = 'on';\n\t} else if (lineNumbers === false) {\n\t\toptions.lineNumbers = 'off';\n\t}\n\n\tconst autoClosingBrackets = options.autoClosingBrackets;\n\tif (autoClosingBrackets === false) {\n\t\toptions.autoClosingBrackets = 'never';\n\t\toptions.autoClosingQuotes = 'never';\n\t\toptions.autoSurround = 'never';\n\t}\n\n\tconst cursorBlinking = options.cursorBlinking;\n\tif (cursorBlinking === 'visible') {\n\t\toptions.cursorBlinking = 'solid';\n\t}\n\n\tconst renderWhitespace = options.renderWhitespace;\n\tif (renderWhitespace === true) {\n\t\toptions.renderWhitespace = 'boundary';\n\t} else if (renderWhitespace === false) {\n\t\toptions.renderWhitespace = 'none';\n\t}\n\n\tconst renderLineHighlight = options.renderLineHighlight;\n\tif (renderLineHighlight === true) {\n\t\toptions.renderLineHighlight = 'line';\n\t} else if (renderLineHighlight === false) {\n\t\toptions.renderLineHighlight = 'none';\n\t}\n\n\tconst acceptSuggestionOnEnter = options.acceptSuggestionOnEnter;\n\tif (acceptSuggestionOnEnter === true) {\n\t\toptions.acceptSuggestionOnEnter = 'on';\n\t} else if (acceptSuggestionOnEnter === false) {\n\t\toptions.acceptSuggestionOnEnter = 'off';\n\t}\n\n\tconst tabCompletion = options.tabCompletion;\n\tif (tabCompletion === false) {\n\t\toptions.tabCompletion = 'off';\n\t} else if (tabCompletion === true) {\n\t\toptions.tabCompletion = 'onlySnippets';\n\t}\n\n\tconst suggest = options.suggest;\n\tif (suggest && typeof (suggest).filteredTypes === 'object' && (suggest).filteredTypes) {\n\t\tconst mapping: Record = {};\n\t\tmapping['method'] = 'showMethods';\n\t\tmapping['function'] = 'showFunctions';\n\t\tmapping['constructor'] = 'showConstructors';\n\t\tmapping['deprecated'] = 'showDeprecated';\n\t\tmapping['field'] = 'showFields';\n\t\tmapping['variable'] = 'showVariables';\n\t\tmapping['class'] = 'showClasses';\n\t\tmapping['struct'] = 'showStructs';\n\t\tmapping['interface'] = 'showInterfaces';\n\t\tmapping['module'] = 'showModules';\n\t\tmapping['property'] = 'showProperties';\n\t\tmapping['event'] = 'showEvents';\n\t\tmapping['operator'] = 'showOperators';\n\t\tmapping['unit'] = 'showUnits';\n\t\tmapping['value'] = 'showValues';\n\t\tmapping['constant'] = 'showConstants';\n\t\tmapping['enum'] = 'showEnums';\n\t\tmapping['enumMember'] = 'showEnumMembers';\n\t\tmapping['keyword'] = 'showKeywords';\n\t\tmapping['text'] = 'showWords';\n\t\tmapping['color'] = 'showColors';\n\t\tmapping['file'] = 'showFiles';\n\t\tmapping['reference'] = 'showReferences';\n\t\tmapping['folder'] = 'showFolders';\n\t\tmapping['typeParameter'] = 'showTypeParameters';\n\t\tmapping['snippet'] = 'showSnippets';\n\t\tforEach(mapping, entry => {\n\t\t\tconst value = (suggest).filteredTypes[entry.key];\n\t\t\tif (value === false) {\n\t\t\t\t(suggest)[entry.value] = value;\n\t\t\t}\n\t\t});\n\t\t// delete (suggest).filteredTypes;\n\t}\n\n\tconst hover = options.hover;\n\tif (hover === true) {\n\t\toptions.hover = {\n\t\t\tenabled: true\n\t\t};\n\t} else if (hover === false) {\n\t\toptions.hover = {\n\t\t\tenabled: false\n\t\t};\n\t}\n\n\tconst parameterHints = options.parameterHints;\n\tif (parameterHints === true) {\n\t\toptions.parameterHints = {\n\t\t\tenabled: true\n\t\t};\n\t} else if (parameterHints === false) {\n\t\toptions.parameterHints = {\n\t\t\tenabled: false\n\t\t};\n\t}\n\n\tconst autoIndent = options.autoIndent;\n\tif (autoIndent === true) {\n\t\toptions.autoIndent = 'full';\n\t} else if (autoIndent === false) {\n\t\toptions.autoIndent = 'advanced';\n\t}\n\n\tconst matchBrackets = options.matchBrackets;\n\tif (matchBrackets === true) {\n\t\toptions.matchBrackets = 'always';\n\t} else if (matchBrackets === false) {\n\t\toptions.matchBrackets = 'never';\n\t}\n\n\tconst { renderIndentGuides, highlightActiveIndentGuide } = options as any as {\n\t\trenderIndentGuides: boolean;\n\t\thighlightActiveIndentGuide: boolean;\n\t};\n\tif (!options.guides) {\n\t\toptions.guides = {};\n\t}\n\n\tif (renderIndentGuides !== undefined) {\n\t\toptions.guides.indentation = !!renderIndentGuides;\n\t}\n\tif (highlightActiveIndentGuide !== undefined) {\n\t\toptions.guides.highlightActiveIndentation = !!highlightActiveIndentGuide;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\n\nclass TabFocusImpl {\n\tprivate _tabFocus: boolean = false;\n\n\tprivate readonly _onDidChangeTabFocus = new Emitter();\n\tpublic readonly onDidChangeTabFocus: Event = this._onDidChangeTabFocus.event;\n\n\tpublic getTabFocusMode(): boolean {\n\t\treturn this._tabFocus;\n\t}\n\n\tpublic setTabFocusMode(tabFocusMode: boolean): void {\n\t\tif (this._tabFocus === tabFocusMode) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._tabFocus = tabFocusMode;\n\t\tthis._onDidChangeTabFocus.fire(this._tabFocus);\n\t}\n}\n\n/**\n * Control what pressing Tab does.\n * If it is false, pressing Tab or Shift-Tab will be handled by the editor.\n * If it is true, pressing Tab or Shift-Tab will move the browser focus.\n * Defaults to false.\n */\nexport const TabFocus = new TabFocusImpl();\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { Position } from 'vs/editor/common/core/position';\n\nexport class StableEditorScrollState {\n\n\tpublic static capture(editor: ICodeEditor): StableEditorScrollState {\n\t\tlet visiblePosition: Position | null = null;\n\t\tlet visiblePositionScrollDelta = 0;\n\t\tif (editor.getScrollTop() !== 0) {\n\t\t\tconst visibleRanges = editor.getVisibleRanges();\n\t\t\tif (visibleRanges.length > 0) {\n\t\t\t\tvisiblePosition = visibleRanges[0].getStartPosition();\n\t\t\t\tconst visiblePositionScrollTop = editor.getTopForPosition(visiblePosition.lineNumber, visiblePosition.column);\n\t\t\t\tvisiblePositionScrollDelta = editor.getScrollTop() - visiblePositionScrollTop;\n\t\t\t}\n\t\t}\n\t\treturn new StableEditorScrollState(visiblePosition, visiblePositionScrollDelta, editor.getPosition());\n\t}\n\n\tconstructor(\n\t\tprivate readonly _visiblePosition: Position | null,\n\t\tprivate readonly _visiblePositionScrollDelta: number,\n\t\tprivate readonly _cursorPosition: Position | null\n\t) {\n\t}\n\n\tpublic restore(editor: ICodeEditor): void {\n\t\tif (this._visiblePosition) {\n\t\t\tconst visiblePositionScrollTop = editor.getTopForPosition(this._visiblePosition.lineNumber, this._visiblePosition.column);\n\t\t\teditor.setScrollTop(visiblePositionScrollTop + this._visiblePositionScrollDelta);\n\t\t}\n\t}\n\n\tpublic restoreRelativeVerticalPositionOfCursor(editor: ICodeEditor): void {\n\t\tconst currentCursorPosition = editor.getPosition();\n\n\t\tif (!this._cursorPosition || !currentCursorPosition) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst offset = editor.getTopForLineNumber(currentCursorPosition.lineNumber) - editor.getTopForLineNumber(this._cursorPosition.lineNumber);\n\t\teditor.setScrollTop(editor.getScrollTop() + offset);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';\nimport { IViewLayout, ViewModelDecoration } from 'vs/editor/common/viewModel/viewModel';\n\nexport interface IViewLines {\n\tlinesVisibleRangesForRange(range: Range, includeNewLines: boolean): LineVisibleRanges[] | null;\n\tvisibleRangeForPosition(position: Position): HorizontalPosition | null;\n}\n\nexport abstract class RestrictedRenderingContext {\n\t_restrictedRenderingContextBrand: void = undefined;\n\n\tpublic readonly viewportData: ViewportData;\n\n\tpublic readonly scrollWidth: number;\n\tpublic readonly scrollHeight: number;\n\n\tpublic readonly visibleRange: Range;\n\tpublic readonly bigNumbersDelta: number;\n\n\tpublic readonly scrollTop: number;\n\tpublic readonly scrollLeft: number;\n\n\tpublic readonly viewportWidth: number;\n\tpublic readonly viewportHeight: number;\n\n\tprivate readonly _viewLayout: IViewLayout;\n\n\tconstructor(viewLayout: IViewLayout, viewportData: ViewportData) {\n\t\tthis._viewLayout = viewLayout;\n\t\tthis.viewportData = viewportData;\n\n\t\tthis.scrollWidth = this._viewLayout.getScrollWidth();\n\t\tthis.scrollHeight = this._viewLayout.getScrollHeight();\n\n\t\tthis.visibleRange = this.viewportData.visibleRange;\n\t\tthis.bigNumbersDelta = this.viewportData.bigNumbersDelta;\n\n\t\tconst vInfo = this._viewLayout.getCurrentViewport();\n\t\tthis.scrollTop = vInfo.top;\n\t\tthis.scrollLeft = vInfo.left;\n\t\tthis.viewportWidth = vInfo.width;\n\t\tthis.viewportHeight = vInfo.height;\n\t}\n\n\tpublic getScrolledTopFromAbsoluteTop(absoluteTop: number): number {\n\t\treturn absoluteTop - this.scrollTop;\n\t}\n\n\tpublic getVerticalOffsetForLineNumber(lineNumber: number): number {\n\t\treturn this._viewLayout.getVerticalOffsetForLineNumber(lineNumber);\n\t}\n\n\tpublic getDecorationsInViewport(): ViewModelDecoration[] {\n\t\treturn this.viewportData.getDecorationsInViewport();\n\t}\n\n}\n\nexport class RenderingContext extends RestrictedRenderingContext {\n\t_renderingContextBrand: void = undefined;\n\n\tprivate readonly _viewLines: IViewLines;\n\n\tconstructor(viewLayout: IViewLayout, viewportData: ViewportData, viewLines: IViewLines) {\n\t\tsuper(viewLayout, viewportData);\n\t\tthis._viewLines = viewLines;\n\t}\n\n\tpublic linesVisibleRangesForRange(range: Range, includeNewLines: boolean): LineVisibleRanges[] | null {\n\t\treturn this._viewLines.linesVisibleRangesForRange(range, includeNewLines);\n\t}\n\n\tpublic visibleRangeForPosition(position: Position): HorizontalPosition | null {\n\t\treturn this._viewLines.visibleRangeForPosition(position);\n\t}\n}\n\nexport class LineVisibleRanges {\n\tconstructor(\n\t\tpublic readonly outsideRenderedLine: boolean,\n\t\tpublic readonly lineNumber: number,\n\t\tpublic readonly ranges: HorizontalRange[]\n\t) { }\n}\n\nexport class HorizontalRange {\n\t_horizontalRangeBrand: void = undefined;\n\n\tpublic left: number;\n\tpublic width: number;\n\n\tpublic static from(ranges: FloatHorizontalRange[]): HorizontalRange[] {\n\t\tconst result = new Array(ranges.length);\n\t\tfor (let i = 0, len = ranges.length; i < len; i++) {\n\t\t\tconst range = ranges[i];\n\t\t\tresult[i] = new HorizontalRange(range.left, range.width);\n\t\t}\n\t\treturn result;\n\t}\n\n\tconstructor(left: number, width: number) {\n\t\tthis.left = Math.round(left);\n\t\tthis.width = Math.round(width);\n\t}\n\n\tpublic toString(): string {\n\t\treturn `[${this.left},${this.width}]`;\n\t}\n}\n\nexport class FloatHorizontalRange {\n\t_floatHorizontalRangeBrand: void = undefined;\n\n\tpublic left: number;\n\tpublic width: number;\n\n\tconstructor(left: number, width: number) {\n\t\tthis.left = left;\n\t\tthis.width = width;\n\t}\n\n\tpublic toString(): string {\n\t\treturn `[${this.left},${this.width}]`;\n\t}\n\n\tpublic static compare(a: FloatHorizontalRange, b: FloatHorizontalRange): number {\n\t\treturn a.left - b.left;\n\t}\n}\n\nexport class HorizontalPosition {\n\tpublic outsideRenderedLine: boolean;\n\t/**\n\t * Math.round(this.originalLeft)\n\t */\n\tpublic left: number;\n\tpublic originalLeft: number;\n\n\tconstructor(outsideRenderedLine: boolean, left: number) {\n\t\tthis.outsideRenderedLine = outsideRenderedLine;\n\t\tthis.originalLeft = left;\n\t\tthis.left = Math.round(this.originalLeft);\n\t}\n}\n\nexport class VisibleRanges {\n\tconstructor(\n\t\tpublic readonly outsideRenderedLine: boolean,\n\t\tpublic readonly ranges: FloatHorizontalRange[]\n\t) {\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { IEditorMouseEvent, IMouseTarget, IPartialEditorMouseEvent } from 'vs/editor/browser/editorBrowser';\nimport { ICoordinatesConverter } from 'vs/editor/common/viewModel/viewModel';\nimport { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';\n\nexport interface EventCallback {\n\t(event: T): void;\n}\n\nexport class ViewUserInputEvents {\n\n\tpublic onKeyDown: EventCallback | null = null;\n\tpublic onKeyUp: EventCallback | null = null;\n\tpublic onContextMenu: EventCallback | null = null;\n\tpublic onMouseMove: EventCallback | null = null;\n\tpublic onMouseLeave: EventCallback | null = null;\n\tpublic onMouseDown: EventCallback | null = null;\n\tpublic onMouseUp: EventCallback | null = null;\n\tpublic onMouseDrag: EventCallback | null = null;\n\tpublic onMouseDrop: EventCallback | null = null;\n\tpublic onMouseDropCanceled: EventCallback | null = null;\n\tpublic onMouseWheel: EventCallback | null = null;\n\n\tprivate readonly _coordinatesConverter: ICoordinatesConverter;\n\n\tconstructor(coordinatesConverter: ICoordinatesConverter) {\n\t\tthis._coordinatesConverter = coordinatesConverter;\n\t}\n\n\tpublic emitKeyDown(e: IKeyboardEvent): void {\n\t\tif (this.onKeyDown) {\n\t\t\tthis.onKeyDown(e);\n\t\t}\n\t}\n\n\tpublic emitKeyUp(e: IKeyboardEvent): void {\n\t\tif (this.onKeyUp) {\n\t\t\tthis.onKeyUp(e);\n\t\t}\n\t}\n\n\tpublic emitContextMenu(e: IEditorMouseEvent): void {\n\t\tif (this.onContextMenu) {\n\t\t\tthis.onContextMenu(this._convertViewToModelMouseEvent(e));\n\t\t}\n\t}\n\n\tpublic emitMouseMove(e: IEditorMouseEvent): void {\n\t\tif (this.onMouseMove) {\n\t\t\tthis.onMouseMove(this._convertViewToModelMouseEvent(e));\n\t\t}\n\t}\n\n\tpublic emitMouseLeave(e: IPartialEditorMouseEvent): void {\n\t\tif (this.onMouseLeave) {\n\t\t\tthis.onMouseLeave(this._convertViewToModelMouseEvent(e));\n\t\t}\n\t}\n\n\tpublic emitMouseDown(e: IEditorMouseEvent): void {\n\t\tif (this.onMouseDown) {\n\t\t\tthis.onMouseDown(this._convertViewToModelMouseEvent(e));\n\t\t}\n\t}\n\n\tpublic emitMouseUp(e: IEditorMouseEvent): void {\n\t\tif (this.onMouseUp) {\n\t\t\tthis.onMouseUp(this._convertViewToModelMouseEvent(e));\n\t\t}\n\t}\n\n\tpublic emitMouseDrag(e: IEditorMouseEvent): void {\n\t\tif (this.onMouseDrag) {\n\t\t\tthis.onMouseDrag(this._convertViewToModelMouseEvent(e));\n\t\t}\n\t}\n\n\tpublic emitMouseDrop(e: IPartialEditorMouseEvent): void {\n\t\tif (this.onMouseDrop) {\n\t\t\tthis.onMouseDrop(this._convertViewToModelMouseEvent(e));\n\t\t}\n\t}\n\n\tpublic emitMouseDropCanceled(): void {\n\t\tif (this.onMouseDropCanceled) {\n\t\t\tthis.onMouseDropCanceled();\n\t\t}\n\t}\n\n\tpublic emitMouseWheel(e: IMouseWheelEvent): void {\n\t\tif (this.onMouseWheel) {\n\t\t\tthis.onMouseWheel(e);\n\t\t}\n\t}\n\n\tprivate _convertViewToModelMouseEvent(e: IEditorMouseEvent): IEditorMouseEvent;\n\tprivate _convertViewToModelMouseEvent(e: IPartialEditorMouseEvent): IPartialEditorMouseEvent;\n\tprivate _convertViewToModelMouseEvent(e: IEditorMouseEvent | IPartialEditorMouseEvent): IEditorMouseEvent | IPartialEditorMouseEvent {\n\t\tif (e.target) {\n\t\t\treturn {\n\t\t\t\tevent: e.event,\n\t\t\t\ttarget: this._convertViewToModelMouseTarget(e.target)\n\t\t\t};\n\t\t}\n\t\treturn e;\n\t}\n\n\tprivate _convertViewToModelMouseTarget(target: IMouseTarget): IMouseTarget {\n\t\treturn ViewUserInputEvents.convertViewToModelMouseTarget(target, this._coordinatesConverter);\n\t}\n\n\tpublic static convertViewToModelMouseTarget(target: IMouseTarget, coordinatesConverter: ICoordinatesConverter): IMouseTarget {\n\t\tconst result = { ...target };\n\t\tif (result.position) {\n\t\t\tresult.position = coordinatesConverter.convertViewPositionToModelPosition(result.position);\n\t\t}\n\t\tif (result.range) {\n\t\t\tresult.range = coordinatesConverter.convertViewRangeToModelRange(result.range);\n\t\t}\n\t\treturn result;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Constants } from 'vs/base/common/uint';\nimport { FloatHorizontalRange } from 'vs/editor/browser/view/renderingContext';\n\nexport class RangeUtil {\n\n\t/**\n\t * Reusing the same range here\n\t * because IE is buggy and constantly freezes when using a large number\n\t * of ranges and calling .detach on them\n\t */\n\tprivate static _handyReadyRange: Range;\n\n\tprivate static _createRange(): Range {\n\t\tif (!this._handyReadyRange) {\n\t\t\tthis._handyReadyRange = document.createRange();\n\t\t}\n\t\treturn this._handyReadyRange;\n\t}\n\n\tprivate static _detachRange(range: Range, endNode: HTMLElement): void {\n\t\t// Move range out of the span node, IE doesn't like having many ranges in\n\t\t// the same spot and will act badly for lines containing dashes ('-')\n\t\trange.selectNodeContents(endNode);\n\t}\n\n\tprivate static _readClientRects(startElement: Node, startOffset: number, endElement: Node, endOffset: number, endNode: HTMLElement): DOMRectList | null {\n\t\tconst range = this._createRange();\n\t\ttry {\n\t\t\trange.setStart(startElement, startOffset);\n\t\t\trange.setEnd(endElement, endOffset);\n\n\t\t\treturn range.getClientRects();\n\t\t} catch (e) {\n\t\t\t// This is life ...\n\t\t\treturn null;\n\t\t} finally {\n\t\t\tthis._detachRange(range, endNode);\n\t\t}\n\t}\n\n\tprivate static _mergeAdjacentRanges(ranges: FloatHorizontalRange[]): FloatHorizontalRange[] {\n\t\tif (ranges.length === 1) {\n\t\t\t// There is nothing to merge\n\t\t\treturn ranges;\n\t\t}\n\n\t\tranges.sort(FloatHorizontalRange.compare);\n\n\t\tconst result: FloatHorizontalRange[] = [];\n\t\tlet resultLen = 0;\n\t\tlet prev = ranges[0];\n\n\t\tfor (let i = 1, len = ranges.length; i < len; i++) {\n\t\t\tconst range = ranges[i];\n\t\t\tif (prev.left + prev.width + 0.9 /* account for browser's rounding errors*/ >= range.left) {\n\t\t\t\tprev.width = Math.max(prev.width, range.left + range.width - prev.left);\n\t\t\t} else {\n\t\t\t\tresult[resultLen++] = prev;\n\t\t\t\tprev = range;\n\t\t\t}\n\t\t}\n\n\t\tresult[resultLen++] = prev;\n\n\t\treturn result;\n\t}\n\n\tprivate static _createHorizontalRangesFromClientRects(clientRects: DOMRectList | null, clientRectDeltaLeft: number, clientRectScale: number): FloatHorizontalRange[] | null {\n\t\tif (!clientRects || clientRects.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// We go through FloatHorizontalRange because it has been observed in bi-di text\n\t\t// that the clientRects are not coming in sorted from the browser\n\n\t\tconst result: FloatHorizontalRange[] = [];\n\t\tfor (let i = 0, len = clientRects.length; i < len; i++) {\n\t\t\tconst clientRect = clientRects[i];\n\t\t\tresult[i] = new FloatHorizontalRange(Math.max(0, (clientRect.left - clientRectDeltaLeft) / clientRectScale), clientRect.width / clientRectScale);\n\t\t}\n\n\t\treturn this._mergeAdjacentRanges(result);\n\t}\n\n\tpublic static readHorizontalRanges(domNode: HTMLElement, startChildIndex: number, startOffset: number, endChildIndex: number, endOffset: number, clientRectDeltaLeft: number, clientRectScale: number, endNode: HTMLElement): FloatHorizontalRange[] | null {\n\t\t// Panic check\n\t\tconst min = 0;\n\t\tconst max = domNode.children.length - 1;\n\t\tif (min > max) {\n\t\t\treturn null;\n\t\t}\n\t\tstartChildIndex = Math.min(max, Math.max(min, startChildIndex));\n\t\tendChildIndex = Math.min(max, Math.max(min, endChildIndex));\n\n\t\tif (startChildIndex === endChildIndex && startOffset === endOffset && startOffset === 0 && !domNode.children[startChildIndex].firstChild) {\n\t\t\t// We must find the position at the beginning of a \n\t\t\t// To cover cases of empty s, avoid using a range and use the 's bounding box\n\t\t\tconst clientRects = domNode.children[startChildIndex].getClientRects();\n\t\t\treturn this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft, clientRectScale);\n\t\t}\n\n\t\t// If crossing over to a span only to select offset 0, then use the previous span's maximum offset\n\t\t// Chrome is buggy and doesn't handle 0 offsets well sometimes.\n\t\tif (startChildIndex !== endChildIndex) {\n\t\t\tif (endChildIndex > 0 && endOffset === 0) {\n\t\t\t\tendChildIndex--;\n\t\t\t\tendOffset = Constants.MAX_SAFE_SMALL_INTEGER;\n\t\t\t}\n\t\t}\n\n\t\tlet startElement = domNode.children[startChildIndex].firstChild;\n\t\tlet endElement = domNode.children[endChildIndex].firstChild;\n\n\t\tif (!startElement || !endElement) {\n\t\t\t// When having an empty (without any text content), try to move to the previous \n\t\t\tif (!startElement && startOffset === 0 && startChildIndex > 0) {\n\t\t\t\tstartElement = domNode.children[startChildIndex - 1].firstChild;\n\t\t\t\tstartOffset = Constants.MAX_SAFE_SMALL_INTEGER;\n\t\t\t}\n\t\t\tif (!endElement && endOffset === 0 && endChildIndex > 0) {\n\t\t\t\tendElement = domNode.children[endChildIndex - 1].firstChild;\n\t\t\t\tendOffset = Constants.MAX_SAFE_SMALL_INTEGER;\n\t\t\t}\n\t\t}\n\n\t\tif (!startElement || !endElement) {\n\t\t\treturn null;\n\t\t}\n\n\t\tstartOffset = Math.min(startElement.textContent!.length, Math.max(0, startOffset));\n\t\tendOffset = Math.min(endElement.textContent!.length, Math.max(0, endOffset));\n\n\t\tconst clientRects = this._readClientRects(startElement, startOffset, endElement, endOffset, endNode);\n\t\treturn this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft, clientRectScale);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport const enum Constants {\n\tSTART_CH_CODE = 32, // Space\n\tEND_CH_CODE = 126, // Tilde (~)\n\tUNKNOWN_CODE = 65533, // UTF placeholder code\n\tCHAR_COUNT = END_CH_CODE - START_CH_CODE + 2,\n\n\tSAMPLED_CHAR_HEIGHT = 16,\n\tSAMPLED_CHAR_WIDTH = 10,\n\n\tBASE_CHAR_HEIGHT = 2,\n\tBASE_CHAR_WIDTH = 1,\n\n\tRGBA_CHANNELS_CNT = 4,\n\tRGBA_SAMPLED_ROW_WIDTH = RGBA_CHANNELS_CNT * CHAR_COUNT * SAMPLED_CHAR_WIDTH\n}\n\nexport const allCharCodes: ReadonlyArray = (() => {\n\tconst v: number[] = [];\n\tfor (let i = Constants.START_CH_CODE; i <= Constants.END_CH_CODE; i++) {\n\t\tv.push(i);\n\t}\n\n\tv.push(Constants.UNKNOWN_CODE);\n\treturn v;\n})();\n\nexport const getCharIndex = (chCode: number, fontScale: number) => {\n\tchCode -= Constants.START_CH_CODE;\n\tif (chCode < 0 || chCode > Constants.CHAR_COUNT) {\n\t\tif (fontScale <= 2) {\n\t\t\t// for smaller scales, we can get away with using any ASCII character...\n\t\t\treturn (chCode + Constants.CHAR_COUNT) % Constants.CHAR_COUNT;\n\t\t}\n\t\treturn Constants.CHAR_COUNT - 1; // unknown symbol\n\t}\n\n\treturn chCode;\n};\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { RGBA8 } from 'vs/editor/common/core/rgba';\nimport { Constants, getCharIndex } from './minimapCharSheet';\nimport { toUint8 } from 'vs/base/common/uint';\n\nexport class MinimapCharRenderer {\n\t_minimapCharRendererBrand: void = undefined;\n\n\tprivate readonly charDataNormal: Uint8ClampedArray;\n\tprivate readonly charDataLight: Uint8ClampedArray;\n\n\tconstructor(charData: Uint8ClampedArray, public readonly scale: number) {\n\t\tthis.charDataNormal = MinimapCharRenderer.soften(charData, 12 / 15);\n\t\tthis.charDataLight = MinimapCharRenderer.soften(charData, 50 / 60);\n\t}\n\n\tprivate static soften(input: Uint8ClampedArray, ratio: number): Uint8ClampedArray {\n\t\tconst result = new Uint8ClampedArray(input.length);\n\t\tfor (let i = 0, len = input.length; i < len; i++) {\n\t\t\tresult[i] = toUint8(input[i] * ratio);\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic renderChar(\n\t\ttarget: ImageData,\n\t\tdx: number,\n\t\tdy: number,\n\t\tchCode: number,\n\t\tcolor: RGBA8,\n\t\tforegroundAlpha: number,\n\t\tbackgroundColor: RGBA8,\n\t\tbackgroundAlpha: number,\n\t\tfontScale: number,\n\t\tuseLighterFont: boolean,\n\t\tforce1pxHeight: boolean\n\t): void {\n\t\tconst charWidth = Constants.BASE_CHAR_WIDTH * this.scale;\n\t\tconst charHeight = Constants.BASE_CHAR_HEIGHT * this.scale;\n\t\tconst renderHeight = (force1pxHeight ? 1 : charHeight);\n\t\tif (dx + charWidth > target.width || dy + renderHeight > target.height) {\n\t\t\tconsole.warn('bad render request outside image data');\n\t\t\treturn;\n\t\t}\n\n\t\tconst charData = useLighterFont ? this.charDataLight : this.charDataNormal;\n\t\tconst charIndex = getCharIndex(chCode, fontScale);\n\n\t\tconst destWidth = target.width * Constants.RGBA_CHANNELS_CNT;\n\n\t\tconst backgroundR = backgroundColor.r;\n\t\tconst backgroundG = backgroundColor.g;\n\t\tconst backgroundB = backgroundColor.b;\n\n\t\tconst deltaR = color.r - backgroundR;\n\t\tconst deltaG = color.g - backgroundG;\n\t\tconst deltaB = color.b - backgroundB;\n\n\t\tconst destAlpha = Math.max(foregroundAlpha, backgroundAlpha);\n\n\t\tconst dest = target.data;\n\t\tlet sourceOffset = charIndex * charWidth * charHeight;\n\n\t\tlet row = dy * destWidth + dx * Constants.RGBA_CHANNELS_CNT;\n\t\tfor (let y = 0; y < renderHeight; y++) {\n\t\t\tlet column = row;\n\t\t\tfor (let x = 0; x < charWidth; x++) {\n\t\t\t\tconst c = (charData[sourceOffset++] / 255) * (foregroundAlpha / 255);\n\t\t\t\tdest[column++] = backgroundR + deltaR * c;\n\t\t\t\tdest[column++] = backgroundG + deltaG * c;\n\t\t\t\tdest[column++] = backgroundB + deltaB * c;\n\t\t\t\tdest[column++] = destAlpha;\n\t\t\t}\n\n\t\t\trow += destWidth;\n\t\t}\n\t}\n\n\tpublic blockRenderChar(\n\t\ttarget: ImageData,\n\t\tdx: number,\n\t\tdy: number,\n\t\tcolor: RGBA8,\n\t\tforegroundAlpha: number,\n\t\tbackgroundColor: RGBA8,\n\t\tbackgroundAlpha: number,\n\t\tforce1pxHeight: boolean\n\t): void {\n\t\tconst charWidth = Constants.BASE_CHAR_WIDTH * this.scale;\n\t\tconst charHeight = Constants.BASE_CHAR_HEIGHT * this.scale;\n\t\tconst renderHeight = (force1pxHeight ? 1 : charHeight);\n\t\tif (dx + charWidth > target.width || dy + renderHeight > target.height) {\n\t\t\tconsole.warn('bad render request outside image data');\n\t\t\treturn;\n\t\t}\n\n\t\tconst destWidth = target.width * Constants.RGBA_CHANNELS_CNT;\n\n\t\tconst c = 0.5 * (foregroundAlpha / 255);\n\n\t\tconst backgroundR = backgroundColor.r;\n\t\tconst backgroundG = backgroundColor.g;\n\t\tconst backgroundB = backgroundColor.b;\n\n\t\tconst deltaR = color.r - backgroundR;\n\t\tconst deltaG = color.g - backgroundG;\n\t\tconst deltaB = color.b - backgroundB;\n\n\t\tconst colorR = backgroundR + deltaR * c;\n\t\tconst colorG = backgroundG + deltaG * c;\n\t\tconst colorB = backgroundB + deltaB * c;\n\n\t\tconst destAlpha = Math.max(foregroundAlpha, backgroundAlpha);\n\n\t\tconst dest = target.data;\n\n\t\tlet row = dy * destWidth + dx * Constants.RGBA_CHANNELS_CNT;\n\t\tfor (let y = 0; y < renderHeight; y++) {\n\t\t\tlet column = row;\n\t\t\tfor (let x = 0; x < charWidth; x++) {\n\t\t\t\tdest[column++] = colorR;\n\t\t\t\tdest[column++] = colorG;\n\t\t\t\tdest[column++] = colorB;\n\t\t\t\tdest[column++] = destAlpha;\n\t\t\t}\n\n\t\t\trow += destWidth;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { once } from 'vs/base/common/functional';\n\nconst charTable: { [hex: string]: number } = {\n\t'0': 0,\n\t'1': 1,\n\t'2': 2,\n\t'3': 3,\n\t'4': 4,\n\t'5': 5,\n\t'6': 6,\n\t'7': 7,\n\t'8': 8,\n\t'9': 9,\n\tA: 10,\n\tB: 11,\n\tC: 12,\n\tD: 13,\n\tE: 14,\n\tF: 15\n};\n\nconst decodeData = (str: string) => {\n\tconst output = new Uint8ClampedArray(str.length / 2);\n\tfor (let i = 0; i < str.length; i += 2) {\n\t\toutput[i >> 1] = (charTable[str[i]] << 4) | (charTable[str[i + 1]] & 0xF);\n\t}\n\n\treturn output;\n};\n\n/*\nconst encodeData = (data: Uint8ClampedArray, length: string) => {\n\tconst chars = '0123456789ABCDEF';\n\tlet output = '';\n\tfor (let i = 0; i < data.length; i++) {\n\t\toutput += chars[data[i] >> 4] + chars[data[i] & 0xf];\n\t}\n\treturn output;\n};\n*/\n\n/**\n * Map of minimap scales to prebaked sample data at those scales. We don't\n * sample much larger data, because then font family becomes visible, which\n * is use-configurable.\n */\nexport const prebakedMiniMaps: { [scale: number]: () => Uint8ClampedArray } = {\n\t1: once(() =>\n\t\tdecodeData(\n\t\t\t'0000511D6300CF609C709645A78432005642574171487021003C451900274D35D762755E8B629C5BA856AF57BA649530C167D1512A272A3F6038604460398526BCA2A968DB6F8957C768BE5FBE2FB467CF5D8D5B795DC7625B5DFF50DE64C466DB2FC47CD860A65E9A2EB96CB54CE06DA763AB2EA26860524D3763536601005116008177A8705E53AB738E6A982F88BAA35B5F5B626D9C636B449B737E5B7B678598869A662F6B5B8542706C704C80736A607578685B70594A49715A4522E792'\n\t\t)\n\t),\n\t2: once(() =>\n\t\tdecodeData(\n\t\t\t'000000000000000055394F383D2800008B8B1F210002000081B1CBCBCC820000847AAF6B9AAF2119BE08B8881AD60000A44FD07DCCF107015338130C00000000385972265F390B406E2437634B4B48031B12B8A0847000001E15B29A402F0000000000004B33460B00007A752C2A0000000000004D3900000084394B82013400ABA5CFC7AD9C0302A45A3E5A98AB000089A43382D97900008BA54AA087A70A0248A6A7AE6DBE0000BF6F94987EA40A01A06DCFA7A7A9030496C32F77891D0000A99FB1A0AFA80603B29AB9CA75930D010C0948354D3900000C0948354F37460D0028BE673D8400000000AF9D7B6E00002B007AA8933400007AA642675C2700007984CFB9C3985B768772A8A6B7B20000CAAECAAFC4B700009F94A6009F840009D09F9BA4CA9C0000CC8FC76DC87F0000C991C472A2000000A894A48CA7B501079BA2C9C69BA20000B19A5D3FA89000005CA6009DA2960901B0A7F0669FB200009D009E00B7890000DAD0F5D092820000D294D4C48BD10000B5A7A4A3B1A50402CAB6CBA6A2000000B5A7A4A3B1A8044FCDADD19D9CB00000B7778F7B8AAE0803C9AB5D3F5D3F00009EA09EA0BAB006039EA0989A8C7900009B9EF4D6B7C00000A9A7816CACA80000ABAC84705D3F000096DA635CDC8C00006F486F266F263D4784006124097B00374F6D2D6D2D6D4A3A95872322000000030000000000008D8939130000000000002E22A5C9CBC70600AB25C0B5C9B400061A2DB04CA67001082AA6BEBEBFC606002321DACBC19E03087AA08B6768380000282FBAC0B8CA7A88AD25BBA5A29900004C396C5894A6000040485A6E356E9442A32CD17EADA70000B4237923628600003E2DE9C1D7B500002F25BBA5A2990000231DB6AFB4A804023025C0B5CAB588062B2CBDBEC0C706882435A75CA20000002326BD6A82A908048B4B9A5A668000002423A09CB4BB060025259C9D8A7900001C1FCAB2C7C700002A2A9387ABA200002626A4A47D6E9D14333163A0C87500004B6F9C2D643A257049364936493647358A34438355497F1A0000A24C1D590000D38DFFBDD4CD3126'\n\t\t)\n\t)\n};\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { MinimapCharRenderer } from 'vs/editor/browser/viewParts/minimap/minimapCharRenderer';\nimport { allCharCodes } from 'vs/editor/browser/viewParts/minimap/minimapCharSheet';\nimport { prebakedMiniMaps } from 'vs/editor/browser/viewParts/minimap/minimapPreBaked';\nimport { Constants } from './minimapCharSheet';\nimport { toUint8 } from 'vs/base/common/uint';\n\n/**\n * Creates character renderers. It takes a 'scale' that determines how large\n * characters should be drawn. Using this, it draws data into a canvas and\n * then downsamples the characters as necessary for the current display.\n * This makes rendering more efficient, rather than drawing a full (tiny)\n * font, or downsampling in real-time.\n */\nexport class MinimapCharRendererFactory {\n\tprivate static lastCreated?: MinimapCharRenderer;\n\tprivate static lastFontFamily?: string;\n\n\t/**\n\t * Creates a new character renderer factory with the given scale.\n\t */\n\tpublic static create(scale: number, fontFamily: string) {\n\t\t// renderers are immutable. By default we'll 'create' a new minimap\n\t\t// character renderer whenever we switch editors, no need to do extra work.\n\t\tif (this.lastCreated && scale === this.lastCreated.scale && fontFamily === this.lastFontFamily) {\n\t\t\treturn this.lastCreated;\n\t\t}\n\n\t\tlet factory: MinimapCharRenderer;\n\t\tif (prebakedMiniMaps[scale]) {\n\t\t\tfactory = new MinimapCharRenderer(prebakedMiniMaps[scale](), scale);\n\t\t} else {\n\t\t\tfactory = MinimapCharRendererFactory.createFromSampleData(\n\t\t\t\tMinimapCharRendererFactory.createSampleData(fontFamily).data,\n\t\t\t\tscale\n\t\t\t);\n\t\t}\n\n\t\tthis.lastFontFamily = fontFamily;\n\t\tthis.lastCreated = factory;\n\t\treturn factory;\n\t}\n\n\t/**\n\t * Creates the font sample data, writing to a canvas.\n\t */\n\tpublic static createSampleData(fontFamily: string): ImageData {\n\t\tconst canvas = document.createElement('canvas');\n\t\tconst ctx = canvas.getContext('2d')!;\n\n\t\tcanvas.style.height = `${Constants.SAMPLED_CHAR_HEIGHT}px`;\n\t\tcanvas.height = Constants.SAMPLED_CHAR_HEIGHT;\n\t\tcanvas.width = Constants.CHAR_COUNT * Constants.SAMPLED_CHAR_WIDTH;\n\t\tcanvas.style.width = Constants.CHAR_COUNT * Constants.SAMPLED_CHAR_WIDTH + 'px';\n\n\t\tctx.fillStyle = '#ffffff';\n\t\tctx.font = `bold ${Constants.SAMPLED_CHAR_HEIGHT}px ${fontFamily}`;\n\t\tctx.textBaseline = 'middle';\n\n\t\tlet x = 0;\n\t\tfor (const code of allCharCodes) {\n\t\t\tctx.fillText(String.fromCharCode(code), x, Constants.SAMPLED_CHAR_HEIGHT / 2);\n\t\t\tx += Constants.SAMPLED_CHAR_WIDTH;\n\t\t}\n\n\t\treturn ctx.getImageData(0, 0, Constants.CHAR_COUNT * Constants.SAMPLED_CHAR_WIDTH, Constants.SAMPLED_CHAR_HEIGHT);\n\t}\n\n\t/**\n\t * Creates a character renderer from the canvas sample data.\n\t */\n\tpublic static createFromSampleData(source: Uint8ClampedArray, scale: number): MinimapCharRenderer {\n\t\tconst expectedLength =\n\t\t\tConstants.SAMPLED_CHAR_HEIGHT * Constants.SAMPLED_CHAR_WIDTH * Constants.RGBA_CHANNELS_CNT * Constants.CHAR_COUNT;\n\t\tif (source.length !== expectedLength) {\n\t\t\tthrow new Error('Unexpected source in MinimapCharRenderer');\n\t\t}\n\n\t\tconst charData = MinimapCharRendererFactory._downsample(source, scale);\n\t\treturn new MinimapCharRenderer(charData, scale);\n\t}\n\n\tprivate static _downsampleChar(\n\t\tsource: Uint8ClampedArray,\n\t\tsourceOffset: number,\n\t\tdest: Uint8ClampedArray,\n\t\tdestOffset: number,\n\t\tscale: number\n\t): number {\n\t\tconst width = Constants.BASE_CHAR_WIDTH * scale;\n\t\tconst height = Constants.BASE_CHAR_HEIGHT * scale;\n\n\t\tlet targetIndex = destOffset;\n\t\tlet brightest = 0;\n\n\t\t// This is essentially an ad-hoc rescaling algorithm. Standard approaches\n\t\t// like bicubic interpolation are awesome for scaling between image sizes,\n\t\t// but don't work so well when scaling to very small pixel values, we end\n\t\t// up with blurry, indistinct forms.\n\t\t//\n\t\t// The approach taken here is simply mapping each source pixel to the target\n\t\t// pixels, and taking the weighted values for all pixels in each, and then\n\t\t// averaging them out. Finally we apply an intensity boost in _downsample,\n\t\t// since when scaling to the smallest pixel sizes there's more black space\n\t\t// which causes characters to be much less distinct.\n\t\tfor (let y = 0; y < height; y++) {\n\t\t\t// 1. For this destination pixel, get the source pixels we're sampling\n\t\t\t// from (x1, y1) to the next pixel (x2, y2)\n\t\t\tconst sourceY1 = (y / height) * Constants.SAMPLED_CHAR_HEIGHT;\n\t\t\tconst sourceY2 = ((y + 1) / height) * Constants.SAMPLED_CHAR_HEIGHT;\n\n\t\t\tfor (let x = 0; x < width; x++) {\n\t\t\t\tconst sourceX1 = (x / width) * Constants.SAMPLED_CHAR_WIDTH;\n\t\t\t\tconst sourceX2 = ((x + 1) / width) * Constants.SAMPLED_CHAR_WIDTH;\n\n\t\t\t\t// 2. Sample all of them, summing them up and weighting them. Similar\n\t\t\t\t// to bilinear interpolation.\n\t\t\t\tlet value = 0;\n\t\t\t\tlet samples = 0;\n\t\t\t\tfor (let sy = sourceY1; sy < sourceY2; sy++) {\n\t\t\t\t\tconst sourceRow = sourceOffset + Math.floor(sy) * Constants.RGBA_SAMPLED_ROW_WIDTH;\n\t\t\t\t\tconst yBalance = 1 - (sy - Math.floor(sy));\n\t\t\t\t\tfor (let sx = sourceX1; sx < sourceX2; sx++) {\n\t\t\t\t\t\tconst xBalance = 1 - (sx - Math.floor(sx));\n\t\t\t\t\t\tconst sourceIndex = sourceRow + Math.floor(sx) * Constants.RGBA_CHANNELS_CNT;\n\n\t\t\t\t\t\tconst weight = xBalance * yBalance;\n\t\t\t\t\t\tsamples += weight;\n\t\t\t\t\t\tvalue += ((source[sourceIndex] * source[sourceIndex + 3]) / 255) * weight;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst final = value / samples;\n\t\t\t\tbrightest = Math.max(brightest, final);\n\t\t\t\tdest[targetIndex++] = toUint8(final);\n\t\t\t}\n\t\t}\n\n\t\treturn brightest;\n\t}\n\n\tprivate static _downsample(data: Uint8ClampedArray, scale: number): Uint8ClampedArray {\n\t\tconst pixelsPerCharacter = Constants.BASE_CHAR_HEIGHT * scale * Constants.BASE_CHAR_WIDTH * scale;\n\t\tconst resultLen = pixelsPerCharacter * Constants.CHAR_COUNT;\n\t\tconst result = new Uint8ClampedArray(resultLen);\n\n\t\tlet resultOffset = 0;\n\t\tlet sourceOffset = 0;\n\t\tlet brightest = 0;\n\t\tfor (let charIndex = 0; charIndex < Constants.CHAR_COUNT; charIndex++) {\n\t\t\tbrightest = Math.max(brightest, this._downsampleChar(data, sourceOffset, result, resultOffset, scale));\n\t\t\tresultOffset += pixelsPerCharacter;\n\t\t\tsourceOffset += Constants.SAMPLED_CHAR_WIDTH * Constants.RGBA_CHANNELS_CNT;\n\t\t}\n\n\t\tif (brightest > 0) {\n\t\t\tconst adjust = 255 / brightest;\n\t\t\tfor (let i = 0; i < resultLen; i++) {\n\t\t\t\tresult[i] *= adjust;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\n\nexport interface IEditorZoom {\n\tonDidChangeZoomLevel: Event;\n\tgetZoomLevel(): number;\n\tsetZoomLevel(zoomLevel: number): void;\n}\n\nexport const EditorZoom: IEditorZoom = new class implements IEditorZoom {\n\n\tprivate _zoomLevel: number = 0;\n\n\tprivate readonly _onDidChangeZoomLevel = new Emitter();\n\tpublic readonly onDidChangeZoomLevel: Event = this._onDidChangeZoomLevel.event;\n\n\tpublic getZoomLevel(): number {\n\t\treturn this._zoomLevel;\n\t}\n\n\tpublic setZoomLevel(zoomLevel: number): void {\n\t\tzoomLevel = Math.min(Math.max(-5, zoomLevel), 20);\n\t\tif (this._zoomLevel === zoomLevel) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._zoomLevel = zoomLevel;\n\t\tthis._onDidChangeZoomLevel.fire(this._zoomLevel);\n\t}\n};\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as platform from 'vs/base/common/platform';\nimport { EditorOption, FindComputedEditorOptionValueById } from 'vs/editor/common/config/editorOptions';\nimport { EditorZoom } from 'vs/editor/common/config/editorZoom';\n\n/**\n * Determined from empirical observations.\n * @internal\n */\nconst GOLDEN_LINE_HEIGHT_RATIO = platform.isMacintosh ? 1.5 : 1.35;\n\n/**\n * @internal\n */\nconst MINIMUM_LINE_HEIGHT = 8;\n\n/**\n * @internal\n */\nexport interface IValidatedEditorOptions {\n\tget(id: T): FindComputedEditorOptionValueById;\n}\n\nexport class BareFontInfo {\n\treadonly _bareFontInfoBrand: void = undefined;\n\n\t/**\n\t * @internal\n\t */\n\tpublic static createFromValidatedSettings(options: IValidatedEditorOptions, pixelRatio: number, ignoreEditorZoom: boolean): BareFontInfo {\n\t\tconst fontFamily = options.get(EditorOption.fontFamily);\n\t\tconst fontWeight = options.get(EditorOption.fontWeight);\n\t\tconst fontSize = options.get(EditorOption.fontSize);\n\t\tconst fontFeatureSettings = options.get(EditorOption.fontLigatures);\n\t\tconst lineHeight = options.get(EditorOption.lineHeight);\n\t\tconst letterSpacing = options.get(EditorOption.letterSpacing);\n\t\treturn BareFontInfo._create(fontFamily, fontWeight, fontSize, fontFeatureSettings, lineHeight, letterSpacing, pixelRatio, ignoreEditorZoom);\n\t}\n\n\t/**\n\t * @internal\n\t */\n\tprivate static _create(fontFamily: string, fontWeight: string, fontSize: number, fontFeatureSettings: string, lineHeight: number, letterSpacing: number, pixelRatio: number, ignoreEditorZoom: boolean): BareFontInfo {\n\t\tif (lineHeight === 0) {\n\t\t\tlineHeight = GOLDEN_LINE_HEIGHT_RATIO * fontSize;\n\t\t} else if (lineHeight < MINIMUM_LINE_HEIGHT) {\n\t\t\t// Values too small to be line heights in pixels are in ems.\n\t\t\tlineHeight = lineHeight * fontSize;\n\t\t}\n\n\t\t// Enforce integer, minimum constraints\n\t\tlineHeight = Math.round(lineHeight);\n\t\tif (lineHeight < MINIMUM_LINE_HEIGHT) {\n\t\t\tlineHeight = MINIMUM_LINE_HEIGHT;\n\t\t}\n\n\t\tconst editorZoomLevelMultiplier = 1 + (ignoreEditorZoom ? 0 : EditorZoom.getZoomLevel() * 0.1);\n\t\tfontSize *= editorZoomLevelMultiplier;\n\t\tlineHeight *= editorZoomLevelMultiplier;\n\n\t\treturn new BareFontInfo({\n\t\t\tpixelRatio: pixelRatio,\n\t\t\tfontFamily: fontFamily,\n\t\t\tfontWeight: fontWeight,\n\t\t\tfontSize: fontSize,\n\t\t\tfontFeatureSettings: fontFeatureSettings,\n\t\t\tlineHeight: lineHeight,\n\t\t\tletterSpacing: letterSpacing\n\t\t});\n\t}\n\n\treadonly pixelRatio: number;\n\treadonly fontFamily: string;\n\treadonly fontWeight: string;\n\treadonly fontSize: number;\n\treadonly fontFeatureSettings: string;\n\treadonly lineHeight: number;\n\treadonly letterSpacing: number;\n\n\t/**\n\t * @internal\n\t */\n\tprotected constructor(opts: {\n\t\tpixelRatio: number;\n\t\tfontFamily: string;\n\t\tfontWeight: string;\n\t\tfontSize: number;\n\t\tfontFeatureSettings: string;\n\t\tlineHeight: number;\n\t\tletterSpacing: number;\n\t}) {\n\t\tthis.pixelRatio = opts.pixelRatio;\n\t\tthis.fontFamily = String(opts.fontFamily);\n\t\tthis.fontWeight = String(opts.fontWeight);\n\t\tthis.fontSize = opts.fontSize;\n\t\tthis.fontFeatureSettings = opts.fontFeatureSettings;\n\t\tthis.lineHeight = opts.lineHeight | 0;\n\t\tthis.letterSpacing = opts.letterSpacing;\n\t}\n\n\t/**\n\t * @internal\n\t */\n\tpublic getId(): string {\n\t\treturn `${this.pixelRatio}-${this.fontFamily}-${this.fontWeight}-${this.fontSize}-${this.fontFeatureSettings}-${this.lineHeight}-${this.letterSpacing}`;\n\t}\n\n\t/**\n\t * @internal\n\t */\n\tpublic getMassagedFontFamily(fallbackFontFamily: string | null): string {\n\t\tconst fontFamily = BareFontInfo._wrapInQuotes(this.fontFamily);\n\t\tif (fallbackFontFamily && this.fontFamily !== fallbackFontFamily) {\n\t\t\treturn `${fontFamily}, ${fallbackFontFamily}`;\n\t\t}\n\t\treturn fontFamily;\n\t}\n\n\tprivate static _wrapInQuotes(fontFamily: string): string {\n\t\tif (/[,\"']/.test(fontFamily)) {\n\t\t\t// Looks like the font family might be already escaped\n\t\t\treturn fontFamily;\n\t\t}\n\t\tif (/[+ ]/.test(fontFamily)) {\n\t\t\t// Wrap a font family using + or with quotes\n\t\t\treturn `\"${fontFamily}\"`;\n\t\t}\n\t\treturn fontFamily;\n\t}\n}\n\n// change this whenever `FontInfo` members are changed\nexport const SERIALIZED_FONT_INFO_VERSION = 1;\n\nexport class FontInfo extends BareFontInfo {\n\treadonly _editorStylingBrand: void = undefined;\n\n\treadonly version: number = SERIALIZED_FONT_INFO_VERSION;\n\treadonly isTrusted: boolean;\n\treadonly isMonospace: boolean;\n\treadonly typicalHalfwidthCharacterWidth: number;\n\treadonly typicalFullwidthCharacterWidth: number;\n\treadonly canUseHalfwidthRightwardsArrow: boolean;\n\treadonly spaceWidth: number;\n\treadonly middotWidth: number;\n\treadonly wsmiddotWidth: number;\n\treadonly maxDigitWidth: number;\n\n\t/**\n\t * @internal\n\t */\n\tconstructor(opts: {\n\t\tpixelRatio: number;\n\t\tfontFamily: string;\n\t\tfontWeight: string;\n\t\tfontSize: number;\n\t\tfontFeatureSettings: string;\n\t\tlineHeight: number;\n\t\tletterSpacing: number;\n\t\tisMonospace: boolean;\n\t\ttypicalHalfwidthCharacterWidth: number;\n\t\ttypicalFullwidthCharacterWidth: number;\n\t\tcanUseHalfwidthRightwardsArrow: boolean;\n\t\tspaceWidth: number;\n\t\tmiddotWidth: number;\n\t\twsmiddotWidth: number;\n\t\tmaxDigitWidth: number;\n\t}, isTrusted: boolean) {\n\t\tsuper(opts);\n\t\tthis.isTrusted = isTrusted;\n\t\tthis.isMonospace = opts.isMonospace;\n\t\tthis.typicalHalfwidthCharacterWidth = opts.typicalHalfwidthCharacterWidth;\n\t\tthis.typicalFullwidthCharacterWidth = opts.typicalFullwidthCharacterWidth;\n\t\tthis.canUseHalfwidthRightwardsArrow = opts.canUseHalfwidthRightwardsArrow;\n\t\tthis.spaceWidth = opts.spaceWidth;\n\t\tthis.middotWidth = opts.middotWidth;\n\t\tthis.wsmiddotWidth = opts.wsmiddotWidth;\n\t\tthis.maxDigitWidth = opts.maxDigitWidth;\n\t}\n\n\t/**\n\t * @internal\n\t */\n\tpublic equals(other: FontInfo): boolean {\n\t\treturn (\n\t\t\tthis.fontFamily === other.fontFamily\n\t\t\t&& this.fontWeight === other.fontWeight\n\t\t\t&& this.fontSize === other.fontSize\n\t\t\t&& this.fontFeatureSettings === other.fontFeatureSettings\n\t\t\t&& this.lineHeight === other.lineHeight\n\t\t\t&& this.letterSpacing === other.letterSpacing\n\t\t\t&& this.typicalHalfwidthCharacterWidth === other.typicalHalfwidthCharacterWidth\n\t\t\t&& this.typicalFullwidthCharacterWidth === other.typicalFullwidthCharacterWidth\n\t\t\t&& this.canUseHalfwidthRightwardsArrow === other.canUseHalfwidthRightwardsArrow\n\t\t\t&& this.spaceWidth === other.spaceWidth\n\t\t\t&& this.middotWidth === other.middotWidth\n\t\t\t&& this.wsmiddotWidth === other.wsmiddotWidth\n\t\t\t&& this.maxDigitWidth === other.maxDigitWidth\n\t\t);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { toUint8 } from 'vs/base/common/uint';\n\n/**\n * A fast character classifier that uses a compact array for ASCII values.\n */\nexport class CharacterClassifier {\n\t/**\n\t * Maintain a compact (fully initialized ASCII map for quickly classifying ASCII characters - used more often in code).\n\t */\n\tprotected _asciiMap: Uint8Array;\n\n\t/**\n\t * The entire map (sparse array).\n\t */\n\tprotected _map: Map;\n\n\tprotected _defaultValue: number;\n\n\tconstructor(_defaultValue: T) {\n\t\tconst defaultValue = toUint8(_defaultValue);\n\n\t\tthis._defaultValue = defaultValue;\n\t\tthis._asciiMap = CharacterClassifier._createAsciiMap(defaultValue);\n\t\tthis._map = new Map();\n\t}\n\n\tprivate static _createAsciiMap(defaultValue: number): Uint8Array {\n\t\tconst asciiMap: Uint8Array = new Uint8Array(256);\n\t\tfor (let i = 0; i < 256; i++) {\n\t\t\tasciiMap[i] = defaultValue;\n\t\t}\n\t\treturn asciiMap;\n\t}\n\n\tpublic set(charCode: number, _value: T): void {\n\t\tconst value = toUint8(_value);\n\n\t\tif (charCode >= 0 && charCode < 256) {\n\t\t\tthis._asciiMap[charCode] = value;\n\t\t} else {\n\t\t\tthis._map.set(charCode, value);\n\t\t}\n\t}\n\n\tpublic get(charCode: number): T {\n\t\tif (charCode >= 0 && charCode < 256) {\n\t\t\treturn this._asciiMap[charCode];\n\t\t} else {\n\t\t\treturn (this._map.get(charCode) || this._defaultValue);\n\t\t}\n\t}\n}\n\nconst enum Boolean {\n\tFalse = 0,\n\tTrue = 1\n}\n\nexport class CharacterSet {\n\n\tprivate readonly _actual: CharacterClassifier;\n\n\tconstructor() {\n\t\tthis._actual = new CharacterClassifier(Boolean.False);\n\t}\n\n\tpublic add(charCode: number): void {\n\t\tthis._actual.set(charCode, Boolean.True);\n\t}\n\n\tpublic has(charCode: number): boolean {\n\t\treturn (this._actual.get(charCode) === Boolean.True);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport * as strings from 'vs/base/common/strings';\n\n/**\n * A column in a position is the gap between two adjacent characters. The methods here\n * work with a concept called \"visible column\". A visible column is a very rough approximation\n * of the horizontal screen position of a column. For example, using a tab size of 4:\n * ```txt\n * |||T|ext\n * | | | \\---- column = 4, visible column = 9\n * | | \\------ column = 3, visible column = 8\n * | \\------------ column = 2, visible column = 4\n * \\------------------ column = 1, visible column = 0\n * ```\n *\n * **NOTE**: Visual columns do not work well for RTL text or variable-width fonts or characters.\n *\n * **NOTE**: These methods work and make sense both on the model and on the view model.\n */\nexport class CursorColumns {\n\n\tprivate static _nextVisibleColumn(codePoint: number, visibleColumn: number, tabSize: number): number {\n\t\tif (codePoint === CharCode.Tab) {\n\t\t\treturn CursorColumns.nextRenderTabStop(visibleColumn, tabSize);\n\t\t}\n\t\tif (strings.isFullWidthCharacter(codePoint) || strings.isEmojiImprecise(codePoint)) {\n\t\t\treturn visibleColumn + 2;\n\t\t}\n\t\treturn visibleColumn + 1;\n\t}\n\n\t/**\n\t * Returns a visible column from a column.\n\t * @see {@link CursorColumns}\n\t */\n\tpublic static visibleColumnFromColumn(lineContent: string, column: number, tabSize: number): number {\n\t\tconst textLen = Math.min(column - 1, lineContent.length);\n\t\tconst text = lineContent.substring(0, textLen);\n\t\tconst iterator = new strings.GraphemeIterator(text);\n\n\t\tlet result = 0;\n\t\twhile (!iterator.eol()) {\n\t\t\tconst codePoint = strings.getNextCodePoint(text, textLen, iterator.offset);\n\t\t\titerator.nextGraphemeLength();\n\n\t\t\tresult = this._nextVisibleColumn(codePoint, result, tabSize);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Returns a column from a visible column.\n\t * @see {@link CursorColumns}\n\t */\n\tpublic static columnFromVisibleColumn(lineContent: string, visibleColumn: number, tabSize: number): number {\n\t\tif (visibleColumn <= 0) {\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst lineContentLength = lineContent.length;\n\t\tconst iterator = new strings.GraphemeIterator(lineContent);\n\n\t\tlet beforeVisibleColumn = 0;\n\t\tlet beforeColumn = 1;\n\t\twhile (!iterator.eol()) {\n\t\t\tconst codePoint = strings.getNextCodePoint(lineContent, lineContentLength, iterator.offset);\n\t\t\titerator.nextGraphemeLength();\n\n\t\t\tconst afterVisibleColumn = this._nextVisibleColumn(codePoint, beforeVisibleColumn, tabSize);\n\t\t\tconst afterColumn = iterator.offset + 1;\n\n\t\t\tif (afterVisibleColumn >= visibleColumn) {\n\t\t\t\tconst beforeDelta = visibleColumn - beforeVisibleColumn;\n\t\t\t\tconst afterDelta = afterVisibleColumn - visibleColumn;\n\t\t\t\tif (afterDelta < beforeDelta) {\n\t\t\t\t\treturn afterColumn;\n\t\t\t\t} else {\n\t\t\t\t\treturn beforeColumn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbeforeVisibleColumn = afterVisibleColumn;\n\t\t\tbeforeColumn = afterColumn;\n\t\t}\n\n\t\t// walked the entire string\n\t\treturn lineContentLength + 1;\n\t}\n\n\t/**\n\t * ATTENTION: This works with 0-based columns (as oposed to the regular 1-based columns)\n\t * @see {@link CursorColumns}\n\t */\n\tpublic static nextRenderTabStop(visibleColumn: number, tabSize: number): number {\n\t\treturn visibleColumn + tabSize - visibleColumn % tabSize;\n\t}\n\n\t/**\n\t * ATTENTION: This works with 0-based columns (as oposed to the regular 1-based columns)\n\t * @see {@link CursorColumns}\n\t */\n\tpublic static nextIndentTabStop(visibleColumn: number, indentSize: number): number {\n\t\treturn visibleColumn + indentSize - visibleColumn % indentSize;\n\t}\n\n\t/**\n\t * ATTENTION: This works with 0-based columns (as opposed to the regular 1-based columns)\n\t * @see {@link CursorColumns}\n\t */\n\tpublic static prevRenderTabStop(column: number, tabSize: number): number {\n\t\treturn Math.max(0, column - 1 - (column - 1) % tabSize);\n\t}\n\n\t/**\n\t * ATTENTION: This works with 0-based columns (as opposed to the regular 1-based columns)\n\t * @see {@link CursorColumns}\n\t */\n\tpublic static prevIndentTabStop(column: number, indentSize: number): number {\n\t\treturn Math.max(0, column - 1 - (column - 1) % indentSize);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\n\nexport const enum StringEOL {\n\tUnknown = 0,\n\tInvalid = 3,\n\tLF = 1,\n\tCRLF = 2\n}\n\nexport function countEOL(text: string): [number, number, number, StringEOL] {\n\tlet eolCount = 0;\n\tlet firstLineLength = 0;\n\tlet lastLineStart = 0;\n\tlet eol: StringEOL = StringEOL.Unknown;\n\tfor (let i = 0, len = text.length; i < len; i++) {\n\t\tconst chr = text.charCodeAt(i);\n\n\t\tif (chr === CharCode.CarriageReturn) {\n\t\t\tif (eolCount === 0) {\n\t\t\t\tfirstLineLength = i;\n\t\t\t}\n\t\t\teolCount++;\n\t\t\tif (i + 1 < len && text.charCodeAt(i + 1) === CharCode.LineFeed) {\n\t\t\t\t// \\r\\n... case\n\t\t\t\teol |= StringEOL.CRLF;\n\t\t\t\ti++; // skip \\n\n\t\t\t} else {\n\t\t\t\t// \\r... case\n\t\t\t\teol |= StringEOL.Invalid;\n\t\t\t}\n\t\t\tlastLineStart = i + 1;\n\t\t} else if (chr === CharCode.LineFeed) {\n\t\t\t// \\n... case\n\t\t\teol |= StringEOL.LF;\n\t\t\tif (eolCount === 0) {\n\t\t\t\tfirstLineLength = i;\n\t\t\t}\n\t\t\teolCount++;\n\t\t\tlastLineStart = i + 1;\n\t\t}\n\t}\n\tif (eolCount === 0) {\n\t\tfirstLineLength = text.length;\n\t}\n\treturn [eolCount, firstLineLength, text.length - lastLineStart, eol];\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n/**\n * A position in the editor. This interface is suitable for serialization.\n */\nexport interface IPosition {\n\t/**\n\t * line number (starts at 1)\n\t */\n\treadonly lineNumber: number;\n\t/**\n\t * column (the first character in a line is between column 1 and column 2)\n\t */\n\treadonly column: number;\n}\n\n/**\n * A position in the editor.\n */\nexport class Position {\n\t/**\n\t * line number (starts at 1)\n\t */\n\tpublic readonly lineNumber: number;\n\t/**\n\t * column (the first character in a line is between column 1 and column 2)\n\t */\n\tpublic readonly column: number;\n\n\tconstructor(lineNumber: number, column: number) {\n\t\tthis.lineNumber = lineNumber;\n\t\tthis.column = column;\n\t}\n\n\t/**\n\t * Create a new position from this position.\n\t *\n\t * @param newLineNumber new line number\n\t * @param newColumn new column\n\t */\n\twith(newLineNumber: number = this.lineNumber, newColumn: number = this.column): Position {\n\t\tif (newLineNumber === this.lineNumber && newColumn === this.column) {\n\t\t\treturn this;\n\t\t} else {\n\t\t\treturn new Position(newLineNumber, newColumn);\n\t\t}\n\t}\n\n\t/**\n\t * Derive a new position from this position.\n\t *\n\t * @param deltaLineNumber line number delta\n\t * @param deltaColumn column delta\n\t */\n\tdelta(deltaLineNumber: number = 0, deltaColumn: number = 0): Position {\n\t\treturn this.with(this.lineNumber + deltaLineNumber, this.column + deltaColumn);\n\t}\n\n\t/**\n\t * Test if this position equals other position\n\t */\n\tpublic equals(other: IPosition): boolean {\n\t\treturn Position.equals(this, other);\n\t}\n\n\t/**\n\t * Test if position `a` equals position `b`\n\t */\n\tpublic static equals(a: IPosition | null, b: IPosition | null): boolean {\n\t\tif (!a && !b) {\n\t\t\treturn true;\n\t\t}\n\t\treturn (\n\t\t\t!!a &&\n\t\t\t!!b &&\n\t\t\ta.lineNumber === b.lineNumber &&\n\t\t\ta.column === b.column\n\t\t);\n\t}\n\n\t/**\n\t * Test if this position is before other position.\n\t * If the two positions are equal, the result will be false.\n\t */\n\tpublic isBefore(other: IPosition): boolean {\n\t\treturn Position.isBefore(this, other);\n\t}\n\n\t/**\n\t * Test if position `a` is before position `b`.\n\t * If the two positions are equal, the result will be false.\n\t */\n\tpublic static isBefore(a: IPosition, b: IPosition): boolean {\n\t\tif (a.lineNumber < b.lineNumber) {\n\t\t\treturn true;\n\t\t}\n\t\tif (b.lineNumber < a.lineNumber) {\n\t\t\treturn false;\n\t\t}\n\t\treturn a.column < b.column;\n\t}\n\n\t/**\n\t * Test if this position is before other position.\n\t * If the two positions are equal, the result will be true.\n\t */\n\tpublic isBeforeOrEqual(other: IPosition): boolean {\n\t\treturn Position.isBeforeOrEqual(this, other);\n\t}\n\n\t/**\n\t * Test if position `a` is before position `b`.\n\t * If the two positions are equal, the result will be true.\n\t */\n\tpublic static isBeforeOrEqual(a: IPosition, b: IPosition): boolean {\n\t\tif (a.lineNumber < b.lineNumber) {\n\t\t\treturn true;\n\t\t}\n\t\tif (b.lineNumber < a.lineNumber) {\n\t\t\treturn false;\n\t\t}\n\t\treturn a.column <= b.column;\n\t}\n\n\t/**\n\t * A function that compares positions, useful for sorting\n\t */\n\tpublic static compare(a: IPosition, b: IPosition): number {\n\t\tconst aLineNumber = a.lineNumber | 0;\n\t\tconst bLineNumber = b.lineNumber | 0;\n\n\t\tif (aLineNumber === bLineNumber) {\n\t\t\tconst aColumn = a.column | 0;\n\t\t\tconst bColumn = b.column | 0;\n\t\t\treturn aColumn - bColumn;\n\t\t}\n\n\t\treturn aLineNumber - bLineNumber;\n\t}\n\n\t/**\n\t * Clone this position.\n\t */\n\tpublic clone(): Position {\n\t\treturn new Position(this.lineNumber, this.column);\n\t}\n\n\t/**\n\t * Convert to a human-readable representation.\n\t */\n\tpublic toString(): string {\n\t\treturn '(' + this.lineNumber + ',' + this.column + ')';\n\t}\n\n\t// ---\n\n\t/**\n\t * Create a `Position` from an `IPosition`.\n\t */\n\tpublic static lift(pos: IPosition): Position {\n\t\treturn new Position(pos.lineNumber, pos.column);\n\t}\n\n\t/**\n\t * Test if `obj` is an `IPosition`.\n\t */\n\tpublic static isIPosition(obj: any): obj is IPosition {\n\t\treturn (\n\t\t\tobj\n\t\t\t&& (typeof obj.lineNumber === 'number')\n\t\t\t&& (typeof obj.column === 'number')\n\t\t);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IPosition, Position } from 'vs/editor/common/core/position';\n\n/**\n * A range in the editor. This interface is suitable for serialization.\n */\nexport interface IRange {\n\t/**\n\t * Line number on which the range starts (starts at 1).\n\t */\n\treadonly startLineNumber: number;\n\t/**\n\t * Column on which the range starts in line `startLineNumber` (starts at 1).\n\t */\n\treadonly startColumn: number;\n\t/**\n\t * Line number on which the range ends.\n\t */\n\treadonly endLineNumber: number;\n\t/**\n\t * Column on which the range ends in line `endLineNumber`.\n\t */\n\treadonly endColumn: number;\n}\n\n/**\n * A range in the editor. (startLineNumber,startColumn) is <= (endLineNumber,endColumn)\n */\nexport class Range {\n\n\t/**\n\t * Line number on which the range starts (starts at 1).\n\t */\n\tpublic readonly startLineNumber: number;\n\t/**\n\t * Column on which the range starts in line `startLineNumber` (starts at 1).\n\t */\n\tpublic readonly startColumn: number;\n\t/**\n\t * Line number on which the range ends.\n\t */\n\tpublic readonly endLineNumber: number;\n\t/**\n\t * Column on which the range ends in line `endLineNumber`.\n\t */\n\tpublic readonly endColumn: number;\n\n\tconstructor(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number) {\n\t\tif ((startLineNumber > endLineNumber) || (startLineNumber === endLineNumber && startColumn > endColumn)) {\n\t\t\tthis.startLineNumber = endLineNumber;\n\t\t\tthis.startColumn = endColumn;\n\t\t\tthis.endLineNumber = startLineNumber;\n\t\t\tthis.endColumn = startColumn;\n\t\t} else {\n\t\t\tthis.startLineNumber = startLineNumber;\n\t\t\tthis.startColumn = startColumn;\n\t\t\tthis.endLineNumber = endLineNumber;\n\t\t\tthis.endColumn = endColumn;\n\t\t}\n\t}\n\n\t/**\n\t * Test if this range is empty.\n\t */\n\tpublic isEmpty(): boolean {\n\t\treturn Range.isEmpty(this);\n\t}\n\n\t/**\n\t * Test if `range` is empty.\n\t */\n\tpublic static isEmpty(range: IRange): boolean {\n\t\treturn (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn);\n\t}\n\n\t/**\n\t * Test if position is in this range. If the position is at the edges, will return true.\n\t */\n\tpublic containsPosition(position: IPosition): boolean {\n\t\treturn Range.containsPosition(this, position);\n\t}\n\n\t/**\n\t * Test if `position` is in `range`. If the position is at the edges, will return true.\n\t */\n\tpublic static containsPosition(range: IRange, position: IPosition): boolean {\n\t\tif (position.lineNumber < range.startLineNumber || position.lineNumber > range.endLineNumber) {\n\t\t\treturn false;\n\t\t}\n\t\tif (position.lineNumber === range.startLineNumber && position.column < range.startColumn) {\n\t\t\treturn false;\n\t\t}\n\t\tif (position.lineNumber === range.endLineNumber && position.column > range.endColumn) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Test if `position` is in `range`. If the position is at the edges, will return false.\n\t * @internal\n\t */\n\tpublic static strictContainsPosition(range: IRange, position: IPosition): boolean {\n\t\tif (position.lineNumber < range.startLineNumber || position.lineNumber > range.endLineNumber) {\n\t\t\treturn false;\n\t\t}\n\t\tif (position.lineNumber === range.startLineNumber && position.column <= range.startColumn) {\n\t\t\treturn false;\n\t\t}\n\t\tif (position.lineNumber === range.endLineNumber && position.column >= range.endColumn) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Test if range is in this range. If the range is equal to this range, will return true.\n\t */\n\tpublic containsRange(range: IRange): boolean {\n\t\treturn Range.containsRange(this, range);\n\t}\n\n\t/**\n\t * Test if `otherRange` is in `range`. If the ranges are equal, will return true.\n\t */\n\tpublic static containsRange(range: IRange, otherRange: IRange): boolean {\n\t\tif (otherRange.startLineNumber < range.startLineNumber || otherRange.endLineNumber < range.startLineNumber) {\n\t\t\treturn false;\n\t\t}\n\t\tif (otherRange.startLineNumber > range.endLineNumber || otherRange.endLineNumber > range.endLineNumber) {\n\t\t\treturn false;\n\t\t}\n\t\tif (otherRange.startLineNumber === range.startLineNumber && otherRange.startColumn < range.startColumn) {\n\t\t\treturn false;\n\t\t}\n\t\tif (otherRange.endLineNumber === range.endLineNumber && otherRange.endColumn > range.endColumn) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Test if `range` is strictly in this range. `range` must start after and end before this range for the result to be true.\n\t */\n\tpublic strictContainsRange(range: IRange): boolean {\n\t\treturn Range.strictContainsRange(this, range);\n\t}\n\n\t/**\n\t * Test if `otherRange` is strictly in `range` (must start after, and end before). If the ranges are equal, will return false.\n\t */\n\tpublic static strictContainsRange(range: IRange, otherRange: IRange): boolean {\n\t\tif (otherRange.startLineNumber < range.startLineNumber || otherRange.endLineNumber < range.startLineNumber) {\n\t\t\treturn false;\n\t\t}\n\t\tif (otherRange.startLineNumber > range.endLineNumber || otherRange.endLineNumber > range.endLineNumber) {\n\t\t\treturn false;\n\t\t}\n\t\tif (otherRange.startLineNumber === range.startLineNumber && otherRange.startColumn <= range.startColumn) {\n\t\t\treturn false;\n\t\t}\n\t\tif (otherRange.endLineNumber === range.endLineNumber && otherRange.endColumn >= range.endColumn) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * A reunion of the two ranges.\n\t * The smallest position will be used as the start point, and the largest one as the end point.\n\t */\n\tpublic plusRange(range: IRange): Range {\n\t\treturn Range.plusRange(this, range);\n\t}\n\n\t/**\n\t * A reunion of the two ranges.\n\t * The smallest position will be used as the start point, and the largest one as the end point.\n\t */\n\tpublic static plusRange(a: IRange, b: IRange): Range {\n\t\tlet startLineNumber: number;\n\t\tlet startColumn: number;\n\t\tlet endLineNumber: number;\n\t\tlet endColumn: number;\n\n\t\tif (b.startLineNumber < a.startLineNumber) {\n\t\t\tstartLineNumber = b.startLineNumber;\n\t\t\tstartColumn = b.startColumn;\n\t\t} else if (b.startLineNumber === a.startLineNumber) {\n\t\t\tstartLineNumber = b.startLineNumber;\n\t\t\tstartColumn = Math.min(b.startColumn, a.startColumn);\n\t\t} else {\n\t\t\tstartLineNumber = a.startLineNumber;\n\t\t\tstartColumn = a.startColumn;\n\t\t}\n\n\t\tif (b.endLineNumber > a.endLineNumber) {\n\t\t\tendLineNumber = b.endLineNumber;\n\t\t\tendColumn = b.endColumn;\n\t\t} else if (b.endLineNumber === a.endLineNumber) {\n\t\t\tendLineNumber = b.endLineNumber;\n\t\t\tendColumn = Math.max(b.endColumn, a.endColumn);\n\t\t} else {\n\t\t\tendLineNumber = a.endLineNumber;\n\t\t\tendColumn = a.endColumn;\n\t\t}\n\n\t\treturn new Range(startLineNumber, startColumn, endLineNumber, endColumn);\n\t}\n\n\t/**\n\t * A intersection of the two ranges.\n\t */\n\tpublic intersectRanges(range: IRange): Range | null {\n\t\treturn Range.intersectRanges(this, range);\n\t}\n\n\t/**\n\t * A intersection of the two ranges.\n\t */\n\tpublic static intersectRanges(a: IRange, b: IRange): Range | null {\n\t\tlet resultStartLineNumber = a.startLineNumber;\n\t\tlet resultStartColumn = a.startColumn;\n\t\tlet resultEndLineNumber = a.endLineNumber;\n\t\tlet resultEndColumn = a.endColumn;\n\t\tlet otherStartLineNumber = b.startLineNumber;\n\t\tlet otherStartColumn = b.startColumn;\n\t\tlet otherEndLineNumber = b.endLineNumber;\n\t\tlet otherEndColumn = b.endColumn;\n\n\t\tif (resultStartLineNumber < otherStartLineNumber) {\n\t\t\tresultStartLineNumber = otherStartLineNumber;\n\t\t\tresultStartColumn = otherStartColumn;\n\t\t} else if (resultStartLineNumber === otherStartLineNumber) {\n\t\t\tresultStartColumn = Math.max(resultStartColumn, otherStartColumn);\n\t\t}\n\n\t\tif (resultEndLineNumber > otherEndLineNumber) {\n\t\t\tresultEndLineNumber = otherEndLineNumber;\n\t\t\tresultEndColumn = otherEndColumn;\n\t\t} else if (resultEndLineNumber === otherEndLineNumber) {\n\t\t\tresultEndColumn = Math.min(resultEndColumn, otherEndColumn);\n\t\t}\n\n\t\t// Check if selection is now empty\n\t\tif (resultStartLineNumber > resultEndLineNumber) {\n\t\t\treturn null;\n\t\t}\n\t\tif (resultStartLineNumber === resultEndLineNumber && resultStartColumn > resultEndColumn) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new Range(resultStartLineNumber, resultStartColumn, resultEndLineNumber, resultEndColumn);\n\t}\n\n\t/**\n\t * Test if this range equals other.\n\t */\n\tpublic equalsRange(other: IRange | null): boolean {\n\t\treturn Range.equalsRange(this, other);\n\t}\n\n\t/**\n\t * Test if range `a` equals `b`.\n\t */\n\tpublic static equalsRange(a: IRange | null, b: IRange | null): boolean {\n\t\treturn (\n\t\t\t!!a &&\n\t\t\t!!b &&\n\t\t\ta.startLineNumber === b.startLineNumber &&\n\t\t\ta.startColumn === b.startColumn &&\n\t\t\ta.endLineNumber === b.endLineNumber &&\n\t\t\ta.endColumn === b.endColumn\n\t\t);\n\t}\n\n\t/**\n\t * Return the end position (which will be after or equal to the start position)\n\t */\n\tpublic getEndPosition(): Position {\n\t\treturn Range.getEndPosition(this);\n\t}\n\n\t/**\n\t * Return the end position (which will be after or equal to the start position)\n\t */\n\tpublic static getEndPosition(range: IRange): Position {\n\t\treturn new Position(range.endLineNumber, range.endColumn);\n\t}\n\n\t/**\n\t * Return the start position (which will be before or equal to the end position)\n\t */\n\tpublic getStartPosition(): Position {\n\t\treturn Range.getStartPosition(this);\n\t}\n\n\t/**\n\t * Return the start position (which will be before or equal to the end position)\n\t */\n\tpublic static getStartPosition(range: IRange): Position {\n\t\treturn new Position(range.startLineNumber, range.startColumn);\n\t}\n\n\t/**\n\t * Transform to a user presentable string representation.\n\t */\n\tpublic toString(): string {\n\t\treturn '[' + this.startLineNumber + ',' + this.startColumn + ' -> ' + this.endLineNumber + ',' + this.endColumn + ']';\n\t}\n\n\t/**\n\t * Create a new range using this range's start position, and using endLineNumber and endColumn as the end position.\n\t */\n\tpublic setEndPosition(endLineNumber: number, endColumn: number): Range {\n\t\treturn new Range(this.startLineNumber, this.startColumn, endLineNumber, endColumn);\n\t}\n\n\t/**\n\t * Create a new range using this range's end position, and using startLineNumber and startColumn as the start position.\n\t */\n\tpublic setStartPosition(startLineNumber: number, startColumn: number): Range {\n\t\treturn new Range(startLineNumber, startColumn, this.endLineNumber, this.endColumn);\n\t}\n\n\t/**\n\t * Create a new empty range using this range's start position.\n\t */\n\tpublic collapseToStart(): Range {\n\t\treturn Range.collapseToStart(this);\n\t}\n\n\t/**\n\t * Create a new empty range using this range's start position.\n\t */\n\tpublic static collapseToStart(range: IRange): Range {\n\t\treturn new Range(range.startLineNumber, range.startColumn, range.startLineNumber, range.startColumn);\n\t}\n\n\t// ---\n\n\tpublic static fromPositions(start: IPosition, end: IPosition = start): Range {\n\t\treturn new Range(start.lineNumber, start.column, end.lineNumber, end.column);\n\t}\n\n\t/**\n\t * Create a `Range` from an `IRange`.\n\t */\n\tpublic static lift(range: undefined | null): null;\n\tpublic static lift(range: IRange): Range;\n\tpublic static lift(range: IRange | undefined | null): Range | null {\n\t\tif (!range) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new Range(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);\n\t}\n\n\t/**\n\t * Test if `obj` is an `IRange`.\n\t */\n\tpublic static isIRange(obj: any): obj is IRange {\n\t\treturn (\n\t\t\tobj\n\t\t\t&& (typeof obj.startLineNumber === 'number')\n\t\t\t&& (typeof obj.startColumn === 'number')\n\t\t\t&& (typeof obj.endLineNumber === 'number')\n\t\t\t&& (typeof obj.endColumn === 'number')\n\t\t);\n\t}\n\n\t/**\n\t * Test if the two ranges are touching in any way.\n\t */\n\tpublic static areIntersectingOrTouching(a: IRange, b: IRange): boolean {\n\t\t// Check if `a` is before `b`\n\t\tif (a.endLineNumber < b.startLineNumber || (a.endLineNumber === b.startLineNumber && a.endColumn < b.startColumn)) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check if `b` is before `a`\n\t\tif (b.endLineNumber < a.startLineNumber || (b.endLineNumber === a.startLineNumber && b.endColumn < a.startColumn)) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// These ranges must intersect\n\t\treturn true;\n\t}\n\n\t/**\n\t * Test if the two ranges are intersecting. If the ranges are touching it returns true.\n\t */\n\tpublic static areIntersecting(a: IRange, b: IRange): boolean {\n\t\t// Check if `a` is before `b`\n\t\tif (a.endLineNumber < b.startLineNumber || (a.endLineNumber === b.startLineNumber && a.endColumn <= b.startColumn)) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check if `b` is before `a`\n\t\tif (b.endLineNumber < a.startLineNumber || (b.endLineNumber === a.startLineNumber && b.endColumn <= a.startColumn)) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// These ranges must intersect\n\t\treturn true;\n\t}\n\n\t/**\n\t * A function that compares ranges, useful for sorting ranges\n\t * It will first compare ranges on the startPosition and then on the endPosition\n\t */\n\tpublic static compareRangesUsingStarts(a: IRange | null | undefined, b: IRange | null | undefined): number {\n\t\tif (a && b) {\n\t\t\tconst aStartLineNumber = a.startLineNumber | 0;\n\t\t\tconst bStartLineNumber = b.startLineNumber | 0;\n\n\t\t\tif (aStartLineNumber === bStartLineNumber) {\n\t\t\t\tconst aStartColumn = a.startColumn | 0;\n\t\t\t\tconst bStartColumn = b.startColumn | 0;\n\n\t\t\t\tif (aStartColumn === bStartColumn) {\n\t\t\t\t\tconst aEndLineNumber = a.endLineNumber | 0;\n\t\t\t\t\tconst bEndLineNumber = b.endLineNumber | 0;\n\n\t\t\t\t\tif (aEndLineNumber === bEndLineNumber) {\n\t\t\t\t\t\tconst aEndColumn = a.endColumn | 0;\n\t\t\t\t\t\tconst bEndColumn = b.endColumn | 0;\n\t\t\t\t\t\treturn aEndColumn - bEndColumn;\n\t\t\t\t\t}\n\t\t\t\t\treturn aEndLineNumber - bEndLineNumber;\n\t\t\t\t}\n\t\t\t\treturn aStartColumn - bStartColumn;\n\t\t\t}\n\t\t\treturn aStartLineNumber - bStartLineNumber;\n\t\t}\n\t\tconst aExists = (a ? 1 : 0);\n\t\tconst bExists = (b ? 1 : 0);\n\t\treturn aExists - bExists;\n\t}\n\n\t/**\n\t * A function that compares ranges, useful for sorting ranges\n\t * It will first compare ranges on the endPosition and then on the startPosition\n\t */\n\tpublic static compareRangesUsingEnds(a: IRange, b: IRange): number {\n\t\tif (a.endLineNumber === b.endLineNumber) {\n\t\t\tif (a.endColumn === b.endColumn) {\n\t\t\t\tif (a.startLineNumber === b.startLineNumber) {\n\t\t\t\t\treturn a.startColumn - b.startColumn;\n\t\t\t\t}\n\t\t\t\treturn a.startLineNumber - b.startLineNumber;\n\t\t\t}\n\t\t\treturn a.endColumn - b.endColumn;\n\t\t}\n\t\treturn a.endLineNumber - b.endLineNumber;\n\t}\n\n\t/**\n\t * Test if the range spans multiple lines.\n\t */\n\tpublic static spansMultipleLines(range: IRange): boolean {\n\t\treturn range.endLineNumber > range.startLineNumber;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as strings from 'vs/base/common/strings';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { EndOfLinePreference } from 'vs/editor/common/model';\n\nexport const _debugComposition = false;\n\nexport interface ITextAreaWrapper {\n\tgetValue(): string;\n\tsetValue(reason: string, value: string): void;\n\n\tgetSelectionStart(): number;\n\tgetSelectionEnd(): number;\n\tsetSelectionRange(reason: string, selectionStart: number, selectionEnd: number): void;\n}\n\nexport interface ISimpleModel {\n\tgetLineCount(): number;\n\tgetLineMaxColumn(lineNumber: number): number;\n\tgetValueInRange(range: Range, eol: EndOfLinePreference): string;\n}\n\nexport interface ITypeData {\n\ttext: string;\n\treplacePrevCharCnt: number;\n\treplaceNextCharCnt: number;\n\tpositionDelta: number;\n}\n\nexport class TextAreaState {\n\n\tpublic static readonly EMPTY = new TextAreaState('', 0, 0, null, null);\n\n\tpublic readonly value: string;\n\tpublic readonly selectionStart: number;\n\tpublic readonly selectionEnd: number;\n\tpublic readonly selectionStartPosition: Position | null;\n\tpublic readonly selectionEndPosition: Position | null;\n\n\tconstructor(value: string, selectionStart: number, selectionEnd: number, selectionStartPosition: Position | null, selectionEndPosition: Position | null) {\n\t\tthis.value = value;\n\t\tthis.selectionStart = selectionStart;\n\t\tthis.selectionEnd = selectionEnd;\n\t\tthis.selectionStartPosition = selectionStartPosition;\n\t\tthis.selectionEndPosition = selectionEndPosition;\n\t}\n\n\tpublic toString(): string {\n\t\treturn `[ <${this.value}>, selectionStart: ${this.selectionStart}, selectionEnd: ${this.selectionEnd}]`;\n\t}\n\n\tpublic static readFromTextArea(textArea: ITextAreaWrapper): TextAreaState {\n\t\treturn new TextAreaState(textArea.getValue(), textArea.getSelectionStart(), textArea.getSelectionEnd(), null, null);\n\t}\n\n\tpublic collapseSelection(): TextAreaState {\n\t\treturn new TextAreaState(this.value, this.value.length, this.value.length, null, null);\n\t}\n\n\tpublic writeToTextArea(reason: string, textArea: ITextAreaWrapper, select: boolean): void {\n\t\tif (_debugComposition) {\n\t\t\tconsole.log(`writeToTextArea ${reason}: ${this.toString()}`);\n\t\t}\n\t\ttextArea.setValue(reason, this.value);\n\t\tif (select) {\n\t\t\ttextArea.setSelectionRange(reason, this.selectionStart, this.selectionEnd);\n\t\t}\n\t}\n\n\tpublic deduceEditorPosition(offset: number): [Position | null, number, number] {\n\t\tif (offset <= this.selectionStart) {\n\t\t\tconst str = this.value.substring(offset, this.selectionStart);\n\t\t\treturn this._finishDeduceEditorPosition(this.selectionStartPosition, str, -1);\n\t\t}\n\t\tif (offset >= this.selectionEnd) {\n\t\t\tconst str = this.value.substring(this.selectionEnd, offset);\n\t\t\treturn this._finishDeduceEditorPosition(this.selectionEndPosition, str, 1);\n\t\t}\n\t\tconst str1 = this.value.substring(this.selectionStart, offset);\n\t\tif (str1.indexOf(String.fromCharCode(8230)) === -1) {\n\t\t\treturn this._finishDeduceEditorPosition(this.selectionStartPosition, str1, 1);\n\t\t}\n\t\tconst str2 = this.value.substring(offset, this.selectionEnd);\n\t\treturn this._finishDeduceEditorPosition(this.selectionEndPosition, str2, -1);\n\t}\n\n\tprivate _finishDeduceEditorPosition(anchor: Position | null, deltaText: string, signum: number): [Position | null, number, number] {\n\t\tlet lineFeedCnt = 0;\n\t\tlet lastLineFeedIndex = -1;\n\t\twhile ((lastLineFeedIndex = deltaText.indexOf('\\n', lastLineFeedIndex + 1)) !== -1) {\n\t\t\tlineFeedCnt++;\n\t\t}\n\t\treturn [anchor, signum * deltaText.length, lineFeedCnt];\n\t}\n\n\tpublic static deduceInput(previousState: TextAreaState, currentState: TextAreaState, couldBeEmojiInput: boolean): ITypeData {\n\t\tif (!previousState) {\n\t\t\t// This is the EMPTY state\n\t\t\treturn {\n\t\t\t\ttext: '',\n\t\t\t\treplacePrevCharCnt: 0,\n\t\t\t\treplaceNextCharCnt: 0,\n\t\t\t\tpositionDelta: 0\n\t\t\t};\n\t\t}\n\n\t\tif (_debugComposition) {\n\t\t\tconsole.log('------------------------deduceInput');\n\t\t\tconsole.log(`PREVIOUS STATE: ${previousState.toString()}`);\n\t\t\tconsole.log(`CURRENT STATE: ${currentState.toString()}`);\n\t\t}\n\n\t\tconst prefixLength = Math.min(\n\t\t\tstrings.commonPrefixLength(previousState.value, currentState.value),\n\t\t\tpreviousState.selectionStart,\n\t\t\tcurrentState.selectionStart\n\t\t);\n\t\tconst suffixLength = Math.min(\n\t\t\tstrings.commonSuffixLength(previousState.value, currentState.value),\n\t\t\tpreviousState.value.length - previousState.selectionEnd,\n\t\t\tcurrentState.value.length - currentState.selectionEnd\n\t\t);\n\t\tconst previousValue = previousState.value.substring(prefixLength, previousState.value.length - suffixLength);\n\t\tconst currentValue = currentState.value.substring(prefixLength, currentState.value.length - suffixLength);\n\t\tconst previousSelectionStart = previousState.selectionStart - prefixLength;\n\t\tconst previousSelectionEnd = previousState.selectionEnd - prefixLength;\n\t\tconst currentSelectionStart = currentState.selectionStart - prefixLength;\n\t\tconst currentSelectionEnd = currentState.selectionEnd - prefixLength;\n\n\t\tif (_debugComposition) {\n\t\t\tconsole.log(`AFTER DIFFING PREVIOUS STATE: <${previousValue}>, selectionStart: ${previousSelectionStart}, selectionEnd: ${previousSelectionEnd}`);\n\t\t\tconsole.log(`AFTER DIFFING CURRENT STATE: <${currentValue}>, selectionStart: ${currentSelectionStart}, selectionEnd: ${currentSelectionEnd}`);\n\t\t}\n\n\t\tif (currentSelectionStart === currentSelectionEnd) {\n\t\t\t// no current selection\n\t\t\tconst replacePreviousCharacters = (previousState.selectionStart - prefixLength);\n\t\t\tif (_debugComposition) {\n\t\t\t\tconsole.log(`REMOVE PREVIOUS: ${replacePreviousCharacters} chars`);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\ttext: currentValue,\n\t\t\t\treplacePrevCharCnt: replacePreviousCharacters,\n\t\t\t\treplaceNextCharCnt: 0,\n\t\t\t\tpositionDelta: 0\n\t\t\t};\n\t\t}\n\n\t\t// there is a current selection => composition case\n\t\tconst replacePreviousCharacters = previousSelectionEnd - previousSelectionStart;\n\t\treturn {\n\t\t\ttext: currentValue,\n\t\t\treplacePrevCharCnt: replacePreviousCharacters,\n\t\t\treplaceNextCharCnt: 0,\n\t\t\tpositionDelta: 0\n\t\t};\n\t}\n\n\tpublic static deduceAndroidCompositionInput(previousState: TextAreaState, currentState: TextAreaState): ITypeData {\n\t\tif (!previousState) {\n\t\t\t// This is the EMPTY state\n\t\t\treturn {\n\t\t\t\ttext: '',\n\t\t\t\treplacePrevCharCnt: 0,\n\t\t\t\treplaceNextCharCnt: 0,\n\t\t\t\tpositionDelta: 0\n\t\t\t};\n\t\t}\n\n\t\tif (_debugComposition) {\n\t\t\tconsole.log('------------------------deduceAndroidCompositionInput');\n\t\t\tconsole.log(`PREVIOUS STATE: ${previousState.toString()}`);\n\t\t\tconsole.log(`CURRENT STATE: ${currentState.toString()}`);\n\t\t}\n\n\t\tif (previousState.value === currentState.value) {\n\t\t\treturn {\n\t\t\t\ttext: '',\n\t\t\t\treplacePrevCharCnt: 0,\n\t\t\t\treplaceNextCharCnt: 0,\n\t\t\t\tpositionDelta: currentState.selectionEnd - previousState.selectionEnd\n\t\t\t};\n\t\t}\n\n\t\tconst prefixLength = Math.min(strings.commonPrefixLength(previousState.value, currentState.value), previousState.selectionEnd);\n\t\tconst suffixLength = Math.min(strings.commonSuffixLength(previousState.value, currentState.value), previousState.value.length - previousState.selectionEnd);\n\t\tconst previousValue = previousState.value.substring(prefixLength, previousState.value.length - suffixLength);\n\t\tconst currentValue = currentState.value.substring(prefixLength, currentState.value.length - suffixLength);\n\t\tconst previousSelectionStart = previousState.selectionStart - prefixLength;\n\t\tconst previousSelectionEnd = previousState.selectionEnd - prefixLength;\n\t\tconst currentSelectionStart = currentState.selectionStart - prefixLength;\n\t\tconst currentSelectionEnd = currentState.selectionEnd - prefixLength;\n\n\t\tif (_debugComposition) {\n\t\t\tconsole.log(`AFTER DIFFING PREVIOUS STATE: <${previousValue}>, selectionStart: ${previousSelectionStart}, selectionEnd: ${previousSelectionEnd}`);\n\t\t\tconsole.log(`AFTER DIFFING CURRENT STATE: <${currentValue}>, selectionStart: ${currentSelectionStart}, selectionEnd: ${currentSelectionEnd}`);\n\t\t}\n\n\t\treturn {\n\t\t\ttext: currentValue,\n\t\t\treplacePrevCharCnt: previousSelectionEnd,\n\t\t\treplaceNextCharCnt: previousValue.length - previousSelectionEnd,\n\t\t\tpositionDelta: currentSelectionEnd - currentValue.length\n\t\t};\n\t}\n}\n\nexport class PagedScreenReaderStrategy {\n\tprivate static _getPageOfLine(lineNumber: number, linesPerPage: number): number {\n\t\treturn Math.floor((lineNumber - 1) / linesPerPage);\n\t}\n\n\tprivate static _getRangeForPage(page: number, linesPerPage: number): Range {\n\t\tconst offset = page * linesPerPage;\n\t\tconst startLineNumber = offset + 1;\n\t\tconst endLineNumber = offset + linesPerPage;\n\t\treturn new Range(startLineNumber, 1, endLineNumber + 1, 1);\n\t}\n\n\tpublic static fromEditorSelection(previousState: TextAreaState, model: ISimpleModel, selection: Range, linesPerPage: number, trimLongText: boolean): TextAreaState {\n\n\t\tconst selectionStartPage = PagedScreenReaderStrategy._getPageOfLine(selection.startLineNumber, linesPerPage);\n\t\tconst selectionStartPageRange = PagedScreenReaderStrategy._getRangeForPage(selectionStartPage, linesPerPage);\n\n\t\tconst selectionEndPage = PagedScreenReaderStrategy._getPageOfLine(selection.endLineNumber, linesPerPage);\n\t\tconst selectionEndPageRange = PagedScreenReaderStrategy._getRangeForPage(selectionEndPage, linesPerPage);\n\n\t\tconst pretextRange = selectionStartPageRange.intersectRanges(new Range(1, 1, selection.startLineNumber, selection.startColumn))!;\n\t\tlet pretext = model.getValueInRange(pretextRange, EndOfLinePreference.LF);\n\n\t\tconst lastLine = model.getLineCount();\n\t\tconst lastLineMaxColumn = model.getLineMaxColumn(lastLine);\n\t\tconst posttextRange = selectionEndPageRange.intersectRanges(new Range(selection.endLineNumber, selection.endColumn, lastLine, lastLineMaxColumn))!;\n\t\tlet posttext = model.getValueInRange(posttextRange, EndOfLinePreference.LF);\n\n\n\t\tlet text: string;\n\t\tif (selectionStartPage === selectionEndPage || selectionStartPage + 1 === selectionEndPage) {\n\t\t\t// take full selection\n\t\t\ttext = model.getValueInRange(selection, EndOfLinePreference.LF);\n\t\t} else {\n\t\t\tconst selectionRange1 = selectionStartPageRange.intersectRanges(selection)!;\n\t\t\tconst selectionRange2 = selectionEndPageRange.intersectRanges(selection)!;\n\t\t\ttext = (\n\t\t\t\tmodel.getValueInRange(selectionRange1, EndOfLinePreference.LF)\n\t\t\t\t+ String.fromCharCode(8230)\n\t\t\t\t+ model.getValueInRange(selectionRange2, EndOfLinePreference.LF)\n\t\t\t);\n\t\t}\n\n\t\t// Chromium handles very poorly text even of a few thousand chars\n\t\t// Cut text to avoid stalling the entire UI\n\t\tif (trimLongText) {\n\t\t\tconst LIMIT_CHARS = 500;\n\t\t\tif (pretext.length > LIMIT_CHARS) {\n\t\t\t\tpretext = pretext.substring(pretext.length - LIMIT_CHARS, pretext.length);\n\t\t\t}\n\t\t\tif (posttext.length > LIMIT_CHARS) {\n\t\t\t\tposttext = posttext.substring(0, LIMIT_CHARS);\n\t\t\t}\n\t\t\tif (text.length > 2 * LIMIT_CHARS) {\n\t\t\t\ttext = text.substring(0, LIMIT_CHARS) + String.fromCharCode(8230) + text.substring(text.length - LIMIT_CHARS, text.length);\n\t\t\t}\n\t\t}\n\n\t\treturn new TextAreaState(pretext + text + posttext, pretext.length, pretext.length + text.length, new Position(selection.startLineNumber, selection.startColumn), new Position(selection.endLineNumber, selection.endColumn));\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as assert from 'vs/base/common/assert';\nimport { Emitter } from 'vs/base/common/event';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport * as objects from 'vs/base/common/objects';\nimport { IDiffEditor } from 'vs/editor/browser/editorBrowser';\nimport { ICursorPositionChangedEvent } from 'vs/editor/common/cursor/cursorEvents';\nimport { Range } from 'vs/editor/common/core/range';\nimport { ILineChange } from 'vs/editor/common/diff/diffComputer';\nimport { ScrollType } from 'vs/editor/common/editorCommon';\n\n\ninterface IDiffRange {\n\trhs: boolean;\n\trange: Range;\n}\n\nexport interface Options {\n\tfollowsCaret?: boolean;\n\tignoreCharChanges?: boolean;\n\talwaysRevealFirst?: boolean;\n}\n\nconst defaultOptions: Options = {\n\tfollowsCaret: true,\n\tignoreCharChanges: true,\n\talwaysRevealFirst: true\n};\n\nexport interface IDiffNavigator {\n\tcanNavigate(): boolean;\n\tnext(): void;\n\tprevious(): void;\n\tdispose(): void;\n}\n\n/**\n * Create a new diff navigator for the provided diff editor.\n */\nexport class DiffNavigator extends Disposable implements IDiffNavigator {\n\n\tprivate readonly _editor: IDiffEditor;\n\tprivate readonly _options: Options;\n\tprivate readonly _onDidUpdate = this._register(new Emitter());\n\n\tprivate disposed: boolean;\n\tprivate revealFirst: boolean;\n\tprivate nextIdx: number;\n\tprivate ranges: IDiffRange[];\n\tprivate ignoreSelectionChange: boolean;\n\n\tconstructor(editor: IDiffEditor, options: Options = {}) {\n\t\tsuper();\n\t\tthis._editor = editor;\n\t\tthis._options = objects.mixin(options, defaultOptions, false);\n\n\t\tthis.disposed = false;\n\n\t\tthis.nextIdx = -1;\n\t\tthis.ranges = [];\n\t\tthis.ignoreSelectionChange = false;\n\t\tthis.revealFirst = Boolean(this._options.alwaysRevealFirst);\n\n\t\t// hook up to diff editor for diff, disposal, and caret move\n\t\tthis._register(this._editor.onDidDispose(() => this.dispose()));\n\t\tthis._register(this._editor.onDidUpdateDiff(() => this._onDiffUpdated()));\n\n\t\tif (this._options.followsCaret) {\n\t\t\tthis._register(this._editor.getModifiedEditor().onDidChangeCursorPosition((e: ICursorPositionChangedEvent) => {\n\t\t\t\tif (this.ignoreSelectionChange) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.nextIdx = -1;\n\t\t\t}));\n\t\t}\n\t\tif (this._options.alwaysRevealFirst) {\n\t\t\tthis._register(this._editor.getModifiedEditor().onDidChangeModel((e) => {\n\t\t\t\tthis.revealFirst = true;\n\t\t\t}));\n\t\t}\n\n\t\t// init things\n\t\tthis._init();\n\t}\n\n\tprivate _init(): void {\n\t\tconst changes = this._editor.getLineChanges();\n\t\tif (!changes) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tprivate _onDiffUpdated(): void {\n\t\tthis._init();\n\n\t\tthis._compute(this._editor.getLineChanges());\n\t\tif (this.revealFirst) {\n\t\t\t// Only reveal first on first non-null changes\n\t\t\tif (this._editor.getLineChanges() !== null) {\n\t\t\t\tthis.revealFirst = false;\n\t\t\t\tthis.nextIdx = -1;\n\t\t\t\tthis.next(ScrollType.Immediate);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _compute(lineChanges: ILineChange[] | null): void {\n\n\t\t// new ranges\n\t\tthis.ranges = [];\n\n\t\tif (lineChanges) {\n\t\t\t// create ranges from changes\n\t\t\tlineChanges.forEach((lineChange) => {\n\n\t\t\t\tif (!this._options.ignoreCharChanges && lineChange.charChanges) {\n\n\t\t\t\t\tlineChange.charChanges.forEach((charChange) => {\n\t\t\t\t\t\tthis.ranges.push({\n\t\t\t\t\t\t\trhs: true,\n\t\t\t\t\t\t\trange: new Range(\n\t\t\t\t\t\t\t\tcharChange.modifiedStartLineNumber,\n\t\t\t\t\t\t\t\tcharChange.modifiedStartColumn,\n\t\t\t\t\t\t\t\tcharChange.modifiedEndLineNumber,\n\t\t\t\t\t\t\t\tcharChange.modifiedEndColumn)\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t} else {\n\t\t\t\t\tif (lineChange.modifiedEndLineNumber === 0) {\n\t\t\t\t\t\t// a deletion\n\t\t\t\t\t\tthis.ranges.push({\n\t\t\t\t\t\t\trhs: true,\n\t\t\t\t\t\t\trange: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedStartLineNumber + 1, 1)\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// an insertion or modification\n\t\t\t\t\t\tthis.ranges.push({\n\t\t\t\t\t\t\trhs: true,\n\t\t\t\t\t\t\trange: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber + 1, 1)\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// sort\n\t\tthis.ranges.sort((left, right) => Range.compareRangesUsingStarts(left.range, right.range));\n\t\tthis._onDidUpdate.fire(this);\n\t}\n\n\tprivate _initIdx(fwd: boolean): void {\n\t\tlet found = false;\n\t\tconst position = this._editor.getPosition();\n\t\tif (!position) {\n\t\t\tthis.nextIdx = 0;\n\t\t\treturn;\n\t\t}\n\t\tfor (let i = 0, len = this.ranges.length; i < len && !found; i++) {\n\t\t\tconst range = this.ranges[i].range;\n\t\t\tif (position.isBeforeOrEqual(range.getStartPosition())) {\n\t\t\t\tthis.nextIdx = i + (fwd ? 0 : -1);\n\t\t\t\tfound = true;\n\t\t\t}\n\t\t}\n\t\tif (!found) {\n\t\t\t// after the last change\n\t\t\tthis.nextIdx = fwd ? 0 : this.ranges.length - 1;\n\t\t}\n\t\tif (this.nextIdx < 0) {\n\t\t\tthis.nextIdx = this.ranges.length - 1;\n\t\t}\n\t}\n\n\tprivate _move(fwd: boolean, scrollType: ScrollType): void {\n\t\tassert.ok(!this.disposed, 'Illegal State - diff navigator has been disposed');\n\n\t\tif (!this.canNavigate()) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.nextIdx === -1) {\n\t\t\tthis._initIdx(fwd);\n\n\t\t} else if (fwd) {\n\t\t\tthis.nextIdx += 1;\n\t\t\tif (this.nextIdx >= this.ranges.length) {\n\t\t\t\tthis.nextIdx = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.nextIdx -= 1;\n\t\t\tif (this.nextIdx < 0) {\n\t\t\t\tthis.nextIdx = this.ranges.length - 1;\n\t\t\t}\n\t\t}\n\n\t\tconst info = this.ranges[this.nextIdx];\n\t\tthis.ignoreSelectionChange = true;\n\t\ttry {\n\t\t\tconst pos = info.range.getStartPosition();\n\t\t\tthis._editor.setPosition(pos);\n\t\t\tthis._editor.revealRangeInCenter(info.range, scrollType);\n\t\t} finally {\n\t\t\tthis.ignoreSelectionChange = false;\n\t\t}\n\t}\n\n\tcanNavigate(): boolean {\n\t\treturn this.ranges && this.ranges.length > 0;\n\t}\n\n\tnext(scrollType: ScrollType = ScrollType.Smooth): void {\n\t\tthis._move(true, scrollType);\n\t}\n\n\tprevious(scrollType: ScrollType = ScrollType.Smooth): void {\n\t\tthis._move(false, scrollType);\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tthis.ranges = [];\n\t\tthis.disposed = true;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Position } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\n\n/**\n * A single edit operation, that acts as a simple replace.\n * i.e. Replace text at `range` with `text` in model.\n */\nexport interface ISingleEditOperation {\n\t/**\n\t * The range to replace. This can be empty to emulate a simple insert.\n\t */\n\trange: IRange;\n\t/**\n\t * The text to replace with. This can be null to emulate a simple delete.\n\t */\n\ttext: string | null;\n\t/**\n\t * This indicates that this operation has \"insert\" semantics.\n\t * i.e. forceMoveMarkers = true => if `range` is collapsed, all markers at the position will be moved.\n\t */\n\tforceMoveMarkers?: boolean;\n}\n\nexport class EditOperation {\n\n\tpublic static insert(position: Position, text: string): ISingleEditOperation {\n\t\treturn {\n\t\t\trange: new Range(position.lineNumber, position.column, position.lineNumber, position.column),\n\t\t\ttext: text,\n\t\t\tforceMoveMarkers: true\n\t\t};\n\t}\n\n\tpublic static delete(range: Range): ISingleEditOperation {\n\t\treturn {\n\t\t\trange: range,\n\t\t\ttext: null\n\t\t};\n\t}\n\n\tpublic static replace(range: Range, text: string | null): ISingleEditOperation {\n\t\treturn {\n\t\t\trange: range,\n\t\t\ttext: text\n\t\t};\n\t}\n\n\tpublic static replaceMove(range: Range, text: string | null): ISingleEditOperation {\n\t\treturn {\n\t\t\trange: range,\n\t\t\ttext: text,\n\t\t\tforceMoveMarkers: true\n\t\t};\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as strings from 'vs/base/common/strings';\nimport { EditOperation } from 'vs/editor/common/core/editOperation';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model';\n\nexport class TrimTrailingWhitespaceCommand implements ICommand {\n\n\tprivate readonly _selection: Selection;\n\tprivate _selectionId: string | null;\n\tprivate readonly _cursors: Position[];\n\n\tconstructor(selection: Selection, cursors: Position[]) {\n\t\tthis._selection = selection;\n\t\tthis._cursors = cursors;\n\t\tthis._selectionId = null;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tconst ops = trimTrailingWhitespace(model, this._cursors);\n\t\tfor (let i = 0, len = ops.length; i < len; i++) {\n\t\t\tconst op = ops[i];\n\n\t\t\tbuilder.addEditOperation(op.range, op.text);\n\t\t}\n\n\t\tthis._selectionId = builder.trackSelection(this._selection);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\treturn helper.getTrackedSelection(this._selectionId!);\n\t}\n}\n\n/**\n * Generate commands for trimming trailing whitespace on a model and ignore lines on which cursors are sitting.\n */\nexport function trimTrailingWhitespace(model: ITextModel, cursors: Position[]): IIdentifiedSingleEditOperation[] {\n\t// Sort cursors ascending\n\tcursors.sort((a, b) => {\n\t\tif (a.lineNumber === b.lineNumber) {\n\t\t\treturn a.column - b.column;\n\t\t}\n\t\treturn a.lineNumber - b.lineNumber;\n\t});\n\n\t// Reduce multiple cursors on the same line and only keep the last one on the line\n\tfor (let i = cursors.length - 2; i >= 0; i--) {\n\t\tif (cursors[i].lineNumber === cursors[i + 1].lineNumber) {\n\t\t\t// Remove cursor at `i`\n\t\t\tcursors.splice(i, 1);\n\t\t}\n\t}\n\n\tconst r: IIdentifiedSingleEditOperation[] = [];\n\tlet rLen = 0;\n\tlet cursorIndex = 0;\n\tconst cursorLen = cursors.length;\n\n\tfor (let lineNumber = 1, lineCount = model.getLineCount(); lineNumber <= lineCount; lineNumber++) {\n\t\tconst lineContent = model.getLineContent(lineNumber);\n\t\tconst maxLineColumn = lineContent.length + 1;\n\t\tlet minEditColumn = 0;\n\n\t\tif (cursorIndex < cursorLen && cursors[cursorIndex].lineNumber === lineNumber) {\n\t\t\tminEditColumn = cursors[cursorIndex].column;\n\t\t\tcursorIndex++;\n\t\t\tif (minEditColumn === maxLineColumn) {\n\t\t\t\t// The cursor is at the end of the line => no edits for sure on this line\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif (lineContent.length === 0) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst lastNonWhitespaceIndex = strings.lastNonWhitespaceIndex(lineContent);\n\n\t\tlet fromColumn = 0;\n\t\tif (lastNonWhitespaceIndex === -1) {\n\t\t\t// Entire line is whitespace\n\t\t\tfromColumn = 1;\n\t\t} else if (lastNonWhitespaceIndex !== lineContent.length - 1) {\n\t\t\t// There is trailing whitespace\n\t\t\tfromColumn = lastNonWhitespaceIndex + 2;\n\t\t} else {\n\t\t\t// There is no trailing whitespace\n\t\t\tcontinue;\n\t\t}\n\n\t\tfromColumn = Math.max(minEditColumn, fromColumn);\n\t\tr[rLen++] = EditOperation.delete(new Range(\n\t\t\tlineNumber, fromColumn,\n\t\t\tlineNumber, maxLineColumn\n\t\t));\n\t}\n\n\treturn r;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n/**\n * A very VM friendly rgba datastructure.\n * Please don't touch unless you take a look at the IR.\n */\nexport class RGBA8 {\n\t_rgba8Brand: void = undefined;\n\n\tstatic readonly Empty = new RGBA8(0, 0, 0, 0);\n\n\t/**\n\t * Red: integer in [0-255]\n\t */\n\tpublic readonly r: number;\n\t/**\n\t * Green: integer in [0-255]\n\t */\n\tpublic readonly g: number;\n\t/**\n\t * Blue: integer in [0-255]\n\t */\n\tpublic readonly b: number;\n\t/**\n\t * Alpha: integer in [0-255]\n\t */\n\tpublic readonly a: number;\n\n\tconstructor(r: number, g: number, b: number, a: number) {\n\t\tthis.r = RGBA8._clamp(r);\n\t\tthis.g = RGBA8._clamp(g);\n\t\tthis.b = RGBA8._clamp(b);\n\t\tthis.a = RGBA8._clamp(a);\n\t}\n\n\tpublic equals(other: RGBA8): boolean {\n\t\treturn (\n\t\t\tthis.r === other.r\n\t\t\t&& this.g === other.g\n\t\t\t&& this.b === other.b\n\t\t\t&& this.a === other.a\n\t\t);\n\t}\n\n\tpublic static _clamp(c: number): number {\n\t\tif (c < 0) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (c > 255) {\n\t\t\treturn 255;\n\t\t}\n\t\treturn c | 0;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IPosition, Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\n\n/**\n * A selection in the editor.\n * The selection is a range that has an orientation.\n */\nexport interface ISelection {\n\t/**\n\t * The line number on which the selection has started.\n\t */\n\treadonly selectionStartLineNumber: number;\n\t/**\n\t * The column on `selectionStartLineNumber` where the selection has started.\n\t */\n\treadonly selectionStartColumn: number;\n\t/**\n\t * The line number on which the selection has ended.\n\t */\n\treadonly positionLineNumber: number;\n\t/**\n\t * The column on `positionLineNumber` where the selection has ended.\n\t */\n\treadonly positionColumn: number;\n}\n\n/**\n * The direction of a selection.\n */\nexport const enum SelectionDirection {\n\t/**\n\t * The selection starts above where it ends.\n\t */\n\tLTR,\n\t/**\n\t * The selection starts below where it ends.\n\t */\n\tRTL\n}\n\n/**\n * A selection in the editor.\n * The selection is a range that has an orientation.\n */\nexport class Selection extends Range {\n\t/**\n\t * The line number on which the selection has started.\n\t */\n\tpublic readonly selectionStartLineNumber: number;\n\t/**\n\t * The column on `selectionStartLineNumber` where the selection has started.\n\t */\n\tpublic readonly selectionStartColumn: number;\n\t/**\n\t * The line number on which the selection has ended.\n\t */\n\tpublic readonly positionLineNumber: number;\n\t/**\n\t * The column on `positionLineNumber` where the selection has ended.\n\t */\n\tpublic readonly positionColumn: number;\n\n\tconstructor(selectionStartLineNumber: number, selectionStartColumn: number, positionLineNumber: number, positionColumn: number) {\n\t\tsuper(selectionStartLineNumber, selectionStartColumn, positionLineNumber, positionColumn);\n\t\tthis.selectionStartLineNumber = selectionStartLineNumber;\n\t\tthis.selectionStartColumn = selectionStartColumn;\n\t\tthis.positionLineNumber = positionLineNumber;\n\t\tthis.positionColumn = positionColumn;\n\t}\n\n\t/**\n\t * Transform to a human-readable representation.\n\t */\n\tpublic override toString(): string {\n\t\treturn '[' + this.selectionStartLineNumber + ',' + this.selectionStartColumn + ' -> ' + this.positionLineNumber + ',' + this.positionColumn + ']';\n\t}\n\n\t/**\n\t * Test if equals other selection.\n\t */\n\tpublic equalsSelection(other: ISelection): boolean {\n\t\treturn (\n\t\t\tSelection.selectionsEqual(this, other)\n\t\t);\n\t}\n\n\t/**\n\t * Test if the two selections are equal.\n\t */\n\tpublic static selectionsEqual(a: ISelection, b: ISelection): boolean {\n\t\treturn (\n\t\t\ta.selectionStartLineNumber === b.selectionStartLineNumber &&\n\t\t\ta.selectionStartColumn === b.selectionStartColumn &&\n\t\t\ta.positionLineNumber === b.positionLineNumber &&\n\t\t\ta.positionColumn === b.positionColumn\n\t\t);\n\t}\n\n\t/**\n\t * Get directions (LTR or RTL).\n\t */\n\tpublic getDirection(): SelectionDirection {\n\t\tif (this.selectionStartLineNumber === this.startLineNumber && this.selectionStartColumn === this.startColumn) {\n\t\t\treturn SelectionDirection.LTR;\n\t\t}\n\t\treturn SelectionDirection.RTL;\n\t}\n\n\t/**\n\t * Create a new selection with a different `positionLineNumber` and `positionColumn`.\n\t */\n\tpublic override setEndPosition(endLineNumber: number, endColumn: number): Selection {\n\t\tif (this.getDirection() === SelectionDirection.LTR) {\n\t\t\treturn new Selection(this.startLineNumber, this.startColumn, endLineNumber, endColumn);\n\t\t}\n\t\treturn new Selection(endLineNumber, endColumn, this.startLineNumber, this.startColumn);\n\t}\n\n\t/**\n\t * Get the position at `positionLineNumber` and `positionColumn`.\n\t */\n\tpublic getPosition(): Position {\n\t\treturn new Position(this.positionLineNumber, this.positionColumn);\n\t}\n\n\t/**\n\t * Get the position at the start of the selection.\n\t*/\n\tpublic getSelectionStart(): Position {\n\t\treturn new Position(this.selectionStartLineNumber, this.selectionStartColumn);\n\t}\n\n\t/**\n\t * Create a new selection with a different `selectionStartLineNumber` and `selectionStartColumn`.\n\t */\n\tpublic override setStartPosition(startLineNumber: number, startColumn: number): Selection {\n\t\tif (this.getDirection() === SelectionDirection.LTR) {\n\t\t\treturn new Selection(startLineNumber, startColumn, this.endLineNumber, this.endColumn);\n\t\t}\n\t\treturn new Selection(this.endLineNumber, this.endColumn, startLineNumber, startColumn);\n\t}\n\n\t// ----\n\n\t/**\n\t * Create a `Selection` from one or two positions\n\t */\n\tpublic static override fromPositions(start: IPosition, end: IPosition = start): Selection {\n\t\treturn new Selection(start.lineNumber, start.column, end.lineNumber, end.column);\n\t}\n\n\t/**\n\t * Creates a `Selection` from a range, given a direction.\n\t */\n\tpublic static fromRange(range: Range, direction: SelectionDirection): Selection {\n\t\tif (direction === SelectionDirection.LTR) {\n\t\t\treturn new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);\n\t\t} else {\n\t\t\treturn new Selection(range.endLineNumber, range.endColumn, range.startLineNumber, range.startColumn);\n\t\t}\n\t}\n\n\t/**\n\t * Create a `Selection` from an `ISelection`.\n\t */\n\tpublic static liftSelection(sel: ISelection): Selection {\n\t\treturn new Selection(sel.selectionStartLineNumber, sel.selectionStartColumn, sel.positionLineNumber, sel.positionColumn);\n\t}\n\n\t/**\n\t * `a` equals `b`.\n\t */\n\tpublic static selectionsArrEqual(a: ISelection[], b: ISelection[]): boolean {\n\t\tif (a && !b || !a && b) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!a && !b) {\n\t\t\treturn true;\n\t\t}\n\t\tif (a.length !== b.length) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let i = 0, len = a.length; i < len; i++) {\n\t\t\tif (!this.selectionsEqual(a[i], b[i])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Test if `obj` is an `ISelection`.\n\t */\n\tpublic static isISelection(obj: any): obj is ISelection {\n\t\treturn (\n\t\t\tobj\n\t\t\t&& (typeof obj.selectionStartLineNumber === 'number')\n\t\t\t&& (typeof obj.selectionStartColumn === 'number')\n\t\t\t&& (typeof obj.positionLineNumber === 'number')\n\t\t\t&& (typeof obj.positionColumn === 'number')\n\t\t);\n\t}\n\n\t/**\n\t * Create with a direction.\n\t */\n\tpublic static createWithDirection(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, direction: SelectionDirection): Selection {\n\n\t\tif (direction === SelectionDirection.LTR) {\n\t\t\treturn new Selection(startLineNumber, startColumn, endLineNumber, endColumn);\n\t\t}\n\n\t\treturn new Selection(endLineNumber, endColumn, startLineNumber, startColumn);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as browser from 'vs/base/browser/browser';\nimport * as dom from 'vs/base/browser/dom';\nimport { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { RunOnceScheduler } from 'vs/base/common/async';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport { Mimes } from 'vs/base/common/mime';\nimport { OperatingSystem } from 'vs/base/common/platform';\nimport * as strings from 'vs/base/common/strings';\nimport { ITextAreaWrapper, ITypeData, TextAreaState, _debugComposition } from 'vs/editor/browser/controller/textAreaState';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Selection } from 'vs/editor/common/core/selection';\n\nexport namespace TextAreaSyntethicEvents {\n\texport const Tap = '-monaco-textarea-synthetic-tap';\n}\n\nexport interface ICompositionData {\n}\n\nexport const CopyOptions = {\n\tforceCopyWithSyntaxHighlighting: false\n};\n\nexport interface IPasteData {\n\ttext: string;\n\tmetadata: ClipboardStoredMetadata | null;\n}\n\nexport interface ClipboardDataToCopy {\n\tisFromEmptySelection: boolean;\n\tmulticursorText: string[] | null | undefined;\n\ttext: string;\n\thtml: string | null | undefined;\n\tmode: string | null;\n}\n\nexport interface ClipboardStoredMetadata {\n\tversion: 1;\n\tisFromEmptySelection: boolean | undefined;\n\tmulticursorText: string[] | null | undefined;\n\tmode: string | null;\n}\n\nexport interface ITextAreaInputHost {\n\tgetDataToCopy(): ClipboardDataToCopy;\n\tgetScreenReaderContent(currentState: TextAreaState): TextAreaState;\n\tdeduceModelPosition(viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position;\n}\n\ninterface InMemoryClipboardMetadata {\n\tlastCopiedValue: string;\n\tdata: ClipboardStoredMetadata;\n}\n\n/**\n * Every time we write to the clipboard, we record a bit of extra metadata here.\n * Every time we read from the cipboard, if the text matches our last written text,\n * we can fetch the previous metadata.\n */\nexport class InMemoryClipboardMetadataManager {\n\tpublic static readonly INSTANCE = new InMemoryClipboardMetadataManager();\n\n\tprivate _lastState: InMemoryClipboardMetadata | null;\n\n\tconstructor() {\n\t\tthis._lastState = null;\n\t}\n\n\tpublic set(lastCopiedValue: string, data: ClipboardStoredMetadata): void {\n\t\tthis._lastState = { lastCopiedValue, data };\n\t}\n\n\tpublic get(pastedText: string): ClipboardStoredMetadata | null {\n\t\tif (this._lastState && this._lastState.lastCopiedValue === pastedText) {\n\t\t\t// match!\n\t\t\treturn this._lastState.data;\n\t\t}\n\t\tthis._lastState = null;\n\t\treturn null;\n\t}\n}\n\nexport interface ICompositionStartEvent {\n\tdata: string;\n}\n\nexport interface ICompleteTextAreaWrapper extends ITextAreaWrapper {\n\treadonly onKeyDown: Event;\n\treadonly onKeyUp: Event;\n\treadonly onCompositionStart: Event;\n\treadonly onCompositionUpdate: Event;\n\treadonly onCompositionEnd: Event;\n\treadonly onInput: Event;\n\treadonly onCut: Event;\n\treadonly onCopy: Event;\n\treadonly onPaste: Event;\n\treadonly onFocus: Event;\n\treadonly onBlur: Event;\n\treadonly onSyntheticTap: Event;\n\n\tsetIgnoreSelectionChangeTime(reason: string): void;\n\tgetIgnoreSelectionChangeTime(): number;\n\tresetSelectionChangeTime(): void;\n\n\thasFocus(): boolean;\n}\n\nexport interface IBrowser {\n\tisAndroid: boolean;\n\tisFirefox: boolean;\n\tisChrome: boolean;\n\tisSafari: boolean;\n}\n\nclass CompositionContext {\n\n\tprivate _lastTypeTextLength: number;\n\n\tconstructor() {\n\t\tthis._lastTypeTextLength = 0;\n\t}\n\n\tpublic handleCompositionUpdate(text: string | null | undefined): ITypeData {\n\t\ttext = text || '';\n\t\tconst typeInput: ITypeData = {\n\t\t\ttext: text,\n\t\t\treplacePrevCharCnt: this._lastTypeTextLength,\n\t\t\treplaceNextCharCnt: 0,\n\t\t\tpositionDelta: 0\n\t\t};\n\t\tthis._lastTypeTextLength = text.length;\n\t\treturn typeInput;\n\t}\n}\n\n/**\n * Writes screen reader content to the textarea and is able to analyze its input events to generate:\n * - onCut\n * - onPaste\n * - onType\n *\n * Composition events are generated for presentation purposes (composition input is reflected in onType).\n */\nexport class TextAreaInput extends Disposable {\n\n\tprivate _onFocus = this._register(new Emitter());\n\tpublic readonly onFocus: Event = this._onFocus.event;\n\n\tprivate _onBlur = this._register(new Emitter());\n\tpublic readonly onBlur: Event = this._onBlur.event;\n\n\tprivate _onKeyDown = this._register(new Emitter());\n\tpublic readonly onKeyDown: Event = this._onKeyDown.event;\n\n\tprivate _onKeyUp = this._register(new Emitter());\n\tpublic readonly onKeyUp: Event = this._onKeyUp.event;\n\n\tprivate _onCut = this._register(new Emitter());\n\tpublic readonly onCut: Event = this._onCut.event;\n\n\tprivate _onPaste = this._register(new Emitter());\n\tpublic readonly onPaste: Event = this._onPaste.event;\n\n\tprivate _onType = this._register(new Emitter());\n\tpublic readonly onType: Event = this._onType.event;\n\n\tprivate _onCompositionStart = this._register(new Emitter());\n\tpublic readonly onCompositionStart: Event = this._onCompositionStart.event;\n\n\tprivate _onCompositionUpdate = this._register(new Emitter());\n\tpublic readonly onCompositionUpdate: Event = this._onCompositionUpdate.event;\n\n\tprivate _onCompositionEnd = this._register(new Emitter());\n\tpublic readonly onCompositionEnd: Event = this._onCompositionEnd.event;\n\n\tprivate _onSelectionChangeRequest = this._register(new Emitter());\n\tpublic readonly onSelectionChangeRequest: Event = this._onSelectionChangeRequest.event;\n\n\t// ---\n\n\tprivate readonly _asyncTriggerCut: RunOnceScheduler;\n\tprivate readonly _asyncFocusGainWriteScreenReaderContent: RunOnceScheduler;\n\n\tprivate _textAreaState: TextAreaState;\n\tprivate _selectionChangeListener: IDisposable | null;\n\n\tprivate _hasFocus: boolean;\n\tprivate _currentComposition: CompositionContext | null;\n\n\tconstructor(\n\t\tprivate readonly _host: ITextAreaInputHost,\n\t\tprivate readonly _textArea: ICompleteTextAreaWrapper,\n\t\tprivate readonly _OS: OperatingSystem,\n\t\tprivate readonly _browser: IBrowser\n\t) {\n\t\tsuper();\n\t\tthis._asyncTriggerCut = this._register(new RunOnceScheduler(() => this._onCut.fire(), 0));\n\t\tthis._asyncFocusGainWriteScreenReaderContent = this._register(new RunOnceScheduler(() => this.writeScreenReaderContent('asyncFocusGain'), 0));\n\n\t\tthis._textAreaState = TextAreaState.EMPTY;\n\t\tthis._selectionChangeListener = null;\n\t\tthis.writeScreenReaderContent('ctor');\n\n\t\tthis._hasFocus = false;\n\t\tthis._currentComposition = null;\n\n\t\tlet lastKeyDown: IKeyboardEvent | null = null;\n\n\t\tthis._register(this._textArea.onKeyDown((_e) => {\n\t\t\tconst e = new StandardKeyboardEvent(_e);\n\t\t\tif (e.keyCode === KeyCode.KEY_IN_COMPOSITION\n\t\t\t\t|| (this._currentComposition && e.keyCode === KeyCode.Backspace)) {\n\t\t\t\t// Stop propagation for keyDown events if the IME is processing key input\n\t\t\t\te.stopPropagation();\n\t\t\t}\n\n\t\t\tif (e.equals(KeyCode.Escape)) {\n\t\t\t\t// Prevent default always for `Esc`, otherwise it will generate a keypress\n\t\t\t\t// See https://msdn.microsoft.com/en-us/library/ie/ms536939(v=vs.85).aspx\n\t\t\t\te.preventDefault();\n\t\t\t}\n\n\t\t\tlastKeyDown = e;\n\t\t\tthis._onKeyDown.fire(e);\n\t\t}));\n\n\t\tthis._register(this._textArea.onKeyUp((_e) => {\n\t\t\tconst e = new StandardKeyboardEvent(_e);\n\t\t\tthis._onKeyUp.fire(e);\n\t\t}));\n\n\t\tthis._register(this._textArea.onCompositionStart((e) => {\n\t\t\tif (_debugComposition) {\n\t\t\t\tconsole.log(`[compositionstart]`, e);\n\t\t\t}\n\n\t\t\tconst currentComposition = new CompositionContext();\n\t\t\tif (this._currentComposition) {\n\t\t\t\t// simply reset the composition context\n\t\t\t\tthis._currentComposition = currentComposition;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._currentComposition = currentComposition;\n\n\t\t\tif (\n\t\t\t\tthis._OS === OperatingSystem.Macintosh\n\t\t\t\t&& lastKeyDown\n\t\t\t\t&& lastKeyDown.equals(KeyCode.KEY_IN_COMPOSITION)\n\t\t\t\t&& this._textAreaState.selectionStart === this._textAreaState.selectionEnd\n\t\t\t\t&& this._textAreaState.selectionStart > 0\n\t\t\t\t&& this._textAreaState.value.substr(this._textAreaState.selectionStart - 1, 1) === e.data\n\t\t\t\t&& (lastKeyDown.code === 'ArrowRight' || lastKeyDown.code === 'ArrowLeft')\n\t\t\t) {\n\t\t\t\t// Handling long press case on Chromium/Safari macOS + arrow key => pretend the character was selected\n\t\t\t\tif (_debugComposition) {\n\t\t\t\t\tconsole.log(`[compositionstart] Handling long press case on macOS + arrow key`, e);\n\t\t\t\t}\n\t\t\t\t// Pretend the previous character was composed (in order to get it removed by subsequent compositionupdate events)\n\t\t\t\tcurrentComposition.handleCompositionUpdate('x');\n\t\t\t\tthis._onCompositionStart.fire({ data: e.data });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this._browser.isAndroid) {\n\t\t\t\t// when tapping on the editor, Android enters composition mode to edit the current word\n\t\t\t\t// so we cannot clear the textarea on Android and we must pretend the current word was selected\n\t\t\t\tthis._onCompositionStart.fire({ data: e.data });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._onCompositionStart.fire({ data: e.data });\n\t\t}));\n\n\t\tthis._register(this._textArea.onCompositionUpdate((e) => {\n\t\t\tif (_debugComposition) {\n\t\t\t\tconsole.log(`[compositionupdate]`, e);\n\t\t\t}\n\t\t\tconst currentComposition = this._currentComposition;\n\t\t\tif (!currentComposition) {\n\t\t\t\t// should not be possible to receive a 'compositionupdate' without a 'compositionstart'\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this._browser.isAndroid) {\n\t\t\t\t// On Android, the data sent with the composition update event is unusable.\n\t\t\t\t// For example, if the cursor is in the middle of a word like Mic|osoft\n\t\t\t\t// and Microsoft is chosen from the keyboard's suggestions, the e.data will contain \"Microsoft\".\n\t\t\t\t// This is not really usable because it doesn't tell us where the edit began and where it ended.\n\t\t\t\tconst newState = TextAreaState.readFromTextArea(this._textArea);\n\t\t\t\tconst typeInput = TextAreaState.deduceAndroidCompositionInput(this._textAreaState, newState);\n\t\t\t\tthis._textAreaState = newState;\n\t\t\t\tthis._onType.fire(typeInput);\n\t\t\t\tthis._onCompositionUpdate.fire(e);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst typeInput = currentComposition.handleCompositionUpdate(e.data);\n\t\t\tthis._textAreaState = TextAreaState.readFromTextArea(this._textArea);\n\t\t\tthis._onType.fire(typeInput);\n\t\t\tthis._onCompositionUpdate.fire(e);\n\t\t}));\n\n\t\tthis._register(this._textArea.onCompositionEnd((e) => {\n\t\t\tif (_debugComposition) {\n\t\t\t\tconsole.log(`[compositionend]`, e);\n\t\t\t}\n\t\t\tconst currentComposition = this._currentComposition;\n\t\t\tif (!currentComposition) {\n\t\t\t\t// https://github.com/microsoft/monaco-editor/issues/1663\n\t\t\t\t// On iOS 13.2, Chinese system IME randomly trigger an additional compositionend event with empty data\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._currentComposition = null;\n\n\t\t\tif (this._browser.isAndroid) {\n\t\t\t\t// On Android, the data sent with the composition update event is unusable.\n\t\t\t\t// For example, if the cursor is in the middle of a word like Mic|osoft\n\t\t\t\t// and Microsoft is chosen from the keyboard's suggestions, the e.data will contain \"Microsoft\".\n\t\t\t\t// This is not really usable because it doesn't tell us where the edit began and where it ended.\n\t\t\t\tconst newState = TextAreaState.readFromTextArea(this._textArea);\n\t\t\t\tconst typeInput = TextAreaState.deduceAndroidCompositionInput(this._textAreaState, newState);\n\t\t\t\tthis._textAreaState = newState;\n\t\t\t\tthis._onType.fire(typeInput);\n\t\t\t\tthis._onCompositionEnd.fire();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst typeInput = currentComposition.handleCompositionUpdate(e.data);\n\t\t\tthis._textAreaState = TextAreaState.readFromTextArea(this._textArea);\n\t\t\tthis._onType.fire(typeInput);\n\t\t\tthis._onCompositionEnd.fire();\n\t\t}));\n\n\t\tthis._register(this._textArea.onInput((e) => {\n\t\t\tif (_debugComposition) {\n\t\t\t\tconsole.log(`[input]`, e);\n\t\t\t}\n\n\t\t\t// Pretend here we touched the text area, as the `input` event will most likely\n\t\t\t// result in a `selectionchange` event which we want to ignore\n\t\t\tthis._textArea.setIgnoreSelectionChangeTime('received input event');\n\n\t\t\tif (this._currentComposition) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst newState = TextAreaState.readFromTextArea(this._textArea);\n\t\t\tconst typeInput = TextAreaState.deduceInput(this._textAreaState, newState, /*couldBeEmojiInput*/this._OS === OperatingSystem.Macintosh);\n\n\t\t\tif (typeInput.replacePrevCharCnt === 0 && typeInput.text.length === 1 && strings.isHighSurrogate(typeInput.text.charCodeAt(0))) {\n\t\t\t\t// Ignore invalid input but keep it around for next time\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._textAreaState = newState;\n\t\t\tif (\n\t\t\t\ttypeInput.text !== ''\n\t\t\t\t|| typeInput.replacePrevCharCnt !== 0\n\t\t\t\t|| typeInput.replaceNextCharCnt !== 0\n\t\t\t\t|| typeInput.positionDelta !== 0\n\t\t\t) {\n\t\t\t\tthis._onType.fire(typeInput);\n\t\t\t}\n\t\t}));\n\n\t\t// --- Clipboard operations\n\n\t\tthis._register(this._textArea.onCut((e) => {\n\t\t\t// Pretend here we touched the text area, as the `cut` event will most likely\n\t\t\t// result in a `selectionchange` event which we want to ignore\n\t\t\tthis._textArea.setIgnoreSelectionChangeTime('received cut event');\n\n\t\t\tthis._ensureClipboardGetsEditorSelection(e);\n\t\t\tthis._asyncTriggerCut.schedule();\n\t\t}));\n\n\t\tthis._register(this._textArea.onCopy((e) => {\n\t\t\tthis._ensureClipboardGetsEditorSelection(e);\n\t\t}));\n\n\t\tthis._register(this._textArea.onPaste((e) => {\n\t\t\t// Pretend here we touched the text area, as the `paste` event will most likely\n\t\t\t// result in a `selectionchange` event which we want to ignore\n\t\t\tthis._textArea.setIgnoreSelectionChangeTime('received paste event');\n\n\t\t\te.preventDefault();\n\n\t\t\tif (!e.clipboardData) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet [text, metadata] = ClipboardEventUtils.getTextData(e.clipboardData);\n\t\t\tif (!text) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// try the in-memory store\n\t\t\tmetadata = metadata || InMemoryClipboardMetadataManager.INSTANCE.get(text);\n\n\t\t\tthis._onPaste.fire({\n\t\t\t\ttext: text,\n\t\t\t\tmetadata: metadata\n\t\t\t});\n\t\t}));\n\n\t\tthis._register(this._textArea.onFocus(() => {\n\t\t\tconst hadFocus = this._hasFocus;\n\n\t\t\tthis._setHasFocus(true);\n\n\t\t\tif (this._browser.isSafari && !hadFocus && this._hasFocus) {\n\t\t\t\t// When \"tabbing into\" the textarea, immediately after dispatching the 'focus' event,\n\t\t\t\t// Safari will always move the selection at offset 0 in the textarea\n\t\t\t\tthis._asyncFocusGainWriteScreenReaderContent.schedule();\n\t\t\t}\n\t\t}));\n\t\tthis._register(this._textArea.onBlur(() => {\n\t\t\tif (this._currentComposition) {\n\t\t\t\t// See https://github.com/microsoft/vscode/issues/112621\n\t\t\t\t// where compositionend is not triggered when the editor\n\t\t\t\t// is taken off-dom during a composition\n\n\t\t\t\t// Clear the flag to be able to write to the textarea\n\t\t\t\tthis._currentComposition = null;\n\n\t\t\t\t// Clear the textarea to avoid an unwanted cursor type\n\t\t\t\tthis.writeScreenReaderContent('blurWithoutCompositionEnd');\n\n\t\t\t\t// Fire artificial composition end\n\t\t\t\tthis._onCompositionEnd.fire();\n\t\t\t}\n\t\t\tthis._setHasFocus(false);\n\t\t}));\n\t\tthis._register(this._textArea.onSyntheticTap(() => {\n\t\t\tif (this._browser.isAndroid && this._currentComposition) {\n\t\t\t\t// on Android, tapping does not cancel the current composition, so the\n\t\t\t\t// textarea is stuck showing the old composition\n\n\t\t\t\t// Clear the flag to be able to write to the textarea\n\t\t\t\tthis._currentComposition = null;\n\n\t\t\t\t// Clear the textarea to avoid an unwanted cursor type\n\t\t\t\tthis.writeScreenReaderContent('tapWithoutCompositionEnd');\n\n\t\t\t\t// Fire artificial composition end\n\t\t\t\tthis._onCompositionEnd.fire();\n\t\t\t}\n\t\t}));\n\t}\n\n\tprivate _installSelectionChangeListener(): IDisposable {\n\t\t// See https://github.com/microsoft/vscode/issues/27216 and https://github.com/microsoft/vscode/issues/98256\n\t\t// When using a Braille display, it is possible for users to reposition the\n\t\t// system caret. This is reflected in Chrome as a `selectionchange` event.\n\t\t//\n\t\t// The `selectionchange` event appears to be emitted under numerous other circumstances,\n\t\t// so it is quite a challenge to distinguish a `selectionchange` coming in from a user\n\t\t// using a Braille display from all the other cases.\n\t\t//\n\t\t// The problems with the `selectionchange` event are:\n\t\t// * the event is emitted when the textarea is focused programmatically -- textarea.focus()\n\t\t// * the event is emitted when the selection is changed in the textarea programmatically -- textarea.setSelectionRange(...)\n\t\t// * the event is emitted when the value of the textarea is changed programmatically -- textarea.value = '...'\n\t\t// * the event is emitted when tabbing into the textarea\n\t\t// * the event is emitted asynchronously (sometimes with a delay as high as a few tens of ms)\n\t\t// * the event sometimes comes in bursts for a single logical textarea operation\n\n\t\t// `selectionchange` events often come multiple times for a single logical change\n\t\t// so throttle multiple `selectionchange` events that burst in a short period of time.\n\t\tlet previousSelectionChangeEventTime = 0;\n\t\treturn dom.addDisposableListener(document, 'selectionchange', (e) => {\n\t\t\tif (!this._hasFocus) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this._currentComposition) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!this._browser.isChrome) {\n\t\t\t\t// Support only for Chrome until testing happens on other browsers\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst now = Date.now();\n\n\t\t\tconst delta1 = now - previousSelectionChangeEventTime;\n\t\t\tpreviousSelectionChangeEventTime = now;\n\t\t\tif (delta1 < 5) {\n\t\t\t\t// received another `selectionchange` event within 5ms of the previous `selectionchange` event\n\t\t\t\t// => ignore it\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst delta2 = now - this._textArea.getIgnoreSelectionChangeTime();\n\t\t\tthis._textArea.resetSelectionChangeTime();\n\t\t\tif (delta2 < 100) {\n\t\t\t\t// received a `selectionchange` event within 100ms since we touched the textarea\n\t\t\t\t// => ignore it, since we caused it\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!this._textAreaState.selectionStartPosition || !this._textAreaState.selectionEndPosition) {\n\t\t\t\t// Cannot correlate a position in the textarea with a position in the editor...\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst newValue = this._textArea.getValue();\n\t\t\tif (this._textAreaState.value !== newValue) {\n\t\t\t\t// Cannot correlate a position in the textarea with a position in the editor...\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst newSelectionStart = this._textArea.getSelectionStart();\n\t\t\tconst newSelectionEnd = this._textArea.getSelectionEnd();\n\t\t\tif (this._textAreaState.selectionStart === newSelectionStart && this._textAreaState.selectionEnd === newSelectionEnd) {\n\t\t\t\t// Nothing to do...\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst _newSelectionStartPosition = this._textAreaState.deduceEditorPosition(newSelectionStart);\n\t\t\tconst newSelectionStartPosition = this._host.deduceModelPosition(_newSelectionStartPosition[0]!, _newSelectionStartPosition[1], _newSelectionStartPosition[2]);\n\n\t\t\tconst _newSelectionEndPosition = this._textAreaState.deduceEditorPosition(newSelectionEnd);\n\t\t\tconst newSelectionEndPosition = this._host.deduceModelPosition(_newSelectionEndPosition[0]!, _newSelectionEndPosition[1], _newSelectionEndPosition[2]);\n\n\t\t\tconst newSelection = new Selection(\n\t\t\t\tnewSelectionStartPosition.lineNumber, newSelectionStartPosition.column,\n\t\t\t\tnewSelectionEndPosition.lineNumber, newSelectionEndPosition.column\n\t\t\t);\n\n\t\t\tthis._onSelectionChangeRequest.fire(newSelection);\n\t\t});\n\t}\n\n\tpublic override dispose(): void {\n\t\tsuper.dispose();\n\t\tif (this._selectionChangeListener) {\n\t\t\tthis._selectionChangeListener.dispose();\n\t\t\tthis._selectionChangeListener = null;\n\t\t}\n\t}\n\n\tpublic focusTextArea(): void {\n\t\t// Setting this._hasFocus and writing the screen reader content\n\t\t// will result in a focus() and setSelectionRange() in the textarea\n\t\tthis._setHasFocus(true);\n\n\t\t// If the editor is off DOM, focus cannot be really set, so let's double check that we have managed to set the focus\n\t\tthis.refreshFocusState();\n\t}\n\n\tpublic isFocused(): boolean {\n\t\treturn this._hasFocus;\n\t}\n\n\tpublic refreshFocusState(): void {\n\t\tthis._setHasFocus(this._textArea.hasFocus());\n\t}\n\n\tprivate _setHasFocus(newHasFocus: boolean): void {\n\t\tif (this._hasFocus === newHasFocus) {\n\t\t\t// no change\n\t\t\treturn;\n\t\t}\n\t\tthis._hasFocus = newHasFocus;\n\n\t\tif (this._selectionChangeListener) {\n\t\t\tthis._selectionChangeListener.dispose();\n\t\t\tthis._selectionChangeListener = null;\n\t\t}\n\t\tif (this._hasFocus) {\n\t\t\tthis._selectionChangeListener = this._installSelectionChangeListener();\n\t\t}\n\n\t\tif (this._hasFocus) {\n\t\t\tthis.writeScreenReaderContent('focusgain');\n\t\t}\n\n\t\tif (this._hasFocus) {\n\t\t\tthis._onFocus.fire();\n\t\t} else {\n\t\t\tthis._onBlur.fire();\n\t\t}\n\t}\n\n\tprivate _setAndWriteTextAreaState(reason: string, textAreaState: TextAreaState): void {\n\t\tif (!this._hasFocus) {\n\t\t\ttextAreaState = textAreaState.collapseSelection();\n\t\t}\n\n\t\ttextAreaState.writeToTextArea(reason, this._textArea, this._hasFocus);\n\t\tthis._textAreaState = textAreaState;\n\t}\n\n\tpublic writeScreenReaderContent(reason: string): void {\n\t\tif (this._currentComposition) {\n\t\t\t// Do not write to the text area when doing composition\n\t\t\treturn;\n\t\t}\n\n\t\tthis._setAndWriteTextAreaState(reason, this._host.getScreenReaderContent(this._textAreaState));\n\t}\n\n\tprivate _ensureClipboardGetsEditorSelection(e: ClipboardEvent): void {\n\t\tconst dataToCopy = this._host.getDataToCopy();\n\t\tconst storedMetadata: ClipboardStoredMetadata = {\n\t\t\tversion: 1,\n\t\t\tisFromEmptySelection: dataToCopy.isFromEmptySelection,\n\t\t\tmulticursorText: dataToCopy.multicursorText,\n\t\t\tmode: dataToCopy.mode\n\t\t};\n\t\tInMemoryClipboardMetadataManager.INSTANCE.set(\n\t\t\t// When writing \"LINE\\r\\n\" to the clipboard and then pasting,\n\t\t\t// Firefox pastes \"LINE\\n\", so let's work around this quirk\n\t\t\t(this._browser.isFirefox ? dataToCopy.text.replace(/\\r\\n/g, '\\n') : dataToCopy.text),\n\t\t\tstoredMetadata\n\t\t);\n\n\t\te.preventDefault();\n\t\tif (e.clipboardData) {\n\t\t\tClipboardEventUtils.setTextData(e.clipboardData, dataToCopy.text, dataToCopy.html, storedMetadata);\n\t\t}\n\t}\n}\n\nclass ClipboardEventUtils {\n\n\tpublic static getTextData(clipboardData: DataTransfer): [string, ClipboardStoredMetadata | null] {\n\t\tconst text = clipboardData.getData(Mimes.text);\n\t\tlet metadata: ClipboardStoredMetadata | null = null;\n\t\tconst rawmetadata = clipboardData.getData('vscode-editor-data');\n\t\tif (typeof rawmetadata === 'string') {\n\t\t\ttry {\n\t\t\t\tmetadata = JSON.parse(rawmetadata);\n\t\t\t\tif (metadata.version !== 1) {\n\t\t\t\t\tmetadata = null;\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// no problem!\n\t\t\t}\n\t\t}\n\n\t\treturn [text, metadata];\n\t}\n\n\tpublic static setTextData(clipboardData: DataTransfer, text: string, html: string | null | undefined, metadata: ClipboardStoredMetadata): void {\n\t\tclipboardData.setData(Mimes.text, text);\n\t\tif (typeof html === 'string') {\n\t\t\tclipboardData.setData('text/html', html);\n\t\t}\n\t\tclipboardData.setData('vscode-editor-data', JSON.stringify(metadata));\n\t}\n}\n\nexport class TextAreaWrapper extends Disposable implements ICompleteTextAreaWrapper {\n\n\tpublic readonly onKeyDown = this._register(dom.createEventEmitter(this._actual, 'keydown')).event;\n\tpublic readonly onKeyUp = this._register(dom.createEventEmitter(this._actual, 'keyup')).event;\n\tpublic readonly onCompositionStart = this._register(dom.createEventEmitter(this._actual, 'compositionstart')).event;\n\tpublic readonly onCompositionUpdate = this._register(dom.createEventEmitter(this._actual, 'compositionupdate')).event;\n\tpublic readonly onCompositionEnd = this._register(dom.createEventEmitter(this._actual, 'compositionend')).event;\n\tpublic readonly onInput = >this._register(dom.createEventEmitter(this._actual, 'input')).event;\n\tpublic readonly onCut = this._register(dom.createEventEmitter(this._actual, 'cut')).event;\n\tpublic readonly onCopy = this._register(dom.createEventEmitter(this._actual, 'copy')).event;\n\tpublic readonly onPaste = this._register(dom.createEventEmitter(this._actual, 'paste')).event;\n\tpublic readonly onFocus = this._register(dom.createEventEmitter(this._actual, 'focus')).event;\n\tpublic readonly onBlur = this._register(dom.createEventEmitter(this._actual, 'blur')).event;\n\n\tprivate _onSyntheticTap = this._register(new Emitter());\n\tpublic readonly onSyntheticTap: Event = this._onSyntheticTap.event;\n\n\tprivate _ignoreSelectionChangeTime: number;\n\n\tconstructor(\n\t\tprivate readonly _actual: HTMLTextAreaElement\n\t) {\n\t\tsuper();\n\t\tthis._ignoreSelectionChangeTime = 0;\n\n\t\tthis._register(dom.addDisposableListener(this._actual, TextAreaSyntethicEvents.Tap, () => this._onSyntheticTap.fire()));\n\t}\n\n\tpublic hasFocus(): boolean {\n\t\tconst shadowRoot = dom.getShadowRoot(this._actual);\n\t\tif (shadowRoot) {\n\t\t\treturn shadowRoot.activeElement === this._actual;\n\t\t} else if (dom.isInDOM(this._actual)) {\n\t\t\treturn document.activeElement === this._actual;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic setIgnoreSelectionChangeTime(reason: string): void {\n\t\tthis._ignoreSelectionChangeTime = Date.now();\n\t}\n\n\tpublic getIgnoreSelectionChangeTime(): number {\n\t\treturn this._ignoreSelectionChangeTime;\n\t}\n\n\tpublic resetSelectionChangeTime(): void {\n\t\tthis._ignoreSelectionChangeTime = 0;\n\t}\n\n\tpublic getValue(): string {\n\t\t// console.log('current value: ' + this._textArea.value);\n\t\treturn this._actual.value;\n\t}\n\n\tpublic setValue(reason: string, value: string): void {\n\t\tconst textArea = this._actual;\n\t\tif (textArea.value === value) {\n\t\t\t// No change\n\t\t\treturn;\n\t\t}\n\t\t// console.log('reason: ' + reason + ', current value: ' + textArea.value + ' => new value: ' + value);\n\t\tthis.setIgnoreSelectionChangeTime('setValue');\n\t\ttextArea.value = value;\n\t}\n\n\tpublic getSelectionStart(): number {\n\t\treturn this._actual.selectionDirection === 'backward' ? this._actual.selectionEnd : this._actual.selectionStart;\n\t}\n\n\tpublic getSelectionEnd(): number {\n\t\treturn this._actual.selectionDirection === 'backward' ? this._actual.selectionStart : this._actual.selectionEnd;\n\t}\n\n\tpublic setSelectionRange(reason: string, selectionStart: number, selectionEnd: number): void {\n\t\tconst textArea = this._actual;\n\n\t\tlet activeElement: Element | null = null;\n\t\tconst shadowRoot = dom.getShadowRoot(textArea);\n\t\tif (shadowRoot) {\n\t\t\tactiveElement = shadowRoot.activeElement;\n\t\t} else {\n\t\t\tactiveElement = document.activeElement;\n\t\t}\n\n\t\tconst currentIsFocused = (activeElement === textArea);\n\t\tconst currentSelectionStart = textArea.selectionStart;\n\t\tconst currentSelectionEnd = textArea.selectionEnd;\n\n\t\tif (currentIsFocused && currentSelectionStart === selectionStart && currentSelectionEnd === selectionEnd) {\n\t\t\t// No change\n\t\t\t// Firefox iframe bug https://github.com/microsoft/monaco-editor/issues/643#issuecomment-367871377\n\t\t\tif (browser.isFirefox && window.parent !== window) {\n\t\t\t\ttextArea.focus();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// console.log('reason: ' + reason + ', setSelectionRange: ' + selectionStart + ' -> ' + selectionEnd);\n\n\t\tif (currentIsFocused) {\n\t\t\t// No need to focus, only need to change the selection range\n\t\t\tthis.setIgnoreSelectionChangeTime('setSelectionRange');\n\t\t\ttextArea.setSelectionRange(selectionStart, selectionEnd);\n\t\t\tif (browser.isFirefox && window.parent !== window) {\n\t\t\t\ttextArea.focus();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// If the focus is outside the textarea, browsers will try really hard to reveal the textarea.\n\t\t// Here, we try to undo the browser's desperate reveal.\n\t\ttry {\n\t\t\tconst scrollState = dom.saveParentsScrollTop(textArea);\n\t\t\tthis.setIgnoreSelectionChangeTime('setSelectionRange');\n\t\t\ttextArea.focus();\n\t\t\ttextArea.setSelectionRange(selectionStart, selectionEnd);\n\t\t\tdom.restoreParentsScrollTop(textArea, scrollState);\n\t\t} catch (e) {\n\t\t\t// Sometimes IE throws when setting selection (e.g. textarea is off-DOM)\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection, SelectionDirection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { ITextModel } from 'vs/editor/common/model';\n\nexport class ReplaceCommand implements ICommand {\n\n\tprivate readonly _range: Range;\n\tprivate readonly _text: string;\n\tpublic readonly insertsAutoWhitespace: boolean;\n\n\tconstructor(range: Range, text: string, insertsAutoWhitespace: boolean = false) {\n\t\tthis._range = range;\n\t\tthis._text = text;\n\t\tthis.insertsAutoWhitespace = insertsAutoWhitespace;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tbuilder.addTrackedEditOperation(this._range, this._text);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tconst inverseEditOperations = helper.getInverseEditOperations();\n\t\tconst srcRange = inverseEditOperations[0].range;\n\t\treturn Selection.fromPositions(srcRange.getEndPosition());\n\t}\n}\n\nexport class ReplaceCommandThatSelectsText implements ICommand {\n\n\tprivate readonly _range: Range;\n\tprivate readonly _text: string;\n\n\tconstructor(range: Range, text: string) {\n\t\tthis._range = range;\n\t\tthis._text = text;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tbuilder.addTrackedEditOperation(this._range, this._text);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tconst inverseEditOperations = helper.getInverseEditOperations();\n\t\tconst srcRange = inverseEditOperations[0].range;\n\t\treturn Selection.fromRange(srcRange, SelectionDirection.LTR);\n\t}\n}\n\nexport class ReplaceCommandWithoutChangingPosition implements ICommand {\n\n\tprivate readonly _range: Range;\n\tprivate readonly _text: string;\n\tpublic readonly insertsAutoWhitespace: boolean;\n\n\tconstructor(range: Range, text: string, insertsAutoWhitespace: boolean = false) {\n\t\tthis._range = range;\n\t\tthis._text = text;\n\t\tthis.insertsAutoWhitespace = insertsAutoWhitespace;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tbuilder.addTrackedEditOperation(this._range, this._text);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tconst inverseEditOperations = helper.getInverseEditOperations();\n\t\tconst srcRange = inverseEditOperations[0].range;\n\t\treturn Selection.fromPositions(srcRange.getStartPosition());\n\t}\n}\n\nexport class ReplaceCommandWithOffsetCursorState implements ICommand {\n\n\tprivate readonly _range: Range;\n\tprivate readonly _text: string;\n\tprivate readonly _columnDeltaOffset: number;\n\tprivate readonly _lineNumberDeltaOffset: number;\n\tpublic readonly insertsAutoWhitespace: boolean;\n\n\tconstructor(range: Range, text: string, lineNumberDeltaOffset: number, columnDeltaOffset: number, insertsAutoWhitespace: boolean = false) {\n\t\tthis._range = range;\n\t\tthis._text = text;\n\t\tthis._columnDeltaOffset = columnDeltaOffset;\n\t\tthis._lineNumberDeltaOffset = lineNumberDeltaOffset;\n\t\tthis.insertsAutoWhitespace = insertsAutoWhitespace;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tbuilder.addTrackedEditOperation(this._range, this._text);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tconst inverseEditOperations = helper.getInverseEditOperations();\n\t\tconst srcRange = inverseEditOperations[0].range;\n\t\treturn Selection.fromPositions(srcRange.getEndPosition().delta(this._lineNumberDeltaOffset, this._columnDeltaOffset));\n\t}\n}\n\nexport class ReplaceCommandThatPreservesSelection implements ICommand {\n\n\tprivate readonly _range: Range;\n\tprivate readonly _text: string;\n\tprivate readonly _initialSelection: Selection;\n\tprivate readonly _forceMoveMarkers: boolean;\n\tprivate _selectionId: string | null;\n\n\tconstructor(editRange: Range, text: string, initialSelection: Selection, forceMoveMarkers: boolean = false) {\n\t\tthis._range = editRange;\n\t\tthis._text = text;\n\t\tthis._initialSelection = initialSelection;\n\t\tthis._forceMoveMarkers = forceMoveMarkers;\n\t\tthis._selectionId = null;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tbuilder.addTrackedEditOperation(this._range, this._text, this._forceMoveMarkers);\n\t\tthis._selectionId = builder.trackSelection(this._initialSelection);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\treturn helper.getTrackedSelection(this._selectionId!);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { ITextModel } from 'vs/editor/common/model';\n\nexport class SurroundSelectionCommand implements ICommand {\n\tprivate readonly _range: Selection;\n\tprivate readonly _charBeforeSelection: string;\n\tprivate readonly _charAfterSelection: string;\n\n\tconstructor(range: Selection, charBeforeSelection: string, charAfterSelection: string) {\n\t\tthis._range = range;\n\t\tthis._charBeforeSelection = charBeforeSelection;\n\t\tthis._charAfterSelection = charAfterSelection;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tbuilder.addTrackedEditOperation(new Range(\n\t\t\tthis._range.startLineNumber,\n\t\t\tthis._range.startColumn,\n\t\t\tthis._range.startLineNumber,\n\t\t\tthis._range.startColumn\n\t\t), this._charBeforeSelection);\n\n\t\tbuilder.addTrackedEditOperation(new Range(\n\t\t\tthis._range.endLineNumber,\n\t\t\tthis._range.endColumn,\n\t\t\tthis._range.endLineNumber,\n\t\t\tthis._range.endColumn\n\t\t), this._charAfterSelection);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tconst inverseEditOperations = helper.getInverseEditOperations();\n\t\tconst firstOperationRange = inverseEditOperations[0].range;\n\t\tconst secondOperationRange = inverseEditOperations[1].range;\n\n\t\treturn new Selection(\n\t\t\tfirstOperationRange.endLineNumber,\n\t\t\tfirstOperationRange.endColumn,\n\t\t\tsecondOperationRange.endLineNumber,\n\t\t\tsecondOperationRange.endColumn - this._charAfterSelection.length\n\t\t);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as strings from 'vs/base/common/strings';\nimport * as platform from 'vs/base/common/platform';\nimport * as buffer from 'vs/base/common/buffer';\n\ndeclare const TextDecoder: {\n\tprototype: TextDecoder;\n\tnew(label?: string): TextDecoder;\n};\ninterface TextDecoder {\n\tdecode(view: Uint16Array): string;\n}\n\nexport interface IStringBuilder {\n\tbuild(): string;\n\treset(): void;\n\twrite1(charCode: number): void;\n\tappendASCII(charCode: number): void;\n\tappendASCIIString(str: string): void;\n}\n\nlet _utf16LE_TextDecoder: TextDecoder | null;\nfunction getUTF16LE_TextDecoder(): TextDecoder {\n\tif (!_utf16LE_TextDecoder) {\n\t\t_utf16LE_TextDecoder = new TextDecoder('UTF-16LE');\n\t}\n\treturn _utf16LE_TextDecoder;\n}\n\nlet _utf16BE_TextDecoder: TextDecoder | null;\nfunction getUTF16BE_TextDecoder(): TextDecoder {\n\tif (!_utf16BE_TextDecoder) {\n\t\t_utf16BE_TextDecoder = new TextDecoder('UTF-16BE');\n\t}\n\treturn _utf16BE_TextDecoder;\n}\n\nlet _platformTextDecoder: TextDecoder | null;\nexport function getPlatformTextDecoder(): TextDecoder {\n\tif (!_platformTextDecoder) {\n\t\t_platformTextDecoder = platform.isLittleEndian() ? getUTF16LE_TextDecoder() : getUTF16BE_TextDecoder();\n\t}\n\treturn _platformTextDecoder;\n}\n\nexport const hasTextDecoder = (typeof TextDecoder !== 'undefined');\nexport let createStringBuilder: (capacity: number) => IStringBuilder;\nexport let decodeUTF16LE: (source: Uint8Array, offset: number, len: number) => string;\n\nif (hasTextDecoder) {\n\tcreateStringBuilder = (capacity) => new StringBuilder(capacity);\n\tdecodeUTF16LE = standardDecodeUTF16LE;\n} else {\n\tcreateStringBuilder = (capacity) => new CompatStringBuilder();\n\tdecodeUTF16LE = compatDecodeUTF16LE;\n}\n\nfunction standardDecodeUTF16LE(source: Uint8Array, offset: number, len: number): string {\n\tconst view = new Uint16Array(source.buffer, offset, len);\n\tif (len > 0 && (view[0] === 0xFEFF || view[0] === 0xFFFE)) {\n\t\t// UTF16 sometimes starts with a BOM https://de.wikipedia.org/wiki/Byte_Order_Mark\n\t\t// It looks like TextDecoder.decode will eat up a leading BOM (0xFEFF or 0xFFFE)\n\t\t// We don't want that behavior because we know the string is UTF16LE and the BOM should be maintained\n\t\t// So we use the manual decoder\n\t\treturn compatDecodeUTF16LE(source, offset, len);\n\t}\n\treturn getUTF16LE_TextDecoder().decode(view);\n}\n\nfunction compatDecodeUTF16LE(source: Uint8Array, offset: number, len: number): string {\n\tconst result: string[] = [];\n\tlet resultLen = 0;\n\tfor (let i = 0; i < len; i++) {\n\t\tconst charCode = buffer.readUInt16LE(source, offset); offset += 2;\n\t\tresult[resultLen++] = String.fromCharCode(charCode);\n\t}\n\treturn result.join('');\n}\n\nclass StringBuilder implements IStringBuilder {\n\n\tprivate readonly _capacity: number;\n\tprivate readonly _buffer: Uint16Array;\n\n\tprivate _completedStrings: string[] | null;\n\tprivate _bufferLength: number;\n\n\tconstructor(capacity: number) {\n\t\tthis._capacity = capacity | 0;\n\t\tthis._buffer = new Uint16Array(this._capacity);\n\n\t\tthis._completedStrings = null;\n\t\tthis._bufferLength = 0;\n\t}\n\n\tpublic reset(): void {\n\t\tthis._completedStrings = null;\n\t\tthis._bufferLength = 0;\n\t}\n\n\tpublic build(): string {\n\t\tif (this._completedStrings !== null) {\n\t\t\tthis._flushBuffer();\n\t\t\treturn this._completedStrings.join('');\n\t\t}\n\t\treturn this._buildBuffer();\n\t}\n\n\tprivate _buildBuffer(): string {\n\t\tif (this._bufferLength === 0) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst view = new Uint16Array(this._buffer.buffer, 0, this._bufferLength);\n\t\treturn getPlatformTextDecoder().decode(view);\n\t}\n\n\tprivate _flushBuffer(): void {\n\t\tconst bufferString = this._buildBuffer();\n\t\tthis._bufferLength = 0;\n\n\t\tif (this._completedStrings === null) {\n\t\t\tthis._completedStrings = [bufferString];\n\t\t} else {\n\t\t\tthis._completedStrings[this._completedStrings.length] = bufferString;\n\t\t}\n\t}\n\n\tpublic write1(charCode: number): void {\n\t\tconst remainingSpace = this._capacity - this._bufferLength;\n\n\t\tif (remainingSpace <= 1) {\n\t\t\tif (remainingSpace === 0 || strings.isHighSurrogate(charCode)) {\n\t\t\t\tthis._flushBuffer();\n\t\t\t}\n\t\t}\n\n\t\tthis._buffer[this._bufferLength++] = charCode;\n\t}\n\n\tpublic appendASCII(charCode: number): void {\n\t\tif (this._bufferLength === this._capacity) {\n\t\t\t// buffer is full\n\t\t\tthis._flushBuffer();\n\t\t}\n\t\tthis._buffer[this._bufferLength++] = charCode;\n\t}\n\n\tpublic appendASCIIString(str: string): void {\n\t\tconst strLen = str.length;\n\n\t\tif (this._bufferLength + strLen >= this._capacity) {\n\t\t\t// This string does not fit in the remaining buffer space\n\n\t\t\tthis._flushBuffer();\n\t\t\tthis._completedStrings![this._completedStrings!.length] = str;\n\t\t\treturn;\n\t\t}\n\n\t\tfor (let i = 0; i < strLen; i++) {\n\t\t\tthis._buffer[this._bufferLength++] = str.charCodeAt(i);\n\t\t}\n\t}\n}\n\nclass CompatStringBuilder implements IStringBuilder {\n\n\tprivate _pieces: string[];\n\tprivate _piecesLen: number;\n\n\tconstructor() {\n\t\tthis._pieces = [];\n\t\tthis._piecesLen = 0;\n\t}\n\n\tpublic reset(): void {\n\t\tthis._pieces = [];\n\t\tthis._piecesLen = 0;\n\t}\n\n\tpublic build(): string {\n\t\treturn this._pieces.join('');\n\t}\n\n\tpublic write1(charCode: number): void {\n\t\tthis._pieces[this._piecesLen++] = String.fromCharCode(charCode);\n\t}\n\n\tpublic appendASCII(charCode: number): void {\n\t\tthis._pieces[this._piecesLen++] = String.fromCharCode(charCode);\n\t}\n\n\tpublic appendASCIIString(str: string): void {\n\t\tthis._pieces[this._piecesLen++] = str;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';\nimport { IStringBuilder, createStringBuilder } from 'vs/editor/common/core/stringBuilder';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\nimport { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\n\n/**\n * Represents a visible line\n */\nexport interface IVisibleLine extends ILine {\n\tgetDomNode(): HTMLElement | null;\n\tsetDomNode(domNode: HTMLElement): void;\n\n\t/**\n\t * Return null if the HTML should not be touched.\n\t * Return the new HTML otherwise.\n\t */\n\trenderLine(lineNumber: number, deltaTop: number, viewportData: ViewportData, sb: IStringBuilder): boolean;\n\n\t/**\n\t * Layout the line.\n\t */\n\tlayoutLine(lineNumber: number, deltaTop: number): void;\n}\n\nexport interface ILine {\n\tonContentChanged(): void;\n\tonTokensChanged(): void;\n}\n\nexport class RenderedLinesCollection {\n\tprivate readonly _createLine: () => T;\n\tprivate _lines!: T[];\n\tprivate _rendLineNumberStart!: number;\n\n\tconstructor(createLine: () => T) {\n\t\tthis._createLine = createLine;\n\t\tthis._set(1, []);\n\t}\n\n\tpublic flush(): void {\n\t\tthis._set(1, []);\n\t}\n\n\t_set(rendLineNumberStart: number, lines: T[]): void {\n\t\tthis._lines = lines;\n\t\tthis._rendLineNumberStart = rendLineNumberStart;\n\t}\n\n\t_get(): { rendLineNumberStart: number; lines: T[]; } {\n\t\treturn {\n\t\t\trendLineNumberStart: this._rendLineNumberStart,\n\t\t\tlines: this._lines\n\t\t};\n\t}\n\n\t/**\n\t * @returns Inclusive line number that is inside this collection\n\t */\n\tpublic getStartLineNumber(): number {\n\t\treturn this._rendLineNumberStart;\n\t}\n\n\t/**\n\t * @returns Inclusive line number that is inside this collection\n\t */\n\tpublic getEndLineNumber(): number {\n\t\treturn this._rendLineNumberStart + this._lines.length - 1;\n\t}\n\n\tpublic getCount(): number {\n\t\treturn this._lines.length;\n\t}\n\n\tpublic getLine(lineNumber: number): T {\n\t\tconst lineIndex = lineNumber - this._rendLineNumberStart;\n\t\tif (lineIndex < 0 || lineIndex >= this._lines.length) {\n\t\t\tthrow new Error('Illegal value for lineNumber');\n\t\t}\n\t\treturn this._lines[lineIndex];\n\t}\n\n\t/**\n\t * @returns Lines that were removed from this collection\n\t */\n\tpublic onLinesDeleted(deleteFromLineNumber: number, deleteToLineNumber: number): T[] | null {\n\t\tif (this.getCount() === 0) {\n\t\t\t// no lines\n\t\t\treturn null;\n\t\t}\n\n\t\tconst startLineNumber = this.getStartLineNumber();\n\t\tconst endLineNumber = this.getEndLineNumber();\n\n\t\tif (deleteToLineNumber < startLineNumber) {\n\t\t\t// deleting above the viewport\n\t\t\tconst deleteCnt = deleteToLineNumber - deleteFromLineNumber + 1;\n\t\t\tthis._rendLineNumberStart -= deleteCnt;\n\t\t\treturn null;\n\t\t}\n\n\t\tif (deleteFromLineNumber > endLineNumber) {\n\t\t\t// deleted below the viewport\n\t\t\treturn null;\n\t\t}\n\n\t\t// Record what needs to be deleted\n\t\tlet deleteStartIndex = 0;\n\t\tlet deleteCount = 0;\n\t\tfor (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n\t\t\tconst lineIndex = lineNumber - this._rendLineNumberStart;\n\n\t\t\tif (deleteFromLineNumber <= lineNumber && lineNumber <= deleteToLineNumber) {\n\t\t\t\t// this is a line to be deleted\n\t\t\t\tif (deleteCount === 0) {\n\t\t\t\t\t// this is the first line to be deleted\n\t\t\t\t\tdeleteStartIndex = lineIndex;\n\t\t\t\t\tdeleteCount = 1;\n\t\t\t\t} else {\n\t\t\t\t\tdeleteCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Adjust this._rendLineNumberStart for lines deleted above\n\t\tif (deleteFromLineNumber < startLineNumber) {\n\t\t\t// Something was deleted above\n\t\t\tlet deleteAboveCount = 0;\n\n\t\t\tif (deleteToLineNumber < startLineNumber) {\n\t\t\t\t// the entire deleted lines are above\n\t\t\t\tdeleteAboveCount = deleteToLineNumber - deleteFromLineNumber + 1;\n\t\t\t} else {\n\t\t\t\tdeleteAboveCount = startLineNumber - deleteFromLineNumber;\n\t\t\t}\n\n\t\t\tthis._rendLineNumberStart -= deleteAboveCount;\n\t\t}\n\n\t\tconst deleted = this._lines.splice(deleteStartIndex, deleteCount);\n\t\treturn deleted;\n\t}\n\n\tpublic onLinesChanged(changeFromLineNumber: number, changeToLineNumber: number): boolean {\n\t\tif (this.getCount() === 0) {\n\t\t\t// no lines\n\t\t\treturn false;\n\t\t}\n\n\t\tconst startLineNumber = this.getStartLineNumber();\n\t\tconst endLineNumber = this.getEndLineNumber();\n\n\t\tlet someoneNotified = false;\n\n\t\tfor (let changedLineNumber = changeFromLineNumber; changedLineNumber <= changeToLineNumber; changedLineNumber++) {\n\t\t\tif (changedLineNumber >= startLineNumber && changedLineNumber <= endLineNumber) {\n\t\t\t\t// Notify the line\n\t\t\t\tthis._lines[changedLineNumber - this._rendLineNumberStart].onContentChanged();\n\t\t\t\tsomeoneNotified = true;\n\t\t\t}\n\t\t}\n\n\t\treturn someoneNotified;\n\t}\n\n\tpublic onLinesInserted(insertFromLineNumber: number, insertToLineNumber: number): T[] | null {\n\t\tif (this.getCount() === 0) {\n\t\t\t// no lines\n\t\t\treturn null;\n\t\t}\n\n\t\tconst insertCnt = insertToLineNumber - insertFromLineNumber + 1;\n\t\tconst startLineNumber = this.getStartLineNumber();\n\t\tconst endLineNumber = this.getEndLineNumber();\n\n\t\tif (insertFromLineNumber <= startLineNumber) {\n\t\t\t// inserting above the viewport\n\t\t\tthis._rendLineNumberStart += insertCnt;\n\t\t\treturn null;\n\t\t}\n\n\t\tif (insertFromLineNumber > endLineNumber) {\n\t\t\t// inserting below the viewport\n\t\t\treturn null;\n\t\t}\n\n\t\tif (insertCnt + insertFromLineNumber > endLineNumber) {\n\t\t\t// insert inside the viewport in such a way that all remaining lines are pushed outside\n\t\t\tconst deleted = this._lines.splice(insertFromLineNumber - this._rendLineNumberStart, endLineNumber - insertFromLineNumber + 1);\n\t\t\treturn deleted;\n\t\t}\n\n\t\t// insert inside the viewport, push out some lines, but not all remaining lines\n\t\tconst newLines: T[] = [];\n\t\tfor (let i = 0; i < insertCnt; i++) {\n\t\t\tnewLines[i] = this._createLine();\n\t\t}\n\t\tconst insertIndex = insertFromLineNumber - this._rendLineNumberStart;\n\t\tconst beforeLines = this._lines.slice(0, insertIndex);\n\t\tconst afterLines = this._lines.slice(insertIndex, this._lines.length - insertCnt);\n\t\tconst deletedLines = this._lines.slice(this._lines.length - insertCnt, this._lines.length);\n\n\t\tthis._lines = beforeLines.concat(newLines).concat(afterLines);\n\n\t\treturn deletedLines;\n\t}\n\n\tpublic onTokensChanged(ranges: { fromLineNumber: number; toLineNumber: number; }[]): boolean {\n\t\tif (this.getCount() === 0) {\n\t\t\t// no lines\n\t\t\treturn false;\n\t\t}\n\n\t\tconst startLineNumber = this.getStartLineNumber();\n\t\tconst endLineNumber = this.getEndLineNumber();\n\n\t\tlet notifiedSomeone = false;\n\t\tfor (let i = 0, len = ranges.length; i < len; i++) {\n\t\t\tconst rng = ranges[i];\n\n\t\t\tif (rng.toLineNumber < startLineNumber || rng.fromLineNumber > endLineNumber) {\n\t\t\t\t// range outside viewport\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst from = Math.max(startLineNumber, rng.fromLineNumber);\n\t\t\tconst to = Math.min(endLineNumber, rng.toLineNumber);\n\n\t\t\tfor (let lineNumber = from; lineNumber <= to; lineNumber++) {\n\t\t\t\tconst lineIndex = lineNumber - this._rendLineNumberStart;\n\t\t\t\tthis._lines[lineIndex].onTokensChanged();\n\t\t\t\tnotifiedSomeone = true;\n\t\t\t}\n\t\t}\n\n\t\treturn notifiedSomeone;\n\t}\n}\n\nexport interface IVisibleLinesHost {\n\tcreateVisibleLine(): T;\n}\n\nexport class VisibleLinesCollection {\n\n\tprivate readonly _host: IVisibleLinesHost;\n\tpublic readonly domNode: FastDomNode;\n\tprivate readonly _linesCollection: RenderedLinesCollection;\n\n\tconstructor(host: IVisibleLinesHost) {\n\t\tthis._host = host;\n\t\tthis.domNode = this._createDomNode();\n\t\tthis._linesCollection = new RenderedLinesCollection(() => this._host.createVisibleLine());\n\t}\n\n\tprivate _createDomNode(): FastDomNode {\n\t\tconst domNode = createFastDomNode(document.createElement('div'));\n\t\tdomNode.setClassName('view-layer');\n\t\tdomNode.setPosition('absolute');\n\t\tdomNode.domNode.setAttribute('role', 'presentation');\n\t\tdomNode.domNode.setAttribute('aria-hidden', 'true');\n\t\treturn domNode;\n\t}\n\n\t// ---- begin view event handlers\n\n\tpublic onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tif (e.hasChanged(EditorOption.layoutInfo)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic onFlushed(e: viewEvents.ViewFlushedEvent): boolean {\n\t\tthis._linesCollection.flush();\n\t\t// No need to clear the dom node because a full .innerHTML will occur in ViewLayerRenderer._render\n\t\treturn true;\n\t}\n\n\tpublic onLinesChanged(e: viewEvents.ViewLinesChangedEvent): boolean {\n\t\treturn this._linesCollection.onLinesChanged(e.fromLineNumber, e.toLineNumber);\n\t}\n\n\tpublic onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean {\n\t\tconst deleted = this._linesCollection.onLinesDeleted(e.fromLineNumber, e.toLineNumber);\n\t\tif (deleted) {\n\t\t\t// Remove from DOM\n\t\t\tfor (let i = 0, len = deleted.length; i < len; i++) {\n\t\t\t\tconst lineDomNode = deleted[i].getDomNode();\n\t\t\t\tif (lineDomNode) {\n\t\t\t\t\tthis.domNode.domNode.removeChild(lineDomNode);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tpublic onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean {\n\t\tconst deleted = this._linesCollection.onLinesInserted(e.fromLineNumber, e.toLineNumber);\n\t\tif (deleted) {\n\t\t\t// Remove from DOM\n\t\t\tfor (let i = 0, len = deleted.length; i < len; i++) {\n\t\t\t\tconst lineDomNode = deleted[i].getDomNode();\n\t\t\t\tif (lineDomNode) {\n\t\t\t\t\tthis.domNode.domNode.removeChild(lineDomNode);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tpublic onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn e.scrollTopChanged;\n\t}\n\n\tpublic onTokensChanged(e: viewEvents.ViewTokensChangedEvent): boolean {\n\t\treturn this._linesCollection.onTokensChanged(e.ranges);\n\t}\n\n\tpublic onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\n\t// ---- end view event handlers\n\n\tpublic getStartLineNumber(): number {\n\t\treturn this._linesCollection.getStartLineNumber();\n\t}\n\n\tpublic getEndLineNumber(): number {\n\t\treturn this._linesCollection.getEndLineNumber();\n\t}\n\n\tpublic getVisibleLine(lineNumber: number): T {\n\t\treturn this._linesCollection.getLine(lineNumber);\n\t}\n\n\tpublic renderLines(viewportData: ViewportData): void {\n\n\t\tconst inp = this._linesCollection._get();\n\n\t\tconst renderer = new ViewLayerRenderer(this.domNode.domNode, this._host, viewportData);\n\n\t\tconst ctx: IRendererContext = {\n\t\t\trendLineNumberStart: inp.rendLineNumberStart,\n\t\t\tlines: inp.lines,\n\t\t\tlinesLength: inp.lines.length\n\t\t};\n\n\t\t// Decide if this render will do a single update (single large .innerHTML) or many updates (inserting/removing dom nodes)\n\t\tconst resCtx = renderer.render(ctx, viewportData.startLineNumber, viewportData.endLineNumber, viewportData.relativeVerticalOffset);\n\n\t\tthis._linesCollection._set(resCtx.rendLineNumberStart, resCtx.lines);\n\t}\n}\n\ninterface IRendererContext {\n\trendLineNumberStart: number;\n\tlines: T[];\n\tlinesLength: number;\n}\n\nclass ViewLayerRenderer {\n\n\tprivate static _ttPolicy = window.trustedTypes?.createPolicy('editorViewLayer', { createHTML: value => value });\n\n\treadonly domNode: HTMLElement;\n\treadonly host: IVisibleLinesHost;\n\treadonly viewportData: ViewportData;\n\n\tconstructor(domNode: HTMLElement, host: IVisibleLinesHost, viewportData: ViewportData) {\n\t\tthis.domNode = domNode;\n\t\tthis.host = host;\n\t\tthis.viewportData = viewportData;\n\t}\n\n\tpublic render(inContext: IRendererContext, startLineNumber: number, stopLineNumber: number, deltaTop: number[]): IRendererContext {\n\n\t\tconst ctx: IRendererContext = {\n\t\t\trendLineNumberStart: inContext.rendLineNumberStart,\n\t\t\tlines: inContext.lines.slice(0),\n\t\t\tlinesLength: inContext.linesLength\n\t\t};\n\n\t\tif ((ctx.rendLineNumberStart + ctx.linesLength - 1 < startLineNumber) || (stopLineNumber < ctx.rendLineNumberStart)) {\n\t\t\t// There is no overlap whatsoever\n\t\t\tctx.rendLineNumberStart = startLineNumber;\n\t\t\tctx.linesLength = stopLineNumber - startLineNumber + 1;\n\t\t\tctx.lines = [];\n\t\t\tfor (let x = startLineNumber; x <= stopLineNumber; x++) {\n\t\t\t\tctx.lines[x - startLineNumber] = this.host.createVisibleLine();\n\t\t\t}\n\t\t\tthis._finishRendering(ctx, true, deltaTop);\n\t\t\treturn ctx;\n\t\t}\n\n\t\t// Update lines which will remain untouched\n\t\tthis._renderUntouchedLines(\n\t\t\tctx,\n\t\t\tMath.max(startLineNumber - ctx.rendLineNumberStart, 0),\n\t\t\tMath.min(stopLineNumber - ctx.rendLineNumberStart, ctx.linesLength - 1),\n\t\t\tdeltaTop,\n\t\t\tstartLineNumber\n\t\t);\n\n\t\tif (ctx.rendLineNumberStart > startLineNumber) {\n\t\t\t// Insert lines before\n\t\t\tconst fromLineNumber = startLineNumber;\n\t\t\tconst toLineNumber = Math.min(stopLineNumber, ctx.rendLineNumberStart - 1);\n\t\t\tif (fromLineNumber <= toLineNumber) {\n\t\t\t\tthis._insertLinesBefore(ctx, fromLineNumber, toLineNumber, deltaTop, startLineNumber);\n\t\t\t\tctx.linesLength += toLineNumber - fromLineNumber + 1;\n\t\t\t}\n\t\t} else if (ctx.rendLineNumberStart < startLineNumber) {\n\t\t\t// Remove lines before\n\t\t\tconst removeCnt = Math.min(ctx.linesLength, startLineNumber - ctx.rendLineNumberStart);\n\t\t\tif (removeCnt > 0) {\n\t\t\t\tthis._removeLinesBefore(ctx, removeCnt);\n\t\t\t\tctx.linesLength -= removeCnt;\n\t\t\t}\n\t\t}\n\n\t\tctx.rendLineNumberStart = startLineNumber;\n\n\t\tif (ctx.rendLineNumberStart + ctx.linesLength - 1 < stopLineNumber) {\n\t\t\t// Insert lines after\n\t\t\tconst fromLineNumber = ctx.rendLineNumberStart + ctx.linesLength;\n\t\t\tconst toLineNumber = stopLineNumber;\n\n\t\t\tif (fromLineNumber <= toLineNumber) {\n\t\t\t\tthis._insertLinesAfter(ctx, fromLineNumber, toLineNumber, deltaTop, startLineNumber);\n\t\t\t\tctx.linesLength += toLineNumber - fromLineNumber + 1;\n\t\t\t}\n\n\t\t} else if (ctx.rendLineNumberStart + ctx.linesLength - 1 > stopLineNumber) {\n\t\t\t// Remove lines after\n\t\t\tconst fromLineNumber = Math.max(0, stopLineNumber - ctx.rendLineNumberStart + 1);\n\t\t\tconst toLineNumber = ctx.linesLength - 1;\n\t\t\tconst removeCnt = toLineNumber - fromLineNumber + 1;\n\n\t\t\tif (removeCnt > 0) {\n\t\t\t\tthis._removeLinesAfter(ctx, removeCnt);\n\t\t\t\tctx.linesLength -= removeCnt;\n\t\t\t}\n\t\t}\n\n\t\tthis._finishRendering(ctx, false, deltaTop);\n\n\t\treturn ctx;\n\t}\n\n\tprivate _renderUntouchedLines(ctx: IRendererContext, startIndex: number, endIndex: number, deltaTop: number[], deltaLN: number): void {\n\t\tconst rendLineNumberStart = ctx.rendLineNumberStart;\n\t\tconst lines = ctx.lines;\n\n\t\tfor (let i = startIndex; i <= endIndex; i++) {\n\t\t\tconst lineNumber = rendLineNumberStart + i;\n\t\t\tlines[i].layoutLine(lineNumber, deltaTop[lineNumber - deltaLN]);\n\t\t}\n\t}\n\n\tprivate _insertLinesBefore(ctx: IRendererContext, fromLineNumber: number, toLineNumber: number, deltaTop: number[], deltaLN: number): void {\n\t\tconst newLines: T[] = [];\n\t\tlet newLinesLen = 0;\n\t\tfor (let lineNumber = fromLineNumber; lineNumber <= toLineNumber; lineNumber++) {\n\t\t\tnewLines[newLinesLen++] = this.host.createVisibleLine();\n\t\t}\n\t\tctx.lines = newLines.concat(ctx.lines);\n\t}\n\n\tprivate _removeLinesBefore(ctx: IRendererContext, removeCount: number): void {\n\t\tfor (let i = 0; i < removeCount; i++) {\n\t\t\tconst lineDomNode = ctx.lines[i].getDomNode();\n\t\t\tif (lineDomNode) {\n\t\t\t\tthis.domNode.removeChild(lineDomNode);\n\t\t\t}\n\t\t}\n\t\tctx.lines.splice(0, removeCount);\n\t}\n\n\tprivate _insertLinesAfter(ctx: IRendererContext, fromLineNumber: number, toLineNumber: number, deltaTop: number[], deltaLN: number): void {\n\t\tconst newLines: T[] = [];\n\t\tlet newLinesLen = 0;\n\t\tfor (let lineNumber = fromLineNumber; lineNumber <= toLineNumber; lineNumber++) {\n\t\t\tnewLines[newLinesLen++] = this.host.createVisibleLine();\n\t\t}\n\t\tctx.lines = ctx.lines.concat(newLines);\n\t}\n\n\tprivate _removeLinesAfter(ctx: IRendererContext, removeCount: number): void {\n\t\tconst removeIndex = ctx.linesLength - removeCount;\n\n\t\tfor (let i = 0; i < removeCount; i++) {\n\t\t\tconst lineDomNode = ctx.lines[removeIndex + i].getDomNode();\n\t\t\tif (lineDomNode) {\n\t\t\t\tthis.domNode.removeChild(lineDomNode);\n\t\t\t}\n\t\t}\n\t\tctx.lines.splice(removeIndex, removeCount);\n\t}\n\n\tprivate _finishRenderingNewLines(ctx: IRendererContext, domNodeIsEmpty: boolean, newLinesHTML: string | TrustedHTML, wasNew: boolean[]): void {\n\t\tif (ViewLayerRenderer._ttPolicy) {\n\t\t\tnewLinesHTML = ViewLayerRenderer._ttPolicy.createHTML(newLinesHTML as string);\n\t\t}\n\t\tconst lastChild = this.domNode.lastChild;\n\t\tif (domNodeIsEmpty || !lastChild) {\n\t\t\tthis.domNode.innerHTML = newLinesHTML as string; // explains the ugly casts -> https://github.com/microsoft/vscode/issues/106396#issuecomment-692625393;\n\t\t} else {\n\t\t\tlastChild.insertAdjacentHTML('afterend', newLinesHTML as string);\n\t\t}\n\n\t\tlet currChild = this.domNode.lastChild;\n\t\tfor (let i = ctx.linesLength - 1; i >= 0; i--) {\n\t\t\tconst line = ctx.lines[i];\n\t\t\tif (wasNew[i]) {\n\t\t\t\tline.setDomNode(currChild);\n\t\t\t\tcurrChild = currChild.previousSibling;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _finishRenderingInvalidLines(ctx: IRendererContext, invalidLinesHTML: string | TrustedHTML, wasInvalid: boolean[]): void {\n\t\tconst hugeDomNode = document.createElement('div');\n\n\t\tif (ViewLayerRenderer._ttPolicy) {\n\t\t\tinvalidLinesHTML = ViewLayerRenderer._ttPolicy.createHTML(invalidLinesHTML as string);\n\t\t}\n\t\thugeDomNode.innerHTML = invalidLinesHTML as string;\n\n\t\tfor (let i = 0; i < ctx.linesLength; i++) {\n\t\t\tconst line = ctx.lines[i];\n\t\t\tif (wasInvalid[i]) {\n\t\t\t\tconst source = hugeDomNode.firstChild;\n\t\t\t\tconst lineDomNode = line.getDomNode()!;\n\t\t\t\tlineDomNode.parentNode!.replaceChild(source, lineDomNode);\n\t\t\t\tline.setDomNode(source);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static readonly _sb = createStringBuilder(100000);\n\n\tprivate _finishRendering(ctx: IRendererContext, domNodeIsEmpty: boolean, deltaTop: number[]): void {\n\n\t\tconst sb = ViewLayerRenderer._sb;\n\t\tconst linesLength = ctx.linesLength;\n\t\tconst lines = ctx.lines;\n\t\tconst rendLineNumberStart = ctx.rendLineNumberStart;\n\n\t\tconst wasNew: boolean[] = [];\n\t\t{\n\t\t\tsb.reset();\n\t\t\tlet hadNewLine = false;\n\n\t\t\tfor (let i = 0; i < linesLength; i++) {\n\t\t\t\tconst line = lines[i];\n\t\t\t\twasNew[i] = false;\n\n\t\t\t\tconst lineDomNode = line.getDomNode();\n\t\t\t\tif (lineDomNode) {\n\t\t\t\t\t// line is not new\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst renderResult = line.renderLine(i + rendLineNumberStart, deltaTop[i], this.viewportData, sb);\n\t\t\t\tif (!renderResult) {\n\t\t\t\t\t// line does not need rendering\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\twasNew[i] = true;\n\t\t\t\thadNewLine = true;\n\t\t\t}\n\n\t\t\tif (hadNewLine) {\n\t\t\t\tthis._finishRenderingNewLines(ctx, domNodeIsEmpty, sb.build(), wasNew);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tsb.reset();\n\n\t\t\tlet hadInvalidLine = false;\n\t\t\tconst wasInvalid: boolean[] = [];\n\n\t\t\tfor (let i = 0; i < linesLength; i++) {\n\t\t\t\tconst line = lines[i];\n\t\t\t\twasInvalid[i] = false;\n\n\t\t\t\tif (wasNew[i]) {\n\t\t\t\t\t// line was new\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst renderResult = line.renderLine(i + rendLineNumberStart, deltaTop[i], this.viewportData, sb);\n\t\t\t\tif (!renderResult) {\n\t\t\t\t\t// line does not need rendering\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\twasInvalid[i] = true;\n\t\t\t\thadInvalidLine = true;\n\t\t\t}\n\n\t\t\tif (hadInvalidLine) {\n\t\t\t\tthis._finishRenderingInvalidLines(ctx, sb.build(), wasInvalid);\n\t\t\t}\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as buffer from 'vs/base/common/buffer';\nimport { decodeUTF16LE } from 'vs/editor/common/core/stringBuilder';\n\nfunction escapeNewLine(str: string): string {\n\treturn (\n\t\tstr\n\t\t\t.replace(/\\n/g, '\\\\n')\n\t\t\t.replace(/\\r/g, '\\\\r')\n\t);\n}\n\nexport class TextChange {\n\n\tpublic get oldLength(): number {\n\t\treturn this.oldText.length;\n\t}\n\n\tpublic get oldEnd(): number {\n\t\treturn this.oldPosition + this.oldText.length;\n\t}\n\n\tpublic get newLength(): number {\n\t\treturn this.newText.length;\n\t}\n\n\tpublic get newEnd(): number {\n\t\treturn this.newPosition + this.newText.length;\n\t}\n\n\tconstructor(\n\t\tpublic readonly oldPosition: number,\n\t\tpublic readonly oldText: string,\n\t\tpublic readonly newPosition: number,\n\t\tpublic readonly newText: string\n\t) { }\n\n\tpublic toString(): string {\n\t\tif (this.oldText.length === 0) {\n\t\t\treturn `(insert@${this.oldPosition} \"${escapeNewLine(this.newText)}\")`;\n\t\t}\n\t\tif (this.newText.length === 0) {\n\t\t\treturn `(delete@${this.oldPosition} \"${escapeNewLine(this.oldText)}\")`;\n\t\t}\n\t\treturn `(replace@${this.oldPosition} \"${escapeNewLine(this.oldText)}\" with \"${escapeNewLine(this.newText)}\")`;\n\t}\n\n\tprivate static _writeStringSize(str: string): number {\n\t\treturn (\n\t\t\t4 + 2 * str.length\n\t\t);\n\t}\n\n\tprivate static _writeString(b: Uint8Array, str: string, offset: number): number {\n\t\tconst len = str.length;\n\t\tbuffer.writeUInt32BE(b, len, offset); offset += 4;\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tbuffer.writeUInt16LE(b, str.charCodeAt(i), offset); offset += 2;\n\t\t}\n\t\treturn offset;\n\t}\n\n\tprivate static _readString(b: Uint8Array, offset: number): string {\n\t\tconst len = buffer.readUInt32BE(b, offset); offset += 4;\n\t\treturn decodeUTF16LE(b, offset, len);\n\t}\n\n\tpublic writeSize(): number {\n\t\treturn (\n\t\t\t+ 4 // oldPosition\n\t\t\t+ 4 // newPosition\n\t\t\t+ TextChange._writeStringSize(this.oldText)\n\t\t\t+ TextChange._writeStringSize(this.newText)\n\t\t);\n\t}\n\n\tpublic write(b: Uint8Array, offset: number): number {\n\t\tbuffer.writeUInt32BE(b, this.oldPosition, offset); offset += 4;\n\t\tbuffer.writeUInt32BE(b, this.newPosition, offset); offset += 4;\n\t\toffset = TextChange._writeString(b, this.oldText, offset);\n\t\toffset = TextChange._writeString(b, this.newText, offset);\n\t\treturn offset;\n\t}\n\n\tpublic static read(b: Uint8Array, offset: number, dest: TextChange[]): number {\n\t\tconst oldPosition = buffer.readUInt32BE(b, offset); offset += 4;\n\t\tconst newPosition = buffer.readUInt32BE(b, offset); offset += 4;\n\t\tconst oldText = TextChange._readString(b, offset); offset += TextChange._writeStringSize(oldText);\n\t\tconst newText = TextChange._readString(b, offset); offset += TextChange._writeStringSize(newText);\n\t\tdest.push(new TextChange(oldPosition, oldText, newPosition, newText));\n\t\treturn offset;\n\t}\n}\n\nexport function compressConsecutiveTextChanges(prevEdits: TextChange[] | null, currEdits: TextChange[]): TextChange[] {\n\tif (prevEdits === null || prevEdits.length === 0) {\n\t\treturn currEdits;\n\t}\n\tconst compressor = new TextChangeCompressor(prevEdits, currEdits);\n\treturn compressor.compress();\n}\n\nclass TextChangeCompressor {\n\n\tprivate _prevEdits: TextChange[];\n\tprivate _currEdits: TextChange[];\n\n\tprivate _result: TextChange[];\n\tprivate _resultLen: number;\n\n\tprivate _prevLen: number;\n\tprivate _prevDeltaOffset: number;\n\n\tprivate _currLen: number;\n\tprivate _currDeltaOffset: number;\n\n\tconstructor(prevEdits: TextChange[], currEdits: TextChange[]) {\n\t\tthis._prevEdits = prevEdits;\n\t\tthis._currEdits = currEdits;\n\n\t\tthis._result = [];\n\t\tthis._resultLen = 0;\n\n\t\tthis._prevLen = this._prevEdits.length;\n\t\tthis._prevDeltaOffset = 0;\n\n\t\tthis._currLen = this._currEdits.length;\n\t\tthis._currDeltaOffset = 0;\n\t}\n\n\tpublic compress(): TextChange[] {\n\t\tlet prevIndex = 0;\n\t\tlet currIndex = 0;\n\n\t\tlet prevEdit = this._getPrev(prevIndex);\n\t\tlet currEdit = this._getCurr(currIndex);\n\n\t\twhile (prevIndex < this._prevLen || currIndex < this._currLen) {\n\n\t\t\tif (prevEdit === null) {\n\t\t\t\tthis._acceptCurr(currEdit!);\n\t\t\t\tcurrEdit = this._getCurr(++currIndex);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (currEdit === null) {\n\t\t\t\tthis._acceptPrev(prevEdit);\n\t\t\t\tprevEdit = this._getPrev(++prevIndex);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (currEdit.oldEnd <= prevEdit.newPosition) {\n\t\t\t\tthis._acceptCurr(currEdit);\n\t\t\t\tcurrEdit = this._getCurr(++currIndex);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (prevEdit.newEnd <= currEdit.oldPosition) {\n\t\t\t\tthis._acceptPrev(prevEdit);\n\t\t\t\tprevEdit = this._getPrev(++prevIndex);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (currEdit.oldPosition < prevEdit.newPosition) {\n\t\t\t\tconst [e1, e2] = TextChangeCompressor._splitCurr(currEdit, prevEdit.newPosition - currEdit.oldPosition);\n\t\t\t\tthis._acceptCurr(e1);\n\t\t\t\tcurrEdit = e2;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (prevEdit.newPosition < currEdit.oldPosition) {\n\t\t\t\tconst [e1, e2] = TextChangeCompressor._splitPrev(prevEdit, currEdit.oldPosition - prevEdit.newPosition);\n\t\t\t\tthis._acceptPrev(e1);\n\t\t\t\tprevEdit = e2;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// At this point, currEdit.oldPosition === prevEdit.newPosition\n\n\t\t\tlet mergePrev: TextChange;\n\t\t\tlet mergeCurr: TextChange;\n\n\t\t\tif (currEdit.oldEnd === prevEdit.newEnd) {\n\t\t\t\tmergePrev = prevEdit;\n\t\t\t\tmergeCurr = currEdit;\n\t\t\t\tprevEdit = this._getPrev(++prevIndex);\n\t\t\t\tcurrEdit = this._getCurr(++currIndex);\n\t\t\t} else if (currEdit.oldEnd < prevEdit.newEnd) {\n\t\t\t\tconst [e1, e2] = TextChangeCompressor._splitPrev(prevEdit, currEdit.oldLength);\n\t\t\t\tmergePrev = e1;\n\t\t\t\tmergeCurr = currEdit;\n\t\t\t\tprevEdit = e2;\n\t\t\t\tcurrEdit = this._getCurr(++currIndex);\n\t\t\t} else {\n\t\t\t\tconst [e1, e2] = TextChangeCompressor._splitCurr(currEdit, prevEdit.newLength);\n\t\t\t\tmergePrev = prevEdit;\n\t\t\t\tmergeCurr = e1;\n\t\t\t\tprevEdit = this._getPrev(++prevIndex);\n\t\t\t\tcurrEdit = e2;\n\t\t\t}\n\n\t\t\tthis._result[this._resultLen++] = new TextChange(\n\t\t\t\tmergePrev.oldPosition,\n\t\t\t\tmergePrev.oldText,\n\t\t\t\tmergeCurr.newPosition,\n\t\t\t\tmergeCurr.newText\n\t\t\t);\n\t\t\tthis._prevDeltaOffset += mergePrev.newLength - mergePrev.oldLength;\n\t\t\tthis._currDeltaOffset += mergeCurr.newLength - mergeCurr.oldLength;\n\t\t}\n\n\t\tconst merged = TextChangeCompressor._merge(this._result);\n\t\tconst cleaned = TextChangeCompressor._removeNoOps(merged);\n\t\treturn cleaned;\n\t}\n\n\tprivate _acceptCurr(currEdit: TextChange): void {\n\t\tthis._result[this._resultLen++] = TextChangeCompressor._rebaseCurr(this._prevDeltaOffset, currEdit);\n\t\tthis._currDeltaOffset += currEdit.newLength - currEdit.oldLength;\n\t}\n\n\tprivate _getCurr(currIndex: number): TextChange | null {\n\t\treturn (currIndex < this._currLen ? this._currEdits[currIndex] : null);\n\t}\n\n\tprivate _acceptPrev(prevEdit: TextChange): void {\n\t\tthis._result[this._resultLen++] = TextChangeCompressor._rebasePrev(this._currDeltaOffset, prevEdit);\n\t\tthis._prevDeltaOffset += prevEdit.newLength - prevEdit.oldLength;\n\t}\n\n\tprivate _getPrev(prevIndex: number): TextChange | null {\n\t\treturn (prevIndex < this._prevLen ? this._prevEdits[prevIndex] : null);\n\t}\n\n\tprivate static _rebaseCurr(prevDeltaOffset: number, currEdit: TextChange): TextChange {\n\t\treturn new TextChange(\n\t\t\tcurrEdit.oldPosition - prevDeltaOffset,\n\t\t\tcurrEdit.oldText,\n\t\t\tcurrEdit.newPosition,\n\t\t\tcurrEdit.newText\n\t\t);\n\t}\n\n\tprivate static _rebasePrev(currDeltaOffset: number, prevEdit: TextChange): TextChange {\n\t\treturn new TextChange(\n\t\t\tprevEdit.oldPosition,\n\t\t\tprevEdit.oldText,\n\t\t\tprevEdit.newPosition + currDeltaOffset,\n\t\t\tprevEdit.newText\n\t\t);\n\t}\n\n\tprivate static _splitPrev(edit: TextChange, offset: number): [TextChange, TextChange] {\n\t\tconst preText = edit.newText.substr(0, offset);\n\t\tconst postText = edit.newText.substr(offset);\n\n\t\treturn [\n\t\t\tnew TextChange(\n\t\t\t\tedit.oldPosition,\n\t\t\t\tedit.oldText,\n\t\t\t\tedit.newPosition,\n\t\t\t\tpreText\n\t\t\t),\n\t\t\tnew TextChange(\n\t\t\t\tedit.oldEnd,\n\t\t\t\t'',\n\t\t\t\tedit.newPosition + offset,\n\t\t\t\tpostText\n\t\t\t)\n\t\t];\n\t}\n\n\tprivate static _splitCurr(edit: TextChange, offset: number): [TextChange, TextChange] {\n\t\tconst preText = edit.oldText.substr(0, offset);\n\t\tconst postText = edit.oldText.substr(offset);\n\n\t\treturn [\n\t\t\tnew TextChange(\n\t\t\t\tedit.oldPosition,\n\t\t\t\tpreText,\n\t\t\t\tedit.newPosition,\n\t\t\t\tedit.newText\n\t\t\t),\n\t\t\tnew TextChange(\n\t\t\t\tedit.oldPosition + offset,\n\t\t\t\tpostText,\n\t\t\t\tedit.newEnd,\n\t\t\t\t''\n\t\t\t)\n\t\t];\n\t}\n\n\tprivate static _merge(edits: TextChange[]): TextChange[] {\n\t\tif (edits.length === 0) {\n\t\t\treturn edits;\n\t\t}\n\n\t\tconst result: TextChange[] = [];\n\t\tlet resultLen = 0;\n\n\t\tlet prev = edits[0];\n\t\tfor (let i = 1; i < edits.length; i++) {\n\t\t\tconst curr = edits[i];\n\n\t\t\tif (prev.oldEnd === curr.oldPosition) {\n\t\t\t\t// Merge into `prev`\n\t\t\t\tprev = new TextChange(\n\t\t\t\t\tprev.oldPosition,\n\t\t\t\t\tprev.oldText + curr.oldText,\n\t\t\t\t\tprev.newPosition,\n\t\t\t\t\tprev.newText + curr.newText\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tresult[resultLen++] = prev;\n\t\t\t\tprev = curr;\n\t\t\t}\n\t\t}\n\t\tresult[resultLen++] = prev;\n\n\t\treturn result;\n\t}\n\n\tprivate static _removeNoOps(edits: TextChange[]): TextChange[] {\n\t\tif (edits.length === 0) {\n\t\t\treturn edits;\n\t\t}\n\n\t\tconst result: TextChange[] = [];\n\t\tlet resultLen = 0;\n\n\t\tfor (let i = 0; i < edits.length; i++) {\n\t\t\tconst edit = edits[i];\n\n\t\t\tif (edit.oldText === edit.newText) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tresult[resultLen++] = edit;\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport const EDITOR_MODEL_DEFAULTS = {\n\ttabSize: 4,\n\tindentSize: 4,\n\tinsertSpaces: true,\n\tdetectIndentation: true,\n\ttrimAutoWhitespace: true,\n\tlargeFileOptimizations: true,\n\tbracketPairColorizationOptions: { enabled: false }\n};\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { CharacterClassifier } from 'vs/editor/common/core/characterClassifier';\n\nexport const enum WordCharacterClass {\n\tRegular = 0,\n\tWhitespace = 1,\n\tWordSeparator = 2\n}\n\nexport class WordCharacterClassifier extends CharacterClassifier {\n\n\tconstructor(wordSeparators: string) {\n\t\tsuper(WordCharacterClass.Regular);\n\n\t\tfor (let i = 0, len = wordSeparators.length; i < len; i++) {\n\t\t\tthis.set(wordSeparators.charCodeAt(i), WordCharacterClass.WordSeparator);\n\t\t}\n\n\t\tthis.set(CharCode.Space, WordCharacterClass.Whitespace);\n\t\tthis.set(CharCode.Tab, WordCharacterClass.Whitespace);\n\t}\n\n}\n\nfunction once(computeFn: (input: string) => R): (input: string) => R {\n\tconst cache: { [key: string]: R; } = {}; // TODO@Alex unbounded cache\n\treturn (input: string): R => {\n\t\tif (!cache.hasOwnProperty(input)) {\n\t\t\tcache[input] = computeFn(input);\n\t\t}\n\t\treturn cache[input];\n\t};\n}\n\nexport const getMapForWordSeparators = once(\n\t(input) => new WordCharacterClassifier(input)\n);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport const USUAL_WORD_SEPARATORS = '`~!@#$%^&*()-=+[{]}\\\\|;:\\'\",.<>/?';\n\n/**\n * Word inside a model.\n */\nexport interface IWordAtPosition {\n\t/**\n\t * The word.\n\t */\n\treadonly word: string;\n\t/**\n\t * The column where the word starts.\n\t */\n\treadonly startColumn: number;\n\t/**\n\t * The column where the word ends.\n\t */\n\treadonly endColumn: number;\n}\n\n/**\n * Create a word definition regular expression based on default word separators.\n * Optionally provide allowed separators that should be included in words.\n *\n * The default would look like this:\n * /(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)/g\n */\nfunction createWordRegExp(allowInWords: string = ''): RegExp {\n\tlet source = '(-?\\\\d*\\\\.\\\\d\\\\w*)|([^';\n\tfor (const sep of USUAL_WORD_SEPARATORS) {\n\t\tif (allowInWords.indexOf(sep) >= 0) {\n\t\t\tcontinue;\n\t\t}\n\t\tsource += '\\\\' + sep;\n\t}\n\tsource += '\\\\s]+)';\n\treturn new RegExp(source, 'g');\n}\n\n// catches numbers (including floating numbers) in the first group, and alphanum in the second\nexport const DEFAULT_WORD_REGEXP = createWordRegExp();\n\nexport function ensureValidWordDefinition(wordDefinition?: RegExp | null): RegExp {\n\tlet result: RegExp = DEFAULT_WORD_REGEXP;\n\n\tif (wordDefinition && (wordDefinition instanceof RegExp)) {\n\t\tif (!wordDefinition.global) {\n\t\t\tlet flags = 'g';\n\t\t\tif (wordDefinition.ignoreCase) {\n\t\t\t\tflags += 'i';\n\t\t\t}\n\t\t\tif (wordDefinition.multiline) {\n\t\t\t\tflags += 'm';\n\t\t\t}\n\t\t\tif ((wordDefinition as any).unicode) {\n\t\t\t\tflags += 'u';\n\t\t\t}\n\t\t\tresult = new RegExp(wordDefinition.source, flags);\n\t\t} else {\n\t\t\tresult = wordDefinition;\n\t\t}\n\t}\n\n\tresult.lastIndex = 0;\n\n\treturn result;\n}\n\nconst _defaultConfig = {\n\tmaxLen: 1000,\n\twindowSize: 15,\n\ttimeBudget: 150\n};\n\nexport function getWordAtText(column: number, wordDefinition: RegExp, text: string, textOffset: number, config = _defaultConfig): IWordAtPosition | null {\n\n\tif (text.length > config.maxLen) {\n\t\t// don't throw strings that long at the regexp\n\t\t// but use a sub-string in which a word must occur\n\t\tlet start = column - config.maxLen / 2;\n\t\tif (start < 0) {\n\t\t\tstart = 0;\n\t\t} else {\n\t\t\ttextOffset += start;\n\t\t}\n\t\ttext = text.substring(start, column + config.maxLen / 2);\n\t\treturn getWordAtText(column, wordDefinition, text, textOffset, config);\n\t}\n\n\tconst t1 = Date.now();\n\tconst pos = column - 1 - textOffset;\n\n\tlet prevRegexIndex = -1;\n\tlet match: RegExpMatchArray | null = null;\n\n\tfor (let i = 1; ; i++) {\n\t\t// check time budget\n\t\tif (Date.now() - t1 >= config.timeBudget) {\n\t\t\tbreak;\n\t\t}\n\n\t\t// reset the index at which the regexp should start matching, also know where it\n\t\t// should stop so that subsequent search don't repeat previous searches\n\t\tconst regexIndex = pos - config.windowSize * i;\n\t\twordDefinition.lastIndex = Math.max(0, regexIndex);\n\t\tconst thisMatch = _findRegexMatchEnclosingPosition(wordDefinition, text, pos, prevRegexIndex);\n\n\t\tif (!thisMatch && match) {\n\t\t\t// stop: we have something\n\t\t\tbreak;\n\t\t}\n\n\t\tmatch = thisMatch;\n\n\t\t// stop: searched at start\n\t\tif (regexIndex <= 0) {\n\t\t\tbreak;\n\t\t}\n\t\tprevRegexIndex = regexIndex;\n\t}\n\n\tif (match) {\n\t\tconst result = {\n\t\t\tword: match[0],\n\t\t\tstartColumn: textOffset + 1 + match.index!,\n\t\t\tendColumn: textOffset + 1 + match.index! + match[0].length\n\t\t};\n\t\twordDefinition.lastIndex = 0;\n\t\treturn result;\n\t}\n\n\treturn null;\n}\n\nfunction _findRegexMatchEnclosingPosition(wordDefinition: RegExp, text: string, pos: number, stopPos: number): RegExpMatchArray | null {\n\tlet match: RegExpMatchArray | null;\n\twhile (match = wordDefinition.exec(text)) {\n\t\tconst matchIndex = match.index || 0;\n\t\tif (matchIndex <= pos && wordDefinition.lastIndex >= pos) {\n\t\t\treturn match;\n\t\t} else if (stopPos > 0 && matchIndex > stopPos) {\n\t\t\treturn null;\n\t\t}\n\t}\n\treturn null;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { CursorColumns } from 'vs/editor/common/core/cursorColumns';\n\nexport const enum Direction {\n\tLeft,\n\tRight,\n\tNearest,\n}\n\nexport class AtomicTabMoveOperations {\n\t/**\n\t * Get the visible column at the position. If we get to a non-whitespace character first\n\t * or past the end of string then return -1.\n\t *\n\t * **Note** `position` and the return value are 0-based.\n\t */\n\tpublic static whitespaceVisibleColumn(lineContent: string, position: number, tabSize: number): [number, number, number] {\n\t\tconst lineLength = lineContent.length;\n\t\tlet visibleColumn = 0;\n\t\tlet prevTabStopPosition = -1;\n\t\tlet prevTabStopVisibleColumn = -1;\n\t\tfor (let i = 0; i < lineLength; i++) {\n\t\t\tif (i === position) {\n\t\t\t\treturn [prevTabStopPosition, prevTabStopVisibleColumn, visibleColumn];\n\t\t\t}\n\t\t\tif (visibleColumn % tabSize === 0) {\n\t\t\t\tprevTabStopPosition = i;\n\t\t\t\tprevTabStopVisibleColumn = visibleColumn;\n\t\t\t}\n\t\t\tconst chCode = lineContent.charCodeAt(i);\n\t\t\tswitch (chCode) {\n\t\t\t\tcase CharCode.Space:\n\t\t\t\t\tvisibleColumn += 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CharCode.Tab:\n\t\t\t\t\t// Skip to the next multiple of tabSize.\n\t\t\t\t\tvisibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\treturn [-1, -1, -1];\n\t\t\t}\n\t\t}\n\t\tif (position === lineLength) {\n\t\t\treturn [prevTabStopPosition, prevTabStopVisibleColumn, visibleColumn];\n\t\t}\n\t\treturn [-1, -1, -1];\n\t}\n\n\t/**\n\t * Return the position that should result from a move left, right or to the\n\t * nearest tab, if atomic tabs are enabled. Left and right are used for the\n\t * arrow key movements, nearest is used for mouse selection. It returns\n\t * -1 if atomic tabs are not relevant and you should fall back to normal\n\t * behaviour.\n\t *\n\t * **Note**: `position` and the return value are 0-based.\n\t */\n\tpublic static atomicPosition(lineContent: string, position: number, tabSize: number, direction: Direction): number {\n\t\tconst lineLength = lineContent.length;\n\n\t\t// Get the 0-based visible column corresponding to the position, or return\n\t\t// -1 if it is not in the initial whitespace.\n\t\tconst [prevTabStopPosition, prevTabStopVisibleColumn, visibleColumn] = AtomicTabMoveOperations.whitespaceVisibleColumn(lineContent, position, tabSize);\n\n\t\tif (visibleColumn === -1) {\n\t\t\treturn -1;\n\t\t}\n\n\t\t// Is the output left or right of the current position. The case for nearest\n\t\t// where it is the same as the current position is handled in the switch.\n\t\tlet left: boolean;\n\t\tswitch (direction) {\n\t\t\tcase Direction.Left:\n\t\t\t\tleft = true;\n\t\t\t\tbreak;\n\t\t\tcase Direction.Right:\n\t\t\t\tleft = false;\n\t\t\t\tbreak;\n\t\t\tcase Direction.Nearest:\n\t\t\t\t// The code below assumes the output position is either left or right\n\t\t\t\t// of the input position. If it is the same, return immediately.\n\t\t\t\tif (visibleColumn % tabSize === 0) {\n\t\t\t\t\treturn position;\n\t\t\t\t}\n\t\t\t\t// Go to the nearest indentation.\n\t\t\t\tleft = visibleColumn % tabSize <= (tabSize / 2);\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// If going left, we can just use the info about the last tab stop position and\n\t\t// last tab stop visible column that we computed in the first walk over the whitespace.\n\t\tif (left) {\n\t\t\tif (prevTabStopPosition === -1) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\t// If the direction is left, we need to keep scanning right to ensure\n\t\t\t// that targetVisibleColumn + tabSize is before non-whitespace.\n\t\t\t// This is so that when we press left at the end of a partial\n\t\t\t// indentation it only goes one character. For example ' foo' with\n\t\t\t// tabSize 4, should jump from position 6 to position 5, not 4.\n\t\t\tlet currentVisibleColumn = prevTabStopVisibleColumn;\n\t\t\tfor (let i = prevTabStopPosition; i < lineLength; ++i) {\n\t\t\t\tif (currentVisibleColumn === prevTabStopVisibleColumn + tabSize) {\n\t\t\t\t\t// It is a full indentation.\n\t\t\t\t\treturn prevTabStopPosition;\n\t\t\t\t}\n\n\t\t\t\tconst chCode = lineContent.charCodeAt(i);\n\t\t\t\tswitch (chCode) {\n\t\t\t\t\tcase CharCode.Space:\n\t\t\t\t\t\tcurrentVisibleColumn += 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CharCode.Tab:\n\t\t\t\t\t\tcurrentVisibleColumn = CursorColumns.nextRenderTabStop(currentVisibleColumn, tabSize);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (currentVisibleColumn === prevTabStopVisibleColumn + tabSize) {\n\t\t\t\treturn prevTabStopPosition;\n\t\t\t}\n\t\t\t// It must have been a partial indentation.\n\t\t\treturn -1;\n\t\t}\n\n\t\t// We are going right.\n\t\tconst targetVisibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize);\n\n\t\t// We can just continue from where whitespaceVisibleColumn got to.\n\t\tlet currentVisibleColumn = visibleColumn;\n\t\tfor (let i = position; i < lineLength; i++) {\n\t\t\tif (currentVisibleColumn === targetVisibleColumn) {\n\t\t\t\treturn i;\n\t\t\t}\n\n\t\t\tconst chCode = lineContent.charCodeAt(i);\n\t\t\tswitch (chCode) {\n\t\t\t\tcase CharCode.Space:\n\t\t\t\t\tcurrentVisibleColumn += 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CharCode.Tab:\n\t\t\t\t\tcurrentVisibleColumn = CursorColumns.nextRenderTabStop(currentVisibleColumn, tabSize);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t\t// This condition handles when the target column is at the end of the line.\n\t\tif (currentVisibleColumn === targetVisibleColumn) {\n\t\t\treturn lineLength;\n\t\t}\n\t\treturn -1;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDiffChange, ISequence, LcsDiff, IDiffResult } from 'vs/base/common/diff/diff';\nimport * as strings from 'vs/base/common/strings';\n\nconst MINIMUM_MATCHING_CHARACTER_LENGTH = 3;\n\nexport interface IDiffComputationResult {\n\tquitEarly: boolean;\n\tidentical: boolean;\n\tchanges: ILineChange[];\n}\n\n/**\n * A change\n */\nexport interface IChange {\n\treadonly originalStartLineNumber: number;\n\treadonly originalEndLineNumber: number;\n\treadonly modifiedStartLineNumber: number;\n\treadonly modifiedEndLineNumber: number;\n}\n\n/**\n * A character level change.\n */\nexport interface ICharChange extends IChange {\n\treadonly originalStartColumn: number;\n\treadonly originalEndColumn: number;\n\treadonly modifiedStartColumn: number;\n\treadonly modifiedEndColumn: number;\n}\n\n/**\n * A line change\n */\nexport interface ILineChange extends IChange {\n\treadonly charChanges: ICharChange[] | undefined;\n}\n\nexport interface IDiffComputerResult {\n\tquitEarly: boolean;\n\tchanges: ILineChange[];\n}\n\nfunction computeDiff(originalSequence: ISequence, modifiedSequence: ISequence, continueProcessingPredicate: () => boolean, pretty: boolean): IDiffResult {\n\tconst diffAlgo = new LcsDiff(originalSequence, modifiedSequence, continueProcessingPredicate);\n\treturn diffAlgo.ComputeDiff(pretty);\n}\n\nclass LineSequence implements ISequence {\n\n\tpublic readonly lines: string[];\n\tprivate readonly _startColumns: number[];\n\tprivate readonly _endColumns: number[];\n\n\tconstructor(lines: string[]) {\n\t\tconst startColumns: number[] = [];\n\t\tconst endColumns: number[] = [];\n\t\tfor (let i = 0, length = lines.length; i < length; i++) {\n\t\t\tstartColumns[i] = getFirstNonBlankColumn(lines[i], 1);\n\t\t\tendColumns[i] = getLastNonBlankColumn(lines[i], 1);\n\t\t}\n\t\tthis.lines = lines;\n\t\tthis._startColumns = startColumns;\n\t\tthis._endColumns = endColumns;\n\t}\n\n\tpublic getElements(): Int32Array | number[] | string[] {\n\t\tconst elements: string[] = [];\n\t\tfor (let i = 0, len = this.lines.length; i < len; i++) {\n\t\t\telements[i] = this.lines[i].substring(this._startColumns[i] - 1, this._endColumns[i] - 1);\n\t\t}\n\t\treturn elements;\n\t}\n\n\tpublic getStrictElement(index: number): string {\n\t\treturn this.lines[index];\n\t}\n\n\tpublic getStartLineNumber(i: number): number {\n\t\treturn i + 1;\n\t}\n\n\tpublic getEndLineNumber(i: number): number {\n\t\treturn i + 1;\n\t}\n\n\tpublic createCharSequence(shouldIgnoreTrimWhitespace: boolean, startIndex: number, endIndex: number): CharSequence {\n\t\tconst charCodes: number[] = [];\n\t\tconst lineNumbers: number[] = [];\n\t\tconst columns: number[] = [];\n\t\tlet len = 0;\n\t\tfor (let index = startIndex; index <= endIndex; index++) {\n\t\t\tconst lineContent = this.lines[index];\n\t\t\tconst startColumn = (shouldIgnoreTrimWhitespace ? this._startColumns[index] : 1);\n\t\t\tconst endColumn = (shouldIgnoreTrimWhitespace ? this._endColumns[index] : lineContent.length + 1);\n\t\t\tfor (let col = startColumn; col < endColumn; col++) {\n\t\t\t\tcharCodes[len] = lineContent.charCodeAt(col - 1);\n\t\t\t\tlineNumbers[len] = index + 1;\n\t\t\t\tcolumns[len] = col;\n\t\t\t\tlen++;\n\t\t\t}\n\t\t}\n\t\treturn new CharSequence(charCodes, lineNumbers, columns);\n\t}\n}\n\nclass CharSequence implements ISequence {\n\n\tprivate readonly _charCodes: number[];\n\tprivate readonly _lineNumbers: number[];\n\tprivate readonly _columns: number[];\n\n\tconstructor(charCodes: number[], lineNumbers: number[], columns: number[]) {\n\t\tthis._charCodes = charCodes;\n\t\tthis._lineNumbers = lineNumbers;\n\t\tthis._columns = columns;\n\t}\n\n\tpublic getElements(): Int32Array | number[] | string[] {\n\t\treturn this._charCodes;\n\t}\n\n\tpublic getStartLineNumber(i: number): number {\n\t\treturn this._lineNumbers[i];\n\t}\n\n\tpublic getStartColumn(i: number): number {\n\t\treturn this._columns[i];\n\t}\n\n\tpublic getEndLineNumber(i: number): number {\n\t\treturn this._lineNumbers[i];\n\t}\n\n\tpublic getEndColumn(i: number): number {\n\t\treturn this._columns[i] + 1;\n\t}\n}\n\nclass CharChange implements ICharChange {\n\n\tpublic originalStartLineNumber: number;\n\tpublic originalStartColumn: number;\n\tpublic originalEndLineNumber: number;\n\tpublic originalEndColumn: number;\n\n\tpublic modifiedStartLineNumber: number;\n\tpublic modifiedStartColumn: number;\n\tpublic modifiedEndLineNumber: number;\n\tpublic modifiedEndColumn: number;\n\n\tconstructor(\n\t\toriginalStartLineNumber: number,\n\t\toriginalStartColumn: number,\n\t\toriginalEndLineNumber: number,\n\t\toriginalEndColumn: number,\n\t\tmodifiedStartLineNumber: number,\n\t\tmodifiedStartColumn: number,\n\t\tmodifiedEndLineNumber: number,\n\t\tmodifiedEndColumn: number\n\t) {\n\t\tthis.originalStartLineNumber = originalStartLineNumber;\n\t\tthis.originalStartColumn = originalStartColumn;\n\t\tthis.originalEndLineNumber = originalEndLineNumber;\n\t\tthis.originalEndColumn = originalEndColumn;\n\t\tthis.modifiedStartLineNumber = modifiedStartLineNumber;\n\t\tthis.modifiedStartColumn = modifiedStartColumn;\n\t\tthis.modifiedEndLineNumber = modifiedEndLineNumber;\n\t\tthis.modifiedEndColumn = modifiedEndColumn;\n\t}\n\n\tpublic static createFromDiffChange(diffChange: IDiffChange, originalCharSequence: CharSequence, modifiedCharSequence: CharSequence): CharChange {\n\t\tlet originalStartLineNumber: number;\n\t\tlet originalStartColumn: number;\n\t\tlet originalEndLineNumber: number;\n\t\tlet originalEndColumn: number;\n\t\tlet modifiedStartLineNumber: number;\n\t\tlet modifiedStartColumn: number;\n\t\tlet modifiedEndLineNumber: number;\n\t\tlet modifiedEndColumn: number;\n\n\t\tif (diffChange.originalLength === 0) {\n\t\t\toriginalStartLineNumber = 0;\n\t\t\toriginalStartColumn = 0;\n\t\t\toriginalEndLineNumber = 0;\n\t\t\toriginalEndColumn = 0;\n\t\t} else {\n\t\t\toriginalStartLineNumber = originalCharSequence.getStartLineNumber(diffChange.originalStart);\n\t\t\toriginalStartColumn = originalCharSequence.getStartColumn(diffChange.originalStart);\n\t\t\toriginalEndLineNumber = originalCharSequence.getEndLineNumber(diffChange.originalStart + diffChange.originalLength - 1);\n\t\t\toriginalEndColumn = originalCharSequence.getEndColumn(diffChange.originalStart + diffChange.originalLength - 1);\n\t\t}\n\n\t\tif (diffChange.modifiedLength === 0) {\n\t\t\tmodifiedStartLineNumber = 0;\n\t\t\tmodifiedStartColumn = 0;\n\t\t\tmodifiedEndLineNumber = 0;\n\t\t\tmodifiedEndColumn = 0;\n\t\t} else {\n\t\t\tmodifiedStartLineNumber = modifiedCharSequence.getStartLineNumber(diffChange.modifiedStart);\n\t\t\tmodifiedStartColumn = modifiedCharSequence.getStartColumn(diffChange.modifiedStart);\n\t\t\tmodifiedEndLineNumber = modifiedCharSequence.getEndLineNumber(diffChange.modifiedStart + diffChange.modifiedLength - 1);\n\t\t\tmodifiedEndColumn = modifiedCharSequence.getEndColumn(diffChange.modifiedStart + diffChange.modifiedLength - 1);\n\t\t}\n\n\t\treturn new CharChange(\n\t\t\toriginalStartLineNumber, originalStartColumn, originalEndLineNumber, originalEndColumn,\n\t\t\tmodifiedStartLineNumber, modifiedStartColumn, modifiedEndLineNumber, modifiedEndColumn,\n\t\t);\n\t}\n}\n\nfunction postProcessCharChanges(rawChanges: IDiffChange[]): IDiffChange[] {\n\tif (rawChanges.length <= 1) {\n\t\treturn rawChanges;\n\t}\n\n\tconst result = [rawChanges[0]];\n\tlet prevChange = result[0];\n\n\tfor (let i = 1, len = rawChanges.length; i < len; i++) {\n\t\tconst currChange = rawChanges[i];\n\n\t\tconst originalMatchingLength = currChange.originalStart - (prevChange.originalStart + prevChange.originalLength);\n\t\tconst modifiedMatchingLength = currChange.modifiedStart - (prevChange.modifiedStart + prevChange.modifiedLength);\n\t\t// Both of the above should be equal, but the continueProcessingPredicate may prevent this from being true\n\t\tconst matchingLength = Math.min(originalMatchingLength, modifiedMatchingLength);\n\n\t\tif (matchingLength < MINIMUM_MATCHING_CHARACTER_LENGTH) {\n\t\t\t// Merge the current change into the previous one\n\t\t\tprevChange.originalLength = (currChange.originalStart + currChange.originalLength) - prevChange.originalStart;\n\t\t\tprevChange.modifiedLength = (currChange.modifiedStart + currChange.modifiedLength) - prevChange.modifiedStart;\n\t\t} else {\n\t\t\t// Add the current change\n\t\t\tresult.push(currChange);\n\t\t\tprevChange = currChange;\n\t\t}\n\t}\n\n\treturn result;\n}\n\nclass LineChange implements ILineChange {\n\tpublic originalStartLineNumber: number;\n\tpublic originalEndLineNumber: number;\n\tpublic modifiedStartLineNumber: number;\n\tpublic modifiedEndLineNumber: number;\n\tpublic charChanges: CharChange[] | undefined;\n\n\tconstructor(\n\t\toriginalStartLineNumber: number,\n\t\toriginalEndLineNumber: number,\n\t\tmodifiedStartLineNumber: number,\n\t\tmodifiedEndLineNumber: number,\n\t\tcharChanges: CharChange[] | undefined\n\t) {\n\t\tthis.originalStartLineNumber = originalStartLineNumber;\n\t\tthis.originalEndLineNumber = originalEndLineNumber;\n\t\tthis.modifiedStartLineNumber = modifiedStartLineNumber;\n\t\tthis.modifiedEndLineNumber = modifiedEndLineNumber;\n\t\tthis.charChanges = charChanges;\n\t}\n\n\tpublic static createFromDiffResult(shouldIgnoreTrimWhitespace: boolean, diffChange: IDiffChange, originalLineSequence: LineSequence, modifiedLineSequence: LineSequence, continueCharDiff: () => boolean, shouldComputeCharChanges: boolean, shouldPostProcessCharChanges: boolean): LineChange {\n\t\tlet originalStartLineNumber: number;\n\t\tlet originalEndLineNumber: number;\n\t\tlet modifiedStartLineNumber: number;\n\t\tlet modifiedEndLineNumber: number;\n\t\tlet charChanges: CharChange[] | undefined = undefined;\n\n\t\tif (diffChange.originalLength === 0) {\n\t\t\toriginalStartLineNumber = originalLineSequence.getStartLineNumber(diffChange.originalStart) - 1;\n\t\t\toriginalEndLineNumber = 0;\n\t\t} else {\n\t\t\toriginalStartLineNumber = originalLineSequence.getStartLineNumber(diffChange.originalStart);\n\t\t\toriginalEndLineNumber = originalLineSequence.getEndLineNumber(diffChange.originalStart + diffChange.originalLength - 1);\n\t\t}\n\n\t\tif (diffChange.modifiedLength === 0) {\n\t\t\tmodifiedStartLineNumber = modifiedLineSequence.getStartLineNumber(diffChange.modifiedStart) - 1;\n\t\t\tmodifiedEndLineNumber = 0;\n\t\t} else {\n\t\t\tmodifiedStartLineNumber = modifiedLineSequence.getStartLineNumber(diffChange.modifiedStart);\n\t\t\tmodifiedEndLineNumber = modifiedLineSequence.getEndLineNumber(diffChange.modifiedStart + diffChange.modifiedLength - 1);\n\t\t}\n\n\t\tif (shouldComputeCharChanges && diffChange.originalLength > 0 && diffChange.originalLength < 20 && diffChange.modifiedLength > 0 && diffChange.modifiedLength < 20 && continueCharDiff()) {\n\t\t\t// Compute character changes for diff chunks of at most 20 lines...\n\t\t\tconst originalCharSequence = originalLineSequence.createCharSequence(shouldIgnoreTrimWhitespace, diffChange.originalStart, diffChange.originalStart + diffChange.originalLength - 1);\n\t\t\tconst modifiedCharSequence = modifiedLineSequence.createCharSequence(shouldIgnoreTrimWhitespace, diffChange.modifiedStart, diffChange.modifiedStart + diffChange.modifiedLength - 1);\n\n\t\t\tlet rawChanges = computeDiff(originalCharSequence, modifiedCharSequence, continueCharDiff, true).changes;\n\n\t\t\tif (shouldPostProcessCharChanges) {\n\t\t\t\trawChanges = postProcessCharChanges(rawChanges);\n\t\t\t}\n\n\t\t\tcharChanges = [];\n\t\t\tfor (let i = 0, length = rawChanges.length; i < length; i++) {\n\t\t\t\tcharChanges.push(CharChange.createFromDiffChange(rawChanges[i], originalCharSequence, modifiedCharSequence));\n\t\t\t}\n\t\t}\n\n\t\treturn new LineChange(originalStartLineNumber, originalEndLineNumber, modifiedStartLineNumber, modifiedEndLineNumber, charChanges);\n\t}\n}\n\nexport interface IDiffComputerOpts {\n\tshouldComputeCharChanges: boolean;\n\tshouldPostProcessCharChanges: boolean;\n\tshouldIgnoreTrimWhitespace: boolean;\n\tshouldMakePrettyDiff: boolean;\n\tmaxComputationTime: number;\n}\n\nexport class DiffComputer {\n\n\tprivate readonly shouldComputeCharChanges: boolean;\n\tprivate readonly shouldPostProcessCharChanges: boolean;\n\tprivate readonly shouldIgnoreTrimWhitespace: boolean;\n\tprivate readonly shouldMakePrettyDiff: boolean;\n\tprivate readonly originalLines: string[];\n\tprivate readonly modifiedLines: string[];\n\tprivate readonly original: LineSequence;\n\tprivate readonly modified: LineSequence;\n\tprivate readonly continueLineDiff: () => boolean;\n\tprivate readonly continueCharDiff: () => boolean;\n\n\tconstructor(originalLines: string[], modifiedLines: string[], opts: IDiffComputerOpts) {\n\t\tthis.shouldComputeCharChanges = opts.shouldComputeCharChanges;\n\t\tthis.shouldPostProcessCharChanges = opts.shouldPostProcessCharChanges;\n\t\tthis.shouldIgnoreTrimWhitespace = opts.shouldIgnoreTrimWhitespace;\n\t\tthis.shouldMakePrettyDiff = opts.shouldMakePrettyDiff;\n\t\tthis.originalLines = originalLines;\n\t\tthis.modifiedLines = modifiedLines;\n\t\tthis.original = new LineSequence(originalLines);\n\t\tthis.modified = new LineSequence(modifiedLines);\n\n\t\tthis.continueLineDiff = createContinueProcessingPredicate(opts.maxComputationTime);\n\t\tthis.continueCharDiff = createContinueProcessingPredicate(opts.maxComputationTime === 0 ? 0 : Math.min(opts.maxComputationTime, 5000)); // never run after 5s for character changes...\n\t}\n\n\tpublic computeDiff(): IDiffComputerResult {\n\n\t\tif (this.original.lines.length === 1 && this.original.lines[0].length === 0) {\n\t\t\t// empty original => fast path\n\t\t\tif (this.modified.lines.length === 1 && this.modified.lines[0].length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tquitEarly: false,\n\t\t\t\t\tchanges: []\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tquitEarly: false,\n\t\t\t\tchanges: [{\n\t\t\t\t\toriginalStartLineNumber: 1,\n\t\t\t\t\toriginalEndLineNumber: 1,\n\t\t\t\t\tmodifiedStartLineNumber: 1,\n\t\t\t\t\tmodifiedEndLineNumber: this.modified.lines.length,\n\t\t\t\t\tcharChanges: [{\n\t\t\t\t\t\tmodifiedEndColumn: 0,\n\t\t\t\t\t\tmodifiedEndLineNumber: 0,\n\t\t\t\t\t\tmodifiedStartColumn: 0,\n\t\t\t\t\t\tmodifiedStartLineNumber: 0,\n\t\t\t\t\t\toriginalEndColumn: 0,\n\t\t\t\t\t\toriginalEndLineNumber: 0,\n\t\t\t\t\t\toriginalStartColumn: 0,\n\t\t\t\t\t\toriginalStartLineNumber: 0\n\t\t\t\t\t}]\n\t\t\t\t}]\n\t\t\t};\n\t\t}\n\n\t\tif (this.modified.lines.length === 1 && this.modified.lines[0].length === 0) {\n\t\t\t// empty modified => fast path\n\t\t\treturn {\n\t\t\t\tquitEarly: false,\n\t\t\t\tchanges: [{\n\t\t\t\t\toriginalStartLineNumber: 1,\n\t\t\t\t\toriginalEndLineNumber: this.original.lines.length,\n\t\t\t\t\tmodifiedStartLineNumber: 1,\n\t\t\t\t\tmodifiedEndLineNumber: 1,\n\t\t\t\t\tcharChanges: [{\n\t\t\t\t\t\tmodifiedEndColumn: 0,\n\t\t\t\t\t\tmodifiedEndLineNumber: 0,\n\t\t\t\t\t\tmodifiedStartColumn: 0,\n\t\t\t\t\t\tmodifiedStartLineNumber: 0,\n\t\t\t\t\t\toriginalEndColumn: 0,\n\t\t\t\t\t\toriginalEndLineNumber: 0,\n\t\t\t\t\t\toriginalStartColumn: 0,\n\t\t\t\t\t\toriginalStartLineNumber: 0\n\t\t\t\t\t}]\n\t\t\t\t}]\n\t\t\t};\n\t\t}\n\n\t\tconst diffResult = computeDiff(this.original, this.modified, this.continueLineDiff, this.shouldMakePrettyDiff);\n\t\tconst rawChanges = diffResult.changes;\n\t\tconst quitEarly = diffResult.quitEarly;\n\n\t\t// The diff is always computed with ignoring trim whitespace\n\t\t// This ensures we get the prettiest diff\n\n\t\tif (this.shouldIgnoreTrimWhitespace) {\n\t\t\tconst lineChanges: LineChange[] = [];\n\t\t\tfor (let i = 0, length = rawChanges.length; i < length; i++) {\n\t\t\t\tlineChanges.push(LineChange.createFromDiffResult(this.shouldIgnoreTrimWhitespace, rawChanges[i], this.original, this.modified, this.continueCharDiff, this.shouldComputeCharChanges, this.shouldPostProcessCharChanges));\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tquitEarly: quitEarly,\n\t\t\t\tchanges: lineChanges\n\t\t\t};\n\t\t}\n\n\t\t// Need to post-process and introduce changes where the trim whitespace is different\n\t\t// Note that we are looping starting at -1 to also cover the lines before the first change\n\t\tconst result: LineChange[] = [];\n\n\t\tlet originalLineIndex = 0;\n\t\tlet modifiedLineIndex = 0;\n\t\tfor (let i = -1 /* !!!! */, len = rawChanges.length; i < len; i++) {\n\t\t\tconst nextChange = (i + 1 < len ? rawChanges[i + 1] : null);\n\t\t\tconst originalStop = (nextChange ? nextChange.originalStart : this.originalLines.length);\n\t\t\tconst modifiedStop = (nextChange ? nextChange.modifiedStart : this.modifiedLines.length);\n\n\t\t\twhile (originalLineIndex < originalStop && modifiedLineIndex < modifiedStop) {\n\t\t\t\tconst originalLine = this.originalLines[originalLineIndex];\n\t\t\t\tconst modifiedLine = this.modifiedLines[modifiedLineIndex];\n\n\t\t\t\tif (originalLine !== modifiedLine) {\n\t\t\t\t\t// These lines differ only in trim whitespace\n\n\t\t\t\t\t// Check the leading whitespace\n\t\t\t\t\t{\n\t\t\t\t\t\tlet originalStartColumn = getFirstNonBlankColumn(originalLine, 1);\n\t\t\t\t\t\tlet modifiedStartColumn = getFirstNonBlankColumn(modifiedLine, 1);\n\t\t\t\t\t\twhile (originalStartColumn > 1 && modifiedStartColumn > 1) {\n\t\t\t\t\t\t\tconst originalChar = originalLine.charCodeAt(originalStartColumn - 2);\n\t\t\t\t\t\t\tconst modifiedChar = modifiedLine.charCodeAt(modifiedStartColumn - 2);\n\t\t\t\t\t\t\tif (originalChar !== modifiedChar) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\toriginalStartColumn--;\n\t\t\t\t\t\t\tmodifiedStartColumn--;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (originalStartColumn > 1 || modifiedStartColumn > 1) {\n\t\t\t\t\t\t\tthis._pushTrimWhitespaceCharChange(result,\n\t\t\t\t\t\t\t\toriginalLineIndex + 1, 1, originalStartColumn,\n\t\t\t\t\t\t\t\tmodifiedLineIndex + 1, 1, modifiedStartColumn\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check the trailing whitespace\n\t\t\t\t\t{\n\t\t\t\t\t\tlet originalEndColumn = getLastNonBlankColumn(originalLine, 1);\n\t\t\t\t\t\tlet modifiedEndColumn = getLastNonBlankColumn(modifiedLine, 1);\n\t\t\t\t\t\tconst originalMaxColumn = originalLine.length + 1;\n\t\t\t\t\t\tconst modifiedMaxColumn = modifiedLine.length + 1;\n\t\t\t\t\t\twhile (originalEndColumn < originalMaxColumn && modifiedEndColumn < modifiedMaxColumn) {\n\t\t\t\t\t\t\tconst originalChar = originalLine.charCodeAt(originalEndColumn - 1);\n\t\t\t\t\t\t\tconst modifiedChar = originalLine.charCodeAt(modifiedEndColumn - 1);\n\t\t\t\t\t\t\tif (originalChar !== modifiedChar) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\toriginalEndColumn++;\n\t\t\t\t\t\t\tmodifiedEndColumn++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (originalEndColumn < originalMaxColumn || modifiedEndColumn < modifiedMaxColumn) {\n\t\t\t\t\t\t\tthis._pushTrimWhitespaceCharChange(result,\n\t\t\t\t\t\t\t\toriginalLineIndex + 1, originalEndColumn, originalMaxColumn,\n\t\t\t\t\t\t\t\tmodifiedLineIndex + 1, modifiedEndColumn, modifiedMaxColumn\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\toriginalLineIndex++;\n\t\t\t\tmodifiedLineIndex++;\n\t\t\t}\n\n\t\t\tif (nextChange) {\n\t\t\t\t// Emit the actual change\n\t\t\t\tresult.push(LineChange.createFromDiffResult(this.shouldIgnoreTrimWhitespace, nextChange, this.original, this.modified, this.continueCharDiff, this.shouldComputeCharChanges, this.shouldPostProcessCharChanges));\n\n\t\t\t\toriginalLineIndex += nextChange.originalLength;\n\t\t\t\tmodifiedLineIndex += nextChange.modifiedLength;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tquitEarly: quitEarly,\n\t\t\tchanges: result\n\t\t};\n\t}\n\n\tprivate _pushTrimWhitespaceCharChange(\n\t\tresult: LineChange[],\n\t\toriginalLineNumber: number, originalStartColumn: number, originalEndColumn: number,\n\t\tmodifiedLineNumber: number, modifiedStartColumn: number, modifiedEndColumn: number\n\t): void {\n\t\tif (this._mergeTrimWhitespaceCharChange(result, originalLineNumber, originalStartColumn, originalEndColumn, modifiedLineNumber, modifiedStartColumn, modifiedEndColumn)) {\n\t\t\t// Merged into previous\n\t\t\treturn;\n\t\t}\n\n\t\tlet charChanges: CharChange[] | undefined = undefined;\n\t\tif (this.shouldComputeCharChanges) {\n\t\t\tcharChanges = [new CharChange(\n\t\t\t\toriginalLineNumber, originalStartColumn, originalLineNumber, originalEndColumn,\n\t\t\t\tmodifiedLineNumber, modifiedStartColumn, modifiedLineNumber, modifiedEndColumn\n\t\t\t)];\n\t\t}\n\t\tresult.push(new LineChange(\n\t\t\toriginalLineNumber, originalLineNumber,\n\t\t\tmodifiedLineNumber, modifiedLineNumber,\n\t\t\tcharChanges\n\t\t));\n\t}\n\n\tprivate _mergeTrimWhitespaceCharChange(\n\t\tresult: LineChange[],\n\t\toriginalLineNumber: number, originalStartColumn: number, originalEndColumn: number,\n\t\tmodifiedLineNumber: number, modifiedStartColumn: number, modifiedEndColumn: number\n\t): boolean {\n\t\tconst len = result.length;\n\t\tif (len === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst prevChange = result[len - 1];\n\n\t\tif (prevChange.originalEndLineNumber === 0 || prevChange.modifiedEndLineNumber === 0) {\n\t\t\t// Don't merge with inserts/deletes\n\t\t\treturn false;\n\t\t}\n\n\t\tif (prevChange.originalEndLineNumber + 1 === originalLineNumber && prevChange.modifiedEndLineNumber + 1 === modifiedLineNumber) {\n\t\t\tprevChange.originalEndLineNumber = originalLineNumber;\n\t\t\tprevChange.modifiedEndLineNumber = modifiedLineNumber;\n\t\t\tif (this.shouldComputeCharChanges && prevChange.charChanges) {\n\t\t\t\tprevChange.charChanges.push(new CharChange(\n\t\t\t\t\toriginalLineNumber, originalStartColumn, originalLineNumber, originalEndColumn,\n\t\t\t\t\tmodifiedLineNumber, modifiedStartColumn, modifiedLineNumber, modifiedEndColumn\n\t\t\t\t));\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n\nfunction getFirstNonBlankColumn(txt: string, defaultValue: number): number {\n\tconst r = strings.firstNonWhitespaceIndex(txt);\n\tif (r === -1) {\n\t\treturn defaultValue;\n\t}\n\treturn r + 1;\n}\n\nfunction getLastNonBlankColumn(txt: string, defaultValue: number): number {\n\tconst r = strings.lastNonWhitespaceIndex(txt);\n\tif (r === -1) {\n\t\treturn defaultValue;\n\t}\n\treturn r + 2;\n}\n\nfunction createContinueProcessingPredicate(maximumRuntime: number): () => boolean {\n\tif (maximumRuntime === 0) {\n\t\treturn () => true;\n\t}\n\n\tconst startTime = Date.now();\n\treturn () => {\n\t\treturn Date.now() - startTime < maximumRuntime;\n\t};\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IEditorAction } from 'vs/editor/common/editorCommon';\nimport { IContextKeyService, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';\n\nexport class InternalEditorAction implements IEditorAction {\n\n\tpublic readonly id: string;\n\tpublic readonly label: string;\n\tpublic readonly alias: string;\n\n\tprivate readonly _precondition: ContextKeyExpression | undefined;\n\tprivate readonly _run: () => Promise;\n\tprivate readonly _contextKeyService: IContextKeyService;\n\n\tconstructor(\n\t\tid: string,\n\t\tlabel: string,\n\t\talias: string,\n\t\tprecondition: ContextKeyExpression | undefined,\n\t\trun: () => Promise,\n\t\tcontextKeyService: IContextKeyService\n\t) {\n\t\tthis.id = id;\n\t\tthis.label = label;\n\t\tthis.alias = alias;\n\t\tthis._precondition = precondition;\n\t\tthis._run = run;\n\t\tthis._contextKeyService = contextKeyService;\n\t}\n\n\tpublic isSupported(): boolean {\n\t\treturn this._contextKeyService.contextMatchesRules(this._precondition);\n\t}\n\n\tpublic run(): Promise {\n\t\tif (!this.isSupported()) {\n\t\t\treturn Promise.resolve(undefined);\n\t\t}\n\n\t\treturn this._run();\n\t}\n}\n","\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { URI } from 'vs/base/common/uri';\nimport { IEditorOptions } from 'vs/editor/common/config/editorOptions';\nimport { IPosition, Position } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { ISelection, Selection } from 'vs/editor/common/core/selection';\nimport { IModelDecorationsChangeAccessor, ITextModel, IValidEditOperation } from 'vs/editor/common/model';\nimport { IDimension } from 'vs/editor/common/core/dimension';\n\n/**\n * A builder and helper for edit operations for a command.\n */\nexport interface IEditOperationBuilder {\n\t/**\n\t * Add a new edit operation (a replace operation).\n\t * @param range The range to replace (delete). May be empty to represent a simple insert.\n\t * @param text The text to replace with. May be null to represent a simple delete.\n\t */\n\taddEditOperation(range: IRange, text: string | null, forceMoveMarkers?: boolean): void;\n\n\t/**\n\t * Add a new edit operation (a replace operation).\n\t * The inverse edits will be accessible in `ICursorStateComputerData.getInverseEditOperations()`\n\t * @param range The range to replace (delete). May be empty to represent a simple insert.\n\t * @param text The text to replace with. May be null to represent a simple delete.\n\t */\n\taddTrackedEditOperation(range: IRange, text: string | null, forceMoveMarkers?: boolean): void;\n\n\t/**\n\t * Track `selection` when applying edit operations.\n\t * A best effort will be made to not grow/expand the selection.\n\t * An empty selection will clamp to a nearby character.\n\t * @param selection The selection to track.\n\t * @param trackPreviousOnEmpty If set, and the selection is empty, indicates whether the selection\n\t * should clamp to the previous or the next character.\n\t * @return A unique identifier.\n\t */\n\ttrackSelection(selection: Selection, trackPreviousOnEmpty?: boolean): string;\n}\n\n/**\n * A helper for computing cursor state after a command.\n */\nexport interface ICursorStateComputerData {\n\t/**\n\t * Get the inverse edit operations of the added edit operations.\n\t */\n\tgetInverseEditOperations(): IValidEditOperation[];\n\t/**\n\t * Get a previously tracked selection.\n\t * @param id The unique identifier returned by `trackSelection`.\n\t * @return The selection.\n\t */\n\tgetTrackedSelection(id: string): Selection;\n}\n\n/**\n * A command that modifies text / cursor state on a model.\n */\nexport interface ICommand {\n\n\t/**\n\t * Signal that this command is inserting automatic whitespace that should be trimmed if possible.\n\t * @internal\n\t */\n\treadonly insertsAutoWhitespace?: boolean;\n\n\t/**\n\t * Get the edit operations needed to execute this command.\n\t * @param model The model the command will execute on.\n\t * @param builder A helper to collect the needed edit operations and to track selections.\n\t */\n\tgetEditOperations(model: ITextModel, builder: IEditOperationBuilder): void;\n\n\t/**\n\t * Compute the cursor state after the edit operations were applied.\n\t * @param model The model the command has executed on.\n\t * @param helper A helper to get inverse edit operations and to get previously tracked selections.\n\t * @return The cursor state after the command executed.\n\t */\n\tcomputeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection;\n}\n\n/**\n * A model for the diff editor.\n */\nexport interface IDiffEditorModel {\n\t/**\n\t * Original model.\n\t */\n\toriginal: ITextModel;\n\t/**\n\t * Modified model.\n\t */\n\tmodified: ITextModel;\n}\n\n/**\n * An event describing that an editor has had its model reset (i.e. `editor.setModel()`).\n */\nexport interface IModelChangedEvent {\n\t/**\n\t * The `uri` of the previous model or null.\n\t */\n\treadonly oldModelUrl: URI | null;\n\t/**\n\t * The `uri` of the new model or null.\n\t */\n\treadonly newModelUrl: URI | null;\n}\n\n// --- view\n\nexport interface IScrollEvent {\n\treadonly scrollTop: number;\n\treadonly scrollLeft: number;\n\treadonly scrollWidth: number;\n\treadonly scrollHeight: number;\n\n\treadonly scrollTopChanged: boolean;\n\treadonly scrollLeftChanged: boolean;\n\treadonly scrollWidthChanged: boolean;\n\treadonly scrollHeightChanged: boolean;\n}\n\nexport interface IContentSizeChangedEvent {\n\treadonly contentWidth: number;\n\treadonly contentHeight: number;\n\n\treadonly contentWidthChanged: boolean;\n\treadonly contentHeightChanged: boolean;\n}\n\nexport interface INewScrollPosition {\n\tscrollLeft?: number;\n\tscrollTop?: number;\n}\n\nexport interface IEditorAction {\n\treadonly id: string;\n\treadonly label: string;\n\treadonly alias: string;\n\tisSupported(): boolean;\n\trun(): Promise;\n}\n\nexport type IEditorModel = ITextModel | IDiffEditorModel;\n\n/**\n * A (serializable) state of the cursors.\n */\nexport interface ICursorState {\n\tinSelectionMode: boolean;\n\tselectionStart: IPosition;\n\tposition: IPosition;\n}\n/**\n * A (serializable) state of the view.\n */\nexport interface IViewState {\n\t/** written by previous versions */\n\tscrollTop?: number;\n\t/** written by previous versions */\n\tscrollTopWithoutViewZones?: number;\n\tscrollLeft: number;\n\tfirstPosition: IPosition;\n\tfirstPositionDeltaTop: number;\n}\n/**\n * A (serializable) state of the code editor.\n */\nexport interface ICodeEditorViewState {\n\tcursorState: ICursorState[];\n\tviewState: IViewState;\n\tcontributionsState: { [id: string]: any };\n}\n/**\n * (Serializable) View state for the diff editor.\n */\nexport interface IDiffEditorViewState {\n\toriginal: ICodeEditorViewState | null;\n\tmodified: ICodeEditorViewState | null;\n}\n/**\n * An editor view state.\n */\nexport type IEditorViewState = ICodeEditorViewState | IDiffEditorViewState;\n\nexport const enum ScrollType {\n\tSmooth = 0,\n\tImmediate = 1,\n}\n\n/**\n * An editor.\n */\nexport interface IEditor {\n\t/**\n\t * An event emitted when the editor has been disposed.\n\t * @event\n\t */\n\tonDidDispose(listener: () => void): IDisposable;\n\n\t/**\n\t * Dispose the editor.\n\t */\n\tdispose(): void;\n\n\t/**\n\t * Get a unique id for this editor instance.\n\t */\n\tgetId(): string;\n\n\t/**\n\t * Get the editor type. Please see `EditorType`.\n\t * This is to avoid an instanceof check\n\t */\n\tgetEditorType(): string;\n\n\t/**\n\t * Update the editor's options after the editor has been created.\n\t */\n\tupdateOptions(newOptions: IEditorOptions): void;\n\n\t/**\n\t * Instructs the editor to remeasure its container. This method should\n\t * be called when the container of the editor gets resized.\n\t *\n\t * If a dimension is passed in, the passed in value will be used.\n\t */\n\tlayout(dimension?: IDimension): void;\n\n\t/**\n\t * Brings browser focus to the editor text\n\t */\n\tfocus(): void;\n\n\t/**\n\t * Returns true if the text inside this editor is focused (i.e. cursor is blinking).\n\t */\n\thasTextFocus(): boolean;\n\n\t/**\n\t * Returns all actions associated with this editor.\n\t */\n\tgetSupportedActions(): IEditorAction[];\n\n\t/**\n\t * Saves current view state of the editor in a serializable object.\n\t */\n\tsaveViewState(): IEditorViewState | null;\n\n\t/**\n\t * Restores the view state of the editor from a serializable object generated by `saveViewState`.\n\t */\n\trestoreViewState(state: IEditorViewState): void;\n\n\t/**\n\t * Given a position, returns a column number that takes tab-widths into account.\n\t */\n\tgetVisibleColumnFromPosition(position: IPosition): number;\n\n\t/**\n\t * Returns the primary position of the cursor.\n\t */\n\tgetPosition(): Position | null;\n\n\t/**\n\t * Set the primary position of the cursor. This will remove any secondary cursors.\n\t * @param position New primary cursor's position\n\t */\n\tsetPosition(position: IPosition): void;\n\n\t/**\n\t * Scroll vertically as necessary and reveal a line.\n\t */\n\trevealLine(lineNumber: number, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically as necessary and reveal a line centered vertically.\n\t */\n\trevealLineInCenter(lineNumber: number, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically as necessary and reveal a line centered vertically only if it lies outside the viewport.\n\t */\n\trevealLineInCenterIfOutsideViewport(lineNumber: number, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically as necessary and reveal a line close to the top of the viewport,\n\t * optimized for viewing a code definition.\n\t */\n\trevealLineNearTop(lineNumber: number, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically or horizontally as necessary and reveal a position.\n\t */\n\trevealPosition(position: IPosition, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically or horizontally as necessary and reveal a position centered vertically.\n\t */\n\trevealPositionInCenter(position: IPosition, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically or horizontally as necessary and reveal a position centered vertically only if it lies outside the viewport.\n\t */\n\trevealPositionInCenterIfOutsideViewport(position: IPosition, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically or horizontally as necessary and reveal a position close to the top of the viewport,\n\t * optimized for viewing a code definition.\n\t */\n\trevealPositionNearTop(position: IPosition, scrollType?: ScrollType): void;\n\n\t/**\n\t * Returns the primary selection of the editor.\n\t */\n\tgetSelection(): Selection | null;\n\n\t/**\n\t * Returns all the selections of the editor.\n\t */\n\tgetSelections(): Selection[] | null;\n\n\t/**\n\t * Set the primary selection of the editor. This will remove any secondary cursors.\n\t * @param selection The new selection\n\t */\n\tsetSelection(selection: IRange): void;\n\t/**\n\t * Set the primary selection of the editor. This will remove any secondary cursors.\n\t * @param selection The new selection\n\t */\n\tsetSelection(selection: Range): void;\n\t/**\n\t * Set the primary selection of the editor. This will remove any secondary cursors.\n\t * @param selection The new selection\n\t */\n\tsetSelection(selection: ISelection): void;\n\t/**\n\t * Set the primary selection of the editor. This will remove any secondary cursors.\n\t * @param selection The new selection\n\t */\n\tsetSelection(selection: Selection): void;\n\n\t/**\n\t * Set the selections for all the cursors of the editor.\n\t * Cursors will be removed or added, as necessary.\n\t */\n\tsetSelections(selections: readonly ISelection[]): void;\n\n\t/**\n\t * Scroll vertically as necessary and reveal lines.\n\t */\n\trevealLines(startLineNumber: number, endLineNumber: number, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically as necessary and reveal lines centered vertically.\n\t */\n\trevealLinesInCenter(lineNumber: number, endLineNumber: number, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically as necessary and reveal lines centered vertically only if it lies outside the viewport.\n\t */\n\trevealLinesInCenterIfOutsideViewport(lineNumber: number, endLineNumber: number, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically as necessary and reveal lines close to the top of the viewport,\n\t * optimized for viewing a code definition.\n\t */\n\trevealLinesNearTop(lineNumber: number, endLineNumber: number, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically or horizontally as necessary and reveal a range.\n\t */\n\trevealRange(range: IRange, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically or horizontally as necessary and reveal a range centered vertically.\n\t */\n\trevealRangeInCenter(range: IRange, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically or horizontally as necessary and reveal a range at the top of the viewport.\n\t */\n\trevealRangeAtTop(range: IRange, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically or horizontally as necessary and reveal a range centered vertically only if it lies outside the viewport.\n\t */\n\trevealRangeInCenterIfOutsideViewport(range: IRange, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically or horizontally as necessary and reveal a range close to the top of the viewport,\n\t * optimized for viewing a code definition.\n\t */\n\trevealRangeNearTop(range: IRange, scrollType?: ScrollType): void;\n\n\t/**\n\t * Scroll vertically or horizontally as necessary and reveal a range close to the top of the viewport,\n\t * optimized for viewing a code definition. Only if it lies outside the viewport.\n\t */\n\trevealRangeNearTopIfOutsideViewport(range: IRange, scrollType?: ScrollType): void;\n\n\t/**\n\t * Directly trigger a handler or an editor action.\n\t * @param source The source of the call.\n\t * @param handlerId The id of the handler or the id of a contribution.\n\t * @param payload Extra data to be sent to the handler.\n\t */\n\ttrigger(source: string | null | undefined, handlerId: string, payload: any): void;\n\n\t/**\n\t * Gets the current model attached to this editor.\n\t */\n\tgetModel(): IEditorModel | null;\n\n\t/**\n\t * Sets the current model attached to this editor.\n\t * If the previous model was created by the editor via the value key in the options\n\t * literal object, it will be destroyed. Otherwise, if the previous model was set\n\t * via setModel, or the model key in the options literal object, the previous model\n\t * will not be destroyed.\n\t * It is safe to call setModel(null) to simply detach the current model from the editor.\n\t */\n\tsetModel(model: IEditorModel | null): void;\n\n\t/**\n\t * Change the decorations. All decorations added through this changeAccessor\n\t * will get the ownerId of the editor (meaning they will not show up in other\n\t * editors).\n\t * @see {@link ITextModel.changeDecorations}\n\t * @internal\n\t */\n\tchangeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => any): any;\n}\n\n/**\n * A diff editor.\n *\n * @internal\n */\nexport interface IDiffEditor extends IEditor {\n\n\t/**\n\t * Type the getModel() of IEditor.\n\t */\n\tgetModel(): IDiffEditorModel | null;\n}\n\n\n/**\n * An editor contribution that gets created every time a new editor gets created and gets disposed when the editor gets disposed.\n */\nexport interface IEditorContribution {\n\t/**\n\t * Dispose this contribution.\n\t */\n\tdispose(): void;\n\t/**\n\t * Store view state.\n\t */\n\tsaveViewState?(): any;\n\t/**\n\t * Restore view state.\n\t */\n\trestoreViewState?(state: any): void;\n}\n\n/**\n * A diff editor contribution that gets created every time a new diffeditor gets created and gets disposed when the diff editor gets disposed.\n * @internal\n */\nexport interface IDiffEditorContribution {\n\t/**\n\t * Dispose this contribution.\n\t */\n\tdispose(): void;\n}\n\n/**\n * The type of the `IEditor`.\n */\nexport const EditorType = {\n\tICodeEditor: 'vs.editor.ICodeEditor',\n\tIDiffEditor: 'vs.editor.IDiffEditor'\n};\n\n/**\n * Built-in commands.\n * @internal\n */\nexport const enum Handler {\n\tCompositionStart = 'compositionStart',\n\tCompositionEnd = 'compositionEnd',\n\tType = 'type',\n\tReplacePreviousChar = 'replacePreviousChar',\n\tCompositionType = 'compositionType',\n\tPaste = 'paste',\n\tCut = 'cut',\n}\n\n/**\n * @internal\n */\nexport interface TypePayload {\n\ttext: string;\n}\n\n/**\n * @internal\n */\nexport interface ReplacePreviousCharPayload {\n\ttext: string;\n\treplaceCharCnt: number;\n}\n\n/**\n * @internal\n */\nexport interface CompositionTypePayload {\n\ttext: string;\n\treplacePrevCharCnt: number;\n\treplaceNextCharCnt: number;\n\tpositionDelta: number;\n}\n\n/**\n * @internal\n */\nexport interface PastePayload {\n\ttext: string;\n\tpasteOnNewLine: boolean;\n\tmulticursorText: string[] | null;\n\tmode: string | null;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { IMouseEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent';\nimport { OverviewRulerPosition, ConfigurationChangedEvent, EditorLayoutInfo, IComputedEditorOptions, EditorOption, FindComputedEditorOptionValueById, IEditorOptions, IDiffEditorOptions } from 'vs/editor/common/config/editorOptions';\nimport { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/cursor/cursorEvents';\nimport { IPosition, Position } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport * as editorCommon from 'vs/editor/common/editorCommon';\nimport { IIdentifiedSingleEditOperation, IModelDecoration, IModelDeltaDecoration, ITextModel, ICursorStateComputer, PositionAffinity } from 'vs/editor/common/model';\nimport { IWordAtPosition } from 'vs/editor/common/core/wordHelper';\nimport { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent } from 'vs/editor/common/textModelEvents';\nimport { OverviewRulerZone } from 'vs/editor/common/viewModel/overviewZoneManager';\nimport { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';\nimport { IViewModel } from 'vs/editor/common/viewModel/viewModel';\nimport { InjectedText } from 'vs/editor/common/viewModel/modelLineProjectionData';\nimport { ILineChange } from 'vs/editor/common/diff/diffComputer';\nimport { IDimension } from 'vs/editor/common/core/dimension';\n\n/**\n * A view zone is a full horizontal rectangle that 'pushes' text down.\n * The editor reserves space for view zones when rendering.\n */\nexport interface IViewZone {\n\t/**\n\t * The line number after which this zone should appear.\n\t * Use 0 to place a view zone before the first line number.\n\t */\n\tafterLineNumber: number;\n\t/**\n\t * The column after which this zone should appear.\n\t * If not set, the maxLineColumn of `afterLineNumber` will be used.\n\t * This is relevant for wrapped lines.\n\t */\n\tafterColumn?: number;\n\n\t/**\n\t * If the `afterColumn` has multiple view columns, the affinity specifies which one to use. Defaults to `none`.\n\t*/\n\tafterColumnAffinity?: PositionAffinity;\n\t/**\n\t * Suppress mouse down events.\n\t * If set, the editor will attach a mouse down listener to the view zone and .preventDefault on it.\n\t * Defaults to false\n\t */\n\tsuppressMouseDown?: boolean;\n\t/**\n\t * The height in lines of the view zone.\n\t * If specified, `heightInPx` will be used instead of this.\n\t * If neither `heightInPx` nor `heightInLines` is specified, a default of `heightInLines` = 1 will be chosen.\n\t */\n\theightInLines?: number;\n\t/**\n\t * The height in px of the view zone.\n\t * If this is set, the editor will give preference to it rather than `heightInLines` above.\n\t * If neither `heightInPx` nor `heightInLines` is specified, a default of `heightInLines` = 1 will be chosen.\n\t */\n\theightInPx?: number;\n\t/**\n\t * The minimum width in px of the view zone.\n\t * If this is set, the editor will ensure that the scroll width is >= than this value.\n\t */\n\tminWidthInPx?: number;\n\t/**\n\t * The dom node of the view zone\n\t */\n\tdomNode: HTMLElement;\n\t/**\n\t * An optional dom node for the view zone that will be placed in the margin area.\n\t */\n\tmarginDomNode?: HTMLElement | null;\n\t/**\n\t * Callback which gives the relative top of the view zone as it appears (taking scrolling into account).\n\t */\n\tonDomNodeTop?: (top: number) => void;\n\t/**\n\t * Callback which gives the height in pixels of the view zone.\n\t */\n\tonComputedHeight?: (height: number) => void;\n}\n/**\n * An accessor that allows for zones to be added or removed.\n */\nexport interface IViewZoneChangeAccessor {\n\t/**\n\t * Create a new view zone.\n\t * @param zone Zone to create\n\t * @return A unique identifier to the view zone.\n\t */\n\taddZone(zone: IViewZone): string;\n\t/**\n\t * Remove a zone\n\t * @param id A unique identifier to the view zone, as returned by the `addZone` call.\n\t */\n\tremoveZone(id: string): void;\n\t/**\n\t * Change a zone's position.\n\t * The editor will rescan the `afterLineNumber` and `afterColumn` properties of a view zone.\n\t */\n\tlayoutZone(id: string): void;\n}\n\n/**\n * A positioning preference for rendering content widgets.\n */\nexport const enum ContentWidgetPositionPreference {\n\t/**\n\t * Place the content widget exactly at a position\n\t */\n\tEXACT,\n\t/**\n\t * Place the content widget above a position\n\t */\n\tABOVE,\n\t/**\n\t * Place the content widget below a position\n\t */\n\tBELOW\n}\n/**\n * A position for rendering content widgets.\n */\nexport interface IContentWidgetPosition {\n\t/**\n\t * Desired position for the content widget.\n\t * `preference` will also affect the placement.\n\t */\n\tposition: IPosition | null;\n\t/**\n\t * Optionally, a range can be provided to further\n\t * define the position of the content widget.\n\t */\n\trange?: IRange | null;\n\t/**\n\t * Placement preference for position, in order of preference.\n\t */\n\tpreference: ContentWidgetPositionPreference[];\n}\n/**\n * A content widget renders inline with the text and can be easily placed 'near' an editor position.\n */\nexport interface IContentWidget {\n\t/**\n\t * Render this content widget in a location where it could overflow the editor's view dom node.\n\t */\n\tallowEditorOverflow?: boolean;\n\t/**\n\t * Call preventDefault() on mousedown events that target the content widget.\n\t */\n\tsuppressMouseDown?: boolean;\n\t/**\n\t * Get a unique identifier of the content widget.\n\t */\n\tgetId(): string;\n\t/**\n\t * Get the dom node of the content widget.\n\t */\n\tgetDomNode(): HTMLElement;\n\t/**\n\t * Get the placement of the content widget.\n\t * If null is returned, the content widget will be placed off screen.\n\t */\n\tgetPosition(): IContentWidgetPosition | null;\n\t/**\n\t * Optional function that is invoked before rendering\n\t * the content widget. If a dimension is returned the editor will\n\t * attempt to use it.\n\t */\n\tbeforeRender?(): IDimension | null;\n\t/**\n\t * Optional function that is invoked after rendering the content\n\t * widget. Is being invoked with the selected position preference\n\t * or `null` if not rendered.\n\t */\n\tafterRender?(position: ContentWidgetPositionPreference | null): void;\n}\n\n/**\n * A positioning preference for rendering overlay widgets.\n */\nexport const enum OverlayWidgetPositionPreference {\n\t/**\n\t * Position the overlay widget in the top right corner\n\t */\n\tTOP_RIGHT_CORNER,\n\n\t/**\n\t * Position the overlay widget in the bottom right corner\n\t */\n\tBOTTOM_RIGHT_CORNER,\n\n\t/**\n\t * Position the overlay widget in the top center\n\t */\n\tTOP_CENTER\n}\n/**\n * A position for rendering overlay widgets.\n */\nexport interface IOverlayWidgetPosition {\n\t/**\n\t * The position preference for the overlay widget.\n\t */\n\tpreference: OverlayWidgetPositionPreference | null;\n}\n/**\n * An overlay widgets renders on top of the text.\n */\nexport interface IOverlayWidget {\n\t/**\n\t * Get a unique identifier of the overlay widget.\n\t */\n\tgetId(): string;\n\t/**\n\t * Get the dom node of the overlay widget.\n\t */\n\tgetDomNode(): HTMLElement;\n\t/**\n\t * Get the placement of the overlay widget.\n\t * If null is returned, the overlay widget is responsible to place itself.\n\t */\n\tgetPosition(): IOverlayWidgetPosition | null;\n}\n\n/**\n * Type of hit element with the mouse in the editor.\n */\nexport const enum MouseTargetType {\n\t/**\n\t * Mouse is on top of an unknown element.\n\t */\n\tUNKNOWN,\n\t/**\n\t * Mouse is on top of the textarea used for input.\n\t */\n\tTEXTAREA,\n\t/**\n\t * Mouse is on top of the glyph margin\n\t */\n\tGUTTER_GLYPH_MARGIN,\n\t/**\n\t * Mouse is on top of the line numbers\n\t */\n\tGUTTER_LINE_NUMBERS,\n\t/**\n\t * Mouse is on top of the line decorations\n\t */\n\tGUTTER_LINE_DECORATIONS,\n\t/**\n\t * Mouse is on top of the whitespace left in the gutter by a view zone.\n\t */\n\tGUTTER_VIEW_ZONE,\n\t/**\n\t * Mouse is on top of text in the content.\n\t */\n\tCONTENT_TEXT,\n\t/**\n\t * Mouse is on top of empty space in the content (e.g. after line text or below last line)\n\t */\n\tCONTENT_EMPTY,\n\t/**\n\t * Mouse is on top of a view zone in the content.\n\t */\n\tCONTENT_VIEW_ZONE,\n\t/**\n\t * Mouse is on top of a content widget.\n\t */\n\tCONTENT_WIDGET,\n\t/**\n\t * Mouse is on top of the decorations overview ruler.\n\t */\n\tOVERVIEW_RULER,\n\t/**\n\t * Mouse is on top of a scrollbar.\n\t */\n\tSCROLLBAR,\n\t/**\n\t * Mouse is on top of an overlay widget.\n\t */\n\tOVERLAY_WIDGET,\n\t/**\n\t * Mouse is outside of the editor.\n\t */\n\tOUTSIDE_EDITOR,\n}\nexport interface IBaseMouseTarget {\n\t/**\n\t * The target element\n\t */\n\treadonly element: Element | null;\n\t/**\n\t * The 'approximate' editor position\n\t */\n\treadonly position: Position | null;\n\t/**\n\t * Desired mouse column (e.g. when position.column gets clamped to text length -- clicking after text on a line).\n\t */\n\treadonly mouseColumn: number;\n\t/**\n\t * The 'approximate' editor range\n\t */\n\treadonly range: Range | null;\n}\nexport interface IMouseTargetUnknown extends IBaseMouseTarget {\n\treadonly type: MouseTargetType.UNKNOWN;\n}\nexport interface IMouseTargetTextarea extends IBaseMouseTarget {\n\treadonly type: MouseTargetType.TEXTAREA;\n\treadonly position: null;\n\treadonly range: null;\n}\nexport interface IMouseTargetMarginData {\n\treadonly isAfterLines: boolean;\n\treadonly glyphMarginLeft: number;\n\treadonly glyphMarginWidth: number;\n\treadonly lineNumbersWidth: number;\n\treadonly offsetX: number;\n}\nexport interface IMouseTargetMargin extends IBaseMouseTarget {\n\treadonly type: MouseTargetType.GUTTER_GLYPH_MARGIN | MouseTargetType.GUTTER_LINE_NUMBERS | MouseTargetType.GUTTER_LINE_DECORATIONS;\n\treadonly position: Position;\n\treadonly range: Range;\n\treadonly detail: IMouseTargetMarginData;\n}\nexport interface IMouseTargetViewZoneData {\n\treadonly viewZoneId: string;\n\treadonly positionBefore: Position | null;\n\treadonly positionAfter: Position | null;\n\treadonly position: Position;\n\treadonly afterLineNumber: number;\n}\nexport interface IMouseTargetViewZone extends IBaseMouseTarget {\n\treadonly type: MouseTargetType.GUTTER_VIEW_ZONE | MouseTargetType.CONTENT_VIEW_ZONE;\n\treadonly position: Position;\n\treadonly range: Range;\n\treadonly detail: IMouseTargetViewZoneData;\n}\nexport interface IMouseTargetContentTextData {\n\treadonly mightBeForeignElement: boolean;\n\t/**\n\t * @internal\n\t */\n\treadonly injectedText: InjectedText | null;\n}\nexport interface IMouseTargetContentText extends IBaseMouseTarget {\n\treadonly type: MouseTargetType.CONTENT_TEXT;\n\treadonly position: Position;\n\treadonly range: Range;\n\treadonly detail: IMouseTargetContentTextData;\n}\nexport interface IMouseTargetContentEmptyData {\n\treadonly isAfterLines: boolean;\n\treadonly horizontalDistanceToText?: number;\n}\nexport interface IMouseTargetContentEmpty extends IBaseMouseTarget {\n\treadonly type: MouseTargetType.CONTENT_EMPTY;\n\treadonly position: Position;\n\treadonly range: Range;\n\treadonly detail: IMouseTargetContentEmptyData;\n}\nexport interface IMouseTargetContentWidget extends IBaseMouseTarget {\n\treadonly type: MouseTargetType.CONTENT_WIDGET;\n\treadonly position: null;\n\treadonly range: null;\n\treadonly detail: string;\n}\nexport interface IMouseTargetOverlayWidget extends IBaseMouseTarget {\n\treadonly type: MouseTargetType.OVERLAY_WIDGET;\n\treadonly position: null;\n\treadonly range: null;\n\treadonly detail: string;\n}\nexport interface IMouseTargetScrollbar extends IBaseMouseTarget {\n\treadonly type: MouseTargetType.SCROLLBAR;\n\treadonly position: Position;\n\treadonly range: Range;\n}\nexport interface IMouseTargetOverviewRuler extends IBaseMouseTarget {\n\treadonly type: MouseTargetType.OVERVIEW_RULER;\n}\nexport interface IMouseTargetOutsideEditor extends IBaseMouseTarget {\n\treadonly type: MouseTargetType.OUTSIDE_EDITOR;\n}\n/**\n * Target hit with the mouse in the editor.\n */\nexport type IMouseTarget = (\n\tIMouseTargetUnknown\n\t| IMouseTargetTextarea\n\t| IMouseTargetMargin\n\t| IMouseTargetViewZone\n\t| IMouseTargetContentText\n\t| IMouseTargetContentEmpty\n\t| IMouseTargetContentWidget\n\t| IMouseTargetOverlayWidget\n\t| IMouseTargetScrollbar\n\t| IMouseTargetOverviewRuler\n\t| IMouseTargetOutsideEditor\n);\n/**\n * A mouse event originating from the editor.\n */\nexport interface IEditorMouseEvent {\n\treadonly event: IMouseEvent;\n\treadonly target: IMouseTarget;\n}\nexport interface IPartialEditorMouseEvent {\n\treadonly event: IMouseEvent;\n\treadonly target: IMouseTarget | null;\n}\n\n/**\n * A paste event originating from the editor.\n */\nexport interface IPasteEvent {\n\treadonly range: Range;\n\treadonly languageId: string | null;\n}\n\n/**\n * An overview ruler\n * @internal\n */\nexport interface IOverviewRuler {\n\tgetDomNode(): HTMLElement;\n\tdispose(): void;\n\tsetZones(zones: OverviewRulerZone[]): void;\n\tsetLayout(position: OverviewRulerPosition): void;\n}\n\n/**\n * Editor aria options.\n * @internal\n */\nexport interface IEditorAriaOptions {\n\tactiveDescendant: string | undefined;\n\trole?: string;\n}\n\nexport interface IDiffEditorConstructionOptions extends IDiffEditorOptions {\n\t/**\n\t * The initial editor dimension (to avoid measuring the container).\n\t */\n\tdimension?: IDimension;\n\n\t/**\n\t * Place overflow widgets inside an external DOM node.\n\t * Defaults to an internal DOM node.\n\t */\n\toverflowWidgetsDomNode?: HTMLElement;\n\n\t/**\n\t * Aria label for original editor.\n\t */\n\toriginalAriaLabel?: string;\n\n\t/**\n\t * Aria label for modified editor.\n\t */\n\tmodifiedAriaLabel?: string;\n\n\t/**\n\t * Is the diff editor inside another editor\n\t * Defaults to false\n\t */\n\tisInEmbeddedEditor?: boolean;\n}\n\n/**\n * A rich code editor.\n */\nexport interface ICodeEditor extends editorCommon.IEditor {\n\t/**\n\t * This editor is used as an alternative to an box, i.e. as a simple widget.\n\t * @internal\n\t */\n\treadonly isSimpleWidget: boolean;\n\t/**\n\t * An event emitted when the content of the current model has changed.\n\t * @event\n\t */\n\treadonly onDidChangeModelContent: Event;\n\t/**\n\t * An event emitted when the language of the current model has changed.\n\t * @event\n\t */\n\treadonly onDidChangeModelLanguage: Event;\n\t/**\n\t * An event emitted when the language configuration of the current model has changed.\n\t * @event\n\t */\n\treadonly onDidChangeModelLanguageConfiguration: Event;\n\t/**\n\t * An event emitted when the options of the current model has changed.\n\t * @event\n\t */\n\treadonly onDidChangeModelOptions: Event;\n\t/**\n\t * An event emitted when the configuration of the editor has changed. (e.g. `editor.updateOptions()`)\n\t * @event\n\t */\n\treadonly onDidChangeConfiguration: Event;\n\t/**\n\t * An event emitted when the cursor position has changed.\n\t * @event\n\t */\n\treadonly onDidChangeCursorPosition: Event;\n\t/**\n\t * An event emitted when the cursor selection has changed.\n\t * @event\n\t */\n\treadonly onDidChangeCursorSelection: Event;\n\t/**\n\t * An event emitted when the model of this editor has changed (e.g. `editor.setModel()`).\n\t * @event\n\t */\n\treadonly onDidChangeModel: Event;\n\t/**\n\t * An event emitted when the decorations of the current model have changed.\n\t * @event\n\t */\n\treadonly onDidChangeModelDecorations: Event;\n\t/**\n\t * An event emitted when the text inside this editor gained focus (i.e. cursor starts blinking).\n\t * @event\n\t */\n\treadonly onDidFocusEditorText: Event;\n\t/**\n\t * An event emitted when the text inside this editor lost focus (i.e. cursor stops blinking).\n\t * @event\n\t */\n\treadonly onDidBlurEditorText: Event;\n\t/**\n\t * An event emitted when the text inside this editor or an editor widget gained focus.\n\t * @event\n\t */\n\treadonly onDidFocusEditorWidget: Event;\n\t/**\n\t * An event emitted when the text inside this editor or an editor widget lost focus.\n\t * @event\n\t */\n\treadonly onDidBlurEditorWidget: Event;\n\t/**\n\t * An event emitted before interpreting typed characters (on the keyboard).\n\t * @event\n\t * @internal\n\t */\n\treadonly onWillType: Event;\n\t/**\n\t * An event emitted after interpreting typed characters (on the keyboard).\n\t * @event\n\t * @internal\n\t */\n\treadonly onDidType: Event;\n\t/**\n\t * An event emitted after composition has started.\n\t */\n\treadonly onDidCompositionStart: Event;\n\t/**\n\t * An event emitted after composition has ended.\n\t */\n\treadonly onDidCompositionEnd: Event;\n\t/**\n\t * An event emitted when editing failed because the editor is read-only.\n\t * @event\n\t */\n\treadonly onDidAttemptReadOnlyEdit: Event;\n\t/**\n\t * An event emitted when users paste text in the editor.\n\t * @event\n\t */\n\treadonly onDidPaste: Event;\n\t/**\n\t * An event emitted on a \"mouseup\".\n\t * @event\n\t */\n\treadonly onMouseUp: Event;\n\t/**\n\t * An event emitted on a \"mousedown\".\n\t * @event\n\t */\n\treadonly onMouseDown: Event;\n\t/**\n\t * An event emitted on a \"mousedrag\".\n\t * @internal\n\t * @event\n\t */\n\treadonly onMouseDrag: Event;\n\t/**\n\t * An event emitted on a \"mousedrop\".\n\t * @internal\n\t * @event\n\t */\n\treadonly onMouseDrop: Event;\n\t/**\n\t * An event emitted on a \"mousedropcanceled\".\n\t * @internal\n\t * @event\n\t */\n\treadonly onMouseDropCanceled: Event;\n\t/**\n\t * An event emitted on a \"contextmenu\".\n\t * @event\n\t */\n\treadonly onContextMenu: Event;\n\t/**\n\t * An event emitted on a \"mousemove\".\n\t * @event\n\t */\n\treadonly onMouseMove: Event;\n\t/**\n\t * An event emitted on a \"mouseleave\".\n\t * @event\n\t */\n\treadonly onMouseLeave: Event;\n\t/**\n\t * An event emitted on a \"mousewheel\"\n\t * @event\n\t * @internal\n\t */\n\treadonly onMouseWheel: Event;\n\t/**\n\t * An event emitted on a \"keyup\".\n\t * @event\n\t */\n\treadonly onKeyUp: Event;\n\t/**\n\t * An event emitted on a \"keydown\".\n\t * @event\n\t */\n\treadonly onKeyDown: Event;\n\t/**\n\t * An event emitted when the layout of the editor has changed.\n\t * @event\n\t */\n\treadonly onDidLayoutChange: Event;\n\t/**\n\t * An event emitted when the content width or content height in the editor has changed.\n\t * @event\n\t */\n\treadonly onDidContentSizeChange: Event;\n\t/**\n\t * An event emitted when the scroll in the editor has changed.\n\t * @event\n\t */\n\treadonly onDidScrollChange: Event;\n\n\t/**\n\t * An event emitted when hidden areas change in the editor (e.g. due to folding).\n\t * @event\n\t */\n\treadonly onDidChangeHiddenAreas: Event;\n\n\t/**\n\t * Saves current view state of the editor in a serializable object.\n\t */\n\tsaveViewState(): editorCommon.ICodeEditorViewState | null;\n\n\t/**\n\t * Restores the view state of the editor from a serializable object generated by `saveViewState`.\n\t */\n\trestoreViewState(state: editorCommon.ICodeEditorViewState): void;\n\n\t/**\n\t * Returns true if the text inside this editor or an editor widget has focus.\n\t */\n\thasWidgetFocus(): boolean;\n\n\t/**\n\t * Get a contribution of this editor.\n\t * @id Unique identifier of the contribution.\n\t * @return The contribution or null if contribution not found.\n\t */\n\tgetContribution(id: string): T | null;\n\n\t/**\n\t * Execute `fn` with the editor's services.\n\t * @internal\n\t */\n\tinvokeWithinContext(fn: (accessor: ServicesAccessor) => T): T;\n\n\t/**\n\t * Type the getModel() of IEditor.\n\t */\n\tgetModel(): ITextModel | null;\n\n\t/**\n\t * Sets the current model attached to this editor.\n\t * If the previous model was created by the editor via the value key in the options\n\t * literal object, it will be destroyed. Otherwise, if the previous model was set\n\t * via setModel, or the model key in the options literal object, the previous model\n\t * will not be destroyed.\n\t * It is safe to call setModel(null) to simply detach the current model from the editor.\n\t */\n\tsetModel(model: ITextModel | null): void;\n\n\t/**\n\t * Gets all the editor computed options.\n\t */\n\tgetOptions(): IComputedEditorOptions;\n\n\t/**\n\t * Gets a specific editor option.\n\t */\n\tgetOption(id: T): FindComputedEditorOptionValueById;\n\n\t/**\n\t * Returns the editor's configuration (without any validation or defaults).\n\t */\n\tgetRawOptions(): IEditorOptions;\n\n\t/**\n\t * @internal\n\t */\n\tgetOverflowWidgetsDomNode(): HTMLElement | undefined;\n\n\t/**\n\t * @internal\n\t */\n\tgetConfiguredWordAtPosition(position: Position): IWordAtPosition | null;\n\n\t/**\n\t * Get value of the current model attached to this editor.\n\t * @see {@link ITextModel.getValue}\n\t */\n\tgetValue(options?: { preserveBOM: boolean; lineEnding: string; }): string;\n\n\t/**\n\t * Set the value of the current model attached to this editor.\n\t * @see {@link ITextModel.setValue}\n\t */\n\tsetValue(newValue: string): void;\n\n\t/**\n\t * Get the width of the editor's content.\n\t * This is information that is \"erased\" when computing `scrollWidth = Math.max(contentWidth, width)`\n\t */\n\tgetContentWidth(): number;\n\t/**\n\t * Get the scrollWidth of the editor's viewport.\n\t */\n\tgetScrollWidth(): number;\n\t/**\n\t * Get the scrollLeft of the editor's viewport.\n\t */\n\tgetScrollLeft(): number;\n\n\t/**\n\t * Get the height of the editor's content.\n\t * This is information that is \"erased\" when computing `scrollHeight = Math.max(contentHeight, height)`\n\t */\n\tgetContentHeight(): number;\n\t/**\n\t * Get the scrollHeight of the editor's viewport.\n\t */\n\tgetScrollHeight(): number;\n\t/**\n\t * Get the scrollTop of the editor's viewport.\n\t */\n\tgetScrollTop(): number;\n\n\t/**\n\t * Change the scrollLeft of the editor's viewport.\n\t */\n\tsetScrollLeft(newScrollLeft: number, scrollType?: editorCommon.ScrollType): void;\n\t/**\n\t * Change the scrollTop of the editor's viewport.\n\t */\n\tsetScrollTop(newScrollTop: number, scrollType?: editorCommon.ScrollType): void;\n\t/**\n\t * Change the scroll position of the editor's viewport.\n\t */\n\tsetScrollPosition(position: editorCommon.INewScrollPosition, scrollType?: editorCommon.ScrollType): void;\n\n\t/**\n\t * Get an action that is a contribution to this editor.\n\t * @id Unique identifier of the contribution.\n\t * @return The action or null if action not found.\n\t */\n\tgetAction(id: string): editorCommon.IEditorAction;\n\n\t/**\n\t * Execute a command on the editor.\n\t * The edits will land on the undo-redo stack, but no \"undo stop\" will be pushed.\n\t * @param source The source of the call.\n\t * @param command The command to execute\n\t */\n\texecuteCommand(source: string | null | undefined, command: editorCommon.ICommand): void;\n\n\t/**\n\t * Create an \"undo stop\" in the undo-redo stack.\n\t */\n\tpushUndoStop(): boolean;\n\n\t/**\n\t * Remove the \"undo stop\" in the undo-redo stack.\n\t */\n\tpopUndoStop(): boolean;\n\n\t/**\n\t * Execute edits on the editor.\n\t * The edits will land on the undo-redo stack, but no \"undo stop\" will be pushed.\n\t * @param source The source of the call.\n\t * @param edits The edits to execute.\n\t * @param endCursorState Cursor state after the edits were applied.\n\t */\n\texecuteEdits(source: string | null | undefined, edits: IIdentifiedSingleEditOperation[], endCursorState?: ICursorStateComputer | Selection[]): boolean;\n\n\t/**\n\t * Execute multiple (concomitant) commands on the editor.\n\t * @param source The source of the call.\n\t * @param command The commands to execute\n\t */\n\texecuteCommands(source: string | null | undefined, commands: (editorCommon.ICommand | null)[]): void;\n\n\t/**\n\t * @internal\n\t */\n\t_getViewModel(): IViewModel | null;\n\n\t/**\n\t * Get all the decorations on a line (filtering out decorations from other editors).\n\t */\n\tgetLineDecorations(lineNumber: number): IModelDecoration[] | null;\n\n\t/**\n\t * Get all the decorations for a range (filtering out decorations from other editors).\n\t */\n\tgetDecorationsInRange(range: Range): IModelDecoration[] | null;\n\n\t/**\n\t * All decorations added through this call will get the ownerId of this editor.\n\t * @see {@link ITextModel.deltaDecorations}\n\t */\n\tdeltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[];\n\n\t/**\n\t * @internal\n\t */\n\tremoveDecorations(decorationTypeKey: string): void;\n\n\t/**\n\t * Get the layout info for the editor.\n\t */\n\tgetLayoutInfo(): EditorLayoutInfo;\n\n\t/**\n\t * Returns the ranges that are currently visible.\n\t * Does not account for horizontal scrolling.\n\t */\n\tgetVisibleRanges(): Range[];\n\n\t/**\n\t * @internal\n\t */\n\tgetVisibleRangesPlusViewportAboveBelow(): Range[];\n\n\t/**\n\t * Get the vertical position (top offset) for the line w.r.t. to the first line.\n\t */\n\tgetTopForLineNumber(lineNumber: number): number;\n\n\t/**\n\t * Get the vertical position (top offset) for the position w.r.t. to the first line.\n\t */\n\tgetTopForPosition(lineNumber: number, column: number): number;\n\n\t/**\n\t * Set the model ranges that will be hidden in the view.\n\t * @internal\n\t */\n\tsetHiddenAreas(ranges: IRange[]): void;\n\n\t/**\n\t * Sets the editor aria options, primarily the active descendent.\n\t * @internal\n\t */\n\tsetAriaOptions(options: IEditorAriaOptions): void;\n\n\t/**\n\t * Returns the editor's container dom node\n\t */\n\tgetContainerDomNode(): HTMLElement;\n\n\t/**\n\t * Returns the editor's dom node\n\t */\n\tgetDomNode(): HTMLElement | null;\n\n\t/**\n\t * Add a content widget. Widgets must have unique ids, otherwise they will be overwritten.\n\t */\n\taddContentWidget(widget: IContentWidget): void;\n\t/**\n\t * Layout/Reposition a content widget. This is a ping to the editor to call widget.getPosition()\n\t * and update appropriately.\n\t */\n\tlayoutContentWidget(widget: IContentWidget): void;\n\t/**\n\t * Remove a content widget.\n\t */\n\tremoveContentWidget(widget: IContentWidget): void;\n\n\t/**\n\t * Add an overlay widget. Widgets must have unique ids, otherwise they will be overwritten.\n\t */\n\taddOverlayWidget(widget: IOverlayWidget): void;\n\t/**\n\t * Layout/Reposition an overlay widget. This is a ping to the editor to call widget.getPosition()\n\t * and update appropriately.\n\t */\n\tlayoutOverlayWidget(widget: IOverlayWidget): void;\n\t/**\n\t * Remove an overlay widget.\n\t */\n\tremoveOverlayWidget(widget: IOverlayWidget): void;\n\n\t/**\n\t * Change the view zones. View zones are lost when a new model is attached to the editor.\n\t */\n\tchangeViewZones(callback: (accessor: IViewZoneChangeAccessor) => void): void;\n\n\t/**\n\t * Get the horizontal position (left offset) for the column w.r.t to the beginning of the line.\n\t * This method works only if the line `lineNumber` is currently rendered (in the editor's viewport).\n\t * Use this method with caution.\n\t */\n\tgetOffsetForColumn(lineNumber: number, column: number): number;\n\n\t/**\n\t * Force an editor render now.\n\t */\n\trender(forceRedraw?: boolean): void;\n\n\t/**\n\t * Get the hit test target at coordinates `clientX` and `clientY`.\n\t * The coordinates are relative to the top-left of the viewport.\n\t *\n\t * @returns Hit test target or null if the coordinates fall outside the editor or the editor has no model.\n\t */\n\tgetTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget | null;\n\n\t/**\n\t * Get the visible position for `position`.\n\t * The result position takes scrolling into account and is relative to the top left corner of the editor.\n\t * Explanation 1: the results of this method will change for the same `position` if the user scrolls the editor.\n\t * Explanation 2: the results of this method will not change if the container of the editor gets repositioned.\n\t * Warning: the results of this method are inaccurate for positions that are outside the current editor viewport.\n\t */\n\tgetScrolledVisiblePosition(position: IPosition): { top: number; left: number; height: number; } | null;\n\n\t/**\n\t * Apply the same font settings as the editor to `target`.\n\t */\n\tapplyFontInfo(target: HTMLElement): void;\n\n\t/**\n\t * Check if the current instance has a model attached.\n\t * @internal\n\t */\n\thasModel(): this is IActiveCodeEditor;\n\n\tsetBanner(bannerDomNode: HTMLElement | null, height: number): void;\n}\n\n/**\n * @internal\n */\nexport interface IActiveCodeEditor extends ICodeEditor {\n\t/**\n\t * Returns the primary position of the cursor.\n\t */\n\tgetPosition(): Position;\n\n\t/**\n\t * Returns the primary selection of the editor.\n\t */\n\tgetSelection(): Selection;\n\n\t/**\n\t * Returns all the selections of the editor.\n\t */\n\tgetSelections(): Selection[];\n\n\t/**\n\t * Type the getModel() of IEditor.\n\t */\n\tgetModel(): ITextModel;\n\n\t/**\n\t * @internal\n\t */\n\t_getViewModel(): IViewModel;\n\n\t/**\n\t * Get all the decorations on a line (filtering out decorations from other editors).\n\t */\n\tgetLineDecorations(lineNumber: number): IModelDecoration[];\n\n\t/**\n\t * Returns the editor's dom node\n\t */\n\tgetDomNode(): HTMLElement;\n\n\t/**\n\t * Get the visible position for `position`.\n\t * The result position takes scrolling into account and is relative to the top left corner of the editor.\n\t * Explanation 1: the results of this method will change for the same `position` if the user scrolls the editor.\n\t * Explanation 2: the results of this method will not change if the container of the editor gets repositioned.\n\t * Warning: the results of this method are inaccurate for positions that are outside the current editor viewport.\n\t */\n\tgetScrolledVisiblePosition(position: IPosition): { top: number; left: number; height: number; };\n}\n\n/**\n * Information about a line in the diff editor\n */\nexport interface IDiffLineInformation {\n\treadonly equivalentLineNumber: number;\n}\n\n/**\n * @internal\n */\nexport const enum DiffEditorState {\n\tIdle,\n\tComputingDiff,\n\tDiffComputed\n}\n\n/**\n * A rich diff editor.\n */\nexport interface IDiffEditor extends editorCommon.IEditor {\n\n\t/**\n\t * @see {@link ICodeEditor.getContainerDomNode}\n\t */\n\tgetContainerDomNode(): HTMLElement;\n\n\t/**\n\t * An event emitted when the diff information computed by this diff editor has been updated.\n\t * @event\n\t */\n\treadonly onDidUpdateDiff: Event;\n\n\t/**\n\t * Saves current view state of the editor in a serializable object.\n\t */\n\tsaveViewState(): editorCommon.IDiffEditorViewState | null;\n\n\t/**\n\t * Restores the view state of the editor from a serializable object generated by `saveViewState`.\n\t */\n\trestoreViewState(state: editorCommon.IDiffEditorViewState): void;\n\n\t/**\n\t * Type the getModel() of IEditor.\n\t */\n\tgetModel(): editorCommon.IDiffEditorModel | null;\n\n\t/**\n\t * Sets the current model attached to this editor.\n\t * If the previous model was created by the editor via the value key in the options\n\t * literal object, it will be destroyed. Otherwise, if the previous model was set\n\t * via setModel, or the model key in the options literal object, the previous model\n\t * will not be destroyed.\n\t * It is safe to call setModel(null) to simply detach the current model from the editor.\n\t */\n\tsetModel(model: editorCommon.IDiffEditorModel | null): void;\n\n\t/**\n\t * Get the `original` editor.\n\t */\n\tgetOriginalEditor(): ICodeEditor;\n\n\t/**\n\t * Get the `modified` editor.\n\t */\n\tgetModifiedEditor(): ICodeEditor;\n\n\t/**\n\t * Get the computed diff information.\n\t */\n\tgetLineChanges(): ILineChange[] | null;\n\n\t/**\n\t * Get information based on computed diff about a line number from the original model.\n\t * If the diff computation is not finished or the model is missing, will return null.\n\t */\n\tgetDiffLineInformationForOriginal(lineNumber: number): IDiffLineInformation | null;\n\n\t/**\n\t * Get information based on computed diff about a line number from the modified model.\n\t * If the diff computation is not finished or the model is missing, will return null.\n\t */\n\tgetDiffLineInformationForModified(lineNumber: number): IDiffLineInformation | null;\n\n\t/**\n\t * Update the editor's options after the editor has been created.\n\t */\n\tupdateOptions(newOptions: IDiffEditorOptions): void;\n}\n\n/**\n *@internal\n */\nexport function isCodeEditor(thing: unknown): thing is ICodeEditor {\n\tif (thing && typeof (thing).getEditorType === 'function') {\n\t\treturn (thing).getEditorType() === editorCommon.EditorType.ICodeEditor;\n\t} else {\n\t\treturn false;\n\t}\n}\n\n/**\n *@internal\n */\nexport function isDiffEditor(thing: unknown): thing is IDiffEditor {\n\tif (thing && typeof (thing).getEditorType === 'function') {\n\t\treturn (thing).getEditorType() === editorCommon.EditorType.IDiffEditor;\n\t} else {\n\t\treturn false;\n\t}\n}\n\n/**\n *@internal\n */\nexport function getCodeEditor(thing: unknown): ICodeEditor | null {\n\tif (isCodeEditor(thing)) {\n\t\treturn thing;\n\t}\n\n\tif (isDiffEditor(thing)) {\n\t\treturn thing.getModifiedEditor();\n\t}\n\n\treturn null;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IRelativePattern, match as matchGlobPattern } from 'vs/base/common/glob';\nimport { URI } from 'vs/base/common/uri';\nimport { normalize } from 'vs/base/common/path';\n\nexport interface LanguageFilter {\n\treadonly language?: string;\n\treadonly scheme?: string;\n\treadonly pattern?: string | IRelativePattern;\n\t/**\n\t * This provider is implemented in the UI thread.\n\t */\n\treadonly hasAccessToAllModels?: boolean;\n\treadonly exclusive?: boolean;\n}\n\nexport type LanguageSelector = string | LanguageFilter | ReadonlyArray;\n\nexport function score(selector: LanguageSelector | undefined, candidateUri: URI, candidateLanguage: string, candidateIsSynchronized: boolean): number {\n\n\tif (Array.isArray(selector)) {\n\t\t// array -> take max individual value\n\t\tlet ret = 0;\n\t\tfor (const filter of selector) {\n\t\t\tconst value = score(filter, candidateUri, candidateLanguage, candidateIsSynchronized);\n\t\t\tif (value === 10) {\n\t\t\t\treturn value; // already at the highest\n\t\t\t}\n\t\t\tif (value > ret) {\n\t\t\t\tret = value;\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\n\t} else if (typeof selector === 'string') {\n\n\t\tif (!candidateIsSynchronized) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t// short-hand notion, desugars to\n\t\t// 'fooLang' -> { language: 'fooLang'}\n\t\t// '*' -> { language: '*' }\n\t\tif (selector === '*') {\n\t\t\treturn 5;\n\t\t} else if (selector === candidateLanguage) {\n\t\t\treturn 10;\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\n\t} else if (selector) {\n\t\t// filter -> select accordingly, use defaults for scheme\n\t\tconst { language, pattern, scheme, hasAccessToAllModels } = selector as LanguageFilter; // TODO: microsoft/TypeScript#42768\n\n\t\tif (!candidateIsSynchronized && !hasAccessToAllModels) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tlet ret = 0;\n\n\t\tif (scheme) {\n\t\t\tif (scheme === candidateUri.scheme) {\n\t\t\t\tret = 10;\n\t\t\t} else if (scheme === '*') {\n\t\t\t\tret = 5;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\n\t\tif (language) {\n\t\t\tif (language === candidateLanguage) {\n\t\t\t\tret = 10;\n\t\t\t} else if (language === '*') {\n\t\t\t\tret = Math.max(ret, 5);\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\n\t\tif (pattern) {\n\t\t\tlet normalizedPattern: string | IRelativePattern;\n\t\t\tif (typeof pattern === 'string') {\n\t\t\t\tnormalizedPattern = pattern;\n\t\t\t} else {\n\t\t\t\t// Since this pattern has a `base` property, we need\n\t\t\t\t// to normalize this path first before passing it on\n\t\t\t\t// because we will compare it against `Uri.fsPath`\n\t\t\t\t// which uses platform specific separators.\n\t\t\t\t// Refs: https://github.com/microsoft/vscode/issues/99938\n\t\t\t\tnormalizedPattern = { ...pattern, base: normalize(pattern.base) };\n\t\t\t}\n\n\t\t\tif (normalizedPattern === candidateUri.fsPath || matchGlobPattern(normalizedPattern, candidateUri.fsPath)) {\n\t\t\t\tret = 10;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\n\t} else {\n\t\treturn 0;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { StandardTokenType } from 'vs/editor/common/languages';\nimport { ScopedLineTokens } from 'vs/editor/common/languages/supports';\n\n/**\n * Describes how comments for a language work.\n */\nexport interface CommentRule {\n\t/**\n\t * The line comment token, like `// this is a comment`\n\t */\n\tlineComment?: string | null;\n\t/**\n\t * The block comment character pair, like `/* block comment */`\n\t */\n\tblockComment?: CharacterPair | null;\n}\n\n/**\n * The language configuration interface defines the contract between extensions and\n * various editor features, like automatic bracket insertion, automatic indentation etc.\n */\nexport interface LanguageConfiguration {\n\t/**\n\t * The language's comment settings.\n\t */\n\tcomments?: CommentRule;\n\t/**\n\t * The language's brackets.\n\t * This configuration implicitly affects pressing Enter around these brackets.\n\t */\n\tbrackets?: CharacterPair[];\n\t/**\n\t * The language's word definition.\n\t * If the language supports Unicode identifiers (e.g. JavaScript), it is preferable\n\t * to provide a word definition that uses exclusion of known separators.\n\t * e.g.: A regex that matches anything except known separators (and dot is allowed to occur in a floating point number):\n\t * /(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)/g\n\t */\n\twordPattern?: RegExp;\n\t/**\n\t * The language's indentation settings.\n\t */\n\tindentationRules?: IndentationRule;\n\t/**\n\t * The language's rules to be evaluated when pressing Enter.\n\t */\n\tonEnterRules?: OnEnterRule[];\n\t/**\n\t * The language's auto closing pairs. The 'close' character is automatically inserted with the\n\t * 'open' character is typed. If not set, the configured brackets will be used.\n\t */\n\tautoClosingPairs?: IAutoClosingPairConditional[];\n\t/**\n\t * The language's surrounding pairs. When the 'open' character is typed on a selection, the\n\t * selected string is surrounded by the open and close characters. If not set, the autoclosing pairs\n\t * settings will be used.\n\t */\n\tsurroundingPairs?: IAutoClosingPair[];\n\t/**\n\t * Defines a list of bracket pairs that are colorized depending on their nesting level.\n\t * If not set, the configured brackets will be used.\n\t*/\n\tcolorizedBracketPairs?: CharacterPair[];\n\t/**\n\t * Defines what characters must be after the cursor for bracket or quote autoclosing to occur when using the \\'languageDefined\\' autoclosing setting.\n\t *\n\t * This is typically the set of characters which can not start an expression, such as whitespace, closing brackets, non-unary operators, etc.\n\t */\n\tautoCloseBefore?: string;\n\n\t/**\n\t * The language's folding rules.\n\t */\n\tfolding?: FoldingRules;\n\n\t/**\n\t * **Deprecated** Do not use.\n\t *\n\t * @deprecated Will be replaced by a better API soon.\n\t */\n\t__electricCharacterSupport?: {\n\t\tdocComment?: IDocComment;\n\t};\n}\n\n/**\n * @internal\n */\ntype OrUndefined = { [P in keyof T]: T[P] | undefined };\n\n/**\n * @internal\n */\nexport type ExplicitLanguageConfiguration = OrUndefined>;\n\n/**\n * Describes indentation rules for a language.\n */\nexport interface IndentationRule {\n\t/**\n\t * If a line matches this pattern, then all the lines after it should be unindented once (until another rule matches).\n\t */\n\tdecreaseIndentPattern: RegExp;\n\t/**\n\t * If a line matches this pattern, then all the lines after it should be indented once (until another rule matches).\n\t */\n\tincreaseIndentPattern: RegExp;\n\t/**\n\t * If a line matches this pattern, then **only the next line** after it should be indented once.\n\t */\n\tindentNextLinePattern?: RegExp | null;\n\t/**\n\t * If a line matches this pattern, then its indentation should not be changed and it should not be evaluated against the other rules.\n\t */\n\tunIndentedLinePattern?: RegExp | null;\n\n}\n\n/**\n * Describes language specific folding markers such as '#region' and '#endregion'.\n * The start and end regexes will be tested against the contents of all lines and must be designed efficiently:\n * - the regex should start with '^'\n * - regexp flags (i, g) are ignored\n */\nexport interface FoldingMarkers {\n\tstart: RegExp;\n\tend: RegExp;\n}\n\n/**\n * Describes folding rules for a language.\n */\nexport interface FoldingRules {\n\t/**\n\t * Used by the indentation based strategy to decide whether empty lines belong to the previous or the next block.\n\t * A language adheres to the off-side rule if blocks in that language are expressed by their indentation.\n\t * See [wikipedia](https://en.wikipedia.org/wiki/Off-side_rule) for more information.\n\t * If not set, `false` is used and empty lines belong to the previous block.\n\t */\n\toffSide?: boolean;\n\n\t/**\n\t * Region markers used by the language.\n\t */\n\tmarkers?: FoldingMarkers;\n}\n\n/**\n * Describes a rule to be evaluated when pressing Enter.\n */\nexport interface OnEnterRule {\n\t/**\n\t * This rule will only execute if the text before the cursor matches this regular expression.\n\t */\n\tbeforeText: RegExp;\n\t/**\n\t * This rule will only execute if the text after the cursor matches this regular expression.\n\t */\n\tafterText?: RegExp;\n\t/**\n\t * This rule will only execute if the text above the this line matches this regular expression.\n\t */\n\tpreviousLineText?: RegExp;\n\t/**\n\t * The action to execute.\n\t */\n\taction: EnterAction;\n}\n\n/**\n * Definition of documentation comments (e.g. Javadoc/JSdoc)\n */\nexport interface IDocComment {\n\t/**\n\t * The string that starts a doc comment (e.g. '/**')\n\t */\n\topen: string;\n\t/**\n\t * The string that appears on the last line and closes the doc comment (e.g. ' * /').\n\t */\n\tclose?: string;\n}\n\n/**\n * A tuple of two characters, like a pair of\n * opening and closing brackets.\n */\nexport type CharacterPair = [string, string];\n\nexport interface IAutoClosingPair {\n\topen: string;\n\tclose: string;\n}\n\nexport interface IAutoClosingPairConditional extends IAutoClosingPair {\n\tnotIn?: string[];\n}\n\n/**\n * Describes what to do with the indentation when pressing Enter.\n */\nexport enum IndentAction {\n\t/**\n\t * Insert new line and copy the previous line's indentation.\n\t */\n\tNone = 0,\n\t/**\n\t * Insert new line and indent once (relative to the previous line's indentation).\n\t */\n\tIndent = 1,\n\t/**\n\t * Insert two new lines:\n\t * - the first one indented which will hold the cursor\n\t * - the second one at the same indentation level\n\t */\n\tIndentOutdent = 2,\n\t/**\n\t * Insert new line and outdent once (relative to the previous line's indentation).\n\t */\n\tOutdent = 3\n}\n\n/**\n * Describes what to do when pressing Enter.\n */\nexport interface EnterAction {\n\t/**\n\t * Describe what to do with the indentation.\n\t */\n\tindentAction: IndentAction;\n\t/**\n\t * Describes text to be appended after the new line and after the indentation.\n\t */\n\tappendText?: string;\n\t/**\n\t * Describes the number of characters to remove from the new line's indentation.\n\t */\n\tremoveText?: number;\n}\n\n/**\n * @internal\n */\nexport interface CompleteEnterAction {\n\t/**\n\t * Describe what to do with the indentation.\n\t */\n\tindentAction: IndentAction;\n\t/**\n\t * Describes text to be appended after the new line and after the indentation.\n\t */\n\tappendText: string;\n\t/**\n\t * Describes the number of characters to remove from the new line's indentation.\n\t */\n\tremoveText: number;\n\t/**\n\t * The line's indentation minus removeText\n\t */\n\tindentation: string;\n}\n\n/**\n * @internal\n */\nexport class StandardAutoClosingPairConditional {\n\n\treadonly open: string;\n\treadonly close: string;\n\tprivate readonly _inString: boolean;\n\tprivate readonly _inComment: boolean;\n\tprivate readonly _inRegEx: boolean;\n\tprivate _neutralCharacter: string | null = null;\n\tprivate _neutralCharacterSearched: boolean = false;\n\n\tconstructor(source: IAutoClosingPairConditional) {\n\t\tthis.open = source.open;\n\t\tthis.close = source.close;\n\n\t\t// initially allowed in all tokens\n\t\tthis._inString = true;\n\t\tthis._inComment = true;\n\t\tthis._inRegEx = true;\n\n\t\tif (Array.isArray(source.notIn)) {\n\t\t\tfor (let i = 0, len = source.notIn.length; i < len; i++) {\n\t\t\t\tconst notIn: string = source.notIn[i];\n\t\t\t\tswitch (notIn) {\n\t\t\t\t\tcase 'string':\n\t\t\t\t\t\tthis._inString = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'comment':\n\t\t\t\t\t\tthis._inComment = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'regex':\n\t\t\t\t\t\tthis._inRegEx = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic isOK(standardToken: StandardTokenType): boolean {\n\t\tswitch (standardToken) {\n\t\t\tcase StandardTokenType.Other:\n\t\t\t\treturn true;\n\t\t\tcase StandardTokenType.Comment:\n\t\t\t\treturn this._inComment;\n\t\t\tcase StandardTokenType.String:\n\t\t\t\treturn this._inString;\n\t\t\tcase StandardTokenType.RegEx:\n\t\t\t\treturn this._inRegEx;\n\t\t}\n\t}\n\n\tpublic shouldAutoClose(context: ScopedLineTokens, column: number): boolean {\n\t\t// Always complete on empty line\n\t\tif (context.getTokenCount() === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst tokenIndex = context.findTokenIndexAtOffset(column - 2);\n\t\tconst standardTokenType = context.getStandardTokenType(tokenIndex);\n\t\treturn this.isOK(standardTokenType);\n\t}\n\n\tprivate _findNeutralCharacterInRange(fromCharCode: number, toCharCode: number): string | null {\n\t\tfor (let charCode = fromCharCode; charCode <= toCharCode; charCode++) {\n\t\t\tconst character = String.fromCharCode(charCode);\n\t\t\tif (!this.open.includes(character) && !this.close.includes(character)) {\n\t\t\t\treturn character;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Find a character in the range [0-9a-zA-Z] that does not appear in the open or close\n\t */\n\tpublic findNeutralCharacter(): string | null {\n\t\tif (!this._neutralCharacterSearched) {\n\t\t\tthis._neutralCharacterSearched = true;\n\t\t\tif (!this._neutralCharacter) {\n\t\t\t\tthis._neutralCharacter = this._findNeutralCharacterInRange(CharCode.Digit0, CharCode.Digit9);\n\t\t\t}\n\t\t\tif (!this._neutralCharacter) {\n\t\t\t\tthis._neutralCharacter = this._findNeutralCharacterInRange(CharCode.a, CharCode.z);\n\t\t\t}\n\t\t\tif (!this._neutralCharacter) {\n\t\t\t\tthis._neutralCharacter = this._findNeutralCharacterInRange(CharCode.A, CharCode.Z);\n\t\t\t}\n\t\t}\n\t\treturn this._neutralCharacter;\n\t}\n}\n\n/**\n * @internal\n */\nexport class AutoClosingPairs {\n\t// it is useful to be able to get pairs using either end of open and close\n\n\t/** Key is first character of open */\n\tpublic readonly autoClosingPairsOpenByStart: Map;\n\t/** Key is last character of open */\n\tpublic readonly autoClosingPairsOpenByEnd: Map;\n\t/** Key is first character of close */\n\tpublic readonly autoClosingPairsCloseByStart: Map;\n\t/** Key is last character of close */\n\tpublic readonly autoClosingPairsCloseByEnd: Map;\n\t/** Key is close. Only has pairs that are a single character */\n\tpublic readonly autoClosingPairsCloseSingleChar: Map;\n\n\tconstructor(autoClosingPairs: StandardAutoClosingPairConditional[]) {\n\t\tthis.autoClosingPairsOpenByStart = new Map();\n\t\tthis.autoClosingPairsOpenByEnd = new Map();\n\t\tthis.autoClosingPairsCloseByStart = new Map();\n\t\tthis.autoClosingPairsCloseByEnd = new Map();\n\t\tthis.autoClosingPairsCloseSingleChar = new Map();\n\t\tfor (const pair of autoClosingPairs) {\n\t\t\tappendEntry(this.autoClosingPairsOpenByStart, pair.open.charAt(0), pair);\n\t\t\tappendEntry(this.autoClosingPairsOpenByEnd, pair.open.charAt(pair.open.length - 1), pair);\n\t\t\tappendEntry(this.autoClosingPairsCloseByStart, pair.close.charAt(0), pair);\n\t\t\tappendEntry(this.autoClosingPairsCloseByEnd, pair.close.charAt(pair.close.length - 1), pair);\n\t\t\tif (pair.close.length === 1 && pair.open.length === 1) {\n\t\t\t\tappendEntry(this.autoClosingPairsCloseSingleChar, pair.close, pair);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction appendEntry(target: Map, key: K, value: V): void {\n\tif (target.has(key)) {\n\t\ttarget.get(key)!.push(value);\n\t} else {\n\t\ttarget.set(key, [value]);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { CharacterClassifier } from 'vs/editor/common/core/characterClassifier';\nimport { ILink } from 'vs/editor/common/languages';\n\nexport interface ILinkComputerTarget {\n\tgetLineCount(): number;\n\tgetLineContent(lineNumber: number): string;\n}\n\nexport const enum State {\n\tInvalid = 0,\n\tStart = 1,\n\tH = 2,\n\tHT = 3,\n\tHTT = 4,\n\tHTTP = 5,\n\tF = 6,\n\tFI = 7,\n\tFIL = 8,\n\tBeforeColon = 9,\n\tAfterColon = 10,\n\tAlmostThere = 11,\n\tEnd = 12,\n\tAccept = 13,\n\tLastKnownState = 14 // marker, custom states may follow\n}\n\nexport type Edge = [State, number, State];\n\nexport class Uint8Matrix {\n\n\tprivate readonly _data: Uint8Array;\n\tpublic readonly rows: number;\n\tpublic readonly cols: number;\n\n\tconstructor(rows: number, cols: number, defaultValue: number) {\n\t\tconst data = new Uint8Array(rows * cols);\n\t\tfor (let i = 0, len = rows * cols; i < len; i++) {\n\t\t\tdata[i] = defaultValue;\n\t\t}\n\n\t\tthis._data = data;\n\t\tthis.rows = rows;\n\t\tthis.cols = cols;\n\t}\n\n\tpublic get(row: number, col: number): number {\n\t\treturn this._data[row * this.cols + col];\n\t}\n\n\tpublic set(row: number, col: number, value: number): void {\n\t\tthis._data[row * this.cols + col] = value;\n\t}\n}\n\nexport class StateMachine {\n\n\tprivate readonly _states: Uint8Matrix;\n\tprivate readonly _maxCharCode: number;\n\n\tconstructor(edges: Edge[]) {\n\t\tlet maxCharCode = 0;\n\t\tlet maxState = State.Invalid;\n\t\tfor (let i = 0, len = edges.length; i < len; i++) {\n\t\t\tconst [from, chCode, to] = edges[i];\n\t\t\tif (chCode > maxCharCode) {\n\t\t\t\tmaxCharCode = chCode;\n\t\t\t}\n\t\t\tif (from > maxState) {\n\t\t\t\tmaxState = from;\n\t\t\t}\n\t\t\tif (to > maxState) {\n\t\t\t\tmaxState = to;\n\t\t\t}\n\t\t}\n\n\t\tmaxCharCode++;\n\t\tmaxState++;\n\n\t\tconst states = new Uint8Matrix(maxState, maxCharCode, State.Invalid);\n\t\tfor (let i = 0, len = edges.length; i < len; i++) {\n\t\t\tconst [from, chCode, to] = edges[i];\n\t\t\tstates.set(from, chCode, to);\n\t\t}\n\n\t\tthis._states = states;\n\t\tthis._maxCharCode = maxCharCode;\n\t}\n\n\tpublic nextState(currentState: State, chCode: number): State {\n\t\tif (chCode < 0 || chCode >= this._maxCharCode) {\n\t\t\treturn State.Invalid;\n\t\t}\n\t\treturn this._states.get(currentState, chCode);\n\t}\n}\n\n// State machine for http:// or https:// or file://\nlet _stateMachine: StateMachine | null = null;\nfunction getStateMachine(): StateMachine {\n\tif (_stateMachine === null) {\n\t\t_stateMachine = new StateMachine([\n\t\t\t[State.Start, CharCode.h, State.H],\n\t\t\t[State.Start, CharCode.H, State.H],\n\t\t\t[State.Start, CharCode.f, State.F],\n\t\t\t[State.Start, CharCode.F, State.F],\n\n\t\t\t[State.H, CharCode.t, State.HT],\n\t\t\t[State.H, CharCode.T, State.HT],\n\n\t\t\t[State.HT, CharCode.t, State.HTT],\n\t\t\t[State.HT, CharCode.T, State.HTT],\n\n\t\t\t[State.HTT, CharCode.p, State.HTTP],\n\t\t\t[State.HTT, CharCode.P, State.HTTP],\n\n\t\t\t[State.HTTP, CharCode.s, State.BeforeColon],\n\t\t\t[State.HTTP, CharCode.S, State.BeforeColon],\n\t\t\t[State.HTTP, CharCode.Colon, State.AfterColon],\n\n\t\t\t[State.F, CharCode.i, State.FI],\n\t\t\t[State.F, CharCode.I, State.FI],\n\n\t\t\t[State.FI, CharCode.l, State.FIL],\n\t\t\t[State.FI, CharCode.L, State.FIL],\n\n\t\t\t[State.FIL, CharCode.e, State.BeforeColon],\n\t\t\t[State.FIL, CharCode.E, State.BeforeColon],\n\n\t\t\t[State.BeforeColon, CharCode.Colon, State.AfterColon],\n\n\t\t\t[State.AfterColon, CharCode.Slash, State.AlmostThere],\n\n\t\t\t[State.AlmostThere, CharCode.Slash, State.End],\n\t\t]);\n\t}\n\treturn _stateMachine;\n}\n\n\nconst enum CharacterClass {\n\tNone = 0,\n\tForceTermination = 1,\n\tCannotEndIn = 2\n}\n\nlet _classifier: CharacterClassifier | null = null;\nfunction getClassifier(): CharacterClassifier {\n\tif (_classifier === null) {\n\t\t_classifier = new CharacterClassifier(CharacterClass.None);\n\n\t\t// allow-any-unicode-next-line\n\t\tconst FORCE_TERMINATION_CHARACTERS = ' \\t<>\\'\\\"、。。、,.:;‘〈「『〔([{「」}])〕』」〉’`~…';\n\t\tfor (let i = 0; i < FORCE_TERMINATION_CHARACTERS.length; i++) {\n\t\t\t_classifier.set(FORCE_TERMINATION_CHARACTERS.charCodeAt(i), CharacterClass.ForceTermination);\n\t\t}\n\n\t\tconst CANNOT_END_WITH_CHARACTERS = '.,;';\n\t\tfor (let i = 0; i < CANNOT_END_WITH_CHARACTERS.length; i++) {\n\t\t\t_classifier.set(CANNOT_END_WITH_CHARACTERS.charCodeAt(i), CharacterClass.CannotEndIn);\n\t\t}\n\t}\n\treturn _classifier;\n}\n\nexport class LinkComputer {\n\n\tprivate static _createLink(classifier: CharacterClassifier, line: string, lineNumber: number, linkBeginIndex: number, linkEndIndex: number): ILink {\n\t\t// Do not allow to end link in certain characters...\n\t\tlet lastIncludedCharIndex = linkEndIndex - 1;\n\t\tdo {\n\t\t\tconst chCode = line.charCodeAt(lastIncludedCharIndex);\n\t\t\tconst chClass = classifier.get(chCode);\n\t\t\tif (chClass !== CharacterClass.CannotEndIn) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlastIncludedCharIndex--;\n\t\t} while (lastIncludedCharIndex > linkBeginIndex);\n\n\t\t// Handle links enclosed in parens, square brackets and curlys.\n\t\tif (linkBeginIndex > 0) {\n\t\t\tconst charCodeBeforeLink = line.charCodeAt(linkBeginIndex - 1);\n\t\t\tconst lastCharCodeInLink = line.charCodeAt(lastIncludedCharIndex);\n\n\t\t\tif (\n\t\t\t\t(charCodeBeforeLink === CharCode.OpenParen && lastCharCodeInLink === CharCode.CloseParen)\n\t\t\t\t|| (charCodeBeforeLink === CharCode.OpenSquareBracket && lastCharCodeInLink === CharCode.CloseSquareBracket)\n\t\t\t\t|| (charCodeBeforeLink === CharCode.OpenCurlyBrace && lastCharCodeInLink === CharCode.CloseCurlyBrace)\n\t\t\t) {\n\t\t\t\t// Do not end in ) if ( is before the link start\n\t\t\t\t// Do not end in ] if [ is before the link start\n\t\t\t\t// Do not end in } if { is before the link start\n\t\t\t\tlastIncludedCharIndex--;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\trange: {\n\t\t\t\tstartLineNumber: lineNumber,\n\t\t\t\tstartColumn: linkBeginIndex + 1,\n\t\t\t\tendLineNumber: lineNumber,\n\t\t\t\tendColumn: lastIncludedCharIndex + 2\n\t\t\t},\n\t\t\turl: line.substring(linkBeginIndex, lastIncludedCharIndex + 1)\n\t\t};\n\t}\n\n\tpublic static computeLinks(model: ILinkComputerTarget, stateMachine: StateMachine = getStateMachine()): ILink[] {\n\t\tconst classifier = getClassifier();\n\n\t\tconst result: ILink[] = [];\n\t\tfor (let i = 1, lineCount = model.getLineCount(); i <= lineCount; i++) {\n\t\t\tconst line = model.getLineContent(i);\n\t\t\tconst len = line.length;\n\n\t\t\tlet j = 0;\n\t\t\tlet linkBeginIndex = 0;\n\t\t\tlet linkBeginChCode = 0;\n\t\t\tlet state = State.Start;\n\t\t\tlet hasOpenParens = false;\n\t\t\tlet hasOpenSquareBracket = false;\n\t\t\tlet inSquareBrackets = false;\n\t\t\tlet hasOpenCurlyBracket = false;\n\n\t\t\twhile (j < len) {\n\n\t\t\t\tlet resetStateMachine = false;\n\t\t\t\tconst chCode = line.charCodeAt(j);\n\n\t\t\t\tif (state === State.Accept) {\n\t\t\t\t\tlet chClass: CharacterClass;\n\t\t\t\t\tswitch (chCode) {\n\t\t\t\t\t\tcase CharCode.OpenParen:\n\t\t\t\t\t\t\thasOpenParens = true;\n\t\t\t\t\t\t\tchClass = CharacterClass.None;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CharCode.CloseParen:\n\t\t\t\t\t\t\tchClass = (hasOpenParens ? CharacterClass.None : CharacterClass.ForceTermination);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CharCode.OpenSquareBracket:\n\t\t\t\t\t\t\tinSquareBrackets = true;\n\t\t\t\t\t\t\thasOpenSquareBracket = true;\n\t\t\t\t\t\t\tchClass = CharacterClass.None;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CharCode.CloseSquareBracket:\n\t\t\t\t\t\t\tinSquareBrackets = false;\n\t\t\t\t\t\t\tchClass = (hasOpenSquareBracket ? CharacterClass.None : CharacterClass.ForceTermination);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CharCode.OpenCurlyBrace:\n\t\t\t\t\t\t\thasOpenCurlyBracket = true;\n\t\t\t\t\t\t\tchClass = CharacterClass.None;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CharCode.CloseCurlyBrace:\n\t\t\t\t\t\t\tchClass = (hasOpenCurlyBracket ? CharacterClass.None : CharacterClass.ForceTermination);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t/* The following three rules make it that ' or \" or ` are allowed inside links if the link began with a different one */\n\t\t\t\t\t\tcase CharCode.SingleQuote:\n\t\t\t\t\t\t\tchClass = (linkBeginChCode === CharCode.DoubleQuote || linkBeginChCode === CharCode.BackTick) ? CharacterClass.None : CharacterClass.ForceTermination;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CharCode.DoubleQuote:\n\t\t\t\t\t\t\tchClass = (linkBeginChCode === CharCode.SingleQuote || linkBeginChCode === CharCode.BackTick) ? CharacterClass.None : CharacterClass.ForceTermination;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CharCode.BackTick:\n\t\t\t\t\t\t\tchClass = (linkBeginChCode === CharCode.SingleQuote || linkBeginChCode === CharCode.DoubleQuote) ? CharacterClass.None : CharacterClass.ForceTermination;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CharCode.Asterisk:\n\t\t\t\t\t\t\t// `*` terminates a link if the link began with `*`\n\t\t\t\t\t\t\tchClass = (linkBeginChCode === CharCode.Asterisk) ? CharacterClass.ForceTermination : CharacterClass.None;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CharCode.Pipe:\n\t\t\t\t\t\t\t// `|` terminates a link if the link began with `|`\n\t\t\t\t\t\t\tchClass = (linkBeginChCode === CharCode.Pipe) ? CharacterClass.ForceTermination : CharacterClass.None;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CharCode.Space:\n\t\t\t\t\t\t\t// ` ` allow space in between [ and ]\n\t\t\t\t\t\t\tchClass = (inSquareBrackets ? CharacterClass.None : CharacterClass.ForceTermination);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tchClass = classifier.get(chCode);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check if character terminates link\n\t\t\t\t\tif (chClass === CharacterClass.ForceTermination) {\n\t\t\t\t\t\tresult.push(LinkComputer._createLink(classifier, line, i, linkBeginIndex, j));\n\t\t\t\t\t\tresetStateMachine = true;\n\t\t\t\t\t}\n\t\t\t\t} else if (state === State.End) {\n\n\t\t\t\t\tlet chClass: CharacterClass;\n\t\t\t\t\tif (chCode === CharCode.OpenSquareBracket) {\n\t\t\t\t\t\t// Allow for the authority part to contain ipv6 addresses which contain [ and ]\n\t\t\t\t\t\thasOpenSquareBracket = true;\n\t\t\t\t\t\tchClass = CharacterClass.None;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tchClass = classifier.get(chCode);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check if character terminates link\n\t\t\t\t\tif (chClass === CharacterClass.ForceTermination) {\n\t\t\t\t\t\tresetStateMachine = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstate = State.Accept;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tstate = stateMachine.nextState(state, chCode);\n\t\t\t\t\tif (state === State.Invalid) {\n\t\t\t\t\t\tresetStateMachine = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (resetStateMachine) {\n\t\t\t\t\tstate = State.Start;\n\t\t\t\t\thasOpenParens = false;\n\t\t\t\t\thasOpenSquareBracket = false;\n\t\t\t\t\thasOpenCurlyBracket = false;\n\n\t\t\t\t\t// Record where the link started\n\t\t\t\t\tlinkBeginIndex = j + 1;\n\t\t\t\t\tlinkBeginChCode = chCode;\n\t\t\t\t}\n\n\t\t\t\tj++;\n\t\t\t}\n\n\t\t\tif (state === State.Accept) {\n\t\t\t\tresult.push(LinkComputer._createLink(classifier, line, i, linkBeginIndex, len));\n\t\t\t}\n\n\t\t}\n\n\t\treturn result;\n\t}\n}\n\n/**\n * Returns an array of all links contains in the provided\n * document. *Note* that this operation is computational\n * expensive and should not run in the UI thread.\n */\nexport function computeLinks(model: ILinkComputerTarget | null): ILink[] {\n\tif (!model || typeof model.getLineCount !== 'function' || typeof model.getLineContent !== 'function') {\n\t\t// Unknown caller!\n\t\treturn [];\n\t}\n\treturn LinkComputer.computeLinks(model);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { LineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { StandardTokenType } from 'vs/editor/common/languages';\n\nexport function createScopedLineTokens(context: LineTokens, offset: number): ScopedLineTokens {\n\tconst tokenCount = context.getCount();\n\tconst tokenIndex = context.findTokenIndexAtOffset(offset);\n\tconst desiredLanguageId = context.getLanguageId(tokenIndex);\n\n\tlet lastTokenIndex = tokenIndex;\n\twhile (lastTokenIndex + 1 < tokenCount && context.getLanguageId(lastTokenIndex + 1) === desiredLanguageId) {\n\t\tlastTokenIndex++;\n\t}\n\n\tlet firstTokenIndex = tokenIndex;\n\twhile (firstTokenIndex > 0 && context.getLanguageId(firstTokenIndex - 1) === desiredLanguageId) {\n\t\tfirstTokenIndex--;\n\t}\n\n\treturn new ScopedLineTokens(\n\t\tcontext,\n\t\tdesiredLanguageId,\n\t\tfirstTokenIndex,\n\t\tlastTokenIndex + 1,\n\t\tcontext.getStartOffset(firstTokenIndex),\n\t\tcontext.getEndOffset(lastTokenIndex)\n\t);\n}\n\nexport class ScopedLineTokens {\n\t_scopedLineTokensBrand: void = undefined;\n\n\tpublic readonly languageId: string;\n\tprivate readonly _actual: LineTokens;\n\tprivate readonly _firstTokenIndex: number;\n\tprivate readonly _lastTokenIndex: number;\n\tpublic readonly firstCharOffset: number;\n\tprivate readonly _lastCharOffset: number;\n\n\tconstructor(\n\t\tactual: LineTokens,\n\t\tlanguageId: string,\n\t\tfirstTokenIndex: number,\n\t\tlastTokenIndex: number,\n\t\tfirstCharOffset: number,\n\t\tlastCharOffset: number\n\t) {\n\t\tthis._actual = actual;\n\t\tthis.languageId = languageId;\n\t\tthis._firstTokenIndex = firstTokenIndex;\n\t\tthis._lastTokenIndex = lastTokenIndex;\n\t\tthis.firstCharOffset = firstCharOffset;\n\t\tthis._lastCharOffset = lastCharOffset;\n\t}\n\n\tpublic getLineContent(): string {\n\t\tconst actualLineContent = this._actual.getLineContent();\n\t\treturn actualLineContent.substring(this.firstCharOffset, this._lastCharOffset);\n\t}\n\n\tpublic getActualLineContentBefore(offset: number): string {\n\t\tconst actualLineContent = this._actual.getLineContent();\n\t\treturn actualLineContent.substring(0, this.firstCharOffset + offset);\n\t}\n\n\tpublic getTokenCount(): number {\n\t\treturn this._lastTokenIndex - this._firstTokenIndex;\n\t}\n\n\tpublic findTokenIndexAtOffset(offset: number): number {\n\t\treturn this._actual.findTokenIndexAtOffset(offset + this.firstCharOffset) - this._firstTokenIndex;\n\t}\n\n\tpublic getStandardTokenType(tokenIndex: number): StandardTokenType {\n\t\treturn this._actual.getStandardTokenType(tokenIndex + this._firstTokenIndex);\n\t}\n}\n\nconst enum IgnoreBracketsInTokens {\n\tvalue = StandardTokenType.Comment | StandardTokenType.String | StandardTokenType.RegEx\n}\n\nexport function ignoreBracketsInToken(standardTokenType: StandardTokenType): boolean {\n\treturn (standardTokenType & IgnoreBracketsInTokens.value) !== 0;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IAutoClosingPair, StandardAutoClosingPairConditional, LanguageConfiguration, CharacterPair } from 'vs/editor/common/languages/languageConfiguration';\n\nexport class CharacterPairSupport {\n\n\tstatic readonly DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED = ';:.,=}])> \\n\\t';\n\n\tprivate readonly _autoClosingPairs: StandardAutoClosingPairConditional[];\n\tprivate readonly _surroundingPairs: IAutoClosingPair[];\n\tprivate readonly _autoCloseBefore: string;\n\tprivate readonly _colorizedBracketPairs: CharacterPair[];\n\n\tconstructor(config: LanguageConfiguration) {\n\t\tif (config.autoClosingPairs) {\n\t\t\tthis._autoClosingPairs = config.autoClosingPairs.map(el => new StandardAutoClosingPairConditional(el));\n\t\t} else if (config.brackets) {\n\t\t\tthis._autoClosingPairs = config.brackets.map(b => new StandardAutoClosingPairConditional({ open: b[0], close: b[1] }));\n\t\t} else {\n\t\t\tthis._autoClosingPairs = [];\n\t\t}\n\n\t\tif (config.colorizedBracketPairs) {\n\t\t\tthis._colorizedBracketPairs = filterValidBrackets(config.colorizedBracketPairs.map(b => [b[0], b[1]]));\n\t\t} else if (config.brackets) {\n\t\t\tthis._colorizedBracketPairs = filterValidBrackets(config.brackets\n\t\t\t\t.map((b) => [b[0], b[1]] as [string, string])\n\t\t\t\t// Many languages set < ... > as bracket pair, even though they also use it as comparison operator.\n\t\t\t\t// This leads to problems when colorizing this bracket, so we exclude it by default.\n\t\t\t\t// Languages can still override this by configuring `colorizedBracketPairs`\n\t\t\t\t// https://github.com/microsoft/vscode/issues/132476\n\t\t\t\t.filter((p) => !(p[0] === '<' && p[1] === '>')));\n\t\t} else {\n\t\t\tthis._colorizedBracketPairs = [];\n\t\t}\n\n\t\tif (config.__electricCharacterSupport && config.__electricCharacterSupport.docComment) {\n\t\t\tconst docComment = config.__electricCharacterSupport.docComment;\n\t\t\t// IDocComment is legacy, only partially supported\n\t\t\tthis._autoClosingPairs.push(new StandardAutoClosingPairConditional({ open: docComment.open, close: docComment.close || '' }));\n\t\t}\n\n\t\tthis._autoCloseBefore = typeof config.autoCloseBefore === 'string' ? config.autoCloseBefore : CharacterPairSupport.DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED;\n\n\t\tthis._surroundingPairs = config.surroundingPairs || this._autoClosingPairs;\n\t}\n\n\tpublic getAutoClosingPairs(): StandardAutoClosingPairConditional[] {\n\t\treturn this._autoClosingPairs;\n\t}\n\n\tpublic getAutoCloseBeforeSet(): string {\n\t\treturn this._autoCloseBefore;\n\t}\n\n\tpublic getSurroundingPairs(): IAutoClosingPair[] {\n\t\treturn this._surroundingPairs;\n\t}\n\n\tpublic getColorizedBrackets(): readonly CharacterPair[] {\n\t\treturn this._colorizedBracketPairs;\n\t}\n}\n\nfunction filterValidBrackets(bracketPairs: [string, string][]): [string, string][] {\n\treturn bracketPairs.filter(([open, close]) => open !== '' && close !== '');\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IndentationRule } from 'vs/editor/common/languages/languageConfiguration';\n\nexport const enum IndentConsts {\n\tINCREASE_MASK = 0b00000001,\n\tDECREASE_MASK = 0b00000010,\n\tINDENT_NEXTLINE_MASK = 0b00000100,\n\tUNINDENT_MASK = 0b00001000,\n}\n\nfunction resetGlobalRegex(reg: RegExp) {\n\tif (reg.global) {\n\t\treg.lastIndex = 0;\n\t}\n\n\treturn true;\n}\n\nexport class IndentRulesSupport {\n\n\tprivate readonly _indentationRules: IndentationRule;\n\n\tconstructor(indentationRules: IndentationRule) {\n\t\tthis._indentationRules = indentationRules;\n\t}\n\n\tpublic shouldIncrease(text: string): boolean {\n\t\tif (this._indentationRules) {\n\t\t\tif (this._indentationRules.increaseIndentPattern && resetGlobalRegex(this._indentationRules.increaseIndentPattern) && this._indentationRules.increaseIndentPattern.test(text)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t// if (this._indentationRules.indentNextLinePattern && this._indentationRules.indentNextLinePattern.test(text)) {\n\t\t\t// \treturn true;\n\t\t\t// }\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic shouldDecrease(text: string): boolean {\n\t\tif (this._indentationRules && this._indentationRules.decreaseIndentPattern && resetGlobalRegex(this._indentationRules.decreaseIndentPattern) && this._indentationRules.decreaseIndentPattern.test(text)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic shouldIndentNextLine(text: string): boolean {\n\t\tif (this._indentationRules && this._indentationRules.indentNextLinePattern && resetGlobalRegex(this._indentationRules.indentNextLinePattern) && this._indentationRules.indentNextLinePattern.test(text)) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic shouldIgnore(text: string): boolean {\n\t\t// the text matches `unIndentedLinePattern`\n\t\tif (this._indentationRules && this._indentationRules.unIndentedLinePattern && resetGlobalRegex(this._indentationRules.unIndentedLinePattern) && this._indentationRules.unIndentedLinePattern.test(text)) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic getIndentMetadata(text: string): number {\n\t\tlet ret = 0;\n\t\tif (this.shouldIncrease(text)) {\n\t\t\tret += IndentConsts.INCREASE_MASK;\n\t\t}\n\t\tif (this.shouldDecrease(text)) {\n\t\t\tret += IndentConsts.DECREASE_MASK;\n\t\t}\n\t\tif (this.shouldIndentNextLine(text)) {\n\t\t\tret += IndentConsts.INDENT_NEXTLINE_MASK;\n\t\t}\n\t\tif (this.shouldIgnore(text)) {\n\t\t\tret += IndentConsts.UNINDENT_MASK;\n\t\t}\n\t\treturn ret;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IRange } from 'vs/editor/common/core/range';\nimport { IInplaceReplaceSupportResult } from 'vs/editor/common/languages';\n\nexport class BasicInplaceReplace {\n\n\tpublic static readonly INSTANCE = new BasicInplaceReplace();\n\n\tpublic navigateValueSet(range1: IRange, text1: string, range2: IRange, text2: string | null, up: boolean): IInplaceReplaceSupportResult | null {\n\n\t\tif (range1 && text1) {\n\t\t\tconst result = this.doNavigateValueSet(text1, up);\n\t\t\tif (result) {\n\t\t\t\treturn {\n\t\t\t\t\trange: range1,\n\t\t\t\t\tvalue: result\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif (range2 && text2) {\n\t\t\tconst result = this.doNavigateValueSet(text2, up);\n\t\t\tif (result) {\n\t\t\t\treturn {\n\t\t\t\t\trange: range2,\n\t\t\t\t\tvalue: result\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate doNavigateValueSet(text: string, up: boolean): string | null {\n\t\tconst numberResult = this.numberReplace(text, up);\n\t\tif (numberResult !== null) {\n\t\t\treturn numberResult;\n\t\t}\n\t\treturn this.textReplace(text, up);\n\t}\n\n\tprivate numberReplace(value: string, up: boolean): string | null {\n\t\tconst precision = Math.pow(10, value.length - (value.lastIndexOf('.') + 1));\n\t\tlet n1 = Number(value);\n\t\tlet n2 = parseFloat(value);\n\n\t\tif (!isNaN(n1) && !isNaN(n2) && n1 === n2) {\n\n\t\t\tif (n1 === 0 && !up) {\n\t\t\t\treturn null; // don't do negative\n\t\t\t\t//\t\t\t} else if(n1 === 9 && up) {\n\t\t\t\t//\t\t\t\treturn null; // don't insert 10 into a number\n\t\t\t} else {\n\t\t\t\tn1 = Math.floor(n1 * precision);\n\t\t\t\tn1 += up ? precision : -precision;\n\t\t\t\treturn String(n1 / precision);\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate readonly _defaultValueSet: string[][] = [\n\t\t['true', 'false'],\n\t\t['True', 'False'],\n\t\t['Private', 'Public', 'Friend', 'ReadOnly', 'Partial', 'Protected', 'WriteOnly'],\n\t\t['public', 'protected', 'private'],\n\t];\n\n\tprivate textReplace(value: string, up: boolean): string | null {\n\t\treturn this.valueSetsReplace(this._defaultValueSet, value, up);\n\t}\n\n\tprivate valueSetsReplace(valueSets: string[][], value: string, up: boolean): string | null {\n\t\tlet result: string | null = null;\n\t\tfor (let i = 0, len = valueSets.length; result === null && i < len; i++) {\n\t\t\tresult = this.valueSetReplace(valueSets[i], value, up);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate valueSetReplace(valueSet: string[], value: string, up: boolean): string | null {\n\t\tlet idx = valueSet.indexOf(value);\n\t\tif (idx >= 0) {\n\t\t\tidx += up ? +1 : -1;\n\t\t\tif (idx < 0) {\n\t\t\t\tidx = valueSet.length - 1;\n\t\t\t} else {\n\t\t\t\tidx %= valueSet.length;\n\t\t\t}\n\t\t\treturn valueSet[idx];\n\t\t}\n\t\treturn null;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport * as strings from 'vs/base/common/strings';\nimport { CharacterPair, EnterAction, IndentAction, OnEnterRule } from 'vs/editor/common/languages/languageConfiguration';\nimport { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';\n\nexport interface IOnEnterSupportOptions {\n\tbrackets?: CharacterPair[];\n\tonEnterRules?: OnEnterRule[];\n}\n\ninterface IProcessedBracketPair {\n\topen: string;\n\tclose: string;\n\topenRegExp: RegExp;\n\tcloseRegExp: RegExp;\n}\n\nexport class OnEnterSupport {\n\n\tprivate readonly _brackets: IProcessedBracketPair[];\n\tprivate readonly _regExpRules: OnEnterRule[];\n\n\tconstructor(opts: IOnEnterSupportOptions) {\n\t\topts = opts || {};\n\t\topts.brackets = opts.brackets || [\n\t\t\t['(', ')'],\n\t\t\t['{', '}'],\n\t\t\t['[', ']']\n\t\t];\n\n\t\tthis._brackets = [];\n\t\topts.brackets.forEach((bracket) => {\n\t\t\tconst openRegExp = OnEnterSupport._createOpenBracketRegExp(bracket[0]);\n\t\t\tconst closeRegExp = OnEnterSupport._createCloseBracketRegExp(bracket[1]);\n\t\t\tif (openRegExp && closeRegExp) {\n\t\t\t\tthis._brackets.push({\n\t\t\t\t\topen: bracket[0],\n\t\t\t\t\topenRegExp: openRegExp,\n\t\t\t\t\tclose: bracket[1],\n\t\t\t\t\tcloseRegExp: closeRegExp,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\tthis._regExpRules = opts.onEnterRules || [];\n\t}\n\n\tpublic onEnter(autoIndent: EditorAutoIndentStrategy, previousLineText: string, beforeEnterText: string, afterEnterText: string): EnterAction | null {\n\t\t// (1): `regExpRules`\n\t\tif (autoIndent >= EditorAutoIndentStrategy.Advanced) {\n\t\t\tfor (let i = 0, len = this._regExpRules.length; i < len; i++) {\n\t\t\t\tconst rule = this._regExpRules[i];\n\t\t\t\tconst regResult = [{\n\t\t\t\t\treg: rule.beforeText,\n\t\t\t\t\ttext: beforeEnterText\n\t\t\t\t}, {\n\t\t\t\t\treg: rule.afterText,\n\t\t\t\t\ttext: afterEnterText\n\t\t\t\t}, {\n\t\t\t\t\treg: rule.previousLineText,\n\t\t\t\t\ttext: previousLineText\n\t\t\t\t}].every((obj): boolean => {\n\t\t\t\t\tif (!obj.reg) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tobj.reg.lastIndex = 0; // To disable the effect of the \"g\" flag.\n\t\t\t\t\treturn obj.reg.test(obj.text);\n\t\t\t\t});\n\n\t\t\t\tif (regResult) {\n\t\t\t\t\treturn rule.action;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// (2): Special indent-outdent\n\t\tif (autoIndent >= EditorAutoIndentStrategy.Brackets) {\n\t\t\tif (beforeEnterText.length > 0 && afterEnterText.length > 0) {\n\t\t\t\tfor (let i = 0, len = this._brackets.length; i < len; i++) {\n\t\t\t\t\tconst bracket = this._brackets[i];\n\t\t\t\t\tif (bracket.openRegExp.test(beforeEnterText) && bracket.closeRegExp.test(afterEnterText)) {\n\t\t\t\t\t\treturn { indentAction: IndentAction.IndentOutdent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\t// (4): Open bracket based logic\n\t\tif (autoIndent >= EditorAutoIndentStrategy.Brackets) {\n\t\t\tif (beforeEnterText.length > 0) {\n\t\t\t\tfor (let i = 0, len = this._brackets.length; i < len; i++) {\n\t\t\t\t\tconst bracket = this._brackets[i];\n\t\t\t\t\tif (bracket.openRegExp.test(beforeEnterText)) {\n\t\t\t\t\t\treturn { indentAction: IndentAction.Indent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate static _createOpenBracketRegExp(bracket: string): RegExp | null {\n\t\tlet str = strings.escapeRegExpCharacters(bracket);\n\t\tif (!/\\B/.test(str.charAt(0))) {\n\t\t\tstr = '\\\\b' + str;\n\t\t}\n\t\tstr += '\\\\s*$';\n\t\treturn OnEnterSupport._safeRegExp(str);\n\t}\n\n\tprivate static _createCloseBracketRegExp(bracket: string): RegExp | null {\n\t\tlet str = strings.escapeRegExpCharacters(bracket);\n\t\tif (!/\\B/.test(str.charAt(str.length - 1))) {\n\t\t\tstr = str + '\\\\b';\n\t\t}\n\t\tstr = '^\\\\s*' + str;\n\t\treturn OnEnterSupport._safeRegExp(str);\n\t}\n\n\tprivate static _safeRegExp(def: string): RegExp | null {\n\t\ttry {\n\t\t\treturn new RegExp(def);\n\t\t} catch (err) {\n\t\t\tonUnexpectedError(err);\n\t\t\treturn null;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as strings from 'vs/base/common/strings';\nimport * as stringBuilder from 'vs/editor/common/core/stringBuilder';\nimport { Range } from 'vs/editor/common/core/range';\nimport { CharacterPair } from 'vs/editor/common/languages/languageConfiguration';\n\ninterface InternalBracket {\n\topen: string[];\n\tclose: string[];\n}\n\n/**\n * Represents a grouping of colliding bracket pairs.\n *\n * Most of the times this contains a single bracket pair,\n * but sometimes this contains multiple bracket pairs in cases\n * where the same string appears as a closing bracket for multiple\n * bracket pairs, or the same string appears an opening bracket for\n * multiple bracket pairs.\n *\n * e.g. of a group containing a single pair:\n * open: ['{'], close: ['}']\n *\n * e.g. of a group containing multiple pairs:\n * open: ['if', 'for'], close: ['end', 'end']\n */\nexport class RichEditBracket {\n\t_richEditBracketBrand: void = undefined;\n\n\treadonly languageId: string;\n\t/**\n\t * A 0-based consecutive unique identifier for this bracket pair.\n\t * If a language has 5 bracket pairs, out of which 2 are grouped together,\n\t * it is expected that the `index` goes from 0 to 4.\n\t */\n\treadonly index: number;\n\t/**\n\t * The open sequence for each bracket pair contained in this group.\n\t *\n\t * The open sequence at a specific index corresponds to the\n\t * closing sequence at the same index.\n\t *\n\t * [ open[i], closed[i] ] represent a bracket pair.\n\t */\n\treadonly open: string[];\n\t/**\n\t * The close sequence for each bracket pair contained in this group.\n\t *\n\t * The close sequence at a specific index corresponds to the\n\t * opening sequence at the same index.\n\t *\n\t * [ open[i], closed[i] ] represent a bracket pair.\n\t */\n\treadonly close: string[];\n\t/**\n\t * A regular expression that is useful to search for this bracket pair group in a string.\n\t *\n\t * This regular expression is built in a way that it is aware of the other bracket\n\t * pairs defined for the language, so it might match brackets from other groups.\n\t *\n\t * See the fine details in `getRegexForBracketPair`.\n\t */\n\treadonly forwardRegex: RegExp;\n\t/**\n\t * A regular expression that is useful to search for this bracket pair group in a string backwards.\n\t *\n\t * This regular expression is built in a way that it is aware of the other bracket\n\t * pairs defined for the language, so it might match brackets from other groups.\n\t *\n\t * See the fine defails in `getReversedRegexForBracketPair`.\n\t */\n\treadonly reversedRegex: RegExp;\n\tprivate readonly _openSet: Set;\n\tprivate readonly _closeSet: Set;\n\n\tconstructor(languageId: string, index: number, open: string[], close: string[], forwardRegex: RegExp, reversedRegex: RegExp) {\n\t\tthis.languageId = languageId;\n\t\tthis.index = index;\n\t\tthis.open = open;\n\t\tthis.close = close;\n\t\tthis.forwardRegex = forwardRegex;\n\t\tthis.reversedRegex = reversedRegex;\n\t\tthis._openSet = RichEditBracket._toSet(this.open);\n\t\tthis._closeSet = RichEditBracket._toSet(this.close);\n\t}\n\n\t/**\n\t * Check if the provided `text` is an open bracket in this group.\n\t */\n\tpublic isOpen(text: string) {\n\t\treturn this._openSet.has(text);\n\t}\n\n\t/**\n\t * Check if the provided `text` is a close bracket in this group.\n\t */\n\tpublic isClose(text: string) {\n\t\treturn this._closeSet.has(text);\n\t}\n\n\tprivate static _toSet(arr: string[]): Set {\n\t\tconst result = new Set();\n\t\tfor (const element of arr) {\n\t\t\tresult.add(element);\n\t\t}\n\t\treturn result;\n\t}\n}\n\n/**\n * Groups together brackets that have equal open or close sequences.\n *\n * For example, if the following brackets are defined:\n * ['IF','END']\n * ['for','end']\n * ['{','}']\n *\n * Then the grouped brackets would be:\n * { open: ['if', 'for'], close: ['end', 'end'] }\n * { open: ['{'], close: ['}'] }\n *\n */\nfunction groupFuzzyBrackets(brackets: readonly CharacterPair[]): InternalBracket[] {\n\tconst N = brackets.length;\n\n\tbrackets = brackets.map(b => [b[0].toLowerCase(), b[1].toLowerCase()]);\n\n\tconst group: number[] = [];\n\tfor (let i = 0; i < N; i++) {\n\t\tgroup[i] = i;\n\t}\n\n\tconst areOverlapping = (a: CharacterPair, b: CharacterPair) => {\n\t\tconst [aOpen, aClose] = a;\n\t\tconst [bOpen, bClose] = b;\n\t\treturn (aOpen === bOpen || aOpen === bClose || aClose === bOpen || aClose === bClose);\n\t};\n\n\tconst mergeGroups = (g1: number, g2: number) => {\n\t\tconst newG = Math.min(g1, g2);\n\t\tconst oldG = Math.max(g1, g2);\n\t\tfor (let i = 0; i < N; i++) {\n\t\t\tif (group[i] === oldG) {\n\t\t\t\tgroup[i] = newG;\n\t\t\t}\n\t\t}\n\t};\n\n\t// group together brackets that have the same open or the same close sequence\n\tfor (let i = 0; i < N; i++) {\n\t\tconst a = brackets[i];\n\t\tfor (let j = i + 1; j < N; j++) {\n\t\t\tconst b = brackets[j];\n\t\t\tif (areOverlapping(a, b)) {\n\t\t\t\tmergeGroups(group[i], group[j]);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst result: InternalBracket[] = [];\n\tfor (let g = 0; g < N; g++) {\n\t\tconst currentOpen: string[] = [];\n\t\tconst currentClose: string[] = [];\n\t\tfor (let i = 0; i < N; i++) {\n\t\t\tif (group[i] === g) {\n\t\t\t\tconst [open, close] = brackets[i];\n\t\t\t\tcurrentOpen.push(open);\n\t\t\t\tcurrentClose.push(close);\n\t\t\t}\n\t\t}\n\t\tif (currentOpen.length > 0) {\n\t\t\tresult.push({\n\t\t\t\topen: currentOpen,\n\t\t\t\tclose: currentClose\n\t\t\t});\n\t\t}\n\t}\n\treturn result;\n}\n\nexport class RichEditBrackets {\n\t_richEditBracketsBrand: void = undefined;\n\n\t/**\n\t * All groups of brackets defined for this language.\n\t */\n\tpublic readonly brackets: RichEditBracket[];\n\t/**\n\t * A regular expression that is useful to search for all bracket pairs in a string.\n\t *\n\t * See the fine details in `getRegexForBrackets`.\n\t */\n\tpublic readonly forwardRegex: RegExp;\n\t/**\n\t * A regular expression that is useful to search for all bracket pairs in a string backwards.\n\t *\n\t * See the fine details in `getReversedRegexForBrackets`.\n\t */\n\tpublic readonly reversedRegex: RegExp;\n\t/**\n\t * The length (i.e. str.length) for the longest bracket pair.\n\t */\n\tpublic readonly maxBracketLength: number;\n\t/**\n\t * A map useful for decoding a regex match and finding which bracket group was matched.\n\t */\n\tpublic readonly textIsBracket: { [text: string]: RichEditBracket; };\n\t/**\n\t * A set useful for decoding if a regex match is the open bracket of a bracket pair.\n\t */\n\tpublic readonly textIsOpenBracket: { [text: string]: boolean; };\n\n\tconstructor(languageId: string, _brackets: readonly CharacterPair[]) {\n\t\tconst brackets = groupFuzzyBrackets(_brackets);\n\n\t\tthis.brackets = brackets.map((b, index) => {\n\t\t\treturn new RichEditBracket(\n\t\t\t\tlanguageId,\n\t\t\t\tindex,\n\t\t\t\tb.open,\n\t\t\t\tb.close,\n\t\t\t\tgetRegexForBracketPair(b.open, b.close, brackets, index),\n\t\t\t\tgetReversedRegexForBracketPair(b.open, b.close, brackets, index)\n\t\t\t);\n\t\t});\n\n\t\tthis.forwardRegex = getRegexForBrackets(this.brackets);\n\t\tthis.reversedRegex = getReversedRegexForBrackets(this.brackets);\n\n\t\tthis.textIsBracket = {};\n\t\tthis.textIsOpenBracket = {};\n\n\t\tthis.maxBracketLength = 0;\n\t\tfor (const bracket of this.brackets) {\n\t\t\tfor (const open of bracket.open) {\n\t\t\t\tthis.textIsBracket[open] = bracket;\n\t\t\t\tthis.textIsOpenBracket[open] = true;\n\t\t\t\tthis.maxBracketLength = Math.max(this.maxBracketLength, open.length);\n\t\t\t}\n\t\t\tfor (const close of bracket.close) {\n\t\t\t\tthis.textIsBracket[close] = bracket;\n\t\t\t\tthis.textIsOpenBracket[close] = false;\n\t\t\t\tthis.maxBracketLength = Math.max(this.maxBracketLength, close.length);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction collectSuperstrings(str: string, brackets: InternalBracket[], currentIndex: number, dest: string[]): void {\n\tfor (let i = 0, len = brackets.length; i < len; i++) {\n\t\tif (i === currentIndex) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst bracket = brackets[i];\n\t\tfor (const open of bracket.open) {\n\t\t\tif (open.indexOf(str) >= 0) {\n\t\t\t\tdest.push(open);\n\t\t\t}\n\t\t}\n\t\tfor (const close of bracket.close) {\n\t\t\tif (close.indexOf(str) >= 0) {\n\t\t\t\tdest.push(close);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction lengthcmp(a: string, b: string) {\n\treturn a.length - b.length;\n}\n\nfunction unique(arr: string[]): string[] {\n\tif (arr.length <= 1) {\n\t\treturn arr;\n\t}\n\tconst result: string[] = [];\n\tconst seen = new Set();\n\tfor (const element of arr) {\n\t\tif (seen.has(element)) {\n\t\t\tcontinue;\n\t\t}\n\t\tresult.push(element);\n\t\tseen.add(element);\n\t}\n\treturn result;\n}\n\n/**\n * Create a regular expression that can be used to search forward in a piece of text\n * for a group of bracket pairs. But this regex must be built in a way in which\n * it is aware of the other bracket pairs defined for the language.\n *\n * For example, if a language contains the following bracket pairs:\n * ['begin', 'end']\n * ['if', 'end if']\n * The two bracket pairs do not collide because no open or close brackets are equal.\n * So the function getRegexForBracketPair is called twice, once with\n * the ['begin'], ['end'] group consisting of one bracket pair, and once with\n * the ['if'], ['end if'] group consiting of the other bracket pair.\n *\n * But there could be a situation where an occurrence of 'end if' is mistaken\n * for an occurrence of 'end'.\n *\n * Therefore, for the bracket pair ['begin', 'end'], the regex will also\n * target 'end if'. The regex will be something like:\n * /(\\bend if\\b)|(\\bend\\b)|(\\bif\\b)/\n *\n * The regex also searches for \"superstrings\" (other brackets that might be mistaken with the current bracket).\n *\n */\nfunction getRegexForBracketPair(open: string[], close: string[], brackets: InternalBracket[], currentIndex: number): RegExp {\n\t// search in all brackets for other brackets that are a superstring of these brackets\n\tlet pieces: string[] = [];\n\tpieces = pieces.concat(open);\n\tpieces = pieces.concat(close);\n\tfor (let i = 0, len = pieces.length; i < len; i++) {\n\t\tcollectSuperstrings(pieces[i], brackets, currentIndex, pieces);\n\t}\n\tpieces = unique(pieces);\n\tpieces.sort(lengthcmp);\n\tpieces.reverse();\n\treturn createBracketOrRegExp(pieces);\n}\n\n/**\n * Matching a regular expression in JS can only be done \"forwards\". So JS offers natively only\n * methods to find the first match of a regex in a string. But sometimes, it is useful to\n * find the last match of a regex in a string. For such a situation, a nice solution is to\n * simply reverse the string and then search for a reversed regex.\n *\n * This function also has the fine details of `getRegexForBracketPair`. For the same example\n * given above, the regex produced here would look like:\n * /(\\bfi dne\\b)|(\\bdne\\b)|(\\bfi\\b)/\n */\nfunction getReversedRegexForBracketPair(open: string[], close: string[], brackets: InternalBracket[], currentIndex: number): RegExp {\n\t// search in all brackets for other brackets that are a superstring of these brackets\n\tlet pieces: string[] = [];\n\tpieces = pieces.concat(open);\n\tpieces = pieces.concat(close);\n\tfor (let i = 0, len = pieces.length; i < len; i++) {\n\t\tcollectSuperstrings(pieces[i], brackets, currentIndex, pieces);\n\t}\n\tpieces = unique(pieces);\n\tpieces.sort(lengthcmp);\n\tpieces.reverse();\n\treturn createBracketOrRegExp(pieces.map(toReversedString));\n}\n\n/**\n * Creates a regular expression that targets all bracket pairs.\n *\n * e.g. for the bracket pairs:\n * ['{','}']\n * ['begin,'end']\n * ['for','end']\n * the regex would look like:\n * /(\\{)|(\\})|(\\bbegin\\b)|(\\bend\\b)|(\\bfor\\b)/\n */\nfunction getRegexForBrackets(brackets: RichEditBracket[]): RegExp {\n\tlet pieces: string[] = [];\n\tfor (const bracket of brackets) {\n\t\tfor (const open of bracket.open) {\n\t\t\tpieces.push(open);\n\t\t}\n\t\tfor (const close of bracket.close) {\n\t\t\tpieces.push(close);\n\t\t}\n\t}\n\tpieces = unique(pieces);\n\treturn createBracketOrRegExp(pieces);\n}\n\n/**\n * Matching a regular expression in JS can only be done \"forwards\". So JS offers natively only\n * methods to find the first match of a regex in a string. But sometimes, it is useful to\n * find the last match of a regex in a string. For such a situation, a nice solution is to\n * simply reverse the string and then search for a reversed regex.\n *\n * e.g. for the bracket pairs:\n * ['{','}']\n * ['begin,'end']\n * ['for','end']\n * the regex would look like:\n * /(\\{)|(\\})|(\\bnigeb\\b)|(\\bdne\\b)|(\\brof\\b)/\n */\nfunction getReversedRegexForBrackets(brackets: RichEditBracket[]): RegExp {\n\tlet pieces: string[] = [];\n\tfor (const bracket of brackets) {\n\t\tfor (const open of bracket.open) {\n\t\t\tpieces.push(open);\n\t\t}\n\t\tfor (const close of bracket.close) {\n\t\t\tpieces.push(close);\n\t\t}\n\t}\n\tpieces = unique(pieces);\n\treturn createBracketOrRegExp(pieces.map(toReversedString));\n}\n\nfunction prepareBracketForRegExp(str: string): string {\n\t// This bracket pair uses letters like e.g. \"begin\" - \"end\"\n\tconst insertWordBoundaries = (/^[\\w ]+$/.test(str));\n\tstr = strings.escapeRegExpCharacters(str);\n\treturn (insertWordBoundaries ? `\\\\b${str}\\\\b` : str);\n}\n\nfunction createBracketOrRegExp(pieces: string[]): RegExp {\n\tconst regexStr = `(${pieces.map(prepareBracketForRegExp).join(')|(')})`;\n\treturn strings.createRegExp(regexStr, true);\n}\n\nconst toReversedString = (function () {\n\n\tfunction reverse(str: string): string {\n\t\tif (stringBuilder.hasTextDecoder) {\n\t\t\t// create a Uint16Array and then use a TextDecoder to create a string\n\t\t\tconst arr = new Uint16Array(str.length);\n\t\t\tlet offset = 0;\n\t\t\tfor (let i = str.length - 1; i >= 0; i--) {\n\t\t\t\tarr[offset++] = str.charCodeAt(i);\n\t\t\t}\n\t\t\treturn stringBuilder.getPlatformTextDecoder().decode(arr);\n\t\t} else {\n\t\t\tconst result: string[] = [];\n\t\t\tlet resultLen = 0;\n\t\t\tfor (let i = str.length - 1; i >= 0; i--) {\n\t\t\t\tresult[resultLen++] = str.charAt(i);\n\t\t\t}\n\t\t\treturn result.join('');\n\t\t}\n\t}\n\n\tlet lastInput: string | null = null;\n\tlet lastOutput: string | null = null;\n\treturn function toReversedString(str: string): string {\n\t\tif (lastInput !== str) {\n\t\t\tlastInput = str;\n\t\t\tlastOutput = reverse(lastInput);\n\t\t}\n\t\treturn lastOutput!;\n\t};\n})();\n\nexport class BracketsUtils {\n\n\tprivate static _findPrevBracketInText(reversedBracketRegex: RegExp, lineNumber: number, reversedText: string, offset: number): Range | null {\n\t\tconst m = reversedText.match(reversedBracketRegex);\n\n\t\tif (!m) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst matchOffset = reversedText.length - (m.index || 0);\n\t\tconst matchLength = m[0].length;\n\t\tconst absoluteMatchOffset = offset + matchOffset;\n\n\t\treturn new Range(lineNumber, absoluteMatchOffset - matchLength + 1, lineNumber, absoluteMatchOffset + 1);\n\t}\n\n\tpublic static findPrevBracketInRange(reversedBracketRegex: RegExp, lineNumber: number, lineText: string, startOffset: number, endOffset: number): Range | null {\n\t\t// Because JS does not support backwards regex search, we search forwards in a reversed string with a reversed regex ;)\n\t\tconst reversedLineText = toReversedString(lineText);\n\t\tconst reversedSubstr = reversedLineText.substring(lineText.length - endOffset, lineText.length - startOffset);\n\t\treturn this._findPrevBracketInText(reversedBracketRegex, lineNumber, reversedSubstr, startOffset);\n\t}\n\n\tpublic static findNextBracketInText(bracketRegex: RegExp, lineNumber: number, text: string, offset: number): Range | null {\n\t\tconst m = text.match(bracketRegex);\n\n\t\tif (!m) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst matchOffset = m.index || 0;\n\t\tconst matchLength = m[0].length;\n\t\tif (matchLength === 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst absoluteMatchOffset = offset + matchOffset;\n\n\t\treturn new Range(lineNumber, absoluteMatchOffset + 1, lineNumber, absoluteMatchOffset + 1 + matchLength);\n\t}\n\n\tpublic static findNextBracketInRange(bracketRegex: RegExp, lineNumber: number, lineText: string, startOffset: number, endOffset: number): Range | null {\n\t\tconst substr = lineText.substring(startOffset, endOffset);\n\t\treturn this.findNextBracketInText(bracketRegex, lineNumber, substr, startOffset);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { distinct } from 'vs/base/common/arrays';\nimport { ScopedLineTokens, ignoreBracketsInToken } from 'vs/editor/common/languages/supports';\nimport { BracketsUtils, RichEditBrackets } from 'vs/editor/common/languages/supports/richEditBrackets';\n\n/**\n * Interface used to support electric characters\n * @internal\n */\nexport interface IElectricAction {\n\t// The line will be indented at the same level of the line\n\t// which contains the matching given bracket type.\n\tmatchOpenBracket: string;\n}\n\nexport class BracketElectricCharacterSupport {\n\n\tprivate readonly _richEditBrackets: RichEditBrackets | null;\n\n\tconstructor(richEditBrackets: RichEditBrackets | null) {\n\t\tthis._richEditBrackets = richEditBrackets;\n\t}\n\n\tpublic getElectricCharacters(): string[] {\n\t\tconst result: string[] = [];\n\n\t\tif (this._richEditBrackets) {\n\t\t\tfor (const bracket of this._richEditBrackets.brackets) {\n\t\t\t\tfor (const close of bracket.close) {\n\t\t\t\t\tconst lastChar = close.charAt(close.length - 1);\n\t\t\t\t\tresult.push(lastChar);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn distinct(result);\n\t}\n\n\tpublic onElectricCharacter(character: string, context: ScopedLineTokens, column: number): IElectricAction | null {\n\t\tif (!this._richEditBrackets || this._richEditBrackets.brackets.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst tokenIndex = context.findTokenIndexAtOffset(column - 1);\n\t\tif (ignoreBracketsInToken(context.getStandardTokenType(tokenIndex))) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst reversedBracketRegex = this._richEditBrackets.reversedRegex;\n\t\tconst text = context.getLineContent().substring(0, column - 1) + character;\n\n\t\tconst r = BracketsUtils.findPrevBracketInRange(reversedBracketRegex, 1, text, 0, text.length);\n\t\tif (!r) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst bracketText = text.substring(r.startColumn - 1, r.endColumn - 1).toLowerCase();\n\n\t\tconst isOpen = this._richEditBrackets.textIsOpenBracket[bracketText];\n\t\tif (isOpen) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst textBeforeBracket = context.getActualLineContentBefore(r.startColumn - 1);\n\t\tif (!/^\\s*$/.test(textBeforeBracket)) {\n\t\t\t// There is other text on the line before the bracket\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\tmatchOpenBracket: bracketText\n\t\t};\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Color } from 'vs/base/common/color';\nimport { ColorId, FontStyle, LanguageId, MetadataConsts, StandardTokenType } from 'vs/editor/common/languages';\n\nexport interface ITokenThemeRule {\n\ttoken: string;\n\tforeground?: string;\n\tbackground?: string;\n\tfontStyle?: string;\n}\n\nexport class ParsedTokenThemeRule {\n\t_parsedThemeRuleBrand: void = undefined;\n\n\treadonly token: string;\n\treadonly index: number;\n\n\t/**\n\t * -1 if not set. An or mask of `FontStyle` otherwise.\n\t */\n\treadonly fontStyle: FontStyle;\n\treadonly foreground: string | null;\n\treadonly background: string | null;\n\n\tconstructor(\n\t\ttoken: string,\n\t\tindex: number,\n\t\tfontStyle: number,\n\t\tforeground: string | null,\n\t\tbackground: string | null,\n\t) {\n\t\tthis.token = token;\n\t\tthis.index = index;\n\t\tthis.fontStyle = fontStyle;\n\t\tthis.foreground = foreground;\n\t\tthis.background = background;\n\t}\n}\n\n/**\n * Parse a raw theme into rules.\n */\nexport function parseTokenTheme(source: ITokenThemeRule[]): ParsedTokenThemeRule[] {\n\tif (!source || !Array.isArray(source)) {\n\t\treturn [];\n\t}\n\tconst result: ParsedTokenThemeRule[] = [];\n\tlet resultLen = 0;\n\tfor (let i = 0, len = source.length; i < len; i++) {\n\t\tconst entry = source[i];\n\n\t\tlet fontStyle: number = FontStyle.NotSet;\n\t\tif (typeof entry.fontStyle === 'string') {\n\t\t\tfontStyle = FontStyle.None;\n\n\t\t\tconst segments = entry.fontStyle.split(' ');\n\t\t\tfor (let j = 0, lenJ = segments.length; j < lenJ; j++) {\n\t\t\t\tconst segment = segments[j];\n\t\t\t\tswitch (segment) {\n\t\t\t\t\tcase 'italic':\n\t\t\t\t\t\tfontStyle = fontStyle | FontStyle.Italic;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'bold':\n\t\t\t\t\t\tfontStyle = fontStyle | FontStyle.Bold;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'underline':\n\t\t\t\t\t\tfontStyle = fontStyle | FontStyle.Underline;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'strikethrough':\n\t\t\t\t\t\tfontStyle = fontStyle | FontStyle.Strikethrough;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet foreground: string | null = null;\n\t\tif (typeof entry.foreground === 'string') {\n\t\t\tforeground = entry.foreground;\n\t\t}\n\n\t\tlet background: string | null = null;\n\t\tif (typeof entry.background === 'string') {\n\t\t\tbackground = entry.background;\n\t\t}\n\n\t\tresult[resultLen++] = new ParsedTokenThemeRule(\n\t\t\tentry.token || '',\n\t\t\ti,\n\t\t\tfontStyle,\n\t\t\tforeground,\n\t\t\tbackground\n\t\t);\n\t}\n\n\treturn result;\n}\n\n/**\n * Resolve rules (i.e. inheritance).\n */\nfunction resolveParsedTokenThemeRules(parsedThemeRules: ParsedTokenThemeRule[], customTokenColors: string[]): TokenTheme {\n\n\t// Sort rules lexicographically, and then by index if necessary\n\tparsedThemeRules.sort((a, b) => {\n\t\tconst r = strcmp(a.token, b.token);\n\t\tif (r !== 0) {\n\t\t\treturn r;\n\t\t}\n\t\treturn a.index - b.index;\n\t});\n\n\t// Determine defaults\n\tlet defaultFontStyle = FontStyle.None;\n\tlet defaultForeground = '000000';\n\tlet defaultBackground = 'ffffff';\n\twhile (parsedThemeRules.length >= 1 && parsedThemeRules[0].token === '') {\n\t\tconst incomingDefaults = parsedThemeRules.shift()!;\n\t\tif (incomingDefaults.fontStyle !== FontStyle.NotSet) {\n\t\t\tdefaultFontStyle = incomingDefaults.fontStyle;\n\t\t}\n\t\tif (incomingDefaults.foreground !== null) {\n\t\t\tdefaultForeground = incomingDefaults.foreground;\n\t\t}\n\t\tif (incomingDefaults.background !== null) {\n\t\t\tdefaultBackground = incomingDefaults.background;\n\t\t}\n\t}\n\tconst colorMap = new ColorMap();\n\n\t// start with token colors from custom token themes\n\tfor (let color of customTokenColors) {\n\t\tcolorMap.getId(color);\n\t}\n\n\n\tconst foregroundColorId = colorMap.getId(defaultForeground);\n\tconst backgroundColorId = colorMap.getId(defaultBackground);\n\n\tconst defaults = new ThemeTrieElementRule(defaultFontStyle, foregroundColorId, backgroundColorId);\n\tconst root = new ThemeTrieElement(defaults);\n\tfor (let i = 0, len = parsedThemeRules.length; i < len; i++) {\n\t\tconst rule = parsedThemeRules[i];\n\t\troot.insert(rule.token, rule.fontStyle, colorMap.getId(rule.foreground), colorMap.getId(rule.background));\n\t}\n\n\treturn new TokenTheme(colorMap, root);\n}\n\nconst colorRegExp = /^#?([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$/;\n\nexport class ColorMap {\n\n\tprivate _lastColorId: number;\n\tprivate readonly _id2color: Color[];\n\tprivate readonly _color2id: Map;\n\n\tconstructor() {\n\t\tthis._lastColorId = 0;\n\t\tthis._id2color = [];\n\t\tthis._color2id = new Map();\n\t}\n\n\tpublic getId(color: string | null): ColorId {\n\t\tif (color === null) {\n\t\t\treturn 0;\n\t\t}\n\t\tconst match = color.match(colorRegExp);\n\t\tif (!match) {\n\t\t\tthrow new Error('Illegal value for token color: ' + color);\n\t\t}\n\t\tcolor = match[1].toUpperCase();\n\t\tlet value = this._color2id.get(color);\n\t\tif (value) {\n\t\t\treturn value;\n\t\t}\n\t\tvalue = ++this._lastColorId;\n\t\tthis._color2id.set(color, value);\n\t\tthis._id2color[value] = Color.fromHex('#' + color);\n\t\treturn value;\n\t}\n\n\tpublic getColorMap(): Color[] {\n\t\treturn this._id2color.slice(0);\n\t}\n\n}\n\nexport class TokenTheme {\n\n\tpublic static createFromRawTokenTheme(source: ITokenThemeRule[], customTokenColors: string[]): TokenTheme {\n\t\treturn this.createFromParsedTokenTheme(parseTokenTheme(source), customTokenColors);\n\t}\n\n\tpublic static createFromParsedTokenTheme(source: ParsedTokenThemeRule[], customTokenColors: string[]): TokenTheme {\n\t\treturn resolveParsedTokenThemeRules(source, customTokenColors);\n\t}\n\n\tprivate readonly _colorMap: ColorMap;\n\tprivate readonly _root: ThemeTrieElement;\n\tprivate readonly _cache: Map;\n\n\tconstructor(colorMap: ColorMap, root: ThemeTrieElement) {\n\t\tthis._colorMap = colorMap;\n\t\tthis._root = root;\n\t\tthis._cache = new Map();\n\t}\n\n\tpublic getColorMap(): Color[] {\n\t\treturn this._colorMap.getColorMap();\n\t}\n\n\tpublic _match(token: string): ThemeTrieElementRule {\n\t\treturn this._root.match(token);\n\t}\n\n\tpublic match(languageId: LanguageId, token: string): number {\n\t\t// The cache contains the metadata without the language bits set.\n\t\tlet result = this._cache.get(token);\n\t\tif (typeof result === 'undefined') {\n\t\t\tconst rule = this._match(token);\n\t\t\tconst standardToken = toStandardTokenType(token);\n\t\t\tresult = (\n\t\t\t\trule.metadata\n\t\t\t\t| (standardToken << MetadataConsts.TOKEN_TYPE_OFFSET)\n\t\t\t) >>> 0;\n\t\t\tthis._cache.set(token, result);\n\t\t}\n\n\t\treturn (\n\t\t\tresult\n\t\t\t| (languageId << MetadataConsts.LANGUAGEID_OFFSET)\n\t\t) >>> 0;\n\t}\n}\n\nconst STANDARD_TOKEN_TYPE_REGEXP = /\\b(comment|string|regex|regexp)\\b/;\nexport function toStandardTokenType(tokenType: string): StandardTokenType {\n\tconst m = tokenType.match(STANDARD_TOKEN_TYPE_REGEXP);\n\tif (!m) {\n\t\treturn StandardTokenType.Other;\n\t}\n\tswitch (m[1]) {\n\t\tcase 'comment':\n\t\t\treturn StandardTokenType.Comment;\n\t\tcase 'string':\n\t\t\treturn StandardTokenType.String;\n\t\tcase 'regex':\n\t\t\treturn StandardTokenType.RegEx;\n\t\tcase 'regexp':\n\t\t\treturn StandardTokenType.RegEx;\n\t}\n\tthrow new Error('Unexpected match for standard token type!');\n}\n\nexport function strcmp(a: string, b: string): number {\n\tif (a < b) {\n\t\treturn -1;\n\t}\n\tif (a > b) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nexport class ThemeTrieElementRule {\n\t_themeTrieElementRuleBrand: void = undefined;\n\n\tprivate _fontStyle: FontStyle;\n\tprivate _foreground: ColorId;\n\tprivate _background: ColorId;\n\tpublic metadata: number;\n\n\tconstructor(fontStyle: FontStyle, foreground: ColorId, background: ColorId) {\n\t\tthis._fontStyle = fontStyle;\n\t\tthis._foreground = foreground;\n\t\tthis._background = background;\n\t\tthis.metadata = (\n\t\t\t(this._fontStyle << MetadataConsts.FONT_STYLE_OFFSET)\n\t\t\t| (this._foreground << MetadataConsts.FOREGROUND_OFFSET)\n\t\t\t| (this._background << MetadataConsts.BACKGROUND_OFFSET)\n\t\t) >>> 0;\n\t}\n\n\tpublic clone(): ThemeTrieElementRule {\n\t\treturn new ThemeTrieElementRule(this._fontStyle, this._foreground, this._background);\n\t}\n\n\tpublic acceptOverwrite(fontStyle: FontStyle, foreground: ColorId, background: ColorId): void {\n\t\tif (fontStyle !== FontStyle.NotSet) {\n\t\t\tthis._fontStyle = fontStyle;\n\t\t}\n\t\tif (foreground !== ColorId.None) {\n\t\t\tthis._foreground = foreground;\n\t\t}\n\t\tif (background !== ColorId.None) {\n\t\t\tthis._background = background;\n\t\t}\n\t\tthis.metadata = (\n\t\t\t(this._fontStyle << MetadataConsts.FONT_STYLE_OFFSET)\n\t\t\t| (this._foreground << MetadataConsts.FOREGROUND_OFFSET)\n\t\t\t| (this._background << MetadataConsts.BACKGROUND_OFFSET)\n\t\t) >>> 0;\n\t}\n}\n\nexport class ThemeTrieElement {\n\t_themeTrieElementBrand: void = undefined;\n\n\tprivate readonly _mainRule: ThemeTrieElementRule;\n\tprivate readonly _children: Map;\n\n\tconstructor(mainRule: ThemeTrieElementRule) {\n\t\tthis._mainRule = mainRule;\n\t\tthis._children = new Map();\n\t}\n\n\tpublic match(token: string): ThemeTrieElementRule {\n\t\tif (token === '') {\n\t\t\treturn this._mainRule;\n\t\t}\n\n\t\tconst dotIndex = token.indexOf('.');\n\t\tlet head: string;\n\t\tlet tail: string;\n\t\tif (dotIndex === -1) {\n\t\t\thead = token;\n\t\t\ttail = '';\n\t\t} else {\n\t\t\thead = token.substring(0, dotIndex);\n\t\t\ttail = token.substring(dotIndex + 1);\n\t\t}\n\n\t\tconst child = this._children.get(head);\n\t\tif (typeof child !== 'undefined') {\n\t\t\treturn child.match(tail);\n\t\t}\n\n\t\treturn this._mainRule;\n\t}\n\n\tpublic insert(token: string, fontStyle: FontStyle, foreground: ColorId, background: ColorId): void {\n\t\tif (token === '') {\n\t\t\t// Merge into the main rule\n\t\t\tthis._mainRule.acceptOverwrite(fontStyle, foreground, background);\n\t\t\treturn;\n\t\t}\n\n\t\tconst dotIndex = token.indexOf('.');\n\t\tlet head: string;\n\t\tlet tail: string;\n\t\tif (dotIndex === -1) {\n\t\t\thead = token;\n\t\t\ttail = '';\n\t\t} else {\n\t\t\thead = token.substring(0, dotIndex);\n\t\t\ttail = token.substring(dotIndex + 1);\n\t\t}\n\n\t\tlet child = this._children.get(head);\n\t\tif (typeof child === 'undefined') {\n\t\t\tchild = new ThemeTrieElement(this._mainRule.clone());\n\t\t\tthis._children.set(head, child);\n\t\t}\n\n\t\tchild.insert(tail, fontStyle, foreground, background);\n\t}\n}\n\nexport function generateTokensCSSForColorMap(colorMap: readonly Color[]): string {\n\tconst rules: string[] = [];\n\tfor (let i = 1, len = colorMap.length; i < len; i++) {\n\t\tconst color = colorMap[i];\n\t\trules[i] = `.mtk${i} { color: ${color}; }`;\n\t}\n\trules.push('.mtki { font-style: italic; }');\n\trules.push('.mtkb { font-weight: bold; }');\n\trules.push('.mtku { text-decoration: underline; text-underline-position: under; }');\n\trules.push('.mtks { text-decoration: line-through; }');\n\trules.push('.mtks.mtku { text-decoration: underline line-through; text-underline-position: under; }');\n\treturn rules.join('\\n');\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport { IMarkdownString } from 'vs/base/common/htmlContent';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { URI } from 'vs/base/common/uri';\nimport { LineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { IPosition, Position } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { IModelContentChange, IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent, IModelTokensChangedEvent, ModelInjectedTextChangedEvent, ModelRawContentChangedEvent } from 'vs/editor/common/textModelEvents';\nimport { WordCharacterClassifier } from 'vs/editor/common/core/wordCharacterClassifier';\nimport { FormattingOptions, StandardTokenType } from 'vs/editor/common/languages';\nimport { ThemeColor } from 'vs/platform/theme/common/themeService';\nimport { SparseMultilineTokens } from 'vs/editor/common/tokens/sparseMultilineTokens';\nimport { TextChange } from 'vs/editor/common/core/textChange';\nimport { equals } from 'vs/base/common/objects';\nimport { IBracketPairsTextModelPart } from 'vs/editor/common/textModelBracketPairs';\nimport { IGuidesTextModelPart } from 'vs/editor/common/textModelGuides';\nimport { IWordAtPosition } from 'vs/editor/common/core/wordHelper';\n\n/**\n * Vertical Lane in the overview ruler of the editor.\n */\nexport enum OverviewRulerLane {\n\tLeft = 1,\n\tCenter = 2,\n\tRight = 4,\n\tFull = 7\n}\n\n/**\n * Position in the minimap to render the decoration.\n */\nexport enum MinimapPosition {\n\tInline = 1,\n\tGutter = 2\n}\n\nexport interface IDecorationOptions {\n\t/**\n\t * CSS color to render.\n\t * e.g.: rgba(100, 100, 100, 0.5) or a color from the color registry\n\t */\n\tcolor: string | ThemeColor | undefined;\n\t/**\n\t * CSS color to render.\n\t * e.g.: rgba(100, 100, 100, 0.5) or a color from the color registry\n\t */\n\tdarkColor?: string | ThemeColor;\n}\n\n/**\n * Options for rendering a model decoration in the overview ruler.\n */\nexport interface IModelDecorationOverviewRulerOptions extends IDecorationOptions {\n\t/**\n\t * The position in the overview ruler.\n\t */\n\tposition: OverviewRulerLane;\n}\n\n/**\n * Options for rendering a model decoration in the overview ruler.\n */\nexport interface IModelDecorationMinimapOptions extends IDecorationOptions {\n\t/**\n\t * The position in the overview ruler.\n\t */\n\tposition: MinimapPosition;\n}\n\n/**\n * Options for a model decoration.\n */\nexport interface IModelDecorationOptions {\n\t/**\n\t * A debug description that can be used for inspecting model decorations.\n\t * @internal\n\t */\n\tdescription: string;\n\t/**\n\t * Customize the growing behavior of the decoration when typing at the edges of the decoration.\n\t * Defaults to TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges\n\t */\n\tstickiness?: TrackedRangeStickiness;\n\t/**\n\t * CSS class name describing the decoration.\n\t */\n\tclassName?: string | null;\n\t/**\n\t * Message to be rendered when hovering over the glyph margin decoration.\n\t */\n\tglyphMarginHoverMessage?: IMarkdownString | IMarkdownString[] | null;\n\t/**\n\t * Array of MarkdownString to render as the decoration message.\n\t */\n\thoverMessage?: IMarkdownString | IMarkdownString[] | null;\n\t/**\n\t * Should the decoration expand to encompass a whole line.\n\t */\n\tisWholeLine?: boolean;\n\t/**\n\t * Always render the decoration (even when the range it encompasses is collapsed).\n\t * @internal\n\t */\n\tshowIfCollapsed?: boolean;\n\t/**\n\t * Collapse the decoration if its entire range is being replaced via an edit.\n\t * @internal\n\t */\n\tcollapseOnReplaceEdit?: boolean;\n\t/**\n\t * Specifies the stack order of a decoration.\n\t * A decoration with greater stack order is always in front of a decoration with\n\t * a lower stack order when the decorations are on the same line.\n\t */\n\tzIndex?: number;\n\t/**\n\t * If set, render this decoration in the overview ruler.\n\t */\n\toverviewRuler?: IModelDecorationOverviewRulerOptions | null;\n\t/**\n\t * If set, render this decoration in the minimap.\n\t */\n\tminimap?: IModelDecorationMinimapOptions | null;\n\t/**\n\t * If set, the decoration will be rendered in the glyph margin with this CSS class name.\n\t */\n\tglyphMarginClassName?: string | null;\n\t/**\n\t * If set, the decoration will be rendered in the lines decorations with this CSS class name.\n\t */\n\tlinesDecorationsClassName?: string | null;\n\t/**\n\t * If set, the decoration will be rendered in the lines decorations with this CSS class name, but only for the first line in case of line wrapping.\n\t */\n\tfirstLineDecorationClassName?: string | null;\n\t/**\n\t * If set, the decoration will be rendered in the margin (covering its full width) with this CSS class name.\n\t */\n\tmarginClassName?: string | null;\n\t/**\n\t * If set, the decoration will be rendered inline with the text with this CSS class name.\n\t * Please use this only for CSS rules that must impact the text. For example, use `className`\n\t * to have a background color decoration.\n\t */\n\tinlineClassName?: string | null;\n\t/**\n\t * If there is an `inlineClassName` which affects letter spacing.\n\t */\n\tinlineClassNameAffectsLetterSpacing?: boolean;\n\t/**\n\t * If set, the decoration will be rendered before the text with this CSS class name.\n\t */\n\tbeforeContentClassName?: string | null;\n\t/**\n\t * If set, the decoration will be rendered after the text with this CSS class name.\n\t */\n\tafterContentClassName?: string | null;\n\t/**\n\t * If set, text will be injected in the view after the range.\n\t */\n\tafter?: InjectedTextOptions | null;\n\n\t/**\n\t * If set, text will be injected in the view before the range.\n\t */\n\tbefore?: InjectedTextOptions | null;\n\n\t/**\n\t * If set, this decoration will not be rendered for comment tokens.\n\t * @internal\n\t*/\n\thideInCommentTokens?: boolean | null;\n\n\t/**\n\t * If set, this decoration will not be rendered for string tokens.\n\t * @internal\n\t*/\n\thideInStringTokens?: boolean | null;\n}\n\n/**\n * Configures text that is injected into the view without changing the underlying document.\n*/\nexport interface InjectedTextOptions {\n\t/**\n\t * Sets the text to inject. Must be a single line.\n\t */\n\treadonly content: string;\n\n\t/**\n\t * If set, the decoration will be rendered inline with the text with this CSS class name.\n\t */\n\treadonly inlineClassName?: string | null;\n\n\t/**\n\t * If there is an `inlineClassName` which affects letter spacing.\n\t */\n\treadonly inlineClassNameAffectsLetterSpacing?: boolean;\n\n\t/**\n\t * This field allows to attach data to this injected text.\n\t * The data can be read when injected texts at a given position are queried.\n\t */\n\treadonly attachedData?: unknown;\n\n\t/**\n\t * Configures cursor stops around injected text.\n\t * Defaults to {@link InjectedTextCursorStops.Both}.\n\t*/\n\treadonly cursorStops?: InjectedTextCursorStops | null;\n}\n\nexport enum InjectedTextCursorStops {\n\tBoth,\n\tRight,\n\tLeft,\n\tNone\n}\n\n/**\n * New model decorations.\n */\nexport interface IModelDeltaDecoration {\n\t/**\n\t * Range that this decoration covers.\n\t */\n\trange: IRange;\n\t/**\n\t * Options associated with this decoration.\n\t */\n\toptions: IModelDecorationOptions;\n}\n\n/**\n * A decoration in the model.\n */\nexport interface IModelDecoration {\n\t/**\n\t * Identifier for a decoration.\n\t */\n\treadonly id: string;\n\t/**\n\t * Identifier for a decoration's owner.\n\t */\n\treadonly ownerId: number;\n\t/**\n\t * Range that this decoration covers.\n\t */\n\treadonly range: Range;\n\t/**\n\t * Options associated with this decoration.\n\t */\n\treadonly options: IModelDecorationOptions;\n}\n\n/**\n * An accessor that can add, change or remove model decorations.\n * @internal\n */\nexport interface IModelDecorationsChangeAccessor {\n\t/**\n\t * Add a new decoration.\n\t * @param range Range that this decoration covers.\n\t * @param options Options associated with this decoration.\n\t * @return An unique identifier associated with this decoration.\n\t */\n\taddDecoration(range: IRange, options: IModelDecorationOptions): string;\n\t/**\n\t * Change the range that an existing decoration covers.\n\t * @param id The unique identifier associated with the decoration.\n\t * @param newRange The new range that this decoration covers.\n\t */\n\tchangeDecoration(id: string, newRange: IRange): void;\n\t/**\n\t * Change the options associated with an existing decoration.\n\t * @param id The unique identifier associated with the decoration.\n\t * @param newOptions The new options associated with this decoration.\n\t */\n\tchangeDecorationOptions(id: string, newOptions: IModelDecorationOptions): void;\n\t/**\n\t * Remove an existing decoration.\n\t * @param id The unique identifier associated with the decoration.\n\t */\n\tremoveDecoration(id: string): void;\n\t/**\n\t * Perform a minimum amount of operations, in order to transform the decorations\n\t * identified by `oldDecorations` to the decorations described by `newDecorations`\n\t * and returns the new identifiers associated with the resulting decorations.\n\t *\n\t * @param oldDecorations Array containing previous decorations identifiers.\n\t * @param newDecorations Array describing what decorations should result after the call.\n\t * @return An array containing the new decorations identifiers.\n\t */\n\tdeltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[];\n}\n\n/**\n * End of line character preference.\n */\nexport const enum EndOfLinePreference {\n\t/**\n\t * Use the end of line character identified in the text buffer.\n\t */\n\tTextDefined = 0,\n\t/**\n\t * Use line feed (\\n) as the end of line character.\n\t */\n\tLF = 1,\n\t/**\n\t * Use carriage return and line feed (\\r\\n) as the end of line character.\n\t */\n\tCRLF = 2\n}\n\n/**\n * The default end of line to use when instantiating models.\n */\nexport const enum DefaultEndOfLine {\n\t/**\n\t * Use line feed (\\n) as the end of line character.\n\t */\n\tLF = 1,\n\t/**\n\t * Use carriage return and line feed (\\r\\n) as the end of line character.\n\t */\n\tCRLF = 2\n}\n\n/**\n * End of line character preference.\n */\nexport const enum EndOfLineSequence {\n\t/**\n\t * Use line feed (\\n) as the end of line character.\n\t */\n\tLF = 0,\n\t/**\n\t * Use carriage return and line feed (\\r\\n) as the end of line character.\n\t */\n\tCRLF = 1\n}\n\n/**\n * An identifier for a single edit operation.\n * @internal\n */\nexport interface ISingleEditOperationIdentifier {\n\t/**\n\t * Identifier major\n\t */\n\tmajor: number;\n\t/**\n\t * Identifier minor\n\t */\n\tminor: number;\n}\n\n/**\n * A single edit operation, that has an identifier.\n */\nexport interface IIdentifiedSingleEditOperation {\n\t/**\n\t * An identifier associated with this single edit operation.\n\t * @internal\n\t */\n\tidentifier?: ISingleEditOperationIdentifier | null;\n\t/**\n\t * The range to replace. This can be empty to emulate a simple insert.\n\t */\n\trange: IRange;\n\t/**\n\t * The text to replace with. This can be null to emulate a simple delete.\n\t */\n\ttext: string | null;\n\t/**\n\t * This indicates that this operation has \"insert\" semantics.\n\t * i.e. forceMoveMarkers = true => if `range` is collapsed, all markers at the position will be moved.\n\t */\n\tforceMoveMarkers?: boolean;\n\t/**\n\t * This indicates that this operation is inserting automatic whitespace\n\t * that can be removed on next model edit operation if `config.trimAutoWhitespace` is true.\n\t * @internal\n\t */\n\tisAutoWhitespaceEdit?: boolean;\n\t/**\n\t * This indicates that this operation is in a set of operations that are tracked and should not be \"simplified\".\n\t * @internal\n\t */\n\t_isTracked?: boolean;\n}\n\nexport interface IValidEditOperation {\n\t/**\n\t * An identifier associated with this single edit operation.\n\t * @internal\n\t */\n\tidentifier: ISingleEditOperationIdentifier | null;\n\t/**\n\t * The range to replace. This can be empty to emulate a simple insert.\n\t */\n\trange: Range;\n\t/**\n\t * The text to replace with. This can be empty to emulate a simple delete.\n\t */\n\ttext: string;\n\t/**\n\t * @internal\n\t */\n\ttextChange: TextChange;\n}\n\n/**\n * A callback that can compute the cursor state after applying a series of edit operations.\n */\nexport interface ICursorStateComputer {\n\t/**\n\t * A callback that can compute the resulting cursors state after some edit operations have been executed.\n\t */\n\t(inverseEditOperations: IValidEditOperation[]): Selection[] | null;\n}\n\nexport class TextModelResolvedOptions {\n\t_textModelResolvedOptionsBrand: void = undefined;\n\n\treadonly tabSize: number;\n\treadonly indentSize: number;\n\treadonly insertSpaces: boolean;\n\treadonly defaultEOL: DefaultEndOfLine;\n\treadonly trimAutoWhitespace: boolean;\n\treadonly bracketPairColorizationOptions: BracketPairColorizationOptions;\n\n\t/**\n\t * @internal\n\t */\n\tconstructor(src: {\n\t\ttabSize: number;\n\t\tindentSize: number;\n\t\tinsertSpaces: boolean;\n\t\tdefaultEOL: DefaultEndOfLine;\n\t\ttrimAutoWhitespace: boolean;\n\t\tbracketPairColorizationOptions: BracketPairColorizationOptions;\n\t}) {\n\t\tthis.tabSize = Math.max(1, src.tabSize | 0);\n\t\tthis.indentSize = src.tabSize | 0;\n\t\tthis.insertSpaces = Boolean(src.insertSpaces);\n\t\tthis.defaultEOL = src.defaultEOL | 0;\n\t\tthis.trimAutoWhitespace = Boolean(src.trimAutoWhitespace);\n\t\tthis.bracketPairColorizationOptions = src.bracketPairColorizationOptions;\n\t}\n\n\t/**\n\t * @internal\n\t */\n\tpublic equals(other: TextModelResolvedOptions): boolean {\n\t\treturn (\n\t\t\tthis.tabSize === other.tabSize\n\t\t\t&& this.indentSize === other.indentSize\n\t\t\t&& this.insertSpaces === other.insertSpaces\n\t\t\t&& this.defaultEOL === other.defaultEOL\n\t\t\t&& this.trimAutoWhitespace === other.trimAutoWhitespace\n\t\t\t&& equals(this.bracketPairColorizationOptions, other.bracketPairColorizationOptions)\n\t\t);\n\t}\n\n\t/**\n\t * @internal\n\t */\n\tpublic createChangeEvent(newOpts: TextModelResolvedOptions): IModelOptionsChangedEvent {\n\t\treturn {\n\t\t\ttabSize: this.tabSize !== newOpts.tabSize,\n\t\t\tindentSize: this.indentSize !== newOpts.indentSize,\n\t\t\tinsertSpaces: this.insertSpaces !== newOpts.insertSpaces,\n\t\t\ttrimAutoWhitespace: this.trimAutoWhitespace !== newOpts.trimAutoWhitespace,\n\t\t};\n\t}\n}\n\n/**\n * @internal\n */\nexport interface ITextModelCreationOptions {\n\ttabSize: number;\n\tindentSize: number;\n\tinsertSpaces: boolean;\n\tdetectIndentation: boolean;\n\ttrimAutoWhitespace: boolean;\n\tdefaultEOL: DefaultEndOfLine;\n\tisForSimpleWidget: boolean;\n\tlargeFileOptimizations: boolean;\n\tbracketPairColorizationOptions: BracketPairColorizationOptions;\n}\n\nexport interface BracketPairColorizationOptions {\n\tenabled: boolean;\n}\n\nexport interface ITextModelUpdateOptions {\n\ttabSize?: number;\n\tindentSize?: number;\n\tinsertSpaces?: boolean;\n\ttrimAutoWhitespace?: boolean;\n\tbracketColorizationOptions?: BracketPairColorizationOptions;\n}\n\nexport class FindMatch {\n\t_findMatchBrand: void = undefined;\n\n\tpublic readonly range: Range;\n\tpublic readonly matches: string[] | null;\n\n\t/**\n\t * @internal\n\t */\n\tconstructor(range: Range, matches: string[] | null) {\n\t\tthis.range = range;\n\t\tthis.matches = matches;\n\t}\n}\n\n/**\n * Describes the behavior of decorations when typing/editing near their edges.\n * Note: Please do not edit the values, as they very carefully match `DecorationRangeBehavior`\n */\nexport const enum TrackedRangeStickiness {\n\tAlwaysGrowsWhenTypingAtEdges = 0,\n\tNeverGrowsWhenTypingAtEdges = 1,\n\tGrowsOnlyWhenTypingBefore = 2,\n\tGrowsOnlyWhenTypingAfter = 3,\n}\n\n/**\n * Text snapshot that works like an iterator.\n * Will try to return chunks of roughly ~64KB size.\n * Will return null when finished.\n *\n * @internal\n */\nexport interface ITextSnapshot {\n\tread(): string | null;\n}\n\n/**\n * A model.\n */\nexport interface ITextModel {\n\n\t/**\n\t * Gets the resource associated with this editor model.\n\t */\n\treadonly uri: URI;\n\n\t/**\n\t * A unique identifier associated with this model.\n\t */\n\treadonly id: string;\n\n\t/**\n\t * This model is constructed for a simple widget code editor.\n\t * @internal\n\t */\n\treadonly isForSimpleWidget: boolean;\n\n\t/**\n\t * If true, the text model might contain RTL.\n\t * If false, the text model **contains only** contain LTR.\n\t * @internal\n\t */\n\tmightContainRTL(): boolean;\n\n\t/**\n\t * If true, the text model might contain LINE SEPARATOR (LS), PARAGRAPH SEPARATOR (PS).\n\t * If false, the text model definitely does not contain these.\n\t * @internal\n\t */\n\tmightContainUnusualLineTerminators(): boolean;\n\n\t/**\n\t * @internal\n\t */\n\tremoveUnusualLineTerminators(selections?: Selection[]): void;\n\n\t/**\n\t * If true, the text model might contain non basic ASCII.\n\t * If false, the text model **contains only** basic ASCII.\n\t * @internal\n\t */\n\tmightContainNonBasicASCII(): boolean;\n\n\t/**\n\t * Get the resolved options for this model.\n\t */\n\tgetOptions(): TextModelResolvedOptions;\n\n\t/**\n\t * Get the formatting options for this model.\n\t * @internal\n\t */\n\tgetFormattingOptions(): FormattingOptions;\n\n\t/**\n\t * Get the current version id of the model.\n\t * Anytime a change happens to the model (even undo/redo),\n\t * the version id is incremented.\n\t */\n\tgetVersionId(): number;\n\n\t/**\n\t * Get the alternative version id of the model.\n\t * This alternative version id is not always incremented,\n\t * it will return the same values in the case of undo-redo.\n\t */\n\tgetAlternativeVersionId(): number;\n\n\t/**\n\t * Replace the entire text buffer value contained in this model.\n\t */\n\tsetValue(newValue: string): void;\n\n\t/**\n\t * Get the text stored in this model.\n\t * @param eol The end of line character preference. Defaults to `EndOfLinePreference.TextDefined`.\n\t * @param preserverBOM Preserve a BOM character if it was detected when the model was constructed.\n\t * @return The text.\n\t */\n\tgetValue(eol?: EndOfLinePreference, preserveBOM?: boolean): string;\n\n\t/**\n\t * Get the text stored in this model.\n\t * @param preserverBOM Preserve a BOM character if it was detected when the model was constructed.\n\t * @return The text snapshot (it is safe to consume it asynchronously).\n\t * @internal\n\t */\n\tcreateSnapshot(preserveBOM?: boolean): ITextSnapshot;\n\n\t/**\n\t * Get the length of the text stored in this model.\n\t */\n\tgetValueLength(eol?: EndOfLinePreference, preserveBOM?: boolean): number;\n\n\t/**\n\t * Get the text in a certain range.\n\t * @param range The range describing what text to get.\n\t * @param eol The end of line character preference. This will only be used for multiline ranges. Defaults to `EndOfLinePreference.TextDefined`.\n\t * @return The text.\n\t */\n\tgetValueInRange(range: IRange, eol?: EndOfLinePreference): string;\n\n\t/**\n\t * Get the length of text in a certain range.\n\t * @param range The range describing what text length to get.\n\t * @return The text length.\n\t */\n\tgetValueLengthInRange(range: IRange): number;\n\n\t/**\n\t * Get the character count of text in a certain range.\n\t * @param range The range describing what text length to get.\n\t */\n\tgetCharacterCountInRange(range: IRange): number;\n\n\t/**\n\t * Splits characters in two buckets. First bucket (A) is of characters that\n\t * sit in lines with length < `LONG_LINE_BOUNDARY`. Second bucket (B) is of\n\t * characters that sit in lines with length >= `LONG_LINE_BOUNDARY`.\n\t * If count(B) > count(A) return true. Returns false otherwise.\n\t * @internal\n\t */\n\tisDominatedByLongLines(): boolean;\n\n\t/**\n\t * Get the number of lines in the model.\n\t */\n\tgetLineCount(): number;\n\n\t/**\n\t * Get the text for a certain line.\n\t */\n\tgetLineContent(lineNumber: number): string;\n\n\t/**\n\t * Get the text length for a certain line.\n\t */\n\tgetLineLength(lineNumber: number): number;\n\n\t/**\n\t * Get the text for all lines.\n\t */\n\tgetLinesContent(): string[];\n\n\t/**\n\t * Get the end of line sequence predominantly used in the text buffer.\n\t * @return EOL char sequence (e.g.: '\\n' or '\\r\\n').\n\t */\n\tgetEOL(): string;\n\n\t/**\n\t * Get the end of line sequence predominantly used in the text buffer.\n\t */\n\tgetEndOfLineSequence(): EndOfLineSequence;\n\n\t/**\n\t * Get the minimum legal column for line at `lineNumber`\n\t */\n\tgetLineMinColumn(lineNumber: number): number;\n\n\t/**\n\t * Get the maximum legal column for line at `lineNumber`\n\t */\n\tgetLineMaxColumn(lineNumber: number): number;\n\n\t/**\n\t * Returns the column before the first non whitespace character for line at `lineNumber`.\n\t * Returns 0 if line is empty or contains only whitespace.\n\t */\n\tgetLineFirstNonWhitespaceColumn(lineNumber: number): number;\n\n\t/**\n\t * Returns the column after the last non whitespace character for line at `lineNumber`.\n\t * Returns 0 if line is empty or contains only whitespace.\n\t */\n\tgetLineLastNonWhitespaceColumn(lineNumber: number): number;\n\n\t/**\n\t * Create a valid position.\n\t */\n\tvalidatePosition(position: IPosition): Position;\n\n\t/**\n\t * Advances the given position by the given offset (negative offsets are also accepted)\n\t * and returns it as a new valid position.\n\t *\n\t * If the offset and position are such that their combination goes beyond the beginning or\n\t * end of the model, throws an exception.\n\t *\n\t * If the offset is such that the new position would be in the middle of a multi-byte\n\t * line terminator, throws an exception.\n\t */\n\tmodifyPosition(position: IPosition, offset: number): Position;\n\n\t/**\n\t * Create a valid range.\n\t */\n\tvalidateRange(range: IRange): Range;\n\n\t/**\n\t * Converts the position to a zero-based offset.\n\t *\n\t * The position will be [adjusted](#TextDocument.validatePosition).\n\t *\n\t * @param position A position.\n\t * @return A valid zero-based offset.\n\t */\n\tgetOffsetAt(position: IPosition): number;\n\n\t/**\n\t * Converts a zero-based offset to a position.\n\t *\n\t * @param offset A zero-based offset.\n\t * @return A valid [position](#Position).\n\t */\n\tgetPositionAt(offset: number): Position;\n\n\t/**\n\t * Get a range covering the entire model.\n\t */\n\tgetFullModelRange(): Range;\n\n\t/**\n\t * Returns if the model was disposed or not.\n\t */\n\tisDisposed(): boolean;\n\n\t/**\n\t * @internal\n\t */\n\ttokenizeViewport(startLineNumber: number, endLineNumber: number): void;\n\n\t/**\n\t * This model is so large that it would not be a good idea to sync it over\n\t * to web workers or other places.\n\t * @internal\n\t */\n\tisTooLargeForSyncing(): boolean;\n\n\t/**\n\t * The file is so large, that even tokenization is disabled.\n\t * @internal\n\t */\n\tisTooLargeForTokenization(): boolean;\n\n\t/**\n\t * Search the model.\n\t * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.\n\t * @param searchOnlyEditableRange Limit the searching to only search inside the editable range of the model.\n\t * @param isRegex Used to indicate that `searchString` is a regular expression.\n\t * @param matchCase Force the matching to match lower/upper case exactly.\n\t * @param wordSeparators Force the matching to match entire words only. Pass null otherwise.\n\t * @param captureMatches The result will contain the captured groups.\n\t * @param limitResultCount Limit the number of results\n\t * @return The ranges where the matches are. It is empty if not matches have been found.\n\t */\n\tfindMatches(searchString: string, searchOnlyEditableRange: boolean, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean, limitResultCount?: number): FindMatch[];\n\t/**\n\t * Search the model.\n\t * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.\n\t * @param searchScope Limit the searching to only search inside these ranges.\n\t * @param isRegex Used to indicate that `searchString` is a regular expression.\n\t * @param matchCase Force the matching to match lower/upper case exactly.\n\t * @param wordSeparators Force the matching to match entire words only. Pass null otherwise.\n\t * @param captureMatches The result will contain the captured groups.\n\t * @param limitResultCount Limit the number of results\n\t * @return The ranges where the matches are. It is empty if no matches have been found.\n\t */\n\tfindMatches(searchString: string, searchScope: IRange | IRange[], isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean, limitResultCount?: number): FindMatch[];\n\t/**\n\t * Search the model for the next match. Loops to the beginning of the model if needed.\n\t * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.\n\t * @param searchStart Start the searching at the specified position.\n\t * @param isRegex Used to indicate that `searchString` is a regular expression.\n\t * @param matchCase Force the matching to match lower/upper case exactly.\n\t * @param wordSeparators Force the matching to match entire words only. Pass null otherwise.\n\t * @param captureMatches The result will contain the captured groups.\n\t * @return The range where the next match is. It is null if no next match has been found.\n\t */\n\tfindNextMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch | null;\n\t/**\n\t * Search the model for the previous match. Loops to the end of the model if needed.\n\t * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.\n\t * @param searchStart Start the searching at the specified position.\n\t * @param isRegex Used to indicate that `searchString` is a regular expression.\n\t * @param matchCase Force the matching to match lower/upper case exactly.\n\t * @param wordSeparators Force the matching to match entire words only. Pass null otherwise.\n\t * @param captureMatches The result will contain the captured groups.\n\t * @return The range where the previous match is. It is null if no previous match has been found.\n\t */\n\tfindPreviousMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch | null;\n\n\t/**\n\t * @internal\n\t */\n\tsetSemanticTokens(tokens: SparseMultilineTokens[] | null, isComplete: boolean): void;\n\n\t/**\n\t * @internal\n\t */\n\tsetPartialSemanticTokens(range: Range, tokens: SparseMultilineTokens[] | null): void;\n\n\t/**\n\t * @internal\n\t */\n\thasCompleteSemanticTokens(): boolean;\n\n\t/**\n\t * @internal\n\t */\n\thasSomeSemanticTokens(): boolean;\n\n\t/**\n\t * Flush all tokenization state.\n\t * @internal\n\t */\n\tresetTokenization(): void;\n\n\t/**\n\t * Force tokenization information for `lineNumber` to be accurate.\n\t * @internal\n\t */\n\tforceTokenization(lineNumber: number): void;\n\n\t/**\n\t * If it is cheap, force tokenization information for `lineNumber` to be accurate.\n\t * This is based on a heuristic.\n\t * @internal\n\t */\n\ttokenizeIfCheap(lineNumber: number): void;\n\n\t/**\n\t * Check if calling `forceTokenization` for this `lineNumber` will be cheap (time-wise).\n\t * This is based on a heuristic.\n\t * @internal\n\t */\n\tisCheapToTokenize(lineNumber: number): boolean;\n\n\t/**\n\t * Get the tokens for the line `lineNumber`.\n\t * The tokens might be inaccurate. Use `forceTokenization` to ensure accurate tokens.\n\t * @internal\n\t */\n\tgetLineTokens(lineNumber: number): LineTokens;\n\n\t/**\n\t * Get the language associated with this model.\n\t */\n\tgetLanguageId(): string;\n\n\t/**\n\t * Returns the real (inner-most) language mode at a given position.\n\t * The result might be inaccurate. Use `forceTokenization` to ensure accurate tokens.\n\t * @internal\n\t */\n\tgetLanguageIdAtPosition(lineNumber: number, column: number): string;\n\n\t/**\n\t * Returns the standard token type for a character if the character were to be inserted at\n\t * the given position. If the result cannot be accurate, it returns null.\n\t * @internal\n\t */\n\tgetTokenTypeIfInsertingCharacter(lineNumber: number, column: number, character: string): StandardTokenType;\n\n\t/**\n\t * @internal\n\t*/\n\ttokenizeLineWithEdit(position: IPosition, length: number, newText: string): LineTokens | null;\n\n\t/**\n\t * Get the word under or besides `position`.\n\t * @param position The position to look for a word.\n\t * @return The word under or besides `position`. Might be null.\n\t */\n\tgetWordAtPosition(position: IPosition): IWordAtPosition | null;\n\n\t/**\n\t * Get the word under or besides `position` trimmed to `position`.column\n\t * @param position The position to look for a word.\n\t * @return The word under or besides `position`. Will never be null.\n\t */\n\tgetWordUntilPosition(position: IPosition): IWordAtPosition;\n\n\t/**\n\t * Change the decorations. The callback will be called with a change accessor\n\t * that becomes invalid as soon as the callback finishes executing.\n\t * This allows for all events to be queued up until the change\n\t * is completed. Returns whatever the callback returns.\n\t * @param ownerId Identifies the editor id in which these decorations should appear. If no `ownerId` is provided, the decorations will appear in all editors that attach this model.\n\t * @internal\n\t */\n\tchangeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T, ownerId?: number): T | null;\n\n\t/**\n\t * Perform a minimum amount of operations, in order to transform the decorations\n\t * identified by `oldDecorations` to the decorations described by `newDecorations`\n\t * and returns the new identifiers associated with the resulting decorations.\n\t *\n\t * @param oldDecorations Array containing previous decorations identifiers.\n\t * @param newDecorations Array describing what decorations should result after the call.\n\t * @param ownerId Identifies the editor id in which these decorations should appear. If no `ownerId` is provided, the decorations will appear in all editors that attach this model.\n\t * @return An array containing the new decorations identifiers.\n\t */\n\tdeltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[], ownerId?: number): string[];\n\n\t/**\n\t * Remove all decorations that have been added with this specific ownerId.\n\t * @param ownerId The owner id to search for.\n\t * @internal\n\t */\n\tremoveAllDecorationsWithOwnerId(ownerId: number): void;\n\n\t/**\n\t * Get the options associated with a decoration.\n\t * @param id The decoration id.\n\t * @return The decoration options or null if the decoration was not found.\n\t */\n\tgetDecorationOptions(id: string): IModelDecorationOptions | null;\n\n\t/**\n\t * Get the range associated with a decoration.\n\t * @param id The decoration id.\n\t * @return The decoration range or null if the decoration was not found.\n\t */\n\tgetDecorationRange(id: string): Range | null;\n\n\t/**\n\t * Gets all the decorations for the line `lineNumber` as an array.\n\t * @param lineNumber The line number\n\t * @param ownerId If set, it will ignore decorations belonging to other owners.\n\t * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors).\n\t * @return An array with the decorations\n\t */\n\tgetLineDecorations(lineNumber: number, ownerId?: number, filterOutValidation?: boolean): IModelDecoration[];\n\n\t/**\n\t * Gets all the decorations for the lines between `startLineNumber` and `endLineNumber` as an array.\n\t * @param startLineNumber The start line number\n\t * @param endLineNumber The end line number\n\t * @param ownerId If set, it will ignore decorations belonging to other owners.\n\t * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors).\n\t * @return An array with the decorations\n\t */\n\tgetLinesDecorations(startLineNumber: number, endLineNumber: number, ownerId?: number, filterOutValidation?: boolean): IModelDecoration[];\n\n\t/**\n\t * Gets all the decorations in a range as an array. Only `startLineNumber` and `endLineNumber` from `range` are used for filtering.\n\t * So for now it returns all the decorations on the same line as `range`.\n\t * @param range The range to search in\n\t * @param ownerId If set, it will ignore decorations belonging to other owners.\n\t * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors).\n\t * @return An array with the decorations\n\t */\n\tgetDecorationsInRange(range: IRange, ownerId?: number, filterOutValidation?: boolean): IModelDecoration[];\n\n\t/**\n\t * Gets all the decorations as an array.\n\t * @param ownerId If set, it will ignore decorations belonging to other owners.\n\t * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors).\n\t */\n\tgetAllDecorations(ownerId?: number, filterOutValidation?: boolean): IModelDecoration[];\n\n\t/**\n\t * Gets all the decorations that should be rendered in the overview ruler as an array.\n\t * @param ownerId If set, it will ignore decorations belonging to other owners.\n\t * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors).\n\t */\n\tgetOverviewRulerDecorations(ownerId?: number, filterOutValidation?: boolean): IModelDecoration[];\n\n\t/**\n\t * Gets all the decorations that contain injected text.\n\t * @param ownerId If set, it will ignore decorations belonging to other owners.\n\t */\n\tgetInjectedTextDecorations(ownerId?: number): IModelDecoration[];\n\n\t/**\n\t * @internal\n\t */\n\t_getTrackedRange(id: string): Range | null;\n\n\t/**\n\t * @internal\n\t */\n\t_setTrackedRange(id: string | null, newRange: null, newStickiness: TrackedRangeStickiness): null;\n\t/**\n\t * @internal\n\t */\n\t_setTrackedRange(id: string | null, newRange: Range, newStickiness: TrackedRangeStickiness): string;\n\n\t/**\n\t * Normalize a string containing whitespace according to indentation rules (converts to spaces or to tabs).\n\t */\n\tnormalizeIndentation(str: string): string;\n\n\t/**\n\t * Change the options of this model.\n\t */\n\tupdateOptions(newOpts: ITextModelUpdateOptions): void;\n\n\t/**\n\t * Detect the indentation options for this model from its content.\n\t */\n\tdetectIndentation(defaultInsertSpaces: boolean, defaultTabSize: number): void;\n\n\t/**\n\t * Close the current undo-redo element.\n\t * This offers a way to create an undo/redo stop point.\n\t */\n\tpushStackElement(): void;\n\n\t/**\n\t * Open the current undo-redo element.\n\t * This offers a way to remove the current undo/redo stop point.\n\t */\n\tpopStackElement(): void;\n\n\t/**\n\t * Push edit operations, basically editing the model. This is the preferred way\n\t * of editing the model. The edit operations will land on the undo stack.\n\t * @param beforeCursorState The cursor state before the edit operations. This cursor state will be returned when `undo` or `redo` are invoked.\n\t * @param editOperations The edit operations.\n\t * @param cursorStateComputer A callback that can compute the resulting cursors state after the edit operations have been executed.\n\t * @return The cursor state returned by the `cursorStateComputer`.\n\t */\n\tpushEditOperations(beforeCursorState: Selection[] | null, editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[] | null;\n\n\t/**\n\t * Change the end of line sequence. This is the preferred way of\n\t * changing the eol sequence. This will land on the undo stack.\n\t */\n\tpushEOL(eol: EndOfLineSequence): void;\n\n\t/**\n\t * Edit the model without adding the edits to the undo stack.\n\t * This can have dire consequences on the undo stack! See @pushEditOperations for the preferred way.\n\t * @param operations The edit operations.\n\t * @return If desired, the inverse edit operations, that, when applied, will bring the model back to the previous state.\n\t */\n\tapplyEdits(operations: IIdentifiedSingleEditOperation[]): void;\n\tapplyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: false): void;\n\tapplyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: true): IValidEditOperation[];\n\n\t/**\n\t * Change the end of line sequence without recording in the undo stack.\n\t * This can have dire consequences on the undo stack! See @pushEOL for the preferred way.\n\t */\n\tsetEOL(eol: EndOfLineSequence): void;\n\n\t/**\n\t * @internal\n\t */\n\t_applyUndo(changes: TextChange[], eol: EndOfLineSequence, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void;\n\n\t/**\n\t * @internal\n\t */\n\t_applyRedo(changes: TextChange[], eol: EndOfLineSequence, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void;\n\n\t/**\n\t * Undo edit operations until the previous undo/redo point.\n\t * The inverse edit operations will be pushed on the redo stack.\n\t * @internal\n\t */\n\tundo(): void | Promise;\n\n\t/**\n\t * Is there anything in the undo stack?\n\t * @internal\n\t */\n\tcanUndo(): boolean;\n\n\t/**\n\t * Redo edit operations until the next undo/redo point.\n\t * The inverse edit operations will be pushed on the undo stack.\n\t * @internal\n\t */\n\tredo(): void | Promise;\n\n\t/**\n\t * Is there anything in the redo stack?\n\t * @internal\n\t */\n\tcanRedo(): boolean;\n\n\t/**\n\t * @deprecated Please use `onDidChangeContent` instead.\n\t * An event emitted when the contents of the model have changed.\n\t * @internal\n\t * @event\n\t */\n\treadonly onDidChangeContentOrInjectedText: Event;\n\t/**\n\t * An event emitted when the contents of the model have changed.\n\t * @event\n\t */\n\tonDidChangeContent(listener: (e: IModelContentChangedEvent) => void): IDisposable;\n\t/**\n\t * An event emitted when decorations of the model have changed.\n\t * @event\n\t */\n\treadonly onDidChangeDecorations: Event;\n\t/**\n\t * An event emitted when the model options have changed.\n\t * @event\n\t */\n\treadonly onDidChangeOptions: Event;\n\t/**\n\t * An event emitted when the language associated with the model has changed.\n\t * @event\n\t */\n\treadonly onDidChangeLanguage: Event;\n\t/**\n\t * An event emitted when the language configuration associated with the model has changed.\n\t * @event\n\t */\n\treadonly onDidChangeLanguageConfiguration: Event;\n\t/**\n\t * An event emitted when the tokens associated with the model have changed.\n\t * @event\n\t * @internal\n\t */\n\treadonly onDidChangeTokens: Event;\n\t/**\n\t * An event emitted when the model has been attached to the first editor or detached from the last editor.\n\t * @event\n\t */\n\treadonly onDidChangeAttached: Event;\n\t/**\n\t * An event emitted right before disposing the model.\n\t * @event\n\t */\n\treadonly onWillDispose: Event;\n\n\t/**\n\t * Destroy this model.\n\t */\n\tdispose(): void;\n\n\t/**\n\t * @internal\n\t */\n\tonBeforeAttached(): void;\n\n\t/**\n\t * @internal\n\t */\n\tonBeforeDetached(): void;\n\n\t/**\n\t * Returns if this model is attached to an editor or not.\n\t */\n\tisAttachedToEditor(): boolean;\n\n\t/**\n\t * Returns the count of editors this model is attached to.\n\t * @internal\n\t */\n\tgetAttachedEditorCount(): number;\n\n\t/**\n\t * Among all positions that are projected to the same position in the underlying text model as\n\t * the given position, select a unique position as indicated by the affinity.\n\t *\n\t * PositionAffinity.Left:\n\t * The normalized position must be equal or left to the requested position.\n\t *\n\t * PositionAffinity.Right:\n\t * The normalized position must be equal or right to the requested position.\n\t *\n\t * @internal\n\t */\n\tnormalizePosition(position: Position, affinity: PositionAffinity): Position;\n\n\t/**\n\t * Gets the column at which indentation stops at a given line.\n\t * @internal\n\t*/\n\tgetLineIndentColumn(lineNumber: number): number;\n\n\t/**\n\t * Returns an object that can be used to query brackets.\n\t * @internal\n\t*/\n\treadonly bracketPairs: IBracketPairsTextModelPart;\n\n\t/**\n\t * Returns an object that can be used to query indent guides.\n\t * @internal\n\t*/\n\treadonly guides: IGuidesTextModelPart;\n}\n\nexport const enum PositionAffinity {\n\t/**\n\t * Prefers the left most position.\n\t*/\n\tLeft = 0,\n\n\t/**\n\t * Prefers the right most position.\n\t*/\n\tRight = 1,\n\n\t/**\n\t * No preference.\n\t*/\n\tNone = 2,\n}\n\n/**\n * @internal\n */\nexport interface ITextBufferBuilder {\n}\n\n/**\n * @internal\n */\nexport interface ITextBufferFactory {\n\tcreate(defaultEOL: DefaultEndOfLine): { textBuffer: ITextBuffer; disposable: IDisposable; };\n}\n\n/**\n * @internal\n */\nexport class ValidAnnotatedEditOperation implements IIdentifiedSingleEditOperation {\n\tconstructor(\n\t\tpublic readonly identifier: ISingleEditOperationIdentifier | null,\n\t\tpublic readonly range: Range,\n\t\tpublic readonly text: string | null,\n\t\tpublic readonly forceMoveMarkers: boolean,\n\t\tpublic readonly isAutoWhitespaceEdit: boolean,\n\t\tpublic readonly _isTracked: boolean,\n\t) { }\n}\n\n/**\n * @internal\n */\nexport interface IReadonlyTextBuffer {\n\tmightContainRTL(): boolean;\n\tmightContainUnusualLineTerminators(): boolean;\n\tresetMightContainUnusualLineTerminators(): void;\n\tmightContainNonBasicASCII(): boolean;\n\tgetBOM(): string;\n\tgetEOL(): string;\n\n\tgetOffsetAt(lineNumber: number, column: number): number;\n\tgetPositionAt(offset: number): Position;\n\tgetRangeAt(offset: number, length: number): Range;\n\n\tgetValueInRange(range: Range, eol: EndOfLinePreference): string;\n\tcreateSnapshot(preserveBOM: boolean): ITextSnapshot;\n\tgetValueLengthInRange(range: Range, eol: EndOfLinePreference): number;\n\tgetCharacterCountInRange(range: Range, eol: EndOfLinePreference): number;\n\tgetLength(): number;\n\tgetLineCount(): number;\n\tgetLinesContent(): string[];\n\tgetLineContent(lineNumber: number): string;\n\tgetLineCharCode(lineNumber: number, index: number): number;\n\tgetLineLength(lineNumber: number): number;\n\tgetLineFirstNonWhitespaceColumn(lineNumber: number): number;\n\tgetLineLastNonWhitespaceColumn(lineNumber: number): number;\n\tfindMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[];\n}\n\n/**\n * @internal\n */\nexport class SearchData {\n\n\t/**\n\t * The regex to search for. Always defined.\n\t */\n\tpublic readonly regex: RegExp;\n\t/**\n\t * The word separator classifier.\n\t */\n\tpublic readonly wordSeparators: WordCharacterClassifier | null;\n\t/**\n\t * The simple string to search for (if possible).\n\t */\n\tpublic readonly simpleSearch: string | null;\n\n\tconstructor(regex: RegExp, wordSeparators: WordCharacterClassifier | null, simpleSearch: string | null) {\n\t\tthis.regex = regex;\n\t\tthis.wordSeparators = wordSeparators;\n\t\tthis.simpleSearch = simpleSearch;\n\t}\n}\n\n/**\n * @internal\n */\nexport interface ITextBuffer extends IReadonlyTextBuffer {\n\tsetEOL(newEOL: '\\r\\n' | '\\n'): void;\n\tapplyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean, computeUndoEdits: boolean): ApplyEditsResult;\n}\n\n/**\n * @internal\n */\nexport class ApplyEditsResult {\n\n\tconstructor(\n\t\tpublic readonly reverseEdits: IValidEditOperation[] | null,\n\t\tpublic readonly changes: IInternalModelContentChange[],\n\t\tpublic readonly trimAutoWhitespaceLineNumbers: number[] | null\n\t) { }\n\n}\n\n/**\n * @internal\n */\nexport interface IInternalModelContentChange extends IModelContentChange {\n\trange: Range;\n\tforceMoveMarkers: boolean;\n}\n\n/**\n * @internal\n */\nexport function shouldSynchronizeModel(model: ITextModel): boolean {\n\treturn (\n\t\t!model.isTooLargeForSyncing() && !model.isForSimpleWidget\n\t);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { ITextModel, shouldSynchronizeModel } from 'vs/editor/common/model';\nimport { LanguageFilter, LanguageSelector, score } from 'vs/editor/common/languageSelector';\n\ninterface Entry {\n\tselector: LanguageSelector;\n\tprovider: T;\n\t_score: number;\n\t_time: number;\n}\n\nfunction isExclusive(selector: LanguageSelector): boolean {\n\tif (typeof selector === 'string') {\n\t\treturn false;\n\t} else if (Array.isArray(selector)) {\n\t\treturn selector.every(isExclusive);\n\t} else {\n\t\treturn !!(selector as LanguageFilter).exclusive; // TODO: microsoft/TypeScript#42768\n\t}\n}\n\nexport class LanguageFeatureRegistry {\n\n\tprivate _clock: number = 0;\n\tprivate readonly _entries: Entry[] = [];\n\tprivate readonly _onDidChange = new Emitter();\n\n\tget onDidChange(): Event {\n\t\treturn this._onDidChange.event;\n\t}\n\n\tregister(selector: LanguageSelector, provider: T): IDisposable {\n\n\t\tlet entry: Entry | undefined = {\n\t\t\tselector,\n\t\t\tprovider,\n\t\t\t_score: -1,\n\t\t\t_time: this._clock++\n\t\t};\n\n\t\tthis._entries.push(entry);\n\t\tthis._lastCandidate = undefined;\n\t\tthis._onDidChange.fire(this._entries.length);\n\n\t\treturn toDisposable(() => {\n\t\t\tif (entry) {\n\t\t\t\tconst idx = this._entries.indexOf(entry);\n\t\t\t\tif (idx >= 0) {\n\t\t\t\t\tthis._entries.splice(idx, 1);\n\t\t\t\t\tthis._lastCandidate = undefined;\n\t\t\t\t\tthis._onDidChange.fire(this._entries.length);\n\t\t\t\t\tentry = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\thas(model: ITextModel): boolean {\n\t\treturn this.all(model).length > 0;\n\t}\n\n\tall(model: ITextModel): T[] {\n\t\tif (!model) {\n\t\t\treturn [];\n\t\t}\n\n\t\tthis._updateScores(model);\n\t\tconst result: T[] = [];\n\n\t\t// from registry\n\t\tfor (let entry of this._entries) {\n\t\t\tif (entry._score > 0) {\n\t\t\t\tresult.push(entry.provider);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tordered(model: ITextModel): T[] {\n\t\tconst result: T[] = [];\n\t\tthis._orderedForEach(model, entry => result.push(entry.provider));\n\t\treturn result;\n\t}\n\n\torderedGroups(model: ITextModel): T[][] {\n\t\tconst result: T[][] = [];\n\t\tlet lastBucket: T[];\n\t\tlet lastBucketScore: number;\n\n\t\tthis._orderedForEach(model, entry => {\n\t\t\tif (lastBucket && lastBucketScore === entry._score) {\n\t\t\t\tlastBucket.push(entry.provider);\n\t\t\t} else {\n\t\t\t\tlastBucketScore = entry._score;\n\t\t\t\tlastBucket = [entry.provider];\n\t\t\t\tresult.push(lastBucket);\n\t\t\t}\n\t\t});\n\n\t\treturn result;\n\t}\n\n\tprivate _orderedForEach(model: ITextModel, callback: (provider: Entry) => any): void {\n\n\t\tif (!model) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._updateScores(model);\n\n\t\tfor (const entry of this._entries) {\n\t\t\tif (entry._score > 0) {\n\t\t\t\tcallback(entry);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _lastCandidate: { uri: string; language: string; } | undefined;\n\n\tprivate _updateScores(model: ITextModel): void {\n\n\t\tconst candidate = {\n\t\t\turi: model.uri.toString(),\n\t\t\tlanguage: model.getLanguageId()\n\t\t};\n\n\t\tif (this._lastCandidate\n\t\t\t&& this._lastCandidate.language === candidate.language\n\t\t\t&& this._lastCandidate.uri === candidate.uri) {\n\n\t\t\t// nothing has changed\n\t\t\treturn;\n\t\t}\n\n\t\tthis._lastCandidate = candidate;\n\n\t\tfor (let entry of this._entries) {\n\t\t\tentry._score = score(entry.selector, model.uri, model.getLanguageId(), shouldSynchronizeModel(model));\n\n\t\t\tif (isExclusive(entry.selector) && entry._score > 0) {\n\t\t\t\t// support for one exclusive selector that overwrites\n\t\t\t\t// any other selector\n\t\t\t\tfor (let entry of this._entries) {\n\t\t\t\t\tentry._score = 0;\n\t\t\t\t}\n\t\t\t\tentry._score = 1000;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// needs sorting\n\t\tthis._entries.sort(LanguageFeatureRegistry._compareByScoreAndTime);\n\t}\n\n\tprivate static _compareByScoreAndTime(a: Entry, b: Entry): number {\n\t\tif (a._score < b._score) {\n\t\t\treturn 1;\n\t\t} else if (a._score > b._score) {\n\t\t\treturn -1;\n\t\t} else if (a._time < b._time) {\n\t\t\treturn 1;\n\t\t} else if (a._time > b._time) {\n\t\t\treturn -1;\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { splitLines } from 'vs/base/common/strings';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\n\n/**\n * Represents a non-negative length in terms of line and column count.\n * Prefer using {@link Length} for performance reasons.\n*/\nexport class LengthObj {\n\tpublic static zero = new LengthObj(0, 0);\n\n\tconstructor(\n\t\tpublic readonly lineCount: number,\n\t\tpublic readonly columnCount: number\n\t) { }\n\n\ttoString() {\n\t\treturn `${this.lineCount},${this.columnCount}`;\n\t}\n}\n\n/**\n * The end must be greater than or equal to the start.\n*/\nexport function lengthDiff(startLineCount: number, startColumnCount: number, endLineCount: number, endColumnCount: number): Length {\n\treturn (startLineCount !== endLineCount)\n\t\t? toLength(endLineCount - startLineCount, endColumnCount)\n\t\t: toLength(0, endColumnCount - startColumnCount);\n}\n\n/**\n * Represents a non-negative length in terms of line and column count.\n * Does not allocate.\n*/\nexport type Length = { _brand: 'Length' };\n\nexport const lengthZero = 0 as any as Length;\n\nexport function lengthIsZero(length: Length): boolean {\n\treturn length as any as number === 0;\n}\n\n/*\n * We have 52 bits available in a JS number.\n * We use the upper 26 bits to store the line and the lower 26 bits to store the column.\n *\n * Set boolean to `true` when debugging, so that debugging is easier.\n */\nconst factor = /* is debug: */ false ? 100000 : 2 ** 26;\n\nexport function toLength(lineCount: number, columnCount: number): Length {\n\t// llllllllllllllllllllllllllcccccccccccccccccccccccccc (52 bits)\n\t// line count (26 bits) column count (26 bits)\n\n\t// If there is no overflow (all values/sums below 2^26 = 67108864),\n\t// we have `toLength(lns1, cols1) + toLength(lns2, cols2) = toLength(lns1 + lns2, cols1 + cols2)`.\n\n\treturn (lineCount * factor + columnCount) as any as Length;\n}\n\nexport function lengthToObj(length: Length): LengthObj {\n\tconst l = length as any as number;\n\tconst lineCount = Math.floor(l / factor);\n\tconst columnCount = l - lineCount * factor;\n\treturn new LengthObj(lineCount, columnCount);\n}\n\nexport function lengthGetLineCount(length: Length): number {\n\treturn Math.floor(length as any as number / factor);\n}\n\n/**\n * Returns the amount of columns of the given length, assuming that it does not span any line.\n*/\nexport function lengthGetColumnCountIfZeroLineCount(length: Length): number {\n\treturn length as any as number;\n}\n\n\n// [10 lines, 5 cols] + [ 0 lines, 3 cols] = [10 lines, 8 cols]\n// [10 lines, 5 cols] + [20 lines, 3 cols] = [30 lines, 3 cols]\nexport function lengthAdd(length1: Length, length2: Length): Length;\nexport function lengthAdd(l1: any, l2: any): Length {\n\treturn ((l2 < factor)\n\t\t? (l1 + l2) // l2 is the amount of columns (zero line count). Keep the column count from l1.\n\t\t: (l1 - (l1 % factor) + l2)); // l1 - (l1 % factor) equals toLength(l1.lineCount, 0)\n}\n\n/**\n * Returns a non negative length `result` such that `lengthAdd(length1, result) = length2`, or zero if such length does not exist.\n */\nexport function lengthDiffNonNegative(length1: Length, length2: Length): Length {\n\tconst l1 = length1 as any as number;\n\tconst l2 = length2 as any as number;\n\n\tconst diff = l2 - l1;\n\tif (diff <= 0) {\n\t\t// line-count of length1 is higher than line-count of length2\n\t\t// or they are equal and column-count of length1 is higher than column-count of length2\n\t\treturn lengthZero;\n\t}\n\n\tconst lineCount1 = Math.floor(l1 / factor);\n\tconst lineCount2 = Math.floor(l2 / factor);\n\n\tconst colCount2 = l2 - lineCount2 * factor;\n\n\tif (lineCount1 === lineCount2) {\n\t\tconst colCount1 = l1 - lineCount1 * factor;\n\t\treturn toLength(0, colCount2 - colCount1);\n\t} else {\n\t\treturn toLength(lineCount2 - lineCount1, colCount2);\n\t}\n}\n\nexport function lengthLessThan(length1: Length, length2: Length): boolean {\n\t// First, compare line counts, then column counts.\n\treturn (length1 as any as number) < (length2 as any as number);\n}\n\nexport function lengthLessThanEqual(length1: Length, length2: Length): boolean {\n\treturn (length1 as any as number) <= (length2 as any as number);\n}\n\nexport function lengthGreaterThanEqual(length1: Length, length2: Length): boolean {\n\treturn (length1 as any as number) >= (length2 as any as number);\n}\n\nexport function positionToLength(position: Position): Length {\n\treturn toLength(position.lineNumber - 1, position.column - 1);\n}\n\nexport function lengthsToRange(lengthStart: Length, lengthEnd: Length): Range {\n\tconst l = lengthStart as any as number;\n\tconst lineCount = Math.floor(l / factor);\n\tconst colCount = l - lineCount * factor;\n\n\tconst l2 = lengthEnd as any as number;\n\tconst lineCount2 = Math.floor(l2 / factor);\n\tconst colCount2 = l2 - lineCount2 * factor;\n\n\treturn new Range(lineCount + 1, colCount + 1, lineCount2 + 1, colCount2 + 1);\n}\n\nexport function lengthOfString(str: string): Length {\n\tconst lines = splitLines(str);\n\treturn toLength(lines.length - 1, lines[lines.length - 1].length);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Length, lengthAdd, lengthDiffNonNegative, lengthLessThanEqual, LengthObj, lengthToObj, toLength } from './length';\n\nexport class TextEditInfo {\n\tconstructor(\n\t\tpublic readonly startOffset: Length,\n\t\tpublic readonly endOffset: Length,\n\t\tpublic readonly newLength: Length\n\t) {\n\t}\n}\n\nexport class BeforeEditPositionMapper {\n\tprivate nextEditIdx = 0;\n\tprivate deltaOldToNewLineCount = 0;\n\tprivate deltaOldToNewColumnCount = 0;\n\tprivate deltaLineIdxInOld = -1;\n\tprivate readonly edits: readonly TextEditInfoCache[];\n\n\t/**\n\t * @param edits Must be sorted by offset in ascending order.\n\t*/\n\tconstructor(\n\t\tedits: readonly TextEditInfo[],\n\t\tprivate readonly documentLength: Length,\n\t) {\n\t\tthis.edits = edits.map(edit => TextEditInfoCache.from(edit));\n\t}\n\n\t/**\n\t * @param offset Must be equal to or greater than the last offset this method has been called with.\n\t*/\n\tgetOffsetBeforeChange(offset: Length): Length {\n\t\tthis.adjustNextEdit(offset);\n\t\treturn this.translateCurToOld(offset);\n\t}\n\n\t/**\n\t * @param offset Must be equal to or greater than the last offset this method has been called with.\n\t*/\n\tgetDistanceToNextChange(offset: Length): Length {\n\t\tthis.adjustNextEdit(offset);\n\n\t\tconst nextEdit = this.edits[this.nextEditIdx];\n\t\tconst nextChangeOffset = nextEdit ? this.translateOldToCur(nextEdit.offsetObj) : this.documentLength;\n\n\t\treturn lengthDiffNonNegative(offset, nextChangeOffset);\n\t}\n\n\tprivate translateOldToCur(oldOffsetObj: LengthObj): Length {\n\t\tif (oldOffsetObj.lineCount === this.deltaLineIdxInOld) {\n\t\t\treturn toLength(oldOffsetObj.lineCount + this.deltaOldToNewLineCount, oldOffsetObj.columnCount + this.deltaOldToNewColumnCount);\n\t\t} else {\n\t\t\treturn toLength(oldOffsetObj.lineCount + this.deltaOldToNewLineCount, oldOffsetObj.columnCount);\n\t\t}\n\t}\n\n\tprivate translateCurToOld(newOffset: Length): Length {\n\t\tconst offsetObj = lengthToObj(newOffset);\n\t\tif (offsetObj.lineCount - this.deltaOldToNewLineCount === this.deltaLineIdxInOld) {\n\t\t\treturn toLength(offsetObj.lineCount - this.deltaOldToNewLineCount, offsetObj.columnCount - this.deltaOldToNewColumnCount);\n\t\t} else {\n\t\t\treturn toLength(offsetObj.lineCount - this.deltaOldToNewLineCount, offsetObj.columnCount);\n\t\t}\n\t}\n\n\tprivate adjustNextEdit(offset: Length) {\n\t\twhile (this.nextEditIdx < this.edits.length) {\n\t\t\tconst nextEdit = this.edits[this.nextEditIdx];\n\n\t\t\t// After applying the edit, what is its end offset (considering all previous edits)?\n\t\t\tconst nextEditEndOffsetInCur = this.translateOldToCur(nextEdit.endOffsetAfterObj);\n\n\t\t\tif (lengthLessThanEqual(nextEditEndOffsetInCur, offset)) {\n\t\t\t\t// We are after the edit, skip it\n\t\t\t\tthis.nextEditIdx++;\n\n\t\t\t\tconst nextEditEndOffsetInCurObj = lengthToObj(nextEditEndOffsetInCur);\n\n\t\t\t\t// Before applying the edit, what is its end offset (considering all previous edits)?\n\t\t\t\tconst nextEditEndOffsetBeforeInCurObj = lengthToObj(this.translateOldToCur(nextEdit.endOffsetBeforeObj));\n\n\t\t\t\tconst lineDelta = nextEditEndOffsetInCurObj.lineCount - nextEditEndOffsetBeforeInCurObj.lineCount;\n\t\t\t\tthis.deltaOldToNewLineCount += lineDelta;\n\n\t\t\t\tconst previousColumnDelta = this.deltaLineIdxInOld === nextEdit.endOffsetBeforeObj.lineCount ? this.deltaOldToNewColumnCount : 0;\n\t\t\t\tconst columnDelta = nextEditEndOffsetInCurObj.columnCount - nextEditEndOffsetBeforeInCurObj.columnCount;\n\t\t\t\tthis.deltaOldToNewColumnCount = previousColumnDelta + columnDelta;\n\t\t\t\tthis.deltaLineIdxInOld = nextEdit.endOffsetBeforeObj.lineCount;\n\t\t\t} else {\n\t\t\t\t// We are in or before the edit.\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nclass TextEditInfoCache {\n\tstatic from(edit: TextEditInfo): TextEditInfoCache {\n\t\treturn new TextEditInfoCache(edit.startOffset, edit.endOffset, edit.newLength);\n\t}\n\n\tpublic readonly endOffsetBeforeObj: LengthObj;\n\tpublic readonly endOffsetAfterObj: LengthObj;\n\tpublic readonly offsetObj: LengthObj;\n\n\tconstructor(\n\t\tstartOffset: Length,\n\t\tendOffset: Length,\n\t\ttextLength: Length,\n\t) {\n\t\tthis.endOffsetBeforeObj = lengthToObj(endOffset);\n\t\tthis.endOffsetAfterObj = lengthToObj(lengthAdd(startOffset, textLength));\n\t\tthis.offsetObj = lengthToObj(startOffset);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { AstNode } from './ast';\nimport { lengthAdd, lengthZero, Length, lengthLessThan } from './length';\n\n/**\n * Allows to efficiently find a longest child at a given offset in a fixed node.\n * The requested offsets must increase monotonously.\n*/\nexport class NodeReader {\n\tprivate readonly nextNodes: AstNode[];\n\tprivate readonly offsets: Length[];\n\tprivate readonly idxs: number[];\n\tprivate lastOffset: Length = lengthZero;\n\n\tconstructor(node: AstNode) {\n\t\tthis.nextNodes = [node];\n\t\tthis.offsets = [lengthZero];\n\t\tthis.idxs = [];\n\t}\n\n\t/**\n\t * Returns the longest node at `offset` that satisfies the predicate.\n\t * @param offset must be greater than or equal to the last offset this method has been called with!\n\t*/\n\treadLongestNodeAt(offset: Length, predicate: (node: AstNode) => boolean): AstNode | undefined {\n\t\tif (lengthLessThan(offset, this.lastOffset)) {\n\t\t\tthrow new Error('Invalid offset');\n\t\t}\n\t\tthis.lastOffset = offset;\n\n\t\t// Find the longest node of all those that are closest to the current offset.\n\t\twhile (true) {\n\t\t\tconst curNode = lastOrUndefined(this.nextNodes);\n\n\t\t\tif (!curNode) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tconst curNodeOffset = lastOrUndefined(this.offsets)!;\n\n\t\t\tif (lengthLessThan(offset, curNodeOffset)) {\n\t\t\t\t// The next best node is not here yet.\n\t\t\t\t// The reader must advance before a cached node is hit.\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tif (lengthLessThan(curNodeOffset, offset)) {\n\t\t\t\t// The reader is ahead of the current node.\n\t\t\t\tif (lengthAdd(curNodeOffset, curNode.length) <= offset) {\n\t\t\t\t\t// The reader is after the end of the current node.\n\t\t\t\t\tthis.nextNodeAfterCurrent();\n\t\t\t\t} else {\n\t\t\t\t\t// The reader is somewhere in the current node.\n\t\t\t\t\tconst nextChildIdx = getNextChildIdx(curNode);\n\t\t\t\t\tif (nextChildIdx !== -1) {\n\t\t\t\t\t\t// Go to the first child and repeat.\n\t\t\t\t\t\tthis.nextNodes.push(curNode.getChild(nextChildIdx)!);\n\t\t\t\t\t\tthis.offsets.push(curNodeOffset);\n\t\t\t\t\t\tthis.idxs.push(nextChildIdx);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We don't have children\n\t\t\t\t\t\tthis.nextNodeAfterCurrent();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// readerOffsetBeforeChange === curNodeOffset\n\t\t\t\tif (predicate(curNode)) {\n\t\t\t\t\tthis.nextNodeAfterCurrent();\n\t\t\t\t\treturn curNode;\n\t\t\t\t} else {\n\t\t\t\t\tconst nextChildIdx = getNextChildIdx(curNode);\n\t\t\t\t\t// look for shorter node\n\t\t\t\t\tif (nextChildIdx === -1) {\n\t\t\t\t\t\t// There is no shorter node.\n\t\t\t\t\t\tthis.nextNodeAfterCurrent();\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Descend into first child & repeat.\n\t\t\t\t\t\tthis.nextNodes.push(curNode.getChild(nextChildIdx)!);\n\t\t\t\t\t\tthis.offsets.push(curNodeOffset);\n\t\t\t\t\t\tthis.idxs.push(nextChildIdx);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Navigates to the longest node that continues after the current node.\n\tprivate nextNodeAfterCurrent(): void {\n\t\twhile (true) {\n\t\t\tconst currentOffset = lastOrUndefined(this.offsets);\n\t\t\tconst currentNode = lastOrUndefined(this.nextNodes);\n\t\t\tthis.nextNodes.pop();\n\t\t\tthis.offsets.pop();\n\n\t\t\tif (this.idxs.length === 0) {\n\t\t\t\t// We just popped the root node, there is no next node.\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Parent is not undefined, because idxs is not empty\n\t\t\tconst parent = lastOrUndefined(this.nextNodes)!;\n\t\t\tconst nextChildIdx = getNextChildIdx(parent, this.idxs[this.idxs.length - 1]);\n\n\t\t\tif (nextChildIdx !== -1) {\n\t\t\t\tthis.nextNodes.push(parent.getChild(nextChildIdx)!);\n\t\t\t\tthis.offsets.push(lengthAdd(currentOffset!, currentNode!.length));\n\t\t\t\tthis.idxs[this.idxs.length - 1] = nextChildIdx;\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tthis.idxs.pop();\n\t\t\t}\n\t\t\t// We fully consumed the parent.\n\t\t\t// Current node is now parent, so call nextNodeAfterCurrent again\n\t\t}\n\t}\n}\n\nfunction getNextChildIdx(node: AstNode, curIdx: number = -1): number | -1 {\n\twhile (true) {\n\t\tcurIdx++;\n\t\tif (curIdx >= node.childrenLength) {\n\t\t\treturn -1;\n\t\t}\n\t\tif (node.getChild(curIdx)) {\n\t\t\treturn curIdx;\n\t\t}\n\t}\n}\n\nfunction lastOrUndefined(arr: readonly T[]): T | undefined {\n\treturn arr.length > 0 ? arr[arr.length - 1] : undefined;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nconst emptyArr = new Array();\n\n/**\n * Represents an immutable set that works best for a small number of elements (less than 32).\n * It uses bits to encode element membership efficiently.\n*/\nexport class SmallImmutableSet {\n\tprivate static cache = new Array>(129);\n\n\tprivate static create(items: number, additionalItems: readonly number[]): SmallImmutableSet {\n\t\tif (items <= 128 && additionalItems.length === 0) {\n\t\t\t// We create a cache of 128=2^7 elements to cover all sets with up to 7 (dense) elements.\n\t\t\tlet cached = SmallImmutableSet.cache[items];\n\t\t\tif (!cached) {\n\t\t\t\tcached = new SmallImmutableSet(items, additionalItems);\n\t\t\t\tSmallImmutableSet.cache[items] = cached;\n\t\t\t}\n\t\t\treturn cached;\n\t\t}\n\n\t\treturn new SmallImmutableSet(items, additionalItems);\n\t}\n\n\tprivate static empty = SmallImmutableSet.create(0, emptyArr);\n\tpublic static getEmpty(): SmallImmutableSet {\n\t\treturn this.empty;\n\t}\n\n\tprivate constructor(\n\t\tprivate readonly items: number,\n\t\tprivate readonly additionalItems: readonly number[]\n\t) {\n\t}\n\n\tpublic add(value: T, keyProvider: IDenseKeyProvider): SmallImmutableSet {\n\t\tconst key = keyProvider.getKey(value);\n\t\tlet idx = key >> 5; // divided by 32\n\t\tif (idx === 0) {\n\t\t\t// fast path\n\t\t\tconst newItem = (1 << key) | this.items;\n\t\t\tif (newItem === this.items) {\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\treturn SmallImmutableSet.create(newItem, this.additionalItems);\n\t\t}\n\t\tidx--;\n\n\t\tconst newItems = this.additionalItems.slice(0);\n\t\twhile (newItems.length < idx) {\n\t\t\tnewItems.push(0);\n\t\t}\n\t\tnewItems[idx] |= 1 << (key & 31);\n\n\t\treturn SmallImmutableSet.create(this.items, newItems);\n\t}\n\n\tpublic merge(other: SmallImmutableSet): SmallImmutableSet {\n\t\tconst merged = this.items | other.items;\n\n\t\tif (this.additionalItems === emptyArr && other.additionalItems === emptyArr) {\n\t\t\t// fast path\n\t\t\tif (merged === this.items) {\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tif (merged === other.items) {\n\t\t\t\treturn other;\n\t\t\t}\n\t\t\treturn SmallImmutableSet.create(merged, emptyArr);\n\t\t}\n\n\t\t// This can be optimized, but it's not a common case\n\t\tconst newItems = new Array();\n\t\tfor (let i = 0; i < Math.max(this.additionalItems.length, other.additionalItems.length); i++) {\n\t\t\tconst item1 = this.additionalItems[i] || 0;\n\t\t\tconst item2 = other.additionalItems[i] || 0;\n\t\t\tnewItems.push(item1 | item2);\n\t\t}\n\n\t\treturn SmallImmutableSet.create(merged, newItems);\n\t}\n\n\tpublic intersects(other: SmallImmutableSet): boolean {\n\t\tif ((this.items & other.items) !== 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tfor (let i = 0; i < Math.min(this.additionalItems.length, other.additionalItems.length); i++) {\n\t\t\tif ((this.additionalItems[i] & other.additionalItems[i]) !== 0) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n}\n\nexport interface IDenseKeyProvider {\n\tgetKey(value: T): number;\n}\n\nexport const identityKeyProvider: IDenseKeyProvider = {\n\tgetKey(value: number) {\n\t\treturn value;\n\t}\n};\n\n/**\n * Assigns values a unique incrementing key.\n*/\nexport class DenseKeyProvider {\n\tprivate readonly items = new Map();\n\n\tgetKey(value: T): number {\n\t\tlet existing = this.items.get(value);\n\t\tif (existing === undefined) {\n\t\t\texisting = this.items.size;\n\t\t\tthis.items.set(value, existing);\n\t\t}\n\t\treturn existing;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CursorColumns } from 'vs/editor/common/core/cursorColumns';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { Length, lengthAdd, lengthGetLineCount, lengthToObj, lengthZero } from './length';\nimport { SmallImmutableSet } from './smallImmutableSet';\nimport { OpeningBracketId } from './tokenizer';\n\nexport const enum AstNodeKind {\n\tText = 0,\n\tBracket = 1,\n\tPair = 2,\n\tUnexpectedClosingBracket = 3,\n\tList = 4,\n}\n\nexport type AstNode = PairAstNode | ListAstNode | BracketAstNode | InvalidBracketAstNode | TextAstNode;\n\n/**\n * The base implementation for all AST nodes.\n*/\nabstract class BaseAstNode {\n\tpublic abstract readonly kind: AstNodeKind;\n\n\tpublic abstract readonly childrenLength: number;\n\n\t/**\n\t * Might return null even if {@link idx} is smaller than {@link BaseAstNode.childrenLength}.\n\t*/\n\tpublic abstract getChild(idx: number): AstNode | null;\n\n\t/**\n\t * Try to avoid using this property, as implementations might need to allocate the resulting array.\n\t*/\n\tpublic abstract readonly children: readonly AstNode[];\n\n\t/**\n\t * Represents the set of all (potentially) missing opening bracket ids in this node.\n\t * E.g. in `{ ] ) }` that set is {`[`, `(` }.\n\t*/\n\tpublic abstract readonly missingOpeningBracketIds: SmallImmutableSet;\n\n\t/**\n\t * In case of a list, determines the height of the (2,3) tree.\n\t*/\n\tpublic abstract readonly listHeight: number;\n\n\tprotected _length: Length;\n\n\t/**\n\t * The length of the entire node, which should equal the sum of lengths of all children.\n\t*/\n\tpublic get length(): Length {\n\t\treturn this._length;\n\t}\n\n\tpublic constructor(length: Length) {\n\t\tthis._length = length;\n\t}\n\n\t/**\n\t * @param openBracketIds The set of all opening brackets that have not yet been closed.\n\t */\n\tpublic abstract canBeReused(\n\t\topenBracketIds: SmallImmutableSet\n\t): boolean;\n\n\t/**\n\t * Creates a deep clone.\n\t */\n\tpublic abstract deepClone(): AstNode;\n\n\tpublic abstract computeMinIndentation(offset: Length, textModel: ITextModel): number;\n}\n\n/**\n * Represents a bracket pair including its child (e.g. `{ ... }`).\n * Might be unclosed.\n * Immutable, if all children are immutable.\n*/\nexport class PairAstNode extends BaseAstNode {\n\tpublic static create(\n\t\topeningBracket: BracketAstNode,\n\t\tchild: AstNode | null,\n\t\tclosingBracket: BracketAstNode | null\n\t) {\n\t\tlet length = openingBracket.length;\n\t\tif (child) {\n\t\t\tlength = lengthAdd(length, child.length);\n\t\t}\n\t\tif (closingBracket) {\n\t\t\tlength = lengthAdd(length, closingBracket.length);\n\t\t}\n\t\treturn new PairAstNode(length, openingBracket, child, closingBracket, child ? child.missingOpeningBracketIds : SmallImmutableSet.getEmpty());\n\t}\n\n\tpublic get kind(): AstNodeKind.Pair {\n\t\treturn AstNodeKind.Pair;\n\t}\n\tpublic get listHeight() {\n\t\treturn 0;\n\t}\n\tpublic get childrenLength(): number {\n\t\treturn 3;\n\t}\n\tpublic getChild(idx: number): AstNode | null {\n\t\tswitch (idx) {\n\t\t\tcase 0: return this.openingBracket;\n\t\t\tcase 1: return this.child;\n\t\t\tcase 2: return this.closingBracket;\n\t\t}\n\t\tthrow new Error('Invalid child index');\n\t}\n\n\t/**\n\t * Avoid using this property, it allocates an array!\n\t*/\n\tpublic get children() {\n\t\tconst result = new Array();\n\t\tresult.push(this.openingBracket);\n\t\tif (this.child) {\n\t\t\tresult.push(this.child);\n\t\t}\n\t\tif (this.closingBracket) {\n\t\t\tresult.push(this.closingBracket);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate constructor(\n\t\tlength: Length,\n\t\tpublic readonly openingBracket: BracketAstNode,\n\t\tpublic readonly child: AstNode | null,\n\t\tpublic readonly closingBracket: BracketAstNode | null,\n\t\tpublic readonly missingOpeningBracketIds: SmallImmutableSet\n\t) {\n\t\tsuper(length);\n\t}\n\n\tpublic canBeReused(openBracketIds: SmallImmutableSet) {\n\t\tif (this.closingBracket === null) {\n\t\t\t// Unclosed pair ast nodes only\n\t\t\t// end at the end of the document\n\t\t\t// or when a parent node is closed.\n\n\t\t\t// This could be improved:\n\t\t\t// Only return false if some next token is neither \"undefined\" nor a bracket that closes a parent.\n\n\t\t\treturn false;\n\t\t}\n\n\t\tif (openBracketIds.intersects(this.missingOpeningBracketIds)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tpublic deepClone(): PairAstNode {\n\t\treturn new PairAstNode(\n\t\t\tthis.length,\n\t\t\tthis.openingBracket.deepClone(),\n\t\t\tthis.child && this.child.deepClone(),\n\t\t\tthis.closingBracket && this.closingBracket.deepClone(),\n\t\t\tthis.missingOpeningBracketIds\n\t\t);\n\t}\n\n\tpublic computeMinIndentation(offset: Length, textModel: ITextModel): number {\n\t\treturn this.child ? this.child.computeMinIndentation(lengthAdd(offset, this.openingBracket.length), textModel) : Number.MAX_SAFE_INTEGER;\n\t}\n}\n\nexport abstract class ListAstNode extends BaseAstNode {\n\t/**\n\t * This method uses more memory-efficient list nodes that can only store 2 or 3 children.\n\t*/\n\tpublic static create23(item1: AstNode, item2: AstNode, item3: AstNode | null, immutable: boolean = false): ListAstNode {\n\t\tlet length = item1.length;\n\t\tlet missingBracketIds = item1.missingOpeningBracketIds;\n\n\t\tif (item1.listHeight !== item2.listHeight) {\n\t\t\tthrow new Error('Invalid list heights');\n\t\t}\n\n\t\tlength = lengthAdd(length, item2.length);\n\t\tmissingBracketIds = missingBracketIds.merge(item2.missingOpeningBracketIds);\n\n\t\tif (item3) {\n\t\t\tif (item1.listHeight !== item3.listHeight) {\n\t\t\t\tthrow new Error('Invalid list heights');\n\t\t\t}\n\t\t\tlength = lengthAdd(length, item3.length);\n\t\t\tmissingBracketIds = missingBracketIds.merge(item3.missingOpeningBracketIds);\n\t\t}\n\t\treturn immutable\n\t\t\t? new Immutable23ListAstNode(length, item1.listHeight + 1, item1, item2, item3, missingBracketIds)\n\t\t\t: new TwoThreeListAstNode(length, item1.listHeight + 1, item1, item2, item3, missingBracketIds);\n\t}\n\n\tpublic static getEmpty() {\n\t\treturn new ImmutableArrayListAstNode(lengthZero, 0, [], SmallImmutableSet.getEmpty());\n\t}\n\n\tpublic get kind(): AstNodeKind.List {\n\t\treturn AstNodeKind.List;\n\t}\n\n\tpublic get missingOpeningBracketIds(): SmallImmutableSet {\n\t\treturn this._missingOpeningBracketIds;\n\t}\n\n\tprivate cachedMinIndentation: number = -1;\n\n\t/**\n\t * Use ListAstNode.create.\n\t*/\n\tconstructor(\n\t\tlength: Length,\n\t\tpublic readonly listHeight: number,\n\t\tprivate _missingOpeningBracketIds: SmallImmutableSet\n\t) {\n\t\tsuper(length);\n\t}\n\n\tprotected throwIfImmutable(): void {\n\t\t// NOOP\n\t}\n\n\tprotected abstract setChild(idx: number, child: AstNode): void;\n\n\tpublic makeLastElementMutable(): AstNode | undefined {\n\t\tthis.throwIfImmutable();\n\t\tconst childCount = this.childrenLength;\n\t\tif (childCount === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst lastChild = this.getChild(childCount - 1)!;\n\t\tconst mutable = lastChild.kind === AstNodeKind.List ? lastChild.toMutable() : lastChild;\n\t\tif (lastChild !== mutable) {\n\t\t\tthis.setChild(childCount - 1, mutable);\n\t\t}\n\t\treturn mutable;\n\t}\n\n\tpublic makeFirstElementMutable(): AstNode | undefined {\n\t\tthis.throwIfImmutable();\n\t\tconst childCount = this.childrenLength;\n\t\tif (childCount === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst firstChild = this.getChild(0)!;\n\t\tconst mutable = firstChild.kind === AstNodeKind.List ? firstChild.toMutable() : firstChild;\n\t\tif (firstChild !== mutable) {\n\t\t\tthis.setChild(0, mutable);\n\t\t}\n\t\treturn mutable;\n\t}\n\n\tpublic canBeReused(openBracketIds: SmallImmutableSet): boolean {\n\t\tif (openBracketIds.intersects(this.missingOpeningBracketIds)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet lastChild: ListAstNode = this;\n\t\tlet lastLength: number;\n\t\twhile (lastChild.kind === AstNodeKind.List && (lastLength = lastChild.childrenLength) > 0) {\n\t\t\tlastChild = lastChild.getChild(lastLength! - 1) as ListAstNode;\n\t\t}\n\n\t\treturn lastChild.canBeReused(openBracketIds);\n\t}\n\n\tpublic handleChildrenChanged(): void {\n\t\tthis.throwIfImmutable();\n\n\t\tconst count = this.childrenLength;\n\n\t\tlet length = this.getChild(0)!.length;\n\t\tlet unopenedBrackets = this.getChild(0)!.missingOpeningBracketIds;\n\n\t\tfor (let i = 1; i < count; i++) {\n\t\t\tconst child = this.getChild(i)!;\n\t\t\tlength = lengthAdd(length, child.length);\n\t\t\tunopenedBrackets = unopenedBrackets.merge(child.missingOpeningBracketIds);\n\t\t}\n\n\t\tthis._length = length;\n\t\tthis._missingOpeningBracketIds = unopenedBrackets;\n\t\tthis.cachedMinIndentation = -1;\n\t}\n\n\tpublic computeMinIndentation(offset: Length, textModel: ITextModel): number {\n\t\tif (this.cachedMinIndentation !== -1) {\n\t\t\treturn this.cachedMinIndentation;\n\t\t}\n\n\t\tlet minIndentation = Number.MAX_SAFE_INTEGER;\n\t\tlet childOffset = offset;\n\t\tfor (let i = 0; i < this.childrenLength; i++) {\n\t\t\tconst child = this.getChild(i);\n\t\t\tif (child) {\n\t\t\t\tminIndentation = Math.min(minIndentation, child.computeMinIndentation(childOffset, textModel));\n\t\t\t\tchildOffset = lengthAdd(childOffset, child.length);\n\t\t\t}\n\t\t}\n\n\t\tthis.cachedMinIndentation = minIndentation;\n\t\treturn minIndentation;\n\t}\n\n\t/**\n\t * Creates a shallow clone that is mutable, or itself if it is already mutable.\n\t */\n\tpublic abstract toMutable(): ListAstNode;\n\n\tpublic abstract appendChildOfSameHeight(node: AstNode): void;\n\tpublic abstract unappendChild(): AstNode | undefined;\n\tpublic abstract prependChildOfSameHeight(node: AstNode): void;\n\tpublic abstract unprependChild(): AstNode | undefined;\n}\n\nclass TwoThreeListAstNode extends ListAstNode {\n\tpublic get childrenLength(): number {\n\t\treturn this._item3 !== null ? 3 : 2;\n\t}\n\tpublic getChild(idx: number): AstNode | null {\n\t\tswitch (idx) {\n\t\t\tcase 0: return this._item1;\n\t\t\tcase 1: return this._item2;\n\t\t\tcase 2: return this._item3;\n\t\t}\n\t\tthrow new Error('Invalid child index');\n\t}\n\tpublic setChild(idx: number, node: AstNode): void {\n\t\tswitch (idx) {\n\t\t\tcase 0: this._item1 = node; return;\n\t\t\tcase 1: this._item2 = node; return;\n\t\t\tcase 2: this._item3 = node; return;\n\t\t}\n\t\tthrow new Error('Invalid child index');\n\t}\n\n\tpublic get children(): readonly AstNode[] {\n\t\treturn this._item3 ? [this._item1, this._item2, this._item3] : [this._item1, this._item2];\n\t}\n\n\tpublic get item1(): AstNode {\n\t\treturn this._item1;\n\t}\n\tpublic get item2(): AstNode {\n\t\treturn this._item2;\n\t}\n\tpublic get item3(): AstNode | null {\n\t\treturn this._item3;\n\t}\n\n\tpublic constructor(\n\t\tlength: Length,\n\t\tlistHeight: number,\n\t\tprivate _item1: AstNode,\n\t\tprivate _item2: AstNode,\n\t\tprivate _item3: AstNode | null,\n\t\tmissingOpeningBracketIds: SmallImmutableSet\n\t) {\n\t\tsuper(length, listHeight, missingOpeningBracketIds);\n\t}\n\n\tpublic deepClone(): ListAstNode {\n\t\treturn new TwoThreeListAstNode(\n\t\t\tthis.length,\n\t\t\tthis.listHeight,\n\t\t\tthis._item1.deepClone(),\n\t\t\tthis._item2.deepClone(),\n\t\t\tthis._item3 ? this._item3.deepClone() : null,\n\t\t\tthis.missingOpeningBracketIds\n\t\t);\n\t}\n\n\tpublic appendChildOfSameHeight(node: AstNode): void {\n\t\tif (this._item3) {\n\t\t\tthrow new Error('Cannot append to a full (2,3) tree node');\n\t\t}\n\t\tthis.throwIfImmutable();\n\t\tthis._item3 = node;\n\t\tthis.handleChildrenChanged();\n\t}\n\n\tpublic unappendChild(): AstNode | undefined {\n\t\tif (!this._item3) {\n\t\t\tthrow new Error('Cannot remove from a non-full (2,3) tree node');\n\t\t}\n\t\tthis.throwIfImmutable();\n\t\tconst result = this._item3;\n\t\tthis._item3 = null;\n\t\tthis.handleChildrenChanged();\n\t\treturn result;\n\t}\n\n\tpublic prependChildOfSameHeight(node: AstNode): void {\n\t\tif (this._item3) {\n\t\t\tthrow new Error('Cannot prepend to a full (2,3) tree node');\n\t\t}\n\t\tthis.throwIfImmutable();\n\t\tthis._item3 = this._item2;\n\t\tthis._item2 = this._item1;\n\t\tthis._item1 = node;\n\t\tthis.handleChildrenChanged();\n\t}\n\n\tpublic unprependChild(): AstNode | undefined {\n\t\tif (!this._item3) {\n\t\t\tthrow new Error('Cannot remove from a non-full (2,3) tree node');\n\t\t}\n\t\tthis.throwIfImmutable();\n\t\tconst result = this._item1;\n\t\tthis._item1 = this._item2;\n\t\tthis._item2 = this._item3;\n\t\tthis._item3 = null;\n\n\t\tthis.handleChildrenChanged();\n\t\treturn result;\n\t}\n\n\toverride toMutable(): ListAstNode {\n\t\treturn this;\n\t}\n}\n\n/**\n * Immutable, if all children are immutable.\n*/\nclass Immutable23ListAstNode extends TwoThreeListAstNode {\n\toverride toMutable(): ListAstNode {\n\t\treturn new TwoThreeListAstNode(this.length, this.listHeight, this.item1, this.item2, this.item3, this.missingOpeningBracketIds);\n\t}\n\n\tprotected override throwIfImmutable(): void {\n\t\tthrow new Error('this instance is immutable');\n\t}\n}\n\n/**\n * For debugging.\n*/\nclass ArrayListAstNode extends ListAstNode {\n\tget childrenLength(): number {\n\t\treturn this._children.length;\n\t}\n\tgetChild(idx: number): AstNode | null {\n\t\treturn this._children[idx];\n\t}\n\tsetChild(idx: number, child: AstNode): void {\n\t\tthis._children[idx] = child;\n\t}\n\tget children(): readonly AstNode[] {\n\t\treturn this._children;\n\t}\n\n\tconstructor(\n\t\tlength: Length,\n\t\tlistHeight: number,\n\t\tprivate readonly _children: AstNode[],\n\t\tmissingOpeningBracketIds: SmallImmutableSet\n\t) {\n\t\tsuper(length, listHeight, missingOpeningBracketIds);\n\t}\n\n\tdeepClone(): ListAstNode {\n\t\tconst children = new Array(this._children.length);\n\t\tfor (let i = 0; i < this._children.length; i++) {\n\t\t\tchildren[i] = this._children[i].deepClone();\n\t\t}\n\t\treturn new ArrayListAstNode(this.length, this.listHeight, children, this.missingOpeningBracketIds);\n\t}\n\n\tpublic appendChildOfSameHeight(node: AstNode): void {\n\t\tthis.throwIfImmutable();\n\t\tthis._children.push(node);\n\t\tthis.handleChildrenChanged();\n\t}\n\n\tpublic unappendChild(): AstNode | undefined {\n\t\tthis.throwIfImmutable();\n\t\tconst item = this._children.pop();\n\t\tthis.handleChildrenChanged();\n\t\treturn item;\n\t}\n\n\tpublic prependChildOfSameHeight(node: AstNode): void {\n\t\tthis.throwIfImmutable();\n\t\tthis._children.unshift(node);\n\t\tthis.handleChildrenChanged();\n\t}\n\n\tpublic unprependChild(): AstNode | undefined {\n\t\tthis.throwIfImmutable();\n\t\tconst item = this._children.shift();\n\t\tthis.handleChildrenChanged();\n\t\treturn item;\n\t}\n\n\tpublic override toMutable(): ListAstNode {\n\t\treturn this;\n\t}\n}\n\n/**\n * Immutable, if all children are immutable.\n*/\nclass ImmutableArrayListAstNode extends ArrayListAstNode {\n\toverride toMutable(): ListAstNode {\n\t\treturn new ArrayListAstNode(this.length, this.listHeight, [...this.children], this.missingOpeningBracketIds);\n\t}\n\n\tprotected override throwIfImmutable(): void {\n\t\tthrow new Error('this instance is immutable');\n\t}\n}\n\nconst emptyArray: readonly AstNode[] = [];\n\nabstract class ImmutableLeafAstNode extends BaseAstNode {\n\tpublic get listHeight() {\n\t\treturn 0;\n\t}\n\tpublic get childrenLength(): number {\n\t\treturn 0;\n\t}\n\tpublic getChild(idx: number): AstNode | null {\n\t\treturn null;\n\t}\n\tpublic get children(): readonly AstNode[] {\n\t\treturn emptyArray;\n\t}\n\tpublic deepClone(): this & AstNode {\n\t\treturn this as this & AstNode;\n\t}\n}\n\nexport class TextAstNode extends ImmutableLeafAstNode {\n\tpublic get kind(): AstNodeKind.Text {\n\t\treturn AstNodeKind.Text;\n\t}\n\tpublic get missingOpeningBracketIds(): SmallImmutableSet {\n\t\treturn SmallImmutableSet.getEmpty();\n\t}\n\n\tpublic canBeReused(_openedBracketIds: SmallImmutableSet) {\n\t\treturn true;\n\t}\n\n\tpublic computeMinIndentation(offset: Length, textModel: ITextModel): number {\n\t\tconst start = lengthToObj(offset);\n\t\t// Text ast nodes don't have partial indentation (ensured by the tokenizer).\n\t\t// Thus, if this text node does not start at column 0, the first line cannot have any indentation at all.\n\t\tconst startLineNumber = (start.columnCount === 0 ? start.lineCount : start.lineCount + 1) + 1;\n\t\tconst endLineNumber = lengthGetLineCount(lengthAdd(offset, this.length)) + 1;\n\n\t\tlet result = Number.MAX_SAFE_INTEGER;\n\n\t\tfor (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n\t\t\tconst firstNonWsColumn = textModel.getLineFirstNonWhitespaceColumn(lineNumber);\n\t\t\tconst lineContent = textModel.getLineContent(lineNumber);\n\t\t\tif (firstNonWsColumn === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst visibleColumn = CursorColumns.visibleColumnFromColumn(lineContent, firstNonWsColumn, textModel.getOptions().tabSize)!;\n\t\t\tresult = Math.min(result, visibleColumn);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n\nexport class BracketAstNode extends ImmutableLeafAstNode {\n\tpublic static create(\n\t\tlength: Length,\n\t\tlanguageId: string,\n\t\tbracketIds: SmallImmutableSet\n\t): BracketAstNode {\n\t\tconst node = new BracketAstNode(length, languageId, bracketIds);\n\t\treturn node;\n\t}\n\n\tpublic get kind(): AstNodeKind.Bracket {\n\t\treturn AstNodeKind.Bracket;\n\t}\n\n\tpublic get missingOpeningBracketIds(): SmallImmutableSet {\n\t\treturn SmallImmutableSet.getEmpty();\n\t}\n\n\tprivate constructor(\n\t\tlength: Length,\n\t\tpublic readonly languageId: string,\n\t\t/**\n\t\t * In case of a opening bracket, this is the id of the opening bracket.\n\t\t * In case of a closing bracket, this contains the ids of all opening brackets it can close.\n\t\t*/\n\t\tpublic readonly bracketIds: SmallImmutableSet\n\t) {\n\t\tsuper(length);\n\t}\n\n\tpublic canBeReused(_openedBracketIds: SmallImmutableSet) {\n\t\t// These nodes could be reused,\n\t\t// but not in a general way.\n\t\t// Their parent may be reused.\n\t\treturn false;\n\t}\n\n\tpublic computeMinIndentation(offset: Length, textModel: ITextModel): number {\n\t\treturn Number.MAX_SAFE_INTEGER;\n\t}\n}\n\nexport class InvalidBracketAstNode extends ImmutableLeafAstNode {\n\tpublic get kind(): AstNodeKind.UnexpectedClosingBracket {\n\t\treturn AstNodeKind.UnexpectedClosingBracket;\n\t}\n\n\tpublic readonly missingOpeningBracketIds: SmallImmutableSet;\n\n\tpublic constructor(closingBrackets: SmallImmutableSet, length: Length) {\n\t\tsuper(length);\n\t\tthis.missingOpeningBracketIds = closingBrackets;\n\t}\n\n\tpublic canBeReused(openedBracketIds: SmallImmutableSet) {\n\t\treturn !openedBracketIds.intersects(this.missingOpeningBracketIds);\n\t}\n\n\tpublic computeMinIndentation(offset: Length, textModel: ITextModel): number {\n\t\treturn Number.MAX_SAFE_INTEGER;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { AstNode, AstNodeKind, ListAstNode } from './ast';\n\n/**\n * Concatenates a list of (2,3) AstNode's into a single (2,3) AstNode.\n * This mutates the items of the input array!\n * If all items have the same height, this method has runtime O(items.length).\n * Otherwise, it has runtime O(items.length * max(log(items.length), items.max(i => i.height))).\n*/\nexport function concat23Trees(items: AstNode[]): AstNode | null {\n\tif (items.length === 0) {\n\t\treturn null;\n\t}\n\tif (items.length === 1) {\n\t\treturn items[0];\n\t}\n\n\tlet i = 0;\n\t/**\n\t * Reads nodes of same height and concatenates them to a single node.\n\t*/\n\tfunction readNode(): AstNode | null {\n\t\tif (i >= items.length) {\n\t\t\treturn null;\n\t\t}\n\t\tconst start = i;\n\t\tconst height = items[start].listHeight;\n\n\t\ti++;\n\t\twhile (i < items.length && items[i].listHeight === height) {\n\t\t\ti++;\n\t\t}\n\n\t\tif (i - start >= 2) {\n\t\t\treturn concat23TreesOfSameHeight(start === 0 && i === items.length ? items : items.slice(start, i), false);\n\t\t} else {\n\t\t\treturn items[start];\n\t\t}\n\t}\n\n\t// The items might not have the same height.\n\t// We merge all items by using a binary concat operator.\n\tlet first = readNode()!; // There must be a first item\n\tlet second = readNode();\n\tif (!second) {\n\t\treturn first;\n\t}\n\n\tfor (let item = readNode(); item; item = readNode()) {\n\t\t// Prefer concatenating smaller trees, as the runtime of concat depends on the tree height.\n\t\tif (heightDiff(first, second) <= heightDiff(second, item)) {\n\t\t\tfirst = concat(first, second);\n\t\t\tsecond = item;\n\t\t} else {\n\t\t\tsecond = concat(second, item);\n\t\t}\n\t}\n\n\tconst result = concat(first, second);\n\treturn result;\n}\n\nexport function concat23TreesOfSameHeight(items: AstNode[], createImmutableLists: boolean = false): AstNode | null {\n\tif (items.length === 0) {\n\t\treturn null;\n\t}\n\tif (items.length === 1) {\n\t\treturn items[0];\n\t}\n\n\tlet length = items.length;\n\t// All trees have same height, just create parent nodes.\n\twhile (length > 3) {\n\t\tconst newLength = length >> 1;\n\t\tfor (let i = 0; i < newLength; i++) {\n\t\t\tconst j = i << 1;\n\t\t\titems[i] = ListAstNode.create23(items[j], items[j + 1], j + 3 === length ? items[j + 2] : null, createImmutableLists);\n\t\t}\n\t\tlength = newLength;\n\t}\n\treturn ListAstNode.create23(items[0], items[1], length >= 3 ? items[2] : null, createImmutableLists);\n}\n\nfunction heightDiff(node1: AstNode, node2: AstNode): number {\n\treturn Math.abs(node1.listHeight - node2.listHeight);\n}\n\nfunction concat(node1: AstNode, node2: AstNode): AstNode {\n\tif (node1.listHeight === node2.listHeight) {\n\t\treturn ListAstNode.create23(node1, node2, null, false);\n\t}\n\telse if (node1.listHeight > node2.listHeight) {\n\t\t// node1 is the tree we want to insert into\n\t\treturn append(node1 as ListAstNode, node2);\n\t} else {\n\t\treturn prepend(node2 as ListAstNode, node1);\n\t}\n}\n\n/**\n * Appends the given node to the end of this (2,3) tree.\n * Returns the new root.\n*/\nfunction append(list: ListAstNode, nodeToAppend: AstNode): AstNode {\n\tlist = list.toMutable() as ListAstNode;\n\tlet curNode: AstNode = list;\n\tconst parents = new Array();\n\tlet nodeToAppendOfCorrectHeight: AstNode | undefined;\n\twhile (true) {\n\t\t// assert nodeToInsert.listHeight <= curNode.listHeight\n\t\tif (nodeToAppend.listHeight === curNode.listHeight) {\n\t\t\tnodeToAppendOfCorrectHeight = nodeToAppend;\n\t\t\tbreak;\n\t\t}\n\t\t// assert 0 <= nodeToInsert.listHeight < curNode.listHeight\n\t\tif (curNode.kind !== AstNodeKind.List) {\n\t\t\tthrow new Error('unexpected');\n\t\t}\n\t\tparents.push(curNode);\n\t\t// assert 2 <= curNode.childrenLength <= 3\n\t\tcurNode = curNode.makeLastElementMutable()!;\n\t}\n\t// assert nodeToAppendOfCorrectHeight!.listHeight === curNode.listHeight\n\tfor (let i = parents.length - 1; i >= 0; i--) {\n\t\tconst parent = parents[i];\n\t\tif (nodeToAppendOfCorrectHeight) {\n\t\t\t// Can we take the element?\n\t\t\tif (parent.childrenLength >= 3) {\n\t\t\t\t// assert parent.childrenLength === 3 && parent.listHeight === nodeToAppendOfCorrectHeight.listHeight + 1\n\n\t\t\t\t// we need to split to maintain (2,3)-tree property.\n\t\t\t\t// Send the third element + the new element to the parent.\n\t\t\t\tnodeToAppendOfCorrectHeight = ListAstNode.create23(parent.unappendChild()!, nodeToAppendOfCorrectHeight, null, false);\n\t\t\t} else {\n\t\t\t\tparent.appendChildOfSameHeight(nodeToAppendOfCorrectHeight);\n\t\t\t\tnodeToAppendOfCorrectHeight = undefined;\n\t\t\t}\n\t\t} else {\n\t\t\tparent.handleChildrenChanged();\n\t\t}\n\t}\n\tif (nodeToAppendOfCorrectHeight) {\n\t\treturn ListAstNode.create23(list, nodeToAppendOfCorrectHeight, null, false);\n\t} else {\n\t\treturn list;\n\t}\n}\n\n/**\n * Prepends the given node to the end of this (2,3) tree.\n * Returns the new root.\n*/\nfunction prepend(list: ListAstNode, nodeToAppend: AstNode): AstNode {\n\tlist = list.toMutable() as ListAstNode;\n\tlet curNode: AstNode = list;\n\tconst parents = new Array();\n\t// assert nodeToInsert.listHeight <= curNode.listHeight\n\twhile (nodeToAppend.listHeight !== curNode.listHeight) {\n\t\t// assert 0 <= nodeToInsert.listHeight < curNode.listHeight\n\t\tif (curNode.kind !== AstNodeKind.List) {\n\t\t\tthrow new Error('unexpected');\n\t\t}\n\t\tparents.push(curNode);\n\t\t// assert 2 <= curNode.childrenFast.length <= 3\n\t\tcurNode = curNode.makeFirstElementMutable()!;\n\t}\n\tlet nodeToPrependOfCorrectHeight: AstNode | undefined = nodeToAppend;\n\t// assert nodeToAppendOfCorrectHeight!.listHeight === curNode.listHeight\n\tfor (let i = parents.length - 1; i >= 0; i--) {\n\t\tconst parent = parents[i];\n\t\tif (nodeToPrependOfCorrectHeight) {\n\t\t\t// Can we take the element?\n\t\t\tif (parent.childrenLength >= 3) {\n\t\t\t\t// assert parent.childrenLength === 3 && parent.listHeight === nodeToAppendOfCorrectHeight.listHeight + 1\n\n\t\t\t\t// we need to split to maintain (2,3)-tree property.\n\t\t\t\t// Send the third element + the new element to the parent.\n\t\t\t\tnodeToPrependOfCorrectHeight = ListAstNode.create23(nodeToPrependOfCorrectHeight, parent.unprependChild()!, null, false);\n\t\t\t} else {\n\t\t\t\tparent.prependChildOfSameHeight(nodeToPrependOfCorrectHeight);\n\t\t\t\tnodeToPrependOfCorrectHeight = undefined;\n\t\t\t}\n\t\t} else {\n\t\t\tparent.handleChildrenChanged();\n\t\t}\n\t}\n\tif (nodeToPrependOfCorrectHeight) {\n\t\treturn ListAstNode.create23(nodeToPrependOfCorrectHeight, list, null, false);\n\t} else {\n\t\treturn list;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { AstNode, AstNodeKind, BracketAstNode, InvalidBracketAstNode, ListAstNode, PairAstNode, TextAstNode } from './ast';\nimport { BeforeEditPositionMapper, TextEditInfo } from './beforeEditPositionMapper';\nimport { SmallImmutableSet } from './smallImmutableSet';\nimport { lengthIsZero, lengthLessThan } from './length';\nimport { concat23Trees, concat23TreesOfSameHeight } from './concat23Trees';\nimport { NodeReader } from './nodeReader';\nimport { OpeningBracketId, Tokenizer, TokenKind } from './tokenizer';\n\n/**\n * Non incrementally built ASTs are immutable.\n*/\nexport function parseDocument(tokenizer: Tokenizer, edits: TextEditInfo[], oldNode: AstNode | undefined, createImmutableLists: boolean): AstNode {\n\tconst parser = new Parser(tokenizer, edits, oldNode, createImmutableLists);\n\treturn parser.parseDocument();\n}\n\n/**\n * Non incrementally built ASTs are immutable.\n*/\nclass Parser {\n\tprivate readonly oldNodeReader?: NodeReader;\n\tprivate readonly positionMapper: BeforeEditPositionMapper;\n\tprivate _itemsConstructed: number = 0;\n\tprivate _itemsFromCache: number = 0;\n\n\tconstructor(\n\t\tprivate readonly tokenizer: Tokenizer,\n\t\tedits: TextEditInfo[],\n\t\toldNode: AstNode | undefined,\n\t\tprivate readonly createImmutableLists: boolean,\n\t) {\n\t\tif (oldNode && createImmutableLists) {\n\t\t\tthrow new Error('Not supported');\n\t\t}\n\n\t\tthis.oldNodeReader = oldNode ? new NodeReader(oldNode) : undefined;\n\t\tthis.positionMapper = new BeforeEditPositionMapper(edits, tokenizer.length);\n\t}\n\n\tparseDocument(): AstNode {\n\t\tthis._itemsConstructed = 0;\n\t\tthis._itemsFromCache = 0;\n\n\t\tlet result = this.parseList(SmallImmutableSet.getEmpty());\n\t\tif (!result) {\n\t\t\tresult = ListAstNode.getEmpty();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate parseList(\n\t\topenedBracketIds: SmallImmutableSet,\n\t): AstNode | null {\n\t\tconst items = new Array();\n\n\t\twhile (true) {\n\t\t\tconst token = this.tokenizer.peek();\n\t\t\tif (\n\t\t\t\t!token ||\n\t\t\t\t(token.kind === TokenKind.ClosingBracket &&\n\t\t\t\t\ttoken.bracketIds.intersects(openedBracketIds))\n\t\t\t) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst child = this.parseChild(openedBracketIds);\n\t\t\tif (child.kind === AstNodeKind.List && child.childrenLength === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\titems.push(child);\n\t\t}\n\n\t\t// When there is no oldNodeReader, all items are created from scratch and must have the same height.\n\t\tconst result = this.oldNodeReader ? concat23Trees(items) : concat23TreesOfSameHeight(items, this.createImmutableLists);\n\t\treturn result;\n\t}\n\n\tprivate parseChild(\n\t\topenedBracketIds: SmallImmutableSet,\n\t): AstNode {\n\t\tif (this.oldNodeReader) {\n\t\t\tconst maxCacheableLength = this.positionMapper.getDistanceToNextChange(this.tokenizer.offset);\n\t\t\tif (!lengthIsZero(maxCacheableLength)) {\n\t\t\t\tconst cachedNode = this.oldNodeReader.readLongestNodeAt(this.positionMapper.getOffsetBeforeChange(this.tokenizer.offset), curNode => {\n\t\t\t\t\tif (!lengthLessThan(curNode.length, maxCacheableLength)) {\n\t\t\t\t\t\t// Either the node contains edited text or touches edited text.\n\t\t\t\t\t\t// In the latter case, brackets might have been extended (`end` -> `ending`), so even touching nodes cannot be reused.\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tconst canBeReused = curNode.canBeReused(openedBracketIds);\n\t\t\t\t\treturn canBeReused;\n\t\t\t\t});\n\n\t\t\t\tif (cachedNode) {\n\t\t\t\t\tthis._itemsFromCache++;\n\t\t\t\t\tthis.tokenizer.skip(cachedNode.length);\n\t\t\t\t\treturn cachedNode;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._itemsConstructed++;\n\n\t\tconst token = this.tokenizer.read()!;\n\n\t\tswitch (token.kind) {\n\t\t\tcase TokenKind.ClosingBracket:\n\t\t\t\treturn new InvalidBracketAstNode(token.bracketIds, token.length);\n\n\t\t\tcase TokenKind.Text:\n\t\t\t\treturn token.astNode as TextAstNode;\n\n\t\t\tcase TokenKind.OpeningBracket: {\n\t\t\t\tconst set = openedBracketIds.merge(token.bracketIds);\n\t\t\t\tconst child = this.parseList(set);\n\n\t\t\t\tconst nextToken = this.tokenizer.peek();\n\t\t\t\tif (\n\t\t\t\t\tnextToken &&\n\t\t\t\t\tnextToken.kind === TokenKind.ClosingBracket &&\n\t\t\t\t\t(nextToken.bracketId === token.bracketId || nextToken.bracketIds.intersects(token.bracketIds))\n\t\t\t\t) {\n\t\t\t\t\tthis.tokenizer.read();\n\t\t\t\t\treturn PairAstNode.create(\n\t\t\t\t\t\ttoken.astNode as BracketAstNode,\n\t\t\t\t\t\tchild,\n\t\t\t\t\t\tnextToken.astNode as BracketAstNode\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\treturn PairAstNode.create(\n\t\t\t\t\t\ttoken.astNode as BracketAstNode,\n\t\t\t\t\t\tchild,\n\t\t\t\t\t\tnull\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new Error('unexpected');\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { ITextBuffer } from 'vs/editor/common/model';\n\nclass SpacesDiffResult {\n\tpublic spacesDiff: number = 0;\n\tpublic looksLikeAlignment: boolean = false;\n}\n\n/**\n * Compute the diff in spaces between two line's indentation.\n */\nfunction spacesDiff(a: string, aLength: number, b: string, bLength: number, result: SpacesDiffResult): void {\n\n\tresult.spacesDiff = 0;\n\tresult.looksLikeAlignment = false;\n\n\t// This can go both ways (e.g.):\n\t// - a: \"\\t\"\n\t// - b: \"\\t \"\n\t// => This should count 1 tab and 4 spaces\n\n\tlet i: number;\n\n\tfor (i = 0; i < aLength && i < bLength; i++) {\n\t\tconst aCharCode = a.charCodeAt(i);\n\t\tconst bCharCode = b.charCodeAt(i);\n\n\t\tif (aCharCode !== bCharCode) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet aSpacesCnt = 0, aTabsCount = 0;\n\tfor (let j = i; j < aLength; j++) {\n\t\tconst aCharCode = a.charCodeAt(j);\n\t\tif (aCharCode === CharCode.Space) {\n\t\t\taSpacesCnt++;\n\t\t} else {\n\t\t\taTabsCount++;\n\t\t}\n\t}\n\n\tlet bSpacesCnt = 0, bTabsCount = 0;\n\tfor (let j = i; j < bLength; j++) {\n\t\tconst bCharCode = b.charCodeAt(j);\n\t\tif (bCharCode === CharCode.Space) {\n\t\t\tbSpacesCnt++;\n\t\t} else {\n\t\t\tbTabsCount++;\n\t\t}\n\t}\n\n\tif (aSpacesCnt > 0 && aTabsCount > 0) {\n\t\treturn;\n\t}\n\tif (bSpacesCnt > 0 && bTabsCount > 0) {\n\t\treturn;\n\t}\n\n\tconst tabsDiff = Math.abs(aTabsCount - bTabsCount);\n\tconst spacesDiff = Math.abs(aSpacesCnt - bSpacesCnt);\n\n\tif (tabsDiff === 0) {\n\t\t// check if the indentation difference might be caused by alignment reasons\n\t\t// sometime folks like to align their code, but this should not be used as a hint\n\t\tresult.spacesDiff = spacesDiff;\n\n\t\tif (spacesDiff > 0 && 0 <= bSpacesCnt - 1 && bSpacesCnt - 1 < a.length && bSpacesCnt < b.length) {\n\t\t\tif (b.charCodeAt(bSpacesCnt) !== CharCode.Space && a.charCodeAt(bSpacesCnt - 1) === CharCode.Space) {\n\t\t\t\tif (a.charCodeAt(a.length - 1) === CharCode.Comma) {\n\t\t\t\t\t// This looks like an alignment desire: e.g.\n\t\t\t\t\t// const a = b + c,\n\t\t\t\t\t// d = b - c;\n\t\t\t\t\tresult.looksLikeAlignment = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\tif (spacesDiff % tabsDiff === 0) {\n\t\tresult.spacesDiff = spacesDiff / tabsDiff;\n\t\treturn;\n\t}\n}\n\n/**\n * Result for a guessIndentation\n */\nexport interface IGuessedIndentation {\n\t/**\n\t * If indentation is based on spaces (`insertSpaces` = true), then what is the number of spaces that make an indent?\n\t */\n\ttabSize: number;\n\t/**\n\t * Is indentation based on spaces?\n\t */\n\tinsertSpaces: boolean;\n}\n\nexport function guessIndentation(source: ITextBuffer, defaultTabSize: number, defaultInsertSpaces: boolean): IGuessedIndentation {\n\t// Look at most at the first 10k lines\n\tconst linesCount = Math.min(source.getLineCount(), 10000);\n\n\tlet linesIndentedWithTabsCount = 0;\t\t\t\t// number of lines that contain at least one tab in indentation\n\tlet linesIndentedWithSpacesCount = 0;\t\t\t// number of lines that contain only spaces in indentation\n\n\tlet previousLineText = '';\t\t\t\t\t\t// content of latest line that contained non-whitespace chars\n\tlet previousLineIndentation = 0;\t\t\t\t// index at which latest line contained the first non-whitespace char\n\n\tconst ALLOWED_TAB_SIZE_GUESSES = [2, 4, 6, 8, 3, 5, 7];\t// prefer even guesses for `tabSize`, limit to [2, 8].\n\tconst MAX_ALLOWED_TAB_SIZE_GUESS = 8;\t\t\t// max(ALLOWED_TAB_SIZE_GUESSES) = 8\n\n\tconst spacesDiffCount = [0, 0, 0, 0, 0, 0, 0, 0, 0];\t\t// `tabSize` scores\n\tconst tmp = new SpacesDiffResult();\n\n\tfor (let lineNumber = 1; lineNumber <= linesCount; lineNumber++) {\n\t\tconst currentLineLength = source.getLineLength(lineNumber);\n\t\tconst currentLineText = source.getLineContent(lineNumber);\n\n\t\t// if the text buffer is chunk based, so long lines are cons-string, v8 will flattern the string when we check charCode.\n\t\t// checking charCode on chunks directly is cheaper.\n\t\tconst useCurrentLineText = (currentLineLength <= 65536);\n\n\t\tlet currentLineHasContent = false;\t\t\t// does `currentLineText` contain non-whitespace chars\n\t\tlet currentLineIndentation = 0;\t\t\t\t// index at which `currentLineText` contains the first non-whitespace char\n\t\tlet currentLineSpacesCount = 0;\t\t\t\t// count of spaces found in `currentLineText` indentation\n\t\tlet currentLineTabsCount = 0;\t\t\t\t// count of tabs found in `currentLineText` indentation\n\t\tfor (let j = 0, lenJ = currentLineLength; j < lenJ; j++) {\n\t\t\tconst charCode = (useCurrentLineText ? currentLineText.charCodeAt(j) : source.getLineCharCode(lineNumber, j));\n\n\t\t\tif (charCode === CharCode.Tab) {\n\t\t\t\tcurrentLineTabsCount++;\n\t\t\t} else if (charCode === CharCode.Space) {\n\t\t\t\tcurrentLineSpacesCount++;\n\t\t\t} else {\n\t\t\t\t// Hit non whitespace character on this line\n\t\t\t\tcurrentLineHasContent = true;\n\t\t\t\tcurrentLineIndentation = j;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Ignore empty or only whitespace lines\n\t\tif (!currentLineHasContent) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (currentLineTabsCount > 0) {\n\t\t\tlinesIndentedWithTabsCount++;\n\t\t} else if (currentLineSpacesCount > 1) {\n\t\t\tlinesIndentedWithSpacesCount++;\n\t\t}\n\n\t\tspacesDiff(previousLineText, previousLineIndentation, currentLineText, currentLineIndentation, tmp);\n\n\t\tif (tmp.looksLikeAlignment) {\n\t\t\t// if defaultInsertSpaces === true && the spaces count == tabSize, we may want to count it as valid indentation\n\t\t\t//\n\t\t\t// - item1\n\t\t\t// - item2\n\t\t\t//\n\t\t\t// otherwise skip this line entirely\n\t\t\t//\n\t\t\t// const a = 1,\n\t\t\t// b = 2;\n\n\t\t\tif (!(defaultInsertSpaces && defaultTabSize === tmp.spacesDiff)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tconst currentSpacesDiff = tmp.spacesDiff;\n\t\tif (currentSpacesDiff <= MAX_ALLOWED_TAB_SIZE_GUESS) {\n\t\t\tspacesDiffCount[currentSpacesDiff]++;\n\t\t}\n\n\t\tpreviousLineText = currentLineText;\n\t\tpreviousLineIndentation = currentLineIndentation;\n\t}\n\n\tlet insertSpaces = defaultInsertSpaces;\n\tif (linesIndentedWithTabsCount !== linesIndentedWithSpacesCount) {\n\t\tinsertSpaces = (linesIndentedWithTabsCount < linesIndentedWithSpacesCount);\n\t}\n\n\tlet tabSize = defaultTabSize;\n\n\t// Guess tabSize only if inserting spaces...\n\tif (insertSpaces) {\n\t\tlet tabSizeScore = (insertSpaces ? 0 : 0.1 * linesCount);\n\n\t\t// console.log(\"score threshold: \" + tabSizeScore);\n\n\t\tALLOWED_TAB_SIZE_GUESSES.forEach((possibleTabSize) => {\n\t\t\tconst possibleTabSizeScore = spacesDiffCount[possibleTabSize];\n\t\t\tif (possibleTabSizeScore > tabSizeScore) {\n\t\t\t\ttabSizeScore = possibleTabSizeScore;\n\t\t\t\ttabSize = possibleTabSize;\n\t\t\t}\n\t\t});\n\n\t\t// Let a tabSize of 2 win even if it is not the maximum\n\t\t// (only in case 4 was guessed)\n\t\tif (tabSize === 4 && spacesDiffCount[4] > 0 && spacesDiffCount[2] > 0 && spacesDiffCount[2] >= spacesDiffCount[4] / 2) {\n\t\t\ttabSize = 2;\n\t\t}\n\t}\n\n\n\t// console.log('--------------------------');\n\t// console.log('linesIndentedWithTabsCount: ' + linesIndentedWithTabsCount + ', linesIndentedWithSpacesCount: ' + linesIndentedWithSpacesCount);\n\t// console.log('spacesDiffCount: ' + spacesDiffCount);\n\t// console.log('tabSize: ' + tabSize + ', tabSizeScore: ' + tabSizeScore);\n\n\treturn {\n\t\tinsertSpaces: insertSpaces,\n\t\ttabSize: tabSize\n\t};\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Range } from 'vs/editor/common/core/range';\nimport { TrackedRangeStickiness } from 'vs/editor/common/model';\nimport { ModelDecorationOptions } from 'vs/editor/common/model/textModel';\n\n//\n// The red-black tree is based on the \"Introduction to Algorithms\" by Cormen, Leiserson and Rivest.\n//\n\nexport const enum ClassName {\n\tEditorHintDecoration = 'squiggly-hint',\n\tEditorInfoDecoration = 'squiggly-info',\n\tEditorWarningDecoration = 'squiggly-warning',\n\tEditorErrorDecoration = 'squiggly-error',\n\tEditorUnnecessaryDecoration = 'squiggly-unnecessary',\n\tEditorUnnecessaryInlineDecoration = 'squiggly-inline-unnecessary',\n\tEditorDeprecatedInlineDecoration = 'squiggly-inline-deprecated'\n}\n\nexport const enum NodeColor {\n\tBlack = 0,\n\tRed = 1,\n}\n\nconst enum Constants {\n\tColorMask = 0b00000001,\n\tColorMaskInverse = 0b11111110,\n\tColorOffset = 0,\n\n\tIsVisitedMask = 0b00000010,\n\tIsVisitedMaskInverse = 0b11111101,\n\tIsVisitedOffset = 1,\n\n\tIsForValidationMask = 0b00000100,\n\tIsForValidationMaskInverse = 0b11111011,\n\tIsForValidationOffset = 2,\n\n\tStickinessMask = 0b00011000,\n\tStickinessMaskInverse = 0b11100111,\n\tStickinessOffset = 3,\n\n\tCollapseOnReplaceEditMask = 0b00100000,\n\tCollapseOnReplaceEditMaskInverse = 0b11011111,\n\tCollapseOnReplaceEditOffset = 5,\n\n\t/**\n\t * Due to how deletion works (in order to avoid always walking the right subtree of the deleted node),\n\t * the deltas for nodes can grow and shrink dramatically. It has been observed, in practice, that unless\n\t * the deltas are corrected, integer overflow will occur.\n\t *\n\t * The integer overflow occurs when 53 bits are used in the numbers, but we will try to avoid it as\n\t * a node's delta gets below a negative 30 bits number.\n\t *\n\t * MIN SMI (SMall Integer) as defined in v8.\n\t * one bit is lost for boxing/unboxing flag.\n\t * one bit is lost for sign flag.\n\t * See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values\n\t */\n\tMIN_SAFE_DELTA = -(1 << 30),\n\t/**\n\t * MAX SMI (SMall Integer) as defined in v8.\n\t * one bit is lost for boxing/unboxing flag.\n\t * one bit is lost for sign flag.\n\t * See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values\n\t */\n\tMAX_SAFE_DELTA = 1 << 30,\n}\n\nexport function getNodeColor(node: IntervalNode): NodeColor {\n\treturn ((node.metadata & Constants.ColorMask) >>> Constants.ColorOffset);\n}\nfunction setNodeColor(node: IntervalNode, color: NodeColor): void {\n\tnode.metadata = (\n\t\t(node.metadata & Constants.ColorMaskInverse) | (color << Constants.ColorOffset)\n\t);\n}\nfunction getNodeIsVisited(node: IntervalNode): boolean {\n\treturn ((node.metadata & Constants.IsVisitedMask) >>> Constants.IsVisitedOffset) === 1;\n}\nfunction setNodeIsVisited(node: IntervalNode, value: boolean): void {\n\tnode.metadata = (\n\t\t(node.metadata & Constants.IsVisitedMaskInverse) | ((value ? 1 : 0) << Constants.IsVisitedOffset)\n\t);\n}\nfunction getNodeIsForValidation(node: IntervalNode): boolean {\n\treturn ((node.metadata & Constants.IsForValidationMask) >>> Constants.IsForValidationOffset) === 1;\n}\nfunction setNodeIsForValidation(node: IntervalNode, value: boolean): void {\n\tnode.metadata = (\n\t\t(node.metadata & Constants.IsForValidationMaskInverse) | ((value ? 1 : 0) << Constants.IsForValidationOffset)\n\t);\n}\nfunction getNodeStickiness(node: IntervalNode): TrackedRangeStickiness {\n\treturn ((node.metadata & Constants.StickinessMask) >>> Constants.StickinessOffset);\n}\nfunction _setNodeStickiness(node: IntervalNode, stickiness: TrackedRangeStickiness): void {\n\tnode.metadata = (\n\t\t(node.metadata & Constants.StickinessMaskInverse) | (stickiness << Constants.StickinessOffset)\n\t);\n}\nfunction getCollapseOnReplaceEdit(node: IntervalNode): boolean {\n\treturn ((node.metadata & Constants.CollapseOnReplaceEditMask) >>> Constants.CollapseOnReplaceEditOffset) === 1;\n}\nfunction setCollapseOnReplaceEdit(node: IntervalNode, value: boolean): void {\n\tnode.metadata = (\n\t\t(node.metadata & Constants.CollapseOnReplaceEditMaskInverse) | ((value ? 1 : 0) << Constants.CollapseOnReplaceEditOffset)\n\t);\n}\n\nexport class IntervalNode {\n\n\t/**\n\t * contains binary encoded information for color, visited, isForValidation and stickiness.\n\t */\n\tpublic metadata: number;\n\n\tpublic parent: IntervalNode;\n\tpublic left: IntervalNode;\n\tpublic right: IntervalNode;\n\n\tpublic start: number;\n\tpublic end: number;\n\tpublic delta: number;\n\tpublic maxEnd: number;\n\n\tpublic id: string;\n\tpublic ownerId: number;\n\tpublic options: ModelDecorationOptions;\n\n\tpublic cachedVersionId: number;\n\tpublic cachedAbsoluteStart: number;\n\tpublic cachedAbsoluteEnd: number;\n\tpublic range: Range | null;\n\n\tconstructor(id: string, start: number, end: number) {\n\t\tthis.metadata = 0;\n\n\t\tthis.parent = this;\n\t\tthis.left = this;\n\t\tthis.right = this;\n\t\tsetNodeColor(this, NodeColor.Red);\n\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\t// FORCE_OVERFLOWING_TEST: this.delta = start;\n\t\tthis.delta = 0;\n\t\tthis.maxEnd = end;\n\n\t\tthis.id = id;\n\t\tthis.ownerId = 0;\n\t\tthis.options = null!;\n\t\tsetNodeIsForValidation(this, false);\n\t\t_setNodeStickiness(this, TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges);\n\t\tsetCollapseOnReplaceEdit(this, false);\n\n\t\tthis.cachedVersionId = 0;\n\t\tthis.cachedAbsoluteStart = start;\n\t\tthis.cachedAbsoluteEnd = end;\n\t\tthis.range = null;\n\n\t\tsetNodeIsVisited(this, false);\n\t}\n\n\tpublic reset(versionId: number, start: number, end: number, range: Range): void {\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\tthis.maxEnd = end;\n\t\tthis.cachedVersionId = versionId;\n\t\tthis.cachedAbsoluteStart = start;\n\t\tthis.cachedAbsoluteEnd = end;\n\t\tthis.range = range;\n\t}\n\n\tpublic setOptions(options: ModelDecorationOptions) {\n\t\tthis.options = options;\n\t\tconst className = this.options.className;\n\t\tsetNodeIsForValidation(this, (\n\t\t\tclassName === ClassName.EditorErrorDecoration\n\t\t\t|| className === ClassName.EditorWarningDecoration\n\t\t\t|| className === ClassName.EditorInfoDecoration\n\t\t));\n\t\t_setNodeStickiness(this, this.options.stickiness);\n\t\tsetCollapseOnReplaceEdit(this, this.options.collapseOnReplaceEdit);\n\t}\n\n\tpublic setCachedOffsets(absoluteStart: number, absoluteEnd: number, cachedVersionId: number): void {\n\t\tif (this.cachedVersionId !== cachedVersionId) {\n\t\t\tthis.range = null;\n\t\t}\n\t\tthis.cachedVersionId = cachedVersionId;\n\t\tthis.cachedAbsoluteStart = absoluteStart;\n\t\tthis.cachedAbsoluteEnd = absoluteEnd;\n\t}\n\n\tpublic detach(): void {\n\t\tthis.parent = null!;\n\t\tthis.left = null!;\n\t\tthis.right = null!;\n\t}\n}\n\nexport const SENTINEL: IntervalNode = new IntervalNode(null!, 0, 0);\nSENTINEL.parent = SENTINEL;\nSENTINEL.left = SENTINEL;\nSENTINEL.right = SENTINEL;\nsetNodeColor(SENTINEL, NodeColor.Black);\n\nexport class IntervalTree {\n\n\tpublic root: IntervalNode;\n\tpublic requestNormalizeDelta: boolean;\n\n\tconstructor() {\n\t\tthis.root = SENTINEL;\n\t\tthis.requestNormalizeDelta = false;\n\t}\n\n\tpublic intervalSearch(start: number, end: number, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] {\n\t\tif (this.root === SENTINEL) {\n\t\t\treturn [];\n\t\t}\n\t\treturn intervalSearch(this, start, end, filterOwnerId, filterOutValidation, cachedVersionId);\n\t}\n\n\tpublic search(filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] {\n\t\tif (this.root === SENTINEL) {\n\t\t\treturn [];\n\t\t}\n\t\treturn search(this, filterOwnerId, filterOutValidation, cachedVersionId);\n\t}\n\n\t/**\n\t * Will not set `cachedAbsoluteStart` nor `cachedAbsoluteEnd` on the returned nodes!\n\t */\n\tpublic collectNodesFromOwner(ownerId: number): IntervalNode[] {\n\t\treturn collectNodesFromOwner(this, ownerId);\n\t}\n\n\t/**\n\t * Will not set `cachedAbsoluteStart` nor `cachedAbsoluteEnd` on the returned nodes!\n\t */\n\tpublic collectNodesPostOrder(): IntervalNode[] {\n\t\treturn collectNodesPostOrder(this);\n\t}\n\n\tpublic insert(node: IntervalNode): void {\n\t\trbTreeInsert(this, node);\n\t\tthis._normalizeDeltaIfNecessary();\n\t}\n\n\tpublic delete(node: IntervalNode): void {\n\t\trbTreeDelete(this, node);\n\t\tthis._normalizeDeltaIfNecessary();\n\t}\n\n\tpublic resolveNode(node: IntervalNode, cachedVersionId: number): void {\n\t\tconst initialNode = node;\n\t\tlet delta = 0;\n\t\twhile (node !== this.root) {\n\t\t\tif (node === node.parent.right) {\n\t\t\t\tdelta += node.parent.delta;\n\t\t\t}\n\t\t\tnode = node.parent;\n\t\t}\n\n\t\tconst nodeStart = initialNode.start + delta;\n\t\tconst nodeEnd = initialNode.end + delta;\n\t\tinitialNode.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId);\n\t}\n\n\tpublic acceptReplace(offset: number, length: number, textLength: number, forceMoveMarkers: boolean): void {\n\t\t// Our strategy is to remove all directly impacted nodes, and then add them back to the tree.\n\n\t\t// (1) collect all nodes that are intersecting this edit as nodes of interest\n\t\tconst nodesOfInterest = searchForEditing(this, offset, offset + length);\n\n\t\t// (2) remove all nodes that are intersecting this edit\n\t\tfor (let i = 0, len = nodesOfInterest.length; i < len; i++) {\n\t\t\tconst node = nodesOfInterest[i];\n\t\t\trbTreeDelete(this, node);\n\t\t}\n\t\tthis._normalizeDeltaIfNecessary();\n\n\t\t// (3) edit all tree nodes except the nodes of interest\n\t\tnoOverlapReplace(this, offset, offset + length, textLength);\n\t\tthis._normalizeDeltaIfNecessary();\n\n\t\t// (4) edit the nodes of interest and insert them back in the tree\n\t\tfor (let i = 0, len = nodesOfInterest.length; i < len; i++) {\n\t\t\tconst node = nodesOfInterest[i];\n\t\t\tnode.start = node.cachedAbsoluteStart;\n\t\t\tnode.end = node.cachedAbsoluteEnd;\n\t\t\tnodeAcceptEdit(node, offset, (offset + length), textLength, forceMoveMarkers);\n\t\t\tnode.maxEnd = node.end;\n\t\t\trbTreeInsert(this, node);\n\t\t}\n\t\tthis._normalizeDeltaIfNecessary();\n\t}\n\n\tprivate _normalizeDeltaIfNecessary(): void {\n\t\tif (!this.requestNormalizeDelta) {\n\t\t\treturn;\n\t\t}\n\t\tthis.requestNormalizeDelta = false;\n\t\tnormalizeDelta(this);\n\t}\n}\n\n//#region Delta Normalization\nfunction normalizeDelta(T: IntervalTree): void {\n\tlet node = T.root;\n\tlet delta = 0;\n\twhile (node !== SENTINEL) {\n\n\t\tif (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {\n\t\t\t// go left\n\t\t\tnode = node.left;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n\t\t\t// go right\n\t\t\tdelta += node.delta;\n\t\t\tnode = node.right;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// handle current node\n\t\tnode.start = delta + node.start;\n\t\tnode.end = delta + node.end;\n\t\tnode.delta = 0;\n\t\trecomputeMaxEnd(node);\n\n\t\tsetNodeIsVisited(node, true);\n\n\t\t// going up from this node\n\t\tsetNodeIsVisited(node.left, false);\n\t\tsetNodeIsVisited(node.right, false);\n\t\tif (node === node.parent.right) {\n\t\t\tdelta -= node.parent.delta;\n\t\t}\n\t\tnode = node.parent;\n\t}\n\n\tsetNodeIsVisited(T.root, false);\n}\n//#endregion\n\n//#region Editing\n\nconst enum MarkerMoveSemantics {\n\tMarkerDefined = 0,\n\tForceMove = 1,\n\tForceStay = 2\n}\n\nfunction adjustMarkerBeforeColumn(markerOffset: number, markerStickToPreviousCharacter: boolean, checkOffset: number, moveSemantics: MarkerMoveSemantics): boolean {\n\tif (markerOffset < checkOffset) {\n\t\treturn true;\n\t}\n\tif (markerOffset > checkOffset) {\n\t\treturn false;\n\t}\n\tif (moveSemantics === MarkerMoveSemantics.ForceMove) {\n\t\treturn false;\n\t}\n\tif (moveSemantics === MarkerMoveSemantics.ForceStay) {\n\t\treturn true;\n\t}\n\treturn markerStickToPreviousCharacter;\n}\n\n/**\n * This is a lot more complicated than strictly necessary to maintain the same behaviour\n * as when decorations were implemented using two markers.\n */\nexport function nodeAcceptEdit(node: IntervalNode, start: number, end: number, textLength: number, forceMoveMarkers: boolean): void {\n\tconst nodeStickiness = getNodeStickiness(node);\n\tconst startStickToPreviousCharacter = (\n\t\tnodeStickiness === TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges\n\t\t|| nodeStickiness === TrackedRangeStickiness.GrowsOnlyWhenTypingBefore\n\t);\n\tconst endStickToPreviousCharacter = (\n\t\tnodeStickiness === TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges\n\t\t|| nodeStickiness === TrackedRangeStickiness.GrowsOnlyWhenTypingBefore\n\t);\n\n\tconst deletingCnt = (end - start);\n\tconst insertingCnt = textLength;\n\tconst commonLength = Math.min(deletingCnt, insertingCnt);\n\n\tconst nodeStart = node.start;\n\tlet startDone = false;\n\n\tconst nodeEnd = node.end;\n\tlet endDone = false;\n\n\tif (start <= nodeStart && nodeEnd <= end && getCollapseOnReplaceEdit(node)) {\n\t\t// This edit encompasses the entire decoration range\n\t\t// and the decoration has asked to become collapsed\n\t\tnode.start = start;\n\t\tstartDone = true;\n\t\tnode.end = start;\n\t\tendDone = true;\n\t}\n\n\t{\n\t\tconst moveSemantics = forceMoveMarkers ? MarkerMoveSemantics.ForceMove : (deletingCnt > 0 ? MarkerMoveSemantics.ForceStay : MarkerMoveSemantics.MarkerDefined);\n\t\tif (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, start, moveSemantics)) {\n\t\t\tstartDone = true;\n\t\t}\n\t\tif (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, start, moveSemantics)) {\n\t\t\tendDone = true;\n\t\t}\n\t}\n\n\tif (commonLength > 0 && !forceMoveMarkers) {\n\t\tconst moveSemantics = (deletingCnt > insertingCnt ? MarkerMoveSemantics.ForceStay : MarkerMoveSemantics.MarkerDefined);\n\t\tif (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, start + commonLength, moveSemantics)) {\n\t\t\tstartDone = true;\n\t\t}\n\t\tif (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, start + commonLength, moveSemantics)) {\n\t\t\tendDone = true;\n\t\t}\n\t}\n\n\t{\n\t\tconst moveSemantics = forceMoveMarkers ? MarkerMoveSemantics.ForceMove : MarkerMoveSemantics.MarkerDefined;\n\t\tif (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, end, moveSemantics)) {\n\t\t\tnode.start = start + insertingCnt;\n\t\t\tstartDone = true;\n\t\t}\n\t\tif (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, end, moveSemantics)) {\n\t\t\tnode.end = start + insertingCnt;\n\t\t\tendDone = true;\n\t\t}\n\t}\n\n\t// Finish\n\tconst deltaColumn = (insertingCnt - deletingCnt);\n\tif (!startDone) {\n\t\tnode.start = Math.max(0, nodeStart + deltaColumn);\n\t}\n\tif (!endDone) {\n\t\tnode.end = Math.max(0, nodeEnd + deltaColumn);\n\t}\n\n\tif (node.start > node.end) {\n\t\tnode.end = node.start;\n\t}\n}\n\nfunction searchForEditing(T: IntervalTree, start: number, end: number): IntervalNode[] {\n\t// https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree\n\t// Now, it is known that two intervals A and B overlap only when both\n\t// A.low <= B.high and A.high >= B.low. When searching the trees for\n\t// nodes overlapping with a given interval, you can immediately skip:\n\t// a) all nodes to the right of nodes whose low value is past the end of the given interval.\n\t// b) all nodes that have their maximum 'high' value below the start of the given interval.\n\tlet node = T.root;\n\tlet delta = 0;\n\tlet nodeMaxEnd = 0;\n\tlet nodeStart = 0;\n\tlet nodeEnd = 0;\n\tconst result: IntervalNode[] = [];\n\tlet resultLen = 0;\n\twhile (node !== SENTINEL) {\n\t\tif (getNodeIsVisited(node)) {\n\t\t\t// going up from this node\n\t\t\tsetNodeIsVisited(node.left, false);\n\t\t\tsetNodeIsVisited(node.right, false);\n\t\t\tif (node === node.parent.right) {\n\t\t\t\tdelta -= node.parent.delta;\n\t\t\t}\n\t\t\tnode = node.parent;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!getNodeIsVisited(node.left)) {\n\t\t\t// first time seeing this node\n\t\t\tnodeMaxEnd = delta + node.maxEnd;\n\t\t\tif (nodeMaxEnd < start) {\n\t\t\t\t// cover case b) from above\n\t\t\t\t// there is no need to search this node or its children\n\t\t\t\tsetNodeIsVisited(node, true);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (node.left !== SENTINEL) {\n\t\t\t\t// go left\n\t\t\t\tnode = node.left;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// handle current node\n\t\tnodeStart = delta + node.start;\n\t\tif (nodeStart > end) {\n\t\t\t// cover case a) from above\n\t\t\t// there is no need to search this node or its right subtree\n\t\t\tsetNodeIsVisited(node, true);\n\t\t\tcontinue;\n\t\t}\n\n\t\tnodeEnd = delta + node.end;\n\t\tif (nodeEnd >= start) {\n\t\t\tnode.setCachedOffsets(nodeStart, nodeEnd, 0);\n\t\t\tresult[resultLen++] = node;\n\t\t}\n\t\tsetNodeIsVisited(node, true);\n\n\t\tif (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n\t\t\t// go right\n\t\t\tdelta += node.delta;\n\t\t\tnode = node.right;\n\t\t\tcontinue;\n\t\t}\n\t}\n\n\tsetNodeIsVisited(T.root, false);\n\n\treturn result;\n}\n\nfunction noOverlapReplace(T: IntervalTree, start: number, end: number, textLength: number): void {\n\t// https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree\n\t// Now, it is known that two intervals A and B overlap only when both\n\t// A.low <= B.high and A.high >= B.low. When searching the trees for\n\t// nodes overlapping with a given interval, you can immediately skip:\n\t// a) all nodes to the right of nodes whose low value is past the end of the given interval.\n\t// b) all nodes that have their maximum 'high' value below the start of the given interval.\n\tlet node = T.root;\n\tlet delta = 0;\n\tlet nodeMaxEnd = 0;\n\tlet nodeStart = 0;\n\tconst editDelta = (textLength - (end - start));\n\twhile (node !== SENTINEL) {\n\t\tif (getNodeIsVisited(node)) {\n\t\t\t// going up from this node\n\t\t\tsetNodeIsVisited(node.left, false);\n\t\t\tsetNodeIsVisited(node.right, false);\n\t\t\tif (node === node.parent.right) {\n\t\t\t\tdelta -= node.parent.delta;\n\t\t\t}\n\t\t\trecomputeMaxEnd(node);\n\t\t\tnode = node.parent;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!getNodeIsVisited(node.left)) {\n\t\t\t// first time seeing this node\n\t\t\tnodeMaxEnd = delta + node.maxEnd;\n\t\t\tif (nodeMaxEnd < start) {\n\t\t\t\t// cover case b) from above\n\t\t\t\t// there is no need to search this node or its children\n\t\t\t\tsetNodeIsVisited(node, true);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (node.left !== SENTINEL) {\n\t\t\t\t// go left\n\t\t\t\tnode = node.left;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// handle current node\n\t\tnodeStart = delta + node.start;\n\t\tif (nodeStart > end) {\n\t\t\tnode.start += editDelta;\n\t\t\tnode.end += editDelta;\n\t\t\tnode.delta += editDelta;\n\t\t\tif (node.delta < Constants.MIN_SAFE_DELTA || node.delta > Constants.MAX_SAFE_DELTA) {\n\t\t\t\tT.requestNormalizeDelta = true;\n\t\t\t}\n\t\t\t// cover case a) from above\n\t\t\t// there is no need to search this node or its right subtree\n\t\t\tsetNodeIsVisited(node, true);\n\t\t\tcontinue;\n\t\t}\n\n\t\tsetNodeIsVisited(node, true);\n\n\t\tif (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n\t\t\t// go right\n\t\t\tdelta += node.delta;\n\t\t\tnode = node.right;\n\t\t\tcontinue;\n\t\t}\n\t}\n\n\tsetNodeIsVisited(T.root, false);\n}\n\n//#endregion\n\n//#region Searching\n\nfunction collectNodesFromOwner(T: IntervalTree, ownerId: number): IntervalNode[] {\n\tlet node = T.root;\n\tconst result: IntervalNode[] = [];\n\tlet resultLen = 0;\n\twhile (node !== SENTINEL) {\n\t\tif (getNodeIsVisited(node)) {\n\t\t\t// going up from this node\n\t\t\tsetNodeIsVisited(node.left, false);\n\t\t\tsetNodeIsVisited(node.right, false);\n\t\t\tnode = node.parent;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {\n\t\t\t// go left\n\t\t\tnode = node.left;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// handle current node\n\t\tif (node.ownerId === ownerId) {\n\t\t\tresult[resultLen++] = node;\n\t\t}\n\n\t\tsetNodeIsVisited(node, true);\n\n\t\tif (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n\t\t\t// go right\n\t\t\tnode = node.right;\n\t\t\tcontinue;\n\t\t}\n\t}\n\n\tsetNodeIsVisited(T.root, false);\n\n\treturn result;\n}\n\nfunction collectNodesPostOrder(T: IntervalTree): IntervalNode[] {\n\tlet node = T.root;\n\tconst result: IntervalNode[] = [];\n\tlet resultLen = 0;\n\twhile (node !== SENTINEL) {\n\t\tif (getNodeIsVisited(node)) {\n\t\t\t// going up from this node\n\t\t\tsetNodeIsVisited(node.left, false);\n\t\t\tsetNodeIsVisited(node.right, false);\n\t\t\tnode = node.parent;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {\n\t\t\t// go left\n\t\t\tnode = node.left;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n\t\t\t// go right\n\t\t\tnode = node.right;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// handle current node\n\t\tresult[resultLen++] = node;\n\t\tsetNodeIsVisited(node, true);\n\t}\n\n\tsetNodeIsVisited(T.root, false);\n\n\treturn result;\n}\n\nfunction search(T: IntervalTree, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] {\n\tlet node = T.root;\n\tlet delta = 0;\n\tlet nodeStart = 0;\n\tlet nodeEnd = 0;\n\tconst result: IntervalNode[] = [];\n\tlet resultLen = 0;\n\twhile (node !== SENTINEL) {\n\t\tif (getNodeIsVisited(node)) {\n\t\t\t// going up from this node\n\t\t\tsetNodeIsVisited(node.left, false);\n\t\t\tsetNodeIsVisited(node.right, false);\n\t\t\tif (node === node.parent.right) {\n\t\t\t\tdelta -= node.parent.delta;\n\t\t\t}\n\t\t\tnode = node.parent;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {\n\t\t\t// go left\n\t\t\tnode = node.left;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// handle current node\n\t\tnodeStart = delta + node.start;\n\t\tnodeEnd = delta + node.end;\n\n\t\tnode.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId);\n\n\t\tlet include = true;\n\t\tif (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) {\n\t\t\tinclude = false;\n\t\t}\n\t\tif (filterOutValidation && getNodeIsForValidation(node)) {\n\t\t\tinclude = false;\n\t\t}\n\t\tif (include) {\n\t\t\tresult[resultLen++] = node;\n\t\t}\n\n\t\tsetNodeIsVisited(node, true);\n\n\t\tif (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n\t\t\t// go right\n\t\t\tdelta += node.delta;\n\t\t\tnode = node.right;\n\t\t\tcontinue;\n\t\t}\n\t}\n\n\tsetNodeIsVisited(T.root, false);\n\n\treturn result;\n}\n\nfunction intervalSearch(T: IntervalTree, intervalStart: number, intervalEnd: number, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] {\n\t// https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree\n\t// Now, it is known that two intervals A and B overlap only when both\n\t// A.low <= B.high and A.high >= B.low. When searching the trees for\n\t// nodes overlapping with a given interval, you can immediately skip:\n\t// a) all nodes to the right of nodes whose low value is past the end of the given interval.\n\t// b) all nodes that have their maximum 'high' value below the start of the given interval.\n\n\tlet node = T.root;\n\tlet delta = 0;\n\tlet nodeMaxEnd = 0;\n\tlet nodeStart = 0;\n\tlet nodeEnd = 0;\n\tconst result: IntervalNode[] = [];\n\tlet resultLen = 0;\n\twhile (node !== SENTINEL) {\n\t\tif (getNodeIsVisited(node)) {\n\t\t\t// going up from this node\n\t\t\tsetNodeIsVisited(node.left, false);\n\t\t\tsetNodeIsVisited(node.right, false);\n\t\t\tif (node === node.parent.right) {\n\t\t\t\tdelta -= node.parent.delta;\n\t\t\t}\n\t\t\tnode = node.parent;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!getNodeIsVisited(node.left)) {\n\t\t\t// first time seeing this node\n\t\t\tnodeMaxEnd = delta + node.maxEnd;\n\t\t\tif (nodeMaxEnd < intervalStart) {\n\t\t\t\t// cover case b) from above\n\t\t\t\t// there is no need to search this node or its children\n\t\t\t\tsetNodeIsVisited(node, true);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (node.left !== SENTINEL) {\n\t\t\t\t// go left\n\t\t\t\tnode = node.left;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// handle current node\n\t\tnodeStart = delta + node.start;\n\t\tif (nodeStart > intervalEnd) {\n\t\t\t// cover case a) from above\n\t\t\t// there is no need to search this node or its right subtree\n\t\t\tsetNodeIsVisited(node, true);\n\t\t\tcontinue;\n\t\t}\n\n\t\tnodeEnd = delta + node.end;\n\n\t\tif (nodeEnd >= intervalStart) {\n\t\t\t// There is overlap\n\t\t\tnode.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId);\n\n\t\t\tlet include = true;\n\t\t\tif (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) {\n\t\t\t\tinclude = false;\n\t\t\t}\n\t\t\tif (filterOutValidation && getNodeIsForValidation(node)) {\n\t\t\t\tinclude = false;\n\t\t\t}\n\n\t\t\tif (include) {\n\t\t\t\tresult[resultLen++] = node;\n\t\t\t}\n\t\t}\n\n\t\tsetNodeIsVisited(node, true);\n\n\t\tif (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n\t\t\t// go right\n\t\t\tdelta += node.delta;\n\t\t\tnode = node.right;\n\t\t\tcontinue;\n\t\t}\n\t}\n\n\tsetNodeIsVisited(T.root, false);\n\n\treturn result;\n}\n\n//#endregion\n\n//#region Insertion\nfunction rbTreeInsert(T: IntervalTree, newNode: IntervalNode): IntervalNode {\n\tif (T.root === SENTINEL) {\n\t\tnewNode.parent = SENTINEL;\n\t\tnewNode.left = SENTINEL;\n\t\tnewNode.right = SENTINEL;\n\t\tsetNodeColor(newNode, NodeColor.Black);\n\t\tT.root = newNode;\n\t\treturn T.root;\n\t}\n\n\ttreeInsert(T, newNode);\n\n\trecomputeMaxEndWalkToRoot(newNode.parent);\n\n\t// repair tree\n\tlet x = newNode;\n\twhile (x !== T.root && getNodeColor(x.parent) === NodeColor.Red) {\n\t\tif (x.parent === x.parent.parent.left) {\n\t\t\tconst y = x.parent.parent.right;\n\n\t\t\tif (getNodeColor(y) === NodeColor.Red) {\n\t\t\t\tsetNodeColor(x.parent, NodeColor.Black);\n\t\t\t\tsetNodeColor(y, NodeColor.Black);\n\t\t\t\tsetNodeColor(x.parent.parent, NodeColor.Red);\n\t\t\t\tx = x.parent.parent;\n\t\t\t} else {\n\t\t\t\tif (x === x.parent.right) {\n\t\t\t\t\tx = x.parent;\n\t\t\t\t\tleftRotate(T, x);\n\t\t\t\t}\n\t\t\t\tsetNodeColor(x.parent, NodeColor.Black);\n\t\t\t\tsetNodeColor(x.parent.parent, NodeColor.Red);\n\t\t\t\trightRotate(T, x.parent.parent);\n\t\t\t}\n\t\t} else {\n\t\t\tconst y = x.parent.parent.left;\n\n\t\t\tif (getNodeColor(y) === NodeColor.Red) {\n\t\t\t\tsetNodeColor(x.parent, NodeColor.Black);\n\t\t\t\tsetNodeColor(y, NodeColor.Black);\n\t\t\t\tsetNodeColor(x.parent.parent, NodeColor.Red);\n\t\t\t\tx = x.parent.parent;\n\t\t\t} else {\n\t\t\t\tif (x === x.parent.left) {\n\t\t\t\t\tx = x.parent;\n\t\t\t\t\trightRotate(T, x);\n\t\t\t\t}\n\t\t\t\tsetNodeColor(x.parent, NodeColor.Black);\n\t\t\t\tsetNodeColor(x.parent.parent, NodeColor.Red);\n\t\t\t\tleftRotate(T, x.parent.parent);\n\t\t\t}\n\t\t}\n\t}\n\n\tsetNodeColor(T.root, NodeColor.Black);\n\n\treturn newNode;\n}\n\nfunction treeInsert(T: IntervalTree, z: IntervalNode): void {\n\tlet delta: number = 0;\n\tlet x = T.root;\n\tconst zAbsoluteStart = z.start;\n\tconst zAbsoluteEnd = z.end;\n\twhile (true) {\n\t\tconst cmp = intervalCompare(zAbsoluteStart, zAbsoluteEnd, x.start + delta, x.end + delta);\n\t\tif (cmp < 0) {\n\t\t\t// this node should be inserted to the left\n\t\t\t// => it is not affected by the node's delta\n\t\t\tif (x.left === SENTINEL) {\n\t\t\t\tz.start -= delta;\n\t\t\t\tz.end -= delta;\n\t\t\t\tz.maxEnd -= delta;\n\t\t\t\tx.left = z;\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tx = x.left;\n\t\t\t}\n\t\t} else {\n\t\t\t// this node should be inserted to the right\n\t\t\t// => it is not affected by the node's delta\n\t\t\tif (x.right === SENTINEL) {\n\t\t\t\tz.start -= (delta + x.delta);\n\t\t\t\tz.end -= (delta + x.delta);\n\t\t\t\tz.maxEnd -= (delta + x.delta);\n\t\t\t\tx.right = z;\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tdelta += x.delta;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\t}\n\n\tz.parent = x;\n\tz.left = SENTINEL;\n\tz.right = SENTINEL;\n\tsetNodeColor(z, NodeColor.Red);\n}\n//#endregion\n\n//#region Deletion\nfunction rbTreeDelete(T: IntervalTree, z: IntervalNode): void {\n\n\tlet x: IntervalNode;\n\tlet y: IntervalNode;\n\n\t// RB-DELETE except we don't swap z and y in case c)\n\t// i.e. we always delete what's pointed at by z.\n\n\tif (z.left === SENTINEL) {\n\t\tx = z.right;\n\t\ty = z;\n\n\t\t// x's delta is no longer influenced by z's delta\n\t\tx.delta += z.delta;\n\t\tif (x.delta < Constants.MIN_SAFE_DELTA || x.delta > Constants.MAX_SAFE_DELTA) {\n\t\t\tT.requestNormalizeDelta = true;\n\t\t}\n\t\tx.start += z.delta;\n\t\tx.end += z.delta;\n\n\t} else if (z.right === SENTINEL) {\n\t\tx = z.left;\n\t\ty = z;\n\n\t} else {\n\t\ty = leftest(z.right);\n\t\tx = y.right;\n\n\t\t// y's delta is no longer influenced by z's delta,\n\t\t// but we don't want to walk the entire right-hand-side subtree of x.\n\t\t// we therefore maintain z's delta in y, and adjust only x\n\t\tx.start += y.delta;\n\t\tx.end += y.delta;\n\t\tx.delta += y.delta;\n\t\tif (x.delta < Constants.MIN_SAFE_DELTA || x.delta > Constants.MAX_SAFE_DELTA) {\n\t\t\tT.requestNormalizeDelta = true;\n\t\t}\n\n\t\ty.start += z.delta;\n\t\ty.end += z.delta;\n\t\ty.delta = z.delta;\n\t\tif (y.delta < Constants.MIN_SAFE_DELTA || y.delta > Constants.MAX_SAFE_DELTA) {\n\t\t\tT.requestNormalizeDelta = true;\n\t\t}\n\t}\n\n\tif (y === T.root) {\n\t\tT.root = x;\n\t\tsetNodeColor(x, NodeColor.Black);\n\n\t\tz.detach();\n\t\tresetSentinel();\n\t\trecomputeMaxEnd(x);\n\t\tT.root.parent = SENTINEL;\n\t\treturn;\n\t}\n\n\tconst yWasRed = (getNodeColor(y) === NodeColor.Red);\n\n\tif (y === y.parent.left) {\n\t\ty.parent.left = x;\n\t} else {\n\t\ty.parent.right = x;\n\t}\n\n\tif (y === z) {\n\t\tx.parent = y.parent;\n\t} else {\n\n\t\tif (y.parent === z) {\n\t\t\tx.parent = y;\n\t\t} else {\n\t\t\tx.parent = y.parent;\n\t\t}\n\n\t\ty.left = z.left;\n\t\ty.right = z.right;\n\t\ty.parent = z.parent;\n\t\tsetNodeColor(y, getNodeColor(z));\n\n\t\tif (z === T.root) {\n\t\t\tT.root = y;\n\t\t} else {\n\t\t\tif (z === z.parent.left) {\n\t\t\t\tz.parent.left = y;\n\t\t\t} else {\n\t\t\t\tz.parent.right = y;\n\t\t\t}\n\t\t}\n\n\t\tif (y.left !== SENTINEL) {\n\t\t\ty.left.parent = y;\n\t\t}\n\t\tif (y.right !== SENTINEL) {\n\t\t\ty.right.parent = y;\n\t\t}\n\t}\n\n\tz.detach();\n\n\tif (yWasRed) {\n\t\trecomputeMaxEndWalkToRoot(x.parent);\n\t\tif (y !== z) {\n\t\t\trecomputeMaxEndWalkToRoot(y);\n\t\t\trecomputeMaxEndWalkToRoot(y.parent);\n\t\t}\n\t\tresetSentinel();\n\t\treturn;\n\t}\n\n\trecomputeMaxEndWalkToRoot(x);\n\trecomputeMaxEndWalkToRoot(x.parent);\n\tif (y !== z) {\n\t\trecomputeMaxEndWalkToRoot(y);\n\t\trecomputeMaxEndWalkToRoot(y.parent);\n\t}\n\n\t// RB-DELETE-FIXUP\n\tlet w: IntervalNode;\n\twhile (x !== T.root && getNodeColor(x) === NodeColor.Black) {\n\n\t\tif (x === x.parent.left) {\n\t\t\tw = x.parent.right;\n\n\t\t\tif (getNodeColor(w) === NodeColor.Red) {\n\t\t\t\tsetNodeColor(w, NodeColor.Black);\n\t\t\t\tsetNodeColor(x.parent, NodeColor.Red);\n\t\t\t\tleftRotate(T, x.parent);\n\t\t\t\tw = x.parent.right;\n\t\t\t}\n\n\t\t\tif (getNodeColor(w.left) === NodeColor.Black && getNodeColor(w.right) === NodeColor.Black) {\n\t\t\t\tsetNodeColor(w, NodeColor.Red);\n\t\t\t\tx = x.parent;\n\t\t\t} else {\n\t\t\t\tif (getNodeColor(w.right) === NodeColor.Black) {\n\t\t\t\t\tsetNodeColor(w.left, NodeColor.Black);\n\t\t\t\t\tsetNodeColor(w, NodeColor.Red);\n\t\t\t\t\trightRotate(T, w);\n\t\t\t\t\tw = x.parent.right;\n\t\t\t\t}\n\n\t\t\t\tsetNodeColor(w, getNodeColor(x.parent));\n\t\t\t\tsetNodeColor(x.parent, NodeColor.Black);\n\t\t\t\tsetNodeColor(w.right, NodeColor.Black);\n\t\t\t\tleftRotate(T, x.parent);\n\t\t\t\tx = T.root;\n\t\t\t}\n\n\t\t} else {\n\t\t\tw = x.parent.left;\n\n\t\t\tif (getNodeColor(w) === NodeColor.Red) {\n\t\t\t\tsetNodeColor(w, NodeColor.Black);\n\t\t\t\tsetNodeColor(x.parent, NodeColor.Red);\n\t\t\t\trightRotate(T, x.parent);\n\t\t\t\tw = x.parent.left;\n\t\t\t}\n\n\t\t\tif (getNodeColor(w.left) === NodeColor.Black && getNodeColor(w.right) === NodeColor.Black) {\n\t\t\t\tsetNodeColor(w, NodeColor.Red);\n\t\t\t\tx = x.parent;\n\n\t\t\t} else {\n\t\t\t\tif (getNodeColor(w.left) === NodeColor.Black) {\n\t\t\t\t\tsetNodeColor(w.right, NodeColor.Black);\n\t\t\t\t\tsetNodeColor(w, NodeColor.Red);\n\t\t\t\t\tleftRotate(T, w);\n\t\t\t\t\tw = x.parent.left;\n\t\t\t\t}\n\n\t\t\t\tsetNodeColor(w, getNodeColor(x.parent));\n\t\t\t\tsetNodeColor(x.parent, NodeColor.Black);\n\t\t\t\tsetNodeColor(w.left, NodeColor.Black);\n\t\t\t\trightRotate(T, x.parent);\n\t\t\t\tx = T.root;\n\t\t\t}\n\t\t}\n\t}\n\n\tsetNodeColor(x, NodeColor.Black);\n\tresetSentinel();\n}\n\nfunction leftest(node: IntervalNode): IntervalNode {\n\twhile (node.left !== SENTINEL) {\n\t\tnode = node.left;\n\t}\n\treturn node;\n}\n\nfunction resetSentinel(): void {\n\tSENTINEL.parent = SENTINEL;\n\tSENTINEL.delta = 0; // optional\n\tSENTINEL.start = 0; // optional\n\tSENTINEL.end = 0; // optional\n}\n//#endregion\n\n//#region Rotations\nfunction leftRotate(T: IntervalTree, x: IntervalNode): void {\n\tconst y = x.right;\t\t\t\t// set y.\n\n\ty.delta += x.delta;\t\t\t\t// y's delta is no longer influenced by x's delta\n\tif (y.delta < Constants.MIN_SAFE_DELTA || y.delta > Constants.MAX_SAFE_DELTA) {\n\t\tT.requestNormalizeDelta = true;\n\t}\n\ty.start += x.delta;\n\ty.end += x.delta;\n\n\tx.right = y.left;\t\t\t\t// turn y's left subtree into x's right subtree.\n\tif (y.left !== SENTINEL) {\n\t\ty.left.parent = x;\n\t}\n\ty.parent = x.parent;\t\t\t// link x's parent to y.\n\tif (x.parent === SENTINEL) {\n\t\tT.root = y;\n\t} else if (x === x.parent.left) {\n\t\tx.parent.left = y;\n\t} else {\n\t\tx.parent.right = y;\n\t}\n\n\ty.left = x;\t\t\t\t\t\t// put x on y's left.\n\tx.parent = y;\n\n\trecomputeMaxEnd(x);\n\trecomputeMaxEnd(y);\n}\n\nfunction rightRotate(T: IntervalTree, y: IntervalNode): void {\n\tconst x = y.left;\n\n\ty.delta -= x.delta;\n\tif (y.delta < Constants.MIN_SAFE_DELTA || y.delta > Constants.MAX_SAFE_DELTA) {\n\t\tT.requestNormalizeDelta = true;\n\t}\n\ty.start -= x.delta;\n\ty.end -= x.delta;\n\n\ty.left = x.right;\n\tif (x.right !== SENTINEL) {\n\t\tx.right.parent = y;\n\t}\n\tx.parent = y.parent;\n\tif (y.parent === SENTINEL) {\n\t\tT.root = x;\n\t} else if (y === y.parent.right) {\n\t\ty.parent.right = x;\n\t} else {\n\t\ty.parent.left = x;\n\t}\n\n\tx.right = y;\n\ty.parent = x;\n\n\trecomputeMaxEnd(y);\n\trecomputeMaxEnd(x);\n}\n//#endregion\n\n//#region max end computation\n\nfunction computeMaxEnd(node: IntervalNode): number {\n\tlet maxEnd = node.end;\n\tif (node.left !== SENTINEL) {\n\t\tconst leftMaxEnd = node.left.maxEnd;\n\t\tif (leftMaxEnd > maxEnd) {\n\t\t\tmaxEnd = leftMaxEnd;\n\t\t}\n\t}\n\tif (node.right !== SENTINEL) {\n\t\tconst rightMaxEnd = node.right.maxEnd + node.delta;\n\t\tif (rightMaxEnd > maxEnd) {\n\t\t\tmaxEnd = rightMaxEnd;\n\t\t}\n\t}\n\treturn maxEnd;\n}\n\nexport function recomputeMaxEnd(node: IntervalNode): void {\n\tnode.maxEnd = computeMaxEnd(node);\n}\n\nfunction recomputeMaxEndWalkToRoot(node: IntervalNode): void {\n\twhile (node !== SENTINEL) {\n\n\t\tconst maxEnd = computeMaxEnd(node);\n\n\t\tif (node.maxEnd === maxEnd) {\n\t\t\t// no need to go further\n\t\t\treturn;\n\t\t}\n\n\t\tnode.maxEnd = maxEnd;\n\t\tnode = node.parent;\n\t}\n}\n\n//#endregion\n\n//#region utils\nexport function intervalCompare(aStart: number, aEnd: number, bStart: number, bEnd: number): number {\n\tif (aStart === bStart) {\n\t\treturn aEnd - bEnd;\n\t}\n\treturn aStart - bStart;\n}\n//#endregion\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Piece, PieceTreeBase } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase';\n\nexport class TreeNode {\n\tparent: TreeNode;\n\tleft: TreeNode;\n\tright: TreeNode;\n\tcolor: NodeColor;\n\n\t// Piece\n\tpiece: Piece;\n\tsize_left: number; // size of the left subtree (not inorder)\n\tlf_left: number; // line feeds cnt in the left subtree (not in order)\n\n\tconstructor(piece: Piece, color: NodeColor) {\n\t\tthis.piece = piece;\n\t\tthis.color = color;\n\t\tthis.size_left = 0;\n\t\tthis.lf_left = 0;\n\t\tthis.parent = this;\n\t\tthis.left = this;\n\t\tthis.right = this;\n\t}\n\n\tpublic next(): TreeNode {\n\t\tif (this.right !== SENTINEL) {\n\t\t\treturn leftest(this.right);\n\t\t}\n\n\t\tlet node: TreeNode = this;\n\n\t\twhile (node.parent !== SENTINEL) {\n\t\t\tif (node.parent.left === node) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tnode = node.parent;\n\t\t}\n\n\t\tif (node.parent === SENTINEL) {\n\t\t\treturn SENTINEL;\n\t\t} else {\n\t\t\treturn node.parent;\n\t\t}\n\t}\n\n\tpublic prev(): TreeNode {\n\t\tif (this.left !== SENTINEL) {\n\t\t\treturn righttest(this.left);\n\t\t}\n\n\t\tlet node: TreeNode = this;\n\n\t\twhile (node.parent !== SENTINEL) {\n\t\t\tif (node.parent.right === node) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tnode = node.parent;\n\t\t}\n\n\t\tif (node.parent === SENTINEL) {\n\t\t\treturn SENTINEL;\n\t\t} else {\n\t\t\treturn node.parent;\n\t\t}\n\t}\n\n\tpublic detach(): void {\n\t\tthis.parent = null!;\n\t\tthis.left = null!;\n\t\tthis.right = null!;\n\t}\n}\n\nexport const enum NodeColor {\n\tBlack = 0,\n\tRed = 1,\n}\n\nexport const SENTINEL: TreeNode = new TreeNode(null!, NodeColor.Black);\nSENTINEL.parent = SENTINEL;\nSENTINEL.left = SENTINEL;\nSENTINEL.right = SENTINEL;\nSENTINEL.color = NodeColor.Black;\n\nexport function leftest(node: TreeNode): TreeNode {\n\twhile (node.left !== SENTINEL) {\n\t\tnode = node.left;\n\t}\n\treturn node;\n}\n\nexport function righttest(node: TreeNode): TreeNode {\n\twhile (node.right !== SENTINEL) {\n\t\tnode = node.right;\n\t}\n\treturn node;\n}\n\nexport function calculateSize(node: TreeNode): number {\n\tif (node === SENTINEL) {\n\t\treturn 0;\n\t}\n\n\treturn node.size_left + node.piece.length + calculateSize(node.right);\n}\n\nexport function calculateLF(node: TreeNode): number {\n\tif (node === SENTINEL) {\n\t\treturn 0;\n\t}\n\n\treturn node.lf_left + node.piece.lineFeedCnt + calculateLF(node.right);\n}\n\nexport function resetSentinel(): void {\n\tSENTINEL.parent = SENTINEL;\n}\n\nexport function leftRotate(tree: PieceTreeBase, x: TreeNode) {\n\tconst y = x.right;\n\n\t// fix size_left\n\ty.size_left += x.size_left + (x.piece ? x.piece.length : 0);\n\ty.lf_left += x.lf_left + (x.piece ? x.piece.lineFeedCnt : 0);\n\tx.right = y.left;\n\n\tif (y.left !== SENTINEL) {\n\t\ty.left.parent = x;\n\t}\n\ty.parent = x.parent;\n\tif (x.parent === SENTINEL) {\n\t\ttree.root = y;\n\t} else if (x.parent.left === x) {\n\t\tx.parent.left = y;\n\t} else {\n\t\tx.parent.right = y;\n\t}\n\ty.left = x;\n\tx.parent = y;\n}\n\nexport function rightRotate(tree: PieceTreeBase, y: TreeNode) {\n\tconst x = y.left;\n\ty.left = x.right;\n\tif (x.right !== SENTINEL) {\n\t\tx.right.parent = y;\n\t}\n\tx.parent = y.parent;\n\n\t// fix size_left\n\ty.size_left -= x.size_left + (x.piece ? x.piece.length : 0);\n\ty.lf_left -= x.lf_left + (x.piece ? x.piece.lineFeedCnt : 0);\n\n\tif (y.parent === SENTINEL) {\n\t\ttree.root = x;\n\t} else if (y === y.parent.right) {\n\t\ty.parent.right = x;\n\t} else {\n\t\ty.parent.left = x;\n\t}\n\n\tx.right = y;\n\ty.parent = x;\n}\n\nexport function rbDelete(tree: PieceTreeBase, z: TreeNode) {\n\tlet x: TreeNode;\n\tlet y: TreeNode;\n\n\tif (z.left === SENTINEL) {\n\t\ty = z;\n\t\tx = y.right;\n\t} else if (z.right === SENTINEL) {\n\t\ty = z;\n\t\tx = y.left;\n\t} else {\n\t\ty = leftest(z.right);\n\t\tx = y.right;\n\t}\n\n\tif (y === tree.root) {\n\t\ttree.root = x;\n\n\t\t// if x is null, we are removing the only node\n\t\tx.color = NodeColor.Black;\n\t\tz.detach();\n\t\tresetSentinel();\n\t\ttree.root.parent = SENTINEL;\n\n\t\treturn;\n\t}\n\n\tconst yWasRed = (y.color === NodeColor.Red);\n\n\tif (y === y.parent.left) {\n\t\ty.parent.left = x;\n\t} else {\n\t\ty.parent.right = x;\n\t}\n\n\tif (y === z) {\n\t\tx.parent = y.parent;\n\t\trecomputeTreeMetadata(tree, x);\n\t} else {\n\t\tif (y.parent === z) {\n\t\t\tx.parent = y;\n\t\t} else {\n\t\t\tx.parent = y.parent;\n\t\t}\n\n\t\t// as we make changes to x's hierarchy, update size_left of subtree first\n\t\trecomputeTreeMetadata(tree, x);\n\n\t\ty.left = z.left;\n\t\ty.right = z.right;\n\t\ty.parent = z.parent;\n\t\ty.color = z.color;\n\n\t\tif (z === tree.root) {\n\t\t\ttree.root = y;\n\t\t} else {\n\t\t\tif (z === z.parent.left) {\n\t\t\t\tz.parent.left = y;\n\t\t\t} else {\n\t\t\t\tz.parent.right = y;\n\t\t\t}\n\t\t}\n\n\t\tif (y.left !== SENTINEL) {\n\t\t\ty.left.parent = y;\n\t\t}\n\t\tif (y.right !== SENTINEL) {\n\t\t\ty.right.parent = y;\n\t\t}\n\t\t// update metadata\n\t\t// we replace z with y, so in this sub tree, the length change is z.item.length\n\t\ty.size_left = z.size_left;\n\t\ty.lf_left = z.lf_left;\n\t\trecomputeTreeMetadata(tree, y);\n\t}\n\n\tz.detach();\n\n\tif (x.parent.left === x) {\n\t\tconst newSizeLeft = calculateSize(x);\n\t\tconst newLFLeft = calculateLF(x);\n\t\tif (newSizeLeft !== x.parent.size_left || newLFLeft !== x.parent.lf_left) {\n\t\t\tconst delta = newSizeLeft - x.parent.size_left;\n\t\t\tconst lf_delta = newLFLeft - x.parent.lf_left;\n\t\t\tx.parent.size_left = newSizeLeft;\n\t\t\tx.parent.lf_left = newLFLeft;\n\t\t\tupdateTreeMetadata(tree, x.parent, delta, lf_delta);\n\t\t}\n\t}\n\n\trecomputeTreeMetadata(tree, x.parent);\n\n\tif (yWasRed) {\n\t\tresetSentinel();\n\t\treturn;\n\t}\n\n\t// RB-DELETE-FIXUP\n\tlet w: TreeNode;\n\twhile (x !== tree.root && x.color === NodeColor.Black) {\n\t\tif (x === x.parent.left) {\n\t\t\tw = x.parent.right;\n\n\t\t\tif (w.color === NodeColor.Red) {\n\t\t\t\tw.color = NodeColor.Black;\n\t\t\t\tx.parent.color = NodeColor.Red;\n\t\t\t\tleftRotate(tree, x.parent);\n\t\t\t\tw = x.parent.right;\n\t\t\t}\n\n\t\t\tif (w.left.color === NodeColor.Black && w.right.color === NodeColor.Black) {\n\t\t\t\tw.color = NodeColor.Red;\n\t\t\t\tx = x.parent;\n\t\t\t} else {\n\t\t\t\tif (w.right.color === NodeColor.Black) {\n\t\t\t\t\tw.left.color = NodeColor.Black;\n\t\t\t\t\tw.color = NodeColor.Red;\n\t\t\t\t\trightRotate(tree, w);\n\t\t\t\t\tw = x.parent.right;\n\t\t\t\t}\n\n\t\t\t\tw.color = x.parent.color;\n\t\t\t\tx.parent.color = NodeColor.Black;\n\t\t\t\tw.right.color = NodeColor.Black;\n\t\t\t\tleftRotate(tree, x.parent);\n\t\t\t\tx = tree.root;\n\t\t\t}\n\t\t} else {\n\t\t\tw = x.parent.left;\n\n\t\t\tif (w.color === NodeColor.Red) {\n\t\t\t\tw.color = NodeColor.Black;\n\t\t\t\tx.parent.color = NodeColor.Red;\n\t\t\t\trightRotate(tree, x.parent);\n\t\t\t\tw = x.parent.left;\n\t\t\t}\n\n\t\t\tif (w.left.color === NodeColor.Black && w.right.color === NodeColor.Black) {\n\t\t\t\tw.color = NodeColor.Red;\n\t\t\t\tx = x.parent;\n\n\t\t\t} else {\n\t\t\t\tif (w.left.color === NodeColor.Black) {\n\t\t\t\t\tw.right.color = NodeColor.Black;\n\t\t\t\t\tw.color = NodeColor.Red;\n\t\t\t\t\tleftRotate(tree, w);\n\t\t\t\t\tw = x.parent.left;\n\t\t\t\t}\n\n\t\t\t\tw.color = x.parent.color;\n\t\t\t\tx.parent.color = NodeColor.Black;\n\t\t\t\tw.left.color = NodeColor.Black;\n\t\t\t\trightRotate(tree, x.parent);\n\t\t\t\tx = tree.root;\n\t\t\t}\n\t\t}\n\t}\n\tx.color = NodeColor.Black;\n\tresetSentinel();\n}\n\nexport function fixInsert(tree: PieceTreeBase, x: TreeNode) {\n\trecomputeTreeMetadata(tree, x);\n\n\twhile (x !== tree.root && x.parent.color === NodeColor.Red) {\n\t\tif (x.parent === x.parent.parent.left) {\n\t\t\tconst y = x.parent.parent.right;\n\n\t\t\tif (y.color === NodeColor.Red) {\n\t\t\t\tx.parent.color = NodeColor.Black;\n\t\t\t\ty.color = NodeColor.Black;\n\t\t\t\tx.parent.parent.color = NodeColor.Red;\n\t\t\t\tx = x.parent.parent;\n\t\t\t} else {\n\t\t\t\tif (x === x.parent.right) {\n\t\t\t\t\tx = x.parent;\n\t\t\t\t\tleftRotate(tree, x);\n\t\t\t\t}\n\n\t\t\t\tx.parent.color = NodeColor.Black;\n\t\t\t\tx.parent.parent.color = NodeColor.Red;\n\t\t\t\trightRotate(tree, x.parent.parent);\n\t\t\t}\n\t\t} else {\n\t\t\tconst y = x.parent.parent.left;\n\n\t\t\tif (y.color === NodeColor.Red) {\n\t\t\t\tx.parent.color = NodeColor.Black;\n\t\t\t\ty.color = NodeColor.Black;\n\t\t\t\tx.parent.parent.color = NodeColor.Red;\n\t\t\t\tx = x.parent.parent;\n\t\t\t} else {\n\t\t\t\tif (x === x.parent.left) {\n\t\t\t\t\tx = x.parent;\n\t\t\t\t\trightRotate(tree, x);\n\t\t\t\t}\n\t\t\t\tx.parent.color = NodeColor.Black;\n\t\t\t\tx.parent.parent.color = NodeColor.Red;\n\t\t\t\tleftRotate(tree, x.parent.parent);\n\t\t\t}\n\t\t}\n\t}\n\n\ttree.root.color = NodeColor.Black;\n}\n\nexport function updateTreeMetadata(tree: PieceTreeBase, x: TreeNode, delta: number, lineFeedCntDelta: number): void {\n\t// node length change or line feed count change\n\twhile (x !== tree.root && x !== SENTINEL) {\n\t\tif (x.parent.left === x) {\n\t\t\tx.parent.size_left += delta;\n\t\t\tx.parent.lf_left += lineFeedCntDelta;\n\t\t}\n\n\t\tx = x.parent;\n\t}\n}\n\nexport function recomputeTreeMetadata(tree: PieceTreeBase, x: TreeNode) {\n\tlet delta = 0;\n\tlet lf_delta = 0;\n\tif (x === tree.root) {\n\t\treturn;\n\t}\n\n\t// go upwards till the node whose left subtree is changed.\n\twhile (x !== tree.root && x === x.parent.right) {\n\t\tx = x.parent;\n\t}\n\n\tif (x === tree.root) {\n\t\t// well, it means we add a node to the end (inorder)\n\t\treturn;\n\t}\n\n\t// x is the node whose right subtree is changed.\n\tx = x.parent;\n\n\tdelta = calculateSize(x.left) - x.size_left;\n\tlf_delta = calculateLF(x.left) - x.lf_left;\n\tx.size_left += delta;\n\tx.lf_left += lf_delta;\n\n\n\t// go upwards till root. O(logN)\n\twhile (x !== tree.root && (delta !== 0 || lf_delta !== 0)) {\n\t\tif (x.parent.left === x) {\n\t\t\tx.parent.size_left += delta;\n\t\t\tx.parent.lf_left += lf_delta;\n\t\t}\n\n\t\tx = x.parent;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { arrayInsert } from 'vs/base/common/arrays';\nimport { toUint32 } from 'vs/base/common/uint';\n\nexport class PrefixSumComputer {\n\n\t/**\n\t * values[i] is the value at index i\n\t */\n\tprivate values: Uint32Array;\n\n\t/**\n\t * prefixSum[i] = SUM(heights[j]), 0 <= j <= i\n\t */\n\tprivate prefixSum: Uint32Array;\n\n\t/**\n\t * prefixSum[i], 0 <= i <= prefixSumValidIndex can be trusted\n\t */\n\tprivate readonly prefixSumValidIndex: Int32Array;\n\n\tconstructor(values: Uint32Array) {\n\t\tthis.values = values;\n\t\tthis.prefixSum = new Uint32Array(values.length);\n\t\tthis.prefixSumValidIndex = new Int32Array(1);\n\t\tthis.prefixSumValidIndex[0] = -1;\n\t}\n\n\tpublic insertValues(insertIndex: number, insertValues: Uint32Array): boolean {\n\t\tinsertIndex = toUint32(insertIndex);\n\t\tconst oldValues = this.values;\n\t\tconst oldPrefixSum = this.prefixSum;\n\t\tconst insertValuesLen = insertValues.length;\n\n\t\tif (insertValuesLen === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.values = new Uint32Array(oldValues.length + insertValuesLen);\n\t\tthis.values.set(oldValues.subarray(0, insertIndex), 0);\n\t\tthis.values.set(oldValues.subarray(insertIndex), insertIndex + insertValuesLen);\n\t\tthis.values.set(insertValues, insertIndex);\n\n\t\tif (insertIndex - 1 < this.prefixSumValidIndex[0]) {\n\t\t\tthis.prefixSumValidIndex[0] = insertIndex - 1;\n\t\t}\n\n\t\tthis.prefixSum = new Uint32Array(this.values.length);\n\t\tif (this.prefixSumValidIndex[0] >= 0) {\n\t\t\tthis.prefixSum.set(oldPrefixSum.subarray(0, this.prefixSumValidIndex[0] + 1));\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic setValue(index: number, value: number): boolean {\n\t\tindex = toUint32(index);\n\t\tvalue = toUint32(value);\n\n\t\tif (this.values[index] === value) {\n\t\t\treturn false;\n\t\t}\n\t\tthis.values[index] = value;\n\t\tif (index - 1 < this.prefixSumValidIndex[0]) {\n\t\t\tthis.prefixSumValidIndex[0] = index - 1;\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic removeValues(startIndex: number, count: number): boolean {\n\t\tstartIndex = toUint32(startIndex);\n\t\tcount = toUint32(count);\n\n\t\tconst oldValues = this.values;\n\t\tconst oldPrefixSum = this.prefixSum;\n\n\t\tif (startIndex >= oldValues.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst maxCount = oldValues.length - startIndex;\n\t\tif (count >= maxCount) {\n\t\t\tcount = maxCount;\n\t\t}\n\n\t\tif (count === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.values = new Uint32Array(oldValues.length - count);\n\t\tthis.values.set(oldValues.subarray(0, startIndex), 0);\n\t\tthis.values.set(oldValues.subarray(startIndex + count), startIndex);\n\n\t\tthis.prefixSum = new Uint32Array(this.values.length);\n\t\tif (startIndex - 1 < this.prefixSumValidIndex[0]) {\n\t\t\tthis.prefixSumValidIndex[0] = startIndex - 1;\n\t\t}\n\t\tif (this.prefixSumValidIndex[0] >= 0) {\n\t\t\tthis.prefixSum.set(oldPrefixSum.subarray(0, this.prefixSumValidIndex[0] + 1));\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic getTotalSum(): number {\n\t\tif (this.values.length === 0) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn this._getPrefixSum(this.values.length - 1);\n\t}\n\n\t/**\n\t * Returns the sum of the first `index + 1` many items.\n\t * @returns `SUM(0 <= j <= index, values[j])`.\n\t */\n\tpublic getPrefixSum(index: number): number {\n\t\tif (index < 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tindex = toUint32(index);\n\t\treturn this._getPrefixSum(index);\n\t}\n\n\tprivate _getPrefixSum(index: number): number {\n\t\tif (index <= this.prefixSumValidIndex[0]) {\n\t\t\treturn this.prefixSum[index];\n\t\t}\n\n\t\tlet startIndex = this.prefixSumValidIndex[0] + 1;\n\t\tif (startIndex === 0) {\n\t\t\tthis.prefixSum[0] = this.values[0];\n\t\t\tstartIndex++;\n\t\t}\n\n\t\tif (index >= this.values.length) {\n\t\t\tindex = this.values.length - 1;\n\t\t}\n\n\t\tfor (let i = startIndex; i <= index; i++) {\n\t\t\tthis.prefixSum[i] = this.prefixSum[i - 1] + this.values[i];\n\t\t}\n\t\tthis.prefixSumValidIndex[0] = Math.max(this.prefixSumValidIndex[0], index);\n\t\treturn this.prefixSum[index];\n\t}\n\n\tpublic getIndexOf(sum: number): PrefixSumIndexOfResult {\n\t\tsum = Math.floor(sum);\n\n\t\t// Compute all sums (to get a fully valid prefixSum)\n\t\tthis.getTotalSum();\n\n\t\tlet low = 0;\n\t\tlet high = this.values.length - 1;\n\t\tlet mid = 0;\n\t\tlet midStop = 0;\n\t\tlet midStart = 0;\n\n\t\twhile (low <= high) {\n\t\t\tmid = low + ((high - low) / 2) | 0;\n\n\t\t\tmidStop = this.prefixSum[mid];\n\t\t\tmidStart = midStop - this.values[mid];\n\n\t\t\tif (sum < midStart) {\n\t\t\t\thigh = mid - 1;\n\t\t\t} else if (sum >= midStop) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn new PrefixSumIndexOfResult(mid, sum - midStart);\n\t}\n}\n\n/**\n * {@link getIndexOf} has an amortized runtime complexity of O(1).\n *\n * ({@link PrefixSumComputer.getIndexOf} is just O(log n))\n*/\nexport class ConstantTimePrefixSumComputer {\n\tprivate _values: number[];\n\tprivate _isValid: boolean;\n\tprivate _validEndIndex: number;\n\n\t/**\n\t * _prefixSum[i] = SUM(values[j]), 0 <= j <= i\n\t */\n\tprivate _prefixSum: number[];\n\n\t/**\n\t * _indexBySum[sum] = idx => _prefixSum[idx - 1] <= sum < _prefixSum[idx]\n\t*/\n\tprivate _indexBySum: number[];\n\n\tconstructor(values: number[]) {\n\t\tthis._values = values;\n\t\tthis._isValid = false;\n\t\tthis._validEndIndex = -1;\n\t\tthis._prefixSum = [];\n\t\tthis._indexBySum = [];\n\t}\n\n\t/**\n\t * @returns SUM(0 <= j < values.length, values[j])\n\t */\n\tpublic getTotalSum(): number {\n\t\tthis._ensureValid();\n\t\treturn this._indexBySum.length;\n\t}\n\n\t/**\n\t * Returns the sum of the first `count` many items.\n\t * @returns `SUM(0 <= j < count, values[j])`.\n\t */\n\tpublic getPrefixSum(count: number): number {\n\t\tthis._ensureValid();\n\t\tif (count === 0) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn this._prefixSum[count - 1];\n\t}\n\n\t/**\n\t * @returns `result`, such that `getPrefixSum(result.index) + result.remainder = sum`\n\t */\n\tpublic getIndexOf(sum: number): PrefixSumIndexOfResult {\n\t\tthis._ensureValid();\n\t\tconst idx = this._indexBySum[sum];\n\t\tconst viewLinesAbove = idx > 0 ? this._prefixSum[idx - 1] : 0;\n\t\treturn new PrefixSumIndexOfResult(idx, sum - viewLinesAbove);\n\t}\n\n\tpublic removeValues(start: number, deleteCount: number): void {\n\t\tthis._values.splice(start, deleteCount);\n\t\tthis._invalidate(start);\n\t}\n\n\tpublic insertValues(insertIndex: number, insertArr: number[]): void {\n\t\tthis._values = arrayInsert(this._values, insertIndex, insertArr);\n\t\tthis._invalidate(insertIndex);\n\t}\n\n\tprivate _invalidate(index: number): void {\n\t\tthis._isValid = false;\n\t\tthis._validEndIndex = Math.min(this._validEndIndex, index - 1);\n\t}\n\n\tprivate _ensureValid(): void {\n\t\tif (this._isValid) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (let i = this._validEndIndex + 1, len = this._values.length; i < len; i++) {\n\t\t\tconst value = this._values[i];\n\t\t\tconst sumAbove = i > 0 ? this._prefixSum[i - 1] : 0;\n\n\t\t\tthis._prefixSum[i] = sumAbove + value;\n\t\t\tfor (let j = 0; j < value; j++) {\n\t\t\t\tthis._indexBySum[sumAbove + j] = i;\n\t\t\t}\n\t\t}\n\n\t\t// trim things\n\t\tthis._prefixSum.length = this._values.length;\n\t\tthis._indexBySum.length = this._prefixSum[this._prefixSum.length - 1];\n\n\t\t// mark as valid\n\t\tthis._isValid = true;\n\t\tthis._validEndIndex = this._values.length - 1;\n\t}\n\n\tpublic setValue(index: number, value: number): void {\n\t\tif (this._values[index] === value) {\n\t\t\t// no change\n\t\t\treturn;\n\t\t}\n\t\tthis._values[index] = value;\n\t\tthis._invalidate(index);\n\t}\n}\n\n\nexport class PrefixSumIndexOfResult {\n\t_prefixSumIndexOfResultBrand: void = undefined;\n\n\tconstructor(\n\t\tpublic readonly index: number,\n\t\tpublic readonly remainder: number\n\t) {\n\t\tthis.index = index;\n\t\tthis.remainder = remainder;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { splitLines } from 'vs/base/common/strings';\nimport { URI } from 'vs/base/common/uri';\nimport { Position } from 'vs/editor/common/core/position';\nimport { IRange } from 'vs/editor/common/core/range';\nimport { IModelContentChange } from 'vs/editor/common/textModelEvents';\nimport { PrefixSumComputer } from 'vs/editor/common/model/prefixSumComputer';\n\nexport interface IModelChangedEvent {\n\t/**\n\t * The actual changes.\n\t */\n\treadonly changes: IModelContentChange[];\n\t/**\n\t * The (new) end-of-line character.\n\t */\n\treadonly eol: string;\n\t/**\n\t * The new version id the model has transitioned to.\n\t */\n\treadonly versionId: number;\n}\n\nexport interface IMirrorTextModel {\n\treadonly version: number;\n}\n\nexport class MirrorTextModel implements IMirrorTextModel {\n\n\tprotected _uri: URI;\n\tprotected _lines: string[];\n\tprotected _eol: string;\n\tprotected _versionId: number;\n\tprotected _lineStarts: PrefixSumComputer | null;\n\tprivate _cachedTextValue: string | null;\n\n\tconstructor(uri: URI, lines: string[], eol: string, versionId: number) {\n\t\tthis._uri = uri;\n\t\tthis._lines = lines;\n\t\tthis._eol = eol;\n\t\tthis._versionId = versionId;\n\t\tthis._lineStarts = null;\n\t\tthis._cachedTextValue = null;\n\t}\n\n\tdispose(): void {\n\t\tthis._lines.length = 0;\n\t}\n\n\tget version(): number {\n\t\treturn this._versionId;\n\t}\n\n\tgetText(): string {\n\t\tif (this._cachedTextValue === null) {\n\t\t\tthis._cachedTextValue = this._lines.join(this._eol);\n\t\t}\n\t\treturn this._cachedTextValue;\n\t}\n\n\tonEvents(e: IModelChangedEvent): void {\n\t\tif (e.eol && e.eol !== this._eol) {\n\t\t\tthis._eol = e.eol;\n\t\t\tthis._lineStarts = null;\n\t\t}\n\n\t\t// Update my lines\n\t\tconst changes = e.changes;\n\t\tfor (const change of changes) {\n\t\t\tthis._acceptDeleteRange(change.range);\n\t\t\tthis._acceptInsertText(new Position(change.range.startLineNumber, change.range.startColumn), change.text);\n\t\t}\n\n\t\tthis._versionId = e.versionId;\n\t\tthis._cachedTextValue = null;\n\t}\n\n\tprotected _ensureLineStarts(): void {\n\t\tif (!this._lineStarts) {\n\t\t\tconst eolLength = this._eol.length;\n\t\t\tconst linesLength = this._lines.length;\n\t\t\tconst lineStartValues = new Uint32Array(linesLength);\n\t\t\tfor (let i = 0; i < linesLength; i++) {\n\t\t\t\tlineStartValues[i] = this._lines[i].length + eolLength;\n\t\t\t}\n\t\t\tthis._lineStarts = new PrefixSumComputer(lineStartValues);\n\t\t}\n\t}\n\n\t/**\n\t * All changes to a line's text go through this method\n\t */\n\tprivate _setLineText(lineIndex: number, newValue: string): void {\n\t\tthis._lines[lineIndex] = newValue;\n\t\tif (this._lineStarts) {\n\t\t\t// update prefix sum\n\t\t\tthis._lineStarts.setValue(lineIndex, this._lines[lineIndex].length + this._eol.length);\n\t\t}\n\t}\n\n\tprivate _acceptDeleteRange(range: IRange): void {\n\n\t\tif (range.startLineNumber === range.endLineNumber) {\n\t\t\tif (range.startColumn === range.endColumn) {\n\t\t\t\t// Nothing to delete\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Delete text on the affected line\n\t\t\tthis._setLineText(range.startLineNumber - 1,\n\t\t\t\tthis._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1)\n\t\t\t\t+ this._lines[range.startLineNumber - 1].substring(range.endColumn - 1)\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Take remaining text on last line and append it to remaining text on first line\n\t\tthis._setLineText(range.startLineNumber - 1,\n\t\t\tthis._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1)\n\t\t\t+ this._lines[range.endLineNumber - 1].substring(range.endColumn - 1)\n\t\t);\n\n\t\t// Delete middle lines\n\t\tthis._lines.splice(range.startLineNumber, range.endLineNumber - range.startLineNumber);\n\t\tif (this._lineStarts) {\n\t\t\t// update prefix sum\n\t\t\tthis._lineStarts.removeValues(range.startLineNumber, range.endLineNumber - range.startLineNumber);\n\t\t}\n\t}\n\n\tprivate _acceptInsertText(position: Position, insertText: string): void {\n\t\tif (insertText.length === 0) {\n\t\t\t// Nothing to insert\n\t\t\treturn;\n\t\t}\n\t\tconst insertLines = splitLines(insertText);\n\t\tif (insertLines.length === 1) {\n\t\t\t// Inserting text on one line\n\t\t\tthis._setLineText(position.lineNumber - 1,\n\t\t\t\tthis._lines[position.lineNumber - 1].substring(0, position.column - 1)\n\t\t\t\t+ insertLines[0]\n\t\t\t\t+ this._lines[position.lineNumber - 1].substring(position.column - 1)\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Append overflowing text from first line to the end of text to insert\n\t\tinsertLines[insertLines.length - 1] += this._lines[position.lineNumber - 1].substring(position.column - 1);\n\n\t\t// Delete overflowing text from first line and insert text on first line\n\t\tthis._setLineText(position.lineNumber - 1,\n\t\t\tthis._lines[position.lineNumber - 1].substring(0, position.column - 1)\n\t\t\t+ insertLines[0]\n\t\t);\n\n\t\t// Insert new lines & store lengths\n\t\tconst newLengths = new Uint32Array(insertLines.length - 1);\n\t\tfor (let i = 1; i < insertLines.length; i++) {\n\t\t\tthis._lines.splice(position.lineNumber + i - 1, 0, insertLines[i]);\n\t\t\tnewLengths[i - 1] = insertLines[i].length + this._eol.length;\n\t\t}\n\n\t\tif (this._lineStarts) {\n\t\t\t// update prefix sum\n\t\t\tthis._lineStarts.insertValues(position.lineNumber, newLengths);\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDisposable } from 'vs/base/common/lifecycle';\n\nexport class TextModelPart implements IDisposable {\n\tprivate _isDisposed = false;\n\n\tpublic dispose(): void {\n\t\tthis._isDisposed = true;\n\t}\n\tprotected assertNotDisposed(): void {\n\t\tif (this._isDisposed) {\n\t\t\tthrow new Error('TextModelPart is disposed!');\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport * as strings from 'vs/base/common/strings';\nimport { WordCharacterClass, WordCharacterClassifier, getMapForWordSeparators } from 'vs/editor/common/core/wordCharacterClassifier';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { EndOfLinePreference, FindMatch, SearchData } from 'vs/editor/common/model';\nimport { TextModel } from 'vs/editor/common/model/textModel';\n\nconst LIMIT_FIND_COUNT = 999;\n\nexport class SearchParams {\n\tpublic readonly searchString: string;\n\tpublic readonly isRegex: boolean;\n\tpublic readonly matchCase: boolean;\n\tpublic readonly wordSeparators: string | null;\n\n\tconstructor(searchString: string, isRegex: boolean, matchCase: boolean, wordSeparators: string | null) {\n\t\tthis.searchString = searchString;\n\t\tthis.isRegex = isRegex;\n\t\tthis.matchCase = matchCase;\n\t\tthis.wordSeparators = wordSeparators;\n\t}\n\n\tpublic parseSearchRequest(): SearchData | null {\n\t\tif (this.searchString === '') {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Try to create a RegExp out of the params\n\t\tlet multiline: boolean;\n\t\tif (this.isRegex) {\n\t\t\tmultiline = isMultilineRegexSource(this.searchString);\n\t\t} else {\n\t\t\tmultiline = (this.searchString.indexOf('\\n') >= 0);\n\t\t}\n\n\t\tlet regex: RegExp | null = null;\n\t\ttry {\n\t\t\tregex = strings.createRegExp(this.searchString, this.isRegex, {\n\t\t\t\tmatchCase: this.matchCase,\n\t\t\t\twholeWord: false,\n\t\t\t\tmultiline: multiline,\n\t\t\t\tglobal: true,\n\t\t\t\tunicode: true\n\t\t\t});\n\t\t} catch (err) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (!regex) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlet canUseSimpleSearch = (!this.isRegex && !multiline);\n\t\tif (canUseSimpleSearch && this.searchString.toLowerCase() !== this.searchString.toUpperCase()) {\n\t\t\t// casing might make a difference\n\t\t\tcanUseSimpleSearch = this.matchCase;\n\t\t}\n\n\t\treturn new SearchData(regex, this.wordSeparators ? getMapForWordSeparators(this.wordSeparators) : null, canUseSimpleSearch ? this.searchString : null);\n\t}\n}\n\nexport function isMultilineRegexSource(searchString: string): boolean {\n\tif (!searchString || searchString.length === 0) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0, len = searchString.length; i < len; i++) {\n\t\tconst chCode = searchString.charCodeAt(i);\n\n\t\tif (chCode === CharCode.Backslash) {\n\n\t\t\t// move to next char\n\t\t\ti++;\n\n\t\t\tif (i >= len) {\n\t\t\t\t// string ends with a \\\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst nextChCode = searchString.charCodeAt(i);\n\t\t\tif (nextChCode === CharCode.n || nextChCode === CharCode.r || nextChCode === CharCode.W) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\nexport function createFindMatch(range: Range, rawMatches: RegExpExecArray, captureMatches: boolean): FindMatch {\n\tif (!captureMatches) {\n\t\treturn new FindMatch(range, null);\n\t}\n\tconst matches: string[] = [];\n\tfor (let i = 0, len = rawMatches.length; i < len; i++) {\n\t\tmatches[i] = rawMatches[i];\n\t}\n\treturn new FindMatch(range, matches);\n}\n\nclass LineFeedCounter {\n\n\tprivate readonly _lineFeedsOffsets: number[];\n\n\tconstructor(text: string) {\n\t\tconst lineFeedsOffsets: number[] = [];\n\t\tlet lineFeedsOffsetsLen = 0;\n\t\tfor (let i = 0, textLen = text.length; i < textLen; i++) {\n\t\t\tif (text.charCodeAt(i) === CharCode.LineFeed) {\n\t\t\t\tlineFeedsOffsets[lineFeedsOffsetsLen++] = i;\n\t\t\t}\n\t\t}\n\t\tthis._lineFeedsOffsets = lineFeedsOffsets;\n\t}\n\n\tpublic findLineFeedCountBeforeOffset(offset: number): number {\n\t\tconst lineFeedsOffsets = this._lineFeedsOffsets;\n\t\tlet min = 0;\n\t\tlet max = lineFeedsOffsets.length - 1;\n\n\t\tif (max === -1) {\n\t\t\t// no line feeds\n\t\t\treturn 0;\n\t\t}\n\n\t\tif (offset <= lineFeedsOffsets[0]) {\n\t\t\t// before first line feed\n\t\t\treturn 0;\n\t\t}\n\n\t\twhile (min < max) {\n\t\t\tconst mid = min + ((max - min) / 2 >> 0);\n\n\t\t\tif (lineFeedsOffsets[mid] >= offset) {\n\t\t\t\tmax = mid - 1;\n\t\t\t} else {\n\t\t\t\tif (lineFeedsOffsets[mid + 1] >= offset) {\n\t\t\t\t\t// bingo!\n\t\t\t\t\tmin = mid;\n\t\t\t\t\tmax = mid;\n\t\t\t\t} else {\n\t\t\t\t\tmin = mid + 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn min + 1;\n\t}\n}\n\nexport class TextModelSearch {\n\n\tpublic static findMatches(model: TextModel, searchParams: SearchParams, searchRange: Range, captureMatches: boolean, limitResultCount: number): FindMatch[] {\n\t\tconst searchData = searchParams.parseSearchRequest();\n\t\tif (!searchData) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (searchData.regex.multiline) {\n\t\t\treturn this._doFindMatchesMultiline(model, searchRange, new Searcher(searchData.wordSeparators, searchData.regex), captureMatches, limitResultCount);\n\t\t}\n\t\treturn this._doFindMatchesLineByLine(model, searchRange, searchData, captureMatches, limitResultCount);\n\t}\n\n\t/**\n\t * Multiline search always executes on the lines concatenated with \\n.\n\t * We must therefore compensate for the count of \\n in case the model is CRLF\n\t */\n\tprivate static _getMultilineMatchRange(model: TextModel, deltaOffset: number, text: string, lfCounter: LineFeedCounter | null, matchIndex: number, match0: string): Range {\n\t\tlet startOffset: number;\n\t\tlet lineFeedCountBeforeMatch = 0;\n\t\tif (lfCounter) {\n\t\t\tlineFeedCountBeforeMatch = lfCounter.findLineFeedCountBeforeOffset(matchIndex);\n\t\t\tstartOffset = deltaOffset + matchIndex + lineFeedCountBeforeMatch /* add as many \\r as there were \\n */;\n\t\t} else {\n\t\t\tstartOffset = deltaOffset + matchIndex;\n\t\t}\n\n\t\tlet endOffset: number;\n\t\tif (lfCounter) {\n\t\t\tconst lineFeedCountBeforeEndOfMatch = lfCounter.findLineFeedCountBeforeOffset(matchIndex + match0.length);\n\t\t\tconst lineFeedCountInMatch = lineFeedCountBeforeEndOfMatch - lineFeedCountBeforeMatch;\n\t\t\tendOffset = startOffset + match0.length + lineFeedCountInMatch /* add as many \\r as there were \\n */;\n\t\t} else {\n\t\t\tendOffset = startOffset + match0.length;\n\t\t}\n\n\t\tconst startPosition = model.getPositionAt(startOffset);\n\t\tconst endPosition = model.getPositionAt(endOffset);\n\t\treturn new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column);\n\t}\n\n\tprivate static _doFindMatchesMultiline(model: TextModel, searchRange: Range, searcher: Searcher, captureMatches: boolean, limitResultCount: number): FindMatch[] {\n\t\tconst deltaOffset = model.getOffsetAt(searchRange.getStartPosition());\n\t\t// We always execute multiline search over the lines joined with \\n\n\t\t// This makes it that \\n will match the EOL for both CRLF and LF models\n\t\t// We compensate for offset errors in `_getMultilineMatchRange`\n\t\tconst text = model.getValueInRange(searchRange, EndOfLinePreference.LF);\n\t\tconst lfCounter = (model.getEOL() === '\\r\\n' ? new LineFeedCounter(text) : null);\n\n\t\tconst result: FindMatch[] = [];\n\t\tlet counter = 0;\n\n\t\tlet m: RegExpExecArray | null;\n\t\tsearcher.reset(0);\n\t\twhile ((m = searcher.next(text))) {\n\t\t\tresult[counter++] = createFindMatch(this._getMultilineMatchRange(model, deltaOffset, text, lfCounter, m.index, m[0]), m, captureMatches);\n\t\t\tif (counter >= limitResultCount) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate static _doFindMatchesLineByLine(model: TextModel, searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[] {\n\t\tconst result: FindMatch[] = [];\n\t\tlet resultLen = 0;\n\n\t\t// Early case for a search range that starts & stops on the same line number\n\t\tif (searchRange.startLineNumber === searchRange.endLineNumber) {\n\t\t\tconst text = model.getLineContent(searchRange.startLineNumber).substring(searchRange.startColumn - 1, searchRange.endColumn - 1);\n\t\t\tresultLen = this._findMatchesInLine(searchData, text, searchRange.startLineNumber, searchRange.startColumn - 1, resultLen, result, captureMatches, limitResultCount);\n\t\t\treturn result;\n\t\t}\n\n\t\t// Collect results from first line\n\t\tconst text = model.getLineContent(searchRange.startLineNumber).substring(searchRange.startColumn - 1);\n\t\tresultLen = this._findMatchesInLine(searchData, text, searchRange.startLineNumber, searchRange.startColumn - 1, resultLen, result, captureMatches, limitResultCount);\n\n\t\t// Collect results from middle lines\n\t\tfor (let lineNumber = searchRange.startLineNumber + 1; lineNumber < searchRange.endLineNumber && resultLen < limitResultCount; lineNumber++) {\n\t\t\tresultLen = this._findMatchesInLine(searchData, model.getLineContent(lineNumber), lineNumber, 0, resultLen, result, captureMatches, limitResultCount);\n\t\t}\n\n\t\t// Collect results from last line\n\t\tif (resultLen < limitResultCount) {\n\t\t\tconst text = model.getLineContent(searchRange.endLineNumber).substring(0, searchRange.endColumn - 1);\n\t\t\tresultLen = this._findMatchesInLine(searchData, text, searchRange.endLineNumber, 0, resultLen, result, captureMatches, limitResultCount);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate static _findMatchesInLine(searchData: SearchData, text: string, lineNumber: number, deltaOffset: number, resultLen: number, result: FindMatch[], captureMatches: boolean, limitResultCount: number): number {\n\t\tconst wordSeparators = searchData.wordSeparators;\n\t\tif (!captureMatches && searchData.simpleSearch) {\n\t\t\tconst searchString = searchData.simpleSearch;\n\t\t\tconst searchStringLen = searchString.length;\n\t\t\tconst textLength = text.length;\n\n\t\t\tlet lastMatchIndex = -searchStringLen;\n\t\t\twhile ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {\n\t\t\t\tif (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {\n\t\t\t\t\tresult[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);\n\t\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\t\treturn resultLen;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn resultLen;\n\t\t}\n\n\t\tconst searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n\t\tlet m: RegExpExecArray | null;\n\t\t// Reset regex to search from the beginning\n\t\tsearcher.reset(0);\n\t\tdo {\n\t\t\tm = searcher.next(text);\n\t\t\tif (m) {\n\t\t\t\tresult[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (m);\n\t\treturn resultLen;\n\t}\n\n\tpublic static findNextMatch(model: TextModel, searchParams: SearchParams, searchStart: Position, captureMatches: boolean): FindMatch | null {\n\t\tconst searchData = searchParams.parseSearchRequest();\n\t\tif (!searchData) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n\n\t\tif (searchData.regex.multiline) {\n\t\t\treturn this._doFindNextMatchMultiline(model, searchStart, searcher, captureMatches);\n\t\t}\n\t\treturn this._doFindNextMatchLineByLine(model, searchStart, searcher, captureMatches);\n\t}\n\n\tprivate static _doFindNextMatchMultiline(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch | null {\n\t\tconst searchTextStart = new Position(searchStart.lineNumber, 1);\n\t\tconst deltaOffset = model.getOffsetAt(searchTextStart);\n\t\tconst lineCount = model.getLineCount();\n\t\t// We always execute multiline search over the lines joined with \\n\n\t\t// This makes it that \\n will match the EOL for both CRLF and LF models\n\t\t// We compensate for offset errors in `_getMultilineMatchRange`\n\t\tconst text = model.getValueInRange(new Range(searchTextStart.lineNumber, searchTextStart.column, lineCount, model.getLineMaxColumn(lineCount)), EndOfLinePreference.LF);\n\t\tconst lfCounter = (model.getEOL() === '\\r\\n' ? new LineFeedCounter(text) : null);\n\t\tsearcher.reset(searchStart.column - 1);\n\t\tlet m = searcher.next(text);\n\t\tif (m) {\n\t\t\treturn createFindMatch(\n\t\t\t\tthis._getMultilineMatchRange(model, deltaOffset, text, lfCounter, m.index, m[0]),\n\t\t\t\tm,\n\t\t\t\tcaptureMatches\n\t\t\t);\n\t\t}\n\n\t\tif (searchStart.lineNumber !== 1 || searchStart.column !== 1) {\n\t\t\t// Try again from the top\n\t\t\treturn this._doFindNextMatchMultiline(model, new Position(1, 1), searcher, captureMatches);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate static _doFindNextMatchLineByLine(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch | null {\n\t\tconst lineCount = model.getLineCount();\n\t\tconst startLineNumber = searchStart.lineNumber;\n\n\t\t// Look in first line\n\t\tconst text = model.getLineContent(startLineNumber);\n\t\tconst r = this._findFirstMatchInLine(searcher, text, startLineNumber, searchStart.column, captureMatches);\n\t\tif (r) {\n\t\t\treturn r;\n\t\t}\n\n\t\tfor (let i = 1; i <= lineCount; i++) {\n\t\t\tconst lineIndex = (startLineNumber + i - 1) % lineCount;\n\t\t\tconst text = model.getLineContent(lineIndex + 1);\n\t\t\tconst r = this._findFirstMatchInLine(searcher, text, lineIndex + 1, 1, captureMatches);\n\t\t\tif (r) {\n\t\t\t\treturn r;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate static _findFirstMatchInLine(searcher: Searcher, text: string, lineNumber: number, fromColumn: number, captureMatches: boolean): FindMatch | null {\n\t\t// Set regex to search from column\n\t\tsearcher.reset(fromColumn - 1);\n\t\tconst m: RegExpExecArray | null = searcher.next(text);\n\t\tif (m) {\n\t\t\treturn createFindMatch(\n\t\t\t\tnew Range(lineNumber, m.index + 1, lineNumber, m.index + 1 + m[0].length),\n\t\t\t\tm,\n\t\t\t\tcaptureMatches\n\t\t\t);\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic static findPreviousMatch(model: TextModel, searchParams: SearchParams, searchStart: Position, captureMatches: boolean): FindMatch | null {\n\t\tconst searchData = searchParams.parseSearchRequest();\n\t\tif (!searchData) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n\n\t\tif (searchData.regex.multiline) {\n\t\t\treturn this._doFindPreviousMatchMultiline(model, searchStart, searcher, captureMatches);\n\t\t}\n\t\treturn this._doFindPreviousMatchLineByLine(model, searchStart, searcher, captureMatches);\n\t}\n\n\tprivate static _doFindPreviousMatchMultiline(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch | null {\n\t\tconst matches = this._doFindMatchesMultiline(model, new Range(1, 1, searchStart.lineNumber, searchStart.column), searcher, captureMatches, 10 * LIMIT_FIND_COUNT);\n\t\tif (matches.length > 0) {\n\t\t\treturn matches[matches.length - 1];\n\t\t}\n\n\t\tconst lineCount = model.getLineCount();\n\t\tif (searchStart.lineNumber !== lineCount || searchStart.column !== model.getLineMaxColumn(lineCount)) {\n\t\t\t// Try again with all content\n\t\t\treturn this._doFindPreviousMatchMultiline(model, new Position(lineCount, model.getLineMaxColumn(lineCount)), searcher, captureMatches);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate static _doFindPreviousMatchLineByLine(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch | null {\n\t\tconst lineCount = model.getLineCount();\n\t\tconst startLineNumber = searchStart.lineNumber;\n\n\t\t// Look in first line\n\t\tconst text = model.getLineContent(startLineNumber).substring(0, searchStart.column - 1);\n\t\tconst r = this._findLastMatchInLine(searcher, text, startLineNumber, captureMatches);\n\t\tif (r) {\n\t\t\treturn r;\n\t\t}\n\n\t\tfor (let i = 1; i <= lineCount; i++) {\n\t\t\tconst lineIndex = (lineCount + startLineNumber - i - 1) % lineCount;\n\t\t\tconst text = model.getLineContent(lineIndex + 1);\n\t\t\tconst r = this._findLastMatchInLine(searcher, text, lineIndex + 1, captureMatches);\n\t\t\tif (r) {\n\t\t\t\treturn r;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate static _findLastMatchInLine(searcher: Searcher, text: string, lineNumber: number, captureMatches: boolean): FindMatch | null {\n\t\tlet bestResult: FindMatch | null = null;\n\t\tlet m: RegExpExecArray | null;\n\t\tsearcher.reset(0);\n\t\twhile ((m = searcher.next(text))) {\n\t\t\tbestResult = createFindMatch(new Range(lineNumber, m.index + 1, lineNumber, m.index + 1 + m[0].length), m, captureMatches);\n\t\t}\n\t\treturn bestResult;\n\t}\n}\n\nfunction leftIsWordBounday(wordSeparators: WordCharacterClassifier, text: string, textLength: number, matchStartIndex: number, matchLength: number): boolean {\n\tif (matchStartIndex === 0) {\n\t\t// Match starts at start of string\n\t\treturn true;\n\t}\n\n\tconst charBefore = text.charCodeAt(matchStartIndex - 1);\n\tif (wordSeparators.get(charBefore) !== WordCharacterClass.Regular) {\n\t\t// The character before the match is a word separator\n\t\treturn true;\n\t}\n\n\tif (charBefore === CharCode.CarriageReturn || charBefore === CharCode.LineFeed) {\n\t\t// The character before the match is line break or carriage return.\n\t\treturn true;\n\t}\n\n\tif (matchLength > 0) {\n\t\tconst firstCharInMatch = text.charCodeAt(matchStartIndex);\n\t\tif (wordSeparators.get(firstCharInMatch) !== WordCharacterClass.Regular) {\n\t\t\t// The first character inside the match is a word separator\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nfunction rightIsWordBounday(wordSeparators: WordCharacterClassifier, text: string, textLength: number, matchStartIndex: number, matchLength: number): boolean {\n\tif (matchStartIndex + matchLength === textLength) {\n\t\t// Match ends at end of string\n\t\treturn true;\n\t}\n\n\tconst charAfter = text.charCodeAt(matchStartIndex + matchLength);\n\tif (wordSeparators.get(charAfter) !== WordCharacterClass.Regular) {\n\t\t// The character after the match is a word separator\n\t\treturn true;\n\t}\n\n\tif (charAfter === CharCode.CarriageReturn || charAfter === CharCode.LineFeed) {\n\t\t// The character after the match is line break or carriage return.\n\t\treturn true;\n\t}\n\n\tif (matchLength > 0) {\n\t\tconst lastCharInMatch = text.charCodeAt(matchStartIndex + matchLength - 1);\n\t\tif (wordSeparators.get(lastCharInMatch) !== WordCharacterClass.Regular) {\n\t\t\t// The last character in the match is a word separator\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nexport function isValidMatch(wordSeparators: WordCharacterClassifier, text: string, textLength: number, matchStartIndex: number, matchLength: number): boolean {\n\treturn (\n\t\tleftIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength)\n\t\t&& rightIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength)\n\t);\n}\n\nexport class Searcher {\n\tpublic readonly _wordSeparators: WordCharacterClassifier | null;\n\tprivate readonly _searchRegex: RegExp;\n\tprivate _prevMatchStartIndex: number;\n\tprivate _prevMatchLength: number;\n\n\tconstructor(wordSeparators: WordCharacterClassifier | null, searchRegex: RegExp,) {\n\t\tthis._wordSeparators = wordSeparators;\n\t\tthis._searchRegex = searchRegex;\n\t\tthis._prevMatchStartIndex = -1;\n\t\tthis._prevMatchLength = 0;\n\t}\n\n\tpublic reset(lastIndex: number): void {\n\t\tthis._searchRegex.lastIndex = lastIndex;\n\t\tthis._prevMatchStartIndex = -1;\n\t\tthis._prevMatchLength = 0;\n\t}\n\n\tpublic next(text: string): RegExpExecArray | null {\n\t\tconst textLength = text.length;\n\n\t\tlet m: RegExpExecArray | null;\n\t\tdo {\n\t\t\tif (this._prevMatchStartIndex + this._prevMatchLength === textLength) {\n\t\t\t\t// Reached the end of the line\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tm = this._searchRegex.exec(text);\n\t\t\tif (!m) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst matchStartIndex = m.index;\n\t\t\tconst matchLength = m[0].length;\n\t\t\tif (matchStartIndex === this._prevMatchStartIndex && matchLength === this._prevMatchLength) {\n\t\t\t\tif (matchLength === 0) {\n\t\t\t\t\t// the search result is an empty string and won't advance `regex.lastIndex`, so `regex.exec` will stuck here\n\t\t\t\t\t// we attempt to recover from that by advancing by two if surrogate pair found and by one otherwise\n\t\t\t\t\tif (strings.getNextCodePoint(text, textLength, this._searchRegex.lastIndex) > 0xFFFF) {\n\t\t\t\t\t\tthis._searchRegex.lastIndex += 2;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._searchRegex.lastIndex += 1;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// Exit early if the regex matches the same range twice\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tthis._prevMatchStartIndex = matchStartIndex;\n\t\t\tthis._prevMatchLength = matchLength;\n\n\t\t\tif (!this._wordSeparators || isValidMatch(this._wordSeparators, text, textLength, matchStartIndex, matchLength)) {\n\t\t\t\treturn m;\n\t\t\t}\n\n\t\t} while (m);\n\n\t\treturn null;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { Searcher } from 'vs/editor/common/model/textModelSearch';\nimport * as strings from 'vs/base/common/strings';\nimport { IUnicodeHighlightsResult } from 'vs/editor/common/services/editorWorker';\nimport { assertNever } from 'vs/base/common/types';\n\nexport class UnicodeTextModelHighlighter {\n\tpublic static computeUnicodeHighlights(model: IUnicodeCharacterSearcherTarget, options: UnicodeHighlighterOptions, range?: IRange): IUnicodeHighlightsResult {\n\t\tconst startLine = range ? range.startLineNumber : 1;\n\t\tconst endLine = range ? range.endLineNumber : model.getLineCount();\n\n\t\tconst codePointHighlighter = new CodePointHighlighter(options);\n\n\t\tconst candidates = codePointHighlighter.getCandidateCodePoints();\n\t\tlet regex: RegExp;\n\t\tif (candidates === 'allNonBasicAscii') {\n\t\t\tregex = new RegExp('[^\\\\t\\\\n\\\\r\\\\x20-\\\\x7E]', 'g');\n\t\t} else {\n\t\t\tregex = new RegExp(`${buildRegExpCharClassExpr(Array.from(candidates))}`, 'g');\n\t\t}\n\n\t\tconst searcher = new Searcher(null, regex);\n\t\tconst ranges: Range[] = [];\n\t\tlet hasMore = false;\n\t\tlet m: RegExpExecArray | null;\n\n\t\tlet ambiguousCharacterCount = 0;\n\t\tlet invisibleCharacterCount = 0;\n\t\tlet nonBasicAsciiCharacterCount = 0;\n\n\t\tforLoop:\n\t\tfor (let lineNumber = startLine, lineCount = endLine; lineNumber <= lineCount; lineNumber++) {\n\t\t\tconst lineContent = model.getLineContent(lineNumber);\n\t\t\tconst lineLength = lineContent.length;\n\n\t\t\t// Reset regex to search from the beginning\n\t\t\tsearcher.reset(0);\n\t\t\tdo {\n\t\t\t\tm = searcher.next(lineContent);\n\t\t\t\tif (m) {\n\t\t\t\t\tlet startIndex = m.index;\n\t\t\t\t\tlet endIndex = m.index + m[0].length;\n\n\t\t\t\t\t// Extend range to entire code point\n\t\t\t\t\tif (startIndex > 0) {\n\t\t\t\t\t\tconst charCodeBefore = lineContent.charCodeAt(startIndex - 1);\n\t\t\t\t\t\tif (strings.isHighSurrogate(charCodeBefore)) {\n\t\t\t\t\t\t\tstartIndex--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (endIndex + 1 < lineLength) {\n\t\t\t\t\t\tconst charCodeBefore = lineContent.charCodeAt(endIndex - 1);\n\t\t\t\t\t\tif (strings.isHighSurrogate(charCodeBefore)) {\n\t\t\t\t\t\t\tendIndex++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconst str = lineContent.substring(startIndex, endIndex);\n\t\t\t\t\tconst highlightReason = codePointHighlighter.shouldHighlightNonBasicASCII(str);\n\n\t\t\t\t\tif (highlightReason !== SimpleHighlightReason.None) {\n\t\t\t\t\t\tif (highlightReason === SimpleHighlightReason.Ambiguous) {\n\t\t\t\t\t\t\tambiguousCharacterCount++;\n\t\t\t\t\t\t} else if (highlightReason === SimpleHighlightReason.Invisible) {\n\t\t\t\t\t\t\tinvisibleCharacterCount++;\n\t\t\t\t\t\t} else if (highlightReason === SimpleHighlightReason.NonBasicASCII) {\n\t\t\t\t\t\t\tnonBasicAsciiCharacterCount++;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tassertNever(highlightReason);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst MAX_RESULT_LENGTH = 1000;\n\t\t\t\t\t\tif (ranges.length >= MAX_RESULT_LENGTH) {\n\t\t\t\t\t\t\thasMore = true;\n\t\t\t\t\t\t\tbreak forLoop;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tranges.push(new Range(lineNumber, startIndex + 1, lineNumber, endIndex + 1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} while (m);\n\t\t}\n\t\treturn {\n\t\t\tranges,\n\t\t\thasMore,\n\t\t\tambiguousCharacterCount,\n\t\t\tinvisibleCharacterCount,\n\t\t\tnonBasicAsciiCharacterCount\n\t\t};\n\t}\n\n\tpublic static computeUnicodeHighlightReason(char: string, options: UnicodeHighlighterOptions): UnicodeHighlighterReason | null {\n\t\tconst codePointHighlighter = new CodePointHighlighter(options);\n\n\t\tconst reason = codePointHighlighter.shouldHighlightNonBasicASCII(char);\n\t\tswitch (reason) {\n\t\t\tcase SimpleHighlightReason.None:\n\t\t\t\treturn null;\n\t\t\tcase SimpleHighlightReason.Invisible:\n\t\t\t\treturn { kind: UnicodeHighlighterReasonKind.Invisible };\n\n\t\t\tcase SimpleHighlightReason.Ambiguous: {\n\t\t\t\tconst codePoint = char.codePointAt(0)!;\n\t\t\t\tconst primaryConfusable = codePointHighlighter.ambiguousCharacters.getPrimaryConfusable(codePoint)!;\n\t\t\t\tconst notAmbiguousInLocales =\n\t\t\t\t\tstrings.AmbiguousCharacters.getLocales().filter(\n\t\t\t\t\t\t(l) =>\n\t\t\t\t\t\t\t!strings.AmbiguousCharacters.getInstance(\n\t\t\t\t\t\t\t\tnew Set([...options.allowedLocales, l])\n\t\t\t\t\t\t\t).isAmbiguous(codePoint)\n\t\t\t\t\t);\n\t\t\t\treturn { kind: UnicodeHighlighterReasonKind.Ambiguous, confusableWith: String.fromCodePoint(primaryConfusable), notAmbiguousInLocales };\n\t\t\t}\n\t\t\tcase SimpleHighlightReason.NonBasicASCII:\n\t\t\t\treturn { kind: UnicodeHighlighterReasonKind.NonBasicAscii };\n\t\t}\n\t}\n}\n\nfunction buildRegExpCharClassExpr(codePoints: number[], flags?: string): string {\n\tconst src = `[${strings.escapeRegExpCharacters(\n\t\tcodePoints.map((i) => String.fromCodePoint(i)).join('')\n\t)}]`;\n\treturn src;\n}\n\nexport const enum UnicodeHighlighterReasonKind {\n\tAmbiguous, Invisible, NonBasicAscii\n}\n\nexport type UnicodeHighlighterReason = {\n\tkind: UnicodeHighlighterReasonKind.Ambiguous;\n\tconfusableWith: string;\n\tnotAmbiguousInLocales: string[];\n} | {\n\tkind: UnicodeHighlighterReasonKind.Invisible;\n} | {\n\tkind: UnicodeHighlighterReasonKind.NonBasicAscii\n};\n\nclass CodePointHighlighter {\n\tprivate readonly allowedCodePoints: Set;\n\tpublic readonly ambiguousCharacters: strings.AmbiguousCharacters;\n\tconstructor(private readonly options: UnicodeHighlighterOptions) {\n\t\tthis.allowedCodePoints = new Set(options.allowedCodePoints);\n\t\tthis.ambiguousCharacters = strings.AmbiguousCharacters.getInstance(new Set(options.allowedLocales));\n\t}\n\n\tpublic getCandidateCodePoints(): Set | 'allNonBasicAscii' {\n\t\tif (this.options.nonBasicASCII) {\n\t\t\treturn 'allNonBasicAscii';\n\t\t}\n\n\t\tconst set = new Set();\n\n\t\tif (this.options.invisibleCharacters) {\n\t\t\tfor (const cp of strings.InvisibleCharacters.codePoints) {\n\t\t\t\tset.add(cp);\n\t\t\t}\n\t\t}\n\n\t\tif (this.options.ambiguousCharacters) {\n\t\t\tfor (const cp of this.ambiguousCharacters.getConfusableCodePoints()) {\n\t\t\t\tset.add(cp);\n\t\t\t}\n\t\t}\n\n\t\tfor (const cp of this.allowedCodePoints) {\n\t\t\tset.delete(cp);\n\t\t}\n\n\t\treturn set;\n\t}\n\n\tpublic shouldHighlightNonBasicASCII(character: string): SimpleHighlightReason {\n\t\tconst codePoint = character.codePointAt(0)!;\n\n\t\tif (this.allowedCodePoints.has(codePoint)) {\n\t\t\treturn SimpleHighlightReason.None;\n\t\t}\n\n\t\tif (this.options.nonBasicASCII) {\n\t\t\treturn SimpleHighlightReason.NonBasicASCII;\n\t\t}\n\n\t\tif (this.options.invisibleCharacters) {\n\t\t\tconst isAllowedInvisibleCharacter = character === ' ' || character === '\\n' || character === '\\t';\n\t\t\t// TODO check for emojis\n\t\t\tif (!isAllowedInvisibleCharacter && strings.InvisibleCharacters.isInvisibleCharacter(codePoint)) {\n\t\t\t\treturn SimpleHighlightReason.Invisible;\n\t\t\t}\n\t\t}\n\n\t\tif (this.options.ambiguousCharacters) {\n\t\t\tif (this.ambiguousCharacters.isAmbiguous(codePoint)) {\n\t\t\t\treturn SimpleHighlightReason.Ambiguous;\n\t\t\t}\n\t\t}\n\n\t\treturn SimpleHighlightReason.None;\n\t}\n}\n\nconst enum SimpleHighlightReason {\n\tNone,\n\tNonBasicASCII,\n\tInvisible,\n\tAmbiguous\n}\n\nexport interface IUnicodeCharacterSearcherTarget {\n\tgetLineCount(): number;\n\tgetLineContent(lineNumber: number): string;\n}\n\nexport interface UnicodeHighlighterOptions {\n\tnonBasicASCII: boolean;\n\tambiguousCharacters: boolean;\n\tinvisibleCharacters: boolean;\n\tincludeComments: boolean;\n\tincludeStrings: boolean;\n\tallowedCodePoints: number[];\n\tallowedLocales: string[];\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { FindMatch, ITextSnapshot, SearchData } from 'vs/editor/common/model';\nimport { NodeColor, SENTINEL, TreeNode, fixInsert, leftest, rbDelete, righttest, updateTreeMetadata } from 'vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase';\nimport { Searcher, createFindMatch, isValidMatch } from 'vs/editor/common/model/textModelSearch';\n\n// const lfRegex = new RegExp(/\\r\\n|\\r|\\n/g);\nexport const AverageBufferSize = 65535;\n\nexport function createUintArray(arr: number[]): Uint32Array | Uint16Array {\n\tlet r;\n\tif (arr[arr.length - 1] < 65536) {\n\t\tr = new Uint16Array(arr.length);\n\t} else {\n\t\tr = new Uint32Array(arr.length);\n\t}\n\tr.set(arr, 0);\n\treturn r;\n}\n\nexport class LineStarts {\n\tconstructor(\n\t\tpublic readonly lineStarts: Uint32Array | Uint16Array | number[],\n\t\tpublic readonly cr: number,\n\t\tpublic readonly lf: number,\n\t\tpublic readonly crlf: number,\n\t\tpublic readonly isBasicASCII: boolean\n\t) { }\n}\n\nexport function createLineStartsFast(str: string, readonly: boolean = true): Uint32Array | Uint16Array | number[] {\n\tconst r: number[] = [0];\n\tlet rLength = 1;\n\n\tfor (let i = 0, len = str.length; i < len; i++) {\n\t\tconst chr = str.charCodeAt(i);\n\n\t\tif (chr === CharCode.CarriageReturn) {\n\t\t\tif (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) {\n\t\t\t\t// \\r\\n... case\n\t\t\t\tr[rLength++] = i + 2;\n\t\t\t\ti++; // skip \\n\n\t\t\t} else {\n\t\t\t\t// \\r... case\n\t\t\t\tr[rLength++] = i + 1;\n\t\t\t}\n\t\t} else if (chr === CharCode.LineFeed) {\n\t\t\tr[rLength++] = i + 1;\n\t\t}\n\t}\n\tif (readonly) {\n\t\treturn createUintArray(r);\n\t} else {\n\t\treturn r;\n\t}\n}\n\nexport function createLineStarts(r: number[], str: string): LineStarts {\n\tr.length = 0;\n\tr[0] = 0;\n\tlet rLength = 1;\n\tlet cr = 0, lf = 0, crlf = 0;\n\tlet isBasicASCII = true;\n\tfor (let i = 0, len = str.length; i < len; i++) {\n\t\tconst chr = str.charCodeAt(i);\n\n\t\tif (chr === CharCode.CarriageReturn) {\n\t\t\tif (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) {\n\t\t\t\t// \\r\\n... case\n\t\t\t\tcrlf++;\n\t\t\t\tr[rLength++] = i + 2;\n\t\t\t\ti++; // skip \\n\n\t\t\t} else {\n\t\t\t\tcr++;\n\t\t\t\t// \\r... case\n\t\t\t\tr[rLength++] = i + 1;\n\t\t\t}\n\t\t} else if (chr === CharCode.LineFeed) {\n\t\t\tlf++;\n\t\t\tr[rLength++] = i + 1;\n\t\t} else {\n\t\t\tif (isBasicASCII) {\n\t\t\t\tif (chr !== CharCode.Tab && (chr < 32 || chr > 126)) {\n\t\t\t\t\tisBasicASCII = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tconst result = new LineStarts(createUintArray(r), cr, lf, crlf, isBasicASCII);\n\tr.length = 0;\n\n\treturn result;\n}\n\nexport interface NodePosition {\n\t/**\n\t * Piece Index\n\t */\n\tnode: TreeNode;\n\t/**\n\t * remainer in current piece.\n\t*/\n\tremainder: number;\n\t/**\n\t * node start offset in document.\n\t */\n\tnodeStartOffset: number;\n}\n\nexport interface BufferCursor {\n\t/**\n\t * Line number in current buffer\n\t */\n\tline: number;\n\t/**\n\t * Column number in current buffer\n\t */\n\tcolumn: number;\n}\n\nexport class Piece {\n\treadonly bufferIndex: number;\n\treadonly start: BufferCursor;\n\treadonly end: BufferCursor;\n\treadonly length: number;\n\treadonly lineFeedCnt: number;\n\n\tconstructor(bufferIndex: number, start: BufferCursor, end: BufferCursor, lineFeedCnt: number, length: number) {\n\t\tthis.bufferIndex = bufferIndex;\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\tthis.lineFeedCnt = lineFeedCnt;\n\t\tthis.length = length;\n\t}\n}\n\nexport class StringBuffer {\n\tbuffer: string;\n\tlineStarts: Uint32Array | Uint16Array | number[];\n\n\tconstructor(buffer: string, lineStarts: Uint32Array | Uint16Array | number[]) {\n\t\tthis.buffer = buffer;\n\t\tthis.lineStarts = lineStarts;\n\t}\n}\n\n/**\n * Readonly snapshot for piece tree.\n * In a real multiple thread environment, to make snapshot reading always work correctly, we need to\n * 1. Make TreeNode.piece immutable, then reading and writing can run in parallel.\n * 2. TreeNode/Buffers normalization should not happen during snapshot reading.\n */\nclass PieceTreeSnapshot implements ITextSnapshot {\n\tprivate readonly _pieces: Piece[];\n\tprivate _index: number;\n\tprivate readonly _tree: PieceTreeBase;\n\tprivate readonly _BOM: string;\n\n\tconstructor(tree: PieceTreeBase, BOM: string) {\n\t\tthis._pieces = [];\n\t\tthis._tree = tree;\n\t\tthis._BOM = BOM;\n\t\tthis._index = 0;\n\t\tif (tree.root !== SENTINEL) {\n\t\t\ttree.iterate(tree.root, node => {\n\t\t\t\tif (node !== SENTINEL) {\n\t\t\t\t\tthis._pieces.push(node.piece);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t});\n\t\t}\n\t}\n\n\tread(): string | null {\n\t\tif (this._pieces.length === 0) {\n\t\t\tif (this._index === 0) {\n\t\t\t\tthis._index++;\n\t\t\t\treturn this._BOM;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tif (this._index > this._pieces.length - 1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (this._index === 0) {\n\t\t\treturn this._BOM + this._tree.getPieceContent(this._pieces[this._index++]);\n\t\t}\n\t\treturn this._tree.getPieceContent(this._pieces[this._index++]);\n\t}\n}\n\ninterface CacheEntry {\n\tnode: TreeNode;\n\tnodeStartOffset: number;\n\tnodeStartLineNumber?: number;\n}\n\nclass PieceTreeSearchCache {\n\tprivate readonly _limit: number;\n\tprivate _cache: CacheEntry[];\n\n\tconstructor(limit: number) {\n\t\tthis._limit = limit;\n\t\tthis._cache = [];\n\t}\n\n\tpublic get(offset: number): CacheEntry | null {\n\t\tfor (let i = this._cache.length - 1; i >= 0; i--) {\n\t\t\tconst nodePos = this._cache[i];\n\t\t\tif (nodePos.nodeStartOffset <= offset && nodePos.nodeStartOffset + nodePos.node.piece.length >= offset) {\n\t\t\t\treturn nodePos;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic get2(lineNumber: number): { node: TreeNode, nodeStartOffset: number, nodeStartLineNumber: number } | null {\n\t\tfor (let i = this._cache.length - 1; i >= 0; i--) {\n\t\t\tconst nodePos = this._cache[i];\n\t\t\tif (nodePos.nodeStartLineNumber && nodePos.nodeStartLineNumber < lineNumber && nodePos.nodeStartLineNumber + nodePos.node.piece.lineFeedCnt >= lineNumber) {\n\t\t\t\treturn <{ node: TreeNode, nodeStartOffset: number, nodeStartLineNumber: number }>nodePos;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic set(nodePosition: CacheEntry) {\n\t\tif (this._cache.length >= this._limit) {\n\t\t\tthis._cache.shift();\n\t\t}\n\t\tthis._cache.push(nodePosition);\n\t}\n\n\tpublic validate(offset: number) {\n\t\tlet hasInvalidVal = false;\n\t\tconst tmp: Array = this._cache;\n\t\tfor (let i = 0; i < tmp.length; i++) {\n\t\t\tconst nodePos = tmp[i]!;\n\t\t\tif (nodePos.node.parent === null || nodePos.nodeStartOffset >= offset) {\n\t\t\t\ttmp[i] = null;\n\t\t\t\thasInvalidVal = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif (hasInvalidVal) {\n\t\t\tconst newArr: CacheEntry[] = [];\n\t\t\tfor (const entry of tmp) {\n\t\t\t\tif (entry !== null) {\n\t\t\t\t\tnewArr.push(entry);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._cache = newArr;\n\t\t}\n\t}\n}\n\nexport class PieceTreeBase {\n\troot!: TreeNode;\n\tprotected _buffers!: StringBuffer[]; // 0 is change buffer, others are readonly original buffer.\n\tprotected _lineCnt!: number;\n\tprotected _length!: number;\n\tprotected _EOL!: '\\r\\n' | '\\n';\n\tprotected _EOLLength!: number;\n\tprotected _EOLNormalized!: boolean;\n\tprivate _lastChangeBufferPos!: BufferCursor;\n\tprivate _searchCache!: PieceTreeSearchCache;\n\tprivate _lastVisitedLine!: { lineNumber: number; value: string; };\n\n\tconstructor(chunks: StringBuffer[], eol: '\\r\\n' | '\\n', eolNormalized: boolean) {\n\t\tthis.create(chunks, eol, eolNormalized);\n\t}\n\n\tcreate(chunks: StringBuffer[], eol: '\\r\\n' | '\\n', eolNormalized: boolean) {\n\t\tthis._buffers = [\n\t\t\tnew StringBuffer('', [0])\n\t\t];\n\t\tthis._lastChangeBufferPos = { line: 0, column: 0 };\n\t\tthis.root = SENTINEL;\n\t\tthis._lineCnt = 1;\n\t\tthis._length = 0;\n\t\tthis._EOL = eol;\n\t\tthis._EOLLength = eol.length;\n\t\tthis._EOLNormalized = eolNormalized;\n\n\t\tlet lastNode: TreeNode | null = null;\n\t\tfor (let i = 0, len = chunks.length; i < len; i++) {\n\t\t\tif (chunks[i].buffer.length > 0) {\n\t\t\t\tif (!chunks[i].lineStarts) {\n\t\t\t\t\tchunks[i].lineStarts = createLineStartsFast(chunks[i].buffer);\n\t\t\t\t}\n\n\t\t\t\tconst piece = new Piece(\n\t\t\t\t\ti + 1,\n\t\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t\t{ line: chunks[i].lineStarts.length - 1, column: chunks[i].buffer.length - chunks[i].lineStarts[chunks[i].lineStarts.length - 1] },\n\t\t\t\t\tchunks[i].lineStarts.length - 1,\n\t\t\t\t\tchunks[i].buffer.length\n\t\t\t\t);\n\t\t\t\tthis._buffers.push(chunks[i]);\n\t\t\t\tlastNode = this.rbInsertRight(lastNode, piece);\n\t\t\t}\n\t\t}\n\n\t\tthis._searchCache = new PieceTreeSearchCache(1);\n\t\tthis._lastVisitedLine = { lineNumber: 0, value: '' };\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tnormalizeEOL(eol: '\\r\\n' | '\\n') {\n\t\tconst averageBufferSize = AverageBufferSize;\n\t\tconst min = averageBufferSize - Math.floor(averageBufferSize / 3);\n\t\tconst max = min * 2;\n\n\t\tlet tempChunk = '';\n\t\tlet tempChunkLen = 0;\n\t\tconst chunks: StringBuffer[] = [];\n\n\t\tthis.iterate(this.root, node => {\n\t\t\tconst str = this.getNodeContent(node);\n\t\t\tconst len = str.length;\n\t\t\tif (tempChunkLen <= min || tempChunkLen + len < max) {\n\t\t\t\ttempChunk += str;\n\t\t\t\ttempChunkLen += len;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// flush anyways\n\t\t\tconst text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\tchunks.push(new StringBuffer(text, createLineStartsFast(text)));\n\t\t\ttempChunk = str;\n\t\t\ttempChunkLen = len;\n\t\t\treturn true;\n\t\t});\n\n\t\tif (tempChunkLen > 0) {\n\t\t\tconst text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\tchunks.push(new StringBuffer(text, createLineStartsFast(text)));\n\t\t}\n\n\t\tthis.create(chunks, eol, true);\n\t}\n\n\t// #region Buffer API\n\tpublic getEOL(): '\\r\\n' | '\\n' {\n\t\treturn this._EOL;\n\t}\n\n\tpublic setEOL(newEOL: '\\r\\n' | '\\n'): void {\n\t\tthis._EOL = newEOL;\n\t\tthis._EOLLength = this._EOL.length;\n\t\tthis.normalizeEOL(newEOL);\n\t}\n\n\tpublic createSnapshot(BOM: string): ITextSnapshot {\n\t\treturn new PieceTreeSnapshot(this, BOM);\n\t}\n\n\tpublic getOffsetAt(lineNumber: number, column: number): number {\n\t\tlet leftLen = 0; // inorder\n\n\t\tlet x = this.root;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.left !== SENTINEL && x.lf_left + 1 >= lineNumber) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt + 1 >= lineNumber) {\n\t\t\t\tleftLen += x.size_left;\n\t\t\t\t// lineNumber >= 2\n\t\t\t\tconst accumualtedValInCurrentIndex = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\treturn leftLen += accumualtedValInCurrentIndex + column - 1;\n\t\t\t} else {\n\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\tleftLen += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\treturn leftLen;\n\t}\n\n\tpublic getPositionAt(offset: number): Position {\n\t\toffset = Math.floor(offset);\n\t\toffset = Math.max(0, offset);\n\n\t\tlet x = this.root;\n\t\tlet lfCnt = 0;\n\t\tconst originalOffset = offset;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.size_left !== 0 && x.size_left >= offset) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.size_left + x.piece.length >= offset) {\n\t\t\t\tconst out = this.getIndexOf(x, offset - x.size_left);\n\n\t\t\t\tlfCnt += x.lf_left + out.index;\n\n\t\t\t\tif (out.index === 0) {\n\t\t\t\t\tconst lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n\t\t\t\t\tconst column = originalOffset - lineStartOffset;\n\t\t\t\t\treturn new Position(lfCnt + 1, column + 1);\n\t\t\t\t}\n\n\t\t\t\treturn new Position(lfCnt + 1, out.remainder + 1);\n\t\t\t} else {\n\t\t\t\toffset -= x.size_left + x.piece.length;\n\t\t\t\tlfCnt += x.lf_left + x.piece.lineFeedCnt;\n\n\t\t\t\tif (x.right === SENTINEL) {\n\t\t\t\t\t// last node\n\t\t\t\t\tconst lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n\t\t\t\t\tconst column = originalOffset - offset - lineStartOffset;\n\t\t\t\t\treturn new Position(lfCnt + 1, column + 1);\n\t\t\t\t} else {\n\t\t\t\t\tx = x.right;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn new Position(1, 1);\n\t}\n\n\tpublic getValueInRange(range: Range, eol?: string): string {\n\t\tif (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst startPosition = this.nodeAt2(range.startLineNumber, range.startColumn);\n\t\tconst endPosition = this.nodeAt2(range.endLineNumber, range.endColumn);\n\n\t\tconst value = this.getValueInRange2(startPosition, endPosition);\n\t\tif (eol) {\n\t\t\tif (eol !== this._EOL || !this._EOLNormalized) {\n\t\t\t\treturn value.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\t}\n\n\t\t\tif (eol === this.getEOL() && this._EOLNormalized) {\n\t\t\t\tif (eol === '\\r\\n') {\n\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\treturn value.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t}\n\t\treturn value;\n\t}\n\n\tpublic getValueInRange2(startPosition: NodePosition, endPosition: NodePosition): string {\n\t\tif (startPosition.node === endPosition.node) {\n\t\t\tconst node = startPosition.node;\n\t\t\tconst buffer = this._buffers[node.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n\t\t\treturn buffer.substring(startOffset + startPosition.remainder, startOffset + endPosition.remainder);\n\t\t}\n\n\t\tlet x = startPosition.node;\n\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\tlet ret = buffer.substring(startOffset + startPosition.remainder, startOffset + x.piece.length);\n\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\tif (x === endPosition.node) {\n\t\t\t\tret += buffer.substring(startOffset, startOffset + endPosition.remainder);\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tret += buffer.substr(startOffset, x.piece.length);\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tpublic getLinesContent(): string[] {\n\t\tconst lines: string[] = [];\n\t\tlet linesLength = 0;\n\t\tlet currentLine = '';\n\t\tlet danglingCR = false;\n\n\t\tthis.iterate(this.root, node => {\n\t\t\tif (node === SENTINEL) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst piece = node.piece;\n\t\t\tlet pieceLength = piece.length;\n\t\t\tif (pieceLength === 0) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[piece.bufferIndex].buffer;\n\t\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\n\t\t\tconst pieceStartLine = piece.start.line;\n\t\t\tconst pieceEndLine = piece.end.line;\n\t\t\tlet pieceStartOffset = lineStarts[pieceStartLine] + piece.start.column;\n\n\t\t\tif (danglingCR) {\n\t\t\t\tif (buffer.charCodeAt(pieceStartOffset) === CharCode.LineFeed) {\n\t\t\t\t\t// pretend the \\n was in the previous piece..\n\t\t\t\t\tpieceStartOffset++;\n\t\t\t\t\tpieceLength--;\n\t\t\t\t}\n\t\t\t\tlines[linesLength++] = currentLine;\n\t\t\t\tcurrentLine = '';\n\t\t\t\tdanglingCR = false;\n\t\t\t\tif (pieceLength === 0) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pieceStartLine === pieceEndLine) {\n\t\t\t\t// this piece has no new lines\n\t\t\t\tif (!this._EOLNormalized && buffer.charCodeAt(pieceStartOffset + pieceLength - 1) === CharCode.CarriageReturn) {\n\t\t\t\t\tdanglingCR = true;\n\t\t\t\t\tcurrentLine += buffer.substr(pieceStartOffset, pieceLength - 1);\n\t\t\t\t} else {\n\t\t\t\t\tcurrentLine += buffer.substr(pieceStartOffset, pieceLength);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// add the text before the first line start in this piece\n\t\t\tcurrentLine += (\n\t\t\t\tthis._EOLNormalized\n\t\t\t\t\t? buffer.substring(pieceStartOffset, Math.max(pieceStartOffset, lineStarts[pieceStartLine + 1] - this._EOLLength))\n\t\t\t\t\t: buffer.substring(pieceStartOffset, lineStarts[pieceStartLine + 1]).replace(/(\\r\\n|\\r|\\n)$/, '')\n\t\t\t);\n\t\t\tlines[linesLength++] = currentLine;\n\n\t\t\tfor (let line = pieceStartLine + 1; line < pieceEndLine; line++) {\n\t\t\t\tcurrentLine = (\n\t\t\t\t\tthis._EOLNormalized\n\t\t\t\t\t\t? buffer.substring(lineStarts[line], lineStarts[line + 1] - this._EOLLength)\n\t\t\t\t\t\t: buffer.substring(lineStarts[line], lineStarts[line + 1]).replace(/(\\r\\n|\\r|\\n)$/, '')\n\t\t\t\t);\n\t\t\t\tlines[linesLength++] = currentLine;\n\t\t\t}\n\n\t\t\tif (!this._EOLNormalized && buffer.charCodeAt(lineStarts[pieceEndLine] + piece.end.column - 1) === CharCode.CarriageReturn) {\n\t\t\t\tdanglingCR = true;\n\t\t\t\tif (piece.end.column === 0) {\n\t\t\t\t\t// The last line ended with a \\r, let's undo the push, it will be pushed by next iteration\n\t\t\t\t\tlinesLength--;\n\t\t\t\t} else {\n\t\t\t\t\tcurrentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column - 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcurrentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t});\n\n\t\tif (danglingCR) {\n\t\t\tlines[linesLength++] = currentLine;\n\t\t\tcurrentLine = '';\n\t\t}\n\n\t\tlines[linesLength++] = currentLine;\n\t\treturn lines;\n\t}\n\n\tpublic getLength(): number {\n\t\treturn this._length;\n\t}\n\n\tpublic getLineCount(): number {\n\t\treturn this._lineCnt;\n\t}\n\n\tpublic getLineContent(lineNumber: number): string {\n\t\tif (this._lastVisitedLine.lineNumber === lineNumber) {\n\t\t\treturn this._lastVisitedLine.value;\n\t\t}\n\n\t\tthis._lastVisitedLine.lineNumber = lineNumber;\n\n\t\tif (lineNumber === this._lineCnt) {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber);\n\t\t} else if (this._EOLNormalized) {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber, this._EOLLength);\n\t\t} else {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber).replace(/(\\r\\n|\\r|\\n)$/, '');\n\t\t}\n\n\t\treturn this._lastVisitedLine.value;\n\t}\n\n\tprivate _getCharCode(nodePos: NodePosition): number {\n\t\tif (nodePos.remainder === nodePos.node.piece.length) {\n\t\t\t// the char we want to fetch is at the head of next node.\n\t\t\tconst matchingNode = nodePos.node.next();\n\t\t\tif (!matchingNode) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[matchingNode.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);\n\t\t\treturn buffer.buffer.charCodeAt(startOffset);\n\t\t} else {\n\t\t\tconst buffer = this._buffers[nodePos.node.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);\n\t\t\tconst targetOffset = startOffset + nodePos.remainder;\n\n\t\t\treturn buffer.buffer.charCodeAt(targetOffset);\n\t\t}\n\t}\n\n\tpublic getLineCharCode(lineNumber: number, index: number): number {\n\t\tconst nodePos = this.nodeAt2(lineNumber, index + 1);\n\t\treturn this._getCharCode(nodePos);\n\t}\n\n\tpublic getLineLength(lineNumber: number): number {\n\t\tif (lineNumber === this.getLineCount()) {\n\t\t\tconst startOffset = this.getOffsetAt(lineNumber, 1);\n\t\t\treturn this.getLength() - startOffset;\n\t\t}\n\t\treturn this.getOffsetAt(lineNumber + 1, 1) - this.getOffsetAt(lineNumber, 1) - this._EOLLength;\n\t}\n\n\tpublic findMatchesInNode(node: TreeNode, searcher: Searcher, startLineNumber: number, startColumn: number, startCursor: BufferCursor, endCursor: BufferCursor, searchData: SearchData, captureMatches: boolean, limitResultCount: number, resultLen: number, result: FindMatch[]) {\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst startOffsetInBuffer = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n\t\tconst start = this.offsetInBuffer(node.piece.bufferIndex, startCursor);\n\t\tconst end = this.offsetInBuffer(node.piece.bufferIndex, endCursor);\n\n\t\tlet m: RegExpExecArray | null;\n\t\t// Reset regex to search from the beginning\n\t\tconst ret: BufferCursor = { line: 0, column: 0 };\n\t\tlet searchText: string;\n\t\tlet offsetInBuffer: (offset: number) => number;\n\n\t\tif (searcher._wordSeparators) {\n\t\t\tsearchText = buffer.buffer.substring(start, end);\n\t\t\toffsetInBuffer = (offset: number) => offset + start;\n\t\t\tsearcher.reset(0);\n\t\t} else {\n\t\t\tsearchText = buffer.buffer;\n\t\t\toffsetInBuffer = (offset: number) => offset;\n\t\t\tsearcher.reset(start);\n\t\t}\n\n\t\tdo {\n\t\t\tm = searcher.next(searchText);\n\n\t\t\tif (m) {\n\t\t\t\tif (offsetInBuffer(m.index) >= end) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t\tthis.positionInBuffer(node, offsetInBuffer(m.index) - startOffsetInBuffer, ret);\n\t\t\t\tconst lineFeedCnt = this.getLineFeedCnt(node.piece.bufferIndex, startCursor, ret);\n\t\t\t\tconst retStartColumn = ret.line === startCursor.line ? ret.column - startCursor.column + startColumn : ret.column + 1;\n\t\t\t\tconst retEndColumn = retStartColumn + m[0].length;\n\t\t\t\tresult[resultLen++] = createFindMatch(new Range(startLineNumber + lineFeedCnt, retStartColumn, startLineNumber + lineFeedCnt, retEndColumn), m, captureMatches);\n\n\t\t\t\tif (offsetInBuffer(m.index) + m[0].length >= end) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} while (m);\n\n\t\treturn resultLen;\n\t}\n\n\tpublic findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[] {\n\t\tconst result: FindMatch[] = [];\n\t\tlet resultLen = 0;\n\t\tconst searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n\n\t\tlet startPosition = this.nodeAt2(searchRange.startLineNumber, searchRange.startColumn);\n\t\tif (startPosition === null) {\n\t\t\treturn [];\n\t\t}\n\t\tconst endPosition = this.nodeAt2(searchRange.endLineNumber, searchRange.endColumn);\n\t\tif (endPosition === null) {\n\t\t\treturn [];\n\t\t}\n\t\tlet start = this.positionInBuffer(startPosition.node, startPosition.remainder);\n\t\tconst end = this.positionInBuffer(endPosition.node, endPosition.remainder);\n\n\t\tif (startPosition.node === endPosition.node) {\n\t\t\tthis.findMatchesInNode(startPosition.node, searcher, searchRange.startLineNumber, searchRange.startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n\t\t\treturn result;\n\t\t}\n\n\t\tlet startLineNumber = searchRange.startLineNumber;\n\n\t\tlet currentNode = startPosition.node;\n\t\twhile (currentNode !== endPosition.node) {\n\t\t\tconst lineBreakCnt = this.getLineFeedCnt(currentNode.piece.bufferIndex, start, currentNode.piece.end);\n\n\t\t\tif (lineBreakCnt >= 1) {\n\t\t\t\t// last line break position\n\t\t\t\tconst lineStarts = this._buffers[currentNode.piece.bufferIndex].lineStarts;\n\t\t\t\tconst startOffsetInBuffer = this.offsetInBuffer(currentNode.piece.bufferIndex, currentNode.piece.start);\n\t\t\t\tconst nextLineStartOffset = lineStarts[start.line + lineBreakCnt];\n\t\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n\t\t\t\tresultLen = this.findMatchesInNode(currentNode, searcher, startLineNumber, startColumn, start, this.positionInBuffer(currentNode, nextLineStartOffset - startOffsetInBuffer), searchData, captureMatches, limitResultCount, resultLen, result);\n\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tstartLineNumber += lineBreakCnt;\n\t\t\t}\n\n\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n\t\t\t// search for the remaining content\n\t\t\tif (startLineNumber === searchRange.endLineNumber) {\n\t\t\t\tconst text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n\t\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, this.getLineContent(startLineNumber).substr(startColumn), startLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\n\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tstartLineNumber++;\n\t\t\tstartPosition = this.nodeAt2(startLineNumber, 1);\n\t\t\tcurrentNode = startPosition.node;\n\t\t\tstart = this.positionInBuffer(startPosition.node, startPosition.remainder);\n\t\t}\n\n\t\tif (startLineNumber === searchRange.endLineNumber) {\n\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n\t\t\tconst text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\t\t\treturn result;\n\t\t}\n\n\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n\t\tresultLen = this.findMatchesInNode(endPosition.node, searcher, startLineNumber, startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n\t\treturn result;\n\t}\n\n\tprivate _findMatchesInLine(searchData: SearchData, searcher: Searcher, text: string, lineNumber: number, deltaOffset: number, resultLen: number, result: FindMatch[], captureMatches: boolean, limitResultCount: number): number {\n\t\tconst wordSeparators = searchData.wordSeparators;\n\t\tif (!captureMatches && searchData.simpleSearch) {\n\t\t\tconst searchString = searchData.simpleSearch;\n\t\t\tconst searchStringLen = searchString.length;\n\t\t\tconst textLength = text.length;\n\n\t\t\tlet lastMatchIndex = -searchStringLen;\n\t\t\twhile ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {\n\t\t\t\tif (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {\n\t\t\t\t\tresult[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);\n\t\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\t\treturn resultLen;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn resultLen;\n\t\t}\n\n\t\tlet m: RegExpExecArray | null;\n\t\t// Reset regex to search from the beginning\n\t\tsearcher.reset(0);\n\t\tdo {\n\t\t\tm = searcher.next(text);\n\t\t\tif (m) {\n\t\t\t\tresult[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (m);\n\t\treturn resultLen;\n\t}\n\n\t// #endregion\n\n\t// #region Piece Table\n\tpublic insert(offset: number, value: string, eolNormalized: boolean = false): void {\n\t\tthis._EOLNormalized = this._EOLNormalized && eolNormalized;\n\t\tthis._lastVisitedLine.lineNumber = 0;\n\t\tthis._lastVisitedLine.value = '';\n\n\t\tif (this.root !== SENTINEL) {\n\t\t\tconst { node, remainder, nodeStartOffset } = this.nodeAt(offset);\n\t\t\tconst piece = node.piece;\n\t\t\tconst bufferIndex = piece.bufferIndex;\n\t\t\tconst insertPosInBuffer = this.positionInBuffer(node, remainder);\n\t\t\tif (node.piece.bufferIndex === 0 &&\n\t\t\t\tpiece.end.line === this._lastChangeBufferPos.line &&\n\t\t\t\tpiece.end.column === this._lastChangeBufferPos.column &&\n\t\t\t\t(nodeStartOffset + piece.length === offset) &&\n\t\t\t\tvalue.length < AverageBufferSize\n\t\t\t) {\n\t\t\t\t// changed buffer\n\t\t\t\tthis.appendToNode(node, value);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (nodeStartOffset === offset) {\n\t\t\t\tthis.insertContentToNodeLeft(value, node);\n\t\t\t\tthis._searchCache.validate(offset);\n\t\t\t} else if (nodeStartOffset + node.piece.length > offset) {\n\t\t\t\t// we are inserting into the middle of a node.\n\t\t\t\tconst nodesToDel: TreeNode[] = [];\n\t\t\t\tlet newRightPiece = new Piece(\n\t\t\t\t\tpiece.bufferIndex,\n\t\t\t\t\tinsertPosInBuffer,\n\t\t\t\t\tpiece.end,\n\t\t\t\t\tthis.getLineFeedCnt(piece.bufferIndex, insertPosInBuffer, piece.end),\n\t\t\t\t\tthis.offsetInBuffer(bufferIndex, piece.end) - this.offsetInBuffer(bufferIndex, insertPosInBuffer)\n\t\t\t\t);\n\n\t\t\t\tif (this.shouldCheckCRLF() && this.endWithCR(value)) {\n\t\t\t\t\tconst headOfRight = this.nodeCharCodeAt(node, remainder);\n\n\t\t\t\t\tif (headOfRight === 10 /** \\n */) {\n\t\t\t\t\t\tconst newStart: BufferCursor = { line: newRightPiece.start.line + 1, column: 0 };\n\t\t\t\t\t\tnewRightPiece = new Piece(\n\t\t\t\t\t\t\tnewRightPiece.bufferIndex,\n\t\t\t\t\t\t\tnewStart,\n\t\t\t\t\t\t\tnewRightPiece.end,\n\t\t\t\t\t\t\tthis.getLineFeedCnt(newRightPiece.bufferIndex, newStart, newRightPiece.end),\n\t\t\t\t\t\t\tnewRightPiece.length - 1\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tvalue += '\\n';\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// reuse node for content before insertion point.\n\t\t\t\tif (this.shouldCheckCRLF() && this.startWithLF(value)) {\n\t\t\t\t\tconst tailOfLeft = this.nodeCharCodeAt(node, remainder - 1);\n\t\t\t\t\tif (tailOfLeft === 13 /** \\r */) {\n\t\t\t\t\t\tconst previousPos = this.positionInBuffer(node, remainder - 1);\n\t\t\t\t\t\tthis.deleteNodeTail(node, previousPos);\n\t\t\t\t\t\tvalue = '\\r' + value;\n\n\t\t\t\t\t\tif (node.piece.length === 0) {\n\t\t\t\t\t\t\tnodesToDel.push(node);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.deleteNodeTail(node, insertPosInBuffer);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.deleteNodeTail(node, insertPosInBuffer);\n\t\t\t\t}\n\n\t\t\t\tconst newPieces = this.createNewPieces(value);\n\t\t\t\tif (newRightPiece.length > 0) {\n\t\t\t\t\tthis.rbInsertRight(node, newRightPiece);\n\t\t\t\t}\n\n\t\t\t\tlet tmpNode = node;\n\t\t\t\tfor (let k = 0; k < newPieces.length; k++) {\n\t\t\t\t\ttmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n\t\t\t\t}\n\t\t\t\tthis.deleteNodes(nodesToDel);\n\t\t\t} else {\n\t\t\t\tthis.insertContentToNodeRight(value, node);\n\t\t\t}\n\t\t} else {\n\t\t\t// insert new node\n\t\t\tconst pieces = this.createNewPieces(value);\n\t\t\tlet node = this.rbInsertLeft(null, pieces[0]);\n\n\t\t\tfor (let k = 1; k < pieces.length; k++) {\n\t\t\t\tnode = this.rbInsertRight(node, pieces[k]);\n\t\t\t}\n\t\t}\n\n\t\t// todo, this is too brutal. Total line feed count should be updated the same way as lf_left.\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tpublic delete(offset: number, cnt: number): void {\n\t\tthis._lastVisitedLine.lineNumber = 0;\n\t\tthis._lastVisitedLine.value = '';\n\n\t\tif (cnt <= 0 || this.root === SENTINEL) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst startPosition = this.nodeAt(offset);\n\t\tconst endPosition = this.nodeAt(offset + cnt);\n\t\tconst startNode = startPosition.node;\n\t\tconst endNode = endPosition.node;\n\n\t\tif (startNode === endNode) {\n\t\t\tconst startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n\t\t\tconst endSplitPosInBuffer = this.positionInBuffer(startNode, endPosition.remainder);\n\n\t\t\tif (startPosition.nodeStartOffset === offset) {\n\t\t\t\tif (cnt === startNode.piece.length) { // delete node\n\t\t\t\t\tconst next = startNode.next();\n\t\t\t\t\trbDelete(this, startNode);\n\t\t\t\t\tthis.validateCRLFWithPrevNode(next);\n\t\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.deleteNodeHead(startNode, endSplitPosInBuffer);\n\t\t\t\tthis._searchCache.validate(offset);\n\t\t\t\tthis.validateCRLFWithPrevNode(startNode);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (startPosition.nodeStartOffset + startNode.piece.length === offset + cnt) {\n\t\t\t\tthis.deleteNodeTail(startNode, startSplitPosInBuffer);\n\t\t\t\tthis.validateCRLFWithNextNode(startNode);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// delete content in the middle, this node will be splitted to nodes\n\t\t\tthis.shrinkNode(startNode, startSplitPosInBuffer, endSplitPosInBuffer);\n\t\t\tthis.computeBufferMetadata();\n\t\t\treturn;\n\t\t}\n\n\t\tconst nodesToDel: TreeNode[] = [];\n\n\t\tconst startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n\t\tthis.deleteNodeTail(startNode, startSplitPosInBuffer);\n\t\tthis._searchCache.validate(offset);\n\t\tif (startNode.piece.length === 0) {\n\t\t\tnodesToDel.push(startNode);\n\t\t}\n\n\t\t// update last touched node\n\t\tconst endSplitPosInBuffer = this.positionInBuffer(endNode, endPosition.remainder);\n\t\tthis.deleteNodeHead(endNode, endSplitPosInBuffer);\n\t\tif (endNode.piece.length === 0) {\n\t\t\tnodesToDel.push(endNode);\n\t\t}\n\n\t\t// delete nodes in between\n\t\tconst secondNode = startNode.next();\n\t\tfor (let node = secondNode; node !== SENTINEL && node !== endNode; node = node.next()) {\n\t\t\tnodesToDel.push(node);\n\t\t}\n\n\t\tconst prev = startNode.piece.length === 0 ? startNode.prev() : startNode;\n\t\tthis.deleteNodes(nodesToDel);\n\t\tthis.validateCRLFWithNextNode(prev);\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tprivate insertContentToNodeLeft(value: string, node: TreeNode) {\n\t\t// we are inserting content to the beginning of node\n\t\tconst nodesToDel: TreeNode[] = [];\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(value) && this.startWithLF(node)) {\n\t\t\t// move `\\n` to new node.\n\n\t\t\tconst piece = node.piece;\n\t\t\tconst newStart: BufferCursor = { line: piece.start.line + 1, column: 0 };\n\t\t\tconst nPiece = new Piece(\n\t\t\t\tpiece.bufferIndex,\n\t\t\t\tnewStart,\n\t\t\t\tpiece.end,\n\t\t\t\tthis.getLineFeedCnt(piece.bufferIndex, newStart, piece.end),\n\t\t\t\tpiece.length - 1\n\t\t\t);\n\n\t\t\tnode.piece = nPiece;\n\n\t\t\tvalue += '\\n';\n\t\t\tupdateTreeMetadata(this, node, -1, -1);\n\n\t\t\tif (node.piece.length === 0) {\n\t\t\t\tnodesToDel.push(node);\n\t\t\t}\n\t\t}\n\n\t\tconst newPieces = this.createNewPieces(value);\n\t\tlet newNode = this.rbInsertLeft(node, newPieces[newPieces.length - 1]);\n\t\tfor (let k = newPieces.length - 2; k >= 0; k--) {\n\t\t\tnewNode = this.rbInsertLeft(newNode, newPieces[k]);\n\t\t}\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t\tthis.deleteNodes(nodesToDel);\n\t}\n\n\tprivate insertContentToNodeRight(value: string, node: TreeNode) {\n\t\t// we are inserting to the right of this node.\n\t\tif (this.adjustCarriageReturnFromNext(value, node)) {\n\t\t\t// move \\n to the new node.\n\t\t\tvalue += '\\n';\n\t\t}\n\n\t\tconst newPieces = this.createNewPieces(value);\n\t\tconst newNode = this.rbInsertRight(node, newPieces[0]);\n\t\tlet tmpNode = newNode;\n\n\t\tfor (let k = 1; k < newPieces.length; k++) {\n\t\t\ttmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n\t\t}\n\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t}\n\n\tprivate positionInBuffer(node: TreeNode, remainder: number): BufferCursor;\n\tprivate positionInBuffer(node: TreeNode, remainder: number, ret: BufferCursor): null;\n\tprivate positionInBuffer(node: TreeNode, remainder: number, ret?: BufferCursor): BufferCursor | null {\n\t\tconst piece = node.piece;\n\t\tconst bufferIndex = node.piece.bufferIndex;\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\n\t\tconst startOffset = lineStarts[piece.start.line] + piece.start.column;\n\n\t\tconst offset = startOffset + remainder;\n\n\t\t// binary search offset between startOffset and endOffset\n\t\tlet low = piece.start.line;\n\t\tlet high = piece.end.line;\n\n\t\tlet mid: number = 0;\n\t\tlet midStop: number = 0;\n\t\tlet midStart: number = 0;\n\n\t\twhile (low <= high) {\n\t\t\tmid = low + ((high - low) / 2) | 0;\n\t\t\tmidStart = lineStarts[mid];\n\n\t\t\tif (mid === high) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tmidStop = lineStarts[mid + 1];\n\n\t\t\tif (offset < midStart) {\n\t\t\t\thigh = mid - 1;\n\t\t\t} else if (offset >= midStop) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (ret) {\n\t\t\tret.line = mid;\n\t\t\tret.column = offset - midStart;\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\tline: mid,\n\t\t\tcolumn: offset - midStart\n\t\t};\n\t}\n\n\tprivate getLineFeedCnt(bufferIndex: number, start: BufferCursor, end: BufferCursor): number {\n\t\t// 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.\n\t\t// 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\n\t\tif (end.column === 0) {\n\t\t\treturn end.line - start.line;\n\t\t}\n\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\t\tif (end.line === lineStarts.length - 1) { // it means, there is no \\n after end, otherwise, there will be one more lineStart.\n\t\t\treturn end.line - start.line;\n\t\t}\n\n\t\tconst nextLineStartOffset = lineStarts[end.line + 1];\n\t\tconst endOffset = lineStarts[end.line] + end.column;\n\t\tif (nextLineStartOffset > endOffset + 1) { // there are more than 1 character after end, which means it can't be \\n\n\t\t\treturn end.line - start.line;\n\t\t}\n\t\t// endOffset + 1 === nextLineStartOffset\n\t\t// character at endOffset is \\n, so we check the character before first\n\t\t// if character at endOffset is \\r, end.column is 0 and we can't get here.\n\t\tconst previousCharOffset = endOffset - 1; // end.column > 0 so it's okay.\n\t\tconst buffer = this._buffers[bufferIndex].buffer;\n\n\t\tif (buffer.charCodeAt(previousCharOffset) === 13) {\n\t\t\treturn end.line - start.line + 1;\n\t\t} else {\n\t\t\treturn end.line - start.line;\n\t\t}\n\t}\n\n\tprivate offsetInBuffer(bufferIndex: number, cursor: BufferCursor): number {\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\t\treturn lineStarts[cursor.line] + cursor.column;\n\t}\n\n\tprivate deleteNodes(nodes: TreeNode[]): void {\n\t\tfor (let i = 0; i < nodes.length; i++) {\n\t\t\trbDelete(this, nodes[i]);\n\t\t}\n\t}\n\n\tprivate createNewPieces(text: string): Piece[] {\n\t\tif (text.length > AverageBufferSize) {\n\t\t\t// the content is large, operations like substring, charCode becomes slow\n\t\t\t// so here we split it into smaller chunks, just like what we did for CR/LF normalization\n\t\t\tconst newPieces: Piece[] = [];\n\t\t\twhile (text.length > AverageBufferSize) {\n\t\t\t\tconst lastChar = text.charCodeAt(AverageBufferSize - 1);\n\t\t\t\tlet splitText;\n\t\t\t\tif (lastChar === CharCode.CarriageReturn || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {\n\t\t\t\t\t// last character is \\r or a high surrogate => keep it back\n\t\t\t\t\tsplitText = text.substring(0, AverageBufferSize - 1);\n\t\t\t\t\ttext = text.substring(AverageBufferSize - 1);\n\t\t\t\t} else {\n\t\t\t\t\tsplitText = text.substring(0, AverageBufferSize);\n\t\t\t\t\ttext = text.substring(AverageBufferSize);\n\t\t\t\t}\n\n\t\t\t\tconst lineStarts = createLineStartsFast(splitText);\n\t\t\t\tnewPieces.push(new Piece(\n\t\t\t\t\tthis._buffers.length, /* buffer index */\n\t\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t\t{ line: lineStarts.length - 1, column: splitText.length - lineStarts[lineStarts.length - 1] },\n\t\t\t\t\tlineStarts.length - 1,\n\t\t\t\t\tsplitText.length\n\t\t\t\t));\n\t\t\t\tthis._buffers.push(new StringBuffer(splitText, lineStarts));\n\t\t\t}\n\n\t\t\tconst lineStarts = createLineStartsFast(text);\n\t\t\tnewPieces.push(new Piece(\n\t\t\t\tthis._buffers.length, /* buffer index */\n\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t{ line: lineStarts.length - 1, column: text.length - lineStarts[lineStarts.length - 1] },\n\t\t\t\tlineStarts.length - 1,\n\t\t\t\ttext.length\n\t\t\t));\n\t\t\tthis._buffers.push(new StringBuffer(text, lineStarts));\n\n\t\t\treturn newPieces;\n\t\t}\n\n\t\tlet startOffset = this._buffers[0].buffer.length;\n\t\tconst lineStarts = createLineStartsFast(text, false);\n\n\t\tlet start = this._lastChangeBufferPos;\n\t\tif (this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 1] === startOffset\n\t\t\t&& startOffset !== 0\n\t\t\t&& this.startWithLF(text)\n\t\t\t&& this.endWithCR(this._buffers[0].buffer) // todo, we can check this._lastChangeBufferPos's column as it's the last one\n\t\t) {\n\t\t\tthis._lastChangeBufferPos = { line: this._lastChangeBufferPos.line, column: this._lastChangeBufferPos.column + 1 };\n\t\t\tstart = this._lastChangeBufferPos;\n\n\t\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\t\tlineStarts[i] += startOffset + 1;\n\t\t\t}\n\n\t\t\tthis._buffers[0].lineStarts = (this._buffers[0].lineStarts).concat(lineStarts.slice(1));\n\t\t\tthis._buffers[0].buffer += '_' + text;\n\t\t\tstartOffset += 1;\n\t\t} else {\n\t\t\tif (startOffset !== 0) {\n\t\t\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\t\t\tlineStarts[i] += startOffset;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._buffers[0].lineStarts = (this._buffers[0].lineStarts).concat(lineStarts.slice(1));\n\t\t\tthis._buffers[0].buffer += text;\n\t\t}\n\n\t\tconst endOffset = this._buffers[0].buffer.length;\n\t\tconst endIndex = this._buffers[0].lineStarts.length - 1;\n\t\tconst endColumn = endOffset - this._buffers[0].lineStarts[endIndex];\n\t\tconst endPos = { line: endIndex, column: endColumn };\n\t\tconst newPiece = new Piece(\n\t\t\t0, /** todo@peng */\n\t\t\tstart,\n\t\t\tendPos,\n\t\t\tthis.getLineFeedCnt(0, start, endPos),\n\t\t\tendOffset - startOffset\n\t\t);\n\t\tthis._lastChangeBufferPos = endPos;\n\t\treturn [newPiece];\n\t}\n\n\tpublic getLineRawContent(lineNumber: number, endOffset: number = 0): string {\n\t\tlet x = this.root;\n\n\t\tlet ret = '';\n\t\tconst cache = this._searchCache.get2(lineNumber);\n\t\tif (cache) {\n\t\t\tx = cache.node;\n\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber - 1);\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\tif (cache.nodeStartLineNumber + x.piece.lineFeedCnt === lineNumber) {\n\t\t\t\tret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n\t\t\t} else {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber);\n\t\t\t\treturn buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n\t\t\t}\n\t\t} else {\n\t\t\tlet nodeStartOffset = 0;\n\t\t\tconst originalLineNumber = lineNumber;\n\t\t\twhile (x !== SENTINEL) {\n\t\t\t\tif (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n\t\t\t\t\tx = x.left;\n\t\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n\t\t\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n\t\t\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\t\t\tnodeStartOffset += x.size_left;\n\t\t\t\t\tthis._searchCache.set({\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tnodeStartOffset,\n\t\t\t\t\t\tnodeStartLineNumber: originalLineNumber - (lineNumber - 1 - x.lf_left)\n\t\t\t\t\t});\n\n\t\t\t\t\treturn buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n\t\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n\t\t\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\t\t\tret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\t\tx = x.right;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// search in order, to find the node contains end column\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\n\t\t\tif (x.piece.lineFeedCnt > 0) {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, 0);\n\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\t\tret += buffer.substring(startOffset, startOffset + accumulatedValue - endOffset);\n\t\t\t\treturn ret;\n\t\t\t} else {\n\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\t\tret += buffer.substr(startOffset, x.piece.length);\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tprivate computeBufferMetadata() {\n\t\tlet x = this.root;\n\n\t\tlet lfCnt = 1;\n\t\tlet len = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tlfCnt += x.lf_left + x.piece.lineFeedCnt;\n\t\t\tlen += x.size_left + x.piece.length;\n\t\t\tx = x.right;\n\t\t}\n\n\t\tthis._lineCnt = lfCnt;\n\t\tthis._length = len;\n\t\tthis._searchCache.validate(this._length);\n\t}\n\n\t// #region node operations\n\tprivate getIndexOf(node: TreeNode, accumulatedValue: number): { index: number, remainder: number } {\n\t\tconst piece = node.piece;\n\t\tconst pos = this.positionInBuffer(node, accumulatedValue);\n\t\tconst lineCnt = pos.line - piece.start.line;\n\n\t\tif (this.offsetInBuffer(piece.bufferIndex, piece.end) - this.offsetInBuffer(piece.bufferIndex, piece.start) === accumulatedValue) {\n\t\t\t// we are checking the end of this node, so a CRLF check is necessary.\n\t\t\tconst realLineCnt = this.getLineFeedCnt(node.piece.bufferIndex, piece.start, pos);\n\t\t\tif (realLineCnt !== lineCnt) {\n\t\t\t\t// aha yes, CRLF\n\t\t\t\treturn { index: realLineCnt, remainder: 0 };\n\t\t\t}\n\t\t}\n\n\t\treturn { index: lineCnt, remainder: pos.column };\n\t}\n\n\tprivate getAccumulatedValue(node: TreeNode, index: number) {\n\t\tif (index < 0) {\n\t\t\treturn 0;\n\t\t}\n\t\tconst piece = node.piece;\n\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\t\tconst expectedLineStartIndex = piece.start.line + index + 1;\n\t\tif (expectedLineStartIndex > piece.end.line) {\n\t\t\treturn lineStarts[piece.end.line] + piece.end.column - lineStarts[piece.start.line] - piece.start.column;\n\t\t} else {\n\t\t\treturn lineStarts[expectedLineStartIndex] - lineStarts[piece.start.line] - piece.start.column;\n\t\t}\n\t}\n\n\tprivate deleteNodeTail(node: TreeNode, pos: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalLFCnt = piece.lineFeedCnt;\n\t\tconst originalEndOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\n\t\tconst newEnd = pos;\n\t\tconst newEndOffset = this.offsetInBuffer(piece.bufferIndex, newEnd);\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n\n\t\tconst lf_delta = newLineFeedCnt - originalLFCnt;\n\t\tconst size_delta = newEndOffset - originalEndOffset;\n\t\tconst newLength = piece.length + size_delta;\n\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tpiece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, size_delta, lf_delta);\n\t}\n\n\tprivate deleteNodeHead(node: TreeNode, pos: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalLFCnt = piece.lineFeedCnt;\n\t\tconst originalStartOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\n\t\tconst newStart = pos;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n\t\tconst newStartOffset = this.offsetInBuffer(piece.bufferIndex, newStart);\n\t\tconst lf_delta = newLineFeedCnt - originalLFCnt;\n\t\tconst size_delta = originalStartOffset - newStartOffset;\n\t\tconst newLength = piece.length + size_delta;\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tnewStart,\n\t\t\tpiece.end,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, size_delta, lf_delta);\n\t}\n\n\tprivate shrinkNode(node: TreeNode, start: BufferCursor, end: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalStartPos = piece.start;\n\t\tconst originalEndPos = piece.end;\n\n\t\t// old piece, originalStartPos, start\n\t\tconst oldLength = piece.length;\n\t\tconst oldLFCnt = piece.lineFeedCnt;\n\t\tconst newEnd = start;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n\t\tconst newLength = this.offsetInBuffer(piece.bufferIndex, start) - this.offsetInBuffer(piece.bufferIndex, originalStartPos);\n\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tpiece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, newLength - oldLength, newLineFeedCnt - oldLFCnt);\n\n\t\t// new right piece, end, originalEndPos\n\t\tconst newPiece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tend,\n\t\t\toriginalEndPos,\n\t\t\tthis.getLineFeedCnt(piece.bufferIndex, end, originalEndPos),\n\t\t\tthis.offsetInBuffer(piece.bufferIndex, originalEndPos) - this.offsetInBuffer(piece.bufferIndex, end)\n\t\t);\n\n\t\tconst newNode = this.rbInsertRight(node, newPiece);\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t}\n\n\tprivate appendToNode(node: TreeNode, value: string): void {\n\t\tif (this.adjustCarriageReturnFromNext(value, node)) {\n\t\t\tvalue += '\\n';\n\t\t}\n\n\t\tconst hitCRLF = this.shouldCheckCRLF() && this.startWithLF(value) && this.endWithCR(node);\n\t\tconst startOffset = this._buffers[0].buffer.length;\n\t\tthis._buffers[0].buffer += value;\n\t\tconst lineStarts = createLineStartsFast(value, false);\n\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\tlineStarts[i] += startOffset;\n\t\t}\n\t\tif (hitCRLF) {\n\t\t\tconst prevStartOffset = this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 2];\n\t\t\t(this._buffers[0].lineStarts).pop();\n\t\t\t// _lastChangeBufferPos is already wrong\n\t\t\tthis._lastChangeBufferPos = { line: this._lastChangeBufferPos.line - 1, column: startOffset - prevStartOffset };\n\t\t}\n\n\t\tthis._buffers[0].lineStarts = (this._buffers[0].lineStarts).concat(lineStarts.slice(1));\n\t\tconst endIndex = this._buffers[0].lineStarts.length - 1;\n\t\tconst endColumn = this._buffers[0].buffer.length - this._buffers[0].lineStarts[endIndex];\n\t\tconst newEnd = { line: endIndex, column: endColumn };\n\t\tconst newLength = node.piece.length + value.length;\n\t\tconst oldLineFeedCnt = node.piece.lineFeedCnt;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(0, node.piece.start, newEnd);\n\t\tconst lf_delta = newLineFeedCnt - oldLineFeedCnt;\n\n\t\tnode.piece = new Piece(\n\t\t\tnode.piece.bufferIndex,\n\t\t\tnode.piece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tthis._lastChangeBufferPos = newEnd;\n\t\tupdateTreeMetadata(this, node, value.length, lf_delta);\n\t}\n\n\tprivate nodeAt(offset: number): NodePosition {\n\t\tlet x = this.root;\n\t\tconst cache = this._searchCache.get(offset);\n\t\tif (cache) {\n\t\t\treturn {\n\t\t\t\tnode: cache.node,\n\t\t\t\tnodeStartOffset: cache.nodeStartOffset,\n\t\t\t\tremainder: offset - cache.nodeStartOffset\n\t\t\t};\n\t\t}\n\n\t\tlet nodeStartOffset = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.size_left > offset) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.size_left + x.piece.length >= offset) {\n\t\t\t\tnodeStartOffset += x.size_left;\n\t\t\t\tconst ret = {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: offset - x.size_left,\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t\tthis._searchCache.set(ret);\n\t\t\t\treturn ret;\n\t\t\t} else {\n\t\t\t\toffset -= x.size_left + x.piece.length;\n\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\treturn null!;\n\t}\n\n\tprivate nodeAt2(lineNumber: number, column: number): NodePosition {\n\t\tlet x = this.root;\n\t\tlet nodeStartOffset = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n\t\t\t\tconst prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n\t\t\t\tnodeStartOffset += x.size_left;\n\n\t\t\t\treturn {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: Math.min(prevAccumualtedValue + column - 1, accumulatedValue),\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n\t\t\t\tconst prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\tif (prevAccumualtedValue + column - 1 <= x.piece.length) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tremainder: prevAccumualtedValue + column - 1,\n\t\t\t\t\t\tnodeStartOffset\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tcolumn -= x.piece.length - prevAccumualtedValue;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\t// search in order, to find the node contains position.column\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\n\t\t\tif (x.piece.lineFeedCnt > 0) {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, 0);\n\t\t\t\tconst nodeStartOffset = this.offsetOfNode(x);\n\t\t\t\treturn {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: Math.min(column - 1, accumulatedValue),\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tif (x.piece.length >= column - 1) {\n\t\t\t\t\tconst nodeStartOffset = this.offsetOfNode(x);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tremainder: column - 1,\n\t\t\t\t\t\tnodeStartOffset\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tcolumn -= x.piece.length;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn null!;\n\t}\n\n\tprivate nodeCharCodeAt(node: TreeNode, offset: number): number {\n\t\tif (node.piece.lineFeedCnt < 1) {\n\t\t\treturn -1;\n\t\t}\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst newOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start) + offset;\n\t\treturn buffer.buffer.charCodeAt(newOffset);\n\t}\n\n\tprivate offsetOfNode(node: TreeNode): number {\n\t\tif (!node) {\n\t\t\treturn 0;\n\t\t}\n\t\tlet pos = node.size_left;\n\t\twhile (node !== this.root) {\n\t\t\tif (node.parent.right === node) {\n\t\t\t\tpos += node.parent.size_left + node.parent.piece.length;\n\t\t\t}\n\n\t\t\tnode = node.parent;\n\t\t}\n\n\t\treturn pos;\n\t}\n\n\t// #endregion\n\n\t// #region CRLF\n\tprivate shouldCheckCRLF() {\n\t\treturn !(this._EOLNormalized && this._EOL === '\\n');\n\t}\n\n\tprivate startWithLF(val: string | TreeNode): boolean {\n\t\tif (typeof val === 'string') {\n\t\t\treturn val.charCodeAt(0) === 10;\n\t\t}\n\n\t\tif (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst piece = val.piece;\n\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\t\tconst line = piece.start.line;\n\t\tconst startOffset = lineStarts[line] + piece.start.column;\n\t\tif (line === lineStarts.length - 1) {\n\t\t\t// last line, so there is no line feed at the end of this line\n\t\t\treturn false;\n\t\t}\n\t\tconst nextLineOffset = lineStarts[line + 1];\n\t\tif (nextLineOffset > startOffset + 1) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this._buffers[piece.bufferIndex].buffer.charCodeAt(startOffset) === 10;\n\t}\n\n\tprivate endWithCR(val: string | TreeNode): boolean {\n\t\tif (typeof val === 'string') {\n\t\t\treturn val.charCodeAt(val.length - 1) === 13;\n\t\t}\n\n\t\tif (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.nodeCharCodeAt(val, val.piece.length - 1) === 13;\n\t}\n\n\tprivate validateCRLFWithPrevNode(nextNode: TreeNode) {\n\t\tif (this.shouldCheckCRLF() && this.startWithLF(nextNode)) {\n\t\t\tconst node = nextNode.prev();\n\t\t\tif (this.endWithCR(node)) {\n\t\t\t\tthis.fixCRLF(node, nextNode);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate validateCRLFWithNextNode(node: TreeNode) {\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(node)) {\n\t\t\tconst nextNode = node.next();\n\t\t\tif (this.startWithLF(nextNode)) {\n\t\t\t\tthis.fixCRLF(node, nextNode);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fixCRLF(prev: TreeNode, next: TreeNode) {\n\t\tconst nodesToDel: TreeNode[] = [];\n\t\t// update node\n\t\tconst lineStarts = this._buffers[prev.piece.bufferIndex].lineStarts;\n\t\tlet newEnd: BufferCursor;\n\t\tif (prev.piece.end.column === 0) {\n\t\t\t// it means, last line ends with \\r, not \\r\\n\n\t\t\tnewEnd = { line: prev.piece.end.line - 1, column: lineStarts[prev.piece.end.line] - lineStarts[prev.piece.end.line - 1] - 1 };\n\t\t} else {\n\t\t\t// \\r\\n\n\t\t\tnewEnd = { line: prev.piece.end.line, column: prev.piece.end.column - 1 };\n\t\t}\n\n\t\tconst prevNewLength = prev.piece.length - 1;\n\t\tconst prevNewLFCnt = prev.piece.lineFeedCnt - 1;\n\t\tprev.piece = new Piece(\n\t\t\tprev.piece.bufferIndex,\n\t\t\tprev.piece.start,\n\t\t\tnewEnd,\n\t\t\tprevNewLFCnt,\n\t\t\tprevNewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, prev, - 1, -1);\n\t\tif (prev.piece.length === 0) {\n\t\t\tnodesToDel.push(prev);\n\t\t}\n\n\t\t// update nextNode\n\t\tconst newStart: BufferCursor = { line: next.piece.start.line + 1, column: 0 };\n\t\tconst newLength = next.piece.length - 1;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(next.piece.bufferIndex, newStart, next.piece.end);\n\t\tnext.piece = new Piece(\n\t\t\tnext.piece.bufferIndex,\n\t\t\tnewStart,\n\t\t\tnext.piece.end,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, next, - 1, -1);\n\t\tif (next.piece.length === 0) {\n\t\t\tnodesToDel.push(next);\n\t\t}\n\n\t\t// create new piece which contains \\r\\n\n\t\tconst pieces = this.createNewPieces('\\r\\n');\n\t\tthis.rbInsertRight(prev, pieces[0]);\n\t\t// delete empty nodes\n\n\t\tfor (let i = 0; i < nodesToDel.length; i++) {\n\t\t\trbDelete(this, nodesToDel[i]);\n\t\t}\n\t}\n\n\tprivate adjustCarriageReturnFromNext(value: string, node: TreeNode): boolean {\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(value)) {\n\t\t\tconst nextNode = node.next();\n\t\t\tif (this.startWithLF(nextNode)) {\n\t\t\t\t// move `\\n` forward\n\t\t\t\tvalue += '\\n';\n\n\t\t\t\tif (nextNode.piece.length === 1) {\n\t\t\t\t\trbDelete(this, nextNode);\n\t\t\t\t} else {\n\n\t\t\t\t\tconst piece = nextNode.piece;\n\t\t\t\t\tconst newStart: BufferCursor = { line: piece.start.line + 1, column: 0 };\n\t\t\t\t\tconst newLength = piece.length - 1;\n\t\t\t\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n\t\t\t\t\tnextNode.piece = new Piece(\n\t\t\t\t\t\tpiece.bufferIndex,\n\t\t\t\t\t\tnewStart,\n\t\t\t\t\t\tpiece.end,\n\t\t\t\t\t\tnewLineFeedCnt,\n\t\t\t\t\t\tnewLength\n\t\t\t\t\t);\n\n\t\t\t\t\tupdateTreeMetadata(this, nextNode, -1, -1);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t// #endregion\n\n\t// #endregion\n\n\t// #region Tree operations\n\titerate(node: TreeNode, callback: (node: TreeNode) => boolean): boolean {\n\t\tif (node === SENTINEL) {\n\t\t\treturn callback(SENTINEL);\n\t\t}\n\n\t\tconst leftRet = this.iterate(node.left, callback);\n\t\tif (!leftRet) {\n\t\t\treturn leftRet;\n\t\t}\n\n\t\treturn callback(node) && this.iterate(node.right, callback);\n\t}\n\n\tprivate getNodeContent(node: TreeNode) {\n\t\tif (node === SENTINEL) {\n\t\t\treturn '';\n\t\t}\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tlet currentContent;\n\t\tconst piece = node.piece;\n\t\tconst startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\t\tconst endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\t\tcurrentContent = buffer.buffer.substring(startOffset, endOffset);\n\t\treturn currentContent;\n\t}\n\n\tgetPieceContent(piece: Piece) {\n\t\tconst buffer = this._buffers[piece.bufferIndex];\n\t\tconst startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\t\tconst endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\t\tconst currentContent = buffer.buffer.substring(startOffset, endOffset);\n\t\treturn currentContent;\n\t}\n\n\t/**\n\t * node node\n\t * / \\ / \\\n\t * a b <---- a b\n\t * /\n\t * z\n\t */\n\tprivate rbInsertRight(node: TreeNode | null, p: Piece): TreeNode {\n\t\tconst z = new TreeNode(p, NodeColor.Red);\n\t\tz.left = SENTINEL;\n\t\tz.right = SENTINEL;\n\t\tz.parent = SENTINEL;\n\t\tz.size_left = 0;\n\t\tz.lf_left = 0;\n\n\t\tconst x = this.root;\n\t\tif (x === SENTINEL) {\n\t\t\tthis.root = z;\n\t\t\tz.color = NodeColor.Black;\n\t\t} else if (node!.right === SENTINEL) {\n\t\t\tnode!.right = z;\n\t\t\tz.parent = node!;\n\t\t} else {\n\t\t\tconst nextNode = leftest(node!.right);\n\t\t\tnextNode.left = z;\n\t\t\tz.parent = nextNode;\n\t\t}\n\n\t\tfixInsert(this, z);\n\t\treturn z;\n\t}\n\n\t/**\n\t * node node\n\t * / \\ / \\\n\t * a b ----> a b\n\t * \\\n\t * z\n\t */\n\tprivate rbInsertLeft(node: TreeNode | null, p: Piece): TreeNode {\n\t\tconst z = new TreeNode(p, NodeColor.Red);\n\t\tz.left = SENTINEL;\n\t\tz.right = SENTINEL;\n\t\tz.parent = SENTINEL;\n\t\tz.size_left = 0;\n\t\tz.lf_left = 0;\n\n\t\tif (this.root === SENTINEL) {\n\t\t\tthis.root = z;\n\t\t\tz.color = NodeColor.Black;\n\t\t} else if (node!.left === SENTINEL) {\n\t\t\tnode!.left = z;\n\t\t\tz.parent = node!;\n\t\t} else {\n\t\t\tconst prevNode = righttest(node!.left); // a\n\t\t\tprevNode.right = z;\n\t\t\tz.parent = prevNode;\n\t\t}\n\n\t\tfixInsert(this, z);\n\t\treturn z;\n\t}\n\t// #endregion\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter } from 'vs/base/common/event';\nimport * as strings from 'vs/base/common/strings';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { ApplyEditsResult, EndOfLinePreference, FindMatch, IInternalModelContentChange, ISingleEditOperationIdentifier, ITextBuffer, ITextSnapshot, ValidAnnotatedEditOperation, IValidEditOperation, SearchData } from 'vs/editor/common/model';\nimport { PieceTreeBase, StringBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase';\nimport { countEOL, StringEOL } from 'vs/editor/common/core/eolCounter';\nimport { TextChange } from 'vs/editor/common/core/textChange';\nimport { Disposable } from 'vs/base/common/lifecycle';\n\nexport interface IValidatedEditOperation {\n\tsortIndex: number;\n\tidentifier: ISingleEditOperationIdentifier | null;\n\trange: Range;\n\trangeOffset: number;\n\trangeLength: number;\n\ttext: string;\n\teolCount: number;\n\tfirstLineLength: number;\n\tlastLineLength: number;\n\tforceMoveMarkers: boolean;\n\tisAutoWhitespaceEdit: boolean;\n}\n\nexport interface IReverseSingleEditOperation extends IValidEditOperation {\n\tsortIndex: number;\n}\n\nexport class PieceTreeTextBuffer extends Disposable implements ITextBuffer {\n\tprivate _pieceTree: PieceTreeBase;\n\tprivate readonly _BOM: string;\n\tprivate _mightContainRTL: boolean;\n\tprivate _mightContainUnusualLineTerminators: boolean;\n\tprivate _mightContainNonBasicASCII: boolean;\n\n\tprivate readonly _onDidChangeContent: Emitter = this._register(new Emitter());\n\n\tconstructor(chunks: StringBuffer[], BOM: string, eol: '\\r\\n' | '\\n', containsRTL: boolean, containsUnusualLineTerminators: boolean, isBasicASCII: boolean, eolNormalized: boolean) {\n\t\tsuper();\n\t\tthis._BOM = BOM;\n\t\tthis._mightContainNonBasicASCII = !isBasicASCII;\n\t\tthis._mightContainRTL = containsRTL;\n\t\tthis._mightContainUnusualLineTerminators = containsUnusualLineTerminators;\n\t\tthis._pieceTree = new PieceTreeBase(chunks, eol, eolNormalized);\n\t}\n\tpublic mightContainRTL(): boolean {\n\t\treturn this._mightContainRTL;\n\t}\n\tpublic mightContainUnusualLineTerminators(): boolean {\n\t\treturn this._mightContainUnusualLineTerminators;\n\t}\n\tpublic resetMightContainUnusualLineTerminators(): void {\n\t\tthis._mightContainUnusualLineTerminators = false;\n\t}\n\tpublic mightContainNonBasicASCII(): boolean {\n\t\treturn this._mightContainNonBasicASCII;\n\t}\n\tpublic getBOM(): string {\n\t\treturn this._BOM;\n\t}\n\tpublic getEOL(): '\\r\\n' | '\\n' {\n\t\treturn this._pieceTree.getEOL();\n\t}\n\n\tpublic createSnapshot(preserveBOM: boolean): ITextSnapshot {\n\t\treturn this._pieceTree.createSnapshot(preserveBOM ? this._BOM : '');\n\t}\n\n\tpublic getOffsetAt(lineNumber: number, column: number): number {\n\t\treturn this._pieceTree.getOffsetAt(lineNumber, column);\n\t}\n\n\tpublic getPositionAt(offset: number): Position {\n\t\treturn this._pieceTree.getPositionAt(offset);\n\t}\n\n\tpublic getRangeAt(start: number, length: number): Range {\n\t\tconst end = start + length;\n\t\tconst startPosition = this.getPositionAt(start);\n\t\tconst endPosition = this.getPositionAt(end);\n\t\treturn new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column);\n\t}\n\n\tpublic getValueInRange(range: Range, eol: EndOfLinePreference = EndOfLinePreference.TextDefined): string {\n\t\tif (range.isEmpty()) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst lineEnding = this._getEndOfLine(eol);\n\t\treturn this._pieceTree.getValueInRange(range, lineEnding);\n\t}\n\n\tpublic getValueLengthInRange(range: Range, eol: EndOfLinePreference = EndOfLinePreference.TextDefined): number {\n\t\tif (range.isEmpty()) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tif (range.startLineNumber === range.endLineNumber) {\n\t\t\treturn (range.endColumn - range.startColumn);\n\t\t}\n\n\t\tconst startOffset = this.getOffsetAt(range.startLineNumber, range.startColumn);\n\t\tconst endOffset = this.getOffsetAt(range.endLineNumber, range.endColumn);\n\t\treturn endOffset - startOffset;\n\t}\n\n\tpublic getCharacterCountInRange(range: Range, eol: EndOfLinePreference = EndOfLinePreference.TextDefined): number {\n\t\tif (this._mightContainNonBasicASCII) {\n\t\t\t// we must count by iterating\n\n\t\t\tlet result = 0;\n\n\t\t\tconst fromLineNumber = range.startLineNumber;\n\t\t\tconst toLineNumber = range.endLineNumber;\n\t\t\tfor (let lineNumber = fromLineNumber; lineNumber <= toLineNumber; lineNumber++) {\n\t\t\t\tconst lineContent = this.getLineContent(lineNumber);\n\t\t\t\tconst fromOffset = (lineNumber === fromLineNumber ? range.startColumn - 1 : 0);\n\t\t\t\tconst toOffset = (lineNumber === toLineNumber ? range.endColumn - 1 : lineContent.length);\n\n\t\t\t\tfor (let offset = fromOffset; offset < toOffset; offset++) {\n\t\t\t\t\tif (strings.isHighSurrogate(lineContent.charCodeAt(offset))) {\n\t\t\t\t\t\tresult = result + 1;\n\t\t\t\t\t\toffset = offset + 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = result + 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tresult += this._getEndOfLine(eol).length * (toLineNumber - fromLineNumber);\n\n\t\t\treturn result;\n\t\t}\n\n\t\treturn this.getValueLengthInRange(range, eol);\n\t}\n\n\tpublic getLength(): number {\n\t\treturn this._pieceTree.getLength();\n\t}\n\n\tpublic getLineCount(): number {\n\t\treturn this._pieceTree.getLineCount();\n\t}\n\n\tpublic getLinesContent(): string[] {\n\t\treturn this._pieceTree.getLinesContent();\n\t}\n\n\tpublic getLineContent(lineNumber: number): string {\n\t\treturn this._pieceTree.getLineContent(lineNumber);\n\t}\n\n\tpublic getLineCharCode(lineNumber: number, index: number): number {\n\t\treturn this._pieceTree.getLineCharCode(lineNumber, index);\n\t}\n\n\tpublic getLineLength(lineNumber: number): number {\n\t\treturn this._pieceTree.getLineLength(lineNumber);\n\t}\n\n\tpublic getLineFirstNonWhitespaceColumn(lineNumber: number): number {\n\t\tconst result = strings.firstNonWhitespaceIndex(this.getLineContent(lineNumber));\n\t\tif (result === -1) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn result + 1;\n\t}\n\n\tpublic getLineLastNonWhitespaceColumn(lineNumber: number): number {\n\t\tconst result = strings.lastNonWhitespaceIndex(this.getLineContent(lineNumber));\n\t\tif (result === -1) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn result + 2;\n\t}\n\n\tprivate _getEndOfLine(eol: EndOfLinePreference): string {\n\t\tswitch (eol) {\n\t\t\tcase EndOfLinePreference.LF:\n\t\t\t\treturn '\\n';\n\t\t\tcase EndOfLinePreference.CRLF:\n\t\t\t\treturn '\\r\\n';\n\t\t\tcase EndOfLinePreference.TextDefined:\n\t\t\t\treturn this.getEOL();\n\t\t\tdefault:\n\t\t\t\tthrow new Error('Unknown EOL preference');\n\t\t}\n\t}\n\n\tpublic setEOL(newEOL: '\\r\\n' | '\\n'): void {\n\t\tthis._pieceTree.setEOL(newEOL);\n\t}\n\n\tpublic applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean, computeUndoEdits: boolean): ApplyEditsResult {\n\t\tlet mightContainRTL = this._mightContainRTL;\n\t\tlet mightContainUnusualLineTerminators = this._mightContainUnusualLineTerminators;\n\t\tlet mightContainNonBasicASCII = this._mightContainNonBasicASCII;\n\t\tlet canReduceOperations = true;\n\n\t\tlet operations: IValidatedEditOperation[] = [];\n\t\tfor (let i = 0; i < rawOperations.length; i++) {\n\t\t\tconst op = rawOperations[i];\n\t\t\tif (canReduceOperations && op._isTracked) {\n\t\t\t\tcanReduceOperations = false;\n\t\t\t}\n\t\t\tconst validatedRange = op.range;\n\t\t\tif (op.text) {\n\t\t\t\tlet textMightContainNonBasicASCII = true;\n\t\t\t\tif (!mightContainNonBasicASCII) {\n\t\t\t\t\ttextMightContainNonBasicASCII = !strings.isBasicASCII(op.text);\n\t\t\t\t\tmightContainNonBasicASCII = textMightContainNonBasicASCII;\n\t\t\t\t}\n\t\t\t\tif (!mightContainRTL && textMightContainNonBasicASCII) {\n\t\t\t\t\t// check if the new inserted text contains RTL\n\t\t\t\t\tmightContainRTL = strings.containsRTL(op.text);\n\t\t\t\t}\n\t\t\t\tif (!mightContainUnusualLineTerminators && textMightContainNonBasicASCII) {\n\t\t\t\t\t// check if the new inserted text contains unusual line terminators\n\t\t\t\t\tmightContainUnusualLineTerminators = strings.containsUnusualLineTerminators(op.text);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet validText = '';\n\t\t\tlet eolCount = 0;\n\t\t\tlet firstLineLength = 0;\n\t\t\tlet lastLineLength = 0;\n\t\t\tif (op.text) {\n\t\t\t\tlet strEOL: StringEOL;\n\t\t\t\t[eolCount, firstLineLength, lastLineLength, strEOL] = countEOL(op.text);\n\n\t\t\t\tconst bufferEOL = this.getEOL();\n\t\t\t\tconst expectedStrEOL = (bufferEOL === '\\r\\n' ? StringEOL.CRLF : StringEOL.LF);\n\t\t\t\tif (strEOL === StringEOL.Unknown || strEOL === expectedStrEOL) {\n\t\t\t\t\tvalidText = op.text;\n\t\t\t\t} else {\n\t\t\t\t\tvalidText = op.text.replace(/\\r\\n|\\r|\\n/g, bufferEOL);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toperations[i] = {\n\t\t\t\tsortIndex: i,\n\t\t\t\tidentifier: op.identifier || null,\n\t\t\t\trange: validatedRange,\n\t\t\t\trangeOffset: this.getOffsetAt(validatedRange.startLineNumber, validatedRange.startColumn),\n\t\t\t\trangeLength: this.getValueLengthInRange(validatedRange),\n\t\t\t\ttext: validText,\n\t\t\t\teolCount: eolCount,\n\t\t\t\tfirstLineLength: firstLineLength,\n\t\t\t\tlastLineLength: lastLineLength,\n\t\t\t\tforceMoveMarkers: Boolean(op.forceMoveMarkers),\n\t\t\t\tisAutoWhitespaceEdit: op.isAutoWhitespaceEdit || false\n\t\t\t};\n\t\t}\n\n\t\t// Sort operations ascending\n\t\toperations.sort(PieceTreeTextBuffer._sortOpsAscending);\n\n\t\tlet hasTouchingRanges = false;\n\t\tfor (let i = 0, count = operations.length - 1; i < count; i++) {\n\t\t\tconst rangeEnd = operations[i].range.getEndPosition();\n\t\t\tconst nextRangeStart = operations[i + 1].range.getStartPosition();\n\n\t\t\tif (nextRangeStart.isBeforeOrEqual(rangeEnd)) {\n\t\t\t\tif (nextRangeStart.isBefore(rangeEnd)) {\n\t\t\t\t\t// overlapping ranges\n\t\t\t\t\tthrow new Error('Overlapping ranges are not allowed!');\n\t\t\t\t}\n\t\t\t\thasTouchingRanges = true;\n\t\t\t}\n\t\t}\n\n\t\tif (canReduceOperations) {\n\t\t\toperations = this._reduceOperations(operations);\n\t\t}\n\n\t\t// Delta encode operations\n\t\tconst reverseRanges = (computeUndoEdits || recordTrimAutoWhitespace ? PieceTreeTextBuffer._getInverseEditRanges(operations) : []);\n\t\tconst newTrimAutoWhitespaceCandidates: { lineNumber: number, oldContent: string }[] = [];\n\t\tif (recordTrimAutoWhitespace) {\n\t\t\tfor (let i = 0; i < operations.length; i++) {\n\t\t\t\tconst op = operations[i];\n\t\t\t\tconst reverseRange = reverseRanges[i];\n\n\t\t\t\tif (op.isAutoWhitespaceEdit && op.range.isEmpty()) {\n\t\t\t\t\t// Record already the future line numbers that might be auto whitespace removal candidates on next edit\n\t\t\t\t\tfor (let lineNumber = reverseRange.startLineNumber; lineNumber <= reverseRange.endLineNumber; lineNumber++) {\n\t\t\t\t\t\tlet currentLineContent = '';\n\t\t\t\t\t\tif (lineNumber === reverseRange.startLineNumber) {\n\t\t\t\t\t\t\tcurrentLineContent = this.getLineContent(op.range.startLineNumber);\n\t\t\t\t\t\t\tif (strings.firstNonWhitespaceIndex(currentLineContent) !== -1) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnewTrimAutoWhitespaceCandidates.push({ lineNumber: lineNumber, oldContent: currentLineContent });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet reverseOperations: IReverseSingleEditOperation[] | null = null;\n\t\tif (computeUndoEdits) {\n\n\t\t\tlet reverseRangeDeltaOffset = 0;\n\t\t\treverseOperations = [];\n\t\t\tfor (let i = 0; i < operations.length; i++) {\n\t\t\t\tconst op = operations[i];\n\t\t\t\tconst reverseRange = reverseRanges[i];\n\t\t\t\tconst bufferText = this.getValueInRange(op.range);\n\t\t\t\tconst reverseRangeOffset = op.rangeOffset + reverseRangeDeltaOffset;\n\t\t\t\treverseRangeDeltaOffset += (op.text.length - bufferText.length);\n\n\t\t\t\treverseOperations[i] = {\n\t\t\t\t\tsortIndex: op.sortIndex,\n\t\t\t\t\tidentifier: op.identifier,\n\t\t\t\t\trange: reverseRange,\n\t\t\t\t\ttext: bufferText,\n\t\t\t\t\ttextChange: new TextChange(op.rangeOffset, bufferText, reverseRangeOffset, op.text)\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Can only sort reverse operations when the order is not significant\n\t\t\tif (!hasTouchingRanges) {\n\t\t\t\treverseOperations.sort((a, b) => a.sortIndex - b.sortIndex);\n\t\t\t}\n\t\t}\n\n\n\t\tthis._mightContainRTL = mightContainRTL;\n\t\tthis._mightContainUnusualLineTerminators = mightContainUnusualLineTerminators;\n\t\tthis._mightContainNonBasicASCII = mightContainNonBasicASCII;\n\n\t\tconst contentChanges = this._doApplyEdits(operations);\n\n\t\tlet trimAutoWhitespaceLineNumbers: number[] | null = null;\n\t\tif (recordTrimAutoWhitespace && newTrimAutoWhitespaceCandidates.length > 0) {\n\t\t\t// sort line numbers auto whitespace removal candidates for next edit descending\n\t\t\tnewTrimAutoWhitespaceCandidates.sort((a, b) => b.lineNumber - a.lineNumber);\n\n\t\t\ttrimAutoWhitespaceLineNumbers = [];\n\t\t\tfor (let i = 0, len = newTrimAutoWhitespaceCandidates.length; i < len; i++) {\n\t\t\t\tconst lineNumber = newTrimAutoWhitespaceCandidates[i].lineNumber;\n\t\t\t\tif (i > 0 && newTrimAutoWhitespaceCandidates[i - 1].lineNumber === lineNumber) {\n\t\t\t\t\t// Do not have the same line number twice\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst prevContent = newTrimAutoWhitespaceCandidates[i].oldContent;\n\t\t\t\tconst lineContent = this.getLineContent(lineNumber);\n\n\t\t\t\tif (lineContent.length === 0 || lineContent === prevContent || strings.firstNonWhitespaceIndex(lineContent) !== -1) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\ttrimAutoWhitespaceLineNumbers.push(lineNumber);\n\t\t\t}\n\t\t}\n\n\t\tthis._onDidChangeContent.fire();\n\n\t\treturn new ApplyEditsResult(\n\t\t\treverseOperations,\n\t\t\tcontentChanges,\n\t\t\ttrimAutoWhitespaceLineNumbers\n\t\t);\n\t}\n\n\t/**\n\t * Transform operations such that they represent the same logic edit,\n\t * but that they also do not cause OOM crashes.\n\t */\n\tprivate _reduceOperations(operations: IValidatedEditOperation[]): IValidatedEditOperation[] {\n\t\tif (operations.length < 1000) {\n\t\t\t// We know from empirical testing that a thousand edits work fine regardless of their shape.\n\t\t\treturn operations;\n\t\t}\n\n\t\t// At one point, due to how events are emitted and how each operation is handled,\n\t\t// some operations can trigger a high amount of temporary string allocations,\n\t\t// that will immediately get edited again.\n\t\t// e.g. a formatter inserting ridiculous ammounts of \\n on a model with a single line\n\t\t// Therefore, the strategy is to collapse all the operations into a huge single edit operation\n\t\treturn [this._toSingleEditOperation(operations)];\n\t}\n\n\t_toSingleEditOperation(operations: IValidatedEditOperation[]): IValidatedEditOperation {\n\t\tlet forceMoveMarkers = false;\n\t\tconst firstEditRange = operations[0].range;\n\t\tconst lastEditRange = operations[operations.length - 1].range;\n\t\tconst entireEditRange = new Range(firstEditRange.startLineNumber, firstEditRange.startColumn, lastEditRange.endLineNumber, lastEditRange.endColumn);\n\t\tlet lastEndLineNumber = firstEditRange.startLineNumber;\n\t\tlet lastEndColumn = firstEditRange.startColumn;\n\t\tconst result: string[] = [];\n\n\t\tfor (let i = 0, len = operations.length; i < len; i++) {\n\t\t\tconst operation = operations[i];\n\t\t\tconst range = operation.range;\n\n\t\t\tforceMoveMarkers = forceMoveMarkers || operation.forceMoveMarkers;\n\n\t\t\t// (1) -- Push old text\n\t\t\tresult.push(this.getValueInRange(new Range(lastEndLineNumber, lastEndColumn, range.startLineNumber, range.startColumn)));\n\n\t\t\t// (2) -- Push new text\n\t\t\tif (operation.text.length > 0) {\n\t\t\t\tresult.push(operation.text);\n\t\t\t}\n\n\t\t\tlastEndLineNumber = range.endLineNumber;\n\t\t\tlastEndColumn = range.endColumn;\n\t\t}\n\n\t\tconst text = result.join('');\n\t\tconst [eolCount, firstLineLength, lastLineLength] = countEOL(text);\n\n\t\treturn {\n\t\t\tsortIndex: 0,\n\t\t\tidentifier: operations[0].identifier,\n\t\t\trange: entireEditRange,\n\t\t\trangeOffset: this.getOffsetAt(entireEditRange.startLineNumber, entireEditRange.startColumn),\n\t\t\trangeLength: this.getValueLengthInRange(entireEditRange, EndOfLinePreference.TextDefined),\n\t\t\ttext: text,\n\t\t\teolCount: eolCount,\n\t\t\tfirstLineLength: firstLineLength,\n\t\t\tlastLineLength: lastLineLength,\n\t\t\tforceMoveMarkers: forceMoveMarkers,\n\t\t\tisAutoWhitespaceEdit: false\n\t\t};\n\t}\n\n\tprivate _doApplyEdits(operations: IValidatedEditOperation[]): IInternalModelContentChange[] {\n\t\toperations.sort(PieceTreeTextBuffer._sortOpsDescending);\n\n\t\tconst contentChanges: IInternalModelContentChange[] = [];\n\n\t\t// operations are from bottom to top\n\t\tfor (let i = 0; i < operations.length; i++) {\n\t\t\tconst op = operations[i];\n\n\t\t\tconst startLineNumber = op.range.startLineNumber;\n\t\t\tconst startColumn = op.range.startColumn;\n\t\t\tconst endLineNumber = op.range.endLineNumber;\n\t\t\tconst endColumn = op.range.endColumn;\n\n\t\t\tif (startLineNumber === endLineNumber && startColumn === endColumn && op.text.length === 0) {\n\t\t\t\t// no-op\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (op.text) {\n\t\t\t\t// replacement\n\t\t\t\tthis._pieceTree.delete(op.rangeOffset, op.rangeLength);\n\t\t\t\tthis._pieceTree.insert(op.rangeOffset, op.text, true);\n\n\t\t\t} else {\n\t\t\t\t// deletion\n\t\t\t\tthis._pieceTree.delete(op.rangeOffset, op.rangeLength);\n\t\t\t}\n\n\t\t\tconst contentChangeRange = new Range(startLineNumber, startColumn, endLineNumber, endColumn);\n\t\t\tcontentChanges.push({\n\t\t\t\trange: contentChangeRange,\n\t\t\t\trangeLength: op.rangeLength,\n\t\t\t\ttext: op.text,\n\t\t\t\trangeOffset: op.rangeOffset,\n\t\t\t\tforceMoveMarkers: op.forceMoveMarkers\n\t\t\t});\n\t\t}\n\t\treturn contentChanges;\n\t}\n\n\tfindMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[] {\n\t\treturn this._pieceTree.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);\n\t}\n\n\t/**\n\t * Assumes `operations` are validated and sorted ascending\n\t */\n\tpublic static _getInverseEditRanges(operations: IValidatedEditOperation[]): Range[] {\n\t\tconst result: Range[] = [];\n\n\t\tlet prevOpEndLineNumber: number = 0;\n\t\tlet prevOpEndColumn: number = 0;\n\t\tlet prevOp: IValidatedEditOperation | null = null;\n\t\tfor (let i = 0, len = operations.length; i < len; i++) {\n\t\t\tconst op = operations[i];\n\n\t\t\tlet startLineNumber: number;\n\t\t\tlet startColumn: number;\n\n\t\t\tif (prevOp) {\n\t\t\t\tif (prevOp.range.endLineNumber === op.range.startLineNumber) {\n\t\t\t\t\tstartLineNumber = prevOpEndLineNumber;\n\t\t\t\t\tstartColumn = prevOpEndColumn + (op.range.startColumn - prevOp.range.endColumn);\n\t\t\t\t} else {\n\t\t\t\t\tstartLineNumber = prevOpEndLineNumber + (op.range.startLineNumber - prevOp.range.endLineNumber);\n\t\t\t\t\tstartColumn = op.range.startColumn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tstartLineNumber = op.range.startLineNumber;\n\t\t\t\tstartColumn = op.range.startColumn;\n\t\t\t}\n\n\t\t\tlet resultRange: Range;\n\n\t\t\tif (op.text.length > 0) {\n\t\t\t\t// the operation inserts something\n\t\t\t\tconst lineCount = op.eolCount + 1;\n\n\t\t\t\tif (lineCount === 1) {\n\t\t\t\t\t// single line insert\n\t\t\t\t\tresultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn + op.firstLineLength);\n\t\t\t\t} else {\n\t\t\t\t\t// multi line insert\n\t\t\t\t\tresultRange = new Range(startLineNumber, startColumn, startLineNumber + lineCount - 1, op.lastLineLength + 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// There is nothing to insert\n\t\t\t\tresultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn);\n\t\t\t}\n\n\t\t\tprevOpEndLineNumber = resultRange.endLineNumber;\n\t\t\tprevOpEndColumn = resultRange.endColumn;\n\n\t\t\tresult.push(resultRange);\n\t\t\tprevOp = op;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate static _sortOpsAscending(a: IValidatedEditOperation, b: IValidatedEditOperation): number {\n\t\tconst r = Range.compareRangesUsingEnds(a.range, b.range);\n\t\tif (r === 0) {\n\t\t\treturn a.sortIndex - b.sortIndex;\n\t\t}\n\t\treturn r;\n\t}\n\n\tprivate static _sortOpsDescending(a: IValidatedEditOperation, b: IValidatedEditOperation): number {\n\t\tconst r = Range.compareRangesUsingEnds(a.range, b.range);\n\t\tif (r === 0) {\n\t\t\treturn b.sortIndex - a.sortIndex;\n\t\t}\n\t\treturn -r;\n\t}\n\t// #endregion\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport * as strings from 'vs/base/common/strings';\nimport { DefaultEndOfLine, ITextBuffer, ITextBufferBuilder, ITextBufferFactory } from 'vs/editor/common/model';\nimport { StringBuffer, createLineStarts, createLineStartsFast } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase';\nimport { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer';\n\nexport class PieceTreeTextBufferFactory implements ITextBufferFactory {\n\n\tconstructor(\n\t\tprivate readonly _chunks: StringBuffer[],\n\t\tprivate readonly _bom: string,\n\t\tprivate readonly _cr: number,\n\t\tprivate readonly _lf: number,\n\t\tprivate readonly _crlf: number,\n\t\tprivate readonly _containsRTL: boolean,\n\t\tprivate readonly _containsUnusualLineTerminators: boolean,\n\t\tprivate readonly _isBasicASCII: boolean,\n\t\tprivate readonly _normalizeEOL: boolean\n\t) { }\n\n\tprivate _getEOL(defaultEOL: DefaultEndOfLine): '\\r\\n' | '\\n' {\n\t\tconst totalEOLCount = this._cr + this._lf + this._crlf;\n\t\tconst totalCRCount = this._cr + this._crlf;\n\t\tif (totalEOLCount === 0) {\n\t\t\t// This is an empty file or a file with precisely one line\n\t\t\treturn (defaultEOL === DefaultEndOfLine.LF ? '\\n' : '\\r\\n');\n\t\t}\n\t\tif (totalCRCount > totalEOLCount / 2) {\n\t\t\t// More than half of the file contains \\r\\n ending lines\n\t\t\treturn '\\r\\n';\n\t\t}\n\t\t// At least one line more ends in \\n\n\t\treturn '\\n';\n\t}\n\n\tpublic create(defaultEOL: DefaultEndOfLine): { textBuffer: ITextBuffer; disposable: IDisposable; } {\n\t\tconst eol = this._getEOL(defaultEOL);\n\t\tconst chunks = this._chunks;\n\n\t\tif (this._normalizeEOL &&\n\t\t\t((eol === '\\r\\n' && (this._cr > 0 || this._lf > 0))\n\t\t\t\t|| (eol === '\\n' && (this._cr > 0 || this._crlf > 0)))\n\t\t) {\n\t\t\t// Normalize pieces\n\t\t\tfor (let i = 0, len = chunks.length; i < len; i++) {\n\t\t\t\tconst str = chunks[i].buffer.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\t\tconst newLineStart = createLineStartsFast(str);\n\t\t\t\tchunks[i] = new StringBuffer(str, newLineStart);\n\t\t\t}\n\t\t}\n\n\t\tconst textBuffer = new PieceTreeTextBuffer(chunks, this._bom, eol, this._containsRTL, this._containsUnusualLineTerminators, this._isBasicASCII, this._normalizeEOL);\n\t\treturn { textBuffer: textBuffer, disposable: textBuffer };\n\t}\n}\n\nexport class PieceTreeTextBufferBuilder implements ITextBufferBuilder {\n\tprivate readonly chunks: StringBuffer[];\n\tprivate BOM: string;\n\n\tprivate _hasPreviousChar: boolean;\n\tprivate _previousChar: number;\n\tprivate readonly _tmpLineStarts: number[];\n\n\tprivate cr: number;\n\tprivate lf: number;\n\tprivate crlf: number;\n\tprivate containsRTL: boolean;\n\tprivate containsUnusualLineTerminators: boolean;\n\tprivate isBasicASCII: boolean;\n\n\tconstructor() {\n\t\tthis.chunks = [];\n\t\tthis.BOM = '';\n\n\t\tthis._hasPreviousChar = false;\n\t\tthis._previousChar = 0;\n\t\tthis._tmpLineStarts = [];\n\n\t\tthis.cr = 0;\n\t\tthis.lf = 0;\n\t\tthis.crlf = 0;\n\t\tthis.containsRTL = false;\n\t\tthis.containsUnusualLineTerminators = false;\n\t\tthis.isBasicASCII = true;\n\t}\n\n\tpublic acceptChunk(chunk: string): void {\n\t\tif (chunk.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.chunks.length === 0) {\n\t\t\tif (strings.startsWithUTF8BOM(chunk)) {\n\t\t\t\tthis.BOM = strings.UTF8_BOM_CHARACTER;\n\t\t\t\tchunk = chunk.substr(1);\n\t\t\t}\n\t\t}\n\n\t\tconst lastChar = chunk.charCodeAt(chunk.length - 1);\n\t\tif (lastChar === CharCode.CarriageReturn || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {\n\t\t\t// last character is \\r or a high surrogate => keep it back\n\t\t\tthis._acceptChunk1(chunk.substr(0, chunk.length - 1), false);\n\t\t\tthis._hasPreviousChar = true;\n\t\t\tthis._previousChar = lastChar;\n\t\t} else {\n\t\t\tthis._acceptChunk1(chunk, false);\n\t\t\tthis._hasPreviousChar = false;\n\t\t\tthis._previousChar = lastChar;\n\t\t}\n\t}\n\n\tprivate _acceptChunk1(chunk: string, allowEmptyStrings: boolean): void {\n\t\tif (!allowEmptyStrings && chunk.length === 0) {\n\t\t\t// Nothing to do\n\t\t\treturn;\n\t\t}\n\n\t\tif (this._hasPreviousChar) {\n\t\t\tthis._acceptChunk2(String.fromCharCode(this._previousChar) + chunk);\n\t\t} else {\n\t\t\tthis._acceptChunk2(chunk);\n\t\t}\n\t}\n\n\tprivate _acceptChunk2(chunk: string): void {\n\t\tconst lineStarts = createLineStarts(this._tmpLineStarts, chunk);\n\n\t\tthis.chunks.push(new StringBuffer(chunk, lineStarts.lineStarts));\n\t\tthis.cr += lineStarts.cr;\n\t\tthis.lf += lineStarts.lf;\n\t\tthis.crlf += lineStarts.crlf;\n\n\t\tif (this.isBasicASCII) {\n\t\t\tthis.isBasicASCII = lineStarts.isBasicASCII;\n\t\t}\n\t\tif (!this.isBasicASCII && !this.containsRTL) {\n\t\t\t// No need to check if it is basic ASCII\n\t\t\tthis.containsRTL = strings.containsRTL(chunk);\n\t\t}\n\t\tif (!this.isBasicASCII && !this.containsUnusualLineTerminators) {\n\t\t\t// No need to check if it is basic ASCII\n\t\t\tthis.containsUnusualLineTerminators = strings.containsUnusualLineTerminators(chunk);\n\t\t}\n\t}\n\n\tpublic finish(normalizeEOL: boolean = true): PieceTreeTextBufferFactory {\n\t\tthis._finish();\n\t\treturn new PieceTreeTextBufferFactory(\n\t\t\tthis.chunks,\n\t\t\tthis.BOM,\n\t\t\tthis.cr,\n\t\t\tthis.lf,\n\t\t\tthis.crlf,\n\t\t\tthis.containsRTL,\n\t\t\tthis.containsUnusualLineTerminators,\n\t\t\tthis.isBasicASCII,\n\t\t\tnormalizeEOL\n\t\t);\n\t}\n\n\tprivate _finish(): void {\n\t\tif (this.chunks.length === 0) {\n\t\t\tthis._acceptChunk1('', true);\n\t\t}\n\n\t\tif (this._hasPreviousChar) {\n\t\t\tthis._hasPreviousChar = false;\n\t\t\t// recreate last chunk\n\t\t\tconst lastChunk = this.chunks[this.chunks.length - 1];\n\t\t\tlastChunk.buffer += String.fromCharCode(this._previousChar);\n\t\t\tconst newLineStarts = createLineStartsFast(lastChunk.buffer);\n\t\t\tlastChunk.lineStarts = newLineStarts;\n\t\t\tif (this._previousChar === CharCode.CarriageReturn) {\n\t\t\t\tthis.cr++;\n\t\t\t}\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\n\n/**\n * Returns:\n * - -1 => the line consists of whitespace\n * - otherwise => the indent level is returned value\n */\nexport function computeIndentLevel(line: string, tabSize: number): number {\n\tlet indent = 0;\n\tlet i = 0;\n\tconst len = line.length;\n\n\twhile (i < len) {\n\t\tconst chCode = line.charCodeAt(i);\n\t\tif (chCode === CharCode.Space) {\n\t\t\tindent++;\n\t\t} else if (chCode === CharCode.Tab) {\n\t\t\tindent = indent - indent % tabSize + tabSize;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t\ti++;\n\t}\n\n\tif (i === len) {\n\t\treturn -1; // line only consists of whitespace\n\t}\n\n\treturn indent;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ParsedPattern, parse } from 'vs/base/common/glob';\nimport { Mimes } from 'vs/base/common/mime';\nimport { Schemas } from 'vs/base/common/network';\nimport { basename, posix } from 'vs/base/common/path';\nimport { DataUri } from 'vs/base/common/resources';\nimport { startsWithUTF8BOM } from 'vs/base/common/strings';\nimport { URI } from 'vs/base/common/uri';\n\nexport interface ILanguageAssociation {\n\treadonly id: string;\n\treadonly mime: string;\n\treadonly filename?: string;\n\treadonly extension?: string;\n\treadonly filepattern?: string;\n\treadonly firstline?: RegExp;\n\treadonly userConfigured?: boolean;\n}\n\ninterface ILanguageAssociationItem extends ILanguageAssociation {\n\treadonly filenameLowercase?: string;\n\treadonly extensionLowercase?: string;\n\treadonly filepatternLowercase?: ParsedPattern;\n\treadonly filepatternOnPath?: boolean;\n}\n\nlet registeredAssociations: ILanguageAssociationItem[] = [];\nlet nonUserRegisteredAssociations: ILanguageAssociationItem[] = [];\nlet userRegisteredAssociations: ILanguageAssociationItem[] = [];\n\n/**\n * Associate a language to the registry.\n */\nexport function registerLanguageAssociation(association: ILanguageAssociation, warnOnOverwrite = false): void {\n\n\t// Register\n\tconst associationItem = toLanguageAssociationItem(association);\n\tregisteredAssociations.push(associationItem);\n\tif (!associationItem.userConfigured) {\n\t\tnonUserRegisteredAssociations.push(associationItem);\n\t} else {\n\t\tuserRegisteredAssociations.push(associationItem);\n\t}\n\n\t// Check for conflicts unless this is a user configured association\n\tif (warnOnOverwrite && !associationItem.userConfigured) {\n\t\tregisteredAssociations.forEach(a => {\n\t\t\tif (a.mime === associationItem.mime || a.userConfigured) {\n\t\t\t\treturn; // same mime or userConfigured is ok\n\t\t\t}\n\n\t\t\tif (associationItem.extension && a.extension === associationItem.extension) {\n\t\t\t\tconsole.warn(`Overwriting extension <<${associationItem.extension}>> to now point to mime <<${associationItem.mime}>>`);\n\t\t\t}\n\n\t\t\tif (associationItem.filename && a.filename === associationItem.filename) {\n\t\t\t\tconsole.warn(`Overwriting filename <<${associationItem.filename}>> to now point to mime <<${associationItem.mime}>>`);\n\t\t\t}\n\n\t\t\tif (associationItem.filepattern && a.filepattern === associationItem.filepattern) {\n\t\t\t\tconsole.warn(`Overwriting filepattern <<${associationItem.filepattern}>> to now point to mime <<${associationItem.mime}>>`);\n\t\t\t}\n\n\t\t\tif (associationItem.firstline && a.firstline === associationItem.firstline) {\n\t\t\t\tconsole.warn(`Overwriting firstline <<${associationItem.firstline}>> to now point to mime <<${associationItem.mime}>>`);\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction toLanguageAssociationItem(association: ILanguageAssociation): ILanguageAssociationItem {\n\treturn {\n\t\tid: association.id,\n\t\tmime: association.mime,\n\t\tfilename: association.filename,\n\t\textension: association.extension,\n\t\tfilepattern: association.filepattern,\n\t\tfirstline: association.firstline,\n\t\tuserConfigured: association.userConfigured,\n\t\tfilenameLowercase: association.filename ? association.filename.toLowerCase() : undefined,\n\t\textensionLowercase: association.extension ? association.extension.toLowerCase() : undefined,\n\t\tfilepatternLowercase: association.filepattern ? parse(association.filepattern.toLowerCase()) : undefined,\n\t\tfilepatternOnPath: association.filepattern ? association.filepattern.indexOf(posix.sep) >= 0 : false\n\t};\n}\n\n/**\n * Clear language associations from the registry.\n */\nexport function clearLanguageAssociations(onlyUserConfigured?: boolean): void {\n\tif (!onlyUserConfigured) {\n\t\tregisteredAssociations = [];\n\t\tnonUserRegisteredAssociations = [];\n\t\tuserRegisteredAssociations = [];\n\t} else {\n\t\tregisteredAssociations = registeredAssociations.filter(a => !a.userConfigured);\n\t\tuserRegisteredAssociations = [];\n\t}\n}\n\n/**\n * Given a file, return the best matching mime types for it\n * based on the registered language associations.\n */\nexport function getMimeTypes(resource: URI | null, firstLine?: string): string[] {\n\tlet path: string | undefined;\n\tif (resource) {\n\t\tswitch (resource.scheme) {\n\t\t\tcase Schemas.file:\n\t\t\t\tpath = resource.fsPath;\n\t\t\t\tbreak;\n\t\t\tcase Schemas.data: {\n\t\t\t\tconst metadata = DataUri.parseMetaData(resource);\n\t\t\t\tpath = metadata.get(DataUri.META_DATA_LABEL);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tpath = resource.path;\n\t\t}\n\t}\n\n\tif (!path) {\n\t\treturn [Mimes.unknown];\n\t}\n\n\tpath = path.toLowerCase();\n\n\tconst filename = basename(path);\n\n\t// 1.) User configured mappings have highest priority\n\tconst configuredLanguage = getMimeByPath(path, filename, userRegisteredAssociations);\n\tif (configuredLanguage) {\n\t\treturn [configuredLanguage, Mimes.text];\n\t}\n\n\t// 2.) Registered mappings have middle priority\n\tconst registeredLanguage = getMimeByPath(path, filename, nonUserRegisteredAssociations);\n\tif (registeredLanguage) {\n\t\treturn [registeredLanguage, Mimes.text];\n\t}\n\n\t// 3.) Firstline has lowest priority\n\tif (firstLine) {\n\t\tconst firstlineLanguage = getMimeByFirstline(firstLine);\n\t\tif (firstlineLanguage) {\n\t\t\treturn [firstlineLanguage, Mimes.text];\n\t\t}\n\t}\n\n\treturn [Mimes.unknown];\n}\n\nfunction getMimeByPath(path: string, filename: string, associations: ILanguageAssociationItem[]): string | undefined {\n\tlet filenameMatch: ILanguageAssociationItem | undefined = undefined;\n\tlet patternMatch: ILanguageAssociationItem | undefined = undefined;\n\tlet extensionMatch: ILanguageAssociationItem | undefined = undefined;\n\n\t// We want to prioritize associations based on the order they are registered so that the last registered\n\t// association wins over all other. This is for https://github.com/microsoft/vscode/issues/20074\n\tfor (let i = associations.length - 1; i >= 0; i--) {\n\t\tconst association = associations[i];\n\n\t\t// First exact name match\n\t\tif (filename === association.filenameLowercase) {\n\t\t\tfilenameMatch = association;\n\t\t\tbreak; // take it!\n\t\t}\n\n\t\t// Longest pattern match\n\t\tif (association.filepattern) {\n\t\t\tif (!patternMatch || association.filepattern.length > patternMatch.filepattern!.length) {\n\t\t\t\tconst target = association.filepatternOnPath ? path : filename; // match on full path if pattern contains path separator\n\t\t\t\tif (association.filepatternLowercase?.(target)) {\n\t\t\t\t\tpatternMatch = association;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Longest extension match\n\t\tif (association.extension) {\n\t\t\tif (!extensionMatch || association.extension.length > extensionMatch.extension!.length) {\n\t\t\t\tif (filename.endsWith(association.extensionLowercase!)) {\n\t\t\t\t\textensionMatch = association;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 1.) Exact name match has second highest priority\n\tif (filenameMatch) {\n\t\treturn filenameMatch.mime;\n\t}\n\n\t// 2.) Match on pattern\n\tif (patternMatch) {\n\t\treturn patternMatch.mime;\n\t}\n\n\t// 3.) Match on extension comes next\n\tif (extensionMatch) {\n\t\treturn extensionMatch.mime;\n\t}\n\n\treturn undefined;\n}\n\nfunction getMimeByFirstline(firstLine: string): string | undefined {\n\tif (startsWithUTF8BOM(firstLine)) {\n\t\tfirstLine = firstLine.substr(1);\n\t}\n\n\tif (firstLine.length > 0) {\n\n\t\t// We want to prioritize associations based on the order they are registered so that the last registered\n\t\t// association wins over all other. This is for https://github.com/microsoft/vscode/issues/20074\n\t\tfor (let i = registeredAssociations.length - 1; i >= 0; i--) {\n\t\t\tconst association = registeredAssociations[i];\n\t\t\tif (!association.firstline) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst matches = firstLine.match(association.firstline);\n\t\t\tif (matches && matches.length > 0) {\n\t\t\t\treturn association.mime;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn undefined;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { VSBuffer } from 'vs/base/common/buffer';\nimport * as platform from 'vs/base/common/platform';\n\nexport interface IFullSemanticTokensDto {\n\tid: number;\n\ttype: 'full';\n\tdata: Uint32Array;\n}\n\nexport interface IDeltaSemanticTokensDto {\n\tid: number;\n\ttype: 'delta';\n\tdeltas: { start: number; deleteCount: number; data?: Uint32Array; }[];\n}\n\nexport type ISemanticTokensDto = IFullSemanticTokensDto | IDeltaSemanticTokensDto;\n\nconst enum EncodedSemanticTokensType {\n\tFull = 1,\n\tDelta = 2\n}\n\nfunction reverseEndianness(arr: Uint8Array): void {\n\tfor (let i = 0, len = arr.length; i < len; i += 4) {\n\t\t// flip bytes 0<->3 and 1<->2\n\t\tconst b0 = arr[i + 0];\n\t\tconst b1 = arr[i + 1];\n\t\tconst b2 = arr[i + 2];\n\t\tconst b3 = arr[i + 3];\n\t\tarr[i + 0] = b3;\n\t\tarr[i + 1] = b2;\n\t\tarr[i + 2] = b1;\n\t\tarr[i + 3] = b0;\n\t}\n}\n\nfunction toLittleEndianBuffer(arr: Uint32Array): VSBuffer {\n\tconst uint8Arr = new Uint8Array(arr.buffer, arr.byteOffset, arr.length * 4);\n\tif (!platform.isLittleEndian()) {\n\t\t// the byte order must be changed\n\t\treverseEndianness(uint8Arr);\n\t}\n\treturn VSBuffer.wrap(uint8Arr);\n}\n\nexport function encodeSemanticTokensDto(semanticTokens: ISemanticTokensDto): VSBuffer {\n\tconst dest = new Uint32Array(encodeSemanticTokensDtoSize(semanticTokens));\n\tlet offset = 0;\n\tdest[offset++] = semanticTokens.id;\n\tif (semanticTokens.type === 'full') {\n\t\tdest[offset++] = EncodedSemanticTokensType.Full;\n\t\tdest[offset++] = semanticTokens.data.length;\n\t\tdest.set(semanticTokens.data, offset); offset += semanticTokens.data.length;\n\t} else {\n\t\tdest[offset++] = EncodedSemanticTokensType.Delta;\n\t\tdest[offset++] = semanticTokens.deltas.length;\n\t\tfor (const delta of semanticTokens.deltas) {\n\t\t\tdest[offset++] = delta.start;\n\t\t\tdest[offset++] = delta.deleteCount;\n\t\t\tif (delta.data) {\n\t\t\t\tdest[offset++] = delta.data.length;\n\t\t\t\tdest.set(delta.data, offset); offset += delta.data.length;\n\t\t\t} else {\n\t\t\t\tdest[offset++] = 0;\n\t\t\t}\n\t\t}\n\t}\n\treturn toLittleEndianBuffer(dest);\n}\n\nfunction encodeSemanticTokensDtoSize(semanticTokens: ISemanticTokensDto): number {\n\tlet result = 0;\n\tresult += (\n\t\t+ 1 // id\n\t\t+ 1 // type\n\t);\n\tif (semanticTokens.type === 'full') {\n\t\tresult += (\n\t\t\t+ 1 // data length\n\t\t\t+ semanticTokens.data.length\n\t\t);\n\t} else {\n\t\tresult += (\n\t\t\t+ 1 // delta count\n\t\t);\n\t\tresult += (\n\t\t\t+ 1 // start\n\t\t\t+ 1 // deleteCount\n\t\t\t+ 1 // data length\n\t\t) * semanticTokens.deltas.length;\n\t\tfor (const delta of semanticTokens.deltas) {\n\t\t\tif (delta.data) {\n\t\t\t\tresult += delta.data.length;\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n// THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY.\n\n\nexport enum AccessibilitySupport {\n\t/**\n\t * This should be the browser case where it is not known if a screen reader is attached or no.\n\t */\n\tUnknown = 0,\n\tDisabled = 1,\n\tEnabled = 2\n}\n\nexport enum CompletionItemInsertTextRule {\n\t/**\n\t * Adjust whitespace/indentation of multiline insert texts to\n\t * match the current line indentation.\n\t */\n\tKeepWhitespace = 1,\n\t/**\n\t * `insertText` is a snippet.\n\t */\n\tInsertAsSnippet = 4\n}\n\nexport enum CompletionItemKind {\n\tMethod = 0,\n\tFunction = 1,\n\tConstructor = 2,\n\tField = 3,\n\tVariable = 4,\n\tClass = 5,\n\tStruct = 6,\n\tInterface = 7,\n\tModule = 8,\n\tProperty = 9,\n\tEvent = 10,\n\tOperator = 11,\n\tUnit = 12,\n\tValue = 13,\n\tConstant = 14,\n\tEnum = 15,\n\tEnumMember = 16,\n\tKeyword = 17,\n\tText = 18,\n\tColor = 19,\n\tFile = 20,\n\tReference = 21,\n\tCustomcolor = 22,\n\tFolder = 23,\n\tTypeParameter = 24,\n\tUser = 25,\n\tIssue = 26,\n\tSnippet = 27\n}\n\nexport enum CompletionItemTag {\n\tDeprecated = 1\n}\n\n/**\n * How a suggest provider was triggered.\n */\nexport enum CompletionTriggerKind {\n\tInvoke = 0,\n\tTriggerCharacter = 1,\n\tTriggerForIncompleteCompletions = 2\n}\n\n/**\n * A positioning preference for rendering content widgets.\n */\nexport enum ContentWidgetPositionPreference {\n\t/**\n\t * Place the content widget exactly at a position\n\t */\n\tEXACT = 0,\n\t/**\n\t * Place the content widget above a position\n\t */\n\tABOVE = 1,\n\t/**\n\t * Place the content widget below a position\n\t */\n\tBELOW = 2\n}\n\n/**\n * Describes the reason the cursor has changed its position.\n */\nexport enum CursorChangeReason {\n\t/**\n\t * Unknown or not set.\n\t */\n\tNotSet = 0,\n\t/**\n\t * A `model.setValue()` was called.\n\t */\n\tContentFlush = 1,\n\t/**\n\t * The `model` has been changed outside of this cursor and the cursor recovers its position from associated markers.\n\t */\n\tRecoverFromMarkers = 2,\n\t/**\n\t * There was an explicit user gesture.\n\t */\n\tExplicit = 3,\n\t/**\n\t * There was a Paste.\n\t */\n\tPaste = 4,\n\t/**\n\t * There was an Undo.\n\t */\n\tUndo = 5,\n\t/**\n\t * There was a Redo.\n\t */\n\tRedo = 6\n}\n\n/**\n * The default end of line to use when instantiating models.\n */\nexport enum DefaultEndOfLine {\n\t/**\n\t * Use line feed (\\n) as the end of line character.\n\t */\n\tLF = 1,\n\t/**\n\t * Use carriage return and line feed (\\r\\n) as the end of line character.\n\t */\n\tCRLF = 2\n}\n\n/**\n * A document highlight kind.\n */\nexport enum DocumentHighlightKind {\n\t/**\n\t * A textual occurrence.\n\t */\n\tText = 0,\n\t/**\n\t * Read-access of a symbol, like reading a variable.\n\t */\n\tRead = 1,\n\t/**\n\t * Write-access of a symbol, like writing to a variable.\n\t */\n\tWrite = 2\n}\n\n/**\n * Configuration options for auto indentation in the editor\n */\nexport enum EditorAutoIndentStrategy {\n\tNone = 0,\n\tKeep = 1,\n\tBrackets = 2,\n\tAdvanced = 3,\n\tFull = 4\n}\n\nexport enum EditorOption {\n\tacceptSuggestionOnCommitCharacter = 0,\n\tacceptSuggestionOnEnter = 1,\n\taccessibilitySupport = 2,\n\taccessibilityPageSize = 3,\n\tariaLabel = 4,\n\tautoClosingBrackets = 5,\n\tautoClosingDelete = 6,\n\tautoClosingOvertype = 7,\n\tautoClosingQuotes = 8,\n\tautoIndent = 9,\n\tautomaticLayout = 10,\n\tautoSurround = 11,\n\tbracketPairColorization = 12,\n\tguides = 13,\n\tcodeLens = 14,\n\tcodeLensFontFamily = 15,\n\tcodeLensFontSize = 16,\n\tcolorDecorators = 17,\n\tcolumnSelection = 18,\n\tcomments = 19,\n\tcontextmenu = 20,\n\tcopyWithSyntaxHighlighting = 21,\n\tcursorBlinking = 22,\n\tcursorSmoothCaretAnimation = 23,\n\tcursorStyle = 24,\n\tcursorSurroundingLines = 25,\n\tcursorSurroundingLinesStyle = 26,\n\tcursorWidth = 27,\n\tdisableLayerHinting = 28,\n\tdisableMonospaceOptimizations = 29,\n\tdomReadOnly = 30,\n\tdragAndDrop = 31,\n\temptySelectionClipboard = 32,\n\textraEditorClassName = 33,\n\tfastScrollSensitivity = 34,\n\tfind = 35,\n\tfixedOverflowWidgets = 36,\n\tfolding = 37,\n\tfoldingStrategy = 38,\n\tfoldingHighlight = 39,\n\tfoldingImportsByDefault = 40,\n\tfoldingMaximumRegions = 41,\n\tunfoldOnClickAfterEndOfLine = 42,\n\tfontFamily = 43,\n\tfontInfo = 44,\n\tfontLigatures = 45,\n\tfontSize = 46,\n\tfontWeight = 47,\n\tformatOnPaste = 48,\n\tformatOnType = 49,\n\tglyphMargin = 50,\n\tgotoLocation = 51,\n\thideCursorInOverviewRuler = 52,\n\thover = 53,\n\tinDiffEditor = 54,\n\tinlineSuggest = 55,\n\tletterSpacing = 56,\n\tlightbulb = 57,\n\tlineDecorationsWidth = 58,\n\tlineHeight = 59,\n\tlineNumbers = 60,\n\tlineNumbersMinChars = 61,\n\tlinkedEditing = 62,\n\tlinks = 63,\n\tmatchBrackets = 64,\n\tminimap = 65,\n\tmouseStyle = 66,\n\tmouseWheelScrollSensitivity = 67,\n\tmouseWheelZoom = 68,\n\tmultiCursorMergeOverlapping = 69,\n\tmultiCursorModifier = 70,\n\tmultiCursorPaste = 71,\n\toccurrencesHighlight = 72,\n\toverviewRulerBorder = 73,\n\toverviewRulerLanes = 74,\n\tpadding = 75,\n\tparameterHints = 76,\n\tpeekWidgetDefaultFocus = 77,\n\tdefinitionLinkOpensInPeek = 78,\n\tquickSuggestions = 79,\n\tquickSuggestionsDelay = 80,\n\treadOnly = 81,\n\trenameOnType = 82,\n\trenderControlCharacters = 83,\n\trenderFinalNewline = 84,\n\trenderLineHighlight = 85,\n\trenderLineHighlightOnlyWhenFocus = 86,\n\trenderValidationDecorations = 87,\n\trenderWhitespace = 88,\n\trevealHorizontalRightPadding = 89,\n\troundedSelection = 90,\n\trulers = 91,\n\tscrollbar = 92,\n\tscrollBeyondLastColumn = 93,\n\tscrollBeyondLastLine = 94,\n\tscrollPredominantAxis = 95,\n\tselectionClipboard = 96,\n\tselectionHighlight = 97,\n\tselectOnLineNumbers = 98,\n\tshowFoldingControls = 99,\n\tshowUnused = 100,\n\tsnippetSuggestions = 101,\n\tsmartSelect = 102,\n\tsmoothScrolling = 103,\n\tstickyTabStops = 104,\n\tstopRenderingLineAfter = 105,\n\tsuggest = 106,\n\tsuggestFontSize = 107,\n\tsuggestLineHeight = 108,\n\tsuggestOnTriggerCharacters = 109,\n\tsuggestSelection = 110,\n\ttabCompletion = 111,\n\ttabIndex = 112,\n\tunicodeHighlighting = 113,\n\tunusualLineTerminators = 114,\n\tuseShadowDOM = 115,\n\tuseTabStops = 116,\n\twordSeparators = 117,\n\twordWrap = 118,\n\twordWrapBreakAfterCharacters = 119,\n\twordWrapBreakBeforeCharacters = 120,\n\twordWrapColumn = 121,\n\twordWrapOverride1 = 122,\n\twordWrapOverride2 = 123,\n\twrappingIndent = 124,\n\twrappingStrategy = 125,\n\tshowDeprecated = 126,\n\tinlayHints = 127,\n\teditorClassName = 128,\n\tpixelRatio = 129,\n\ttabFocusMode = 130,\n\tlayoutInfo = 131,\n\twrappingInfo = 132\n}\n\n/**\n * End of line character preference.\n */\nexport enum EndOfLinePreference {\n\t/**\n\t * Use the end of line character identified in the text buffer.\n\t */\n\tTextDefined = 0,\n\t/**\n\t * Use line feed (\\n) as the end of line character.\n\t */\n\tLF = 1,\n\t/**\n\t * Use carriage return and line feed (\\r\\n) as the end of line character.\n\t */\n\tCRLF = 2\n}\n\n/**\n * End of line character preference.\n */\nexport enum EndOfLineSequence {\n\t/**\n\t * Use line feed (\\n) as the end of line character.\n\t */\n\tLF = 0,\n\t/**\n\t * Use carriage return and line feed (\\r\\n) as the end of line character.\n\t */\n\tCRLF = 1\n}\n\n/**\n * Describes what to do with the indentation when pressing Enter.\n */\nexport enum IndentAction {\n\t/**\n\t * Insert new line and copy the previous line's indentation.\n\t */\n\tNone = 0,\n\t/**\n\t * Insert new line and indent once (relative to the previous line's indentation).\n\t */\n\tIndent = 1,\n\t/**\n\t * Insert two new lines:\n\t * - the first one indented which will hold the cursor\n\t * - the second one at the same indentation level\n\t */\n\tIndentOutdent = 2,\n\t/**\n\t * Insert new line and outdent once (relative to the previous line's indentation).\n\t */\n\tOutdent = 3\n}\n\nexport enum InjectedTextCursorStops {\n\tBoth = 0,\n\tRight = 1,\n\tLeft = 2,\n\tNone = 3\n}\n\nexport enum InlayHintKind {\n\tOther = 0,\n\tType = 1,\n\tParameter = 2\n}\n\n/**\n * How an {@link InlineCompletionsProvider inline completion provider} was triggered.\n */\nexport enum InlineCompletionTriggerKind {\n\t/**\n\t * Completion was triggered automatically while editing.\n\t * It is sufficient to return a single completion item in this case.\n\t */\n\tAutomatic = 0,\n\t/**\n\t * Completion was triggered explicitly by a user gesture.\n\t * Return multiple completion items to enable cycling through them.\n\t */\n\tExplicit = 1\n}\n/**\n * Virtual Key Codes, the value does not hold any inherent meaning.\n * Inspired somewhat from https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx\n * But these are \"more general\", as they should work across browsers & OS`s.\n */\nexport enum KeyCode {\n\tDependsOnKbLayout = -1,\n\t/**\n\t * Placed first to cover the 0 value of the enum.\n\t */\n\tUnknown = 0,\n\tBackspace = 1,\n\tTab = 2,\n\tEnter = 3,\n\tShift = 4,\n\tCtrl = 5,\n\tAlt = 6,\n\tPauseBreak = 7,\n\tCapsLock = 8,\n\tEscape = 9,\n\tSpace = 10,\n\tPageUp = 11,\n\tPageDown = 12,\n\tEnd = 13,\n\tHome = 14,\n\tLeftArrow = 15,\n\tUpArrow = 16,\n\tRightArrow = 17,\n\tDownArrow = 18,\n\tInsert = 19,\n\tDelete = 20,\n\tDigit0 = 21,\n\tDigit1 = 22,\n\tDigit2 = 23,\n\tDigit3 = 24,\n\tDigit4 = 25,\n\tDigit5 = 26,\n\tDigit6 = 27,\n\tDigit7 = 28,\n\tDigit8 = 29,\n\tDigit9 = 30,\n\tKeyA = 31,\n\tKeyB = 32,\n\tKeyC = 33,\n\tKeyD = 34,\n\tKeyE = 35,\n\tKeyF = 36,\n\tKeyG = 37,\n\tKeyH = 38,\n\tKeyI = 39,\n\tKeyJ = 40,\n\tKeyK = 41,\n\tKeyL = 42,\n\tKeyM = 43,\n\tKeyN = 44,\n\tKeyO = 45,\n\tKeyP = 46,\n\tKeyQ = 47,\n\tKeyR = 48,\n\tKeyS = 49,\n\tKeyT = 50,\n\tKeyU = 51,\n\tKeyV = 52,\n\tKeyW = 53,\n\tKeyX = 54,\n\tKeyY = 55,\n\tKeyZ = 56,\n\tMeta = 57,\n\tContextMenu = 58,\n\tF1 = 59,\n\tF2 = 60,\n\tF3 = 61,\n\tF4 = 62,\n\tF5 = 63,\n\tF6 = 64,\n\tF7 = 65,\n\tF8 = 66,\n\tF9 = 67,\n\tF10 = 68,\n\tF11 = 69,\n\tF12 = 70,\n\tF13 = 71,\n\tF14 = 72,\n\tF15 = 73,\n\tF16 = 74,\n\tF17 = 75,\n\tF18 = 76,\n\tF19 = 77,\n\tNumLock = 78,\n\tScrollLock = 79,\n\t/**\n\t * Used for miscellaneous characters; it can vary by keyboard.\n\t * For the US standard keyboard, the ';:' key\n\t */\n\tSemicolon = 80,\n\t/**\n\t * For any country/region, the '+' key\n\t * For the US standard keyboard, the '=+' key\n\t */\n\tEqual = 81,\n\t/**\n\t * For any country/region, the ',' key\n\t * For the US standard keyboard, the ',<' key\n\t */\n\tComma = 82,\n\t/**\n\t * For any country/region, the '-' key\n\t * For the US standard keyboard, the '-_' key\n\t */\n\tMinus = 83,\n\t/**\n\t * For any country/region, the '.' key\n\t * For the US standard keyboard, the '.>' key\n\t */\n\tPeriod = 84,\n\t/**\n\t * Used for miscellaneous characters; it can vary by keyboard.\n\t * For the US standard keyboard, the '/?' key\n\t */\n\tSlash = 85,\n\t/**\n\t * Used for miscellaneous characters; it can vary by keyboard.\n\t * For the US standard keyboard, the '`~' key\n\t */\n\tBackquote = 86,\n\t/**\n\t * Used for miscellaneous characters; it can vary by keyboard.\n\t * For the US standard keyboard, the '[{' key\n\t */\n\tBracketLeft = 87,\n\t/**\n\t * Used for miscellaneous characters; it can vary by keyboard.\n\t * For the US standard keyboard, the '\\|' key\n\t */\n\tBackslash = 88,\n\t/**\n\t * Used for miscellaneous characters; it can vary by keyboard.\n\t * For the US standard keyboard, the ']}' key\n\t */\n\tBracketRight = 89,\n\t/**\n\t * Used for miscellaneous characters; it can vary by keyboard.\n\t * For the US standard keyboard, the ''\"' key\n\t */\n\tQuote = 90,\n\t/**\n\t * Used for miscellaneous characters; it can vary by keyboard.\n\t */\n\tOEM_8 = 91,\n\t/**\n\t * Either the angle bracket key or the backslash key on the RT 102-key keyboard.\n\t */\n\tIntlBackslash = 92,\n\tNumpad0 = 93,\n\tNumpad1 = 94,\n\tNumpad2 = 95,\n\tNumpad3 = 96,\n\tNumpad4 = 97,\n\tNumpad5 = 98,\n\tNumpad6 = 99,\n\tNumpad7 = 100,\n\tNumpad8 = 101,\n\tNumpad9 = 102,\n\tNumpadMultiply = 103,\n\tNumpadAdd = 104,\n\tNUMPAD_SEPARATOR = 105,\n\tNumpadSubtract = 106,\n\tNumpadDecimal = 107,\n\tNumpadDivide = 108,\n\t/**\n\t * Cover all key codes when IME is processing input.\n\t */\n\tKEY_IN_COMPOSITION = 109,\n\tABNT_C1 = 110,\n\tABNT_C2 = 111,\n\tAudioVolumeMute = 112,\n\tAudioVolumeUp = 113,\n\tAudioVolumeDown = 114,\n\tBrowserSearch = 115,\n\tBrowserHome = 116,\n\tBrowserBack = 117,\n\tBrowserForward = 118,\n\tMediaTrackNext = 119,\n\tMediaTrackPrevious = 120,\n\tMediaStop = 121,\n\tMediaPlayPause = 122,\n\tLaunchMediaPlayer = 123,\n\tLaunchMail = 124,\n\tLaunchApp2 = 125,\n\t/**\n\t * Placed last to cover the length of the enum.\n\t * Please do not depend on this value!\n\t */\n\tMAX_VALUE = 126\n}\n\nexport enum MarkerSeverity {\n\tHint = 1,\n\tInfo = 2,\n\tWarning = 4,\n\tError = 8\n}\n\nexport enum MarkerTag {\n\tUnnecessary = 1,\n\tDeprecated = 2\n}\n\n/**\n * Position in the minimap to render the decoration.\n */\nexport enum MinimapPosition {\n\tInline = 1,\n\tGutter = 2\n}\n\n/**\n * Type of hit element with the mouse in the editor.\n */\nexport enum MouseTargetType {\n\t/**\n\t * Mouse is on top of an unknown element.\n\t */\n\tUNKNOWN = 0,\n\t/**\n\t * Mouse is on top of the textarea used for input.\n\t */\n\tTEXTAREA = 1,\n\t/**\n\t * Mouse is on top of the glyph margin\n\t */\n\tGUTTER_GLYPH_MARGIN = 2,\n\t/**\n\t * Mouse is on top of the line numbers\n\t */\n\tGUTTER_LINE_NUMBERS = 3,\n\t/**\n\t * Mouse is on top of the line decorations\n\t */\n\tGUTTER_LINE_DECORATIONS = 4,\n\t/**\n\t * Mouse is on top of the whitespace left in the gutter by a view zone.\n\t */\n\tGUTTER_VIEW_ZONE = 5,\n\t/**\n\t * Mouse is on top of text in the content.\n\t */\n\tCONTENT_TEXT = 6,\n\t/**\n\t * Mouse is on top of empty space in the content (e.g. after line text or below last line)\n\t */\n\tCONTENT_EMPTY = 7,\n\t/**\n\t * Mouse is on top of a view zone in the content.\n\t */\n\tCONTENT_VIEW_ZONE = 8,\n\t/**\n\t * Mouse is on top of a content widget.\n\t */\n\tCONTENT_WIDGET = 9,\n\t/**\n\t * Mouse is on top of the decorations overview ruler.\n\t */\n\tOVERVIEW_RULER = 10,\n\t/**\n\t * Mouse is on top of a scrollbar.\n\t */\n\tSCROLLBAR = 11,\n\t/**\n\t * Mouse is on top of an overlay widget.\n\t */\n\tOVERLAY_WIDGET = 12,\n\t/**\n\t * Mouse is outside of the editor.\n\t */\n\tOUTSIDE_EDITOR = 13\n}\n\n/**\n * A positioning preference for rendering overlay widgets.\n */\nexport enum OverlayWidgetPositionPreference {\n\t/**\n\t * Position the overlay widget in the top right corner\n\t */\n\tTOP_RIGHT_CORNER = 0,\n\t/**\n\t * Position the overlay widget in the bottom right corner\n\t */\n\tBOTTOM_RIGHT_CORNER = 1,\n\t/**\n\t * Position the overlay widget in the top center\n\t */\n\tTOP_CENTER = 2\n}\n\n/**\n * Vertical Lane in the overview ruler of the editor.\n */\nexport enum OverviewRulerLane {\n\tLeft = 1,\n\tCenter = 2,\n\tRight = 4,\n\tFull = 7\n}\n\nexport enum PositionAffinity {\n\t/**\n\t * Prefers the left most position.\n\t*/\n\tLeft = 0,\n\t/**\n\t * Prefers the right most position.\n\t*/\n\tRight = 1,\n\t/**\n\t * No preference.\n\t*/\n\tNone = 2\n}\n\nexport enum RenderLineNumbersType {\n\tOff = 0,\n\tOn = 1,\n\tRelative = 2,\n\tInterval = 3,\n\tCustom = 4\n}\n\nexport enum RenderMinimap {\n\tNone = 0,\n\tText = 1,\n\tBlocks = 2\n}\n\nexport enum ScrollType {\n\tSmooth = 0,\n\tImmediate = 1\n}\n\nexport enum ScrollbarVisibility {\n\tAuto = 1,\n\tHidden = 2,\n\tVisible = 3\n}\n\n/**\n * The direction of a selection.\n */\nexport enum SelectionDirection {\n\t/**\n\t * The selection starts above where it ends.\n\t */\n\tLTR = 0,\n\t/**\n\t * The selection starts below where it ends.\n\t */\n\tRTL = 1\n}\n\nexport enum SignatureHelpTriggerKind {\n\tInvoke = 1,\n\tTriggerCharacter = 2,\n\tContentChange = 3\n}\n\n/**\n * A symbol kind.\n */\nexport enum SymbolKind {\n\tFile = 0,\n\tModule = 1,\n\tNamespace = 2,\n\tPackage = 3,\n\tClass = 4,\n\tMethod = 5,\n\tProperty = 6,\n\tField = 7,\n\tConstructor = 8,\n\tEnum = 9,\n\tInterface = 10,\n\tFunction = 11,\n\tVariable = 12,\n\tConstant = 13,\n\tString = 14,\n\tNumber = 15,\n\tBoolean = 16,\n\tArray = 17,\n\tObject = 18,\n\tKey = 19,\n\tNull = 20,\n\tEnumMember = 21,\n\tStruct = 22,\n\tEvent = 23,\n\tOperator = 24,\n\tTypeParameter = 25\n}\n\nexport enum SymbolTag {\n\tDeprecated = 1\n}\n\n/**\n * The kind of animation in which the editor's cursor should be rendered.\n */\nexport enum TextEditorCursorBlinkingStyle {\n\t/**\n\t * Hidden\n\t */\n\tHidden = 0,\n\t/**\n\t * Blinking\n\t */\n\tBlink = 1,\n\t/**\n\t * Blinking with smooth fading\n\t */\n\tSmooth = 2,\n\t/**\n\t * Blinking with prolonged filled state and smooth fading\n\t */\n\tPhase = 3,\n\t/**\n\t * Expand collapse animation on the y axis\n\t */\n\tExpand = 4,\n\t/**\n\t * No-Blinking\n\t */\n\tSolid = 5\n}\n\n/**\n * The style in which the editor's cursor should be rendered.\n */\nexport enum TextEditorCursorStyle {\n\t/**\n\t * As a vertical line (sitting between two characters).\n\t */\n\tLine = 1,\n\t/**\n\t * As a block (sitting on top of a character).\n\t */\n\tBlock = 2,\n\t/**\n\t * As a horizontal line (sitting under a character).\n\t */\n\tUnderline = 3,\n\t/**\n\t * As a thin vertical line (sitting between two characters).\n\t */\n\tLineThin = 4,\n\t/**\n\t * As an outlined block (sitting on top of a character).\n\t */\n\tBlockOutline = 5,\n\t/**\n\t * As a thin horizontal line (sitting under a character).\n\t */\n\tUnderlineThin = 6\n}\n\n/**\n * Describes the behavior of decorations when typing/editing near their edges.\n * Note: Please do not edit the values, as they very carefully match `DecorationRangeBehavior`\n */\nexport enum TrackedRangeStickiness {\n\tAlwaysGrowsWhenTypingAtEdges = 0,\n\tNeverGrowsWhenTypingAtEdges = 1,\n\tGrowsOnlyWhenTypingBefore = 2,\n\tGrowsOnlyWhenTypingAfter = 3\n}\n\n/**\n * Describes how to indent wrapped lines.\n */\nexport enum WrappingIndent {\n\t/**\n\t * No indentation => wrapped lines begin at column 1.\n\t */\n\tNone = 0,\n\t/**\n\t * Same => wrapped lines get the same indentation as the parent.\n\t */\n\tSame = 1,\n\t/**\n\t * Indent => wrapped lines get +1 indentation toward the parent.\n\t */\n\tIndent = 2,\n\t/**\n\t * DeepIndent => wrapped lines get +2 indentation toward the parent.\n\t */\n\tDeepIndent = 3\n}","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport { IPosition } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\n\nexport interface IBracketPairsTextModelPart {\n\t/**\n\t * Is fired when bracket pairs change, either due to a text or a settings change.\n\t*/\n\tonDidChange: Event;\n\n\t/**\n\t * Gets all bracket pairs that intersect the given position.\n\t * The result is sorted by the start position.\n\t */\n\tgetBracketPairsInRange(range: IRange): BracketPairInfo[];\n\n\t/**\n\t * Gets all bracket pairs that intersect the given position.\n\t * The result is sorted by the start position.\n\t */\n\tgetBracketPairsInRangeWithMinIndentation(range: IRange): BracketPairWithMinIndentationInfo[];\n\n\tgetBracketsInRange(range: IRange): BracketInfo[];\n\n\t/**\n\t * Find the matching bracket of `request` up, counting brackets.\n\t * @param request The bracket we're searching for\n\t * @param position The position at which to start the search.\n\t * @return The range of the matching bracket, or null if the bracket match was not found.\n\t */\n\tfindMatchingBracketUp(bracket: string, position: IPosition): Range | null;\n\n\t/**\n\t * Find the first bracket in the model before `position`.\n\t * @param position The position at which to start the search.\n\t * @return The info for the first bracket before `position`, or null if there are no more brackets before `positions`.\n\t */\n\tfindPrevBracket(position: IPosition): IFoundBracket | null;\n\n\t/**\n\t * Find the first bracket in the model after `position`.\n\t * @param position The position at which to start the search.\n\t * @return The info for the first bracket after `position`, or null if there are no more brackets after `positions`.\n\t */\n\tfindNextBracket(position: IPosition): IFoundBracket | null;\n\n\t/**\n\t * Find the enclosing brackets that contain `position`.\n\t * @param position The position at which to start the search.\n\t */\n\tfindEnclosingBrackets(position: IPosition, maxDuration?: number): [Range, Range] | null;\n\n\t/**\n\t * Given a `position`, if the position is on top or near a bracket,\n\t * find the matching bracket of that bracket and return the ranges of both brackets.\n\t * @param position The position at which to look for a bracket.\n\t */\n\tmatchBracket(position: IPosition): [Range, Range] | null;\n}\n\nexport interface IFoundBracket {\n\trange: Range;\n\topen: string[];\n\tclose: string[];\n\tisOpen: boolean;\n}\n\nexport class BracketInfo {\n\tconstructor(\n\t\tpublic readonly range: Range,\n\t\t/** 0-based level */\n\t\tpublic readonly nestingLevel: number,\n\t\tpublic readonly isInvalid: boolean,\n\t) { }\n}\n\nexport class BracketPairInfo {\n\tconstructor(\n\t\tpublic readonly range: Range,\n\t\tpublic readonly openingBracketRange: Range,\n\t\tpublic readonly closingBracketRange: Range | undefined,\n\t\t/**\n\t\t * 0-based\n\t\t*/\n\t\tpublic readonly nestingLevel: number,\n\t) { }\n}\n\nexport class BracketPairWithMinIndentationInfo extends BracketPairInfo {\n\tconstructor(\n\t\trange: Range,\n\t\topeningBracketRange: Range,\n\t\tclosingBracketRange: Range | undefined,\n\t\t/**\n\t\t * 0-based\n\t\t*/\n\t\tnestingLevel: number,\n\t\t/**\n\t\t * -1 if not requested, otherwise the size of the minimum indentation in the bracket pair in terms of visible columns.\n\t\t*/\n\t\tpublic readonly minVisibleColumnIndentation: number,\n\t) {\n\t\tsuper(range, openingBracketRange, closingBracketRange, nestingLevel);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IRange } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { IModelDecoration, InjectedTextOptions } from 'vs/editor/common/model';\n\n/**\n * An event describing that the current language associated with a model has changed.\n */\nexport interface IModelLanguageChangedEvent {\n\t/**\n\t * Previous language\n\t */\n\treadonly oldLanguage: string;\n\t/**\n\t * New language\n\t */\n\treadonly newLanguage: string;\n}\n\n/**\n * An event describing that the language configuration associated with a model has changed.\n */\nexport interface IModelLanguageConfigurationChangedEvent {\n}\n\nexport interface IModelContentChange {\n\t/**\n\t * The range that got replaced.\n\t */\n\treadonly range: IRange;\n\t/**\n\t * The offset of the range that got replaced.\n\t */\n\treadonly rangeOffset: number;\n\t/**\n\t * The length of the range that got replaced.\n\t */\n\treadonly rangeLength: number;\n\t/**\n\t * The new text for the range.\n\t */\n\treadonly text: string;\n}\n\n/**\n * An event describing a change in the text of a model.\n */\nexport interface IModelContentChangedEvent {\n\treadonly changes: IModelContentChange[];\n\t/**\n\t * The (new) end-of-line character.\n\t */\n\treadonly eol: string;\n\t/**\n\t * The new version id the model has transitioned to.\n\t */\n\treadonly versionId: number;\n\t/**\n\t * Flag that indicates that this event was generated while undoing.\n\t */\n\treadonly isUndoing: boolean;\n\t/**\n\t * Flag that indicates that this event was generated while redoing.\n\t */\n\treadonly isRedoing: boolean;\n\t/**\n\t * Flag that indicates that all decorations were lost with this edit.\n\t * The model has been reset to a new value.\n\t */\n\treadonly isFlush: boolean;\n}\n\n/**\n * An event describing that model decorations have changed.\n */\nexport interface IModelDecorationsChangedEvent {\n\treadonly affectsMinimap: boolean;\n\treadonly affectsOverviewRuler: boolean;\n}\n\n/**\n * An event describing that some ranges of lines have been tokenized (their tokens have changed).\n * @internal\n */\nexport interface IModelTokensChangedEvent {\n\treadonly tokenizationSupportChanged: boolean;\n\treadonly semanticTokensApplied: boolean;\n\treadonly ranges: {\n\t\t/**\n\t\t * The start of the range (inclusive)\n\t\t */\n\t\treadonly fromLineNumber: number;\n\t\t/**\n\t\t * The end of the range (inclusive)\n\t\t */\n\t\treadonly toLineNumber: number;\n\t}[];\n}\n\nexport interface IModelOptionsChangedEvent {\n\treadonly tabSize: boolean;\n\treadonly indentSize: boolean;\n\treadonly insertSpaces: boolean;\n\treadonly trimAutoWhitespace: boolean;\n}\n\n/**\n * @internal\n */\nexport const enum RawContentChangedType {\n\tFlush = 1,\n\tLineChanged = 2,\n\tLinesDeleted = 3,\n\tLinesInserted = 4,\n\tEOLChanged = 5\n}\n\n/**\n * An event describing that a model has been reset to a new value.\n * @internal\n */\nexport class ModelRawFlush {\n\tpublic readonly changeType = RawContentChangedType.Flush;\n}\n\n/**\n * Represents text injected on a line\n * @internal\n */\nexport class LineInjectedText {\n\tpublic static applyInjectedText(lineText: string, injectedTexts: LineInjectedText[] | null): string {\n\t\tif (!injectedTexts || injectedTexts.length === 0) {\n\t\t\treturn lineText;\n\t\t}\n\t\tlet result = '';\n\t\tlet lastOriginalOffset = 0;\n\t\tfor (const injectedText of injectedTexts) {\n\t\t\tresult += lineText.substring(lastOriginalOffset, injectedText.column - 1);\n\t\t\tlastOriginalOffset = injectedText.column - 1;\n\t\t\tresult += injectedText.options.content;\n\t\t}\n\t\tresult += lineText.substring(lastOriginalOffset);\n\t\treturn result;\n\t}\n\n\tpublic static fromDecorations(decorations: IModelDecoration[]): LineInjectedText[] {\n\t\tconst result: LineInjectedText[] = [];\n\t\tfor (const decoration of decorations) {\n\t\t\tif (decoration.options.before && decoration.options.before.content.length > 0) {\n\t\t\t\tresult.push(new LineInjectedText(\n\t\t\t\t\tdecoration.ownerId,\n\t\t\t\t\tdecoration.range.startLineNumber,\n\t\t\t\t\tdecoration.range.startColumn,\n\t\t\t\t\tdecoration.options.before,\n\t\t\t\t\t0,\n\t\t\t\t));\n\t\t\t}\n\t\t\tif (decoration.options.after && decoration.options.after.content.length > 0) {\n\t\t\t\tresult.push(new LineInjectedText(\n\t\t\t\t\tdecoration.ownerId,\n\t\t\t\t\tdecoration.range.endLineNumber,\n\t\t\t\t\tdecoration.range.endColumn,\n\t\t\t\t\tdecoration.options.after,\n\t\t\t\t\t1,\n\t\t\t\t));\n\t\t\t}\n\t\t}\n\t\tresult.sort((a, b) => {\n\t\t\tif (a.lineNumber === b.lineNumber) {\n\t\t\t\tif (a.column === b.column) {\n\t\t\t\t\treturn a.order - b.order;\n\t\t\t\t}\n\t\t\t\treturn a.column - b.column;\n\t\t\t}\n\t\t\treturn a.lineNumber - b.lineNumber;\n\t\t});\n\t\treturn result;\n\t}\n\n\tconstructor(\n\t\tpublic readonly ownerId: number,\n\t\tpublic readonly lineNumber: number,\n\t\tpublic readonly column: number,\n\t\tpublic readonly options: InjectedTextOptions,\n\t\tpublic readonly order: number\n\t) { }\n}\n\n/**\n * An event describing that a line has changed in a model.\n * @internal\n */\nexport class ModelRawLineChanged {\n\tpublic readonly changeType = RawContentChangedType.LineChanged;\n\t/**\n\t * The line that has changed.\n\t */\n\tpublic readonly lineNumber: number;\n\t/**\n\t * The new value of the line.\n\t */\n\tpublic readonly detail: string;\n\t/**\n\t * The injected text on the line.\n\t */\n\tpublic readonly injectedText: LineInjectedText[] | null;\n\n\tconstructor(lineNumber: number, detail: string, injectedText: LineInjectedText[] | null) {\n\t\tthis.lineNumber = lineNumber;\n\t\tthis.detail = detail;\n\t\tthis.injectedText = injectedText;\n\t}\n}\n\n/**\n * An event describing that line(s) have been deleted in a model.\n * @internal\n */\nexport class ModelRawLinesDeleted {\n\tpublic readonly changeType = RawContentChangedType.LinesDeleted;\n\t/**\n\t * At what line the deletion began (inclusive).\n\t */\n\tpublic readonly fromLineNumber: number;\n\t/**\n\t * At what line the deletion stopped (inclusive).\n\t */\n\tpublic readonly toLineNumber: number;\n\n\tconstructor(fromLineNumber: number, toLineNumber: number) {\n\t\tthis.fromLineNumber = fromLineNumber;\n\t\tthis.toLineNumber = toLineNumber;\n\t}\n}\n\n/**\n * An event describing that line(s) have been inserted in a model.\n * @internal\n */\nexport class ModelRawLinesInserted {\n\tpublic readonly changeType = RawContentChangedType.LinesInserted;\n\t/**\n\t * Before what line did the insertion begin\n\t */\n\tpublic readonly fromLineNumber: number;\n\t/**\n\t * `toLineNumber` - `fromLineNumber` + 1 denotes the number of lines that were inserted\n\t */\n\tpublic readonly toLineNumber: number;\n\t/**\n\t * The text that was inserted\n\t */\n\tpublic readonly detail: string[];\n\t/**\n\t * The injected texts for every inserted line.\n\t */\n\tpublic readonly injectedTexts: (LineInjectedText[] | null)[];\n\n\tconstructor(fromLineNumber: number, toLineNumber: number, detail: string[], injectedTexts: (LineInjectedText[] | null)[]) {\n\t\tthis.injectedTexts = injectedTexts;\n\t\tthis.fromLineNumber = fromLineNumber;\n\t\tthis.toLineNumber = toLineNumber;\n\t\tthis.detail = detail;\n\t}\n}\n\n/**\n * An event describing that a model has had its EOL changed.\n * @internal\n */\nexport class ModelRawEOLChanged {\n\tpublic readonly changeType = RawContentChangedType.EOLChanged;\n}\n\n/**\n * @internal\n */\nexport type ModelRawChange = ModelRawFlush | ModelRawLineChanged | ModelRawLinesDeleted | ModelRawLinesInserted | ModelRawEOLChanged;\n\n/**\n * An event describing a change in the text of a model.\n * @internal\n */\nexport class ModelRawContentChangedEvent {\n\n\tpublic readonly changes: ModelRawChange[];\n\t/**\n\t * The new version id the model has transitioned to.\n\t */\n\tpublic readonly versionId: number;\n\t/**\n\t * Flag that indicates that this event was generated while undoing.\n\t */\n\tpublic readonly isUndoing: boolean;\n\t/**\n\t * Flag that indicates that this event was generated while redoing.\n\t */\n\tpublic readonly isRedoing: boolean;\n\n\tpublic resultingSelection: Selection[] | null;\n\n\tconstructor(changes: ModelRawChange[], versionId: number, isUndoing: boolean, isRedoing: boolean) {\n\t\tthis.changes = changes;\n\t\tthis.versionId = versionId;\n\t\tthis.isUndoing = isUndoing;\n\t\tthis.isRedoing = isRedoing;\n\t\tthis.resultingSelection = null;\n\t}\n\n\tpublic containsEvent(type: RawContentChangedType): boolean {\n\t\tfor (let i = 0, len = this.changes.length; i < len; i++) {\n\t\t\tconst change = this.changes[i];\n\t\t\tif (change.changeType === type) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic static merge(a: ModelRawContentChangedEvent, b: ModelRawContentChangedEvent): ModelRawContentChangedEvent {\n\t\tconst changes = ([] as ModelRawChange[]).concat(a.changes).concat(b.changes);\n\t\tconst versionId = b.versionId;\n\t\tconst isUndoing = (a.isUndoing || b.isUndoing);\n\t\tconst isRedoing = (a.isRedoing || b.isRedoing);\n\t\treturn new ModelRawContentChangedEvent(changes, versionId, isUndoing, isRedoing);\n\t}\n}\n\n/**\n * An event describing a change in injected text.\n * @internal\n */\nexport class ModelInjectedTextChangedEvent {\n\n\tpublic readonly changes: ModelRawLineChanged[];\n\n\tconstructor(changes: ModelRawLineChanged[]) {\n\t\tthis.changes = changes;\n\t}\n}\n\n/**\n * @internal\n */\nexport class InternalModelContentChangeEvent {\n\tconstructor(\n\t\tpublic readonly rawContentChangedEvent: ModelRawContentChangedEvent,\n\t\tpublic readonly contentChangedEvent: IModelContentChangedEvent,\n\t) { }\n\n\tpublic merge(other: InternalModelContentChangeEvent): InternalModelContentChangeEvent {\n\t\tconst rawContentChangedEvent = ModelRawContentChangedEvent.merge(this.rawContentChangedEvent, other.rawContentChangedEvent);\n\t\tconst contentChangedEvent = InternalModelContentChangeEvent._mergeChangeEvents(this.contentChangedEvent, other.contentChangedEvent);\n\t\treturn new InternalModelContentChangeEvent(rawContentChangedEvent, contentChangedEvent);\n\t}\n\n\tprivate static _mergeChangeEvents(a: IModelContentChangedEvent, b: IModelContentChangedEvent): IModelContentChangedEvent {\n\t\tconst changes = ([] as IModelContentChange[]).concat(a.changes).concat(b.changes);\n\t\tconst eol = b.eol;\n\t\tconst versionId = b.versionId;\n\t\tconst isUndoing = (a.isUndoing || b.isUndoing);\n\t\tconst isRedoing = (a.isRedoing || b.isRedoing);\n\t\tconst isFlush = (a.isFlush || b.isFlush);\n\t\treturn {\n\t\t\tchanges: changes,\n\t\t\teol: eol,\n\t\t\tversionId: versionId,\n\t\t\tisUndoing: isUndoing,\n\t\t\tisRedoing: isRedoing,\n\t\t\tisFlush: isFlush\n\t\t};\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IPosition } from 'vs/editor/common/core/position';\n\nexport interface IGuidesTextModelPart {\n\t/**\n\t * @internal\n\t */\n\tgetActiveIndentGuide(lineNumber: number, minLineNumber: number, maxLineNumber: number): IActiveIndentGuideInfo;\n\n\t/**\n\t * @internal\n\t */\n\tgetLinesIndentGuides(startLineNumber: number, endLineNumber: number): number[];\n\n\t/**\n\t * @internal\n\t */\n\tgetLinesBracketGuides(startLineNumber: number, endLineNumber: number, activePosition: IPosition | null, options: BracketGuideOptions): IndentGuide[][];\n}\n\nexport interface IActiveIndentGuideInfo {\n\tstartLineNumber: number;\n\tendLineNumber: number;\n\tindent: number;\n}\n\nexport enum HorizontalGuidesState {\n\tDisabled,\n\tEnabledForActive,\n\tEnabled\n}\n\nexport interface BracketGuideOptions {\n\tincludeInactive: boolean,\n\thorizontalGuides: HorizontalGuidesState,\n\thighlightActive: boolean,\n}\n\nexport class IndentGuide {\n\tconstructor(\n\t\tpublic readonly visibleColumn: number,\n\t\tpublic readonly className: string,\n\t\t/**\n\t\t * If set, this indent guide is a horizontal guide (no vertical part).\n\t\t * It starts at visibleColumn and continues until endColumn.\n\t\t*/\n\t\tpublic readonly horizontalLine: IndentGuideHorizontalLine | null,\n\t) { }\n}\n\nexport class IndentGuideHorizontalLine {\n\tconstructor(\n\t\tpublic readonly top: boolean,\n\t\tpublic readonly endColumn: number,\n\t) { }\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ArrayQueue, findLast } from 'vs/base/common/arrays';\nimport * as strings from 'vs/base/common/strings';\nimport { CursorColumns } from 'vs/editor/common/core/cursorColumns';\nimport { IPosition, Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { BracketPairInfo } from 'vs/editor/common/textModelBracketPairs';\nimport { TextModel } from 'vs/editor/common/model/textModel';\nimport { TextModelPart } from 'vs/editor/common/model/textModelPart';\nimport { computeIndentLevel } from 'vs/editor/common/model/utils';\nimport { ILanguageConfigurationService, ResolvedLanguageConfiguration } from 'vs/editor/common/languages/languageConfigurationRegistry';\nimport { BracketGuideOptions, HorizontalGuidesState, IActiveIndentGuideInfo, IGuidesTextModelPart, IndentGuide, IndentGuideHorizontalLine } from 'vs/editor/common/textModelGuides';\n\nexport class GuidesTextModelPart extends TextModelPart implements IGuidesTextModelPart {\n\tconstructor(\n\t\tprivate readonly textModel: TextModel,\n\t\tprivate readonly languageConfigurationService: ILanguageConfigurationService\n\t) {\n\t\tsuper();\n\t}\n\n\tprivate getLanguageConfiguration(\n\t\tlanguageId: string\n\t): ResolvedLanguageConfiguration {\n\t\treturn this.languageConfigurationService.getLanguageConfiguration(\n\t\t\tlanguageId\n\t\t);\n\t}\n\n\tprivate _computeIndentLevel(lineIndex: number): number {\n\t\treturn computeIndentLevel(\n\t\t\tthis.textModel.getLineContent(lineIndex + 1),\n\t\t\tthis.textModel.getOptions().tabSize\n\t\t);\n\t}\n\n\tpublic getActiveIndentGuide(\n\t\tlineNumber: number,\n\t\tminLineNumber: number,\n\t\tmaxLineNumber: number\n\t): IActiveIndentGuideInfo {\n\t\tthis.assertNotDisposed();\n\t\tconst lineCount = this.textModel.getLineCount();\n\n\t\tif (lineNumber < 1 || lineNumber > lineCount) {\n\t\t\tthrow new Error('Illegal value for lineNumber');\n\t\t}\n\n\t\tconst foldingRules = this.getLanguageConfiguration(\n\t\t\tthis.textModel.getLanguageId()\n\t\t).foldingRules;\n\t\tconst offSide = Boolean(foldingRules && foldingRules.offSide);\n\n\t\tlet up_aboveContentLineIndex =\n\t\t\t-2; /* -2 is a marker for not having computed it */\n\t\tlet up_aboveContentLineIndent = -1;\n\t\tlet up_belowContentLineIndex =\n\t\t\t-2; /* -2 is a marker for not having computed it */\n\t\tlet up_belowContentLineIndent = -1;\n\t\tconst up_resolveIndents = (lineNumber: number) => {\n\t\t\tif (\n\t\t\t\tup_aboveContentLineIndex !== -1 &&\n\t\t\t\t(up_aboveContentLineIndex === -2 ||\n\t\t\t\t\tup_aboveContentLineIndex > lineNumber - 1)\n\t\t\t) {\n\t\t\t\tup_aboveContentLineIndex = -1;\n\t\t\t\tup_aboveContentLineIndent = -1;\n\n\t\t\t\t// must find previous line with content\n\t\t\t\tfor (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) {\n\t\t\t\t\tconst indent = this._computeIndentLevel(lineIndex);\n\t\t\t\t\tif (indent >= 0) {\n\t\t\t\t\t\tup_aboveContentLineIndex = lineIndex;\n\t\t\t\t\t\tup_aboveContentLineIndent = indent;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (up_belowContentLineIndex === -2) {\n\t\t\t\tup_belowContentLineIndex = -1;\n\t\t\t\tup_belowContentLineIndent = -1;\n\n\t\t\t\t// must find next line with content\n\t\t\t\tfor (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) {\n\t\t\t\t\tconst indent = this._computeIndentLevel(lineIndex);\n\t\t\t\t\tif (indent >= 0) {\n\t\t\t\t\t\tup_belowContentLineIndex = lineIndex;\n\t\t\t\t\t\tup_belowContentLineIndent = indent;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tlet down_aboveContentLineIndex =\n\t\t\t-2; /* -2 is a marker for not having computed it */\n\t\tlet down_aboveContentLineIndent = -1;\n\t\tlet down_belowContentLineIndex =\n\t\t\t-2; /* -2 is a marker for not having computed it */\n\t\tlet down_belowContentLineIndent = -1;\n\t\tconst down_resolveIndents = (lineNumber: number) => {\n\t\t\tif (down_aboveContentLineIndex === -2) {\n\t\t\t\tdown_aboveContentLineIndex = -1;\n\t\t\t\tdown_aboveContentLineIndent = -1;\n\n\t\t\t\t// must find previous line with content\n\t\t\t\tfor (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) {\n\t\t\t\t\tconst indent = this._computeIndentLevel(lineIndex);\n\t\t\t\t\tif (indent >= 0) {\n\t\t\t\t\t\tdown_aboveContentLineIndex = lineIndex;\n\t\t\t\t\t\tdown_aboveContentLineIndent = indent;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tdown_belowContentLineIndex !== -1 &&\n\t\t\t\t(down_belowContentLineIndex === -2 ||\n\t\t\t\t\tdown_belowContentLineIndex < lineNumber - 1)\n\t\t\t) {\n\t\t\t\tdown_belowContentLineIndex = -1;\n\t\t\t\tdown_belowContentLineIndent = -1;\n\n\t\t\t\t// must find next line with content\n\t\t\t\tfor (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) {\n\t\t\t\t\tconst indent = this._computeIndentLevel(lineIndex);\n\t\t\t\t\tif (indent >= 0) {\n\t\t\t\t\t\tdown_belowContentLineIndex = lineIndex;\n\t\t\t\t\t\tdown_belowContentLineIndent = indent;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tlet startLineNumber = 0;\n\t\tlet goUp = true;\n\t\tlet endLineNumber = 0;\n\t\tlet goDown = true;\n\t\tlet indent = 0;\n\n\t\tlet initialIndent = 0;\n\n\t\tfor (let distance = 0; goUp || goDown; distance++) {\n\t\t\tconst upLineNumber = lineNumber - distance;\n\t\t\tconst downLineNumber = lineNumber + distance;\n\n\t\t\tif (distance > 1 && (upLineNumber < 1 || upLineNumber < minLineNumber)) {\n\t\t\t\tgoUp = false;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tdistance > 1 &&\n\t\t\t\t(downLineNumber > lineCount || downLineNumber > maxLineNumber)\n\t\t\t) {\n\t\t\t\tgoDown = false;\n\t\t\t}\n\t\t\tif (distance > 50000) {\n\t\t\t\t// stop processing\n\t\t\t\tgoUp = false;\n\t\t\t\tgoDown = false;\n\t\t\t}\n\n\t\t\tlet upLineIndentLevel: number = -1;\n\t\t\tif (goUp && upLineNumber >= 1) {\n\t\t\t\t// compute indent level going up\n\t\t\t\tconst currentIndent = this._computeIndentLevel(upLineNumber - 1);\n\t\t\t\tif (currentIndent >= 0) {\n\t\t\t\t\t// This line has content (besides whitespace)\n\t\t\t\t\t// Use the line's indent\n\t\t\t\t\tup_belowContentLineIndex = upLineNumber - 1;\n\t\t\t\t\tup_belowContentLineIndent = currentIndent;\n\t\t\t\t\tupLineIndentLevel = Math.ceil(\n\t\t\t\t\t\tcurrentIndent / this.textModel.getOptions().indentSize\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tup_resolveIndents(upLineNumber);\n\t\t\t\t\tupLineIndentLevel = this._getIndentLevelForWhitespaceLine(\n\t\t\t\t\t\toffSide,\n\t\t\t\t\t\tup_aboveContentLineIndent,\n\t\t\t\t\t\tup_belowContentLineIndent\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet downLineIndentLevel = -1;\n\t\t\tif (goDown && downLineNumber <= lineCount) {\n\t\t\t\t// compute indent level going down\n\t\t\t\tconst currentIndent = this._computeIndentLevel(downLineNumber - 1);\n\t\t\t\tif (currentIndent >= 0) {\n\t\t\t\t\t// This line has content (besides whitespace)\n\t\t\t\t\t// Use the line's indent\n\t\t\t\t\tdown_aboveContentLineIndex = downLineNumber - 1;\n\t\t\t\t\tdown_aboveContentLineIndent = currentIndent;\n\t\t\t\t\tdownLineIndentLevel = Math.ceil(\n\t\t\t\t\t\tcurrentIndent / this.textModel.getOptions().indentSize\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tdown_resolveIndents(downLineNumber);\n\t\t\t\t\tdownLineIndentLevel = this._getIndentLevelForWhitespaceLine(\n\t\t\t\t\t\toffSide,\n\t\t\t\t\t\tdown_aboveContentLineIndent,\n\t\t\t\t\t\tdown_belowContentLineIndent\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (distance === 0) {\n\t\t\t\tinitialIndent = upLineIndentLevel;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (distance === 1) {\n\t\t\t\tif (\n\t\t\t\t\tdownLineNumber <= lineCount &&\n\t\t\t\t\tdownLineIndentLevel >= 0 &&\n\t\t\t\t\tinitialIndent + 1 === downLineIndentLevel\n\t\t\t\t) {\n\t\t\t\t\t// This is the beginning of a scope, we have special handling here, since we want the\n\t\t\t\t\t// child scope indent to be active, not the parent scope\n\t\t\t\t\tgoUp = false;\n\t\t\t\t\tstartLineNumber = downLineNumber;\n\t\t\t\t\tendLineNumber = downLineNumber;\n\t\t\t\t\tindent = downLineIndentLevel;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tupLineNumber >= 1 &&\n\t\t\t\t\tupLineIndentLevel >= 0 &&\n\t\t\t\t\tupLineIndentLevel - 1 === initialIndent\n\t\t\t\t) {\n\t\t\t\t\t// This is the end of a scope, just like above\n\t\t\t\t\tgoDown = false;\n\t\t\t\t\tstartLineNumber = upLineNumber;\n\t\t\t\t\tendLineNumber = upLineNumber;\n\t\t\t\t\tindent = upLineIndentLevel;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tstartLineNumber = lineNumber;\n\t\t\t\tendLineNumber = lineNumber;\n\t\t\t\tindent = initialIndent;\n\t\t\t\tif (indent === 0) {\n\t\t\t\t\t// No need to continue\n\t\t\t\t\treturn { startLineNumber, endLineNumber, indent };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (goUp) {\n\t\t\t\tif (upLineIndentLevel >= indent) {\n\t\t\t\t\tstartLineNumber = upLineNumber;\n\t\t\t\t} else {\n\t\t\t\t\tgoUp = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (goDown) {\n\t\t\t\tif (downLineIndentLevel >= indent) {\n\t\t\t\t\tendLineNumber = downLineNumber;\n\t\t\t\t} else {\n\t\t\t\t\tgoDown = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { startLineNumber, endLineNumber, indent };\n\t}\n\n\tpublic getLinesBracketGuides(\n\t\tstartLineNumber: number,\n\t\tendLineNumber: number,\n\t\tactivePosition: IPosition | null,\n\t\toptions: BracketGuideOptions\n\t): IndentGuide[][] {\n\t\tconst result: IndentGuide[][] = [];\n\t\tconst bracketPairs =\n\t\t\tthis.textModel.bracketPairs.getBracketPairsInRangeWithMinIndentation(\n\t\t\t\tnew Range(\n\t\t\t\t\tstartLineNumber,\n\t\t\t\t\t1,\n\t\t\t\t\tendLineNumber,\n\t\t\t\t\tthis.textModel.getLineMaxColumn(endLineNumber)\n\t\t\t\t)\n\t\t\t);\n\n\t\tlet activeBracketPairRange: Range | undefined = undefined;\n\t\tif (activePosition && bracketPairs.length > 0) {\n\t\t\tconst bracketsContainingActivePosition =\n\t\t\t\tstartLineNumber <= activePosition.lineNumber &&\n\t\t\t\t\tactivePosition.lineNumber <= endLineNumber\n\t\t\t\t\t? // Does active position intersect with the view port? -> Intersect bracket pairs with activePosition\n\t\t\t\t\tbracketPairs.filter((bp) =>\n\t\t\t\t\t\tRange.strictContainsPosition(bp.range, activePosition)\n\t\t\t\t\t)\n\t\t\t\t\t: this.textModel.bracketPairs.getBracketPairsInRange(\n\t\t\t\t\t\tRange.fromPositions(activePosition)\n\t\t\t\t\t);\n\n\t\t\tactiveBracketPairRange = findLast(\n\t\t\t\tbracketsContainingActivePosition,\n\t\t\t\t/* Exclude single line bracket pairs for cases such as\n\t\t\t\t * ```\n\t\t\t\t * function test() {\n\t\t\t\t * \t\tif (true) { | }\n\t\t\t\t * }\n\t\t\t\t * ```\n\t\t\t\t */\n\t\t\t\t(i) => i.range.startLineNumber !== i.range.endLineNumber\n\t\t\t)?.range;\n\t\t}\n\n\t\tconst queue = new ArrayQueue(bracketPairs);\n\t\t/** Indexed by nesting level */\n\t\tconst activeGuides = new Array<{\n\t\t\tnestingLevel: number;\n\t\t\tguideVisibleColumn: number;\n\t\t\tstart: Position;\n\t\t\tvisibleStartColumn: number;\n\t\t\tend: Position;\n\t\t\tvisibleEndColumn: number;\n\t\t\tbracketPair: BracketPairInfo;\n\t\t\trenderHorizontalEndLineAtTheBottom: boolean;\n\t\t} | null>();\n\t\tconst nextGuides = new Array();\n\t\tconst colorProvider = new BracketPairGuidesClassNames();\n\n\t\tfor (\n\t\t\tlet lineNumber = startLineNumber;\n\t\t\tlineNumber <= endLineNumber;\n\t\t\tlineNumber++\n\t\t) {\n\t\t\tlet guides = new Array();\n\t\t\tif (nextGuides.length > 0) {\n\t\t\t\tguides = guides.concat(nextGuides);\n\t\t\t\tnextGuides.length = 0;\n\t\t\t}\n\t\t\tresult.push(guides);\n\n\t\t\t// Update activeGuides\n\t\t\tfor (const pair of queue.takeWhile(\n\t\t\t\t(b) => b.openingBracketRange.startLineNumber <= lineNumber\n\t\t\t) || []) {\n\t\t\t\tif (pair.range.startLineNumber === pair.range.endLineNumber) {\n\t\t\t\t\t// ignore single line brackets\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst guideVisibleColumn = Math.min(\n\t\t\t\t\tthis.getVisibleColumnFromPosition(\n\t\t\t\t\t\tpair.openingBracketRange.getStartPosition()\n\t\t\t\t\t),\n\t\t\t\t\tthis.getVisibleColumnFromPosition(\n\t\t\t\t\t\tpair.closingBracketRange?.getStartPosition() ??\n\t\t\t\t\t\tpair.range.getEndPosition()\n\t\t\t\t\t),\n\t\t\t\t\tpair.minVisibleColumnIndentation + 1\n\t\t\t\t);\n\t\t\t\tlet renderHorizontalEndLineAtTheBottom = false;\n\t\t\t\tif (pair.closingBracketRange) {\n\t\t\t\t\tconst firstNonWsIndex = strings.firstNonWhitespaceIndex(\n\t\t\t\t\t\tthis.textModel.getLineContent(\n\t\t\t\t\t\t\tpair.closingBracketRange.startLineNumber\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t\tif (firstNonWsIndex < pair.closingBracketRange.startColumn - 1) {\n\t\t\t\t\t\trenderHorizontalEndLineAtTheBottom = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst start = pair.openingBracketRange.getStartPosition();\n\t\t\t\tconst end =\n\t\t\t\t\tpair.closingBracketRange?.getStartPosition() ??\n\t\t\t\t\tpair.range.getEndPosition();\n\n\t\t\t\tif (pair.closingBracketRange === undefined) {\n\t\t\t\t\t// Don't show guides for bracket pairs that are not balanced.\n\t\t\t\t\t// See #135125.\n\t\t\t\t\tactiveGuides[pair.nestingLevel] = null;\n\t\t\t\t} else {\n\t\t\t\t\tactiveGuides[pair.nestingLevel] = {\n\t\t\t\t\t\tnestingLevel: pair.nestingLevel,\n\t\t\t\t\t\tguideVisibleColumn,\n\t\t\t\t\t\tstart,\n\t\t\t\t\t\tvisibleStartColumn: this.getVisibleColumnFromPosition(start),\n\t\t\t\t\t\tend,\n\t\t\t\t\t\tvisibleEndColumn: this.getVisibleColumnFromPosition(end),\n\t\t\t\t\t\tbracketPair: pair,\n\t\t\t\t\t\trenderHorizontalEndLineAtTheBottom,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const line of activeGuides) {\n\t\t\t\tif (!line) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst isActive =\n\t\t\t\t\tactiveBracketPairRange &&\n\t\t\t\t\tline.bracketPair.range.equalsRange(activeBracketPairRange);\n\n\t\t\t\tconst className =\n\t\t\t\t\tcolorProvider.getInlineClassNameOfLevel(line.nestingLevel) +\n\t\t\t\t\t(options.highlightActive && isActive\n\t\t\t\t\t\t? ' ' + colorProvider.activeClassName\n\t\t\t\t\t\t: '');\n\n\t\t\t\tif (\n\t\t\t\t\t(isActive &&\n\t\t\t\t\t\toptions.horizontalGuides !==\n\t\t\t\t\t\tHorizontalGuidesState.Disabled) ||\n\t\t\t\t\t(options.includeInactive &&\n\t\t\t\t\t\toptions.horizontalGuides === HorizontalGuidesState.Enabled)\n\t\t\t\t) {\n\t\t\t\t\tif (line.start.lineNumber === lineNumber) {\n\t\t\t\t\t\tif (line.guideVisibleColumn < line.visibleStartColumn) {\n\t\t\t\t\t\t\tguides.push(\n\t\t\t\t\t\t\t\tnew IndentGuide(\n\t\t\t\t\t\t\t\t\tline.guideVisibleColumn,\n\t\t\t\t\t\t\t\t\tclassName,\n\t\t\t\t\t\t\t\t\tnew IndentGuideHorizontalLine(false, line.start.column)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (line.end.lineNumber === lineNumber + 1) {\n\t\t\t\t\t\t// The next line might have horizontal guides.\n\t\t\t\t\t\t// However, the next line might also have a new bracket pair with the same indentation,\n\t\t\t\t\t\t// so the current bracket pair might get replaced. That's why we push the guide to nextGuides one line ahead.\n\t\t\t\t\t\tif (line.guideVisibleColumn < line.visibleEndColumn) {\n\t\t\t\t\t\t\tnextGuides.push(\n\t\t\t\t\t\t\t\tnew IndentGuide(\n\t\t\t\t\t\t\t\t\tline.guideVisibleColumn,\n\t\t\t\t\t\t\t\t\tclassName,\n\t\t\t\t\t\t\t\t\tnew IndentGuideHorizontalLine(\n\t\t\t\t\t\t\t\t\t\t!line.renderHorizontalEndLineAtTheBottom,\n\t\t\t\t\t\t\t\t\t\tline.end.column\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet lastVisibleColumnCount = Number.MAX_SAFE_INTEGER;\n\t\t\t// Going backwards, so the last guide potentially replaces others\n\t\t\tfor (let i = activeGuides.length - 1; i >= 0; i--) {\n\t\t\t\tconst line = activeGuides[i];\n\t\t\t\tif (!line) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst isActive =\n\t\t\t\t\toptions.highlightActive &&\n\t\t\t\t\tactiveBracketPairRange &&\n\t\t\t\t\tline.bracketPair.range.equalsRange(activeBracketPairRange);\n\n\t\t\t\tconst className =\n\t\t\t\t\tcolorProvider.getInlineClassNameOfLevel(line.nestingLevel) +\n\t\t\t\t\t(isActive ? ' ' + colorProvider.activeClassName : '');\n\n\t\t\t\tif (isActive || options.includeInactive) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tline.renderHorizontalEndLineAtTheBottom &&\n\t\t\t\t\t\tline.end.lineNumber === lineNumber + 1\n\t\t\t\t\t) {\n\t\t\t\t\t\tnextGuides.push(\n\t\t\t\t\t\t\tnew IndentGuide(line.guideVisibleColumn, className, null)\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tline.end.lineNumber <= lineNumber ||\n\t\t\t\t\tline.start.lineNumber >= lineNumber\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (line.guideVisibleColumn >= lastVisibleColumnCount && !isActive) {\n\t\t\t\t\t// Don't render a guide on top of an existing guide, unless it is active.\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlastVisibleColumnCount = line.guideVisibleColumn;\n\n\t\t\t\tif (isActive || options.includeInactive) {\n\t\t\t\t\tguides.push(\n\t\t\t\t\t\tnew IndentGuide(line.guideVisibleColumn, className, null)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tguides.sort((a, b) => a.visibleColumn - b.visibleColumn);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate getVisibleColumnFromPosition(position: Position): number {\n\t\treturn (\n\t\t\tCursorColumns.visibleColumnFromColumn(\n\t\t\t\tthis.textModel.getLineContent(position.lineNumber),\n\t\t\t\tposition.column,\n\t\t\t\tthis.textModel.getOptions().tabSize\n\t\t\t) + 1\n\t\t);\n\t}\n\n\tpublic getLinesIndentGuides(\n\t\tstartLineNumber: number,\n\t\tendLineNumber: number\n\t): number[] {\n\t\tthis.assertNotDisposed();\n\t\tconst lineCount = this.textModel.getLineCount();\n\n\t\tif (startLineNumber < 1 || startLineNumber > lineCount) {\n\t\t\tthrow new Error('Illegal value for startLineNumber');\n\t\t}\n\t\tif (endLineNumber < 1 || endLineNumber > lineCount) {\n\t\t\tthrow new Error('Illegal value for endLineNumber');\n\t\t}\n\n\t\tconst options = this.textModel.getOptions();\n\t\tconst foldingRules = this.getLanguageConfiguration(\n\t\t\tthis.textModel.getLanguageId()\n\t\t).foldingRules;\n\t\tconst offSide = Boolean(foldingRules && foldingRules.offSide);\n\n\t\tconst result: number[] = new Array(\n\t\t\tendLineNumber - startLineNumber + 1\n\t\t);\n\n\t\tlet aboveContentLineIndex =\n\t\t\t-2; /* -2 is a marker for not having computed it */\n\t\tlet aboveContentLineIndent = -1;\n\n\t\tlet belowContentLineIndex =\n\t\t\t-2; /* -2 is a marker for not having computed it */\n\t\tlet belowContentLineIndent = -1;\n\n\t\tfor (\n\t\t\tlet lineNumber = startLineNumber;\n\t\t\tlineNumber <= endLineNumber;\n\t\t\tlineNumber++\n\t\t) {\n\t\t\tconst resultIndex = lineNumber - startLineNumber;\n\n\t\t\tconst currentIndent = this._computeIndentLevel(lineNumber - 1);\n\t\t\tif (currentIndent >= 0) {\n\t\t\t\t// This line has content (besides whitespace)\n\t\t\t\t// Use the line's indent\n\t\t\t\taboveContentLineIndex = lineNumber - 1;\n\t\t\t\taboveContentLineIndent = currentIndent;\n\t\t\t\tresult[resultIndex] = Math.ceil(currentIndent / options.indentSize);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (aboveContentLineIndex === -2) {\n\t\t\t\taboveContentLineIndex = -1;\n\t\t\t\taboveContentLineIndent = -1;\n\n\t\t\t\t// must find previous line with content\n\t\t\t\tfor (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) {\n\t\t\t\t\tconst indent = this._computeIndentLevel(lineIndex);\n\t\t\t\t\tif (indent >= 0) {\n\t\t\t\t\t\taboveContentLineIndex = lineIndex;\n\t\t\t\t\t\taboveContentLineIndent = indent;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tbelowContentLineIndex !== -1 &&\n\t\t\t\t(belowContentLineIndex === -2 || belowContentLineIndex < lineNumber - 1)\n\t\t\t) {\n\t\t\t\tbelowContentLineIndex = -1;\n\t\t\t\tbelowContentLineIndent = -1;\n\n\t\t\t\t// must find next line with content\n\t\t\t\tfor (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) {\n\t\t\t\t\tconst indent = this._computeIndentLevel(lineIndex);\n\t\t\t\t\tif (indent >= 0) {\n\t\t\t\t\t\tbelowContentLineIndex = lineIndex;\n\t\t\t\t\t\tbelowContentLineIndent = indent;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tresult[resultIndex] = this._getIndentLevelForWhitespaceLine(\n\t\t\t\toffSide,\n\t\t\t\taboveContentLineIndent,\n\t\t\t\tbelowContentLineIndent\n\t\t\t);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate _getIndentLevelForWhitespaceLine(\n\t\toffSide: boolean,\n\t\taboveContentLineIndent: number,\n\t\tbelowContentLineIndent: number\n\t): number {\n\t\tconst options = this.textModel.getOptions();\n\n\t\tif (aboveContentLineIndent === -1 || belowContentLineIndent === -1) {\n\t\t\t// At the top or bottom of the file\n\t\t\treturn 0;\n\t\t} else if (aboveContentLineIndent < belowContentLineIndent) {\n\t\t\t// we are inside the region above\n\t\t\treturn 1 + Math.floor(aboveContentLineIndent / options.indentSize);\n\t\t} else if (aboveContentLineIndent === belowContentLineIndent) {\n\t\t\t// we are in between two regions\n\t\t\treturn Math.ceil(belowContentLineIndent / options.indentSize);\n\t\t} else {\n\t\t\tif (offSide) {\n\t\t\t\t// same level as region below\n\t\t\t\treturn Math.ceil(belowContentLineIndent / options.indentSize);\n\t\t\t} else {\n\t\t\t\t// we are inside the region that ends below\n\t\t\t\treturn 1 + Math.floor(belowContentLineIndent / options.indentSize);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class BracketPairGuidesClassNames {\n\tpublic readonly activeClassName = 'indent-active';\n\n\tgetInlineClassNameOfLevel(level: number): string {\n\t\t// To support a dynamic amount of colors up to 6 colors,\n\t\t// we use a number that is a lcm of all numbers from 1 to 6.\n\t\treturn `bracket-indent-guide lvl-${level % 30}`;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Color } from 'vs/base/common/color';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { ColorId, ITokenizationRegistry, ITokenizationSupport, ITokenizationSupportChangedEvent, ITokenizationSupportFactory } from 'vs/editor/common/languages';\n\nexport class TokenizationRegistry implements ITokenizationRegistry {\n\n\tprivate readonly _map = new Map();\n\tprivate readonly _factories = new Map();\n\n\tprivate readonly _onDidChange = new Emitter();\n\tpublic readonly onDidChange: Event = this._onDidChange.event;\n\n\tprivate _colorMap: Color[] | null;\n\n\tconstructor() {\n\t\tthis._colorMap = null;\n\t}\n\n\tpublic fire(languages: string[]): void {\n\t\tthis._onDidChange.fire({\n\t\t\tchangedLanguages: languages,\n\t\t\tchangedColorMap: false\n\t\t});\n\t}\n\n\tpublic register(language: string, support: ITokenizationSupport) {\n\t\tthis._map.set(language, support);\n\t\tthis.fire([language]);\n\t\treturn toDisposable(() => {\n\t\t\tif (this._map.get(language) !== support) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._map.delete(language);\n\t\t\tthis.fire([language]);\n\t\t});\n\t}\n\n\tpublic registerFactory(languageId: string, factory: ITokenizationSupportFactory): IDisposable {\n\t\tthis._factories.get(languageId)?.dispose();\n\t\tconst myData = new TokenizationSupportFactoryData(this, languageId, factory);\n\t\tthis._factories.set(languageId, myData);\n\t\treturn toDisposable(() => {\n\t\t\tconst v = this._factories.get(languageId);\n\t\t\tif (!v || v !== myData) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._factories.delete(languageId);\n\t\t\tv.dispose();\n\t\t});\n\t}\n\n\tpublic async getOrCreate(languageId: string): Promise {\n\t\t// check first if the support is already set\n\t\tconst tokenizationSupport = this.get(languageId);\n\t\tif (tokenizationSupport) {\n\t\t\treturn tokenizationSupport;\n\t\t}\n\n\t\tconst factory = this._factories.get(languageId);\n\t\tif (!factory || factory.isResolved) {\n\t\t\t// no factory or factory.resolve already finished\n\t\t\treturn null;\n\t\t}\n\n\t\tawait factory.resolve();\n\n\t\treturn this.get(languageId);\n\t}\n\n\tpublic get(language: string): ITokenizationSupport | null {\n\t\treturn (this._map.get(language) || null);\n\t}\n\n\tpublic isResolved(languageId: string): boolean {\n\t\tconst tokenizationSupport = this.get(languageId);\n\t\tif (tokenizationSupport) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst factory = this._factories.get(languageId);\n\t\tif (!factory || factory.isResolved) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic setColorMap(colorMap: Color[]): void {\n\t\tthis._colorMap = colorMap;\n\t\tthis._onDidChange.fire({\n\t\t\tchangedLanguages: Array.from(this._map.keys()),\n\t\t\tchangedColorMap: true\n\t\t});\n\t}\n\n\tpublic getColorMap(): Color[] | null {\n\t\treturn this._colorMap;\n\t}\n\n\tpublic getDefaultBackground(): Color | null {\n\t\tif (this._colorMap && this._colorMap.length > ColorId.DefaultBackground) {\n\t\t\treturn this._colorMap[ColorId.DefaultBackground];\n\t\t}\n\t\treturn null;\n\t}\n}\n\nclass TokenizationSupportFactoryData extends Disposable {\n\n\tprivate _isDisposed: boolean = false;\n\tprivate _resolvePromise: Promise | null = null;\n\tprivate _isResolved: boolean = false;\n\n\tpublic get isResolved(): boolean {\n\t\treturn this._isResolved;\n\t}\n\n\tconstructor(\n\t\tprivate readonly _registry: TokenizationRegistry,\n\t\tprivate readonly _languageId: string,\n\t\tprivate readonly _factory: ITokenizationSupportFactory,\n\t) {\n\t\tsuper();\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._isDisposed = true;\n\t\tsuper.dispose();\n\t}\n\n\tpublic async resolve(): Promise {\n\t\tif (!this._resolvePromise) {\n\t\t\tthis._resolvePromise = this._create();\n\t\t}\n\t\treturn this._resolvePromise;\n\t}\n\n\tprivate async _create(): Promise {\n\t\tconst value = await Promise.resolve(this._factory.createTokenizationSupport());\n\t\tthis._isResolved = true;\n\t\tif (value && !this._isDisposed) {\n\t\t\tthis._register(this._registry.register(this._languageId, value));\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { Color } from 'vs/base/common/color';\nimport { Event } from 'vs/base/common/event';\nimport { IMarkdownString } from 'vs/base/common/htmlContent';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { URI } from 'vs/base/common/uri';\nimport { IPosition, Position } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport * as model from 'vs/editor/common/model';\nimport { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry';\nimport { TokenizationRegistry as TokenizationRegistryImpl } from 'vs/editor/common/tokenizationRegistry';\nimport { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';\nimport { IMarkerData } from 'vs/platform/markers/common/markers';\nimport { Codicon, CSSIcon } from 'vs/base/common/codicons';\nimport { ISingleEditOperation } from 'vs/editor/common/core/editOperation';\n\n/**\n * Open ended enum at runtime\n * @internal\n */\nexport const enum LanguageId {\n\tNull = 0,\n\tPlainText = 1\n}\n\n/**\n * A font style. Values are 2^x such that a bit mask can be used.\n * @internal\n */\nexport const enum FontStyle {\n\tNotSet = -1,\n\tNone = 0,\n\tItalic = 1,\n\tBold = 2,\n\tUnderline = 4,\n\tStrikethrough = 8,\n}\n\n/**\n * Open ended enum at runtime\n * @internal\n */\nexport const enum ColorId {\n\tNone = 0,\n\tDefaultForeground = 1,\n\tDefaultBackground = 2\n}\n\n/**\n * A standard token type.\n * @internal\n */\nexport const enum StandardTokenType {\n\tOther = 0,\n\tComment = 1,\n\tString = 2,\n\tRegEx = 3\n}\n\n/**\n * Helpers to manage the \"collapsed\" metadata of an entire StackElement stack.\n * The following assumptions have been made:\n * - languageId < 256 => needs 8 bits\n * - unique color count < 512 => needs 9 bits\n *\n * The binary format is:\n * - -------------------------------------------\n * 3322 2222 2222 1111 1111 1100 0000 0000\n * 1098 7654 3210 9876 5432 1098 7654 3210\n * - -------------------------------------------\n * xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx\n * bbbb bbbb bfff ffff ffFF FFTT LLLL LLLL\n * - -------------------------------------------\n * - L = LanguageId (8 bits)\n * - T = StandardTokenType (2 bits)\n * - F = FontStyle (4 bits)\n * - f = foreground color (9 bits)\n * - b = background color (9 bits)\n *\n * @internal\n */\nexport const enum MetadataConsts {\n\tLANGUAGEID_MASK = 0b00000000000000000000000011111111,\n\tTOKEN_TYPE_MASK = 0b00000000000000000000001100000000,\n\tFONT_STYLE_MASK = 0b00000000000000000011110000000000,\n\tFOREGROUND_MASK = 0b00000000011111111100000000000000,\n\tBACKGROUND_MASK = 0b11111111100000000000000000000000,\n\n\tITALIC_MASK = 0b00000000000000000000010000000000,\n\tBOLD_MASK = 0b00000000000000000000100000000000,\n\tUNDERLINE_MASK = 0b00000000000000000001000000000000,\n\tSTRIKETHROUGH_MASK = 0b00000000000000000010000000000000,\n\n\t// Semantic tokens cannot set the language id, so we can\n\t// use the first 8 bits for control purposes\n\tSEMANTIC_USE_ITALIC = 0b00000000000000000000000000000001,\n\tSEMANTIC_USE_BOLD = 0b00000000000000000000000000000010,\n\tSEMANTIC_USE_UNDERLINE = 0b00000000000000000000000000000100,\n\tSEMANTIC_USE_STRIKETHROUGH = 0b00000000000000000000000000001000,\n\tSEMANTIC_USE_FOREGROUND = 0b00000000000000000000000000010000,\n\tSEMANTIC_USE_BACKGROUND = 0b00000000000000000000000000100000,\n\n\tLANGUAGEID_OFFSET = 0,\n\tTOKEN_TYPE_OFFSET = 8,\n\tFONT_STYLE_OFFSET = 10,\n\tFOREGROUND_OFFSET = 14,\n\tBACKGROUND_OFFSET = 23\n}\n\n/**\n * @internal\n */\nexport class TokenMetadata {\n\n\tpublic static getLanguageId(metadata: number): LanguageId {\n\t\treturn (metadata & MetadataConsts.LANGUAGEID_MASK) >>> MetadataConsts.LANGUAGEID_OFFSET;\n\t}\n\n\tpublic static getTokenType(metadata: number): StandardTokenType {\n\t\treturn (metadata & MetadataConsts.TOKEN_TYPE_MASK) >>> MetadataConsts.TOKEN_TYPE_OFFSET;\n\t}\n\n\tpublic static getFontStyle(metadata: number): FontStyle {\n\t\treturn (metadata & MetadataConsts.FONT_STYLE_MASK) >>> MetadataConsts.FONT_STYLE_OFFSET;\n\t}\n\n\tpublic static getForeground(metadata: number): ColorId {\n\t\treturn (metadata & MetadataConsts.FOREGROUND_MASK) >>> MetadataConsts.FOREGROUND_OFFSET;\n\t}\n\n\tpublic static getBackground(metadata: number): ColorId {\n\t\treturn (metadata & MetadataConsts.BACKGROUND_MASK) >>> MetadataConsts.BACKGROUND_OFFSET;\n\t}\n\n\tpublic static getClassNameFromMetadata(metadata: number): string {\n\t\tconst foreground = this.getForeground(metadata);\n\t\tlet className = 'mtk' + foreground;\n\n\t\tconst fontStyle = this.getFontStyle(metadata);\n\t\tif (fontStyle & FontStyle.Italic) {\n\t\t\tclassName += ' mtki';\n\t\t}\n\t\tif (fontStyle & FontStyle.Bold) {\n\t\t\tclassName += ' mtkb';\n\t\t}\n\t\tif (fontStyle & FontStyle.Underline) {\n\t\t\tclassName += ' mtku';\n\t\t}\n\t\tif (fontStyle & FontStyle.Strikethrough) {\n\t\t\tclassName += ' mtks';\n\t\t}\n\n\t\treturn className;\n\t}\n\n\tpublic static getInlineStyleFromMetadata(metadata: number, colorMap: string[]): string {\n\t\tconst foreground = this.getForeground(metadata);\n\t\tconst fontStyle = this.getFontStyle(metadata);\n\n\t\tlet result = `color: ${colorMap[foreground]};`;\n\t\tif (fontStyle & FontStyle.Italic) {\n\t\t\tresult += 'font-style: italic;';\n\t\t}\n\t\tif (fontStyle & FontStyle.Bold) {\n\t\t\tresult += 'font-weight: bold;';\n\t\t}\n\t\tlet textDecoration = '';\n\t\tif (fontStyle & FontStyle.Underline) {\n\t\t\ttextDecoration += ' underline';\n\t\t}\n\t\tif (fontStyle & FontStyle.Strikethrough) {\n\t\t\ttextDecoration += ' line-through';\n\t\t}\n\t\tif (textDecoration) {\n\t\t\tresult += `text-decoration:${textDecoration};`;\n\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic static getPresentationFromMetadata(metadata: number): ITokenPresentation {\n\t\tconst foreground = this.getForeground(metadata);\n\t\tconst fontStyle = this.getFontStyle(metadata);\n\n\t\treturn {\n\t\t\tforeground: foreground,\n\t\t\titalic: Boolean(fontStyle & FontStyle.Italic),\n\t\t\tbold: Boolean(fontStyle & FontStyle.Bold),\n\t\t\tunderline: Boolean(fontStyle & FontStyle.Underline),\n\t\t\tstrikethrough: Boolean(fontStyle & FontStyle.Strikethrough),\n\t\t};\n\t}\n}\n\n/**\n * @internal\n */\nexport interface ITokenPresentation {\n\tforeground: ColorId;\n\titalic: boolean;\n\tbold: boolean;\n\tunderline: boolean;\n\tstrikethrough: boolean;\n}\n\n/**\n * @internal\n */\nexport interface ILanguageIdCodec {\n\tencodeLanguageId(languageId: string): LanguageId;\n\tdecodeLanguageId(languageId: LanguageId): string;\n}\n\nexport class Token {\n\t_tokenBrand: void = undefined;\n\n\tpublic readonly offset: number;\n\tpublic readonly type: string;\n\tpublic readonly language: string;\n\n\tconstructor(offset: number, type: string, language: string) {\n\t\tthis.offset = offset;\n\t\tthis.type = type;\n\t\tthis.language = language;\n\t}\n\n\tpublic toString(): string {\n\t\treturn '(' + this.offset + ', ' + this.type + ')';\n\t}\n}\n\n/**\n * @internal\n */\nexport class TokenizationResult {\n\t_tokenizationResultBrand: void = undefined;\n\n\tpublic readonly tokens: Token[];\n\tpublic readonly endState: IState;\n\n\tconstructor(tokens: Token[], endState: IState) {\n\t\tthis.tokens = tokens;\n\t\tthis.endState = endState;\n\t}\n}\n\n/**\n * @internal\n */\nexport class EncodedTokenizationResult {\n\t_encodedTokenizationResultBrand: void = undefined;\n\n\t/**\n\t * The tokens in binary format. Each token occupies two array indices. For token i:\n\t * - at offset 2*i => startIndex\n\t * - at offset 2*i + 1 => metadata\n\t *\n\t */\n\tpublic readonly tokens: Uint32Array;\n\tpublic readonly endState: IState;\n\n\tconstructor(tokens: Uint32Array, endState: IState) {\n\t\tthis.tokens = tokens;\n\t\tthis.endState = endState;\n\t}\n}\n\n/**\n * @internal\n */\nexport interface ITokenizationSupport {\n\n\tgetInitialState(): IState;\n\n\ttokenize(line: string, hasEOL: boolean, state: IState): TokenizationResult;\n\n\ttokenizeEncoded(line: string, hasEOL: boolean, state: IState): EncodedTokenizationResult;\n}\n\n/**\n * The state of the tokenizer between two lines.\n * It is useful to store flags such as in multiline comment, etc.\n * The model will clone the previous line's state and pass it in to tokenize the next line.\n */\nexport interface IState {\n\tclone(): IState;\n\tequals(other: IState): boolean;\n}\n\n/**\n * A provider result represents the values a provider, like the {@link HoverProvider},\n * may return. For once this is the actual result type `T`, like `Hover`, or a thenable that resolves\n * to that type `T`. In addition, `null` and `undefined` can be returned - either directly or from a\n * thenable.\n */\nexport type ProviderResult = T | undefined | null | Thenable;\n\n/**\n * A hover represents additional information for a symbol or word. Hovers are\n * rendered in a tooltip-like widget.\n */\nexport interface Hover {\n\t/**\n\t * The contents of this hover.\n\t */\n\tcontents: IMarkdownString[];\n\n\t/**\n\t * The range to which this hover applies. When missing, the\n\t * editor will use the range at the current position or the\n\t * current position itself.\n\t */\n\trange?: IRange;\n}\n\n/**\n * The hover provider interface defines the contract between extensions and\n * the [hover](https://code.visualstudio.com/docs/editor/intellisense)-feature.\n */\nexport interface HoverProvider {\n\t/**\n\t * Provide a hover for the given position and document. Multiple hovers at the same\n\t * position will be merged by the editor. A hover can have a range which defaults\n\t * to the word range at the position when omitted.\n\t */\n\tprovideHover(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult;\n}\n\n\n/**\n * The evaluatable expression provider interface defines the contract between extensions and\n * the debug hover.\n * @internal\n */\nexport interface EvaluatableExpressionProvider {\n}\n\n/**\n * The inline values provider interface defines the contract between extensions and\n * the debugger's inline values feature.\n * @internal\n */\nexport interface InlineValuesProvider {\n}\n\nexport const enum CompletionItemKind {\n\tMethod,\n\tFunction,\n\tConstructor,\n\tField,\n\tVariable,\n\tClass,\n\tStruct,\n\tInterface,\n\tModule,\n\tProperty,\n\tEvent,\n\tOperator,\n\tUnit,\n\tValue,\n\tConstant,\n\tEnum,\n\tEnumMember,\n\tKeyword,\n\tText,\n\tColor,\n\tFile,\n\tReference,\n\tCustomcolor,\n\tFolder,\n\tTypeParameter,\n\tUser,\n\tIssue,\n\tSnippet, // <- highest value (used for compare!)\n}\n\n/**\n * @internal\n */\nexport namespace CompletionItemKinds {\n\n\tconst byKind = new Map();\n\tbyKind.set(CompletionItemKind.Method, Codicon.symbolMethod);\n\tbyKind.set(CompletionItemKind.Function, Codicon.symbolFunction);\n\tbyKind.set(CompletionItemKind.Constructor, Codicon.symbolConstructor);\n\tbyKind.set(CompletionItemKind.Field, Codicon.symbolField);\n\tbyKind.set(CompletionItemKind.Variable, Codicon.symbolVariable);\n\tbyKind.set(CompletionItemKind.Class, Codicon.symbolClass);\n\tbyKind.set(CompletionItemKind.Struct, Codicon.symbolStruct);\n\tbyKind.set(CompletionItemKind.Interface, Codicon.symbolInterface);\n\tbyKind.set(CompletionItemKind.Module, Codicon.symbolModule);\n\tbyKind.set(CompletionItemKind.Property, Codicon.symbolProperty);\n\tbyKind.set(CompletionItemKind.Event, Codicon.symbolEvent);\n\tbyKind.set(CompletionItemKind.Operator, Codicon.symbolOperator);\n\tbyKind.set(CompletionItemKind.Unit, Codicon.symbolUnit);\n\tbyKind.set(CompletionItemKind.Value, Codicon.symbolValue);\n\tbyKind.set(CompletionItemKind.Enum, Codicon.symbolEnum);\n\tbyKind.set(CompletionItemKind.Constant, Codicon.symbolConstant);\n\tbyKind.set(CompletionItemKind.Enum, Codicon.symbolEnum);\n\tbyKind.set(CompletionItemKind.EnumMember, Codicon.symbolEnumMember);\n\tbyKind.set(CompletionItemKind.Keyword, Codicon.symbolKeyword);\n\tbyKind.set(CompletionItemKind.Snippet, Codicon.symbolSnippet);\n\tbyKind.set(CompletionItemKind.Text, Codicon.symbolText);\n\tbyKind.set(CompletionItemKind.Color, Codicon.symbolColor);\n\tbyKind.set(CompletionItemKind.File, Codicon.symbolFile);\n\tbyKind.set(CompletionItemKind.Reference, Codicon.symbolReference);\n\tbyKind.set(CompletionItemKind.Customcolor, Codicon.symbolCustomColor);\n\tbyKind.set(CompletionItemKind.Folder, Codicon.symbolFolder);\n\tbyKind.set(CompletionItemKind.TypeParameter, Codicon.symbolTypeParameter);\n\tbyKind.set(CompletionItemKind.User, Codicon.account);\n\tbyKind.set(CompletionItemKind.Issue, Codicon.issues);\n\n\t/**\n\t * @internal\n\t */\n\texport function toIcon(kind: CompletionItemKind): CSSIcon {\n\t\tlet codicon = byKind.get(kind);\n\t\tif (!codicon) {\n\t\t\tconsole.info('No codicon found for CompletionItemKind ' + kind);\n\t\t\tcodicon = Codicon.symbolProperty;\n\t\t}\n\t\treturn codicon;\n\t}\n\n\tconst data = new Map();\n\tdata.set('method', CompletionItemKind.Method);\n\tdata.set('function', CompletionItemKind.Function);\n\tdata.set('constructor', CompletionItemKind.Constructor);\n\tdata.set('field', CompletionItemKind.Field);\n\tdata.set('variable', CompletionItemKind.Variable);\n\tdata.set('class', CompletionItemKind.Class);\n\tdata.set('struct', CompletionItemKind.Struct);\n\tdata.set('interface', CompletionItemKind.Interface);\n\tdata.set('module', CompletionItemKind.Module);\n\tdata.set('property', CompletionItemKind.Property);\n\tdata.set('event', CompletionItemKind.Event);\n\tdata.set('operator', CompletionItemKind.Operator);\n\tdata.set('unit', CompletionItemKind.Unit);\n\tdata.set('value', CompletionItemKind.Value);\n\tdata.set('constant', CompletionItemKind.Constant);\n\tdata.set('enum', CompletionItemKind.Enum);\n\tdata.set('enum-member', CompletionItemKind.EnumMember);\n\tdata.set('enumMember', CompletionItemKind.EnumMember);\n\tdata.set('keyword', CompletionItemKind.Keyword);\n\tdata.set('snippet', CompletionItemKind.Snippet);\n\tdata.set('text', CompletionItemKind.Text);\n\tdata.set('color', CompletionItemKind.Color);\n\tdata.set('file', CompletionItemKind.File);\n\tdata.set('reference', CompletionItemKind.Reference);\n\tdata.set('customcolor', CompletionItemKind.Customcolor);\n\tdata.set('folder', CompletionItemKind.Folder);\n\tdata.set('type-parameter', CompletionItemKind.TypeParameter);\n\tdata.set('typeParameter', CompletionItemKind.TypeParameter);\n\tdata.set('account', CompletionItemKind.User);\n\tdata.set('issue', CompletionItemKind.Issue);\n\n\t/**\n\t * @internal\n\t */\n\texport function fromString(value: string): CompletionItemKind;\n\t/**\n\t * @internal\n\t */\n\texport function fromString(value: string, strict: true): CompletionItemKind | undefined;\n\t/**\n\t * @internal\n\t */\n\texport function fromString(value: string, strict?: boolean): CompletionItemKind | undefined {\n\t\tlet res = data.get(value);\n\t\tif (typeof res === 'undefined' && !strict) {\n\t\t\tres = CompletionItemKind.Property;\n\t\t}\n\t\treturn res;\n\t}\n}\n\nexport interface CompletionItemLabel {\n\tlabel: string;\n\tdetail?: string;\n\tdescription?: string;\n}\n\nexport const enum CompletionItemTag {\n\tDeprecated = 1\n}\n\nexport const enum CompletionItemInsertTextRule {\n\t/**\n\t * Adjust whitespace/indentation of multiline insert texts to\n\t * match the current line indentation.\n\t */\n\tKeepWhitespace = 0b001,\n\n\t/**\n\t * `insertText` is a snippet.\n\t */\n\tInsertAsSnippet = 0b100,\n}\n\nexport interface CompletionItemRanges {\n\tinsert: IRange;\n\treplace: IRange;\n}\n\n/**\n * A completion item represents a text snippet that is\n * proposed to complete text that is being typed.\n */\nexport interface CompletionItem {\n\t/**\n\t * The label of this completion item. By default\n\t * this is also the text that is inserted when selecting\n\t * this completion.\n\t */\n\tlabel: string | CompletionItemLabel;\n\t/**\n\t * The kind of this completion item. Based on the kind\n\t * an icon is chosen by the editor.\n\t */\n\tkind: CompletionItemKind;\n\t/**\n\t * A modifier to the `kind` which affect how the item\n\t * is rendered, e.g. Deprecated is rendered with a strikeout\n\t */\n\ttags?: ReadonlyArray;\n\t/**\n\t * A human-readable string with additional information\n\t * about this item, like type or symbol information.\n\t */\n\tdetail?: string;\n\t/**\n\t * A human-readable string that represents a doc-comment.\n\t */\n\tdocumentation?: string | IMarkdownString;\n\t/**\n\t * A string that should be used when comparing this item\n\t * with other items. When `falsy` the {@link CompletionItem.label label}\n\t * is used.\n\t */\n\tsortText?: string;\n\t/**\n\t * A string that should be used when filtering a set of\n\t * completion items. When `falsy` the {@link CompletionItem.label label}\n\t * is used.\n\t */\n\tfilterText?: string;\n\t/**\n\t * Select this item when showing. *Note* that only one completion item can be selected and\n\t * that the editor decides which item that is. The rule is that the *first* item of those\n\t * that match best is selected.\n\t */\n\tpreselect?: boolean;\n\t/**\n\t * A string or snippet that should be inserted in a document when selecting\n\t * this completion.\n\t */\n\tinsertText: string;\n\t/**\n\t * Additional rules (as bitmask) that should be applied when inserting\n\t * this completion.\n\t */\n\tinsertTextRules?: CompletionItemInsertTextRule;\n\t/**\n\t * A range of text that should be replaced by this completion item.\n\t *\n\t * Defaults to a range from the start of the {@link TextDocument.getWordRangeAtPosition current word} to the\n\t * current position.\n\t *\n\t * *Note:* The range must be a {@link Range.isSingleLine single line} and it must\n\t * {@link Range.contains contain} the position at which completion has been {@link CompletionItemProvider.provideCompletionItems requested}.\n\t */\n\trange: IRange | CompletionItemRanges;\n\t/**\n\t * An optional set of characters that when pressed while this completion is active will accept it first and\n\t * then type that character. *Note* that all commit characters should have `length=1` and that superfluous\n\t * characters will be ignored.\n\t */\n\tcommitCharacters?: string[];\n\t/**\n\t * An optional array of additional text edits that are applied when\n\t * selecting this completion. Edits must not overlap with the main edit\n\t * nor with themselves.\n\t */\n\tadditionalTextEdits?: ISingleEditOperation[];\n\t/**\n\t * A command that should be run upon acceptance of this item.\n\t */\n\tcommand?: Command;\n}\n\nexport interface CompletionList {\n\tsuggestions: CompletionItem[];\n\tincomplete?: boolean;\n\tdispose?(): void;\n\n\t/**\n\t * @internal\n\t */\n\tduration?: number;\n}\n\n/**\n * How a suggest provider was triggered.\n */\nexport const enum CompletionTriggerKind {\n\tInvoke = 0,\n\tTriggerCharacter = 1,\n\tTriggerForIncompleteCompletions = 2\n}\n/**\n * Contains additional information about the context in which\n * {@link CompletionItemProvider.provideCompletionItems completion provider} is triggered.\n */\nexport interface CompletionContext {\n\t/**\n\t * How the completion was triggered.\n\t */\n\ttriggerKind: CompletionTriggerKind;\n\t/**\n\t * Character that triggered the completion item provider.\n\t *\n\t * `undefined` if provider was not triggered by a character.\n\t */\n\ttriggerCharacter?: string;\n}\n/**\n * The completion item provider interface defines the contract between extensions and\n * the [IntelliSense](https://code.visualstudio.com/docs/editor/intellisense).\n *\n * When computing *complete* completion items is expensive, providers can optionally implement\n * the `resolveCompletionItem`-function. In that case it is enough to return completion\n * items with a {@link CompletionItem.label label} from the\n * {@link CompletionItemProvider.provideCompletionItems provideCompletionItems}-function. Subsequently,\n * when a completion item is shown in the UI and gains focus this provider is asked to resolve\n * the item, like adding {@link CompletionItem.documentation doc-comment} or {@link CompletionItem.detail details}.\n */\nexport interface CompletionItemProvider {\n\n\t/**\n\t * @internal\n\t */\n\t_debugDisplayName?: string;\n\n\ttriggerCharacters?: string[];\n\t/**\n\t * Provide completion items for the given position and document.\n\t */\n\tprovideCompletionItems(model: model.ITextModel, position: Position, context: CompletionContext, token: CancellationToken): ProviderResult;\n\n\t/**\n\t * Given a completion item fill in more data, like {@link CompletionItem.documentation doc-comment}\n\t * or {@link CompletionItem.detail details}.\n\t *\n\t * The editor will only resolve a completion item once.\n\t */\n\tresolveCompletionItem?(item: CompletionItem, token: CancellationToken): ProviderResult;\n}\n\n/**\n * How an {@link InlineCompletionsProvider inline completion provider} was triggered.\n */\nexport enum InlineCompletionTriggerKind {\n\t/**\n\t * Completion was triggered automatically while editing.\n\t * It is sufficient to return a single completion item in this case.\n\t */\n\tAutomatic = 0,\n\n\t/**\n\t * Completion was triggered explicitly by a user gesture.\n\t * Return multiple completion items to enable cycling through them.\n\t */\n\tExplicit = 1,\n}\n\nexport interface InlineCompletionContext {\n\t/**\n\t * How the completion was triggered.\n\t */\n\treadonly triggerKind: InlineCompletionTriggerKind;\n\n\treadonly selectedSuggestionInfo: SelectedSuggestionInfo | undefined;\n}\n\nexport interface SelectedSuggestionInfo {\n\trange: IRange;\n\ttext: string;\n\tisSnippetText: boolean;\n\tcompletionKind: CompletionItemKind;\n}\n\nexport interface InlineCompletion {\n\t/**\n\t * The text to insert.\n\t * If the text contains a line break, the range must end at the end of a line.\n\t * If existing text should be replaced, the existing text must be a prefix of the text to insert.\n\t*/\n\treadonly text: string;\n\n\t/**\n\t * The range to replace.\n\t * Must begin and end on the same line.\n\t*/\n\treadonly range?: IRange;\n\n\treadonly command?: Command;\n\n\t/**\n\t * If set to `true`, unopened closing brackets are removed and unclosed opening brackets are closed.\n\t * Defaults to `false`.\n\t*/\n\treadonly completeBracketPairs?: boolean;\n}\n\nexport interface InlineCompletions {\n\treadonly items: readonly TItem[];\n}\n\nexport interface InlineCompletionsProvider {\n\tprovideInlineCompletions(model: model.ITextModel, position: Position, context: InlineCompletionContext, token: CancellationToken): ProviderResult;\n\n\t/**\n\t * Will be called when an item is shown.\n\t*/\n\thandleItemDidShow?(completions: T, item: T['items'][number]): void;\n\n\t/**\n\t * Will be called when a completions list is no longer in use and can be garbage-collected.\n\t*/\n\tfreeInlineCompletions(completions: T): void;\n}\n\nexport interface CodeAction {\n\ttitle: string;\n\tcommand?: Command;\n\tedit?: WorkspaceEdit;\n\tdiagnostics?: IMarkerData[];\n\tkind?: string;\n\tisPreferred?: boolean;\n\tdisabled?: string;\n}\n\n/**\n * @internal\n */\nexport const enum CodeActionTriggerType {\n\tInvoke = 1,\n\tAuto = 2,\n}\n\n/**\n * @internal\n */\nexport interface CodeActionContext {\n\tonly?: string;\n\ttrigger: CodeActionTriggerType;\n}\n\nexport interface CodeActionList extends IDisposable {\n\treadonly actions: ReadonlyArray;\n}\n\n/**\n * The code action interface defines the contract between extensions and\n * the [light bulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) feature.\n * @internal\n */\nexport interface CodeActionProvider {\n\n\t/**\n\t * Provide commands for the given document and range.\n\t */\n\tprovideCodeActions(model: model.ITextModel, range: Range | Selection, context: CodeActionContext, token: CancellationToken): ProviderResult;\n\n\t/**\n\t * Given a code action fill in the edit. Will only invoked when missing.\n\t */\n\tresolveCodeAction?(codeAction: CodeAction, token: CancellationToken): ProviderResult;\n\n\t/**\n\t * Optional list of CodeActionKinds that this provider returns.\n\t */\n\treadonly providedCodeActionKinds?: ReadonlyArray;\n\n\treadonly documentation?: ReadonlyArray<{ readonly kind: string, readonly command: Command }>;\n\n\t/**\n\t * @internal\n\t */\n\t_getAdditionalMenuItems?(context: CodeActionContext, actions: readonly CodeAction[]): Command[];\n}\n\n/**\n * Represents a parameter of a callable-signature. A parameter can\n * have a label and a doc-comment.\n */\nexport interface ParameterInformation {\n\t/**\n\t * The label of this signature. Will be shown in\n\t * the UI.\n\t */\n\tlabel: string | [number, number];\n\t/**\n\t * The human-readable doc-comment of this signature. Will be shown\n\t * in the UI but can be omitted.\n\t */\n\tdocumentation?: string | IMarkdownString;\n}\n/**\n * Represents the signature of something callable. A signature\n * can have a label, like a function-name, a doc-comment, and\n * a set of parameters.\n */\nexport interface SignatureInformation {\n\t/**\n\t * The label of this signature. Will be shown in\n\t * the UI.\n\t */\n\tlabel: string;\n\t/**\n\t * The human-readable doc-comment of this signature. Will be shown\n\t * in the UI but can be omitted.\n\t */\n\tdocumentation?: string | IMarkdownString;\n\t/**\n\t * The parameters of this signature.\n\t */\n\tparameters: ParameterInformation[];\n\t/**\n\t * Index of the active parameter.\n\t *\n\t * If provided, this is used in place of `SignatureHelp.activeSignature`.\n\t */\n\tactiveParameter?: number;\n}\n/**\n * Signature help represents the signature of something\n * callable. There can be multiple signatures but only one\n * active and only one active parameter.\n */\nexport interface SignatureHelp {\n\t/**\n\t * One or more signatures.\n\t */\n\tsignatures: SignatureInformation[];\n\t/**\n\t * The active signature.\n\t */\n\tactiveSignature: number;\n\t/**\n\t * The active parameter of the active signature.\n\t */\n\tactiveParameter: number;\n}\n\nexport interface SignatureHelpResult extends IDisposable {\n\tvalue: SignatureHelp;\n}\n\nexport enum SignatureHelpTriggerKind {\n\tInvoke = 1,\n\tTriggerCharacter = 2,\n\tContentChange = 3,\n}\n\nexport interface SignatureHelpContext {\n\treadonly triggerKind: SignatureHelpTriggerKind;\n\treadonly triggerCharacter?: string;\n\treadonly isRetrigger: boolean;\n\treadonly activeSignatureHelp?: SignatureHelp;\n}\n\n/**\n * The signature help provider interface defines the contract between extensions and\n * the [parameter hints](https://code.visualstudio.com/docs/editor/intellisense)-feature.\n */\nexport interface SignatureHelpProvider {\n\n\treadonly signatureHelpTriggerCharacters?: ReadonlyArray;\n\treadonly signatureHelpRetriggerCharacters?: ReadonlyArray;\n\n\t/**\n\t * Provide help for the signature at the given position and document.\n\t */\n\tprovideSignatureHelp(model: model.ITextModel, position: Position, token: CancellationToken, context: SignatureHelpContext): ProviderResult;\n}\n\n/**\n * A document highlight kind.\n */\nexport enum DocumentHighlightKind {\n\t/**\n\t * A textual occurrence.\n\t */\n\tText,\n\t/**\n\t * Read-access of a symbol, like reading a variable.\n\t */\n\tRead,\n\t/**\n\t * Write-access of a symbol, like writing to a variable.\n\t */\n\tWrite\n}\n/**\n * A document highlight is a range inside a text document which deserves\n * special attention. Usually a document highlight is visualized by changing\n * the background color of its range.\n */\nexport interface DocumentHighlight {\n\t/**\n\t * The range this highlight applies to.\n\t */\n\trange: IRange;\n\t/**\n\t * The highlight kind, default is {@link DocumentHighlightKind.Text text}.\n\t */\n\tkind?: DocumentHighlightKind;\n}\n/**\n * The document highlight provider interface defines the contract between extensions and\n * the word-highlight-feature.\n */\nexport interface DocumentHighlightProvider {\n\t/**\n\t * Provide a set of document highlights, like all occurrences of a variable or\n\t * all exit-points of a function.\n\t */\n\tprovideDocumentHighlights(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult;\n}\n\n/**\n * The linked editing range provider interface defines the contract between extensions and\n * the linked editing feature.\n */\nexport interface LinkedEditingRangeProvider {\n\n\t/**\n\t * Provide a list of ranges that can be edited together.\n\t */\n\tprovideLinkedEditingRanges(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult;\n}\n\n/**\n * Represents a list of ranges that can be edited together along with a word pattern to describe valid contents.\n */\nexport interface LinkedEditingRanges {\n\t/**\n\t * A list of ranges that can be edited together. The ranges must have\n\t * identical length and text content. The ranges cannot overlap\n\t */\n\tranges: IRange[];\n\n\t/**\n\t * An optional word pattern that describes valid contents for the given ranges.\n\t * If no pattern is provided, the language configuration's word pattern will be used.\n\t */\n\twordPattern?: RegExp;\n}\n\n/**\n * Value-object that contains additional information when\n * requesting references.\n */\nexport interface ReferenceContext {\n\t/**\n\t * Include the declaration of the current symbol.\n\t */\n\tincludeDeclaration: boolean;\n}\n/**\n * The reference provider interface defines the contract between extensions and\n * the [find references](https://code.visualstudio.com/docs/editor/editingevolved#_peek)-feature.\n */\nexport interface ReferenceProvider {\n\t/**\n\t * Provide a set of project-wide references for the given position and document.\n\t */\n\tprovideReferences(model: model.ITextModel, position: Position, context: ReferenceContext, token: CancellationToken): ProviderResult;\n}\n\n/**\n * Represents a location inside a resource, such as a line\n * inside a text file.\n */\nexport interface Location {\n\t/**\n\t * The resource identifier of this location.\n\t */\n\turi: URI;\n\t/**\n\t * The document range of this locations.\n\t */\n\trange: IRange;\n}\n\nexport interface LocationLink {\n\t/**\n\t * A range to select where this link originates from.\n\t */\n\toriginSelectionRange?: IRange;\n\n\t/**\n\t * The target uri this link points to.\n\t */\n\turi: URI;\n\n\t/**\n\t * The full range this link points to.\n\t */\n\trange: IRange;\n\n\t/**\n\t * A range to select this link points to. Must be contained\n\t * in `LocationLink.range`.\n\t */\n\ttargetSelectionRange?: IRange;\n}\n\n/**\n * @internal\n */\nexport function isLocationLink(thing: any): thing is LocationLink {\n\treturn thing\n\t\t&& URI.isUri((thing as LocationLink).uri)\n\t\t&& Range.isIRange((thing as LocationLink).range)\n\t\t&& (Range.isIRange((thing as LocationLink).originSelectionRange) || Range.isIRange((thing as LocationLink).targetSelectionRange));\n}\n\nexport type Definition = Location | Location[] | LocationLink[];\n\n/**\n * The definition provider interface defines the contract between extensions and\n * the [go to definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition)\n * and peek definition features.\n */\nexport interface DefinitionProvider {\n\t/**\n\t * Provide the definition of the symbol at the given position and document.\n\t */\n\tprovideDefinition(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult;\n}\n\n/**\n * The definition provider interface defines the contract between extensions and\n * the [go to definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition)\n * and peek definition features.\n */\nexport interface DeclarationProvider {\n\t/**\n\t * Provide the declaration of the symbol at the given position and document.\n\t */\n\tprovideDeclaration(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult;\n}\n\n/**\n * The implementation provider interface defines the contract between extensions and\n * the go to implementation feature.\n */\nexport interface ImplementationProvider {\n\t/**\n\t * Provide the implementation of the symbol at the given position and document.\n\t */\n\tprovideImplementation(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult;\n}\n\n/**\n * The type definition provider interface defines the contract between extensions and\n * the go to type definition feature.\n */\nexport interface TypeDefinitionProvider {\n\t/**\n\t * Provide the type definition of the symbol at the given position and document.\n\t */\n\tprovideTypeDefinition(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult;\n}\n\n/**\n * A symbol kind.\n */\nexport const enum SymbolKind {\n\tFile = 0,\n\tModule = 1,\n\tNamespace = 2,\n\tPackage = 3,\n\tClass = 4,\n\tMethod = 5,\n\tProperty = 6,\n\tField = 7,\n\tConstructor = 8,\n\tEnum = 9,\n\tInterface = 10,\n\tFunction = 11,\n\tVariable = 12,\n\tConstant = 13,\n\tString = 14,\n\tNumber = 15,\n\tBoolean = 16,\n\tArray = 17,\n\tObject = 18,\n\tKey = 19,\n\tNull = 20,\n\tEnumMember = 21,\n\tStruct = 22,\n\tEvent = 23,\n\tOperator = 24,\n\tTypeParameter = 25\n}\n\nexport const enum SymbolTag {\n\tDeprecated = 1,\n}\n\n/**\n * @internal\n */\nexport namespace SymbolKinds {\n\n\tconst byKind = new Map();\n\tbyKind.set(SymbolKind.File, Codicon.symbolFile);\n\tbyKind.set(SymbolKind.Module, Codicon.symbolModule);\n\tbyKind.set(SymbolKind.Namespace, Codicon.symbolNamespace);\n\tbyKind.set(SymbolKind.Package, Codicon.symbolPackage);\n\tbyKind.set(SymbolKind.Class, Codicon.symbolClass);\n\tbyKind.set(SymbolKind.Method, Codicon.symbolMethod);\n\tbyKind.set(SymbolKind.Property, Codicon.symbolProperty);\n\tbyKind.set(SymbolKind.Field, Codicon.symbolField);\n\tbyKind.set(SymbolKind.Constructor, Codicon.symbolConstructor);\n\tbyKind.set(SymbolKind.Enum, Codicon.symbolEnum);\n\tbyKind.set(SymbolKind.Interface, Codicon.symbolInterface);\n\tbyKind.set(SymbolKind.Function, Codicon.symbolFunction);\n\tbyKind.set(SymbolKind.Variable, Codicon.symbolVariable);\n\tbyKind.set(SymbolKind.Constant, Codicon.symbolConstant);\n\tbyKind.set(SymbolKind.String, Codicon.symbolString);\n\tbyKind.set(SymbolKind.Number, Codicon.symbolNumber);\n\tbyKind.set(SymbolKind.Boolean, Codicon.symbolBoolean);\n\tbyKind.set(SymbolKind.Array, Codicon.symbolArray);\n\tbyKind.set(SymbolKind.Object, Codicon.symbolObject);\n\tbyKind.set(SymbolKind.Key, Codicon.symbolKey);\n\tbyKind.set(SymbolKind.Null, Codicon.symbolNull);\n\tbyKind.set(SymbolKind.EnumMember, Codicon.symbolEnumMember);\n\tbyKind.set(SymbolKind.Struct, Codicon.symbolStruct);\n\tbyKind.set(SymbolKind.Event, Codicon.symbolEvent);\n\tbyKind.set(SymbolKind.Operator, Codicon.symbolOperator);\n\tbyKind.set(SymbolKind.TypeParameter, Codicon.symbolTypeParameter);\n\t/**\n\t * @internal\n\t */\n\texport function toIcon(kind: SymbolKind): CSSIcon {\n\t\tlet icon = byKind.get(kind);\n\t\tif (!icon) {\n\t\t\tconsole.info('No codicon found for SymbolKind ' + kind);\n\t\t\ticon = Codicon.symbolProperty;\n\t\t}\n\t\treturn icon;\n\t}\n}\n\nexport interface DocumentSymbol {\n\tname: string;\n\tdetail: string;\n\tkind: SymbolKind;\n\ttags: ReadonlyArray;\n\tcontainerName?: string;\n\trange: IRange;\n\tselectionRange: IRange;\n\tchildren?: DocumentSymbol[];\n}\n\n/**\n * The document symbol provider interface defines the contract between extensions and\n * the [go to symbol](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-symbol)-feature.\n */\nexport interface DocumentSymbolProvider {\n\n\tdisplayName?: string;\n\n\t/**\n\t * Provide symbol information for the given document.\n\t */\n\tprovideDocumentSymbols(model: model.ITextModel, token: CancellationToken): ProviderResult;\n}\n\nexport type TextEdit = { range: IRange; text: string; eol?: model.EndOfLineSequence; };\n\n/**\n * Interface used to format a model\n */\nexport interface FormattingOptions {\n\t/**\n\t * Size of a tab in spaces.\n\t */\n\ttabSize: number;\n\t/**\n\t * Prefer spaces over tabs.\n\t */\n\tinsertSpaces: boolean;\n}\n/**\n * The document formatting provider interface defines the contract between extensions and\n * the formatting-feature.\n */\nexport interface DocumentFormattingEditProvider {\n\n\t/**\n\t * @internal\n\t */\n\treadonly extensionId?: ExtensionIdentifier;\n\n\treadonly displayName?: string;\n\n\t/**\n\t * Provide formatting edits for a whole document.\n\t */\n\tprovideDocumentFormattingEdits(model: model.ITextModel, options: FormattingOptions, token: CancellationToken): ProviderResult;\n}\n/**\n * The document formatting provider interface defines the contract between extensions and\n * the formatting-feature.\n */\nexport interface DocumentRangeFormattingEditProvider {\n\t/**\n\t * @internal\n\t */\n\treadonly extensionId?: ExtensionIdentifier;\n\n\treadonly displayName?: string;\n\n\t/**\n\t * Provide formatting edits for a range in a document.\n\t *\n\t * The given range is a hint and providers can decide to format a smaller\n\t * or larger range. Often this is done by adjusting the start and end\n\t * of the range to full syntax nodes.\n\t */\n\tprovideDocumentRangeFormattingEdits(model: model.ITextModel, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult;\n}\n/**\n * The document formatting provider interface defines the contract between extensions and\n * the formatting-feature.\n */\nexport interface OnTypeFormattingEditProvider {\n\n\tautoFormatTriggerCharacters: string[];\n\n\t/**\n\t * Provide formatting edits after a character has been typed.\n\t *\n\t * The given position and character should hint to the provider\n\t * what range the position to expand to, like find the matching `{`\n\t * when `}` has been entered.\n\t */\n\tprovideOnTypeFormattingEdits(model: model.ITextModel, position: Position, ch: string, options: FormattingOptions, token: CancellationToken): ProviderResult;\n}\n\n/**\n * @internal\n */\nexport interface IInplaceReplaceSupportResult {\n\tvalue: string;\n\trange: IRange;\n}\n\n/**\n * A link inside the editor.\n */\nexport interface ILink {\n\trange: IRange;\n\turl?: URI | string;\n\ttooltip?: string;\n}\n\nexport interface ILinksList {\n\tlinks: ILink[];\n\tdispose?(): void;\n}\n/**\n * A provider of links.\n */\nexport interface LinkProvider {\n\tprovideLinks(model: model.ITextModel, token: CancellationToken): ProviderResult;\n\tresolveLink?: (link: ILink, token: CancellationToken) => ProviderResult;\n}\n\n/**\n * A color in RGBA format.\n */\nexport interface IColor {\n\n\t/**\n\t * The red component in the range [0-1].\n\t */\n\treadonly red: number;\n\n\t/**\n\t * The green component in the range [0-1].\n\t */\n\treadonly green: number;\n\n\t/**\n\t * The blue component in the range [0-1].\n\t */\n\treadonly blue: number;\n\n\t/**\n\t * The alpha component in the range [0-1].\n\t */\n\treadonly alpha: number;\n}\n\n/**\n * String representations for a color\n */\nexport interface IColorPresentation {\n\t/**\n\t * The label of this color presentation. It will be shown on the color\n\t * picker header. By default this is also the text that is inserted when selecting\n\t * this color presentation.\n\t */\n\tlabel: string;\n\t/**\n\t * An {@link TextEdit edit} which is applied to a document when selecting\n\t * this presentation for the color.\n\t */\n\ttextEdit?: TextEdit;\n\t/**\n\t * An optional array of additional {@link TextEdit text edits} that are applied when\n\t * selecting this color presentation.\n\t */\n\tadditionalTextEdits?: TextEdit[];\n}\n\n/**\n * A color range is a range in a text model which represents a color.\n */\nexport interface IColorInformation {\n\n\t/**\n\t * The range within the model.\n\t */\n\trange: IRange;\n\n\t/**\n\t * The color represented in this range.\n\t */\n\tcolor: IColor;\n}\n\n/**\n * A provider of colors for editor models.\n */\nexport interface DocumentColorProvider {\n\t/**\n\t * Provides the color ranges for a specific model.\n\t */\n\tprovideDocumentColors(model: model.ITextModel, token: CancellationToken): ProviderResult;\n\t/**\n\t * Provide the string representations for a color.\n\t */\n\tprovideColorPresentations(model: model.ITextModel, colorInfo: IColorInformation, token: CancellationToken): ProviderResult;\n}\n\nexport interface SelectionRange {\n\trange: IRange;\n}\n\nexport interface SelectionRangeProvider {\n\t/**\n\t * Provide ranges that should be selected from the given position.\n\t */\n\tprovideSelectionRanges(model: model.ITextModel, positions: Position[], token: CancellationToken): ProviderResult;\n}\n\nexport interface FoldingContext {\n}\n/**\n * A provider of folding ranges for editor models.\n */\nexport interface FoldingRangeProvider {\n\n\t/**\n\t * An optional event to signal that the folding ranges from this provider have changed.\n\t */\n\tonDidChange?: Event;\n\n\t/**\n\t * Provides the folding ranges for a specific model.\n\t */\n\tprovideFoldingRanges(model: model.ITextModel, context: FoldingContext, token: CancellationToken): ProviderResult;\n}\n\nexport interface FoldingRange {\n\n\t/**\n\t * The one-based start line of the range to fold. The folded area starts after the line's last character.\n\t */\n\tstart: number;\n\n\t/**\n\t * The one-based end line of the range to fold. The folded area ends with the line's last character.\n\t */\n\tend: number;\n\n\t/**\n\t * Describes the {@link FoldingRangeKind Kind} of the folding range such as {@link FoldingRangeKind.Comment Comment} or\n\t * {@link FoldingRangeKind.Region Region}. The kind is used to categorize folding ranges and used by commands\n\t * like 'Fold all comments'. See\n\t * {@link FoldingRangeKind} for an enumeration of standardized kinds.\n\t */\n\tkind?: FoldingRangeKind;\n}\nexport class FoldingRangeKind {\n\t/**\n\t * Kind for folding range representing a comment. The value of the kind is 'comment'.\n\t */\n\tstatic readonly Comment = new FoldingRangeKind('comment');\n\t/**\n\t * Kind for folding range representing a import. The value of the kind is 'imports'.\n\t */\n\tstatic readonly Imports = new FoldingRangeKind('imports');\n\t/**\n\t * Kind for folding range representing regions (for example marked by `#region`, `#endregion`).\n\t * The value of the kind is 'region'.\n\t */\n\tstatic readonly Region = new FoldingRangeKind('region');\n\n\t/**\n\t * Creates a new {@link FoldingRangeKind}.\n\t *\n\t * @param value of the kind.\n\t */\n\tpublic constructor(public value: string) {\n\t}\n}\n\n\nexport interface WorkspaceEditMetadata {\n\tneedsConfirmation: boolean;\n\tlabel: string;\n\tdescription?: string;\n}\n\nexport interface WorkspaceFileEditOptions {\n\toverwrite?: boolean;\n\tignoreIfNotExists?: boolean;\n\tignoreIfExists?: boolean;\n\trecursive?: boolean;\n\tcopy?: boolean;\n\tfolder?: boolean;\n\tskipTrashBin?: boolean;\n\tmaxSize?: number;\n}\n\nexport interface WorkspaceFileEdit {\n\toldUri?: URI;\n\tnewUri?: URI;\n\toptions?: WorkspaceFileEditOptions;\n\tmetadata?: WorkspaceEditMetadata;\n}\n\nexport interface WorkspaceTextEdit {\n\tresource: URI;\n\tedit: TextEdit;\n\tmodelVersionId?: number;\n\tmetadata?: WorkspaceEditMetadata;\n}\n\nexport interface WorkspaceEdit {\n\tedits: Array;\n}\n\nexport interface Rejection {\n\trejectReason?: string;\n}\nexport interface RenameLocation {\n\trange: IRange;\n\ttext: string;\n}\n\nexport interface RenameProvider {\n\tprovideRenameEdits(model: model.ITextModel, position: Position, newName: string, token: CancellationToken): ProviderResult;\n\tresolveRenameLocation?(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult;\n}\n\nexport interface Command {\n\tid: string;\n\ttitle: string;\n\ttooltip?: string;\n\targuments?: any[];\n}\n\n/**\n * @internal\n */\nexport namespace Command {\n\n\t/**\n\t * @internal\n\t */\n\texport function is(obj: any): obj is Command {\n\t\tif (!obj || typeof obj !== 'object') {\n\t\t\treturn false;\n\t\t}\n\t\treturn typeof (obj).id === 'string' &&\n\t\t\ttypeof (obj).title === 'string';\n\t}\n}\n\nexport interface CodeLens {\n\trange: IRange;\n\tid?: string;\n\tcommand?: Command;\n}\n\nexport interface CodeLensList {\n\tlenses: CodeLens[];\n\tdispose(): void;\n}\n\nexport interface CodeLensProvider {\n\tonDidChange?: Event;\n\tprovideCodeLenses(model: model.ITextModel, token: CancellationToken): ProviderResult;\n\tresolveCodeLens?(model: model.ITextModel, codeLens: CodeLens, token: CancellationToken): ProviderResult;\n}\n\n\nexport enum InlayHintKind {\n\tOther = 0,\n\tType = 1,\n\tParameter = 2,\n}\n\nexport interface InlayHintLabelPart {\n\tlabel: string;\n\ttooltip?: string | IMarkdownString\n\t// collapsible?: boolean;\n\tcommand?: Command\n\tlocation?: Location;\n}\n\nexport interface InlayHint {\n\tlabel: string | InlayHintLabelPart[];\n\ttooltip?: string | IMarkdownString\n\tposition: IPosition;\n\tkind: InlayHintKind;\n\tpaddingLeft?: boolean;\n\tpaddingRight?: boolean;\n}\n\nexport interface InlayHintList {\n\thints: InlayHint[];\n\tdispose(): void;\n}\n\nexport interface InlayHintsProvider {\n\tdisplayName?: string\n\tonDidChangeInlayHints?: Event;\n\tprovideInlayHints(model: model.ITextModel, range: Range, token: CancellationToken): ProviderResult;\n\tresolveInlayHint?(hint: InlayHint, token: CancellationToken): ProviderResult;\n}\n\nexport interface SemanticTokensLegend {\n\treadonly tokenTypes: string[];\n\treadonly tokenModifiers: string[];\n}\n\nexport interface SemanticTokens {\n\treadonly resultId?: string;\n\treadonly data: Uint32Array;\n}\n\nexport interface SemanticTokensEdit {\n\treadonly start: number;\n\treadonly deleteCount: number;\n\treadonly data?: Uint32Array;\n}\n\nexport interface SemanticTokensEdits {\n\treadonly resultId?: string;\n\treadonly edits: SemanticTokensEdit[];\n}\n\nexport interface DocumentSemanticTokensProvider {\n\tonDidChange?: Event;\n\tgetLegend(): SemanticTokensLegend;\n\tprovideDocumentSemanticTokens(model: model.ITextModel, lastResultId: string | null, token: CancellationToken): ProviderResult;\n\treleaseDocumentSemanticTokens(resultId: string | undefined): void;\n}\n\nexport interface DocumentRangeSemanticTokensProvider {\n\tgetLegend(): SemanticTokensLegend;\n\tprovideDocumentRangeSemanticTokens(model: model.ITextModel, range: Range, token: CancellationToken): ProviderResult;\n}\n\n// --- feature registries ------\n\n/**\n * @internal\n */\nexport const ReferenceProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const RenameProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const CompletionProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const InlineCompletionsProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const SignatureHelpProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const HoverProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const EvaluatableExpressionProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const InlineValuesProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const DocumentSymbolProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const DocumentHighlightProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const LinkedEditingRangeProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const DefinitionProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const DeclarationProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const ImplementationProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const TypeDefinitionProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const CodeLensProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const InlayHintsProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const CodeActionProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const DocumentFormattingEditProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const DocumentRangeFormattingEditProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const OnTypeFormattingEditProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const LinkProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const ColorProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const SelectionRangeRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const FoldingRangeProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const DocumentSemanticTokensProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport const DocumentRangeSemanticTokensProviderRegistry = new LanguageFeatureRegistry();\n\n/**\n * @internal\n */\nexport interface ITokenizationSupportChangedEvent {\n\tchangedLanguages: string[];\n\tchangedColorMap: boolean;\n}\n\n/**\n * @internal\n */\nexport interface ITokenizationSupportFactory {\n\tcreateTokenizationSupport(): ProviderResult;\n}\n\n/**\n * @internal\n */\nexport interface ITokenizationRegistry {\n\n\t/**\n\t * An event triggered when:\n\t * - a tokenization support is registered, unregistered or changed.\n\t * - the color map is changed.\n\t */\n\tonDidChange: Event;\n\n\t/**\n\t * Fire a change event for a language.\n\t * This is useful for languages that embed other languages.\n\t */\n\tfire(languageIds: string[]): void;\n\n\t/**\n\t * Register a tokenization support.\n\t */\n\tregister(languageId: string, support: ITokenizationSupport): IDisposable;\n\n\t/**\n\t * Register a tokenization support factory.\n\t */\n\tregisterFactory(languageId: string, factory: ITokenizationSupportFactory): IDisposable;\n\n\t/**\n\t * Get or create the tokenization support for a language.\n\t * Returns `null` if not found.\n\t */\n\tgetOrCreate(languageId: string): Promise;\n\n\t/**\n\t * Get the tokenization support for a language.\n\t * Returns `null` if not found.\n\t */\n\tget(languageId: string): ITokenizationSupport | null;\n\n\t/**\n\t * Returns false if a factory is still pending.\n\t */\n\tisResolved(languageId: string): boolean;\n\n\t/**\n\t * Set the new color map that all tokens will use in their ColorId binary encoded bits for foreground and background.\n\t */\n\tsetColorMap(colorMap: Color[]): void;\n\n\tgetColorMap(): Color[] | null;\n\n\tgetDefaultBackground(): Color | null;\n}\n\n/**\n * @internal\n */\nexport const TokenizationRegistry: ITokenizationRegistry = new TokenizationRegistryImpl();\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Token, TokenizationResult, EncodedTokenizationResult, ColorId, FontStyle, IState, LanguageId, MetadataConsts, StandardTokenType } from 'vs/editor/common/languages';\n\nexport const NullState: IState = new class implements IState {\n\tpublic clone(): IState {\n\t\treturn this;\n\t}\n\tpublic equals(other: IState): boolean {\n\t\treturn (this === other);\n\t}\n};\n\nexport function nullTokenize(languageId: string, state: IState): TokenizationResult {\n\treturn new TokenizationResult([new Token(0, '', languageId)], state);\n}\n\nexport function nullTokenizeEncoded(languageId: LanguageId, state: IState | null): EncodedTokenizationResult {\n\tconst tokens = new Uint32Array(2);\n\ttokens[0] = 0;\n\ttokens[1] = (\n\t\t(languageId << MetadataConsts.LANGUAGEID_OFFSET)\n\t\t| (StandardTokenType.Other << MetadataConsts.TOKEN_TYPE_OFFSET)\n\t\t| (FontStyle.None << MetadataConsts.FONT_STYLE_OFFSET)\n\t\t| (ColorId.DefaultForeground << MetadataConsts.FOREGROUND_OFFSET)\n\t\t| (ColorId.DefaultBackground << MetadataConsts.BACKGROUND_OFFSET)\n\t) >>> 0;\n\n\treturn new EncodedTokenizationResult(tokens, state === null ? NullState : state);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { NotSupportedError } from 'vs/base/common/errors';\nimport { StandardTokenType, TokenMetadata } from 'vs/editor/common/languages';\nimport { IViewLineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { BracketAstNode, TextAstNode } from './ast';\nimport { BracketTokens, LanguageAgnosticBracketTokens } from './brackets';\nimport { Length, lengthAdd, lengthDiff, lengthGetColumnCountIfZeroLineCount, lengthToObj, lengthZero, toLength } from './length';\nimport { SmallImmutableSet } from './smallImmutableSet';\n\nexport interface Tokenizer {\n\treadonly offset: Length;\n\treadonly length: Length;\n\n\tread(): Token | null;\n\tpeek(): Token | null;\n\tskip(length: Length): void;\n}\n\nexport const enum TokenKind {\n\tText = 0,\n\tOpeningBracket = 1,\n\tClosingBracket = 2,\n}\n\nexport type OpeningBracketId = number;\n\nexport class Token {\n\tconstructor(\n\t\treadonly length: Length,\n\t\treadonly kind: TokenKind,\n\t\t/**\n\t\t * If this token is an opening bracket, this is the id of the opening bracket.\n\t\t * If this token is a closing bracket, this is the id of the first opening bracket that is closed by this bracket.\n\t\t * Otherwise, it is -1.\n\t\t */\n\t\treadonly bracketId: OpeningBracketId,\n\t\t/**\n\t\t * If this token is an opening bracket, this just contains `bracketId`.\n\t\t * If this token is a closing bracket, this lists all opening bracket ids, that it closes.\n\t\t * Otherwise, it is empty.\n\t\t */\n\t\treadonly bracketIds: SmallImmutableSet,\n\t\treadonly astNode: BracketAstNode | TextAstNode | undefined,\n\t) { }\n}\n\nexport interface ITokenizerSource {\n\tgetLineCount(): number;\n\tgetLineLength(lineNumber: number): number;\n\tgetLineTokens(lineNumber: number): IViewLineTokens;\n}\n\nexport class TextBufferTokenizer implements Tokenizer {\n\tprivate readonly textBufferLineCount: number;\n\tprivate readonly textBufferLastLineLength: number;\n\n\tprivate readonly reader = new NonPeekableTextBufferTokenizer(this.textModel, this.bracketTokens);\n\n\tconstructor(\n\t\tprivate readonly textModel: ITokenizerSource,\n\t\tprivate readonly bracketTokens: LanguageAgnosticBracketTokens\n\t) {\n\t\tthis.textBufferLineCount = textModel.getLineCount();\n\t\tthis.textBufferLastLineLength = textModel.getLineLength(this.textBufferLineCount);\n\t}\n\n\tprivate _offset: Length = lengthZero;\n\n\tget offset() {\n\t\treturn this._offset;\n\t}\n\n\tget length() {\n\t\treturn toLength(this.textBufferLineCount, this.textBufferLastLineLength);\n\t}\n\n\tskip(length: Length): void {\n\t\tthis.didPeek = false;\n\t\tthis._offset = lengthAdd(this._offset, length);\n\t\tconst obj = lengthToObj(this._offset);\n\t\tthis.reader.setPosition(obj.lineCount, obj.columnCount);\n\t}\n\n\tprivate didPeek = false;\n\tprivate peeked: Token | null = null;\n\n\tread(): Token | null {\n\t\tlet token: Token | null;\n\t\tif (this.peeked) {\n\t\t\tthis.didPeek = false;\n\t\t\ttoken = this.peeked;\n\t\t} else {\n\t\t\ttoken = this.reader.read();\n\t\t}\n\t\tif (token) {\n\t\t\tthis._offset = lengthAdd(this._offset, token.length);\n\t\t}\n\t\treturn token;\n\t}\n\n\tpeek(): Token | null {\n\t\tif (!this.didPeek) {\n\t\t\tthis.peeked = this.reader.read();\n\t\t\tthis.didPeek = true;\n\t\t}\n\t\treturn this.peeked;\n\t}\n}\n\n/**\n * Does not support peek.\n*/\nclass NonPeekableTextBufferTokenizer {\n\tprivate readonly textBufferLineCount: number;\n\tprivate readonly textBufferLastLineLength: number;\n\n\tconstructor(private readonly textModel: ITokenizerSource, private readonly bracketTokens: LanguageAgnosticBracketTokens) {\n\t\tthis.textBufferLineCount = textModel.getLineCount();\n\t\tthis.textBufferLastLineLength = textModel.getLineLength(this.textBufferLineCount);\n\t}\n\n\tprivate lineIdx = 0;\n\tprivate line: string | null = null;\n\tprivate lineCharOffset = 0;\n\tprivate lineTokens: IViewLineTokens | null = null;\n\tprivate lineTokenOffset = 0;\n\n\tpublic setPosition(lineIdx: number, column: number): void {\n\t\t// We must not jump into a token!\n\t\tif (lineIdx === this.lineIdx) {\n\t\t\tthis.lineCharOffset = column;\n\t\t\tthis.lineTokenOffset = this.lineCharOffset === 0 ? 0 : this.lineTokens!.findTokenIndexAtOffset(this.lineCharOffset);\n\t\t} else {\n\t\t\tthis.lineIdx = lineIdx;\n\t\t\tthis.lineCharOffset = column;\n\t\t\tthis.line = null;\n\t\t}\n\t\tthis.peekedToken = null;\n\t}\n\n\t/** Must be a zero line token. The end of the document cannot be peeked. */\n\tprivate peekedToken: Token | null = null;\n\n\tpublic read(): Token | null {\n\t\tif (this.peekedToken) {\n\t\t\tconst token = this.peekedToken;\n\t\t\tthis.peekedToken = null;\n\t\t\tthis.lineCharOffset += lengthGetColumnCountIfZeroLineCount(token.length);\n\t\t\treturn token;\n\t\t}\n\n\t\tif (this.lineIdx > this.textBufferLineCount - 1 || (this.lineIdx === this.textBufferLineCount - 1 && this.lineCharOffset >= this.textBufferLastLineLength)) {\n\t\t\t// We are after the end\n\t\t\treturn null;\n\t\t}\n\n\t\tif (this.line === null) {\n\t\t\tthis.lineTokens = this.textModel.getLineTokens(this.lineIdx + 1);\n\t\t\tthis.line = this.lineTokens.getLineContent();\n\t\t\tthis.lineTokenOffset = this.lineCharOffset === 0 ? 0 : this.lineTokens!.findTokenIndexAtOffset(this.lineCharOffset);\n\t\t}\n\n\t\tconst startLineIdx = this.lineIdx;\n\t\tconst startLineCharOffset = this.lineCharOffset;\n\n\t\t// limits the length of text tokens.\n\t\t// If text tokens get too long, incremental updates will be slow\n\t\tlet lengthHeuristic = 0;\n\t\twhile (true) {\n\t\t\tconst lineTokens = this.lineTokens!;\n\t\t\tconst tokenCount = lineTokens.getCount();\n\n\t\t\tlet peekedBracketToken: Token | null = null;\n\n\t\t\tif (this.lineTokenOffset < tokenCount) {\n\t\t\t\tconst tokenMetadata = lineTokens.getMetadata(this.lineTokenOffset);\n\t\t\t\twhile (this.lineTokenOffset + 1 < tokenCount && tokenMetadata === lineTokens.getMetadata(this.lineTokenOffset + 1)) {\n\t\t\t\t\t// Skip tokens that are identical.\n\t\t\t\t\t// Sometimes, (bracket) identifiers are split up into multiple tokens.\n\t\t\t\t\tthis.lineTokenOffset++;\n\t\t\t\t}\n\n\t\t\t\tconst isOther = TokenMetadata.getTokenType(tokenMetadata) === StandardTokenType.Other;\n\n\t\t\t\tconst endOffset = lineTokens.getEndOffset(this.lineTokenOffset);\n\t\t\t\t// Is there a bracket token next? Only consume text.\n\t\t\t\tif (isOther && endOffset !== this.lineCharOffset) {\n\t\t\t\t\tconst languageId = lineTokens.getLanguageId(this.lineTokenOffset);\n\t\t\t\t\tconst text = this.line.substring(this.lineCharOffset, endOffset);\n\n\t\t\t\t\tconst brackets = this.bracketTokens.getSingleLanguageBracketTokens(languageId);\n\t\t\t\t\tconst regexp = brackets.regExpGlobal;\n\t\t\t\t\tif (regexp) {\n\t\t\t\t\t\tregexp.lastIndex = 0;\n\t\t\t\t\t\tconst match = regexp.exec(text);\n\t\t\t\t\t\tif (match) {\n\t\t\t\t\t\t\tpeekedBracketToken = brackets.getToken(match[0])!;\n\t\t\t\t\t\t\tif (peekedBracketToken) {\n\t\t\t\t\t\t\t\t// Consume leading text of the token\n\t\t\t\t\t\t\t\tthis.lineCharOffset += match.index;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlengthHeuristic += endOffset - this.lineCharOffset;\n\n\t\t\t\tif (peekedBracketToken) {\n\t\t\t\t\t// Don't skip the entire token, as a single token could contain multiple brackets.\n\n\t\t\t\t\tif (startLineIdx !== this.lineIdx || startLineCharOffset !== this.lineCharOffset) {\n\t\t\t\t\t\t// There is text before the bracket\n\t\t\t\t\t\tthis.peekedToken = peekedBracketToken;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Consume the peeked token\n\t\t\t\t\t\tthis.lineCharOffset += lengthGetColumnCountIfZeroLineCount(peekedBracketToken.length);\n\t\t\t\t\t\treturn peekedBracketToken;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Skip the entire token, as the token contains no brackets at all.\n\t\t\t\t\tthis.lineTokenOffset++;\n\t\t\t\t\tthis.lineCharOffset = endOffset;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (this.lineIdx === this.textBufferLineCount - 1) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthis.lineIdx++;\n\t\t\t\tthis.lineTokens = this.textModel.getLineTokens(this.lineIdx + 1);\n\t\t\t\tthis.lineTokenOffset = 0;\n\t\t\t\tthis.line = this.lineTokens.getLineContent();\n\t\t\t\tthis.lineCharOffset = 0;\n\n\t\t\t\tlengthHeuristic += 33; // max 1000/33 = 30 lines\n\t\t\t\t// This limits the amount of work to recompute min-indentation\n\n\t\t\t\tif (lengthHeuristic > 1000) {\n\t\t\t\t\t// only break (automatically) at the end of line.\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (lengthHeuristic > 1500) {\n\t\t\t\t// Eventually break regardless of the line length so that\n\t\t\t\t// very long lines do not cause bad performance.\n\t\t\t\t// This effective limits max indentation to 500, as\n\t\t\t\t// indentation is not computed across multiple text nodes.\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// If a token contains some proper indentation, it also contains \\n{INDENTATION+}(?!{INDENTATION}),\n\t\t// unless the line is too long.\n\t\t// Thus, the min indentation of the document is the minimum min indentation of every text node.\n\t\tconst length = lengthDiff(startLineIdx, startLineCharOffset, this.lineIdx, this.lineCharOffset);\n\t\treturn new Token(length, TokenKind.Text, -1, SmallImmutableSet.getEmpty(), new TextAstNode(length));\n\t}\n}\n\nexport class FastTokenizer implements Tokenizer {\n\tprivate _offset: Length = lengthZero;\n\tprivate readonly tokens: readonly Token[];\n\tprivate idx = 0;\n\n\tconstructor(private readonly text: string, brackets: BracketTokens) {\n\t\tconst regExpStr = brackets.getRegExpStr();\n\t\tconst regexp = regExpStr ? new RegExp(brackets.getRegExpStr() + '|\\n', 'g') : null;\n\n\t\tconst tokens: Token[] = [];\n\n\t\tlet match: RegExpExecArray | null;\n\t\tlet curLineCount = 0;\n\t\tlet lastLineBreakOffset = 0;\n\n\t\tlet lastTokenEndOffset = 0;\n\t\tlet lastTokenEndLine = 0;\n\n\t\tconst smallTextTokens0Line = new Array();\n\t\tfor (let i = 0; i < 60; i++) {\n\t\t\tsmallTextTokens0Line.push(\n\t\t\t\tnew Token(\n\t\t\t\t\ttoLength(0, i), TokenKind.Text, -1, SmallImmutableSet.getEmpty(),\n\t\t\t\t\tnew TextAstNode(toLength(0, i))\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\tconst smallTextTokens1Line = new Array();\n\t\tfor (let i = 0; i < 60; i++) {\n\t\t\tsmallTextTokens1Line.push(\n\t\t\t\tnew Token(\n\t\t\t\t\ttoLength(1, i), TokenKind.Text, -1, SmallImmutableSet.getEmpty(),\n\t\t\t\t\tnew TextAstNode(toLength(1, i))\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\tif (regexp) {\n\t\t\tregexp.lastIndex = 0;\n\t\t\t// If a token contains indentation, it also contains \\n{INDENTATION+}(?!{INDENTATION})\n\t\t\twhile ((match = regexp.exec(text)) !== null) {\n\t\t\t\tconst curOffset = match.index;\n\t\t\t\tconst value = match[0];\n\t\t\t\tif (value === '\\n') {\n\t\t\t\t\tcurLineCount++;\n\t\t\t\t\tlastLineBreakOffset = curOffset + 1;\n\t\t\t\t} else {\n\t\t\t\t\tif (lastTokenEndOffset !== curOffset) {\n\t\t\t\t\t\tlet token: Token;\n\t\t\t\t\t\tif (lastTokenEndLine === curLineCount) {\n\t\t\t\t\t\t\tconst colCount = curOffset - lastTokenEndOffset;\n\t\t\t\t\t\t\tif (colCount < smallTextTokens0Line.length) {\n\t\t\t\t\t\t\t\ttoken = smallTextTokens0Line[colCount];\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconst length = toLength(0, colCount);\n\t\t\t\t\t\t\t\ttoken = new Token(length, TokenKind.Text, -1, SmallImmutableSet.getEmpty(), new TextAstNode(length));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst lineCount = curLineCount - lastTokenEndLine;\n\t\t\t\t\t\t\tconst colCount = curOffset - lastLineBreakOffset;\n\t\t\t\t\t\t\tif (lineCount === 1 && colCount < smallTextTokens1Line.length) {\n\t\t\t\t\t\t\t\ttoken = smallTextTokens1Line[colCount];\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconst length = toLength(lineCount, colCount);\n\t\t\t\t\t\t\t\ttoken = new Token(length, TokenKind.Text, -1, SmallImmutableSet.getEmpty(), new TextAstNode(length));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttokens.push(token);\n\t\t\t\t\t}\n\n\t\t\t\t\t// value is matched by regexp, so the token must exist\n\t\t\t\t\ttokens.push(brackets.getToken(value)!);\n\n\t\t\t\t\tlastTokenEndOffset = curOffset + value.length;\n\t\t\t\t\tlastTokenEndLine = curLineCount;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst offset = text.length;\n\n\t\tif (lastTokenEndOffset !== offset) {\n\t\t\tconst length = (lastTokenEndLine === curLineCount)\n\t\t\t\t? toLength(0, offset - lastTokenEndOffset)\n\t\t\t\t: toLength(curLineCount - lastTokenEndLine, offset - lastLineBreakOffset);\n\t\t\ttokens.push(new Token(length, TokenKind.Text, -1, SmallImmutableSet.getEmpty(), new TextAstNode(length)));\n\t\t}\n\n\t\tthis.length = toLength(curLineCount, offset - lastLineBreakOffset);\n\t\tthis.tokens = tokens;\n\t}\n\n\tget offset(): Length {\n\t\treturn this._offset;\n\t}\n\n\treadonly length: Length;\n\n\tread(): Token | null {\n\t\treturn this.tokens[this.idx++] || null;\n\t}\n\n\tpeek(): Token | null {\n\t\treturn this.tokens[this.idx] || null;\n\t}\n\n\tskip(length: Length): void {\n\t\tthrow new NotSupportedError();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nimport { escapeRegExpCharacters } from 'vs/base/common/strings';\nimport { ResolvedLanguageConfiguration } from 'vs/editor/common/languages/languageConfigurationRegistry';\nimport { BracketAstNode } from './ast';\nimport { toLength } from './length';\nimport { DenseKeyProvider, identityKeyProvider, SmallImmutableSet } from './smallImmutableSet';\nimport { OpeningBracketId, Token, TokenKind } from './tokenizer';\n\nexport class BracketTokens {\n\tstatic createFromLanguage(configuration: ResolvedLanguageConfiguration, denseKeyProvider: DenseKeyProvider): BracketTokens {\n\t\tfunction getId(languageId: string, openingText: string): OpeningBracketId {\n\t\t\treturn denseKeyProvider.getKey(`${languageId}:::${openingText}`);\n\t\t}\n\n\t\tconst brackets = configuration.characterPair.getColorizedBrackets();\n\n\t\tconst closingBrackets = new Map, first: OpeningBracketId }>();\n\t\tconst openingBrackets = new Set();\n\n\t\tfor (const [openingText, closingText] of brackets) {\n\t\t\topeningBrackets.add(openingText);\n\n\t\t\tlet info = closingBrackets.get(closingText);\n\t\t\tconst openingTextId = getId(configuration.languageId, openingText);\n\t\t\tif (!info) {\n\t\t\t\tinfo = { openingBrackets: SmallImmutableSet.getEmpty(), first: openingTextId };\n\t\t\t\tclosingBrackets.set(closingText, info);\n\t\t\t}\n\t\t\tinfo.openingBrackets = info.openingBrackets.add(openingTextId, identityKeyProvider);\n\t\t}\n\n\t\tconst map = new Map();\n\n\t\tfor (const [closingText, info] of closingBrackets) {\n\t\t\tconst length = toLength(0, closingText.length);\n\t\t\tmap.set(closingText, new Token(\n\t\t\t\tlength,\n\t\t\t\tTokenKind.ClosingBracket,\n\t\t\t\tinfo.first,\n\t\t\t\tinfo.openingBrackets,\n\t\t\t\tBracketAstNode.create(length, configuration.languageId, info.openingBrackets)\n\t\t\t));\n\t\t}\n\n\t\tfor (const openingText of openingBrackets) {\n\t\t\tconst length = toLength(0, openingText.length);\n\t\t\tconst openingTextId = getId(configuration.languageId, openingText);\n\t\t\tconst bracketIds = SmallImmutableSet.getEmpty().add(openingTextId, identityKeyProvider);\n\t\t\tmap.set(openingText, new Token(\n\t\t\t\tlength,\n\t\t\t\tTokenKind.OpeningBracket,\n\t\t\t\topeningTextId,\n\t\t\t\tbracketIds,\n\t\t\t\tBracketAstNode.create(length, configuration.languageId, bracketIds)\n\t\t\t));\n\t\t}\n\n\t\treturn new BracketTokens(map);\n\t}\n\n\tprivate hasRegExp = false;\n\tprivate _regExpGlobal: RegExp | null = null;\n\n\tconstructor(\n\t\tprivate readonly map: Map\n\t) { }\n\n\tgetRegExpStr(): string | null {\n\t\tif (this.isEmpty) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\tconst keys = [...this.map.keys()];\n\t\t\tkeys.sort();\n\t\t\tkeys.reverse();\n\t\t\treturn keys.map(k => prepareBracketForRegExp(k)).join('|');\n\t\t}\n\t}\n\n\t/**\n\t * Returns null if there is no such regexp (because there are no brackets).\n\t*/\n\tget regExpGlobal(): RegExp | null {\n\t\tif (!this.hasRegExp) {\n\t\t\tconst regExpStr = this.getRegExpStr();\n\t\t\tthis._regExpGlobal = regExpStr ? new RegExp(regExpStr, 'g') : null;\n\t\t\tthis.hasRegExp = true;\n\t\t}\n\t\treturn this._regExpGlobal;\n\t}\n\n\tgetToken(value: string): Token | undefined {\n\t\treturn this.map.get(value);\n\t}\n\n\tfindClosingTokenText(openingBracketIds: SmallImmutableSet): string | undefined {\n\t\tfor (const [closingText, info] of this.map) {\n\t\t\tif (info.bracketIds.intersects(openingBracketIds)) {\n\t\t\t\treturn closingText;\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tget isEmpty(): boolean {\n\t\treturn this.map.size === 0;\n\t}\n}\n\nfunction prepareBracketForRegExp(str: string): string {\n\tconst escaped = escapeRegExpCharacters(str);\n\t// This bracket pair uses letters like e.g. \"begin\" - \"end\" (see https://github.com/microsoft/vscode/issues/132162)\n\tconst needsWordBoundaries = (/^[\\w ]+$/.test(str));\n\treturn (needsWordBoundaries ? `\\\\b${escaped}\\\\b` : escaped);\n}\n\nexport class LanguageAgnosticBracketTokens {\n\tprivate readonly languageIdToBracketTokens = new Map();\n\n\tconstructor(\n\t\tprivate readonly denseKeyProvider: DenseKeyProvider,\n\t\tprivate readonly getLanguageConfiguration: (languageId: string) => ResolvedLanguageConfiguration,\n\t) {\n\t}\n\n\tpublic didLanguageChange(languageId: string): boolean {\n\t\tconst existing = this.languageIdToBracketTokens.get(languageId);\n\t\tif (!existing) {\n\t\t\treturn false;\n\t\t}\n\t\tconst newRegExpStr = BracketTokens.createFromLanguage(this.getLanguageConfiguration(languageId), this.denseKeyProvider).getRegExpStr();\n\t\treturn existing.getRegExpStr() !== newRegExpStr;\n\t}\n\n\tgetSingleLanguageBracketTokens(languageId: string): BracketTokens {\n\t\tlet singleLanguageBracketTokens = this.languageIdToBracketTokens.get(languageId);\n\t\tif (!singleLanguageBracketTokens) {\n\t\t\tsingleLanguageBracketTokens = BracketTokens.createFromLanguage(this.getLanguageConfiguration(languageId), this.denseKeyProvider);\n\t\t\tthis.languageIdToBracketTokens.set(languageId, singleLanguageBracketTokens);\n\t\t}\n\t\treturn singleLanguageBracketTokens;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter } from 'vs/base/common/event';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { Range } from 'vs/editor/common/core/range';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { BracketInfo, BracketPairWithMinIndentationInfo } from 'vs/editor/common/textModelBracketPairs';\nimport { BackgroundTokenizationState, TextModel } from 'vs/editor/common/model/textModel';\nimport { IModelContentChangedEvent } from 'vs/editor/common/textModelEvents';\nimport { ResolvedLanguageConfiguration } from 'vs/editor/common/languages/languageConfigurationRegistry';\nimport { AstNode, AstNodeKind } from './ast';\nimport { TextEditInfo } from './beforeEditPositionMapper';\nimport { LanguageAgnosticBracketTokens } from './brackets';\nimport { Length, lengthAdd, lengthGreaterThanEqual, lengthLessThanEqual, lengthOfString, lengthsToRange, lengthZero, positionToLength, toLength } from './length';\nimport { parseDocument } from './parser';\nimport { DenseKeyProvider } from './smallImmutableSet';\nimport { FastTokenizer, TextBufferTokenizer } from './tokenizer';\n\nexport class BracketPairsTree extends Disposable {\n\tprivate readonly didChangeEmitter = new Emitter();\n\n\t/*\n\t\tThere are two trees:\n\t\t* The initial tree that has no token information and is used for performant initial bracket colorization.\n\t\t* The tree that used token information to detect bracket pairs.\n\n\t\tTo prevent flickering, we only switch from the initial tree to tree with token information\n\t\twhen tokenization completes.\n\t\tSince the text can be edited while background tokenization is in progress, we need to update both trees.\n\t*/\n\tprivate initialAstWithoutTokens: AstNode | undefined;\n\tprivate astWithTokens: AstNode | undefined;\n\n\tprivate readonly denseKeyProvider = new DenseKeyProvider();\n\tprivate readonly brackets = new LanguageAgnosticBracketTokens(this.denseKeyProvider, this.getLanguageConfiguration);\n\n\tpublic didLanguageChange(languageId: string): boolean {\n\t\treturn this.brackets.didLanguageChange(languageId);\n\t}\n\n\tpublic readonly onDidChange = this.didChangeEmitter.event;\n\n\tpublic constructor(\n\t\tprivate readonly textModel: TextModel,\n\t\tprivate readonly getLanguageConfiguration: (languageId: string) => ResolvedLanguageConfiguration\n\t) {\n\t\tsuper();\n\n\t\tthis._register(textModel.onBackgroundTokenizationStateChanged(() => {\n\t\t\tif (textModel.backgroundTokenizationState === BackgroundTokenizationState.Completed) {\n\t\t\t\tconst wasUndefined = this.initialAstWithoutTokens === undefined;\n\t\t\t\t// Clear the initial tree as we can use the tree with token information now.\n\t\t\t\tthis.initialAstWithoutTokens = undefined;\n\t\t\t\tif (!wasUndefined) {\n\t\t\t\t\tthis.didChangeEmitter.fire();\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(textModel.onDidChangeTokens(({ ranges }) => {\n\t\t\tconst edits = ranges.map(r =>\n\t\t\t\tnew TextEditInfo(\n\t\t\t\t\ttoLength(r.fromLineNumber - 1, 0),\n\t\t\t\t\ttoLength(r.toLineNumber, 0),\n\t\t\t\t\ttoLength(r.toLineNumber - r.fromLineNumber + 1, 0)\n\t\t\t\t)\n\t\t\t);\n\t\t\tthis.astWithTokens = this.parseDocumentFromTextBuffer(edits, this.astWithTokens, false);\n\t\t\tif (!this.initialAstWithoutTokens) {\n\t\t\t\tthis.didChangeEmitter.fire();\n\t\t\t}\n\t\t}));\n\n\t\tif (textModel.backgroundTokenizationState === BackgroundTokenizationState.Uninitialized) {\n\t\t\t// There are no token information yet\n\t\t\tconst brackets = this.brackets.getSingleLanguageBracketTokens(this.textModel.getLanguageId());\n\t\t\tconst tokenizer = new FastTokenizer(this.textModel.getValue(), brackets);\n\t\t\tthis.initialAstWithoutTokens = parseDocument(tokenizer, [], undefined, true);\n\t\t\tthis.astWithTokens = this.initialAstWithoutTokens;\n\t\t} else if (textModel.backgroundTokenizationState === BackgroundTokenizationState.Completed) {\n\t\t\t// Skip the initial ast, as there is no flickering.\n\t\t\t// Directly create the tree with token information.\n\t\t\tthis.initialAstWithoutTokens = undefined;\n\t\t\tthis.astWithTokens = this.parseDocumentFromTextBuffer([], undefined, false);\n\t\t} else if (textModel.backgroundTokenizationState === BackgroundTokenizationState.InProgress) {\n\t\t\tthis.initialAstWithoutTokens = this.parseDocumentFromTextBuffer([], undefined, true);\n\t\t\tthis.astWithTokens = this.initialAstWithoutTokens;\n\t\t}\n\t}\n\n\tpublic handleContentChanged(change: IModelContentChangedEvent) {\n\t\tconst edits = change.changes.map(c => {\n\t\t\tconst range = Range.lift(c.range);\n\t\t\treturn new TextEditInfo(\n\t\t\t\tpositionToLength(range.getStartPosition()),\n\t\t\t\tpositionToLength(range.getEndPosition()),\n\t\t\t\tlengthOfString(c.text)\n\t\t\t);\n\t\t}).reverse();\n\n\t\tthis.astWithTokens = this.parseDocumentFromTextBuffer(edits, this.astWithTokens, false);\n\t\tif (this.initialAstWithoutTokens) {\n\t\t\tthis.initialAstWithoutTokens = this.parseDocumentFromTextBuffer(edits, this.initialAstWithoutTokens, false);\n\t\t}\n\t}\n\n\t/**\n\t * @pure (only if isPure = true)\n\t*/\n\tprivate parseDocumentFromTextBuffer(edits: TextEditInfo[], previousAst: AstNode | undefined, immutable: boolean): AstNode {\n\t\t// Is much faster if `isPure = false`.\n\t\tconst isPure = false;\n\t\tconst previousAstClone = isPure ? previousAst?.deepClone() : previousAst;\n\t\tconst tokenizer = new TextBufferTokenizer(this.textModel, this.brackets);\n\t\tconst result = parseDocument(tokenizer, edits, previousAstClone, immutable);\n\t\treturn result;\n\t}\n\n\tpublic getBracketsInRange(range: Range): BracketInfo[] {\n\t\tconst startOffset = toLength(range.startLineNumber - 1, range.startColumn - 1);\n\t\tconst endOffset = toLength(range.endLineNumber - 1, range.endColumn - 1);\n\t\tconst result = new Array();\n\t\tconst node = this.initialAstWithoutTokens || this.astWithTokens!;\n\t\tcollectBrackets(node, lengthZero, node.length, startOffset, endOffset, result);\n\t\treturn result;\n\t}\n\n\tpublic getBracketPairsInRange(range: Range, includeMinIndentation: boolean): BracketPairWithMinIndentationInfo[] {\n\t\tconst result = new Array();\n\n\t\tconst startLength = positionToLength(range.getStartPosition());\n\t\tconst endLength = positionToLength(range.getEndPosition());\n\n\t\tconst node = this.initialAstWithoutTokens || this.astWithTokens!;\n\t\tconst context = new CollectBracketPairsContext(result, includeMinIndentation, this.textModel);\n\t\tcollectBracketPairs(node, lengthZero, node.length, startLength, endLength, context);\n\n\t\treturn result;\n\t}\n}\n\nfunction collectBrackets(node: AstNode, nodeOffsetStart: Length, nodeOffsetEnd: Length, startOffset: Length, endOffset: Length, result: BracketInfo[], level: number = 0): void {\n\tif (node.kind === AstNodeKind.Bracket) {\n\t\tconst range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd);\n\t\tresult.push(new BracketInfo(range, level - 1, false));\n\t} else if (node.kind === AstNodeKind.UnexpectedClosingBracket) {\n\t\tconst range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd);\n\t\tresult.push(new BracketInfo(range, level - 1, true));\n\t} else if (node.kind === AstNodeKind.List) {\n\t\tfor (const child of node.children) {\n\t\t\tnodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length);\n\t\t\tif (lengthLessThanEqual(nodeOffsetStart, endOffset) && lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) {\n\t\t\t\tcollectBrackets(child, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, result, level);\n\t\t\t}\n\t\t\tnodeOffsetStart = nodeOffsetEnd;\n\t\t}\n\t} else if (node.kind === AstNodeKind.Pair) {\n\t\t// Don't use node.children here to improve performance\n\t\tlevel++;\n\n\t\t{\n\t\t\tconst child = node.openingBracket;\n\t\t\tnodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length);\n\t\t\tif (lengthLessThanEqual(nodeOffsetStart, endOffset) && lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) {\n\t\t\t\tcollectBrackets(child, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, result, level);\n\t\t\t}\n\t\t\tnodeOffsetStart = nodeOffsetEnd;\n\t\t}\n\n\t\tif (node.child) {\n\t\t\tconst child = node.child;\n\t\t\tnodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length);\n\t\t\tif (lengthLessThanEqual(nodeOffsetStart, endOffset) && lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) {\n\t\t\t\tcollectBrackets(child, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, result, level);\n\t\t\t}\n\t\t\tnodeOffsetStart = nodeOffsetEnd;\n\t\t}\n\t\tif (node.closingBracket) {\n\t\t\tconst child = node.closingBracket;\n\t\t\tnodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length);\n\t\t\tif (lengthLessThanEqual(nodeOffsetStart, endOffset) && lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) {\n\t\t\t\tcollectBrackets(child, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, result, level);\n\t\t\t}\n\t\t\tnodeOffsetStart = nodeOffsetEnd;\n\t\t}\n\t}\n}\n\nclass CollectBracketPairsContext {\n\tconstructor(\n\t\tpublic readonly result: BracketPairWithMinIndentationInfo[],\n\t\tpublic readonly includeMinIndentation: boolean,\n\t\tpublic readonly textModel: ITextModel,\n\t) {\n\t}\n}\n\nfunction collectBracketPairs(node: AstNode, nodeOffset: Length, nodeOffsetEnd: Length, startOffset: Length, endOffset: Length, context: CollectBracketPairsContext, level: number = 0) {\n\tif (node.kind === AstNodeKind.Pair) {\n\t\tconst openingBracketEnd = lengthAdd(nodeOffset, node.openingBracket.length);\n\t\tlet minIndentation = -1;\n\t\tif (context.includeMinIndentation) {\n\t\t\tminIndentation = node.computeMinIndentation(nodeOffset, context.textModel);\n\t\t}\n\n\t\tcontext.result.push(new BracketPairWithMinIndentationInfo(\n\t\t\tlengthsToRange(nodeOffset, nodeOffsetEnd),\n\t\t\tlengthsToRange(nodeOffset, openingBracketEnd),\n\t\t\tnode.closingBracket\n\t\t\t\t? lengthsToRange(lengthAdd(openingBracketEnd, node.child?.length || lengthZero), nodeOffsetEnd)\n\t\t\t\t: undefined,\n\t\t\tlevel,\n\t\t\tminIndentation\n\t\t));\n\t\tlevel++;\n\t}\n\n\tlet curOffset = nodeOffset;\n\tfor (const child of node.children) {\n\t\tconst childOffset = curOffset;\n\t\tcurOffset = lengthAdd(curOffset, child.length);\n\n\t\tif (lengthLessThanEqual(childOffset, endOffset) && lengthLessThanEqual(startOffset, curOffset)) {\n\t\t\tcollectBracketPairs(child, childOffset, curOffset, startOffset, endOffset, context, level);\n\t\t}\n\t}\n}\n\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter } from 'vs/base/common/event';\nimport { Disposable, DisposableStore, IDisposable, IReference, MutableDisposable } from 'vs/base/common/lifecycle';\nimport { LineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { IPosition, Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { BracketPairsTree } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/bracketPairsTree';\nimport { BracketInfo, BracketPairInfo, BracketPairWithMinIndentationInfo, IBracketPairsTextModelPart, IFoundBracket } from 'vs/editor/common/textModelBracketPairs';\nimport { TextModel } from 'vs/editor/common/model/textModel';\nimport { IModelContentChangedEvent } from 'vs/editor/common/textModelEvents';\nimport { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';\nimport { ignoreBracketsInToken } from 'vs/editor/common/languages/supports';\nimport { RichEditBrackets, BracketsUtils, RichEditBracket } from 'vs/editor/common/languages/supports/richEditBrackets';\n\nexport class BracketPairsTextModelPart extends Disposable implements IBracketPairsTextModelPart {\n\tprivate readonly bracketPairsTree = this._register(new MutableDisposable>());\n\n\tprivate readonly onDidChangeEmitter = new Emitter();\n\tpublic readonly onDidChange = this.onDidChangeEmitter.event;\n\n\tprivate get isDocumentSupported() {\n\t\tconst maxSupportedDocumentLength = /* max lines */ 50_000 * /* average column count */ 100;\n\t\treturn this.textModel.getValueLength() <= maxSupportedDocumentLength;\n\t}\n\n\tprivate bracketsRequested = false;\n\n\tpublic constructor(\n\t\tprivate readonly textModel: TextModel,\n\t\tprivate readonly languageConfigurationService: ILanguageConfigurationService\n\t) {\n\t\tsuper();\n\n\t\tthis._register(textModel.onDidChangeOptions(e => {\n\t\t\tthis.bracketPairsTree.clear();\n\t\t\tthis.updateBracketPairsTree();\n\t\t}));\n\n\t\tthis._register(textModel.onDidChangeLanguage(e => {\n\t\t\tthis.bracketPairsTree.clear();\n\t\t\tthis.updateBracketPairsTree();\n\t\t}));\n\n\t\tthis._register(\n\t\t\tthis.languageConfigurationService.onDidChange(e => {\n\t\t\t\tif (!e.languageId || this.bracketPairsTree.value?.object.didLanguageChange(e.languageId)) {\n\t\t\t\t\tthis.bracketPairsTree.clear();\n\t\t\t\t\tthis.updateBracketPairsTree();\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n\n\tprivate updateBracketPairsTree() {\n\t\tif (this.bracketsRequested && this.isDocumentSupported) {\n\t\t\tif (!this.bracketPairsTree.value) {\n\t\t\t\tconst store = new DisposableStore();\n\n\t\t\t\tthis.bracketPairsTree.value = createDisposableRef(\n\t\t\t\t\tstore.add(\n\t\t\t\t\t\tnew BracketPairsTree(this.textModel, (languageId) => {\n\t\t\t\t\t\t\treturn this.languageConfigurationService.getLanguageConfiguration(languageId);\n\t\t\t\t\t\t})\n\t\t\t\t\t),\n\t\t\t\t\tstore\n\t\t\t\t);\n\t\t\t\tstore.add(this.bracketPairsTree.value.object.onDidChange(e => this.onDidChangeEmitter.fire(e)));\n\t\t\t\tthis.onDidChangeEmitter.fire();\n\t\t\t}\n\t\t} else {\n\t\t\tif (this.bracketPairsTree.value) {\n\t\t\t\tthis.bracketPairsTree.clear();\n\t\t\t\t// Important: Don't call fire if there was no change!\n\t\t\t\tthis.onDidChangeEmitter.fire();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic handleContentChanged(change: IModelContentChangedEvent) {\n\t\tthis.bracketPairsTree.value?.object.handleContentChanged(change);\n\t}\n\n\t/**\n\t * Returns all bracket pairs that intersect the given range.\n\t * The result is sorted by the start position.\n\t*/\n\tpublic getBracketPairsInRange(range: Range): BracketPairInfo[] {\n\t\tthis.bracketsRequested = true;\n\t\tthis.updateBracketPairsTree();\n\t\treturn this.bracketPairsTree.value?.object.getBracketPairsInRange(range, false) || [];\n\t}\n\n\tpublic getBracketPairsInRangeWithMinIndentation(range: Range): BracketPairWithMinIndentationInfo[] {\n\t\tthis.bracketsRequested = true;\n\t\tthis.updateBracketPairsTree();\n\t\treturn this.bracketPairsTree.value?.object.getBracketPairsInRange(range, true) || [];\n\t}\n\n\tpublic getBracketsInRange(range: Range): BracketInfo[] {\n\t\tthis.bracketsRequested = true;\n\t\tthis.updateBracketPairsTree();\n\t\treturn this.bracketPairsTree.value?.object.getBracketsInRange(range) || [];\n\t}\n\n\tpublic findMatchingBracketUp(_bracket: string, _position: IPosition): Range | null {\n\t\tconst bracket = _bracket.toLowerCase();\n\t\tconst position = this.textModel.validatePosition(_position);\n\n\t\tconst languageId = this.textModel.getLanguageIdAtPosition(position.lineNumber, position.column);\n\t\tconst bracketsSupport = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n\n\t\tif (!bracketsSupport) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst data = bracketsSupport.textIsBracket[bracket];\n\n\t\tif (!data) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn stripBracketSearchCanceled(this._findMatchingBracketUp(data, position, null));\n\t}\n\n\tpublic matchBracket(position: IPosition): [Range, Range] | null {\n\t\treturn this._matchBracket(this.textModel.validatePosition(position));\n\t}\n\n\tprivate _establishBracketSearchOffsets(position: Position, lineTokens: LineTokens, modeBrackets: RichEditBrackets, tokenIndex: number) {\n\t\tconst tokenCount = lineTokens.getCount();\n\t\tconst currentLanguageId = lineTokens.getLanguageId(tokenIndex);\n\n\t\t// limit search to not go before `maxBracketLength`\n\t\tlet searchStartOffset = Math.max(0, position.column - 1 - modeBrackets.maxBracketLength);\n\t\tfor (let i = tokenIndex - 1; i >= 0; i--) {\n\t\t\tconst tokenEndOffset = lineTokens.getEndOffset(i);\n\t\t\tif (tokenEndOffset <= searchStartOffset) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (ignoreBracketsInToken(lineTokens.getStandardTokenType(i)) || lineTokens.getLanguageId(i) !== currentLanguageId) {\n\t\t\t\tsearchStartOffset = tokenEndOffset;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// limit search to not go after `maxBracketLength`\n\t\tlet searchEndOffset = Math.min(lineTokens.getLineContent().length, position.column - 1 + modeBrackets.maxBracketLength);\n\t\tfor (let i = tokenIndex + 1; i < tokenCount; i++) {\n\t\t\tconst tokenStartOffset = lineTokens.getStartOffset(i);\n\t\t\tif (tokenStartOffset >= searchEndOffset) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (ignoreBracketsInToken(lineTokens.getStandardTokenType(i)) || lineTokens.getLanguageId(i) !== currentLanguageId) {\n\t\t\t\tsearchEndOffset = tokenStartOffset;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn { searchStartOffset, searchEndOffset };\n\t}\n\n\tprivate _matchBracket(position: Position): [Range, Range] | null {\n\t\tconst lineNumber = position.lineNumber;\n\t\tconst lineTokens = this.textModel.getLineTokens(lineNumber);\n\t\tconst lineText = this.textModel.getLineContent(lineNumber);\n\n\t\tconst tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n\t\tif (tokenIndex < 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst currentModeBrackets = this.languageConfigurationService.getLanguageConfiguration(lineTokens.getLanguageId(tokenIndex)).brackets;\n\n\t\t// check that the token is not to be ignored\n\t\tif (currentModeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex))) {\n\n\t\t\tlet { searchStartOffset, searchEndOffset } = this._establishBracketSearchOffsets(position, lineTokens, currentModeBrackets, tokenIndex);\n\n\t\t\t// it might be the case that [currentTokenStart -> currentTokenEnd] contains multiple brackets\n\t\t\t// `bestResult` will contain the most right-side result\n\t\t\tlet bestResult: [Range, Range] | null = null;\n\t\t\twhile (true) {\n\t\t\t\tconst foundBracket = BracketsUtils.findNextBracketInRange(currentModeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\tif (!foundBracket) {\n\t\t\t\t\t// there are no more brackets in this text\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// check that we didn't hit a bracket too far away from position\n\t\t\t\tif (foundBracket.startColumn <= position.column && position.column <= foundBracket.endColumn) {\n\t\t\t\t\tconst foundBracketText = lineText.substring(foundBracket.startColumn - 1, foundBracket.endColumn - 1).toLowerCase();\n\t\t\t\t\tconst r = this._matchFoundBracket(foundBracket, currentModeBrackets.textIsBracket[foundBracketText], currentModeBrackets.textIsOpenBracket[foundBracketText], null);\n\t\t\t\t\tif (r) {\n\t\t\t\t\t\tif (r instanceof BracketSearchCanceled) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbestResult = r;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsearchStartOffset = foundBracket.endColumn - 1;\n\t\t\t}\n\n\t\t\tif (bestResult) {\n\t\t\t\treturn bestResult;\n\t\t\t}\n\t\t}\n\n\t\t// If position is in between two tokens, try also looking in the previous token\n\t\tif (tokenIndex > 0 && lineTokens.getStartOffset(tokenIndex) === position.column - 1) {\n\t\t\tconst prevTokenIndex = tokenIndex - 1;\n\t\t\tconst prevModeBrackets = this.languageConfigurationService.getLanguageConfiguration(lineTokens.getLanguageId(prevTokenIndex)).brackets;\n\n\t\t\t// check that previous token is not to be ignored\n\t\t\tif (prevModeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(prevTokenIndex))) {\n\n\t\t\t\tconst { searchStartOffset, searchEndOffset } = this._establishBracketSearchOffsets(position, lineTokens, prevModeBrackets, prevTokenIndex);\n\n\t\t\t\tconst foundBracket = BracketsUtils.findPrevBracketInRange(prevModeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\n\t\t\t\t// check that we didn't hit a bracket too far away from position\n\t\t\t\tif (foundBracket && foundBracket.startColumn <= position.column && position.column <= foundBracket.endColumn) {\n\t\t\t\t\tconst foundBracketText = lineText.substring(foundBracket.startColumn - 1, foundBracket.endColumn - 1).toLowerCase();\n\t\t\t\t\tconst r = this._matchFoundBracket(foundBracket, prevModeBrackets.textIsBracket[foundBracketText], prevModeBrackets.textIsOpenBracket[foundBracketText], null);\n\t\t\t\t\tif (r) {\n\t\t\t\t\t\tif (r instanceof BracketSearchCanceled) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn r;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate _matchFoundBracket(foundBracket: Range, data: RichEditBracket, isOpen: boolean, continueSearchPredicate: ContinueBracketSearchPredicate): [Range, Range] | null | BracketSearchCanceled {\n\t\tif (!data) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst matched = (\n\t\t\tisOpen\n\t\t\t\t? this._findMatchingBracketDown(data, foundBracket.getEndPosition(), continueSearchPredicate)\n\t\t\t\t: this._findMatchingBracketUp(data, foundBracket.getStartPosition(), continueSearchPredicate)\n\t\t);\n\n\t\tif (!matched) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (matched instanceof BracketSearchCanceled) {\n\t\t\treturn matched;\n\t\t}\n\n\t\treturn [foundBracket, matched];\n\t}\n\n\tprivate _findMatchingBracketUp(bracket: RichEditBracket, position: Position, continueSearchPredicate: ContinueBracketSearchPredicate): Range | null | BracketSearchCanceled {\n\t\t// console.log('_findMatchingBracketUp: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position));\n\n\t\tconst languageId = bracket.languageId;\n\t\tconst reversedBracketRegex = bracket.reversedRegex;\n\t\tlet count = -1;\n\n\t\tlet totalCallCount = 0;\n\t\tconst searchPrevMatchingBracketInRange = (lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): Range | null | BracketSearchCanceled => {\n\t\t\twhile (true) {\n\t\t\t\tif (continueSearchPredicate && (++totalCallCount) % 100 === 0 && !continueSearchPredicate()) {\n\t\t\t\t\treturn BracketSearchCanceled.INSTANCE;\n\t\t\t\t}\n\t\t\t\tconst r = BracketsUtils.findPrevBracketInRange(reversedBracketRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\tif (!r) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tconst hitText = lineText.substring(r.startColumn - 1, r.endColumn - 1).toLowerCase();\n\t\t\t\tif (bracket.isOpen(hitText)) {\n\t\t\t\t\tcount++;\n\t\t\t\t} else if (bracket.isClose(hitText)) {\n\t\t\t\t\tcount--;\n\t\t\t\t}\n\n\t\t\t\tif (count === 0) {\n\t\t\t\t\treturn r;\n\t\t\t\t}\n\n\t\t\t\tsearchEndOffset = r.startColumn - 1;\n\t\t\t}\n\n\t\t\treturn null;\n\t\t};\n\n\t\tfor (let lineNumber = position.lineNumber; lineNumber >= 1; lineNumber--) {\n\t\t\tconst lineTokens = this.textModel.getLineTokens(lineNumber);\n\t\t\tconst tokenCount = lineTokens.getCount();\n\t\t\tconst lineText = this.textModel.getLineContent(lineNumber);\n\n\t\t\tlet tokenIndex = tokenCount - 1;\n\t\t\tlet searchStartOffset = lineText.length;\n\t\t\tlet searchEndOffset = lineText.length;\n\t\t\tif (lineNumber === position.lineNumber) {\n\t\t\t\ttokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n\t\t\t\tsearchStartOffset = position.column - 1;\n\t\t\t\tsearchEndOffset = position.column - 1;\n\t\t\t}\n\n\t\t\tlet prevSearchInToken = true;\n\t\t\tfor (; tokenIndex >= 0; tokenIndex--) {\n\t\t\t\tconst searchInToken = (lineTokens.getLanguageId(tokenIndex) === languageId && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));\n\n\t\t\t\tif (searchInToken) {\n\t\t\t\t\t// this token should be searched\n\t\t\t\t\tif (prevSearchInToken) {\n\t\t\t\t\t\t// the previous token should be searched, simply extend searchStartOffset\n\t\t\t\t\t\tsearchStartOffset = lineTokens.getStartOffset(tokenIndex);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// the previous token should not be searched\n\t\t\t\t\t\tsearchStartOffset = lineTokens.getStartOffset(tokenIndex);\n\t\t\t\t\t\tsearchEndOffset = lineTokens.getEndOffset(tokenIndex);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// this token should not be searched\n\t\t\t\t\tif (prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\t\t\tconst r = searchPrevMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\t\t\tif (r) {\n\t\t\t\t\t\t\treturn r;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tprevSearchInToken = searchInToken;\n\t\t\t}\n\n\t\t\tif (prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\tconst r = searchPrevMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\tif (r) {\n\t\t\t\t\treturn r;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate _findMatchingBracketDown(bracket: RichEditBracket, position: Position, continueSearchPredicate: ContinueBracketSearchPredicate): Range | null | BracketSearchCanceled {\n\t\t// console.log('_findMatchingBracketDown: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position));\n\n\t\tconst languageId = bracket.languageId;\n\t\tconst bracketRegex = bracket.forwardRegex;\n\t\tlet count = 1;\n\n\t\tlet totalCallCount = 0;\n\t\tconst searchNextMatchingBracketInRange = (lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): Range | null | BracketSearchCanceled => {\n\t\t\twhile (true) {\n\t\t\t\tif (continueSearchPredicate && (++totalCallCount) % 100 === 0 && !continueSearchPredicate()) {\n\t\t\t\t\treturn BracketSearchCanceled.INSTANCE;\n\t\t\t\t}\n\t\t\t\tconst r = BracketsUtils.findNextBracketInRange(bracketRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\tif (!r) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tconst hitText = lineText.substring(r.startColumn - 1, r.endColumn - 1).toLowerCase();\n\t\t\t\tif (bracket.isOpen(hitText)) {\n\t\t\t\t\tcount++;\n\t\t\t\t} else if (bracket.isClose(hitText)) {\n\t\t\t\t\tcount--;\n\t\t\t\t}\n\n\t\t\t\tif (count === 0) {\n\t\t\t\t\treturn r;\n\t\t\t\t}\n\n\t\t\t\tsearchStartOffset = r.endColumn - 1;\n\t\t\t}\n\n\t\t\treturn null;\n\t\t};\n\n\t\tconst lineCount = this.textModel.getLineCount();\n\t\tfor (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {\n\t\t\tconst lineTokens = this.textModel.getLineTokens(lineNumber);\n\t\t\tconst tokenCount = lineTokens.getCount();\n\t\t\tconst lineText = this.textModel.getLineContent(lineNumber);\n\n\t\t\tlet tokenIndex = 0;\n\t\t\tlet searchStartOffset = 0;\n\t\t\tlet searchEndOffset = 0;\n\t\t\tif (lineNumber === position.lineNumber) {\n\t\t\t\ttokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n\t\t\t\tsearchStartOffset = position.column - 1;\n\t\t\t\tsearchEndOffset = position.column - 1;\n\t\t\t}\n\n\t\t\tlet prevSearchInToken = true;\n\t\t\tfor (; tokenIndex < tokenCount; tokenIndex++) {\n\t\t\t\tconst searchInToken = (lineTokens.getLanguageId(tokenIndex) === languageId && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));\n\n\t\t\t\tif (searchInToken) {\n\t\t\t\t\t// this token should be searched\n\t\t\t\t\tif (prevSearchInToken) {\n\t\t\t\t\t\t// the previous token should be searched, simply extend searchEndOffset\n\t\t\t\t\t\tsearchEndOffset = lineTokens.getEndOffset(tokenIndex);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// the previous token should not be searched\n\t\t\t\t\t\tsearchStartOffset = lineTokens.getStartOffset(tokenIndex);\n\t\t\t\t\t\tsearchEndOffset = lineTokens.getEndOffset(tokenIndex);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// this token should not be searched\n\t\t\t\t\tif (prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\t\t\tconst r = searchNextMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\t\t\tif (r) {\n\t\t\t\t\t\t\treturn r;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tprevSearchInToken = searchInToken;\n\t\t\t}\n\n\t\t\tif (prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\tconst r = searchNextMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\tif (r) {\n\t\t\t\t\treturn r;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic findPrevBracket(_position: IPosition): IFoundBracket | null {\n\t\tconst position = this.textModel.validatePosition(_position);\n\n\t\tlet languageId: string | null = null;\n\t\tlet modeBrackets: RichEditBrackets | null = null;\n\t\tfor (let lineNumber = position.lineNumber; lineNumber >= 1; lineNumber--) {\n\t\t\tconst lineTokens = this.textModel.getLineTokens(lineNumber);\n\t\t\tconst tokenCount = lineTokens.getCount();\n\t\t\tconst lineText = this.textModel.getLineContent(lineNumber);\n\n\t\t\tlet tokenIndex = tokenCount - 1;\n\t\t\tlet searchStartOffset = lineText.length;\n\t\t\tlet searchEndOffset = lineText.length;\n\t\t\tif (lineNumber === position.lineNumber) {\n\t\t\t\ttokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n\t\t\t\tsearchStartOffset = position.column - 1;\n\t\t\t\tsearchEndOffset = position.column - 1;\n\t\t\t\tconst tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n\t\t\t\tif (languageId !== tokenLanguageId) {\n\t\t\t\t\tlanguageId = tokenLanguageId;\n\t\t\t\t\tmodeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet prevSearchInToken = true;\n\t\t\tfor (; tokenIndex >= 0; tokenIndex--) {\n\t\t\t\tconst tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n\n\t\t\t\tif (languageId !== tokenLanguageId) {\n\t\t\t\t\t// language id change!\n\t\t\t\t\tif (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\t\t\tconst r = BracketsUtils.findPrevBracketInRange(modeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\t\t\tif (r) {\n\t\t\t\t\t\t\treturn this._toFoundBracket(modeBrackets, r);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprevSearchInToken = false;\n\t\t\t\t\t}\n\t\t\t\t\tlanguageId = tokenLanguageId;\n\t\t\t\t\tmodeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n\t\t\t\t}\n\n\t\t\t\tconst searchInToken = (!!modeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));\n\n\t\t\t\tif (searchInToken) {\n\t\t\t\t\t// this token should be searched\n\t\t\t\t\tif (prevSearchInToken) {\n\t\t\t\t\t\t// the previous token should be searched, simply extend searchStartOffset\n\t\t\t\t\t\tsearchStartOffset = lineTokens.getStartOffset(tokenIndex);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// the previous token should not be searched\n\t\t\t\t\t\tsearchStartOffset = lineTokens.getStartOffset(tokenIndex);\n\t\t\t\t\t\tsearchEndOffset = lineTokens.getEndOffset(tokenIndex);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// this token should not be searched\n\t\t\t\t\tif (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\t\t\tconst r = BracketsUtils.findPrevBracketInRange(modeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\t\t\tif (r) {\n\t\t\t\t\t\t\treturn this._toFoundBracket(modeBrackets, r);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tprevSearchInToken = searchInToken;\n\t\t\t}\n\n\t\t\tif (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\tconst r = BracketsUtils.findPrevBracketInRange(modeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\tif (r) {\n\t\t\t\t\treturn this._toFoundBracket(modeBrackets, r);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic findNextBracket(_position: IPosition): IFoundBracket | null {\n\t\tconst position = this.textModel.validatePosition(_position);\n\t\tconst lineCount = this.textModel.getLineCount();\n\n\t\tlet languageId: string | null = null;\n\t\tlet modeBrackets: RichEditBrackets | null = null;\n\t\tfor (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {\n\t\t\tconst lineTokens = this.textModel.getLineTokens(lineNumber);\n\t\t\tconst tokenCount = lineTokens.getCount();\n\t\t\tconst lineText = this.textModel.getLineContent(lineNumber);\n\n\t\t\tlet tokenIndex = 0;\n\t\t\tlet searchStartOffset = 0;\n\t\t\tlet searchEndOffset = 0;\n\t\t\tif (lineNumber === position.lineNumber) {\n\t\t\t\ttokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n\t\t\t\tsearchStartOffset = position.column - 1;\n\t\t\t\tsearchEndOffset = position.column - 1;\n\t\t\t\tconst tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n\t\t\t\tif (languageId !== tokenLanguageId) {\n\t\t\t\t\tlanguageId = tokenLanguageId;\n\t\t\t\t\tmodeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet prevSearchInToken = true;\n\t\t\tfor (; tokenIndex < tokenCount; tokenIndex++) {\n\t\t\t\tconst tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n\n\t\t\t\tif (languageId !== tokenLanguageId) {\n\t\t\t\t\t// language id change!\n\t\t\t\t\tif (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\t\t\tconst r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\t\t\tif (r) {\n\t\t\t\t\t\t\treturn this._toFoundBracket(modeBrackets, r);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprevSearchInToken = false;\n\t\t\t\t\t}\n\t\t\t\t\tlanguageId = tokenLanguageId;\n\t\t\t\t\tmodeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n\t\t\t\t}\n\n\t\t\t\tconst searchInToken = (!!modeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));\n\t\t\t\tif (searchInToken) {\n\t\t\t\t\t// this token should be searched\n\t\t\t\t\tif (prevSearchInToken) {\n\t\t\t\t\t\t// the previous token should be searched, simply extend searchEndOffset\n\t\t\t\t\t\tsearchEndOffset = lineTokens.getEndOffset(tokenIndex);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// the previous token should not be searched\n\t\t\t\t\t\tsearchStartOffset = lineTokens.getStartOffset(tokenIndex);\n\t\t\t\t\t\tsearchEndOffset = lineTokens.getEndOffset(tokenIndex);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// this token should not be searched\n\t\t\t\t\tif (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\t\t\tconst r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\t\t\tif (r) {\n\t\t\t\t\t\t\treturn this._toFoundBracket(modeBrackets, r);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tprevSearchInToken = searchInToken;\n\t\t\t}\n\n\t\t\tif (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\tconst r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\tif (r) {\n\t\t\t\t\treturn this._toFoundBracket(modeBrackets, r);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic findEnclosingBrackets(_position: IPosition, maxDuration?: number): [Range, Range] | null {\n\t\tlet continueSearchPredicate: ContinueBracketSearchPredicate;\n\t\tif (typeof maxDuration === 'undefined') {\n\t\t\tcontinueSearchPredicate = null;\n\t\t} else {\n\t\t\tconst startTime = Date.now();\n\t\t\tcontinueSearchPredicate = () => {\n\t\t\t\treturn (Date.now() - startTime <= maxDuration);\n\t\t\t};\n\t\t}\n\t\tconst position = this.textModel.validatePosition(_position);\n\t\tconst lineCount = this.textModel.getLineCount();\n\t\tconst savedCounts = new Map();\n\n\t\tlet counts: number[] = [];\n\t\tconst resetCounts = (languageId: string, modeBrackets: RichEditBrackets | null) => {\n\t\t\tif (!savedCounts.has(languageId)) {\n\t\t\t\tconst tmp = [];\n\t\t\t\tfor (let i = 0, len = modeBrackets ? modeBrackets.brackets.length : 0; i < len; i++) {\n\t\t\t\t\ttmp[i] = 0;\n\t\t\t\t}\n\t\t\t\tsavedCounts.set(languageId, tmp);\n\t\t\t}\n\t\t\tcounts = savedCounts.get(languageId)!;\n\t\t};\n\n\t\tlet totalCallCount = 0;\n\t\tconst searchInRange = (modeBrackets: RichEditBrackets, lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): [Range, Range] | null | BracketSearchCanceled => {\n\t\t\twhile (true) {\n\t\t\t\tif (continueSearchPredicate && (++totalCallCount) % 100 === 0 && !continueSearchPredicate()) {\n\t\t\t\t\treturn BracketSearchCanceled.INSTANCE;\n\t\t\t\t}\n\t\t\t\tconst r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\tif (!r) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tconst hitText = lineText.substring(r.startColumn - 1, r.endColumn - 1).toLowerCase();\n\t\t\t\tconst bracket = modeBrackets.textIsBracket[hitText];\n\t\t\t\tif (bracket) {\n\t\t\t\t\tif (bracket.isOpen(hitText)) {\n\t\t\t\t\t\tcounts[bracket.index]++;\n\t\t\t\t\t} else if (bracket.isClose(hitText)) {\n\t\t\t\t\t\tcounts[bracket.index]--;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (counts[bracket.index] === -1) {\n\t\t\t\t\t\treturn this._matchFoundBracket(r, bracket, false, continueSearchPredicate);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsearchStartOffset = r.endColumn - 1;\n\t\t\t}\n\t\t\treturn null;\n\t\t};\n\n\t\tlet languageId: string | null = null;\n\t\tlet modeBrackets: RichEditBrackets | null = null;\n\t\tfor (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {\n\t\t\tconst lineTokens = this.textModel.getLineTokens(lineNumber);\n\t\t\tconst tokenCount = lineTokens.getCount();\n\t\t\tconst lineText = this.textModel.getLineContent(lineNumber);\n\n\t\t\tlet tokenIndex = 0;\n\t\t\tlet searchStartOffset = 0;\n\t\t\tlet searchEndOffset = 0;\n\t\t\tif (lineNumber === position.lineNumber) {\n\t\t\t\ttokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n\t\t\t\tsearchStartOffset = position.column - 1;\n\t\t\t\tsearchEndOffset = position.column - 1;\n\t\t\t\tconst tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n\t\t\t\tif (languageId !== tokenLanguageId) {\n\t\t\t\t\tlanguageId = tokenLanguageId;\n\t\t\t\t\tmodeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n\t\t\t\t\tresetCounts(languageId, modeBrackets);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet prevSearchInToken = true;\n\t\t\tfor (; tokenIndex < tokenCount; tokenIndex++) {\n\t\t\t\tconst tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n\n\t\t\t\tif (languageId !== tokenLanguageId) {\n\t\t\t\t\t// language id change!\n\t\t\t\t\tif (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\t\t\tconst r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\t\t\tif (r) {\n\t\t\t\t\t\t\treturn stripBracketSearchCanceled(r);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprevSearchInToken = false;\n\t\t\t\t\t}\n\t\t\t\t\tlanguageId = tokenLanguageId;\n\t\t\t\t\tmodeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n\t\t\t\t\tresetCounts(languageId, modeBrackets);\n\t\t\t\t}\n\n\t\t\t\tconst searchInToken = (!!modeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));\n\t\t\t\tif (searchInToken) {\n\t\t\t\t\t// this token should be searched\n\t\t\t\t\tif (prevSearchInToken) {\n\t\t\t\t\t\t// the previous token should be searched, simply extend searchEndOffset\n\t\t\t\t\t\tsearchEndOffset = lineTokens.getEndOffset(tokenIndex);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// the previous token should not be searched\n\t\t\t\t\t\tsearchStartOffset = lineTokens.getStartOffset(tokenIndex);\n\t\t\t\t\t\tsearchEndOffset = lineTokens.getEndOffset(tokenIndex);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// this token should not be searched\n\t\t\t\t\tif (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\t\t\tconst r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\t\t\tif (r) {\n\t\t\t\t\t\t\treturn stripBracketSearchCanceled(r);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tprevSearchInToken = searchInToken;\n\t\t\t}\n\n\t\t\tif (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n\t\t\t\tconst r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);\n\t\t\t\tif (r) {\n\t\t\t\t\treturn stripBracketSearchCanceled(r);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate _toFoundBracket(modeBrackets: RichEditBrackets, r: Range): IFoundBracket | null {\n\t\tif (!r) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlet text = this.textModel.getValueInRange(r);\n\t\ttext = text.toLowerCase();\n\n\t\tconst data = modeBrackets.textIsBracket[text];\n\t\tif (!data) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\trange: r,\n\t\t\topen: data.open,\n\t\t\tclose: data.close,\n\t\t\tisOpen: modeBrackets.textIsOpenBracket[text]\n\t\t};\n\t}\n}\n\nfunction createDisposableRef(object: T, disposable?: IDisposable): IReference {\n\treturn {\n\t\tobject,\n\t\tdispose: () => disposable?.dispose(),\n\t};\n}\n\ntype ContinueBracketSearchPredicate = null | (() => boolean);\n\nclass BracketSearchCanceled {\n\tpublic static INSTANCE = new BracketSearchCanceled();\n\t_searchCanceledBrand = undefined;\n\tprivate constructor() { }\n}\n\nfunction stripBracketSearchCanceled(result: T | null | BracketSearchCanceled): T | null {\n\tif (result instanceof BracketSearchCanceled) {\n\t\treturn null;\n\t}\n\treturn result;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';\nimport { AstNode, AstNodeKind } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/ast';\nimport { LanguageAgnosticBracketTokens } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/brackets';\nimport { Length, lengthAdd, lengthGetColumnCountIfZeroLineCount, lengthZero } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/length';\nimport { parseDocument } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/parser';\nimport { DenseKeyProvider } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/smallImmutableSet';\nimport { ITokenizerSource, TextBufferTokenizer } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/tokenizer';\nimport { IViewLineTokens } from 'vs/editor/common/tokens/lineTokens';\n\nexport function fixBracketsInLine(tokens: IViewLineTokens, languageConfigurationService: ILanguageConfigurationService): string {\n\tconst denseKeyProvider = new DenseKeyProvider();\n\tconst bracketTokens = new LanguageAgnosticBracketTokens(denseKeyProvider, (languageId) =>\n\t\tlanguageConfigurationService.getLanguageConfiguration(languageId)\n\t);\n\tconst tokenizer = new TextBufferTokenizer(\n\t\tnew StaticTokenizerSource([tokens]),\n\t\tbracketTokens\n\t);\n\tconst node = parseDocument(tokenizer, [], undefined, true);\n\n\tlet str = '';\n\tconst line = tokens.getLineContent();\n\n\tfunction processNode(node: AstNode, offset: Length) {\n\t\tif (node.kind === AstNodeKind.Pair) {\n\t\t\tprocessNode(node.openingBracket, offset);\n\t\t\toffset = lengthAdd(offset, node.openingBracket.length);\n\n\t\t\tif (node.child) {\n\t\t\t\tprocessNode(node.child, offset);\n\t\t\t\toffset = lengthAdd(offset, node.child.length);\n\t\t\t}\n\t\t\tif (node.closingBracket) {\n\t\t\t\tprocessNode(node.closingBracket, offset);\n\t\t\t\toffset = lengthAdd(offset, node.closingBracket.length);\n\t\t\t} else {\n\t\t\t\tconst singleLangBracketTokens = bracketTokens.getSingleLanguageBracketTokens(node.openingBracket.languageId);\n\n\t\t\t\tconst closingTokenText = singleLangBracketTokens.findClosingTokenText(node.openingBracket.bracketIds);\n\t\t\t\tstr += closingTokenText;\n\t\t\t}\n\t\t} else if (node.kind === AstNodeKind.UnexpectedClosingBracket) {\n\t\t\t// remove the bracket\n\t\t} else if (node.kind === AstNodeKind.Text || node.kind === AstNodeKind.Bracket) {\n\t\t\tstr += line.substring(\n\t\t\t\tlengthGetColumnCountIfZeroLineCount(offset),\n\t\t\t\tlengthGetColumnCountIfZeroLineCount(lengthAdd(offset, node.length))\n\t\t\t);\n\t\t} else if (node.kind === AstNodeKind.List) {\n\t\t\tfor (const child of node.children) {\n\t\t\t\tprocessNode(child, offset);\n\t\t\t\toffset = lengthAdd(offset, child.length);\n\t\t\t}\n\t\t}\n\t}\n\n\tprocessNode(node, lengthZero);\n\n\treturn str;\n}\n\nclass StaticTokenizerSource implements ITokenizerSource {\n\tconstructor(private readonly lines: IViewLineTokens[]) { }\n\tgetLineCount(): number {\n\t\treturn this.lines.length;\n\t}\n\tgetLineLength(lineNumber: number): number {\n\t\treturn this.lines[lineNumber - 1].getLineContent().length;\n\t}\n\tgetLineTokens(lineNumber: number): IViewLineTokens {\n\t\treturn this.lines[lineNumber - 1];\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationTokenSource } from 'vs/base/common/cancellation';\nimport { Emitter } from 'vs/base/common/event';\nimport { KeyChord, KeyMod as ConstKeyMod } from 'vs/base/common/keyCodes';\nimport { URI } from 'vs/base/common/uri';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { Token } from 'vs/editor/common/languages';\nimport * as standaloneEnums from 'vs/editor/common/standalone/standaloneEnums';\n\nexport class KeyMod {\n\tpublic static readonly CtrlCmd: number = ConstKeyMod.CtrlCmd;\n\tpublic static readonly Shift: number = ConstKeyMod.Shift;\n\tpublic static readonly Alt: number = ConstKeyMod.Alt;\n\tpublic static readonly WinCtrl: number = ConstKeyMod.WinCtrl;\n\n\tpublic static chord(firstPart: number, secondPart: number): number {\n\t\treturn KeyChord(firstPart, secondPart);\n\t}\n}\n\nexport function createMonacoBaseAPI(): typeof monaco {\n\treturn {\n\t\teditor: undefined!, // undefined override expected here\n\t\tlanguages: undefined!, // undefined override expected here\n\t\tCancellationTokenSource: CancellationTokenSource,\n\t\tEmitter: Emitter,\n\t\tKeyCode: standaloneEnums.KeyCode,\n\t\tKeyMod: KeyMod,\n\t\tPosition: Position,\n\t\tRange: Range,\n\t\tSelection: Selection,\n\t\tSelectionDirection: standaloneEnums.SelectionDirection,\n\t\tMarkerSeverity: standaloneEnums.MarkerSeverity,\n\t\tMarkerTag: standaloneEnums.MarkerTag,\n\t\tUri: URI,\n\t\tToken: Token\n\t};\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { stringDiff } from 'vs/base/common/diff/diff';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { globals } from 'vs/base/common/platform';\nimport { URI } from 'vs/base/common/uri';\nimport { IRequestHandler } from 'vs/base/common/worker/simpleWorker';\nimport { IPosition, Position } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { DiffComputer, IDiffComputationResult } from 'vs/editor/common/diff/diffComputer';\nimport { EndOfLineSequence } from 'vs/editor/common/model';\nimport { IMirrorTextModel, IModelChangedEvent, MirrorTextModel as BaseMirrorModel } from 'vs/editor/common/model/mirrorTextModel';\nimport { ensureValidWordDefinition, getWordAtText, IWordAtPosition } from 'vs/editor/common/core/wordHelper';\nimport { IInplaceReplaceSupportResult, ILink, TextEdit } from 'vs/editor/common/languages';\nimport { ILinkComputerTarget, computeLinks } from 'vs/editor/common/languages/linkComputer';\nimport { BasicInplaceReplace } from 'vs/editor/common/languages/supports/inplaceReplaceSupport';\nimport { IUnicodeHighlightsResult } from 'vs/editor/common/services/editorWorker';\nimport { createMonacoBaseAPI } from 'vs/editor/common/services/editorBaseApi';\nimport * as types from 'vs/base/common/types';\nimport { IEditorWorkerHost } from 'vs/editor/common/services/editorWorkerHost';\nimport { StopWatch } from 'vs/base/common/stopwatch';\nimport { UnicodeTextModelHighlighter, UnicodeHighlighterOptions } from 'vs/editor/common/languages/unicodeTextModelHighlighter';\n\nexport interface IMirrorModel extends IMirrorTextModel {\n\treadonly uri: URI;\n\treadonly version: number;\n\tgetValue(): string;\n}\n\nexport interface IWorkerContext {\n\t/**\n\t * A proxy to the main thread host object.\n\t */\n\thost: H;\n\t/**\n\t * Get all available mirror models in this worker.\n\t */\n\tgetMirrorModels(): IMirrorModel[];\n}\n\n/**\n * @internal\n */\nexport interface IRawModelData {\n\turl: string;\n\tversionId: number;\n\tlines: string[];\n\tEOL: string;\n}\n\n/**\n * @internal\n */\nexport interface ICommonModel extends ILinkComputerTarget, IMirrorModel {\n\teol: string;\n\n\tgetLinesContent(): string[];\n\tgetLineCount(): number;\n\tgetLineContent(lineNumber: number): string;\n\tgetLineWords(lineNumber: number, wordDefinition: RegExp): IWordAtPosition[];\n\twords(wordDefinition: RegExp): Iterable;\n\tgetValueInRange(range: IRange): string;\n\tgetWordAtPosition(position: IPosition, wordDefinition: RegExp): Range | null;\n\toffsetAt(position: IPosition): number;\n\tpositionAt(offset: number): IPosition;\n}\n\n/**\n * Range of a word inside a model.\n * @internal\n */\nexport interface IWordRange {\n\t/**\n\t * The index where the word starts.\n\t */\n\treadonly start: number;\n\t/**\n\t * The index where the word ends.\n\t */\n\treadonly end: number;\n}\n\n/**\n * @internal\n */\nexport class MirrorModel extends BaseMirrorModel implements ICommonModel {\n\n\tpublic get uri(): URI {\n\t\treturn this._uri;\n\t}\n\n\tpublic get eol(): string {\n\t\treturn this._eol;\n\t}\n\n\tpublic getValue(): string {\n\t\treturn this.getText();\n\t}\n\n\tpublic getLinesContent(): string[] {\n\t\treturn this._lines.slice(0);\n\t}\n\n\tpublic getLineCount(): number {\n\t\treturn this._lines.length;\n\t}\n\n\tpublic getLineContent(lineNumber: number): string {\n\t\treturn this._lines[lineNumber - 1];\n\t}\n\n\tpublic getWordAtPosition(position: IPosition, wordDefinition: RegExp): Range | null {\n\n\t\tconst wordAtText = getWordAtText(\n\t\t\tposition.column,\n\t\t\tensureValidWordDefinition(wordDefinition),\n\t\t\tthis._lines[position.lineNumber - 1],\n\t\t\t0\n\t\t);\n\n\t\tif (wordAtText) {\n\t\t\treturn new Range(position.lineNumber, wordAtText.startColumn, position.lineNumber, wordAtText.endColumn);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\n\tpublic words(wordDefinition: RegExp): Iterable {\n\n\t\tconst lines = this._lines;\n\t\tconst wordenize = this._wordenize.bind(this);\n\n\t\tlet lineNumber = 0;\n\t\tlet lineText = '';\n\t\tlet wordRangesIdx = 0;\n\t\tlet wordRanges: IWordRange[] = [];\n\n\t\treturn {\n\t\t\t*[Symbol.iterator]() {\n\t\t\t\twhile (true) {\n\t\t\t\t\tif (wordRangesIdx < wordRanges.length) {\n\t\t\t\t\t\tconst value = lineText.substring(wordRanges[wordRangesIdx].start, wordRanges[wordRangesIdx].end);\n\t\t\t\t\t\twordRangesIdx += 1;\n\t\t\t\t\t\tyield value;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (lineNumber < lines.length) {\n\t\t\t\t\t\t\tlineText = lines[lineNumber];\n\t\t\t\t\t\t\twordRanges = wordenize(lineText, wordDefinition);\n\t\t\t\t\t\t\twordRangesIdx = 0;\n\t\t\t\t\t\t\tlineNumber += 1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic getLineWords(lineNumber: number, wordDefinition: RegExp): IWordAtPosition[] {\n\t\tconst content = this._lines[lineNumber - 1];\n\t\tconst ranges = this._wordenize(content, wordDefinition);\n\t\tconst words: IWordAtPosition[] = [];\n\t\tfor (const range of ranges) {\n\t\t\twords.push({\n\t\t\t\tword: content.substring(range.start, range.end),\n\t\t\t\tstartColumn: range.start + 1,\n\t\t\t\tendColumn: range.end + 1\n\t\t\t});\n\t\t}\n\t\treturn words;\n\t}\n\n\tprivate _wordenize(content: string, wordDefinition: RegExp): IWordRange[] {\n\t\tconst result: IWordRange[] = [];\n\t\tlet match: RegExpExecArray | null;\n\n\t\twordDefinition.lastIndex = 0; // reset lastIndex just to be sure\n\n\t\twhile (match = wordDefinition.exec(content)) {\n\t\t\tif (match[0].length === 0) {\n\t\t\t\t// it did match the empty string\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tresult.push({ start: match.index, end: match.index + match[0].length });\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic getValueInRange(range: IRange): string {\n\t\trange = this._validateRange(range);\n\n\t\tif (range.startLineNumber === range.endLineNumber) {\n\t\t\treturn this._lines[range.startLineNumber - 1].substring(range.startColumn - 1, range.endColumn - 1);\n\t\t}\n\n\t\tconst lineEnding = this._eol;\n\t\tconst startLineIndex = range.startLineNumber - 1;\n\t\tconst endLineIndex = range.endLineNumber - 1;\n\t\tconst resultLines: string[] = [];\n\n\t\tresultLines.push(this._lines[startLineIndex].substring(range.startColumn - 1));\n\t\tfor (let i = startLineIndex + 1; i < endLineIndex; i++) {\n\t\t\tresultLines.push(this._lines[i]);\n\t\t}\n\t\tresultLines.push(this._lines[endLineIndex].substring(0, range.endColumn - 1));\n\n\t\treturn resultLines.join(lineEnding);\n\t}\n\n\tpublic offsetAt(position: IPosition): number {\n\t\tposition = this._validatePosition(position);\n\t\tthis._ensureLineStarts();\n\t\treturn this._lineStarts!.getPrefixSum(position.lineNumber - 2) + (position.column - 1);\n\t}\n\n\tpublic positionAt(offset: number): IPosition {\n\t\toffset = Math.floor(offset);\n\t\toffset = Math.max(0, offset);\n\n\t\tthis._ensureLineStarts();\n\t\tconst out = this._lineStarts!.getIndexOf(offset);\n\t\tconst lineLength = this._lines[out.index].length;\n\n\t\t// Ensure we return a valid position\n\t\treturn {\n\t\t\tlineNumber: 1 + out.index,\n\t\t\tcolumn: 1 + Math.min(out.remainder, lineLength)\n\t\t};\n\t}\n\n\tprivate _validateRange(range: IRange): IRange {\n\n\t\tconst start = this._validatePosition({ lineNumber: range.startLineNumber, column: range.startColumn });\n\t\tconst end = this._validatePosition({ lineNumber: range.endLineNumber, column: range.endColumn });\n\n\t\tif (start.lineNumber !== range.startLineNumber\n\t\t\t|| start.column !== range.startColumn\n\t\t\t|| end.lineNumber !== range.endLineNumber\n\t\t\t|| end.column !== range.endColumn) {\n\n\t\t\treturn {\n\t\t\t\tstartLineNumber: start.lineNumber,\n\t\t\t\tstartColumn: start.column,\n\t\t\t\tendLineNumber: end.lineNumber,\n\t\t\t\tendColumn: end.column\n\t\t\t};\n\t\t}\n\n\t\treturn range;\n\t}\n\n\tprivate _validatePosition(position: IPosition): IPosition {\n\t\tif (!Position.isIPosition(position)) {\n\t\t\tthrow new Error('bad position');\n\t\t}\n\t\tlet { lineNumber, column } = position;\n\t\tlet hasChanged = false;\n\n\t\tif (lineNumber < 1) {\n\t\t\tlineNumber = 1;\n\t\t\tcolumn = 1;\n\t\t\thasChanged = true;\n\n\t\t} else if (lineNumber > this._lines.length) {\n\t\t\tlineNumber = this._lines.length;\n\t\t\tcolumn = this._lines[lineNumber - 1].length + 1;\n\t\t\thasChanged = true;\n\n\t\t} else {\n\t\t\tconst maxCharacter = this._lines[lineNumber - 1].length + 1;\n\t\t\tif (column < 1) {\n\t\t\t\tcolumn = 1;\n\t\t\t\thasChanged = true;\n\t\t\t}\n\t\t\telse if (column > maxCharacter) {\n\t\t\t\tcolumn = maxCharacter;\n\t\t\t\thasChanged = true;\n\t\t\t}\n\t\t}\n\n\t\tif (!hasChanged) {\n\t\t\treturn position;\n\t\t} else {\n\t\t\treturn { lineNumber, column };\n\t\t}\n\t}\n}\n\n/**\n * @internal\n */\nexport interface IForeignModuleFactory {\n\t(ctx: IWorkerContext, createData: any): any;\n}\n\ndeclare const require: any;\n\n/**\n * @internal\n */\nexport class EditorSimpleWorker implements IRequestHandler, IDisposable {\n\t_requestHandlerBrand: any;\n\n\tprotected readonly _host: IEditorWorkerHost;\n\tprivate _models: { [uri: string]: MirrorModel; };\n\tprivate readonly _foreignModuleFactory: IForeignModuleFactory | null;\n\tprivate _foreignModule: any;\n\n\tconstructor(host: IEditorWorkerHost, foreignModuleFactory: IForeignModuleFactory | null) {\n\t\tthis._host = host;\n\t\tthis._models = Object.create(null);\n\t\tthis._foreignModuleFactory = foreignModuleFactory;\n\t\tthis._foreignModule = null;\n\t}\n\n\tpublic dispose(): void {\n\t\tthis._models = Object.create(null);\n\t}\n\n\tprotected _getModel(uri: string): ICommonModel {\n\t\treturn this._models[uri];\n\t}\n\n\tprivate _getModels(): ICommonModel[] {\n\t\tconst all: MirrorModel[] = [];\n\t\tObject.keys(this._models).forEach((key) => all.push(this._models[key]));\n\t\treturn all;\n\t}\n\n\tpublic acceptNewModel(data: IRawModelData): void {\n\t\tthis._models[data.url] = new MirrorModel(URI.parse(data.url), data.lines, data.EOL, data.versionId);\n\t}\n\n\tpublic acceptModelChanged(strURL: string, e: IModelChangedEvent): void {\n\t\tif (!this._models[strURL]) {\n\t\t\treturn;\n\t\t}\n\t\tconst model = this._models[strURL];\n\t\tmodel.onEvents(e);\n\t}\n\n\tpublic acceptRemovedModel(strURL: string): void {\n\t\tif (!this._models[strURL]) {\n\t\t\treturn;\n\t\t}\n\t\tdelete this._models[strURL];\n\t}\n\n\tpublic async computeUnicodeHighlights(url: string, options: UnicodeHighlighterOptions, range?: IRange): Promise {\n\t\tconst model = this._getModel(url);\n\t\tif (!model) {\n\t\t\treturn { ranges: [], hasMore: false, ambiguousCharacterCount: 0, invisibleCharacterCount: 0, nonBasicAsciiCharacterCount: 0 };\n\t\t}\n\t\treturn UnicodeTextModelHighlighter.computeUnicodeHighlights(model, options, range);\n\t}\n\n\t// ---- BEGIN diff --------------------------------------------------------------------------\n\n\tpublic async computeDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean, maxComputationTime: number): Promise {\n\t\tconst original = this._getModel(originalUrl);\n\t\tconst modified = this._getModel(modifiedUrl);\n\t\tif (!original || !modified) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst originalLines = original.getLinesContent();\n\t\tconst modifiedLines = modified.getLinesContent();\n\t\tconst diffComputer = new DiffComputer(originalLines, modifiedLines, {\n\t\t\tshouldComputeCharChanges: true,\n\t\t\tshouldPostProcessCharChanges: true,\n\t\t\tshouldIgnoreTrimWhitespace: ignoreTrimWhitespace,\n\t\t\tshouldMakePrettyDiff: true,\n\t\t\tmaxComputationTime: maxComputationTime\n\t\t});\n\n\t\tconst diffResult = diffComputer.computeDiff();\n\t\tconst identical = (diffResult.changes.length > 0 ? false : this._modelsAreIdentical(original, modified));\n\t\treturn {\n\t\t\tquitEarly: diffResult.quitEarly,\n\t\t\tidentical: identical,\n\t\t\tchanges: diffResult.changes\n\t\t};\n\t}\n\n\tprivate _modelsAreIdentical(original: ICommonModel, modified: ICommonModel): boolean {\n\t\tconst originalLineCount = original.getLineCount();\n\t\tconst modifiedLineCount = modified.getLineCount();\n\t\tif (originalLineCount !== modifiedLineCount) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let line = 1; line <= originalLineCount; line++) {\n\t\t\tconst originalLine = original.getLineContent(line);\n\t\t\tconst modifiedLine = modified.getLineContent(line);\n\t\t\tif (originalLine !== modifiedLine) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t// ---- END diff --------------------------------------------------------------------------\n\n\n\t// ---- BEGIN minimal edits ---------------------------------------------------------------\n\n\tprivate static readonly _diffLimit = 100000;\n\n\tpublic async computeMoreMinimalEdits(modelUrl: string, edits: TextEdit[]): Promise {\n\t\tconst model = this._getModel(modelUrl);\n\t\tif (!model) {\n\t\t\treturn edits;\n\t\t}\n\n\t\tconst result: TextEdit[] = [];\n\t\tlet lastEol: EndOfLineSequence | undefined = undefined;\n\n\t\tedits = edits.slice(0).sort((a, b) => {\n\t\t\tif (a.range && b.range) {\n\t\t\t\treturn Range.compareRangesUsingStarts(a.range, b.range);\n\t\t\t}\n\t\t\t// eol only changes should go to the end\n\t\t\tconst aRng = a.range ? 0 : 1;\n\t\t\tconst bRng = b.range ? 0 : 1;\n\t\t\treturn aRng - bRng;\n\t\t});\n\n\t\tfor (let { range, text, eol } of edits) {\n\n\t\t\tif (typeof eol === 'number') {\n\t\t\t\tlastEol = eol;\n\t\t\t}\n\n\t\t\tif (Range.isEmpty(range) && !text) {\n\t\t\t\t// empty change\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst original = model.getValueInRange(range);\n\t\t\ttext = text.replace(/\\r\\n|\\n|\\r/g, model.eol);\n\n\t\t\tif (original === text) {\n\t\t\t\t// noop\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// make sure diff won't take too long\n\t\t\tif (Math.max(text.length, original.length) > EditorSimpleWorker._diffLimit) {\n\t\t\t\tresult.push({ range, text });\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// compute diff between original and edit.text\n\t\t\tconst changes = stringDiff(original, text, false);\n\t\t\tconst editOffset = model.offsetAt(Range.lift(range).getStartPosition());\n\n\t\t\tfor (const change of changes) {\n\t\t\t\tconst start = model.positionAt(editOffset + change.originalStart);\n\t\t\t\tconst end = model.positionAt(editOffset + change.originalStart + change.originalLength);\n\t\t\t\tconst newEdit: TextEdit = {\n\t\t\t\t\ttext: text.substr(change.modifiedStart, change.modifiedLength),\n\t\t\t\t\trange: { startLineNumber: start.lineNumber, startColumn: start.column, endLineNumber: end.lineNumber, endColumn: end.column }\n\t\t\t\t};\n\n\t\t\t\tif (model.getValueInRange(newEdit.range) !== newEdit.text) {\n\t\t\t\t\tresult.push(newEdit);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (typeof lastEol === 'number') {\n\t\t\tresult.push({ eol: lastEol, text: '', range: { startLineNumber: 0, startColumn: 0, endLineNumber: 0, endColumn: 0 } });\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// ---- END minimal edits ---------------------------------------------------------------\n\n\tpublic async computeLinks(modelUrl: string): Promise {\n\t\tconst model = this._getModel(modelUrl);\n\t\tif (!model) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn computeLinks(model);\n\t}\n\n\t// ---- BEGIN suggest --------------------------------------------------------------------------\n\n\tprivate static readonly _suggestionsLimit = 10000;\n\n\tpublic async textualSuggest(modelUrls: string[], leadingWord: string | undefined, wordDef: string, wordDefFlags: string): Promise<{ words: string[], duration: number } | null> {\n\n\t\tconst sw = new StopWatch(true);\n\t\tconst wordDefRegExp = new RegExp(wordDef, wordDefFlags);\n\t\tconst seen = new Set();\n\n\t\touter: for (let url of modelUrls) {\n\t\t\tconst model = this._getModel(url);\n\t\t\tif (!model) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor (let word of model.words(wordDefRegExp)) {\n\t\t\t\tif (word === leadingWord || !isNaN(Number(word))) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tseen.add(word);\n\t\t\t\tif (seen.size > EditorSimpleWorker._suggestionsLimit) {\n\t\t\t\t\tbreak outer;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { words: Array.from(seen), duration: sw.elapsed() };\n\t}\n\n\n\t// ---- END suggest --------------------------------------------------------------------------\n\n\t//#region -- word ranges --\n\n\tpublic async computeWordRanges(modelUrl: string, range: IRange, wordDef: string, wordDefFlags: string): Promise<{ [word: string]: IRange[] }> {\n\t\tconst model = this._getModel(modelUrl);\n\t\tif (!model) {\n\t\t\treturn Object.create(null);\n\t\t}\n\t\tconst wordDefRegExp = new RegExp(wordDef, wordDefFlags);\n\t\tconst result: { [word: string]: IRange[] } = Object.create(null);\n\t\tfor (let line = range.startLineNumber; line < range.endLineNumber; line++) {\n\t\t\tconst words = model.getLineWords(line, wordDefRegExp);\n\t\t\tfor (const word of words) {\n\t\t\t\tif (!isNaN(Number(word.word))) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlet array = result[word.word];\n\t\t\t\tif (!array) {\n\t\t\t\t\tarray = [];\n\t\t\t\t\tresult[word.word] = array;\n\t\t\t\t}\n\t\t\t\tarray.push({\n\t\t\t\t\tstartLineNumber: line,\n\t\t\t\t\tstartColumn: word.startColumn,\n\t\t\t\t\tendLineNumber: line,\n\t\t\t\t\tendColumn: word.endColumn\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t//#endregion\n\n\tpublic async navigateValueSet(modelUrl: string, range: IRange, up: boolean, wordDef: string, wordDefFlags: string): Promise {\n\t\tconst model = this._getModel(modelUrl);\n\t\tif (!model) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst wordDefRegExp = new RegExp(wordDef, wordDefFlags);\n\n\t\tif (range.startColumn === range.endColumn) {\n\t\t\trange = {\n\t\t\t\tstartLineNumber: range.startLineNumber,\n\t\t\t\tstartColumn: range.startColumn,\n\t\t\t\tendLineNumber: range.endLineNumber,\n\t\t\t\tendColumn: range.endColumn + 1\n\t\t\t};\n\t\t}\n\n\t\tconst selectionText = model.getValueInRange(range);\n\n\t\tconst wordRange = model.getWordAtPosition({ lineNumber: range.startLineNumber, column: range.startColumn }, wordDefRegExp);\n\t\tif (!wordRange) {\n\t\t\treturn null;\n\t\t}\n\t\tconst word = model.getValueInRange(wordRange);\n\t\tconst result = BasicInplaceReplace.INSTANCE.navigateValueSet(range, selectionText, wordRange, word, up);\n\t\treturn result;\n\t}\n\n\t// ---- BEGIN foreign module support --------------------------------------------------------------------------\n\n\tpublic loadForeignModule(moduleId: string, createData: any, foreignHostMethods: string[]): Promise {\n\t\tconst proxyMethodRequest = (method: string, args: any[]): Promise => {\n\t\t\treturn this._host.fhr(method, args);\n\t\t};\n\n\t\tconst foreignHost = types.createProxyObject(foreignHostMethods, proxyMethodRequest);\n\n\t\tconst ctx: IWorkerContext = {\n\t\t\thost: foreignHost,\n\t\t\tgetMirrorModels: (): IMirrorModel[] => {\n\t\t\t\treturn this._getModels();\n\t\t\t}\n\t\t};\n\n\t\tif (this._foreignModuleFactory) {\n\t\t\tthis._foreignModule = this._foreignModuleFactory(ctx, createData);\n\t\t\t// static foreing module\n\t\t\treturn Promise.resolve(types.getAllMethodNames(this._foreignModule));\n\t\t}\n\t\t// ESM-comment-begin\n\t\treturn new Promise((resolve, reject) => {\n\t\t\trequire([moduleId], (foreignModule: { create: IForeignModuleFactory }) => {\n\t\t\t\tthis._foreignModule = foreignModule.create(ctx, createData);\n\n\t\t\t\tresolve(types.getAllMethodNames(this._foreignModule));\n\n\t\t\t}, reject);\n\t\t});\n\t\t// ESM-comment-end\n\n\t\t// ESM-uncomment-begin\n\t\t// return Promise.reject(new Error(`Unexpected usage`));\n\t\t// ESM-uncomment-end\n\t}\n\n\t// foreign method request\n\tpublic fmr(method: string, args: any[]): Promise {\n\t\tif (!this._foreignModule || typeof this._foreignModule[method] !== 'function') {\n\t\t\treturn Promise.reject(new Error('Missing requestHandler or method: ' + method));\n\t\t}\n\n\t\ttry {\n\t\t\treturn Promise.resolve(this._foreignModule[method].apply(this._foreignModule, args));\n\t\t} catch (e) {\n\t\t\treturn Promise.reject(e);\n\t\t}\n\t}\n\n\t// ---- END foreign module support --------------------------------------------------------------------------\n}\n\n/**\n * Called on the worker side\n * @internal\n */\nexport function create(host: IEditorWorkerHost): IRequestHandler {\n\treturn new EditorSimpleWorker(host, null);\n}\n\n// This is only available in a Web Worker\ndeclare function importScripts(...urls: string[]): void;\n\nif (typeof importScripts === 'function') {\n\t// Running in a web worker\n\tglobals.monaco = createMonacoBaseAPI();\n}\n","\n\n/**\n * Represents contiguous tokens over a contiguous range of lines.\n */\nexport class ContiguousMultilineTokens {\n\n\t/**\n\t * The start line number for this block of tokens.\n\t */\n\tprivate _startLineNumber: number;\n\n\t/**\n\t * The tokens are stored in a binary format. There is an element for each line,\n\t * so `tokens[index]` contains all tokens on line `startLineNumber + index`.\n\t *\n\t * On a specific line, each token occupies two array indices. For token i:\n\t * - at offset 2*i => endOffset\n\t * - at offset 2*i + 1 => metadata\n\t *\n\t */\n\tprivate _tokens: (Uint32Array | ArrayBuffer | null)[];\n\n\t/**\n\t * (Inclusive) start line number for these tokens.\n\t */\n\tpublic get startLineNumber(): number {\n\t\treturn this._startLineNumber;\n\t}\n\n\t/**\n\t * (Inclusive) end line number for these tokens.\n\t */\n\tpublic get endLineNumber(): number {\n\t\treturn this._startLineNumber + this._tokens.length - 1;\n\t}\n\n\tconstructor(startLineNumber: number, tokens: Uint32Array[]) {\n\t\tthis._startLineNumber = startLineNumber;\n\t\tthis._tokens = tokens;\n\t}\n\n\t/**\n\t * @see {@link _tokens}\n\t */\n\tpublic getLineTokens(lineNumber: number): Uint32Array | ArrayBuffer | null {\n\t\treturn this._tokens[lineNumber - this._startLineNumber];\n\t}\n\n\tpublic appendLineTokens(lineTokens: Uint32Array): void {\n\t\tthis._tokens.push(lineTokens);\n\t}\n}\n","\nimport { ContiguousMultilineTokens } from 'vs/editor/common/tokens/contiguousMultilineTokens';\n\nexport class ContiguousMultilineTokensBuilder {\n\n\tprivate readonly _tokens: ContiguousMultilineTokens[];\n\n\tconstructor() {\n\t\tthis._tokens = [];\n\t}\n\n\tpublic add(lineNumber: number, lineTokens: Uint32Array): void {\n\t\tif (this._tokens.length > 0) {\n\t\t\tconst last = this._tokens[this._tokens.length - 1];\n\t\t\tif (last.endLineNumber + 1 === lineNumber) {\n\t\t\t\t// append\n\t\t\t\tlast.appendLineTokens(lineTokens);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis._tokens.push(new ContiguousMultilineTokens(lineNumber, [lineTokens]));\n\t}\n\n\tpublic finalize(): ContiguousMultilineTokens[] {\n\t\treturn this._tokens;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ColorId, FontStyle, ILanguageIdCodec, ITokenPresentation, MetadataConsts, StandardTokenType, TokenMetadata } from 'vs/editor/common/languages';\n\nexport interface IViewLineTokens {\n\tequals(other: IViewLineTokens): boolean;\n\tgetCount(): number;\n\tgetForeground(tokenIndex: number): ColorId;\n\tgetEndOffset(tokenIndex: number): number;\n\tgetClassName(tokenIndex: number): string;\n\tgetInlineStyle(tokenIndex: number, colorMap: string[]): string;\n\tgetPresentation(tokenIndex: number): ITokenPresentation;\n\tfindTokenIndexAtOffset(offset: number): number;\n\tgetLineContent(): string;\n\tgetMetadata(tokenIndex: number): number;\n\tgetLanguageId(tokenIndex: number): string;\n}\n\nexport class LineTokens implements IViewLineTokens {\n\t_lineTokensBrand: void = undefined;\n\n\tprivate readonly _tokens: Uint32Array;\n\tprivate readonly _tokensCount: number;\n\tprivate readonly _text: string;\n\tprivate readonly _languageIdCodec: ILanguageIdCodec;\n\n\tpublic static defaultTokenMetadata = (\n\t\t(FontStyle.None << MetadataConsts.FONT_STYLE_OFFSET)\n\t\t| (ColorId.DefaultForeground << MetadataConsts.FOREGROUND_OFFSET)\n\t\t| (ColorId.DefaultBackground << MetadataConsts.BACKGROUND_OFFSET)\n\t) >>> 0;\n\n\tpublic static createEmpty(lineContent: string, decoder: ILanguageIdCodec): LineTokens {\n\t\tconst defaultMetadata = LineTokens.defaultTokenMetadata;\n\n\t\tconst tokens = new Uint32Array(2);\n\t\ttokens[0] = lineContent.length;\n\t\ttokens[1] = defaultMetadata;\n\n\t\treturn new LineTokens(tokens, lineContent, decoder);\n\t}\n\n\tconstructor(tokens: Uint32Array, text: string, decoder: ILanguageIdCodec) {\n\t\tthis._tokens = tokens;\n\t\tthis._tokensCount = (this._tokens.length >>> 1);\n\t\tthis._text = text;\n\t\tthis._languageIdCodec = decoder;\n\t}\n\n\tpublic equals(other: IViewLineTokens): boolean {\n\t\tif (other instanceof LineTokens) {\n\t\t\treturn this.slicedEquals(other, 0, this._tokensCount);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic slicedEquals(other: LineTokens, sliceFromTokenIndex: number, sliceTokenCount: number): boolean {\n\t\tif (this._text !== other._text) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this._tokensCount !== other._tokensCount) {\n\t\t\treturn false;\n\t\t}\n\t\tconst from = (sliceFromTokenIndex << 1);\n\t\tconst to = from + (sliceTokenCount << 1);\n\t\tfor (let i = from; i < to; i++) {\n\t\t\tif (this._tokens[i] !== other._tokens[i]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic getLineContent(): string {\n\t\treturn this._text;\n\t}\n\n\tpublic getCount(): number {\n\t\treturn this._tokensCount;\n\t}\n\n\tpublic getStartOffset(tokenIndex: number): number {\n\t\tif (tokenIndex > 0) {\n\t\t\treturn this._tokens[(tokenIndex - 1) << 1];\n\t\t}\n\t\treturn 0;\n\t}\n\n\tpublic getMetadata(tokenIndex: number): number {\n\t\tconst metadata = this._tokens[(tokenIndex << 1) + 1];\n\t\treturn metadata;\n\t}\n\n\tpublic getLanguageId(tokenIndex: number): string {\n\t\tconst metadata = this._tokens[(tokenIndex << 1) + 1];\n\t\tconst languageId = TokenMetadata.getLanguageId(metadata);\n\t\treturn this._languageIdCodec.decodeLanguageId(languageId);\n\t}\n\n\tpublic getStandardTokenType(tokenIndex: number): StandardTokenType {\n\t\tconst metadata = this._tokens[(tokenIndex << 1) + 1];\n\t\treturn TokenMetadata.getTokenType(metadata);\n\t}\n\n\tpublic getForeground(tokenIndex: number): ColorId {\n\t\tconst metadata = this._tokens[(tokenIndex << 1) + 1];\n\t\treturn TokenMetadata.getForeground(metadata);\n\t}\n\n\tpublic getClassName(tokenIndex: number): string {\n\t\tconst metadata = this._tokens[(tokenIndex << 1) + 1];\n\t\treturn TokenMetadata.getClassNameFromMetadata(metadata);\n\t}\n\n\tpublic getInlineStyle(tokenIndex: number, colorMap: string[]): string {\n\t\tconst metadata = this._tokens[(tokenIndex << 1) + 1];\n\t\treturn TokenMetadata.getInlineStyleFromMetadata(metadata, colorMap);\n\t}\n\n\tpublic getPresentation(tokenIndex: number): ITokenPresentation {\n\t\tconst metadata = this._tokens[(tokenIndex << 1) + 1];\n\t\treturn TokenMetadata.getPresentationFromMetadata(metadata);\n\t}\n\n\tpublic getEndOffset(tokenIndex: number): number {\n\t\treturn this._tokens[tokenIndex << 1];\n\t}\n\n\t/**\n\t * Find the token containing offset `offset`.\n\t * @param offset The search offset\n\t * @return The index of the token containing the offset.\n\t */\n\tpublic findTokenIndexAtOffset(offset: number): number {\n\t\treturn LineTokens.findIndexInTokensArray(this._tokens, offset);\n\t}\n\n\tpublic inflate(): IViewLineTokens {\n\t\treturn this;\n\t}\n\n\tpublic sliceAndInflate(startOffset: number, endOffset: number, deltaOffset: number): IViewLineTokens {\n\t\treturn new SliceLineTokens(this, startOffset, endOffset, deltaOffset);\n\t}\n\n\tpublic static convertToEndOffset(tokens: Uint32Array, lineTextLength: number): void {\n\t\tconst tokenCount = (tokens.length >>> 1);\n\t\tconst lastTokenIndex = tokenCount - 1;\n\t\tfor (let tokenIndex = 0; tokenIndex < lastTokenIndex; tokenIndex++) {\n\t\t\ttokens[tokenIndex << 1] = tokens[(tokenIndex + 1) << 1];\n\t\t}\n\t\ttokens[lastTokenIndex << 1] = lineTextLength;\n\t}\n\n\tpublic static findIndexInTokensArray(tokens: Uint32Array, desiredIndex: number): number {\n\t\tif (tokens.length <= 2) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tlet low = 0;\n\t\tlet high = (tokens.length >>> 1) - 1;\n\n\t\twhile (low < high) {\n\n\t\t\tconst mid = low + Math.floor((high - low) / 2);\n\t\t\tconst endOffset = tokens[(mid << 1)];\n\n\t\t\tif (endOffset === desiredIndex) {\n\t\t\t\treturn mid + 1;\n\t\t\t} else if (endOffset < desiredIndex) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else if (endOffset > desiredIndex) {\n\t\t\t\thigh = mid;\n\t\t\t}\n\t\t}\n\n\t\treturn low;\n\t}\n\n\t/**\n\t * @pure\n\t * @param insertTokens Must be sorted by offset.\n\t*/\n\tpublic withInserted(insertTokens: { offset: number, text: string, tokenMetadata: number }[]): LineTokens {\n\t\tif (insertTokens.length === 0) {\n\t\t\treturn this;\n\t\t}\n\n\t\tlet nextOriginalTokenIdx = 0;\n\t\tlet nextInsertTokenIdx = 0;\n\t\tlet text = '';\n\t\tconst newTokens = new Array();\n\n\t\tlet originalEndOffset = 0;\n\t\twhile (true) {\n\t\t\tconst nextOriginalTokenEndOffset = nextOriginalTokenIdx < this._tokensCount ? this._tokens[nextOriginalTokenIdx << 1] : -1;\n\t\t\tconst nextInsertToken = nextInsertTokenIdx < insertTokens.length ? insertTokens[nextInsertTokenIdx] : null;\n\n\t\t\tif (nextOriginalTokenEndOffset !== -1 && (nextInsertToken === null || nextOriginalTokenEndOffset <= nextInsertToken.offset)) {\n\t\t\t\t// original token ends before next insert token\n\t\t\t\ttext += this._text.substring(originalEndOffset, nextOriginalTokenEndOffset);\n\t\t\t\tconst metadata = this._tokens[(nextOriginalTokenIdx << 1) + 1];\n\t\t\t\tnewTokens.push(text.length, metadata);\n\t\t\t\tnextOriginalTokenIdx++;\n\t\t\t\toriginalEndOffset = nextOriginalTokenEndOffset;\n\n\t\t\t} else if (nextInsertToken) {\n\t\t\t\tif (nextInsertToken.offset > originalEndOffset) {\n\t\t\t\t\t// insert token is in the middle of the next token.\n\t\t\t\t\ttext += this._text.substring(originalEndOffset, nextInsertToken.offset);\n\t\t\t\t\tconst metadata = this._tokens[(nextOriginalTokenIdx << 1) + 1];\n\t\t\t\t\tnewTokens.push(text.length, metadata);\n\t\t\t\t\toriginalEndOffset = nextInsertToken.offset;\n\t\t\t\t}\n\n\t\t\t\ttext += nextInsertToken.text;\n\t\t\t\tnewTokens.push(text.length, nextInsertToken.tokenMetadata);\n\t\t\t\tnextInsertTokenIdx++;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn new LineTokens(new Uint32Array(newTokens), text, this._languageIdCodec);\n\t}\n}\n\nclass SliceLineTokens implements IViewLineTokens {\n\n\tprivate readonly _source: LineTokens;\n\tprivate readonly _startOffset: number;\n\tprivate readonly _endOffset: number;\n\tprivate readonly _deltaOffset: number;\n\n\tprivate readonly _firstTokenIndex: number;\n\tprivate readonly _tokensCount: number;\n\n\tconstructor(source: LineTokens, startOffset: number, endOffset: number, deltaOffset: number) {\n\t\tthis._source = source;\n\t\tthis._startOffset = startOffset;\n\t\tthis._endOffset = endOffset;\n\t\tthis._deltaOffset = deltaOffset;\n\t\tthis._firstTokenIndex = source.findTokenIndexAtOffset(startOffset);\n\n\t\tthis._tokensCount = 0;\n\t\tfor (let i = this._firstTokenIndex, len = source.getCount(); i < len; i++) {\n\t\t\tconst tokenStartOffset = source.getStartOffset(i);\n\t\t\tif (tokenStartOffset >= endOffset) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tthis._tokensCount++;\n\t\t}\n\t}\n\n\tpublic getMetadata(tokenIndex: number): number {\n\t\treturn this._source.getMetadata(this._firstTokenIndex + tokenIndex);\n\t}\n\n\tpublic getLanguageId(tokenIndex: number): string {\n\t\treturn this._source.getLanguageId(this._firstTokenIndex + tokenIndex);\n\t}\n\n\tpublic getLineContent(): string {\n\t\treturn this._source.getLineContent().substring(this._startOffset, this._endOffset);\n\t}\n\n\tpublic equals(other: IViewLineTokens): boolean {\n\t\tif (other instanceof SliceLineTokens) {\n\t\t\treturn (\n\t\t\t\tthis._startOffset === other._startOffset\n\t\t\t\t&& this._endOffset === other._endOffset\n\t\t\t\t&& this._deltaOffset === other._deltaOffset\n\t\t\t\t&& this._source.slicedEquals(other._source, this._firstTokenIndex, this._tokensCount)\n\t\t\t);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic getCount(): number {\n\t\treturn this._tokensCount;\n\t}\n\n\tpublic getForeground(tokenIndex: number): ColorId {\n\t\treturn this._source.getForeground(this._firstTokenIndex + tokenIndex);\n\t}\n\n\tpublic getEndOffset(tokenIndex: number): number {\n\t\tconst tokenEndOffset = this._source.getEndOffset(this._firstTokenIndex + tokenIndex);\n\t\treturn Math.min(this._endOffset, tokenEndOffset) - this._startOffset + this._deltaOffset;\n\t}\n\n\tpublic getClassName(tokenIndex: number): string {\n\t\treturn this._source.getClassName(this._firstTokenIndex + tokenIndex);\n\t}\n\n\tpublic getInlineStyle(tokenIndex: number, colorMap: string[]): string {\n\t\treturn this._source.getInlineStyle(this._firstTokenIndex + tokenIndex, colorMap);\n\t}\n\n\tpublic getPresentation(tokenIndex: number): ITokenPresentation {\n\t\treturn this._source.getPresentation(this._firstTokenIndex + tokenIndex);\n\t}\n\n\tpublic findTokenIndexAtOffset(offset: number): number {\n\t\treturn this._source.findTokenIndexAtOffset(offset + this._startOffset - this._deltaOffset) - this._firstTokenIndex;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport * as strings from 'vs/base/common/strings';\nimport { IViewLineTokens, LineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { ILanguageIdCodec, IState, ITokenizationSupport, LanguageId, TokenizationRegistry } from 'vs/editor/common/languages';\nimport { NullState, nullTokenizeEncoded } from 'vs/editor/common/languages/nullMode';\nimport { ILanguageService } from 'vs/editor/common/services/language';\n\nexport type IReducedTokenizationSupport = Omit;\n\nconst fallback: IReducedTokenizationSupport = {\n\tgetInitialState: () => NullState,\n\ttokenizeEncoded: (buffer: string, hasEOL: boolean, state: IState) => nullTokenizeEncoded(LanguageId.Null, state)\n};\n\nexport async function tokenizeToString(languageService: ILanguageService, text: string, languageId: string | null): Promise {\n\tif (!languageId) {\n\t\treturn _tokenizeToString(text, languageService.languageIdCodec, fallback);\n\t}\n\tconst tokenizationSupport = await TokenizationRegistry.getOrCreate(languageId);\n\treturn _tokenizeToString(text, languageService.languageIdCodec, tokenizationSupport || fallback);\n}\n\nexport function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens, colorMap: string[], startOffset: number, endOffset: number, tabSize: number, useNbsp: boolean): string {\n\tlet result = `
    `;\n\tlet charIndex = startOffset;\n\tlet tabsCharDelta = 0;\n\n\tlet prevIsSpace = true;\n\n\tfor (let tokenIndex = 0, tokenCount = viewLineTokens.getCount(); tokenIndex < tokenCount; tokenIndex++) {\n\t\tconst tokenEndIndex = viewLineTokens.getEndOffset(tokenIndex);\n\n\t\tif (tokenEndIndex <= startOffset) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tlet partContent = '';\n\n\t\tfor (; charIndex < tokenEndIndex && charIndex < endOffset; charIndex++) {\n\t\t\tconst charCode = text.charCodeAt(charIndex);\n\n\t\t\tswitch (charCode) {\n\t\t\t\tcase CharCode.Tab: {\n\t\t\t\t\tlet insertSpacesCount = tabSize - (charIndex + tabsCharDelta) % tabSize;\n\t\t\t\t\ttabsCharDelta += insertSpacesCount - 1;\n\t\t\t\t\twhile (insertSpacesCount > 0) {\n\t\t\t\t\t\tif (useNbsp && prevIsSpace) {\n\t\t\t\t\t\t\tpartContent += ' ';\n\t\t\t\t\t\t\tprevIsSpace = false;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tpartContent += ' ';\n\t\t\t\t\t\t\tprevIsSpace = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tinsertSpacesCount--;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase CharCode.LessThan:\n\t\t\t\t\tpartContent += '<';\n\t\t\t\t\tprevIsSpace = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CharCode.GreaterThan:\n\t\t\t\t\tpartContent += '>';\n\t\t\t\t\tprevIsSpace = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CharCode.Ampersand:\n\t\t\t\t\tpartContent += '&';\n\t\t\t\t\tprevIsSpace = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CharCode.Null:\n\t\t\t\t\tpartContent += '�';\n\t\t\t\t\tprevIsSpace = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CharCode.UTF8_BOM:\n\t\t\t\tcase CharCode.LINE_SEPARATOR:\n\t\t\t\tcase CharCode.PARAGRAPH_SEPARATOR:\n\t\t\t\tcase CharCode.NEXT_LINE:\n\t\t\t\t\tpartContent += '\\ufffd';\n\t\t\t\t\tprevIsSpace = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CharCode.CarriageReturn:\n\t\t\t\t\t// zero width space, because carriage return would introduce a line break\n\t\t\t\t\tpartContent += '​';\n\t\t\t\t\tprevIsSpace = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CharCode.Space:\n\t\t\t\t\tif (useNbsp && prevIsSpace) {\n\t\t\t\t\t\tpartContent += ' ';\n\t\t\t\t\t\tprevIsSpace = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpartContent += ' ';\n\t\t\t\t\t\tprevIsSpace = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tpartContent += String.fromCharCode(charCode);\n\t\t\t\t\tprevIsSpace = false;\n\t\t\t}\n\t\t}\n\n\t\tresult += `${partContent}`;\n\n\t\tif (tokenEndIndex > endOffset || charIndex >= endOffset) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tresult += `
    `;\n\treturn result;\n}\n\nexport function _tokenizeToString(text: string, languageIdCodec: ILanguageIdCodec, tokenizationSupport: IReducedTokenizationSupport): string {\n\tlet result = `
    `;\n\tconst lines = strings.splitLines(text);\n\tlet currentState = tokenizationSupport.getInitialState();\n\tfor (let i = 0, len = lines.length; i < len; i++) {\n\t\tconst line = lines[i];\n\n\t\tif (i > 0) {\n\t\t\tresult += `
    `;\n\t\t}\n\n\t\tconst tokenizationResult = tokenizationSupport.tokenizeEncoded(line, true, currentState);\n\t\tLineTokens.convertToEndOffset(tokenizationResult.tokens, line.length);\n\t\tconst lineTokens = new LineTokens(tokenizationResult.tokens, line, languageIdCodec);\n\t\tconst viewLineTokens = lineTokens.inflate();\n\n\t\tlet startOffset = 0;\n\t\tfor (let j = 0, lenJ = viewLineTokens.getCount(); j < lenJ; j++) {\n\t\t\tconst type = viewLineTokens.getClassName(j);\n\t\t\tconst endIndex = viewLineTokens.getEndOffset(j);\n\t\t\tresult += `${strings.escape(line.substring(startOffset, endIndex))}`;\n\t\t\tstartOffset = endIndex;\n\t\t}\n\n\t\tcurrentState = tokenizationResult.endState;\n\t}\n\n\tresult += `
    `;\n\treturn result;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as arrays from 'vs/base/common/arrays';\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport { LineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { Position } from 'vs/editor/common/core/position';\nimport { IRange } from 'vs/editor/common/core/range';\nimport { EncodedTokenizationResult, ILanguageIdCodec, IState, ITokenizationSupport, StandardTokenType, TokenizationRegistry } from 'vs/editor/common/languages';\nimport { nullTokenizeEncoded } from 'vs/editor/common/languages/nullMode';\nimport { TextModel } from 'vs/editor/common/model/textModel';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { StopWatch } from 'vs/base/common/stopwatch';\nimport { countEOL } from 'vs/editor/common/core/eolCounter';\nimport { ContiguousMultilineTokensBuilder } from 'vs/editor/common/tokens/contiguousMultilineTokensBuilder';\nimport { runWhenIdle, IdleDeadline } from 'vs/base/common/async';\nimport { setTimeout0 } from 'vs/base/common/platform';\n\nconst enum Constants {\n\tCHEAP_TOKENIZATION_LENGTH_LIMIT = 2048\n}\n\n/**\n * An array that avoids being sparse by always\n * filling up unused indices with a default value.\n */\nclass ContiguousGrowingArray {\n\n\tprivate _store: T[] = [];\n\n\tconstructor(\n\t\tprivate readonly _default: T\n\t) { }\n\n\tpublic get(index: number): T {\n\t\tif (index < this._store.length) {\n\t\t\treturn this._store[index];\n\t\t}\n\t\treturn this._default;\n\t}\n\n\tpublic set(index: number, value: T): void {\n\t\twhile (index >= this._store.length) {\n\t\t\tthis._store[this._store.length] = this._default;\n\t\t}\n\t\tthis._store[index] = value;\n\t}\n\n\tpublic delete(deleteIndex: number, deleteCount: number): void {\n\t\tif (deleteCount === 0 || deleteIndex >= this._store.length) {\n\t\t\treturn;\n\t\t}\n\t\tthis._store.splice(deleteIndex, deleteCount);\n\t}\n\n\tpublic insert(insertIndex: number, insertCount: number): void {\n\t\tif (insertCount === 0 || insertIndex >= this._store.length) {\n\t\t\treturn;\n\t\t}\n\t\tconst arr: T[] = [];\n\t\tfor (let i = 0; i < insertCount; i++) {\n\t\t\tarr[i] = this._default;\n\t\t}\n\t\tthis._store = arrays.arrayInsert(this._store, insertIndex, arr);\n\t}\n}\n\n/**\n * Stores the states at the start of each line and keeps track of which lines\n * must be retokenized. Also uses state equality to quickly validate lines\n * that don't need to be retokenized.\n *\n * For example, when typing on a line, the line gets marked as needing to be tokenized.\n * Once the line is tokenized, the end state is checked for equality against the begin\n * state of the next line. If the states are equal, tokenization doesn't need to run\n * again over the rest of the file. If the states are not equal, the next line gets marked\n * as needing to be tokenized.\n */\nexport class TokenizationStateStore {\n\n\t/**\n\t * `lineBeginState[i]` contains the begin state used to tokenize line number `i + 1`.\n\t */\n\tprivate readonly _lineBeginState = new ContiguousGrowingArray(null);\n\t/**\n\t * `lineNeedsTokenization[i]` describes if line number `i + 1` needs to be tokenized.\n\t */\n\tprivate readonly _lineNeedsTokenization = new ContiguousGrowingArray(true);\n\t/**\n\t * `invalidLineStartIndex` indicates that line number `invalidLineStartIndex + 1`\n\t * is the first one that needs to be retokenized.\n\t */\n\tprivate _firstLineNeedsTokenization: number;\n\n\tpublic get invalidLineStartIndex() {\n\t\treturn this._firstLineNeedsTokenization;\n\t}\n\n\tconstructor(\n\t\tpublic readonly tokenizationSupport: ITokenizationSupport,\n\t\tpublic readonly initialState: IState\n\t) {\n\t\tthis._firstLineNeedsTokenization = 0;\n\t\tthis._lineBeginState.set(0, this.initialState);\n\t}\n\n\tpublic markMustBeTokenized(lineIndex: number): void {\n\t\tthis._lineNeedsTokenization.set(lineIndex, true);\n\t\tthis._firstLineNeedsTokenization = Math.min(this._firstLineNeedsTokenization, lineIndex);\n\t}\n\n\tpublic getBeginState(lineIndex: number): IState | null {\n\t\treturn this._lineBeginState.get(lineIndex);\n\t}\n\n\tpublic setEndState(linesLength: number, lineIndex: number, endState: IState): void {\n\t\tthis._lineNeedsTokenization.set(lineIndex, false);\n\t\tthis._firstLineNeedsTokenization = lineIndex + 1;\n\n\t\t// Check if this was the last line\n\t\tif (lineIndex === linesLength - 1) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if the end state has changed\n\t\tconst previousEndState = this._lineBeginState.get(lineIndex + 1);\n\t\tif (previousEndState === null || !endState.equals(previousEndState)) {\n\t\t\tthis._lineBeginState.set(lineIndex + 1, endState);\n\t\t\tthis.markMustBeTokenized(lineIndex + 1);\n\t\t\treturn;\n\t\t}\n\n\t\t// Perhaps we can skip tokenizing some lines...\n\t\tlet i = lineIndex + 1;\n\t\twhile (i < linesLength) {\n\t\t\tif (this._lineNeedsTokenization.get(i)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\t\tthis._firstLineNeedsTokenization = i;\n\t}\n\n\t//#region Editing\n\n\tpublic applyEdits(range: IRange, eolCount: number): void {\n\t\tthis.markMustBeTokenized(range.startLineNumber - 1);\n\n\t\tthis._lineBeginState.delete(range.startLineNumber, range.endLineNumber - range.startLineNumber);\n\t\tthis._lineNeedsTokenization.delete(range.startLineNumber, range.endLineNumber - range.startLineNumber);\n\n\t\tthis._lineBeginState.insert(range.startLineNumber, eolCount);\n\t\tthis._lineNeedsTokenization.insert(range.startLineNumber, eolCount);\n\t}\n\n\t//#endregion\n}\n\nexport class TextModelTokenization extends Disposable {\n\n\tprivate _tokenizationStateStore: TokenizationStateStore | null;\n\tprivate _isDisposed: boolean;\n\n\tconstructor(\n\t\tprivate readonly _textModel: TextModel,\n\t\tprivate readonly _languageIdCodec: ILanguageIdCodec\n\t) {\n\t\tsuper();\n\t\tthis._isDisposed = false;\n\t\tthis._tokenizationStateStore = null;\n\n\t\tthis._register(TokenizationRegistry.onDidChange((e) => {\n\t\t\tconst languageId = this._textModel.getLanguageId();\n\t\t\tif (e.changedLanguages.indexOf(languageId) === -1) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._resetTokenizationState();\n\t\t\tthis._textModel.clearTokens();\n\t\t}));\n\n\t\tthis._register(this._textModel.onDidChangeContentFast((e) => {\n\t\t\tif (e.isFlush) {\n\t\t\t\tthis._resetTokenizationState();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this._tokenizationStateStore) {\n\t\t\t\tfor (let i = 0, len = e.changes.length; i < len; i++) {\n\t\t\t\t\tconst change = e.changes[i];\n\t\t\t\t\tconst [eolCount] = countEOL(change.text);\n\t\t\t\t\tthis._tokenizationStateStore.applyEdits(change.range, eolCount);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._beginBackgroundTokenization();\n\t\t}));\n\n\t\tthis._register(this._textModel.onDidChangeAttached(() => {\n\t\t\tthis._beginBackgroundTokenization();\n\t\t}));\n\n\t\tthis._register(this._textModel.onDidChangeLanguage(() => {\n\t\t\tthis._resetTokenizationState();\n\t\t\tthis._textModel.clearTokens();\n\t\t}));\n\n\t\tthis._resetTokenizationState();\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._isDisposed = true;\n\t\tsuper.dispose();\n\t}\n\n\tprivate _resetTokenizationState(): void {\n\t\tconst [tokenizationSupport, initialState] = initializeTokenization(this._textModel);\n\t\tif (tokenizationSupport && initialState) {\n\t\t\tthis._tokenizationStateStore = new TokenizationStateStore(tokenizationSupport, initialState);\n\t\t} else {\n\t\t\tthis._tokenizationStateStore = null;\n\t\t}\n\t\tthis._beginBackgroundTokenization();\n\t}\n\n\tprivate _isScheduled = false;\n\tprivate _beginBackgroundTokenization(): void {\n\t\tif (this._isScheduled || !this._textModel.isAttachedToEditor() || !this._hasLinesToTokenize()) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._isScheduled = true;\n\t\trunWhenIdle((deadline) => {\n\t\t\tthis._isScheduled = false;\n\n\t\t\tthis._backgroundTokenizeWithDeadline(deadline);\n\t\t});\n\t}\n\n\t/**\n\t * Tokenize until the deadline occurs, but try to yield every 1-2ms.\n\t */\n\tprivate _backgroundTokenizeWithDeadline(deadline: IdleDeadline): void {\n\t\t// Read the time remaining from the `deadline` immediately because it is unclear\n\t\t// if the `deadline` object will be valid after execution leaves this function.\n\t\tconst endTime = Date.now() + deadline.timeRemaining();\n\n\t\tconst execute = () => {\n\t\t\tif (this._isDisposed || !this._textModel.isAttachedToEditor() || !this._hasLinesToTokenize()) {\n\t\t\t\t// disposed in the meantime or detached or finished\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._backgroundTokenizeForAtLeast1ms();\n\n\t\t\tif (Date.now() < endTime) {\n\t\t\t\t// There is still time before reaching the deadline, so yield to the browser and then\n\t\t\t\t// continue execution\n\t\t\t\tsetTimeout0(execute);\n\t\t\t} else {\n\t\t\t\t// The deadline has been reached, so schedule a new idle callback if necessary\n\t\t\t\tthis._beginBackgroundTokenization();\n\t\t\t}\n\t\t};\n\t\texecute();\n\t}\n\n\t/**\n\t * Tokenize for at least 1ms.\n\t */\n\tprivate _backgroundTokenizeForAtLeast1ms(): void {\n\t\tconst lineCount = this._textModel.getLineCount();\n\t\tconst builder = new ContiguousMultilineTokensBuilder();\n\t\tconst sw = StopWatch.create(false);\n\n\t\tdo {\n\t\t\tif (sw.elapsed() > 1) {\n\t\t\t\t// the comparison is intentionally > 1 and not >= 1 to ensure that\n\t\t\t\t// a full millisecond has elapsed, given how microseconds are rounded\n\t\t\t\t// to milliseconds\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst tokenizedLineNumber = this._tokenizeOneInvalidLine(builder);\n\n\t\t\tif (tokenizedLineNumber >= lineCount) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} while (this._hasLinesToTokenize());\n\n\t\tthis._textModel.setTokens(builder.finalize(), !this._hasLinesToTokenize());\n\t}\n\n\tpublic tokenizeViewport(startLineNumber: number, endLineNumber: number): void {\n\t\tconst builder = new ContiguousMultilineTokensBuilder();\n\t\tthis._tokenizeViewport(builder, startLineNumber, endLineNumber);\n\t\tthis._textModel.setTokens(builder.finalize(), !this._hasLinesToTokenize());\n\t}\n\n\tpublic reset(): void {\n\t\tthis._resetTokenizationState();\n\t\tthis._textModel.clearTokens();\n\t}\n\n\tpublic forceTokenization(lineNumber: number): void {\n\t\tconst builder = new ContiguousMultilineTokensBuilder();\n\t\tthis._updateTokensUntilLine(builder, lineNumber);\n\t\tthis._textModel.setTokens(builder.finalize(), !this._hasLinesToTokenize());\n\t}\n\n\tpublic getTokenTypeIfInsertingCharacter(position: Position, character: string): StandardTokenType {\n\t\tif (!this._tokenizationStateStore) {\n\t\t\treturn StandardTokenType.Other;\n\t\t}\n\n\t\tthis.forceTokenization(position.lineNumber);\n\t\tconst lineStartState = this._tokenizationStateStore.getBeginState(position.lineNumber - 1);\n\t\tif (!lineStartState) {\n\t\t\treturn StandardTokenType.Other;\n\t\t}\n\n\t\tconst languageId = this._textModel.getLanguageId();\n\t\tconst lineContent = this._textModel.getLineContent(position.lineNumber);\n\n\t\t// Create the text as if `character` was inserted\n\t\tconst text = (\n\t\t\tlineContent.substring(0, position.column - 1)\n\t\t\t+ character\n\t\t\t+ lineContent.substring(position.column - 1)\n\t\t);\n\n\t\tconst r = safeTokenize(this._languageIdCodec, languageId, this._tokenizationStateStore.tokenizationSupport, text, true, lineStartState);\n\t\tconst lineTokens = new LineTokens(r.tokens, text, this._languageIdCodec);\n\t\tif (lineTokens.getCount() === 0) {\n\t\t\treturn StandardTokenType.Other;\n\t\t}\n\n\t\tconst tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n\t\treturn lineTokens.getStandardTokenType(tokenIndex);\n\t}\n\n\tpublic tokenizeLineWithEdit(position: Position, length: number, newText: string): LineTokens | null {\n\t\tconst lineNumber = position.lineNumber;\n\t\tconst column = position.column;\n\n\t\tif (!this._tokenizationStateStore) {\n\t\t\treturn null;\n\t\t}\n\n\t\tthis.forceTokenization(lineNumber);\n\t\tconst lineStartState = this._tokenizationStateStore.getBeginState(lineNumber - 1);\n\t\tif (!lineStartState) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst curLineContent = this._textModel.getLineContent(lineNumber);\n\t\tconst newLineContent = curLineContent.substring(0, column - 1)\n\t\t\t+ newText + curLineContent.substring(column - 1 + length);\n\n\t\tconst languageId = this._textModel.getLanguageIdAtPosition(lineNumber, 0);\n\t\tconst result = safeTokenize(\n\t\t\tthis._languageIdCodec,\n\t\t\tlanguageId,\n\t\t\tthis._tokenizationStateStore.tokenizationSupport,\n\t\t\tnewLineContent,\n\t\t\ttrue,\n\t\t\tlineStartState\n\t\t);\n\n\t\tconst lineTokens = new LineTokens(result.tokens, newLineContent, this._languageIdCodec);\n\t\treturn lineTokens;\n\t}\n\n\tpublic isCheapToTokenize(lineNumber: number): boolean {\n\t\tif (!this._tokenizationStateStore) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst firstInvalidLineNumber = this._tokenizationStateStore.invalidLineStartIndex + 1;\n\t\tif (lineNumber > firstInvalidLineNumber) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (lineNumber < firstInvalidLineNumber) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (this._textModel.getLineLength(lineNumber) < Constants.CHEAP_TOKENIZATION_LENGTH_LIMIT) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate _hasLinesToTokenize(): boolean {\n\t\tif (!this._tokenizationStateStore) {\n\t\t\treturn false;\n\t\t}\n\t\treturn (this._tokenizationStateStore.invalidLineStartIndex < this._textModel.getLineCount());\n\t}\n\n\tprivate _tokenizeOneInvalidLine(builder: ContiguousMultilineTokensBuilder): number {\n\t\tif (!this._tokenizationStateStore || !this._hasLinesToTokenize()) {\n\t\t\treturn this._textModel.getLineCount() + 1;\n\t\t}\n\t\tconst lineNumber = this._tokenizationStateStore.invalidLineStartIndex + 1;\n\t\tthis._updateTokensUntilLine(builder, lineNumber);\n\t\treturn lineNumber;\n\t}\n\n\tprivate _updateTokensUntilLine(builder: ContiguousMultilineTokensBuilder, lineNumber: number): void {\n\t\tif (!this._tokenizationStateStore) {\n\t\t\treturn;\n\t\t}\n\t\tconst languageId = this._textModel.getLanguageId();\n\t\tconst linesLength = this._textModel.getLineCount();\n\t\tconst endLineIndex = lineNumber - 1;\n\n\t\t// Validate all states up to and including endLineIndex\n\t\tfor (let lineIndex = this._tokenizationStateStore.invalidLineStartIndex; lineIndex <= endLineIndex; lineIndex++) {\n\t\t\tconst text = this._textModel.getLineContent(lineIndex + 1);\n\t\t\tconst lineStartState = this._tokenizationStateStore.getBeginState(lineIndex);\n\n\t\t\tconst r = safeTokenize(this._languageIdCodec, languageId, this._tokenizationStateStore.tokenizationSupport, text, true, lineStartState!);\n\t\t\tbuilder.add(lineIndex + 1, r.tokens);\n\t\t\tthis._tokenizationStateStore.setEndState(linesLength, lineIndex, r.endState);\n\t\t\tlineIndex = this._tokenizationStateStore.invalidLineStartIndex - 1; // -1 because the outer loop increments it\n\t\t}\n\t}\n\n\tprivate _tokenizeViewport(builder: ContiguousMultilineTokensBuilder, startLineNumber: number, endLineNumber: number): void {\n\t\tif (!this._tokenizationStateStore) {\n\t\t\t// nothing to do\n\t\t\treturn;\n\t\t}\n\n\t\tif (endLineNumber <= this._tokenizationStateStore.invalidLineStartIndex) {\n\t\t\t// nothing to do\n\t\t\treturn;\n\t\t}\n\n\t\tif (startLineNumber <= this._tokenizationStateStore.invalidLineStartIndex) {\n\t\t\t// tokenization has reached the viewport start...\n\t\t\tthis._updateTokensUntilLine(builder, endLineNumber);\n\t\t\treturn;\n\t\t}\n\n\t\tlet nonWhitespaceColumn = this._textModel.getLineFirstNonWhitespaceColumn(startLineNumber);\n\t\tconst fakeLines: string[] = [];\n\t\tlet initialState: IState | null = null;\n\t\tfor (let i = startLineNumber - 1; nonWhitespaceColumn > 1 && i >= 1; i--) {\n\t\t\tconst newNonWhitespaceIndex = this._textModel.getLineFirstNonWhitespaceColumn(i);\n\n\t\t\tif (newNonWhitespaceIndex === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (newNonWhitespaceIndex < nonWhitespaceColumn) {\n\t\t\t\tinitialState = this._tokenizationStateStore.getBeginState(i - 1);\n\t\t\t\tif (initialState) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tfakeLines.push(this._textModel.getLineContent(i));\n\t\t\t\tnonWhitespaceColumn = newNonWhitespaceIndex;\n\t\t\t}\n\t\t}\n\n\t\tif (!initialState) {\n\t\t\tinitialState = this._tokenizationStateStore.initialState;\n\t\t}\n\n\t\tconst languageId = this._textModel.getLanguageId();\n\t\tlet state = initialState;\n\t\tfor (let i = fakeLines.length - 1; i >= 0; i--) {\n\t\t\tconst r = safeTokenize(this._languageIdCodec, languageId, this._tokenizationStateStore.tokenizationSupport, fakeLines[i], false, state);\n\t\t\tstate = r.endState;\n\t\t}\n\n\t\tfor (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n\t\t\tconst text = this._textModel.getLineContent(lineNumber);\n\t\t\tconst r = safeTokenize(this._languageIdCodec, languageId, this._tokenizationStateStore.tokenizationSupport, text, true, state);\n\t\t\tbuilder.add(lineNumber, r.tokens);\n\t\t\tthis._tokenizationStateStore.markMustBeTokenized(lineNumber - 1);\n\t\t\tstate = r.endState;\n\t\t}\n\t}\n}\n\nfunction initializeTokenization(textModel: TextModel): [ITokenizationSupport, IState] | [null, null] {\n\tif (textModel.isTooLargeForTokenization()) {\n\t\treturn [null, null];\n\t}\n\tconst tokenizationSupport = TokenizationRegistry.get(textModel.getLanguageId());\n\tif (!tokenizationSupport) {\n\t\treturn [null, null];\n\t}\n\tlet initialState: IState;\n\ttry {\n\t\tinitialState = tokenizationSupport.getInitialState();\n\t} catch (e) {\n\t\tonUnexpectedError(e);\n\t\treturn [null, null];\n\t}\n\treturn [tokenizationSupport, initialState];\n}\n\nfunction safeTokenize(languageIdCodec: ILanguageIdCodec, languageId: string, tokenizationSupport: ITokenizationSupport | null, text: string, hasEOL: boolean, state: IState): EncodedTokenizationResult {\n\tlet r: EncodedTokenizationResult | null = null;\n\n\tif (tokenizationSupport) {\n\t\ttry {\n\t\t\tr = tokenizationSupport.tokenizeEncoded(text, hasEOL, state.clone());\n\t\t} catch (e) {\n\t\t\tonUnexpectedError(e);\n\t\t}\n\t}\n\n\tif (!r) {\n\t\tr = nullTokenizeEncoded(languageIdCodec.encodeLanguageId(languageId), state);\n\t}\n\n\tLineTokens.convertToEndOffset(r.tokens, text.length);\n\treturn r;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { LineTokens } from 'vs/editor/common/tokens/lineTokens';\n\nexport const EMPTY_LINE_TOKENS = (new Uint32Array(0)).buffer;\n\nexport class ContiguousTokensEditing {\n\n\tpublic static deleteBeginning(lineTokens: Uint32Array | ArrayBuffer | null, toChIndex: number): Uint32Array | ArrayBuffer | null {\n\t\tif (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {\n\t\t\treturn lineTokens;\n\t\t}\n\t\treturn ContiguousTokensEditing.delete(lineTokens, 0, toChIndex);\n\t}\n\n\tpublic static deleteEnding(lineTokens: Uint32Array | ArrayBuffer | null, fromChIndex: number): Uint32Array | ArrayBuffer | null {\n\t\tif (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {\n\t\t\treturn lineTokens;\n\t\t}\n\n\t\tconst tokens = toUint32Array(lineTokens);\n\t\tconst lineTextLength = tokens[tokens.length - 2];\n\t\treturn ContiguousTokensEditing.delete(lineTokens, fromChIndex, lineTextLength);\n\t}\n\n\tpublic static delete(lineTokens: Uint32Array | ArrayBuffer | null, fromChIndex: number, toChIndex: number): Uint32Array | ArrayBuffer | null {\n\t\tif (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS || fromChIndex === toChIndex) {\n\t\t\treturn lineTokens;\n\t\t}\n\n\t\tconst tokens = toUint32Array(lineTokens);\n\t\tconst tokensCount = (tokens.length >>> 1);\n\n\t\t// special case: deleting everything\n\t\tif (fromChIndex === 0 && tokens[tokens.length - 2] === toChIndex) {\n\t\t\treturn EMPTY_LINE_TOKENS;\n\t\t}\n\n\t\tconst fromTokenIndex = LineTokens.findIndexInTokensArray(tokens, fromChIndex);\n\t\tconst fromTokenStartOffset = (fromTokenIndex > 0 ? tokens[(fromTokenIndex - 1) << 1] : 0);\n\t\tconst fromTokenEndOffset = tokens[fromTokenIndex << 1];\n\n\t\tif (toChIndex < fromTokenEndOffset) {\n\t\t\t// the delete range is inside a single token\n\t\t\tconst delta = (toChIndex - fromChIndex);\n\t\t\tfor (let i = fromTokenIndex; i < tokensCount; i++) {\n\t\t\t\ttokens[i << 1] -= delta;\n\t\t\t}\n\t\t\treturn lineTokens;\n\t\t}\n\n\t\tlet dest: number;\n\t\tlet lastEnd: number;\n\t\tif (fromTokenStartOffset !== fromChIndex) {\n\t\t\ttokens[fromTokenIndex << 1] = fromChIndex;\n\t\t\tdest = ((fromTokenIndex + 1) << 1);\n\t\t\tlastEnd = fromChIndex;\n\t\t} else {\n\t\t\tdest = (fromTokenIndex << 1);\n\t\t\tlastEnd = fromTokenStartOffset;\n\t\t}\n\n\t\tconst delta = (toChIndex - fromChIndex);\n\t\tfor (let tokenIndex = fromTokenIndex + 1; tokenIndex < tokensCount; tokenIndex++) {\n\t\t\tconst tokenEndOffset = tokens[tokenIndex << 1] - delta;\n\t\t\tif (tokenEndOffset > lastEnd) {\n\t\t\t\ttokens[dest++] = tokenEndOffset;\n\t\t\t\ttokens[dest++] = tokens[(tokenIndex << 1) + 1];\n\t\t\t\tlastEnd = tokenEndOffset;\n\t\t\t}\n\t\t}\n\n\t\tif (dest === tokens.length) {\n\t\t\t// nothing to trim\n\t\t\treturn lineTokens;\n\t\t}\n\n\t\tconst tmp = new Uint32Array(dest);\n\t\ttmp.set(tokens.subarray(0, dest), 0);\n\t\treturn tmp.buffer;\n\t}\n\n\tpublic static append(lineTokens: Uint32Array | ArrayBuffer | null, _otherTokens: Uint32Array | ArrayBuffer | null): Uint32Array | ArrayBuffer | null {\n\t\tif (_otherTokens === EMPTY_LINE_TOKENS) {\n\t\t\treturn lineTokens;\n\t\t}\n\t\tif (lineTokens === EMPTY_LINE_TOKENS) {\n\t\t\treturn _otherTokens;\n\t\t}\n\t\tif (lineTokens === null) {\n\t\t\treturn lineTokens;\n\t\t}\n\t\tif (_otherTokens === null) {\n\t\t\t// cannot determine combined line length...\n\t\t\treturn null;\n\t\t}\n\t\tconst myTokens = toUint32Array(lineTokens);\n\t\tconst otherTokens = toUint32Array(_otherTokens);\n\t\tconst otherTokensCount = (otherTokens.length >>> 1);\n\n\t\tconst result = new Uint32Array(myTokens.length + otherTokens.length);\n\t\tresult.set(myTokens, 0);\n\t\tlet dest = myTokens.length;\n\t\tconst delta = myTokens[myTokens.length - 2];\n\t\tfor (let i = 0; i < otherTokensCount; i++) {\n\t\t\tresult[dest++] = otherTokens[(i << 1)] + delta;\n\t\t\tresult[dest++] = otherTokens[(i << 1) + 1];\n\t\t}\n\t\treturn result.buffer;\n\t}\n\n\tpublic static insert(lineTokens: Uint32Array | ArrayBuffer | null, chIndex: number, textLength: number): Uint32Array | ArrayBuffer | null {\n\t\tif (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {\n\t\t\t// nothing to do\n\t\t\treturn lineTokens;\n\t\t}\n\n\t\tconst tokens = toUint32Array(lineTokens);\n\t\tconst tokensCount = (tokens.length >>> 1);\n\n\t\tlet fromTokenIndex = LineTokens.findIndexInTokensArray(tokens, chIndex);\n\t\tif (fromTokenIndex > 0) {\n\t\t\tconst fromTokenStartOffset = tokens[(fromTokenIndex - 1) << 1];\n\t\t\tif (fromTokenStartOffset === chIndex) {\n\t\t\t\tfromTokenIndex--;\n\t\t\t}\n\t\t}\n\t\tfor (let tokenIndex = fromTokenIndex; tokenIndex < tokensCount; tokenIndex++) {\n\t\t\ttokens[tokenIndex << 1] += textLength;\n\t\t}\n\t\treturn lineTokens;\n\t}\n}\n\nexport function toUint32Array(arr: Uint32Array | ArrayBuffer): Uint32Array {\n\tif (arr instanceof Uint32Array) {\n\t\treturn arr;\n\t} else {\n\t\treturn new Uint32Array(arr);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as arrays from 'vs/base/common/arrays';\nimport { Position } from 'vs/editor/common/core/position';\nimport { IRange } from 'vs/editor/common/core/range';\nimport { ContiguousTokensEditing, EMPTY_LINE_TOKENS, toUint32Array } from 'vs/editor/common/tokens/contiguousTokensEditing';\nimport { LineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { ColorId, FontStyle, ILanguageIdCodec, LanguageId, MetadataConsts, StandardTokenType, TokenMetadata } from 'vs/editor/common/languages';\n\n/**\n * Represents contiguous tokens in a text model.\n */\nexport class ContiguousTokensStore {\n\tprivate _lineTokens: (Uint32Array | ArrayBuffer | null)[];\n\tprivate _len: number;\n\tprivate readonly _languageIdCodec: ILanguageIdCodec;\n\n\tconstructor(languageIdCodec: ILanguageIdCodec) {\n\t\tthis._lineTokens = [];\n\t\tthis._len = 0;\n\t\tthis._languageIdCodec = languageIdCodec;\n\t}\n\n\tpublic flush(): void {\n\t\tthis._lineTokens = [];\n\t\tthis._len = 0;\n\t}\n\n\tpublic getTokens(topLevelLanguageId: string, lineIndex: number, lineText: string): LineTokens {\n\t\tlet rawLineTokens: Uint32Array | ArrayBuffer | null = null;\n\t\tif (lineIndex < this._len) {\n\t\t\trawLineTokens = this._lineTokens[lineIndex];\n\t\t}\n\n\t\tif (rawLineTokens !== null && rawLineTokens !== EMPTY_LINE_TOKENS) {\n\t\t\treturn new LineTokens(toUint32Array(rawLineTokens), lineText, this._languageIdCodec);\n\t\t}\n\n\t\tconst lineTokens = new Uint32Array(2);\n\t\tlineTokens[0] = lineText.length;\n\t\tlineTokens[1] = getDefaultMetadata(this._languageIdCodec.encodeLanguageId(topLevelLanguageId));\n\t\treturn new LineTokens(lineTokens, lineText, this._languageIdCodec);\n\t}\n\n\tprivate static _massageTokens(topLevelLanguageId: LanguageId, lineTextLength: number, _tokens: Uint32Array | ArrayBuffer | null): Uint32Array | ArrayBuffer {\n\n\t\tconst tokens = _tokens ? toUint32Array(_tokens) : null;\n\n\t\tif (lineTextLength === 0) {\n\t\t\tlet hasDifferentLanguageId = false;\n\t\t\tif (tokens && tokens.length > 1) {\n\t\t\t\thasDifferentLanguageId = (TokenMetadata.getLanguageId(tokens[1]) !== topLevelLanguageId);\n\t\t\t}\n\n\t\t\tif (!hasDifferentLanguageId) {\n\t\t\t\treturn EMPTY_LINE_TOKENS;\n\t\t\t}\n\t\t}\n\n\t\tif (!tokens || tokens.length === 0) {\n\t\t\tconst tokens = new Uint32Array(2);\n\t\t\ttokens[0] = lineTextLength;\n\t\t\ttokens[1] = getDefaultMetadata(topLevelLanguageId);\n\t\t\treturn tokens.buffer;\n\t\t}\n\n\t\t// Ensure the last token covers the end of the text\n\t\ttokens[tokens.length - 2] = lineTextLength;\n\n\t\tif (tokens.byteOffset === 0 && tokens.byteLength === tokens.buffer.byteLength) {\n\t\t\t// Store directly the ArrayBuffer pointer to save an object\n\t\t\treturn tokens.buffer;\n\t\t}\n\t\treturn tokens;\n\t}\n\n\tprivate _ensureLine(lineIndex: number): void {\n\t\twhile (lineIndex >= this._len) {\n\t\t\tthis._lineTokens[this._len] = null;\n\t\t\tthis._len++;\n\t\t}\n\t}\n\n\tprivate _deleteLines(start: number, deleteCount: number): void {\n\t\tif (deleteCount === 0) {\n\t\t\treturn;\n\t\t}\n\t\tif (start + deleteCount > this._len) {\n\t\t\tdeleteCount = this._len - start;\n\t\t}\n\t\tthis._lineTokens.splice(start, deleteCount);\n\t\tthis._len -= deleteCount;\n\t}\n\n\tprivate _insertLines(insertIndex: number, insertCount: number): void {\n\t\tif (insertCount === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst lineTokens: (Uint32Array | ArrayBuffer | null)[] = [];\n\t\tfor (let i = 0; i < insertCount; i++) {\n\t\t\tlineTokens[i] = null;\n\t\t}\n\t\tthis._lineTokens = arrays.arrayInsert(this._lineTokens, insertIndex, lineTokens);\n\t\tthis._len += insertCount;\n\t}\n\n\tpublic setTokens(topLevelLanguageId: string, lineIndex: number, lineTextLength: number, _tokens: Uint32Array | ArrayBuffer | null, checkEquality: boolean): boolean {\n\t\tconst tokens = ContiguousTokensStore._massageTokens(this._languageIdCodec.encodeLanguageId(topLevelLanguageId), lineTextLength, _tokens);\n\t\tthis._ensureLine(lineIndex);\n\t\tconst oldTokens = this._lineTokens[lineIndex];\n\t\tthis._lineTokens[lineIndex] = tokens;\n\n\t\tif (checkEquality) {\n\t\t\treturn !ContiguousTokensStore._equals(oldTokens, tokens);\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate static _equals(_a: Uint32Array | ArrayBuffer | null, _b: Uint32Array | ArrayBuffer | null) {\n\t\tif (!_a || !_b) {\n\t\t\treturn !_a && !_b;\n\t\t}\n\n\t\tconst a = toUint32Array(_a);\n\t\tconst b = toUint32Array(_b);\n\n\t\tif (a.length !== b.length) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let i = 0, len = a.length; i < len; i++) {\n\t\t\tif (a[i] !== b[i]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t//#region Editing\n\n\tpublic acceptEdit(range: IRange, eolCount: number, firstLineLength: number): void {\n\t\tthis._acceptDeleteRange(range);\n\t\tthis._acceptInsertText(new Position(range.startLineNumber, range.startColumn), eolCount, firstLineLength);\n\t}\n\n\tprivate _acceptDeleteRange(range: IRange): void {\n\n\t\tconst firstLineIndex = range.startLineNumber - 1;\n\t\tif (firstLineIndex >= this._len) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (range.startLineNumber === range.endLineNumber) {\n\t\t\tif (range.startColumn === range.endColumn) {\n\t\t\t\t// Nothing to delete\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._lineTokens[firstLineIndex] = ContiguousTokensEditing.delete(this._lineTokens[firstLineIndex], range.startColumn - 1, range.endColumn - 1);\n\t\t\treturn;\n\t\t}\n\n\t\tthis._lineTokens[firstLineIndex] = ContiguousTokensEditing.deleteEnding(this._lineTokens[firstLineIndex], range.startColumn - 1);\n\n\t\tconst lastLineIndex = range.endLineNumber - 1;\n\t\tlet lastLineTokens: Uint32Array | ArrayBuffer | null = null;\n\t\tif (lastLineIndex < this._len) {\n\t\t\tlastLineTokens = ContiguousTokensEditing.deleteBeginning(this._lineTokens[lastLineIndex], range.endColumn - 1);\n\t\t}\n\n\t\t// Take remaining text on last line and append it to remaining text on first line\n\t\tthis._lineTokens[firstLineIndex] = ContiguousTokensEditing.append(this._lineTokens[firstLineIndex], lastLineTokens);\n\n\t\t// Delete middle lines\n\t\tthis._deleteLines(range.startLineNumber, range.endLineNumber - range.startLineNumber);\n\t}\n\n\tprivate _acceptInsertText(position: Position, eolCount: number, firstLineLength: number): void {\n\n\t\tif (eolCount === 0 && firstLineLength === 0) {\n\t\t\t// Nothing to insert\n\t\t\treturn;\n\t\t}\n\n\t\tconst lineIndex = position.lineNumber - 1;\n\t\tif (lineIndex >= this._len) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (eolCount === 0) {\n\t\t\t// Inserting text on one line\n\t\t\tthis._lineTokens[lineIndex] = ContiguousTokensEditing.insert(this._lineTokens[lineIndex], position.column - 1, firstLineLength);\n\t\t\treturn;\n\t\t}\n\n\t\tthis._lineTokens[lineIndex] = ContiguousTokensEditing.deleteEnding(this._lineTokens[lineIndex], position.column - 1);\n\t\tthis._lineTokens[lineIndex] = ContiguousTokensEditing.insert(this._lineTokens[lineIndex], position.column - 1, firstLineLength);\n\n\t\tthis._insertLines(position.lineNumber, eolCount);\n\t}\n\n\t//#endregion\n}\n\nfunction getDefaultMetadata(topLevelLanguageId: LanguageId): number {\n\treturn (\n\t\t(topLevelLanguageId << MetadataConsts.LANGUAGEID_OFFSET)\n\t\t| (StandardTokenType.Other << MetadataConsts.TOKEN_TYPE_OFFSET)\n\t\t| (FontStyle.None << MetadataConsts.FONT_STYLE_OFFSET)\n\t\t| (ColorId.DefaultForeground << MetadataConsts.FOREGROUND_OFFSET)\n\t\t| (ColorId.DefaultBackground << MetadataConsts.BACKGROUND_OFFSET)\n\t) >>> 0;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { Position } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { countEOL } from 'vs/editor/common/core/eolCounter';\n\n/**\n * Represents sparse tokens over a contiguous range of lines.\n */\nexport class SparseMultilineTokens {\n\n\tpublic static create(startLineNumber: number, tokens: Uint32Array): SparseMultilineTokens {\n\t\treturn new SparseMultilineTokens(startLineNumber, new SparseMultilineTokensStorage(tokens));\n\t}\n\n\tprivate _startLineNumber: number;\n\tprivate _endLineNumber: number;\n\tprivate readonly _tokens: SparseMultilineTokensStorage;\n\n\t/**\n\t * (Inclusive) start line number for these tokens.\n\t */\n\tpublic get startLineNumber(): number {\n\t\treturn this._startLineNumber;\n\t}\n\n\t/**\n\t * (Inclusive) end line number for these tokens.\n\t */\n\tpublic get endLineNumber(): number {\n\t\treturn this._endLineNumber;\n\t}\n\n\tprivate constructor(startLineNumber: number, tokens: SparseMultilineTokensStorage) {\n\t\tthis._startLineNumber = startLineNumber;\n\t\tthis._tokens = tokens;\n\t\tthis._endLineNumber = this._startLineNumber + this._tokens.getMaxDeltaLine();\n\t}\n\n\tpublic toString(): string {\n\t\treturn this._tokens.toString(this._startLineNumber);\n\t}\n\n\tprivate _updateEndLineNumber(): void {\n\t\tthis._endLineNumber = this._startLineNumber + this._tokens.getMaxDeltaLine();\n\t}\n\n\tpublic isEmpty(): boolean {\n\t\treturn this._tokens.isEmpty();\n\t}\n\n\tpublic getLineTokens(lineNumber: number): SparseLineTokens | null {\n\t\tif (this._startLineNumber <= lineNumber && lineNumber <= this._endLineNumber) {\n\t\t\treturn this._tokens.getLineTokens(lineNumber - this._startLineNumber);\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic getRange(): Range | null {\n\t\tconst deltaRange = this._tokens.getRange();\n\t\tif (!deltaRange) {\n\t\t\treturn deltaRange;\n\t\t}\n\t\treturn new Range(this._startLineNumber + deltaRange.startLineNumber, deltaRange.startColumn, this._startLineNumber + deltaRange.endLineNumber, deltaRange.endColumn);\n\t}\n\n\tpublic removeTokens(range: Range): void {\n\t\tconst startLineIndex = range.startLineNumber - this._startLineNumber;\n\t\tconst endLineIndex = range.endLineNumber - this._startLineNumber;\n\n\t\tthis._startLineNumber += this._tokens.removeTokens(startLineIndex, range.startColumn - 1, endLineIndex, range.endColumn - 1);\n\t\tthis._updateEndLineNumber();\n\t}\n\n\tpublic split(range: Range): [SparseMultilineTokens, SparseMultilineTokens] {\n\t\t// split tokens to two:\n\t\t// a) all the tokens before `range`\n\t\t// b) all the tokens after `range`\n\t\tconst startLineIndex = range.startLineNumber - this._startLineNumber;\n\t\tconst endLineIndex = range.endLineNumber - this._startLineNumber;\n\n\t\tconst [a, b, bDeltaLine] = this._tokens.split(startLineIndex, range.startColumn - 1, endLineIndex, range.endColumn - 1);\n\t\treturn [new SparseMultilineTokens(this._startLineNumber, a), new SparseMultilineTokens(this._startLineNumber + bDeltaLine, b)];\n\t}\n\n\tpublic applyEdit(range: IRange, text: string): void {\n\t\tconst [eolCount, firstLineLength, lastLineLength] = countEOL(text);\n\t\tthis.acceptEdit(range, eolCount, firstLineLength, lastLineLength, text.length > 0 ? text.charCodeAt(0) : CharCode.Null);\n\t}\n\n\tpublic acceptEdit(range: IRange, eolCount: number, firstLineLength: number, lastLineLength: number, firstCharCode: number): void {\n\t\tthis._acceptDeleteRange(range);\n\t\tthis._acceptInsertText(new Position(range.startLineNumber, range.startColumn), eolCount, firstLineLength, lastLineLength, firstCharCode);\n\t\tthis._updateEndLineNumber();\n\t}\n\n\tprivate _acceptDeleteRange(range: IRange): void {\n\t\tif (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {\n\t\t\t// Nothing to delete\n\t\t\treturn;\n\t\t}\n\n\t\tconst firstLineIndex = range.startLineNumber - this._startLineNumber;\n\t\tconst lastLineIndex = range.endLineNumber - this._startLineNumber;\n\n\t\tif (lastLineIndex < 0) {\n\t\t\t// this deletion occurs entirely before this block, so we only need to adjust line numbers\n\t\t\tconst deletedLinesCount = lastLineIndex - firstLineIndex;\n\t\t\tthis._startLineNumber -= deletedLinesCount;\n\t\t\treturn;\n\t\t}\n\n\t\tconst tokenMaxDeltaLine = this._tokens.getMaxDeltaLine();\n\n\t\tif (firstLineIndex >= tokenMaxDeltaLine + 1) {\n\t\t\t// this deletion occurs entirely after this block, so there is nothing to do\n\t\t\treturn;\n\t\t}\n\n\t\tif (firstLineIndex < 0 && lastLineIndex >= tokenMaxDeltaLine + 1) {\n\t\t\t// this deletion completely encompasses this block\n\t\t\tthis._startLineNumber = 0;\n\t\t\tthis._tokens.clear();\n\t\t\treturn;\n\t\t}\n\n\t\tif (firstLineIndex < 0) {\n\t\t\tconst deletedBefore = -firstLineIndex;\n\t\t\tthis._startLineNumber -= deletedBefore;\n\n\t\t\tthis._tokens.acceptDeleteRange(range.startColumn - 1, 0, 0, lastLineIndex, range.endColumn - 1);\n\t\t} else {\n\t\t\tthis._tokens.acceptDeleteRange(0, firstLineIndex, range.startColumn - 1, lastLineIndex, range.endColumn - 1);\n\t\t}\n\t}\n\n\tprivate _acceptInsertText(position: Position, eolCount: number, firstLineLength: number, lastLineLength: number, firstCharCode: number): void {\n\n\t\tif (eolCount === 0 && firstLineLength === 0) {\n\t\t\t// Nothing to insert\n\t\t\treturn;\n\t\t}\n\n\t\tconst lineIndex = position.lineNumber - this._startLineNumber;\n\n\t\tif (lineIndex < 0) {\n\t\t\t// this insertion occurs before this block, so we only need to adjust line numbers\n\t\t\tthis._startLineNumber += eolCount;\n\t\t\treturn;\n\t\t}\n\n\t\tconst tokenMaxDeltaLine = this._tokens.getMaxDeltaLine();\n\n\t\tif (lineIndex >= tokenMaxDeltaLine + 1) {\n\t\t\t// this insertion occurs after this block, so there is nothing to do\n\t\t\treturn;\n\t\t}\n\n\t\tthis._tokens.acceptInsertText(lineIndex, position.column - 1, eolCount, firstLineLength, lastLineLength, firstCharCode);\n\t}\n}\n\nclass SparseMultilineTokensStorage {\n\t/**\n\t * The encoding of tokens is:\n\t * 4*i deltaLine (from `startLineNumber`)\n\t * 4*i+1 startCharacter (from the line start)\n\t * 4*i+2 endCharacter (from the line start)\n\t * 4*i+3 metadata\n\t */\n\tprivate readonly _tokens: Uint32Array;\n\tprivate _tokenCount: number;\n\n\tconstructor(tokens: Uint32Array) {\n\t\tthis._tokens = tokens;\n\t\tthis._tokenCount = tokens.length / 4;\n\t}\n\n\tpublic toString(startLineNumber: number): string {\n\t\tconst pieces: string[] = [];\n\t\tfor (let i = 0; i < this._tokenCount; i++) {\n\t\t\tpieces.push(`(${this._getDeltaLine(i) + startLineNumber},${this._getStartCharacter(i)}-${this._getEndCharacter(i)})`);\n\t\t}\n\t\treturn `[${pieces.join(',')}]`;\n\t}\n\n\tpublic getMaxDeltaLine(): number {\n\t\tconst tokenCount = this._getTokenCount();\n\t\tif (tokenCount === 0) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn this._getDeltaLine(tokenCount - 1);\n\t}\n\n\tpublic getRange(): Range | null {\n\t\tconst tokenCount = this._getTokenCount();\n\t\tif (tokenCount === 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst startChar = this._getStartCharacter(0);\n\t\tconst maxDeltaLine = this._getDeltaLine(tokenCount - 1);\n\t\tconst endChar = this._getEndCharacter(tokenCount - 1);\n\t\treturn new Range(0, startChar + 1, maxDeltaLine, endChar + 1);\n\t}\n\n\tprivate _getTokenCount(): number {\n\t\treturn this._tokenCount;\n\t}\n\n\tprivate _getDeltaLine(tokenIndex: number): number {\n\t\treturn this._tokens[4 * tokenIndex];\n\t}\n\n\tprivate _getStartCharacter(tokenIndex: number): number {\n\t\treturn this._tokens[4 * tokenIndex + 1];\n\t}\n\n\tprivate _getEndCharacter(tokenIndex: number): number {\n\t\treturn this._tokens[4 * tokenIndex + 2];\n\t}\n\n\tpublic isEmpty(): boolean {\n\t\treturn (this._getTokenCount() === 0);\n\t}\n\n\tpublic getLineTokens(deltaLine: number): SparseLineTokens | null {\n\t\tlet low = 0;\n\t\tlet high = this._getTokenCount() - 1;\n\n\t\twhile (low < high) {\n\t\t\tconst mid = low + Math.floor((high - low) / 2);\n\t\t\tconst midDeltaLine = this._getDeltaLine(mid);\n\n\t\t\tif (midDeltaLine < deltaLine) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else if (midDeltaLine > deltaLine) {\n\t\t\t\thigh = mid - 1;\n\t\t\t} else {\n\t\t\t\tlet min = mid;\n\t\t\t\twhile (min > low && this._getDeltaLine(min - 1) === deltaLine) {\n\t\t\t\t\tmin--;\n\t\t\t\t}\n\t\t\t\tlet max = mid;\n\t\t\t\twhile (max < high && this._getDeltaLine(max + 1) === deltaLine) {\n\t\t\t\t\tmax++;\n\t\t\t\t}\n\t\t\t\treturn new SparseLineTokens(this._tokens.subarray(4 * min, 4 * max + 4));\n\t\t\t}\n\t\t}\n\n\t\tif (this._getDeltaLine(low) === deltaLine) {\n\t\t\treturn new SparseLineTokens(this._tokens.subarray(4 * low, 4 * low + 4));\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic clear(): void {\n\t\tthis._tokenCount = 0;\n\t}\n\n\tpublic removeTokens(startDeltaLine: number, startChar: number, endDeltaLine: number, endChar: number): number {\n\t\tconst tokens = this._tokens;\n\t\tconst tokenCount = this._tokenCount;\n\t\tlet newTokenCount = 0;\n\t\tlet hasDeletedTokens = false;\n\t\tlet firstDeltaLine = 0;\n\t\tfor (let i = 0; i < tokenCount; i++) {\n\t\t\tconst srcOffset = 4 * i;\n\t\t\tconst tokenDeltaLine = tokens[srcOffset];\n\t\t\tconst tokenStartCharacter = tokens[srcOffset + 1];\n\t\t\tconst tokenEndCharacter = tokens[srcOffset + 2];\n\t\t\tconst tokenMetadata = tokens[srcOffset + 3];\n\n\t\t\tif (\n\t\t\t\t(tokenDeltaLine > startDeltaLine || (tokenDeltaLine === startDeltaLine && tokenEndCharacter >= startChar))\n\t\t\t\t&& (tokenDeltaLine < endDeltaLine || (tokenDeltaLine === endDeltaLine && tokenStartCharacter <= endChar))\n\t\t\t) {\n\t\t\t\thasDeletedTokens = true;\n\t\t\t} else {\n\t\t\t\tif (newTokenCount === 0) {\n\t\t\t\t\tfirstDeltaLine = tokenDeltaLine;\n\t\t\t\t}\n\t\t\t\tif (hasDeletedTokens) {\n\t\t\t\t\t// must move the token to the left\n\t\t\t\t\tconst destOffset = 4 * newTokenCount;\n\t\t\t\t\ttokens[destOffset] = tokenDeltaLine - firstDeltaLine;\n\t\t\t\t\ttokens[destOffset + 1] = tokenStartCharacter;\n\t\t\t\t\ttokens[destOffset + 2] = tokenEndCharacter;\n\t\t\t\t\ttokens[destOffset + 3] = tokenMetadata;\n\t\t\t\t}\n\t\t\t\tnewTokenCount++;\n\t\t\t}\n\t\t}\n\n\t\tthis._tokenCount = newTokenCount;\n\n\t\treturn firstDeltaLine;\n\t}\n\n\tpublic split(startDeltaLine: number, startChar: number, endDeltaLine: number, endChar: number): [SparseMultilineTokensStorage, SparseMultilineTokensStorage, number] {\n\t\tconst tokens = this._tokens;\n\t\tconst tokenCount = this._tokenCount;\n\t\tconst aTokens: number[] = [];\n\t\tconst bTokens: number[] = [];\n\t\tlet destTokens: number[] = aTokens;\n\t\tlet destOffset = 0;\n\t\tlet destFirstDeltaLine: number = 0;\n\t\tfor (let i = 0; i < tokenCount; i++) {\n\t\t\tconst srcOffset = 4 * i;\n\t\t\tconst tokenDeltaLine = tokens[srcOffset];\n\t\t\tconst tokenStartCharacter = tokens[srcOffset + 1];\n\t\t\tconst tokenEndCharacter = tokens[srcOffset + 2];\n\t\t\tconst tokenMetadata = tokens[srcOffset + 3];\n\n\t\t\tif ((tokenDeltaLine > startDeltaLine || (tokenDeltaLine === startDeltaLine && tokenEndCharacter >= startChar))) {\n\t\t\t\tif ((tokenDeltaLine < endDeltaLine || (tokenDeltaLine === endDeltaLine && tokenStartCharacter <= endChar))) {\n\t\t\t\t\t// this token is touching the range\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\t// this token is after the range\n\t\t\t\t\tif (destTokens !== bTokens) {\n\t\t\t\t\t\t// this token is the first token after the range\n\t\t\t\t\t\tdestTokens = bTokens;\n\t\t\t\t\t\tdestOffset = 0;\n\t\t\t\t\t\tdestFirstDeltaLine = tokenDeltaLine;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdestTokens[destOffset++] = tokenDeltaLine - destFirstDeltaLine;\n\t\t\tdestTokens[destOffset++] = tokenStartCharacter;\n\t\t\tdestTokens[destOffset++] = tokenEndCharacter;\n\t\t\tdestTokens[destOffset++] = tokenMetadata;\n\t\t}\n\n\t\treturn [new SparseMultilineTokensStorage(new Uint32Array(aTokens)), new SparseMultilineTokensStorage(new Uint32Array(bTokens)), destFirstDeltaLine];\n\t}\n\n\tpublic acceptDeleteRange(horizontalShiftForFirstLineTokens: number, startDeltaLine: number, startCharacter: number, endDeltaLine: number, endCharacter: number): void {\n\t\t// This is a bit complex, here are the cases I used to think about this:\n\t\t//\n\t\t// 1. The token starts before the deletion range\n\t\t// 1a. The token is completely before the deletion range\n\t\t// -----------\n\t\t// xxxxxxxxxxx\n\t\t// 1b. The token starts before, the deletion range ends after the token\n\t\t// -----------\n\t\t// xxxxxxxxxxx\n\t\t// 1c. The token starts before, the deletion range ends precisely with the token\n\t\t// ---------------\n\t\t// xxxxxxxx\n\t\t// 1d. The token starts before, the deletion range is inside the token\n\t\t// ---------------\n\t\t// xxxxx\n\t\t//\n\t\t// 2. The token starts at the same position with the deletion range\n\t\t// 2a. The token starts at the same position, and ends inside the deletion range\n\t\t// -------\n\t\t// xxxxxxxxxxx\n\t\t// 2b. The token starts at the same position, and ends at the same position as the deletion range\n\t\t// ----------\n\t\t// xxxxxxxxxx\n\t\t// 2c. The token starts at the same position, and ends after the deletion range\n\t\t// -------------\n\t\t// xxxxxxx\n\t\t//\n\t\t// 3. The token starts inside the deletion range\n\t\t// 3a. The token is inside the deletion range\n\t\t// -------\n\t\t// xxxxxxxxxxxxx\n\t\t// 3b. The token starts inside the deletion range, and ends at the same position as the deletion range\n\t\t// ----------\n\t\t// xxxxxxxxxxxxx\n\t\t// 3c. The token starts inside the deletion range, and ends after the deletion range\n\t\t// ------------\n\t\t// xxxxxxxxxxx\n\t\t//\n\t\t// 4. The token starts after the deletion range\n\t\t// -----------\n\t\t// xxxxxxxx\n\t\t//\n\t\tconst tokens = this._tokens;\n\t\tconst tokenCount = this._tokenCount;\n\t\tconst deletedLineCount = (endDeltaLine - startDeltaLine);\n\t\tlet newTokenCount = 0;\n\t\tlet hasDeletedTokens = false;\n\t\tfor (let i = 0; i < tokenCount; i++) {\n\t\t\tconst srcOffset = 4 * i;\n\t\t\tlet tokenDeltaLine = tokens[srcOffset];\n\t\t\tlet tokenStartCharacter = tokens[srcOffset + 1];\n\t\t\tlet tokenEndCharacter = tokens[srcOffset + 2];\n\t\t\tconst tokenMetadata = tokens[srcOffset + 3];\n\n\t\t\tif (tokenDeltaLine < startDeltaLine || (tokenDeltaLine === startDeltaLine && tokenEndCharacter <= startCharacter)) {\n\t\t\t\t// 1a. The token is completely before the deletion range\n\t\t\t\t// => nothing to do\n\t\t\t\tnewTokenCount++;\n\t\t\t\tcontinue;\n\t\t\t} else if (tokenDeltaLine === startDeltaLine && tokenStartCharacter < startCharacter) {\n\t\t\t\t// 1b, 1c, 1d\n\t\t\t\t// => the token survives, but it needs to shrink\n\t\t\t\tif (tokenDeltaLine === endDeltaLine && tokenEndCharacter > endCharacter) {\n\t\t\t\t\t// 1d. The token starts before, the deletion range is inside the token\n\t\t\t\t\t// => the token shrinks by the deletion character count\n\t\t\t\t\ttokenEndCharacter -= (endCharacter - startCharacter);\n\t\t\t\t} else {\n\t\t\t\t\t// 1b. The token starts before, the deletion range ends after the token\n\t\t\t\t\t// 1c. The token starts before, the deletion range ends precisely with the token\n\t\t\t\t\t// => the token shrinks its ending to the deletion start\n\t\t\t\t\ttokenEndCharacter = startCharacter;\n\t\t\t\t}\n\t\t\t} else if (tokenDeltaLine === startDeltaLine && tokenStartCharacter === startCharacter) {\n\t\t\t\t// 2a, 2b, 2c\n\t\t\t\tif (tokenDeltaLine === endDeltaLine && tokenEndCharacter > endCharacter) {\n\t\t\t\t\t// 2c. The token starts at the same position, and ends after the deletion range\n\t\t\t\t\t// => the token shrinks by the deletion character count\n\t\t\t\t\ttokenEndCharacter -= (endCharacter - startCharacter);\n\t\t\t\t} else {\n\t\t\t\t\t// 2a. The token starts at the same position, and ends inside the deletion range\n\t\t\t\t\t// 2b. The token starts at the same position, and ends at the same position as the deletion range\n\t\t\t\t\t// => the token is deleted\n\t\t\t\t\thasDeletedTokens = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if (tokenDeltaLine < endDeltaLine || (tokenDeltaLine === endDeltaLine && tokenStartCharacter < endCharacter)) {\n\t\t\t\t// 3a, 3b, 3c\n\t\t\t\tif (tokenDeltaLine === endDeltaLine && tokenEndCharacter > endCharacter) {\n\t\t\t\t\t// 3c. The token starts inside the deletion range, and ends after the deletion range\n\t\t\t\t\t// => the token moves left and shrinks\n\t\t\t\t\tif (tokenDeltaLine === startDeltaLine) {\n\t\t\t\t\t\t// the deletion started on the same line as the token\n\t\t\t\t\t\t// => the token moves left and shrinks\n\t\t\t\t\t\ttokenStartCharacter = startCharacter;\n\t\t\t\t\t\ttokenEndCharacter = tokenStartCharacter + (tokenEndCharacter - endCharacter);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// the deletion started on a line above the token\n\t\t\t\t\t\t// => the token moves to the beginning of the line\n\t\t\t\t\t\ttokenStartCharacter = 0;\n\t\t\t\t\t\ttokenEndCharacter = tokenStartCharacter + (tokenEndCharacter - endCharacter);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// 3a. The token is inside the deletion range\n\t\t\t\t\t// 3b. The token starts inside the deletion range, and ends at the same position as the deletion range\n\t\t\t\t\t// => the token is deleted\n\t\t\t\t\thasDeletedTokens = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if (tokenDeltaLine > endDeltaLine) {\n\t\t\t\t// 4. (partial) The token starts after the deletion range, on a line below...\n\t\t\t\tif (deletedLineCount === 0 && !hasDeletedTokens) {\n\t\t\t\t\t// early stop, there is no need to walk all the tokens and do nothing...\n\t\t\t\t\tnewTokenCount = tokenCount;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttokenDeltaLine -= deletedLineCount;\n\t\t\t} else if (tokenDeltaLine === endDeltaLine && tokenStartCharacter >= endCharacter) {\n\t\t\t\t// 4. (continued) The token starts after the deletion range, on the last line where a deletion occurs\n\t\t\t\tif (horizontalShiftForFirstLineTokens && tokenDeltaLine === 0) {\n\t\t\t\t\ttokenStartCharacter += horizontalShiftForFirstLineTokens;\n\t\t\t\t\ttokenEndCharacter += horizontalShiftForFirstLineTokens;\n\t\t\t\t}\n\t\t\t\ttokenDeltaLine -= deletedLineCount;\n\t\t\t\ttokenStartCharacter -= (endCharacter - startCharacter);\n\t\t\t\ttokenEndCharacter -= (endCharacter - startCharacter);\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Not possible!`);\n\t\t\t}\n\n\t\t\tconst destOffset = 4 * newTokenCount;\n\t\t\ttokens[destOffset] = tokenDeltaLine;\n\t\t\ttokens[destOffset + 1] = tokenStartCharacter;\n\t\t\ttokens[destOffset + 2] = tokenEndCharacter;\n\t\t\ttokens[destOffset + 3] = tokenMetadata;\n\t\t\tnewTokenCount++;\n\t\t}\n\n\t\tthis._tokenCount = newTokenCount;\n\t}\n\n\tpublic acceptInsertText(deltaLine: number, character: number, eolCount: number, firstLineLength: number, lastLineLength: number, firstCharCode: number): void {\n\t\t// Here are the cases I used to think about this:\n\t\t//\n\t\t// 1. The token is completely before the insertion point\n\t\t// ----------- |\n\t\t// 2. The token ends precisely at the insertion point\n\t\t// -----------|\n\t\t// 3. The token contains the insertion point\n\t\t// -----|------\n\t\t// 4. The token starts precisely at the insertion point\n\t\t// |-----------\n\t\t// 5. The token is completely after the insertion point\n\t\t// | -----------\n\t\t//\n\t\tconst isInsertingPreciselyOneWordCharacter = (\n\t\t\teolCount === 0\n\t\t\t&& firstLineLength === 1\n\t\t\t&& (\n\t\t\t\t(firstCharCode >= CharCode.Digit0 && firstCharCode <= CharCode.Digit9)\n\t\t\t\t|| (firstCharCode >= CharCode.A && firstCharCode <= CharCode.Z)\n\t\t\t\t|| (firstCharCode >= CharCode.a && firstCharCode <= CharCode.z)\n\t\t\t)\n\t\t);\n\t\tconst tokens = this._tokens;\n\t\tconst tokenCount = this._tokenCount;\n\t\tfor (let i = 0; i < tokenCount; i++) {\n\t\t\tconst offset = 4 * i;\n\t\t\tlet tokenDeltaLine = tokens[offset];\n\t\t\tlet tokenStartCharacter = tokens[offset + 1];\n\t\t\tlet tokenEndCharacter = tokens[offset + 2];\n\n\t\t\tif (tokenDeltaLine < deltaLine || (tokenDeltaLine === deltaLine && tokenEndCharacter < character)) {\n\t\t\t\t// 1. The token is completely before the insertion point\n\t\t\t\t// => nothing to do\n\t\t\t\tcontinue;\n\t\t\t} else if (tokenDeltaLine === deltaLine && tokenEndCharacter === character) {\n\t\t\t\t// 2. The token ends precisely at the insertion point\n\t\t\t\t// => expand the end character only if inserting precisely one character that is a word character\n\t\t\t\tif (isInsertingPreciselyOneWordCharacter) {\n\t\t\t\t\ttokenEndCharacter += 1;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if (tokenDeltaLine === deltaLine && tokenStartCharacter < character && character < tokenEndCharacter) {\n\t\t\t\t// 3. The token contains the insertion point\n\t\t\t\tif (eolCount === 0) {\n\t\t\t\t\t// => just expand the end character\n\t\t\t\t\ttokenEndCharacter += firstLineLength;\n\t\t\t\t} else {\n\t\t\t\t\t// => cut off the token\n\t\t\t\t\ttokenEndCharacter = character;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// 4. or 5.\n\t\t\t\tif (tokenDeltaLine === deltaLine && tokenStartCharacter === character) {\n\t\t\t\t\t// 4. The token starts precisely at the insertion point\n\t\t\t\t\t// => grow the token (by keeping its start constant) only if inserting precisely one character that is a word character\n\t\t\t\t\t// => otherwise behave as in case 5.\n\t\t\t\t\tif (isInsertingPreciselyOneWordCharacter) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// => the token must move and keep its size constant\n\t\t\t\tif (tokenDeltaLine === deltaLine) {\n\t\t\t\t\ttokenDeltaLine += eolCount;\n\t\t\t\t\t// this token is on the line where the insertion is taking place\n\t\t\t\t\tif (eolCount === 0) {\n\t\t\t\t\t\ttokenStartCharacter += firstLineLength;\n\t\t\t\t\t\ttokenEndCharacter += firstLineLength;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst tokenLength = tokenEndCharacter - tokenStartCharacter;\n\t\t\t\t\t\ttokenStartCharacter = lastLineLength + (tokenStartCharacter - character);\n\t\t\t\t\t\ttokenEndCharacter = tokenStartCharacter + tokenLength;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttokenDeltaLine += eolCount;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttokens[offset] = tokenDeltaLine;\n\t\t\ttokens[offset + 1] = tokenStartCharacter;\n\t\t\ttokens[offset + 2] = tokenEndCharacter;\n\t\t}\n\t}\n}\n\nexport class SparseLineTokens {\n\n\tprivate readonly _tokens: Uint32Array;\n\n\tconstructor(tokens: Uint32Array) {\n\t\tthis._tokens = tokens;\n\t}\n\n\tpublic getCount(): number {\n\t\treturn this._tokens.length / 4;\n\t}\n\n\tpublic getStartCharacter(tokenIndex: number): number {\n\t\treturn this._tokens[4 * tokenIndex + 1];\n\t}\n\n\tpublic getEndCharacter(tokenIndex: number): number {\n\t\treturn this._tokens[4 * tokenIndex + 2];\n\t}\n\n\tpublic getMetadata(tokenIndex: number): number {\n\t\treturn this._tokens[4 * tokenIndex + 3];\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as arrays from 'vs/base/common/arrays';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { LineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { SparseMultilineTokens } from 'vs/editor/common/tokens/sparseMultilineTokens';\nimport { ILanguageIdCodec, MetadataConsts } from 'vs/editor/common/languages';\n\n/**\n * Represents sparse tokens in a text model.\n */\nexport class SparseTokensStore {\n\n\tprivate _pieces: SparseMultilineTokens[];\n\tprivate _isComplete: boolean;\n\tprivate readonly _languageIdCodec: ILanguageIdCodec;\n\n\tconstructor(languageIdCodec: ILanguageIdCodec) {\n\t\tthis._pieces = [];\n\t\tthis._isComplete = false;\n\t\tthis._languageIdCodec = languageIdCodec;\n\t}\n\n\tpublic flush(): void {\n\t\tthis._pieces = [];\n\t\tthis._isComplete = false;\n\t}\n\n\tpublic isEmpty(): boolean {\n\t\treturn (this._pieces.length === 0);\n\t}\n\n\tpublic set(pieces: SparseMultilineTokens[] | null, isComplete: boolean): void {\n\t\tthis._pieces = pieces || [];\n\t\tthis._isComplete = isComplete;\n\t}\n\n\tpublic setPartial(_range: Range, pieces: SparseMultilineTokens[]): Range {\n\t\t// console.log(`setPartial ${_range} ${pieces.map(p => p.toString()).join(', ')}`);\n\n\t\tlet range = _range;\n\t\tif (pieces.length > 0) {\n\t\t\tconst _firstRange = pieces[0].getRange();\n\t\t\tconst _lastRange = pieces[pieces.length - 1].getRange();\n\t\t\tif (!_firstRange || !_lastRange) {\n\t\t\t\treturn _range;\n\t\t\t}\n\t\t\trange = _range.plusRange(_firstRange).plusRange(_lastRange);\n\t\t}\n\n\t\tlet insertPosition: { index: number; } | null = null;\n\t\tfor (let i = 0, len = this._pieces.length; i < len; i++) {\n\t\t\tconst piece = this._pieces[i];\n\t\t\tif (piece.endLineNumber < range.startLineNumber) {\n\t\t\t\t// this piece is before the range\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (piece.startLineNumber > range.endLineNumber) {\n\t\t\t\t// this piece is after the range, so mark the spot before this piece\n\t\t\t\t// as a good insertion position and stop looping\n\t\t\t\tinsertPosition = insertPosition || { index: i };\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// this piece might intersect with the range\n\t\t\tpiece.removeTokens(range);\n\n\t\t\tif (piece.isEmpty()) {\n\t\t\t\t// remove the piece if it became empty\n\t\t\t\tthis._pieces.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t\tlen--;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (piece.endLineNumber < range.startLineNumber) {\n\t\t\t\t// after removal, this piece is before the range\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (piece.startLineNumber > range.endLineNumber) {\n\t\t\t\t// after removal, this piece is after the range\n\t\t\t\tinsertPosition = insertPosition || { index: i };\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// after removal, this piece contains the range\n\t\t\tconst [a, b] = piece.split(range);\n\t\t\tif (a.isEmpty()) {\n\t\t\t\t// this piece is actually after the range\n\t\t\t\tinsertPosition = insertPosition || { index: i };\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (b.isEmpty()) {\n\t\t\t\t// this piece is actually before the range\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis._pieces.splice(i, 1, a, b);\n\t\t\ti++;\n\t\t\tlen++;\n\n\t\t\tinsertPosition = insertPosition || { index: i };\n\t\t}\n\n\t\tinsertPosition = insertPosition || { index: this._pieces.length };\n\n\t\tif (pieces.length > 0) {\n\t\t\tthis._pieces = arrays.arrayInsert(this._pieces, insertPosition.index, pieces);\n\t\t}\n\n\t\t// console.log(`I HAVE ${this._pieces.length} pieces`);\n\t\t// console.log(`${this._pieces.map(p => p.toString()).join('\\n')}`);\n\n\t\treturn range;\n\t}\n\n\tpublic isComplete(): boolean {\n\t\treturn this._isComplete;\n\t}\n\n\tpublic addSparseTokens(lineNumber: number, aTokens: LineTokens): LineTokens {\n\t\tconst pieces = this._pieces;\n\n\t\tif (pieces.length === 0) {\n\t\t\treturn aTokens;\n\t\t}\n\n\t\tconst pieceIndex = SparseTokensStore._findFirstPieceWithLine(pieces, lineNumber);\n\t\tconst bTokens = pieces[pieceIndex].getLineTokens(lineNumber);\n\n\t\tif (!bTokens) {\n\t\t\treturn aTokens;\n\t\t}\n\n\t\tconst aLen = aTokens.getCount();\n\t\tconst bLen = bTokens.getCount();\n\n\t\tlet aIndex = 0;\n\t\tconst result: number[] = [];\n\t\tlet resultLen = 0;\n\t\tlet lastEndOffset = 0;\n\n\t\tconst emitToken = (endOffset: number, metadata: number) => {\n\t\t\tif (endOffset === lastEndOffset) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlastEndOffset = endOffset;\n\t\t\tresult[resultLen++] = endOffset;\n\t\t\tresult[resultLen++] = metadata;\n\t\t};\n\n\t\tfor (let bIndex = 0; bIndex < bLen; bIndex++) {\n\t\t\tconst bStartCharacter = bTokens.getStartCharacter(bIndex);\n\t\t\tconst bEndCharacter = bTokens.getEndCharacter(bIndex);\n\t\t\tconst bMetadata = bTokens.getMetadata(bIndex);\n\n\t\t\tconst bMask = (\n\t\t\t\t((bMetadata & MetadataConsts.SEMANTIC_USE_ITALIC) ? MetadataConsts.ITALIC_MASK : 0)\n\t\t\t\t| ((bMetadata & MetadataConsts.SEMANTIC_USE_BOLD) ? MetadataConsts.BOLD_MASK : 0)\n\t\t\t\t| ((bMetadata & MetadataConsts.SEMANTIC_USE_UNDERLINE) ? MetadataConsts.UNDERLINE_MASK : 0)\n\t\t\t\t| ((bMetadata & MetadataConsts.SEMANTIC_USE_STRIKETHROUGH) ? MetadataConsts.STRIKETHROUGH_MASK : 0)\n\t\t\t\t| ((bMetadata & MetadataConsts.SEMANTIC_USE_FOREGROUND) ? MetadataConsts.FOREGROUND_MASK : 0)\n\t\t\t\t| ((bMetadata & MetadataConsts.SEMANTIC_USE_BACKGROUND) ? MetadataConsts.BACKGROUND_MASK : 0)\n\t\t\t) >>> 0;\n\t\t\tconst aMask = (~bMask) >>> 0;\n\n\t\t\t// push any token from `a` that is before `b`\n\t\t\twhile (aIndex < aLen && aTokens.getEndOffset(aIndex) <= bStartCharacter) {\n\t\t\t\temitToken(aTokens.getEndOffset(aIndex), aTokens.getMetadata(aIndex));\n\t\t\t\taIndex++;\n\t\t\t}\n\n\t\t\t// push the token from `a` if it intersects the token from `b`\n\t\t\tif (aIndex < aLen && aTokens.getStartOffset(aIndex) < bStartCharacter) {\n\t\t\t\temitToken(bStartCharacter, aTokens.getMetadata(aIndex));\n\t\t\t}\n\n\t\t\t// skip any tokens from `a` that are contained inside `b`\n\t\t\twhile (aIndex < aLen && aTokens.getEndOffset(aIndex) < bEndCharacter) {\n\t\t\t\temitToken(aTokens.getEndOffset(aIndex), (aTokens.getMetadata(aIndex) & aMask) | (bMetadata & bMask));\n\t\t\t\taIndex++;\n\t\t\t}\n\n\t\t\tif (aIndex < aLen) {\n\t\t\t\temitToken(bEndCharacter, (aTokens.getMetadata(aIndex) & aMask) | (bMetadata & bMask));\n\t\t\t\tif (aTokens.getEndOffset(aIndex) === bEndCharacter) {\n\t\t\t\t\t// `a` ends exactly at the same spot as `b`!\n\t\t\t\t\taIndex++;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst aMergeIndex = Math.min(Math.max(0, aIndex - 1), aLen - 1);\n\n\t\t\t\t// push the token from `b`\n\t\t\t\temitToken(bEndCharacter, (aTokens.getMetadata(aMergeIndex) & aMask) | (bMetadata & bMask));\n\t\t\t}\n\t\t}\n\n\t\t// push the remaining tokens from `a`\n\t\twhile (aIndex < aLen) {\n\t\t\temitToken(aTokens.getEndOffset(aIndex), aTokens.getMetadata(aIndex));\n\t\t\taIndex++;\n\t\t}\n\n\t\treturn new LineTokens(new Uint32Array(result), aTokens.getLineContent(), this._languageIdCodec);\n\t}\n\n\tprivate static _findFirstPieceWithLine(pieces: SparseMultilineTokens[], lineNumber: number): number {\n\t\tlet low = 0;\n\t\tlet high = pieces.length - 1;\n\n\t\twhile (low < high) {\n\t\t\tlet mid = low + Math.floor((high - low) / 2);\n\n\t\t\tif (pieces[mid].endLineNumber < lineNumber) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else if (pieces[mid].startLineNumber > lineNumber) {\n\t\t\t\thigh = mid - 1;\n\t\t\t} else {\n\t\t\t\twhile (mid > low && pieces[mid - 1].startLineNumber <= lineNumber && lineNumber <= pieces[mid - 1].endLineNumber) {\n\t\t\t\t\tmid--;\n\t\t\t\t}\n\t\t\t\treturn mid;\n\t\t\t}\n\t\t}\n\n\t\treturn low;\n\t}\n\n\tpublic acceptEdit(range: IRange, eolCount: number, firstLineLength: number, lastLineLength: number, firstCharCode: number): void {\n\t\tfor (const piece of this._pieces) {\n\t\t\tpiece.acceptEdit(range, eolCount, firstLineLength, lastLineLength, firstCharCode);\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as strings from 'vs/base/common/strings';\nimport { Constants } from 'vs/base/common/uint';\nimport { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewModel/viewModel';\nimport { LinePartMetadata } from 'vs/editor/common/viewLayout/viewLineRenderer';\n\nexport class LineDecoration {\n\t_lineDecorationBrand: void = undefined;\n\n\tconstructor(\n\t\tpublic readonly startColumn: number,\n\t\tpublic readonly endColumn: number,\n\t\tpublic readonly className: string,\n\t\tpublic readonly type: InlineDecorationType\n\t) {\n\t}\n\n\tprivate static _equals(a: LineDecoration, b: LineDecoration): boolean {\n\t\treturn (\n\t\t\ta.startColumn === b.startColumn\n\t\t\t&& a.endColumn === b.endColumn\n\t\t\t&& a.className === b.className\n\t\t\t&& a.type === b.type\n\t\t);\n\t}\n\n\tpublic static equalsArr(a: LineDecoration[], b: LineDecoration[]): boolean {\n\t\tconst aLen = a.length;\n\t\tconst bLen = b.length;\n\t\tif (aLen !== bLen) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let i = 0; i < aLen; i++) {\n\t\t\tif (!LineDecoration._equals(a[i], b[i])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic static extractWrapped(arr: LineDecoration[], startOffset: number, endOffset: number): LineDecoration[] {\n\t\tif (arr.length === 0) {\n\t\t\treturn arr;\n\t\t}\n\t\tconst startColumn = startOffset + 1;\n\t\tconst endColumn = endOffset + 1;\n\t\tconst lineLength = endOffset - startOffset;\n\t\tconst r = [];\n\t\tlet rLength = 0;\n\t\tfor (const dec of arr) {\n\t\t\tif (dec.endColumn <= startColumn || dec.startColumn >= endColumn) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tr[rLength++] = new LineDecoration(Math.max(1, dec.startColumn - startColumn + 1), Math.min(lineLength + 1, dec.endColumn - startColumn + 1), dec.className, dec.type);\n\t\t}\n\t\treturn r;\n\t}\n\n\tpublic static filter(lineDecorations: InlineDecoration[], lineNumber: number, minLineColumn: number, maxLineColumn: number): LineDecoration[] {\n\t\tif (lineDecorations.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst result: LineDecoration[] = [];\n\t\tlet resultLen = 0;\n\n\t\tfor (let i = 0, len = lineDecorations.length; i < len; i++) {\n\t\t\tconst d = lineDecorations[i];\n\t\t\tconst range = d.range;\n\n\t\t\tif (range.endLineNumber < lineNumber || range.startLineNumber > lineNumber) {\n\t\t\t\t// Ignore decorations that sit outside this line\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (range.isEmpty() && (d.type === InlineDecorationType.Regular || d.type === InlineDecorationType.RegularAffectingLetterSpacing)) {\n\t\t\t\t// Ignore empty range decorations\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst startColumn = (range.startLineNumber === lineNumber ? range.startColumn : minLineColumn);\n\t\t\tconst endColumn = (range.endLineNumber === lineNumber ? range.endColumn : maxLineColumn);\n\n\t\t\tresult[resultLen++] = new LineDecoration(startColumn, endColumn, d.inlineClassName, d.type);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate static _typeCompare(a: InlineDecorationType, b: InlineDecorationType): number {\n\t\tconst ORDER = [2, 0, 1, 3];\n\t\treturn ORDER[a] - ORDER[b];\n\t}\n\n\tpublic static compare(a: LineDecoration, b: LineDecoration): number {\n\t\tif (a.startColumn !== b.startColumn) {\n\t\t\treturn a.startColumn - b.startColumn;\n\t\t}\n\n\t\tif (a.endColumn !== b.endColumn) {\n\t\t\treturn a.endColumn - b.endColumn;\n\t\t}\n\n\t\tconst typeCmp = LineDecoration._typeCompare(a.type, b.type);\n\t\tif (typeCmp !== 0) {\n\t\t\treturn typeCmp;\n\t\t}\n\n\t\tif (a.className !== b.className) {\n\t\t\treturn a.className < b.className ? -1 : 1;\n\t\t}\n\n\t\treturn 0;\n\t}\n}\n\nexport class DecorationSegment {\n\tstartOffset: number;\n\tendOffset: number;\n\tclassName: string;\n\tmetadata: number;\n\n\tconstructor(startOffset: number, endOffset: number, className: string, metadata: number) {\n\t\tthis.startOffset = startOffset;\n\t\tthis.endOffset = endOffset;\n\t\tthis.className = className;\n\t\tthis.metadata = metadata;\n\t}\n}\n\nclass Stack {\n\tpublic count: number;\n\tprivate readonly stopOffsets: number[];\n\tprivate readonly classNames: string[];\n\tprivate readonly metadata: number[];\n\n\tconstructor() {\n\t\tthis.stopOffsets = [];\n\t\tthis.classNames = [];\n\t\tthis.metadata = [];\n\t\tthis.count = 0;\n\t}\n\n\tprivate static _metadata(metadata: number[]): number {\n\t\tlet result = 0;\n\t\tfor (let i = 0, len = metadata.length; i < len; i++) {\n\t\t\tresult |= metadata[i];\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic consumeLowerThan(maxStopOffset: number, nextStartOffset: number, result: DecorationSegment[]): number {\n\n\t\twhile (this.count > 0 && this.stopOffsets[0] < maxStopOffset) {\n\t\t\tlet i = 0;\n\n\t\t\t// Take all equal stopping offsets\n\t\t\twhile (i + 1 < this.count && this.stopOffsets[i] === this.stopOffsets[i + 1]) {\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\t// Basically we are consuming the first i + 1 elements of the stack\n\t\t\tresult.push(new DecorationSegment(nextStartOffset, this.stopOffsets[i], this.classNames.join(' '), Stack._metadata(this.metadata)));\n\t\t\tnextStartOffset = this.stopOffsets[i] + 1;\n\n\t\t\t// Consume them\n\t\t\tthis.stopOffsets.splice(0, i + 1);\n\t\t\tthis.classNames.splice(0, i + 1);\n\t\t\tthis.metadata.splice(0, i + 1);\n\t\t\tthis.count -= (i + 1);\n\t\t}\n\n\t\tif (this.count > 0 && nextStartOffset < maxStopOffset) {\n\t\t\tresult.push(new DecorationSegment(nextStartOffset, maxStopOffset - 1, this.classNames.join(' '), Stack._metadata(this.metadata)));\n\t\t\tnextStartOffset = maxStopOffset;\n\t\t}\n\n\t\treturn nextStartOffset;\n\t}\n\n\tpublic insert(stopOffset: number, className: string, metadata: number): void {\n\t\tif (this.count === 0 || this.stopOffsets[this.count - 1] <= stopOffset) {\n\t\t\t// Insert at the end\n\t\t\tthis.stopOffsets.push(stopOffset);\n\t\t\tthis.classNames.push(className);\n\t\t\tthis.metadata.push(metadata);\n\t\t} else {\n\t\t\t// Find the insertion position for `stopOffset`\n\t\t\tfor (let i = 0; i < this.count; i++) {\n\t\t\t\tif (this.stopOffsets[i] >= stopOffset) {\n\t\t\t\t\tthis.stopOffsets.splice(i, 0, stopOffset);\n\t\t\t\t\tthis.classNames.splice(i, 0, className);\n\t\t\t\t\tthis.metadata.splice(i, 0, metadata);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.count++;\n\t\treturn;\n\t}\n}\n\nexport class LineDecorationsNormalizer {\n\t/**\n\t * Normalize line decorations. Overlapping decorations will generate multiple segments\n\t */\n\tpublic static normalize(lineContent: string, lineDecorations: LineDecoration[]): DecorationSegment[] {\n\t\tif (lineDecorations.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst result: DecorationSegment[] = [];\n\n\t\tconst stack = new Stack();\n\t\tlet nextStartOffset = 0;\n\n\t\tfor (let i = 0, len = lineDecorations.length; i < len; i++) {\n\t\t\tconst d = lineDecorations[i];\n\t\t\tlet startColumn = d.startColumn;\n\t\t\tlet endColumn = d.endColumn;\n\t\t\tconst className = d.className;\n\t\t\tconst metadata = (\n\t\t\t\td.type === InlineDecorationType.Before\n\t\t\t\t\t? LinePartMetadata.PSEUDO_BEFORE\n\t\t\t\t\t: d.type === InlineDecorationType.After\n\t\t\t\t\t\t? LinePartMetadata.PSEUDO_AFTER\n\t\t\t\t\t\t: 0\n\t\t\t);\n\n\t\t\t// If the position would end up in the middle of a high-low surrogate pair, we move it to before the pair\n\t\t\tif (startColumn > 1) {\n\t\t\t\tconst charCodeBefore = lineContent.charCodeAt(startColumn - 2);\n\t\t\t\tif (strings.isHighSurrogate(charCodeBefore)) {\n\t\t\t\t\tstartColumn--;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (endColumn > 1) {\n\t\t\t\tconst charCodeBefore = lineContent.charCodeAt(endColumn - 2);\n\t\t\t\tif (strings.isHighSurrogate(charCodeBefore)) {\n\t\t\t\t\tendColumn--;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst currentStartOffset = startColumn - 1;\n\t\t\tconst currentEndOffset = endColumn - 2;\n\n\t\t\tnextStartOffset = stack.consumeLowerThan(currentStartOffset, nextStartOffset, result);\n\n\t\t\tif (stack.count === 0) {\n\t\t\t\tnextStartOffset = currentStartOffset;\n\t\t\t}\n\t\t\tstack.insert(currentEndOffset, className, metadata);\n\t\t}\n\n\t\tstack.consumeLowerThan(Constants.MAX_SAFE_SMALL_INTEGER, nextStartOffset, result);\n\n\t\treturn result;\n\t}\n\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';\nimport { IViewWhitespaceViewportData } from 'vs/editor/common/viewModel/viewModel';\nimport * as strings from 'vs/base/common/strings';\n\nexport interface IEditorWhitespace {\n\treadonly id: string;\n\treadonly afterLineNumber: number;\n\treadonly height: number;\n}\n\n/**\n * An accessor that allows for whtiespace to be added, removed or changed in bulk.\n */\nexport interface IWhitespaceChangeAccessor {\n\tinsertWhitespace(afterLineNumber: number, ordinal: number, heightInPx: number, minWidth: number): string;\n\tchangeOneWhitespace(id: string, newAfterLineNumber: number, newHeight: number): void;\n\tremoveWhitespace(id: string): void;\n}\n\ninterface IPendingChange { id: string; newAfterLineNumber: number; newHeight: number; }\ninterface IPendingRemove { id: string; }\n\nclass PendingChanges {\n\tprivate _hasPending: boolean;\n\tprivate _inserts: EditorWhitespace[];\n\tprivate _changes: IPendingChange[];\n\tprivate _removes: IPendingRemove[];\n\n\tconstructor() {\n\t\tthis._hasPending = false;\n\t\tthis._inserts = [];\n\t\tthis._changes = [];\n\t\tthis._removes = [];\n\t}\n\n\tpublic insert(x: EditorWhitespace): void {\n\t\tthis._hasPending = true;\n\t\tthis._inserts.push(x);\n\t}\n\n\tpublic change(x: IPendingChange): void {\n\t\tthis._hasPending = true;\n\t\tthis._changes.push(x);\n\t}\n\n\tpublic remove(x: IPendingRemove): void {\n\t\tthis._hasPending = true;\n\t\tthis._removes.push(x);\n\t}\n\n\tpublic mustCommit(): boolean {\n\t\treturn this._hasPending;\n\t}\n\n\tpublic commit(linesLayout: LinesLayout): void {\n\t\tif (!this._hasPending) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst inserts = this._inserts;\n\t\tconst changes = this._changes;\n\t\tconst removes = this._removes;\n\n\t\tthis._hasPending = false;\n\t\tthis._inserts = [];\n\t\tthis._changes = [];\n\t\tthis._removes = [];\n\n\t\tlinesLayout._commitPendingChanges(inserts, changes, removes);\n\t}\n}\n\nexport class EditorWhitespace implements IEditorWhitespace {\n\tpublic id: string;\n\tpublic afterLineNumber: number;\n\tpublic ordinal: number;\n\tpublic height: number;\n\tpublic minWidth: number;\n\tpublic prefixSum: number;\n\n\tconstructor(id: string, afterLineNumber: number, ordinal: number, height: number, minWidth: number) {\n\t\tthis.id = id;\n\t\tthis.afterLineNumber = afterLineNumber;\n\t\tthis.ordinal = ordinal;\n\t\tthis.height = height;\n\t\tthis.minWidth = minWidth;\n\t\tthis.prefixSum = 0;\n\t}\n}\n\n/**\n * Layouting of objects that take vertical space (by having a height) and push down other objects.\n *\n * These objects are basically either text (lines) or spaces between those lines (whitespaces).\n * This provides commodity operations for working with lines that contain whitespace that pushes lines lower (vertically).\n */\nexport class LinesLayout {\n\n\tprivate static INSTANCE_COUNT = 0;\n\n\tprivate readonly _instanceId: string;\n\tprivate readonly _pendingChanges: PendingChanges;\n\tprivate _lastWhitespaceId: number;\n\tprivate _arr: EditorWhitespace[];\n\tprivate _prefixSumValidIndex: number;\n\tprivate _minWidth: number;\n\tprivate _lineCount: number;\n\tprivate _lineHeight: number;\n\tprivate _paddingTop: number;\n\tprivate _paddingBottom: number;\n\n\tconstructor(lineCount: number, lineHeight: number, paddingTop: number, paddingBottom: number) {\n\t\tthis._instanceId = strings.singleLetterHash(++LinesLayout.INSTANCE_COUNT);\n\t\tthis._pendingChanges = new PendingChanges();\n\t\tthis._lastWhitespaceId = 0;\n\t\tthis._arr = [];\n\t\tthis._prefixSumValidIndex = -1;\n\t\tthis._minWidth = -1; /* marker for not being computed */\n\t\tthis._lineCount = lineCount;\n\t\tthis._lineHeight = lineHeight;\n\t\tthis._paddingTop = paddingTop;\n\t\tthis._paddingBottom = paddingBottom;\n\t}\n\n\t/**\n\t * Find the insertion index for a new value inside a sorted array of values.\n\t * If the value is already present in the sorted array, the insertion index will be after the already existing value.\n\t */\n\tpublic static findInsertionIndex(arr: EditorWhitespace[], afterLineNumber: number, ordinal: number): number {\n\t\tlet low = 0;\n\t\tlet high = arr.length;\n\n\t\twhile (low < high) {\n\t\t\tconst mid = ((low + high) >>> 1);\n\n\t\t\tif (afterLineNumber === arr[mid].afterLineNumber) {\n\t\t\t\tif (ordinal < arr[mid].ordinal) {\n\t\t\t\t\thigh = mid;\n\t\t\t\t} else {\n\t\t\t\t\tlow = mid + 1;\n\t\t\t\t}\n\t\t\t} else if (afterLineNumber < arr[mid].afterLineNumber) {\n\t\t\t\thigh = mid;\n\t\t\t} else {\n\t\t\t\tlow = mid + 1;\n\t\t\t}\n\t\t}\n\n\t\treturn low;\n\t}\n\n\t/**\n\t * Change the height of a line in pixels.\n\t */\n\tpublic setLineHeight(lineHeight: number): void {\n\t\tthis._checkPendingChanges();\n\t\tthis._lineHeight = lineHeight;\n\t}\n\n\t/**\n\t * Changes the padding used to calculate vertical offsets.\n\t */\n\tpublic setPadding(paddingTop: number, paddingBottom: number): void {\n\t\tthis._paddingTop = paddingTop;\n\t\tthis._paddingBottom = paddingBottom;\n\t}\n\n\t/**\n\t * Set the number of lines.\n\t *\n\t * @param lineCount New number of lines.\n\t */\n\tpublic onFlushed(lineCount: number): void {\n\t\tthis._checkPendingChanges();\n\t\tthis._lineCount = lineCount;\n\t}\n\n\tpublic changeWhitespace(callback: (accessor: IWhitespaceChangeAccessor) => void): boolean {\n\t\tlet hadAChange = false;\n\t\ttry {\n\t\t\tconst accessor: IWhitespaceChangeAccessor = {\n\t\t\t\tinsertWhitespace: (afterLineNumber: number, ordinal: number, heightInPx: number, minWidth: number): string => {\n\t\t\t\t\thadAChange = true;\n\t\t\t\t\tafterLineNumber = afterLineNumber | 0;\n\t\t\t\t\tordinal = ordinal | 0;\n\t\t\t\t\theightInPx = heightInPx | 0;\n\t\t\t\t\tminWidth = minWidth | 0;\n\t\t\t\t\tconst id = this._instanceId + (++this._lastWhitespaceId);\n\t\t\t\t\tthis._pendingChanges.insert(new EditorWhitespace(id, afterLineNumber, ordinal, heightInPx, minWidth));\n\t\t\t\t\treturn id;\n\t\t\t\t},\n\t\t\t\tchangeOneWhitespace: (id: string, newAfterLineNumber: number, newHeight: number): void => {\n\t\t\t\t\thadAChange = true;\n\t\t\t\t\tnewAfterLineNumber = newAfterLineNumber | 0;\n\t\t\t\t\tnewHeight = newHeight | 0;\n\t\t\t\t\tthis._pendingChanges.change({ id, newAfterLineNumber, newHeight });\n\t\t\t\t},\n\t\t\t\tremoveWhitespace: (id: string): void => {\n\t\t\t\t\thadAChange = true;\n\t\t\t\t\tthis._pendingChanges.remove({ id });\n\t\t\t\t}\n\t\t\t};\n\t\t\tcallback(accessor);\n\t\t} finally {\n\t\t\tthis._pendingChanges.commit(this);\n\t\t}\n\t\treturn hadAChange;\n\t}\n\n\tpublic _commitPendingChanges(inserts: EditorWhitespace[], changes: IPendingChange[], removes: IPendingRemove[]): void {\n\t\tif (inserts.length > 0 || removes.length > 0) {\n\t\t\tthis._minWidth = -1; /* marker for not being computed */\n\t\t}\n\n\t\tif (inserts.length + changes.length + removes.length <= 1) {\n\t\t\t// when only one thing happened, handle it \"delicately\"\n\t\t\tfor (const insert of inserts) {\n\t\t\t\tthis._insertWhitespace(insert);\n\t\t\t}\n\t\t\tfor (const change of changes) {\n\t\t\t\tthis._changeOneWhitespace(change.id, change.newAfterLineNumber, change.newHeight);\n\t\t\t}\n\t\t\tfor (const remove of removes) {\n\t\t\t\tconst index = this._findWhitespaceIndex(remove.id);\n\t\t\t\tif (index === -1) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthis._removeWhitespace(index);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// simply rebuild the entire datastructure\n\n\t\tconst toRemove = new Set();\n\t\tfor (const remove of removes) {\n\t\t\ttoRemove.add(remove.id);\n\t\t}\n\n\t\tconst toChange = new Map();\n\t\tfor (const change of changes) {\n\t\t\ttoChange.set(change.id, change);\n\t\t}\n\n\t\tconst applyRemoveAndChange = (whitespaces: EditorWhitespace[]): EditorWhitespace[] => {\n\t\t\tconst result: EditorWhitespace[] = [];\n\t\t\tfor (const whitespace of whitespaces) {\n\t\t\t\tif (toRemove.has(whitespace.id)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (toChange.has(whitespace.id)) {\n\t\t\t\t\tconst change = toChange.get(whitespace.id)!;\n\t\t\t\t\twhitespace.afterLineNumber = change.newAfterLineNumber;\n\t\t\t\t\twhitespace.height = change.newHeight;\n\t\t\t\t}\n\t\t\t\tresult.push(whitespace);\n\t\t\t}\n\t\t\treturn result;\n\t\t};\n\n\t\tconst result = applyRemoveAndChange(this._arr).concat(applyRemoveAndChange(inserts));\n\t\tresult.sort((a, b) => {\n\t\t\tif (a.afterLineNumber === b.afterLineNumber) {\n\t\t\t\treturn a.ordinal - b.ordinal;\n\t\t\t}\n\t\t\treturn a.afterLineNumber - b.afterLineNumber;\n\t\t});\n\n\t\tthis._arr = result;\n\t\tthis._prefixSumValidIndex = -1;\n\t}\n\n\tprivate _checkPendingChanges(): void {\n\t\tif (this._pendingChanges.mustCommit()) {\n\t\t\tthis._pendingChanges.commit(this);\n\t\t}\n\t}\n\n\tprivate _insertWhitespace(whitespace: EditorWhitespace): void {\n\t\tconst insertIndex = LinesLayout.findInsertionIndex(this._arr, whitespace.afterLineNumber, whitespace.ordinal);\n\t\tthis._arr.splice(insertIndex, 0, whitespace);\n\t\tthis._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, insertIndex - 1);\n\t}\n\n\tprivate _findWhitespaceIndex(id: string): number {\n\t\tconst arr = this._arr;\n\t\tfor (let i = 0, len = arr.length; i < len; i++) {\n\t\t\tif (arr[i].id === id) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t}\n\n\tprivate _changeOneWhitespace(id: string, newAfterLineNumber: number, newHeight: number): void {\n\t\tconst index = this._findWhitespaceIndex(id);\n\t\tif (index === -1) {\n\t\t\treturn;\n\t\t}\n\t\tif (this._arr[index].height !== newHeight) {\n\t\t\tthis._arr[index].height = newHeight;\n\t\t\tthis._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, index - 1);\n\t\t}\n\t\tif (this._arr[index].afterLineNumber !== newAfterLineNumber) {\n\t\t\t// `afterLineNumber` changed for this whitespace\n\n\t\t\t// Record old whitespace\n\t\t\tconst whitespace = this._arr[index];\n\n\t\t\t// Since changing `afterLineNumber` can trigger a reordering, we're gonna remove this whitespace\n\t\t\tthis._removeWhitespace(index);\n\n\t\t\twhitespace.afterLineNumber = newAfterLineNumber;\n\n\t\t\t// And add it again\n\t\t\tthis._insertWhitespace(whitespace);\n\t\t}\n\t}\n\n\tprivate _removeWhitespace(removeIndex: number): void {\n\t\tthis._arr.splice(removeIndex, 1);\n\t\tthis._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, removeIndex - 1);\n\t}\n\n\t/**\n\t * Notify the layouter that lines have been deleted (a continuous zone of lines).\n\t *\n\t * @param fromLineNumber The line number at which the deletion started, inclusive\n\t * @param toLineNumber The line number at which the deletion ended, inclusive\n\t */\n\tpublic onLinesDeleted(fromLineNumber: number, toLineNumber: number): void {\n\t\tthis._checkPendingChanges();\n\t\tfromLineNumber = fromLineNumber | 0;\n\t\ttoLineNumber = toLineNumber | 0;\n\n\t\tthis._lineCount -= (toLineNumber - fromLineNumber + 1);\n\t\tfor (let i = 0, len = this._arr.length; i < len; i++) {\n\t\t\tconst afterLineNumber = this._arr[i].afterLineNumber;\n\n\t\t\tif (fromLineNumber <= afterLineNumber && afterLineNumber <= toLineNumber) {\n\t\t\t\t// The line this whitespace was after has been deleted\n\t\t\t\t// => move whitespace to before first deleted line\n\t\t\t\tthis._arr[i].afterLineNumber = fromLineNumber - 1;\n\t\t\t} else if (afterLineNumber > toLineNumber) {\n\t\t\t\t// The line this whitespace was after has been moved up\n\t\t\t\t// => move whitespace up\n\t\t\t\tthis._arr[i].afterLineNumber -= (toLineNumber - fromLineNumber + 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Notify the layouter that lines have been inserted (a continuous zone of lines).\n\t *\n\t * @param fromLineNumber The line number at which the insertion started, inclusive\n\t * @param toLineNumber The line number at which the insertion ended, inclusive.\n\t */\n\tpublic onLinesInserted(fromLineNumber: number, toLineNumber: number): void {\n\t\tthis._checkPendingChanges();\n\t\tfromLineNumber = fromLineNumber | 0;\n\t\ttoLineNumber = toLineNumber | 0;\n\n\t\tthis._lineCount += (toLineNumber - fromLineNumber + 1);\n\t\tfor (let i = 0, len = this._arr.length; i < len; i++) {\n\t\t\tconst afterLineNumber = this._arr[i].afterLineNumber;\n\n\t\t\tif (fromLineNumber <= afterLineNumber) {\n\t\t\t\tthis._arr[i].afterLineNumber += (toLineNumber - fromLineNumber + 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get the sum of all the whitespaces.\n\t */\n\tpublic getWhitespacesTotalHeight(): number {\n\t\tthis._checkPendingChanges();\n\t\tif (this._arr.length === 0) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn this.getWhitespacesAccumulatedHeight(this._arr.length - 1);\n\t}\n\n\t/**\n\t * Return the sum of the heights of the whitespaces at [0..index].\n\t * This includes the whitespace at `index`.\n\t *\n\t * @param index The index of the whitespace.\n\t * @return The sum of the heights of all whitespaces before the one at `index`, including the one at `index`.\n\t */\n\tpublic getWhitespacesAccumulatedHeight(index: number): number {\n\t\tthis._checkPendingChanges();\n\t\tindex = index | 0;\n\n\t\tlet startIndex = Math.max(0, this._prefixSumValidIndex + 1);\n\t\tif (startIndex === 0) {\n\t\t\tthis._arr[0].prefixSum = this._arr[0].height;\n\t\t\tstartIndex++;\n\t\t}\n\n\t\tfor (let i = startIndex; i <= index; i++) {\n\t\t\tthis._arr[i].prefixSum = this._arr[i - 1].prefixSum + this._arr[i].height;\n\t\t}\n\t\tthis._prefixSumValidIndex = Math.max(this._prefixSumValidIndex, index);\n\t\treturn this._arr[index].prefixSum;\n\t}\n\n\t/**\n\t * Get the sum of heights for all objects.\n\t *\n\t * @return The sum of heights for all objects.\n\t */\n\tpublic getLinesTotalHeight(): number {\n\t\tthis._checkPendingChanges();\n\t\tconst linesHeight = this._lineHeight * this._lineCount;\n\t\tconst whitespacesHeight = this.getWhitespacesTotalHeight();\n\n\t\treturn linesHeight + whitespacesHeight + this._paddingTop + this._paddingBottom;\n\t}\n\n\t/**\n\t * Returns the accumulated height of whitespaces before the given line number.\n\t *\n\t * @param lineNumber The line number\n\t */\n\tpublic getWhitespaceAccumulatedHeightBeforeLineNumber(lineNumber: number): number {\n\t\tthis._checkPendingChanges();\n\t\tlineNumber = lineNumber | 0;\n\n\t\tconst lastWhitespaceBeforeLineNumber = this._findLastWhitespaceBeforeLineNumber(lineNumber);\n\n\t\tif (lastWhitespaceBeforeLineNumber === -1) {\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn this.getWhitespacesAccumulatedHeight(lastWhitespaceBeforeLineNumber);\n\t}\n\n\tprivate _findLastWhitespaceBeforeLineNumber(lineNumber: number): number {\n\t\tlineNumber = lineNumber | 0;\n\n\t\t// Find the whitespace before line number\n\t\tconst arr = this._arr;\n\t\tlet low = 0;\n\t\tlet high = arr.length - 1;\n\n\t\twhile (low <= high) {\n\t\t\tconst delta = (high - low) | 0;\n\t\t\tconst halfDelta = (delta / 2) | 0;\n\t\t\tconst mid = (low + halfDelta) | 0;\n\n\t\t\tif (arr[mid].afterLineNumber < lineNumber) {\n\t\t\t\tif (mid + 1 >= arr.length || arr[mid + 1].afterLineNumber >= lineNumber) {\n\t\t\t\t\treturn mid;\n\t\t\t\t} else {\n\t\t\t\t\tlow = (mid + 1) | 0;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\thigh = (mid - 1) | 0;\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\tprivate _findFirstWhitespaceAfterLineNumber(lineNumber: number): number {\n\t\tlineNumber = lineNumber | 0;\n\n\t\tconst lastWhitespaceBeforeLineNumber = this._findLastWhitespaceBeforeLineNumber(lineNumber);\n\t\tconst firstWhitespaceAfterLineNumber = lastWhitespaceBeforeLineNumber + 1;\n\n\t\tif (firstWhitespaceAfterLineNumber < this._arr.length) {\n\t\t\treturn firstWhitespaceAfterLineNumber;\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t/**\n\t * Find the index of the first whitespace which has `afterLineNumber` >= `lineNumber`.\n\t * @return The index of the first whitespace with `afterLineNumber` >= `lineNumber` or -1 if no whitespace is found.\n\t */\n\tpublic getFirstWhitespaceIndexAfterLineNumber(lineNumber: number): number {\n\t\tthis._checkPendingChanges();\n\t\tlineNumber = lineNumber | 0;\n\n\t\treturn this._findFirstWhitespaceAfterLineNumber(lineNumber);\n\t}\n\n\t/**\n\t * Get the vertical offset (the sum of heights for all objects above) a certain line number.\n\t *\n\t * @param lineNumber The line number\n\t * @return The sum of heights for all objects above `lineNumber`.\n\t */\n\tpublic getVerticalOffsetForLineNumber(lineNumber: number): number {\n\t\tthis._checkPendingChanges();\n\t\tlineNumber = lineNumber | 0;\n\n\t\tlet previousLinesHeight: number;\n\t\tif (lineNumber > 1) {\n\t\t\tpreviousLinesHeight = this._lineHeight * (lineNumber - 1);\n\t\t} else {\n\t\t\tpreviousLinesHeight = 0;\n\t\t}\n\n\t\tconst previousWhitespacesHeight = this.getWhitespaceAccumulatedHeightBeforeLineNumber(lineNumber);\n\n\t\treturn previousLinesHeight + previousWhitespacesHeight + this._paddingTop;\n\t}\n\n\t/**\n\t * The maximum min width for all whitespaces.\n\t */\n\tpublic getWhitespaceMinWidth(): number {\n\t\tthis._checkPendingChanges();\n\t\tif (this._minWidth === -1) {\n\t\t\tlet minWidth = 0;\n\t\t\tfor (let i = 0, len = this._arr.length; i < len; i++) {\n\t\t\t\tminWidth = Math.max(minWidth, this._arr[i].minWidth);\n\t\t\t}\n\t\t\tthis._minWidth = minWidth;\n\t\t}\n\t\treturn this._minWidth;\n\t}\n\n\t/**\n\t * Check if `verticalOffset` is below all lines.\n\t */\n\tpublic isAfterLines(verticalOffset: number): boolean {\n\t\tthis._checkPendingChanges();\n\t\tconst totalHeight = this.getLinesTotalHeight();\n\t\treturn verticalOffset > totalHeight;\n\t}\n\n\tpublic isInTopPadding(verticalOffset: number): boolean {\n\t\tif (this._paddingTop === 0) {\n\t\t\treturn false;\n\t\t}\n\t\tthis._checkPendingChanges();\n\t\treturn (verticalOffset < this._paddingTop);\n\t}\n\n\tpublic isInBottomPadding(verticalOffset: number): boolean {\n\t\tif (this._paddingBottom === 0) {\n\t\t\treturn false;\n\t\t}\n\t\tthis._checkPendingChanges();\n\t\tconst totalHeight = this.getLinesTotalHeight();\n\t\treturn (verticalOffset >= totalHeight - this._paddingBottom);\n\t}\n\n\t/**\n\t * Find the first line number that is at or after vertical offset `verticalOffset`.\n\t * i.e. if getVerticalOffsetForLine(line) is x and getVerticalOffsetForLine(line + 1) is y, then\n\t * getLineNumberAtOrAfterVerticalOffset(i) = line, x <= i < y.\n\t *\n\t * @param verticalOffset The vertical offset to search at.\n\t * @return The line number at or after vertical offset `verticalOffset`.\n\t */\n\tpublic getLineNumberAtOrAfterVerticalOffset(verticalOffset: number): number {\n\t\tthis._checkPendingChanges();\n\t\tverticalOffset = verticalOffset | 0;\n\n\t\tif (verticalOffset < 0) {\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst linesCount = this._lineCount | 0;\n\t\tconst lineHeight = this._lineHeight;\n\t\tlet minLineNumber = 1;\n\t\tlet maxLineNumber = linesCount;\n\n\t\twhile (minLineNumber < maxLineNumber) {\n\t\t\tconst midLineNumber = ((minLineNumber + maxLineNumber) / 2) | 0;\n\n\t\t\tconst midLineNumberVerticalOffset = this.getVerticalOffsetForLineNumber(midLineNumber) | 0;\n\n\t\t\tif (verticalOffset >= midLineNumberVerticalOffset + lineHeight) {\n\t\t\t\t// vertical offset is after mid line number\n\t\t\t\tminLineNumber = midLineNumber + 1;\n\t\t\t} else if (verticalOffset >= midLineNumberVerticalOffset) {\n\t\t\t\t// Hit\n\t\t\t\treturn midLineNumber;\n\t\t\t} else {\n\t\t\t\t// vertical offset is before mid line number, but mid line number could still be what we're searching for\n\t\t\t\tmaxLineNumber = midLineNumber;\n\t\t\t}\n\t\t}\n\n\t\tif (minLineNumber > linesCount) {\n\t\t\treturn linesCount;\n\t\t}\n\n\t\treturn minLineNumber;\n\t}\n\n\t/**\n\t * Get all the lines and their relative vertical offsets that are positioned between `verticalOffset1` and `verticalOffset2`.\n\t *\n\t * @param verticalOffset1 The beginning of the viewport.\n\t * @param verticalOffset2 The end of the viewport.\n\t * @return A structure describing the lines positioned between `verticalOffset1` and `verticalOffset2`.\n\t */\n\tpublic getLinesViewportData(verticalOffset1: number, verticalOffset2: number): IPartialViewLinesViewportData {\n\t\tthis._checkPendingChanges();\n\t\tverticalOffset1 = verticalOffset1 | 0;\n\t\tverticalOffset2 = verticalOffset2 | 0;\n\t\tconst lineHeight = this._lineHeight;\n\n\t\t// Find first line number\n\t\t// We don't live in a perfect world, so the line number might start before or after verticalOffset1\n\t\tconst startLineNumber = this.getLineNumberAtOrAfterVerticalOffset(verticalOffset1) | 0;\n\t\tconst startLineNumberVerticalOffset = this.getVerticalOffsetForLineNumber(startLineNumber) | 0;\n\n\t\tlet endLineNumber = this._lineCount | 0;\n\n\t\t// Also keep track of what whitespace we've got\n\t\tlet whitespaceIndex = this.getFirstWhitespaceIndexAfterLineNumber(startLineNumber) | 0;\n\t\tconst whitespaceCount = this.getWhitespacesCount() | 0;\n\t\tlet currentWhitespaceHeight: number;\n\t\tlet currentWhitespaceAfterLineNumber: number;\n\n\t\tif (whitespaceIndex === -1) {\n\t\t\twhitespaceIndex = whitespaceCount;\n\t\t\tcurrentWhitespaceAfterLineNumber = endLineNumber + 1;\n\t\t\tcurrentWhitespaceHeight = 0;\n\t\t} else {\n\t\t\tcurrentWhitespaceAfterLineNumber = this.getAfterLineNumberForWhitespaceIndex(whitespaceIndex) | 0;\n\t\t\tcurrentWhitespaceHeight = this.getHeightForWhitespaceIndex(whitespaceIndex) | 0;\n\t\t}\n\n\t\tlet currentVerticalOffset = startLineNumberVerticalOffset;\n\t\tlet currentLineRelativeOffset = currentVerticalOffset;\n\n\t\t// IE (all versions) cannot handle units above about 1,533,908 px, so every 500k pixels bring numbers down\n\t\tconst STEP_SIZE = 500000;\n\t\tlet bigNumbersDelta = 0;\n\t\tif (startLineNumberVerticalOffset >= STEP_SIZE) {\n\t\t\t// Compute a delta that guarantees that lines are positioned at `lineHeight` increments\n\t\t\tbigNumbersDelta = Math.floor(startLineNumberVerticalOffset / STEP_SIZE) * STEP_SIZE;\n\t\t\tbigNumbersDelta = Math.floor(bigNumbersDelta / lineHeight) * lineHeight;\n\n\t\t\tcurrentLineRelativeOffset -= bigNumbersDelta;\n\t\t}\n\n\t\tconst linesOffsets: number[] = [];\n\n\t\tconst verticalCenter = verticalOffset1 + (verticalOffset2 - verticalOffset1) / 2;\n\t\tlet centeredLineNumber = -1;\n\n\t\t// Figure out how far the lines go\n\t\tfor (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n\n\t\t\tif (centeredLineNumber === -1) {\n\t\t\t\tconst currentLineTop = currentVerticalOffset;\n\t\t\t\tconst currentLineBottom = currentVerticalOffset + lineHeight;\n\t\t\t\tif ((currentLineTop <= verticalCenter && verticalCenter < currentLineBottom) || currentLineTop > verticalCenter) {\n\t\t\t\t\tcenteredLineNumber = lineNumber;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Count current line height in the vertical offsets\n\t\t\tcurrentVerticalOffset += lineHeight;\n\t\t\tlinesOffsets[lineNumber - startLineNumber] = currentLineRelativeOffset;\n\n\t\t\t// Next line starts immediately after this one\n\t\t\tcurrentLineRelativeOffset += lineHeight;\n\t\t\twhile (currentWhitespaceAfterLineNumber === lineNumber) {\n\t\t\t\t// Push down next line with the height of the current whitespace\n\t\t\t\tcurrentLineRelativeOffset += currentWhitespaceHeight;\n\n\t\t\t\t// Count current whitespace in the vertical offsets\n\t\t\t\tcurrentVerticalOffset += currentWhitespaceHeight;\n\t\t\t\twhitespaceIndex++;\n\n\t\t\t\tif (whitespaceIndex >= whitespaceCount) {\n\t\t\t\t\tcurrentWhitespaceAfterLineNumber = endLineNumber + 1;\n\t\t\t\t} else {\n\t\t\t\t\tcurrentWhitespaceAfterLineNumber = this.getAfterLineNumberForWhitespaceIndex(whitespaceIndex) | 0;\n\t\t\t\t\tcurrentWhitespaceHeight = this.getHeightForWhitespaceIndex(whitespaceIndex) | 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentVerticalOffset >= verticalOffset2) {\n\t\t\t\t// We have covered the entire viewport area, time to stop\n\t\t\t\tendLineNumber = lineNumber;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (centeredLineNumber === -1) {\n\t\t\tcenteredLineNumber = endLineNumber;\n\t\t}\n\n\t\tconst endLineNumberVerticalOffset = this.getVerticalOffsetForLineNumber(endLineNumber) | 0;\n\n\t\tlet completelyVisibleStartLineNumber = startLineNumber;\n\t\tlet completelyVisibleEndLineNumber = endLineNumber;\n\n\t\tif (completelyVisibleStartLineNumber < completelyVisibleEndLineNumber) {\n\t\t\tif (startLineNumberVerticalOffset < verticalOffset1) {\n\t\t\t\tcompletelyVisibleStartLineNumber++;\n\t\t\t}\n\t\t}\n\t\tif (completelyVisibleStartLineNumber < completelyVisibleEndLineNumber) {\n\t\t\tif (endLineNumberVerticalOffset + lineHeight > verticalOffset2) {\n\t\t\t\tcompletelyVisibleEndLineNumber--;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tbigNumbersDelta: bigNumbersDelta,\n\t\t\tstartLineNumber: startLineNumber,\n\t\t\tendLineNumber: endLineNumber,\n\t\t\trelativeVerticalOffset: linesOffsets,\n\t\t\tcenteredLineNumber: centeredLineNumber,\n\t\t\tcompletelyVisibleStartLineNumber: completelyVisibleStartLineNumber,\n\t\t\tcompletelyVisibleEndLineNumber: completelyVisibleEndLineNumber\n\t\t};\n\t}\n\n\tpublic getVerticalOffsetForWhitespaceIndex(whitespaceIndex: number): number {\n\t\tthis._checkPendingChanges();\n\t\twhitespaceIndex = whitespaceIndex | 0;\n\n\t\tconst afterLineNumber = this.getAfterLineNumberForWhitespaceIndex(whitespaceIndex);\n\n\t\tlet previousLinesHeight: number;\n\t\tif (afterLineNumber >= 1) {\n\t\t\tpreviousLinesHeight = this._lineHeight * afterLineNumber;\n\t\t} else {\n\t\t\tpreviousLinesHeight = 0;\n\t\t}\n\n\t\tlet previousWhitespacesHeight: number;\n\t\tif (whitespaceIndex > 0) {\n\t\t\tpreviousWhitespacesHeight = this.getWhitespacesAccumulatedHeight(whitespaceIndex - 1);\n\t\t} else {\n\t\t\tpreviousWhitespacesHeight = 0;\n\t\t}\n\t\treturn previousLinesHeight + previousWhitespacesHeight + this._paddingTop;\n\t}\n\n\tpublic getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset: number): number {\n\t\tthis._checkPendingChanges();\n\t\tverticalOffset = verticalOffset | 0;\n\n\t\tlet minWhitespaceIndex = 0;\n\t\tlet maxWhitespaceIndex = this.getWhitespacesCount() - 1;\n\n\t\tif (maxWhitespaceIndex < 0) {\n\t\t\treturn -1;\n\t\t}\n\n\t\t// Special case: nothing to be found\n\t\tconst maxWhitespaceVerticalOffset = this.getVerticalOffsetForWhitespaceIndex(maxWhitespaceIndex);\n\t\tconst maxWhitespaceHeight = this.getHeightForWhitespaceIndex(maxWhitespaceIndex);\n\t\tif (verticalOffset >= maxWhitespaceVerticalOffset + maxWhitespaceHeight) {\n\t\t\treturn -1;\n\t\t}\n\n\t\twhile (minWhitespaceIndex < maxWhitespaceIndex) {\n\t\t\tconst midWhitespaceIndex = Math.floor((minWhitespaceIndex + maxWhitespaceIndex) / 2);\n\n\t\t\tconst midWhitespaceVerticalOffset = this.getVerticalOffsetForWhitespaceIndex(midWhitespaceIndex);\n\t\t\tconst midWhitespaceHeight = this.getHeightForWhitespaceIndex(midWhitespaceIndex);\n\n\t\t\tif (verticalOffset >= midWhitespaceVerticalOffset + midWhitespaceHeight) {\n\t\t\t\t// vertical offset is after whitespace\n\t\t\t\tminWhitespaceIndex = midWhitespaceIndex + 1;\n\t\t\t} else if (verticalOffset >= midWhitespaceVerticalOffset) {\n\t\t\t\t// Hit\n\t\t\t\treturn midWhitespaceIndex;\n\t\t\t} else {\n\t\t\t\t// vertical offset is before whitespace, but midWhitespaceIndex might still be what we're searching for\n\t\t\t\tmaxWhitespaceIndex = midWhitespaceIndex;\n\t\t\t}\n\t\t}\n\t\treturn minWhitespaceIndex;\n\t}\n\n\t/**\n\t * Get exactly the whitespace that is layouted at `verticalOffset`.\n\t *\n\t * @param verticalOffset The vertical offset.\n\t * @return Precisely the whitespace that is layouted at `verticaloffset` or null.\n\t */\n\tpublic getWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData | null {\n\t\tthis._checkPendingChanges();\n\t\tverticalOffset = verticalOffset | 0;\n\n\t\tconst candidateIndex = this.getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset);\n\n\t\tif (candidateIndex < 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (candidateIndex >= this.getWhitespacesCount()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst candidateTop = this.getVerticalOffsetForWhitespaceIndex(candidateIndex);\n\n\t\tif (candidateTop > verticalOffset) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst candidateHeight = this.getHeightForWhitespaceIndex(candidateIndex);\n\t\tconst candidateId = this.getIdForWhitespaceIndex(candidateIndex);\n\t\tconst candidateAfterLineNumber = this.getAfterLineNumberForWhitespaceIndex(candidateIndex);\n\n\t\treturn {\n\t\t\tid: candidateId,\n\t\t\tafterLineNumber: candidateAfterLineNumber,\n\t\t\tverticalOffset: candidateTop,\n\t\t\theight: candidateHeight\n\t\t};\n\t}\n\n\t/**\n\t * Get a list of whitespaces that are positioned between `verticalOffset1` and `verticalOffset2`.\n\t *\n\t * @param verticalOffset1 The beginning of the viewport.\n\t * @param verticalOffset2 The end of the viewport.\n\t * @return An array with all the whitespaces in the viewport. If no whitespace is in viewport, the array is empty.\n\t */\n\tpublic getWhitespaceViewportData(verticalOffset1: number, verticalOffset2: number): IViewWhitespaceViewportData[] {\n\t\tthis._checkPendingChanges();\n\t\tverticalOffset1 = verticalOffset1 | 0;\n\t\tverticalOffset2 = verticalOffset2 | 0;\n\n\t\tconst startIndex = this.getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset1);\n\t\tconst endIndex = this.getWhitespacesCount() - 1;\n\n\t\tif (startIndex < 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst result: IViewWhitespaceViewportData[] = [];\n\t\tfor (let i = startIndex; i <= endIndex; i++) {\n\t\t\tconst top = this.getVerticalOffsetForWhitespaceIndex(i);\n\t\t\tconst height = this.getHeightForWhitespaceIndex(i);\n\t\t\tif (top >= verticalOffset2) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tresult.push({\n\t\t\t\tid: this.getIdForWhitespaceIndex(i),\n\t\t\t\tafterLineNumber: this.getAfterLineNumberForWhitespaceIndex(i),\n\t\t\t\tverticalOffset: top,\n\t\t\t\theight: height\n\t\t\t});\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Get all whitespaces.\n\t */\n\tpublic getWhitespaces(): IEditorWhitespace[] {\n\t\tthis._checkPendingChanges();\n\t\treturn this._arr.slice(0);\n\t}\n\n\t/**\n\t * The number of whitespaces.\n\t */\n\tpublic getWhitespacesCount(): number {\n\t\tthis._checkPendingChanges();\n\t\treturn this._arr.length;\n\t}\n\n\t/**\n\t * Get the `id` for whitespace at index `index`.\n\t *\n\t * @param index The index of the whitespace.\n\t * @return `id` of whitespace at `index`.\n\t */\n\tpublic getIdForWhitespaceIndex(index: number): string {\n\t\tthis._checkPendingChanges();\n\t\tindex = index | 0;\n\n\t\treturn this._arr[index].id;\n\t}\n\n\t/**\n\t * Get the `afterLineNumber` for whitespace at index `index`.\n\t *\n\t * @param index The index of the whitespace.\n\t * @return `afterLineNumber` of whitespace at `index`.\n\t */\n\tpublic getAfterLineNumberForWhitespaceIndex(index: number): number {\n\t\tthis._checkPendingChanges();\n\t\tindex = index | 0;\n\n\t\treturn this._arr[index].afterLineNumber;\n\t}\n\n\t/**\n\t * Get the `height` for whitespace at index `index`.\n\t *\n\t * @param index The index of the whitespace.\n\t * @return `height` of whitespace at `index`.\n\t */\n\tpublic getHeightForWhitespaceIndex(index: number): number {\n\t\tthis._checkPendingChanges();\n\t\tindex = index | 0;\n\n\t\treturn this._arr[index].height;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport * as strings from 'vs/base/common/strings';\nimport { IViewLineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { IStringBuilder, createStringBuilder } from 'vs/editor/common/core/stringBuilder';\nimport { LineDecoration, LineDecorationsNormalizer } from 'vs/editor/common/viewLayout/lineDecorations';\nimport { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel';\n\nexport const enum RenderWhitespace {\n\tNone = 0,\n\tBoundary = 1,\n\tSelection = 2,\n\tTrailing = 3,\n\tAll = 4\n}\n\nexport const enum LinePartMetadata {\n\tIS_WHITESPACE = 1,\n\tPSEUDO_BEFORE = 2,\n\tPSEUDO_AFTER = 4,\n\n\tIS_WHITESPACE_MASK = 0b001,\n\tPSEUDO_BEFORE_MASK = 0b010,\n\tPSEUDO_AFTER_MASK = 0b100,\n}\n\nclass LinePart {\n\t_linePartBrand: void = undefined;\n\n\t/**\n\t * last char index of this token (not inclusive).\n\t */\n\tpublic readonly endIndex: number;\n\tpublic readonly type: string;\n\tpublic readonly metadata: number;\n\n\tconstructor(endIndex: number, type: string, metadata: number) {\n\t\tthis.endIndex = endIndex;\n\t\tthis.type = type;\n\t\tthis.metadata = metadata;\n\t}\n\n\tpublic isWhitespace(): boolean {\n\t\treturn (this.metadata & LinePartMetadata.IS_WHITESPACE_MASK ? true : false);\n\t}\n\n\tpublic isPseudoAfter(): boolean {\n\t\treturn (this.metadata & LinePartMetadata.PSEUDO_AFTER_MASK ? true : false);\n\t}\n}\n\nexport class LineRange {\n\t/**\n\t * Zero-based offset on which the range starts, inclusive.\n\t */\n\tpublic readonly startOffset: number;\n\n\t/**\n\t * Zero-based offset on which the range ends, inclusive.\n\t */\n\tpublic readonly endOffset: number;\n\n\tconstructor(startIndex: number, endIndex: number) {\n\t\tthis.startOffset = startIndex;\n\t\tthis.endOffset = endIndex;\n\t}\n\n\tpublic equals(otherLineRange: LineRange) {\n\t\treturn this.startOffset === otherLineRange.startOffset\n\t\t\t&& this.endOffset === otherLineRange.endOffset;\n\t}\n}\n\nexport class RenderLineInput {\n\n\tpublic readonly useMonospaceOptimizations: boolean;\n\tpublic readonly canUseHalfwidthRightwardsArrow: boolean;\n\tpublic readonly lineContent: string;\n\tpublic readonly continuesWithWrappedLine: boolean;\n\tpublic readonly isBasicASCII: boolean;\n\tpublic readonly containsRTL: boolean;\n\tpublic readonly fauxIndentLength: number;\n\tpublic readonly lineTokens: IViewLineTokens;\n\tpublic readonly lineDecorations: LineDecoration[];\n\tpublic readonly tabSize: number;\n\tpublic readonly startVisibleColumn: number;\n\tpublic readonly spaceWidth: number;\n\tpublic readonly renderSpaceWidth: number;\n\tpublic readonly renderSpaceCharCode: number;\n\tpublic readonly stopRenderingLineAfter: number;\n\tpublic readonly renderWhitespace: RenderWhitespace;\n\tpublic readonly renderControlCharacters: boolean;\n\tpublic readonly fontLigatures: boolean;\n\n\t/**\n\t * Defined only when renderWhitespace is 'selection'. Selections are non-overlapping,\n\t * and ordered by position within the line.\n\t */\n\tpublic readonly selectionsOnLine: LineRange[] | null;\n\n\tconstructor(\n\t\tuseMonospaceOptimizations: boolean,\n\t\tcanUseHalfwidthRightwardsArrow: boolean,\n\t\tlineContent: string,\n\t\tcontinuesWithWrappedLine: boolean,\n\t\tisBasicASCII: boolean,\n\t\tcontainsRTL: boolean,\n\t\tfauxIndentLength: number,\n\t\tlineTokens: IViewLineTokens,\n\t\tlineDecorations: LineDecoration[],\n\t\ttabSize: number,\n\t\tstartVisibleColumn: number,\n\t\tspaceWidth: number,\n\t\tmiddotWidth: number,\n\t\twsmiddotWidth: number,\n\t\tstopRenderingLineAfter: number,\n\t\trenderWhitespace: 'none' | 'boundary' | 'selection' | 'trailing' | 'all',\n\t\trenderControlCharacters: boolean,\n\t\tfontLigatures: boolean,\n\t\tselectionsOnLine: LineRange[] | null\n\t) {\n\t\tthis.useMonospaceOptimizations = useMonospaceOptimizations;\n\t\tthis.canUseHalfwidthRightwardsArrow = canUseHalfwidthRightwardsArrow;\n\t\tthis.lineContent = lineContent;\n\t\tthis.continuesWithWrappedLine = continuesWithWrappedLine;\n\t\tthis.isBasicASCII = isBasicASCII;\n\t\tthis.containsRTL = containsRTL;\n\t\tthis.fauxIndentLength = fauxIndentLength;\n\t\tthis.lineTokens = lineTokens;\n\t\tthis.lineDecorations = lineDecorations.sort(LineDecoration.compare);\n\t\tthis.tabSize = tabSize;\n\t\tthis.startVisibleColumn = startVisibleColumn;\n\t\tthis.spaceWidth = spaceWidth;\n\t\tthis.stopRenderingLineAfter = stopRenderingLineAfter;\n\t\tthis.renderWhitespace = (\n\t\t\trenderWhitespace === 'all'\n\t\t\t\t? RenderWhitespace.All\n\t\t\t\t: renderWhitespace === 'boundary'\n\t\t\t\t\t? RenderWhitespace.Boundary\n\t\t\t\t\t: renderWhitespace === 'selection'\n\t\t\t\t\t\t? RenderWhitespace.Selection\n\t\t\t\t\t\t: renderWhitespace === 'trailing'\n\t\t\t\t\t\t\t? RenderWhitespace.Trailing\n\t\t\t\t\t\t\t: RenderWhitespace.None\n\t\t);\n\t\tthis.renderControlCharacters = renderControlCharacters;\n\t\tthis.fontLigatures = fontLigatures;\n\t\tthis.selectionsOnLine = selectionsOnLine && selectionsOnLine.sort((a, b) => a.startOffset < b.startOffset ? -1 : 1);\n\n\t\tconst wsmiddotDiff = Math.abs(wsmiddotWidth - spaceWidth);\n\t\tconst middotDiff = Math.abs(middotWidth - spaceWidth);\n\t\tif (wsmiddotDiff < middotDiff) {\n\t\t\tthis.renderSpaceWidth = wsmiddotWidth;\n\t\t\tthis.renderSpaceCharCode = 0x2E31; // U+2E31 - WORD SEPARATOR MIDDLE DOT\n\t\t} else {\n\t\t\tthis.renderSpaceWidth = middotWidth;\n\t\t\tthis.renderSpaceCharCode = 0xB7; // U+00B7 - MIDDLE DOT\n\t\t}\n\t}\n\n\tprivate sameSelection(otherSelections: LineRange[] | null): boolean {\n\t\tif (this.selectionsOnLine === null) {\n\t\t\treturn otherSelections === null;\n\t\t}\n\n\t\tif (otherSelections === null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (otherSelections.length !== this.selectionsOnLine.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = 0; i < this.selectionsOnLine.length; i++) {\n\t\t\tif (!this.selectionsOnLine[i].equals(otherSelections[i])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tpublic equals(other: RenderLineInput): boolean {\n\t\treturn (\n\t\t\tthis.useMonospaceOptimizations === other.useMonospaceOptimizations\n\t\t\t&& this.canUseHalfwidthRightwardsArrow === other.canUseHalfwidthRightwardsArrow\n\t\t\t&& this.lineContent === other.lineContent\n\t\t\t&& this.continuesWithWrappedLine === other.continuesWithWrappedLine\n\t\t\t&& this.isBasicASCII === other.isBasicASCII\n\t\t\t&& this.containsRTL === other.containsRTL\n\t\t\t&& this.fauxIndentLength === other.fauxIndentLength\n\t\t\t&& this.tabSize === other.tabSize\n\t\t\t&& this.startVisibleColumn === other.startVisibleColumn\n\t\t\t&& this.spaceWidth === other.spaceWidth\n\t\t\t&& this.renderSpaceWidth === other.renderSpaceWidth\n\t\t\t&& this.renderSpaceCharCode === other.renderSpaceCharCode\n\t\t\t&& this.stopRenderingLineAfter === other.stopRenderingLineAfter\n\t\t\t&& this.renderWhitespace === other.renderWhitespace\n\t\t\t&& this.renderControlCharacters === other.renderControlCharacters\n\t\t\t&& this.fontLigatures === other.fontLigatures\n\t\t\t&& LineDecoration.equalsArr(this.lineDecorations, other.lineDecorations)\n\t\t\t&& this.lineTokens.equals(other.lineTokens)\n\t\t\t&& this.sameSelection(other.selectionsOnLine)\n\t\t);\n\t}\n}\n\nexport const enum CharacterMappingConstants {\n\tPART_INDEX_MASK = 0b11111111111111110000000000000000,\n\tCHAR_INDEX_MASK = 0b00000000000000001111111111111111,\n\n\tCHAR_INDEX_OFFSET = 0,\n\tPART_INDEX_OFFSET = 16\n}\n\nexport class DomPosition {\n\tconstructor(\n\t\tpublic readonly partIndex: number,\n\t\tpublic readonly charIndex: number\n\t) { }\n}\n\n/**\n * Provides a both direction mapping between a line's character and its rendered position.\n */\nexport class CharacterMapping {\n\n\tprivate static getPartIndex(partData: number): number {\n\t\treturn (partData & CharacterMappingConstants.PART_INDEX_MASK) >>> CharacterMappingConstants.PART_INDEX_OFFSET;\n\t}\n\n\tprivate static getCharIndex(partData: number): number {\n\t\treturn (partData & CharacterMappingConstants.CHAR_INDEX_MASK) >>> CharacterMappingConstants.CHAR_INDEX_OFFSET;\n\t}\n\n\tpublic readonly length: number;\n\tprivate readonly _data: Uint32Array;\n\tprivate readonly _absoluteOffsets: Uint32Array;\n\n\tconstructor(length: number, partCount: number) {\n\t\tthis.length = length;\n\t\tthis._data = new Uint32Array(this.length);\n\t\tthis._absoluteOffsets = new Uint32Array(this.length);\n\t}\n\n\tpublic setColumnInfo(column: number, partIndex: number, charIndex: number, partAbsoluteOffset: number): void {\n\t\tconst partData = (\n\t\t\t(partIndex << CharacterMappingConstants.PART_INDEX_OFFSET)\n\t\t\t| (charIndex << CharacterMappingConstants.CHAR_INDEX_OFFSET)\n\t\t) >>> 0;\n\t\tthis._data[column - 1] = partData;\n\t\tthis._absoluteOffsets[column - 1] = partAbsoluteOffset + charIndex;\n\t}\n\n\tpublic getAbsoluteOffset(column: number): number {\n\t\tif (this._absoluteOffsets.length === 0) {\n\t\t\t// No characters on this line\n\t\t\treturn 0;\n\t\t}\n\t\treturn this._absoluteOffsets[column - 1];\n\t}\n\n\tprivate charOffsetToPartData(charOffset: number): number {\n\t\tif (this.length === 0) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (charOffset < 0) {\n\t\t\treturn this._data[0];\n\t\t}\n\t\tif (charOffset >= this.length) {\n\t\t\treturn this._data[this.length - 1];\n\t\t}\n\t\treturn this._data[charOffset];\n\t}\n\n\tpublic getDomPosition(column: number): DomPosition {\n\t\tconst partData = this.charOffsetToPartData(column - 1);\n\t\tconst partIndex = CharacterMapping.getPartIndex(partData);\n\t\tconst charIndex = CharacterMapping.getCharIndex(partData);\n\t\treturn new DomPosition(partIndex, charIndex);\n\t}\n\n\tpublic getColumn(domPosition: DomPosition, partLength: number): number {\n\t\tconst charOffset = this.partDataToCharOffset(domPosition.partIndex, partLength, domPosition.charIndex);\n\t\treturn charOffset + 1;\n\t}\n\n\tprivate partDataToCharOffset(partIndex: number, partLength: number, charIndex: number): number {\n\t\tif (this.length === 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst searchEntry = (\n\t\t\t(partIndex << CharacterMappingConstants.PART_INDEX_OFFSET)\n\t\t\t| (charIndex << CharacterMappingConstants.CHAR_INDEX_OFFSET)\n\t\t) >>> 0;\n\n\t\tlet min = 0;\n\t\tlet max = this.length - 1;\n\t\twhile (min + 1 < max) {\n\t\t\tconst mid = ((min + max) >>> 1);\n\t\t\tconst midEntry = this._data[mid];\n\t\t\tif (midEntry === searchEntry) {\n\t\t\t\treturn mid;\n\t\t\t} else if (midEntry > searchEntry) {\n\t\t\t\tmax = mid;\n\t\t\t} else {\n\t\t\t\tmin = mid;\n\t\t\t}\n\t\t}\n\n\t\tif (min === max) {\n\t\t\treturn min;\n\t\t}\n\n\t\tconst minEntry = this._data[min];\n\t\tconst maxEntry = this._data[max];\n\n\t\tif (minEntry === searchEntry) {\n\t\t\treturn min;\n\t\t}\n\t\tif (maxEntry === searchEntry) {\n\t\t\treturn max;\n\t\t}\n\n\t\tconst minPartIndex = CharacterMapping.getPartIndex(minEntry);\n\t\tconst minCharIndex = CharacterMapping.getCharIndex(minEntry);\n\n\t\tconst maxPartIndex = CharacterMapping.getPartIndex(maxEntry);\n\t\tlet maxCharIndex: number;\n\n\t\tif (minPartIndex !== maxPartIndex) {\n\t\t\t// sitting between parts\n\t\t\tmaxCharIndex = partLength;\n\t\t} else {\n\t\t\tmaxCharIndex = CharacterMapping.getCharIndex(maxEntry);\n\t\t}\n\n\t\tconst minEntryDistance = charIndex - minCharIndex;\n\t\tconst maxEntryDistance = maxCharIndex - charIndex;\n\n\t\tif (minEntryDistance <= maxEntryDistance) {\n\t\t\treturn min;\n\t\t}\n\t\treturn max;\n\t}\n}\n\nexport const enum ForeignElementType {\n\tNone = 0,\n\tBefore = 1,\n\tAfter = 2\n}\n\nexport class RenderLineOutput {\n\t_renderLineOutputBrand: void = undefined;\n\n\treadonly characterMapping: CharacterMapping;\n\treadonly containsRTL: boolean;\n\treadonly containsForeignElements: ForeignElementType;\n\n\tconstructor(characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) {\n\t\tthis.characterMapping = characterMapping;\n\t\tthis.containsRTL = containsRTL;\n\t\tthis.containsForeignElements = containsForeignElements;\n\t}\n}\n\nexport function renderViewLine(input: RenderLineInput, sb: IStringBuilder): RenderLineOutput {\n\tif (input.lineContent.length === 0) {\n\n\t\tif (input.lineDecorations.length > 0) {\n\t\t\t// This line is empty, but it contains inline decorations\n\t\t\tsb.appendASCIIString(``);\n\n\t\t\tlet beforeCount = 0;\n\t\t\tlet afterCount = 0;\n\t\t\tlet containsForeignElements = ForeignElementType.None;\n\t\t\tfor (const lineDecoration of input.lineDecorations) {\n\t\t\t\tif (lineDecoration.type === InlineDecorationType.Before || lineDecoration.type === InlineDecorationType.After) {\n\t\t\t\t\tsb.appendASCIIString(``);\n\n\t\t\t\t\tif (lineDecoration.type === InlineDecorationType.Before) {\n\t\t\t\t\t\tcontainsForeignElements |= ForeignElementType.Before;\n\t\t\t\t\t\tbeforeCount++;\n\t\t\t\t\t}\n\t\t\t\t\tif (lineDecoration.type === InlineDecorationType.After) {\n\t\t\t\t\t\tcontainsForeignElements |= ForeignElementType.After;\n\t\t\t\t\t\tafterCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsb.appendASCIIString(``);\n\n\t\t\tconst characterMapping = new CharacterMapping(1, beforeCount + afterCount);\n\t\t\tcharacterMapping.setColumnInfo(1, beforeCount, 0, 0);\n\n\t\t\treturn new RenderLineOutput(\n\t\t\t\tcharacterMapping,\n\t\t\t\tfalse,\n\t\t\t\tcontainsForeignElements\n\t\t\t);\n\t\t}\n\n\t\t// completely empty line\n\t\tsb.appendASCIIString('');\n\t\treturn new RenderLineOutput(\n\t\t\tnew CharacterMapping(0, 0),\n\t\t\tfalse,\n\t\t\tForeignElementType.None\n\t\t);\n\t}\n\n\treturn _renderLine(resolveRenderLineInput(input), sb);\n}\n\nexport class RenderLineOutput2 {\n\tconstructor(\n\t\tpublic readonly characterMapping: CharacterMapping,\n\t\tpublic readonly html: string,\n\t\tpublic readonly containsRTL: boolean,\n\t\tpublic readonly containsForeignElements: ForeignElementType\n\t) {\n\t}\n}\n\nexport function renderViewLine2(input: RenderLineInput): RenderLineOutput2 {\n\tconst sb = createStringBuilder(10000);\n\tconst out = renderViewLine(input, sb);\n\treturn new RenderLineOutput2(out.characterMapping, sb.build(), out.containsRTL, out.containsForeignElements);\n}\n\nclass ResolvedRenderLineInput {\n\tconstructor(\n\t\tpublic readonly fontIsMonospace: boolean,\n\t\tpublic readonly canUseHalfwidthRightwardsArrow: boolean,\n\t\tpublic readonly lineContent: string,\n\t\tpublic readonly len: number,\n\t\tpublic readonly isOverflowing: boolean,\n\t\tpublic readonly parts: LinePart[],\n\t\tpublic readonly containsForeignElements: ForeignElementType,\n\t\tpublic readonly fauxIndentLength: number,\n\t\tpublic readonly tabSize: number,\n\t\tpublic readonly startVisibleColumn: number,\n\t\tpublic readonly containsRTL: boolean,\n\t\tpublic readonly spaceWidth: number,\n\t\tpublic readonly renderSpaceCharCode: number,\n\t\tpublic readonly renderWhitespace: RenderWhitespace,\n\t\tpublic readonly renderControlCharacters: boolean,\n\t) {\n\t\t//\n\t}\n}\n\nfunction resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput {\n\tconst lineContent = input.lineContent;\n\n\tlet isOverflowing: boolean;\n\tlet len: number;\n\n\tif (input.stopRenderingLineAfter !== -1 && input.stopRenderingLineAfter < lineContent.length) {\n\t\tisOverflowing = true;\n\t\tlen = input.stopRenderingLineAfter;\n\t} else {\n\t\tisOverflowing = false;\n\t\tlen = lineContent.length;\n\t}\n\n\tlet tokens = transformAndRemoveOverflowing(input.lineTokens, input.fauxIndentLength, len);\n\tif (input.renderControlCharacters && !input.isBasicASCII) {\n\t\t// Calling `extractControlCharacters` before adding (possibly empty) line parts\n\t\t// for inline decorations. `extractControlCharacters` removes empty line parts.\n\t\ttokens = extractControlCharacters(lineContent, tokens);\n\t}\n\tif (input.renderWhitespace === RenderWhitespace.All ||\n\t\tinput.renderWhitespace === RenderWhitespace.Boundary ||\n\t\t(input.renderWhitespace === RenderWhitespace.Selection && !!input.selectionsOnLine) ||\n\t\tinput.renderWhitespace === RenderWhitespace.Trailing) {\n\n\t\ttokens = _applyRenderWhitespace(input, lineContent, len, tokens);\n\t}\n\tlet containsForeignElements = ForeignElementType.None;\n\tif (input.lineDecorations.length > 0) {\n\t\tfor (let i = 0, len = input.lineDecorations.length; i < len; i++) {\n\t\t\tconst lineDecoration = input.lineDecorations[i];\n\t\t\tif (lineDecoration.type === InlineDecorationType.RegularAffectingLetterSpacing) {\n\t\t\t\t// Pretend there are foreign elements... although not 100% accurate.\n\t\t\t\tcontainsForeignElements |= ForeignElementType.Before;\n\t\t\t} else if (lineDecoration.type === InlineDecorationType.Before) {\n\t\t\t\tcontainsForeignElements |= ForeignElementType.Before;\n\t\t\t} else if (lineDecoration.type === InlineDecorationType.After) {\n\t\t\t\tcontainsForeignElements |= ForeignElementType.After;\n\t\t\t}\n\t\t}\n\t\ttokens = _applyInlineDecorations(lineContent, len, tokens, input.lineDecorations);\n\t}\n\tif (!input.containsRTL) {\n\t\t// We can never split RTL text, as it ruins the rendering\n\t\ttokens = splitLargeTokens(lineContent, tokens, !input.isBasicASCII || input.fontLigatures);\n\t}\n\n\treturn new ResolvedRenderLineInput(\n\t\tinput.useMonospaceOptimizations,\n\t\tinput.canUseHalfwidthRightwardsArrow,\n\t\tlineContent,\n\t\tlen,\n\t\tisOverflowing,\n\t\ttokens,\n\t\tcontainsForeignElements,\n\t\tinput.fauxIndentLength,\n\t\tinput.tabSize,\n\t\tinput.startVisibleColumn,\n\t\tinput.containsRTL,\n\t\tinput.spaceWidth,\n\t\tinput.renderSpaceCharCode,\n\t\tinput.renderWhitespace,\n\t\tinput.renderControlCharacters\n\t);\n}\n\n/**\n * In the rendering phase, characters are always looped until token.endIndex.\n * Ensure that all tokens end before `len` and the last one ends precisely at `len`.\n */\nfunction transformAndRemoveOverflowing(tokens: IViewLineTokens, fauxIndentLength: number, len: number): LinePart[] {\n\tconst result: LinePart[] = [];\n\tlet resultLen = 0;\n\n\t// The faux indent part of the line should have no token type\n\tif (fauxIndentLength > 0) {\n\t\tresult[resultLen++] = new LinePart(fauxIndentLength, '', 0);\n\t}\n\n\tfor (let tokenIndex = 0, tokensLen = tokens.getCount(); tokenIndex < tokensLen; tokenIndex++) {\n\t\tconst endIndex = tokens.getEndOffset(tokenIndex);\n\t\tif (endIndex <= fauxIndentLength) {\n\t\t\t// The faux indent part of the line should have no token type\n\t\t\tcontinue;\n\t\t}\n\t\tconst type = tokens.getClassName(tokenIndex);\n\t\tif (endIndex >= len) {\n\t\t\tresult[resultLen++] = new LinePart(len, type, 0);\n\t\t\tbreak;\n\t\t}\n\t\tresult[resultLen++] = new LinePart(endIndex, type, 0);\n\t}\n\n\treturn result;\n}\n\n/**\n * written as a const enum to get value inlining.\n */\nconst enum Constants {\n\tLongToken = 50\n}\n\n/**\n * See https://github.com/microsoft/vscode/issues/6885.\n * It appears that having very large spans causes very slow reading of character positions.\n * So here we try to avoid that.\n */\nfunction splitLargeTokens(lineContent: string, tokens: LinePart[], onlyAtSpaces: boolean): LinePart[] {\n\tlet lastTokenEndIndex = 0;\n\tconst result: LinePart[] = [];\n\tlet resultLen = 0;\n\n\tif (onlyAtSpaces) {\n\t\t// Split only at spaces => we need to walk each character\n\t\tfor (let i = 0, len = tokens.length; i < len; i++) {\n\t\t\tconst token = tokens[i];\n\t\t\tconst tokenEndIndex = token.endIndex;\n\t\t\tif (lastTokenEndIndex + Constants.LongToken < tokenEndIndex) {\n\t\t\t\tconst tokenType = token.type;\n\t\t\t\tconst tokenMetadata = token.metadata;\n\n\t\t\t\tlet lastSpaceOffset = -1;\n\t\t\t\tlet currTokenStart = lastTokenEndIndex;\n\t\t\t\tfor (let j = lastTokenEndIndex; j < tokenEndIndex; j++) {\n\t\t\t\t\tif (lineContent.charCodeAt(j) === CharCode.Space) {\n\t\t\t\t\t\tlastSpaceOffset = j;\n\t\t\t\t\t}\n\t\t\t\t\tif (lastSpaceOffset !== -1 && j - currTokenStart >= Constants.LongToken) {\n\t\t\t\t\t\t// Split at `lastSpaceOffset` + 1\n\t\t\t\t\t\tresult[resultLen++] = new LinePart(lastSpaceOffset + 1, tokenType, tokenMetadata);\n\t\t\t\t\t\tcurrTokenStart = lastSpaceOffset + 1;\n\t\t\t\t\t\tlastSpaceOffset = -1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (currTokenStart !== tokenEndIndex) {\n\t\t\t\t\tresult[resultLen++] = new LinePart(tokenEndIndex, tokenType, tokenMetadata);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresult[resultLen++] = token;\n\t\t\t}\n\n\t\t\tlastTokenEndIndex = tokenEndIndex;\n\t\t}\n\t} else {\n\t\t// Split anywhere => we don't need to walk each character\n\t\tfor (let i = 0, len = tokens.length; i < len; i++) {\n\t\t\tconst token = tokens[i];\n\t\t\tconst tokenEndIndex = token.endIndex;\n\t\t\tconst diff = (tokenEndIndex - lastTokenEndIndex);\n\t\t\tif (diff > Constants.LongToken) {\n\t\t\t\tconst tokenType = token.type;\n\t\t\t\tconst tokenMetadata = token.metadata;\n\t\t\t\tconst piecesCount = Math.ceil(diff / Constants.LongToken);\n\t\t\t\tfor (let j = 1; j < piecesCount; j++) {\n\t\t\t\t\tconst pieceEndIndex = lastTokenEndIndex + (j * Constants.LongToken);\n\t\t\t\t\tresult[resultLen++] = new LinePart(pieceEndIndex, tokenType, tokenMetadata);\n\t\t\t\t}\n\t\t\t\tresult[resultLen++] = new LinePart(tokenEndIndex, tokenType, tokenMetadata);\n\t\t\t} else {\n\t\t\t\tresult[resultLen++] = token;\n\t\t\t}\n\t\t\tlastTokenEndIndex = tokenEndIndex;\n\t\t}\n\t}\n\n\treturn result;\n}\n\nfunction isControlCharacter(charCode: number): boolean {\n\tif (charCode < 32) {\n\t\treturn (charCode !== CharCode.Tab);\n\t}\n\tif (charCode === 127) {\n\t\t// DEL\n\t\treturn true;\n\t}\n\n\tif (\n\t\t(charCode >= 0x202A && charCode <= 0x202E)\n\t\t|| (charCode >= 0x2066 && charCode <= 0x2069)\n\t\t|| (charCode >= 0x200E && charCode <= 0x200F)\n\t\t|| charCode === 0x061C\n\t) {\n\t\t// Unicode Directional Formatting Characters\n\t\t// LRE\tU+202A\tLEFT-TO-RIGHT EMBEDDING\n\t\t// RLE\tU+202B\tRIGHT-TO-LEFT EMBEDDING\n\t\t// PDF\tU+202C\tPOP DIRECTIONAL FORMATTING\n\t\t// LRO\tU+202D\tLEFT-TO-RIGHT OVERRIDE\n\t\t// RLO\tU+202E\tRIGHT-TO-LEFT OVERRIDE\n\t\t// LRI\tU+2066\tLEFT-TO-RIGHT ISOLATE\n\t\t// RLI\tU+2067\tRIGHT-TO-LEFT ISOLATE\n\t\t// FSI\tU+2068\tFIRST STRONG ISOLATE\n\t\t// PDI\tU+2069\tPOP DIRECTIONAL ISOLATE\n\t\t// LRM\tU+200E\tLEFT-TO-RIGHT MARK\n\t\t// RLM\tU+200F\tRIGHT-TO-LEFT MARK\n\t\t// ALM\tU+061C\tARABIC LETTER MARK\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nfunction extractControlCharacters(lineContent: string, tokens: LinePart[]): LinePart[] {\n\tconst result: LinePart[] = [];\n\tlet lastLinePart: LinePart = new LinePart(0, '', 0);\n\tlet charOffset = 0;\n\tfor (const token of tokens) {\n\t\tconst tokenEndIndex = token.endIndex;\n\t\tfor (; charOffset < tokenEndIndex; charOffset++) {\n\t\t\tconst charCode = lineContent.charCodeAt(charOffset);\n\t\t\tif (isControlCharacter(charCode)) {\n\t\t\t\tif (charOffset > lastLinePart.endIndex) {\n\t\t\t\t\t// emit previous part if it has text\n\t\t\t\t\tlastLinePart = new LinePart(charOffset, token.type, token.metadata);\n\t\t\t\t\tresult.push(lastLinePart);\n\t\t\t\t}\n\t\t\t\tlastLinePart = new LinePart(charOffset + 1, 'mtkcontrol', token.metadata);\n\t\t\t\tresult.push(lastLinePart);\n\t\t\t}\n\t\t}\n\t\tif (charOffset > lastLinePart.endIndex) {\n\t\t\t// emit previous part if it has text\n\t\t\tlastLinePart = new LinePart(tokenEndIndex, token.type, token.metadata);\n\t\t\tresult.push(lastLinePart);\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Whitespace is rendered by \"replacing\" tokens with a special-purpose `mtkw` type that is later recognized in the rendering phase.\n * Moreover, a token is created for every visual indent because on some fonts the glyphs used for rendering whitespace (→ or ·) do not have the same width as  .\n * The rendering phase will generate `style=\"width:...\"` for these tokens.\n */\nfunction _applyRenderWhitespace(input: RenderLineInput, lineContent: string, len: number, tokens: LinePart[]): LinePart[] {\n\n\tconst continuesWithWrappedLine = input.continuesWithWrappedLine;\n\tconst fauxIndentLength = input.fauxIndentLength;\n\tconst tabSize = input.tabSize;\n\tconst startVisibleColumn = input.startVisibleColumn;\n\tconst useMonospaceOptimizations = input.useMonospaceOptimizations;\n\tconst selections = input.selectionsOnLine;\n\tconst onlyBoundary = (input.renderWhitespace === RenderWhitespace.Boundary);\n\tconst onlyTrailing = (input.renderWhitespace === RenderWhitespace.Trailing);\n\tconst generateLinePartForEachWhitespace = (input.renderSpaceWidth !== input.spaceWidth);\n\n\tconst result: LinePart[] = [];\n\tlet resultLen = 0;\n\tlet tokenIndex = 0;\n\tlet tokenType = tokens[tokenIndex].type;\n\tlet tokenEndIndex = tokens[tokenIndex].endIndex;\n\tconst tokensLength = tokens.length;\n\n\tlet lineIsEmptyOrWhitespace = false;\n\tlet firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineContent);\n\tlet lastNonWhitespaceIndex: number;\n\tif (firstNonWhitespaceIndex === -1) {\n\t\tlineIsEmptyOrWhitespace = true;\n\t\tfirstNonWhitespaceIndex = len;\n\t\tlastNonWhitespaceIndex = len;\n\t} else {\n\t\tlastNonWhitespaceIndex = strings.lastNonWhitespaceIndex(lineContent);\n\t}\n\n\tlet wasInWhitespace = false;\n\tlet currentSelectionIndex = 0;\n\tlet currentSelection = selections && selections[currentSelectionIndex];\n\tlet tmpIndent = startVisibleColumn % tabSize;\n\tfor (let charIndex = fauxIndentLength; charIndex < len; charIndex++) {\n\t\tconst chCode = lineContent.charCodeAt(charIndex);\n\n\t\tif (currentSelection && charIndex >= currentSelection.endOffset) {\n\t\t\tcurrentSelectionIndex++;\n\t\t\tcurrentSelection = selections && selections[currentSelectionIndex];\n\t\t}\n\n\t\tlet isInWhitespace: boolean;\n\t\tif (charIndex < firstNonWhitespaceIndex || charIndex > lastNonWhitespaceIndex) {\n\t\t\t// in leading or trailing whitespace\n\t\t\tisInWhitespace = true;\n\t\t} else if (chCode === CharCode.Tab) {\n\t\t\t// a tab character is rendered both in all and boundary cases\n\t\t\tisInWhitespace = true;\n\t\t} else if (chCode === CharCode.Space) {\n\t\t\t// hit a space character\n\t\t\tif (onlyBoundary) {\n\t\t\t\t// rendering only boundary whitespace\n\t\t\t\tif (wasInWhitespace) {\n\t\t\t\t\tisInWhitespace = true;\n\t\t\t\t} else {\n\t\t\t\t\tconst nextChCode = (charIndex + 1 < len ? lineContent.charCodeAt(charIndex + 1) : CharCode.Null);\n\t\t\t\t\tisInWhitespace = (nextChCode === CharCode.Space || nextChCode === CharCode.Tab);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tisInWhitespace = true;\n\t\t\t}\n\t\t} else {\n\t\t\tisInWhitespace = false;\n\t\t}\n\n\t\t// If rendering whitespace on selection, check that the charIndex falls within a selection\n\t\tif (isInWhitespace && selections) {\n\t\t\tisInWhitespace = !!currentSelection && currentSelection.startOffset <= charIndex && currentSelection.endOffset > charIndex;\n\t\t}\n\n\t\t// If rendering only trailing whitespace, check that the charIndex points to trailing whitespace.\n\t\tif (isInWhitespace && onlyTrailing) {\n\t\t\tisInWhitespace = lineIsEmptyOrWhitespace || charIndex > lastNonWhitespaceIndex;\n\t\t}\n\n\t\tif (wasInWhitespace) {\n\t\t\t// was in whitespace token\n\t\t\tif (!isInWhitespace || (!useMonospaceOptimizations && tmpIndent >= tabSize)) {\n\t\t\t\t// leaving whitespace token or entering a new indent\n\t\t\t\tif (generateLinePartForEachWhitespace) {\n\t\t\t\t\tconst lastEndIndex = (resultLen > 0 ? result[resultLen - 1].endIndex : fauxIndentLength);\n\t\t\t\t\tfor (let i = lastEndIndex + 1; i <= charIndex; i++) {\n\t\t\t\t\t\tresult[resultLen++] = new LinePart(i, 'mtkw', LinePartMetadata.IS_WHITESPACE);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresult[resultLen++] = new LinePart(charIndex, 'mtkw', LinePartMetadata.IS_WHITESPACE);\n\t\t\t\t}\n\t\t\t\ttmpIndent = tmpIndent % tabSize;\n\t\t\t}\n\t\t} else {\n\t\t\t// was in regular token\n\t\t\tif (charIndex === tokenEndIndex || (isInWhitespace && charIndex > fauxIndentLength)) {\n\t\t\t\tresult[resultLen++] = new LinePart(charIndex, tokenType, 0);\n\t\t\t\ttmpIndent = tmpIndent % tabSize;\n\t\t\t}\n\t\t}\n\n\t\tif (chCode === CharCode.Tab) {\n\t\t\ttmpIndent = tabSize;\n\t\t} else if (strings.isFullWidthCharacter(chCode)) {\n\t\t\ttmpIndent += 2;\n\t\t} else {\n\t\t\ttmpIndent++;\n\t\t}\n\n\t\twasInWhitespace = isInWhitespace;\n\n\t\twhile (charIndex === tokenEndIndex) {\n\t\t\ttokenIndex++;\n\t\t\tif (tokenIndex < tokensLength) {\n\t\t\t\ttokenType = tokens[tokenIndex].type;\n\t\t\t\ttokenEndIndex = tokens[tokenIndex].endIndex;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tlet generateWhitespace = false;\n\tif (wasInWhitespace) {\n\t\t// was in whitespace token\n\t\tif (continuesWithWrappedLine && onlyBoundary) {\n\t\t\tconst lastCharCode = (len > 0 ? lineContent.charCodeAt(len - 1) : CharCode.Null);\n\t\t\tconst prevCharCode = (len > 1 ? lineContent.charCodeAt(len - 2) : CharCode.Null);\n\t\t\tconst isSingleTrailingSpace = (lastCharCode === CharCode.Space && (prevCharCode !== CharCode.Space && prevCharCode !== CharCode.Tab));\n\t\t\tif (!isSingleTrailingSpace) {\n\t\t\t\tgenerateWhitespace = true;\n\t\t\t}\n\t\t} else {\n\t\t\tgenerateWhitespace = true;\n\t\t}\n\t}\n\n\tif (generateWhitespace) {\n\t\tif (generateLinePartForEachWhitespace) {\n\t\t\tconst lastEndIndex = (resultLen > 0 ? result[resultLen - 1].endIndex : fauxIndentLength);\n\t\t\tfor (let i = lastEndIndex + 1; i <= len; i++) {\n\t\t\t\tresult[resultLen++] = new LinePart(i, 'mtkw', LinePartMetadata.IS_WHITESPACE);\n\t\t\t}\n\t\t} else {\n\t\t\tresult[resultLen++] = new LinePart(len, 'mtkw', LinePartMetadata.IS_WHITESPACE);\n\t\t}\n\t} else {\n\t\tresult[resultLen++] = new LinePart(len, tokenType, 0);\n\t}\n\n\treturn result;\n}\n\n/**\n * Inline decorations are \"merged\" on top of tokens.\n * Special care must be taken when multiple inline decorations are at play and they overlap.\n */\nfunction _applyInlineDecorations(lineContent: string, len: number, tokens: LinePart[], _lineDecorations: LineDecoration[]): LinePart[] {\n\t_lineDecorations.sort(LineDecoration.compare);\n\tconst lineDecorations = LineDecorationsNormalizer.normalize(lineContent, _lineDecorations);\n\tconst lineDecorationsLen = lineDecorations.length;\n\n\tlet lineDecorationIndex = 0;\n\tconst result: LinePart[] = [];\n\tlet resultLen = 0;\n\tlet lastResultEndIndex = 0;\n\tfor (let tokenIndex = 0, len = tokens.length; tokenIndex < len; tokenIndex++) {\n\t\tconst token = tokens[tokenIndex];\n\t\tconst tokenEndIndex = token.endIndex;\n\t\tconst tokenType = token.type;\n\t\tconst tokenMetadata = token.metadata;\n\n\t\twhile (lineDecorationIndex < lineDecorationsLen && lineDecorations[lineDecorationIndex].startOffset < tokenEndIndex) {\n\t\t\tconst lineDecoration = lineDecorations[lineDecorationIndex];\n\n\t\t\tif (lineDecoration.startOffset > lastResultEndIndex) {\n\t\t\t\tlastResultEndIndex = lineDecoration.startOffset;\n\t\t\t\tresult[resultLen++] = new LinePart(lastResultEndIndex, tokenType, tokenMetadata);\n\t\t\t}\n\n\t\t\tif (lineDecoration.endOffset + 1 <= tokenEndIndex) {\n\t\t\t\t// This line decoration ends before this token ends\n\t\t\t\tlastResultEndIndex = lineDecoration.endOffset + 1;\n\t\t\t\tresult[resultLen++] = new LinePart(lastResultEndIndex, tokenType + ' ' + lineDecoration.className, tokenMetadata | lineDecoration.metadata);\n\t\t\t\tlineDecorationIndex++;\n\t\t\t} else {\n\t\t\t\t// This line decoration continues on to the next token\n\t\t\t\tlastResultEndIndex = tokenEndIndex;\n\t\t\t\tresult[resultLen++] = new LinePart(lastResultEndIndex, tokenType + ' ' + lineDecoration.className, tokenMetadata | lineDecoration.metadata);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (tokenEndIndex > lastResultEndIndex) {\n\t\t\tlastResultEndIndex = tokenEndIndex;\n\t\t\tresult[resultLen++] = new LinePart(lastResultEndIndex, tokenType, tokenMetadata);\n\t\t}\n\t}\n\n\tconst lastTokenEndIndex = tokens[tokens.length - 1].endIndex;\n\tif (lineDecorationIndex < lineDecorationsLen && lineDecorations[lineDecorationIndex].startOffset === lastTokenEndIndex) {\n\t\twhile (lineDecorationIndex < lineDecorationsLen && lineDecorations[lineDecorationIndex].startOffset === lastTokenEndIndex) {\n\t\t\tconst lineDecoration = lineDecorations[lineDecorationIndex];\n\t\t\tresult[resultLen++] = new LinePart(lastResultEndIndex, lineDecoration.className, lineDecoration.metadata);\n\t\t\tlineDecorationIndex++;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * This function is on purpose not split up into multiple functions to allow runtime type inference (i.e. performance reasons).\n * Notice how all the needed data is fully resolved and passed in (i.e. no other calls).\n */\nfunction _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): RenderLineOutput {\n\tconst fontIsMonospace = input.fontIsMonospace;\n\tconst canUseHalfwidthRightwardsArrow = input.canUseHalfwidthRightwardsArrow;\n\tconst containsForeignElements = input.containsForeignElements;\n\tconst lineContent = input.lineContent;\n\tconst len = input.len;\n\tconst isOverflowing = input.isOverflowing;\n\tconst parts = input.parts;\n\tconst fauxIndentLength = input.fauxIndentLength;\n\tconst tabSize = input.tabSize;\n\tconst startVisibleColumn = input.startVisibleColumn;\n\tconst containsRTL = input.containsRTL;\n\tconst spaceWidth = input.spaceWidth;\n\tconst renderSpaceCharCode = input.renderSpaceCharCode;\n\tconst renderWhitespace = input.renderWhitespace;\n\tconst renderControlCharacters = input.renderControlCharacters;\n\n\tconst characterMapping = new CharacterMapping(len + 1, parts.length);\n\tlet lastCharacterMappingDefined = false;\n\n\tlet charIndex = 0;\n\tlet visibleColumn = startVisibleColumn;\n\tlet charOffsetInPart = 0;\n\n\tlet partDisplacement = 0;\n\tlet prevPartContentCnt = 0;\n\tlet partAbsoluteOffset = 0;\n\n\tif (containsRTL) {\n\t\tsb.appendASCIIString('');\n\t} else {\n\t\tsb.appendASCIIString('');\n\t}\n\n\tfor (let partIndex = 0, tokensLen = parts.length; partIndex < tokensLen; partIndex++) {\n\t\tpartAbsoluteOffset += prevPartContentCnt;\n\n\t\tconst part = parts[partIndex];\n\t\tconst partEndIndex = part.endIndex;\n\t\tconst partType = part.type;\n\t\tconst partRendersWhitespace = (renderWhitespace !== RenderWhitespace.None && part.isWhitespace());\n\t\tconst partRendersWhitespaceWithWidth = partRendersWhitespace && !fontIsMonospace && (partType === 'mtkw'/*only whitespace*/ || !containsForeignElements);\n\t\tconst partIsEmptyAndHasPseudoAfter = (charIndex === partEndIndex && part.isPseudoAfter());\n\t\tcharOffsetInPart = 0;\n\n\t\tsb.appendASCIIString('= fauxIndentLength) {\n\t\t\t\t\t\t_visibleColumn += charWidth;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (partRendersWhitespaceWithWidth) {\n\t\t\t\tsb.appendASCIIString(' style=\"width:');\n\t\t\t\tsb.appendASCIIString(String(spaceWidth * partContentCnt));\n\t\t\t\tsb.appendASCIIString('px\"');\n\t\t\t}\n\t\t\tsb.appendASCII(CharCode.GreaterThan);\n\n\t\t\tfor (; charIndex < partEndIndex; charIndex++) {\n\t\t\t\tcharacterMapping.setColumnInfo(charIndex + 1, partIndex - partDisplacement, charOffsetInPart, partAbsoluteOffset);\n\t\t\t\tpartDisplacement = 0;\n\t\t\t\tconst charCode = lineContent.charCodeAt(charIndex);\n\t\t\t\tlet charWidth: number;\n\n\t\t\t\tif (charCode === CharCode.Tab) {\n\t\t\t\t\tcharWidth = (tabSize - (visibleColumn % tabSize)) | 0;\n\n\t\t\t\t\tif (!canUseHalfwidthRightwardsArrow || charWidth > 1) {\n\t\t\t\t\t\tsb.write1(0x2192); // RIGHTWARDS ARROW\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsb.write1(0xFFEB); // HALFWIDTH RIGHTWARDS ARROW\n\t\t\t\t\t}\n\t\t\t\t\tfor (let space = 2; space <= charWidth; space++) {\n\t\t\t\t\t\tsb.write1(0xA0); //  \n\t\t\t\t\t}\n\n\t\t\t\t} else { // must be CharCode.Space\n\t\t\t\t\tcharWidth = 1;\n\n\t\t\t\t\tsb.write1(renderSpaceCharCode); // · or word separator middle dot\n\t\t\t\t}\n\n\t\t\t\tcharOffsetInPart += charWidth;\n\t\t\t\tif (charIndex >= fauxIndentLength) {\n\t\t\t\t\tvisibleColumn += charWidth;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tprevPartContentCnt = partContentCnt;\n\n\t\t} else {\n\n\t\t\tlet partContentCnt = 0;\n\n\t\t\tsb.appendASCII(CharCode.GreaterThan);\n\n\t\t\tfor (; charIndex < partEndIndex; charIndex++) {\n\t\t\t\tcharacterMapping.setColumnInfo(charIndex + 1, partIndex - partDisplacement, charOffsetInPart, partAbsoluteOffset);\n\t\t\t\tpartDisplacement = 0;\n\t\t\t\tconst charCode = lineContent.charCodeAt(charIndex);\n\n\t\t\t\tlet producedCharacters = 1;\n\t\t\t\tlet charWidth = 1;\n\n\t\t\t\tswitch (charCode) {\n\t\t\t\t\tcase CharCode.Tab:\n\t\t\t\t\t\tproducedCharacters = (tabSize - (visibleColumn % tabSize));\n\t\t\t\t\t\tcharWidth = producedCharacters;\n\t\t\t\t\t\tfor (let space = 1; space <= producedCharacters; space++) {\n\t\t\t\t\t\t\tsb.write1(0xA0); //  \n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CharCode.Space:\n\t\t\t\t\t\tsb.write1(0xA0); //  \n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CharCode.LessThan:\n\t\t\t\t\t\tsb.appendASCIIString('<');\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CharCode.GreaterThan:\n\t\t\t\t\t\tsb.appendASCIIString('>');\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CharCode.Ampersand:\n\t\t\t\t\t\tsb.appendASCIIString('&');\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CharCode.Null:\n\t\t\t\t\t\tif (renderControlCharacters) {\n\t\t\t\t\t\t\t// See https://unicode-table.com/en/blocks/control-pictures/\n\t\t\t\t\t\t\tsb.write1(9216);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsb.appendASCIIString('�');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CharCode.UTF8_BOM:\n\t\t\t\t\tcase CharCode.LINE_SEPARATOR:\n\t\t\t\t\tcase CharCode.PARAGRAPH_SEPARATOR:\n\t\t\t\t\tcase CharCode.NEXT_LINE:\n\t\t\t\t\t\tsb.write1(0xFFFD);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif (strings.isFullWidthCharacter(charCode)) {\n\t\t\t\t\t\t\tcharWidth++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// See https://unicode-table.com/en/blocks/control-pictures/\n\t\t\t\t\t\tif (renderControlCharacters && charCode < 32) {\n\t\t\t\t\t\t\tsb.write1(9216 + charCode);\n\t\t\t\t\t\t} else if (renderControlCharacters && charCode === 127) {\n\t\t\t\t\t\t\t// DEL\n\t\t\t\t\t\t\tsb.write1(9249);\n\t\t\t\t\t\t} else if (renderControlCharacters && isControlCharacter(charCode)) {\n\t\t\t\t\t\t\tsb.appendASCIIString('[U+');\n\t\t\t\t\t\t\tsb.appendASCIIString(to4CharHex(charCode));\n\t\t\t\t\t\t\tsb.appendASCIIString(']');\n\t\t\t\t\t\t\tproducedCharacters = 8;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsb.write1(charCode);\n\t\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcharOffsetInPart += producedCharacters;\n\t\t\t\tpartContentCnt += producedCharacters;\n\t\t\t\tif (charIndex >= fauxIndentLength) {\n\t\t\t\t\tvisibleColumn += charWidth;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tprevPartContentCnt = partContentCnt;\n\t\t}\n\n\t\tif (partIsEmptyAndHasPseudoAfter) {\n\t\t\tpartDisplacement++;\n\t\t} else {\n\t\t\tpartDisplacement = 0;\n\t\t}\n\n\t\tif (charIndex >= len && !lastCharacterMappingDefined && part.isPseudoAfter()) {\n\t\t\tlastCharacterMappingDefined = true;\n\t\t\tcharacterMapping.setColumnInfo(charIndex + 1, partIndex, charOffsetInPart, partAbsoluteOffset);\n\t\t}\n\n\t\tsb.appendASCIIString('');\n\n\t}\n\n\tif (!lastCharacterMappingDefined) {\n\t\t// When getting client rects for the last character, we will position the\n\t\t// text range at the end of the span, insteaf of at the beginning of next span\n\t\tcharacterMapping.setColumnInfo(len + 1, parts.length - 1, charOffsetInPart, partAbsoluteOffset);\n\t}\n\n\tif (isOverflowing) {\n\t\tsb.appendASCIIString('');\n\t}\n\n\tsb.appendASCIIString('');\n\n\treturn new RenderLineOutput(characterMapping, containsRTL, containsForeignElements);\n}\n\nfunction to4CharHex(n: number): string {\n\treturn n.toString(16).toUpperCase().padStart(4, '0');\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { IViewModel, IViewWhitespaceViewportData, ViewLineRenderingData, ViewModelDecoration } from 'vs/editor/common/viewModel/viewModel';\n\nexport interface IPartialViewLinesViewportData {\n\t/**\n\t * Value to be substracted from `scrollTop` (in order to vertical offset numbers < 1MM)\n\t */\n\treadonly bigNumbersDelta: number;\n\t/**\n\t * The first (partially) visible line number.\n\t */\n\treadonly startLineNumber: number;\n\t/**\n\t * The last (partially) visible line number.\n\t */\n\treadonly endLineNumber: number;\n\t/**\n\t * relativeVerticalOffset[i] is the `top` position for line at `i` + `startLineNumber`.\n\t */\n\treadonly relativeVerticalOffset: number[];\n\t/**\n\t * The centered line in the viewport.\n\t */\n\treadonly centeredLineNumber: number;\n\t/**\n\t * The first completely visible line number.\n\t */\n\treadonly completelyVisibleStartLineNumber: number;\n\t/**\n\t * The last completely visible line number.\n\t */\n\treadonly completelyVisibleEndLineNumber: number;\n}\n\n/**\n * Contains all data needed to render at a specific viewport.\n */\nexport class ViewportData {\n\n\tpublic readonly selections: Selection[];\n\n\t/**\n\t * The line number at which to start rendering (inclusive).\n\t */\n\tpublic readonly startLineNumber: number;\n\n\t/**\n\t * The line number at which to end rendering (inclusive).\n\t */\n\tpublic readonly endLineNumber: number;\n\n\t/**\n\t * relativeVerticalOffset[i] is the `top` position for line at `i` + `startLineNumber`.\n\t */\n\tpublic readonly relativeVerticalOffset: number[];\n\n\t/**\n\t * The viewport as a range (startLineNumber,1) -> (endLineNumber,maxColumn(endLineNumber)).\n\t */\n\tpublic readonly visibleRange: Range;\n\n\t/**\n\t * Value to be substracted from `scrollTop` (in order to vertical offset numbers < 1MM)\n\t */\n\tpublic readonly bigNumbersDelta: number;\n\n\t/**\n\t * Positioning information about gaps whitespace.\n\t */\n\tpublic readonly whitespaceViewportData: IViewWhitespaceViewportData[];\n\n\tprivate readonly _model: IViewModel;\n\n\tconstructor(\n\t\tselections: Selection[],\n\t\tpartialData: IPartialViewLinesViewportData,\n\t\twhitespaceViewportData: IViewWhitespaceViewportData[],\n\t\tmodel: IViewModel\n\t) {\n\t\tthis.selections = selections;\n\t\tthis.startLineNumber = partialData.startLineNumber | 0;\n\t\tthis.endLineNumber = partialData.endLineNumber | 0;\n\t\tthis.relativeVerticalOffset = partialData.relativeVerticalOffset;\n\t\tthis.bigNumbersDelta = partialData.bigNumbersDelta | 0;\n\t\tthis.whitespaceViewportData = whitespaceViewportData;\n\n\t\tthis._model = model;\n\n\t\tthis.visibleRange = new Range(\n\t\t\tpartialData.startLineNumber,\n\t\t\tthis._model.getLineMinColumn(partialData.startLineNumber),\n\t\t\tpartialData.endLineNumber,\n\t\t\tthis._model.getLineMaxColumn(partialData.endLineNumber)\n\t\t);\n\t}\n\n\tpublic getViewLineRenderingData(lineNumber: number): ViewLineRenderingData {\n\t\treturn this._model.getViewLineRenderingData(this.visibleRange, lineNumber);\n\t}\n\n\tpublic getDecorationsInViewport(): ViewModelDecoration[] {\n\t\treturn this._model.getDecorationsInViewport(this.visibleRange);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable, markAsSingleton } from 'vs/base/common/lifecycle';\nimport { RGBA8 } from 'vs/editor/common/core/rgba';\nimport { ColorId, TokenizationRegistry } from 'vs/editor/common/languages';\n\nexport class MinimapTokensColorTracker extends Disposable {\n\tprivate static _INSTANCE: MinimapTokensColorTracker | null = null;\n\tpublic static getInstance(): MinimapTokensColorTracker {\n\t\tif (!this._INSTANCE) {\n\t\t\tthis._INSTANCE = markAsSingleton(new MinimapTokensColorTracker());\n\t\t}\n\t\treturn this._INSTANCE;\n\t}\n\n\tprivate _colors!: RGBA8[];\n\tprivate _backgroundIsLight!: boolean;\n\n\tprivate readonly _onDidChange = new Emitter();\n\tpublic readonly onDidChange: Event = this._onDidChange.event;\n\n\tprivate constructor() {\n\t\tsuper();\n\t\tthis._updateColorMap();\n\t\tthis._register(TokenizationRegistry.onDidChange(e => {\n\t\t\tif (e.changedColorMap) {\n\t\t\t\tthis._updateColorMap();\n\t\t\t}\n\t\t}));\n\t}\n\n\tprivate _updateColorMap(): void {\n\t\tconst colorMap = TokenizationRegistry.getColorMap();\n\t\tif (!colorMap) {\n\t\t\tthis._colors = [RGBA8.Empty];\n\t\t\tthis._backgroundIsLight = true;\n\t\t\treturn;\n\t\t}\n\t\tthis._colors = [RGBA8.Empty];\n\t\tfor (let colorId = 1; colorId < colorMap.length; colorId++) {\n\t\t\tconst source = colorMap[colorId].rgba;\n\t\t\t// Use a VM friendly data-type\n\t\t\tthis._colors[colorId] = new RGBA8(source.r, source.g, source.b, Math.round(source.a * 255));\n\t\t}\n\t\tconst backgroundLuminosity = colorMap[ColorId.DefaultBackground].getRelativeLuminance();\n\t\tthis._backgroundIsLight = backgroundLuminosity >= 0.5;\n\t\tthis._onDidChange.fire(undefined);\n\t}\n\n\tpublic getColor(colorId: ColorId): RGBA8 {\n\t\tif (colorId < 1 || colorId >= this._colors.length) {\n\t\t\t// background color (basically invisible)\n\t\t\tcolorId = ColorId.DefaultBackground;\n\t\t}\n\t\treturn this._colors[colorId];\n\t}\n\n\tpublic backgroundIsLight(): boolean {\n\t\treturn this._backgroundIsLight;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { assertNever } from 'vs/base/common/types';\nimport { WrappingIndent } from 'vs/editor/common/config/editorOptions';\nimport { FontInfo } from 'vs/editor/common/config/fontInfo';\nimport { Position } from 'vs/editor/common/core/position';\nimport { InjectedTextCursorStops, InjectedTextOptions, PositionAffinity } from 'vs/editor/common/model';\nimport { LineInjectedText } from 'vs/editor/common/textModelEvents';\n\n/**\n * *input*:\n * ```\n * xxxxxxxxxxxxxxxxxxxxxxxxxxx\n * ```\n *\n * -> Applying injections `[i...i]`, *inputWithInjections*:\n * ```\n * xxxxxx[iiiiiiiiii]xxxxxxxxxxxxxxxxx[ii]xxxx\n * ```\n *\n * -> breaking at offsets `|` in `xxxxxx[iiiiiii|iii]xxxxxxxxxxx|xxxxxx[ii]xxxx|`:\n * ```\n * xxxxxx[iiiiiii\n * iii]xxxxxxxxxxx\n * xxxxxx[ii]xxxx\n * ```\n *\n * -> applying wrappedTextIndentLength, *output*:\n * ```\n * xxxxxx[iiiiiii\n * iii]xxxxxxxxxxx\n * xxxxxx[ii]xxxx\n * ```\n */\nexport class ModelLineProjectionData {\n\tconstructor(\n\t\tpublic injectionOffsets: number[] | null,\n\t\t/**\n\t\t * `injectionOptions.length` must equal `injectionOffsets.length`\n\t\t */\n\t\tpublic injectionOptions: InjectedTextOptions[] | null,\n\t\t/**\n\t\t * Refers to offsets after applying injections to the source.\n\t\t * The last break offset indicates the length of the source after applying injections.\n\t\t */\n\t\tpublic breakOffsets: number[],\n\t\t/**\n\t\t * Refers to offsets after applying injections\n\t\t */\n\t\tpublic breakOffsetsVisibleColumn: number[],\n\t\tpublic wrappedTextIndentLength: number\n\t) {\n\t}\n\n\tpublic getOutputLineCount(): number {\n\t\treturn this.breakOffsets.length;\n\t}\n\n\tpublic getMinOutputOffset(outputLineIndex: number): number {\n\t\tif (outputLineIndex > 0) {\n\t\t\treturn this.wrappedTextIndentLength;\n\t\t}\n\t\treturn 0;\n\t}\n\n\tpublic getLineLength(outputLineIndex: number): number {\n\t\t// These offsets refer to model text with injected text.\n\t\tconst startOffset = outputLineIndex > 0 ? this.breakOffsets[outputLineIndex - 1] : 0;\n\t\tconst endOffset = this.breakOffsets[outputLineIndex];\n\n\t\tlet lineLength = endOffset - startOffset;\n\t\tif (outputLineIndex > 0) {\n\t\t\tlineLength += this.wrappedTextIndentLength;\n\t\t}\n\t\treturn lineLength;\n\t}\n\n\tpublic getMaxOutputOffset(outputLineIndex: number): number {\n\t\treturn this.getLineLength(outputLineIndex);\n\t}\n\n\tpublic translateToInputOffset(outputLineIndex: number, outputOffset: number): number {\n\t\tif (outputLineIndex > 0) {\n\t\t\toutputOffset = Math.max(0, outputOffset - this.wrappedTextIndentLength);\n\t\t}\n\n\t\tconst offsetInInputWithInjection = outputLineIndex === 0 ? outputOffset : this.breakOffsets[outputLineIndex - 1] + outputOffset;\n\t\tlet offsetInInput = offsetInInputWithInjection;\n\n\t\tif (this.injectionOffsets !== null) {\n\t\t\tfor (let i = 0; i < this.injectionOffsets.length; i++) {\n\t\t\t\tif (offsetInInput > this.injectionOffsets[i]) {\n\t\t\t\t\tif (offsetInInput < this.injectionOffsets[i] + this.injectionOptions![i].content.length) {\n\t\t\t\t\t\t// `inputOffset` is within injected text\n\t\t\t\t\t\toffsetInInput = this.injectionOffsets[i];\n\t\t\t\t\t} else {\n\t\t\t\t\t\toffsetInInput -= this.injectionOptions![i].content.length;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn offsetInInput;\n\t}\n\n\tpublic translateToOutputPosition(inputOffset: number, affinity: PositionAffinity = PositionAffinity.None): OutputPosition {\n\t\tlet inputOffsetInInputWithInjection = inputOffset;\n\t\tif (this.injectionOffsets !== null) {\n\t\t\tfor (let i = 0; i < this.injectionOffsets.length; i++) {\n\t\t\t\tif (inputOffset < this.injectionOffsets[i]) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (affinity !== PositionAffinity.Right && inputOffset === this.injectionOffsets[i]) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tinputOffsetInInputWithInjection += this.injectionOptions![i].content.length;\n\t\t\t}\n\t\t}\n\n\t\treturn this.offsetInInputWithInjectionsToOutputPosition(inputOffsetInInputWithInjection, affinity);\n\t}\n\n\tprivate offsetInInputWithInjectionsToOutputPosition(offsetInInputWithInjections: number, affinity: PositionAffinity = PositionAffinity.None): OutputPosition {\n\t\tlet low = 0;\n\t\tlet high = this.breakOffsets.length - 1;\n\t\tlet mid = 0;\n\t\tlet midStart = 0;\n\n\t\twhile (low <= high) {\n\t\t\tmid = low + ((high - low) / 2) | 0;\n\n\t\t\tconst midStop = this.breakOffsets[mid];\n\t\t\tmidStart = mid > 0 ? this.breakOffsets[mid - 1] : 0;\n\n\t\t\tif (affinity === PositionAffinity.Left) {\n\t\t\t\tif (offsetInInputWithInjections <= midStart) {\n\t\t\t\t\thigh = mid - 1;\n\t\t\t\t} else if (offsetInInputWithInjections > midStop) {\n\t\t\t\t\tlow = mid + 1;\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (offsetInInputWithInjections < midStart) {\n\t\t\t\t\thigh = mid - 1;\n\t\t\t\t} else if (offsetInInputWithInjections >= midStop) {\n\t\t\t\t\tlow = mid + 1;\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet outputOffset = offsetInInputWithInjections - midStart;\n\t\tif (mid > 0) {\n\t\t\toutputOffset += this.wrappedTextIndentLength;\n\t\t}\n\n\t\treturn new OutputPosition(mid, outputOffset);\n\t}\n\n\tpublic normalizeOutputPosition(outputLineIndex: number, outputOffset: number, affinity: PositionAffinity): OutputPosition {\n\t\tif (this.injectionOffsets !== null) {\n\t\t\tconst offsetInInputWithInjections = this.outputPositionToOffsetInInputWithInjections(outputLineIndex, outputOffset);\n\t\t\tconst normalizedOffsetInUnwrappedLine = this.normalizeOffsetInInputWithInjectionsAroundInjections(offsetInInputWithInjections, affinity);\n\t\t\tif (normalizedOffsetInUnwrappedLine !== offsetInInputWithInjections) {\n\t\t\t\t// injected text caused a change\n\t\t\t\treturn this.offsetInInputWithInjectionsToOutputPosition(normalizedOffsetInUnwrappedLine, affinity);\n\t\t\t}\n\t\t}\n\n\t\tif (affinity === PositionAffinity.Left) {\n\t\t\tif (outputLineIndex > 0 && outputOffset === this.getMinOutputOffset(outputLineIndex)) {\n\t\t\t\treturn new OutputPosition(outputLineIndex - 1, this.getMaxOutputOffset(outputLineIndex - 1));\n\t\t\t}\n\t\t}\n\t\telse if (affinity === PositionAffinity.Right) {\n\t\t\tconst maxOutputLineIndex = this.getOutputLineCount() - 1;\n\t\t\tif (outputLineIndex < maxOutputLineIndex && outputOffset === this.getMaxOutputOffset(outputLineIndex)) {\n\t\t\t\treturn new OutputPosition(outputLineIndex + 1, this.getMinOutputOffset(outputLineIndex + 1));\n\t\t\t}\n\t\t}\n\n\t\treturn new OutputPosition(outputLineIndex, outputOffset);\n\t}\n\n\tprivate outputPositionToOffsetInInputWithInjections(outputLineIndex: number, outputOffset: number): number {\n\t\tif (outputLineIndex > 0) {\n\t\t\toutputOffset = Math.max(0, outputOffset - this.wrappedTextIndentLength);\n\t\t}\n\t\tconst result = (outputLineIndex > 0 ? this.breakOffsets[outputLineIndex - 1] : 0) + outputOffset;\n\t\treturn result;\n\t}\n\n\tprivate normalizeOffsetInInputWithInjectionsAroundInjections(offsetInInputWithInjections: number, affinity: PositionAffinity): number {\n\t\tconst injectedText = this.getInjectedTextAtOffset(offsetInInputWithInjections);\n\t\tif (!injectedText) {\n\t\t\treturn offsetInInputWithInjections;\n\t\t}\n\n\t\tif (affinity === PositionAffinity.None) {\n\t\t\tif (offsetInInputWithInjections === injectedText.offsetInInputWithInjections + injectedText.length\n\t\t\t\t&& hasRightCursorStop(this.injectionOptions![injectedText.injectedTextIndex].cursorStops)) {\n\t\t\t\treturn injectedText.offsetInInputWithInjections + injectedText.length;\n\t\t\t} else {\n\t\t\t\tlet result = injectedText.offsetInInputWithInjections;\n\t\t\t\tif (hasLeftCursorStop(this.injectionOptions![injectedText.injectedTextIndex].cursorStops)) {\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tlet index = injectedText.injectedTextIndex - 1;\n\t\t\t\twhile (index >= 0 && this.injectionOffsets![index] === this.injectionOffsets![injectedText.injectedTextIndex]) {\n\t\t\t\t\tif (hasRightCursorStop(this.injectionOptions![index].cursorStops)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tresult -= this.injectionOptions![index].content.length;\n\t\t\t\t\tif (hasLeftCursorStop(this.injectionOptions![index].cursorStops)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tindex--;\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t}\n\t\t} else if (affinity === PositionAffinity.Right) {\n\t\t\tlet result = injectedText.offsetInInputWithInjections + injectedText.length;\n\t\t\tlet index = injectedText.injectedTextIndex;\n\t\t\t// traverse all injected text that touch each other\n\t\t\twhile (index + 1 < this.injectionOffsets!.length && this.injectionOffsets![index + 1] === this.injectionOffsets![index]) {\n\t\t\t\tresult += this.injectionOptions![index + 1].content.length;\n\t\t\t\tindex++;\n\t\t\t}\n\t\t\treturn result;\n\t\t} else if (affinity === PositionAffinity.Left) {\n\t\t\t// affinity is left\n\t\t\tlet result = injectedText.offsetInInputWithInjections;\n\t\t\tlet index = injectedText.injectedTextIndex;\n\t\t\t// traverse all injected text that touch each other\n\t\t\twhile (index - 1 >= 0 && this.injectionOffsets![index - 1] === this.injectionOffsets![index]) {\n\t\t\t\tresult -= this.injectionOptions![index - 1].content.length;\n\t\t\t\tindex--;\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tassertNever(affinity);\n\t}\n\n\tpublic getInjectedText(outputLineIndex: number, outputOffset: number): InjectedText | null {\n\t\tconst offset = this.outputPositionToOffsetInInputWithInjections(outputLineIndex, outputOffset);\n\t\tconst injectedText = this.getInjectedTextAtOffset(offset);\n\t\tif (!injectedText) {\n\t\t\treturn null;\n\t\t}\n\t\treturn {\n\t\t\toptions: this.injectionOptions![injectedText.injectedTextIndex]\n\t\t};\n\t}\n\n\tprivate getInjectedTextAtOffset(offsetInInputWithInjections: number): { injectedTextIndex: number, offsetInInputWithInjections: number, length: number } | undefined {\n\t\tconst injectionOffsets = this.injectionOffsets;\n\t\tconst injectionOptions = this.injectionOptions;\n\n\t\tif (injectionOffsets !== null) {\n\t\t\tlet totalInjectedTextLengthBefore = 0;\n\t\t\tfor (let i = 0; i < injectionOffsets.length; i++) {\n\t\t\t\tconst length = injectionOptions![i].content.length;\n\t\t\t\tconst injectedTextStartOffsetInInputWithInjections = injectionOffsets[i] + totalInjectedTextLengthBefore;\n\t\t\t\tconst injectedTextEndOffsetInInputWithInjections = injectionOffsets[i] + totalInjectedTextLengthBefore + length;\n\n\t\t\t\tif (injectedTextStartOffsetInInputWithInjections > offsetInInputWithInjections) {\n\t\t\t\t\t// Injected text starts later.\n\t\t\t\t\tbreak; // All later injected texts have an even larger offset.\n\t\t\t\t}\n\n\t\t\t\tif (offsetInInputWithInjections <= injectedTextEndOffsetInInputWithInjections) {\n\t\t\t\t\t// Injected text ends after or with the given position (but also starts with or before it).\n\t\t\t\t\treturn {\n\t\t\t\t\t\tinjectedTextIndex: i,\n\t\t\t\t\t\toffsetInInputWithInjections: injectedTextStartOffsetInInputWithInjections,\n\t\t\t\t\t\tlength\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\ttotalInjectedTextLengthBefore += length;\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n}\n\nfunction hasRightCursorStop(cursorStop: InjectedTextCursorStops | null | undefined): boolean {\n\tif (cursorStop === null || cursorStop === undefined) { return true; }\n\treturn cursorStop === InjectedTextCursorStops.Right || cursorStop === InjectedTextCursorStops.Both;\n}\nfunction hasLeftCursorStop(cursorStop: InjectedTextCursorStops | null | undefined): boolean {\n\tif (cursorStop === null || cursorStop === undefined) { return true; }\n\treturn cursorStop === InjectedTextCursorStops.Left || cursorStop === InjectedTextCursorStops.Both;\n}\n\nexport class InjectedText {\n\tconstructor(public readonly options: InjectedTextOptions) { }\n}\n\nexport class OutputPosition {\n\toutputLineIndex: number;\n\toutputOffset: number;\n\n\tconstructor(outputLineIndex: number, outputOffset: number) {\n\t\tthis.outputLineIndex = outputLineIndex;\n\t\tthis.outputOffset = outputOffset;\n\t}\n\n\ttoString(): string {\n\t\treturn `${this.outputLineIndex}:${this.outputOffset}`;\n\t}\n\n\ttoPosition(baseLineNumber: number): Position {\n\t\treturn new Position(baseLineNumber + this.outputLineIndex, this.outputOffset + 1);\n\t}\n}\n\nexport interface ILineBreaksComputerFactory {\n\tcreateLineBreaksComputer(fontInfo: FontInfo, tabSize: number, wrappingColumn: number, wrappingIndent: WrappingIndent): ILineBreaksComputer;\n}\n\nexport interface ILineBreaksComputer {\n\t/**\n\t * Pass in `previousLineBreakData` if the only difference is in breaking columns!!!\n\t */\n\taddRequest(lineText: string, injectedText: LineInjectedText[] | null, previousLineBreakData: ModelLineProjectionData | null): void;\n\tfinalize(): (ModelLineProjectionData | null)[];\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport * as strings from 'vs/base/common/strings';\nimport { WrappingIndent, IComputedEditorOptions, EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { CharacterClassifier } from 'vs/editor/common/core/characterClassifier';\nimport { FontInfo } from 'vs/editor/common/config/fontInfo';\nimport { LineInjectedText } from 'vs/editor/common/textModelEvents';\nimport { InjectedTextOptions } from 'vs/editor/common/model';\nimport { ILineBreaksComputerFactory, ILineBreaksComputer, ModelLineProjectionData } from 'vs/editor/common/viewModel/modelLineProjectionData';\n\nexport class MonospaceLineBreaksComputerFactory implements ILineBreaksComputerFactory {\n\tpublic static create(options: IComputedEditorOptions): MonospaceLineBreaksComputerFactory {\n\t\treturn new MonospaceLineBreaksComputerFactory(\n\t\t\toptions.get(EditorOption.wordWrapBreakBeforeCharacters),\n\t\t\toptions.get(EditorOption.wordWrapBreakAfterCharacters)\n\t\t);\n\t}\n\n\tprivate readonly classifier: WrappingCharacterClassifier;\n\n\tconstructor(breakBeforeChars: string, breakAfterChars: string) {\n\t\tthis.classifier = new WrappingCharacterClassifier(breakBeforeChars, breakAfterChars);\n\t}\n\n\tpublic createLineBreaksComputer(fontInfo: FontInfo, tabSize: number, wrappingColumn: number, wrappingIndent: WrappingIndent): ILineBreaksComputer {\n\t\tconst requests: string[] = [];\n\t\tconst injectedTexts: (LineInjectedText[] | null)[] = [];\n\t\tconst previousBreakingData: (ModelLineProjectionData | null)[] = [];\n\t\treturn {\n\t\t\taddRequest: (lineText: string, injectedText: LineInjectedText[] | null, previousLineBreakData: ModelLineProjectionData | null) => {\n\t\t\t\trequests.push(lineText);\n\t\t\t\tinjectedTexts.push(injectedText);\n\t\t\t\tpreviousBreakingData.push(previousLineBreakData);\n\t\t\t},\n\t\t\tfinalize: () => {\n\t\t\t\tconst columnsForFullWidthChar = fontInfo.typicalFullwidthCharacterWidth / fontInfo.typicalHalfwidthCharacterWidth;\n\t\t\t\tconst result: (ModelLineProjectionData | null)[] = [];\n\t\t\t\tfor (let i = 0, len = requests.length; i < len; i++) {\n\t\t\t\t\tconst injectedText = injectedTexts[i];\n\t\t\t\t\tconst previousLineBreakData = previousBreakingData[i];\n\t\t\t\t\tif (previousLineBreakData && !previousLineBreakData.injectionOptions && !injectedText) {\n\t\t\t\t\t\tresult[i] = createLineBreaksFromPreviousLineBreaks(this.classifier, previousLineBreakData, requests[i], tabSize, wrappingColumn, columnsForFullWidthChar, wrappingIndent);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult[i] = createLineBreaks(this.classifier, requests[i], injectedText, tabSize, wrappingColumn, columnsForFullWidthChar, wrappingIndent);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tarrPool1.length = 0;\n\t\t\t\tarrPool2.length = 0;\n\t\t\t\treturn result;\n\t\t\t}\n\t\t};\n\t}\n}\n\nconst enum CharacterClass {\n\tNONE = 0,\n\tBREAK_BEFORE = 1,\n\tBREAK_AFTER = 2,\n\tBREAK_IDEOGRAPHIC = 3 // for Han and Kana.\n}\n\nclass WrappingCharacterClassifier extends CharacterClassifier {\n\n\tconstructor(BREAK_BEFORE: string, BREAK_AFTER: string) {\n\t\tsuper(CharacterClass.NONE);\n\n\t\tfor (let i = 0; i < BREAK_BEFORE.length; i++) {\n\t\t\tthis.set(BREAK_BEFORE.charCodeAt(i), CharacterClass.BREAK_BEFORE);\n\t\t}\n\n\t\tfor (let i = 0; i < BREAK_AFTER.length; i++) {\n\t\t\tthis.set(BREAK_AFTER.charCodeAt(i), CharacterClass.BREAK_AFTER);\n\t\t}\n\t}\n\n\tpublic override get(charCode: number): CharacterClass {\n\t\tif (charCode >= 0 && charCode < 256) {\n\t\t\treturn this._asciiMap[charCode];\n\t\t} else {\n\t\t\t// Initialize CharacterClass.BREAK_IDEOGRAPHIC for these Unicode ranges:\n\t\t\t// 1. CJK Unified Ideographs (0x4E00 -- 0x9FFF)\n\t\t\t// 2. CJK Unified Ideographs Extension A (0x3400 -- 0x4DBF)\n\t\t\t// 3. Hiragana and Katakana (0x3040 -- 0x30FF)\n\t\t\tif (\n\t\t\t\t(charCode >= 0x3040 && charCode <= 0x30FF)\n\t\t\t\t|| (charCode >= 0x3400 && charCode <= 0x4DBF)\n\t\t\t\t|| (charCode >= 0x4E00 && charCode <= 0x9FFF)\n\t\t\t) {\n\t\t\t\treturn CharacterClass.BREAK_IDEOGRAPHIC;\n\t\t\t}\n\n\t\t\treturn (this._map.get(charCode) || this._defaultValue);\n\t\t}\n\t}\n}\n\nlet arrPool1: number[] = [];\nlet arrPool2: number[] = [];\n\nfunction createLineBreaksFromPreviousLineBreaks(classifier: WrappingCharacterClassifier, previousBreakingData: ModelLineProjectionData, lineText: string, tabSize: number, firstLineBreakColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent): ModelLineProjectionData | null {\n\tif (firstLineBreakColumn === -1) {\n\t\treturn null;\n\t}\n\n\tconst len = lineText.length;\n\tif (len <= 1) {\n\t\treturn null;\n\t}\n\n\tconst prevBreakingOffsets = previousBreakingData.breakOffsets;\n\tconst prevBreakingOffsetsVisibleColumn = previousBreakingData.breakOffsetsVisibleColumn;\n\n\tconst wrappedTextIndentLength = computeWrappedTextIndentLength(lineText, tabSize, firstLineBreakColumn, columnsForFullWidthChar, wrappingIndent);\n\tconst wrappedLineBreakColumn = firstLineBreakColumn - wrappedTextIndentLength;\n\n\tconst breakingOffsets: number[] = arrPool1;\n\tconst breakingOffsetsVisibleColumn: number[] = arrPool2;\n\tlet breakingOffsetsCount = 0;\n\tlet lastBreakingOffset = 0;\n\tlet lastBreakingOffsetVisibleColumn = 0;\n\n\tlet breakingColumn = firstLineBreakColumn;\n\tconst prevLen = prevBreakingOffsets.length;\n\tlet prevIndex = 0;\n\n\tif (prevIndex >= 0) {\n\t\tlet bestDistance = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex] - breakingColumn);\n\t\twhile (prevIndex + 1 < prevLen) {\n\t\t\tconst distance = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex + 1] - breakingColumn);\n\t\t\tif (distance >= bestDistance) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbestDistance = distance;\n\t\t\tprevIndex++;\n\t\t}\n\t}\n\n\twhile (prevIndex < prevLen) {\n\t\t// Allow for prevIndex to be -1 (for the case where we hit a tab when walking backwards from the first break)\n\t\tlet prevBreakOffset = prevIndex < 0 ? 0 : prevBreakingOffsets[prevIndex];\n\t\tlet prevBreakOffsetVisibleColumn = prevIndex < 0 ? 0 : prevBreakingOffsetsVisibleColumn[prevIndex];\n\t\tif (lastBreakingOffset > prevBreakOffset) {\n\t\t\tprevBreakOffset = lastBreakingOffset;\n\t\t\tprevBreakOffsetVisibleColumn = lastBreakingOffsetVisibleColumn;\n\t\t}\n\n\t\tlet breakOffset = 0;\n\t\tlet breakOffsetVisibleColumn = 0;\n\n\t\tlet forcedBreakOffset = 0;\n\t\tlet forcedBreakOffsetVisibleColumn = 0;\n\n\t\t// initially, we search as much as possible to the right (if it fits)\n\t\tif (prevBreakOffsetVisibleColumn <= breakingColumn) {\n\t\t\tlet visibleColumn = prevBreakOffsetVisibleColumn;\n\t\t\tlet prevCharCode = prevBreakOffset === 0 ? CharCode.Null : lineText.charCodeAt(prevBreakOffset - 1);\n\t\t\tlet prevCharCodeClass = prevBreakOffset === 0 ? CharacterClass.NONE : classifier.get(prevCharCode);\n\t\t\tlet entireLineFits = true;\n\t\t\tfor (let i = prevBreakOffset; i < len; i++) {\n\t\t\t\tconst charStartOffset = i;\n\t\t\t\tconst charCode = lineText.charCodeAt(i);\n\t\t\t\tlet charCodeClass: number;\n\t\t\t\tlet charWidth: number;\n\n\t\t\t\tif (strings.isHighSurrogate(charCode)) {\n\t\t\t\t\t// A surrogate pair must always be considered as a single unit, so it is never to be broken\n\t\t\t\t\ti++;\n\t\t\t\t\tcharCodeClass = CharacterClass.NONE;\n\t\t\t\t\tcharWidth = 2;\n\t\t\t\t} else {\n\t\t\t\t\tcharCodeClass = classifier.get(charCode);\n\t\t\t\t\tcharWidth = computeCharWidth(charCode, visibleColumn, tabSize, columnsForFullWidthChar);\n\t\t\t\t}\n\n\t\t\t\tif (charStartOffset > lastBreakingOffset && canBreak(prevCharCode, prevCharCodeClass, charCode, charCodeClass)) {\n\t\t\t\t\tbreakOffset = charStartOffset;\n\t\t\t\t\tbreakOffsetVisibleColumn = visibleColumn;\n\t\t\t\t}\n\n\t\t\t\tvisibleColumn += charWidth;\n\n\t\t\t\t// check if adding character at `i` will go over the breaking column\n\t\t\t\tif (visibleColumn > breakingColumn) {\n\t\t\t\t\t// We need to break at least before character at `i`:\n\t\t\t\t\tif (charStartOffset > lastBreakingOffset) {\n\t\t\t\t\t\tforcedBreakOffset = charStartOffset;\n\t\t\t\t\t\tforcedBreakOffsetVisibleColumn = visibleColumn - charWidth;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// we need to advance at least by one character\n\t\t\t\t\t\tforcedBreakOffset = i + 1;\n\t\t\t\t\t\tforcedBreakOffsetVisibleColumn = visibleColumn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (visibleColumn - breakOffsetVisibleColumn > wrappedLineBreakColumn) {\n\t\t\t\t\t\t// Cannot break at `breakOffset` => reset it if it was set\n\t\t\t\t\t\tbreakOffset = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tentireLineFits = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tprevCharCode = charCode;\n\t\t\t\tprevCharCodeClass = charCodeClass;\n\t\t\t}\n\n\t\t\tif (entireLineFits) {\n\t\t\t\t// there is no more need to break => stop the outer loop!\n\t\t\t\tif (breakingOffsetsCount > 0) {\n\t\t\t\t\t// Add last segment, no need to assign to `lastBreakingOffset` and `lastBreakingOffsetVisibleColumn`\n\t\t\t\t\tbreakingOffsets[breakingOffsetsCount] = prevBreakingOffsets[prevBreakingOffsets.length - 1];\n\t\t\t\t\tbreakingOffsetsVisibleColumn[breakingOffsetsCount] = prevBreakingOffsetsVisibleColumn[prevBreakingOffsets.length - 1];\n\t\t\t\t\tbreakingOffsetsCount++;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (breakOffset === 0) {\n\t\t\t// must search left\n\t\t\tlet visibleColumn = prevBreakOffsetVisibleColumn;\n\t\t\tlet charCode = lineText.charCodeAt(prevBreakOffset);\n\t\t\tlet charCodeClass = classifier.get(charCode);\n\t\t\tlet hitATabCharacter = false;\n\t\t\tfor (let i = prevBreakOffset - 1; i >= lastBreakingOffset; i--) {\n\t\t\t\tconst charStartOffset = i + 1;\n\t\t\t\tconst prevCharCode = lineText.charCodeAt(i);\n\n\t\t\t\tif (prevCharCode === CharCode.Tab) {\n\t\t\t\t\t// cannot determine the width of a tab when going backwards, so we must go forwards\n\t\t\t\t\thitATabCharacter = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tlet prevCharCodeClass: number;\n\t\t\t\tlet prevCharWidth: number;\n\n\t\t\t\tif (strings.isLowSurrogate(prevCharCode)) {\n\t\t\t\t\t// A surrogate pair must always be considered as a single unit, so it is never to be broken\n\t\t\t\t\ti--;\n\t\t\t\t\tprevCharCodeClass = CharacterClass.NONE;\n\t\t\t\t\tprevCharWidth = 2;\n\t\t\t\t} else {\n\t\t\t\t\tprevCharCodeClass = classifier.get(prevCharCode);\n\t\t\t\t\tprevCharWidth = (strings.isFullWidthCharacter(prevCharCode) ? columnsForFullWidthChar : 1);\n\t\t\t\t}\n\n\t\t\t\tif (visibleColumn <= breakingColumn) {\n\t\t\t\t\tif (forcedBreakOffset === 0) {\n\t\t\t\t\t\tforcedBreakOffset = charStartOffset;\n\t\t\t\t\t\tforcedBreakOffsetVisibleColumn = visibleColumn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (visibleColumn <= breakingColumn - wrappedLineBreakColumn) {\n\t\t\t\t\t\t// went too far!\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (canBreak(prevCharCode, prevCharCodeClass, charCode, charCodeClass)) {\n\t\t\t\t\t\tbreakOffset = charStartOffset;\n\t\t\t\t\t\tbreakOffsetVisibleColumn = visibleColumn;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvisibleColumn -= prevCharWidth;\n\t\t\t\tcharCode = prevCharCode;\n\t\t\t\tcharCodeClass = prevCharCodeClass;\n\t\t\t}\n\n\t\t\tif (breakOffset !== 0) {\n\t\t\t\tconst remainingWidthOfNextLine = wrappedLineBreakColumn - (forcedBreakOffsetVisibleColumn - breakOffsetVisibleColumn);\n\t\t\t\tif (remainingWidthOfNextLine <= tabSize) {\n\t\t\t\t\tconst charCodeAtForcedBreakOffset = lineText.charCodeAt(forcedBreakOffset);\n\t\t\t\t\tlet charWidth: number;\n\t\t\t\t\tif (strings.isHighSurrogate(charCodeAtForcedBreakOffset)) {\n\t\t\t\t\t\t// A surrogate pair must always be considered as a single unit, so it is never to be broken\n\t\t\t\t\t\tcharWidth = 2;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcharWidth = computeCharWidth(charCodeAtForcedBreakOffset, forcedBreakOffsetVisibleColumn, tabSize, columnsForFullWidthChar);\n\t\t\t\t\t}\n\t\t\t\t\tif (remainingWidthOfNextLine - charWidth < 0) {\n\t\t\t\t\t\t// it is not worth it to break at breakOffset, it just introduces an extra needless line!\n\t\t\t\t\t\tbreakOffset = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (hitATabCharacter) {\n\t\t\t\t// cannot determine the width of a tab when going backwards, so we must go forwards from the previous break\n\t\t\t\tprevIndex--;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif (breakOffset === 0) {\n\t\t\t// Could not find a good breaking point\n\t\t\tbreakOffset = forcedBreakOffset;\n\t\t\tbreakOffsetVisibleColumn = forcedBreakOffsetVisibleColumn;\n\t\t}\n\n\t\tif (breakOffset <= lastBreakingOffset) {\n\t\t\t// Make sure that we are advancing (at least one character)\n\t\t\tconst charCode = lineText.charCodeAt(lastBreakingOffset);\n\t\t\tif (strings.isHighSurrogate(charCode)) {\n\t\t\t\t// A surrogate pair must always be considered as a single unit, so it is never to be broken\n\t\t\t\tbreakOffset = lastBreakingOffset + 2;\n\t\t\t\tbreakOffsetVisibleColumn = lastBreakingOffsetVisibleColumn + 2;\n\t\t\t} else {\n\t\t\t\tbreakOffset = lastBreakingOffset + 1;\n\t\t\t\tbreakOffsetVisibleColumn = lastBreakingOffsetVisibleColumn + computeCharWidth(charCode, lastBreakingOffsetVisibleColumn, tabSize, columnsForFullWidthChar);\n\t\t\t}\n\t\t}\n\n\t\tlastBreakingOffset = breakOffset;\n\t\tbreakingOffsets[breakingOffsetsCount] = breakOffset;\n\t\tlastBreakingOffsetVisibleColumn = breakOffsetVisibleColumn;\n\t\tbreakingOffsetsVisibleColumn[breakingOffsetsCount] = breakOffsetVisibleColumn;\n\t\tbreakingOffsetsCount++;\n\t\tbreakingColumn = breakOffsetVisibleColumn + wrappedLineBreakColumn;\n\n\t\twhile (prevIndex < 0 || (prevIndex < prevLen && prevBreakingOffsetsVisibleColumn[prevIndex] < breakOffsetVisibleColumn)) {\n\t\t\tprevIndex++;\n\t\t}\n\n\t\tlet bestDistance = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex] - breakingColumn);\n\t\twhile (prevIndex + 1 < prevLen) {\n\t\t\tconst distance = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex + 1] - breakingColumn);\n\t\t\tif (distance >= bestDistance) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbestDistance = distance;\n\t\t\tprevIndex++;\n\t\t}\n\t}\n\n\tif (breakingOffsetsCount === 0) {\n\t\treturn null;\n\t}\n\n\t// Doing here some object reuse which ends up helping a huge deal with GC pauses!\n\tbreakingOffsets.length = breakingOffsetsCount;\n\tbreakingOffsetsVisibleColumn.length = breakingOffsetsCount;\n\tarrPool1 = previousBreakingData.breakOffsets;\n\tarrPool2 = previousBreakingData.breakOffsetsVisibleColumn;\n\tpreviousBreakingData.breakOffsets = breakingOffsets;\n\tpreviousBreakingData.breakOffsetsVisibleColumn = breakingOffsetsVisibleColumn;\n\tpreviousBreakingData.wrappedTextIndentLength = wrappedTextIndentLength;\n\treturn previousBreakingData;\n}\n\nfunction createLineBreaks(classifier: WrappingCharacterClassifier, _lineText: string, injectedTexts: LineInjectedText[] | null, tabSize: number, firstLineBreakColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent): ModelLineProjectionData | null {\n\tconst lineText = LineInjectedText.applyInjectedText(_lineText, injectedTexts);\n\n\tlet injectionOptions: InjectedTextOptions[] | null;\n\tlet injectionOffsets: number[] | null;\n\tif (injectedTexts && injectedTexts.length > 0) {\n\t\tinjectionOptions = injectedTexts.map(t => t.options);\n\t\tinjectionOffsets = injectedTexts.map(text => text.column - 1);\n\t} else {\n\t\tinjectionOptions = null;\n\t\tinjectionOffsets = null;\n\t}\n\n\tif (firstLineBreakColumn === -1) {\n\t\tif (!injectionOptions) {\n\t\t\treturn null;\n\t\t}\n\t\t// creating a `LineBreakData` with an invalid `breakOffsetsVisibleColumn` is OK\n\t\t// because `breakOffsetsVisibleColumn` will never be used because it contains injected text\n\t\treturn new ModelLineProjectionData(injectionOffsets, injectionOptions, [lineText.length], [], 0);\n\t}\n\n\tconst len = lineText.length;\n\tif (len <= 1) {\n\t\tif (!injectionOptions) {\n\t\t\treturn null;\n\t\t}\n\t\t// creating a `LineBreakData` with an invalid `breakOffsetsVisibleColumn` is OK\n\t\t// because `breakOffsetsVisibleColumn` will never be used because it contains injected text\n\t\treturn new ModelLineProjectionData(injectionOffsets, injectionOptions, [lineText.length], [], 0);\n\t}\n\n\tconst wrappedTextIndentLength = computeWrappedTextIndentLength(lineText, tabSize, firstLineBreakColumn, columnsForFullWidthChar, wrappingIndent);\n\tconst wrappedLineBreakColumn = firstLineBreakColumn - wrappedTextIndentLength;\n\n\tconst breakingOffsets: number[] = [];\n\tconst breakingOffsetsVisibleColumn: number[] = [];\n\tlet breakingOffsetsCount: number = 0;\n\tlet breakOffset = 0;\n\tlet breakOffsetVisibleColumn = 0;\n\n\tlet breakingColumn = firstLineBreakColumn;\n\tlet prevCharCode = lineText.charCodeAt(0);\n\tlet prevCharCodeClass = classifier.get(prevCharCode);\n\tlet visibleColumn = computeCharWidth(prevCharCode, 0, tabSize, columnsForFullWidthChar);\n\n\tlet startOffset = 1;\n\tif (strings.isHighSurrogate(prevCharCode)) {\n\t\t// A surrogate pair must always be considered as a single unit, so it is never to be broken\n\t\tvisibleColumn += 1;\n\t\tprevCharCode = lineText.charCodeAt(1);\n\t\tprevCharCodeClass = classifier.get(prevCharCode);\n\t\tstartOffset++;\n\t}\n\n\tfor (let i = startOffset; i < len; i++) {\n\t\tconst charStartOffset = i;\n\t\tconst charCode = lineText.charCodeAt(i);\n\t\tlet charCodeClass: number;\n\t\tlet charWidth: number;\n\n\t\tif (strings.isHighSurrogate(charCode)) {\n\t\t\t// A surrogate pair must always be considered as a single unit, so it is never to be broken\n\t\t\ti++;\n\t\t\tcharCodeClass = CharacterClass.NONE;\n\t\t\tcharWidth = 2;\n\t\t} else {\n\t\t\tcharCodeClass = classifier.get(charCode);\n\t\t\tcharWidth = computeCharWidth(charCode, visibleColumn, tabSize, columnsForFullWidthChar);\n\t\t}\n\n\t\tif (canBreak(prevCharCode, prevCharCodeClass, charCode, charCodeClass)) {\n\t\t\tbreakOffset = charStartOffset;\n\t\t\tbreakOffsetVisibleColumn = visibleColumn;\n\t\t}\n\n\t\tvisibleColumn += charWidth;\n\n\t\t// check if adding character at `i` will go over the breaking column\n\t\tif (visibleColumn > breakingColumn) {\n\t\t\t// We need to break at least before character at `i`:\n\n\t\t\tif (breakOffset === 0 || visibleColumn - breakOffsetVisibleColumn > wrappedLineBreakColumn) {\n\t\t\t\t// Cannot break at `breakOffset`, must break at `i`\n\t\t\t\tbreakOffset = charStartOffset;\n\t\t\t\tbreakOffsetVisibleColumn = visibleColumn - charWidth;\n\t\t\t}\n\n\t\t\tbreakingOffsets[breakingOffsetsCount] = breakOffset;\n\t\t\tbreakingOffsetsVisibleColumn[breakingOffsetsCount] = breakOffsetVisibleColumn;\n\t\t\tbreakingOffsetsCount++;\n\t\t\tbreakingColumn = breakOffsetVisibleColumn + wrappedLineBreakColumn;\n\t\t\tbreakOffset = 0;\n\t\t}\n\n\t\tprevCharCode = charCode;\n\t\tprevCharCodeClass = charCodeClass;\n\t}\n\n\tif (breakingOffsetsCount === 0 && (!injectedTexts || injectedTexts.length === 0)) {\n\t\treturn null;\n\t}\n\n\t// Add last segment\n\tbreakingOffsets[breakingOffsetsCount] = len;\n\tbreakingOffsetsVisibleColumn[breakingOffsetsCount] = visibleColumn;\n\n\treturn new ModelLineProjectionData(injectionOffsets, injectionOptions, breakingOffsets, breakingOffsetsVisibleColumn, wrappedTextIndentLength);\n}\n\nfunction computeCharWidth(charCode: number, visibleColumn: number, tabSize: number, columnsForFullWidthChar: number): number {\n\tif (charCode === CharCode.Tab) {\n\t\treturn (tabSize - (visibleColumn % tabSize));\n\t}\n\tif (strings.isFullWidthCharacter(charCode)) {\n\t\treturn columnsForFullWidthChar;\n\t}\n\tif (charCode < 32) {\n\t\t// when using `editor.renderControlCharacters`, the substitutions are often wide\n\t\treturn columnsForFullWidthChar;\n\t}\n\treturn 1;\n}\n\nfunction tabCharacterWidth(visibleColumn: number, tabSize: number): number {\n\treturn (tabSize - (visibleColumn % tabSize));\n}\n\n/**\n * Kinsoku Shori : Don't break after a leading character, like an open bracket\n * Kinsoku Shori : Don't break before a trailing character, like a period\n */\nfunction canBreak(prevCharCode: number, prevCharCodeClass: CharacterClass, charCode: number, charCodeClass: CharacterClass): boolean {\n\treturn (\n\t\tcharCode !== CharCode.Space\n\t\t&& (\n\t\t\t(prevCharCodeClass === CharacterClass.BREAK_AFTER)\n\t\t\t|| (prevCharCodeClass === CharacterClass.BREAK_IDEOGRAPHIC && charCodeClass !== CharacterClass.BREAK_AFTER)\n\t\t\t|| (charCodeClass === CharacterClass.BREAK_BEFORE)\n\t\t\t|| (charCodeClass === CharacterClass.BREAK_IDEOGRAPHIC && prevCharCodeClass !== CharacterClass.BREAK_BEFORE)\n\t\t)\n\t);\n}\n\nfunction computeWrappedTextIndentLength(lineText: string, tabSize: number, firstLineBreakColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent): number {\n\tlet wrappedTextIndentLength = 0;\n\tif (wrappingIndent !== WrappingIndent.None) {\n\t\tconst firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineText);\n\t\tif (firstNonWhitespaceIndex !== -1) {\n\t\t\t// Track existing indent\n\n\t\t\tfor (let i = 0; i < firstNonWhitespaceIndex; i++) {\n\t\t\t\tconst charWidth = (lineText.charCodeAt(i) === CharCode.Tab ? tabCharacterWidth(wrappedTextIndentLength, tabSize) : 1);\n\t\t\t\twrappedTextIndentLength += charWidth;\n\t\t\t}\n\n\t\t\t// Increase indent of continuation lines, if desired\n\t\t\tconst numberOfAdditionalTabs = (wrappingIndent === WrappingIndent.DeepIndent ? 2 : wrappingIndent === WrappingIndent.Indent ? 1 : 0);\n\t\t\tfor (let i = 0; i < numberOfAdditionalTabs; i++) {\n\t\t\t\tconst charWidth = tabCharacterWidth(wrappedTextIndentLength, tabSize);\n\t\t\t\twrappedTextIndentLength += charWidth;\n\t\t\t}\n\n\t\t\t// Force sticking to beginning of line if no character would fit except for the indentation\n\t\t\tif (wrappedTextIndentLength + columnsForFullWidthChar > firstLineBreakColumn) {\n\t\t\t\twrappedTextIndentLength = 0;\n\t\t\t}\n\t\t}\n\t}\n\treturn wrappedTextIndentLength;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nconst enum Constants {\n\tMINIMUM_HEIGHT = 4\n}\n\nexport class ColorZone {\n\t_colorZoneBrand: void = undefined;\n\n\tpublic readonly from: number;\n\tpublic readonly to: number;\n\tpublic readonly colorId: number;\n\n\tconstructor(from: number, to: number, colorId: number) {\n\t\tthis.from = from | 0;\n\t\tthis.to = to | 0;\n\t\tthis.colorId = colorId | 0;\n\t}\n\n\tpublic static compare(a: ColorZone, b: ColorZone): number {\n\t\tif (a.colorId === b.colorId) {\n\t\t\tif (a.from === b.from) {\n\t\t\t\treturn a.to - b.to;\n\t\t\t}\n\t\t\treturn a.from - b.from;\n\t\t}\n\t\treturn a.colorId - b.colorId;\n\t}\n}\n\n/**\n * A zone in the overview ruler\n */\nexport class OverviewRulerZone {\n\t_overviewRulerZoneBrand: void = undefined;\n\n\tpublic readonly startLineNumber: number;\n\tpublic readonly endLineNumber: number;\n\tpublic readonly color: string;\n\n\tprivate _colorZone: ColorZone | null;\n\n\tconstructor(\n\t\tstartLineNumber: number,\n\t\tendLineNumber: number,\n\t\tcolor: string\n\t) {\n\t\tthis.startLineNumber = startLineNumber;\n\t\tthis.endLineNumber = endLineNumber;\n\t\tthis.color = color;\n\t\tthis._colorZone = null;\n\t}\n\n\tpublic static compare(a: OverviewRulerZone, b: OverviewRulerZone): number {\n\t\tif (a.color === b.color) {\n\t\t\tif (a.startLineNumber === b.startLineNumber) {\n\t\t\t\treturn a.endLineNumber - b.endLineNumber;\n\t\t\t}\n\t\t\treturn a.startLineNumber - b.startLineNumber;\n\t\t}\n\t\treturn a.color < b.color ? -1 : 1;\n\t}\n\n\tpublic setColorZone(colorZone: ColorZone): void {\n\t\tthis._colorZone = colorZone;\n\t}\n\n\tpublic getColorZones(): ColorZone | null {\n\t\treturn this._colorZone;\n\t}\n}\n\nexport class OverviewZoneManager {\n\n\tprivate readonly _getVerticalOffsetForLine: (lineNumber: number) => number;\n\tprivate _zones: OverviewRulerZone[];\n\tprivate _colorZonesInvalid: boolean;\n\tprivate _lineHeight: number;\n\tprivate _domWidth: number;\n\tprivate _domHeight: number;\n\tprivate _outerHeight: number;\n\tprivate _pixelRatio: number;\n\n\tprivate _lastAssignedId: number;\n\tprivate readonly _color2Id: { [color: string]: number; };\n\tprivate readonly _id2Color: string[];\n\n\tconstructor(getVerticalOffsetForLine: (lineNumber: number) => number) {\n\t\tthis._getVerticalOffsetForLine = getVerticalOffsetForLine;\n\t\tthis._zones = [];\n\t\tthis._colorZonesInvalid = false;\n\t\tthis._lineHeight = 0;\n\t\tthis._domWidth = 0;\n\t\tthis._domHeight = 0;\n\t\tthis._outerHeight = 0;\n\t\tthis._pixelRatio = 1;\n\n\t\tthis._lastAssignedId = 0;\n\t\tthis._color2Id = Object.create(null);\n\t\tthis._id2Color = [];\n\t}\n\n\tpublic getId2Color(): string[] {\n\t\treturn this._id2Color;\n\t}\n\n\tpublic setZones(newZones: OverviewRulerZone[]): void {\n\t\tthis._zones = newZones;\n\t\tthis._zones.sort(OverviewRulerZone.compare);\n\t}\n\n\tpublic setLineHeight(lineHeight: number): boolean {\n\t\tif (this._lineHeight === lineHeight) {\n\t\t\treturn false;\n\t\t}\n\t\tthis._lineHeight = lineHeight;\n\t\tthis._colorZonesInvalid = true;\n\t\treturn true;\n\t}\n\n\tpublic setPixelRatio(pixelRatio: number): void {\n\t\tthis._pixelRatio = pixelRatio;\n\t\tthis._colorZonesInvalid = true;\n\t}\n\n\tpublic getDOMWidth(): number {\n\t\treturn this._domWidth;\n\t}\n\n\tpublic getCanvasWidth(): number {\n\t\treturn this._domWidth * this._pixelRatio;\n\t}\n\n\tpublic setDOMWidth(width: number): boolean {\n\t\tif (this._domWidth === width) {\n\t\t\treturn false;\n\t\t}\n\t\tthis._domWidth = width;\n\t\tthis._colorZonesInvalid = true;\n\t\treturn true;\n\t}\n\n\tpublic getDOMHeight(): number {\n\t\treturn this._domHeight;\n\t}\n\n\tpublic getCanvasHeight(): number {\n\t\treturn this._domHeight * this._pixelRatio;\n\t}\n\n\tpublic setDOMHeight(height: number): boolean {\n\t\tif (this._domHeight === height) {\n\t\t\treturn false;\n\t\t}\n\t\tthis._domHeight = height;\n\t\tthis._colorZonesInvalid = true;\n\t\treturn true;\n\t}\n\n\tpublic getOuterHeight(): number {\n\t\treturn this._outerHeight;\n\t}\n\n\tpublic setOuterHeight(outerHeight: number): boolean {\n\t\tif (this._outerHeight === outerHeight) {\n\t\t\treturn false;\n\t\t}\n\t\tthis._outerHeight = outerHeight;\n\t\tthis._colorZonesInvalid = true;\n\t\treturn true;\n\t}\n\n\tpublic resolveColorZones(): ColorZone[] {\n\t\tconst colorZonesInvalid = this._colorZonesInvalid;\n\t\tconst lineHeight = Math.floor(this._lineHeight);\n\t\tconst totalHeight = Math.floor(this.getCanvasHeight());\n\t\tconst outerHeight = Math.floor(this._outerHeight);\n\t\tconst heightRatio = totalHeight / outerHeight;\n\t\tconst halfMinimumHeight = Math.floor(Constants.MINIMUM_HEIGHT * this._pixelRatio / 2);\n\n\t\tconst allColorZones: ColorZone[] = [];\n\t\tfor (let i = 0, len = this._zones.length; i < len; i++) {\n\t\t\tconst zone = this._zones[i];\n\n\t\t\tif (!colorZonesInvalid) {\n\t\t\t\tconst colorZone = zone.getColorZones();\n\t\t\t\tif (colorZone) {\n\t\t\t\t\tallColorZones.push(colorZone);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst y1 = Math.floor(heightRatio * (this._getVerticalOffsetForLine(zone.startLineNumber)));\n\t\t\tconst y2 = Math.floor(heightRatio * (this._getVerticalOffsetForLine(zone.endLineNumber) + lineHeight));\n\n\t\t\tlet ycenter = Math.floor((y1 + y2) / 2);\n\t\t\tlet halfHeight = (y2 - ycenter);\n\n\t\t\tif (halfHeight < halfMinimumHeight) {\n\t\t\t\thalfHeight = halfMinimumHeight;\n\t\t\t}\n\n\t\t\tif (ycenter - halfHeight < 0) {\n\t\t\t\tycenter = halfHeight;\n\t\t\t}\n\t\t\tif (ycenter + halfHeight > totalHeight) {\n\t\t\t\tycenter = totalHeight - halfHeight;\n\t\t\t}\n\n\t\t\tconst color = zone.color;\n\t\t\tlet colorId = this._color2Id[color];\n\t\t\tif (!colorId) {\n\t\t\t\tcolorId = (++this._lastAssignedId);\n\t\t\t\tthis._color2Id[color] = colorId;\n\t\t\t\tthis._id2Color[colorId] = color;\n\t\t\t}\n\t\t\tconst colorZone = new ColorZone(ycenter - halfHeight, ycenter + halfHeight, colorId);\n\n\t\t\tzone.setColorZone(colorZone);\n\t\t\tallColorZones.push(colorZone);\n\t\t}\n\n\t\tthis._colorZonesInvalid = false;\n\n\t\tallColorZones.sort(ColorZone.compare);\n\t\treturn allColorZones;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IEditorConfiguration } from 'vs/editor/common/config/editorConfiguration';\nimport { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';\nimport { IViewLayout, IViewModel } from 'vs/editor/common/viewModel/viewModel';\nimport { IColorTheme } from 'vs/platform/theme/common/themeService';\nimport { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry';\nimport { Color } from 'vs/base/common/color';\nimport { ColorScheme } from 'vs/platform/theme/common/theme';\n\nexport class EditorTheme {\n\n\tprivate _theme: IColorTheme;\n\n\tpublic get type(): ColorScheme {\n\t\treturn this._theme.type;\n\t}\n\n\tpublic get value(): IColorTheme {\n\t\treturn this._theme;\n\t}\n\n\tconstructor(theme: IColorTheme) {\n\t\tthis._theme = theme;\n\t}\n\n\tpublic update(theme: IColorTheme): void {\n\t\tthis._theme = theme;\n\t}\n\n\tpublic getColor(color: ColorIdentifier): Color | undefined {\n\t\treturn this._theme.getColor(color);\n\t}\n}\n\nexport class ViewContext {\n\n\tpublic readonly configuration: IEditorConfiguration;\n\tpublic readonly model: IViewModel;\n\tpublic readonly viewLayout: IViewLayout;\n\tpublic readonly theme: EditorTheme;\n\n\tconstructor(\n\t\tconfiguration: IEditorConfiguration,\n\t\ttheme: IColorTheme,\n\t\tmodel: IViewModel\n\t) {\n\t\tthis.configuration = configuration;\n\t\tthis.theme = new EditorTheme(theme);\n\t\tthis.model = model;\n\t\tthis.viewLayout = model.viewLayout;\n\t}\n\n\tpublic addEventHandler(eventHandler: ViewEventHandler): void {\n\t\tthis.model.addViewEventHandler(eventHandler);\n\t}\n\n\tpublic removeEventHandler(eventHandler: ViewEventHandler): void {\n\t\tthis.model.removeViewEventHandler(eventHandler);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\n\nexport class ViewEventHandler extends Disposable {\n\n\tprivate _shouldRender: boolean;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis._shouldRender = true;\n\t}\n\n\tpublic shouldRender(): boolean {\n\t\treturn this._shouldRender;\n\t}\n\n\tpublic forceShouldRender(): void {\n\t\tthis._shouldRender = true;\n\t}\n\n\tprotected setShouldRender(): void {\n\t\tthis._shouldRender = true;\n\t}\n\n\tpublic onDidRender(): void {\n\t\tthis._shouldRender = false;\n\t}\n\n\t// --- begin event handlers\n\n\tpublic onCompositionStart(e: viewEvents.ViewCompositionStartEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onCompositionEnd(e: viewEvents.ViewCompositionEndEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onFlushed(e: viewEvents.ViewFlushedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onFocusChanged(e: viewEvents.ViewFocusChangedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onLanguageConfigurationChanged(e: viewEvents.ViewLanguageConfigurationEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onLineMappingChanged(e: viewEvents.ViewLineMappingChangedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onLinesChanged(e: viewEvents.ViewLinesChangedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onRevealRangeRequest(e: viewEvents.ViewRevealRangeRequestEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onThemeChanged(e: viewEvents.ViewThemeChangedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onTokensChanged(e: viewEvents.ViewTokensChangedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onTokensColorsChanged(e: viewEvents.ViewTokensColorsChangedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {\n\t\treturn false;\n\t}\n\n\t// --- end event handlers\n\n\tpublic handleEvents(events: viewEvents.ViewEvent[]): void {\n\n\t\tlet shouldRender = false;\n\n\t\tfor (let i = 0, len = events.length; i < len; i++) {\n\t\t\tconst e = events[i];\n\n\t\t\tswitch (e.type) {\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewCompositionStart:\n\t\t\t\t\tif (this.onCompositionStart(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewCompositionEnd:\n\t\t\t\t\tif (this.onCompositionEnd(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewConfigurationChanged:\n\t\t\t\t\tif (this.onConfigurationChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewCursorStateChanged:\n\t\t\t\t\tif (this.onCursorStateChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewDecorationsChanged:\n\t\t\t\t\tif (this.onDecorationsChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewFlushed:\n\t\t\t\t\tif (this.onFlushed(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewFocusChanged:\n\t\t\t\t\tif (this.onFocusChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewLanguageConfigurationChanged:\n\t\t\t\t\tif (this.onLanguageConfigurationChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewLineMappingChanged:\n\t\t\t\t\tif (this.onLineMappingChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewLinesChanged:\n\t\t\t\t\tif (this.onLinesChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewLinesDeleted:\n\t\t\t\t\tif (this.onLinesDeleted(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewLinesInserted:\n\t\t\t\t\tif (this.onLinesInserted(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewRevealRangeRequest:\n\t\t\t\t\tif (this.onRevealRangeRequest(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewScrollChanged:\n\t\t\t\t\tif (this.onScrollChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewTokensChanged:\n\t\t\t\t\tif (this.onTokensChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewThemeChanged:\n\t\t\t\t\tif (this.onThemeChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewTokensColorsChanged:\n\t\t\t\t\tif (this.onTokensColorsChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase viewEvents.ViewEventType.ViewZonesChanged:\n\t\t\t\t\tif (this.onZonesChanged(e)) {\n\t\t\t\t\t\tshouldRender = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tconsole.info('View received unknown event: ');\n\t\t\t\t\tconsole.info(e);\n\t\t\t}\n\t\t}\n\n\t\tif (shouldRender) {\n\t\t\tthis._shouldRender = true;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { RenderingContext } from 'vs/editor/browser/view/renderingContext';\nimport { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';\n\nexport abstract class DynamicViewOverlay extends ViewEventHandler {\n\n\tpublic abstract prepareRender(ctx: RenderingContext): void;\n\n\tpublic abstract render(startLineNumber: number, lineNumber: number): string;\n\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { FastDomNode } from 'vs/base/browser/fastDomNode';\nimport { RenderingContext, RestrictedRenderingContext } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';\n\nexport abstract class ViewPart extends ViewEventHandler {\n\n\t_context: ViewContext;\n\n\tconstructor(context: ViewContext) {\n\t\tsuper();\n\t\tthis._context = context;\n\t\tthis._context.addEventHandler(this);\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._context.removeEventHandler(this);\n\t\tsuper.dispose();\n\t}\n\n\tpublic abstract prepareRender(ctx: RenderingContext): void;\n\tpublic abstract render(ctx: RestrictedRenderingContext): void;\n}\n\nexport const enum PartFingerprint {\n\tNone,\n\tContentWidgets,\n\tOverflowingContentWidgets,\n\tOverflowGuard,\n\tOverlayWidgets,\n\tScrollableElement,\n\tTextArea,\n\tViewLines,\n\tMinimap\n}\n\nexport class PartFingerprints {\n\n\tpublic static write(target: Element | FastDomNode, partId: PartFingerprint) {\n\t\ttarget.setAttribute('data-mprt', String(partId));\n\t}\n\n\tpublic static read(target: Element): PartFingerprint {\n\t\tconst r = target.getAttribute('data-mprt');\n\t\tif (r === null) {\n\t\t\treturn PartFingerprint.None;\n\t\t}\n\t\treturn parseInt(r, 10);\n\t}\n\n\tpublic static collect(child: Element | null, stopAt: Element): Uint8Array {\n\t\tconst result: PartFingerprint[] = [];\n\t\tlet resultLen = 0;\n\n\t\twhile (child && child !== document.body) {\n\t\t\tif (child === stopAt) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (child.nodeType === child.ELEMENT_NODE) {\n\t\t\t\tresult[resultLen++] = this.read(child);\n\t\t\t}\n\t\t\tchild = child.parentElement;\n\t\t}\n\n\t\tconst r = new Uint8Array(resultLen);\n\t\tfor (let i = 0; i < resultLen; i++) {\n\t\t\tr[i] = result[resultLen - i - 1];\n\t\t}\n\t\treturn r;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';\nimport { ContentWidgetPositionPreference, IContentWidget } from 'vs/editor/browser/editorBrowser';\nimport { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { Constants } from 'vs/base/common/uint';\nimport { RenderingContext, RestrictedRenderingContext } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\nimport { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { IDimension } from 'vs/editor/common/core/dimension';\n\n\nclass Coordinate {\n\t_coordinateBrand: void = undefined;\n\n\tpublic readonly top: number;\n\tpublic readonly left: number;\n\n\tconstructor(top: number, left: number) {\n\t\tthis.top = top;\n\t\tthis.left = left;\n\t}\n}\n\nexport class ViewContentWidgets extends ViewPart {\n\n\tprivate readonly _viewDomNode: FastDomNode;\n\tprivate _widgets: { [key: string]: Widget; };\n\n\tpublic domNode: FastDomNode;\n\tpublic overflowingContentWidgetsDomNode: FastDomNode;\n\n\tconstructor(context: ViewContext, viewDomNode: FastDomNode) {\n\t\tsuper(context);\n\t\tthis._viewDomNode = viewDomNode;\n\t\tthis._widgets = {};\n\n\t\tthis.domNode = createFastDomNode(document.createElement('div'));\n\t\tPartFingerprints.write(this.domNode, PartFingerprint.ContentWidgets);\n\t\tthis.domNode.setClassName('contentWidgets');\n\t\tthis.domNode.setPosition('absolute');\n\t\tthis.domNode.setTop(0);\n\n\t\tthis.overflowingContentWidgetsDomNode = createFastDomNode(document.createElement('div'));\n\t\tPartFingerprints.write(this.overflowingContentWidgetsDomNode, PartFingerprint.OverflowingContentWidgets);\n\t\tthis.overflowingContentWidgetsDomNode.setClassName('overflowingContentWidgets');\n\t}\n\n\tpublic override dispose(): void {\n\t\tsuper.dispose();\n\t\tthis._widgets = {};\n\t}\n\n\t// --- begin event handlers\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tconst keys = Object.keys(this._widgets);\n\t\tfor (const widgetId of keys) {\n\t\t\tthis._widgets[widgetId].onConfigurationChanged(e);\n\t\t}\n\t\treturn true;\n\t}\n\tpublic override onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean {\n\t\t// true for inline decorations that can end up relayouting text\n\t\treturn true;\n\t}\n\tpublic override onFlushed(e: viewEvents.ViewFlushedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLineMappingChanged(e: viewEvents.ViewLineMappingChangedEvent): boolean {\n\t\tconst keys = Object.keys(this._widgets);\n\t\tfor (const widgetId of keys) {\n\t\t\tthis._widgets[widgetId].onLineMappingChanged(e);\n\t\t}\n\t\treturn true;\n\t}\n\tpublic override onLinesChanged(e: viewEvents.ViewLinesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\n\t// ---- end view event handlers\n\n\tpublic addWidget(_widget: IContentWidget): void {\n\t\tconst myWidget = new Widget(this._context, this._viewDomNode, _widget);\n\t\tthis._widgets[myWidget.id] = myWidget;\n\n\t\tif (myWidget.allowEditorOverflow) {\n\t\t\tthis.overflowingContentWidgetsDomNode.appendChild(myWidget.domNode);\n\t\t} else {\n\t\t\tthis.domNode.appendChild(myWidget.domNode);\n\t\t}\n\n\t\tthis.setShouldRender();\n\t}\n\n\tpublic setWidgetPosition(widget: IContentWidget, range: IRange | null, preference: ContentWidgetPositionPreference[] | null): void {\n\t\tconst myWidget = this._widgets[widget.getId()];\n\t\tmyWidget.setPosition(range, preference);\n\n\t\tthis.setShouldRender();\n\t}\n\n\tpublic removeWidget(widget: IContentWidget): void {\n\t\tconst widgetId = widget.getId();\n\t\tif (this._widgets.hasOwnProperty(widgetId)) {\n\t\t\tconst myWidget = this._widgets[widgetId];\n\t\t\tdelete this._widgets[widgetId];\n\n\t\t\tconst domNode = myWidget.domNode.domNode;\n\t\t\tdomNode.parentNode!.removeChild(domNode);\n\t\t\tdomNode.removeAttribute('monaco-visible-content-widget');\n\n\t\t\tthis.setShouldRender();\n\t\t}\n\t}\n\n\tpublic shouldSuppressMouseDownOnWidget(widgetId: string): boolean {\n\t\tif (this._widgets.hasOwnProperty(widgetId)) {\n\t\t\treturn this._widgets[widgetId].suppressMouseDown;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic onBeforeRender(viewportData: ViewportData): void {\n\t\tconst keys = Object.keys(this._widgets);\n\t\tfor (const widgetId of keys) {\n\t\t\tthis._widgets[widgetId].onBeforeRender(viewportData);\n\t\t}\n\t}\n\n\tpublic prepareRender(ctx: RenderingContext): void {\n\t\tconst keys = Object.keys(this._widgets);\n\t\tfor (const widgetId of keys) {\n\t\t\tthis._widgets[widgetId].prepareRender(ctx);\n\t\t}\n\t}\n\n\tpublic render(ctx: RestrictedRenderingContext): void {\n\t\tconst keys = Object.keys(this._widgets);\n\t\tfor (const widgetId of keys) {\n\t\t\tthis._widgets[widgetId].render(ctx);\n\t\t}\n\t}\n}\n\ninterface IBoxLayoutResult {\n\tfitsAbove: boolean;\n\taboveTop: number;\n\taboveLeft: number;\n\n\tfitsBelow: boolean;\n\tbelowTop: number;\n\tbelowLeft: number;\n}\n\ninterface IRenderData {\n\tcoordinate: Coordinate,\n\tposition: ContentWidgetPositionPreference\n}\n\nclass Widget {\n\tprivate readonly _context: ViewContext;\n\tprivate readonly _viewDomNode: FastDomNode;\n\tprivate readonly _actual: IContentWidget;\n\n\tpublic readonly domNode: FastDomNode;\n\tpublic readonly id: string;\n\tpublic readonly allowEditorOverflow: boolean;\n\tpublic readonly suppressMouseDown: boolean;\n\n\tprivate readonly _fixedOverflowWidgets: boolean;\n\tprivate _contentWidth: number;\n\tprivate _contentLeft: number;\n\tprivate _lineHeight: number;\n\n\tprivate _range: IRange | null;\n\tprivate _viewRange: Range | null;\n\tprivate _preference: ContentWidgetPositionPreference[] | null;\n\tprivate _cachedDomNodeOffsetWidth: number;\n\tprivate _cachedDomNodeOffsetHeight: number;\n\tprivate _maxWidth: number;\n\tprivate _isVisible: boolean;\n\n\tprivate _renderData: IRenderData | null;\n\n\tconstructor(context: ViewContext, viewDomNode: FastDomNode, actual: IContentWidget) {\n\t\tthis._context = context;\n\t\tthis._viewDomNode = viewDomNode;\n\t\tthis._actual = actual;\n\n\t\tthis.domNode = createFastDomNode(this._actual.getDomNode());\n\t\tthis.id = this._actual.getId();\n\t\tthis.allowEditorOverflow = this._actual.allowEditorOverflow || false;\n\t\tthis.suppressMouseDown = this._actual.suppressMouseDown || false;\n\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\n\t\tthis._fixedOverflowWidgets = options.get(EditorOption.fixedOverflowWidgets);\n\t\tthis._contentWidth = layoutInfo.contentWidth;\n\t\tthis._contentLeft = layoutInfo.contentLeft;\n\t\tthis._lineHeight = options.get(EditorOption.lineHeight);\n\n\t\tthis._range = null;\n\t\tthis._viewRange = null;\n\t\tthis._preference = [];\n\t\tthis._cachedDomNodeOffsetWidth = -1;\n\t\tthis._cachedDomNodeOffsetHeight = -1;\n\t\tthis._maxWidth = this._getMaxWidth();\n\t\tthis._isVisible = false;\n\t\tthis._renderData = null;\n\n\t\tthis.domNode.setPosition((this._fixedOverflowWidgets && this.allowEditorOverflow) ? 'fixed' : 'absolute');\n\t\tthis.domNode.setDisplay('none');\n\t\tthis.domNode.setVisibility('hidden');\n\t\tthis.domNode.setAttribute('widgetId', this.id);\n\t\tthis.domNode.setMaxWidth(this._maxWidth);\n\t}\n\n\tpublic onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): void {\n\t\tconst options = this._context.configuration.options;\n\t\tthis._lineHeight = options.get(EditorOption.lineHeight);\n\t\tif (e.hasChanged(EditorOption.layoutInfo)) {\n\t\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\t\t\tthis._contentLeft = layoutInfo.contentLeft;\n\t\t\tthis._contentWidth = layoutInfo.contentWidth;\n\t\t\tthis._maxWidth = this._getMaxWidth();\n\t\t}\n\t}\n\n\tpublic onLineMappingChanged(e: viewEvents.ViewLineMappingChangedEvent): void {\n\t\tthis._setPosition(this._range);\n\t}\n\n\tprivate _setPosition(range: IRange | null): void {\n\t\tthis._range = range;\n\t\tthis._viewRange = null;\n\n\t\tif (this._range) {\n\t\t\t// Do not trust that widgets give a valid position\n\t\t\tconst validModelRange = this._context.model.validateModelRange(this._range);\n\t\t\tif (this._context.model.coordinatesConverter.modelPositionIsVisible(validModelRange.getStartPosition()) || this._context.model.coordinatesConverter.modelPositionIsVisible(validModelRange.getEndPosition())) {\n\t\t\t\tthis._viewRange = this._context.model.coordinatesConverter.convertModelRangeToViewRange(validModelRange);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _getMaxWidth(): number {\n\t\treturn (\n\t\t\tthis.allowEditorOverflow\n\t\t\t\t? window.innerWidth || document.documentElement!.offsetWidth || document.body.offsetWidth\n\t\t\t\t: this._contentWidth\n\t\t);\n\t}\n\n\tpublic setPosition(range: IRange | null, preference: ContentWidgetPositionPreference[] | null): void {\n\t\tthis._setPosition(range);\n\t\tthis._preference = preference;\n\t\tif (this._viewRange && this._preference && this._preference.length > 0) {\n\t\t\t// this content widget would like to be visible if possible\n\t\t\t// we change it from `display:none` to `display:block` even if it\n\t\t\t// might be outside the viewport such that we can measure its size\n\t\t\t// in `prepareRender`\n\t\t\tthis.domNode.setDisplay('block');\n\t\t} else {\n\t\t\tthis.domNode.setDisplay('none');\n\t\t}\n\t\tthis._cachedDomNodeOffsetWidth = -1;\n\t\tthis._cachedDomNodeOffsetHeight = -1;\n\t}\n\n\tprivate _layoutBoxInViewport(topLeft: Coordinate, bottomLeft: Coordinate, width: number, height: number, ctx: RenderingContext): IBoxLayoutResult {\n\t\t// Our visible box is split horizontally by the current line => 2 boxes\n\n\t\t// a) the box above the line\n\t\tconst aboveLineTop = topLeft.top;\n\t\tconst heightAboveLine = aboveLineTop;\n\n\t\t// b) the box under the line\n\t\tconst underLineTop = bottomLeft.top + this._lineHeight;\n\t\tconst heightUnderLine = ctx.viewportHeight - underLineTop;\n\n\t\tconst aboveTop = aboveLineTop - height;\n\t\tconst fitsAbove = (heightAboveLine >= height);\n\t\tconst belowTop = underLineTop;\n\t\tconst fitsBelow = (heightUnderLine >= height);\n\n\t\t// And its left\n\t\tlet actualAboveLeft = topLeft.left;\n\t\tlet actualBelowLeft = bottomLeft.left;\n\t\tif (actualAboveLeft + width > ctx.scrollLeft + ctx.viewportWidth) {\n\t\t\tactualAboveLeft = ctx.scrollLeft + ctx.viewportWidth - width;\n\t\t}\n\t\tif (actualBelowLeft + width > ctx.scrollLeft + ctx.viewportWidth) {\n\t\t\tactualBelowLeft = ctx.scrollLeft + ctx.viewportWidth - width;\n\t\t}\n\t\tif (actualAboveLeft < ctx.scrollLeft) {\n\t\t\tactualAboveLeft = ctx.scrollLeft;\n\t\t}\n\t\tif (actualBelowLeft < ctx.scrollLeft) {\n\t\t\tactualBelowLeft = ctx.scrollLeft;\n\t\t}\n\n\t\treturn {\n\t\t\tfitsAbove: fitsAbove,\n\t\t\taboveTop: aboveTop,\n\t\t\taboveLeft: actualAboveLeft,\n\n\t\t\tfitsBelow: fitsBelow,\n\t\t\tbelowTop: belowTop,\n\t\t\tbelowLeft: actualBelowLeft,\n\t\t};\n\t}\n\n\tprivate _layoutHorizontalSegmentInPage(windowSize: dom.Dimension, domNodePosition: dom.IDomNodePagePosition, left: number, width: number): [number, number] {\n\t\t// Initially, the limits are defined as the dom node limits\n\t\tconst MIN_LIMIT = Math.max(0, domNodePosition.left - width);\n\t\tconst MAX_LIMIT = Math.min(domNodePosition.left + domNodePosition.width + width, windowSize.width);\n\n\t\tlet absoluteLeft = domNodePosition.left + left - dom.StandardWindow.scrollX;\n\n\t\tif (absoluteLeft + width > MAX_LIMIT) {\n\t\t\tconst delta = absoluteLeft - (MAX_LIMIT - width);\n\t\t\tabsoluteLeft -= delta;\n\t\t\tleft -= delta;\n\t\t}\n\n\t\tif (absoluteLeft < MIN_LIMIT) {\n\t\t\tconst delta = absoluteLeft - MIN_LIMIT;\n\t\t\tabsoluteLeft -= delta;\n\t\t\tleft -= delta;\n\t\t}\n\n\t\treturn [left, absoluteLeft];\n\t}\n\n\tprivate _layoutBoxInPage(topLeft: Coordinate, bottomLeft: Coordinate, width: number, height: number, ctx: RenderingContext): IBoxLayoutResult | null {\n\t\tconst aboveTop = topLeft.top - height;\n\t\tconst belowTop = bottomLeft.top + this._lineHeight;\n\n\t\tconst domNodePosition = dom.getDomNodePagePosition(this._viewDomNode.domNode);\n\t\tconst absoluteAboveTop = domNodePosition.top + aboveTop - dom.StandardWindow.scrollY;\n\t\tconst absoluteBelowTop = domNodePosition.top + belowTop - dom.StandardWindow.scrollY;\n\n\t\tconst windowSize = dom.getClientArea(document.body);\n\t\tconst [aboveLeft, absoluteAboveLeft] = this._layoutHorizontalSegmentInPage(windowSize, domNodePosition, topLeft.left - ctx.scrollLeft + this._contentLeft, width);\n\t\tconst [belowLeft, absoluteBelowLeft] = this._layoutHorizontalSegmentInPage(windowSize, domNodePosition, bottomLeft.left - ctx.scrollLeft + this._contentLeft, width);\n\n\t\t// Leave some clearance to the top/bottom\n\t\tconst TOP_PADDING = 22;\n\t\tconst BOTTOM_PADDING = 22;\n\n\t\tconst fitsAbove = (absoluteAboveTop >= TOP_PADDING);\n\t\tconst fitsBelow = (absoluteBelowTop + height <= windowSize.height - BOTTOM_PADDING);\n\n\t\tif (this._fixedOverflowWidgets) {\n\t\t\treturn {\n\t\t\t\tfitsAbove,\n\t\t\t\taboveTop: Math.max(absoluteAboveTop, TOP_PADDING),\n\t\t\t\taboveLeft: absoluteAboveLeft,\n\t\t\t\tfitsBelow,\n\t\t\t\tbelowTop: absoluteBelowTop,\n\t\t\t\tbelowLeft: absoluteBelowLeft\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tfitsAbove,\n\t\t\taboveTop: aboveTop,\n\t\t\taboveLeft,\n\t\t\tfitsBelow,\n\t\t\tbelowTop,\n\t\t\tbelowLeft\n\t\t};\n\t}\n\n\tprivate _prepareRenderWidgetAtExactPositionOverflowing(topLeft: Coordinate): Coordinate {\n\t\treturn new Coordinate(topLeft.top, topLeft.left + this._contentLeft);\n\t}\n\n\t/**\n\t * Compute `this._topLeft`\n\t */\n\tprivate _getTopAndBottomLeft(ctx: RenderingContext): [Coordinate, Coordinate] | [null, null] {\n\t\tif (!this._viewRange) {\n\t\t\treturn [null, null];\n\t\t}\n\n\t\tconst visibleRangesForRange = ctx.linesVisibleRangesForRange(this._viewRange, false);\n\t\tif (!visibleRangesForRange || visibleRangesForRange.length === 0) {\n\t\t\treturn [null, null];\n\t\t}\n\n\t\tlet firstLine = visibleRangesForRange[0];\n\t\tlet lastLine = visibleRangesForRange[0];\n\t\tfor (const visibleRangesForLine of visibleRangesForRange) {\n\t\t\tif (visibleRangesForLine.lineNumber < firstLine.lineNumber) {\n\t\t\t\tfirstLine = visibleRangesForLine;\n\t\t\t}\n\t\t\tif (visibleRangesForLine.lineNumber > lastLine.lineNumber) {\n\t\t\t\tlastLine = visibleRangesForLine;\n\t\t\t}\n\t\t}\n\n\t\tlet firstLineMinLeft = Constants.MAX_SAFE_SMALL_INTEGER;//firstLine.Constants.MAX_SAFE_SMALL_INTEGER;\n\t\tfor (const visibleRange of firstLine.ranges) {\n\t\t\tif (visibleRange.left < firstLineMinLeft) {\n\t\t\t\tfirstLineMinLeft = visibleRange.left;\n\t\t\t}\n\t\t}\n\n\t\tlet lastLineMinLeft = Constants.MAX_SAFE_SMALL_INTEGER;//lastLine.Constants.MAX_SAFE_SMALL_INTEGER;\n\t\tfor (const visibleRange of lastLine.ranges) {\n\t\t\tif (visibleRange.left < lastLineMinLeft) {\n\t\t\t\tlastLineMinLeft = visibleRange.left;\n\t\t\t}\n\t\t}\n\n\t\tconst topForPosition = ctx.getVerticalOffsetForLineNumber(firstLine.lineNumber) - ctx.scrollTop;\n\t\tconst topLeft = new Coordinate(topForPosition, firstLineMinLeft);\n\n\t\tconst topForBottomLine = ctx.getVerticalOffsetForLineNumber(lastLine.lineNumber) - ctx.scrollTop;\n\t\tconst bottomLeft = new Coordinate(topForBottomLine, lastLineMinLeft);\n\n\t\treturn [topLeft, bottomLeft];\n\t}\n\n\tprivate _prepareRenderWidget(ctx: RenderingContext): IRenderData | null {\n\t\tif (!this._preference || this._preference.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst [topLeft, bottomLeft] = this._getTopAndBottomLeft(ctx);\n\t\tif (!topLeft || !bottomLeft) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (this._cachedDomNodeOffsetWidth === -1 || this._cachedDomNodeOffsetHeight === -1) {\n\n\t\t\tlet preferredDimensions: IDimension | null = null;\n\t\t\tif (typeof this._actual.beforeRender === 'function') {\n\t\t\t\tpreferredDimensions = safeInvoke(this._actual.beforeRender, this._actual);\n\t\t\t}\n\t\t\tif (preferredDimensions) {\n\t\t\t\tthis._cachedDomNodeOffsetWidth = preferredDimensions.width;\n\t\t\t\tthis._cachedDomNodeOffsetHeight = preferredDimensions.height;\n\t\t\t} else {\n\t\t\t\tconst domNode = this.domNode.domNode;\n\t\t\t\tthis._cachedDomNodeOffsetWidth = domNode.offsetWidth;\n\t\t\t\tthis._cachedDomNodeOffsetHeight = domNode.offsetHeight;\n\t\t\t}\n\t\t}\n\n\t\tlet placement: IBoxLayoutResult | null;\n\t\tif (this.allowEditorOverflow) {\n\t\t\tplacement = this._layoutBoxInPage(topLeft, bottomLeft, this._cachedDomNodeOffsetWidth, this._cachedDomNodeOffsetHeight, ctx);\n\t\t} else {\n\t\t\tplacement = this._layoutBoxInViewport(topLeft, bottomLeft, this._cachedDomNodeOffsetWidth, this._cachedDomNodeOffsetHeight, ctx);\n\t\t}\n\n\t\t// Do two passes, first for perfect fit, second picks first option\n\t\tfor (let pass = 1; pass <= 2; pass++) {\n\t\t\tfor (const pref of this._preference) {\n\t\t\t\t// placement\n\t\t\t\tif (pref === ContentWidgetPositionPreference.ABOVE) {\n\t\t\t\t\tif (!placement) {\n\t\t\t\t\t\t// Widget outside of viewport\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tif (pass === 2 || placement.fitsAbove) {\n\t\t\t\t\t\treturn { coordinate: new Coordinate(placement.aboveTop, placement.aboveLeft), position: ContentWidgetPositionPreference.ABOVE };\n\t\t\t\t\t}\n\t\t\t\t} else if (pref === ContentWidgetPositionPreference.BELOW) {\n\t\t\t\t\tif (!placement) {\n\t\t\t\t\t\t// Widget outside of viewport\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tif (pass === 2 || placement.fitsBelow) {\n\t\t\t\t\t\treturn { coordinate: new Coordinate(placement.belowTop, placement.belowLeft), position: ContentWidgetPositionPreference.BELOW };\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (this.allowEditorOverflow) {\n\t\t\t\t\t\treturn { coordinate: this._prepareRenderWidgetAtExactPositionOverflowing(topLeft), position: ContentWidgetPositionPreference.EXACT };\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn { coordinate: topLeft, position: ContentWidgetPositionPreference.EXACT };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * On this first pass, we ensure that the content widget (if it is in the viewport) has the max width set correctly.\n\t */\n\tpublic onBeforeRender(viewportData: ViewportData): void {\n\t\tif (!this._viewRange || !this._preference) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this._viewRange.endLineNumber < viewportData.startLineNumber || this._viewRange.startLineNumber > viewportData.endLineNumber) {\n\t\t\t// Outside of viewport\n\t\t\treturn;\n\t\t}\n\n\t\tthis.domNode.setMaxWidth(this._maxWidth);\n\t}\n\n\tpublic prepareRender(ctx: RenderingContext): void {\n\t\tthis._renderData = this._prepareRenderWidget(ctx);\n\t}\n\n\tpublic render(ctx: RestrictedRenderingContext): void {\n\t\tif (!this._renderData) {\n\t\t\t// This widget should be invisible\n\t\t\tif (this._isVisible) {\n\t\t\t\tthis.domNode.removeAttribute('monaco-visible-content-widget');\n\t\t\t\tthis._isVisible = false;\n\t\t\t\tthis.domNode.setVisibility('hidden');\n\t\t\t}\n\n\t\t\tif (typeof this._actual.afterRender === 'function') {\n\t\t\t\tsafeInvoke(this._actual.afterRender, this._actual, null);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// This widget should be visible\n\t\tif (this.allowEditorOverflow) {\n\t\t\tthis.domNode.setTop(this._renderData.coordinate.top);\n\t\t\tthis.domNode.setLeft(this._renderData.coordinate.left);\n\t\t} else {\n\t\t\tthis.domNode.setTop(this._renderData.coordinate.top + ctx.scrollTop - ctx.bigNumbersDelta);\n\t\t\tthis.domNode.setLeft(this._renderData.coordinate.left);\n\t\t}\n\n\t\tif (!this._isVisible) {\n\t\t\tthis.domNode.setVisibility('inherit');\n\t\t\tthis.domNode.setAttribute('monaco-visible-content-widget', 'true');\n\t\t\tthis._isVisible = true;\n\t\t}\n\n\t\tif (typeof this._actual.afterRender === 'function') {\n\t\t\tsafeInvoke(this._actual.afterRender, this._actual, this._renderData.position);\n\t\t}\n\t}\n}\n\nfunction safeInvoke any>(fn: T, thisArg: ThisParameterType, ...args: Parameters): ReturnType | null {\n\ttry {\n\t\treturn fn.call(thisArg, ...args);\n\t} catch {\n\t\t// ignore\n\t\treturn null;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport 'vs/css!./decorations';\nimport { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';\nimport { Range } from 'vs/editor/common/core/range';\nimport { HorizontalRange, RenderingContext } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\nimport { ViewModelDecoration } from 'vs/editor/common/viewModel/viewModel';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\n\nexport class DecorationsOverlay extends DynamicViewOverlay {\n\n\tprivate readonly _context: ViewContext;\n\tprivate _lineHeight: number;\n\tprivate _typicalHalfwidthCharacterWidth: number;\n\tprivate _renderResult: string[] | null;\n\n\tconstructor(context: ViewContext) {\n\t\tsuper();\n\t\tthis._context = context;\n\t\tconst options = this._context.configuration.options;\n\t\tthis._lineHeight = options.get(EditorOption.lineHeight);\n\t\tthis._typicalHalfwidthCharacterWidth = options.get(EditorOption.fontInfo).typicalHalfwidthCharacterWidth;\n\t\tthis._renderResult = null;\n\n\t\tthis._context.addEventHandler(this);\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._context.removeEventHandler(this);\n\t\tthis._renderResult = null;\n\t\tsuper.dispose();\n\t}\n\n\t// --- begin event handlers\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tconst options = this._context.configuration.options;\n\t\tthis._lineHeight = options.get(EditorOption.lineHeight);\n\t\tthis._typicalHalfwidthCharacterWidth = options.get(EditorOption.fontInfo).typicalHalfwidthCharacterWidth;\n\t\treturn true;\n\t}\n\tpublic override onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onFlushed(e: viewEvents.ViewFlushedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesChanged(e: viewEvents.ViewLinesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn e.scrollTopChanged || e.scrollWidthChanged;\n\t}\n\tpublic override onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\t// --- end event handlers\n\n\tpublic prepareRender(ctx: RenderingContext): void {\n\t\tconst _decorations = ctx.getDecorationsInViewport();\n\n\t\t// Keep only decorations with `className`\n\t\tlet decorations: ViewModelDecoration[] = [];\n\t\tlet decorationsLen = 0;\n\t\tfor (let i = 0, len = _decorations.length; i < len; i++) {\n\t\t\tconst d = _decorations[i];\n\t\t\tif (d.options.className) {\n\t\t\t\tdecorations[decorationsLen++] = d;\n\t\t\t}\n\t\t}\n\n\t\t// Sort decorations for consistent render output\n\t\tdecorations = decorations.sort((a, b) => {\n\t\t\tif (a.options.zIndex! < b.options.zIndex!) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif (a.options.zIndex! > b.options.zIndex!) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tconst aClassName = a.options.className!;\n\t\t\tconst bClassName = b.options.className!;\n\n\t\t\tif (aClassName < bClassName) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif (aClassName > bClassName) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\treturn Range.compareRangesUsingStarts(a.range, b.range);\n\t\t});\n\n\t\tconst visibleStartLineNumber = ctx.visibleRange.startLineNumber;\n\t\tconst visibleEndLineNumber = ctx.visibleRange.endLineNumber;\n\t\tconst output: string[] = [];\n\t\tfor (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {\n\t\t\tconst lineIndex = lineNumber - visibleStartLineNumber;\n\t\t\toutput[lineIndex] = '';\n\t\t}\n\n\t\t// Render first whole line decorations and then regular decorations\n\t\tthis._renderWholeLineDecorations(ctx, decorations, output);\n\t\tthis._renderNormalDecorations(ctx, decorations, output);\n\t\tthis._renderResult = output;\n\t}\n\n\tprivate _renderWholeLineDecorations(ctx: RenderingContext, decorations: ViewModelDecoration[], output: string[]): void {\n\t\tconst lineHeight = String(this._lineHeight);\n\t\tconst visibleStartLineNumber = ctx.visibleRange.startLineNumber;\n\t\tconst visibleEndLineNumber = ctx.visibleRange.endLineNumber;\n\n\t\tfor (let i = 0, lenI = decorations.length; i < lenI; i++) {\n\t\t\tconst d = decorations[i];\n\n\t\t\tif (!d.options.isWholeLine) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst decorationOutput = (\n\t\t\t\t'
    '\n\t\t\t);\n\n\t\t\tconst startLineNumber = Math.max(d.range.startLineNumber, visibleStartLineNumber);\n\t\t\tconst endLineNumber = Math.min(d.range.endLineNumber, visibleEndLineNumber);\n\t\t\tfor (let j = startLineNumber; j <= endLineNumber; j++) {\n\t\t\t\tconst lineIndex = j - visibleStartLineNumber;\n\t\t\t\toutput[lineIndex] += decorationOutput;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _renderNormalDecorations(ctx: RenderingContext, decorations: ViewModelDecoration[], output: string[]): void {\n\t\tconst lineHeight = String(this._lineHeight);\n\t\tconst visibleStartLineNumber = ctx.visibleRange.startLineNumber;\n\n\t\tlet prevClassName: string | null = null;\n\t\tlet prevShowIfCollapsed: boolean = false;\n\t\tlet prevRange: Range | null = null;\n\n\t\tfor (let i = 0, lenI = decorations.length; i < lenI; i++) {\n\t\t\tconst d = decorations[i];\n\n\t\t\tif (d.options.isWholeLine) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst className = d.options.className!;\n\t\t\tconst showIfCollapsed = Boolean(d.options.showIfCollapsed);\n\n\t\t\tlet range = d.range;\n\t\t\tif (showIfCollapsed && range.endColumn === 1 && range.endLineNumber !== range.startLineNumber) {\n\t\t\t\trange = new Range(range.startLineNumber, range.startColumn, range.endLineNumber - 1, this._context.model.getLineMaxColumn(range.endLineNumber - 1));\n\t\t\t}\n\n\t\t\tif (prevClassName === className && prevShowIfCollapsed === showIfCollapsed && Range.areIntersectingOrTouching(prevRange!, range)) {\n\t\t\t\t// merge into previous decoration\n\t\t\t\tprevRange = Range.plusRange(prevRange!, range);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// flush previous decoration\n\t\t\tif (prevClassName !== null) {\n\t\t\t\tthis._renderNormalDecoration(ctx, prevRange!, prevClassName, prevShowIfCollapsed, lineHeight, visibleStartLineNumber, output);\n\t\t\t}\n\n\t\t\tprevClassName = className;\n\t\t\tprevShowIfCollapsed = showIfCollapsed;\n\t\t\tprevRange = range;\n\t\t}\n\n\t\tif (prevClassName !== null) {\n\t\t\tthis._renderNormalDecoration(ctx, prevRange!, prevClassName, prevShowIfCollapsed, lineHeight, visibleStartLineNumber, output);\n\t\t}\n\t}\n\n\tprivate _renderNormalDecoration(ctx: RenderingContext, range: Range, className: string, showIfCollapsed: boolean, lineHeight: string, visibleStartLineNumber: number, output: string[]): void {\n\t\tconst linesVisibleRanges = ctx.linesVisibleRangesForRange(range, /*TODO@Alex*/className === 'findMatch');\n\t\tif (!linesVisibleRanges) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (let j = 0, lenJ = linesVisibleRanges.length; j < lenJ; j++) {\n\t\t\tconst lineVisibleRanges = linesVisibleRanges[j];\n\t\t\tif (lineVisibleRanges.outsideRenderedLine) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst lineIndex = lineVisibleRanges.lineNumber - visibleStartLineNumber;\n\n\t\t\tif (showIfCollapsed && lineVisibleRanges.ranges.length === 1) {\n\t\t\t\tconst singleVisibleRange = lineVisibleRanges.ranges[0];\n\t\t\t\tif (singleVisibleRange.width < this._typicalHalfwidthCharacterWidth) {\n\t\t\t\t\t// collapsed/very small range case => make the decoration visible by expanding its width\n\t\t\t\t\t// expand its size on both sides (both to the left and to the right, keeping it centered)\n\t\t\t\t\tconst center = Math.round(singleVisibleRange.left + singleVisibleRange.width / 2);\n\t\t\t\t\tconst left = Math.max(0, Math.round(center - this._typicalHalfwidthCharacterWidth / 2));\n\t\t\t\t\tlineVisibleRanges.ranges[0] = new HorizontalRange(left, this._typicalHalfwidthCharacterWidth);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (let k = 0, lenK = lineVisibleRanges.ranges.length; k < lenK; k++) {\n\t\t\t\tconst visibleRange = lineVisibleRanges.ranges[k];\n\t\t\t\tconst decorationOutput = (\n\t\t\t\t\t'
    '\n\t\t\t\t);\n\t\t\t\toutput[lineIndex] += decorationOutput;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic render(startLineNumber: number, lineNumber: number): string {\n\t\tif (!this._renderResult) {\n\t\t\treturn '';\n\t\t}\n\t\tconst lineIndex = lineNumber - startLineNumber;\n\t\tif (lineIndex < 0 || lineIndex >= this._renderResult.length) {\n\t\t\treturn '';\n\t\t}\n\t\treturn this._renderResult[lineIndex];\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport 'vs/css!./glyphMargin';\nimport { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';\nimport { RenderingContext } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\n\n\nexport class DecorationToRender {\n\t_decorationToRenderBrand: void = undefined;\n\n\tpublic startLineNumber: number;\n\tpublic endLineNumber: number;\n\tpublic className: string;\n\n\tconstructor(startLineNumber: number, endLineNumber: number, className: string) {\n\t\tthis.startLineNumber = +startLineNumber;\n\t\tthis.endLineNumber = +endLineNumber;\n\t\tthis.className = String(className);\n\t}\n}\n\nexport abstract class DedupOverlay extends DynamicViewOverlay {\n\n\tprotected _render(visibleStartLineNumber: number, visibleEndLineNumber: number, decorations: DecorationToRender[]): string[][] {\n\n\t\tconst output: string[][] = [];\n\t\tfor (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {\n\t\t\tconst lineIndex = lineNumber - visibleStartLineNumber;\n\t\t\toutput[lineIndex] = [];\n\t\t}\n\n\t\tif (decorations.length === 0) {\n\t\t\treturn output;\n\t\t}\n\n\t\tdecorations.sort((a, b) => {\n\t\t\tif (a.className === b.className) {\n\t\t\t\tif (a.startLineNumber === b.startLineNumber) {\n\t\t\t\t\treturn a.endLineNumber - b.endLineNumber;\n\t\t\t\t}\n\t\t\t\treturn a.startLineNumber - b.startLineNumber;\n\t\t\t}\n\t\t\treturn (a.className < b.className ? -1 : 1);\n\t\t});\n\n\t\tlet prevClassName: string | null = null;\n\t\tlet prevEndLineIndex = 0;\n\t\tfor (let i = 0, len = decorations.length; i < len; i++) {\n\t\t\tconst d = decorations[i];\n\t\t\tconst className = d.className;\n\t\t\tlet startLineIndex = Math.max(d.startLineNumber, visibleStartLineNumber) - visibleStartLineNumber;\n\t\t\tconst endLineIndex = Math.min(d.endLineNumber, visibleEndLineNumber) - visibleStartLineNumber;\n\n\t\t\tif (prevClassName === className) {\n\t\t\t\tstartLineIndex = Math.max(prevEndLineIndex + 1, startLineIndex);\n\t\t\t\tprevEndLineIndex = Math.max(prevEndLineIndex, endLineIndex);\n\t\t\t} else {\n\t\t\t\tprevClassName = className;\n\t\t\t\tprevEndLineIndex = endLineIndex;\n\t\t\t}\n\n\t\t\tfor (let i = startLineIndex; i <= prevEndLineIndex; i++) {\n\t\t\t\toutput[i].push(prevClassName);\n\t\t\t}\n\t\t}\n\n\t\treturn output;\n\t}\n}\n\nexport class GlyphMarginOverlay extends DedupOverlay {\n\n\tprivate readonly _context: ViewContext;\n\tprivate _lineHeight: number;\n\tprivate _glyphMargin: boolean;\n\tprivate _glyphMarginLeft: number;\n\tprivate _glyphMarginWidth: number;\n\tprivate _renderResult: string[] | null;\n\n\tconstructor(context: ViewContext) {\n\t\tsuper();\n\t\tthis._context = context;\n\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\n\t\tthis._lineHeight = options.get(EditorOption.lineHeight);\n\t\tthis._glyphMargin = options.get(EditorOption.glyphMargin);\n\t\tthis._glyphMarginLeft = layoutInfo.glyphMarginLeft;\n\t\tthis._glyphMarginWidth = layoutInfo.glyphMarginWidth;\n\t\tthis._renderResult = null;\n\t\tthis._context.addEventHandler(this);\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._context.removeEventHandler(this);\n\t\tthis._renderResult = null;\n\t\tsuper.dispose();\n\t}\n\n\t// --- begin event handlers\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\n\t\tthis._lineHeight = options.get(EditorOption.lineHeight);\n\t\tthis._glyphMargin = options.get(EditorOption.glyphMargin);\n\t\tthis._glyphMarginLeft = layoutInfo.glyphMarginLeft;\n\t\tthis._glyphMarginWidth = layoutInfo.glyphMarginWidth;\n\t\treturn true;\n\t}\n\tpublic override onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onFlushed(e: viewEvents.ViewFlushedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesChanged(e: viewEvents.ViewLinesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn e.scrollTopChanged;\n\t}\n\tpublic override onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\n\t// --- end event handlers\n\n\tprotected _getDecorations(ctx: RenderingContext): DecorationToRender[] {\n\t\tconst decorations = ctx.getDecorationsInViewport();\n\t\tconst r: DecorationToRender[] = [];\n\t\tlet rLen = 0;\n\t\tfor (let i = 0, len = decorations.length; i < len; i++) {\n\t\t\tconst d = decorations[i];\n\t\t\tconst glyphMarginClassName = d.options.glyphMarginClassName;\n\t\t\tif (glyphMarginClassName) {\n\t\t\t\tr[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, glyphMarginClassName);\n\t\t\t}\n\t\t}\n\t\treturn r;\n\t}\n\n\tpublic prepareRender(ctx: RenderingContext): void {\n\t\tif (!this._glyphMargin) {\n\t\t\tthis._renderResult = null;\n\t\t\treturn;\n\t\t}\n\n\t\tconst visibleStartLineNumber = ctx.visibleRange.startLineNumber;\n\t\tconst visibleEndLineNumber = ctx.visibleRange.endLineNumber;\n\t\tconst toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx));\n\n\t\tconst lineHeight = this._lineHeight.toString();\n\t\tconst left = this._glyphMarginLeft.toString();\n\t\tconst width = this._glyphMarginWidth.toString();\n\t\tconst common = '\" style=\"left:' + left + 'px;width:' + width + 'px' + ';height:' + lineHeight + 'px;\">';\n\n\t\tconst output: string[] = [];\n\t\tfor (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {\n\t\t\tconst lineIndex = lineNumber - visibleStartLineNumber;\n\t\t\tconst classNames = toRender[lineIndex];\n\n\t\t\tif (classNames.length === 0) {\n\t\t\t\toutput[lineIndex] = '';\n\t\t\t} else {\n\t\t\t\toutput[lineIndex] = (\n\t\t\t\t\t'
    = this._renderResult.length) {\n\t\t\treturn '';\n\t\t}\n\t\treturn this._renderResult[lineIndex];\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport 'vs/css!./linesDecorations';\nimport { DecorationToRender, DedupOverlay } from 'vs/editor/browser/viewParts/glyphMargin/glyphMargin';\nimport { RenderingContext } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\n\n\nexport class LinesDecorationsOverlay extends DedupOverlay {\n\n\tprivate readonly _context: ViewContext;\n\n\tprivate _decorationsLeft: number;\n\tprivate _decorationsWidth: number;\n\tprivate _renderResult: string[] | null;\n\n\tconstructor(context: ViewContext) {\n\t\tsuper();\n\t\tthis._context = context;\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\t\tthis._decorationsLeft = layoutInfo.decorationsLeft;\n\t\tthis._decorationsWidth = layoutInfo.decorationsWidth;\n\t\tthis._renderResult = null;\n\t\tthis._context.addEventHandler(this);\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._context.removeEventHandler(this);\n\t\tthis._renderResult = null;\n\t\tsuper.dispose();\n\t}\n\n\t// --- begin event handlers\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\t\tthis._decorationsLeft = layoutInfo.decorationsLeft;\n\t\tthis._decorationsWidth = layoutInfo.decorationsWidth;\n\t\treturn true;\n\t}\n\tpublic override onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onFlushed(e: viewEvents.ViewFlushedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesChanged(e: viewEvents.ViewLinesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn e.scrollTopChanged;\n\t}\n\tpublic override onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\n\t// --- end event handlers\n\n\tprotected _getDecorations(ctx: RenderingContext): DecorationToRender[] {\n\t\tconst decorations = ctx.getDecorationsInViewport();\n\t\tconst r: DecorationToRender[] = [];\n\t\tlet rLen = 0;\n\t\tfor (let i = 0, len = decorations.length; i < len; i++) {\n\t\t\tconst d = decorations[i];\n\t\t\tconst linesDecorationsClassName = d.options.linesDecorationsClassName;\n\t\t\tif (linesDecorationsClassName) {\n\t\t\t\tr[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, linesDecorationsClassName);\n\t\t\t}\n\t\t\tconst firstLineDecorationClassName = d.options.firstLineDecorationClassName;\n\t\t\tif (firstLineDecorationClassName) {\n\t\t\t\tr[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.startLineNumber, firstLineDecorationClassName);\n\t\t\t}\n\t\t}\n\t\treturn r;\n\t}\n\n\tpublic prepareRender(ctx: RenderingContext): void {\n\t\tconst visibleStartLineNumber = ctx.visibleRange.startLineNumber;\n\t\tconst visibleEndLineNumber = ctx.visibleRange.endLineNumber;\n\t\tconst toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx));\n\n\t\tconst left = this._decorationsLeft.toString();\n\t\tconst width = this._decorationsWidth.toString();\n\t\tconst common = '\" style=\"left:' + left + 'px;width:' + width + 'px;\">
    ';\n\n\t\tconst output: string[] = [];\n\t\tfor (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {\n\t\t\tconst lineIndex = lineNumber - visibleStartLineNumber;\n\t\t\tconst classNames = toRender[lineIndex];\n\t\t\tlet lineOutput = '';\n\t\t\tfor (let i = 0, len = classNames.length; i < len; i++) {\n\t\t\t\tlineOutput += '
    ;\n\tprivate _canUseLayerHinting: boolean;\n\tprivate _contentLeft: number;\n\tprivate _glyphMarginLeft: number;\n\tprivate _glyphMarginWidth: number;\n\tprivate _glyphMarginBackgroundDomNode: FastDomNode;\n\n\tconstructor(context: ViewContext) {\n\t\tsuper(context);\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\n\t\tthis._canUseLayerHinting = !options.get(EditorOption.disableLayerHinting);\n\t\tthis._contentLeft = layoutInfo.contentLeft;\n\t\tthis._glyphMarginLeft = layoutInfo.glyphMarginLeft;\n\t\tthis._glyphMarginWidth = layoutInfo.glyphMarginWidth;\n\n\t\tthis._domNode = createFastDomNode(document.createElement('div'));\n\t\tthis._domNode.setClassName(Margin.OUTER_CLASS_NAME);\n\t\tthis._domNode.setPosition('absolute');\n\t\tthis._domNode.setAttribute('role', 'presentation');\n\t\tthis._domNode.setAttribute('aria-hidden', 'true');\n\n\t\tthis._glyphMarginBackgroundDomNode = createFastDomNode(document.createElement('div'));\n\t\tthis._glyphMarginBackgroundDomNode.setClassName(Margin.CLASS_NAME);\n\n\t\tthis._domNode.appendChild(this._glyphMarginBackgroundDomNode);\n\t}\n\n\tpublic override dispose(): void {\n\t\tsuper.dispose();\n\t}\n\n\tpublic getDomNode(): FastDomNode {\n\t\treturn this._domNode;\n\t}\n\n\t// --- begin event handlers\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\n\t\tthis._canUseLayerHinting = !options.get(EditorOption.disableLayerHinting);\n\t\tthis._contentLeft = layoutInfo.contentLeft;\n\t\tthis._glyphMarginLeft = layoutInfo.glyphMarginLeft;\n\t\tthis._glyphMarginWidth = layoutInfo.glyphMarginWidth;\n\n\t\treturn true;\n\t}\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn super.onScrollChanged(e) || e.scrollTopChanged;\n\t}\n\n\t// --- end event handlers\n\n\tpublic prepareRender(ctx: RenderingContext): void {\n\t\t// Nothing to read\n\t}\n\n\tpublic render(ctx: RestrictedRenderingContext): void {\n\t\tthis._domNode.setLayerHinting(this._canUseLayerHinting);\n\t\tthis._domNode.setContain('strict');\n\t\tconst adjustedScrollTop = ctx.scrollTop - ctx.bigNumbersDelta;\n\t\tthis._domNode.setTop(-adjustedScrollTop);\n\n\t\tconst height = Math.min(ctx.scrollHeight, 1000000);\n\t\tthis._domNode.setHeight(height);\n\t\tthis._domNode.setWidth(this._contentLeft);\n\n\t\tthis._glyphMarginBackgroundDomNode.setLeft(this._glyphMarginLeft);\n\t\tthis._glyphMarginBackgroundDomNode.setWidth(this._glyphMarginWidth);\n\t\tthis._glyphMarginBackgroundDomNode.setHeight(height);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport 'vs/css!./marginDecorations';\nimport { DecorationToRender, DedupOverlay } from 'vs/editor/browser/viewParts/glyphMargin/glyphMargin';\nimport { RenderingContext } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\n\nexport class MarginViewLineDecorationsOverlay extends DedupOverlay {\n\tprivate readonly _context: ViewContext;\n\tprivate _renderResult: string[] | null;\n\n\tconstructor(context: ViewContext) {\n\t\tsuper();\n\t\tthis._context = context;\n\t\tthis._renderResult = null;\n\t\tthis._context.addEventHandler(this);\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._context.removeEventHandler(this);\n\t\tthis._renderResult = null;\n\t\tsuper.dispose();\n\t}\n\n\t// --- begin event handlers\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onFlushed(e: viewEvents.ViewFlushedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesChanged(e: viewEvents.ViewLinesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean {\n\t\treturn true;\n\t}\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn e.scrollTopChanged;\n\t}\n\tpublic override onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\n\t// --- end event handlers\n\n\tprotected _getDecorations(ctx: RenderingContext): DecorationToRender[] {\n\t\tconst decorations = ctx.getDecorationsInViewport();\n\t\tconst r: DecorationToRender[] = [];\n\t\tlet rLen = 0;\n\t\tfor (let i = 0, len = decorations.length; i < len; i++) {\n\t\t\tconst d = decorations[i];\n\t\t\tconst marginClassName = d.options.marginClassName;\n\t\t\tif (marginClassName) {\n\t\t\t\tr[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, marginClassName);\n\t\t\t}\n\t\t}\n\t\treturn r;\n\t}\n\n\tpublic prepareRender(ctx: RenderingContext): void {\n\t\tconst visibleStartLineNumber = ctx.visibleRange.startLineNumber;\n\t\tconst visibleEndLineNumber = ctx.visibleRange.endLineNumber;\n\t\tconst toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx));\n\n\t\tconst output: string[] = [];\n\t\tfor (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {\n\t\t\tconst lineIndex = lineNumber - visibleStartLineNumber;\n\t\t\tconst classNames = toRender[lineIndex];\n\t\t\tlet lineOutput = '';\n\t\t\tfor (let i = 0, len = classNames.length; i < len; i++) {\n\t\t\t\tlineOutput += '
    ';\n\t\t\t}\n\t\t\toutput[lineIndex] = lineOutput;\n\t\t}\n\n\t\tthis._renderResult = output;\n\t}\n\n\tpublic render(startLineNumber: number, lineNumber: number): string {\n\t\tif (!this._renderResult) {\n\t\t\treturn '';\n\t\t}\n\t\treturn this._renderResult[lineNumber - startLineNumber];\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport 'vs/css!./overlayWidgets';\nimport { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';\nimport { IOverlayWidget, OverlayWidgetPositionPreference } from 'vs/editor/browser/editorBrowser';\nimport { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart';\nimport { RenderingContext, RestrictedRenderingContext } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\n\n\ninterface IWidgetData {\n\twidget: IOverlayWidget;\n\tpreference: OverlayWidgetPositionPreference | null;\n\tdomNode: FastDomNode;\n}\n\ninterface IWidgetMap {\n\t[key: string]: IWidgetData;\n}\n\nexport class ViewOverlayWidgets extends ViewPart {\n\n\tprivate _widgets: IWidgetMap;\n\tprivate readonly _domNode: FastDomNode;\n\n\tprivate _verticalScrollbarWidth: number;\n\tprivate _minimapWidth: number;\n\tprivate _horizontalScrollbarHeight: number;\n\tprivate _editorHeight: number;\n\tprivate _editorWidth: number;\n\n\tconstructor(context: ViewContext) {\n\t\tsuper(context);\n\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\n\t\tthis._widgets = {};\n\t\tthis._verticalScrollbarWidth = layoutInfo.verticalScrollbarWidth;\n\t\tthis._minimapWidth = layoutInfo.minimap.minimapWidth;\n\t\tthis._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight;\n\t\tthis._editorHeight = layoutInfo.height;\n\t\tthis._editorWidth = layoutInfo.width;\n\n\t\tthis._domNode = createFastDomNode(document.createElement('div'));\n\t\tPartFingerprints.write(this._domNode, PartFingerprint.OverlayWidgets);\n\t\tthis._domNode.setClassName('overlayWidgets');\n\t}\n\n\tpublic override dispose(): void {\n\t\tsuper.dispose();\n\t\tthis._widgets = {};\n\t}\n\n\tpublic getDomNode(): FastDomNode {\n\t\treturn this._domNode;\n\t}\n\n\t// ---- begin view event handlers\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\n\t\tthis._verticalScrollbarWidth = layoutInfo.verticalScrollbarWidth;\n\t\tthis._minimapWidth = layoutInfo.minimap.minimapWidth;\n\t\tthis._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight;\n\t\tthis._editorHeight = layoutInfo.height;\n\t\tthis._editorWidth = layoutInfo.width;\n\t\treturn true;\n\t}\n\n\t// ---- end view event handlers\n\n\tpublic addWidget(widget: IOverlayWidget): void {\n\t\tconst domNode = createFastDomNode(widget.getDomNode());\n\n\t\tthis._widgets[widget.getId()] = {\n\t\t\twidget: widget,\n\t\t\tpreference: null,\n\t\t\tdomNode: domNode\n\t\t};\n\n\t\t// This is sync because a widget wants to be in the dom\n\t\tdomNode.setPosition('absolute');\n\t\tdomNode.setAttribute('widgetId', widget.getId());\n\t\tthis._domNode.appendChild(domNode);\n\n\t\tthis.setShouldRender();\n\t}\n\n\tpublic setWidgetPosition(widget: IOverlayWidget, preference: OverlayWidgetPositionPreference | null): boolean {\n\t\tconst widgetData = this._widgets[widget.getId()];\n\t\tif (widgetData.preference === preference) {\n\t\t\treturn false;\n\t\t}\n\n\t\twidgetData.preference = preference;\n\t\tthis.setShouldRender();\n\n\t\treturn true;\n\t}\n\n\tpublic removeWidget(widget: IOverlayWidget): void {\n\t\tconst widgetId = widget.getId();\n\t\tif (this._widgets.hasOwnProperty(widgetId)) {\n\t\t\tconst widgetData = this._widgets[widgetId];\n\t\t\tconst domNode = widgetData.domNode.domNode;\n\t\t\tdelete this._widgets[widgetId];\n\n\t\t\tdomNode.parentNode!.removeChild(domNode);\n\t\t\tthis.setShouldRender();\n\t\t}\n\t}\n\n\tprivate _renderWidget(widgetData: IWidgetData): void {\n\t\tconst domNode = widgetData.domNode;\n\n\t\tif (widgetData.preference === null) {\n\t\t\tdomNode.unsetTop();\n\t\t\treturn;\n\t\t}\n\n\t\tif (widgetData.preference === OverlayWidgetPositionPreference.TOP_RIGHT_CORNER) {\n\t\t\tdomNode.setTop(0);\n\t\t\tdomNode.setRight((2 * this._verticalScrollbarWidth) + this._minimapWidth);\n\t\t} else if (widgetData.preference === OverlayWidgetPositionPreference.BOTTOM_RIGHT_CORNER) {\n\t\t\tconst widgetHeight = domNode.domNode.clientHeight;\n\t\t\tdomNode.setTop((this._editorHeight - widgetHeight - 2 * this._horizontalScrollbarHeight));\n\t\t\tdomNode.setRight((2 * this._verticalScrollbarWidth) + this._minimapWidth);\n\t\t} else if (widgetData.preference === OverlayWidgetPositionPreference.TOP_CENTER) {\n\t\t\tdomNode.setTop(0);\n\t\t\tdomNode.domNode.style.right = '50%';\n\t\t}\n\t}\n\n\tpublic prepareRender(ctx: RenderingContext): void {\n\t\t// Nothing to read\n\t}\n\n\tpublic render(ctx: RestrictedRenderingContext): void {\n\t\tthis._domNode.setWidth(this._editorWidth);\n\n\t\tconst keys = Object.keys(this._widgets);\n\t\tfor (let i = 0, len = keys.length; i < len; i++) {\n\t\t\tconst widgetId = keys[i];\n\t\t\tthis._renderWidget(this._widgets[widgetId]);\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';\nimport { IOverviewRuler } from 'vs/editor/browser/editorBrowser';\nimport { OverviewRulerPosition, EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { ColorZone, OverviewRulerZone, OverviewZoneManager } from 'vs/editor/common/viewModel/overviewZoneManager';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\nimport { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';\n\nexport class OverviewRuler extends ViewEventHandler implements IOverviewRuler {\n\n\tprivate readonly _context: ViewContext;\n\tprivate readonly _domNode: FastDomNode;\n\tprivate readonly _zoneManager: OverviewZoneManager;\n\n\tconstructor(context: ViewContext, cssClassName: string) {\n\t\tsuper();\n\t\tthis._context = context;\n\t\tconst options = this._context.configuration.options;\n\n\t\tthis._domNode = createFastDomNode(document.createElement('canvas'));\n\t\tthis._domNode.setClassName(cssClassName);\n\t\tthis._domNode.setPosition('absolute');\n\t\tthis._domNode.setLayerHinting(true);\n\t\tthis._domNode.setContain('strict');\n\n\t\tthis._zoneManager = new OverviewZoneManager((lineNumber: number) => this._context.viewLayout.getVerticalOffsetForLineNumber(lineNumber));\n\t\tthis._zoneManager.setDOMWidth(0);\n\t\tthis._zoneManager.setDOMHeight(0);\n\t\tthis._zoneManager.setOuterHeight(this._context.viewLayout.getScrollHeight());\n\t\tthis._zoneManager.setLineHeight(options.get(EditorOption.lineHeight));\n\n\t\tthis._zoneManager.setPixelRatio(options.get(EditorOption.pixelRatio));\n\n\t\tthis._context.addEventHandler(this);\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._context.removeEventHandler(this);\n\t\tsuper.dispose();\n\t}\n\n\t// ---- begin view event handlers\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tconst options = this._context.configuration.options;\n\n\t\tif (e.hasChanged(EditorOption.lineHeight)) {\n\t\t\tthis._zoneManager.setLineHeight(options.get(EditorOption.lineHeight));\n\t\t\tthis._render();\n\t\t}\n\n\t\tif (e.hasChanged(EditorOption.pixelRatio)) {\n\t\t\tthis._zoneManager.setPixelRatio(options.get(EditorOption.pixelRatio));\n\t\t\tthis._domNode.setWidth(this._zoneManager.getDOMWidth());\n\t\t\tthis._domNode.setHeight(this._zoneManager.getDOMHeight());\n\t\t\tthis._domNode.domNode.width = this._zoneManager.getCanvasWidth();\n\t\t\tthis._domNode.domNode.height = this._zoneManager.getCanvasHeight();\n\t\t\tthis._render();\n\t\t}\n\n\t\treturn true;\n\t}\n\tpublic override onFlushed(e: viewEvents.ViewFlushedEvent): boolean {\n\t\tthis._render();\n\t\treturn true;\n\t}\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\tif (e.scrollHeightChanged) {\n\t\t\tthis._zoneManager.setOuterHeight(e.scrollHeight);\n\t\t\tthis._render();\n\t\t}\n\t\treturn true;\n\t}\n\tpublic override onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {\n\t\tthis._render();\n\t\treturn true;\n\t}\n\n\t// ---- end view event handlers\n\n\tpublic getDomNode(): HTMLElement {\n\t\treturn this._domNode.domNode;\n\t}\n\n\tpublic setLayout(position: OverviewRulerPosition): void {\n\t\tthis._domNode.setTop(position.top);\n\t\tthis._domNode.setRight(position.right);\n\n\t\tlet hasChanged = false;\n\t\thasChanged = this._zoneManager.setDOMWidth(position.width) || hasChanged;\n\t\thasChanged = this._zoneManager.setDOMHeight(position.height) || hasChanged;\n\n\t\tif (hasChanged) {\n\t\t\tthis._domNode.setWidth(this._zoneManager.getDOMWidth());\n\t\t\tthis._domNode.setHeight(this._zoneManager.getDOMHeight());\n\t\t\tthis._domNode.domNode.width = this._zoneManager.getCanvasWidth();\n\t\t\tthis._domNode.domNode.height = this._zoneManager.getCanvasHeight();\n\n\t\t\tthis._render();\n\t\t}\n\t}\n\n\tpublic setZones(zones: OverviewRulerZone[]): void {\n\t\tthis._zoneManager.setZones(zones);\n\t\tthis._render();\n\t}\n\n\tprivate _render(): boolean {\n\t\tif (this._zoneManager.getOuterHeight() === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst width = this._zoneManager.getCanvasWidth();\n\t\tconst height = this._zoneManager.getCanvasHeight();\n\n\t\tconst colorZones = this._zoneManager.resolveColorZones();\n\t\tconst id2Color = this._zoneManager.getId2Color();\n\n\t\tconst ctx = this._domNode.domNode.getContext('2d')!;\n\t\tctx.clearRect(0, 0, width, height);\n\t\tif (colorZones.length > 0) {\n\t\t\tthis._renderOneLane(ctx, colorZones, id2Color, width);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate _renderOneLane(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], width: number): void {\n\n\t\tlet currentColorId = 0;\n\t\tlet currentFrom = 0;\n\t\tlet currentTo = 0;\n\n\t\tfor (const zone of colorZones) {\n\n\t\t\tconst zoneColorId = zone.colorId;\n\t\t\tconst zoneFrom = zone.from;\n\t\t\tconst zoneTo = zone.to;\n\n\t\t\tif (zoneColorId !== currentColorId) {\n\t\t\t\tctx.fillRect(0, currentFrom, width, currentTo - currentFrom);\n\n\t\t\t\tcurrentColorId = zoneColorId;\n\t\t\t\tctx.fillStyle = id2Color[currentColorId];\n\t\t\t\tcurrentFrom = zoneFrom;\n\t\t\t\tcurrentTo = zoneTo;\n\t\t\t} else {\n\t\t\t\tif (currentTo >= zoneFrom) {\n\t\t\t\t\tcurrentTo = Math.max(currentTo, zoneTo);\n\t\t\t\t} else {\n\t\t\t\t\tctx.fillRect(0, currentFrom, width, currentTo - currentFrom);\n\t\t\t\t\tcurrentFrom = zoneFrom;\n\t\t\t\t\tcurrentTo = zoneTo;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tctx.fillRect(0, currentFrom, width, currentTo - currentFrom);\n\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport { IViewZone, IViewZoneChangeAccessor } from 'vs/editor/browser/editorBrowser';\nimport { ViewPart } from 'vs/editor/browser/view/viewPart';\nimport { Position } from 'vs/editor/common/core/position';\nimport { RenderingContext, RestrictedRenderingContext } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\nimport { IViewWhitespaceViewportData } from 'vs/editor/common/viewModel/viewModel';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { IWhitespaceChangeAccessor, IEditorWhitespace } from 'vs/editor/common/viewLayout/linesLayout';\n\nexport interface IMyViewZone {\n\twhitespaceId: string;\n\tdelegate: IViewZone;\n\tisInHiddenArea: boolean;\n\tisVisible: boolean;\n\tdomNode: FastDomNode;\n\tmarginDomNode: FastDomNode | null;\n}\n\ninterface IComputedViewZoneProps {\n\tisInHiddenArea: boolean;\n\tafterViewLineNumber: number;\n\theightInPx: number;\n\tminWidthInPx: number;\n}\n\nconst invalidFunc = () => { throw new Error(`Invalid change accessor`); };\n\nexport class ViewZones extends ViewPart {\n\n\tprivate _zones: { [id: string]: IMyViewZone; };\n\tprivate _lineHeight: number;\n\tprivate _contentWidth: number;\n\tprivate _contentLeft: number;\n\n\tpublic domNode: FastDomNode;\n\n\tpublic marginDomNode: FastDomNode;\n\n\tconstructor(context: ViewContext) {\n\t\tsuper(context);\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\n\t\tthis._lineHeight = options.get(EditorOption.lineHeight);\n\t\tthis._contentWidth = layoutInfo.contentWidth;\n\t\tthis._contentLeft = layoutInfo.contentLeft;\n\n\t\tthis.domNode = createFastDomNode(document.createElement('div'));\n\t\tthis.domNode.setClassName('view-zones');\n\t\tthis.domNode.setPosition('absolute');\n\t\tthis.domNode.setAttribute('role', 'presentation');\n\t\tthis.domNode.setAttribute('aria-hidden', 'true');\n\n\t\tthis.marginDomNode = createFastDomNode(document.createElement('div'));\n\t\tthis.marginDomNode.setClassName('margin-view-zones');\n\t\tthis.marginDomNode.setPosition('absolute');\n\t\tthis.marginDomNode.setAttribute('role', 'presentation');\n\t\tthis.marginDomNode.setAttribute('aria-hidden', 'true');\n\n\t\tthis._zones = {};\n\t}\n\n\tpublic override dispose(): void {\n\t\tsuper.dispose();\n\t\tthis._zones = {};\n\t}\n\n\t// ---- begin view event handlers\n\n\tprivate _recomputeWhitespacesProps(): boolean {\n\t\tconst whitespaces = this._context.viewLayout.getWhitespaces();\n\t\tconst oldWhitespaces = new Map();\n\t\tfor (const whitespace of whitespaces) {\n\t\t\toldWhitespaces.set(whitespace.id, whitespace);\n\t\t}\n\t\tlet hadAChange = false;\n\t\tthis._context.model.changeWhitespace((whitespaceAccessor: IWhitespaceChangeAccessor) => {\n\t\t\tconst keys = Object.keys(this._zones);\n\t\t\tfor (let i = 0, len = keys.length; i < len; i++) {\n\t\t\t\tconst id = keys[i];\n\t\t\t\tconst zone = this._zones[id];\n\t\t\t\tconst props = this._computeWhitespaceProps(zone.delegate);\n\t\t\t\tzone.isInHiddenArea = props.isInHiddenArea;\n\t\t\t\tconst oldWhitespace = oldWhitespaces.get(id);\n\t\t\t\tif (oldWhitespace && (oldWhitespace.afterLineNumber !== props.afterViewLineNumber || oldWhitespace.height !== props.heightInPx)) {\n\t\t\t\t\twhitespaceAccessor.changeOneWhitespace(id, props.afterViewLineNumber, props.heightInPx);\n\t\t\t\t\tthis._safeCallOnComputedHeight(zone.delegate, props.heightInPx);\n\t\t\t\t\thadAChange = true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn hadAChange;\n\t}\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\n\t\tthis._lineHeight = options.get(EditorOption.lineHeight);\n\t\tthis._contentWidth = layoutInfo.contentWidth;\n\t\tthis._contentLeft = layoutInfo.contentLeft;\n\n\t\tif (e.hasChanged(EditorOption.lineHeight)) {\n\t\t\tthis._recomputeWhitespacesProps();\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tpublic override onLineMappingChanged(e: viewEvents.ViewLineMappingChangedEvent): boolean {\n\t\treturn this._recomputeWhitespacesProps();\n\t}\n\n\tpublic override onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean {\n\t\treturn true;\n\t}\n\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn e.scrollTopChanged || e.scrollWidthChanged;\n\t}\n\n\tpublic override onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {\n\t\treturn true;\n\t}\n\n\tpublic override onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean {\n\t\treturn true;\n\t}\n\n\t// ---- end view event handlers\n\n\tprivate _getZoneOrdinal(zone: IViewZone): number {\n\n\t\tif (typeof zone.afterColumn !== 'undefined') {\n\t\t\treturn zone.afterColumn;\n\t\t}\n\n\t\treturn 10000;\n\t}\n\n\tprivate _computeWhitespaceProps(zone: IViewZone): IComputedViewZoneProps {\n\t\tif (zone.afterLineNumber === 0) {\n\t\t\treturn {\n\t\t\t\tisInHiddenArea: false,\n\t\t\t\tafterViewLineNumber: 0,\n\t\t\t\theightInPx: this._heightInPixels(zone),\n\t\t\t\tminWidthInPx: this._minWidthInPixels(zone)\n\t\t\t};\n\t\t}\n\n\t\tlet zoneAfterModelPosition: Position;\n\t\tif (typeof zone.afterColumn !== 'undefined') {\n\t\t\tzoneAfterModelPosition = this._context.model.validateModelPosition({\n\t\t\t\tlineNumber: zone.afterLineNumber,\n\t\t\t\tcolumn: zone.afterColumn\n\t\t\t});\n\t\t} else {\n\t\t\tconst validAfterLineNumber = this._context.model.validateModelPosition({\n\t\t\t\tlineNumber: zone.afterLineNumber,\n\t\t\t\tcolumn: 1\n\t\t\t}).lineNumber;\n\n\t\t\tzoneAfterModelPosition = new Position(\n\t\t\t\tvalidAfterLineNumber,\n\t\t\t\tthis._context.model.getModelLineMaxColumn(validAfterLineNumber)\n\t\t\t);\n\t\t}\n\n\t\tlet zoneBeforeModelPosition: Position;\n\t\tif (zoneAfterModelPosition.column === this._context.model.getModelLineMaxColumn(zoneAfterModelPosition.lineNumber)) {\n\t\t\tzoneBeforeModelPosition = this._context.model.validateModelPosition({\n\t\t\t\tlineNumber: zoneAfterModelPosition.lineNumber + 1,\n\t\t\t\tcolumn: 1\n\t\t\t});\n\t\t} else {\n\t\t\tzoneBeforeModelPosition = this._context.model.validateModelPosition({\n\t\t\t\tlineNumber: zoneAfterModelPosition.lineNumber,\n\t\t\t\tcolumn: zoneAfterModelPosition.column + 1\n\t\t\t});\n\t\t}\n\n\t\tconst viewPosition = this._context.model.coordinatesConverter.convertModelPositionToViewPosition(zoneAfterModelPosition, zone.afterColumnAffinity);\n\t\tconst isVisible = this._context.model.coordinatesConverter.modelPositionIsVisible(zoneBeforeModelPosition);\n\t\treturn {\n\t\t\tisInHiddenArea: !isVisible,\n\t\t\tafterViewLineNumber: viewPosition.lineNumber,\n\t\t\theightInPx: (isVisible ? this._heightInPixels(zone) : 0),\n\t\t\tminWidthInPx: this._minWidthInPixels(zone)\n\t\t};\n\t}\n\n\tpublic changeViewZones(callback: (changeAccessor: IViewZoneChangeAccessor) => any): boolean {\n\t\tlet zonesHaveChanged = false;\n\n\t\tthis._context.model.changeWhitespace((whitespaceAccessor: IWhitespaceChangeAccessor) => {\n\n\t\t\tconst changeAccessor: IViewZoneChangeAccessor = {\n\t\t\t\taddZone: (zone: IViewZone): string => {\n\t\t\t\t\tzonesHaveChanged = true;\n\t\t\t\t\treturn this._addZone(whitespaceAccessor, zone);\n\t\t\t\t},\n\t\t\t\tremoveZone: (id: string): void => {\n\t\t\t\t\tif (!id) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tzonesHaveChanged = this._removeZone(whitespaceAccessor, id) || zonesHaveChanged;\n\t\t\t\t},\n\t\t\t\tlayoutZone: (id: string): void => {\n\t\t\t\t\tif (!id) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tzonesHaveChanged = this._layoutZone(whitespaceAccessor, id) || zonesHaveChanged;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tsafeInvoke1Arg(callback, changeAccessor);\n\n\t\t\t// Invalidate changeAccessor\n\t\t\tchangeAccessor.addZone = invalidFunc;\n\t\t\tchangeAccessor.removeZone = invalidFunc;\n\t\t\tchangeAccessor.layoutZone = invalidFunc;\n\t\t});\n\n\t\treturn zonesHaveChanged;\n\t}\n\n\tprivate _addZone(whitespaceAccessor: IWhitespaceChangeAccessor, zone: IViewZone): string {\n\t\tconst props = this._computeWhitespaceProps(zone);\n\t\tconst whitespaceId = whitespaceAccessor.insertWhitespace(props.afterViewLineNumber, this._getZoneOrdinal(zone), props.heightInPx, props.minWidthInPx);\n\n\t\tconst myZone: IMyViewZone = {\n\t\t\twhitespaceId: whitespaceId,\n\t\t\tdelegate: zone,\n\t\t\tisInHiddenArea: props.isInHiddenArea,\n\t\t\tisVisible: false,\n\t\t\tdomNode: createFastDomNode(zone.domNode),\n\t\t\tmarginDomNode: zone.marginDomNode ? createFastDomNode(zone.marginDomNode) : null\n\t\t};\n\n\t\tthis._safeCallOnComputedHeight(myZone.delegate, props.heightInPx);\n\n\t\tmyZone.domNode.setPosition('absolute');\n\t\tmyZone.domNode.domNode.style.width = '100%';\n\t\tmyZone.domNode.setDisplay('none');\n\t\tmyZone.domNode.setAttribute('monaco-view-zone', myZone.whitespaceId);\n\t\tthis.domNode.appendChild(myZone.domNode);\n\n\t\tif (myZone.marginDomNode) {\n\t\t\tmyZone.marginDomNode.setPosition('absolute');\n\t\t\tmyZone.marginDomNode.domNode.style.width = '100%';\n\t\t\tmyZone.marginDomNode.setDisplay('none');\n\t\t\tmyZone.marginDomNode.setAttribute('monaco-view-zone', myZone.whitespaceId);\n\t\t\tthis.marginDomNode.appendChild(myZone.marginDomNode);\n\t\t}\n\n\t\tthis._zones[myZone.whitespaceId] = myZone;\n\n\n\t\tthis.setShouldRender();\n\n\t\treturn myZone.whitespaceId;\n\t}\n\n\tprivate _removeZone(whitespaceAccessor: IWhitespaceChangeAccessor, id: string): boolean {\n\t\tif (this._zones.hasOwnProperty(id)) {\n\t\t\tconst zone = this._zones[id];\n\t\t\tdelete this._zones[id];\n\t\t\twhitespaceAccessor.removeWhitespace(zone.whitespaceId);\n\n\t\t\tzone.domNode.removeAttribute('monaco-visible-view-zone');\n\t\t\tzone.domNode.removeAttribute('monaco-view-zone');\n\t\t\tzone.domNode.domNode.parentNode!.removeChild(zone.domNode.domNode);\n\n\t\t\tif (zone.marginDomNode) {\n\t\t\t\tzone.marginDomNode.removeAttribute('monaco-visible-view-zone');\n\t\t\t\tzone.marginDomNode.removeAttribute('monaco-view-zone');\n\t\t\t\tzone.marginDomNode.domNode.parentNode!.removeChild(zone.marginDomNode.domNode);\n\t\t\t}\n\n\t\t\tthis.setShouldRender();\n\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate _layoutZone(whitespaceAccessor: IWhitespaceChangeAccessor, id: string): boolean {\n\t\tif (this._zones.hasOwnProperty(id)) {\n\t\t\tconst zone = this._zones[id];\n\t\t\tconst props = this._computeWhitespaceProps(zone.delegate);\n\t\t\tzone.isInHiddenArea = props.isInHiddenArea;\n\t\t\t// const newOrdinal = this._getZoneOrdinal(zone.delegate);\n\t\t\twhitespaceAccessor.changeOneWhitespace(zone.whitespaceId, props.afterViewLineNumber, props.heightInPx);\n\t\t\t// TODO@Alex: change `newOrdinal` too\n\n\t\t\tthis._safeCallOnComputedHeight(zone.delegate, props.heightInPx);\n\t\t\tthis.setShouldRender();\n\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic shouldSuppressMouseDownOnViewZone(id: string): boolean {\n\t\tif (this._zones.hasOwnProperty(id)) {\n\t\t\tconst zone = this._zones[id];\n\t\t\treturn Boolean(zone.delegate.suppressMouseDown);\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate _heightInPixels(zone: IViewZone): number {\n\t\tif (typeof zone.heightInPx === 'number') {\n\t\t\treturn zone.heightInPx;\n\t\t}\n\t\tif (typeof zone.heightInLines === 'number') {\n\t\t\treturn this._lineHeight * zone.heightInLines;\n\t\t}\n\t\treturn this._lineHeight;\n\t}\n\n\tprivate _minWidthInPixels(zone: IViewZone): number {\n\t\tif (typeof zone.minWidthInPx === 'number') {\n\t\t\treturn zone.minWidthInPx;\n\t\t}\n\t\treturn 0;\n\t}\n\n\tprivate _safeCallOnComputedHeight(zone: IViewZone, height: number): void {\n\t\tif (typeof zone.onComputedHeight === 'function') {\n\t\t\ttry {\n\t\t\t\tzone.onComputedHeight(height);\n\t\t\t} catch (e) {\n\t\t\t\tonUnexpectedError(e);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _safeCallOnDomNodeTop(zone: IViewZone, top: number): void {\n\t\tif (typeof zone.onDomNodeTop === 'function') {\n\t\t\ttry {\n\t\t\t\tzone.onDomNodeTop(top);\n\t\t\t} catch (e) {\n\t\t\t\tonUnexpectedError(e);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic prepareRender(ctx: RenderingContext): void {\n\t\t// Nothing to read\n\t}\n\n\tpublic render(ctx: RestrictedRenderingContext): void {\n\t\tconst visibleWhitespaces = ctx.viewportData.whitespaceViewportData;\n\t\tconst visibleZones: { [id: string]: IViewWhitespaceViewportData; } = {};\n\n\t\tlet hasVisibleZone = false;\n\t\tfor (const visibleWhitespace of visibleWhitespaces) {\n\t\t\tif (this._zones[visibleWhitespace.id].isInHiddenArea) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvisibleZones[visibleWhitespace.id] = visibleWhitespace;\n\t\t\thasVisibleZone = true;\n\t\t}\n\n\t\tconst keys = Object.keys(this._zones);\n\t\tfor (let i = 0, len = keys.length; i < len; i++) {\n\t\t\tconst id = keys[i];\n\t\t\tconst zone = this._zones[id];\n\n\t\t\tlet newTop = 0;\n\t\t\tlet newHeight = 0;\n\t\t\tlet newDisplay = 'none';\n\t\t\tif (visibleZones.hasOwnProperty(id)) {\n\t\t\t\tnewTop = visibleZones[id].verticalOffset - ctx.bigNumbersDelta;\n\t\t\t\tnewHeight = visibleZones[id].height;\n\t\t\t\tnewDisplay = 'block';\n\t\t\t\t// zone is visible\n\t\t\t\tif (!zone.isVisible) {\n\t\t\t\t\tzone.domNode.setAttribute('monaco-visible-view-zone', 'true');\n\t\t\t\t\tzone.isVisible = true;\n\t\t\t\t}\n\t\t\t\tthis._safeCallOnDomNodeTop(zone.delegate, ctx.getScrolledTopFromAbsoluteTop(visibleZones[id].verticalOffset));\n\t\t\t} else {\n\t\t\t\tif (zone.isVisible) {\n\t\t\t\t\tzone.domNode.removeAttribute('monaco-visible-view-zone');\n\t\t\t\t\tzone.isVisible = false;\n\t\t\t\t}\n\t\t\t\tthis._safeCallOnDomNodeTop(zone.delegate, ctx.getScrolledTopFromAbsoluteTop(-1000000));\n\t\t\t}\n\t\t\tzone.domNode.setTop(newTop);\n\t\t\tzone.domNode.setHeight(newHeight);\n\t\t\tzone.domNode.setDisplay(newDisplay);\n\n\t\t\tif (zone.marginDomNode) {\n\t\t\t\tzone.marginDomNode.setTop(newTop);\n\t\t\t\tzone.marginDomNode.setHeight(newHeight);\n\t\t\t\tzone.marginDomNode.setDisplay(newDisplay);\n\t\t\t}\n\t\t}\n\n\t\tif (hasVisibleZone) {\n\t\t\tthis.domNode.setWidth(Math.max(ctx.scrollWidth, this._contentWidth));\n\t\t\tthis.marginDomNode.setWidth(this._contentLeft);\n\t\t}\n\t}\n}\n\nfunction safeInvoke1Arg(func: Function, arg1: any): any {\n\ttry {\n\t\treturn func(arg1);\n\t} catch (e) {\n\t\tonUnexpectedError(e);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ScrollEvent } from 'vs/base/common/scrollable';\nimport { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { ScrollType } from 'vs/editor/common/editorCommon';\nimport { IModelDecorationsChangedEvent } from 'vs/editor/common/textModelEvents';\n\nexport const enum ViewEventType {\n\tViewCompositionStart,\n\tViewCompositionEnd,\n\tViewConfigurationChanged,\n\tViewCursorStateChanged,\n\tViewDecorationsChanged,\n\tViewFlushed,\n\tViewFocusChanged,\n\tViewLanguageConfigurationChanged,\n\tViewLineMappingChanged,\n\tViewLinesChanged,\n\tViewLinesDeleted,\n\tViewLinesInserted,\n\tViewRevealRangeRequest,\n\tViewScrollChanged,\n\tViewThemeChanged,\n\tViewTokensChanged,\n\tViewTokensColorsChanged,\n\tViewZonesChanged,\n}\n\nexport class ViewCompositionStartEvent {\n\tpublic readonly type = ViewEventType.ViewCompositionStart;\n\tconstructor() { }\n}\n\nexport class ViewCompositionEndEvent {\n\tpublic readonly type = ViewEventType.ViewCompositionEnd;\n\tconstructor() { }\n}\n\nexport class ViewConfigurationChangedEvent {\n\n\tpublic readonly type = ViewEventType.ViewConfigurationChanged;\n\n\tpublic readonly _source: ConfigurationChangedEvent;\n\n\tconstructor(source: ConfigurationChangedEvent) {\n\t\tthis._source = source;\n\t}\n\n\tpublic hasChanged(id: EditorOption): boolean {\n\t\treturn this._source.hasChanged(id);\n\t}\n}\n\nexport class ViewCursorStateChangedEvent {\n\n\tpublic readonly type = ViewEventType.ViewCursorStateChanged;\n\n\tpublic readonly selections: Selection[];\n\tpublic readonly modelSelections: Selection[];\n\n\tconstructor(selections: Selection[], modelSelections: Selection[]) {\n\t\tthis.selections = selections;\n\t\tthis.modelSelections = modelSelections;\n\t}\n}\n\nexport class ViewDecorationsChangedEvent {\n\n\tpublic readonly type = ViewEventType.ViewDecorationsChanged;\n\n\treadonly affectsMinimap: boolean;\n\treadonly affectsOverviewRuler: boolean;\n\n\tconstructor(source: IModelDecorationsChangedEvent | null) {\n\t\tif (source) {\n\t\t\tthis.affectsMinimap = source.affectsMinimap;\n\t\t\tthis.affectsOverviewRuler = source.affectsOverviewRuler;\n\t\t} else {\n\t\t\tthis.affectsMinimap = true;\n\t\t\tthis.affectsOverviewRuler = true;\n\t\t}\n\t}\n}\n\nexport class ViewFlushedEvent {\n\n\tpublic readonly type = ViewEventType.ViewFlushed;\n\n\tconstructor() {\n\t\t// Nothing to do\n\t}\n}\n\nexport class ViewFocusChangedEvent {\n\n\tpublic readonly type = ViewEventType.ViewFocusChanged;\n\n\tpublic readonly isFocused: boolean;\n\n\tconstructor(isFocused: boolean) {\n\t\tthis.isFocused = isFocused;\n\t}\n}\n\nexport class ViewLanguageConfigurationEvent {\n\n\tpublic readonly type = ViewEventType.ViewLanguageConfigurationChanged;\n}\n\nexport class ViewLineMappingChangedEvent {\n\n\tpublic readonly type = ViewEventType.ViewLineMappingChanged;\n\n\tconstructor() {\n\t\t// Nothing to do\n\t}\n}\n\nexport class ViewLinesChangedEvent {\n\n\tpublic readonly type = ViewEventType.ViewLinesChanged;\n\n\t/**\n\t * The first line that has changed.\n\t */\n\tpublic readonly fromLineNumber: number;\n\t/**\n\t * The last line that has changed.\n\t */\n\tpublic readonly toLineNumber: number;\n\n\tconstructor(fromLineNumber: number, toLineNumber: number) {\n\t\tthis.fromLineNumber = fromLineNumber;\n\t\tthis.toLineNumber = toLineNumber;\n\t}\n}\n\nexport class ViewLinesDeletedEvent {\n\n\tpublic readonly type = ViewEventType.ViewLinesDeleted;\n\n\t/**\n\t * At what line the deletion began (inclusive).\n\t */\n\tpublic readonly fromLineNumber: number;\n\t/**\n\t * At what line the deletion stopped (inclusive).\n\t */\n\tpublic readonly toLineNumber: number;\n\n\tconstructor(fromLineNumber: number, toLineNumber: number) {\n\t\tthis.fromLineNumber = fromLineNumber;\n\t\tthis.toLineNumber = toLineNumber;\n\t}\n}\n\nexport class ViewLinesInsertedEvent {\n\n\tpublic readonly type = ViewEventType.ViewLinesInserted;\n\n\t/**\n\t * Before what line did the insertion begin\n\t */\n\tpublic readonly fromLineNumber: number;\n\t/**\n\t * `toLineNumber` - `fromLineNumber` + 1 denotes the number of lines that were inserted\n\t */\n\tpublic readonly toLineNumber: number;\n\n\tconstructor(fromLineNumber: number, toLineNumber: number) {\n\t\tthis.fromLineNumber = fromLineNumber;\n\t\tthis.toLineNumber = toLineNumber;\n\t}\n}\n\nexport const enum VerticalRevealType {\n\tSimple = 0,\n\tCenter = 1,\n\tCenterIfOutsideViewport = 2,\n\tTop = 3,\n\tBottom = 4,\n\tNearTop = 5,\n\tNearTopIfOutsideViewport = 6,\n}\n\nexport class ViewRevealRangeRequestEvent {\n\n\tpublic readonly type = ViewEventType.ViewRevealRangeRequest;\n\n\n\tconstructor(\n\t\t/**\n\t\t * Source of the call that caused the event.\n\t\t */\n\t\tpublic readonly source: string | null | undefined,\n\t\t/**\n\t\t * Reduce the revealing to a minimum (e.g. avoid scrolling if the bounding box is visible and near the viewport edge).\n\t\t */\n\t\tpublic readonly minimalReveal: boolean,\n\t\t/**\n\t\t * Range to be reavealed.\n\t\t */\n\t\tpublic readonly range: Range | null,\n\t\t/**\n\t\t * Selections to be revealed.\n\t\t */\n\t\tpublic readonly selections: Selection[] | null,\n\t\t/**\n\t\t * The vertical reveal strategy.\n\t\t */\n\t\tpublic readonly verticalType: VerticalRevealType,\n\t\t/**\n\t\t * If true: there should be a horizontal & vertical revealing.\n\t\t * If false: there should be just a vertical revealing.\n\t\t */\n\t\tpublic readonly revealHorizontal: boolean,\n\t\t/**\n\t\t * The scroll type.\n\t\t */\n\t\tpublic readonly scrollType: ScrollType\n\t) { }\n}\n\nexport class ViewScrollChangedEvent {\n\n\tpublic readonly type = ViewEventType.ViewScrollChanged;\n\n\tpublic readonly scrollWidth: number;\n\tpublic readonly scrollLeft: number;\n\tpublic readonly scrollHeight: number;\n\tpublic readonly scrollTop: number;\n\n\tpublic readonly scrollWidthChanged: boolean;\n\tpublic readonly scrollLeftChanged: boolean;\n\tpublic readonly scrollHeightChanged: boolean;\n\tpublic readonly scrollTopChanged: boolean;\n\n\tconstructor(source: ScrollEvent) {\n\t\tthis.scrollWidth = source.scrollWidth;\n\t\tthis.scrollLeft = source.scrollLeft;\n\t\tthis.scrollHeight = source.scrollHeight;\n\t\tthis.scrollTop = source.scrollTop;\n\n\t\tthis.scrollWidthChanged = source.scrollWidthChanged;\n\t\tthis.scrollLeftChanged = source.scrollLeftChanged;\n\t\tthis.scrollHeightChanged = source.scrollHeightChanged;\n\t\tthis.scrollTopChanged = source.scrollTopChanged;\n\t}\n}\n\nexport class ViewThemeChangedEvent {\n\n\tpublic readonly type = ViewEventType.ViewThemeChanged;\n}\n\nexport class ViewTokensChangedEvent {\n\n\tpublic readonly type = ViewEventType.ViewTokensChanged;\n\n\tpublic readonly ranges: {\n\t\t/**\n\t\t * Start line number of range\n\t\t */\n\t\treadonly fromLineNumber: number;\n\t\t/**\n\t\t * End line number of range\n\t\t */\n\t\treadonly toLineNumber: number;\n\t}[];\n\n\tconstructor(ranges: { fromLineNumber: number; toLineNumber: number; }[]) {\n\t\tthis.ranges = ranges;\n\t}\n}\n\nexport class ViewTokensColorsChangedEvent {\n\n\tpublic readonly type = ViewEventType.ViewTokensColorsChanged;\n\n\tconstructor() {\n\t\t// Nothing to do\n\t}\n}\n\nexport class ViewZonesChangedEvent {\n\n\tpublic readonly type = ViewEventType.ViewZonesChanged;\n\n\tconstructor() {\n\t\t// Nothing to do\n\t}\n}\n\nexport type ViewEvent = (\n\tViewCompositionStartEvent\n\t| ViewCompositionEndEvent\n\t| ViewConfigurationChangedEvent\n\t| ViewCursorStateChangedEvent\n\t| ViewDecorationsChangedEvent\n\t| ViewFlushedEvent\n\t| ViewFocusChangedEvent\n\t| ViewLanguageConfigurationEvent\n\t| ViewLineMappingChangedEvent\n\t| ViewLinesChangedEvent\n\t| ViewLinesDeletedEvent\n\t| ViewLinesInsertedEvent\n\t| ViewRevealRangeRequestEvent\n\t| ViewScrollChangedEvent\n\t| ViewThemeChangedEvent\n\t| ViewTokensChangedEvent\n\t| ViewTokensColorsChangedEvent\n\t| ViewZonesChangedEvent\n);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IScrollPosition, Scrollable } from 'vs/base/common/scrollable';\nimport * as strings from 'vs/base/common/strings';\nimport { CursorConfiguration, CursorState, EditOperationType, IColumnSelectData, ICursorSimpleModel, PartialCursorState } from 'vs/editor/common/cursor/cursorCommon';\nimport { CursorChangeReason } from 'vs/editor/common/cursor/cursorEvents';\nimport { IViewLineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { IPosition, Position } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { INewScrollPosition, ScrollType } from 'vs/editor/common/editorCommon';\nimport { EndOfLinePreference, IModelDecorationOptions, ITextModel, PositionAffinity, TextModelResolvedOptions } from 'vs/editor/common/model';\nimport { BracketGuideOptions, IActiveIndentGuideInfo, IndentGuide } from 'vs/editor/common/textModelGuides';\nimport { EditorTheme } from 'vs/editor/common/viewModel/viewContext';\nimport { VerticalRevealType } from 'vs/editor/common/viewModel/viewEvents';\nimport { IEditorWhitespace, IWhitespaceChangeAccessor } from 'vs/editor/common/viewLayout/linesLayout';\nimport { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';\nimport { ILineBreaksComputer, InjectedText } from 'vs/editor/common/viewModel/modelLineProjectionData';\nimport { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';\n\nexport interface IViewModel extends ICursorSimpleModel {\n\n\treadonly model: ITextModel;\n\n\treadonly coordinatesConverter: ICoordinatesConverter;\n\n\treadonly viewLayout: IViewLayout;\n\n\treadonly cursorConfig: CursorConfiguration;\n\n\taddViewEventHandler(eventHandler: ViewEventHandler): void;\n\tremoveViewEventHandler(eventHandler: ViewEventHandler): void;\n\n\t/**\n\t * Gives a hint that a lot of requests are about to come in for these line numbers.\n\t */\n\tsetViewport(startLineNumber: number, endLineNumber: number, centeredLineNumber: number): void;\n\ttokenizeViewport(): void;\n\tsetHasFocus(hasFocus: boolean): void;\n\tonCompositionStart(): void;\n\tonCompositionEnd(): void;\n\tonDidColorThemeChange(): void;\n\n\tgetDecorationsInViewport(visibleRange: Range): ViewModelDecoration[];\n\tgetViewLineRenderingData(visibleRange: Range, lineNumber: number): ViewLineRenderingData;\n\tgetViewLineData(lineNumber: number): ViewLineData;\n\tgetMinimapLinesRenderingData(startLineNumber: number, endLineNumber: number, needed: boolean[]): MinimapLinesRenderingData;\n\tgetCompletelyVisibleViewRange(): Range;\n\tgetCompletelyVisibleViewRangeAtScrollTop(scrollTop: number): Range;\n\n\tgetTextModelOptions(): TextModelResolvedOptions;\n\tgetLineCount(): number;\n\tgetLineContent(lineNumber: number): string;\n\tgetLineLength(lineNumber: number): number;\n\tgetActiveIndentGuide(lineNumber: number, minLineNumber: number, maxLineNumber: number): IActiveIndentGuideInfo;\n\tgetLinesIndentGuides(startLineNumber: number, endLineNumber: number): number[];\n\tgetBracketGuidesInRangeByLine(startLineNumber: number, endLineNumber: number, activePosition: IPosition | null, options: BracketGuideOptions): IndentGuide[][];\n\tgetLineMinColumn(lineNumber: number): number;\n\tgetLineMaxColumn(lineNumber: number): number;\n\tgetLineFirstNonWhitespaceColumn(lineNumber: number): number;\n\tgetLineLastNonWhitespaceColumn(lineNumber: number): number;\n\tgetAllOverviewRulerDecorations(theme: EditorTheme): OverviewRulerDecorationsGroup[];\n\tinvalidateOverviewRulerColorCache(): void;\n\tinvalidateMinimapColorCache(): void;\n\tgetValueInRange(range: Range, eol: EndOfLinePreference): string;\n\n\tgetInjectedTextAt(viewPosition: Position): InjectedText | null;\n\n\tgetModelLineMaxColumn(modelLineNumber: number): number;\n\tvalidateModelPosition(modelPosition: IPosition): Position;\n\tvalidateModelRange(range: IRange): Range;\n\n\tdeduceModelPositionRelativeToViewPosition(viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position;\n\tgetEOL(): string;\n\tgetPlainTextToCopy(modelRanges: Range[], emptySelectionClipboard: boolean, forceCRLF: boolean): string | string[];\n\tgetRichTextToCopy(modelRanges: Range[], emptySelectionClipboard: boolean): { html: string, mode: string } | null;\n\n\t//#region model\n\n\tpushStackElement(): void;\n\n\t//#endregion\n\n\tcreateLineBreaksComputer(): ILineBreaksComputer;\n\n\t//#region cursor\n\tgetPrimaryCursorState(): CursorState;\n\tgetLastAddedCursorIndex(): number;\n\tgetCursorStates(): CursorState[];\n\tsetCursorStates(source: string | null | undefined, reason: CursorChangeReason, states: PartialCursorState[] | null): boolean;\n\tgetCursorColumnSelectData(): IColumnSelectData;\n\tgetCursorAutoClosedCharacters(): Range[];\n\tsetCursorColumnSelectData(columnSelectData: IColumnSelectData): void;\n\tgetPrevEditOperationType(): EditOperationType;\n\tsetPrevEditOperationType(type: EditOperationType): void;\n\trevealPrimaryCursor(source: string | null | undefined, revealHorizontal: boolean, minimalReveal?: boolean): void;\n\trevealTopMostCursor(source: string | null | undefined): void;\n\trevealBottomMostCursor(source: string | null | undefined): void;\n\trevealRange(source: string | null | undefined, revealHorizontal: boolean, viewRange: Range, verticalType: VerticalRevealType, scrollType: ScrollType): void;\n\t//#endregion\n\n\t//#region viewLayout\n\tgetVerticalOffsetForLineNumber(viewLineNumber: number): number;\n\tgetScrollTop(): number;\n\tsetScrollTop(newScrollTop: number, scrollType: ScrollType): void;\n\tsetScrollPosition(position: INewScrollPosition, type: ScrollType): void;\n\tdeltaScrollNow(deltaScrollLeft: number, deltaScrollTop: number): void;\n\tchangeWhitespace(callback: (accessor: IWhitespaceChangeAccessor) => void): void;\n\tsetMaxLineWidth(maxLineWidth: number): void;\n\t//#endregion\n}\n\nexport interface IViewLayout {\n\n\tgetScrollable(): Scrollable;\n\n\tgetScrollWidth(): number;\n\tgetScrollHeight(): number;\n\n\tgetCurrentScrollLeft(): number;\n\tgetCurrentScrollTop(): number;\n\tgetCurrentViewport(): Viewport;\n\n\tgetFutureViewport(): Viewport;\n\n\tvalidateScrollPosition(scrollPosition: INewScrollPosition): IScrollPosition;\n\n\tgetLinesViewportData(): IPartialViewLinesViewportData;\n\tgetWhitespaces(): IEditorWhitespace[];\n\n\tisAfterLines(verticalOffset: number): boolean;\n\tisInTopPadding(verticalOffset: number): boolean;\n\tisInBottomPadding(verticalOffset: number): boolean;\n\tgetLineNumberAtVerticalOffset(verticalOffset: number): number;\n\tgetVerticalOffsetForLineNumber(lineNumber: number): number;\n\tgetWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData | null;\n\n\t/**\n\t * Get the layout information for whitespaces currently in the viewport\n\t */\n\tgetWhitespaceViewportData(): IViewWhitespaceViewportData[];\n}\n\nexport interface IViewWhitespaceViewportData {\n\treadonly id: string;\n\treadonly afterLineNumber: number;\n\treadonly verticalOffset: number;\n\treadonly height: number;\n}\n\nexport class Viewport {\n\treadonly _viewportBrand: void = undefined;\n\n\treadonly top: number;\n\treadonly left: number;\n\treadonly width: number;\n\treadonly height: number;\n\n\tconstructor(top: number, left: number, width: number, height: number) {\n\t\tthis.top = top | 0;\n\t\tthis.left = left | 0;\n\t\tthis.width = width | 0;\n\t\tthis.height = height | 0;\n\t}\n}\n\nexport interface ICoordinatesConverter {\n\t// View -> Model conversion and related methods\n\tconvertViewPositionToModelPosition(viewPosition: Position): Position;\n\tconvertViewRangeToModelRange(viewRange: Range): Range;\n\tvalidateViewPosition(viewPosition: Position, expectedModelPosition: Position): Position;\n\tvalidateViewRange(viewRange: Range, expectedModelRange: Range): Range;\n\n\t// Model -> View conversion and related methods\n\tconvertModelPositionToViewPosition(modelPosition: Position, affinity?: PositionAffinity): Position;\n\t/**\n\t * @param affinity Only has an effect if the range is empty.\n\t*/\n\tconvertModelRangeToViewRange(modelRange: Range, affinity?: PositionAffinity): Range;\n\tmodelPositionIsVisible(modelPosition: Position): boolean;\n\tgetModelLineViewLineCount(modelLineNumber: number): number;\n\tgetViewLineNumberOfModelPosition(modelLineNumber: number, modelColumn: number): number;\n}\n\nexport class MinimapLinesRenderingData {\n\tpublic readonly tabSize: number;\n\tpublic readonly data: Array;\n\n\tconstructor(\n\t\ttabSize: number,\n\t\tdata: Array\n\t) {\n\t\tthis.tabSize = tabSize;\n\t\tthis.data = data;\n\t}\n}\n\nexport class ViewLineData {\n\t_viewLineDataBrand: void = undefined;\n\n\t/**\n\t * The content at this view line.\n\t */\n\tpublic readonly content: string;\n\t/**\n\t * Does this line continue with a wrapped line?\n\t */\n\tpublic readonly continuesWithWrappedLine: boolean;\n\t/**\n\t * The minimum allowed column at this view line.\n\t */\n\tpublic readonly minColumn: number;\n\t/**\n\t * The maximum allowed column at this view line.\n\t */\n\tpublic readonly maxColumn: number;\n\t/**\n\t * The visible column at the start of the line (after the fauxIndent).\n\t */\n\tpublic readonly startVisibleColumn: number;\n\t/**\n\t * The tokens at this view line.\n\t */\n\tpublic readonly tokens: IViewLineTokens;\n\n\t/**\n\t * Additional inline decorations for this line.\n\t*/\n\tpublic readonly inlineDecorations: readonly SingleLineInlineDecoration[] | null;\n\n\tconstructor(\n\t\tcontent: string,\n\t\tcontinuesWithWrappedLine: boolean,\n\t\tminColumn: number,\n\t\tmaxColumn: number,\n\t\tstartVisibleColumn: number,\n\t\ttokens: IViewLineTokens,\n\t\tinlineDecorations: readonly SingleLineInlineDecoration[] | null\n\t) {\n\t\tthis.content = content;\n\t\tthis.continuesWithWrappedLine = continuesWithWrappedLine;\n\t\tthis.minColumn = minColumn;\n\t\tthis.maxColumn = maxColumn;\n\t\tthis.startVisibleColumn = startVisibleColumn;\n\t\tthis.tokens = tokens;\n\t\tthis.inlineDecorations = inlineDecorations;\n\t}\n}\n\nexport class ViewLineRenderingData {\n\t/**\n\t * The minimum allowed column at this view line.\n\t */\n\tpublic readonly minColumn: number;\n\t/**\n\t * The maximum allowed column at this view line.\n\t */\n\tpublic readonly maxColumn: number;\n\t/**\n\t * The content at this view line.\n\t */\n\tpublic readonly content: string;\n\t/**\n\t * Does this line continue with a wrapped line?\n\t */\n\tpublic readonly continuesWithWrappedLine: boolean;\n\t/**\n\t * Describes if `content` contains RTL characters.\n\t */\n\tpublic readonly containsRTL: boolean;\n\t/**\n\t * Describes if `content` contains non basic ASCII chars.\n\t */\n\tpublic readonly isBasicASCII: boolean;\n\t/**\n\t * The tokens at this view line.\n\t */\n\tpublic readonly tokens: IViewLineTokens;\n\t/**\n\t * Inline decorations at this view line.\n\t */\n\tpublic readonly inlineDecorations: InlineDecoration[];\n\t/**\n\t * The tab size for this view model.\n\t */\n\tpublic readonly tabSize: number;\n\t/**\n\t * The visible column at the start of the line (after the fauxIndent)\n\t */\n\tpublic readonly startVisibleColumn: number;\n\n\tconstructor(\n\t\tminColumn: number,\n\t\tmaxColumn: number,\n\t\tcontent: string,\n\t\tcontinuesWithWrappedLine: boolean,\n\t\tmightContainRTL: boolean,\n\t\tmightContainNonBasicASCII: boolean,\n\t\ttokens: IViewLineTokens,\n\t\tinlineDecorations: InlineDecoration[],\n\t\ttabSize: number,\n\t\tstartVisibleColumn: number,\n\t) {\n\t\tthis.minColumn = minColumn;\n\t\tthis.maxColumn = maxColumn;\n\t\tthis.content = content;\n\t\tthis.continuesWithWrappedLine = continuesWithWrappedLine;\n\n\t\tthis.isBasicASCII = ViewLineRenderingData.isBasicASCII(content, mightContainNonBasicASCII);\n\t\tthis.containsRTL = ViewLineRenderingData.containsRTL(content, this.isBasicASCII, mightContainRTL);\n\n\t\tthis.tokens = tokens;\n\t\tthis.inlineDecorations = inlineDecorations;\n\t\tthis.tabSize = tabSize;\n\t\tthis.startVisibleColumn = startVisibleColumn;\n\t}\n\n\tpublic static isBasicASCII(lineContent: string, mightContainNonBasicASCII: boolean): boolean {\n\t\tif (mightContainNonBasicASCII) {\n\t\t\treturn strings.isBasicASCII(lineContent);\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic static containsRTL(lineContent: string, isBasicASCII: boolean, mightContainRTL: boolean): boolean {\n\t\tif (!isBasicASCII && mightContainRTL) {\n\t\t\treturn strings.containsRTL(lineContent);\n\t\t}\n\t\treturn false;\n\t}\n}\n\nexport const enum InlineDecorationType {\n\tRegular = 0,\n\tBefore = 1,\n\tAfter = 2,\n\tRegularAffectingLetterSpacing = 3\n}\n\nexport class InlineDecoration {\n\tconstructor(\n\t\tpublic readonly range: Range,\n\t\tpublic readonly inlineClassName: string,\n\t\tpublic readonly type: InlineDecorationType\n\t) {\n\t}\n}\n\nexport class SingleLineInlineDecoration {\n\tconstructor(\n\t\tpublic readonly startOffset: number,\n\t\tpublic readonly endOffset: number,\n\t\tpublic readonly inlineClassName: string,\n\t\tpublic readonly inlineClassNameAffectsLetterSpacing: boolean\n\t) {\n\t}\n\n\ttoInlineDecoration(lineNumber: number): InlineDecoration {\n\t\treturn new InlineDecoration(\n\t\t\tnew Range(lineNumber, this.startOffset + 1, lineNumber, this.endOffset + 1),\n\t\t\tthis.inlineClassName,\n\t\t\tthis.inlineClassNameAffectsLetterSpacing ? InlineDecorationType.RegularAffectingLetterSpacing : InlineDecorationType.Regular\n\t\t);\n\t}\n}\n\nexport class ViewModelDecoration {\n\t_viewModelDecorationBrand: void = undefined;\n\n\tpublic readonly range: Range;\n\tpublic readonly options: IModelDecorationOptions;\n\n\tconstructor(range: Range, options: IModelDecorationOptions) {\n\t\tthis.range = range;\n\t\tthis.options = options;\n\t}\n}\n\nexport class OverviewRulerDecorationsGroup {\n\n\tconstructor(\n\t\tpublic readonly color: string,\n\t\tpublic readonly zIndex: number,\n\t\t/**\n\t\t * Decorations are encoded in a number array using the following scheme:\n\t\t * - 3*i = lane\n\t\t * - 3*i+1 = startLineNumber\n\t\t * - 3*i+2 = endLineNumber\n\t\t */\n\t\tpublic readonly data: number[]\n\t) { }\n\n\tpublic static cmp(a: OverviewRulerDecorationsGroup, b: OverviewRulerDecorationsGroup): number {\n\t\tif (a.zIndex === b.zIndex) {\n\t\t\tif (a.color < b.color) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif (a.color > b.color) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\treturn 0;\n\t\t}\n\t\treturn a.zIndex - b.zIndex;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { LineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { Position } from 'vs/editor/common/core/position';\nimport { IRange } from 'vs/editor/common/core/range';\nimport { EndOfLinePreference, ITextModel, PositionAffinity } from 'vs/editor/common/model';\nimport { LineInjectedText } from 'vs/editor/common/textModelEvents';\nimport { InjectedText, ModelLineProjectionData } from 'vs/editor/common/viewModel/modelLineProjectionData';\nimport { SingleLineInlineDecoration, ViewLineData } from 'vs/editor/common/viewModel/viewModel';\n\nexport interface IModelLineProjection {\n\tisVisible(): boolean;\n\n\t/**\n\t * This invalidates the current instance (potentially reuses and returns it again).\n\t*/\n\tsetVisible(isVisible: boolean): IModelLineProjection;\n\n\tgetProjectionData(): ModelLineProjectionData | null;\n\tgetViewLineCount(): number;\n\tgetViewLineContent(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): string;\n\tgetViewLineLength(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number;\n\tgetViewLineMinColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number;\n\tgetViewLineMaxColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number;\n\tgetViewLineData(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): ViewLineData;\n\tgetViewLinesData(model: ISimpleModel, modelLineNumber: number, outputLineIdx: number, lineCount: number, globalStartIndex: number, needed: boolean[], result: Array): void;\n\n\tgetModelColumnOfViewPosition(outputLineIndex: number, outputColumn: number): number;\n\tgetViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number, affinity?: PositionAffinity): Position;\n\tgetViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number;\n\tnormalizePosition(outputLineIndex: number, outputPosition: Position, affinity: PositionAffinity): Position;\n\n\tgetInjectedTextAt(outputLineIndex: number, column: number): InjectedText | null;\n}\n\nexport interface ISimpleModel {\n\tgetLineTokens(lineNumber: number): LineTokens;\n\tgetLineContent(lineNumber: number): string;\n\tgetLineLength(lineNumber: number): number;\n\tgetLineMinColumn(lineNumber: number): number;\n\tgetLineMaxColumn(lineNumber: number): number;\n\tgetValueInRange(range: IRange, eol?: EndOfLinePreference): string;\n}\n\nexport function createModelLineProjection(lineBreakData: ModelLineProjectionData | null, isVisible: boolean): IModelLineProjection {\n\tif (lineBreakData === null) {\n\t\t// No mapping needed\n\t\tif (isVisible) {\n\t\t\treturn IdentityModelLineProjection.INSTANCE;\n\t\t}\n\t\treturn HiddenModelLineProjection.INSTANCE;\n\t} else {\n\t\treturn new ModelLineProjection(lineBreakData, isVisible);\n\t}\n}\n\n/**\n * This projection is used to\n * * wrap model lines\n * * inject text\n */\nclass ModelLineProjection implements IModelLineProjection {\n\tprivate readonly _projectionData: ModelLineProjectionData;\n\tprivate _isVisible: boolean;\n\n\tconstructor(lineBreakData: ModelLineProjectionData, isVisible: boolean) {\n\t\tthis._projectionData = lineBreakData;\n\t\tthis._isVisible = isVisible;\n\t}\n\n\tpublic isVisible(): boolean {\n\t\treturn this._isVisible;\n\t}\n\n\tpublic setVisible(isVisible: boolean): IModelLineProjection {\n\t\tthis._isVisible = isVisible;\n\t\treturn this;\n\t}\n\n\tpublic getProjectionData(): ModelLineProjectionData | null {\n\t\treturn this._projectionData;\n\t}\n\n\tpublic getViewLineCount(): number {\n\t\tif (!this._isVisible) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn this._projectionData.getOutputLineCount();\n\t}\n\n\tpublic getViewLineContent(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): string {\n\t\tthis._assertVisible();\n\n\t\tconst startOffsetInInputWithInjections = outputLineIndex > 0 ? this._projectionData.breakOffsets[outputLineIndex - 1] : 0;\n\t\tconst endOffsetInInputWithInjections = this._projectionData.breakOffsets[outputLineIndex];\n\n\t\tlet r: string;\n\t\tif (this._projectionData.injectionOffsets !== null) {\n\t\t\tconst injectedTexts = this._projectionData.injectionOffsets.map(\n\t\t\t\t(offset, idx) => new LineInjectedText(\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\toffset + 1,\n\t\t\t\t\tthis._projectionData.injectionOptions![idx],\n\t\t\t\t\t0\n\t\t\t\t)\n\t\t\t);\n\t\t\tconst lineWithInjections = LineInjectedText.applyInjectedText(\n\t\t\t\tmodel.getLineContent(modelLineNumber),\n\t\t\t\tinjectedTexts\n\t\t\t);\n\t\t\tr = lineWithInjections.substring(startOffsetInInputWithInjections, endOffsetInInputWithInjections);\n\t\t} else {\n\t\t\tr = model.getValueInRange({\n\t\t\t\tstartLineNumber: modelLineNumber,\n\t\t\t\tstartColumn: startOffsetInInputWithInjections + 1,\n\t\t\t\tendLineNumber: modelLineNumber,\n\t\t\t\tendColumn: endOffsetInInputWithInjections + 1\n\t\t\t});\n\t\t}\n\n\t\tif (outputLineIndex > 0) {\n\t\t\tr = spaces(this._projectionData.wrappedTextIndentLength) + r;\n\t\t}\n\n\t\treturn r;\n\t}\n\n\tpublic getViewLineLength(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number {\n\t\tthis._assertVisible();\n\t\treturn this._projectionData.getLineLength(outputLineIndex);\n\t}\n\n\tpublic getViewLineMinColumn(_model: ITextModel, _modelLineNumber: number, outputLineIndex: number): number {\n\t\tthis._assertVisible();\n\t\treturn this._projectionData.getMinOutputOffset(outputLineIndex) + 1;\n\t}\n\n\tpublic getViewLineMaxColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number {\n\t\tthis._assertVisible();\n\t\treturn this._projectionData.getMaxOutputOffset(outputLineIndex) + 1;\n\t}\n\n\t/**\n\t * Try using {@link getViewLinesData} instead.\n\t*/\n\tpublic getViewLineData(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): ViewLineData {\n\t\tconst arr = new Array();\n\t\tthis.getViewLinesData(model, modelLineNumber, outputLineIndex, 1, 0, [true], arr);\n\t\treturn arr[0];\n\t}\n\n\tpublic getViewLinesData(model: ISimpleModel, modelLineNumber: number, outputLineIdx: number, lineCount: number, globalStartIndex: number, needed: boolean[], result: Array): void {\n\t\tthis._assertVisible();\n\n\t\tconst lineBreakData = this._projectionData;\n\n\t\tconst injectionOffsets = lineBreakData.injectionOffsets;\n\t\tconst injectionOptions = lineBreakData.injectionOptions;\n\n\t\tlet inlineDecorationsPerOutputLine: SingleLineInlineDecoration[][] | null = null;\n\n\t\tif (injectionOffsets) {\n\t\t\tinlineDecorationsPerOutputLine = [];\n\t\t\tlet totalInjectedTextLengthBefore = 0;\n\t\t\tlet currentInjectedOffset = 0;\n\n\t\t\tfor (let outputLineIndex = 0; outputLineIndex < lineBreakData.getOutputLineCount(); outputLineIndex++) {\n\t\t\t\tconst inlineDecorations = new Array();\n\t\t\t\tinlineDecorationsPerOutputLine[outputLineIndex] = inlineDecorations;\n\n\t\t\t\tconst lineStartOffsetInInputWithInjections = outputLineIndex > 0 ? lineBreakData.breakOffsets[outputLineIndex - 1] : 0;\n\t\t\t\tconst lineEndOffsetInInputWithInjections = lineBreakData.breakOffsets[outputLineIndex];\n\n\t\t\t\twhile (currentInjectedOffset < injectionOffsets.length) {\n\t\t\t\t\tconst length = injectionOptions![currentInjectedOffset].content.length;\n\t\t\t\t\tconst injectedTextStartOffsetInInputWithInjections = injectionOffsets[currentInjectedOffset] + totalInjectedTextLengthBefore;\n\t\t\t\t\tconst injectedTextEndOffsetInInputWithInjections = injectedTextStartOffsetInInputWithInjections + length;\n\n\t\t\t\t\tif (injectedTextStartOffsetInInputWithInjections > lineEndOffsetInInputWithInjections) {\n\t\t\t\t\t\t// Injected text only starts in later wrapped lines.\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (lineStartOffsetInInputWithInjections < injectedTextEndOffsetInInputWithInjections) {\n\t\t\t\t\t\t// Injected text ends after or in this line (but also starts in or before this line).\n\t\t\t\t\t\tconst options = injectionOptions![currentInjectedOffset];\n\t\t\t\t\t\tif (options.inlineClassName) {\n\t\t\t\t\t\t\tconst offset = (outputLineIndex > 0 ? lineBreakData.wrappedTextIndentLength : 0);\n\t\t\t\t\t\t\tconst start = offset + Math.max(injectedTextStartOffsetInInputWithInjections - lineStartOffsetInInputWithInjections, 0);\n\t\t\t\t\t\t\tconst end = offset + Math.min(injectedTextEndOffsetInInputWithInjections - lineStartOffsetInInputWithInjections, lineEndOffsetInInputWithInjections);\n\t\t\t\t\t\t\tif (start !== end) {\n\t\t\t\t\t\t\t\tinlineDecorations.push(new SingleLineInlineDecoration(start, end, options.inlineClassName, options.inlineClassNameAffectsLetterSpacing!));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (injectedTextEndOffsetInInputWithInjections <= lineEndOffsetInInputWithInjections) {\n\t\t\t\t\t\ttotalInjectedTextLengthBefore += length;\n\t\t\t\t\t\tcurrentInjectedOffset++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// injected text breaks into next line, process it again\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet lineWithInjections: LineTokens;\n\t\tif (injectionOffsets) {\n\t\t\tlineWithInjections = model.getLineTokens(modelLineNumber).withInserted(injectionOffsets.map((offset, idx) => ({\n\t\t\t\toffset,\n\t\t\t\ttext: injectionOptions![idx].content,\n\t\t\t\ttokenMetadata: LineTokens.defaultTokenMetadata\n\t\t\t})));\n\t\t} else {\n\t\t\tlineWithInjections = model.getLineTokens(modelLineNumber);\n\t\t}\n\n\t\tfor (let outputLineIndex = outputLineIdx; outputLineIndex < outputLineIdx + lineCount; outputLineIndex++) {\n\t\t\tconst globalIndex = globalStartIndex + outputLineIndex - outputLineIdx;\n\t\t\tif (!needed[globalIndex]) {\n\t\t\t\tresult[globalIndex] = null;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tresult[globalIndex] = this._getViewLineData(lineWithInjections, inlineDecorationsPerOutputLine ? inlineDecorationsPerOutputLine[outputLineIndex] : null, outputLineIndex);\n\t\t}\n\t}\n\n\tprivate _getViewLineData(lineWithInjections: LineTokens, inlineDecorations: null | SingleLineInlineDecoration[], outputLineIndex: number): ViewLineData {\n\t\tthis._assertVisible();\n\t\tconst lineBreakData = this._projectionData;\n\t\tconst deltaStartIndex = (outputLineIndex > 0 ? lineBreakData.wrappedTextIndentLength : 0);\n\n\t\tconst lineStartOffsetInInputWithInjections = outputLineIndex > 0 ? lineBreakData.breakOffsets[outputLineIndex - 1] : 0;\n\t\tconst lineEndOffsetInInputWithInjections = lineBreakData.breakOffsets[outputLineIndex];\n\t\tconst tokens = lineWithInjections.sliceAndInflate(lineStartOffsetInInputWithInjections, lineEndOffsetInInputWithInjections, deltaStartIndex);\n\n\t\tlet lineContent = tokens.getLineContent();\n\t\tif (outputLineIndex > 0) {\n\t\t\tlineContent = spaces(lineBreakData.wrappedTextIndentLength) + lineContent;\n\t\t}\n\n\t\tconst minColumn = this._projectionData.getMinOutputOffset(outputLineIndex) + 1;\n\t\tconst maxColumn = lineContent.length + 1;\n\t\tconst continuesWithWrappedLine = (outputLineIndex + 1 < this.getViewLineCount());\n\t\tconst startVisibleColumn = (outputLineIndex === 0 ? 0 : lineBreakData.breakOffsetsVisibleColumn[outputLineIndex - 1]);\n\n\t\treturn new ViewLineData(\n\t\t\tlineContent,\n\t\t\tcontinuesWithWrappedLine,\n\t\t\tminColumn,\n\t\t\tmaxColumn,\n\t\t\tstartVisibleColumn,\n\t\t\ttokens,\n\t\t\tinlineDecorations\n\t\t);\n\t}\n\n\tpublic getModelColumnOfViewPosition(outputLineIndex: number, outputColumn: number): number {\n\t\tthis._assertVisible();\n\t\treturn this._projectionData.translateToInputOffset(outputLineIndex, outputColumn - 1) + 1;\n\t}\n\n\tpublic getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number, affinity: PositionAffinity = PositionAffinity.None): Position {\n\t\tthis._assertVisible();\n\t\tconst r = this._projectionData.translateToOutputPosition(inputColumn - 1, affinity);\n\t\treturn r.toPosition(deltaLineNumber);\n\t}\n\n\tpublic getViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number {\n\t\tthis._assertVisible();\n\t\tconst r = this._projectionData.translateToOutputPosition(inputColumn - 1);\n\t\treturn deltaLineNumber + r.outputLineIndex;\n\t}\n\n\tpublic normalizePosition(outputLineIndex: number, outputPosition: Position, affinity: PositionAffinity): Position {\n\t\tconst baseViewLineNumber = outputPosition.lineNumber - outputLineIndex;\n\t\tconst normalizedOutputPosition = this._projectionData.normalizeOutputPosition(outputLineIndex, outputPosition.column - 1, affinity);\n\t\tconst result = normalizedOutputPosition.toPosition(baseViewLineNumber);\n\t\treturn result;\n\t}\n\n\tpublic getInjectedTextAt(outputLineIndex: number, outputColumn: number): InjectedText | null {\n\t\treturn this._projectionData.getInjectedText(outputLineIndex, outputColumn - 1);\n\t}\n\n\tprivate _assertVisible() {\n\t\tif (!this._isVisible) {\n\t\t\tthrow new Error('Not supported');\n\t\t}\n\t}\n}\n\n/**\n * This projection does not change the model line.\n*/\nclass IdentityModelLineProjection implements IModelLineProjection {\n\tpublic static readonly INSTANCE = new IdentityModelLineProjection();\n\n\tprivate constructor() { }\n\n\tpublic isVisible(): boolean {\n\t\treturn true;\n\t}\n\n\tpublic setVisible(isVisible: boolean): IModelLineProjection {\n\t\tif (isVisible) {\n\t\t\treturn this;\n\t\t}\n\t\treturn HiddenModelLineProjection.INSTANCE;\n\t}\n\n\tpublic getProjectionData(): ModelLineProjectionData | null {\n\t\treturn null;\n\t}\n\n\tpublic getViewLineCount(): number {\n\t\treturn 1;\n\t}\n\n\tpublic getViewLineContent(model: ISimpleModel, modelLineNumber: number, _outputLineIndex: number): string {\n\t\treturn model.getLineContent(modelLineNumber);\n\t}\n\n\tpublic getViewLineLength(model: ISimpleModel, modelLineNumber: number, _outputLineIndex: number): number {\n\t\treturn model.getLineLength(modelLineNumber);\n\t}\n\n\tpublic getViewLineMinColumn(model: ISimpleModel, modelLineNumber: number, _outputLineIndex: number): number {\n\t\treturn model.getLineMinColumn(modelLineNumber);\n\t}\n\n\tpublic getViewLineMaxColumn(model: ISimpleModel, modelLineNumber: number, _outputLineIndex: number): number {\n\t\treturn model.getLineMaxColumn(modelLineNumber);\n\t}\n\n\tpublic getViewLineData(model: ISimpleModel, modelLineNumber: number, _outputLineIndex: number): ViewLineData {\n\t\tconst lineTokens = model.getLineTokens(modelLineNumber);\n\t\tconst lineContent = lineTokens.getLineContent();\n\t\treturn new ViewLineData(\n\t\t\tlineContent,\n\t\t\tfalse,\n\t\t\t1,\n\t\t\tlineContent.length + 1,\n\t\t\t0,\n\t\t\tlineTokens.inflate(),\n\t\t\tnull\n\t\t);\n\t}\n\n\tpublic getViewLinesData(model: ISimpleModel, modelLineNumber: number, _fromOuputLineIndex: number, _toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: Array): void {\n\t\tif (!needed[globalStartIndex]) {\n\t\t\tresult[globalStartIndex] = null;\n\t\t\treturn;\n\t\t}\n\t\tresult[globalStartIndex] = this.getViewLineData(model, modelLineNumber, 0);\n\t}\n\n\tpublic getModelColumnOfViewPosition(_outputLineIndex: number, outputColumn: number): number {\n\t\treturn outputColumn;\n\t}\n\n\tpublic getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number): Position {\n\t\treturn new Position(deltaLineNumber, inputColumn);\n\t}\n\n\tpublic getViewLineNumberOfModelPosition(deltaLineNumber: number, _inputColumn: number): number {\n\t\treturn deltaLineNumber;\n\t}\n\n\tpublic normalizePosition(outputLineIndex: number, outputPosition: Position, affinity: PositionAffinity): Position {\n\t\treturn outputPosition;\n\t}\n\n\tpublic getInjectedTextAt(_outputLineIndex: number, _outputColumn: number): InjectedText | null {\n\t\treturn null;\n\t}\n}\n\n/**\n * This projection hides the model line.\n */\nclass HiddenModelLineProjection implements IModelLineProjection {\n\tpublic static readonly INSTANCE = new HiddenModelLineProjection();\n\n\tprivate constructor() { }\n\n\tpublic isVisible(): boolean {\n\t\treturn false;\n\t}\n\n\tpublic setVisible(isVisible: boolean): IModelLineProjection {\n\t\tif (!isVisible) {\n\t\t\treturn this;\n\t\t}\n\t\treturn IdentityModelLineProjection.INSTANCE;\n\t}\n\n\tpublic getProjectionData(): ModelLineProjectionData | null {\n\t\treturn null;\n\t}\n\n\tpublic getViewLineCount(): number {\n\t\treturn 0;\n\t}\n\n\tpublic getViewLineContent(_model: ISimpleModel, _modelLineNumber: number, _outputLineIndex: number): string {\n\t\tthrow new Error('Not supported');\n\t}\n\n\tpublic getViewLineLength(_model: ISimpleModel, _modelLineNumber: number, _outputLineIndex: number): number {\n\t\tthrow new Error('Not supported');\n\t}\n\n\tpublic getViewLineMinColumn(_model: ISimpleModel, _modelLineNumber: number, _outputLineIndex: number): number {\n\t\tthrow new Error('Not supported');\n\t}\n\n\tpublic getViewLineMaxColumn(_model: ISimpleModel, _modelLineNumber: number, _outputLineIndex: number): number {\n\t\tthrow new Error('Not supported');\n\t}\n\n\tpublic getViewLineData(_model: ISimpleModel, _modelLineNumber: number, _outputLineIndex: number): ViewLineData {\n\t\tthrow new Error('Not supported');\n\t}\n\n\tpublic getViewLinesData(_model: ISimpleModel, _modelLineNumber: number, _fromOuputLineIndex: number, _toOutputLineIndex: number, _globalStartIndex: number, _needed: boolean[], _result: ViewLineData[]): void {\n\t\tthrow new Error('Not supported');\n\t}\n\n\tpublic getModelColumnOfViewPosition(_outputLineIndex: number, _outputColumn: number): number {\n\t\tthrow new Error('Not supported');\n\t}\n\n\tpublic getViewPositionOfModelPosition(_deltaLineNumber: number, _inputColumn: number): Position {\n\t\tthrow new Error('Not supported');\n\t}\n\n\tpublic getViewLineNumberOfModelPosition(_deltaLineNumber: number, _inputColumn: number): number {\n\t\tthrow new Error('Not supported');\n\t}\n\n\tpublic normalizePosition(outputLineIndex: number, outputPosition: Position, affinity: PositionAffinity): Position {\n\t\tthrow new Error('Not supported');\n\t}\n\n\tpublic getInjectedTextAt(_outputLineIndex: number, _outputColumn: number): InjectedText | null {\n\t\tthrow new Error('Not supported');\n\t}\n}\n\nlet _spaces: string[] = [''];\nfunction spaces(count: number): string {\n\tif (count >= _spaces.length) {\n\t\tfor (let i = 1; i <= count; i++) {\n\t\t\t_spaces[i] = _makeSpaces(i);\n\t\t}\n\t}\n\treturn _spaces[count];\n}\n\nfunction _makeSpaces(count: number): string {\n\treturn new Array(count + 1).join(' ');\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';\nimport { ViewEvent } from 'vs/editor/common/viewModel/viewEvents';\nimport { IContentSizeChangedEvent } from 'vs/editor/common/editorCommon';\nimport { Emitter } from 'vs/base/common/event';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { CursorChangeReason } from 'vs/editor/common/cursor/cursorEvents';\n\nexport class ViewModelEventDispatcher extends Disposable {\n\n\tprivate readonly _onEvent = this._register(new Emitter());\n\tpublic readonly onEvent = this._onEvent.event;\n\n\tprivate readonly _eventHandlers: ViewEventHandler[];\n\tprivate _viewEventQueue: ViewEvent[] | null;\n\tprivate _isConsumingViewEventQueue: boolean;\n\tprivate _collector: ViewModelEventsCollector | null;\n\tprivate _collectorCnt: number;\n\tprivate _outgoingEvents: OutgoingViewModelEvent[];\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis._eventHandlers = [];\n\t\tthis._viewEventQueue = null;\n\t\tthis._isConsumingViewEventQueue = false;\n\t\tthis._collector = null;\n\t\tthis._collectorCnt = 0;\n\t\tthis._outgoingEvents = [];\n\t}\n\n\tpublic emitOutgoingEvent(e: OutgoingViewModelEvent): void {\n\t\tthis._addOutgoingEvent(e);\n\t\tthis._emitOutgoingEvents();\n\t}\n\n\tprivate _addOutgoingEvent(e: OutgoingViewModelEvent): void {\n\t\tfor (let i = 0, len = this._outgoingEvents.length; i < len; i++) {\n\t\t\tif (this._outgoingEvents[i].kind === e.kind) {\n\t\t\t\tthis._outgoingEvents[i] = this._outgoingEvents[i].merge(e);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t// not merged\n\t\tthis._outgoingEvents.push(e);\n\t}\n\n\tprivate _emitOutgoingEvents(): void {\n\t\twhile (this._outgoingEvents.length > 0) {\n\t\t\tif (this._collector || this._isConsumingViewEventQueue) {\n\t\t\t\t// right now collecting or emitting view events, so let's postpone emitting\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst event = this._outgoingEvents.shift()!;\n\t\t\tif (event.isNoOp()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis._onEvent.fire(event);\n\t\t}\n\t}\n\n\tpublic addViewEventHandler(eventHandler: ViewEventHandler): void {\n\t\tfor (let i = 0, len = this._eventHandlers.length; i < len; i++) {\n\t\t\tif (this._eventHandlers[i] === eventHandler) {\n\t\t\t\tconsole.warn('Detected duplicate listener in ViewEventDispatcher', eventHandler);\n\t\t\t}\n\t\t}\n\t\tthis._eventHandlers.push(eventHandler);\n\t}\n\n\tpublic removeViewEventHandler(eventHandler: ViewEventHandler): void {\n\t\tfor (let i = 0; i < this._eventHandlers.length; i++) {\n\t\t\tif (this._eventHandlers[i] === eventHandler) {\n\t\t\t\tthis._eventHandlers.splice(i, 1);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic beginEmitViewEvents(): ViewModelEventsCollector {\n\t\tthis._collectorCnt++;\n\t\tif (this._collectorCnt === 1) {\n\t\t\tthis._collector = new ViewModelEventsCollector();\n\t\t}\n\t\treturn this._collector!;\n\t}\n\n\tpublic endEmitViewEvents(): void {\n\t\tthis._collectorCnt--;\n\t\tif (this._collectorCnt === 0) {\n\t\t\tconst outgoingEvents = this._collector!.outgoingEvents;\n\t\t\tconst viewEvents = this._collector!.viewEvents;\n\t\t\tthis._collector = null;\n\n\t\t\tfor (const outgoingEvent of outgoingEvents) {\n\t\t\t\tthis._addOutgoingEvent(outgoingEvent);\n\t\t\t}\n\n\t\t\tif (viewEvents.length > 0) {\n\t\t\t\tthis._emitMany(viewEvents);\n\t\t\t}\n\t\t}\n\t\tthis._emitOutgoingEvents();\n\t}\n\n\tpublic emitSingleViewEvent(event: ViewEvent): void {\n\t\ttry {\n\t\t\tconst eventsCollector = this.beginEmitViewEvents();\n\t\t\teventsCollector.emitViewEvent(event);\n\t\t} finally {\n\t\t\tthis.endEmitViewEvents();\n\t\t}\n\t}\n\n\tprivate _emitMany(events: ViewEvent[]): void {\n\t\tif (this._viewEventQueue) {\n\t\t\tthis._viewEventQueue = this._viewEventQueue.concat(events);\n\t\t} else {\n\t\t\tthis._viewEventQueue = events;\n\t\t}\n\n\t\tif (!this._isConsumingViewEventQueue) {\n\t\t\tthis._consumeViewEventQueue();\n\t\t}\n\t}\n\n\tprivate _consumeViewEventQueue(): void {\n\t\ttry {\n\t\t\tthis._isConsumingViewEventQueue = true;\n\t\t\tthis._doConsumeQueue();\n\t\t} finally {\n\t\t\tthis._isConsumingViewEventQueue = false;\n\t\t}\n\t}\n\n\tprivate _doConsumeQueue(): void {\n\t\twhile (this._viewEventQueue) {\n\t\t\t// Empty event queue, as events might come in while sending these off\n\t\t\tconst events = this._viewEventQueue;\n\t\t\tthis._viewEventQueue = null;\n\n\t\t\t// Use a clone of the event handlers list, as they might remove themselves\n\t\t\tconst eventHandlers = this._eventHandlers.slice(0);\n\t\t\tfor (const eventHandler of eventHandlers) {\n\t\t\t\teventHandler.handleEvents(events);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class ViewModelEventsCollector {\n\n\tpublic readonly viewEvents: ViewEvent[];\n\tpublic readonly outgoingEvents: OutgoingViewModelEvent[];\n\n\tconstructor() {\n\t\tthis.viewEvents = [];\n\t\tthis.outgoingEvents = [];\n\t}\n\n\tpublic emitViewEvent(event: ViewEvent) {\n\t\tthis.viewEvents.push(event);\n\t}\n\n\tpublic emitOutgoingEvent(e: OutgoingViewModelEvent): void {\n\t\tthis.outgoingEvents.push(e);\n\t}\n}\n\nexport type OutgoingViewModelEvent = (\n\tContentSizeChangedEvent\n\t| FocusChangedEvent\n\t| ScrollChangedEvent\n\t| ViewZonesChangedEvent\n\t| HiddenAreasChangedEvent\n\t| ReadOnlyEditAttemptEvent\n\t| CursorStateChangedEvent\n);\n\nexport const enum OutgoingViewModelEventKind {\n\tContentSizeChanged,\n\tFocusChanged,\n\tScrollChanged,\n\tViewZonesChanged,\n\tHiddenAreasChanged,\n\tReadOnlyEditAttempt,\n\tCursorStateChanged,\n}\n\nexport class ContentSizeChangedEvent implements IContentSizeChangedEvent {\n\n\tpublic readonly kind = OutgoingViewModelEventKind.ContentSizeChanged;\n\n\tprivate readonly _oldContentWidth: number;\n\tprivate readonly _oldContentHeight: number;\n\n\treadonly contentWidth: number;\n\treadonly contentHeight: number;\n\treadonly contentWidthChanged: boolean;\n\treadonly contentHeightChanged: boolean;\n\n\tconstructor(oldContentWidth: number, oldContentHeight: number, contentWidth: number, contentHeight: number) {\n\t\tthis._oldContentWidth = oldContentWidth;\n\t\tthis._oldContentHeight = oldContentHeight;\n\t\tthis.contentWidth = contentWidth;\n\t\tthis.contentHeight = contentHeight;\n\t\tthis.contentWidthChanged = (this._oldContentWidth !== this.contentWidth);\n\t\tthis.contentHeightChanged = (this._oldContentHeight !== this.contentHeight);\n\t}\n\n\tpublic isNoOp(): boolean {\n\t\treturn (!this.contentWidthChanged && !this.contentHeightChanged);\n\t}\n\n\n\tpublic merge(other: OutgoingViewModelEvent): ContentSizeChangedEvent {\n\t\tif (other.kind !== OutgoingViewModelEventKind.ContentSizeChanged) {\n\t\t\treturn this;\n\t\t}\n\t\treturn new ContentSizeChangedEvent(this._oldContentWidth, this._oldContentHeight, other.contentWidth, other.contentHeight);\n\t}\n}\n\nexport class FocusChangedEvent {\n\n\tpublic readonly kind = OutgoingViewModelEventKind.FocusChanged;\n\n\treadonly oldHasFocus: boolean;\n\treadonly hasFocus: boolean;\n\n\tconstructor(oldHasFocus: boolean, hasFocus: boolean) {\n\t\tthis.oldHasFocus = oldHasFocus;\n\t\tthis.hasFocus = hasFocus;\n\t}\n\n\tpublic isNoOp(): boolean {\n\t\treturn (this.oldHasFocus === this.hasFocus);\n\t}\n\n\tpublic merge(other: OutgoingViewModelEvent): FocusChangedEvent {\n\t\tif (other.kind !== OutgoingViewModelEventKind.FocusChanged) {\n\t\t\treturn this;\n\t\t}\n\t\treturn new FocusChangedEvent(this.oldHasFocus, other.hasFocus);\n\t}\n}\n\nexport class ScrollChangedEvent {\n\n\tpublic readonly kind = OutgoingViewModelEventKind.ScrollChanged;\n\n\tprivate readonly _oldScrollWidth: number;\n\tprivate readonly _oldScrollLeft: number;\n\tprivate readonly _oldScrollHeight: number;\n\tprivate readonly _oldScrollTop: number;\n\n\tpublic readonly scrollWidth: number;\n\tpublic readonly scrollLeft: number;\n\tpublic readonly scrollHeight: number;\n\tpublic readonly scrollTop: number;\n\n\tpublic readonly scrollWidthChanged: boolean;\n\tpublic readonly scrollLeftChanged: boolean;\n\tpublic readonly scrollHeightChanged: boolean;\n\tpublic readonly scrollTopChanged: boolean;\n\n\tconstructor(\n\t\toldScrollWidth: number, oldScrollLeft: number, oldScrollHeight: number, oldScrollTop: number,\n\t\tscrollWidth: number, scrollLeft: number, scrollHeight: number, scrollTop: number,\n\t) {\n\t\tthis._oldScrollWidth = oldScrollWidth;\n\t\tthis._oldScrollLeft = oldScrollLeft;\n\t\tthis._oldScrollHeight = oldScrollHeight;\n\t\tthis._oldScrollTop = oldScrollTop;\n\n\t\tthis.scrollWidth = scrollWidth;\n\t\tthis.scrollLeft = scrollLeft;\n\t\tthis.scrollHeight = scrollHeight;\n\t\tthis.scrollTop = scrollTop;\n\n\t\tthis.scrollWidthChanged = (this._oldScrollWidth !== this.scrollWidth);\n\t\tthis.scrollLeftChanged = (this._oldScrollLeft !== this.scrollLeft);\n\t\tthis.scrollHeightChanged = (this._oldScrollHeight !== this.scrollHeight);\n\t\tthis.scrollTopChanged = (this._oldScrollTop !== this.scrollTop);\n\t}\n\n\tpublic isNoOp(): boolean {\n\t\treturn (!this.scrollWidthChanged && !this.scrollLeftChanged && !this.scrollHeightChanged && !this.scrollTopChanged);\n\t}\n\n\tpublic merge(other: OutgoingViewModelEvent): ScrollChangedEvent {\n\t\tif (other.kind !== OutgoingViewModelEventKind.ScrollChanged) {\n\t\t\treturn this;\n\t\t}\n\t\treturn new ScrollChangedEvent(\n\t\t\tthis._oldScrollWidth, this._oldScrollLeft, this._oldScrollHeight, this._oldScrollTop,\n\t\t\tother.scrollWidth, other.scrollLeft, other.scrollHeight, other.scrollTop\n\t\t);\n\t}\n}\n\nexport class ViewZonesChangedEvent {\n\n\tpublic readonly kind = OutgoingViewModelEventKind.ViewZonesChanged;\n\n\tconstructor() {\n\t}\n\n\tpublic isNoOp(): boolean {\n\t\treturn false;\n\t}\n\n\tpublic merge(other: OutgoingViewModelEvent): ViewZonesChangedEvent {\n\t\treturn this;\n\t}\n}\n\nexport class HiddenAreasChangedEvent {\n\n\tpublic readonly kind = OutgoingViewModelEventKind.HiddenAreasChanged;\n\n\tconstructor() {\n\t}\n\n\tpublic isNoOp(): boolean {\n\t\treturn false;\n\t}\n\n\tpublic merge(other: OutgoingViewModelEvent): HiddenAreasChangedEvent {\n\t\treturn this;\n\t}\n}\n\nexport class CursorStateChangedEvent {\n\n\tpublic readonly kind = OutgoingViewModelEventKind.CursorStateChanged;\n\n\tpublic readonly oldSelections: Selection[] | null;\n\tpublic readonly selections: Selection[];\n\tpublic readonly oldModelVersionId: number;\n\tpublic readonly modelVersionId: number;\n\tpublic readonly source: string;\n\tpublic readonly reason: CursorChangeReason;\n\tpublic readonly reachedMaxCursorCount: boolean;\n\n\tconstructor(oldSelections: Selection[] | null, selections: Selection[], oldModelVersionId: number, modelVersionId: number, source: string, reason: CursorChangeReason, reachedMaxCursorCount: boolean) {\n\t\tthis.oldSelections = oldSelections;\n\t\tthis.selections = selections;\n\t\tthis.oldModelVersionId = oldModelVersionId;\n\t\tthis.modelVersionId = modelVersionId;\n\t\tthis.source = source;\n\t\tthis.reason = reason;\n\t\tthis.reachedMaxCursorCount = reachedMaxCursorCount;\n\t}\n\n\tprivate static _selectionsAreEqual(a: Selection[] | null, b: Selection[] | null): boolean {\n\t\tif (!a && !b) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!a || !b) {\n\t\t\treturn false;\n\t\t}\n\t\tconst aLen = a.length;\n\t\tconst bLen = b.length;\n\t\tif (aLen !== bLen) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let i = 0; i < aLen; i++) {\n\t\t\tif (!a[i].equalsSelection(b[i])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic isNoOp(): boolean {\n\t\treturn (\n\t\t\tCursorStateChangedEvent._selectionsAreEqual(this.oldSelections, this.selections)\n\t\t\t&& this.oldModelVersionId === this.modelVersionId\n\t\t);\n\t}\n\n\tpublic merge(other: OutgoingViewModelEvent): CursorStateChangedEvent {\n\t\tif (other.kind !== OutgoingViewModelEventKind.CursorStateChanged) {\n\t\t\treturn this;\n\t\t}\n\t\treturn new CursorStateChangedEvent(\n\t\t\tthis.oldSelections, other.selections, this.oldModelVersionId, other.modelVersionId, other.source, other.reason, this.reachedMaxCursorCount || other.reachedMaxCursorCount\n\t\t);\n\t}\n}\n\nexport class ReadOnlyEditAttemptEvent {\n\n\tpublic readonly kind = OutgoingViewModelEventKind.ReadOnlyEditAttempt;\n\n\tconstructor() {\n\t}\n\n\tpublic isNoOp(): boolean {\n\t\treturn false;\n\t}\n\n\tpublic merge(other: OutgoingViewModelEvent): ReadOnlyEditAttemptEvent {\n\t\treturn this;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event, Emitter } from 'vs/base/common/event';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport { IScrollPosition, ScrollEvent, Scrollable, ScrollbarVisibility, INewScrollPosition } from 'vs/base/common/scrollable';\nimport { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { ScrollType } from 'vs/editor/common/editorCommon';\nimport { IEditorConfiguration } from 'vs/editor/common/config/editorConfiguration';\nimport { LinesLayout, IEditorWhitespace, IWhitespaceChangeAccessor } from 'vs/editor/common/viewLayout/linesLayout';\nimport { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';\nimport { IViewLayout, IViewWhitespaceViewportData, Viewport } from 'vs/editor/common/viewModel/viewModel';\nimport { ContentSizeChangedEvent } from 'vs/editor/common/viewModel/viewModelEventDispatcher';\n\nconst SMOOTH_SCROLLING_TIME = 125;\n\nclass EditorScrollDimensions {\n\n\tpublic readonly width: number;\n\tpublic readonly contentWidth: number;\n\tpublic readonly scrollWidth: number;\n\n\tpublic readonly height: number;\n\tpublic readonly contentHeight: number;\n\tpublic readonly scrollHeight: number;\n\n\tconstructor(\n\t\twidth: number,\n\t\tcontentWidth: number,\n\t\theight: number,\n\t\tcontentHeight: number,\n\t) {\n\t\twidth = width | 0;\n\t\tcontentWidth = contentWidth | 0;\n\t\theight = height | 0;\n\t\tcontentHeight = contentHeight | 0;\n\n\t\tif (width < 0) {\n\t\t\twidth = 0;\n\t\t}\n\t\tif (contentWidth < 0) {\n\t\t\tcontentWidth = 0;\n\t\t}\n\n\t\tif (height < 0) {\n\t\t\theight = 0;\n\t\t}\n\t\tif (contentHeight < 0) {\n\t\t\tcontentHeight = 0;\n\t\t}\n\n\t\tthis.width = width;\n\t\tthis.contentWidth = contentWidth;\n\t\tthis.scrollWidth = Math.max(width, contentWidth);\n\n\t\tthis.height = height;\n\t\tthis.contentHeight = contentHeight;\n\t\tthis.scrollHeight = Math.max(height, contentHeight);\n\t}\n\n\tpublic equals(other: EditorScrollDimensions): boolean {\n\t\treturn (\n\t\t\tthis.width === other.width\n\t\t\t&& this.contentWidth === other.contentWidth\n\t\t\t&& this.height === other.height\n\t\t\t&& this.contentHeight === other.contentHeight\n\t\t);\n\t}\n}\n\nclass EditorScrollable extends Disposable {\n\n\tprivate readonly _scrollable: Scrollable;\n\tprivate _dimensions: EditorScrollDimensions;\n\n\tpublic readonly onDidScroll: Event;\n\n\tprivate readonly _onDidContentSizeChange = this._register(new Emitter());\n\tpublic readonly onDidContentSizeChange: Event = this._onDidContentSizeChange.event;\n\n\tconstructor(smoothScrollDuration: number, scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable) {\n\t\tsuper();\n\t\tthis._dimensions = new EditorScrollDimensions(0, 0, 0, 0);\n\t\tthis._scrollable = this._register(new Scrollable({\n\t\t\tforceIntegerValues: true,\n\t\t\tsmoothScrollDuration,\n\t\t\tscheduleAtNextAnimationFrame\n\t\t}));\n\t\tthis.onDidScroll = this._scrollable.onScroll;\n\t}\n\n\tpublic getScrollable(): Scrollable {\n\t\treturn this._scrollable;\n\t}\n\n\tpublic setSmoothScrollDuration(smoothScrollDuration: number): void {\n\t\tthis._scrollable.setSmoothScrollDuration(smoothScrollDuration);\n\t}\n\n\tpublic validateScrollPosition(scrollPosition: INewScrollPosition): IScrollPosition {\n\t\treturn this._scrollable.validateScrollPosition(scrollPosition);\n\t}\n\n\tpublic getScrollDimensions(): EditorScrollDimensions {\n\t\treturn this._dimensions;\n\t}\n\n\tpublic setScrollDimensions(dimensions: EditorScrollDimensions): void {\n\t\tif (this._dimensions.equals(dimensions)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst oldDimensions = this._dimensions;\n\t\tthis._dimensions = dimensions;\n\n\t\tthis._scrollable.setScrollDimensions({\n\t\t\twidth: dimensions.width,\n\t\t\tscrollWidth: dimensions.scrollWidth,\n\t\t\theight: dimensions.height,\n\t\t\tscrollHeight: dimensions.scrollHeight\n\t\t}, true);\n\n\t\tconst contentWidthChanged = (oldDimensions.contentWidth !== dimensions.contentWidth);\n\t\tconst contentHeightChanged = (oldDimensions.contentHeight !== dimensions.contentHeight);\n\t\tif (contentWidthChanged || contentHeightChanged) {\n\t\t\tthis._onDidContentSizeChange.fire(new ContentSizeChangedEvent(\n\t\t\t\toldDimensions.contentWidth, oldDimensions.contentHeight,\n\t\t\t\tdimensions.contentWidth, dimensions.contentHeight\n\t\t\t));\n\t\t}\n\t}\n\n\tpublic getFutureScrollPosition(): IScrollPosition {\n\t\treturn this._scrollable.getFutureScrollPosition();\n\t}\n\n\tpublic getCurrentScrollPosition(): IScrollPosition {\n\t\treturn this._scrollable.getCurrentScrollPosition();\n\t}\n\n\tpublic setScrollPositionNow(update: INewScrollPosition): void {\n\t\tthis._scrollable.setScrollPositionNow(update);\n\t}\n\n\tpublic setScrollPositionSmooth(update: INewScrollPosition): void {\n\t\tthis._scrollable.setScrollPositionSmooth(update);\n\t}\n}\n\nexport class ViewLayout extends Disposable implements IViewLayout {\n\n\tprivate readonly _configuration: IEditorConfiguration;\n\tprivate readonly _linesLayout: LinesLayout;\n\n\tprivate readonly _scrollable: EditorScrollable;\n\tpublic readonly onDidScroll: Event;\n\tpublic readonly onDidContentSizeChange: Event;\n\n\tconstructor(configuration: IEditorConfiguration, lineCount: number, scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable) {\n\t\tsuper();\n\n\t\tthis._configuration = configuration;\n\t\tconst options = this._configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\t\tconst padding = options.get(EditorOption.padding);\n\n\t\tthis._linesLayout = new LinesLayout(lineCount, options.get(EditorOption.lineHeight), padding.top, padding.bottom);\n\n\t\tthis._scrollable = this._register(new EditorScrollable(0, scheduleAtNextAnimationFrame));\n\t\tthis._configureSmoothScrollDuration();\n\n\t\tthis._scrollable.setScrollDimensions(new EditorScrollDimensions(\n\t\t\tlayoutInfo.contentWidth,\n\t\t\t0,\n\t\t\tlayoutInfo.height,\n\t\t\t0\n\t\t));\n\t\tthis.onDidScroll = this._scrollable.onDidScroll;\n\t\tthis.onDidContentSizeChange = this._scrollable.onDidContentSizeChange;\n\n\t\tthis._updateHeight();\n\t}\n\n\tpublic override dispose(): void {\n\t\tsuper.dispose();\n\t}\n\n\tpublic getScrollable(): Scrollable {\n\t\treturn this._scrollable.getScrollable();\n\t}\n\n\tpublic onHeightMaybeChanged(): void {\n\t\tthis._updateHeight();\n\t}\n\n\tprivate _configureSmoothScrollDuration(): void {\n\t\tthis._scrollable.setSmoothScrollDuration(this._configuration.options.get(EditorOption.smoothScrolling) ? SMOOTH_SCROLLING_TIME : 0);\n\t}\n\n\t// ---- begin view event handlers\n\n\tpublic onConfigurationChanged(e: ConfigurationChangedEvent): void {\n\t\tconst options = this._configuration.options;\n\t\tif (e.hasChanged(EditorOption.lineHeight)) {\n\t\t\tthis._linesLayout.setLineHeight(options.get(EditorOption.lineHeight));\n\t\t}\n\t\tif (e.hasChanged(EditorOption.padding)) {\n\t\t\tconst padding = options.get(EditorOption.padding);\n\t\t\tthis._linesLayout.setPadding(padding.top, padding.bottom);\n\t\t}\n\t\tif (e.hasChanged(EditorOption.layoutInfo)) {\n\t\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\t\t\tconst width = layoutInfo.contentWidth;\n\t\t\tconst height = layoutInfo.height;\n\t\t\tconst scrollDimensions = this._scrollable.getScrollDimensions();\n\t\t\tconst contentWidth = scrollDimensions.contentWidth;\n\t\t\tthis._scrollable.setScrollDimensions(new EditorScrollDimensions(\n\t\t\t\twidth,\n\t\t\t\tscrollDimensions.contentWidth,\n\t\t\t\theight,\n\t\t\t\tthis._getContentHeight(width, height, contentWidth)\n\t\t\t));\n\t\t} else {\n\t\t\tthis._updateHeight();\n\t\t}\n\t\tif (e.hasChanged(EditorOption.smoothScrolling)) {\n\t\t\tthis._configureSmoothScrollDuration();\n\t\t}\n\t}\n\tpublic onFlushed(lineCount: number): void {\n\t\tthis._linesLayout.onFlushed(lineCount);\n\t}\n\tpublic onLinesDeleted(fromLineNumber: number, toLineNumber: number): void {\n\t\tthis._linesLayout.onLinesDeleted(fromLineNumber, toLineNumber);\n\t}\n\tpublic onLinesInserted(fromLineNumber: number, toLineNumber: number): void {\n\t\tthis._linesLayout.onLinesInserted(fromLineNumber, toLineNumber);\n\t}\n\n\t// ---- end view event handlers\n\n\tprivate _getHorizontalScrollbarHeight(width: number, scrollWidth: number): number {\n\t\tconst options = this._configuration.options;\n\t\tconst scrollbar = options.get(EditorOption.scrollbar);\n\t\tif (scrollbar.horizontal === ScrollbarVisibility.Hidden) {\n\t\t\t// horizontal scrollbar not visible\n\t\t\treturn 0;\n\t\t}\n\t\tif (width >= scrollWidth) {\n\t\t\t// horizontal scrollbar not visible\n\t\t\treturn 0;\n\t\t}\n\t\treturn scrollbar.horizontalScrollbarSize;\n\t}\n\n\tprivate _getContentHeight(width: number, height: number, contentWidth: number): number {\n\t\tconst options = this._configuration.options;\n\n\t\tlet result = this._linesLayout.getLinesTotalHeight();\n\t\tif (options.get(EditorOption.scrollBeyondLastLine)) {\n\t\t\tresult += Math.max(0, height - options.get(EditorOption.lineHeight) - options.get(EditorOption.padding).bottom);\n\t\t} else {\n\t\t\tresult += this._getHorizontalScrollbarHeight(width, contentWidth);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate _updateHeight(): void {\n\t\tconst scrollDimensions = this._scrollable.getScrollDimensions();\n\t\tconst width = scrollDimensions.width;\n\t\tconst height = scrollDimensions.height;\n\t\tconst contentWidth = scrollDimensions.contentWidth;\n\t\tthis._scrollable.setScrollDimensions(new EditorScrollDimensions(\n\t\t\twidth,\n\t\t\tscrollDimensions.contentWidth,\n\t\t\theight,\n\t\t\tthis._getContentHeight(width, height, contentWidth)\n\t\t));\n\t}\n\n\t// ---- Layouting logic\n\n\tpublic getCurrentViewport(): Viewport {\n\t\tconst scrollDimensions = this._scrollable.getScrollDimensions();\n\t\tconst currentScrollPosition = this._scrollable.getCurrentScrollPosition();\n\t\treturn new Viewport(\n\t\t\tcurrentScrollPosition.scrollTop,\n\t\t\tcurrentScrollPosition.scrollLeft,\n\t\t\tscrollDimensions.width,\n\t\t\tscrollDimensions.height\n\t\t);\n\t}\n\n\tpublic getFutureViewport(): Viewport {\n\t\tconst scrollDimensions = this._scrollable.getScrollDimensions();\n\t\tconst currentScrollPosition = this._scrollable.getFutureScrollPosition();\n\t\treturn new Viewport(\n\t\t\tcurrentScrollPosition.scrollTop,\n\t\t\tcurrentScrollPosition.scrollLeft,\n\t\t\tscrollDimensions.width,\n\t\t\tscrollDimensions.height\n\t\t);\n\t}\n\n\tprivate _computeContentWidth(maxLineWidth: number): number {\n\t\tconst options = this._configuration.options;\n\t\tconst wrappingInfo = options.get(EditorOption.wrappingInfo);\n\t\tconst fontInfo = options.get(EditorOption.fontInfo);\n\t\tif (wrappingInfo.isViewportWrapping) {\n\t\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\t\t\tconst minimap = options.get(EditorOption.minimap);\n\t\t\tif (maxLineWidth > layoutInfo.contentWidth + fontInfo.typicalHalfwidthCharacterWidth) {\n\t\t\t\t// This is a case where viewport wrapping is on, but the line extends above the viewport\n\t\t\t\tif (minimap.enabled && minimap.side === 'right') {\n\t\t\t\t\t// We need to accomodate the scrollbar width\n\t\t\t\t\treturn maxLineWidth + layoutInfo.verticalScrollbarWidth;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn maxLineWidth;\n\t\t} else {\n\t\t\tconst extraHorizontalSpace = options.get(EditorOption.scrollBeyondLastColumn) * fontInfo.typicalHalfwidthCharacterWidth;\n\t\t\tconst whitespaceMinWidth = this._linesLayout.getWhitespaceMinWidth();\n\t\t\treturn Math.max(maxLineWidth + extraHorizontalSpace, whitespaceMinWidth);\n\t\t}\n\t}\n\n\tpublic setMaxLineWidth(maxLineWidth: number): void {\n\t\tconst scrollDimensions = this._scrollable.getScrollDimensions();\n\t\t// const newScrollWidth = ;\n\t\tthis._scrollable.setScrollDimensions(new EditorScrollDimensions(\n\t\t\tscrollDimensions.width,\n\t\t\tthis._computeContentWidth(maxLineWidth),\n\t\t\tscrollDimensions.height,\n\t\t\tscrollDimensions.contentHeight\n\t\t));\n\n\t\t// The height might depend on the fact that there is a horizontal scrollbar or not\n\t\tthis._updateHeight();\n\t}\n\n\t// ---- view state\n\n\tpublic saveState(): { scrollTop: number; scrollTopWithoutViewZones: number; scrollLeft: number; } {\n\t\tconst currentScrollPosition = this._scrollable.getFutureScrollPosition();\n\t\tconst scrollTop = currentScrollPosition.scrollTop;\n\t\tconst firstLineNumberInViewport = this._linesLayout.getLineNumberAtOrAfterVerticalOffset(scrollTop);\n\t\tconst whitespaceAboveFirstLine = this._linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(firstLineNumberInViewport);\n\t\treturn {\n\t\t\tscrollTop: scrollTop,\n\t\t\tscrollTopWithoutViewZones: scrollTop - whitespaceAboveFirstLine,\n\t\t\tscrollLeft: currentScrollPosition.scrollLeft\n\t\t};\n\t}\n\n\t// ---- IVerticalLayoutProvider\n\tpublic changeWhitespace(callback: (accessor: IWhitespaceChangeAccessor) => void): boolean {\n\t\tconst hadAChange = this._linesLayout.changeWhitespace(callback);\n\t\tif (hadAChange) {\n\t\t\tthis.onHeightMaybeChanged();\n\t\t}\n\t\treturn hadAChange;\n\t}\n\tpublic getVerticalOffsetForLineNumber(lineNumber: number): number {\n\t\treturn this._linesLayout.getVerticalOffsetForLineNumber(lineNumber);\n\t}\n\tpublic isAfterLines(verticalOffset: number): boolean {\n\t\treturn this._linesLayout.isAfterLines(verticalOffset);\n\t}\n\tpublic isInTopPadding(verticalOffset: number): boolean {\n\t\treturn this._linesLayout.isInTopPadding(verticalOffset);\n\t}\n\tisInBottomPadding(verticalOffset: number): boolean {\n\t\treturn this._linesLayout.isInBottomPadding(verticalOffset);\n\t}\n\n\tpublic getLineNumberAtVerticalOffset(verticalOffset: number): number {\n\t\treturn this._linesLayout.getLineNumberAtOrAfterVerticalOffset(verticalOffset);\n\t}\n\n\tpublic getWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData | null {\n\t\treturn this._linesLayout.getWhitespaceAtVerticalOffset(verticalOffset);\n\t}\n\tpublic getLinesViewportData(): IPartialViewLinesViewportData {\n\t\tconst visibleBox = this.getCurrentViewport();\n\t\treturn this._linesLayout.getLinesViewportData(visibleBox.top, visibleBox.top + visibleBox.height);\n\t}\n\tpublic getLinesViewportDataAtScrollTop(scrollTop: number): IPartialViewLinesViewportData {\n\t\t// do some minimal validations on scrollTop\n\t\tconst scrollDimensions = this._scrollable.getScrollDimensions();\n\t\tif (scrollTop + scrollDimensions.height > scrollDimensions.scrollHeight) {\n\t\t\tscrollTop = scrollDimensions.scrollHeight - scrollDimensions.height;\n\t\t}\n\t\tif (scrollTop < 0) {\n\t\t\tscrollTop = 0;\n\t\t}\n\t\treturn this._linesLayout.getLinesViewportData(scrollTop, scrollTop + scrollDimensions.height);\n\t}\n\tpublic getWhitespaceViewportData(): IViewWhitespaceViewportData[] {\n\t\tconst visibleBox = this.getCurrentViewport();\n\t\treturn this._linesLayout.getWhitespaceViewportData(visibleBox.top, visibleBox.top + visibleBox.height);\n\t}\n\tpublic getWhitespaces(): IEditorWhitespace[] {\n\t\treturn this._linesLayout.getWhitespaces();\n\t}\n\n\t// ---- IScrollingProvider\n\n\tpublic getContentWidth(): number {\n\t\tconst scrollDimensions = this._scrollable.getScrollDimensions();\n\t\treturn scrollDimensions.contentWidth;\n\t}\n\tpublic getScrollWidth(): number {\n\t\tconst scrollDimensions = this._scrollable.getScrollDimensions();\n\t\treturn scrollDimensions.scrollWidth;\n\t}\n\tpublic getContentHeight(): number {\n\t\tconst scrollDimensions = this._scrollable.getScrollDimensions();\n\t\treturn scrollDimensions.contentHeight;\n\t}\n\tpublic getScrollHeight(): number {\n\t\tconst scrollDimensions = this._scrollable.getScrollDimensions();\n\t\treturn scrollDimensions.scrollHeight;\n\t}\n\n\tpublic getCurrentScrollLeft(): number {\n\t\tconst currentScrollPosition = this._scrollable.getCurrentScrollPosition();\n\t\treturn currentScrollPosition.scrollLeft;\n\t}\n\tpublic getCurrentScrollTop(): number {\n\t\tconst currentScrollPosition = this._scrollable.getCurrentScrollPosition();\n\t\treturn currentScrollPosition.scrollTop;\n\t}\n\n\tpublic validateScrollPosition(scrollPosition: INewScrollPosition): IScrollPosition {\n\t\treturn this._scrollable.validateScrollPosition(scrollPosition);\n\t}\n\n\tpublic setScrollPosition(position: INewScrollPosition, type: ScrollType): void {\n\t\tif (type === ScrollType.Immediate) {\n\t\t\tthis._scrollable.setScrollPositionNow(position);\n\t\t} else {\n\t\t\tthis._scrollable.setScrollPositionSmooth(position);\n\t\t}\n\t}\n\n\tpublic deltaScrollNow(deltaScrollLeft: number, deltaScrollTop: number): void {\n\t\tconst currentScrollPosition = this._scrollable.getCurrentScrollPosition();\n\t\tthis._scrollable.setScrollPositionNow({\n\t\t\tscrollLeft: currentScrollPosition.scrollLeft + deltaScrollLeft,\n\t\t\tscrollTop: currentScrollPosition.scrollTop + deltaScrollTop\n\t\t});\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { ITextModel } from 'vs/editor/common/model';\n\nexport class MoveCaretCommand implements ICommand {\n\n\tprivate readonly _selection: Selection;\n\tprivate readonly _isMovingLeft: boolean;\n\n\tconstructor(selection: Selection, isMovingLeft: boolean) {\n\t\tthis._selection = selection;\n\t\tthis._isMovingLeft = isMovingLeft;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tif (this._selection.startLineNumber !== this._selection.endLineNumber || this._selection.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tconst lineNumber = this._selection.startLineNumber;\n\t\tconst startColumn = this._selection.startColumn;\n\t\tconst endColumn = this._selection.endColumn;\n\t\tif (this._isMovingLeft && startColumn === 1) {\n\t\t\treturn;\n\t\t}\n\t\tif (!this._isMovingLeft && endColumn === model.getLineMaxColumn(lineNumber)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this._isMovingLeft) {\n\t\t\tconst rangeBefore = new Range(lineNumber, startColumn - 1, lineNumber, startColumn);\n\t\t\tconst charBefore = model.getValueInRange(rangeBefore);\n\t\t\tbuilder.addEditOperation(rangeBefore, null);\n\t\t\tbuilder.addEditOperation(new Range(lineNumber, endColumn, lineNumber, endColumn), charBefore);\n\t\t} else {\n\t\t\tconst rangeAfter = new Range(lineNumber, endColumn, lineNumber, endColumn + 1);\n\t\t\tconst charAfter = model.getValueInRange(rangeAfter);\n\t\t\tbuilder.addEditOperation(rangeAfter, null);\n\t\t\tbuilder.addEditOperation(new Range(lineNumber, startColumn, lineNumber, startColumn), charAfter);\n\t\t}\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tif (this._isMovingLeft) {\n\t\t\treturn new Selection(this._selection.startLineNumber, this._selection.startColumn - 1, this._selection.endLineNumber, this._selection.endColumn - 1);\n\t\t} else {\n\t\t\treturn new Selection(this._selection.startLineNumber, this._selection.startColumn + 1, this._selection.endLineNumber, this._selection.endColumn + 1);\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Position } from 'vs/editor/common/core/position';\nimport { CodeAction, CodeActionTriggerType } from 'vs/editor/common/languages';\n\nexport class CodeActionKind {\n\tprivate static readonly sep = '.';\n\n\tpublic static readonly None = new CodeActionKind('@@none@@'); // Special code action that contains nothing\n\tpublic static readonly Empty = new CodeActionKind('');\n\tpublic static readonly QuickFix = new CodeActionKind('quickfix');\n\tpublic static readonly Refactor = new CodeActionKind('refactor');\n\tpublic static readonly Source = new CodeActionKind('source');\n\tpublic static readonly SourceOrganizeImports = CodeActionKind.Source.append('organizeImports');\n\tpublic static readonly SourceFixAll = CodeActionKind.Source.append('fixAll');\n\n\tconstructor(\n\t\tpublic readonly value: string\n\t) { }\n\n\tpublic equals(other: CodeActionKind): boolean {\n\t\treturn this.value === other.value;\n\t}\n\n\tpublic contains(other: CodeActionKind): boolean {\n\t\treturn this.equals(other) || this.value === '' || other.value.startsWith(this.value + CodeActionKind.sep);\n\t}\n\n\tpublic intersects(other: CodeActionKind): boolean {\n\t\treturn this.contains(other) || other.contains(this);\n\t}\n\n\tpublic append(part: string): CodeActionKind {\n\t\treturn new CodeActionKind(this.value + CodeActionKind.sep + part);\n\t}\n}\n\nexport const enum CodeActionAutoApply {\n\tIfSingle = 'ifSingle',\n\tFirst = 'first',\n\tNever = 'never',\n}\n\nexport interface CodeActionFilter {\n\treadonly include?: CodeActionKind;\n\treadonly excludes?: readonly CodeActionKind[];\n\treadonly includeSourceActions?: boolean;\n\treadonly onlyIncludePreferredActions?: boolean;\n}\n\nexport function mayIncludeActionsOfKind(filter: CodeActionFilter, providedKind: CodeActionKind): boolean {\n\t// A provided kind may be a subset or superset of our filtered kind.\n\tif (filter.include && !filter.include.intersects(providedKind)) {\n\t\treturn false;\n\t}\n\n\tif (filter.excludes) {\n\t\tif (filter.excludes.some(exclude => excludesAction(providedKind, exclude, filter.include))) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Don't return source actions unless they are explicitly requested\n\tif (!filter.includeSourceActions && CodeActionKind.Source.contains(providedKind)) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nexport function filtersAction(filter: CodeActionFilter, action: CodeAction): boolean {\n\tconst actionKind = action.kind ? new CodeActionKind(action.kind) : undefined;\n\n\t// Filter out actions by kind\n\tif (filter.include) {\n\t\tif (!actionKind || !filter.include.contains(actionKind)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tif (filter.excludes) {\n\t\tif (actionKind && filter.excludes.some(exclude => excludesAction(actionKind, exclude, filter.include))) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Don't return source actions unless they are explicitly requested\n\tif (!filter.includeSourceActions) {\n\t\tif (actionKind && CodeActionKind.Source.contains(actionKind)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tif (filter.onlyIncludePreferredActions) {\n\t\tif (!action.isPreferred) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nfunction excludesAction(providedKind: CodeActionKind, exclude: CodeActionKind, include: CodeActionKind | undefined): boolean {\n\tif (!exclude.contains(providedKind)) {\n\t\treturn false;\n\t}\n\tif (include && exclude.contains(include)) {\n\t\t// The include is more specific, don't filter out\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport interface CodeActionTrigger {\n\treadonly type: CodeActionTriggerType;\n\treadonly filter?: CodeActionFilter;\n\treadonly autoApply?: CodeActionAutoApply;\n\treadonly context?: {\n\t\treadonly notAvailableMessage: string;\n\t\treadonly position: Position;\n\t};\n}\n\nexport class CodeActionCommandArgs {\n\tpublic static fromUser(arg: any, defaults: { kind: CodeActionKind, apply: CodeActionAutoApply }): CodeActionCommandArgs {\n\t\tif (!arg || typeof arg !== 'object') {\n\t\t\treturn new CodeActionCommandArgs(defaults.kind, defaults.apply, false);\n\t\t}\n\t\treturn new CodeActionCommandArgs(\n\t\t\tCodeActionCommandArgs.getKindFromUser(arg, defaults.kind),\n\t\t\tCodeActionCommandArgs.getApplyFromUser(arg, defaults.apply),\n\t\t\tCodeActionCommandArgs.getPreferredUser(arg));\n\t}\n\n\tprivate static getApplyFromUser(arg: any, defaultAutoApply: CodeActionAutoApply) {\n\t\tswitch (typeof arg.apply === 'string' ? arg.apply.toLowerCase() : '') {\n\t\t\tcase 'first': return CodeActionAutoApply.First;\n\t\t\tcase 'never': return CodeActionAutoApply.Never;\n\t\t\tcase 'ifsingle': return CodeActionAutoApply.IfSingle;\n\t\t\tdefault: return defaultAutoApply;\n\t\t}\n\t}\n\n\tprivate static getKindFromUser(arg: any, defaultKind: CodeActionKind) {\n\t\treturn typeof arg.kind === 'string'\n\t\t\t? new CodeActionKind(arg.kind)\n\t\t\t: defaultKind;\n\t}\n\n\tprivate static getPreferredUser(arg: any): boolean {\n\t\treturn typeof arg.preferred === 'boolean'\n\t\t\t? arg.preferred\n\t\t\t: false;\n\t}\n\n\tprivate constructor(\n\t\tpublic readonly kind: CodeActionKind,\n\t\tpublic readonly apply: CodeActionAutoApply,\n\t\tpublic readonly preferred: boolean,\n\t) { }\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Color } from 'vs/base/common/color';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { IColorPresentation } from 'vs/editor/common/languages';\n\nexport class ColorPickerModel {\n\n\treadonly originalColor: Color;\n\tprivate _color: Color;\n\n\tget color(): Color {\n\t\treturn this._color;\n\t}\n\n\tset color(color: Color) {\n\t\tif (this._color.equals(color)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._color = color;\n\t\tthis._onDidChangeColor.fire(color);\n\t}\n\n\tget presentation(): IColorPresentation { return this.colorPresentations[this.presentationIndex]; }\n\n\tprivate _colorPresentations: IColorPresentation[];\n\n\tget colorPresentations(): IColorPresentation[] {\n\t\treturn this._colorPresentations;\n\t}\n\n\tset colorPresentations(colorPresentations: IColorPresentation[]) {\n\t\tthis._colorPresentations = colorPresentations;\n\t\tif (this.presentationIndex > colorPresentations.length - 1) {\n\t\t\tthis.presentationIndex = 0;\n\t\t}\n\t\tthis._onDidChangePresentation.fire(this.presentation);\n\t}\n\n\tprivate readonly _onColorFlushed = new Emitter();\n\treadonly onColorFlushed: Event = this._onColorFlushed.event;\n\n\tprivate readonly _onDidChangeColor = new Emitter();\n\treadonly onDidChangeColor: Event = this._onDidChangeColor.event;\n\n\tprivate readonly _onDidChangePresentation = new Emitter();\n\treadonly onDidChangePresentation: Event = this._onDidChangePresentation.event;\n\n\tconstructor(color: Color, availableColorPresentations: IColorPresentation[], private presentationIndex: number) {\n\t\tthis.originalColor = color;\n\t\tthis._color = color;\n\t\tthis._colorPresentations = availableColorPresentations;\n\t}\n\n\tselectNextColorPresentation(): void {\n\t\tthis.presentationIndex = (this.presentationIndex + 1) % this.colorPresentations.length;\n\t\tthis.flushColor();\n\t\tthis._onDidChangePresentation.fire(this.presentation);\n\t}\n\n\tguessColorPresentation(color: Color, originalText: string): void {\n\t\tfor (let i = 0; i < this.colorPresentations.length; i++) {\n\t\t\tif (originalText.toLowerCase() === this.colorPresentations[i].label) {\n\t\t\t\tthis.presentationIndex = i;\n\t\t\t\tthis._onDidChangePresentation.fire(this.presentation);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tflushColor(): void {\n\t\tthis._onColorFlushed.fire(this._color);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { EditOperation } from 'vs/editor/common/core/editOperation';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model';\nimport { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';\n\nexport class BlockCommentCommand implements ICommand {\n\n\tprivate readonly _selection: Selection;\n\tprivate readonly _insertSpace: boolean;\n\tprivate _usedEndToken: string | null;\n\n\tconstructor(\n\t\tselection: Selection,\n\t\tinsertSpace: boolean,\n\t\tprivate readonly languageConfigurationService: ILanguageConfigurationService\n\t) {\n\t\tthis._selection = selection;\n\t\tthis._insertSpace = insertSpace;\n\t\tthis._usedEndToken = null;\n\t}\n\n\tpublic static _haystackHasNeedleAtOffset(haystack: string, needle: string, offset: number): boolean {\n\t\tif (offset < 0) {\n\t\t\treturn false;\n\t\t}\n\t\tconst needleLength = needle.length;\n\t\tconst haystackLength = haystack.length;\n\t\tif (offset + needleLength > haystackLength) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = 0; i < needleLength; i++) {\n\t\t\tconst codeA = haystack.charCodeAt(offset + i);\n\t\t\tconst codeB = needle.charCodeAt(i);\n\n\t\t\tif (codeA === codeB) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (codeA >= CharCode.A && codeA <= CharCode.Z && codeA + 32 === codeB) {\n\t\t\t\t// codeA is upper-case variant of codeB\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (codeB >= CharCode.A && codeB <= CharCode.Z && codeB + 32 === codeA) {\n\t\t\t\t// codeB is upper-case variant of codeA\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tprivate _createOperationsForBlockComment(selection: Range, startToken: string, endToken: string, insertSpace: boolean, model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tconst startLineNumber = selection.startLineNumber;\n\t\tconst startColumn = selection.startColumn;\n\t\tconst endLineNumber = selection.endLineNumber;\n\t\tconst endColumn = selection.endColumn;\n\n\t\tconst startLineText = model.getLineContent(startLineNumber);\n\t\tconst endLineText = model.getLineContent(endLineNumber);\n\n\t\tlet startTokenIndex = startLineText.lastIndexOf(startToken, startColumn - 1 + startToken.length);\n\t\tlet endTokenIndex = endLineText.indexOf(endToken, endColumn - 1 - endToken.length);\n\n\t\tif (startTokenIndex !== -1 && endTokenIndex !== -1) {\n\n\t\t\tif (startLineNumber === endLineNumber) {\n\t\t\t\tconst lineBetweenTokens = startLineText.substring(startTokenIndex + startToken.length, endTokenIndex);\n\n\t\t\t\tif (lineBetweenTokens.indexOf(endToken) >= 0) {\n\t\t\t\t\t// force to add a block comment\n\t\t\t\t\tstartTokenIndex = -1;\n\t\t\t\t\tendTokenIndex = -1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst startLineAfterStartToken = startLineText.substring(startTokenIndex + startToken.length);\n\t\t\t\tconst endLineBeforeEndToken = endLineText.substring(0, endTokenIndex);\n\n\t\t\t\tif (startLineAfterStartToken.indexOf(endToken) >= 0 || endLineBeforeEndToken.indexOf(endToken) >= 0) {\n\t\t\t\t\t// force to add a block comment\n\t\t\t\t\tstartTokenIndex = -1;\n\t\t\t\t\tendTokenIndex = -1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet ops: IIdentifiedSingleEditOperation[];\n\n\t\tif (startTokenIndex !== -1 && endTokenIndex !== -1) {\n\t\t\t// Consider spaces as part of the comment tokens\n\t\t\tif (insertSpace && startTokenIndex + startToken.length < startLineText.length && startLineText.charCodeAt(startTokenIndex + startToken.length) === CharCode.Space) {\n\t\t\t\t// Pretend the start token contains a trailing space\n\t\t\t\tstartToken = startToken + ' ';\n\t\t\t}\n\n\t\t\tif (insertSpace && endTokenIndex > 0 && endLineText.charCodeAt(endTokenIndex - 1) === CharCode.Space) {\n\t\t\t\t// Pretend the end token contains a leading space\n\t\t\t\tendToken = ' ' + endToken;\n\t\t\t\tendTokenIndex -= 1;\n\t\t\t}\n\t\t\tops = BlockCommentCommand._createRemoveBlockCommentOperations(\n\t\t\t\tnew Range(startLineNumber, startTokenIndex + startToken.length + 1, endLineNumber, endTokenIndex + 1), startToken, endToken\n\t\t\t);\n\t\t} else {\n\t\t\tops = BlockCommentCommand._createAddBlockCommentOperations(selection, startToken, endToken, this._insertSpace);\n\t\t\tthis._usedEndToken = ops.length === 1 ? endToken : null;\n\t\t}\n\n\t\tfor (const op of ops) {\n\t\t\tbuilder.addTrackedEditOperation(op.range, op.text);\n\t\t}\n\t}\n\n\tpublic static _createRemoveBlockCommentOperations(r: Range, startToken: string, endToken: string): IIdentifiedSingleEditOperation[] {\n\t\tlet res: IIdentifiedSingleEditOperation[] = [];\n\n\t\tif (!Range.isEmpty(r)) {\n\t\t\t// Remove block comment start\n\t\t\tres.push(EditOperation.delete(new Range(\n\t\t\t\tr.startLineNumber, r.startColumn - startToken.length,\n\t\t\t\tr.startLineNumber, r.startColumn\n\t\t\t)));\n\n\t\t\t// Remove block comment end\n\t\t\tres.push(EditOperation.delete(new Range(\n\t\t\t\tr.endLineNumber, r.endColumn,\n\t\t\t\tr.endLineNumber, r.endColumn + endToken.length\n\t\t\t)));\n\t\t} else {\n\t\t\t// Remove both continuously\n\t\t\tres.push(EditOperation.delete(new Range(\n\t\t\t\tr.startLineNumber, r.startColumn - startToken.length,\n\t\t\t\tr.endLineNumber, r.endColumn + endToken.length\n\t\t\t)));\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tpublic static _createAddBlockCommentOperations(r: Range, startToken: string, endToken: string, insertSpace: boolean): IIdentifiedSingleEditOperation[] {\n\t\tlet res: IIdentifiedSingleEditOperation[] = [];\n\n\t\tif (!Range.isEmpty(r)) {\n\t\t\t// Insert block comment start\n\t\t\tres.push(EditOperation.insert(new Position(r.startLineNumber, r.startColumn), startToken + (insertSpace ? ' ' : '')));\n\n\t\t\t// Insert block comment end\n\t\t\tres.push(EditOperation.insert(new Position(r.endLineNumber, r.endColumn), (insertSpace ? ' ' : '') + endToken));\n\t\t} else {\n\t\t\t// Insert both continuously\n\t\t\tres.push(EditOperation.replace(new Range(\n\t\t\t\tr.startLineNumber, r.startColumn,\n\t\t\t\tr.endLineNumber, r.endColumn\n\t\t\t), startToken + ' ' + endToken));\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tconst startLineNumber = this._selection.startLineNumber;\n\t\tconst startColumn = this._selection.startColumn;\n\n\t\tmodel.tokenizeIfCheap(startLineNumber);\n\t\tconst languageId = model.getLanguageIdAtPosition(startLineNumber, startColumn);\n\t\tconst config = this.languageConfigurationService.getLanguageConfiguration(languageId).comments;\n\t\tif (!config || !config.blockCommentStartToken || !config.blockCommentEndToken) {\n\t\t\t// Mode does not support block comments\n\t\t\treturn;\n\t\t}\n\n\t\tthis._createOperationsForBlockComment(this._selection, config.blockCommentStartToken, config.blockCommentEndToken, this._insertSpace, model, builder);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tconst inverseEditOperations = helper.getInverseEditOperations();\n\t\tif (inverseEditOperations.length === 2) {\n\t\t\tconst startTokenEditOperation = inverseEditOperations[0];\n\t\t\tconst endTokenEditOperation = inverseEditOperations[1];\n\n\t\t\treturn new Selection(\n\t\t\t\tstartTokenEditOperation.range.endLineNumber,\n\t\t\t\tstartTokenEditOperation.range.endColumn,\n\t\t\t\tendTokenEditOperation.range.startLineNumber,\n\t\t\t\tendTokenEditOperation.range.startColumn\n\t\t\t);\n\t\t} else {\n\t\t\tconst srcRange = inverseEditOperations[0].range;\n\t\t\tconst deltaColumn = this._usedEndToken ? -this._usedEndToken.length - 1 : 0; // minus 1 space before endToken\n\t\t\treturn new Selection(\n\t\t\t\tsrcRange.endLineNumber,\n\t\t\t\tsrcRange.endColumn + deltaColumn,\n\t\t\t\tsrcRange.endLineNumber,\n\t\t\t\tsrcRange.endColumn + deltaColumn\n\t\t\t);\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { ITextModel } from 'vs/editor/common/model';\n\n\nexport class DragAndDropCommand implements ICommand {\n\n\tprivate readonly selection: Selection;\n\tprivate readonly targetPosition: Position;\n\tprivate targetSelection: Selection | null;\n\tprivate readonly copy: boolean;\n\n\tconstructor(selection: Selection, targetPosition: Position, copy: boolean) {\n\t\tthis.selection = selection;\n\t\tthis.targetPosition = targetPosition;\n\t\tthis.copy = copy;\n\t\tthis.targetSelection = null;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tlet text = model.getValueInRange(this.selection);\n\t\tif (!this.copy) {\n\t\t\tbuilder.addEditOperation(this.selection, null);\n\t\t}\n\t\tbuilder.addEditOperation(new Range(this.targetPosition.lineNumber, this.targetPosition.column, this.targetPosition.lineNumber, this.targetPosition.column), text);\n\n\t\tif (this.selection.containsPosition(this.targetPosition) && !(\n\t\t\tthis.copy && (\n\t\t\t\tthis.selection.getEndPosition().equals(this.targetPosition) || this.selection.getStartPosition().equals(this.targetPosition)\n\t\t\t) // we allow users to paste content beside the selection\n\t\t)) {\n\t\t\tthis.targetSelection = this.selection;\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.copy) {\n\t\t\tthis.targetSelection = new Selection(\n\t\t\t\tthis.targetPosition.lineNumber,\n\t\t\t\tthis.targetPosition.column,\n\t\t\t\tthis.selection.endLineNumber - this.selection.startLineNumber + this.targetPosition.lineNumber,\n\t\t\t\tthis.selection.startLineNumber === this.selection.endLineNumber ?\n\t\t\t\t\tthis.targetPosition.column + this.selection.endColumn - this.selection.startColumn :\n\t\t\t\t\tthis.selection.endColumn\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.targetPosition.lineNumber > this.selection.endLineNumber) {\n\t\t\t// Drag the selection downwards\n\t\t\tthis.targetSelection = new Selection(\n\t\t\t\tthis.targetPosition.lineNumber - this.selection.endLineNumber + this.selection.startLineNumber,\n\t\t\t\tthis.targetPosition.column,\n\t\t\t\tthis.targetPosition.lineNumber,\n\t\t\t\tthis.selection.startLineNumber === this.selection.endLineNumber ?\n\t\t\t\t\tthis.targetPosition.column + this.selection.endColumn - this.selection.startColumn :\n\t\t\t\t\tthis.selection.endColumn\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.targetPosition.lineNumber < this.selection.endLineNumber) {\n\t\t\t// Drag the selection upwards\n\t\t\tthis.targetSelection = new Selection(\n\t\t\t\tthis.targetPosition.lineNumber,\n\t\t\t\tthis.targetPosition.column,\n\t\t\t\tthis.targetPosition.lineNumber + this.selection.endLineNumber - this.selection.startLineNumber,\n\t\t\t\tthis.selection.startLineNumber === this.selection.endLineNumber ?\n\t\t\t\t\tthis.targetPosition.column + this.selection.endColumn - this.selection.startColumn :\n\t\t\t\t\tthis.selection.endColumn\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// The target position is at the same line as the selection's end position.\n\t\tif (this.selection.endColumn <= this.targetPosition.column) {\n\t\t\t// The target position is after the selection's end position\n\t\t\tthis.targetSelection = new Selection(\n\t\t\t\tthis.targetPosition.lineNumber - this.selection.endLineNumber + this.selection.startLineNumber,\n\t\t\t\tthis.selection.startLineNumber === this.selection.endLineNumber ?\n\t\t\t\t\tthis.targetPosition.column - this.selection.endColumn + this.selection.startColumn :\n\t\t\t\t\tthis.targetPosition.column - this.selection.endColumn + this.selection.startColumn,\n\t\t\t\tthis.targetPosition.lineNumber,\n\t\t\t\tthis.selection.startLineNumber === this.selection.endLineNumber ?\n\t\t\t\t\tthis.targetPosition.column :\n\t\t\t\t\tthis.selection.endColumn\n\t\t\t);\n\t\t} else {\n\t\t\t// The target position is before the selection's end position. Since the selection doesn't contain the target position, the selection is one-line and target position is before this selection.\n\t\t\tthis.targetSelection = new Selection(\n\t\t\t\tthis.targetPosition.lineNumber - this.selection.endLineNumber + this.selection.startLineNumber,\n\t\t\t\tthis.targetPosition.column,\n\t\t\t\tthis.targetPosition.lineNumber,\n\t\t\t\tthis.targetPosition.column + this.selection.endColumn - this.selection.startColumn\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\treturn this.targetSelection!;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { ITextModel } from 'vs/editor/common/model';\n\ninterface IEditOperation {\n\trange: Range;\n\ttext: string;\n}\n\nexport class ReplaceAllCommand implements ICommand {\n\n\tprivate readonly _editorSelection: Selection;\n\tprivate _trackedEditorSelectionId: string | null;\n\tprivate readonly _ranges: Range[];\n\tprivate readonly _replaceStrings: string[];\n\n\tconstructor(editorSelection: Selection, ranges: Range[], replaceStrings: string[]) {\n\t\tthis._editorSelection = editorSelection;\n\t\tthis._ranges = ranges;\n\t\tthis._replaceStrings = replaceStrings;\n\t\tthis._trackedEditorSelectionId = null;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tif (this._ranges.length > 0) {\n\t\t\t// Collect all edit operations\n\t\t\tlet ops: IEditOperation[] = [];\n\t\t\tfor (let i = 0; i < this._ranges.length; i++) {\n\t\t\t\tops.push({\n\t\t\t\t\trange: this._ranges[i],\n\t\t\t\t\ttext: this._replaceStrings[i]\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Sort them in ascending order by range starts\n\t\t\tops.sort((o1, o2) => {\n\t\t\t\treturn Range.compareRangesUsingStarts(o1.range, o2.range);\n\t\t\t});\n\n\t\t\t// Merge operations that touch each other\n\t\t\tlet resultOps: IEditOperation[] = [];\n\t\t\tlet previousOp = ops[0];\n\t\t\tfor (let i = 1; i < ops.length; i++) {\n\t\t\t\tif (previousOp.range.endLineNumber === ops[i].range.startLineNumber && previousOp.range.endColumn === ops[i].range.startColumn) {\n\t\t\t\t\t// These operations are one after another and can be merged\n\t\t\t\t\tpreviousOp.range = previousOp.range.plusRange(ops[i].range);\n\t\t\t\t\tpreviousOp.text = previousOp.text + ops[i].text;\n\t\t\t\t} else {\n\t\t\t\t\tresultOps.push(previousOp);\n\t\t\t\t\tpreviousOp = ops[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\tresultOps.push(previousOp);\n\n\t\t\tfor (const op of resultOps) {\n\t\t\t\tbuilder.addEditOperation(op.range, op.text);\n\t\t\t}\n\t\t}\n\n\t\tthis._trackedEditorSelectionId = builder.trackSelection(this._editorSelection);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\treturn helper.getTrackedSelection(this._trackedEditorSelectionId!);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { buildReplaceStringWithCasePreserved } from 'vs/base/common/search';\n\nconst enum ReplacePatternKind {\n\tStaticValue = 0,\n\tDynamicPieces = 1\n}\n\n/**\n * Assigned when the replace pattern is entirely static.\n */\nclass StaticValueReplacePattern {\n\tpublic readonly kind = ReplacePatternKind.StaticValue;\n\tconstructor(public readonly staticValue: string) { }\n}\n\n/**\n * Assigned when the replace pattern has replacement patterns.\n */\nclass DynamicPiecesReplacePattern {\n\tpublic readonly kind = ReplacePatternKind.DynamicPieces;\n\tconstructor(public readonly pieces: ReplacePiece[]) { }\n}\n\nexport class ReplacePattern {\n\n\tpublic static fromStaticValue(value: string): ReplacePattern {\n\t\treturn new ReplacePattern([ReplacePiece.staticValue(value)]);\n\t}\n\n\tprivate readonly _state: StaticValueReplacePattern | DynamicPiecesReplacePattern;\n\n\tpublic get hasReplacementPatterns(): boolean {\n\t\treturn (this._state.kind === ReplacePatternKind.DynamicPieces);\n\t}\n\n\tconstructor(pieces: ReplacePiece[] | null) {\n\t\tif (!pieces || pieces.length === 0) {\n\t\t\tthis._state = new StaticValueReplacePattern('');\n\t\t} else if (pieces.length === 1 && pieces[0].staticValue !== null) {\n\t\t\tthis._state = new StaticValueReplacePattern(pieces[0].staticValue);\n\t\t} else {\n\t\t\tthis._state = new DynamicPiecesReplacePattern(pieces);\n\t\t}\n\t}\n\n\tpublic buildReplaceString(matches: string[] | null, preserveCase?: boolean): string {\n\t\tif (this._state.kind === ReplacePatternKind.StaticValue) {\n\t\t\tif (preserveCase) {\n\t\t\t\treturn buildReplaceStringWithCasePreserved(matches, this._state.staticValue);\n\t\t\t} else {\n\t\t\t\treturn this._state.staticValue;\n\t\t\t}\n\t\t}\n\n\t\tlet result = '';\n\t\tfor (let i = 0, len = this._state.pieces.length; i < len; i++) {\n\t\t\tlet piece = this._state.pieces[i];\n\t\t\tif (piece.staticValue !== null) {\n\t\t\t\t// static value ReplacePiece\n\t\t\t\tresult += piece.staticValue;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// match index ReplacePiece\n\t\t\tlet match: string = ReplacePattern._substitute(piece.matchIndex, matches);\n\t\t\tif (piece.caseOps !== null && piece.caseOps.length > 0) {\n\t\t\t\tlet repl: string[] = [];\n\t\t\t\tlet lenOps: number = piece.caseOps.length;\n\t\t\t\tlet opIdx: number = 0;\n\t\t\t\tfor (let idx: number = 0, len: number = match.length; idx < len; idx++) {\n\t\t\t\t\tif (opIdx >= lenOps) {\n\t\t\t\t\t\trepl.push(match.slice(idx));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tswitch (piece.caseOps[opIdx]) {\n\t\t\t\t\t\tcase 'U':\n\t\t\t\t\t\t\trepl.push(match[idx].toUpperCase());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'u':\n\t\t\t\t\t\t\trepl.push(match[idx].toUpperCase());\n\t\t\t\t\t\t\topIdx++;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'L':\n\t\t\t\t\t\t\trepl.push(match[idx].toLowerCase());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'l':\n\t\t\t\t\t\t\trepl.push(match[idx].toLowerCase());\n\t\t\t\t\t\t\topIdx++;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\trepl.push(match[idx]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmatch = repl.join('');\n\t\t\t}\n\t\t\tresult += match;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate static _substitute(matchIndex: number, matches: string[] | null): string {\n\t\tif (matches === null) {\n\t\t\treturn '';\n\t\t}\n\t\tif (matchIndex === 0) {\n\t\t\treturn matches[0];\n\t\t}\n\n\t\tlet remainder = '';\n\t\twhile (matchIndex > 0) {\n\t\t\tif (matchIndex < matches.length) {\n\t\t\t\t// A match can be undefined\n\t\t\t\tlet match = (matches[matchIndex] || '');\n\t\t\t\treturn match + remainder;\n\t\t\t}\n\t\t\tremainder = String(matchIndex % 10) + remainder;\n\t\t\tmatchIndex = Math.floor(matchIndex / 10);\n\t\t}\n\t\treturn '$' + remainder;\n\t}\n}\n\n/**\n * A replace piece can either be a static string or an index to a specific match.\n */\nexport class ReplacePiece {\n\n\tpublic static staticValue(value: string): ReplacePiece {\n\t\treturn new ReplacePiece(value, -1, null);\n\t}\n\n\tpublic static caseOps(index: number, caseOps: string[]): ReplacePiece {\n\t\treturn new ReplacePiece(null, index, caseOps);\n\t}\n\n\tpublic readonly staticValue: string | null;\n\tpublic readonly matchIndex: number;\n\tpublic readonly caseOps: string[] | null;\n\n\tprivate constructor(staticValue: string | null, matchIndex: number, caseOps: string[] | null) {\n\t\tthis.staticValue = staticValue;\n\t\tthis.matchIndex = matchIndex;\n\t\tif (!caseOps || caseOps.length === 0) {\n\t\t\tthis.caseOps = null;\n\t\t} else {\n\t\t\tthis.caseOps = caseOps.slice(0);\n\t\t}\n\t}\n}\n\nclass ReplacePieceBuilder {\n\n\tprivate readonly _source: string;\n\tprivate _lastCharIndex: number;\n\tprivate readonly _result: ReplacePiece[];\n\tprivate _resultLen: number;\n\tprivate _currentStaticPiece: string;\n\n\tconstructor(source: string) {\n\t\tthis._source = source;\n\t\tthis._lastCharIndex = 0;\n\t\tthis._result = [];\n\t\tthis._resultLen = 0;\n\t\tthis._currentStaticPiece = '';\n\t}\n\n\tpublic emitUnchanged(toCharIndex: number): void {\n\t\tthis._emitStatic(this._source.substring(this._lastCharIndex, toCharIndex));\n\t\tthis._lastCharIndex = toCharIndex;\n\t}\n\n\tpublic emitStatic(value: string, toCharIndex: number): void {\n\t\tthis._emitStatic(value);\n\t\tthis._lastCharIndex = toCharIndex;\n\t}\n\n\tprivate _emitStatic(value: string): void {\n\t\tif (value.length === 0) {\n\t\t\treturn;\n\t\t}\n\t\tthis._currentStaticPiece += value;\n\t}\n\n\tpublic emitMatchIndex(index: number, toCharIndex: number, caseOps: string[]): void {\n\t\tif (this._currentStaticPiece.length !== 0) {\n\t\t\tthis._result[this._resultLen++] = ReplacePiece.staticValue(this._currentStaticPiece);\n\t\t\tthis._currentStaticPiece = '';\n\t\t}\n\t\tthis._result[this._resultLen++] = ReplacePiece.caseOps(index, caseOps);\n\t\tthis._lastCharIndex = toCharIndex;\n\t}\n\n\n\tpublic finalize(): ReplacePattern {\n\t\tthis.emitUnchanged(this._source.length);\n\t\tif (this._currentStaticPiece.length !== 0) {\n\t\t\tthis._result[this._resultLen++] = ReplacePiece.staticValue(this._currentStaticPiece);\n\t\t\tthis._currentStaticPiece = '';\n\t\t}\n\t\treturn new ReplacePattern(this._result);\n\t}\n}\n\n/**\n * \\n\t\t\t=> inserts a LF\n * \\t\t\t\t=> inserts a TAB\n * \\\\\t\t\t=> inserts a \"\\\".\n * \\u\t\t\t=> upper-cases one character in a match.\n * \\U\t\t\t=> upper-cases ALL remaining characters in a match.\n * \\l\t\t\t=> lower-cases one character in a match.\n * \\L\t\t\t=> lower-cases ALL remaining characters in a match.\n * $$\t\t\t=> inserts a \"$\".\n * $& and $0\t=> inserts the matched substring.\n * $n\t\t\t=> Where n is a non-negative integer lesser than 100, inserts the nth parenthesized submatch string\n * everything else stays untouched\n *\n * Also see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_string_as_a_parameter\n */\nexport function parseReplaceString(replaceString: string): ReplacePattern {\n\tif (!replaceString || replaceString.length === 0) {\n\t\treturn new ReplacePattern(null);\n\t}\n\n\tlet caseOps: string[] = [];\n\tlet result = new ReplacePieceBuilder(replaceString);\n\n\tfor (let i = 0, len = replaceString.length; i < len; i++) {\n\t\tlet chCode = replaceString.charCodeAt(i);\n\n\t\tif (chCode === CharCode.Backslash) {\n\n\t\t\t// move to next char\n\t\t\ti++;\n\n\t\t\tif (i >= len) {\n\t\t\t\t// string ends with a \\\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tlet nextChCode = replaceString.charCodeAt(i);\n\t\t\t// let replaceWithCharacter: string | null = null;\n\n\t\t\tswitch (nextChCode) {\n\t\t\t\tcase CharCode.Backslash:\n\t\t\t\t\t// \\\\ => inserts a \"\\\"\n\t\t\t\t\tresult.emitUnchanged(i - 1);\n\t\t\t\t\tresult.emitStatic('\\\\', i + 1);\n\t\t\t\t\tbreak;\n\t\t\t\tcase CharCode.n:\n\t\t\t\t\t// \\n => inserts a LF\n\t\t\t\t\tresult.emitUnchanged(i - 1);\n\t\t\t\t\tresult.emitStatic('\\n', i + 1);\n\t\t\t\t\tbreak;\n\t\t\t\tcase CharCode.t:\n\t\t\t\t\t// \\t => inserts a TAB\n\t\t\t\t\tresult.emitUnchanged(i - 1);\n\t\t\t\t\tresult.emitStatic('\\t', i + 1);\n\t\t\t\t\tbreak;\n\t\t\t\t// Case modification of string replacements, patterned after Boost, but only applied\n\t\t\t\t// to the replacement text, not subsequent content.\n\t\t\t\tcase CharCode.u:\n\t\t\t\t// \\u => upper-cases one character.\n\t\t\t\tcase CharCode.U:\n\t\t\t\t// \\U => upper-cases ALL following characters.\n\t\t\t\tcase CharCode.l:\n\t\t\t\t// \\l => lower-cases one character.\n\t\t\t\tcase CharCode.L:\n\t\t\t\t\t// \\L => lower-cases ALL following characters.\n\t\t\t\t\tresult.emitUnchanged(i - 1);\n\t\t\t\t\tresult.emitStatic('', i + 1);\n\t\t\t\t\tcaseOps.push(String.fromCharCode(nextChCode));\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (chCode === CharCode.DollarSign) {\n\n\t\t\t// move to next char\n\t\t\ti++;\n\n\t\t\tif (i >= len) {\n\t\t\t\t// string ends with a $\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tlet nextChCode = replaceString.charCodeAt(i);\n\n\t\t\tif (nextChCode === CharCode.DollarSign) {\n\t\t\t\t// $$ => inserts a \"$\"\n\t\t\t\tresult.emitUnchanged(i - 1);\n\t\t\t\tresult.emitStatic('$', i + 1);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (nextChCode === CharCode.Digit0 || nextChCode === CharCode.Ampersand) {\n\t\t\t\t// $& and $0 => inserts the matched substring.\n\t\t\t\tresult.emitUnchanged(i - 1);\n\t\t\t\tresult.emitMatchIndex(0, i + 1, caseOps);\n\t\t\t\tcaseOps.length = 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (CharCode.Digit1 <= nextChCode && nextChCode <= CharCode.Digit9) {\n\t\t\t\t// $n\n\n\t\t\t\tlet matchIndex = nextChCode - CharCode.Digit0;\n\n\t\t\t\t// peek next char to probe for $nn\n\t\t\t\tif (i + 1 < len) {\n\t\t\t\t\tlet nextNextChCode = replaceString.charCodeAt(i + 1);\n\t\t\t\t\tif (CharCode.Digit0 <= nextNextChCode && nextNextChCode <= CharCode.Digit9) {\n\t\t\t\t\t\t// $nn\n\n\t\t\t\t\t\t// move to next char\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tmatchIndex = matchIndex * 10 + (nextNextChCode - CharCode.Digit0);\n\n\t\t\t\t\t\tresult.emitUnchanged(i - 2);\n\t\t\t\t\t\tresult.emitMatchIndex(matchIndex, i + 1, caseOps);\n\t\t\t\t\t\tcaseOps.length = 0;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresult.emitUnchanged(i - 1);\n\t\t\t\tresult.emitMatchIndex(matchIndex, i + 1, caseOps);\n\t\t\t\tcaseOps.length = 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result.finalize();\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport interface ILineRange {\n\tstartLineNumber: number;\n\tendLineNumber: number;\n}\n\nexport const MAX_FOLDING_REGIONS = 0xFFFF;\nexport const MAX_LINE_NUMBER = 0xFFFFFF;\n\nconst MASK_INDENT = 0xFF000000;\n\nexport class FoldingRegions {\n\tprivate readonly _startIndexes: Uint32Array;\n\tprivate readonly _endIndexes: Uint32Array;\n\tprivate readonly _collapseStates: Uint32Array;\n\tprivate _parentsComputed: boolean;\n\tprivate readonly _types: Array | undefined;\n\n\tconstructor(startIndexes: Uint32Array, endIndexes: Uint32Array, types?: Array) {\n\t\tif (startIndexes.length !== endIndexes.length || startIndexes.length > MAX_FOLDING_REGIONS) {\n\t\t\tthrow new Error('invalid startIndexes or endIndexes size');\n\t\t}\n\t\tthis._startIndexes = startIndexes;\n\t\tthis._endIndexes = endIndexes;\n\t\tthis._collapseStates = new Uint32Array(Math.ceil(startIndexes.length / 32));\n\t\tthis._types = types;\n\t\tthis._parentsComputed = false;\n\t}\n\n\tprivate ensureParentIndices() {\n\t\tif (!this._parentsComputed) {\n\t\t\tthis._parentsComputed = true;\n\t\t\tlet parentIndexes: number[] = [];\n\t\t\tlet isInsideLast = (startLineNumber: number, endLineNumber: number) => {\n\t\t\t\tlet index = parentIndexes[parentIndexes.length - 1];\n\t\t\t\treturn this.getStartLineNumber(index) <= startLineNumber && this.getEndLineNumber(index) >= endLineNumber;\n\t\t\t};\n\t\t\tfor (let i = 0, len = this._startIndexes.length; i < len; i++) {\n\t\t\t\tlet startLineNumber = this._startIndexes[i];\n\t\t\t\tlet endLineNumber = this._endIndexes[i];\n\t\t\t\tif (startLineNumber > MAX_LINE_NUMBER || endLineNumber > MAX_LINE_NUMBER) {\n\t\t\t\t\tthrow new Error('startLineNumber or endLineNumber must not exceed ' + MAX_LINE_NUMBER);\n\t\t\t\t}\n\t\t\t\twhile (parentIndexes.length > 0 && !isInsideLast(startLineNumber, endLineNumber)) {\n\t\t\t\t\tparentIndexes.pop();\n\t\t\t\t}\n\t\t\t\tlet parentIndex = parentIndexes.length > 0 ? parentIndexes[parentIndexes.length - 1] : -1;\n\t\t\t\tparentIndexes.push(i);\n\t\t\t\tthis._startIndexes[i] = startLineNumber + ((parentIndex & 0xFF) << 24);\n\t\t\t\tthis._endIndexes[i] = endLineNumber + ((parentIndex & 0xFF00) << 16);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic get length(): number {\n\t\treturn this._startIndexes.length;\n\t}\n\n\tpublic getStartLineNumber(index: number): number {\n\t\treturn this._startIndexes[index] & MAX_LINE_NUMBER;\n\t}\n\n\tpublic getEndLineNumber(index: number): number {\n\t\treturn this._endIndexes[index] & MAX_LINE_NUMBER;\n\t}\n\n\tpublic getType(index: number): string | undefined {\n\t\treturn this._types ? this._types[index] : undefined;\n\t}\n\n\tpublic hasTypes() {\n\t\treturn !!this._types;\n\t}\n\n\tpublic isCollapsed(index: number): boolean {\n\t\tlet arrayIndex = (index / 32) | 0;\n\t\tlet bit = index % 32;\n\t\treturn (this._collapseStates[arrayIndex] & (1 << bit)) !== 0;\n\t}\n\n\tpublic setCollapsed(index: number, newState: boolean) {\n\t\tlet arrayIndex = (index / 32) | 0;\n\t\tlet bit = index % 32;\n\t\tlet value = this._collapseStates[arrayIndex];\n\t\tif (newState) {\n\t\t\tthis._collapseStates[arrayIndex] = value | (1 << bit);\n\t\t} else {\n\t\t\tthis._collapseStates[arrayIndex] = value & ~(1 << bit);\n\t\t}\n\t}\n\n\tpublic setCollapsedAllOfType(type: string, newState: boolean) {\n\t\tlet hasChanged = false;\n\t\tif (this._types) {\n\t\t\tfor (let i = 0; i < this._types.length; i++) {\n\t\t\t\tif (this._types[i] === type) {\n\t\t\t\t\tthis.setCollapsed(i, newState);\n\t\t\t\t\thasChanged = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn hasChanged;\n\t}\n\n\tpublic toRegion(index: number): FoldingRegion {\n\t\treturn new FoldingRegion(this, index);\n\t}\n\n\tpublic getParentIndex(index: number) {\n\t\tthis.ensureParentIndices();\n\t\tlet parent = ((this._startIndexes[index] & MASK_INDENT) >>> 24) + ((this._endIndexes[index] & MASK_INDENT) >>> 16);\n\t\tif (parent === MAX_FOLDING_REGIONS) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn parent;\n\t}\n\n\tpublic contains(index: number, line: number) {\n\t\treturn this.getStartLineNumber(index) <= line && this.getEndLineNumber(index) >= line;\n\t}\n\n\tprivate findIndex(line: number) {\n\t\tlet low = 0, high = this._startIndexes.length;\n\t\tif (high === 0) {\n\t\t\treturn -1; // no children\n\t\t}\n\t\twhile (low < high) {\n\t\t\tlet mid = Math.floor((low + high) / 2);\n\t\t\tif (line < this.getStartLineNumber(mid)) {\n\t\t\t\thigh = mid;\n\t\t\t} else {\n\t\t\t\tlow = mid + 1;\n\t\t\t}\n\t\t}\n\t\treturn low - 1;\n\t}\n\n\tpublic findRange(line: number): number {\n\t\tlet index = this.findIndex(line);\n\t\tif (index >= 0) {\n\t\t\tlet endLineNumber = this.getEndLineNumber(index);\n\t\t\tif (endLineNumber >= line) {\n\t\t\t\treturn index;\n\t\t\t}\n\t\t\tindex = this.getParentIndex(index);\n\t\t\twhile (index !== -1) {\n\t\t\t\tif (this.contains(index, line)) {\n\t\t\t\t\treturn index;\n\t\t\t\t}\n\t\t\t\tindex = this.getParentIndex(index);\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t}\n\n\tpublic toString() {\n\t\tlet res: string[] = [];\n\t\tfor (let i = 0; i < this.length; i++) {\n\t\t\tres[i] = `[${this.isCollapsed(i) ? '+' : '-'}] ${this.getStartLineNumber(i)}/${this.getEndLineNumber(i)}`;\n\t\t}\n\t\treturn res.join(', ');\n\t}\n}\n\nexport class FoldingRegion {\n\n\tconstructor(private readonly ranges: FoldingRegions, private index: number) {\n\t}\n\n\tpublic get startLineNumber() {\n\t\treturn this.ranges.getStartLineNumber(this.index);\n\t}\n\n\tpublic get endLineNumber() {\n\t\treturn this.ranges.getEndLineNumber(this.index);\n\t}\n\n\tpublic get regionIndex() {\n\t\treturn this.index;\n\t}\n\n\tpublic get parentIndex() {\n\t\treturn this.ranges.getParentIndex(this.index);\n\t}\n\n\tpublic get isCollapsed() {\n\t\treturn this.ranges.isCollapsed(this.index);\n\t}\n\n\tcontainedBy(range: ILineRange): boolean {\n\t\treturn range.startLineNumber <= this.startLineNumber && range.endLineNumber >= this.endLineNumber;\n\t}\n\tcontainsLine(lineNumber: number) {\n\t\treturn this.startLineNumber <= lineNumber && lineNumber <= this.endLineNumber;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { IModelDecorationOptions, IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';\nimport { FoldingRegion, FoldingRegions, ILineRange } from './foldingRanges';\n\nexport interface IDecorationProvider {\n\tgetDecorationOption(isCollapsed: boolean, isHidden: boolean): IModelDecorationOptions;\n\tdeltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[];\n\tchangeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): T | null;\n}\n\nexport interface FoldingModelChangeEvent {\n\tmodel: FoldingModel;\n\tcollapseStateChanged?: FoldingRegion[];\n}\n\nexport type CollapseMemento = ILineRange[];\n\nexport class FoldingModel {\n\tprivate readonly _textModel: ITextModel;\n\tprivate readonly _decorationProvider: IDecorationProvider;\n\n\tprivate _regions: FoldingRegions;\n\tprivate _editorDecorationIds: string[];\n\tprivate _isInitialized: boolean;\n\n\tprivate readonly _updateEventEmitter = new Emitter();\n\tpublic readonly onDidChange: Event = this._updateEventEmitter.event;\n\n\tpublic get regions(): FoldingRegions { return this._regions; }\n\tpublic get textModel() { return this._textModel; }\n\tpublic get isInitialized() { return this._isInitialized; }\n\n\tconstructor(textModel: ITextModel, decorationProvider: IDecorationProvider) {\n\t\tthis._textModel = textModel;\n\t\tthis._decorationProvider = decorationProvider;\n\t\tthis._regions = new FoldingRegions(new Uint32Array(0), new Uint32Array(0));\n\t\tthis._editorDecorationIds = [];\n\t\tthis._isInitialized = false;\n\t}\n\n\tpublic toggleCollapseState(toggledRegions: FoldingRegion[]) {\n\t\tif (!toggledRegions.length) {\n\t\t\treturn;\n\t\t}\n\t\ttoggledRegions = toggledRegions.sort((r1, r2) => r1.regionIndex - r2.regionIndex);\n\n\t\tconst processed: { [key: string]: boolean | undefined } = {};\n\t\tthis._decorationProvider.changeDecorations(accessor => {\n\t\t\tlet k = 0; // index from [0 ... this.regions.length]\n\t\t\tlet dirtyRegionEndLine = -1; // end of the range where decorations need to be updated\n\t\t\tlet lastHiddenLine = -1; // the end of the last hidden lines\n\t\t\tconst updateDecorationsUntil = (index: number) => {\n\t\t\t\twhile (k < index) {\n\t\t\t\t\tconst endLineNumber = this._regions.getEndLineNumber(k);\n\t\t\t\t\tconst isCollapsed = this._regions.isCollapsed(k);\n\t\t\t\t\tif (endLineNumber <= dirtyRegionEndLine) {\n\t\t\t\t\t\taccessor.changeDecorationOptions(this._editorDecorationIds[k], this._decorationProvider.getDecorationOption(isCollapsed, endLineNumber <= lastHiddenLine));\n\t\t\t\t\t}\n\t\t\t\t\tif (isCollapsed && endLineNumber > lastHiddenLine) {\n\t\t\t\t\t\tlastHiddenLine = endLineNumber;\n\t\t\t\t\t}\n\t\t\t\t\tk++;\n\t\t\t\t}\n\t\t\t};\n\t\t\tfor (let region of toggledRegions) {\n\t\t\t\tlet index = region.regionIndex;\n\t\t\t\tlet editorDecorationId = this._editorDecorationIds[index];\n\t\t\t\tif (editorDecorationId && !processed[editorDecorationId]) {\n\t\t\t\t\tprocessed[editorDecorationId] = true;\n\n\t\t\t\t\tupdateDecorationsUntil(index); // update all decorations up to current index using the old dirtyRegionEndLine\n\n\t\t\t\t\tlet newCollapseState = !this._regions.isCollapsed(index);\n\t\t\t\t\tthis._regions.setCollapsed(index, newCollapseState);\n\n\t\t\t\t\tdirtyRegionEndLine = Math.max(dirtyRegionEndLine, this._regions.getEndLineNumber(index));\n\t\t\t\t}\n\t\t\t}\n\t\t\tupdateDecorationsUntil(this._regions.length);\n\t\t});\n\t\tthis._updateEventEmitter.fire({ model: this, collapseStateChanged: toggledRegions });\n\t}\n\n\tpublic update(newRegions: FoldingRegions, blockedLineNumers: number[] = []): void {\n\t\tlet newEditorDecorations: IModelDeltaDecoration[] = [];\n\n\t\tlet isBlocked = (startLineNumber: number, endLineNumber: number) => {\n\t\t\tfor (let blockedLineNumber of blockedLineNumers) {\n\t\t\t\tif (startLineNumber < blockedLineNumber && blockedLineNumber <= endLineNumber) { // first line is visible\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t\tlet lastHiddenLine = -1;\n\n\t\tlet initRange = (index: number, isCollapsed: boolean) => {\n\t\t\tconst startLineNumber = newRegions.getStartLineNumber(index);\n\t\t\tconst endLineNumber = newRegions.getEndLineNumber(index);\n\t\t\tif (!isCollapsed) {\n\t\t\t\tisCollapsed = newRegions.isCollapsed(index);\n\t\t\t}\n\t\t\tif (isCollapsed && isBlocked(startLineNumber, endLineNumber)) {\n\t\t\t\tisCollapsed = false;\n\t\t\t}\n\t\t\tnewRegions.setCollapsed(index, isCollapsed);\n\n\t\t\tconst maxColumn = this._textModel.getLineMaxColumn(startLineNumber);\n\t\t\tconst decorationRange = {\n\t\t\t\tstartLineNumber: startLineNumber,\n\t\t\t\tstartColumn: Math.max(maxColumn - 1, 1), // make it length == 1 to detect deletions\n\t\t\t\tendLineNumber: startLineNumber,\n\t\t\t\tendColumn: maxColumn\n\t\t\t};\n\t\t\tnewEditorDecorations.push({ range: decorationRange, options: this._decorationProvider.getDecorationOption(isCollapsed, endLineNumber <= lastHiddenLine) });\n\t\t\tif (isCollapsed && endLineNumber > lastHiddenLine) {\n\t\t\t\tlastHiddenLine = endLineNumber;\n\t\t\t}\n\t\t};\n\t\tlet i = 0;\n\t\tlet nextCollapsed = () => {\n\t\t\twhile (i < this._regions.length) {\n\t\t\t\tlet isCollapsed = this._regions.isCollapsed(i);\n\t\t\t\ti++;\n\t\t\t\tif (isCollapsed) {\n\t\t\t\t\treturn i - 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn -1;\n\t\t};\n\n\t\tlet k = 0;\n\t\tlet collapsedIndex = nextCollapsed();\n\t\twhile (collapsedIndex !== -1 && k < newRegions.length) {\n\t\t\t// get the latest range\n\t\t\tlet decRange = this._textModel.getDecorationRange(this._editorDecorationIds[collapsedIndex]);\n\t\t\tif (decRange) {\n\t\t\t\tlet collapsedStartLineNumber = decRange.startLineNumber;\n\t\t\t\tif (decRange.startColumn === Math.max(decRange.endColumn - 1, 1) && this._textModel.getLineMaxColumn(collapsedStartLineNumber) === decRange.endColumn) { // test that the decoration is still covering the full line else it got deleted\n\t\t\t\t\twhile (k < newRegions.length) {\n\t\t\t\t\t\tlet startLineNumber = newRegions.getStartLineNumber(k);\n\t\t\t\t\t\tif (collapsedStartLineNumber >= startLineNumber) {\n\t\t\t\t\t\t\tinitRange(k, collapsedStartLineNumber === startLineNumber);\n\t\t\t\t\t\t\tk++;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcollapsedIndex = nextCollapsed();\n\t\t}\n\t\twhile (k < newRegions.length) {\n\t\t\tinitRange(k, false);\n\t\t\tk++;\n\t\t}\n\n\t\tthis._editorDecorationIds = this._decorationProvider.deltaDecorations(this._editorDecorationIds, newEditorDecorations);\n\t\tthis._regions = newRegions;\n\t\tthis._isInitialized = true;\n\t\tthis._updateEventEmitter.fire({ model: this });\n\t}\n\n\t/**\n\t * Collapse state memento, for persistence only\n\t */\n\tpublic getMemento(): CollapseMemento | undefined {\n\t\tlet collapsedRanges: ILineRange[] = [];\n\t\tfor (let i = 0; i < this._regions.length; i++) {\n\t\t\tif (this._regions.isCollapsed(i)) {\n\t\t\t\tlet range = this._textModel.getDecorationRange(this._editorDecorationIds[i]);\n\t\t\t\tif (range) {\n\t\t\t\t\tlet startLineNumber = range.startLineNumber;\n\t\t\t\t\tlet endLineNumber = range.endLineNumber + this._regions.getEndLineNumber(i) - this._regions.getStartLineNumber(i);\n\t\t\t\t\tcollapsedRanges.push({ startLineNumber, endLineNumber });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (collapsedRanges.length > 0) {\n\t\t\treturn collapsedRanges;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Apply persisted state, for persistence only\n\t */\n\tpublic applyMemento(state: CollapseMemento) {\n\t\tif (!Array.isArray(state)) {\n\t\t\treturn;\n\t\t}\n\t\tlet toToogle: FoldingRegion[] = [];\n\t\tfor (let range of state) {\n\t\t\tlet region = this.getRegionAtLine(range.startLineNumber);\n\t\t\tif (region && !region.isCollapsed) {\n\t\t\t\ttoToogle.push(region);\n\t\t\t}\n\t\t}\n\t\tthis.toggleCollapseState(toToogle);\n\t}\n\n\tpublic dispose() {\n\t\tthis._decorationProvider.deltaDecorations(this._editorDecorationIds, []);\n\t}\n\n\tgetAllRegionsAtLine(lineNumber: number, filter?: (r: FoldingRegion, level: number) => boolean): FoldingRegion[] {\n\t\tlet result: FoldingRegion[] = [];\n\t\tif (this._regions) {\n\t\t\tlet index = this._regions.findRange(lineNumber);\n\t\t\tlet level = 1;\n\t\t\twhile (index >= 0) {\n\t\t\t\tlet current = this._regions.toRegion(index);\n\t\t\t\tif (!filter || filter(current, level)) {\n\t\t\t\t\tresult.push(current);\n\t\t\t\t}\n\t\t\t\tlevel++;\n\t\t\t\tindex = current.parentIndex;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tgetRegionAtLine(lineNumber: number): FoldingRegion | null {\n\t\tif (this._regions) {\n\t\t\tlet index = this._regions.findRange(lineNumber);\n\t\t\tif (index >= 0) {\n\t\t\t\treturn this._regions.toRegion(index);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tgetRegionsInside(region: FoldingRegion | null, filter?: RegionFilter | RegionFilterWithLevel): FoldingRegion[] {\n\t\tlet result: FoldingRegion[] = [];\n\t\tlet index = region ? region.regionIndex + 1 : 0;\n\t\tlet endLineNumber = region ? region.endLineNumber : Number.MAX_VALUE;\n\n\t\tif (filter && filter.length === 2) {\n\t\t\tconst levelStack: FoldingRegion[] = [];\n\t\t\tfor (let i = index, len = this._regions.length; i < len; i++) {\n\t\t\t\tlet current = this._regions.toRegion(i);\n\t\t\t\tif (this._regions.getStartLineNumber(i) < endLineNumber) {\n\t\t\t\t\twhile (levelStack.length > 0 && !current.containedBy(levelStack[levelStack.length - 1])) {\n\t\t\t\t\t\tlevelStack.pop();\n\t\t\t\t\t}\n\t\t\t\t\tlevelStack.push(current);\n\t\t\t\t\tif (filter(current, levelStack.length)) {\n\t\t\t\t\t\tresult.push(current);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (let i = index, len = this._regions.length; i < len; i++) {\n\t\t\t\tlet current = this._regions.toRegion(i);\n\t\t\t\tif (this._regions.getStartLineNumber(i) < endLineNumber) {\n\t\t\t\t\tif (!filter || (filter as RegionFilter)(current)) {\n\t\t\t\t\t\tresult.push(current);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n}\n\ntype RegionFilter = (r: FoldingRegion) => boolean;\ntype RegionFilterWithLevel = (r: FoldingRegion, level: number) => boolean;\n\n\n/**\n * Collapse or expand the regions at the given locations\n * @param levels The number of levels. Use 1 to only impact the regions at the location, use Number.MAX_VALUE for all levels.\n * @param lineNumbers the location of the regions to collapse or expand, or if not set, all regions in the model.\n */\nexport function toggleCollapseState(foldingModel: FoldingModel, levels: number, lineNumbers: number[]) {\n\tlet toToggle: FoldingRegion[] = [];\n\tfor (let lineNumber of lineNumbers) {\n\t\tlet region = foldingModel.getRegionAtLine(lineNumber);\n\t\tif (region) {\n\t\t\tconst doCollapse = !region.isCollapsed;\n\t\t\ttoToggle.push(region);\n\t\t\tif (levels > 1) {\n\t\t\t\tlet regionsInside = foldingModel.getRegionsInside(region, (r, level: number) => r.isCollapsed !== doCollapse && level < levels);\n\t\t\t\ttoToggle.push(...regionsInside);\n\t\t\t}\n\t\t}\n\t}\n\tfoldingModel.toggleCollapseState(toToggle);\n}\n\n\n/**\n * Collapse or expand the regions at the given locations including all children.\n * @param doCollapse Whether to collapse or expand\n * @param levels The number of levels. Use 1 to only impact the regions at the location, use Number.MAX_VALUE for all levels.\n * @param lineNumbers the location of the regions to collapse or expand, or if not set, all regions in the model.\n */\nexport function setCollapseStateLevelsDown(foldingModel: FoldingModel, doCollapse: boolean, levels = Number.MAX_VALUE, lineNumbers?: number[]): void {\n\tlet toToggle: FoldingRegion[] = [];\n\tif (lineNumbers && lineNumbers.length > 0) {\n\t\tfor (let lineNumber of lineNumbers) {\n\t\t\tlet region = foldingModel.getRegionAtLine(lineNumber);\n\t\t\tif (region) {\n\t\t\t\tif (region.isCollapsed !== doCollapse) {\n\t\t\t\t\ttoToggle.push(region);\n\t\t\t\t}\n\t\t\t\tif (levels > 1) {\n\t\t\t\t\tlet regionsInside = foldingModel.getRegionsInside(region, (r, level: number) => r.isCollapsed !== doCollapse && level < levels);\n\t\t\t\t\ttoToggle.push(...regionsInside);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tlet regionsInside = foldingModel.getRegionsInside(null, (r, level: number) => r.isCollapsed !== doCollapse && level < levels);\n\t\ttoToggle.push(...regionsInside);\n\t}\n\tfoldingModel.toggleCollapseState(toToggle);\n}\n\n/**\n * Collapse or expand the regions at the given locations including all parents.\n * @param doCollapse Whether to collapse or expand\n * @param levels The number of levels. Use 1 to only impact the regions at the location, use Number.MAX_VALUE for all levels.\n * @param lineNumbers the location of the regions to collapse or expand.\n */\nexport function setCollapseStateLevelsUp(foldingModel: FoldingModel, doCollapse: boolean, levels: number, lineNumbers: number[]): void {\n\tlet toToggle: FoldingRegion[] = [];\n\tfor (let lineNumber of lineNumbers) {\n\t\tlet regions = foldingModel.getAllRegionsAtLine(lineNumber, (region, level) => region.isCollapsed !== doCollapse && level <= levels);\n\t\ttoToggle.push(...regions);\n\t}\n\tfoldingModel.toggleCollapseState(toToggle);\n}\n\n/**\n * Collapse or expand a region at the given locations. If the inner most region is already collapsed/expanded, uses the first parent instead.\n * @param doCollapse Whether to collapse or expand\n * @param lineNumbers the location of the regions to collapse or expand.\n */\nexport function setCollapseStateUp(foldingModel: FoldingModel, doCollapse: boolean, lineNumbers: number[]): void {\n\tlet toToggle: FoldingRegion[] = [];\n\tfor (let lineNumber of lineNumbers) {\n\t\tlet regions = foldingModel.getAllRegionsAtLine(lineNumber, (region,) => region.isCollapsed !== doCollapse);\n\t\tif (regions.length > 0) {\n\t\t\ttoToggle.push(regions[0]);\n\t\t}\n\t}\n\tfoldingModel.toggleCollapseState(toToggle);\n}\n\n/**\n * Folds or unfolds all regions that have a given level, except if they contain one of the blocked lines.\n * @param foldLevel level. Level == 1 is the top level\n * @param doCollapse Whether to collapse or expand\n*/\nexport function setCollapseStateAtLevel(foldingModel: FoldingModel, foldLevel: number, doCollapse: boolean, blockedLineNumbers: number[]): void {\n\tlet filter = (region: FoldingRegion, level: number) => level === foldLevel && region.isCollapsed !== doCollapse && !blockedLineNumbers.some(line => region.containsLine(line));\n\tlet toToggle = foldingModel.getRegionsInside(null, filter);\n\tfoldingModel.toggleCollapseState(toToggle);\n}\n\n/**\n * Folds or unfolds all regions, except if they contain or are contained by a region of one of the blocked lines.\n * @param doCollapse Whether to collapse or expand\n * @param blockedLineNumbers the location of regions to not collapse or expand\n */\nexport function setCollapseStateForRest(foldingModel: FoldingModel, doCollapse: boolean, blockedLineNumbers: number[]): void {\n\tlet filteredRegions: FoldingRegion[] = [];\n\tfor (let lineNumber of blockedLineNumbers) {\n\t\tconst regions = foldingModel.getAllRegionsAtLine(lineNumber, undefined);\n\t\tif (regions.length > 0) {\n\t\t\tfilteredRegions.push(regions[0]);\n\t\t}\n\t}\n\tlet filter = (region: FoldingRegion) => filteredRegions.every((filteredRegion) => !filteredRegion.containedBy(region) && !region.containedBy(filteredRegion)) && region.isCollapsed !== doCollapse;\n\tlet toToggle = foldingModel.getRegionsInside(null, filter);\n\tfoldingModel.toggleCollapseState(toToggle);\n}\n\n/**\n * Folds all regions for which the lines start with a given regex\n * @param foldingModel the folding model\n */\nexport function setCollapseStateForMatchingLines(foldingModel: FoldingModel, regExp: RegExp, doCollapse: boolean): void {\n\tlet editorModel = foldingModel.textModel;\n\tlet regions = foldingModel.regions;\n\tlet toToggle: FoldingRegion[] = [];\n\tfor (let i = regions.length - 1; i >= 0; i--) {\n\t\tif (doCollapse !== regions.isCollapsed(i)) {\n\t\t\tlet startLineNumber = regions.getStartLineNumber(i);\n\t\t\tif (regExp.test(editorModel.getLineContent(startLineNumber))) {\n\t\t\t\ttoToggle.push(regions.toRegion(i));\n\t\t\t}\n\t\t}\n\t}\n\tfoldingModel.toggleCollapseState(toToggle);\n}\n\n/**\n * Folds all regions of the given type\n * @param foldingModel the folding model\n */\nexport function setCollapseStateForType(foldingModel: FoldingModel, type: string, doCollapse: boolean): void {\n\tlet regions = foldingModel.regions;\n\tlet toToggle: FoldingRegion[] = [];\n\tfor (let i = regions.length - 1; i >= 0; i--) {\n\t\tif (doCollapse !== regions.isCollapsed(i) && type === regions.getType(i)) {\n\t\t\ttoToggle.push(regions.toRegion(i));\n\t\t}\n\t}\n\tfoldingModel.toggleCollapseState(toToggle);\n}\n\n/**\n * Get line to go to for parent fold of current line\n * @param lineNumber the current line number\n * @param foldingModel the folding model\n *\n * @return Parent fold start line\n */\nexport function getParentFoldLine(lineNumber: number, foldingModel: FoldingModel): number | null {\n\tlet startLineNumber: number | null = null;\n\tlet foldingRegion = foldingModel.getRegionAtLine(lineNumber);\n\tif (foldingRegion !== null) {\n\t\tstartLineNumber = foldingRegion.startLineNumber;\n\t\t// If current line is not the start of the current fold, go to top line of current fold. If not, go to parent fold\n\t\tif (lineNumber === startLineNumber) {\n\t\t\tlet parentFoldingIdx = foldingRegion.parentIndex;\n\t\t\tif (parentFoldingIdx !== -1) {\n\t\t\t\tstartLineNumber = foldingModel.regions.getStartLineNumber(parentFoldingIdx);\n\t\t\t} else {\n\t\t\t\tstartLineNumber = null;\n\t\t\t}\n\t\t}\n\t}\n\treturn startLineNumber;\n}\n\n/**\n * Get line to go to for previous fold at the same level of current line\n * @param lineNumber the current line number\n * @param foldingModel the folding model\n *\n * @return Previous fold start line\n */\nexport function getPreviousFoldLine(lineNumber: number, foldingModel: FoldingModel): number | null {\n\tlet foldingRegion = foldingModel.getRegionAtLine(lineNumber);\n\t// If on the folding range start line, go to previous sibling.\n\tif (foldingRegion !== null && foldingRegion.startLineNumber === lineNumber) {\n\t\t// If current line is not the start of the current fold, go to top line of current fold. If not, go to previous fold.\n\t\tif (lineNumber !== foldingRegion.startLineNumber) {\n\t\t\treturn foldingRegion.startLineNumber;\n\t\t} else {\n\t\t\t// Find min line number to stay within parent.\n\t\t\tlet expectedParentIndex = foldingRegion.parentIndex;\n\t\t\tlet minLineNumber = 0;\n\t\t\tif (expectedParentIndex !== -1) {\n\t\t\t\tminLineNumber = foldingModel.regions.getStartLineNumber(foldingRegion.parentIndex);\n\t\t\t}\n\n\t\t\t// Find fold at same level.\n\t\t\twhile (foldingRegion !== null) {\n\t\t\t\tif (foldingRegion.regionIndex > 0) {\n\t\t\t\t\tfoldingRegion = foldingModel.regions.toRegion(foldingRegion.regionIndex - 1);\n\n\t\t\t\t\t// Keep at same level.\n\t\t\t\t\tif (foldingRegion.startLineNumber <= minLineNumber) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t} else if (foldingRegion.parentIndex === expectedParentIndex) {\n\t\t\t\t\t\treturn foldingRegion.startLineNumber;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Go to last fold that's before the current line.\n\t\tif (foldingModel.regions.length > 0) {\n\t\t\tfoldingRegion = foldingModel.regions.toRegion(foldingModel.regions.length - 1);\n\t\t\twhile (foldingRegion !== null) {\n\t\t\t\t// Found fold before current line.\n\t\t\t\tif (foldingRegion.startLineNumber < lineNumber) {\n\t\t\t\t\treturn foldingRegion.startLineNumber;\n\t\t\t\t}\n\t\t\t\tif (foldingRegion.regionIndex > 0) {\n\t\t\t\t\tfoldingRegion = foldingModel.regions.toRegion(foldingRegion.regionIndex - 1);\n\t\t\t\t} else {\n\t\t\t\t\tfoldingRegion = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n}\n\n/**\n * Get line to go to next fold at the same level of current line\n * @param lineNumber the current line number\n * @param foldingModel the folding model\n *\n * @return Next fold start line\n */\nexport function getNextFoldLine(lineNumber: number, foldingModel: FoldingModel): number | null {\n\tlet foldingRegion = foldingModel.getRegionAtLine(lineNumber);\n\t// If on the folding range start line, go to next sibling.\n\tif (foldingRegion !== null && foldingRegion.startLineNumber === lineNumber) {\n\t\t// Find max line number to stay within parent.\n\t\tlet expectedParentIndex = foldingRegion.parentIndex;\n\t\tlet maxLineNumber = 0;\n\t\tif (expectedParentIndex !== -1) {\n\t\t\tmaxLineNumber = foldingModel.regions.getEndLineNumber(foldingRegion.parentIndex);\n\t\t} else if (foldingModel.regions.length === 0) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\tmaxLineNumber = foldingModel.regions.getEndLineNumber(foldingModel.regions.length - 1);\n\t\t}\n\n\t\t// Find fold at same level.\n\t\twhile (foldingRegion !== null) {\n\t\t\tif (foldingRegion.regionIndex < foldingModel.regions.length) {\n\t\t\t\tfoldingRegion = foldingModel.regions.toRegion(foldingRegion.regionIndex + 1);\n\n\t\t\t\t// Keep at same level.\n\t\t\t\tif (foldingRegion.startLineNumber >= maxLineNumber) {\n\t\t\t\t\treturn null;\n\t\t\t\t} else if (foldingRegion.parentIndex === expectedParentIndex) {\n\t\t\t\t\treturn foldingRegion.startLineNumber;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Go to first fold that's after the current line.\n\t\tif (foldingModel.regions.length > 0) {\n\t\t\tfoldingRegion = foldingModel.regions.toRegion(0);\n\t\t\twhile (foldingRegion !== null) {\n\t\t\t\t// Found fold after current line.\n\t\t\t\tif (foldingRegion.startLineNumber > lineNumber) {\n\t\t\t\t\treturn foldingRegion.startLineNumber;\n\t\t\t\t}\n\t\t\t\tif (foldingRegion.regionIndex < foldingModel.regions.length) {\n\t\t\t\t\tfoldingRegion = foldingModel.regions.toRegion(foldingRegion.regionIndex + 1);\n\t\t\t\t} else {\n\t\t\t\t\tfoldingRegion = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { findFirstInSorted } from 'vs/base/common/arrays';\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { IModelContentChangedEvent } from 'vs/editor/common/textModelEvents';\nimport { countEOL } from 'vs/editor/common/core/eolCounter';\nimport { CollapseMemento, FoldingModel } from 'vs/editor/contrib/folding/browser/foldingModel';\n\nexport class HiddenRangeModel {\n\n\tprivate readonly _foldingModel: FoldingModel;\n\tprivate _hiddenRanges: IRange[];\n\tprivate _foldingModelListener: IDisposable | null;\n\tprivate readonly _updateEventEmitter = new Emitter();\n\tprivate _hasLineChanges: boolean = false;\n\n\tpublic get onDidChange(): Event { return this._updateEventEmitter.event; }\n\tpublic get hiddenRanges() { return this._hiddenRanges; }\n\n\tpublic constructor(model: FoldingModel) {\n\t\tthis._foldingModel = model;\n\t\tthis._foldingModelListener = model.onDidChange(_ => this.updateHiddenRanges());\n\t\tthis._hiddenRanges = [];\n\t\tif (model.regions.length) {\n\t\t\tthis.updateHiddenRanges();\n\t\t}\n\t}\n\n\tpublic notifyChangeModelContent(e: IModelContentChangedEvent) {\n\t\tif (this._hiddenRanges.length && !this._hasLineChanges) {\n\t\t\tthis._hasLineChanges = e.changes.some(change => {\n\t\t\t\treturn change.range.endLineNumber !== change.range.startLineNumber || countEOL(change.text)[0] !== 0;\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate updateHiddenRanges(): void {\n\t\tlet updateHiddenAreas = false;\n\t\tlet newHiddenAreas: IRange[] = [];\n\t\tlet i = 0; // index into hidden\n\t\tlet k = 0;\n\n\t\tlet lastCollapsedStart = Number.MAX_VALUE;\n\t\tlet lastCollapsedEnd = -1;\n\n\t\tlet ranges = this._foldingModel.regions;\n\t\tfor (; i < ranges.length; i++) {\n\t\t\tif (!ranges.isCollapsed(i)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet startLineNumber = ranges.getStartLineNumber(i) + 1; // the first line is not hidden\n\t\t\tlet endLineNumber = ranges.getEndLineNumber(i);\n\t\t\tif (lastCollapsedStart <= startLineNumber && endLineNumber <= lastCollapsedEnd) {\n\t\t\t\t// ignore ranges contained in collapsed regions\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!updateHiddenAreas && k < this._hiddenRanges.length && this._hiddenRanges[k].startLineNumber === startLineNumber && this._hiddenRanges[k].endLineNumber === endLineNumber) {\n\t\t\t\t// reuse the old ranges\n\t\t\t\tnewHiddenAreas.push(this._hiddenRanges[k]);\n\t\t\t\tk++;\n\t\t\t} else {\n\t\t\t\tupdateHiddenAreas = true;\n\t\t\t\tnewHiddenAreas.push(new Range(startLineNumber, 1, endLineNumber, 1));\n\t\t\t}\n\t\t\tlastCollapsedStart = startLineNumber;\n\t\t\tlastCollapsedEnd = endLineNumber;\n\t\t}\n\t\tif (this._hasLineChanges || updateHiddenAreas || k < this._hiddenRanges.length) {\n\t\t\tthis.applyHiddenRanges(newHiddenAreas);\n\t\t}\n\t}\n\n\tpublic applyMemento(state: CollapseMemento): boolean {\n\t\tif (!Array.isArray(state) || state.length === 0) {\n\t\t\treturn false;\n\t\t}\n\t\tlet hiddenRanges: IRange[] = [];\n\t\tfor (let r of state) {\n\t\t\tif (!r.startLineNumber || !r.endLineNumber) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\thiddenRanges.push(new Range(r.startLineNumber + 1, 1, r.endLineNumber, 1));\n\t\t}\n\t\tthis.applyHiddenRanges(hiddenRanges);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Collapse state memento, for persistence only, only used if folding model is not yet initialized\n\t */\n\tpublic getMemento(): CollapseMemento {\n\t\treturn this._hiddenRanges.map(r => ({ startLineNumber: r.startLineNumber - 1, endLineNumber: r.endLineNumber }));\n\t}\n\n\tprivate applyHiddenRanges(newHiddenAreas: IRange[]) {\n\t\tthis._hiddenRanges = newHiddenAreas;\n\t\tthis._hasLineChanges = false;\n\t\tthis._updateEventEmitter.fire(newHiddenAreas);\n\t}\n\n\tpublic hasRanges() {\n\t\treturn this._hiddenRanges.length > 0;\n\t}\n\n\tpublic isHidden(line: number): boolean {\n\t\treturn findRange(this._hiddenRanges, line) !== null;\n\t}\n\n\tpublic adjustSelections(selections: Selection[]): boolean {\n\t\tlet hasChanges = false;\n\t\tlet editorModel = this._foldingModel.textModel;\n\t\tlet lastRange: IRange | null = null;\n\n\t\tlet adjustLine = (line: number) => {\n\t\t\tif (!lastRange || !isInside(line, lastRange)) {\n\t\t\t\tlastRange = findRange(this._hiddenRanges, line);\n\t\t\t}\n\t\t\tif (lastRange) {\n\t\t\t\treturn lastRange.startLineNumber - 1;\n\t\t\t}\n\t\t\treturn null;\n\t\t};\n\t\tfor (let i = 0, len = selections.length; i < len; i++) {\n\t\t\tlet selection = selections[i];\n\t\t\tlet adjustedStartLine = adjustLine(selection.startLineNumber);\n\t\t\tif (adjustedStartLine) {\n\t\t\t\tselection = selection.setStartPosition(adjustedStartLine, editorModel.getLineMaxColumn(adjustedStartLine));\n\t\t\t\thasChanges = true;\n\t\t\t}\n\t\t\tlet adjustedEndLine = adjustLine(selection.endLineNumber);\n\t\t\tif (adjustedEndLine) {\n\t\t\t\tselection = selection.setEndPosition(adjustedEndLine, editorModel.getLineMaxColumn(adjustedEndLine));\n\t\t\t\thasChanges = true;\n\t\t\t}\n\t\t\tselections[i] = selection;\n\t\t}\n\t\treturn hasChanges;\n\t}\n\n\n\tpublic dispose() {\n\t\tif (this.hiddenRanges.length > 0) {\n\t\t\tthis._hiddenRanges = [];\n\t\t\tthis._updateEventEmitter.fire(this._hiddenRanges);\n\t\t}\n\t\tif (this._foldingModelListener) {\n\t\t\tthis._foldingModelListener.dispose();\n\t\t\tthis._foldingModelListener = null;\n\t\t}\n\t}\n}\n\nfunction isInside(line: number, range: IRange) {\n\treturn line >= range.startLineNumber && line <= range.endLineNumber;\n}\nfunction findRange(ranges: IRange[], line: number): IRange | null {\n\tlet i = findFirstInSorted(ranges, r => line < r.startLineNumber) - 1;\n\tif (i >= 0 && ranges[i].endLineNumber >= line) {\n\t\treturn ranges[i];\n\t}\n\treturn null;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { computeIndentLevel } from 'vs/editor/common/model/utils';\nimport { FoldingMarkers } from 'vs/editor/common/languages/languageConfiguration';\nimport { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';\nimport { FoldingRegions, MAX_LINE_NUMBER } from 'vs/editor/contrib/folding/browser/foldingRanges';\nimport { RangeProvider } from './folding';\n\nconst MAX_FOLDING_REGIONS_FOR_INDENT_DEFAULT = 5000;\n\nexport const ID_INDENT_PROVIDER = 'indent';\n\nexport class IndentRangeProvider implements RangeProvider {\n\treadonly id = ID_INDENT_PROVIDER;\n\n\tconstructor(\n\t\tprivate readonly editorModel: ITextModel,\n\t\tprivate readonly languageConfigurationService: ILanguageConfigurationService,\n\t\tprivate readonly maxFoldingRegions: number\n\t) { }\n\n\tdispose() { }\n\n\tcompute(cancelationToken: CancellationToken, notifyTooManyRegions: (maxRegions: number) => void): Promise {\n\t\tlet foldingRules = this.languageConfigurationService.getLanguageConfiguration(this.editorModel.getLanguageId()).foldingRules;\n\t\tlet offSide = foldingRules && !!foldingRules.offSide;\n\t\tlet markers = foldingRules && foldingRules.markers;\n\t\treturn Promise.resolve(computeRanges(this.editorModel, offSide, markers, this.maxFoldingRegions, notifyTooManyRegions));\n\t}\n}\n\n// public only for testing\nexport class RangesCollector {\n\tprivate readonly _startIndexes: number[];\n\tprivate readonly _endIndexes: number[];\n\tprivate readonly _indentOccurrences: number[];\n\tprivate _length: number;\n\tprivate readonly _foldingRangesLimit: number;\n\n\tconstructor(foldingRangesLimit: number, private readonly _notifyTooManyRegions?: (maxRegions: number) => void) {\n\t\tthis._startIndexes = [];\n\t\tthis._endIndexes = [];\n\t\tthis._indentOccurrences = [];\n\t\tthis._length = 0;\n\t\tthis._foldingRangesLimit = foldingRangesLimit;\n\t}\n\n\tpublic insertFirst(startLineNumber: number, endLineNumber: number, indent: number) {\n\t\tif (startLineNumber > MAX_LINE_NUMBER || endLineNumber > MAX_LINE_NUMBER) {\n\t\t\treturn;\n\t\t}\n\t\tlet index = this._length;\n\t\tthis._startIndexes[index] = startLineNumber;\n\t\tthis._endIndexes[index] = endLineNumber;\n\t\tthis._length++;\n\t\tif (indent < 1000) {\n\t\t\tthis._indentOccurrences[indent] = (this._indentOccurrences[indent] || 0) + 1;\n\t\t}\n\t}\n\n\tpublic toIndentRanges(model: ITextModel) {\n\t\tif (this._length <= this._foldingRangesLimit) {\n\t\t\t// reverse and create arrays of the exact length\n\t\t\tlet startIndexes = new Uint32Array(this._length);\n\t\t\tlet endIndexes = new Uint32Array(this._length);\n\t\t\tfor (let i = this._length - 1, k = 0; i >= 0; i--, k++) {\n\t\t\t\tstartIndexes[k] = this._startIndexes[i];\n\t\t\t\tendIndexes[k] = this._endIndexes[i];\n\t\t\t}\n\t\t\treturn new FoldingRegions(startIndexes, endIndexes);\n\t\t} else {\n\t\t\tif (this._notifyTooManyRegions) {\n\t\t\t\tthis._notifyTooManyRegions(this._foldingRangesLimit);\n\t\t\t}\n\t\t\tlet entries = 0;\n\t\t\tlet maxIndent = this._indentOccurrences.length;\n\t\t\tfor (let i = 0; i < this._indentOccurrences.length; i++) {\n\t\t\t\tlet n = this._indentOccurrences[i];\n\t\t\t\tif (n) {\n\t\t\t\t\tif (n + entries > this._foldingRangesLimit) {\n\t\t\t\t\t\tmaxIndent = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tentries += n;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst tabSize = model.getOptions().tabSize;\n\t\t\t// reverse and create arrays of the exact length\n\t\t\tlet startIndexes = new Uint32Array(this._foldingRangesLimit);\n\t\t\tlet endIndexes = new Uint32Array(this._foldingRangesLimit);\n\t\t\tfor (let i = this._length - 1, k = 0; i >= 0; i--) {\n\t\t\t\tlet startIndex = this._startIndexes[i];\n\t\t\t\tlet lineContent = model.getLineContent(startIndex);\n\t\t\t\tlet indent = computeIndentLevel(lineContent, tabSize);\n\t\t\t\tif (indent < maxIndent || (indent === maxIndent && entries++ < this._foldingRangesLimit)) {\n\t\t\t\t\tstartIndexes[k] = startIndex;\n\t\t\t\t\tendIndexes[k] = this._endIndexes[i];\n\t\t\t\t\tk++;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn new FoldingRegions(startIndexes, endIndexes);\n\t\t}\n\n\t}\n}\n\n\ninterface PreviousRegion {\n\tindent: number; // indent or -2 if a marker\n\tendAbove: number; // end line number for the region above\n\tline: number; // start line of the region. Only used for marker regions.\n}\n\nexport function computeRanges(model: ITextModel, offSide: boolean, markers?: FoldingMarkers, foldingRangesLimit?: number, notifyTooManyRegions?: (maxRegions: number) => void): FoldingRegions {\n\tconst tabSize = model.getOptions().tabSize;\n\tfoldingRangesLimit = foldingRangesLimit ?? MAX_FOLDING_REGIONS_FOR_INDENT_DEFAULT;\n\tlet result = new RangesCollector(foldingRangesLimit, notifyTooManyRegions);\n\n\tlet pattern: RegExp | undefined = undefined;\n\tif (markers) {\n\t\tpattern = new RegExp(`(${markers.start.source})|(?:${markers.end.source})`);\n\t}\n\n\tlet previousRegions: PreviousRegion[] = [];\n\tlet line = model.getLineCount() + 1;\n\tpreviousRegions.push({ indent: -1, endAbove: line, line }); // sentinel, to make sure there's at least one entry\n\n\tfor (let line = model.getLineCount(); line > 0; line--) {\n\t\tlet lineContent = model.getLineContent(line);\n\t\tlet indent = computeIndentLevel(lineContent, tabSize);\n\t\tlet previous = previousRegions[previousRegions.length - 1];\n\t\tif (indent === -1) {\n\t\t\tif (offSide) {\n\t\t\t\t// for offSide languages, empty lines are associated to the previous block\n\t\t\t\t// note: the next block is already written to the results, so this only\n\t\t\t\t// impacts the end position of the block before\n\t\t\t\tprevious.endAbove = line;\n\t\t\t}\n\t\t\tcontinue; // only whitespace\n\t\t}\n\t\tlet m;\n\t\tif (pattern && (m = lineContent.match(pattern))) {\n\t\t\t// folding pattern match\n\t\t\tif (m[1]) { // start pattern match\n\t\t\t\t// discard all regions until the folding pattern\n\t\t\t\tlet i = previousRegions.length - 1;\n\t\t\t\twhile (i > 0 && previousRegions[i].indent !== -2) {\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t\tif (i > 0) {\n\t\t\t\t\tpreviousRegions.length = i + 1;\n\t\t\t\t\tprevious = previousRegions[i];\n\n\t\t\t\t\t// new folding range from pattern, includes the end line\n\t\t\t\t\tresult.insertFirst(line, previous.line, indent);\n\t\t\t\t\tprevious.line = line;\n\t\t\t\t\tprevious.indent = indent;\n\t\t\t\t\tprevious.endAbove = line;\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\t// no end marker found, treat line as a regular line\n\t\t\t\t}\n\t\t\t} else { // end pattern match\n\t\t\t\tpreviousRegions.push({ indent: -2, endAbove: line, line });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (previous.indent > indent) {\n\t\t\t// discard all regions with larger indent\n\t\t\tdo {\n\t\t\t\tpreviousRegions.pop();\n\t\t\t\tprevious = previousRegions[previousRegions.length - 1];\n\t\t\t} while (previous.indent > indent);\n\n\t\t\t// new folding range\n\t\t\tlet endLineNumber = previous.endAbove - 1;\n\t\t\tif (endLineNumber - line >= 1) { // needs at east size 1\n\t\t\t\tresult.insertFirst(line, endLineNumber, indent);\n\t\t\t}\n\t\t}\n\t\tif (previous.indent === indent) {\n\t\t\tprevious.endAbove = line;\n\t\t} else { // previous.indent < indent\n\t\t\t// new region with a bigger indent\n\t\t\tpreviousRegions.push({ indent, endAbove: line, line });\n\t\t}\n\t}\n\treturn result.toIndentRanges(model);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { onUnexpectedExternalError } from 'vs/base/common/errors';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { FoldingContext, FoldingRange, FoldingRangeProvider } from 'vs/editor/common/languages';\nimport { RangeProvider } from './folding';\nimport { FoldingRegions, MAX_LINE_NUMBER } from './foldingRanges';\n\nexport interface IFoldingRangeData extends FoldingRange {\n\trank: number;\n}\n\nconst foldingContext: FoldingContext = {\n};\n\nexport const ID_SYNTAX_PROVIDER = 'syntax';\n\nexport class SyntaxRangeProvider implements RangeProvider {\n\n\treadonly id = ID_SYNTAX_PROVIDER;\n\n\treadonly disposables: DisposableStore | undefined;\n\n\tconstructor(private readonly editorModel: ITextModel, private providers: FoldingRangeProvider[], handleFoldingRangesChange: () => void, private limit: number) {\n\t\tfor (const provider of providers) {\n\t\t\tif (typeof provider.onDidChange === 'function') {\n\t\t\t\tif (!this.disposables) {\n\t\t\t\t\tthis.disposables = new DisposableStore();\n\t\t\t\t}\n\t\t\t\tthis.disposables.add(provider.onDidChange(handleFoldingRangesChange));\n\t\t\t}\n\t\t}\n\t}\n\n\tcompute(cancellationToken: CancellationToken, notifyTooManyRegions?: (maxRegions: number) => void): Promise {\n\t\treturn collectSyntaxRanges(this.providers, this.editorModel, cancellationToken).then(ranges => {\n\t\t\tif (ranges) {\n\t\t\t\tlet res = sanitizeRanges(ranges, this.limit, notifyTooManyRegions);\n\t\t\t\treturn res;\n\t\t\t}\n\t\t\treturn null;\n\t\t});\n\t}\n\n\tdispose() {\n\t\tthis.disposables?.dispose();\n\t}\n}\n\nfunction collectSyntaxRanges(providers: FoldingRangeProvider[], model: ITextModel, cancellationToken: CancellationToken): Promise {\n\tlet rangeData: IFoldingRangeData[] | null = null;\n\tlet promises = providers.map((provider, i) => {\n\t\treturn Promise.resolve(provider.provideFoldingRanges(model, foldingContext, cancellationToken)).then(ranges => {\n\t\t\tif (cancellationToken.isCancellationRequested) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (Array.isArray(ranges)) {\n\t\t\t\tif (!Array.isArray(rangeData)) {\n\t\t\t\t\trangeData = [];\n\t\t\t\t}\n\t\t\t\tlet nLines = model.getLineCount();\n\t\t\t\tfor (let r of ranges) {\n\t\t\t\t\tif (r.start > 0 && r.end > r.start && r.end <= nLines) {\n\t\t\t\t\t\trangeData.push({ start: r.start, end: r.end, rank: i, kind: r.kind });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}, onUnexpectedExternalError);\n\t});\n\treturn Promise.all(promises).then(_ => {\n\t\treturn rangeData;\n\t});\n}\n\nexport class RangesCollector {\n\tprivate readonly _startIndexes: number[];\n\tprivate readonly _endIndexes: number[];\n\tprivate readonly _nestingLevels: number[];\n\tprivate readonly _nestingLevelCounts: number[];\n\tprivate readonly _types: Array;\n\tprivate _length: number;\n\tprivate readonly _foldingRangesLimit: number;\n\n\tconstructor(foldingRangesLimit: number, private readonly _notifyTooManyRegions?: (maxRegions: number) => void) {\n\t\tthis._startIndexes = [];\n\t\tthis._endIndexes = [];\n\t\tthis._nestingLevels = [];\n\t\tthis._nestingLevelCounts = [];\n\t\tthis._types = [];\n\t\tthis._length = 0;\n\t\tthis._foldingRangesLimit = foldingRangesLimit;\n\t}\n\n\tpublic add(startLineNumber: number, endLineNumber: number, type: string | undefined, nestingLevel: number) {\n\t\tif (startLineNumber > MAX_LINE_NUMBER || endLineNumber > MAX_LINE_NUMBER) {\n\t\t\treturn;\n\t\t}\n\t\tlet index = this._length;\n\t\tthis._startIndexes[index] = startLineNumber;\n\t\tthis._endIndexes[index] = endLineNumber;\n\t\tthis._nestingLevels[index] = nestingLevel;\n\t\tthis._types[index] = type;\n\t\tthis._length++;\n\t\tif (nestingLevel < 30) {\n\t\t\tthis._nestingLevelCounts[nestingLevel] = (this._nestingLevelCounts[nestingLevel] || 0) + 1;\n\t\t}\n\t}\n\n\tpublic toIndentRanges() {\n\t\tif (this._length <= this._foldingRangesLimit) {\n\t\t\tlet startIndexes = new Uint32Array(this._length);\n\t\t\tlet endIndexes = new Uint32Array(this._length);\n\t\t\tfor (let i = 0; i < this._length; i++) {\n\t\t\t\tstartIndexes[i] = this._startIndexes[i];\n\t\t\t\tendIndexes[i] = this._endIndexes[i];\n\t\t\t}\n\t\t\treturn new FoldingRegions(startIndexes, endIndexes, this._types);\n\t\t} else {\n\t\t\tif (this._notifyTooManyRegions) {\n\t\t\t\tthis._notifyTooManyRegions(this._foldingRangesLimit);\n\t\t\t}\n\t\t\tlet entries = 0;\n\t\t\tlet maxLevel = this._nestingLevelCounts.length;\n\t\t\tfor (let i = 0; i < this._nestingLevelCounts.length; i++) {\n\t\t\t\tlet n = this._nestingLevelCounts[i];\n\t\t\t\tif (n) {\n\t\t\t\t\tif (n + entries > this._foldingRangesLimit) {\n\t\t\t\t\t\tmaxLevel = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tentries += n;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet startIndexes = new Uint32Array(this._foldingRangesLimit);\n\t\t\tlet endIndexes = new Uint32Array(this._foldingRangesLimit);\n\t\t\tlet types: Array = [];\n\t\t\tfor (let i = 0, k = 0; i < this._length; i++) {\n\t\t\t\tlet level = this._nestingLevels[i];\n\t\t\t\tif (level < maxLevel || (level === maxLevel && entries++ < this._foldingRangesLimit)) {\n\t\t\t\t\tstartIndexes[k] = this._startIndexes[i];\n\t\t\t\t\tendIndexes[k] = this._endIndexes[i];\n\t\t\t\t\ttypes[k] = this._types[i];\n\t\t\t\t\tk++;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn new FoldingRegions(startIndexes, endIndexes, types);\n\t\t}\n\n\t}\n\n}\n\nexport function sanitizeRanges(rangeData: IFoldingRangeData[], limit: number, notifyTooManyRegions?: (maxRegions: number) => void): FoldingRegions {\n\tlet sorted = rangeData.sort((d1, d2) => {\n\t\tlet diff = d1.start - d2.start;\n\t\tif (diff === 0) {\n\t\t\tdiff = d1.rank - d2.rank;\n\t\t}\n\t\treturn diff;\n\t});\n\tlet collector = new RangesCollector(limit, notifyTooManyRegions);\n\n\tlet top: IFoldingRangeData | undefined = undefined;\n\tlet previous: IFoldingRangeData[] = [];\n\tfor (let entry of sorted) {\n\t\tif (!top) {\n\t\t\ttop = entry;\n\t\t\tcollector.add(entry.start, entry.end, entry.kind && entry.kind.value, previous.length);\n\t\t} else {\n\t\t\tif (entry.start > top.start) {\n\t\t\t\tif (entry.end <= top.end) {\n\t\t\t\t\tprevious.push(top);\n\t\t\t\t\ttop = entry;\n\t\t\t\t\tcollector.add(entry.start, entry.end, entry.kind && entry.kind.value, previous.length);\n\t\t\t\t} else {\n\t\t\t\t\tif (entry.start > top.end) {\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\ttop = previous.pop();\n\t\t\t\t\t\t} while (top && entry.start > top.end);\n\t\t\t\t\t\tif (top) {\n\t\t\t\t\t\t\tprevious.push(top);\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttop = entry;\n\t\t\t\t\t}\n\t\t\t\t\tcollector.add(entry.start, entry.end, entry.kind && entry.kind.value, previous.length);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn collector.toIndentRanges();\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { IModelDeltaDecoration, ITextModel, TrackedRangeStickiness } from 'vs/editor/common/model';\nimport { FoldingRegions, ILineRange } from 'vs/editor/contrib/folding/browser/foldingRanges';\nimport { IFoldingRangeData, sanitizeRanges } from 'vs/editor/contrib/folding/browser/syntaxRangeProvider';\nimport { RangeProvider } from './folding';\n\nexport const ID_INIT_PROVIDER = 'init';\n\nexport class InitializingRangeProvider implements RangeProvider {\n\treadonly id = ID_INIT_PROVIDER;\n\n\tprivate decorationIds: string[] | undefined;\n\tprivate timeout: any;\n\n\tconstructor(private readonly editorModel: ITextModel, initialRanges: ILineRange[], onTimeout: () => void, timeoutTime: number) {\n\t\tif (initialRanges.length) {\n\t\t\tlet toDecorationRange = (range: ILineRange): IModelDeltaDecoration => {\n\t\t\t\treturn {\n\t\t\t\t\trange: {\n\t\t\t\t\t\tstartLineNumber: range.startLineNumber,\n\t\t\t\t\t\tstartColumn: 0,\n\t\t\t\t\t\tendLineNumber: range.endLineNumber,\n\t\t\t\t\t\tendColumn: editorModel.getLineLength(range.endLineNumber)\n\t\t\t\t\t},\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tdescription: 'folding-initializing-range-provider',\n\t\t\t\t\t\tstickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\t\t\tthis.decorationIds = editorModel.deltaDecorations([], initialRanges.map(toDecorationRange));\n\t\t\tthis.timeout = setTimeout(onTimeout, timeoutTime);\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tif (this.decorationIds) {\n\t\t\tthis.editorModel.deltaDecorations(this.decorationIds, []);\n\t\t\tthis.decorationIds = undefined;\n\t\t}\n\t\tif (typeof this.timeout === 'number') {\n\t\t\tclearTimeout(this.timeout);\n\t\t\tthis.timeout = undefined;\n\t\t}\n\t}\n\n\tcompute(cancelationToken: CancellationToken): Promise {\n\t\tlet foldingRangeData: IFoldingRangeData[] = [];\n\t\tif (this.decorationIds) {\n\t\t\tfor (let id of this.decorationIds) {\n\t\t\t\tlet range = this.editorModel.getDecorationRange(id);\n\t\t\t\tif (range) {\n\t\t\t\t\tfoldingRangeData.push({ start: range.startLineNumber, end: range.endLineNumber, rank: 1 });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn Promise.resolve(sanitizeRanges(foldingRangeData, Number.MAX_VALUE));\n\t}\n}\n\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { EditOperation, ISingleEditOperation } from 'vs/editor/common/core/editOperation';\nimport { Range } from 'vs/editor/common/core/range';\nimport { EndOfLineSequence } from 'vs/editor/common/model';\nimport { TextEdit } from 'vs/editor/common/languages';\n\nexport class FormattingEdit {\n\n\tprivate static _handleEolEdits(editor: ICodeEditor, edits: TextEdit[]): ISingleEditOperation[] {\n\t\tlet newEol: EndOfLineSequence | undefined = undefined;\n\t\tlet singleEdits: ISingleEditOperation[] = [];\n\n\t\tfor (let edit of edits) {\n\t\t\tif (typeof edit.eol === 'number') {\n\t\t\t\tnewEol = edit.eol;\n\t\t\t}\n\t\t\tif (edit.range && typeof edit.text === 'string') {\n\t\t\t\tsingleEdits.push(edit);\n\t\t\t}\n\t\t}\n\n\t\tif (typeof newEol === 'number') {\n\t\t\tif (editor.hasModel()) {\n\t\t\t\teditor.getModel().pushEOL(newEol);\n\t\t\t}\n\t\t}\n\n\t\treturn singleEdits;\n\t}\n\n\tprivate static _isFullModelReplaceEdit(editor: ICodeEditor, edit: ISingleEditOperation): boolean {\n\t\tif (!editor.hasModel()) {\n\t\t\treturn false;\n\t\t}\n\t\tconst model = editor.getModel();\n\t\tconst editRange = model.validateRange(edit.range);\n\t\tconst fullModelRange = model.getFullModelRange();\n\t\treturn fullModelRange.equalsRange(editRange);\n\t}\n\n\tstatic execute(editor: ICodeEditor, _edits: TextEdit[], addUndoStops: boolean) {\n\t\tif (addUndoStops) {\n\t\t\teditor.pushUndoStop();\n\t\t}\n\t\tconst edits = FormattingEdit._handleEolEdits(editor, _edits);\n\t\tif (edits.length === 1 && FormattingEdit._isFullModelReplaceEdit(editor, edits[0])) {\n\t\t\t// We use replace semantics and hope that markers stay put...\n\t\t\teditor.executeEdits('formatEditsCommand', edits.map(edit => EditOperation.replace(Range.lift(edit.range), edit.text)));\n\t\t} else {\n\t\t\teditor.executeEdits('formatEditsCommand', edits.map(edit => EditOperation.replaceMove(Range.lift(edit.range), edit.text)));\n\t\t}\n\t\tif (addUndoStops) {\n\t\t\teditor.pushUndoStop();\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport * as platform from 'vs/base/common/platform';\nimport { ICodeEditor, IEditorMouseEvent, IMouseTarget } from 'vs/editor/browser/editorBrowser';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { ICursorSelectionChangedEvent } from 'vs/editor/common/cursor/cursorEvents';\n\nfunction hasModifier(e: { ctrlKey: boolean; shiftKey: boolean; altKey: boolean; metaKey: boolean }, modifier: 'ctrlKey' | 'shiftKey' | 'altKey' | 'metaKey'): boolean {\n\treturn !!e[modifier];\n}\n\n/**\n * An event that encapsulates the various trigger modifiers logic needed for go to definition.\n */\nexport class ClickLinkMouseEvent {\n\n\tpublic readonly target: IMouseTarget;\n\tpublic readonly hasTriggerModifier: boolean;\n\tpublic readonly hasSideBySideModifier: boolean;\n\tpublic readonly isNoneOrSingleMouseDown: boolean;\n\n\tconstructor(source: IEditorMouseEvent, opts: ClickLinkOptions) {\n\t\tthis.target = source.target;\n\t\tthis.hasTriggerModifier = hasModifier(source.event, opts.triggerModifier);\n\t\tthis.hasSideBySideModifier = hasModifier(source.event, opts.triggerSideBySideModifier);\n\t\tthis.isNoneOrSingleMouseDown = (source.event.detail <= 1);\n\t}\n}\n\n/**\n * An event that encapsulates the various trigger modifiers logic needed for go to definition.\n */\nexport class ClickLinkKeyboardEvent {\n\n\tpublic readonly keyCodeIsTriggerKey: boolean;\n\tpublic readonly keyCodeIsSideBySideKey: boolean;\n\tpublic readonly hasTriggerModifier: boolean;\n\n\tconstructor(source: IKeyboardEvent, opts: ClickLinkOptions) {\n\t\tthis.keyCodeIsTriggerKey = (source.keyCode === opts.triggerKey);\n\t\tthis.keyCodeIsSideBySideKey = (source.keyCode === opts.triggerSideBySideKey);\n\t\tthis.hasTriggerModifier = hasModifier(source, opts.triggerModifier);\n\t}\n}\nexport type TriggerModifier = 'ctrlKey' | 'shiftKey' | 'altKey' | 'metaKey';\n\nexport class ClickLinkOptions {\n\n\tpublic readonly triggerKey: KeyCode;\n\tpublic readonly triggerModifier: TriggerModifier;\n\tpublic readonly triggerSideBySideKey: KeyCode;\n\tpublic readonly triggerSideBySideModifier: TriggerModifier;\n\n\tconstructor(\n\t\ttriggerKey: KeyCode,\n\t\ttriggerModifier: TriggerModifier,\n\t\ttriggerSideBySideKey: KeyCode,\n\t\ttriggerSideBySideModifier: TriggerModifier\n\t) {\n\t\tthis.triggerKey = triggerKey;\n\t\tthis.triggerModifier = triggerModifier;\n\t\tthis.triggerSideBySideKey = triggerSideBySideKey;\n\t\tthis.triggerSideBySideModifier = triggerSideBySideModifier;\n\t}\n\n\tpublic equals(other: ClickLinkOptions): boolean {\n\t\treturn (\n\t\t\tthis.triggerKey === other.triggerKey\n\t\t\t&& this.triggerModifier === other.triggerModifier\n\t\t\t&& this.triggerSideBySideKey === other.triggerSideBySideKey\n\t\t\t&& this.triggerSideBySideModifier === other.triggerSideBySideModifier\n\t\t);\n\t}\n}\n\nfunction createOptions(multiCursorModifier: 'altKey' | 'ctrlKey' | 'metaKey'): ClickLinkOptions {\n\tif (multiCursorModifier === 'altKey') {\n\t\tif (platform.isMacintosh) {\n\t\t\treturn new ClickLinkOptions(KeyCode.Meta, 'metaKey', KeyCode.Alt, 'altKey');\n\t\t}\n\t\treturn new ClickLinkOptions(KeyCode.Ctrl, 'ctrlKey', KeyCode.Alt, 'altKey');\n\t}\n\n\tif (platform.isMacintosh) {\n\t\treturn new ClickLinkOptions(KeyCode.Alt, 'altKey', KeyCode.Meta, 'metaKey');\n\t}\n\treturn new ClickLinkOptions(KeyCode.Alt, 'altKey', KeyCode.Ctrl, 'ctrlKey');\n}\n\nexport class ClickLinkGesture extends Disposable {\n\n\tprivate readonly _onMouseMoveOrRelevantKeyDown: Emitter<[ClickLinkMouseEvent, ClickLinkKeyboardEvent | null]> = this._register(new Emitter<[ClickLinkMouseEvent, ClickLinkKeyboardEvent | null]>());\n\tpublic readonly onMouseMoveOrRelevantKeyDown: Event<[ClickLinkMouseEvent, ClickLinkKeyboardEvent | null]> = this._onMouseMoveOrRelevantKeyDown.event;\n\n\tprivate readonly _onExecute: Emitter = this._register(new Emitter());\n\tpublic readonly onExecute: Event = this._onExecute.event;\n\n\tprivate readonly _onCancel: Emitter = this._register(new Emitter());\n\tpublic readonly onCancel: Event = this._onCancel.event;\n\n\tprivate readonly _editor: ICodeEditor;\n\tprivate _opts: ClickLinkOptions;\n\n\tprivate _lastMouseMoveEvent: ClickLinkMouseEvent | null;\n\tprivate _hasTriggerKeyOnMouseDown: boolean;\n\tprivate _lineNumberOnMouseDown: number;\n\n\tconstructor(editor: ICodeEditor) {\n\t\tsuper();\n\n\t\tthis._editor = editor;\n\t\tthis._opts = createOptions(this._editor.getOption(EditorOption.multiCursorModifier));\n\n\t\tthis._lastMouseMoveEvent = null;\n\t\tthis._hasTriggerKeyOnMouseDown = false;\n\t\tthis._lineNumberOnMouseDown = 0;\n\n\t\tthis._register(this._editor.onDidChangeConfiguration((e) => {\n\t\t\tif (e.hasChanged(EditorOption.multiCursorModifier)) {\n\t\t\t\tconst newOpts = createOptions(this._editor.getOption(EditorOption.multiCursorModifier));\n\t\t\t\tif (this._opts.equals(newOpts)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._opts = newOpts;\n\t\t\t\tthis._lastMouseMoveEvent = null;\n\t\t\t\tthis._hasTriggerKeyOnMouseDown = false;\n\t\t\t\tthis._lineNumberOnMouseDown = 0;\n\t\t\t\tthis._onCancel.fire();\n\t\t\t}\n\t\t}));\n\t\tthis._register(this._editor.onMouseMove((e: IEditorMouseEvent) => this._onEditorMouseMove(new ClickLinkMouseEvent(e, this._opts))));\n\t\tthis._register(this._editor.onMouseDown((e: IEditorMouseEvent) => this._onEditorMouseDown(new ClickLinkMouseEvent(e, this._opts))));\n\t\tthis._register(this._editor.onMouseUp((e: IEditorMouseEvent) => this._onEditorMouseUp(new ClickLinkMouseEvent(e, this._opts))));\n\t\tthis._register(this._editor.onKeyDown((e: IKeyboardEvent) => this._onEditorKeyDown(new ClickLinkKeyboardEvent(e, this._opts))));\n\t\tthis._register(this._editor.onKeyUp((e: IKeyboardEvent) => this._onEditorKeyUp(new ClickLinkKeyboardEvent(e, this._opts))));\n\t\tthis._register(this._editor.onMouseDrag(() => this._resetHandler()));\n\n\t\tthis._register(this._editor.onDidChangeCursorSelection((e) => this._onDidChangeCursorSelection(e)));\n\t\tthis._register(this._editor.onDidChangeModel((e) => this._resetHandler()));\n\t\tthis._register(this._editor.onDidChangeModelContent(() => this._resetHandler()));\n\t\tthis._register(this._editor.onDidScrollChange((e) => {\n\t\t\tif (e.scrollTopChanged || e.scrollLeftChanged) {\n\t\t\t\tthis._resetHandler();\n\t\t\t}\n\t\t}));\n\t}\n\n\tprivate _onDidChangeCursorSelection(e: ICursorSelectionChangedEvent): void {\n\t\tif (e.selection && e.selection.startColumn !== e.selection.endColumn) {\n\t\t\tthis._resetHandler(); // immediately stop this feature if the user starts to select (https://github.com/microsoft/vscode/issues/7827)\n\t\t}\n\t}\n\n\tprivate _onEditorMouseMove(mouseEvent: ClickLinkMouseEvent): void {\n\t\tthis._lastMouseMoveEvent = mouseEvent;\n\n\t\tthis._onMouseMoveOrRelevantKeyDown.fire([mouseEvent, null]);\n\t}\n\n\tprivate _onEditorMouseDown(mouseEvent: ClickLinkMouseEvent): void {\n\t\t// We need to record if we had the trigger key on mouse down because someone might select something in the editor\n\t\t// holding the mouse down and then while mouse is down start to press Ctrl/Cmd to start a copy operation and then\n\t\t// release the mouse button without wanting to do the navigation.\n\t\t// With this flag we prevent goto definition if the mouse was down before the trigger key was pressed.\n\t\tthis._hasTriggerKeyOnMouseDown = mouseEvent.hasTriggerModifier;\n\t\tthis._lineNumberOnMouseDown = mouseEvent.target.position ? mouseEvent.target.position.lineNumber : 0;\n\t}\n\n\tprivate _onEditorMouseUp(mouseEvent: ClickLinkMouseEvent): void {\n\t\tconst currentLineNumber = mouseEvent.target.position ? mouseEvent.target.position.lineNumber : 0;\n\t\tif (this._hasTriggerKeyOnMouseDown && this._lineNumberOnMouseDown && this._lineNumberOnMouseDown === currentLineNumber) {\n\t\t\tthis._onExecute.fire(mouseEvent);\n\t\t}\n\t}\n\n\tprivate _onEditorKeyDown(e: ClickLinkKeyboardEvent): void {\n\t\tif (\n\t\t\tthis._lastMouseMoveEvent\n\t\t\t&& (\n\t\t\t\te.keyCodeIsTriggerKey // User just pressed Ctrl/Cmd (normal goto definition)\n\t\t\t\t|| (e.keyCodeIsSideBySideKey && e.hasTriggerModifier) // User pressed Ctrl/Cmd+Alt (goto definition to the side)\n\t\t\t)\n\t\t) {\n\t\t\tthis._onMouseMoveOrRelevantKeyDown.fire([this._lastMouseMoveEvent, e]);\n\t\t} else if (e.hasTriggerModifier) {\n\t\t\tthis._onCancel.fire(); // remove decorations if user holds another key with ctrl/cmd to prevent accident goto declaration\n\t\t}\n\t}\n\n\tprivate _onEditorKeyUp(e: ClickLinkKeyboardEvent): void {\n\t\tif (e.keyCodeIsTriggerKey) {\n\t\t\tthis._onCancel.fire();\n\t\t}\n\t}\n\n\tprivate _resetHandler(): void {\n\t\tthis._lastMouseMoveEvent = null;\n\t\tthis._hasTriggerKeyOnMouseDown = false;\n\t\tthis._onCancel.fire();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { AsyncIterableObject, CancelableAsyncIterableObject, createCancelableAsyncIterable, RunOnceScheduler } from 'vs/base/common/async';\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport { Emitter } from 'vs/base/common/event';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\n\nexport interface IHoverComputer {\n\t/**\n\t * This is called after half the hover time\n\t */\n\tcomputeAsync?: (token: CancellationToken) => AsyncIterableObject;\n\t/**\n\t * This is called after all the hover time\n\t */\n\tcomputeSync?: () => T[];\n}\n\nconst enum HoverOperationState {\n\tIdle,\n\tFirstWait,\n\tSecondWait,\n\tWaitingForAsync = 3,\n\tWaitingForAsyncShowingLoading = 4,\n}\n\nexport const enum HoverStartMode {\n\tDelayed = 0,\n\tImmediate = 1\n}\n\nexport class HoverResult {\n\tconstructor(\n\t\tpublic readonly value: T[],\n\t\tpublic readonly isComplete: boolean,\n\t\tpublic readonly hasLoadingMessage: boolean,\n\t) { }\n}\n\n/**\n * Computing the hover is very fine tuned.\n *\n * Suppose the hover delay is 300ms (the default). Then, when resting the mouse at an anchor:\n * - at 150ms, the async computation is triggered (i.e. semantic hover)\n * - if async results already come in, they are not rendered yet.\n * - at 300ms, the sync computation is triggered (i.e. decorations, markers)\n * - if there are sync or async results, they are rendered.\n * - at 900ms, if the async computation hasn't finished, a \"Loading...\" result is added.\n */\nexport class HoverOperation extends Disposable {\n\n\tprivate readonly _onResult = this._register(new Emitter>());\n\tpublic readonly onResult = this._onResult.event;\n\n\tprivate readonly _firstWaitScheduler = this._register(new RunOnceScheduler(() => this._triggerAsyncComputation(), 0));\n\tprivate readonly _secondWaitScheduler = this._register(new RunOnceScheduler(() => this._triggerSyncComputation(), 0));\n\tprivate readonly _loadingMessageScheduler = this._register(new RunOnceScheduler(() => this._triggerLoadingMessage(), 0));\n\n\tprivate _state = HoverOperationState.Idle;\n\tprivate _asyncIterable: CancelableAsyncIterableObject | null = null;\n\tprivate _asyncIterableDone: boolean = false;\n\tprivate _result: T[] = [];\n\n\tconstructor(\n\t\tprivate readonly _editor: ICodeEditor,\n\t\tprivate readonly _computer: IHoverComputer\n\t) {\n\t\tsuper();\n\t}\n\n\tpublic override dispose(): void {\n\t\tif (this._asyncIterable) {\n\t\t\tthis._asyncIterable.cancel();\n\t\t\tthis._asyncIterable = null;\n\t\t}\n\t\tsuper.dispose();\n\t}\n\n\tprivate get _hoverTime(): number {\n\t\treturn this._editor.getOption(EditorOption.hover).delay;\n\t}\n\n\tprivate get _firstWaitTime(): number {\n\t\treturn this._hoverTime / 2;\n\t}\n\n\tprivate get _secondWaitTime(): number {\n\t\treturn this._hoverTime - this._firstWaitTime;\n\t}\n\n\tprivate get _loadingMessageTime(): number {\n\t\treturn 3 * this._hoverTime;\n\t}\n\n\tprivate _setState(state: HoverOperationState, fireResult: boolean = true): void {\n\t\tthis._state = state;\n\t\tif (fireResult) {\n\t\t\tthis._fireResult();\n\t\t}\n\t}\n\n\tprivate _triggerAsyncComputation(): void {\n\t\tthis._setState(HoverOperationState.SecondWait);\n\t\tthis._secondWaitScheduler.schedule(this._secondWaitTime);\n\n\t\tif (this._computer.computeAsync) {\n\t\t\tthis._asyncIterableDone = false;\n\t\t\tthis._asyncIterable = createCancelableAsyncIterable(token => this._computer.computeAsync!(token));\n\n\t\t\t(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tfor await (const item of this._asyncIterable!) {\n\t\t\t\t\t\tif (item) {\n\t\t\t\t\t\t\tthis._result.push(item);\n\t\t\t\t\t\t\tthis._fireResult();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis._asyncIterableDone = true;\n\n\t\t\t\t\tif (this._state === HoverOperationState.WaitingForAsync || this._state === HoverOperationState.WaitingForAsyncShowingLoading) {\n\t\t\t\t\t\tthis._setState(HoverOperationState.Idle);\n\t\t\t\t\t}\n\n\t\t\t\t} catch (e) {\n\t\t\t\t\tonUnexpectedError(e);\n\t\t\t\t}\n\t\t\t})();\n\n\t\t} else {\n\t\t\tthis._asyncIterableDone = true;\n\t\t}\n\t}\n\n\tprivate _triggerSyncComputation(): void {\n\t\tif (this._computer.computeSync) {\n\t\t\tthis._result = this._result.concat(this._computer.computeSync());\n\t\t}\n\t\tthis._setState(this._asyncIterableDone ? HoverOperationState.Idle : HoverOperationState.WaitingForAsync);\n\t}\n\n\tprivate _triggerLoadingMessage(): void {\n\t\tif (this._state === HoverOperationState.WaitingForAsync) {\n\t\t\tthis._setState(HoverOperationState.WaitingForAsyncShowingLoading);\n\t\t}\n\t}\n\n\tprivate _fireResult(): void {\n\t\tif (this._state === HoverOperationState.FirstWait || this._state === HoverOperationState.SecondWait) {\n\t\t\t// Do not send out results before the hover time\n\t\t\treturn;\n\t\t}\n\t\tconst isComplete = (this._state === HoverOperationState.Idle);\n\t\tconst hasLoadingMessage = (this._state === HoverOperationState.WaitingForAsyncShowingLoading);\n\t\tthis._onResult.fire(new HoverResult(this._result.slice(0), isComplete, hasLoadingMessage));\n\t}\n\n\tpublic start(mode: HoverStartMode): void {\n\t\tif (mode === HoverStartMode.Delayed) {\n\t\t\tif (this._state === HoverOperationState.Idle) {\n\t\t\t\tthis._setState(HoverOperationState.FirstWait);\n\t\t\t\tthis._firstWaitScheduler.schedule(this._firstWaitTime);\n\t\t\t\tthis._loadingMessageScheduler.schedule(this._loadingMessageTime);\n\t\t\t}\n\t\t} else {\n\t\t\tswitch (this._state) {\n\t\t\t\tcase HoverOperationState.Idle:\n\t\t\t\t\tthis._triggerAsyncComputation();\n\t\t\t\t\tthis._secondWaitScheduler.cancel();\n\t\t\t\t\tthis._triggerSyncComputation();\n\t\t\t\t\tbreak;\n\t\t\t\tcase HoverOperationState.SecondWait:\n\t\t\t\t\tthis._secondWaitScheduler.cancel();\n\t\t\t\t\tthis._triggerSyncComputation();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic cancel(): void {\n\t\tthis._firstWaitScheduler.cancel();\n\t\tthis._secondWaitScheduler.cancel();\n\t\tthis._loadingMessageScheduler.cancel();\n\t\tif (this._asyncIterable) {\n\t\t\tthis._asyncIterable.cancel();\n\t\t\tthis._asyncIterable = null;\n\t\t}\n\t\tthis._result = [];\n\t\tthis._setState(HoverOperationState.Idle, false);\n\t}\n\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { AsyncIterableObject } from 'vs/base/common/async';\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { IEditorMouseEvent } from 'vs/editor/browser/editorBrowser';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { IModelDecoration } from 'vs/editor/common/model';\nimport { ColorPickerWidget } from 'vs/editor/contrib/colorPicker/browser/colorPickerWidget';\n\nexport interface IHoverPart {\n\t/**\n\t * The creator of this hover part.\n\t */\n\treadonly owner: IEditorHoverParticipant;\n\t/**\n\t * The range where this hover part applies.\n\t */\n\treadonly range: Range;\n\t/**\n\t * Force the hover to always be rendered at this specific range,\n\t * even in the case of multiple hover parts.\n\t */\n\treadonly forceShowAtRange?: boolean;\n\t/**\n\t * Is this hover part still valid for this new anchor?\n\t */\n\tisValidForHoverAnchor(anchor: HoverAnchor): boolean;\n}\n\nexport const enum HoverAnchorType {\n\tRange = 1,\n\tForeignElement = 2\n}\n\nexport class HoverRangeAnchor {\n\tpublic readonly type = HoverAnchorType.Range;\n\tconstructor(\n\t\tpublic readonly priority: number,\n\t\tpublic readonly range: Range\n\t) {\n\t}\n\tpublic equals(other: HoverAnchor) {\n\t\treturn (other.type === HoverAnchorType.Range && this.range.equalsRange(other.range));\n\t}\n\tpublic canAdoptVisibleHover(lastAnchor: HoverAnchor, showAtPosition: Position): boolean {\n\t\treturn (lastAnchor.type === HoverAnchorType.Range && showAtPosition.lineNumber === this.range.startLineNumber);\n\t}\n}\n\nexport class HoverForeignElementAnchor {\n\tpublic readonly type = HoverAnchorType.ForeignElement;\n\tconstructor(\n\t\tpublic readonly priority: number,\n\t\tpublic readonly owner: IEditorHoverParticipant,\n\t\tpublic readonly range: Range\n\t) {\n\t}\n\tpublic equals(other: HoverAnchor) {\n\t\treturn (other.type === HoverAnchorType.ForeignElement && this.owner === other.owner);\n\t}\n\tpublic canAdoptVisibleHover(lastAnchor: HoverAnchor, showAtPosition: Position): boolean {\n\t\treturn (lastAnchor.type === HoverAnchorType.ForeignElement && this.owner === lastAnchor.owner);\n\t}\n}\n\nexport type HoverAnchor = HoverRangeAnchor | HoverForeignElementAnchor;\n\nexport interface IEditorHoverStatusBar {\n\taddAction(actionOptions: { label: string, iconClass?: string, run: (target: HTMLElement) => void, commandId: string }): IEditorHoverAction;\n\tappend(element: HTMLElement): HTMLElement;\n}\n\nexport interface IEditorHoverAction {\n\tsetEnabled(enabled: boolean): void;\n}\n\nexport interface IEditorHoverRenderContext {\n\t/**\n\t * The fragment where dom elements should be attached.\n\t */\n\treadonly fragment: DocumentFragment;\n\t/**\n\t * The status bar for actions for this hover.\n\t */\n\treadonly statusBar: IEditorHoverStatusBar;\n\t/**\n\t * Set if the hover will render a color picker widget.\n\t */\n\tsetColorPicker(widget: ColorPickerWidget): void;\n\t/**\n\t * The contents rendered inside the fragment have been changed, which means that the hover should relayout.\n\t */\n\tonContentsChanged(): void;\n\t/**\n\t * Hide the hover.\n\t */\n\thide(): void;\n}\n\nexport interface IEditorHoverParticipant {\n\tsuggestHoverAnchor?(mouseEvent: IEditorMouseEvent): HoverAnchor | null;\n\tcomputeSync(anchor: HoverAnchor, lineDecorations: IModelDecoration[]): T[];\n\tcomputeAsync?(anchor: HoverAnchor, lineDecorations: IModelDecoration[], token: CancellationToken): AsyncIterableObject;\n\tcreateLoadingMessage?(anchor: HoverAnchor): T | null;\n\trenderHoverParts(context: IEditorHoverRenderContext, hoverParts: T[]): IDisposable;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { ITextModel } from 'vs/editor/common/model';\n\nexport class InPlaceReplaceCommand implements ICommand {\n\n\tprivate readonly _editRange: Range;\n\tprivate readonly _originalSelection: Selection;\n\tprivate readonly _text: string;\n\n\tconstructor(editRange: Range, originalSelection: Selection, text: string) {\n\t\tthis._editRange = editRange;\n\t\tthis._originalSelection = originalSelection;\n\t\tthis._text = text;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tbuilder.addTrackedEditOperation(this._editRange, this._text);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tconst inverseEditOperations = helper.getInverseEditOperations();\n\t\tconst srcRange = inverseEditOperations[0].range;\n\n\t\tif (!this._originalSelection.isEmpty()) {\n\t\t\t// Preserve selection and extends to typed text\n\t\t\treturn new Selection(\n\t\t\t\tsrcRange.endLineNumber,\n\t\t\t\tsrcRange.endColumn - this._text.length,\n\t\t\t\tsrcRange.endLineNumber,\n\t\t\t\tsrcRange.endColumn\n\t\t\t);\n\t\t}\n\n\t\treturn new Selection(\n\t\t\tsrcRange.endLineNumber,\n\t\t\tMath.min(this._originalSelection.positionColumn, srcRange.endColumn),\n\t\t\tsrcRange.endLineNumber,\n\t\t\tMath.min(this._originalSelection.positionColumn, srcRange.endColumn)\n\t\t);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport function getSpaceCnt(str: string, tabSize: number) {\n\tlet spacesCnt = 0;\n\n\tfor (let i = 0; i < str.length; i++) {\n\t\tif (str.charAt(i) === '\\t') {\n\t\t\tspacesCnt += tabSize;\n\t\t} else {\n\t\t\tspacesCnt++;\n\t\t}\n\t}\n\n\treturn spacesCnt;\n}\n\nexport function generateIndent(spacesCnt: number, tabSize: number, insertSpaces: boolean) {\n\tspacesCnt = spacesCnt < 0 ? 0 : spacesCnt;\n\n\tlet result = '';\n\tif (!insertSpaces) {\n\t\tlet tabsCnt = Math.floor(spacesCnt / tabSize);\n\t\tspacesCnt = spacesCnt % tabSize;\n\t\tfor (let i = 0; i < tabsCnt; i++) {\n\t\t\tresult += '\\t';\n\t\t}\n\t}\n\n\tfor (let i = 0; i < spacesCnt; i++) {\n\t\tresult += ' ';\n\t}\n\n\treturn result;\n}","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { CancellationError, onUnexpectedExternalError } from 'vs/base/common/errors';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\nimport { IPosition, Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { InlayHint, InlayHintList, InlayHintsProvider, InlayHintsProviderRegistry } from 'vs/editor/common/languages';\nimport { ITextModel } from 'vs/editor/common/model';\n\nexport class InlayHintAnchor {\n\tconstructor(readonly range: Range, readonly direction: 'before' | 'after') { }\n}\n\nexport class InlayHintItem {\n\n\tprivate _isResolved: boolean = false;\n\tprivate _currentResolve?: Promise;\n\n\tconstructor(readonly hint: InlayHint, readonly anchor: InlayHintAnchor, readonly provider: InlayHintsProvider) { }\n\n\twith(delta: { anchor: InlayHintAnchor; }): InlayHintItem {\n\t\tconst result = new InlayHintItem(this.hint, delta.anchor, this.provider);\n\t\tresult._isResolved = this._isResolved;\n\t\tresult._currentResolve = this._currentResolve;\n\t\treturn result;\n\t}\n\n\tasync resolve(token: CancellationToken): Promise {\n\t\tif (typeof this.provider.resolveInlayHint !== 'function') {\n\t\t\treturn;\n\t\t}\n\t\tif (this._currentResolve) {\n\t\t\t// wait for an active resolve operation and try again\n\t\t\t// when that's done.\n\t\t\tawait this._currentResolve;\n\t\t\tif (token.isCancellationRequested) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn this.resolve(token);\n\t\t}\n\t\tif (!this._isResolved) {\n\t\t\tthis._currentResolve = this._doResolve(token)\n\t\t\t\t.finally(() => this._currentResolve = undefined);\n\t\t}\n\t\tawait this._currentResolve;\n\t}\n\n\tprivate async _doResolve(token: CancellationToken) {\n\t\ttry {\n\t\t\tconst newHint = await Promise.resolve(this.provider.resolveInlayHint!(this.hint, token));\n\t\t\tthis.hint.tooltip = newHint?.tooltip ?? this.hint.tooltip;\n\t\t\tthis.hint.label = newHint?.label ?? this.hint.label;\n\t\t\tthis._isResolved = true;\n\t\t} catch (err) {\n\t\t\tonUnexpectedExternalError(err);\n\t\t\tthis._isResolved = false;\n\t\t}\n\t}\n}\n\nexport class InlayHintsFragments {\n\n\tstatic async create(model: ITextModel, ranges: Range[], token: CancellationToken): Promise {\n\n\t\tconst data: [InlayHintList, InlayHintsProvider][] = [];\n\n\t\tconst promises = InlayHintsProviderRegistry.ordered(model).reverse().map(provider => ranges.map(async range => {\n\t\t\ttry {\n\t\t\t\tconst result = await provider.provideInlayHints(model, range, token);\n\t\t\t\tif (result?.hints.length) {\n\t\t\t\t\tdata.push([result, provider]);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tonUnexpectedExternalError(err);\n\t\t\t}\n\t\t}));\n\n\t\tawait Promise.all(promises.flat());\n\n\t\tif (token.isCancellationRequested || model.isDisposed()) {\n\t\t\tthrow new CancellationError();\n\t\t}\n\n\t\treturn new InlayHintsFragments(ranges, data, model);\n\t}\n\n\tprivate readonly _disposables = new DisposableStore();\n\n\treadonly items: readonly InlayHintItem[];\n\treadonly ranges: readonly Range[];\n\treadonly provider: Set;\n\n\tprivate constructor(ranges: Range[], data: [InlayHintList, InlayHintsProvider][], model: ITextModel) {\n\t\tthis.ranges = ranges;\n\t\tthis.provider = new Set();\n\t\tconst items: InlayHintItem[] = [];\n\t\tfor (const [list, provider] of data) {\n\t\t\tthis._disposables.add(list);\n\t\t\tthis.provider.add(provider);\n\n\t\t\tfor (const hint of list.hints) {\n\t\t\t\t// compute the range to which the item should be attached to\n\t\t\t\tlet position = model.validatePosition(hint.position);\n\t\t\t\tlet direction: 'before' | 'after' = 'before';\n\n\t\t\t\tconst wordRange = InlayHintsFragments._getRangeAtPosition(model, position);\n\t\t\t\tlet range: Range;\n\n\t\t\t\tif (wordRange.getStartPosition().isBefore(position)) {\n\t\t\t\t\trange = Range.fromPositions(wordRange.getStartPosition(), position);\n\t\t\t\t\tdirection = 'after';\n\t\t\t\t} else {\n\t\t\t\t\trange = Range.fromPositions(position, wordRange.getEndPosition());\n\t\t\t\t\tdirection = 'before';\n\t\t\t\t}\n\n\t\t\t\titems.push(new InlayHintItem(hint, new InlayHintAnchor(range, direction), provider));\n\t\t\t}\n\t\t}\n\t\tthis.items = items.sort((a, b) => Position.compare(a.hint.position, b.hint.position));\n\t}\n\n\tdispose(): void {\n\t\tthis._disposables.dispose();\n\t}\n\n\tprivate static _getRangeAtPosition(model: ITextModel, position: IPosition): Range {\n\t\tconst line = position.lineNumber;\n\t\tconst word = model.getWordAtPosition(position);\n\t\tif (word) {\n\t\t\t// always prefer the word range\n\t\t\treturn new Range(line, word.startColumn, line, word.endColumn);\n\t\t}\n\n\t\tmodel.tokenizeIfCheap(line);\n\t\tconst tokens = model.getLineTokens(line);\n\t\tconst offset = position.column - 1;\n\t\tconst idx = tokens.findTokenIndexAtOffset(offset);\n\n\t\tlet start = tokens.getStartOffset(idx);\n\t\tlet end = tokens.getEndOffset(idx);\n\n\t\tif (end - start === 1) {\n\t\t\t// single character token, when at its end try leading/trailing token instead\n\t\t\tif (start === offset && idx > 1) {\n\t\t\t\t// leading token\n\t\t\t\tstart = tokens.getStartOffset(idx - 1);\n\t\t\t\tend = tokens.getEndOffset(idx - 1);\n\t\t\t} else if (end === offset && idx < tokens.getCount() - 1) {\n\t\t\t\t// trailing token\n\t\t\t\tstart = tokens.getStartOffset(idx + 1);\n\t\t\t\tend = tokens.getEndOffset(idx + 1);\n\t\t\t}\n\t\t}\n\n\t\treturn new Range(line, start + 1, line, end + 1);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport const inlineSuggestCommitId = 'editor.action.inlineSuggest.commit';\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { Position } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\n\nexport class GhostText {\n\n\tconstructor(\n\t\tpublic readonly lineNumber: number,\n\t\tpublic readonly parts: GhostTextPart[],\n\t\tpublic readonly additionalReservedLineCount: number = 0\n\t) {\n\t}\n\n\trenderForScreenReader(lineText: string): string {\n\t\tif (this.parts.length === 0) {\n\t\t\treturn '';\n\t\t}\n\t\tconst lastPart = this.parts[this.parts.length - 1];\n\n\t\tconst cappedLineText = lineText.substr(0, lastPart.column - 1);\n\t\tconst text = applyEdits(cappedLineText,\n\t\t\tthis.parts.map(p => ({\n\t\t\t\trange: { startLineNumber: 1, endLineNumber: 1, startColumn: p.column, endColumn: p.column },\n\t\t\t\ttext: p.lines.join('\\n')\n\t\t\t}))\n\t\t);\n\n\t\treturn text.substring(this.parts[0].column - 1);\n\t}\n}\n\nclass PositionOffsetTransformer {\n\tprivate readonly lineStartOffsetByLineIdx: number[];\n\n\tconstructor(text: string) {\n\t\tthis.lineStartOffsetByLineIdx = [];\n\t\tthis.lineStartOffsetByLineIdx.push(0);\n\t\tfor (let i = 0; i < text.length; i++) {\n\t\t\tif (text.charAt(i) === '\\n') {\n\t\t\t\tthis.lineStartOffsetByLineIdx.push(i + 1);\n\t\t\t}\n\t\t}\n\t}\n\n\tgetOffset(position: Position): number {\n\t\treturn this.lineStartOffsetByLineIdx[position.lineNumber - 1] + position.column - 1;\n\t}\n}\n\nfunction applyEdits(text: string, edits: { range: IRange, text: string }[]): string {\n\tconst transformer = new PositionOffsetTransformer(text);\n\tconst offsetEdits = edits.map(e => {\n\t\tconst range = Range.lift(e.range);\n\t\treturn ({\n\t\t\tstartOffset: transformer.getOffset(range.getStartPosition()),\n\t\t\tendOffset: transformer.getOffset(range.getEndPosition()),\n\t\t\ttext: e.text\n\t\t});\n\t});\n\n\toffsetEdits.sort((a, b) => b.startOffset - a.startOffset);\n\n\tfor (const edit of offsetEdits) {\n\t\ttext = text.substring(0, edit.startOffset) + edit.text + text.substring(edit.endOffset);\n\t}\n\n\treturn text;\n}\n\nexport class GhostTextPart {\n\tconstructor(\n\t\treadonly column: number,\n\t\treadonly lines: readonly string[],\n\t\t/**\n\t\t * Indicates if this part is a preview of an inline suggestion when a suggestion is previewed.\n\t\t*/\n\t\treadonly preview: boolean,\n\t) {\n\t}\n}\n\n\nexport interface GhostTextWidgetModel {\n\treadonly onDidChange: Event;\n\treadonly ghostText: GhostText | undefined;\n\n\tsetExpanded(expanded: boolean): void;\n\n\treadonly minReservedLineCount: number;\n}\n\nexport abstract class BaseGhostTextWidgetModel extends Disposable implements GhostTextWidgetModel {\n\tpublic abstract readonly ghostText: GhostText | undefined;\n\n\tprivate _expanded: boolean | undefined = undefined;\n\n\tprotected readonly onDidChangeEmitter = new Emitter();\n\tpublic readonly onDidChange = this.onDidChangeEmitter.event;\n\n\tpublic abstract readonly minReservedLineCount: number;\n\n\tconstructor(protected readonly editor: IActiveCodeEditor) {\n\t\tsuper();\n\n\t\tthis._register(editor.onDidChangeConfiguration((e) => {\n\t\t\tif (e.hasChanged(EditorOption.suggest) && this._expanded === undefined) {\n\t\t\t\tthis.onDidChangeEmitter.fire();\n\t\t\t}\n\t\t}));\n\t}\n\n\tpublic setExpanded(expanded: boolean): void {\n\t\tthis._expanded = true;\n\t\tthis.onDidChangeEmitter.fire();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDiffChange, LcsDiff } from 'vs/base/common/diff/diff';\nimport * as strings from 'vs/base/common/strings';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { InlineCompletion } from 'vs/editor/common/languages';\nimport { GhostText, GhostTextPart } from 'vs/editor/contrib/inlineCompletions/browser/ghostText';\n\n/**\n * A normalized inline completion is an inline completion with a defined range.\n*/\nexport interface NormalizedInlineCompletion extends InlineCompletion {\n\trange: Range;\n}\n\nexport function normalizedInlineCompletionsEquals(a: NormalizedInlineCompletion | undefined, b: NormalizedInlineCompletion | undefined): boolean {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\tif (!a || !b) {\n\t\treturn false;\n\t}\n\treturn a.range.equalsRange(b.range) && a.text === b.text && a.command === b.command;\n}\n\n/**\n * @param previewSuffixLength Sets where to split `inlineCompletion.text`.\n * \tIf the text is `hello` and the suffix length is 2, the non-preview part is `hel` and the preview-part is `lo`.\n*/\nexport function inlineCompletionToGhostText(\n\tinlineCompletion: NormalizedInlineCompletion,\n\ttextModel: ITextModel,\n\tmode: 'prefix' | 'subword' | 'subwordSmart',\n\tcursorPosition?: Position,\n\tpreviewSuffixLength = 0\n): GhostText | undefined {\n\tif (inlineCompletion.range.startLineNumber !== inlineCompletion.range.endLineNumber) {\n\t\t// Only single line replacements are supported.\n\t\treturn undefined;\n\t}\n\n\tconst sourceLine = textModel.getLineContent(inlineCompletion.range.startLineNumber);\n\tconst sourceIndentationLength = strings.getLeadingWhitespace(sourceLine).length;\n\n\tconst suggestionTouchesIndentation = inlineCompletion.range.startColumn - 1 <= sourceIndentationLength;\n\tif (suggestionTouchesIndentation) {\n\t\t// source: ··········[······abc]\n\t\t// ^^^^^^^^^ inlineCompletion.range\n\t\t// ^^^^^^^^^^ ^^^^^^ sourceIndentationLength\n\t\t// ^^^^^^ replacedIndentation.length\n\t\t// ^^^ rangeThatDoesNotReplaceIndentation\n\n\t\t// inlineCompletion.text: '··foo'\n\t\t// ^^ suggestionAddedIndentationLength\n\n\t\tconst suggestionAddedIndentationLength = strings.getLeadingWhitespace(inlineCompletion.text).length;\n\n\t\tconst replacedIndentation = sourceLine.substring(inlineCompletion.range.startColumn - 1, sourceIndentationLength);\n\t\tconst rangeThatDoesNotReplaceIndentation = Range.fromPositions(\n\t\t\tinlineCompletion.range.getStartPosition().delta(0, replacedIndentation.length),\n\t\t\tinlineCompletion.range.getEndPosition()\n\t\t);\n\n\t\tconst suggestionWithoutIndentationChange =\n\t\t\tinlineCompletion.text.startsWith(replacedIndentation)\n\t\t\t\t// Adds more indentation without changing existing indentation: We can add ghost text for this\n\t\t\t\t? inlineCompletion.text.substring(replacedIndentation.length)\n\t\t\t\t// Changes or removes existing indentation. Only add ghost text for the non-indentation part.\n\t\t\t\t: inlineCompletion.text.substring(suggestionAddedIndentationLength);\n\n\t\tinlineCompletion = {\n\t\t\trange: rangeThatDoesNotReplaceIndentation,\n\t\t\ttext: suggestionWithoutIndentationChange,\n\t\t\tcommand: inlineCompletion.command\n\t\t};\n\t}\n\n\t// This is a single line string\n\tconst valueToBeReplaced = textModel.getValueInRange(inlineCompletion.range);\n\n\tconst changes = cachingDiff(valueToBeReplaced, inlineCompletion.text);\n\n\tif (!changes) {\n\t\t// No ghost text in case the diff would be too slow to compute\n\t\treturn undefined;\n\t}\n\n\tconst lineNumber = inlineCompletion.range.startLineNumber;\n\n\tconst parts = new Array();\n\n\tif (mode === 'prefix') {\n\t\tconst filteredChanges = changes.filter(c => c.originalLength === 0);\n\t\tif (filteredChanges.length > 1 || filteredChanges.length === 1 && filteredChanges[0].originalStart !== valueToBeReplaced.length) {\n\t\t\t// Prefixes only have a single change.\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tconst previewStartInCompletionText = inlineCompletion.text.length - previewSuffixLength;\n\n\tfor (const c of changes) {\n\t\tconst insertColumn = inlineCompletion.range.startColumn + c.originalStart + c.originalLength;\n\n\t\tif (mode === 'subwordSmart' && cursorPosition && cursorPosition.lineNumber === inlineCompletion.range.startLineNumber && insertColumn < cursorPosition.column) {\n\t\t\t// No ghost text before cursor\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (c.originalLength > 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (c.modifiedLength === 0) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst modifiedEnd = c.modifiedStart + c.modifiedLength;\n\t\tconst nonPreviewTextEnd = Math.max(c.modifiedStart, Math.min(modifiedEnd, previewStartInCompletionText));\n\t\tconst nonPreviewText = inlineCompletion.text.substring(c.modifiedStart, nonPreviewTextEnd);\n\t\tconst italicText = inlineCompletion.text.substring(nonPreviewTextEnd, Math.max(c.modifiedStart, modifiedEnd));\n\n\t\tif (nonPreviewText.length > 0) {\n\t\t\tconst lines = strings.splitLines(nonPreviewText);\n\t\t\tparts.push(new GhostTextPart(insertColumn, lines, false));\n\t\t}\n\t\tif (italicText.length > 0) {\n\t\t\tconst lines = strings.splitLines(italicText);\n\t\t\tparts.push(new GhostTextPart(insertColumn, lines, true));\n\t\t}\n\t}\n\n\treturn new GhostText(lineNumber, parts, 0);\n}\n\nlet lastRequest: { originalValue: string; newValue: string; changes: readonly IDiffChange[] | undefined; } | undefined = undefined;\nfunction cachingDiff(originalValue: string, newValue: string): readonly IDiffChange[] | undefined {\n\tif (lastRequest?.originalValue === originalValue && lastRequest?.newValue === newValue) {\n\t\treturn lastRequest?.changes;\n\t} else {\n\t\tconst changes = smartDiff(originalValue, newValue);\n\t\tlastRequest = {\n\t\t\toriginalValue,\n\t\t\tnewValue,\n\t\t\tchanges\n\t\t};\n\t\treturn changes;\n\t}\n}\n\n/**\n * When matching `if ()` with `if (f() = 1) { g(); }`,\n * align it like this: `if ( )`\n * Not like this:\t\t\t `if ( )`\n * Also not like this:\t\t `if ( )`.\n *\n * The parenthesis are preprocessed to ensure that they match correctly.\n */\nfunction smartDiff(originalValue: string, newValue: string): (readonly IDiffChange[]) | undefined {\n\tif (originalValue.length > 5000 || newValue.length > 5000) {\n\t\t// We don't want to work on strings that are too big\n\t\treturn undefined;\n\t}\n\n\tfunction getMaxCharCode(val: string): number {\n\t\tlet maxCharCode = 0;\n\t\tfor (let i = 0, len = val.length; i < len; i++) {\n\t\t\tconst charCode = val.charCodeAt(i);\n\t\t\tif (charCode > maxCharCode) {\n\t\t\t\tmaxCharCode = charCode;\n\t\t\t}\n\t\t}\n\t\treturn maxCharCode;\n\t}\n\n\tconst maxCharCode = Math.max(getMaxCharCode(originalValue), getMaxCharCode(newValue));\n\tfunction getUniqueCharCode(id: number): number {\n\t\tif (id < 0) {\n\t\t\tthrow new Error('unexpected');\n\t\t}\n\t\treturn maxCharCode + id + 1;\n\t}\n\n\tfunction getElements(source: string): Int32Array {\n\t\tlet level = 0;\n\t\tlet group = 0;\n\t\tconst characters = new Int32Array(source.length);\n\t\tfor (let i = 0, len = source.length; i < len; i++) {\n\t\t\tconst id = group * 100 + level;\n\n\t\t\t// TODO support more brackets\n\t\t\tif (source[i] === '(') {\n\t\t\t\tcharacters[i] = getUniqueCharCode(2 * id);\n\t\t\t\tlevel++;\n\t\t\t} else if (source[i] === ')') {\n\t\t\t\tcharacters[i] = getUniqueCharCode(2 * id + 1);\n\t\t\t\tif (level === 1) {\n\t\t\t\t\tgroup++;\n\t\t\t\t}\n\t\t\t\tlevel = Math.max(level - 1, 0);\n\t\t\t} else {\n\t\t\t\tcharacters[i] = source.charCodeAt(i);\n\t\t\t}\n\t\t}\n\t\treturn characters;\n\t}\n\n\tconst elements1 = getElements(originalValue);\n\tconst elements2 = getElements(newValue);\n\n\treturn new LcsDiff({ getElements: () => elements1 }, { getElements: () => elements2 }).ComputeDiff(false).changes;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDisposable, IReference } from 'vs/base/common/lifecycle';\n\nexport function createDisposableRef(object: T, disposable?: IDisposable): IReference {\n\treturn {\n\t\tobject,\n\t\tdispose: () => disposable?.dispose(),\n\t};\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection, SelectionDirection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { ITextModel } from 'vs/editor/common/model';\n\nexport class CopyLinesCommand implements ICommand {\n\n\tprivate readonly _selection: Selection;\n\tprivate readonly _isCopyingDown: boolean;\n\tprivate readonly _noop: boolean;\n\n\tprivate _selectionDirection: SelectionDirection;\n\tprivate _selectionId: string | null;\n\tprivate _startLineNumberDelta: number;\n\tprivate _endLineNumberDelta: number;\n\n\tconstructor(selection: Selection, isCopyingDown: boolean, noop?: boolean) {\n\t\tthis._selection = selection;\n\t\tthis._isCopyingDown = isCopyingDown;\n\t\tthis._noop = noop || false;\n\t\tthis._selectionDirection = SelectionDirection.LTR;\n\t\tthis._selectionId = null;\n\t\tthis._startLineNumberDelta = 0;\n\t\tthis._endLineNumberDelta = 0;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tlet s = this._selection;\n\n\t\tthis._startLineNumberDelta = 0;\n\t\tthis._endLineNumberDelta = 0;\n\t\tif (s.startLineNumber < s.endLineNumber && s.endColumn === 1) {\n\t\t\tthis._endLineNumberDelta = 1;\n\t\t\ts = s.setEndPosition(s.endLineNumber - 1, model.getLineMaxColumn(s.endLineNumber - 1));\n\t\t}\n\n\t\tlet sourceLines: string[] = [];\n\t\tfor (let i = s.startLineNumber; i <= s.endLineNumber; i++) {\n\t\t\tsourceLines.push(model.getLineContent(i));\n\t\t}\n\t\tconst sourceText = sourceLines.join('\\n');\n\n\t\tif (sourceText === '') {\n\t\t\t// Duplicating empty line\n\t\t\tif (this._isCopyingDown) {\n\t\t\t\tthis._startLineNumberDelta++;\n\t\t\t\tthis._endLineNumberDelta++;\n\t\t\t}\n\t\t}\n\n\t\tif (this._noop) {\n\t\t\tbuilder.addEditOperation(new Range(s.endLineNumber, model.getLineMaxColumn(s.endLineNumber), s.endLineNumber + 1, 1), s.endLineNumber === model.getLineCount() ? '' : '\\n');\n\t\t} else {\n\t\t\tif (!this._isCopyingDown) {\n\t\t\t\tbuilder.addEditOperation(new Range(s.endLineNumber, model.getLineMaxColumn(s.endLineNumber), s.endLineNumber, model.getLineMaxColumn(s.endLineNumber)), '\\n' + sourceText);\n\t\t\t} else {\n\t\t\t\tbuilder.addEditOperation(new Range(s.startLineNumber, 1, s.startLineNumber, 1), sourceText + '\\n');\n\t\t\t}\n\t\t}\n\n\t\tthis._selectionId = builder.trackSelection(s);\n\t\tthis._selectionDirection = this._selection.getDirection();\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tlet result = helper.getTrackedSelection(this._selectionId!);\n\n\t\tif (this._startLineNumberDelta !== 0 || this._endLineNumberDelta !== 0) {\n\t\t\tlet startLineNumber = result.startLineNumber;\n\t\t\tlet startColumn = result.startColumn;\n\t\t\tlet endLineNumber = result.endLineNumber;\n\t\t\tlet endColumn = result.endColumn;\n\n\t\t\tif (this._startLineNumberDelta !== 0) {\n\t\t\t\tstartLineNumber = startLineNumber + this._startLineNumberDelta;\n\t\t\t\tstartColumn = 1;\n\t\t\t}\n\n\t\t\tif (this._endLineNumberDelta !== 0) {\n\t\t\t\tendLineNumber = endLineNumber + this._endLineNumberDelta;\n\t\t\t\tendColumn = 1;\n\t\t\t}\n\n\t\t\tresult = Selection.createWithDirection(startLineNumber, startColumn, endLineNumber, endColumn, this._selectionDirection);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { EditOperation } from 'vs/editor/common/core/editOperation';\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model';\n\nexport class SortLinesCommand implements ICommand {\n\n\tprivate static _COLLATOR: Intl.Collator | null = null;\n\tpublic static getCollator(): Intl.Collator {\n\t\tif (!SortLinesCommand._COLLATOR) {\n\t\t\tSortLinesCommand._COLLATOR = new Intl.Collator();\n\t\t}\n\t\treturn SortLinesCommand._COLLATOR;\n\t}\n\n\tprivate readonly selection: Selection;\n\tprivate readonly descending: boolean;\n\tprivate selectionId: string | null;\n\n\tconstructor(selection: Selection, descending: boolean) {\n\t\tthis.selection = selection;\n\t\tthis.descending = descending;\n\t\tthis.selectionId = null;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tlet op = sortLines(model, this.selection, this.descending);\n\t\tif (op) {\n\t\t\tbuilder.addEditOperation(op.range, op.text);\n\t\t}\n\n\t\tthis.selectionId = builder.trackSelection(this.selection);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\treturn helper.getTrackedSelection(this.selectionId!);\n\t}\n\n\tpublic static canRun(model: ITextModel | null, selection: Selection, descending: boolean): boolean {\n\t\tif (model === null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet data = getSortData(model, selection, descending);\n\n\t\tif (!data) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = 0, len = data.before.length; i < len; i++) {\n\t\t\tif (data.before[i] !== data.after[i]) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n}\n\nfunction getSortData(model: ITextModel, selection: Selection, descending: boolean) {\n\tlet startLineNumber = selection.startLineNumber;\n\tlet endLineNumber = selection.endLineNumber;\n\n\tif (selection.endColumn === 1) {\n\t\tendLineNumber--;\n\t}\n\n\t// Nothing to sort if user didn't select anything.\n\tif (startLineNumber >= endLineNumber) {\n\t\treturn null;\n\t}\n\n\tlet linesToSort: string[] = [];\n\n\t// Get the contents of the selection to be sorted.\n\tfor (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n\t\tlinesToSort.push(model.getLineContent(lineNumber));\n\t}\n\n\tlet sorted = linesToSort.slice(0);\n\tsorted.sort(SortLinesCommand.getCollator().compare);\n\n\t// If descending, reverse the order.\n\tif (descending === true) {\n\t\tsorted = sorted.reverse();\n\t}\n\n\treturn {\n\t\tstartLineNumber: startLineNumber,\n\t\tendLineNumber: endLineNumber,\n\t\tbefore: linesToSort,\n\t\tafter: sorted\n\t};\n}\n\n/**\n * Generate commands for sorting lines on a model.\n */\nfunction sortLines(model: ITextModel, selection: Selection, descending: boolean): IIdentifiedSingleEditOperation | null {\n\tlet data = getSortData(model, selection, descending);\n\n\tif (!data) {\n\t\treturn null;\n\t}\n\n\treturn EditOperation.replace(\n\t\tnew Range(data.startLineNumber, 1, data.endLineNumber, model.getLineMaxColumn(data.endLineNumber)),\n\t\tdata.after.join('\\n')\n\t);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { LinkedList } from 'vs/base/common/linkedList';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { SelectionRange, SelectionRangeProvider } from 'vs/editor/common/languages';\n\nexport class BracketSelectionRangeProvider implements SelectionRangeProvider {\n\n\tasync provideSelectionRanges(model: ITextModel, positions: Position[]): Promise {\n\t\tconst result: SelectionRange[][] = [];\n\n\t\tfor (const position of positions) {\n\t\t\tconst bucket: SelectionRange[] = [];\n\t\t\tresult.push(bucket);\n\n\t\t\tconst ranges = new Map>();\n\t\t\tawait new Promise(resolve => BracketSelectionRangeProvider._bracketsRightYield(resolve, 0, model, position, ranges));\n\t\t\tawait new Promise(resolve => BracketSelectionRangeProvider._bracketsLeftYield(resolve, 0, model, position, ranges, bucket));\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tpublic static _maxDuration = 30;\n\tprivate static readonly _maxRounds = 2;\n\n\tprivate static _bracketsRightYield(resolve: () => void, round: number, model: ITextModel, pos: Position, ranges: Map>): void {\n\t\tconst counts = new Map();\n\t\tconst t1 = Date.now();\n\t\twhile (true) {\n\t\t\tif (round >= BracketSelectionRangeProvider._maxRounds) {\n\t\t\t\tresolve();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!pos) {\n\t\t\t\tresolve();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlet bracket = model.bracketPairs.findNextBracket(pos);\n\t\t\tif (!bracket) {\n\t\t\t\tresolve();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlet d = Date.now() - t1;\n\t\t\tif (d > BracketSelectionRangeProvider._maxDuration) {\n\t\t\t\tsetTimeout(() => BracketSelectionRangeProvider._bracketsRightYield(resolve, round + 1, model, pos, ranges));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst key = bracket.close[0];\n\t\t\tif (bracket.isOpen) {\n\t\t\t\t// wait for closing\n\t\t\t\tlet val = counts.has(key) ? counts.get(key)! : 0;\n\t\t\t\tcounts.set(key, val + 1);\n\t\t\t} else {\n\t\t\t\t// process closing\n\t\t\t\tlet val = counts.has(key) ? counts.get(key)! : 0;\n\t\t\t\tval -= 1;\n\t\t\t\tcounts.set(key, Math.max(0, val));\n\t\t\t\tif (val < 0) {\n\t\t\t\t\tlet list = ranges.get(key);\n\t\t\t\t\tif (!list) {\n\t\t\t\t\t\tlist = new LinkedList();\n\t\t\t\t\t\tranges.set(key, list);\n\t\t\t\t\t}\n\t\t\t\t\tlist.push(bracket.range);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpos = bracket.range.getEndPosition();\n\t\t}\n\t}\n\n\tprivate static _bracketsLeftYield(resolve: () => void, round: number, model: ITextModel, pos: Position, ranges: Map>, bucket: SelectionRange[]): void {\n\t\tconst counts = new Map();\n\t\tconst t1 = Date.now();\n\t\twhile (true) {\n\t\t\tif (round >= BracketSelectionRangeProvider._maxRounds && ranges.size === 0) {\n\t\t\t\tresolve();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!pos) {\n\t\t\t\tresolve();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlet bracket = model.bracketPairs.findPrevBracket(pos);\n\t\t\tif (!bracket) {\n\t\t\t\tresolve();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlet d = Date.now() - t1;\n\t\t\tif (d > BracketSelectionRangeProvider._maxDuration) {\n\t\t\t\tsetTimeout(() => BracketSelectionRangeProvider._bracketsLeftYield(resolve, round + 1, model, pos, ranges, bucket));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst key = bracket.close[0];\n\t\t\tif (!bracket.isOpen) {\n\t\t\t\t// wait for opening\n\t\t\t\tlet val = counts.has(key) ? counts.get(key)! : 0;\n\t\t\t\tcounts.set(key, val + 1);\n\t\t\t} else {\n\t\t\t\t// opening\n\t\t\t\tlet val = counts.has(key) ? counts.get(key)! : 0;\n\t\t\t\tval -= 1;\n\t\t\t\tcounts.set(key, Math.max(0, val));\n\t\t\t\tif (val < 0) {\n\t\t\t\t\tlet list = ranges.get(key);\n\t\t\t\t\tif (list) {\n\t\t\t\t\t\tlet closing = list.shift();\n\t\t\t\t\t\tif (list.size === 0) {\n\t\t\t\t\t\t\tranges.delete(key);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst innerBracket = Range.fromPositions(bracket.range.getEndPosition(), closing!.getStartPosition());\n\t\t\t\t\t\tconst outerBracket = Range.fromPositions(bracket.range.getStartPosition(), closing!.getEndPosition());\n\t\t\t\t\t\tbucket.push({ range: innerBracket });\n\t\t\t\t\t\tbucket.push({ range: outerBracket });\n\t\t\t\t\t\tBracketSelectionRangeProvider._addBracketLeading(model, outerBracket, bucket);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tpos = bracket.range.getStartPosition();\n\t\t}\n\t}\n\n\tprivate static _addBracketLeading(model: ITextModel, bracket: Range, bucket: SelectionRange[]): void {\n\t\tif (bracket.startLineNumber === bracket.endLineNumber) {\n\t\t\treturn;\n\t\t}\n\t\t// xxxxxxxx {\n\t\t//\n\t\t// }\n\t\tconst startLine = bracket.startLineNumber;\n\t\tconst column = model.getLineFirstNonWhitespaceColumn(startLine);\n\t\tif (column !== 0 && column !== bracket.startColumn) {\n\t\t\tbucket.push({ range: Range.fromPositions(new Position(startLine, column), bracket.getEndPosition()) });\n\t\t\tbucket.push({ range: Range.fromPositions(new Position(startLine, 1), bracket.getEndPosition()) });\n\t\t}\n\n\t\t// xxxxxxxx\n\t\t// {\n\t\t//\n\t\t// }\n\t\tconst aboveLine = startLine - 1;\n\t\tif (aboveLine > 0) {\n\t\t\tconst column = model.getLineFirstNonWhitespaceColumn(aboveLine);\n\t\t\tif (column === bracket.startColumn && column !== model.getLineLastNonWhitespaceColumn(aboveLine)) {\n\t\t\t\tbucket.push({ range: Range.fromPositions(new Position(aboveLine, column), bracket.getEndPosition()) });\n\t\t\t\tbucket.push({ range: Range.fromPositions(new Position(aboveLine, 1), bracket.getEndPosition()) });\n\t\t\t}\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { isLowerAsciiLetter, isUpperAsciiLetter } from 'vs/base/common/strings';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { SelectionRange, SelectionRangeProvider } from 'vs/editor/common/languages';\n\nexport class WordSelectionRangeProvider implements SelectionRangeProvider {\n\n\tprovideSelectionRanges(model: ITextModel, positions: Position[]): SelectionRange[][] {\n\t\tconst result: SelectionRange[][] = [];\n\t\tfor (const position of positions) {\n\t\t\tconst bucket: SelectionRange[] = [];\n\t\t\tresult.push(bucket);\n\t\t\tthis._addInWordRanges(bucket, model, position);\n\t\t\tthis._addWordRanges(bucket, model, position);\n\t\t\tthis._addWhitespaceLine(bucket, model, position);\n\t\t\tbucket.push({ range: model.getFullModelRange() });\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate _addInWordRanges(bucket: SelectionRange[], model: ITextModel, pos: Position): void {\n\t\tconst obj = model.getWordAtPosition(pos);\n\t\tif (!obj) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet { word, startColumn } = obj;\n\t\tlet offset = pos.column - startColumn;\n\t\tlet start = offset;\n\t\tlet end = offset;\n\t\tlet lastCh: number = 0;\n\n\t\t// LEFT anchor (start)\n\t\tfor (; start >= 0; start--) {\n\t\t\tlet ch = word.charCodeAt(start);\n\t\t\tif ((start !== offset) && (ch === CharCode.Underline || ch === CharCode.Dash)) {\n\t\t\t\t// foo-bar OR foo_bar\n\t\t\t\tbreak;\n\t\t\t} else if (isLowerAsciiLetter(ch) && isUpperAsciiLetter(lastCh)) {\n\t\t\t\t// fooBar\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlastCh = ch;\n\t\t}\n\t\tstart += 1;\n\n\t\t// RIGHT anchor (end)\n\t\tfor (; end < word.length; end++) {\n\t\t\tlet ch = word.charCodeAt(end);\n\t\t\tif (isUpperAsciiLetter(ch) && isLowerAsciiLetter(lastCh)) {\n\t\t\t\t// fooBar\n\t\t\t\tbreak;\n\t\t\t} else if (ch === CharCode.Underline || ch === CharCode.Dash) {\n\t\t\t\t// foo-bar OR foo_bar\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlastCh = ch;\n\t\t}\n\n\t\tif (start < end) {\n\t\t\tbucket.push({ range: new Range(pos.lineNumber, startColumn + start, pos.lineNumber, startColumn + end) });\n\t\t}\n\t}\n\n\tprivate _addWordRanges(bucket: SelectionRange[], model: ITextModel, pos: Position): void {\n\t\tconst word = model.getWordAtPosition(pos);\n\t\tif (word) {\n\t\t\tbucket.push({ range: new Range(pos.lineNumber, word.startColumn, pos.lineNumber, word.endColumn) });\n\t\t}\n\t}\n\n\tprivate _addWhitespaceLine(bucket: SelectionRange[], model: ITextModel, pos: Position): void {\n\t\tif (model.getLineLength(pos.lineNumber) > 0\n\t\t\t&& model.getLineFirstNonWhitespaceColumn(pos.lineNumber) === 0\n\t\t\t&& model.getLineLastNonWhitespaceColumn(pos.lineNumber) === 0\n\t\t) {\n\t\t\tbucket.push({ range: new Range(pos.lineNumber, 1, pos.lineNumber, model.getLineMaxColumn(pos.lineNumber)) });\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\n\nexport const enum TokenType {\n\tDollar,\n\tColon,\n\tComma,\n\tCurlyOpen,\n\tCurlyClose,\n\tBackslash,\n\tForwardslash,\n\tPipe,\n\tInt,\n\tVariableName,\n\tFormat,\n\tPlus,\n\tDash,\n\tQuestionMark,\n\tEOF\n}\n\nexport interface Token {\n\ttype: TokenType;\n\tpos: number;\n\tlen: number;\n}\n\n\nexport class Scanner {\n\n\tprivate static _table: { [ch: number]: TokenType } = {\n\t\t[CharCode.DollarSign]: TokenType.Dollar,\n\t\t[CharCode.Colon]: TokenType.Colon,\n\t\t[CharCode.Comma]: TokenType.Comma,\n\t\t[CharCode.OpenCurlyBrace]: TokenType.CurlyOpen,\n\t\t[CharCode.CloseCurlyBrace]: TokenType.CurlyClose,\n\t\t[CharCode.Backslash]: TokenType.Backslash,\n\t\t[CharCode.Slash]: TokenType.Forwardslash,\n\t\t[CharCode.Pipe]: TokenType.Pipe,\n\t\t[CharCode.Plus]: TokenType.Plus,\n\t\t[CharCode.Dash]: TokenType.Dash,\n\t\t[CharCode.QuestionMark]: TokenType.QuestionMark,\n\t};\n\n\tstatic isDigitCharacter(ch: number): boolean {\n\t\treturn ch >= CharCode.Digit0 && ch <= CharCode.Digit9;\n\t}\n\n\tstatic isVariableCharacter(ch: number): boolean {\n\t\treturn ch === CharCode.Underline\n\t\t\t|| (ch >= CharCode.a && ch <= CharCode.z)\n\t\t\t|| (ch >= CharCode.A && ch <= CharCode.Z);\n\t}\n\n\tvalue: string = '';\n\tpos: number = 0;\n\n\ttext(value: string) {\n\t\tthis.value = value;\n\t\tthis.pos = 0;\n\t}\n\n\ttokenText(token: Token): string {\n\t\treturn this.value.substr(token.pos, token.len);\n\t}\n\n\tnext(): Token {\n\n\t\tif (this.pos >= this.value.length) {\n\t\t\treturn { type: TokenType.EOF, pos: this.pos, len: 0 };\n\t\t}\n\n\t\tlet pos = this.pos;\n\t\tlet len = 0;\n\t\tlet ch = this.value.charCodeAt(pos);\n\t\tlet type: TokenType;\n\n\t\t// static types\n\t\ttype = Scanner._table[ch];\n\t\tif (typeof type === 'number') {\n\t\t\tthis.pos += 1;\n\t\t\treturn { type, pos, len: 1 };\n\t\t}\n\n\t\t// number\n\t\tif (Scanner.isDigitCharacter(ch)) {\n\t\t\ttype = TokenType.Int;\n\t\t\tdo {\n\t\t\t\tlen += 1;\n\t\t\t\tch = this.value.charCodeAt(pos + len);\n\t\t\t} while (Scanner.isDigitCharacter(ch));\n\n\t\t\tthis.pos += len;\n\t\t\treturn { type, pos, len };\n\t\t}\n\n\t\t// variable name\n\t\tif (Scanner.isVariableCharacter(ch)) {\n\t\t\ttype = TokenType.VariableName;\n\t\t\tdo {\n\t\t\t\tch = this.value.charCodeAt(pos + (++len));\n\t\t\t} while (Scanner.isVariableCharacter(ch) || Scanner.isDigitCharacter(ch));\n\n\t\t\tthis.pos += len;\n\t\t\treturn { type, pos, len };\n\t\t}\n\n\n\t\t// format\n\t\ttype = TokenType.Format;\n\t\tdo {\n\t\t\tlen += 1;\n\t\t\tch = this.value.charCodeAt(pos + len);\n\t\t} while (\n\t\t\t!isNaN(ch)\n\t\t\t&& typeof Scanner._table[ch] === 'undefined' // not static token\n\t\t\t&& !Scanner.isDigitCharacter(ch) // not number\n\t\t\t&& !Scanner.isVariableCharacter(ch) // not variable\n\t\t);\n\n\t\tthis.pos += len;\n\t\treturn { type, pos, len };\n\t}\n}\n\nexport abstract class Marker {\n\n\treadonly _markerBrand: any;\n\n\tpublic parent!: Marker;\n\tprotected _children: Marker[] = [];\n\n\tappendChild(child: Marker): this {\n\t\tif (child instanceof Text && this._children[this._children.length - 1] instanceof Text) {\n\t\t\t// this and previous child are text -> merge them\n\t\t\t(this._children[this._children.length - 1]).value += child.value;\n\t\t} else {\n\t\t\t// normal adoption of child\n\t\t\tchild.parent = this;\n\t\t\tthis._children.push(child);\n\t\t}\n\t\treturn this;\n\t}\n\n\treplace(child: Marker, others: Marker[]): void {\n\t\tconst { parent } = child;\n\t\tconst idx = parent.children.indexOf(child);\n\t\tconst newChildren = parent.children.slice(0);\n\t\tnewChildren.splice(idx, 1, ...others);\n\t\tparent._children = newChildren;\n\n\t\t(function _fixParent(children: Marker[], parent: Marker) {\n\t\t\tfor (const child of children) {\n\t\t\t\tchild.parent = parent;\n\t\t\t\t_fixParent(child.children, child);\n\t\t\t}\n\t\t})(others, parent);\n\t}\n\n\tget children(): Marker[] {\n\t\treturn this._children;\n\t}\n\n\tget snippet(): TextmateSnippet | undefined {\n\t\tlet candidate: Marker = this;\n\t\twhile (true) {\n\t\t\tif (!candidate) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (candidate instanceof TextmateSnippet) {\n\t\t\t\treturn candidate;\n\t\t\t}\n\t\t\tcandidate = candidate.parent;\n\t\t}\n\t}\n\n\ttoString(): string {\n\t\treturn this.children.reduce((prev, cur) => prev + cur.toString(), '');\n\t}\n\n\tlen(): number {\n\t\treturn 0;\n\t}\n\n\tabstract clone(): Marker;\n}\n\nexport class Text extends Marker {\n\n\tconstructor(public value: string) {\n\t\tsuper();\n\t}\n\toverride toString() {\n\t\treturn this.value;\n\t}\n\toverride len(): number {\n\t\treturn this.value.length;\n\t}\n\tclone(): Text {\n\t\treturn new Text(this.value);\n\t}\n}\n\nexport abstract class TransformableMarker extends Marker {\n\tpublic transform?: Transform;\n}\n\nexport class Placeholder extends TransformableMarker {\n\tstatic compareByIndex(a: Placeholder, b: Placeholder): number {\n\t\tif (a.index === b.index) {\n\t\t\treturn 0;\n\t\t} else if (a.isFinalTabstop) {\n\t\t\treturn 1;\n\t\t} else if (b.isFinalTabstop) {\n\t\t\treturn -1;\n\t\t} else if (a.index < b.index) {\n\t\t\treturn -1;\n\t\t} else if (a.index > b.index) {\n\t\t\treturn 1;\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tconstructor(public index: number) {\n\t\tsuper();\n\t}\n\n\tget isFinalTabstop() {\n\t\treturn this.index === 0;\n\t}\n\n\tget choice(): Choice | undefined {\n\t\treturn this._children.length === 1 && this._children[0] instanceof Choice\n\t\t\t? this._children[0] as Choice\n\t\t\t: undefined;\n\t}\n\n\tclone(): Placeholder {\n\t\tlet ret = new Placeholder(this.index);\n\t\tif (this.transform) {\n\t\t\tret.transform = this.transform.clone();\n\t\t}\n\t\tret._children = this.children.map(child => child.clone());\n\t\treturn ret;\n\t}\n}\n\nexport class Choice extends Marker {\n\n\treadonly options: Text[] = [];\n\n\toverride appendChild(marker: Marker): this {\n\t\tif (marker instanceof Text) {\n\t\t\tmarker.parent = this;\n\t\t\tthis.options.push(marker);\n\t\t}\n\t\treturn this;\n\t}\n\n\toverride toString() {\n\t\treturn this.options[0].value;\n\t}\n\n\toverride len(): number {\n\t\treturn this.options[0].len();\n\t}\n\n\tclone(): Choice {\n\t\tlet ret = new Choice();\n\t\tthis.options.forEach(ret.appendChild, ret);\n\t\treturn ret;\n\t}\n}\n\nexport class Transform extends Marker {\n\n\tregexp: RegExp = new RegExp('');\n\n\tresolve(value: string): string {\n\t\tconst _this = this;\n\t\tlet didMatch = false;\n\t\tlet ret = value.replace(this.regexp, function () {\n\t\t\tdidMatch = true;\n\t\t\treturn _this._replace(Array.prototype.slice.call(arguments, 0, -2));\n\t\t});\n\t\t// when the regex didn't match and when the transform has\n\t\t// else branches, then run those\n\t\tif (!didMatch && this._children.some(child => child instanceof FormatString && Boolean(child.elseValue))) {\n\t\t\tret = this._replace([]);\n\t\t}\n\t\treturn ret;\n\t}\n\n\tprivate _replace(groups: string[]): string {\n\t\tlet ret = '';\n\t\tfor (const marker of this._children) {\n\t\t\tif (marker instanceof FormatString) {\n\t\t\t\tlet value = groups[marker.index] || '';\n\t\t\t\tvalue = marker.resolve(value);\n\t\t\t\tret += value;\n\t\t\t} else {\n\t\t\t\tret += marker.toString();\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t}\n\n\toverride toString(): string {\n\t\treturn '';\n\t}\n\n\tclone(): Transform {\n\t\tlet ret = new Transform();\n\t\tret.regexp = new RegExp(this.regexp.source, '' + (this.regexp.ignoreCase ? 'i' : '') + (this.regexp.global ? 'g' : ''));\n\t\tret._children = this.children.map(child => child.clone());\n\t\treturn ret;\n\t}\n\n}\n\nexport class FormatString extends Marker {\n\n\tconstructor(\n\t\treadonly index: number,\n\t\treadonly shorthandName?: string,\n\t\treadonly ifValue?: string,\n\t\treadonly elseValue?: string,\n\t) {\n\t\tsuper();\n\t}\n\n\tresolve(value?: string): string {\n\t\tif (this.shorthandName === 'upcase') {\n\t\t\treturn !value ? '' : value.toLocaleUpperCase();\n\t\t} else if (this.shorthandName === 'downcase') {\n\t\t\treturn !value ? '' : value.toLocaleLowerCase();\n\t\t} else if (this.shorthandName === 'capitalize') {\n\t\t\treturn !value ? '' : (value[0].toLocaleUpperCase() + value.substr(1));\n\t\t} else if (this.shorthandName === 'pascalcase') {\n\t\t\treturn !value ? '' : this._toPascalCase(value);\n\t\t} else if (this.shorthandName === 'camelcase') {\n\t\t\treturn !value ? '' : this._toCamelCase(value);\n\t\t} else if (Boolean(value) && typeof this.ifValue === 'string') {\n\t\t\treturn this.ifValue;\n\t\t} else if (!Boolean(value) && typeof this.elseValue === 'string') {\n\t\t\treturn this.elseValue;\n\t\t} else {\n\t\t\treturn value || '';\n\t\t}\n\t}\n\n\tprivate _toPascalCase(value: string): string {\n\t\tconst match = value.match(/[a-z0-9]+/gi);\n\t\tif (!match) {\n\t\t\treturn value;\n\t\t}\n\t\treturn match.map(word => {\n\t\t\treturn word.charAt(0).toUpperCase()\n\t\t\t\t+ word.substr(1).toLowerCase();\n\t\t})\n\t\t\t.join('');\n\t}\n\n\tprivate _toCamelCase(value: string): string {\n\t\tconst match = value.match(/[a-z0-9]+/gi);\n\t\tif (!match) {\n\t\t\treturn value;\n\t\t}\n\t\treturn match.map((word, index) => {\n\t\t\tif (index === 0) {\n\t\t\t\treturn word.toLowerCase();\n\t\t\t} else {\n\t\t\t\treturn word.charAt(0).toUpperCase()\n\t\t\t\t\t+ word.substr(1).toLowerCase();\n\t\t\t}\n\t\t})\n\t\t\t.join('');\n\t}\n\n\tclone(): FormatString {\n\t\tlet ret = new FormatString(this.index, this.shorthandName, this.ifValue, this.elseValue);\n\t\treturn ret;\n\t}\n}\n\nexport class Variable extends TransformableMarker {\n\n\tconstructor(public name: string) {\n\t\tsuper();\n\t}\n\n\tresolve(resolver: VariableResolver): boolean {\n\t\tlet value = resolver.resolve(this);\n\t\tif (this.transform) {\n\t\t\tvalue = this.transform.resolve(value || '');\n\t\t}\n\t\tif (value !== undefined) {\n\t\t\tthis._children = [new Text(value)];\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tclone(): Variable {\n\t\tconst ret = new Variable(this.name);\n\t\tif (this.transform) {\n\t\t\tret.transform = this.transform.clone();\n\t\t}\n\t\tret._children = this.children.map(child => child.clone());\n\t\treturn ret;\n\t}\n}\n\nexport interface VariableResolver {\n\tresolve(variable: Variable): string | undefined;\n}\n\nfunction walk(marker: Marker[], visitor: (marker: Marker) => boolean): void {\n\tconst stack = [...marker];\n\twhile (stack.length > 0) {\n\t\tconst marker = stack.shift()!;\n\t\tconst recurse = visitor(marker);\n\t\tif (!recurse) {\n\t\t\tbreak;\n\t\t}\n\t\tstack.unshift(...marker.children);\n\t}\n}\n\nexport class TextmateSnippet extends Marker {\n\n\tprivate _placeholders?: { all: Placeholder[], last?: Placeholder };\n\n\tget placeholderInfo() {\n\t\tif (!this._placeholders) {\n\t\t\t// fill in placeholders\n\t\t\tlet all: Placeholder[] = [];\n\t\t\tlet last: Placeholder | undefined;\n\t\t\tthis.walk(function (candidate) {\n\t\t\t\tif (candidate instanceof Placeholder) {\n\t\t\t\t\tall.push(candidate);\n\t\t\t\t\tlast = !last || last.index < candidate.index ? candidate : last;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t});\n\t\t\tthis._placeholders = { all, last };\n\t\t}\n\t\treturn this._placeholders;\n\t}\n\n\tget placeholders(): Placeholder[] {\n\t\tconst { all } = this.placeholderInfo;\n\t\treturn all;\n\t}\n\n\toffset(marker: Marker): number {\n\t\tlet pos = 0;\n\t\tlet found = false;\n\t\tthis.walk(candidate => {\n\t\t\tif (candidate === marker) {\n\t\t\t\tfound = true;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tpos += candidate.len();\n\t\t\treturn true;\n\t\t});\n\n\t\tif (!found) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn pos;\n\t}\n\n\tfullLen(marker: Marker): number {\n\t\tlet ret = 0;\n\t\twalk([marker], marker => {\n\t\t\tret += marker.len();\n\t\t\treturn true;\n\t\t});\n\t\treturn ret;\n\t}\n\n\tenclosingPlaceholders(placeholder: Placeholder): Placeholder[] {\n\t\tlet ret: Placeholder[] = [];\n\t\tlet { parent } = placeholder;\n\t\twhile (parent) {\n\t\t\tif (parent instanceof Placeholder) {\n\t\t\t\tret.push(parent);\n\t\t\t}\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn ret;\n\t}\n\n\tresolveVariables(resolver: VariableResolver): this {\n\t\tthis.walk(candidate => {\n\t\t\tif (candidate instanceof Variable) {\n\t\t\t\tif (candidate.resolve(resolver)) {\n\t\t\t\t\tthis._placeholders = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t});\n\t\treturn this;\n\t}\n\n\toverride appendChild(child: Marker) {\n\t\tthis._placeholders = undefined;\n\t\treturn super.appendChild(child);\n\t}\n\n\toverride replace(child: Marker, others: Marker[]): void {\n\t\tthis._placeholders = undefined;\n\t\treturn super.replace(child, others);\n\t}\n\n\tclone(): TextmateSnippet {\n\t\tlet ret = new TextmateSnippet();\n\t\tthis._children = this.children.map(child => child.clone());\n\t\treturn ret;\n\t}\n\n\twalk(visitor: (marker: Marker) => boolean): void {\n\t\twalk(this.children, visitor);\n\t}\n}\n\nexport class SnippetParser {\n\n\tstatic escape(value: string): string {\n\t\treturn value.replace(/\\$|}|\\\\/g, '\\\\$&');\n\t}\n\n\tstatic guessNeedsClipboard(template: string): boolean {\n\t\treturn /\\${?CLIPBOARD/.test(template);\n\t}\n\n\tprivate _scanner: Scanner = new Scanner();\n\tprivate _token: Token = { type: TokenType.EOF, pos: 0, len: 0 };\n\n\tparse(value: string, insertFinalTabstop?: boolean, enforceFinalTabstop?: boolean): TextmateSnippet {\n\n\t\tthis._scanner.text(value);\n\t\tthis._token = this._scanner.next();\n\n\t\tconst snippet = new TextmateSnippet();\n\t\twhile (this._parse(snippet)) {\n\t\t\t// nothing\n\t\t}\n\n\t\t// fill in values for placeholders. the first placeholder of an index\n\t\t// that has a value defines the value for all placeholders with that index\n\t\tconst placeholderDefaultValues = new Map();\n\t\tconst incompletePlaceholders: Placeholder[] = [];\n\t\tlet placeholderCount = 0;\n\t\tsnippet.walk(marker => {\n\t\t\tif (marker instanceof Placeholder) {\n\t\t\t\tplaceholderCount += 1;\n\t\t\t\tif (marker.isFinalTabstop) {\n\t\t\t\t\tplaceholderDefaultValues.set(0, undefined);\n\t\t\t\t} else if (!placeholderDefaultValues.has(marker.index) && marker.children.length > 0) {\n\t\t\t\t\tplaceholderDefaultValues.set(marker.index, marker.children);\n\t\t\t\t} else {\n\t\t\t\t\tincompletePlaceholders.push(marker);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t});\n\t\tfor (const placeholder of incompletePlaceholders) {\n\t\t\tconst defaultValues = placeholderDefaultValues.get(placeholder.index);\n\t\t\tif (defaultValues) {\n\t\t\t\tconst clone = new Placeholder(placeholder.index);\n\t\t\t\tclone.transform = placeholder.transform;\n\t\t\t\tfor (const child of defaultValues) {\n\t\t\t\t\tclone.appendChild(child.clone());\n\t\t\t\t}\n\t\t\t\tsnippet.replace(placeholder, [clone]);\n\t\t\t}\n\t\t}\n\n\t\tif (!enforceFinalTabstop) {\n\t\t\tenforceFinalTabstop = placeholderCount > 0 && insertFinalTabstop;\n\t\t}\n\n\t\tif (!placeholderDefaultValues.has(0) && enforceFinalTabstop) {\n\t\t\t// the snippet uses placeholders but has no\n\t\t\t// final tabstop defined -> insert at the end\n\t\t\tsnippet.appendChild(new Placeholder(0));\n\t\t}\n\n\t\treturn snippet;\n\t}\n\n\tprivate _accept(type?: TokenType): boolean;\n\tprivate _accept(type: TokenType | undefined, value: true): string;\n\tprivate _accept(type: TokenType, value?: boolean): boolean | string {\n\t\tif (type === undefined || this._token.type === type) {\n\t\t\tlet ret = !value ? true : this._scanner.tokenText(this._token);\n\t\t\tthis._token = this._scanner.next();\n\t\t\treturn ret;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate _backTo(token: Token): false {\n\t\tthis._scanner.pos = token.pos + token.len;\n\t\tthis._token = token;\n\t\treturn false;\n\t}\n\n\tprivate _until(type: TokenType): false | string {\n\t\tconst start = this._token;\n\t\twhile (this._token.type !== type) {\n\t\t\tif (this._token.type === TokenType.EOF) {\n\t\t\t\treturn false;\n\t\t\t} else if (this._token.type === TokenType.Backslash) {\n\t\t\t\tconst nextToken = this._scanner.next();\n\t\t\t\tif (nextToken.type !== TokenType.Dollar\n\t\t\t\t\t&& nextToken.type !== TokenType.CurlyClose\n\t\t\t\t\t&& nextToken.type !== TokenType.Backslash) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._token = this._scanner.next();\n\t\t}\n\t\tconst value = this._scanner.value.substring(start.pos, this._token.pos).replace(/\\\\(\\$|}|\\\\)/g, '$1');\n\t\tthis._token = this._scanner.next();\n\t\treturn value;\n\t}\n\n\tprivate _parse(marker: Marker): boolean {\n\t\treturn this._parseEscaped(marker)\n\t\t\t|| this._parseTabstopOrVariableName(marker)\n\t\t\t|| this._parseComplexPlaceholder(marker)\n\t\t\t|| this._parseComplexVariable(marker)\n\t\t\t|| this._parseAnything(marker);\n\t}\n\n\t// \\$, \\\\, \\} -> just text\n\tprivate _parseEscaped(marker: Marker): boolean {\n\t\tlet value: string;\n\t\tif (value = this._accept(TokenType.Backslash, true)) {\n\t\t\t// saw a backslash, append escaped token or that backslash\n\t\t\tvalue = this._accept(TokenType.Dollar, true)\n\t\t\t\t|| this._accept(TokenType.CurlyClose, true)\n\t\t\t\t|| this._accept(TokenType.Backslash, true)\n\t\t\t\t|| value;\n\n\t\t\tmarker.appendChild(new Text(value));\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t// $foo -> variable, $1 -> tabstop\n\tprivate _parseTabstopOrVariableName(parent: Marker): boolean {\n\t\tlet value: string;\n\t\tconst token = this._token;\n\t\tconst match = this._accept(TokenType.Dollar)\n\t\t\t&& (value = this._accept(TokenType.VariableName, true) || this._accept(TokenType.Int, true));\n\n\t\tif (!match) {\n\t\t\treturn this._backTo(token);\n\t\t}\n\n\t\tparent.appendChild(/^\\d+$/.test(value!)\n\t\t\t? new Placeholder(Number(value!))\n\t\t\t: new Variable(value!)\n\t\t);\n\t\treturn true;\n\t}\n\n\t// ${1:}, ${1} -> placeholder\n\tprivate _parseComplexPlaceholder(parent: Marker): boolean {\n\t\tlet index: string;\n\t\tconst token = this._token;\n\t\tconst match = this._accept(TokenType.Dollar)\n\t\t\t&& this._accept(TokenType.CurlyOpen)\n\t\t\t&& (index = this._accept(TokenType.Int, true));\n\n\t\tif (!match) {\n\t\t\treturn this._backTo(token);\n\t\t}\n\n\t\tconst placeholder = new Placeholder(Number(index!));\n\n\t\tif (this._accept(TokenType.Colon)) {\n\t\t\t// ${1:}\n\t\t\twhile (true) {\n\n\t\t\t\t// ...} -> done\n\t\t\t\tif (this._accept(TokenType.CurlyClose)) {\n\t\t\t\t\tparent.appendChild(placeholder);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tif (this._parse(placeholder)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// fallback\n\t\t\t\tparent.appendChild(new Text('${' + index! + ':'));\n\t\t\t\tplaceholder.children.forEach(parent.appendChild, parent);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else if (placeholder.index > 0 && this._accept(TokenType.Pipe)) {\n\t\t\t// ${1|one,two,three|}\n\t\t\tconst choice = new Choice();\n\n\t\t\twhile (true) {\n\t\t\t\tif (this._parseChoiceElement(choice)) {\n\n\t\t\t\t\tif (this._accept(TokenType.Comma)) {\n\t\t\t\t\t\t// opt, -> more\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this._accept(TokenType.Pipe)) {\n\t\t\t\t\t\tplaceholder.appendChild(choice);\n\t\t\t\t\t\tif (this._accept(TokenType.CurlyClose)) {\n\t\t\t\t\t\t\t// ..|} -> done\n\t\t\t\t\t\t\tparent.appendChild(placeholder);\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis._backTo(token);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t} else if (this._accept(TokenType.Forwardslash)) {\n\t\t\t// ${1///}\n\t\t\tif (this._parseTransform(placeholder)) {\n\t\t\t\tparent.appendChild(placeholder);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tthis._backTo(token);\n\t\t\treturn false;\n\n\t\t} else if (this._accept(TokenType.CurlyClose)) {\n\t\t\t// ${1}\n\t\t\tparent.appendChild(placeholder);\n\t\t\treturn true;\n\n\t\t} else {\n\t\t\t// ${1 <- missing curly or colon\n\t\t\treturn this._backTo(token);\n\t\t}\n\t}\n\n\tprivate _parseChoiceElement(parent: Choice): boolean {\n\t\tconst token = this._token;\n\t\tconst values: string[] = [];\n\n\t\twhile (true) {\n\t\t\tif (this._token.type === TokenType.Comma || this._token.type === TokenType.Pipe) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlet value: string;\n\t\t\tif (value = this._accept(TokenType.Backslash, true)) {\n\t\t\t\t// \\, \\|, or \\\\\n\t\t\t\tvalue = this._accept(TokenType.Comma, true)\n\t\t\t\t\t|| this._accept(TokenType.Pipe, true)\n\t\t\t\t\t|| this._accept(TokenType.Backslash, true)\n\t\t\t\t\t|| value;\n\t\t\t} else {\n\t\t\t\tvalue = this._accept(undefined, true);\n\t\t\t}\n\t\t\tif (!value) {\n\t\t\t\t// EOF\n\t\t\t\tthis._backTo(token);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvalues.push(value);\n\t\t}\n\n\t\tif (values.length === 0) {\n\t\t\tthis._backTo(token);\n\t\t\treturn false;\n\t\t}\n\n\t\tparent.appendChild(new Text(values.join('')));\n\t\treturn true;\n\t}\n\n\t// ${foo:}, ${foo} -> variable\n\tprivate _parseComplexVariable(parent: Marker): boolean {\n\t\tlet name: string;\n\t\tconst token = this._token;\n\t\tconst match = this._accept(TokenType.Dollar)\n\t\t\t&& this._accept(TokenType.CurlyOpen)\n\t\t\t&& (name = this._accept(TokenType.VariableName, true));\n\n\t\tif (!match) {\n\t\t\treturn this._backTo(token);\n\t\t}\n\n\t\tconst variable = new Variable(name!);\n\n\t\tif (this._accept(TokenType.Colon)) {\n\t\t\t// ${foo:}\n\t\t\twhile (true) {\n\n\t\t\t\t// ...} -> done\n\t\t\t\tif (this._accept(TokenType.CurlyClose)) {\n\t\t\t\t\tparent.appendChild(variable);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tif (this._parse(variable)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// fallback\n\t\t\t\tparent.appendChild(new Text('${' + name! + ':'));\n\t\t\t\tvariable.children.forEach(parent.appendChild, parent);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t} else if (this._accept(TokenType.Forwardslash)) {\n\t\t\t// ${foo///}\n\t\t\tif (this._parseTransform(variable)) {\n\t\t\t\tparent.appendChild(variable);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tthis._backTo(token);\n\t\t\treturn false;\n\n\t\t} else if (this._accept(TokenType.CurlyClose)) {\n\t\t\t// ${foo}\n\t\t\tparent.appendChild(variable);\n\t\t\treturn true;\n\n\t\t} else {\n\t\t\t// ${foo <- missing curly or colon\n\t\t\treturn this._backTo(token);\n\t\t}\n\t}\n\n\tprivate _parseTransform(parent: TransformableMarker): boolean {\n\t\t// ...//}\n\n\t\tlet transform = new Transform();\n\t\tlet regexValue = '';\n\t\tlet regexOptions = '';\n\n\t\t// (1) /regex\n\t\twhile (true) {\n\t\t\tif (this._accept(TokenType.Forwardslash)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tlet escaped: string;\n\t\t\tif (escaped = this._accept(TokenType.Backslash, true)) {\n\t\t\t\tescaped = this._accept(TokenType.Forwardslash, true) || escaped;\n\t\t\t\tregexValue += escaped;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (this._token.type !== TokenType.EOF) {\n\t\t\t\tregexValue += this._accept(undefined, true);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t// (2) /format\n\t\twhile (true) {\n\t\t\tif (this._accept(TokenType.Forwardslash)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tlet escaped: string;\n\t\t\tif (escaped = this._accept(TokenType.Backslash, true)) {\n\t\t\t\tescaped = this._accept(TokenType.Backslash, true) || this._accept(TokenType.Forwardslash, true) || escaped;\n\t\t\t\ttransform.appendChild(new Text(escaped));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (this._parseFormatString(transform) || this._parseAnything(transform)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t// (3) /option\n\t\twhile (true) {\n\t\t\tif (this._accept(TokenType.CurlyClose)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (this._token.type !== TokenType.EOF) {\n\t\t\t\tregexOptions += this._accept(undefined, true);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\ttransform.regexp = new RegExp(regexValue, regexOptions);\n\t\t} catch (e) {\n\t\t\t// invalid regexp\n\t\t\treturn false;\n\t\t}\n\n\t\tparent.transform = transform;\n\t\treturn true;\n\t}\n\n\tprivate _parseFormatString(parent: Transform): boolean {\n\n\t\tconst token = this._token;\n\t\tif (!this._accept(TokenType.Dollar)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet complex = false;\n\t\tif (this._accept(TokenType.CurlyOpen)) {\n\t\t\tcomplex = true;\n\t\t}\n\n\t\tlet index = this._accept(TokenType.Int, true);\n\n\t\tif (!index) {\n\t\t\tthis._backTo(token);\n\t\t\treturn false;\n\n\t\t} else if (!complex) {\n\t\t\t// $1\n\t\t\tparent.appendChild(new FormatString(Number(index)));\n\t\t\treturn true;\n\n\t\t} else if (this._accept(TokenType.CurlyClose)) {\n\t\t\t// ${1}\n\t\t\tparent.appendChild(new FormatString(Number(index)));\n\t\t\treturn true;\n\n\t\t} else if (!this._accept(TokenType.Colon)) {\n\t\t\tthis._backTo(token);\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this._accept(TokenType.Forwardslash)) {\n\t\t\t// ${1:/upcase}\n\t\t\tlet shorthand = this._accept(TokenType.VariableName, true);\n\t\t\tif (!shorthand || !this._accept(TokenType.CurlyClose)) {\n\t\t\t\tthis._backTo(token);\n\t\t\t\treturn false;\n\t\t\t} else {\n\t\t\t\tparent.appendChild(new FormatString(Number(index), shorthand));\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t} else if (this._accept(TokenType.Plus)) {\n\t\t\t// ${1:+}\n\t\t\tlet ifValue = this._until(TokenType.CurlyClose);\n\t\t\tif (ifValue) {\n\t\t\t\tparent.appendChild(new FormatString(Number(index), undefined, ifValue, undefined));\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t} else if (this._accept(TokenType.Dash)) {\n\t\t\t// ${2:-}\n\t\t\tlet elseValue = this._until(TokenType.CurlyClose);\n\t\t\tif (elseValue) {\n\t\t\t\tparent.appendChild(new FormatString(Number(index), undefined, undefined, elseValue));\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t} else if (this._accept(TokenType.QuestionMark)) {\n\t\t\t// ${2:?:}\n\t\t\tlet ifValue = this._until(TokenType.Colon);\n\t\t\tif (ifValue) {\n\t\t\t\tlet elseValue = this._until(TokenType.CurlyClose);\n\t\t\t\tif (elseValue) {\n\t\t\t\t\tparent.appendChild(new FormatString(Number(index), undefined, ifValue, elseValue));\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// ${1:}\n\t\t\tlet elseValue = this._until(TokenType.CurlyClose);\n\t\t\tif (elseValue) {\n\t\t\t\tparent.appendChild(new FormatString(Number(index), undefined, undefined, elseValue));\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tthis._backTo(token);\n\t\treturn false;\n\t}\n\n\tprivate _parseAnything(marker: Marker): boolean {\n\t\tif (this._token.type !== TokenType.EOF) {\n\t\t\tmarker.appendChild(new Text(this._scanner.tokenText(this._token)));\n\t\t\tthis._accept(undefined);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { quickSelect } from 'vs/base/common/arrays';\nimport { CharCode } from 'vs/base/common/charCode';\nimport { anyScore, fuzzyScore, FuzzyScore, fuzzyScoreGracefulAggressive, FuzzyScorer } from 'vs/base/common/filters';\nimport { compareIgnoreCase } from 'vs/base/common/strings';\nimport { InternalSuggestOptions } from 'vs/editor/common/config/editorOptions';\nimport { CompletionItemKind, CompletionItemProvider } from 'vs/editor/common/languages';\nimport { WordDistance } from 'vs/editor/contrib/suggest/browser/wordDistance';\nimport { CompletionItem } from './suggest';\n\ntype StrictCompletionItem = Required;\n\nexport interface ICompletionStats {\n\tpLabelLen: number;\n}\n\nexport class LineContext {\n\tconstructor(\n\t\treadonly leadingLineContent: string,\n\t\treadonly characterCountDelta: number,\n\t) { }\n}\n\nconst enum Refilter {\n\tNothing = 0,\n\tAll = 1,\n\tIncr = 2\n}\n\n/**\n * Sorted, filtered completion view model\n * */\nexport class CompletionModel {\n\n\tprivate readonly _items: CompletionItem[];\n\tprivate readonly _column: number;\n\tprivate readonly _wordDistance: WordDistance;\n\tprivate readonly _options: InternalSuggestOptions;\n\tprivate readonly _snippetCompareFn = CompletionModel._compareCompletionItems;\n\n\tprivate _lineContext: LineContext;\n\tprivate _refilterKind: Refilter;\n\tprivate _filteredItems?: StrictCompletionItem[];\n\tprivate _providerInfo?: Map;\n\tprivate _stats?: ICompletionStats;\n\n\tconstructor(\n\t\titems: CompletionItem[],\n\t\tcolumn: number,\n\t\tlineContext: LineContext,\n\t\twordDistance: WordDistance,\n\t\toptions: InternalSuggestOptions,\n\t\tsnippetSuggestions: 'top' | 'bottom' | 'inline' | 'none',\n\t\treadonly clipboardText: string | undefined\n\t) {\n\t\tthis._items = items;\n\t\tthis._column = column;\n\t\tthis._wordDistance = wordDistance;\n\t\tthis._options = options;\n\t\tthis._refilterKind = Refilter.All;\n\t\tthis._lineContext = lineContext;\n\n\t\tif (snippetSuggestions === 'top') {\n\t\t\tthis._snippetCompareFn = CompletionModel._compareCompletionItemsSnippetsUp;\n\t\t} else if (snippetSuggestions === 'bottom') {\n\t\t\tthis._snippetCompareFn = CompletionModel._compareCompletionItemsSnippetsDown;\n\t\t}\n\t}\n\n\tget lineContext(): LineContext {\n\t\treturn this._lineContext;\n\t}\n\n\tset lineContext(value: LineContext) {\n\t\tif (this._lineContext.leadingLineContent !== value.leadingLineContent\n\t\t\t|| this._lineContext.characterCountDelta !== value.characterCountDelta\n\t\t) {\n\t\t\tthis._refilterKind = this._lineContext.characterCountDelta < value.characterCountDelta && this._filteredItems ? Refilter.Incr : Refilter.All;\n\t\t\tthis._lineContext = value;\n\t\t}\n\t}\n\n\tget items(): CompletionItem[] {\n\t\tthis._ensureCachedState();\n\t\treturn this._filteredItems!;\n\t}\n\n\tget allProvider(): IterableIterator {\n\t\tthis._ensureCachedState();\n\t\treturn this._providerInfo!.keys();\n\t}\n\n\tget incomplete(): Set {\n\t\tthis._ensureCachedState();\n\t\tconst result = new Set();\n\t\tfor (let [provider, incomplete] of this._providerInfo!) {\n\t\t\tif (incomplete) {\n\t\t\t\tresult.add(provider);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tadopt(except: Set): CompletionItem[] {\n\t\tlet res: CompletionItem[] = [];\n\t\tfor (let i = 0; i < this._items.length;) {\n\t\t\tif (!except.has(this._items[i].provider)) {\n\t\t\t\tres.push(this._items[i]);\n\n\t\t\t\t// unordered removed\n\t\t\t\tthis._items[i] = this._items[this._items.length - 1];\n\t\t\t\tthis._items.pop();\n\t\t\t} else {\n\t\t\t\t// continue with next item\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\tthis._refilterKind = Refilter.All;\n\t\treturn res;\n\t}\n\n\tget stats(): ICompletionStats {\n\t\tthis._ensureCachedState();\n\t\treturn this._stats!;\n\t}\n\n\tprivate _ensureCachedState(): void {\n\t\tif (this._refilterKind !== Refilter.Nothing) {\n\t\t\tthis._createCachedState();\n\t\t}\n\t}\n\n\tprivate _createCachedState(): void {\n\n\t\tthis._providerInfo = new Map();\n\n\t\tconst labelLengths: number[] = [];\n\n\t\tconst { leadingLineContent, characterCountDelta } = this._lineContext;\n\t\tlet word = '';\n\t\tlet wordLow = '';\n\n\t\t// incrementally filter less\n\t\tconst source = this._refilterKind === Refilter.All ? this._items : this._filteredItems!;\n\t\tconst target: StrictCompletionItem[] = [];\n\n\t\t// picks a score function based on the number of\n\t\t// items that we have to score/filter and based on the\n\t\t// user-configuration\n\t\tconst scoreFn: FuzzyScorer = (!this._options.filterGraceful || source.length > 2000) ? fuzzyScore : fuzzyScoreGracefulAggressive;\n\n\t\tfor (let i = 0; i < source.length; i++) {\n\n\t\t\tconst item = source[i];\n\n\t\t\tif (item.isInvalid) {\n\t\t\t\tcontinue; // SKIP invalid items\n\t\t\t}\n\n\t\t\t// collect all support, know if their result is incomplete\n\t\t\tthis._providerInfo.set(item.provider, Boolean(item.container.incomplete));\n\n\t\t\t// 'word' is that remainder of the current line that we\n\t\t\t// filter and score against. In theory each suggestion uses a\n\t\t\t// different word, but in practice not - that's why we cache\n\t\t\tconst overwriteBefore = item.position.column - item.editStart.column;\n\t\t\tconst wordLen = overwriteBefore + characterCountDelta - (item.position.column - this._column);\n\t\t\tif (word.length !== wordLen) {\n\t\t\t\tword = wordLen === 0 ? '' : leadingLineContent.slice(-wordLen);\n\t\t\t\twordLow = word.toLowerCase();\n\t\t\t}\n\n\t\t\t// remember the word against which this item was\n\t\t\t// scored\n\t\t\titem.word = word;\n\n\t\t\tif (wordLen === 0) {\n\t\t\t\t// when there is nothing to score against, don't\n\t\t\t\t// event try to do. Use a const rank and rely on\n\t\t\t\t// the fallback-sort using the initial sort order.\n\t\t\t\t// use a score of `-100` because that is out of the\n\t\t\t\t// bound of values `fuzzyScore` will return\n\t\t\t\titem.score = FuzzyScore.Default;\n\n\t\t\t} else {\n\t\t\t\t// skip word characters that are whitespace until\n\t\t\t\t// we have hit the replace range (overwriteBefore)\n\t\t\t\tlet wordPos = 0;\n\t\t\t\twhile (wordPos < overwriteBefore) {\n\t\t\t\t\tconst ch = word.charCodeAt(wordPos);\n\t\t\t\t\tif (ch === CharCode.Space || ch === CharCode.Tab) {\n\t\t\t\t\t\twordPos += 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (wordPos >= wordLen) {\n\t\t\t\t\t// the wordPos at which scoring starts is the whole word\n\t\t\t\t\t// and therefore the same rules as not having a word apply\n\t\t\t\t\titem.score = FuzzyScore.Default;\n\n\t\t\t\t} else if (typeof item.completion.filterText === 'string') {\n\t\t\t\t\t// when there is a `filterText` it must match the `word`.\n\t\t\t\t\t// if it matches we check with the label to compute highlights\n\t\t\t\t\t// and if that doesn't yield a result we have no highlights,\n\t\t\t\t\t// despite having the match\n\t\t\t\t\tlet match = scoreFn(word, wordLow, wordPos, item.completion.filterText, item.filterTextLow!, 0, false);\n\t\t\t\t\tif (!match) {\n\t\t\t\t\t\tcontinue; // NO match\n\t\t\t\t\t}\n\t\t\t\t\tif (compareIgnoreCase(item.completion.filterText, item.textLabel) === 0) {\n\t\t\t\t\t\t// filterText and label are actually the same -> use good highlights\n\t\t\t\t\t\titem.score = match;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// re-run the scorer on the label in the hope of a result BUT use the rank\n\t\t\t\t\t\t// of the filterText-match\n\t\t\t\t\t\titem.score = anyScore(word, wordLow, wordPos, item.textLabel, item.labelLow, 0);\n\t\t\t\t\t\titem.score[0] = match[0]; // use score from filterText\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\t// by default match `word` against the `label`\n\t\t\t\t\tlet match = scoreFn(word, wordLow, wordPos, item.textLabel, item.labelLow, 0, false);\n\t\t\t\t\tif (!match) {\n\t\t\t\t\t\tcontinue; // NO match\n\t\t\t\t\t}\n\t\t\t\t\titem.score = match;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\titem.idx = i;\n\t\t\titem.distance = this._wordDistance.distance(item.position, item.completion);\n\t\t\ttarget.push(item as StrictCompletionItem);\n\n\t\t\t// update stats\n\t\t\tlabelLengths.push(item.textLabel.length);\n\t\t}\n\n\t\tthis._filteredItems = target.sort(this._snippetCompareFn);\n\t\tthis._refilterKind = Refilter.Nothing;\n\t\tthis._stats = {\n\t\t\tpLabelLen: labelLengths.length ?\n\t\t\t\tquickSelect(labelLengths.length - .85, labelLengths, (a, b) => a - b)\n\t\t\t\t: 0\n\t\t};\n\t}\n\n\tprivate static _compareCompletionItems(a: StrictCompletionItem, b: StrictCompletionItem): number {\n\t\tif (a.score[0] > b.score[0]) {\n\t\t\treturn -1;\n\t\t} else if (a.score[0] < b.score[0]) {\n\t\t\treturn 1;\n\t\t} else if (a.distance < b.distance) {\n\t\t\treturn -1;\n\t\t} else if (a.distance > b.distance) {\n\t\t\treturn 1;\n\t\t} else if (a.idx < b.idx) {\n\t\t\treturn -1;\n\t\t} else if (a.idx > b.idx) {\n\t\t\treturn 1;\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tprivate static _compareCompletionItemsSnippetsDown(a: StrictCompletionItem, b: StrictCompletionItem): number {\n\t\tif (a.completion.kind !== b.completion.kind) {\n\t\t\tif (a.completion.kind === CompletionItemKind.Snippet) {\n\t\t\t\treturn 1;\n\t\t\t} else if (b.completion.kind === CompletionItemKind.Snippet) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t\treturn CompletionModel._compareCompletionItems(a, b);\n\t}\n\n\tprivate static _compareCompletionItemsSnippetsUp(a: StrictCompletionItem, b: StrictCompletionItem): number {\n\t\tif (a.completion.kind !== b.completion.kind) {\n\t\t\tif (a.completion.kind === CompletionItemKind.Snippet) {\n\t\t\t\treturn -1;\n\t\t\t} else if (b.completion.kind === CompletionItemKind.Snippet) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t\treturn CompletionModel._compareCompletionItems(a, b);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Dimension } from 'vs/base/browser/dom';\nimport { Orientation, OrthogonalEdge, Sash, SashState } from 'vs/base/browser/ui/sash/sash';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\n\n\nexport interface IResizeEvent {\n\tdimension: Dimension;\n\tdone: boolean;\n\tnorth?: boolean;\n\teast?: boolean;\n\tsouth?: boolean;\n\twest?: boolean;\n}\n\nexport class ResizableHTMLElement {\n\n\treadonly domNode: HTMLElement;\n\n\tprivate readonly _onDidWillResize = new Emitter();\n\treadonly onDidWillResize: Event = this._onDidWillResize.event;\n\n\tprivate readonly _onDidResize = new Emitter();\n\treadonly onDidResize: Event = this._onDidResize.event;\n\n\tprivate readonly _northSash: Sash;\n\tprivate readonly _eastSash: Sash;\n\tprivate readonly _southSash: Sash;\n\tprivate readonly _westSash: Sash;\n\tprivate readonly _sashListener = new DisposableStore();\n\n\tprivate _size = new Dimension(0, 0);\n\tprivate _minSize = new Dimension(0, 0);\n\tprivate _maxSize = new Dimension(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);\n\tprivate _preferredSize?: Dimension;\n\n\tconstructor() {\n\t\tthis.domNode = document.createElement('div');\n\t\tthis._eastSash = new Sash(this.domNode, { getVerticalSashLeft: () => this._size.width }, { orientation: Orientation.VERTICAL });\n\t\tthis._westSash = new Sash(this.domNode, { getVerticalSashLeft: () => 0 }, { orientation: Orientation.VERTICAL });\n\t\tthis._northSash = new Sash(this.domNode, { getHorizontalSashTop: () => 0 }, { orientation: Orientation.HORIZONTAL, orthogonalEdge: OrthogonalEdge.North });\n\t\tthis._southSash = new Sash(this.domNode, { getHorizontalSashTop: () => this._size.height }, { orientation: Orientation.HORIZONTAL, orthogonalEdge: OrthogonalEdge.South });\n\n\t\tthis._northSash.orthogonalStartSash = this._westSash;\n\t\tthis._northSash.orthogonalEndSash = this._eastSash;\n\t\tthis._southSash.orthogonalStartSash = this._westSash;\n\t\tthis._southSash.orthogonalEndSash = this._eastSash;\n\n\t\tlet currentSize: Dimension | undefined;\n\t\tlet deltaY = 0;\n\t\tlet deltaX = 0;\n\n\t\tthis._sashListener.add(Event.any(this._northSash.onDidStart, this._eastSash.onDidStart, this._southSash.onDidStart, this._westSash.onDidStart)(() => {\n\t\t\tif (currentSize === undefined) {\n\t\t\t\tthis._onDidWillResize.fire();\n\t\t\t\tcurrentSize = this._size;\n\t\t\t\tdeltaY = 0;\n\t\t\t\tdeltaX = 0;\n\t\t\t}\n\t\t}));\n\t\tthis._sashListener.add(Event.any(this._northSash.onDidEnd, this._eastSash.onDidEnd, this._southSash.onDidEnd, this._westSash.onDidEnd)(() => {\n\t\t\tif (currentSize !== undefined) {\n\t\t\t\tcurrentSize = undefined;\n\t\t\t\tdeltaY = 0;\n\t\t\t\tdeltaX = 0;\n\t\t\t\tthis._onDidResize.fire({ dimension: this._size, done: true });\n\t\t\t}\n\t\t}));\n\n\t\tthis._sashListener.add(this._eastSash.onDidChange(e => {\n\t\t\tif (currentSize) {\n\t\t\t\tdeltaX = e.currentX - e.startX;\n\t\t\t\tthis.layout(currentSize.height + deltaY, currentSize.width + deltaX);\n\t\t\t\tthis._onDidResize.fire({ dimension: this._size, done: false, east: true });\n\t\t\t}\n\t\t}));\n\t\tthis._sashListener.add(this._westSash.onDidChange(e => {\n\t\t\tif (currentSize) {\n\t\t\t\tdeltaX = -(e.currentX - e.startX);\n\t\t\t\tthis.layout(currentSize.height + deltaY, currentSize.width + deltaX);\n\t\t\t\tthis._onDidResize.fire({ dimension: this._size, done: false, west: true });\n\t\t\t}\n\t\t}));\n\t\tthis._sashListener.add(this._northSash.onDidChange(e => {\n\t\t\tif (currentSize) {\n\t\t\t\tdeltaY = -(e.currentY - e.startY);\n\t\t\t\tthis.layout(currentSize.height + deltaY, currentSize.width + deltaX);\n\t\t\t\tthis._onDidResize.fire({ dimension: this._size, done: false, north: true });\n\t\t\t}\n\t\t}));\n\t\tthis._sashListener.add(this._southSash.onDidChange(e => {\n\t\t\tif (currentSize) {\n\t\t\t\tdeltaY = e.currentY - e.startY;\n\t\t\t\tthis.layout(currentSize.height + deltaY, currentSize.width + deltaX);\n\t\t\t\tthis._onDidResize.fire({ dimension: this._size, done: false, south: true });\n\t\t\t}\n\t\t}));\n\n\t\tthis._sashListener.add(Event.any(this._eastSash.onDidReset, this._westSash.onDidReset)(e => {\n\t\t\tif (this._preferredSize) {\n\t\t\t\tthis.layout(this._size.height, this._preferredSize.width);\n\t\t\t\tthis._onDidResize.fire({ dimension: this._size, done: true });\n\t\t\t}\n\t\t}));\n\t\tthis._sashListener.add(Event.any(this._northSash.onDidReset, this._southSash.onDidReset)(e => {\n\t\t\tif (this._preferredSize) {\n\t\t\t\tthis.layout(this._preferredSize.height, this._size.width);\n\t\t\t\tthis._onDidResize.fire({ dimension: this._size, done: true });\n\t\t\t}\n\t\t}));\n\t}\n\n\tdispose(): void {\n\t\tthis._northSash.dispose();\n\t\tthis._southSash.dispose();\n\t\tthis._eastSash.dispose();\n\t\tthis._westSash.dispose();\n\t\tthis._sashListener.dispose();\n\t\tthis._onDidResize.dispose();\n\t\tthis._onDidWillResize.dispose();\n\t\tthis.domNode.remove();\n\t}\n\n\tenableSashes(north: boolean, east: boolean, south: boolean, west: boolean): void {\n\t\tthis._northSash.state = north ? SashState.Enabled : SashState.Disabled;\n\t\tthis._eastSash.state = east ? SashState.Enabled : SashState.Disabled;\n\t\tthis._southSash.state = south ? SashState.Enabled : SashState.Disabled;\n\t\tthis._westSash.state = west ? SashState.Enabled : SashState.Disabled;\n\t}\n\n\tlayout(height: number = this.size.height, width: number = this.size.width): void {\n\n\t\tconst { height: minHeight, width: minWidth } = this._minSize;\n\t\tconst { height: maxHeight, width: maxWidth } = this._maxSize;\n\n\t\theight = Math.max(minHeight, Math.min(maxHeight, height));\n\t\twidth = Math.max(minWidth, Math.min(maxWidth, width));\n\n\t\tconst newSize = new Dimension(width, height);\n\t\tif (!Dimension.equals(newSize, this._size)) {\n\t\t\tthis.domNode.style.height = height + 'px';\n\t\t\tthis.domNode.style.width = width + 'px';\n\t\t\tthis._size = newSize;\n\t\t\tthis._northSash.layout();\n\t\t\tthis._eastSash.layout();\n\t\t\tthis._southSash.layout();\n\t\t\tthis._westSash.layout();\n\t\t}\n\t}\n\n\tclearSashHoverState(): void {\n\t\tthis._eastSash.clearSashHoverState();\n\t\tthis._westSash.clearSashHoverState();\n\t\tthis._northSash.clearSashHoverState();\n\t\tthis._southSash.clearSashHoverState();\n\t}\n\n\tget size() {\n\t\treturn this._size;\n\t}\n\n\tset maxSize(value: Dimension) {\n\t\tthis._maxSize = value;\n\t}\n\n\tget maxSize() {\n\t\treturn this._maxSize;\n\t}\n\n\tset minSize(value: Dimension) {\n\t\tthis._minSize = value;\n\t}\n\n\tget minSize() {\n\t\treturn this._minSize;\n\t}\n\n\tset preferredSize(value: Dimension | undefined) {\n\t\tthis._preferredSize = value;\n\t}\n\n\tget preferredSize() {\n\t\treturn this._preferredSize;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { isNonEmptyArray } from 'vs/base/common/arrays';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { CharacterSet } from 'vs/editor/common/core/characterClassifier';\nimport { ISelectedSuggestion, SuggestWidget } from './suggestWidget';\n\nexport class CommitCharacterController {\n\n\tprivate readonly _disposables = new DisposableStore();\n\n\tprivate _active?: {\n\t\treadonly acceptCharacters: CharacterSet;\n\t\treadonly item: ISelectedSuggestion;\n\t};\n\n\tconstructor(editor: ICodeEditor, widget: SuggestWidget, accept: (selected: ISelectedSuggestion) => any) {\n\n\t\tthis._disposables.add(widget.onDidShow(() => this._onItem(widget.getFocusedItem())));\n\t\tthis._disposables.add(widget.onDidFocus(this._onItem, this));\n\t\tthis._disposables.add(widget.onDidHide(this.reset, this));\n\n\t\tthis._disposables.add(editor.onWillType(text => {\n\t\t\tif (this._active && !widget.isFrozen()) {\n\t\t\t\tconst ch = text.charCodeAt(text.length - 1);\n\t\t\t\tif (this._active.acceptCharacters.has(ch) && editor.getOption(EditorOption.acceptSuggestionOnCommitCharacter)) {\n\t\t\t\t\taccept(this._active.item);\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\t}\n\n\tprivate _onItem(selected: ISelectedSuggestion | undefined): void {\n\t\tif (!selected || !isNonEmptyArray(selected.item.completion.commitCharacters)) {\n\t\t\t// no item or no commit characters\n\t\t\tthis.reset();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this._active && this._active.item.item === selected.item) {\n\t\t\t// still the same item\n\t\t\treturn;\n\t\t}\n\n\t\t// keep item and its commit characters\n\t\tconst acceptCharacters = new CharacterSet();\n\t\tfor (const ch of selected.item.completion.commitCharacters) {\n\t\t\tif (ch.length > 0) {\n\t\t\t\tacceptCharacters.add(ch.charCodeAt(0));\n\t\t\t}\n\t\t}\n\t\tthis._active = { acceptCharacters, item: selected };\n\t}\n\n\treset(): void {\n\t\tthis._active = undefined;\n\t}\n\n\tdispose() {\n\t\tthis._disposables.dispose();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { SuggestModel } from 'vs/editor/contrib/suggest/browser/suggestModel';\n\nexport class OvertypingCapturer implements IDisposable {\n\n\tprivate static readonly _maxSelectionLength = 51200;\n\tprivate readonly _disposables = new DisposableStore();\n\n\tprivate _lastOvertyped: { value: string; multiline: boolean }[] = [];\n\tprivate _empty: boolean = true;\n\n\tconstructor(editor: ICodeEditor, suggestModel: SuggestModel) {\n\n\t\tthis._disposables.add(editor.onWillType(() => {\n\t\t\tif (!this._empty) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!editor.hasModel()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst selections = editor.getSelections();\n\t\t\tconst selectionsLength = selections.length;\n\n\t\t\t// Check if it will overtype any selections\n\t\t\tlet willOvertype = false;\n\t\t\tfor (let i = 0; i < selectionsLength; i++) {\n\t\t\t\tif (!selections[i].isEmpty()) {\n\t\t\t\t\twillOvertype = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!willOvertype) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._lastOvertyped = [];\n\t\t\tconst model = editor.getModel();\n\t\t\tfor (let i = 0; i < selectionsLength; i++) {\n\t\t\t\tconst selection = selections[i];\n\t\t\t\t// Check for overtyping capturer restrictions\n\t\t\t\tif (model.getValueLengthInRange(selection) > OvertypingCapturer._maxSelectionLength) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._lastOvertyped[i] = { value: model.getValueInRange(selection), multiline: selection.startLineNumber !== selection.endLineNumber };\n\t\t\t}\n\t\t\tthis._empty = false;\n\t\t}));\n\n\t\tthis._disposables.add(suggestModel.onDidCancel(e => {\n\t\t\tif (!this._empty && !e.retrigger) {\n\t\t\t\tthis._empty = true;\n\t\t\t}\n\t\t}));\n\t}\n\n\tgetLastOvertypedInfo(idx: number): { value: string; multiline: boolean } | undefined {\n\t\tif (!this._empty && idx >= 0 && idx < this._lastOvertyped.length) {\n\t\t\treturn this._lastOvertyped[idx];\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tdispose() {\n\t\tthis._disposables.dispose();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { binarySearch, isFalsyOrEmpty } from 'vs/base/common/arrays';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { IPosition } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { CompletionItem, CompletionItemKind } from 'vs/editor/common/languages';\nimport { IEditorWorkerService } from 'vs/editor/common/services/editorWorker';\nimport { BracketSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/browser/bracketSelections';\n\nexport abstract class WordDistance {\n\n\tstatic readonly None = new class extends WordDistance {\n\t\tdistance() { return 0; }\n\t};\n\n\tstatic async create(service: IEditorWorkerService, editor: ICodeEditor): Promise {\n\n\t\tif (!editor.getOption(EditorOption.suggest).localityBonus) {\n\t\t\treturn WordDistance.None;\n\t\t}\n\n\t\tif (!editor.hasModel()) {\n\t\t\treturn WordDistance.None;\n\t\t}\n\n\t\tconst model = editor.getModel();\n\t\tconst position = editor.getPosition();\n\n\t\tif (!service.canComputeWordRanges(model.uri)) {\n\t\t\treturn WordDistance.None;\n\t\t}\n\n\t\tconst [ranges] = await new BracketSelectionRangeProvider().provideSelectionRanges(model, [position]);\n\t\tif (ranges.length === 0) {\n\t\t\treturn WordDistance.None;\n\t\t}\n\n\t\tconst wordRanges = await service.computeWordRanges(model.uri, ranges[0].range);\n\t\tif (!wordRanges) {\n\t\t\treturn WordDistance.None;\n\t\t}\n\n\t\t// remove current word\n\t\tconst wordUntilPos = model.getWordUntilPosition(position);\n\t\tdelete wordRanges[wordUntilPos.word];\n\n\t\treturn new class extends WordDistance {\n\t\t\tdistance(anchor: IPosition, item: CompletionItem) {\n\t\t\t\tif (!position.equals(editor.getPosition())) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t\tif (item.kind === CompletionItemKind.Keyword) {\n\t\t\t\t\treturn 2 << 20;\n\t\t\t\t}\n\t\t\t\tlet word = typeof item.label === 'string' ? item.label : item.label.label;\n\t\t\t\tlet wordLines = wordRanges[word];\n\t\t\t\tif (isFalsyOrEmpty(wordLines)) {\n\t\t\t\t\treturn 2 << 20;\n\t\t\t\t}\n\t\t\t\tlet idx = binarySearch(wordLines, Range.fromPositions(anchor), Range.compareRangesUsingStarts);\n\t\t\t\tlet bestWordRange = idx >= 0 ? wordLines[idx] : wordLines[Math.max(0, ~idx - 1)];\n\t\t\t\tlet blockDistance = ranges.length;\n\t\t\t\tfor (const range of ranges) {\n\t\t\t\t\tif (!Range.containsRange(range.range, bestWordRange)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tblockDistance -= 1;\n\t\t\t\t}\n\t\t\t\treturn blockDistance;\n\t\t\t}\n\t\t};\n\t}\n\n\tabstract distance(anchor: IPosition, suggestion: CompletionItem): number;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n/*\n * This module exports common types and functionality shared between\n * the Monarch compiler that compiles JSON to ILexer, and the Monarch\n * Tokenizer (that highlights at runtime)\n */\n\n/*\n * Type definitions to be used internally to Monarch.\n * Inside monarch we use fully typed definitions and compiled versions of the more abstract JSON descriptions.\n */\n\nexport const enum MonarchBracket {\n\tNone = 0,\n\tOpen = 1,\n\tClose = -1\n}\n\nexport interface ILexerMin {\n\tlanguageId: string;\n\tincludeLF: boolean;\n\tnoThrow: boolean;\n\tignoreCase: boolean;\n\tunicode: boolean;\n\tusesEmbedded: boolean;\n\tdefaultToken: string;\n\tstateNames: { [stateName: string]: any; };\n\t[attr: string]: any;\n}\n\nexport interface ILexer extends ILexerMin {\n\tmaxStack: number;\n\tstart: string | null;\n\tignoreCase: boolean;\n\tunicode: boolean;\n\ttokenPostfix: string;\n\n\ttokenizer: { [stateName: string]: IRule[]; };\n\tbrackets: IBracket[];\n}\n\nexport interface IBracket {\n\ttoken: string;\n\topen: string;\n\tclose: string;\n}\n\nexport type FuzzyAction = IAction | string;\n\nexport function isFuzzyActionArr(what: FuzzyAction | FuzzyAction[]): what is FuzzyAction[] {\n\treturn (Array.isArray(what));\n}\n\nexport function isFuzzyAction(what: FuzzyAction | FuzzyAction[]): what is FuzzyAction {\n\treturn !isFuzzyActionArr(what);\n}\n\nexport function isString(what: FuzzyAction): what is string {\n\treturn (typeof what === 'string');\n}\n\nexport function isIAction(what: FuzzyAction): what is IAction {\n\treturn !isString(what);\n}\n\nexport interface IRule {\n\tregex: RegExp;\n\taction: FuzzyAction;\n\tmatchOnlyAtLineStart: boolean;\n\tname: string;\n}\n\nexport interface IAction {\n\t// an action is either a group of actions\n\tgroup?: FuzzyAction[];\n\n\t// or a function that returns a fresh action\n\ttest?: (id: string, matches: string[], state: string, eos: boolean) => FuzzyAction;\n\n\t// or it is a declarative action with a token value and various other attributes\n\ttoken?: string;\n\ttokenSubst?: boolean;\n\tnext?: string;\n\tnextEmbedded?: string;\n\tbracket?: MonarchBracket;\n\tlog?: string;\n\tswitchTo?: string;\n\tgoBack?: number;\n\ttransform?: (states: string[]) => string[];\n}\n\nexport interface IBranch {\n\tname: string;\n\tvalue: FuzzyAction;\n\ttest?: (id: string, matches: string[], state: string, eos: boolean) => boolean;\n}\n\n// Small helper functions\n\n/**\n * Is a string null, undefined, or empty?\n */\nexport function empty(s: string): boolean {\n\treturn (s ? false : true);\n}\n\n/**\n * Puts a string to lower case if 'ignoreCase' is set.\n */\nexport function fixCase(lexer: ILexerMin, str: string): string {\n\treturn (lexer.ignoreCase && str ? str.toLowerCase() : str);\n}\n\n/**\n * Ensures there are no bad characters in a CSS token class.\n */\nexport function sanitize(s: string) {\n\treturn s.replace(/[&<>'\"_]/g, '-'); // used on all output token CSS classes\n}\n\n// Logging\n\n/**\n * Logs a message.\n */\nexport function log(lexer: ILexerMin, msg: string) {\n\tconsole.log(`${lexer.languageId}: ${msg}`);\n}\n\n// Throwing errors\n\nexport function createError(lexer: ILexerMin, msg: string): Error {\n\treturn new Error(`${lexer.languageId}: ${msg}`);\n}\n\n// Helper functions for rule finding and substitution\n\n/**\n * substituteMatches is used on lexer strings and can substitutes predefined patterns:\n * \t\t$$ => $\n * \t\t$# => id\n * \t\t$n => matched entry n\n * \t\t@attr => contents of lexer[attr]\n *\n * See documentation for more info\n */\nexport function substituteMatches(lexer: ILexerMin, str: string, id: string, matches: string[], state: string): string {\n\tconst re = /\\$((\\$)|(#)|(\\d\\d?)|[sS](\\d\\d?)|@(\\w+))/g;\n\tlet stateMatches: string[] | null = null;\n\treturn str.replace(re, function (full, sub?, dollar?, hash?, n?, s?, attr?, ofs?, total?) {\n\t\tif (!empty(dollar)) {\n\t\t\treturn '$'; // $$\n\t\t}\n\t\tif (!empty(hash)) {\n\t\t\treturn fixCase(lexer, id); // default $#\n\t\t}\n\t\tif (!empty(n) && n < matches.length) {\n\t\t\treturn fixCase(lexer, matches[n]); // $n\n\t\t}\n\t\tif (!empty(attr) && lexer && typeof (lexer[attr]) === 'string') {\n\t\t\treturn lexer[attr]; //@attribute\n\t\t}\n\t\tif (stateMatches === null) { // split state on demand\n\t\t\tstateMatches = state.split('.');\n\t\t\tstateMatches.unshift(state);\n\t\t}\n\t\tif (!empty(s) && s < stateMatches.length) {\n\t\t\treturn fixCase(lexer, stateMatches[s]); //$Sn\n\t\t}\n\t\treturn '';\n\t});\n}\n\n/**\n * Find the tokenizer rules for a specific state (i.e. next action)\n */\nexport function findRules(lexer: ILexer, inState: string): IRule[] | null {\n\tlet state: string | null = inState;\n\twhile (state && state.length > 0) {\n\t\tconst rules = lexer.tokenizer[state];\n\t\tif (rules) {\n\t\t\treturn rules;\n\t\t}\n\n\t\tconst idx = state.lastIndexOf('.');\n\t\tif (idx < 0) {\n\t\t\tstate = null; // no further parent\n\t\t} else {\n\t\t\tstate = state.substr(0, idx);\n\t\t}\n\t}\n\treturn null;\n}\n\n/**\n * Is a certain state defined? In contrast to 'findRules' this works on a ILexerMin.\n * This is used during compilation where we may know the defined states\n * but not yet whether the corresponding rules are correct.\n */\nexport function stateExists(lexer: ILexerMin, inState: string): boolean {\n\tlet state: string | null = inState;\n\twhile (state && state.length > 0) {\n\t\tconst exist = lexer.stateNames[state];\n\t\tif (exist) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst idx = state.lastIndexOf('.');\n\t\tif (idx < 0) {\n\t\t\tstate = null; // no further parent\n\t\t} else {\n\t\t\tstate = state.substr(0, idx);\n\t\t}\n\t}\n\treturn false;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n/*\n * This module only exports 'compile' which compiles a JSON language definition\n * into a typed and checked ILexer definition.\n */\n\nimport * as monarchCommon from 'vs/editor/standalone/common/monarch/monarchCommon';\nimport { IMonarchLanguage, IMonarchLanguageBracket } from 'vs/editor/standalone/common/monarch/monarchTypes';\n\n/*\n * Type helpers\n *\n * Note: this is just for sanity checks on the JSON description which is\n * helpful for the programmer. No checks are done anymore once the lexer is\n * already 'compiled and checked'.\n *\n */\n\nfunction isArrayOf(elemType: (x: any) => boolean, obj: any): boolean {\n\tif (!obj) {\n\t\treturn false;\n\t}\n\tif (!(Array.isArray(obj))) {\n\t\treturn false;\n\t}\n\tfor (const el of obj) {\n\t\tif (!(elemType(el))) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nfunction bool(prop: any, defValue: boolean): boolean {\n\tif (typeof prop === 'boolean') {\n\t\treturn prop;\n\t}\n\treturn defValue;\n}\n\nfunction string(prop: any, defValue: string): string {\n\tif (typeof (prop) === 'string') {\n\t\treturn prop;\n\t}\n\treturn defValue;\n}\n\n\nfunction arrayToHash(array: string[]): { [name: string]: true } {\n\tconst result: any = {};\n\tfor (const e of array) {\n\t\tresult[e] = true;\n\t}\n\treturn result;\n}\n\n\nfunction createKeywordMatcher(arr: string[], caseInsensitive: boolean = false): (str: string) => boolean {\n\tif (caseInsensitive) {\n\t\tarr = arr.map(function (x) { return x.toLowerCase(); });\n\t}\n\tconst hash = arrayToHash(arr);\n\tif (caseInsensitive) {\n\t\treturn function (word) {\n\t\t\treturn hash[word.toLowerCase()] !== undefined && hash.hasOwnProperty(word.toLowerCase());\n\t\t};\n\t} else {\n\t\treturn function (word) {\n\t\t\treturn hash[word] !== undefined && hash.hasOwnProperty(word);\n\t\t};\n\t}\n}\n\n\n// Lexer helpers\n\n/**\n * Compiles a regular expression string, adding the 'i' flag if 'ignoreCase' is set, and the 'u' flag if 'unicode' is set.\n * Also replaces @\\w+ or sequences with the content of the specified attribute\n * @\\w+ replacement can be avoided by escaping `@` signs with another `@` sign.\n * @example /@attr/ will be replaced with the value of lexer[attr]\n * @example /@@text/ will not be replaced and will become /@text/.\n */\nfunction compileRegExp(lexer: monarchCommon.ILexerMin, str: string): RegExp {\n\t// @@ must be interpreted as a literal @, so we replace all occurences of @@ with a placeholder character\n\tstr = str.replace(/@@/g, `\\x01`);\n\n\tlet n = 0;\n\tlet hadExpansion: boolean;\n\tdo {\n\t\thadExpansion = false;\n\t\tstr = str.replace(/@(\\w+)/g, function (s, attr?) {\n\t\t\thadExpansion = true;\n\t\t\tlet sub = '';\n\t\t\tif (typeof (lexer[attr]) === 'string') {\n\t\t\t\tsub = lexer[attr];\n\t\t\t} else if (lexer[attr] && lexer[attr] instanceof RegExp) {\n\t\t\t\tsub = lexer[attr].source;\n\t\t\t} else {\n\t\t\t\tif (lexer[attr] === undefined) {\n\t\t\t\t\tthrow monarchCommon.createError(lexer, 'language definition does not contain attribute \\'' + attr + '\\', used at: ' + str);\n\t\t\t\t} else {\n\t\t\t\t\tthrow monarchCommon.createError(lexer, 'attribute reference \\'' + attr + '\\' must be a string, used at: ' + str);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn (monarchCommon.empty(sub) ? '' : '(?:' + sub + ')');\n\t\t});\n\t\tn++;\n\t} while (hadExpansion && n < 5);\n\n\t// handle escaped @@\n\tstr = str.replace(/\\x01/g, '@');\n\n\tconst flags = (lexer.ignoreCase ? 'i' : '') + (lexer.unicode ? 'u' : '');\n\treturn new RegExp(str, flags);\n}\n\n/**\n * Compiles guard functions for case matches.\n * This compiles 'cases' attributes into efficient match functions.\n *\n */\nfunction selectScrutinee(id: string, matches: string[], state: string, num: number): string | null {\n\tif (num < 0) {\n\t\treturn id;\n\t}\n\tif (num < matches.length) {\n\t\treturn matches[num];\n\t}\n\tif (num >= 100) {\n\t\tnum = num - 100;\n\t\tconst parts = state.split('.');\n\t\tparts.unshift(state);\n\t\tif (num < parts.length) {\n\t\t\treturn parts[num];\n\t\t}\n\t}\n\treturn null;\n}\n\nfunction createGuard(lexer: monarchCommon.ILexerMin, ruleName: string, tkey: string, val: monarchCommon.FuzzyAction): monarchCommon.IBranch {\n\t// get the scrutinee and pattern\n\tlet scrut = -1; // -1: $!, 0-99: $n, 100+n: $Sn\n\tlet oppat = tkey;\n\tlet matches = tkey.match(/^\\$(([sS]?)(\\d\\d?)|#)(.*)$/);\n\tif (matches) {\n\t\tif (matches[3]) { // if digits\n\t\t\tscrut = parseInt(matches[3]);\n\t\t\tif (matches[2]) {\n\t\t\t\tscrut = scrut + 100; // if [sS] present\n\t\t\t}\n\t\t}\n\t\toppat = matches[4];\n\t}\n\t// get operator\n\tlet op = '~';\n\tlet pat = oppat;\n\tif (!oppat || oppat.length === 0) {\n\t\top = '!=';\n\t\tpat = '';\n\t}\n\telse if (/^\\w*$/.test(pat)) { // just a word\n\t\top = '==';\n\t}\n\telse {\n\t\tmatches = oppat.match(/^(@|!@|~|!~|==|!=)(.*)$/);\n\t\tif (matches) {\n\t\t\top = matches[1];\n\t\t\tpat = matches[2];\n\t\t}\n\t}\n\n\t// set the tester function\n\tlet tester: (s: string, id: string, matches: string[], state: string, eos: boolean) => boolean;\n\n\t// special case a regexp that matches just words\n\tif ((op === '~' || op === '!~') && /^(\\w|\\|)*$/.test(pat)) {\n\t\tconst inWords = createKeywordMatcher(pat.split('|'), lexer.ignoreCase);\n\t\ttester = function (s) { return (op === '~' ? inWords(s) : !inWords(s)); };\n\t}\n\telse if (op === '@' || op === '!@') {\n\t\tconst words = lexer[pat];\n\t\tif (!words) {\n\t\t\tthrow monarchCommon.createError(lexer, 'the @ match target \\'' + pat + '\\' is not defined, in rule: ' + ruleName);\n\t\t}\n\t\tif (!(isArrayOf(function (elem) { return (typeof (elem) === 'string'); }, words))) {\n\t\t\tthrow monarchCommon.createError(lexer, 'the @ match target \\'' + pat + '\\' must be an array of strings, in rule: ' + ruleName);\n\t\t}\n\t\tconst inWords = createKeywordMatcher(words, lexer.ignoreCase);\n\t\ttester = function (s) { return (op === '@' ? inWords(s) : !inWords(s)); };\n\t}\n\telse if (op === '~' || op === '!~') {\n\t\tif (pat.indexOf('$') < 0) {\n\t\t\t// precompile regular expression\n\t\t\tconst re = compileRegExp(lexer, '^' + pat + '$');\n\t\t\ttester = function (s) { return (op === '~' ? re.test(s) : !re.test(s)); };\n\t\t}\n\t\telse {\n\t\t\ttester = function (s, id, matches, state) {\n\t\t\t\tconst re = compileRegExp(lexer, '^' + monarchCommon.substituteMatches(lexer, pat, id, matches, state) + '$');\n\t\t\t\treturn re.test(s);\n\t\t\t};\n\t\t}\n\t}\n\telse { // if (op==='==' || op==='!=') {\n\t\tif (pat.indexOf('$') < 0) {\n\t\t\tconst patx = monarchCommon.fixCase(lexer, pat);\n\t\t\ttester = function (s) { return (op === '==' ? s === patx : s !== patx); };\n\t\t}\n\t\telse {\n\t\t\tconst patx = monarchCommon.fixCase(lexer, pat);\n\t\t\ttester = function (s, id, matches, state, eos) {\n\t\t\t\tconst patexp = monarchCommon.substituteMatches(lexer, patx, id, matches, state);\n\t\t\t\treturn (op === '==' ? s === patexp : s !== patexp);\n\t\t\t};\n\t\t}\n\t}\n\n\t// return the branch object\n\tif (scrut === -1) {\n\t\treturn {\n\t\t\tname: tkey, value: val, test: function (id, matches, state, eos) {\n\t\t\t\treturn tester(id, id, matches, state, eos);\n\t\t\t}\n\t\t};\n\t}\n\telse {\n\t\treturn {\n\t\t\tname: tkey, value: val, test: function (id, matches, state, eos) {\n\t\t\t\tconst scrutinee = selectScrutinee(id, matches, state, scrut);\n\t\t\t\treturn tester(!scrutinee ? '' : scrutinee, id, matches, state, eos);\n\t\t\t}\n\t\t};\n\t}\n}\n\n/**\n * Compiles an action: i.e. optimize regular expressions and case matches\n * and do many sanity checks.\n *\n * This is called only during compilation but if the lexer definition\n * contains user functions as actions (which is usually not allowed), then this\n * may be called during lexing. It is important therefore to compile common cases efficiently\n */\nfunction compileAction(lexer: monarchCommon.ILexerMin, ruleName: string, action: any): monarchCommon.FuzzyAction {\n\tif (!action) {\n\t\treturn { token: '' };\n\t}\n\telse if (typeof (action) === 'string') {\n\t\treturn action; // { token: action };\n\t}\n\telse if (action.token || action.token === '') {\n\t\tif (typeof (action.token) !== 'string') {\n\t\t\tthrow monarchCommon.createError(lexer, 'a \\'token\\' attribute must be of type string, in rule: ' + ruleName);\n\t\t}\n\t\telse {\n\t\t\t// only copy specific typed fields (only happens once during compile Lexer)\n\t\t\tconst newAction: monarchCommon.IAction = { token: action.token };\n\t\t\tif (action.token.indexOf('$') >= 0) {\n\t\t\t\tnewAction.tokenSubst = true;\n\t\t\t}\n\t\t\tif (typeof (action.bracket) === 'string') {\n\t\t\t\tif (action.bracket === '@open') {\n\t\t\t\t\tnewAction.bracket = monarchCommon.MonarchBracket.Open;\n\t\t\t\t} else if (action.bracket === '@close') {\n\t\t\t\t\tnewAction.bracket = monarchCommon.MonarchBracket.Close;\n\t\t\t\t} else {\n\t\t\t\t\tthrow monarchCommon.createError(lexer, 'a \\'bracket\\' attribute must be either \\'@open\\' or \\'@close\\', in rule: ' + ruleName);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (action.next) {\n\t\t\t\tif (typeof (action.next) !== 'string') {\n\t\t\t\t\tthrow monarchCommon.createError(lexer, 'the next state must be a string value in rule: ' + ruleName);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tlet next: string = action.next;\n\t\t\t\t\tif (!/^(@pop|@push|@popall)$/.test(next)) {\n\t\t\t\t\t\tif (next[0] === '@') {\n\t\t\t\t\t\t\tnext = next.substr(1); // peel off starting @ sign\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (next.indexOf('$') < 0) { // no dollar substitution, we can check if the state exists\n\t\t\t\t\t\t\tif (!monarchCommon.stateExists(lexer, monarchCommon.substituteMatches(lexer, next, '', [], ''))) {\n\t\t\t\t\t\t\t\tthrow monarchCommon.createError(lexer, 'the next state \\'' + action.next + '\\' is not defined in rule: ' + ruleName);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tnewAction.next = next;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (typeof (action.goBack) === 'number') {\n\t\t\t\tnewAction.goBack = action.goBack;\n\t\t\t}\n\t\t\tif (typeof (action.switchTo) === 'string') {\n\t\t\t\tnewAction.switchTo = action.switchTo;\n\t\t\t}\n\t\t\tif (typeof (action.log) === 'string') {\n\t\t\t\tnewAction.log = action.log;\n\t\t\t}\n\t\t\tif (typeof (action.nextEmbedded) === 'string') {\n\t\t\t\tnewAction.nextEmbedded = action.nextEmbedded;\n\t\t\t\tlexer.usesEmbedded = true;\n\t\t\t}\n\t\t\treturn newAction;\n\t\t}\n\t}\n\telse if (Array.isArray(action)) {\n\t\tconst results: monarchCommon.FuzzyAction[] = [];\n\t\tfor (let i = 0, len = action.length; i < len; i++) {\n\t\t\tresults[i] = compileAction(lexer, ruleName, action[i]);\n\t\t}\n\t\treturn { group: results };\n\t}\n\telse if (action.cases) {\n\t\t// build an array of test cases\n\t\tconst cases: monarchCommon.IBranch[] = [];\n\n\t\t// for each case, push a test function and result value\n\t\tfor (let tkey in action.cases) {\n\t\t\tif (action.cases.hasOwnProperty(tkey)) {\n\t\t\t\tconst val = compileAction(lexer, ruleName, action.cases[tkey]);\n\n\t\t\t\t// what kind of case\n\t\t\t\tif (tkey === '@default' || tkey === '@' || tkey === '') {\n\t\t\t\t\tcases.push({ test: undefined, value: val, name: tkey });\n\t\t\t\t}\n\t\t\t\telse if (tkey === '@eos') {\n\t\t\t\t\tcases.push({ test: function (id, matches, state, eos) { return eos; }, value: val, name: tkey });\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcases.push(createGuard(lexer, ruleName, tkey, val)); // call separate function to avoid local variable capture\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// create a matching function\n\t\tconst def = lexer.defaultToken;\n\t\treturn {\n\t\t\ttest: function (id, matches, state, eos) {\n\t\t\t\tfor (const _case of cases) {\n\t\t\t\t\tconst didmatch = (!_case.test || _case.test(id, matches, state, eos));\n\t\t\t\t\tif (didmatch) {\n\t\t\t\t\t\treturn _case.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn def;\n\t\t\t}\n\t\t};\n\t}\n\telse {\n\t\tthrow monarchCommon.createError(lexer, 'an action must be a string, an object with a \\'token\\' or \\'cases\\' attribute, or an array of actions; in rule: ' + ruleName);\n\t}\n}\n\n/**\n * Helper class for creating matching rules\n */\nclass Rule implements monarchCommon.IRule {\n\tpublic regex: RegExp = new RegExp('');\n\tpublic action: monarchCommon.FuzzyAction = { token: '' };\n\tpublic matchOnlyAtLineStart: boolean = false;\n\tpublic name: string = '';\n\n\tconstructor(name: string) {\n\t\tthis.name = name;\n\t}\n\n\tpublic setRegex(lexer: monarchCommon.ILexerMin, re: string | RegExp): void {\n\t\tlet sregex: string;\n\t\tif (typeof (re) === 'string') {\n\t\t\tsregex = re;\n\t\t}\n\t\telse if (re instanceof RegExp) {\n\t\t\tsregex = (re).source;\n\t\t}\n\t\telse {\n\t\t\tthrow monarchCommon.createError(lexer, 'rules must start with a match string or regular expression: ' + this.name);\n\t\t}\n\n\t\tthis.matchOnlyAtLineStart = (sregex.length > 0 && sregex[0] === '^');\n\t\tthis.name = this.name + ': ' + sregex;\n\t\tthis.regex = compileRegExp(lexer, '^(?:' + (this.matchOnlyAtLineStart ? sregex.substr(1) : sregex) + ')');\n\t}\n\n\tpublic setAction(lexer: monarchCommon.ILexerMin, act: monarchCommon.IAction) {\n\t\tthis.action = compileAction(lexer, this.name, act);\n\t}\n}\n\n/**\n * Compiles a json description function into json where all regular expressions,\n * case matches etc, are compiled and all include rules are expanded.\n * We also compile the bracket definitions, supply defaults, and do many sanity checks.\n * If the 'jsonStrict' parameter is 'false', we allow at certain locations\n * regular expression objects and functions that get called during lexing.\n * (Currently we have no samples that need this so perhaps we should always have\n * jsonStrict to true).\n */\nexport function compile(languageId: string, json: IMonarchLanguage): monarchCommon.ILexer {\n\tif (!json || typeof (json) !== 'object') {\n\t\tthrow new Error('Monarch: expecting a language definition object');\n\t}\n\n\t// Create our lexer\n\tconst lexer: monarchCommon.ILexer = {};\n\tlexer.languageId = languageId;\n\tlexer.includeLF = bool(json.includeLF, false);\n\tlexer.noThrow = false; // raise exceptions during compilation\n\tlexer.maxStack = 100;\n\n\t// Set standard fields: be defensive about types\n\tlexer.start = (typeof json.start === 'string' ? json.start : null);\n\tlexer.ignoreCase = bool(json.ignoreCase, false);\n\tlexer.unicode = bool(json.unicode, false);\n\n\tlexer.tokenPostfix = string(json.tokenPostfix, '.' + lexer.languageId);\n\tlexer.defaultToken = string(json.defaultToken, 'source');\n\n\tlexer.usesEmbedded = false; // becomes true if we find a nextEmbedded action\n\n\t// For calling compileAction later on\n\tconst lexerMin: monarchCommon.ILexerMin = json;\n\tlexerMin.languageId = languageId;\n\tlexerMin.includeLF = lexer.includeLF;\n\tlexerMin.ignoreCase = lexer.ignoreCase;\n\tlexerMin.unicode = lexer.unicode;\n\tlexerMin.noThrow = lexer.noThrow;\n\tlexerMin.usesEmbedded = lexer.usesEmbedded;\n\tlexerMin.stateNames = json.tokenizer;\n\tlexerMin.defaultToken = lexer.defaultToken;\n\n\n\t// Compile an array of rules into newrules where RegExp objects are created.\n\tfunction addRules(state: string, newrules: monarchCommon.IRule[], rules: any[]) {\n\t\tfor (const rule of rules) {\n\n\t\t\tlet include = rule.include;\n\t\t\tif (include) {\n\t\t\t\tif (typeof (include) !== 'string') {\n\t\t\t\t\tthrow monarchCommon.createError(lexer, 'an \\'include\\' attribute must be a string at: ' + state);\n\t\t\t\t}\n\t\t\t\tif (include[0] === '@') {\n\t\t\t\t\tinclude = include.substr(1); // peel off starting @\n\t\t\t\t}\n\t\t\t\tif (!json.tokenizer[include]) {\n\t\t\t\t\tthrow monarchCommon.createError(lexer, 'include target \\'' + include + '\\' is not defined at: ' + state);\n\t\t\t\t}\n\t\t\t\taddRules(state + '.' + include, newrules, json.tokenizer[include]);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconst newrule = new Rule(state);\n\n\t\t\t\t// Set up new rule attributes\n\t\t\t\tif (Array.isArray(rule) && rule.length >= 1 && rule.length <= 3) {\n\t\t\t\t\tnewrule.setRegex(lexerMin, rule[0]);\n\t\t\t\t\tif (rule.length >= 3) {\n\t\t\t\t\t\tif (typeof (rule[1]) === 'string') {\n\t\t\t\t\t\t\tnewrule.setAction(lexerMin, { token: rule[1], next: rule[2] });\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (typeof (rule[1]) === 'object') {\n\t\t\t\t\t\t\tconst rule1 = rule[1];\n\t\t\t\t\t\t\trule1.next = rule[2];\n\t\t\t\t\t\t\tnewrule.setAction(lexerMin, rule1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tthrow monarchCommon.createError(lexer, 'a next state as the last element of a rule can only be given if the action is either an object or a string, at: ' + state);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tnewrule.setAction(lexerMin, rule[1]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif (!rule.regex) {\n\t\t\t\t\t\tthrow monarchCommon.createError(lexer, 'a rule must either be an array, or an object with a \\'regex\\' or \\'include\\' field at: ' + state);\n\t\t\t\t\t}\n\t\t\t\t\tif (rule.name) {\n\t\t\t\t\t\tif (typeof rule.name === 'string') {\n\t\t\t\t\t\t\tnewrule.name = rule.name;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (rule.matchOnlyAtStart) {\n\t\t\t\t\t\tnewrule.matchOnlyAtLineStart = bool(rule.matchOnlyAtLineStart, false);\n\t\t\t\t\t}\n\t\t\t\t\tnewrule.setRegex(lexerMin, rule.regex);\n\t\t\t\t\tnewrule.setAction(lexerMin, rule.action);\n\t\t\t\t}\n\n\t\t\t\tnewrules.push(newrule);\n\t\t\t}\n\t\t}\n\t}\n\n\t// compile the tokenizer rules\n\tif (!json.tokenizer || typeof (json.tokenizer) !== 'object') {\n\t\tthrow monarchCommon.createError(lexer, 'a language definition must define the \\'tokenizer\\' attribute as an object');\n\t}\n\n\tlexer.tokenizer = [];\n\tfor (let key in json.tokenizer) {\n\t\tif (json.tokenizer.hasOwnProperty(key)) {\n\t\t\tif (!lexer.start) {\n\t\t\t\tlexer.start = key;\n\t\t\t}\n\n\t\t\tconst rules = json.tokenizer[key];\n\t\t\tlexer.tokenizer[key] = new Array();\n\t\t\taddRules('tokenizer.' + key, lexer.tokenizer[key], rules);\n\t\t}\n\t}\n\tlexer.usesEmbedded = lexerMin.usesEmbedded; // can be set during compileAction\n\n\t// Set simple brackets\n\tif (json.brackets) {\n\t\tif (!(Array.isArray(json.brackets))) {\n\t\t\tthrow monarchCommon.createError(lexer, 'the \\'brackets\\' attribute must be defined as an array');\n\t\t}\n\t}\n\telse {\n\t\tjson.brackets = [\n\t\t\t{ open: '{', close: '}', token: 'delimiter.curly' },\n\t\t\t{ open: '[', close: ']', token: 'delimiter.square' },\n\t\t\t{ open: '(', close: ')', token: 'delimiter.parenthesis' },\n\t\t\t{ open: '<', close: '>', token: 'delimiter.angle' }];\n\t}\n\tconst brackets: IMonarchLanguageBracket[] = [];\n\tfor (let el of json.brackets) {\n\t\tlet desc: any = el;\n\t\tif (desc && Array.isArray(desc) && desc.length === 3) {\n\t\t\tdesc = { token: desc[2], open: desc[0], close: desc[1] };\n\t\t}\n\t\tif (desc.open === desc.close) {\n\t\t\tthrow monarchCommon.createError(lexer, 'open and close brackets in a \\'brackets\\' attribute must be different: ' + desc.open +\n\t\t\t\t'\\n hint: use the \\'bracket\\' attribute if matching on equal brackets is required.');\n\t\t}\n\t\tif (typeof desc.open === 'string' && typeof desc.token === 'string' && typeof desc.close === 'string') {\n\t\t\tbrackets.push({\n\t\t\t\ttoken: desc.token + lexer.tokenPostfix,\n\t\t\t\topen: monarchCommon.fixCase(lexer, desc.open),\n\t\t\t\tclose: monarchCommon.fixCase(lexer, desc.close)\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tthrow monarchCommon.createError(lexer, 'every element in the \\'brackets\\' array must be a \\'{open,close,token}\\' object or array');\n\t\t}\n\t}\n\tlexer.brackets = brackets;\n\n\t// Disable throw so the syntax highlighter goes, no matter what\n\tlexer.noThrow = true;\n\treturn lexer;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n/**\n * Create a syntax highighter with a fully declarative JSON style lexer description\n * using regular expressions.\n */\n\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport * as languages from 'vs/editor/common/languages';\nimport { NullState } from 'vs/editor/common/languages/nullMode';\nimport { TokenTheme } from 'vs/editor/common/languages/supports/tokenization';\nimport { ILanguageService } from 'vs/editor/common/services/language';\nimport * as monarchCommon from 'vs/editor/standalone/common/monarch/monarchCommon';\nimport { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneTheme';\n\nconst CACHE_STACK_DEPTH = 5;\n\n/**\n * Reuse the same stack elements up to a certain depth.\n */\nclass MonarchStackElementFactory {\n\n\tprivate static readonly _INSTANCE = new MonarchStackElementFactory(CACHE_STACK_DEPTH);\n\tpublic static create(parent: MonarchStackElement | null, state: string): MonarchStackElement {\n\t\treturn this._INSTANCE.create(parent, state);\n\t}\n\n\tprivate readonly _maxCacheDepth: number;\n\tprivate readonly _entries: { [stackElementId: string]: MonarchStackElement; };\n\n\tconstructor(maxCacheDepth: number) {\n\t\tthis._maxCacheDepth = maxCacheDepth;\n\t\tthis._entries = Object.create(null);\n\t}\n\n\tpublic create(parent: MonarchStackElement | null, state: string): MonarchStackElement {\n\t\tif (parent !== null && parent.depth >= this._maxCacheDepth) {\n\t\t\t// no caching above a certain depth\n\t\t\treturn new MonarchStackElement(parent, state);\n\t\t}\n\t\tlet stackElementId = MonarchStackElement.getStackElementId(parent);\n\t\tif (stackElementId.length > 0) {\n\t\t\tstackElementId += '|';\n\t\t}\n\t\tstackElementId += state;\n\n\t\tlet result = this._entries[stackElementId];\n\t\tif (result) {\n\t\t\treturn result;\n\t\t}\n\t\tresult = new MonarchStackElement(parent, state);\n\t\tthis._entries[stackElementId] = result;\n\t\treturn result;\n\t}\n}\n\nclass MonarchStackElement {\n\n\tpublic readonly parent: MonarchStackElement | null;\n\tpublic readonly state: string;\n\tpublic readonly depth: number;\n\n\tconstructor(parent: MonarchStackElement | null, state: string) {\n\t\tthis.parent = parent;\n\t\tthis.state = state;\n\t\tthis.depth = (this.parent ? this.parent.depth : 0) + 1;\n\t}\n\n\tpublic static getStackElementId(element: MonarchStackElement | null): string {\n\t\tlet result = '';\n\t\twhile (element !== null) {\n\t\t\tif (result.length > 0) {\n\t\t\t\tresult += '|';\n\t\t\t}\n\t\t\tresult += element.state;\n\t\t\telement = element.parent;\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate static _equals(a: MonarchStackElement | null, b: MonarchStackElement | null): boolean {\n\t\twhile (a !== null && b !== null) {\n\t\t\tif (a === b) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (a.state !== b.state) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\ta = a.parent;\n\t\t\tb = b.parent;\n\t\t}\n\t\tif (a === null && b === null) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic equals(other: MonarchStackElement): boolean {\n\t\treturn MonarchStackElement._equals(this, other);\n\t}\n\n\tpublic push(state: string): MonarchStackElement {\n\t\treturn MonarchStackElementFactory.create(this, state);\n\t}\n\n\tpublic pop(): MonarchStackElement | null {\n\t\treturn this.parent;\n\t}\n\n\tpublic popall(): MonarchStackElement {\n\t\tlet result: MonarchStackElement = this;\n\t\twhile (result.parent) {\n\t\t\tresult = result.parent;\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic switchTo(state: string): MonarchStackElement {\n\t\treturn MonarchStackElementFactory.create(this.parent, state);\n\t}\n}\n\nclass EmbeddedLanguageData {\n\tpublic readonly languageId: string;\n\tpublic readonly state: languages.IState;\n\n\tconstructor(languageId: string, state: languages.IState) {\n\t\tthis.languageId = languageId;\n\t\tthis.state = state;\n\t}\n\n\tpublic equals(other: EmbeddedLanguageData): boolean {\n\t\treturn (\n\t\t\tthis.languageId === other.languageId\n\t\t\t&& this.state.equals(other.state)\n\t\t);\n\t}\n\n\tpublic clone(): EmbeddedLanguageData {\n\t\tconst stateClone = this.state.clone();\n\t\t// save an object\n\t\tif (stateClone === this.state) {\n\t\t\treturn this;\n\t\t}\n\t\treturn new EmbeddedLanguageData(this.languageId, this.state);\n\t}\n}\n\n/**\n * Reuse the same line states up to a certain depth.\n */\nclass MonarchLineStateFactory {\n\n\tprivate static readonly _INSTANCE = new MonarchLineStateFactory(CACHE_STACK_DEPTH);\n\tpublic static create(stack: MonarchStackElement, embeddedLanguageData: EmbeddedLanguageData | null): MonarchLineState {\n\t\treturn this._INSTANCE.create(stack, embeddedLanguageData);\n\t}\n\n\tprivate readonly _maxCacheDepth: number;\n\tprivate readonly _entries: { [stackElementId: string]: MonarchLineState; };\n\n\tconstructor(maxCacheDepth: number) {\n\t\tthis._maxCacheDepth = maxCacheDepth;\n\t\tthis._entries = Object.create(null);\n\t}\n\n\tpublic create(stack: MonarchStackElement, embeddedLanguageData: EmbeddedLanguageData | null): MonarchLineState {\n\t\tif (embeddedLanguageData !== null) {\n\t\t\t// no caching when embedding\n\t\t\treturn new MonarchLineState(stack, embeddedLanguageData);\n\t\t}\n\t\tif (stack !== null && stack.depth >= this._maxCacheDepth) {\n\t\t\t// no caching above a certain depth\n\t\t\treturn new MonarchLineState(stack, embeddedLanguageData);\n\t\t}\n\t\tconst stackElementId = MonarchStackElement.getStackElementId(stack);\n\n\t\tlet result = this._entries[stackElementId];\n\t\tif (result) {\n\t\t\treturn result;\n\t\t}\n\t\tresult = new MonarchLineState(stack, null);\n\t\tthis._entries[stackElementId] = result;\n\t\treturn result;\n\t}\n}\n\nclass MonarchLineState implements languages.IState {\n\n\tpublic readonly stack: MonarchStackElement;\n\tpublic readonly embeddedLanguageData: EmbeddedLanguageData | null;\n\n\tconstructor(\n\t\tstack: MonarchStackElement,\n\t\tembeddedLanguageData: EmbeddedLanguageData | null\n\t) {\n\t\tthis.stack = stack;\n\t\tthis.embeddedLanguageData = embeddedLanguageData;\n\t}\n\n\tpublic clone(): languages.IState {\n\t\tconst embeddedlanguageDataClone = this.embeddedLanguageData ? this.embeddedLanguageData.clone() : null;\n\t\t// save an object\n\t\tif (embeddedlanguageDataClone === this.embeddedLanguageData) {\n\t\t\treturn this;\n\t\t}\n\t\treturn MonarchLineStateFactory.create(this.stack, this.embeddedLanguageData);\n\t}\n\n\tpublic equals(other: languages.IState): boolean {\n\t\tif (!(other instanceof MonarchLineState)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!this.stack.equals(other.stack)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this.embeddedLanguageData === null && other.embeddedLanguageData === null) {\n\t\t\treturn true;\n\t\t}\n\t\tif (this.embeddedLanguageData === null || other.embeddedLanguageData === null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.embeddedLanguageData.equals(other.embeddedLanguageData);\n\t}\n}\n\ninterface IMonarchTokensCollector {\n\tenterLanguage(languageId: string): void;\n\temit(startOffset: number, type: string): void;\n\tnestedLanguageTokenize(embeddedLanguageLine: string, hasEOL: boolean, embeddedLanguageData: EmbeddedLanguageData, offsetDelta: number): languages.IState;\n}\n\nclass MonarchClassicTokensCollector implements IMonarchTokensCollector {\n\n\tprivate _tokens: languages.Token[];\n\tprivate _languageId: string | null;\n\tprivate _lastTokenType: string | null;\n\tprivate _lastTokenLanguage: string | null;\n\n\tconstructor() {\n\t\tthis._tokens = [];\n\t\tthis._languageId = null;\n\t\tthis._lastTokenType = null;\n\t\tthis._lastTokenLanguage = null;\n\t}\n\n\tpublic enterLanguage(languageId: string): void {\n\t\tthis._languageId = languageId;\n\t}\n\n\tpublic emit(startOffset: number, type: string): void {\n\t\tif (this._lastTokenType === type && this._lastTokenLanguage === this._languageId) {\n\t\t\treturn;\n\t\t}\n\t\tthis._lastTokenType = type;\n\t\tthis._lastTokenLanguage = this._languageId;\n\t\tthis._tokens.push(new languages.Token(startOffset, type, this._languageId!));\n\t}\n\n\tpublic nestedLanguageTokenize(embeddedLanguageLine: string, hasEOL: boolean, embeddedLanguageData: EmbeddedLanguageData, offsetDelta: number): languages.IState {\n\t\tconst nestedLanguageId = embeddedLanguageData.languageId;\n\t\tconst embeddedModeState = embeddedLanguageData.state;\n\n\t\tconst nestedLanguageTokenizationSupport = languages.TokenizationRegistry.get(nestedLanguageId);\n\t\tif (!nestedLanguageTokenizationSupport) {\n\t\t\tthis.enterLanguage(nestedLanguageId);\n\t\t\tthis.emit(offsetDelta, '');\n\t\t\treturn embeddedModeState;\n\t\t}\n\n\t\tconst nestedResult = nestedLanguageTokenizationSupport.tokenize(embeddedLanguageLine, hasEOL, embeddedModeState);\n\t\tif (offsetDelta !== 0) {\n\t\t\tfor (const token of nestedResult.tokens) {\n\t\t\t\tthis._tokens.push(new languages.Token(token.offset + offsetDelta, token.type, token.language));\n\t\t\t}\n\t\t} else {\n\t\t\tthis._tokens = this._tokens.concat(nestedResult.tokens);\n\t\t}\n\t\tthis._lastTokenType = null;\n\t\tthis._lastTokenLanguage = null;\n\t\tthis._languageId = null;\n\t\treturn nestedResult.endState;\n\t}\n\n\tpublic finalize(endState: MonarchLineState): languages.TokenizationResult {\n\t\treturn new languages.TokenizationResult(this._tokens, endState);\n\t}\n}\n\nclass MonarchModernTokensCollector implements IMonarchTokensCollector {\n\n\tprivate readonly _languageService: ILanguageService;\n\tprivate readonly _theme: TokenTheme;\n\tprivate _prependTokens: Uint32Array | null;\n\tprivate _tokens: number[];\n\tprivate _currentLanguageId: languages.LanguageId;\n\tprivate _lastTokenMetadata: number;\n\n\tconstructor(languageService: ILanguageService, theme: TokenTheme) {\n\t\tthis._languageService = languageService;\n\t\tthis._theme = theme;\n\t\tthis._prependTokens = null;\n\t\tthis._tokens = [];\n\t\tthis._currentLanguageId = languages.LanguageId.Null;\n\t\tthis._lastTokenMetadata = 0;\n\t}\n\n\tpublic enterLanguage(languageId: string): void {\n\t\tthis._currentLanguageId = this._languageService.languageIdCodec.encodeLanguageId(languageId);\n\t}\n\n\tpublic emit(startOffset: number, type: string): void {\n\t\tconst metadata = this._theme.match(this._currentLanguageId, type);\n\t\tif (this._lastTokenMetadata === metadata) {\n\t\t\treturn;\n\t\t}\n\t\tthis._lastTokenMetadata = metadata;\n\t\tthis._tokens.push(startOffset);\n\t\tthis._tokens.push(metadata);\n\t}\n\n\tprivate static _merge(a: Uint32Array | null, b: number[], c: Uint32Array | null): Uint32Array {\n\t\tconst aLen = (a !== null ? a.length : 0);\n\t\tconst bLen = b.length;\n\t\tconst cLen = (c !== null ? c.length : 0);\n\n\t\tif (aLen === 0 && bLen === 0 && cLen === 0) {\n\t\t\treturn new Uint32Array(0);\n\t\t}\n\t\tif (aLen === 0 && bLen === 0) {\n\t\t\treturn c!;\n\t\t}\n\t\tif (bLen === 0 && cLen === 0) {\n\t\t\treturn a!;\n\t\t}\n\n\t\tconst result = new Uint32Array(aLen + bLen + cLen);\n\t\tif (a !== null) {\n\t\t\tresult.set(a);\n\t\t}\n\t\tfor (let i = 0; i < bLen; i++) {\n\t\t\tresult[aLen + i] = b[i];\n\t\t}\n\t\tif (c !== null) {\n\t\t\tresult.set(c, aLen + bLen);\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic nestedLanguageTokenize(embeddedLanguageLine: string, hasEOL: boolean, embeddedLanguageData: EmbeddedLanguageData, offsetDelta: number): languages.IState {\n\t\tconst nestedLanguageId = embeddedLanguageData.languageId;\n\t\tconst embeddedModeState = embeddedLanguageData.state;\n\n\t\tconst nestedLanguageTokenizationSupport = languages.TokenizationRegistry.get(nestedLanguageId);\n\t\tif (!nestedLanguageTokenizationSupport) {\n\t\t\tthis.enterLanguage(nestedLanguageId);\n\t\t\tthis.emit(offsetDelta, '');\n\t\t\treturn embeddedModeState;\n\t\t}\n\n\t\tconst nestedResult = nestedLanguageTokenizationSupport.tokenizeEncoded(embeddedLanguageLine, hasEOL, embeddedModeState);\n\t\tif (offsetDelta !== 0) {\n\t\t\tfor (let i = 0, len = nestedResult.tokens.length; i < len; i += 2) {\n\t\t\t\tnestedResult.tokens[i] += offsetDelta;\n\t\t\t}\n\t\t}\n\n\t\tthis._prependTokens = MonarchModernTokensCollector._merge(this._prependTokens, this._tokens, nestedResult.tokens);\n\t\tthis._tokens = [];\n\t\tthis._currentLanguageId = 0;\n\t\tthis._lastTokenMetadata = 0;\n\t\treturn nestedResult.endState;\n\t}\n\n\tpublic finalize(endState: MonarchLineState): languages.EncodedTokenizationResult {\n\t\treturn new languages.EncodedTokenizationResult(\n\t\t\tMonarchModernTokensCollector._merge(this._prependTokens, this._tokens, null),\n\t\t\tendState\n\t\t);\n\t}\n}\n\nexport type ILoadStatus = { loaded: true; } | { loaded: false; promise: Promise; };\n\nexport class MonarchTokenizer implements languages.ITokenizationSupport {\n\n\tprivate readonly _languageService: ILanguageService;\n\tprivate readonly _standaloneThemeService: IStandaloneThemeService;\n\tprivate readonly _languageId: string;\n\tprivate readonly _lexer: monarchCommon.ILexer;\n\tprivate readonly _embeddedLanguages: { [languageId: string]: boolean; };\n\tpublic embeddedLoaded: Promise;\n\tprivate readonly _tokenizationRegistryListener: IDisposable;\n\n\tconstructor(languageService: ILanguageService, standaloneThemeService: IStandaloneThemeService, languageId: string, lexer: monarchCommon.ILexer) {\n\t\tthis._languageService = languageService;\n\t\tthis._standaloneThemeService = standaloneThemeService;\n\t\tthis._languageId = languageId;\n\t\tthis._lexer = lexer;\n\t\tthis._embeddedLanguages = Object.create(null);\n\t\tthis.embeddedLoaded = Promise.resolve(undefined);\n\n\t\t// Set up listening for embedded modes\n\t\tlet emitting = false;\n\t\tthis._tokenizationRegistryListener = languages.TokenizationRegistry.onDidChange((e) => {\n\t\t\tif (emitting) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet isOneOfMyEmbeddedModes = false;\n\t\t\tfor (let i = 0, len = e.changedLanguages.length; i < len; i++) {\n\t\t\t\tconst language = e.changedLanguages[i];\n\t\t\t\tif (this._embeddedLanguages[language]) {\n\t\t\t\t\tisOneOfMyEmbeddedModes = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (isOneOfMyEmbeddedModes) {\n\t\t\t\temitting = true;\n\t\t\t\tlanguages.TokenizationRegistry.fire([this._languageId]);\n\t\t\t\temitting = false;\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic dispose(): void {\n\t\tthis._tokenizationRegistryListener.dispose();\n\t}\n\n\tpublic getLoadStatus(): ILoadStatus {\n\t\tconst promises: Thenable[] = [];\n\t\tfor (let nestedLanguageId in this._embeddedLanguages) {\n\t\t\tconst tokenizationSupport = languages.TokenizationRegistry.get(nestedLanguageId);\n\t\t\tif (tokenizationSupport) {\n\t\t\t\t// The nested language is already loaded\n\t\t\t\tif (tokenizationSupport instanceof MonarchTokenizer) {\n\t\t\t\t\tconst nestedModeStatus = tokenizationSupport.getLoadStatus();\n\t\t\t\t\tif (nestedModeStatus.loaded === false) {\n\t\t\t\t\t\tpromises.push(nestedModeStatus.promise);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!languages.TokenizationRegistry.isResolved(nestedLanguageId)) {\n\t\t\t\t// The nested language is in the process of being loaded\n\t\t\t\tpromises.push(languages.TokenizationRegistry.getOrCreate(nestedLanguageId));\n\t\t\t}\n\t\t}\n\n\t\tif (promises.length === 0) {\n\t\t\treturn {\n\t\t\t\tloaded: true\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tloaded: false,\n\t\t\tpromise: Promise.all(promises).then(_ => undefined)\n\t\t};\n\t}\n\n\tpublic getInitialState(): languages.IState {\n\t\tconst rootState = MonarchStackElementFactory.create(null, this._lexer.start!);\n\t\treturn MonarchLineStateFactory.create(rootState, null);\n\t}\n\n\tpublic tokenize(line: string, hasEOL: boolean, lineState: languages.IState): languages.TokenizationResult {\n\t\tconst tokensCollector = new MonarchClassicTokensCollector();\n\t\tconst endLineState = this._tokenize(line, hasEOL, lineState, tokensCollector);\n\t\treturn tokensCollector.finalize(endLineState);\n\t}\n\n\tpublic tokenizeEncoded(line: string, hasEOL: boolean, lineState: languages.IState): languages.EncodedTokenizationResult {\n\t\tconst tokensCollector = new MonarchModernTokensCollector(this._languageService, this._standaloneThemeService.getColorTheme().tokenTheme);\n\t\tconst endLineState = this._tokenize(line, hasEOL, lineState, tokensCollector);\n\t\treturn tokensCollector.finalize(endLineState);\n\t}\n\n\tprivate _tokenize(line: string, hasEOL: boolean, lineState: MonarchLineState, collector: IMonarchTokensCollector): MonarchLineState {\n\t\tif (lineState.embeddedLanguageData) {\n\t\t\treturn this._nestedTokenize(line, hasEOL, lineState, 0, collector);\n\t\t} else {\n\t\t\treturn this._myTokenize(line, hasEOL, lineState, 0, collector);\n\t\t}\n\t}\n\n\tprivate _findLeavingNestedLanguageOffset(line: string, state: MonarchLineState): number {\n\t\tlet rules: monarchCommon.IRule[] | null = this._lexer.tokenizer[state.stack.state];\n\t\tif (!rules) {\n\t\t\trules = monarchCommon.findRules(this._lexer, state.stack.state); // do parent matching\n\t\t\tif (!rules) {\n\t\t\t\tthrow monarchCommon.createError(this._lexer, 'tokenizer state is not defined: ' + state.stack.state);\n\t\t\t}\n\t\t}\n\n\t\tlet popOffset = -1;\n\t\tlet hasEmbeddedPopRule = false;\n\n\t\tfor (const rule of rules) {\n\t\t\tif (!monarchCommon.isIAction(rule.action) || rule.action.nextEmbedded !== '@pop') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\thasEmbeddedPopRule = true;\n\n\t\t\tlet regex = rule.regex;\n\t\t\tconst regexSource = rule.regex.source;\n\t\t\tif (regexSource.substr(0, 4) === '^(?:' && regexSource.substr(regexSource.length - 1, 1) === ')') {\n\t\t\t\tconst flags = (regex.ignoreCase ? 'i' : '') + (regex.unicode ? 'u' : '');\n\t\t\t\tregex = new RegExp(regexSource.substr(4, regexSource.length - 5), flags);\n\t\t\t}\n\n\t\t\tconst result = line.search(regex);\n\t\t\tif (result === -1 || (result !== 0 && rule.matchOnlyAtLineStart)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (popOffset === -1 || result < popOffset) {\n\t\t\t\tpopOffset = result;\n\t\t\t}\n\t\t}\n\n\t\tif (!hasEmbeddedPopRule) {\n\t\t\tthrow monarchCommon.createError(this._lexer, 'no rule containing nextEmbedded: \"@pop\" in tokenizer embedded state: ' + state.stack.state);\n\t\t}\n\n\t\treturn popOffset;\n\t}\n\n\tprivate _nestedTokenize(line: string, hasEOL: boolean, lineState: MonarchLineState, offsetDelta: number, tokensCollector: IMonarchTokensCollector): MonarchLineState {\n\n\t\tconst popOffset = this._findLeavingNestedLanguageOffset(line, lineState);\n\n\t\tif (popOffset === -1) {\n\t\t\t// tokenization will not leave nested language\n\t\t\tconst nestedEndState = tokensCollector.nestedLanguageTokenize(line, hasEOL, lineState.embeddedLanguageData!, offsetDelta);\n\t\t\treturn MonarchLineStateFactory.create(lineState.stack, new EmbeddedLanguageData(lineState.embeddedLanguageData!.languageId, nestedEndState));\n\t\t}\n\n\t\tconst nestedLanguageLine = line.substring(0, popOffset);\n\t\tif (nestedLanguageLine.length > 0) {\n\t\t\t// tokenize with the nested language\n\t\t\ttokensCollector.nestedLanguageTokenize(nestedLanguageLine, false, lineState.embeddedLanguageData!, offsetDelta);\n\t\t}\n\n\t\tconst restOfTheLine = line.substring(popOffset);\n\t\treturn this._myTokenize(restOfTheLine, hasEOL, lineState, offsetDelta + popOffset, tokensCollector);\n\t}\n\n\tprivate _safeRuleName(rule: monarchCommon.IRule | null): string {\n\t\tif (rule) {\n\t\t\treturn rule.name;\n\t\t}\n\t\treturn '(unknown)';\n\t}\n\n\tprivate _myTokenize(lineWithoutLF: string, hasEOL: boolean, lineState: MonarchLineState, offsetDelta: number, tokensCollector: IMonarchTokensCollector): MonarchLineState {\n\t\ttokensCollector.enterLanguage(this._languageId);\n\n\t\tconst lineWithoutLFLength = lineWithoutLF.length;\n\t\tconst line = (hasEOL && this._lexer.includeLF ? lineWithoutLF + '\\n' : lineWithoutLF);\n\t\tconst lineLength = line.length;\n\n\t\tlet embeddedLanguageData = lineState.embeddedLanguageData;\n\t\tlet stack = lineState.stack;\n\t\tlet pos = 0;\n\n\t\t// regular expression group matching\n\t\t// these never need cloning or equality since they are only used within a line match\n\t\tinterface GroupMatching {\n\t\t\tmatches: string[];\n\t\t\trule: monarchCommon.IRule | null;\n\t\t\tgroups: { action: monarchCommon.FuzzyAction; matched: string; }[];\n\t\t}\n\t\tlet groupMatching: GroupMatching | null = null;\n\n\t\t// See https://github.com/microsoft/monaco-editor/issues/1235\n\t\t// Evaluate rules at least once for an empty line\n\t\tlet forceEvaluation = true;\n\n\t\twhile (forceEvaluation || pos < lineLength) {\n\n\t\t\tconst pos0 = pos;\n\t\t\tconst stackLen0 = stack.depth;\n\t\t\tconst groupLen0 = groupMatching ? groupMatching.groups.length : 0;\n\t\t\tconst state = stack.state;\n\n\t\t\tlet matches: string[] | null = null;\n\t\t\tlet matched: string | null = null;\n\t\t\tlet action: monarchCommon.FuzzyAction | monarchCommon.FuzzyAction[] | null = null;\n\t\t\tlet rule: monarchCommon.IRule | null = null;\n\n\t\t\tlet enteringEmbeddedLanguage: string | null = null;\n\n\t\t\t// check if we need to process group matches first\n\t\t\tif (groupMatching) {\n\t\t\t\tmatches = groupMatching.matches;\n\t\t\t\tconst groupEntry = groupMatching.groups.shift()!;\n\t\t\t\tmatched = groupEntry.matched;\n\t\t\t\taction = groupEntry.action;\n\t\t\t\trule = groupMatching.rule;\n\n\t\t\t\t// cleanup if necessary\n\t\t\t\tif (groupMatching.groups.length === 0) {\n\t\t\t\t\tgroupMatching = null;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// otherwise we match on the token stream\n\n\t\t\t\tif (!forceEvaluation && pos >= lineLength) {\n\t\t\t\t\t// nothing to do\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tforceEvaluation = false;\n\n\t\t\t\t// get the rules for this state\n\t\t\t\tlet rules: monarchCommon.IRule[] | null = this._lexer.tokenizer[state];\n\t\t\t\tif (!rules) {\n\t\t\t\t\trules = monarchCommon.findRules(this._lexer, state); // do parent matching\n\t\t\t\t\tif (!rules) {\n\t\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'tokenizer state is not defined: ' + state);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// try each rule until we match\n\t\t\t\tlet restOfLine = line.substr(pos);\n\t\t\t\tfor (const rule of rules) {\n\t\t\t\t\tif (pos === 0 || !rule.matchOnlyAtLineStart) {\n\t\t\t\t\t\tmatches = restOfLine.match(rule.regex);\n\t\t\t\t\t\tif (matches) {\n\t\t\t\t\t\t\tmatched = matches[0];\n\t\t\t\t\t\t\taction = rule.action;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// We matched 'rule' with 'matches' and 'action'\n\t\t\tif (!matches) {\n\t\t\t\tmatches = [''];\n\t\t\t\tmatched = '';\n\t\t\t}\n\n\t\t\tif (!action) {\n\t\t\t\t// bad: we didn't match anything, and there is no action to take\n\t\t\t\t// we need to advance the stream or we get progress trouble\n\t\t\t\tif (pos < lineLength) {\n\t\t\t\t\tmatches = [line.charAt(pos)];\n\t\t\t\t\tmatched = matches[0];\n\t\t\t\t}\n\t\t\t\taction = this._lexer.defaultToken;\n\t\t\t}\n\n\t\t\tif (matched === null) {\n\t\t\t\t// should never happen, needed for strict null checking\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// advance stream\n\t\t\tpos += matched.length;\n\n\t\t\t// maybe call action function (used for 'cases')\n\t\t\twhile (monarchCommon.isFuzzyAction(action) && monarchCommon.isIAction(action) && action.test) {\n\t\t\t\taction = action.test(matched, matches, state, pos === lineLength);\n\t\t\t}\n\n\t\t\tlet result: monarchCommon.FuzzyAction | monarchCommon.FuzzyAction[] | null = null;\n\t\t\t// set the result: either a string or an array of actions\n\t\t\tif (typeof action === 'string' || Array.isArray(action)) {\n\t\t\t\tresult = action;\n\t\t\t} else if (action.group) {\n\t\t\t\tresult = action.group;\n\t\t\t} else if (action.token !== null && action.token !== undefined) {\n\n\t\t\t\t// do $n replacements?\n\t\t\t\tif (action.tokenSubst) {\n\t\t\t\t\tresult = monarchCommon.substituteMatches(this._lexer, action.token, matched, matches, state);\n\t\t\t\t} else {\n\t\t\t\t\tresult = action.token;\n\t\t\t\t}\n\n\t\t\t\t// enter embedded language?\n\t\t\t\tif (action.nextEmbedded) {\n\t\t\t\t\tif (action.nextEmbedded === '@pop') {\n\t\t\t\t\t\tif (!embeddedLanguageData) {\n\t\t\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'cannot pop embedded language if not inside one');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tembeddedLanguageData = null;\n\t\t\t\t\t} else if (embeddedLanguageData) {\n\t\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'cannot enter embedded language from within an embedded language');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tenteringEmbeddedLanguage = monarchCommon.substituteMatches(this._lexer, action.nextEmbedded, matched, matches, state);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// state transformations\n\t\t\t\tif (action.goBack) { // back up the stream..\n\t\t\t\t\tpos = Math.max(0, pos - action.goBack);\n\t\t\t\t}\n\n\t\t\t\tif (action.switchTo && typeof action.switchTo === 'string') {\n\t\t\t\t\tlet nextState = monarchCommon.substituteMatches(this._lexer, action.switchTo, matched, matches, state); // switch state without a push...\n\t\t\t\t\tif (nextState[0] === '@') {\n\t\t\t\t\t\tnextState = nextState.substr(1); // peel off starting '@'\n\t\t\t\t\t}\n\t\t\t\t\tif (!monarchCommon.findRules(this._lexer, nextState)) {\n\t\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'trying to switch to a state \\'' + nextState + '\\' that is undefined in rule: ' + this._safeRuleName(rule));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstack = stack.switchTo(nextState);\n\t\t\t\t\t}\n\t\t\t\t} else if (action.transform && typeof action.transform === 'function') {\n\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'action.transform not supported');\n\t\t\t\t} else if (action.next) {\n\t\t\t\t\tif (action.next === '@push') {\n\t\t\t\t\t\tif (stack.depth >= this._lexer.maxStack) {\n\t\t\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'maximum tokenizer stack size reached: [' +\n\t\t\t\t\t\t\t\tstack.state + ',' + stack.parent!.state + ',...]');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstack = stack.push(state);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (action.next === '@pop') {\n\t\t\t\t\t\tif (stack.depth <= 1) {\n\t\t\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'trying to pop an empty stack in rule: ' + this._safeRuleName(rule));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstack = stack.pop()!;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (action.next === '@popall') {\n\t\t\t\t\t\tstack = stack.popall();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlet nextState = monarchCommon.substituteMatches(this._lexer, action.next, matched, matches, state);\n\t\t\t\t\t\tif (nextState[0] === '@') {\n\t\t\t\t\t\t\tnextState = nextState.substr(1); // peel off starting '@'\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!monarchCommon.findRules(this._lexer, nextState)) {\n\t\t\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'trying to set a next state \\'' + nextState + '\\' that is undefined in rule: ' + this._safeRuleName(rule));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstack = stack.push(nextState);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (action.log && typeof (action.log) === 'string') {\n\t\t\t\t\tmonarchCommon.log(this._lexer, this._lexer.languageId + ': ' + monarchCommon.substituteMatches(this._lexer, action.log, matched, matches, state));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// check result\n\t\t\tif (result === null) {\n\t\t\t\tthrow monarchCommon.createError(this._lexer, 'lexer rule has no well-defined action in rule: ' + this._safeRuleName(rule));\n\t\t\t}\n\n\t\t\tconst computeNewStateForEmbeddedLanguage = (enteringEmbeddedLanguage: string) => {\n\t\t\t\t// support language names, mime types, and language ids\n\t\t\t\tconst languageId = (\n\t\t\t\t\tthis._languageService.getLanguageIdByLanguageName(enteringEmbeddedLanguage)\n\t\t\t\t\t|| this._languageService.getLanguageIdByMimeType(enteringEmbeddedLanguage)\n\t\t\t\t\t|| enteringEmbeddedLanguage\n\t\t\t\t);\n\n\t\t\t\tconst embeddedLanguageData = this._getNestedEmbeddedLanguageData(languageId);\n\n\t\t\t\tif (pos < lineLength) {\n\t\t\t\t\t// there is content from the embedded language on this line\n\t\t\t\t\tconst restOfLine = lineWithoutLF.substr(pos);\n\t\t\t\t\treturn this._nestedTokenize(restOfLine, hasEOL, MonarchLineStateFactory.create(stack, embeddedLanguageData), offsetDelta + pos, tokensCollector);\n\t\t\t\t} else {\n\t\t\t\t\treturn MonarchLineStateFactory.create(stack, embeddedLanguageData);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// is the result a group match?\n\t\t\tif (Array.isArray(result)) {\n\t\t\t\tif (groupMatching && groupMatching.groups.length > 0) {\n\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'groups cannot be nested: ' + this._safeRuleName(rule));\n\t\t\t\t}\n\t\t\t\tif (matches.length !== result.length + 1) {\n\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'matched number of groups does not match the number of actions in rule: ' + this._safeRuleName(rule));\n\t\t\t\t}\n\t\t\t\tlet totalLen = 0;\n\t\t\t\tfor (let i = 1; i < matches.length; i++) {\n\t\t\t\t\ttotalLen += matches[i].length;\n\t\t\t\t}\n\t\t\t\tif (totalLen !== matched.length) {\n\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'with groups, all characters should be matched in consecutive groups in rule: ' + this._safeRuleName(rule));\n\t\t\t\t}\n\n\t\t\t\tgroupMatching = {\n\t\t\t\t\trule: rule,\n\t\t\t\t\tmatches: matches,\n\t\t\t\t\tgroups: []\n\t\t\t\t};\n\t\t\t\tfor (let i = 0; i < result.length; i++) {\n\t\t\t\t\tgroupMatching.groups[i] = {\n\t\t\t\t\t\taction: result[i],\n\t\t\t\t\t\tmatched: matches[i + 1]\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tpos -= matched.length;\n\t\t\t\t// call recursively to initiate first result match\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\t// regular result\n\n\t\t\t\t// check for '@rematch'\n\t\t\t\tif (result === '@rematch') {\n\t\t\t\t\tpos -= matched.length;\n\t\t\t\t\tmatched = ''; // better set the next state too..\n\t\t\t\t\tmatches = null;\n\t\t\t\t\tresult = '';\n\n\t\t\t\t\t// Even though `@rematch` was specified, if `nextEmbedded` also specified,\n\t\t\t\t\t// a state transition should occur.\n\t\t\t\t\tif (enteringEmbeddedLanguage !== null) {\n\t\t\t\t\t\treturn computeNewStateForEmbeddedLanguage(enteringEmbeddedLanguage);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// check progress\n\t\t\t\tif (matched.length === 0) {\n\t\t\t\t\tif (lineLength === 0 || stackLen0 !== stack.depth || state !== stack.state || (!groupMatching ? 0 : groupMatching.groups.length) !== groupLen0) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow monarchCommon.createError(this._lexer, 'no progress in tokenizer in rule: ' + this._safeRuleName(rule));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// return the result (and check for brace matching)\n\t\t\t\t// todo: for efficiency we could pre-sanitize tokenPostfix and substitutions\n\t\t\t\tlet tokenType: string | null = null;\n\t\t\t\tif (monarchCommon.isString(result) && result.indexOf('@brackets') === 0) {\n\t\t\t\t\tconst rest = result.substr('@brackets'.length);\n\t\t\t\t\tconst bracket = findBracket(this._lexer, matched);\n\t\t\t\t\tif (!bracket) {\n\t\t\t\t\t\tthrow monarchCommon.createError(this._lexer, '@brackets token returned but no bracket defined as: ' + matched);\n\t\t\t\t\t}\n\t\t\t\t\ttokenType = monarchCommon.sanitize(bracket.token + rest);\n\t\t\t\t} else {\n\t\t\t\t\tconst token = (result === '' ? '' : result + this._lexer.tokenPostfix);\n\t\t\t\t\ttokenType = monarchCommon.sanitize(token);\n\t\t\t\t}\n\n\t\t\t\tif (pos0 < lineWithoutLFLength) {\n\t\t\t\t\ttokensCollector.emit(pos0 + offsetDelta, tokenType);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (enteringEmbeddedLanguage !== null) {\n\t\t\t\treturn computeNewStateForEmbeddedLanguage(enteringEmbeddedLanguage);\n\t\t\t}\n\t\t}\n\n\t\treturn MonarchLineStateFactory.create(stack, embeddedLanguageData);\n\t}\n\n\tprivate _getNestedEmbeddedLanguageData(languageId: string): EmbeddedLanguageData {\n\t\tif (!this._languageService.isRegisteredLanguageId(languageId)) {\n\t\t\treturn new EmbeddedLanguageData(languageId, NullState);\n\t\t}\n\n\t\tif (languageId !== this._languageId) {\n\t\t\t// Fire language loading event\n\t\t\tlanguages.TokenizationRegistry.getOrCreate(languageId);\n\t\t\tthis._embeddedLanguages[languageId] = true;\n\t\t}\n\n\t\tconst tokenizationSupport = languages.TokenizationRegistry.get(languageId);\n\t\tif (tokenizationSupport) {\n\t\t\treturn new EmbeddedLanguageData(languageId, tokenizationSupport.getInitialState());\n\t\t}\n\n\t\treturn new EmbeddedLanguageData(languageId, NullState);\n\t}\n}\n\n/**\n * Searches for a bracket in the 'brackets' attribute that matches the input.\n */\nfunction findBracket(lexer: monarchCommon.ILexer, matched: string) {\n\tif (!matched) {\n\t\treturn null;\n\t}\n\tmatched = monarchCommon.fixCase(lexer, matched);\n\n\tconst brackets = lexer.brackets;\n\tfor (const bracket of brackets) {\n\t\tif (bracket.open === matched) {\n\t\t\treturn { token: bracket.token, bracketType: monarchCommon.MonarchBracket.Open };\n\t\t}\n\t\telse if (bracket.close === matched) {\n\t\t\treturn { token: bracket.token, bracketType: monarchCommon.MonarchBracket.Close };\n\t\t}\n\t}\n\treturn null;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as strings from 'vs/base/common/strings';\nimport { IViewLineTokens, LineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { ColorId, FontStyle, ILanguageIdCodec, ITokenizationSupport, MetadataConsts, TokenizationRegistry } from 'vs/editor/common/languages';\nimport { ILanguageService } from 'vs/editor/common/services/language';\nimport { RenderLineInput, renderViewLine2 as renderViewLine } from 'vs/editor/common/viewLayout/viewLineRenderer';\nimport { ViewLineRenderingData } from 'vs/editor/common/viewModel/viewModel';\nimport { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneTheme';\nimport { MonarchTokenizer } from 'vs/editor/standalone/common/monarch/monarchLexer';\n\nconst ttPolicy = window.trustedTypes?.createPolicy('standaloneColorizer', { createHTML: value => value });\n\nexport interface IColorizerOptions {\n\ttabSize?: number;\n}\n\nexport interface IColorizerElementOptions extends IColorizerOptions {\n\ttheme?: string;\n\tmimeType?: string;\n}\n\nexport class Colorizer {\n\n\tpublic static colorizeElement(themeService: IStandaloneThemeService, languageService: ILanguageService, domNode: HTMLElement, options: IColorizerElementOptions): Promise {\n\t\toptions = options || {};\n\t\tconst theme = options.theme || 'vs';\n\t\tconst mimeType = options.mimeType || domNode.getAttribute('lang') || domNode.getAttribute('data-lang');\n\t\tif (!mimeType) {\n\t\t\tconsole.error('Mode not detected');\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tconst languageId = languageService.getLanguageIdByMimeType(mimeType) || mimeType;\n\n\t\tthemeService.setTheme(theme);\n\n\t\tconst text = domNode.firstChild ? domNode.firstChild.nodeValue : '';\n\t\tdomNode.className += ' ' + theme;\n\t\tconst render = (str: string) => {\n\t\t\tconst trustedhtml = ttPolicy?.createHTML(str) ?? str;\n\t\t\tdomNode.innerHTML = trustedhtml as string;\n\t\t};\n\t\treturn this.colorize(languageService, text || '', languageId, options).then(render, (err) => console.error(err));\n\t}\n\n\tpublic static async colorize(languageService: ILanguageService, text: string, languageId: string, options: IColorizerOptions | null | undefined): Promise {\n\t\tconst languageIdCodec = languageService.languageIdCodec;\n\t\tlet tabSize = 4;\n\t\tif (options && typeof options.tabSize === 'number') {\n\t\t\ttabSize = options.tabSize;\n\t\t}\n\n\t\tif (strings.startsWithUTF8BOM(text)) {\n\t\t\ttext = text.substr(1);\n\t\t}\n\t\tconst lines = strings.splitLines(text);\n\t\tif (!languageService.isRegisteredLanguageId(languageId)) {\n\t\t\treturn _fakeColorize(lines, tabSize, languageIdCodec);\n\t\t}\n\n\t\tconst tokenizationSupport = await TokenizationRegistry.getOrCreate(languageId);\n\t\tif (tokenizationSupport) {\n\t\t\treturn _colorize(lines, tabSize, tokenizationSupport, languageIdCodec);\n\t\t}\n\n\t\treturn _fakeColorize(lines, tabSize, languageIdCodec);\n\t}\n\n\tpublic static colorizeLine(line: string, mightContainNonBasicASCII: boolean, mightContainRTL: boolean, tokens: IViewLineTokens, tabSize: number = 4): string {\n\t\tconst isBasicASCII = ViewLineRenderingData.isBasicASCII(line, mightContainNonBasicASCII);\n\t\tconst containsRTL = ViewLineRenderingData.containsRTL(line, isBasicASCII, mightContainRTL);\n\t\tconst renderResult = renderViewLine(new RenderLineInput(\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\tline,\n\t\t\tfalse,\n\t\t\tisBasicASCII,\n\t\t\tcontainsRTL,\n\t\t\t0,\n\t\t\ttokens,\n\t\t\t[],\n\t\t\ttabSize,\n\t\t\t0,\n\t\t\t0,\n\t\t\t0,\n\t\t\t0,\n\t\t\t-1,\n\t\t\t'none',\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t\tnull\n\t\t));\n\t\treturn renderResult.html;\n\t}\n\n\tpublic static colorizeModelLine(model: ITextModel, lineNumber: number, tabSize: number = 4): string {\n\t\tconst content = model.getLineContent(lineNumber);\n\t\tmodel.forceTokenization(lineNumber);\n\t\tconst tokens = model.getLineTokens(lineNumber);\n\t\tconst inflatedTokens = tokens.inflate();\n\t\treturn this.colorizeLine(content, model.mightContainNonBasicASCII(), model.mightContainRTL(), inflatedTokens, tabSize);\n\t}\n}\n\nfunction _colorize(lines: string[], tabSize: number, tokenizationSupport: ITokenizationSupport, languageIdCodec: ILanguageIdCodec): Promise {\n\treturn new Promise((c, e) => {\n\t\tconst execute = () => {\n\t\t\tconst result = _actualColorize(lines, tabSize, tokenizationSupport, languageIdCodec);\n\t\t\tif (tokenizationSupport instanceof MonarchTokenizer) {\n\t\t\t\tconst status = tokenizationSupport.getLoadStatus();\n\t\t\t\tif (status.loaded === false) {\n\t\t\t\t\tstatus.promise.then(execute, e);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tc(result);\n\t\t};\n\t\texecute();\n\t});\n}\n\nfunction _fakeColorize(lines: string[], tabSize: number, languageIdCodec: ILanguageIdCodec): string {\n\tlet html: string[] = [];\n\n\tconst defaultMetadata = (\n\t\t(FontStyle.None << MetadataConsts.FONT_STYLE_OFFSET)\n\t\t| (ColorId.DefaultForeground << MetadataConsts.FOREGROUND_OFFSET)\n\t\t| (ColorId.DefaultBackground << MetadataConsts.BACKGROUND_OFFSET)\n\t) >>> 0;\n\n\tconst tokens = new Uint32Array(2);\n\ttokens[0] = 0;\n\ttokens[1] = defaultMetadata;\n\n\tfor (let i = 0, length = lines.length; i < length; i++) {\n\t\tconst line = lines[i];\n\n\t\ttokens[0] = line.length;\n\t\tconst lineTokens = new LineTokens(tokens, line, languageIdCodec);\n\n\t\tconst isBasicASCII = ViewLineRenderingData.isBasicASCII(line, /* check for basic ASCII */true);\n\t\tconst containsRTL = ViewLineRenderingData.containsRTL(line, isBasicASCII, /* check for RTL */true);\n\t\tconst renderResult = renderViewLine(new RenderLineInput(\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\tline,\n\t\t\tfalse,\n\t\t\tisBasicASCII,\n\t\t\tcontainsRTL,\n\t\t\t0,\n\t\t\tlineTokens,\n\t\t\t[],\n\t\t\ttabSize,\n\t\t\t0,\n\t\t\t0,\n\t\t\t0,\n\t\t\t0,\n\t\t\t-1,\n\t\t\t'none',\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t\tnull\n\t\t));\n\n\t\thtml = html.concat(renderResult.html);\n\t\thtml.push('
    ');\n\t}\n\n\treturn html.join('');\n}\n\nfunction _actualColorize(lines: string[], tabSize: number, tokenizationSupport: ITokenizationSupport, languageIdCodec: ILanguageIdCodec): string {\n\tlet html: string[] = [];\n\tlet state = tokenizationSupport.getInitialState();\n\n\tfor (let i = 0, length = lines.length; i < length; i++) {\n\t\tconst line = lines[i];\n\t\tconst tokenizeResult = tokenizationSupport.tokenizeEncoded(line, true, state);\n\t\tLineTokens.convertToEndOffset(tokenizeResult.tokens, line.length);\n\t\tconst lineTokens = new LineTokens(tokenizeResult.tokens, line, languageIdCodec);\n\t\tconst isBasicASCII = ViewLineRenderingData.isBasicASCII(line, /* check for basic ASCII */true);\n\t\tconst containsRTL = ViewLineRenderingData.containsRTL(line, isBasicASCII, /* check for RTL */true);\n\t\tconst renderResult = renderViewLine(new RenderLineInput(\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\tline,\n\t\t\tfalse,\n\t\t\tisBasicASCII,\n\t\t\tcontainsRTL,\n\t\t\t0,\n\t\t\tlineTokens.inflate(),\n\t\t\t[],\n\t\t\ttabSize,\n\t\t\t0,\n\t\t\t0,\n\t\t\t0,\n\t\t\t0,\n\t\t\t-1,\n\t\t\t'none',\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t\tnull\n\t\t));\n\n\t\thtml = html.concat(renderResult.html);\n\t\thtml.push('
    ');\n\n\t\tstate = tokenizeResult.endState;\n\t}\n\n\treturn html.join('');\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Checkbox } from 'vs/base/browser/ui/checkbox/checkbox';\nimport { Codicon } from 'vs/base/common/codicons';\nimport { Color } from 'vs/base/common/color';\nimport * as nls from 'vs/nls';\n\nexport interface IFindInputCheckboxOpts {\n\treadonly appendTitle: string;\n\treadonly isChecked: boolean;\n\treadonly inputActiveOptionBorder?: Color;\n\treadonly inputActiveOptionForeground?: Color;\n\treadonly inputActiveOptionBackground?: Color;\n}\n\nconst NLS_CASE_SENSITIVE_CHECKBOX_LABEL = nls.localize('caseDescription', \"Match Case\");\nconst NLS_WHOLE_WORD_CHECKBOX_LABEL = nls.localize('wordsDescription', \"Match Whole Word\");\nconst NLS_REGEX_CHECKBOX_LABEL = nls.localize('regexDescription', \"Use Regular Expression\");\n\nexport class CaseSensitiveCheckbox extends Checkbox {\n\tconstructor(opts: IFindInputCheckboxOpts) {\n\t\tsuper({\n\t\t\ticon: Codicon.caseSensitive,\n\t\t\ttitle: NLS_CASE_SENSITIVE_CHECKBOX_LABEL + opts.appendTitle,\n\t\t\tisChecked: opts.isChecked,\n\t\t\tinputActiveOptionBorder: opts.inputActiveOptionBorder,\n\t\t\tinputActiveOptionForeground: opts.inputActiveOptionForeground,\n\t\t\tinputActiveOptionBackground: opts.inputActiveOptionBackground\n\t\t});\n\t}\n}\n\nexport class WholeWordsCheckbox extends Checkbox {\n\tconstructor(opts: IFindInputCheckboxOpts) {\n\t\tsuper({\n\t\t\ticon: Codicon.wholeWord,\n\t\t\ttitle: NLS_WHOLE_WORD_CHECKBOX_LABEL + opts.appendTitle,\n\t\t\tisChecked: opts.isChecked,\n\t\t\tinputActiveOptionBorder: opts.inputActiveOptionBorder,\n\t\t\tinputActiveOptionForeground: opts.inputActiveOptionForeground,\n\t\t\tinputActiveOptionBackground: opts.inputActiveOptionBackground\n\t\t});\n\t}\n}\n\nexport class RegexCheckbox extends Checkbox {\n\tconstructor(opts: IFindInputCheckboxOpts) {\n\t\tsuper({\n\t\t\ticon: Codicon.regex,\n\t\t\ttitle: NLS_REGEX_CHECKBOX_LABEL + opts.appendTitle,\n\t\t\tisChecked: opts.isChecked,\n\t\t\tinputActiveOptionBorder: opts.inputActiveOptionBorder,\n\t\t\tinputActiveOptionForeground: opts.inputActiveOptionForeground,\n\t\t\tinputActiveOptionBackground: opts.inputActiveOptionBackground\n\t\t});\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget';\nimport { IHoverDelegate, IHoverDelegateOptions, IHoverDelegateTarget, IHoverWidget } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';\nimport { IIconLabelMarkdownString } from 'vs/base/browser/ui/iconLabel/iconLabel';\nimport { TimeoutTimer } from 'vs/base/common/async';\nimport { CancellationTokenSource } from 'vs/base/common/cancellation';\nimport { IMarkdownString, isMarkdownString } from 'vs/base/common/htmlContent';\nimport { stripIcons } from 'vs/base/common/iconLabels';\nimport { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';\nimport { isFunction, isString } from 'vs/base/common/types';\nimport { localize } from 'vs/nls';\n\nexport function setupNativeHover(htmlElement: HTMLElement, tooltip: string | IIconLabelMarkdownString | undefined): void {\n\tif (isString(tooltip)) {\n\t\t// Icons don't render in the native hover so we strip them out\n\t\thtmlElement.title = stripIcons(tooltip);\n\t} else if (tooltip?.markdownNotSupportedFallback) {\n\t\thtmlElement.title = tooltip.markdownNotSupportedFallback;\n\t} else {\n\t\thtmlElement.removeAttribute('title');\n\t}\n}\n\nexport interface ICustomHover extends IDisposable {\n\n\t/**\n\t * Allows to programmatically open the hover.\n\t */\n\tshow(focus?: boolean): void;\n\n\t/**\n\t * Allows to programmatically hide the hover.\n\t */\n\thide(): void;\n\n\t/**\n\t * Updates the contents of the hover.\n\t */\n\tupdate(tooltip: string | IIconLabelMarkdownString | HTMLElement): void;\n}\n\ntype MarkdownTooltipContent = string | IIconLabelMarkdownString | HTMLElement | undefined;\ntype ResolvedMarkdownTooltipContent = IMarkdownString | string | HTMLElement | undefined;\nclass UpdatableHoverWidget implements IDisposable {\n\n\tprivate _hoverWidget: IHoverWidget | undefined;\n\tprivate _cancellationTokenSource: CancellationTokenSource | undefined;\n\n\tconstructor(private hoverDelegate: IHoverDelegate, private target: IHoverDelegateTarget | HTMLElement, private fadeInAnimation: boolean) {\n\t}\n\n\tasync update(markdownTooltip: MarkdownTooltipContent, focus?: boolean): Promise {\n\t\tif (this._cancellationTokenSource) {\n\t\t\t// there's an computation ongoing, cancel it\n\t\t\tthis._cancellationTokenSource.dispose(true);\n\t\t\tthis._cancellationTokenSource = undefined;\n\t\t}\n\t\tif (this.isDisposed) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet resolvedContent;\n\t\tif (markdownTooltip === undefined || isString(markdownTooltip) || markdownTooltip instanceof HTMLElement) {\n\t\t\tresolvedContent = markdownTooltip;\n\t\t} else if (!isFunction(markdownTooltip.markdown)) {\n\t\t\tresolvedContent = markdownTooltip.markdown ?? markdownTooltip.markdownNotSupportedFallback;\n\t\t} else {\n\t\t\t// compute the content, potentially long-running\n\n\t\t\t// show 'Loading' if no hover is up yet\n\t\t\tif (!this._hoverWidget) {\n\t\t\t\tthis.show(localize('iconLabel.loading', \"Loading...\"), focus);\n\t\t\t}\n\n\t\t\t// compute the content\n\t\t\tthis._cancellationTokenSource = new CancellationTokenSource();\n\t\t\tconst token = this._cancellationTokenSource.token;\n\t\t\tresolvedContent = await markdownTooltip.markdown(token);\n\n\t\t\tif (this.isDisposed || token.isCancellationRequested) {\n\t\t\t\t// either the widget has been closed in the meantime\n\t\t\t\t// or there has been a new call to `update`\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.show(resolvedContent, focus);\n\t}\n\n\tprivate show(content: ResolvedMarkdownTooltipContent, focus?: boolean): void {\n\t\tconst oldHoverWidget = this._hoverWidget;\n\n\t\tif (this.hasContent(content)) {\n\t\t\tconst hoverOptions: IHoverDelegateOptions = {\n\t\t\t\tcontent,\n\t\t\t\ttarget: this.target,\n\t\t\t\tshowPointer: this.hoverDelegate.placement === 'element',\n\t\t\t\thoverPosition: HoverPosition.BELOW,\n\t\t\t\tskipFadeInAnimation: !this.fadeInAnimation || !!oldHoverWidget // do not fade in if the hover is already showing\n\t\t\t};\n\n\t\t\tthis._hoverWidget = this.hoverDelegate.showHover(hoverOptions, focus);\n\t\t}\n\t\toldHoverWidget?.dispose();\n\t}\n\n\tprivate hasContent(content: ResolvedMarkdownTooltipContent): content is NonNullable {\n\t\tif (!content) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (isMarkdownString(content)) {\n\t\t\treturn !!content.value;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tget isDisposed() {\n\t\treturn this._hoverWidget?.isDisposed;\n\t}\n\n\tdispose(): void {\n\t\tthis._hoverWidget?.dispose();\n\t\tthis._cancellationTokenSource?.dispose(true);\n\t\tthis._cancellationTokenSource = undefined;\n\t}\n}\n\nexport function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTMLElement, markdownTooltip: string | IIconLabelMarkdownString | HTMLElement): ICustomHover {\n\tlet hoverPreparation: IDisposable | undefined;\n\n\tlet hoverWidget: UpdatableHoverWidget | undefined;\n\n\tconst hideHover = (disposeWidget: boolean, disposePreparation: boolean) => {\n\t\tif (disposeWidget) {\n\t\t\thoverWidget?.dispose();\n\t\t\thoverWidget = undefined;\n\t\t}\n\t\tif (disposePreparation) {\n\t\t\thoverPreparation?.dispose();\n\t\t\thoverPreparation = undefined;\n\t\t}\n\t\thoverDelegate.onDidHideHover?.();\n\t};\n\n\tconst triggerShowHover = (delay: number, focus?: boolean, target?: IHoverDelegateTarget) => {\n\t\treturn new TimeoutTimer(async () => {\n\t\t\tif (!hoverWidget || hoverWidget.isDisposed) {\n\t\t\t\thoverWidget = new UpdatableHoverWidget(hoverDelegate, target || htmlElement, delay > 0);\n\t\t\t\tawait hoverWidget.update(markdownTooltip, focus);\n\t\t\t}\n\t\t}, delay);\n\t};\n\n\tconst onMouseOver = () => {\n\t\tif (hoverPreparation) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst toDispose: DisposableStore = new DisposableStore();\n\n\t\tconst onMouseLeave = (e: MouseEvent) => hideHover(false, (e).fromElement === htmlElement);\n\t\ttoDispose.add(dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_LEAVE, onMouseLeave, true));\n\n\t\tconst onMouseDown = () => hideHover(true, true);\n\t\ttoDispose.add(dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_DOWN, onMouseDown, true));\n\n\t\tconst target: IHoverDelegateTarget = {\n\t\t\ttargetElements: [htmlElement],\n\t\t\tdispose: () => { }\n\t\t};\n\t\tif (hoverDelegate.placement === undefined || hoverDelegate.placement === 'mouse') {\n\t\t\t// track the mouse position\n\t\t\tconst onMouseMove = (e: MouseEvent) => target.x = e.x + 10;\n\t\t\ttoDispose.add(dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_MOVE, onMouseMove, true));\n\t\t}\n\t\ttoDispose.add(triggerShowHover(hoverDelegate.delay, false, target));\n\n\t\thoverPreparation = toDispose;\n\t};\n\tconst mouseOverDomEmitter = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_OVER, onMouseOver, true);\n\tconst hover: ICustomHover = {\n\t\tshow: focus => {\n\t\t\thideHover(false, true); // terminate a ongoing mouse over preparation\n\t\t\ttriggerShowHover(0, focus); // show hover immediately\n\t\t},\n\t\thide: () => {\n\t\t\thideHover(true, true);\n\t\t},\n\t\tupdate: async newTooltip => {\n\t\t\tmarkdownTooltip = newTooltip;\n\t\t\tawait hoverWidget?.update(markdownTooltip);\n\t\t},\n\t\tdispose: () => {\n\t\t\tmouseOverDomEmitter.dispose();\n\t\t\thideHover(true, true);\n\t\t}\n\t};\n\treturn hover;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';\nimport { IHoverDelegate } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';\nimport { setupCustomHover, setupNativeHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover';\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { IMatch } from 'vs/base/common/filters';\nimport { IMarkdownString } from 'vs/base/common/htmlContent';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport { equals } from 'vs/base/common/objects';\nimport { Range } from 'vs/base/common/range';\nimport 'vs/css!./iconlabel';\n\nexport interface IIconLabelCreationOptions {\n\tsupportHighlights?: boolean;\n\tsupportDescriptionHighlights?: boolean;\n\tsupportIcons?: boolean;\n\thoverDelegate?: IHoverDelegate;\n}\n\nexport interface IIconLabelMarkdownString {\n\tmarkdown: IMarkdownString | string | HTMLElement | undefined | ((token: CancellationToken) => Promise);\n\tmarkdownNotSupportedFallback: string | undefined;\n}\n\nexport interface IIconLabelValueOptions {\n\ttitle?: string | IIconLabelMarkdownString;\n\tdescriptionTitle?: string;\n\textraClasses?: string[];\n\titalic?: boolean;\n\tstrikethrough?: boolean;\n\tmatches?: IMatch[];\n\tlabelEscapeNewLines?: boolean;\n\tdescriptionMatches?: IMatch[];\n\treadonly separator?: string;\n\treadonly domId?: string;\n}\n\nclass FastLabelNode {\n\tprivate disposed: boolean | undefined;\n\tprivate _textContent: string | undefined;\n\tprivate _className: string | undefined;\n\tprivate _empty: boolean | undefined;\n\n\tconstructor(private _element: HTMLElement) {\n\t}\n\n\tget element(): HTMLElement {\n\t\treturn this._element;\n\t}\n\n\tset textContent(content: string) {\n\t\tif (this.disposed || content === this._textContent) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._textContent = content;\n\t\tthis._element.textContent = content;\n\t}\n\n\tset className(className: string) {\n\t\tif (this.disposed || className === this._className) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._className = className;\n\t\tthis._element.className = className;\n\t}\n\n\tset empty(empty: boolean) {\n\t\tif (this.disposed || empty === this._empty) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._empty = empty;\n\t\tthis._element.style.marginLeft = empty ? '0' : '';\n\t}\n\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t}\n}\n\nexport class IconLabel extends Disposable {\n\n\tprivate readonly domNode: FastLabelNode;\n\n\tprivate readonly nameNode: Label | LabelWithHighlights;\n\n\tprivate readonly descriptionContainer: FastLabelNode;\n\tprivate descriptionNode: FastLabelNode | HighlightedLabel | undefined;\n\tprivate readonly descriptionNodeFactory: () => FastLabelNode | HighlightedLabel;\n\n\tprivate readonly labelContainer: HTMLElement;\n\n\tprivate readonly hoverDelegate: IHoverDelegate | undefined;\n\tprivate readonly customHovers: Map = new Map();\n\n\tconstructor(container: HTMLElement, options?: IIconLabelCreationOptions) {\n\t\tsuper();\n\n\t\tthis.domNode = this._register(new FastLabelNode(dom.append(container, dom.$('.monaco-icon-label'))));\n\n\t\tthis.labelContainer = dom.append(this.domNode.element, dom.$('.monaco-icon-label-container'));\n\n\t\tconst nameContainer = dom.append(this.labelContainer, dom.$('span.monaco-icon-name-container'));\n\t\tthis.descriptionContainer = this._register(new FastLabelNode(dom.append(this.labelContainer, dom.$('span.monaco-icon-description-container'))));\n\n\t\tif (options?.supportHighlights || options?.supportIcons) {\n\t\t\tthis.nameNode = new LabelWithHighlights(nameContainer, !!options.supportIcons);\n\t\t} else {\n\t\t\tthis.nameNode = new Label(nameContainer);\n\t\t}\n\n\t\tif (options?.supportDescriptionHighlights) {\n\t\t\tthis.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.descriptionContainer.element, dom.$('span.label-description')), { supportIcons: !!options.supportIcons });\n\t\t} else {\n\t\t\tthis.descriptionNodeFactory = () => this._register(new FastLabelNode(dom.append(this.descriptionContainer.element, dom.$('span.label-description'))));\n\t\t}\n\n\t\tthis.hoverDelegate = options?.hoverDelegate;\n\t}\n\n\tget element(): HTMLElement {\n\t\treturn this.domNode.element;\n\t}\n\n\tsetLabel(label: string | string[], description?: string, options?: IIconLabelValueOptions): void {\n\t\tconst classes = ['monaco-icon-label'];\n\t\tif (options) {\n\t\t\tif (options.extraClasses) {\n\t\t\t\tclasses.push(...options.extraClasses);\n\t\t\t}\n\n\t\t\tif (options.italic) {\n\t\t\t\tclasses.push('italic');\n\t\t\t}\n\n\t\t\tif (options.strikethrough) {\n\t\t\t\tclasses.push('strikethrough');\n\t\t\t}\n\t\t}\n\n\t\tthis.domNode.className = classes.join(' ');\n\t\tthis.setupHover(options?.descriptionTitle ? this.labelContainer : this.element, options?.title);\n\n\t\tthis.nameNode.setLabel(label, options);\n\n\t\tif (description || this.descriptionNode) {\n\t\t\tif (!this.descriptionNode) {\n\t\t\t\tthis.descriptionNode = this.descriptionNodeFactory(); // description node is created lazily on demand\n\t\t\t}\n\n\t\t\tif (this.descriptionNode instanceof HighlightedLabel) {\n\t\t\t\tthis.descriptionNode.set(description || '', options ? options.descriptionMatches : undefined);\n\t\t\t\tthis.setupHover(this.descriptionNode.element, options?.descriptionTitle);\n\t\t\t} else {\n\t\t\t\tthis.descriptionNode.textContent = description || '';\n\t\t\t\tthis.setupHover(this.descriptionNode.element, options?.descriptionTitle || '');\n\t\t\t\tthis.descriptionNode.empty = !description;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate setupHover(htmlElement: HTMLElement, tooltip: string | IIconLabelMarkdownString | undefined): void {\n\t\tconst previousCustomHover = this.customHovers.get(htmlElement);\n\t\tif (previousCustomHover) {\n\t\t\tpreviousCustomHover.dispose();\n\t\t\tthis.customHovers.delete(htmlElement);\n\t\t}\n\n\t\tif (!tooltip) {\n\t\t\thtmlElement.removeAttribute('title');\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.hoverDelegate) {\n\t\t\tsetupNativeHover(htmlElement, tooltip);\n\t\t} else {\n\t\t\tconst hoverDisposable = setupCustomHover(this.hoverDelegate, htmlElement, tooltip);\n\t\t\tif (hoverDisposable) {\n\t\t\t\tthis.customHovers.set(htmlElement, hoverDisposable);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic override dispose() {\n\t\tsuper.dispose();\n\t\tfor (const disposable of this.customHovers.values()) {\n\t\t\tdisposable.dispose();\n\t\t}\n\t\tthis.customHovers.clear();\n\t}\n}\n\nclass Label {\n\n\tprivate label: string | string[] | undefined = undefined;\n\tprivate singleLabel: HTMLElement | undefined = undefined;\n\tprivate options: IIconLabelValueOptions | undefined;\n\n\tconstructor(private container: HTMLElement) { }\n\n\tsetLabel(label: string | string[], options?: IIconLabelValueOptions): void {\n\t\tif (this.label === label && equals(this.options, options)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.label = label;\n\t\tthis.options = options;\n\n\t\tif (typeof label === 'string') {\n\t\t\tif (!this.singleLabel) {\n\t\t\t\tthis.container.innerText = '';\n\t\t\t\tthis.container.classList.remove('multiple');\n\t\t\t\tthis.singleLabel = dom.append(this.container, dom.$('a.label-name', { id: options?.domId }));\n\t\t\t}\n\n\t\t\tthis.singleLabel.textContent = label;\n\t\t} else {\n\t\t\tthis.container.innerText = '';\n\t\t\tthis.container.classList.add('multiple');\n\t\t\tthis.singleLabel = undefined;\n\n\t\t\tfor (let i = 0; i < label.length; i++) {\n\t\t\t\tconst l = label[i];\n\t\t\t\tconst id = options?.domId && `${options?.domId}_${i}`;\n\n\t\t\t\tdom.append(this.container, dom.$('a.label-name', { id, 'data-icon-label-count': label.length, 'data-icon-label-index': i, 'role': 'treeitem' }, l));\n\n\t\t\t\tif (i < label.length - 1) {\n\t\t\t\t\tdom.append(this.container, dom.$('span.label-separator', undefined, options?.separator || '/'));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction splitMatches(labels: string[], separator: string, matches: IMatch[] | undefined): IMatch[][] | undefined {\n\tif (!matches) {\n\t\treturn undefined;\n\t}\n\n\tlet labelStart = 0;\n\n\treturn labels.map(label => {\n\t\tconst labelRange = { start: labelStart, end: labelStart + label.length };\n\n\t\tconst result = matches\n\t\t\t.map(match => Range.intersect(labelRange, match))\n\t\t\t.filter(range => !Range.isEmpty(range))\n\t\t\t.map(({ start, end }) => ({ start: start - labelStart, end: end - labelStart }));\n\n\t\tlabelStart = labelRange.end + separator.length;\n\t\treturn result;\n\t});\n}\n\nclass LabelWithHighlights {\n\n\tprivate label: string | string[] | undefined = undefined;\n\tprivate singleLabel: HighlightedLabel | undefined = undefined;\n\tprivate options: IIconLabelValueOptions | undefined;\n\n\tconstructor(private container: HTMLElement, private supportIcons: boolean) { }\n\n\tsetLabel(label: string | string[], options?: IIconLabelValueOptions): void {\n\t\tif (this.label === label && equals(this.options, options)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.label = label;\n\t\tthis.options = options;\n\n\t\tif (typeof label === 'string') {\n\t\t\tif (!this.singleLabel) {\n\t\t\t\tthis.container.innerText = '';\n\t\t\t\tthis.container.classList.remove('multiple');\n\t\t\t\tthis.singleLabel = new HighlightedLabel(dom.append(this.container, dom.$('a.label-name', { id: options?.domId })), { supportIcons: this.supportIcons });\n\t\t\t}\n\n\t\t\tthis.singleLabel.set(label, options?.matches, undefined, options?.labelEscapeNewLines);\n\t\t} else {\n\t\t\tthis.container.innerText = '';\n\t\t\tthis.container.classList.add('multiple');\n\t\t\tthis.singleLabel = undefined;\n\n\t\t\tconst separator = options?.separator || '/';\n\t\t\tconst matches = splitMatches(label, separator, options?.matches);\n\n\t\t\tfor (let i = 0; i < label.length; i++) {\n\t\t\t\tconst l = label[i];\n\t\t\t\tconst m = matches ? matches[i] : undefined;\n\t\t\t\tconst id = options?.domId && `${options?.domId}_${i}`;\n\n\t\t\t\tconst name = dom.$('a.label-name', { id, 'data-icon-label-count': label.length, 'data-icon-label-index': i, 'role': 'treeitem' });\n\t\t\t\tconst highlightedLabel = new HighlightedLabel(dom.append(this.container, name), { supportIcons: this.supportIcons });\n\t\t\t\thighlightedLabel.set(l, m, undefined, options?.labelEscapeNewLines);\n\n\t\t\t\tif (i < label.length - 1) {\n\t\t\t\t\tdom.append(name, dom.$('span.label-separator', undefined, separator));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { DragAndDropData, IDragAndDropData, StaticDND } from 'vs/base/browser/dnd';\nimport { $, addDisposableListener, append, clearNode, createStyleSheet, getDomNodePagePosition, hasParentWithClass } from 'vs/base/browser/dom';\nimport { DomEmitter } from 'vs/base/browser/event';\nimport { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { IIdentityProvider, IKeyboardNavigationDelegate, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, IListMouseEvent, IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';\nimport { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';\nimport { DefaultKeyboardNavigationDelegate, IListOptions, IListStyles, isInputElement, isMonacoEditor, List, MouseController } from 'vs/base/browser/ui/list/listWidget';\nimport { getVisibleState, isFilterResult } from 'vs/base/browser/ui/tree/indexTreeModel';\nimport { ICollapseStateChangeEvent, ITreeDragAndDrop, ITreeEvent, ITreeFilter, ITreeModel, ITreeModelSpliceEvent, ITreeMouseEvent, ITreeNode, ITreeRenderer, TreeDragOverBubble, TreeFilterResult, TreeMouseEventTarget, TreeVisibility } from 'vs/base/browser/ui/tree/tree';\nimport { distinct, equals, range } from 'vs/base/common/arrays';\nimport { disposableTimeout } from 'vs/base/common/async';\nimport { Codicon } from 'vs/base/common/codicons';\nimport { SetMap } from 'vs/base/common/collections';\nimport { Emitter, Event, EventBufferer, Relay } from 'vs/base/common/event';\nimport { fuzzyScore, FuzzyScore } from 'vs/base/common/filters';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { Disposable, DisposableStore, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { clamp } from 'vs/base/common/numbers';\nimport { isMacintosh } from 'vs/base/common/platform';\nimport { ISpliceable } from 'vs/base/common/sequence';\nimport 'vs/css!./media/tree';\nimport { localize } from 'vs/nls';\n\nclass TreeElementsDragAndDropData extends ElementsDragAndDropData {\n\n\tconstructor(private data: ElementsDragAndDropData, TContext>) {\n\t\tsuper(data.elements.map(node => node.element));\n\t}\n}\n\nfunction asTreeDragAndDropData(data: IDragAndDropData): IDragAndDropData {\n\tif (data instanceof ElementsDragAndDropData) {\n\t\treturn new TreeElementsDragAndDropData(data);\n\t}\n\n\treturn data;\n}\n\nclass TreeNodeListDragAndDrop implements IListDragAndDrop> {\n\n\tprivate autoExpandNode: ITreeNode | undefined;\n\tprivate autoExpandDisposable: IDisposable = Disposable.None;\n\n\tconstructor(private modelProvider: () => ITreeModel, private dnd: ITreeDragAndDrop) { }\n\n\tgetDragURI(node: ITreeNode): string | null {\n\t\treturn this.dnd.getDragURI(node.element);\n\t}\n\n\tgetDragLabel(nodes: ITreeNode[], originalEvent: DragEvent): string | undefined {\n\t\tif (this.dnd.getDragLabel) {\n\t\t\treturn this.dnd.getDragLabel(nodes.map(node => node.element), originalEvent);\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tonDragStart(data: IDragAndDropData, originalEvent: DragEvent): void {\n\t\tif (this.dnd.onDragStart) {\n\t\t\tthis.dnd.onDragStart(asTreeDragAndDropData(data), originalEvent);\n\t\t}\n\t}\n\n\tonDragOver(data: IDragAndDropData, targetNode: ITreeNode | undefined, targetIndex: number | undefined, originalEvent: DragEvent, raw = true): boolean | IListDragOverReaction {\n\t\tconst result = this.dnd.onDragOver(asTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);\n\t\tconst didChangeAutoExpandNode = this.autoExpandNode !== targetNode;\n\n\t\tif (didChangeAutoExpandNode) {\n\t\t\tthis.autoExpandDisposable.dispose();\n\t\t\tthis.autoExpandNode = targetNode;\n\t\t}\n\n\t\tif (typeof targetNode === 'undefined') {\n\t\t\treturn result;\n\t\t}\n\n\t\tif (didChangeAutoExpandNode && typeof result !== 'boolean' && result.autoExpand) {\n\t\t\tthis.autoExpandDisposable = disposableTimeout(() => {\n\t\t\t\tconst model = this.modelProvider();\n\t\t\t\tconst ref = model.getNodeLocation(targetNode);\n\n\t\t\t\tif (model.isCollapsed(ref)) {\n\t\t\t\t\tmodel.setCollapsed(ref, false);\n\t\t\t\t}\n\n\t\t\t\tthis.autoExpandNode = undefined;\n\t\t\t}, 500);\n\t\t}\n\n\t\tif (typeof result === 'boolean' || !result.accept || typeof result.bubble === 'undefined' || result.feedback) {\n\t\t\tif (!raw) {\n\t\t\t\tconst accept = typeof result === 'boolean' ? result : result.accept;\n\t\t\t\tconst effect = typeof result === 'boolean' ? undefined : result.effect;\n\t\t\t\treturn { accept, effect, feedback: [targetIndex!] };\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tif (result.bubble === TreeDragOverBubble.Up) {\n\t\t\tconst model = this.modelProvider();\n\t\t\tconst ref = model.getNodeLocation(targetNode);\n\t\t\tconst parentRef = model.getParentNodeLocation(ref);\n\t\t\tconst parentNode = model.getNode(parentRef);\n\t\t\tconst parentIndex = parentRef && model.getListIndex(parentRef);\n\n\t\t\treturn this.onDragOver(data, parentNode, parentIndex, originalEvent, false);\n\t\t}\n\n\t\tconst model = this.modelProvider();\n\t\tconst ref = model.getNodeLocation(targetNode);\n\t\tconst start = model.getListIndex(ref);\n\t\tconst length = model.getListRenderCount(ref);\n\n\t\treturn { ...result, feedback: range(start, start + length) };\n\t}\n\n\tdrop(data: IDragAndDropData, targetNode: ITreeNode | undefined, targetIndex: number | undefined, originalEvent: DragEvent): void {\n\t\tthis.autoExpandDisposable.dispose();\n\t\tthis.autoExpandNode = undefined;\n\n\t\tthis.dnd.drop(asTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);\n\t}\n\n\tonDragEnd(originalEvent: DragEvent): void {\n\t\tif (this.dnd.onDragEnd) {\n\t\t\tthis.dnd.onDragEnd(originalEvent);\n\t\t}\n\t}\n}\n\nfunction asListOptions(modelProvider: () => ITreeModel, options?: IAbstractTreeOptions): IListOptions> | undefined {\n\treturn options && {\n\t\t...options,\n\t\tidentityProvider: options.identityProvider && {\n\t\t\tgetId(el) {\n\t\t\t\treturn options.identityProvider!.getId(el.element);\n\t\t\t}\n\t\t},\n\t\tdnd: options.dnd && new TreeNodeListDragAndDrop(modelProvider, options.dnd),\n\t\tmultipleSelectionController: options.multipleSelectionController && {\n\t\t\tisSelectionSingleChangeEvent(e) {\n\t\t\t\treturn options.multipleSelectionController!.isSelectionSingleChangeEvent({ ...e, element: e.element } as any);\n\t\t\t},\n\t\t\tisSelectionRangeChangeEvent(e) {\n\t\t\t\treturn options.multipleSelectionController!.isSelectionRangeChangeEvent({ ...e, element: e.element } as any);\n\t\t\t}\n\t\t},\n\t\taccessibilityProvider: options.accessibilityProvider && {\n\t\t\t...options.accessibilityProvider,\n\t\t\tgetSetSize(node) {\n\t\t\t\tconst model = modelProvider();\n\t\t\t\tconst ref = model.getNodeLocation(node);\n\t\t\t\tconst parentRef = model.getParentNodeLocation(ref);\n\t\t\t\tconst parentNode = model.getNode(parentRef);\n\n\t\t\t\treturn parentNode.visibleChildrenCount;\n\t\t\t},\n\t\t\tgetPosInSet(node) {\n\t\t\t\treturn node.visibleChildIndex + 1;\n\t\t\t},\n\t\t\tisChecked: options.accessibilityProvider && options.accessibilityProvider.isChecked ? (node) => {\n\t\t\t\treturn options.accessibilityProvider!.isChecked!(node.element);\n\t\t\t} : undefined,\n\t\t\tgetRole: options.accessibilityProvider && options.accessibilityProvider.getRole ? (node) => {\n\t\t\t\treturn options.accessibilityProvider!.getRole!(node.element);\n\t\t\t} : () => 'treeitem',\n\t\t\tgetAriaLabel(e) {\n\t\t\t\treturn options.accessibilityProvider!.getAriaLabel(e.element);\n\t\t\t},\n\t\t\tgetWidgetAriaLabel() {\n\t\t\t\treturn options.accessibilityProvider!.getWidgetAriaLabel();\n\t\t\t},\n\t\t\tgetWidgetRole: options.accessibilityProvider && options.accessibilityProvider.getWidgetRole ? () => options.accessibilityProvider!.getWidgetRole!() : () => 'tree',\n\t\t\tgetAriaLevel: options.accessibilityProvider && options.accessibilityProvider.getAriaLevel ? (node) => options.accessibilityProvider!.getAriaLevel!(node.element) : (node) => {\n\t\t\t\treturn node.depth;\n\t\t\t},\n\t\t\tgetActiveDescendantId: options.accessibilityProvider.getActiveDescendantId && (node => {\n\t\t\t\treturn options.accessibilityProvider!.getActiveDescendantId!(node.element);\n\t\t\t})\n\t\t},\n\t\tkeyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && {\n\t\t\t...options.keyboardNavigationLabelProvider,\n\t\t\tgetKeyboardNavigationLabel(node) {\n\t\t\t\treturn options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(node.element);\n\t\t\t}\n\t\t},\n\t\tenableKeyboardNavigation: options.simpleKeyboardNavigation\n\t};\n}\n\nexport class ComposedTreeDelegate implements IListVirtualDelegate {\n\n\tconstructor(private delegate: IListVirtualDelegate) { }\n\n\tgetHeight(element: N): number {\n\t\treturn this.delegate.getHeight(element.element);\n\t}\n\n\tgetTemplateId(element: N): string {\n\t\treturn this.delegate.getTemplateId(element.element);\n\t}\n\n\thasDynamicHeight(element: N): boolean {\n\t\treturn !!this.delegate.hasDynamicHeight && this.delegate.hasDynamicHeight(element.element);\n\t}\n\n\tsetDynamicHeight(element: N, height: number): void {\n\t\tif (this.delegate.setDynamicHeight) {\n\t\t\tthis.delegate.setDynamicHeight(element.element, height);\n\t\t}\n\t}\n}\n\ninterface ITreeListTemplateData {\n\treadonly container: HTMLElement;\n\treadonly indent: HTMLElement;\n\treadonly twistie: HTMLElement;\n\tindentGuidesDisposable: IDisposable;\n\treadonly templateData: T;\n}\n\nexport enum RenderIndentGuides {\n\tNone = 'none',\n\tOnHover = 'onHover',\n\tAlways = 'always'\n}\n\ninterface ITreeRendererOptions {\n\treadonly indent?: number;\n\treadonly renderIndentGuides?: RenderIndentGuides;\n\t// TODO@joao replace this with collapsible: boolean | 'ondemand'\n\treadonly hideTwistiesOfChildlessElements?: boolean;\n}\n\ninterface IRenderData {\n\ttemplateData: ITreeListTemplateData;\n\theight: number;\n}\n\ninterface Collection {\n\treadonly elements: T[];\n\treadonly onDidChange: Event;\n}\n\nclass EventCollection implements Collection {\n\n\treadonly onDidChange: Event;\n\n\tget elements(): T[] {\n\t\treturn this._elements;\n\t}\n\n\tconstructor(onDidChange: Event, private _elements: T[] = []) {\n\t\tthis.onDidChange = Event.forEach(onDidChange, elements => this._elements = elements);\n\t}\n}\n\nclass TreeRenderer implements IListRenderer, ITreeListTemplateData> {\n\n\tprivate static readonly DefaultIndent = 8;\n\n\treadonly templateId: string;\n\tprivate renderedElements = new Map>();\n\tprivate renderedNodes = new Map, IRenderData>();\n\tprivate indent: number = TreeRenderer.DefaultIndent;\n\tprivate hideTwistiesOfChildlessElements: boolean = false;\n\n\tprivate shouldRenderIndentGuides: boolean = false;\n\tprivate renderedIndentGuides = new SetMap, HTMLDivElement>();\n\tprivate activeIndentNodes = new Set>();\n\tprivate indentGuidesDisposable: IDisposable = Disposable.None;\n\n\tprivate readonly disposables = new DisposableStore();\n\n\tconstructor(\n\t\tprivate renderer: ITreeRenderer,\n\t\tprivate modelProvider: () => ITreeModel,\n\t\tonDidChangeCollapseState: Event>,\n\t\tprivate activeNodes: Collection>,\n\t\toptions: ITreeRendererOptions = {}\n\t) {\n\t\tthis.templateId = renderer.templateId;\n\t\tthis.updateOptions(options);\n\n\t\tEvent.map(onDidChangeCollapseState, e => e.node)(this.onDidChangeNodeTwistieState, this, this.disposables);\n\n\t\tif (renderer.onDidChangeTwistieState) {\n\t\t\trenderer.onDidChangeTwistieState(this.onDidChangeTwistieState, this, this.disposables);\n\t\t}\n\t}\n\n\tupdateOptions(options: ITreeRendererOptions = {}): void {\n\t\tif (typeof options.indent !== 'undefined') {\n\t\t\tthis.indent = clamp(options.indent, 0, 40);\n\t\t}\n\n\t\tif (typeof options.renderIndentGuides !== 'undefined') {\n\t\t\tconst shouldRenderIndentGuides = options.renderIndentGuides !== RenderIndentGuides.None;\n\n\t\t\tif (shouldRenderIndentGuides !== this.shouldRenderIndentGuides) {\n\t\t\t\tthis.shouldRenderIndentGuides = shouldRenderIndentGuides;\n\t\t\t\tthis.indentGuidesDisposable.dispose();\n\n\t\t\t\tif (shouldRenderIndentGuides) {\n\t\t\t\t\tconst disposables = new DisposableStore();\n\t\t\t\t\tthis.activeNodes.onDidChange(this._onDidChangeActiveNodes, this, disposables);\n\t\t\t\t\tthis.indentGuidesDisposable = disposables;\n\n\t\t\t\t\tthis._onDidChangeActiveNodes(this.activeNodes.elements);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (typeof options.hideTwistiesOfChildlessElements !== 'undefined') {\n\t\t\tthis.hideTwistiesOfChildlessElements = options.hideTwistiesOfChildlessElements;\n\t\t}\n\t}\n\n\trenderTemplate(container: HTMLElement): ITreeListTemplateData {\n\t\tconst el = append(container, $('.monaco-tl-row'));\n\t\tconst indent = append(el, $('.monaco-tl-indent'));\n\t\tconst twistie = append(el, $('.monaco-tl-twistie'));\n\t\tconst contents = append(el, $('.monaco-tl-contents'));\n\t\tconst templateData = this.renderer.renderTemplate(contents);\n\n\t\treturn { container, indent, twistie, indentGuidesDisposable: Disposable.None, templateData };\n\t}\n\n\trenderElement(node: ITreeNode, index: number, templateData: ITreeListTemplateData, height: number | undefined): void {\n\t\tif (typeof height === 'number') {\n\t\t\tthis.renderedNodes.set(node, { templateData, height });\n\t\t\tthis.renderedElements.set(node.element, node);\n\t\t}\n\n\t\tconst indent = TreeRenderer.DefaultIndent + (node.depth - 1) * this.indent;\n\t\ttemplateData.twistie.style.paddingLeft = `${indent}px`;\n\t\ttemplateData.indent.style.width = `${indent + this.indent - 16}px`;\n\n\t\tthis.renderTwistie(node, templateData);\n\n\t\tif (typeof height === 'number') {\n\t\t\tthis.renderIndentGuides(node, templateData);\n\t\t}\n\n\t\tthis.renderer.renderElement(node, index, templateData.templateData, height);\n\t}\n\n\tdisposeElement(node: ITreeNode, index: number, templateData: ITreeListTemplateData, height: number | undefined): void {\n\t\ttemplateData.indentGuidesDisposable.dispose();\n\n\t\tif (this.renderer.disposeElement) {\n\t\t\tthis.renderer.disposeElement(node, index, templateData.templateData, height);\n\t\t}\n\n\t\tif (typeof height === 'number') {\n\t\t\tthis.renderedNodes.delete(node);\n\t\t\tthis.renderedElements.delete(node.element);\n\t\t}\n\t}\n\n\tdisposeTemplate(templateData: ITreeListTemplateData): void {\n\t\tthis.renderer.disposeTemplate(templateData.templateData);\n\t}\n\n\tprivate onDidChangeTwistieState(element: T): void {\n\t\tconst node = this.renderedElements.get(element);\n\n\t\tif (!node) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.onDidChangeNodeTwistieState(node);\n\t}\n\n\tprivate onDidChangeNodeTwistieState(node: ITreeNode): void {\n\t\tconst data = this.renderedNodes.get(node);\n\n\t\tif (!data) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.renderTwistie(node, data.templateData);\n\t\tthis._onDidChangeActiveNodes(this.activeNodes.elements);\n\t\tthis.renderIndentGuides(node, data.templateData);\n\t}\n\n\tprivate renderTwistie(node: ITreeNode, templateData: ITreeListTemplateData) {\n\t\ttemplateData.twistie.classList.remove(...Codicon.treeItemExpanded.classNamesArray);\n\n\t\tlet twistieRendered = false;\n\n\t\tif (this.renderer.renderTwistie) {\n\t\t\ttwistieRendered = this.renderer.renderTwistie(node.element, templateData.twistie);\n\t\t}\n\n\t\tif (node.collapsible && (!this.hideTwistiesOfChildlessElements || node.visibleChildrenCount > 0)) {\n\t\t\tif (!twistieRendered) {\n\t\t\t\ttemplateData.twistie.classList.add(...Codicon.treeItemExpanded.classNamesArray);\n\t\t\t}\n\n\t\t\ttemplateData.twistie.classList.add('collapsible');\n\t\t\ttemplateData.twistie.classList.toggle('collapsed', node.collapsed);\n\t\t} else {\n\t\t\ttemplateData.twistie.classList.remove('collapsible', 'collapsed');\n\t\t}\n\n\t\tif (node.collapsible) {\n\t\t\ttemplateData.container.setAttribute('aria-expanded', String(!node.collapsed));\n\t\t} else {\n\t\t\ttemplateData.container.removeAttribute('aria-expanded');\n\t\t}\n\t}\n\n\tprivate renderIndentGuides(target: ITreeNode, templateData: ITreeListTemplateData): void {\n\t\tclearNode(templateData.indent);\n\t\ttemplateData.indentGuidesDisposable.dispose();\n\n\t\tif (!this.shouldRenderIndentGuides) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst disposableStore = new DisposableStore();\n\t\tconst model = this.modelProvider();\n\n\t\tlet node = target;\n\n\t\twhile (true) {\n\t\t\tconst ref = model.getNodeLocation(node);\n\t\t\tconst parentRef = model.getParentNodeLocation(ref);\n\n\t\t\tif (!parentRef) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst parent = model.getNode(parentRef);\n\t\t\tconst guide = $('.indent-guide', { style: `width: ${this.indent}px` });\n\n\t\t\tif (this.activeIndentNodes.has(parent)) {\n\t\t\t\tguide.classList.add('active');\n\t\t\t}\n\n\t\t\tif (templateData.indent.childElementCount === 0) {\n\t\t\t\ttemplateData.indent.appendChild(guide);\n\t\t\t} else {\n\t\t\t\ttemplateData.indent.insertBefore(guide, templateData.indent.firstElementChild);\n\t\t\t}\n\n\t\t\tthis.renderedIndentGuides.add(parent, guide);\n\t\t\tdisposableStore.add(toDisposable(() => this.renderedIndentGuides.delete(parent, guide)));\n\n\t\t\tnode = parent;\n\t\t}\n\n\t\ttemplateData.indentGuidesDisposable = disposableStore;\n\t}\n\n\tprivate _onDidChangeActiveNodes(nodes: ITreeNode[]): void {\n\t\tif (!this.shouldRenderIndentGuides) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst set = new Set>();\n\t\tconst model = this.modelProvider();\n\n\t\tnodes.forEach(node => {\n\t\t\tconst ref = model.getNodeLocation(node);\n\t\t\ttry {\n\t\t\t\tconst parentRef = model.getParentNodeLocation(ref);\n\n\t\t\t\tif (node.collapsible && node.children.length > 0 && !node.collapsed) {\n\t\t\t\t\tset.add(node);\n\t\t\t\t} else if (parentRef) {\n\t\t\t\t\tset.add(model.getNode(parentRef));\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// noop\n\t\t\t}\n\t\t});\n\n\t\tthis.activeIndentNodes.forEach(node => {\n\t\t\tif (!set.has(node)) {\n\t\t\t\tthis.renderedIndentGuides.forEach(node, line => line.classList.remove('active'));\n\t\t\t}\n\t\t});\n\n\t\tset.forEach(node => {\n\t\t\tif (!this.activeIndentNodes.has(node)) {\n\t\t\t\tthis.renderedIndentGuides.forEach(node, line => line.classList.add('active'));\n\t\t\t}\n\t\t});\n\n\t\tthis.activeIndentNodes = set;\n\t}\n\n\tdispose(): void {\n\t\tthis.renderedNodes.clear();\n\t\tthis.renderedElements.clear();\n\t\tthis.indentGuidesDisposable.dispose();\n\t\tdispose(this.disposables);\n\t}\n}\n\nexport type LabelFuzzyScore = { label: string; score: FuzzyScore };\n\nclass TypeFilter implements ITreeFilter, IDisposable {\n\tprivate _totalCount = 0;\n\tget totalCount(): number { return this._totalCount; }\n\tprivate _matchCount = 0;\n\tget matchCount(): number { return this._matchCount; }\n\n\tprivate _pattern: string = '';\n\tprivate _lowercasePattern: string = '';\n\tprivate readonly disposables = new DisposableStore();\n\n\tset pattern(pattern: string) {\n\t\tthis._pattern = pattern;\n\t\tthis._lowercasePattern = pattern.toLowerCase();\n\t}\n\n\tconstructor(\n\t\tprivate tree: AbstractTree,\n\t\tprivate keyboardNavigationLabelProvider: IKeyboardNavigationLabelProvider,\n\t\tprivate _filter?: ITreeFilter\n\t) {\n\t\ttree.onWillRefilter(this.reset, this, this.disposables);\n\t}\n\n\tfilter(element: T, parentVisibility: TreeVisibility): TreeFilterResult {\n\t\tif (this._filter) {\n\t\t\tconst result = this._filter.filter(element, parentVisibility);\n\n\t\t\tif (this.tree.options.simpleKeyboardNavigation) {\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tlet visibility: TreeVisibility;\n\n\t\t\tif (typeof result === 'boolean') {\n\t\t\t\tvisibility = result ? TreeVisibility.Visible : TreeVisibility.Hidden;\n\t\t\t} else if (isFilterResult(result)) {\n\t\t\t\tvisibility = getVisibleState(result.visibility);\n\t\t\t} else {\n\t\t\t\tvisibility = result;\n\t\t\t}\n\n\t\t\tif (visibility === TreeVisibility.Hidden) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis._totalCount++;\n\n\t\tif (this.tree.options.simpleKeyboardNavigation || !this._pattern) {\n\t\t\tthis._matchCount++;\n\t\t\treturn { data: FuzzyScore.Default, visibility: true };\n\t\t}\n\n\t\tconst label = this.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(element);\n\t\tconst labels = Array.isArray(label) ? label : [label];\n\n\t\tfor (const l of labels) {\n\t\t\tconst labelStr = l && l.toString();\n\t\t\tif (typeof labelStr === 'undefined') {\n\t\t\t\treturn { data: FuzzyScore.Default, visibility: true };\n\t\t\t}\n\n\t\t\tconst score = fuzzyScore(this._pattern, this._lowercasePattern, 0, labelStr, labelStr.toLowerCase(), 0, true);\n\t\t\tif (score) {\n\t\t\t\tthis._matchCount++;\n\t\t\t\treturn labels.length === 1 ?\n\t\t\t\t\t{ data: score, visibility: true } :\n\t\t\t\t\t{ data: { label: labelStr, score: score }, visibility: true };\n\t\t\t}\n\t\t}\n\n\t\tif (this.tree.options.filterOnType) {\n\t\t\treturn TreeVisibility.Recurse;\n\t\t} else {\n\t\t\treturn { data: FuzzyScore.Default, visibility: true };\n\t\t}\n\t}\n\n\tprivate reset(): void {\n\t\tthis._totalCount = 0;\n\t\tthis._matchCount = 0;\n\t}\n\n\tdispose(): void {\n\t\tdispose(this.disposables);\n\t}\n}\n\nclass TypeFilterController implements IDisposable {\n\n\tprivate _enabled = false;\n\tget enabled(): boolean { return this._enabled; }\n\n\tprivate _pattern = '';\n\tget pattern(): string { return this._pattern; }\n\n\tprivate _filterOnType: boolean;\n\tget filterOnType(): boolean { return this._filterOnType; }\n\n\tprivate _empty: boolean = false;\n\n\tprivate readonly _onDidChangeEmptyState = new Emitter();\n\n\tprivate positionClassName = 'ne';\n\tprivate domNode: HTMLElement;\n\tprivate messageDomNode: HTMLElement;\n\tprivate labelDomNode: HTMLElement;\n\tprivate filterOnTypeDomNode: HTMLInputElement;\n\tprivate clearDomNode: HTMLElement;\n\tprivate keyboardNavigationEventFilter?: IKeyboardNavigationEventFilter;\n\n\tprivate automaticKeyboardNavigation = true;\n\tprivate triggered = false;\n\n\tprivate readonly _onDidChangePattern = new Emitter();\n\n\tprivate readonly enabledDisposables = new DisposableStore();\n\tprivate readonly disposables = new DisposableStore();\n\n\tconstructor(\n\t\tprivate tree: AbstractTree,\n\t\tmodel: ITreeModel,\n\t\tprivate view: List>,\n\t\tprivate filter: TypeFilter,\n\t\tprivate keyboardNavigationDelegate: IKeyboardNavigationDelegate\n\t) {\n\t\tthis.domNode = $(`.monaco-list-type-filter.${this.positionClassName}`);\n\t\tthis.domNode.draggable = true;\n\t\tthis.disposables.add(addDisposableListener(this.domNode, 'dragstart', () => this.onDragStart()));\n\n\t\tthis.messageDomNode = append(view.getHTMLElement(), $(`.monaco-list-type-filter-message`));\n\n\t\tthis.labelDomNode = append(this.domNode, $('span.label'));\n\t\tconst controls = append(this.domNode, $('.controls'));\n\n\t\tthis._filterOnType = !!tree.options.filterOnType;\n\t\tthis.filterOnTypeDomNode = append(controls, $('input.filter'));\n\t\tthis.filterOnTypeDomNode.type = 'checkbox';\n\t\tthis.filterOnTypeDomNode.checked = this._filterOnType;\n\t\tthis.filterOnTypeDomNode.tabIndex = -1;\n\t\tthis.updateFilterOnTypeTitleAndIcon();\n\t\tthis.disposables.add(addDisposableListener(this.filterOnTypeDomNode, 'input', () => this.onDidChangeFilterOnType()));\n\n\t\tthis.clearDomNode = append(controls, $('button.clear' + Codicon.treeFilterClear.cssSelector));\n\t\tthis.clearDomNode.tabIndex = -1;\n\t\tthis.clearDomNode.title = localize('clear', \"Clear\");\n\n\t\tthis.keyboardNavigationEventFilter = tree.options.keyboardNavigationEventFilter;\n\n\t\tmodel.onDidSplice(this.onDidSpliceModel, this, this.disposables);\n\t\tthis.updateOptions(tree.options);\n\t}\n\n\tupdateOptions(options: IAbstractTreeOptions): void {\n\t\tif (options.simpleKeyboardNavigation) {\n\t\t\tthis.disable();\n\t\t} else {\n\t\t\tthis.enable();\n\t\t}\n\n\t\tif (typeof options.filterOnType !== 'undefined') {\n\t\t\tthis._filterOnType = !!options.filterOnType;\n\t\t\tthis.filterOnTypeDomNode.checked = this._filterOnType;\n\t\t\tthis.updateFilterOnTypeTitleAndIcon();\n\t\t}\n\n\t\tif (typeof options.automaticKeyboardNavigation !== 'undefined') {\n\t\t\tthis.automaticKeyboardNavigation = options.automaticKeyboardNavigation;\n\t\t}\n\n\t\tthis.tree.refilter();\n\t\tthis.render();\n\n\t\tif (!this.automaticKeyboardNavigation) {\n\t\t\tthis.onEventOrInput('');\n\t\t}\n\t}\n\n\tprivate enable(): void {\n\t\tif (this._enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst onRawKeyDown = this.enabledDisposables.add(new DomEmitter(this.view.getHTMLElement(), 'keydown'));\n\t\tconst onKeyDown = Event.chain(onRawKeyDown.event)\n\t\t\t.filter(e => !isInputElement(e.target as HTMLElement) || e.target === this.filterOnTypeDomNode)\n\t\t\t.filter(e => e.key !== 'Dead' && !/^Media/.test(e.key))\n\t\t\t.map(e => new StandardKeyboardEvent(e))\n\t\t\t.filter(this.keyboardNavigationEventFilter || (() => true))\n\t\t\t.filter(() => this.automaticKeyboardNavigation || this.triggered)\n\t\t\t.filter(e => (this.keyboardNavigationDelegate.mightProducePrintableCharacter(e) && !(e.keyCode === KeyCode.DownArrow || e.keyCode === KeyCode.UpArrow || e.keyCode === KeyCode.LeftArrow || e.keyCode === KeyCode.RightArrow)) || ((this.pattern.length > 0 || this.triggered) && ((e.keyCode === KeyCode.Escape || e.keyCode === KeyCode.Backspace) && !e.altKey && !e.ctrlKey && !e.metaKey) || (e.keyCode === KeyCode.Backspace && (isMacintosh ? (e.altKey && !e.metaKey) : e.ctrlKey) && !e.shiftKey)))\n\t\t\t.forEach(e => { e.stopPropagation(); e.preventDefault(); })\n\t\t\t.event;\n\n\t\tconst onClearClick = this.enabledDisposables.add(new DomEmitter(this.clearDomNode, 'click'));\n\n\t\tEvent.chain(Event.any(onKeyDown, onClearClick.event))\n\t\t\t.event(this.onEventOrInput, this, this.enabledDisposables);\n\n\t\tthis.filter.pattern = '';\n\t\tthis.tree.refilter();\n\t\tthis.render();\n\t\tthis._enabled = true;\n\t\tthis.triggered = false;\n\t}\n\n\tprivate disable(): void {\n\t\tif (!this._enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.domNode.remove();\n\t\tthis.enabledDisposables.clear();\n\t\tthis.tree.refilter();\n\t\tthis.render();\n\t\tthis._enabled = false;\n\t\tthis.triggered = false;\n\t}\n\n\tprivate onEventOrInput(e: MouseEvent | StandardKeyboardEvent | string): void {\n\t\tif (typeof e === 'string') {\n\t\t\tthis.onInput(e);\n\t\t} else if (e instanceof MouseEvent || e.keyCode === KeyCode.Escape || (e.keyCode === KeyCode.Backspace && (isMacintosh ? e.altKey : e.ctrlKey))) {\n\t\t\tthis.onInput('');\n\t\t} else if (e.keyCode === KeyCode.Backspace) {\n\t\t\tthis.onInput(this.pattern.length === 0 ? '' : this.pattern.substr(0, this.pattern.length - 1));\n\t\t} else {\n\t\t\tthis.onInput(this.pattern + e.browserEvent.key);\n\t\t}\n\t}\n\n\tprivate onInput(pattern: string): void {\n\t\tconst container = this.view.getHTMLElement();\n\n\t\tif (pattern && !this.domNode.parentElement) {\n\t\t\tcontainer.append(this.domNode);\n\t\t} else if (!pattern && this.domNode.parentElement) {\n\t\t\tthis.domNode.remove();\n\t\t\tthis.tree.domFocus();\n\t\t}\n\n\t\tthis._pattern = pattern;\n\t\tthis._onDidChangePattern.fire(pattern);\n\n\t\tthis.filter.pattern = pattern;\n\t\tthis.tree.refilter();\n\n\t\tif (pattern) {\n\t\t\tthis.tree.focusNext(0, true, undefined, node => !FuzzyScore.isDefault(node.filterData as any as FuzzyScore));\n\t\t}\n\n\t\tconst focus = this.tree.getFocus();\n\n\t\tif (focus.length > 0) {\n\t\t\tconst element = focus[0];\n\n\t\t\tif (this.tree.getRelativeTop(element) === null) {\n\t\t\t\tthis.tree.reveal(element, 0.5);\n\t\t\t}\n\t\t}\n\n\t\tthis.render();\n\n\t\tif (!pattern) {\n\t\t\tthis.triggered = false;\n\t\t}\n\t}\n\n\tprivate onDragStart(): void {\n\t\tconst container = this.view.getHTMLElement();\n\t\tconst { left } = getDomNodePagePosition(container);\n\t\tconst containerWidth = container.clientWidth;\n\t\tconst midContainerWidth = containerWidth / 2;\n\t\tconst width = this.domNode.clientWidth;\n\t\tconst disposables = new DisposableStore();\n\t\tlet positionClassName = this.positionClassName;\n\n\t\tconst updatePosition = () => {\n\t\t\tswitch (positionClassName) {\n\t\t\t\tcase 'nw':\n\t\t\t\t\tthis.domNode.style.top = `4px`;\n\t\t\t\t\tthis.domNode.style.left = `4px`;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'ne':\n\t\t\t\t\tthis.domNode.style.top = `4px`;\n\t\t\t\t\tthis.domNode.style.left = `${containerWidth - width - 6}px`;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t};\n\n\t\tconst onDragOver = (event: DragEvent) => {\n\t\t\tevent.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)\n\n\t\t\tconst x = event.clientX - left;\n\t\t\tif (event.dataTransfer) {\n\t\t\t\tevent.dataTransfer.dropEffect = 'none';\n\t\t\t}\n\n\t\t\tif (x < midContainerWidth) {\n\t\t\t\tpositionClassName = 'nw';\n\t\t\t} else {\n\t\t\t\tpositionClassName = 'ne';\n\t\t\t}\n\n\t\t\tupdatePosition();\n\t\t};\n\n\t\tconst onDragEnd = () => {\n\t\t\tthis.positionClassName = positionClassName;\n\t\t\tthis.domNode.className = `monaco-list-type-filter ${this.positionClassName}`;\n\t\t\tthis.domNode.style.top = '';\n\t\t\tthis.domNode.style.left = '';\n\n\t\t\tdispose(disposables);\n\t\t};\n\n\t\tupdatePosition();\n\t\tthis.domNode.classList.remove(positionClassName);\n\n\t\tthis.domNode.classList.add('dragging');\n\t\tdisposables.add(toDisposable(() => this.domNode.classList.remove('dragging')));\n\n\t\tdisposables.add(addDisposableListener(document, 'dragover', e => onDragOver(e)));\n\t\tdisposables.add(addDisposableListener(this.domNode, 'dragend', () => onDragEnd()));\n\n\t\tStaticDND.CurrentDragAndDropData = new DragAndDropData('vscode-ui');\n\t\tdisposables.add(toDisposable(() => StaticDND.CurrentDragAndDropData = undefined));\n\t}\n\n\tprivate onDidSpliceModel(): void {\n\t\tif (!this._enabled || this.pattern.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.tree.refilter();\n\t\tthis.render();\n\t}\n\n\tprivate onDidChangeFilterOnType(): void {\n\t\tthis.tree.updateOptions({ filterOnType: this.filterOnTypeDomNode.checked });\n\t\tthis.tree.refilter();\n\t\tthis.tree.domFocus();\n\t\tthis.render();\n\t\tthis.updateFilterOnTypeTitleAndIcon();\n\t}\n\n\tprivate updateFilterOnTypeTitleAndIcon(): void {\n\t\tif (this.filterOnType) {\n\t\t\tthis.filterOnTypeDomNode.classList.remove(...Codicon.treeFilterOnTypeOff.classNamesArray);\n\t\t\tthis.filterOnTypeDomNode.classList.add(...Codicon.treeFilterOnTypeOn.classNamesArray);\n\t\t\tthis.filterOnTypeDomNode.title = localize('disable filter on type', \"Disable Filter on Type\");\n\t\t} else {\n\t\t\tthis.filterOnTypeDomNode.classList.remove(...Codicon.treeFilterOnTypeOn.classNamesArray);\n\t\t\tthis.filterOnTypeDomNode.classList.add(...Codicon.treeFilterOnTypeOff.classNamesArray);\n\t\t\tthis.filterOnTypeDomNode.title = localize('enable filter on type', \"Enable Filter on Type\");\n\t\t}\n\t}\n\n\tprivate render(): void {\n\t\tconst noMatches = this.filter.totalCount > 0 && this.filter.matchCount === 0;\n\n\t\tif (this.pattern && this.tree.options.filterOnType && noMatches) {\n\t\t\tthis.messageDomNode.textContent = localize('empty', \"No elements found\");\n\t\t\tthis._empty = true;\n\t\t} else {\n\t\t\tthis.messageDomNode.innerText = '';\n\t\t\tthis._empty = false;\n\t\t}\n\n\t\tthis.domNode.classList.toggle('no-matches', noMatches);\n\t\tthis.domNode.title = localize('found', \"Matched {0} out of {1} elements\", this.filter.matchCount, this.filter.totalCount);\n\t\tthis.labelDomNode.textContent = this.pattern.length > 16 ? '…' + this.pattern.substr(this.pattern.length - 16) : this.pattern;\n\n\t\tthis._onDidChangeEmptyState.fire(this._empty);\n\t}\n\n\tshouldAllowFocus(node: ITreeNode): boolean {\n\t\tif (!this.enabled || !this.pattern || this.filterOnType) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (this.filter.totalCount > 0 && this.filter.matchCount <= 1) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn !FuzzyScore.isDefault(node.filterData as any as FuzzyScore);\n\t}\n\n\tdispose() {\n\t\tif (this._enabled) {\n\t\t\tthis.domNode.remove();\n\t\t\tthis.enabledDisposables.dispose();\n\t\t\tthis._enabled = false;\n\t\t\tthis.triggered = false;\n\t\t}\n\n\t\tthis._onDidChangePattern.dispose();\n\t\tdispose(this.disposables);\n\t}\n}\n\nfunction asTreeMouseEvent(event: IListMouseEvent>): ITreeMouseEvent {\n\tlet target: TreeMouseEventTarget = TreeMouseEventTarget.Unknown;\n\n\tif (hasParentWithClass(event.browserEvent.target as HTMLElement, 'monaco-tl-twistie', 'monaco-tl-row')) {\n\t\ttarget = TreeMouseEventTarget.Twistie;\n\t} else if (hasParentWithClass(event.browserEvent.target as HTMLElement, 'monaco-tl-contents', 'monaco-tl-row')) {\n\t\ttarget = TreeMouseEventTarget.Element;\n\t}\n\n\treturn {\n\t\tbrowserEvent: event.browserEvent,\n\t\telement: event.element ? event.element.element : null,\n\t\ttarget\n\t};\n}\n\nexport interface IKeyboardNavigationEventFilter {\n\t(e: StandardKeyboardEvent): boolean;\n}\n\nexport interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions {\n\treadonly multipleSelectionSupport?: boolean;\n\treadonly automaticKeyboardNavigation?: boolean;\n\treadonly simpleKeyboardNavigation?: boolean;\n\treadonly filterOnType?: boolean;\n\treadonly smoothScrolling?: boolean;\n\treadonly horizontalScrolling?: boolean;\n\treadonly mouseWheelScrollSensitivity?: number;\n\treadonly fastScrollSensitivity?: number;\n\treadonly expandOnDoubleClick?: boolean;\n\treadonly expandOnlyOnTwistieClick?: boolean | ((e: any) => boolean); // e is T\n}\n\nexport interface IAbstractTreeOptions extends IAbstractTreeOptionsUpdate, IListOptions {\n\treadonly collapseByDefault?: boolean; // defaults to false\n\treadonly filter?: ITreeFilter;\n\treadonly dnd?: ITreeDragAndDrop;\n\treadonly keyboardNavigationEventFilter?: IKeyboardNavigationEventFilter;\n\treadonly additionalScrollHeight?: number;\n}\n\nfunction dfs(node: ITreeNode, fn: (node: ITreeNode) => void): void {\n\tfn(node);\n\tnode.children.forEach(child => dfs(child, fn));\n}\n\n/**\n * The trait concept needs to exist at the tree level, because collapsed\n * tree nodes will not be known by the list.\n */\nclass Trait {\n\n\tprivate nodes: ITreeNode[] = [];\n\tprivate elements: T[] | undefined;\n\n\tprivate readonly _onDidChange = new Emitter>();\n\treadonly onDidChange = this._onDidChange.event;\n\n\tprivate _nodeSet: Set> | undefined;\n\tprivate get nodeSet(): Set> {\n\t\tif (!this._nodeSet) {\n\t\t\tthis._nodeSet = this.createNodeSet();\n\t\t}\n\n\t\treturn this._nodeSet;\n\t}\n\n\tconstructor(\n\t\tprivate getFirstViewElementWithTrait: () => ITreeNode | undefined,\n\t\tprivate identityProvider?: IIdentityProvider\n\t) { }\n\n\tset(nodes: ITreeNode[], browserEvent?: UIEvent): void {\n\t\tif (!(browserEvent as any)?.__forceEvent && equals(this.nodes, nodes)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._set(nodes, false, browserEvent);\n\t}\n\n\tprivate _set(nodes: ITreeNode[], silent: boolean, browserEvent?: UIEvent): void {\n\t\tthis.nodes = [...nodes];\n\t\tthis.elements = undefined;\n\t\tthis._nodeSet = undefined;\n\n\t\tif (!silent) {\n\t\t\tconst that = this;\n\t\t\tthis._onDidChange.fire({ get elements() { return that.get(); }, browserEvent });\n\t\t}\n\t}\n\n\tget(): T[] {\n\t\tif (!this.elements) {\n\t\t\tthis.elements = this.nodes.map(node => node.element);\n\t\t}\n\n\t\treturn [...this.elements];\n\t}\n\n\tgetNodes(): readonly ITreeNode[] {\n\t\treturn this.nodes;\n\t}\n\n\thas(node: ITreeNode): boolean {\n\t\treturn this.nodeSet.has(node);\n\t}\n\n\tonDidModelSplice({ insertedNodes, deletedNodes }: ITreeModelSpliceEvent): void {\n\t\tif (!this.identityProvider) {\n\t\t\tconst set = this.createNodeSet();\n\t\t\tconst visit = (node: ITreeNode) => set.delete(node);\n\t\t\tdeletedNodes.forEach(node => dfs(node, visit));\n\t\t\tthis.set([...set.values()]);\n\t\t\treturn;\n\t\t}\n\n\t\tconst deletedNodesIdSet = new Set();\n\t\tconst deletedNodesVisitor = (node: ITreeNode) => deletedNodesIdSet.add(this.identityProvider!.getId(node.element).toString());\n\t\tdeletedNodes.forEach(node => dfs(node, deletedNodesVisitor));\n\n\t\tconst insertedNodesMap = new Map>();\n\t\tconst insertedNodesVisitor = (node: ITreeNode) => insertedNodesMap.set(this.identityProvider!.getId(node.element).toString(), node);\n\t\tinsertedNodes.forEach(node => dfs(node, insertedNodesVisitor));\n\n\t\tconst nodes: ITreeNode[] = [];\n\n\t\tfor (const node of this.nodes) {\n\t\t\tconst id = this.identityProvider.getId(node.element).toString();\n\t\t\tconst wasDeleted = deletedNodesIdSet.has(id);\n\n\t\t\tif (!wasDeleted) {\n\t\t\t\tnodes.push(node);\n\t\t\t} else {\n\t\t\t\tconst insertedNode = insertedNodesMap.get(id);\n\n\t\t\t\tif (insertedNode) {\n\t\t\t\t\tnodes.push(insertedNode);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.nodes.length > 0 && nodes.length === 0) {\n\t\t\tconst node = this.getFirstViewElementWithTrait();\n\n\t\t\tif (node) {\n\t\t\t\tnodes.push(node);\n\t\t\t}\n\t\t}\n\n\t\tthis._set(nodes, true);\n\t}\n\n\tprivate createNodeSet(): Set> {\n\t\tconst set = new Set>();\n\n\t\tfor (const node of this.nodes) {\n\t\t\tset.add(node);\n\t\t}\n\n\t\treturn set;\n\t}\n}\n\nclass TreeNodeListMouseController extends MouseController> {\n\n\tconstructor(list: TreeNodeList, private tree: AbstractTree) {\n\t\tsuper(list);\n\t}\n\n\tprotected override onViewPointer(e: IListMouseEvent>): void {\n\t\tif (isInputElement(e.browserEvent.target as HTMLElement) || isMonacoEditor(e.browserEvent.target as HTMLElement)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst node = e.element;\n\n\t\tif (!node) {\n\t\t\treturn super.onViewPointer(e);\n\t\t}\n\n\t\tif (this.isSelectionRangeChangeEvent(e) || this.isSelectionSingleChangeEvent(e)) {\n\t\t\treturn super.onViewPointer(e);\n\t\t}\n\n\t\tconst target = e.browserEvent.target as HTMLElement;\n\t\tconst onTwistie = target.classList.contains('monaco-tl-twistie')\n\t\t\t|| (target.classList.contains('monaco-icon-label') && target.classList.contains('folder-icon') && e.browserEvent.offsetX < 16);\n\n\t\tlet expandOnlyOnTwistieClick = false;\n\n\t\tif (typeof this.tree.expandOnlyOnTwistieClick === 'function') {\n\t\t\texpandOnlyOnTwistieClick = this.tree.expandOnlyOnTwistieClick(node.element);\n\t\t} else {\n\t\t\texpandOnlyOnTwistieClick = !!this.tree.expandOnlyOnTwistieClick;\n\t\t}\n\n\t\tif (expandOnlyOnTwistieClick && !onTwistie && e.browserEvent.detail !== 2) {\n\t\t\treturn super.onViewPointer(e);\n\t\t}\n\n\t\tif (!this.tree.expandOnDoubleClick && e.browserEvent.detail === 2) {\n\t\t\treturn super.onViewPointer(e);\n\t\t}\n\n\t\tif (node.collapsible) {\n\t\t\tconst model = ((this.tree as any).model as ITreeModel); // internal\n\t\t\tconst location = model.getNodeLocation(node);\n\t\t\tconst recursive = e.browserEvent.altKey;\n\t\t\tthis.tree.setFocus([location]);\n\t\t\tmodel.setCollapsed(location, undefined, recursive);\n\n\t\t\tif (expandOnlyOnTwistieClick && onTwistie) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tsuper.onViewPointer(e);\n\t}\n\n\tprotected override onDoubleClick(e: IListMouseEvent>): void {\n\t\tconst onTwistie = (e.browserEvent.target as HTMLElement).classList.contains('monaco-tl-twistie');\n\n\t\tif (onTwistie || !this.tree.expandOnDoubleClick) {\n\t\t\treturn;\n\t\t}\n\n\t\tsuper.onDoubleClick(e);\n\t}\n}\n\ninterface ITreeNodeListOptions extends IListOptions> {\n\treadonly tree: AbstractTree;\n}\n\n/**\n * We use this List subclass to restore selection and focus as nodes\n * get rendered in the list, possibly due to a node expand() call.\n */\nclass TreeNodeList extends List> {\n\n\tconstructor(\n\t\tuser: string,\n\t\tcontainer: HTMLElement,\n\t\tvirtualDelegate: IListVirtualDelegate>,\n\t\trenderers: IListRenderer[],\n\t\tprivate focusTrait: Trait,\n\t\tprivate selectionTrait: Trait,\n\t\tprivate anchorTrait: Trait,\n\t\toptions: ITreeNodeListOptions\n\t) {\n\t\tsuper(user, container, virtualDelegate, renderers, options);\n\t}\n\n\tprotected override createMouseController(options: ITreeNodeListOptions): MouseController> {\n\t\treturn new TreeNodeListMouseController(this, options.tree);\n\t}\n\n\toverride splice(start: number, deleteCount: number, elements: ITreeNode[] = []): void {\n\t\tsuper.splice(start, deleteCount, elements);\n\n\t\tif (elements.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst additionalFocus: number[] = [];\n\t\tconst additionalSelection: number[] = [];\n\t\tlet anchor: number | undefined;\n\n\t\telements.forEach((node, index) => {\n\t\t\tif (this.focusTrait.has(node)) {\n\t\t\t\tadditionalFocus.push(start + index);\n\t\t\t}\n\n\t\t\tif (this.selectionTrait.has(node)) {\n\t\t\t\tadditionalSelection.push(start + index);\n\t\t\t}\n\n\t\t\tif (this.anchorTrait.has(node)) {\n\t\t\t\tanchor = start + index;\n\t\t\t}\n\t\t});\n\n\t\tif (additionalFocus.length > 0) {\n\t\t\tsuper.setFocus(distinct([...super.getFocus(), ...additionalFocus]));\n\t\t}\n\n\t\tif (additionalSelection.length > 0) {\n\t\t\tsuper.setSelection(distinct([...super.getSelection(), ...additionalSelection]));\n\t\t}\n\n\t\tif (typeof anchor === 'number') {\n\t\t\tsuper.setAnchor(anchor);\n\t\t}\n\t}\n\n\toverride setFocus(indexes: number[], browserEvent?: UIEvent, fromAPI = false): void {\n\t\tsuper.setFocus(indexes, browserEvent);\n\n\t\tif (!fromAPI) {\n\t\t\tthis.focusTrait.set(indexes.map(i => this.element(i)), browserEvent);\n\t\t}\n\t}\n\n\toverride setSelection(indexes: number[], browserEvent?: UIEvent, fromAPI = false): void {\n\t\tsuper.setSelection(indexes, browserEvent);\n\n\t\tif (!fromAPI) {\n\t\t\tthis.selectionTrait.set(indexes.map(i => this.element(i)), browserEvent);\n\t\t}\n\t}\n\n\toverride setAnchor(index: number | undefined, fromAPI = false): void {\n\t\tsuper.setAnchor(index);\n\n\t\tif (!fromAPI) {\n\t\t\tif (typeof index === 'undefined') {\n\t\t\t\tthis.anchorTrait.set([]);\n\t\t\t} else {\n\t\t\t\tthis.anchorTrait.set([this.element(index)]);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport abstract class AbstractTree implements IDisposable {\n\n\tprotected view: TreeNodeList;\n\tprivate renderers: TreeRenderer[];\n\tprotected model: ITreeModel;\n\tprivate focus: Trait;\n\tprivate selection: Trait;\n\tprivate anchor: Trait;\n\tprivate eventBufferer = new EventBufferer();\n\tprivate typeFilterController?: TypeFilterController;\n\tprivate focusNavigationFilter: ((node: ITreeNode) => boolean) | undefined;\n\tprivate styleElement: HTMLStyleElement;\n\tprotected readonly disposables = new DisposableStore();\n\n\tget onDidChangeFocus(): Event> { return this.eventBufferer.wrapEvent(this.focus.onDidChange); }\n\tget onDidChangeSelection(): Event> { return this.eventBufferer.wrapEvent(this.selection.onDidChange); }\n\tget onMouseDblClick(): Event> { return Event.map(this.view.onMouseDblClick, asTreeMouseEvent); }\n\tget onPointer(): Event> { return Event.map(this.view.onPointer, asTreeMouseEvent); }\n\n\tget onDidFocus(): Event { return this.view.onDidFocus; }\n\n\tget onDidChangeModel(): Event { return Event.signal(this.model.onDidSplice); }\n\tget onDidChangeCollapseState(): Event> { return this.model.onDidChangeCollapseState; }\n\n\tprivate readonly _onWillRefilter = new Emitter();\n\treadonly onWillRefilter: Event = this._onWillRefilter.event;\n\n\tget expandOnDoubleClick(): boolean { return typeof this._options.expandOnDoubleClick === 'undefined' ? true : this._options.expandOnDoubleClick; }\n\tget expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? true : this._options.expandOnlyOnTwistieClick; }\n\n\tprivate readonly _onDidUpdateOptions = new Emitter>();\n\n\tget onDidDispose(): Event { return this.view.onDidDispose; }\n\n\tconstructor(\n\t\tprivate readonly _user: string,\n\t\tcontainer: HTMLElement,\n\t\tdelegate: IListVirtualDelegate,\n\t\trenderers: ITreeRenderer[],\n\t\tprivate _options: IAbstractTreeOptions = {}\n\t) {\n\t\tconst treeDelegate = new ComposedTreeDelegate>(delegate);\n\n\t\tconst onDidChangeCollapseStateRelay = new Relay>();\n\t\tconst onDidChangeActiveNodes = new Relay[]>();\n\t\tconst activeNodes = new EventCollection(onDidChangeActiveNodes.event);\n\t\tthis.renderers = renderers.map(r => new TreeRenderer(r, () => this.model, onDidChangeCollapseStateRelay.event, activeNodes, _options));\n\t\tfor (let r of this.renderers) {\n\t\t\tthis.disposables.add(r);\n\t\t}\n\n\t\tlet filter: TypeFilter | undefined;\n\n\t\tif (_options.keyboardNavigationLabelProvider) {\n\t\t\tfilter = new TypeFilter(this, _options.keyboardNavigationLabelProvider, _options.filter as any as ITreeFilter);\n\t\t\t_options = { ..._options, filter: filter as ITreeFilter }; // TODO need typescript help here\n\t\t\tthis.disposables.add(filter);\n\t\t}\n\n\t\tthis.focus = new Trait(() => this.view.getFocusedElements()[0], _options.identityProvider);\n\t\tthis.selection = new Trait(() => this.view.getSelectedElements()[0], _options.identityProvider);\n\t\tthis.anchor = new Trait(() => this.view.getAnchorElement(), _options.identityProvider);\n\t\tthis.view = new TreeNodeList(_user, container, treeDelegate, this.renderers, this.focus, this.selection, this.anchor, { ...asListOptions(() => this.model, _options), tree: this });\n\n\t\tthis.model = this.createModel(_user, this.view, _options);\n\t\tonDidChangeCollapseStateRelay.input = this.model.onDidChangeCollapseState;\n\n\t\tconst onDidModelSplice = Event.forEach(this.model.onDidSplice, e => {\n\t\t\tthis.eventBufferer.bufferEvents(() => {\n\t\t\t\tthis.focus.onDidModelSplice(e);\n\t\t\t\tthis.selection.onDidModelSplice(e);\n\t\t\t});\n\t\t});\n\n\t\t// Make sure the `forEach` always runs\n\t\tonDidModelSplice(() => null, null, this.disposables);\n\n\t\t// Active nodes can change when the model changes or when focus or selection change.\n\t\t// We debounce it with 0 delay since these events may fire in the same stack and we only\n\t\t// want to run this once. It also doesn't matter if it runs on the next tick since it's only\n\t\t// a nice to have UI feature.\n\t\tonDidChangeActiveNodes.input = Event.chain(Event.any(onDidModelSplice, this.focus.onDidChange, this.selection.onDidChange))\n\t\t\t.debounce(() => null, 0)\n\t\t\t.map(() => {\n\t\t\t\tconst set = new Set>();\n\n\t\t\t\tfor (const node of this.focus.getNodes()) {\n\t\t\t\t\tset.add(node);\n\t\t\t\t}\n\n\t\t\t\tfor (const node of this.selection.getNodes()) {\n\t\t\t\t\tset.add(node);\n\t\t\t\t}\n\n\t\t\t\treturn [...set.values()];\n\t\t\t}).event;\n\n\t\tif (_options.keyboardSupport !== false) {\n\t\t\tconst onKeyDown = Event.chain(this.view.onKeyDown)\n\t\t\t\t.filter(e => !isInputElement(e.target as HTMLElement))\n\t\t\t\t.map(e => new StandardKeyboardEvent(e));\n\n\t\t\tonKeyDown.filter(e => e.keyCode === KeyCode.LeftArrow).on(this.onLeftArrow, this, this.disposables);\n\t\t\tonKeyDown.filter(e => e.keyCode === KeyCode.RightArrow).on(this.onRightArrow, this, this.disposables);\n\t\t\tonKeyDown.filter(e => e.keyCode === KeyCode.Space).on(this.onSpace, this, this.disposables);\n\t\t}\n\n\t\tif (_options.keyboardNavigationLabelProvider) {\n\t\t\tconst delegate = _options.keyboardNavigationDelegate || DefaultKeyboardNavigationDelegate;\n\t\t\tthis.typeFilterController = new TypeFilterController(this, this.model, this.view, filter!, delegate);\n\t\t\tthis.focusNavigationFilter = node => this.typeFilterController!.shouldAllowFocus(node);\n\t\t\tthis.disposables.add(this.typeFilterController!);\n\t\t}\n\n\t\tthis.styleElement = createStyleSheet(this.view.getHTMLElement());\n\t\tthis.getHTMLElement().classList.toggle('always', this._options.renderIndentGuides === RenderIndentGuides.Always);\n\t}\n\n\tupdateOptions(optionsUpdate: IAbstractTreeOptionsUpdate = {}): void {\n\t\tthis._options = { ...this._options, ...optionsUpdate };\n\n\t\tfor (const renderer of this.renderers) {\n\t\t\trenderer.updateOptions(optionsUpdate);\n\t\t}\n\n\t\tthis.view.updateOptions({\n\t\t\t...this._options,\n\t\t\tenableKeyboardNavigation: this._options.simpleKeyboardNavigation,\n\t\t});\n\n\t\tif (this.typeFilterController) {\n\t\t\tthis.typeFilterController.updateOptions(this._options);\n\t\t}\n\n\t\tthis._onDidUpdateOptions.fire(this._options);\n\n\t\tthis.getHTMLElement().classList.toggle('always', this._options.renderIndentGuides === RenderIndentGuides.Always);\n\t}\n\n\tget options(): IAbstractTreeOptions {\n\t\treturn this._options;\n\t}\n\n\t// Widget\n\n\tgetHTMLElement(): HTMLElement {\n\t\treturn this.view.getHTMLElement();\n\t}\n\n\tget scrollTop(): number {\n\t\treturn this.view.scrollTop;\n\t}\n\n\tset scrollTop(scrollTop: number) {\n\t\tthis.view.scrollTop = scrollTop;\n\t}\n\n\tdomFocus(): void {\n\t\tthis.view.domFocus();\n\t}\n\n\tlayout(height?: number, width?: number): void {\n\t\tthis.view.layout(height, width);\n\t}\n\n\tstyle(styles: IListStyles): void {\n\t\tconst suffix = `.${this.view.domId}`;\n\t\tconst content: string[] = [];\n\n\t\tif (styles.treeIndentGuidesStroke) {\n\t\t\tcontent.push(`.monaco-list${suffix}:hover .monaco-tl-indent > .indent-guide, .monaco-list${suffix}.always .monaco-tl-indent > .indent-guide { border-color: ${styles.treeIndentGuidesStroke.transparent(0.4)}; }`);\n\t\t\tcontent.push(`.monaco-list${suffix} .monaco-tl-indent > .indent-guide.active { border-color: ${styles.treeIndentGuidesStroke}; }`);\n\t\t}\n\n\t\tthis.styleElement.textContent = content.join('\\n');\n\t\tthis.view.style(styles);\n\t}\n\n\t// Tree navigation\n\n\tgetParentElement(location: TRef): T {\n\t\tconst parentRef = this.model.getParentNodeLocation(location);\n\t\tconst parentNode = this.model.getNode(parentRef);\n\t\treturn parentNode.element;\n\t}\n\n\tgetFirstElementChild(location: TRef): T | undefined {\n\t\treturn this.model.getFirstElementChild(location);\n\t}\n\n\t// Tree\n\n\tgetNode(location?: TRef): ITreeNode {\n\t\treturn this.model.getNode(location);\n\t}\n\n\tcollapse(location: TRef, recursive: boolean = false): boolean {\n\t\treturn this.model.setCollapsed(location, true, recursive);\n\t}\n\n\texpand(location: TRef, recursive: boolean = false): boolean {\n\t\treturn this.model.setCollapsed(location, false, recursive);\n\t}\n\n\tisCollapsible(location: TRef): boolean {\n\t\treturn this.model.isCollapsible(location);\n\t}\n\n\tsetCollapsible(location: TRef, collapsible?: boolean): boolean {\n\t\treturn this.model.setCollapsible(location, collapsible);\n\t}\n\n\tisCollapsed(location: TRef): boolean {\n\t\treturn this.model.isCollapsed(location);\n\t}\n\n\trefilter(): void {\n\t\tthis._onWillRefilter.fire(undefined);\n\t\tthis.model.refilter();\n\t}\n\n\tsetSelection(elements: TRef[], browserEvent?: UIEvent): void {\n\t\tconst nodes = elements.map(e => this.model.getNode(e));\n\t\tthis.selection.set(nodes, browserEvent);\n\n\t\tconst indexes = elements.map(e => this.model.getListIndex(e)).filter(i => i > -1);\n\t\tthis.view.setSelection(indexes, browserEvent, true);\n\t}\n\n\tgetSelection(): T[] {\n\t\treturn this.selection.get();\n\t}\n\n\tsetFocus(elements: TRef[], browserEvent?: UIEvent): void {\n\t\tconst nodes = elements.map(e => this.model.getNode(e));\n\t\tthis.focus.set(nodes, browserEvent);\n\n\t\tconst indexes = elements.map(e => this.model.getListIndex(e)).filter(i => i > -1);\n\t\tthis.view.setFocus(indexes, browserEvent, true);\n\t}\n\n\tfocusNext(n = 1, loop = false, browserEvent?: UIEvent, filter = this.focusNavigationFilter): void {\n\t\tthis.view.focusNext(n, loop, browserEvent, filter);\n\t}\n\n\tgetFocus(): T[] {\n\t\treturn this.focus.get();\n\t}\n\n\treveal(location: TRef, relativeTop?: number): void {\n\t\tthis.model.expandTo(location);\n\n\t\tconst index = this.model.getListIndex(location);\n\n\t\tif (index === -1) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.view.reveal(index, relativeTop);\n\t}\n\n\t/**\n\t * Returns the relative position of an element rendered in the list.\n\t * Returns `null` if the element isn't *entirely* in the visible viewport.\n\t */\n\tgetRelativeTop(location: TRef): number | null {\n\t\tconst index = this.model.getListIndex(location);\n\n\t\tif (index === -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn this.view.getRelativeTop(index);\n\t}\n\n\t// List\n\n\tprivate onLeftArrow(e: StandardKeyboardEvent): void {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\n\t\tconst nodes = this.view.getFocusedElements();\n\n\t\tif (nodes.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst node = nodes[0];\n\t\tconst location = this.model.getNodeLocation(node);\n\t\tconst didChange = this.model.setCollapsed(location, true);\n\n\t\tif (!didChange) {\n\t\t\tconst parentLocation = this.model.getParentNodeLocation(location);\n\n\t\t\tif (!parentLocation) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst parentListIndex = this.model.getListIndex(parentLocation);\n\n\t\t\tthis.view.reveal(parentListIndex);\n\t\t\tthis.view.setFocus([parentListIndex]);\n\t\t}\n\t}\n\n\tprivate onRightArrow(e: StandardKeyboardEvent): void {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\n\t\tconst nodes = this.view.getFocusedElements();\n\n\t\tif (nodes.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst node = nodes[0];\n\t\tconst location = this.model.getNodeLocation(node);\n\t\tconst didChange = this.model.setCollapsed(location, false);\n\n\t\tif (!didChange) {\n\t\t\tif (!node.children.some(child => child.visible)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst [focusedIndex] = this.view.getFocus();\n\t\t\tconst firstChildIndex = focusedIndex + 1;\n\n\t\t\tthis.view.reveal(firstChildIndex);\n\t\t\tthis.view.setFocus([firstChildIndex]);\n\t\t}\n\t}\n\n\tprivate onSpace(e: StandardKeyboardEvent): void {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\n\t\tconst nodes = this.view.getFocusedElements();\n\n\t\tif (nodes.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst node = nodes[0];\n\t\tconst location = this.model.getNodeLocation(node);\n\t\tconst recursive = e.browserEvent.altKey;\n\n\t\tthis.model.setCollapsed(location, undefined, recursive);\n\t}\n\n\tprotected abstract createModel(user: string, view: ISpliceable>, options: IAbstractTreeOptions): ITreeModel;\n\n\tdispose(): void {\n\t\tdispose(this.disposables);\n\t\tthis.view.dispose();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IIdentityProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';\nimport { AbstractTree, IAbstractTreeOptions } from 'vs/base/browser/ui/tree/abstractTree';\nimport { IList } from 'vs/base/browser/ui/tree/indexTreeModel';\nimport { ObjectTreeModel } from 'vs/base/browser/ui/tree/objectTreeModel';\nimport { IDataSource, ITreeModel, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree';\n\nexport interface IDataTreeOptions extends IAbstractTreeOptions {\n}\n\nexport class DataTree extends AbstractTree {\n\n\tprotected override model!: ObjectTreeModel;\n\n\tprivate identityProvider: IIdentityProvider | undefined;\n\n\tconstructor(\n\t\tprivate user: string,\n\t\tcontainer: HTMLElement,\n\t\tdelegate: IListVirtualDelegate,\n\t\trenderers: ITreeRenderer[],\n\t\tprivate dataSource: IDataSource,\n\t\toptions: IDataTreeOptions = {}\n\t) {\n\t\tsuper(user, container, delegate, renderers, options as IDataTreeOptions);\n\t\tthis.identityProvider = options.identityProvider;\n\t}\n\n\tprotected createModel(user: string, view: IList>, options: IDataTreeOptions): ITreeModel {\n\t\treturn new ObjectTreeModel(user, view, options);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IIdentityProvider, IKeyboardNavigationLabelProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';\nimport { AbstractTree, IAbstractTreeOptions, IAbstractTreeOptionsUpdate } from 'vs/base/browser/ui/tree/abstractTree';\nimport { CompressibleObjectTreeModel, ICompressedTreeElement, ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';\nimport { IList } from 'vs/base/browser/ui/tree/indexTreeModel';\nimport { IObjectTreeModel, ObjectTreeModel } from 'vs/base/browser/ui/tree/objectTreeModel';\nimport { ICollapseStateChangeEvent, ITreeElement, ITreeModel, ITreeNode, ITreeRenderer, ITreeSorter } from 'vs/base/browser/ui/tree/tree';\nimport { memoize } from 'vs/base/common/decorators';\nimport { Event } from 'vs/base/common/event';\nimport { Iterable } from 'vs/base/common/iterator';\n\nexport interface IObjectTreeOptions extends IAbstractTreeOptions {\n\treadonly sorter?: ITreeSorter;\n}\n\nexport interface IObjectTreeSetChildrenOptions {\n\n\t/**\n\t * Identity provider used to optimize splice() calls in the IndexTree. If\n\t * this is not present, optimized splicing is not enabled.\n\t *\n\t * Warning: if this is present, calls to `setChildren()` will not replace\n\t * or update nodes if their identity is the same, even if the elements are\n\t * different. For this, you should call `rerender()`.\n\t */\n\treadonly diffIdentityProvider?: IIdentityProvider;\n}\n\nexport class ObjectTree, TFilterData = void> extends AbstractTree {\n\n\tprotected override model!: IObjectTreeModel;\n\n\toverride get onDidChangeCollapseState(): Event> { return this.model.onDidChangeCollapseState; }\n\n\tconstructor(\n\t\tprotected readonly user: string,\n\t\tcontainer: HTMLElement,\n\t\tdelegate: IListVirtualDelegate,\n\t\trenderers: ITreeRenderer[],\n\t\toptions: IObjectTreeOptions = {}\n\t) {\n\t\tsuper(user, container, delegate, renderers, options as IObjectTreeOptions);\n\t}\n\n\tsetChildren(element: T | null, children: Iterable> = Iterable.empty(), options?: IObjectTreeSetChildrenOptions): void {\n\t\tthis.model.setChildren(element, children, options);\n\t}\n\n\trerender(element?: T): void {\n\t\tif (element === undefined) {\n\t\t\tthis.view.rerender();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.model.rerender(element);\n\t}\n\n\thasElement(element: T): boolean {\n\t\treturn this.model.has(element);\n\t}\n\n\tprotected createModel(user: string, view: IList>, options: IObjectTreeOptions): ITreeModel {\n\t\treturn new ObjectTreeModel(user, view, options);\n\t}\n}\n\ninterface ICompressedTreeNodeProvider {\n\tgetCompressedTreeNode(location: T | null): ITreeNode | null, TFilterData>;\n}\n\nexport interface ICompressibleTreeRenderer extends ITreeRenderer {\n\trenderCompressedElements(node: ITreeNode, TFilterData>, index: number, templateData: TTemplateData, height: number | undefined): void;\n\tdisposeCompressedElements?(node: ITreeNode, TFilterData>, index: number, templateData: TTemplateData, height: number | undefined): void;\n}\n\ninterface CompressibleTemplateData {\n\tcompressedTreeNode: ITreeNode, TFilterData> | undefined;\n\treadonly data: TTemplateData;\n}\n\nclass CompressibleRenderer, TFilterData, TTemplateData> implements ITreeRenderer> {\n\n\treadonly templateId: string;\n\treadonly onDidChangeTwistieState: Event | undefined;\n\n\t@memoize\n\tprivate get compressedTreeNodeProvider(): ICompressedTreeNodeProvider {\n\t\treturn this._compressedTreeNodeProvider();\n\t}\n\n\tconstructor(private _compressedTreeNodeProvider: () => ICompressedTreeNodeProvider, private renderer: ICompressibleTreeRenderer) {\n\t\tthis.templateId = renderer.templateId;\n\n\t\tif (renderer.onDidChangeTwistieState) {\n\t\t\tthis.onDidChangeTwistieState = renderer.onDidChangeTwistieState;\n\t\t}\n\t}\n\n\trenderTemplate(container: HTMLElement): CompressibleTemplateData {\n\t\tconst data = this.renderer.renderTemplate(container);\n\t\treturn { compressedTreeNode: undefined, data };\n\t}\n\n\trenderElement(node: ITreeNode, index: number, templateData: CompressibleTemplateData, height: number | undefined): void {\n\t\tconst compressedTreeNode = this.compressedTreeNodeProvider.getCompressedTreeNode(node.element) as ITreeNode, TFilterData>;\n\n\t\tif (compressedTreeNode.element.elements.length === 1) {\n\t\t\ttemplateData.compressedTreeNode = undefined;\n\t\t\tthis.renderer.renderElement(node, index, templateData.data, height);\n\t\t} else {\n\t\t\ttemplateData.compressedTreeNode = compressedTreeNode;\n\t\t\tthis.renderer.renderCompressedElements(compressedTreeNode, index, templateData.data, height);\n\t\t}\n\t}\n\n\tdisposeElement(node: ITreeNode, index: number, templateData: CompressibleTemplateData, height: number | undefined): void {\n\t\tif (templateData.compressedTreeNode) {\n\t\t\tif (this.renderer.disposeCompressedElements) {\n\t\t\t\tthis.renderer.disposeCompressedElements(templateData.compressedTreeNode, index, templateData.data, height);\n\t\t\t}\n\t\t} else {\n\t\t\tif (this.renderer.disposeElement) {\n\t\t\t\tthis.renderer.disposeElement(node, index, templateData.data, height);\n\t\t\t}\n\t\t}\n\t}\n\n\tdisposeTemplate(templateData: CompressibleTemplateData): void {\n\t\tthis.renderer.disposeTemplate(templateData.data);\n\t}\n\n\trenderTwistie?(element: T, twistieElement: HTMLElement): boolean {\n\t\tif (this.renderer.renderTwistie) {\n\t\t\treturn this.renderer.renderTwistie(element, twistieElement);\n\t\t}\n\t\treturn false;\n\t}\n}\n\nexport interface ICompressibleKeyboardNavigationLabelProvider extends IKeyboardNavigationLabelProvider {\n\tgetCompressedNodeKeyboardNavigationLabel(elements: T[]): { toString(): string | undefined; } | undefined;\n}\n\nexport interface ICompressibleObjectTreeOptions extends IObjectTreeOptions {\n\treadonly keyboardNavigationLabelProvider?: ICompressibleKeyboardNavigationLabelProvider;\n}\n\nfunction asObjectTreeOptions(compressedTreeNodeProvider: () => ICompressedTreeNodeProvider, options?: ICompressibleObjectTreeOptions): IObjectTreeOptions | undefined {\n\treturn options && {\n\t\t...options,\n\t\tkeyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && {\n\t\t\tgetKeyboardNavigationLabel(e: T) {\n\t\t\t\tlet compressedTreeNode: ITreeNode, TFilterData>;\n\n\t\t\t\ttry {\n\t\t\t\t\tcompressedTreeNode = compressedTreeNodeProvider().getCompressedTreeNode(e) as ITreeNode, TFilterData>;\n\t\t\t\t} catch {\n\t\t\t\t\treturn options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(e);\n\t\t\t\t}\n\n\t\t\t\tif (compressedTreeNode.element.elements.length === 1) {\n\t\t\t\t\treturn options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(e);\n\t\t\t\t} else {\n\t\t\t\t\treturn options.keyboardNavigationLabelProvider!.getCompressedNodeKeyboardNavigationLabel(compressedTreeNode.element.elements);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\nexport interface ICompressibleObjectTreeOptionsUpdate extends IAbstractTreeOptionsUpdate {\n\treadonly compressionEnabled?: boolean;\n}\n\nexport class CompressibleObjectTree, TFilterData = void> extends ObjectTree implements ICompressedTreeNodeProvider {\n\n\tprotected override model!: CompressibleObjectTreeModel;\n\n\tconstructor(\n\t\tuser: string,\n\t\tcontainer: HTMLElement,\n\t\tdelegate: IListVirtualDelegate,\n\t\trenderers: ICompressibleTreeRenderer[],\n\t\toptions: ICompressibleObjectTreeOptions = {}\n\t) {\n\t\tconst compressedTreeNodeProvider = () => this;\n\t\tconst compressibleRenderers = renderers.map(r => new CompressibleRenderer(compressedTreeNodeProvider, r));\n\t\tsuper(user, container, delegate, compressibleRenderers, asObjectTreeOptions(compressedTreeNodeProvider, options));\n\t}\n\n\toverride setChildren(element: T | null, children: Iterable> = Iterable.empty(), options?: IObjectTreeSetChildrenOptions): void {\n\t\tthis.model.setChildren(element, children, options);\n\t}\n\n\tprotected override createModel(user: string, view: IList>, options: ICompressibleObjectTreeOptions): ITreeModel {\n\t\treturn new CompressibleObjectTreeModel(user, view, options);\n\t}\n\n\toverride updateOptions(optionsUpdate: ICompressibleObjectTreeOptionsUpdate = {}): void {\n\t\tsuper.updateOptions(optionsUpdate);\n\n\t\tif (typeof optionsUpdate.compressionEnabled !== 'undefined') {\n\t\t\tthis.model.setCompressionEnabled(optionsUpdate.compressionEnabled);\n\t\t}\n\t}\n\n\tgetCompressedTreeNode(element: T | null = null): ITreeNode | null, TFilterData> {\n\t\treturn this.model.getCompressedTreeNode(element);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDragAndDropData } from 'vs/base/browser/dnd';\nimport { IIdentityProvider, IListDragAndDrop, IListDragOverReaction, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';\nimport { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';\nimport { IListStyles } from 'vs/base/browser/ui/list/listWidget';\nimport { ComposedTreeDelegate, IAbstractTreeOptions, IAbstractTreeOptionsUpdate } from 'vs/base/browser/ui/tree/abstractTree';\nimport { ICompressedTreeElement, ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';\nimport { getVisibleState, isFilterResult } from 'vs/base/browser/ui/tree/indexTreeModel';\nimport { CompressibleObjectTree, ICompressibleKeyboardNavigationLabelProvider, ICompressibleObjectTreeOptions, ICompressibleTreeRenderer, IObjectTreeOptions, IObjectTreeSetChildrenOptions, ObjectTree } from 'vs/base/browser/ui/tree/objectTree';\nimport { IAsyncDataSource, ICollapseStateChangeEvent, ITreeDragAndDrop, ITreeElement, ITreeEvent, ITreeFilter, ITreeMouseEvent, ITreeNode, ITreeRenderer, ITreeSorter, TreeError, TreeFilterResult, TreeVisibility, WeakMapper } from 'vs/base/browser/ui/tree/tree';\nimport { CancelablePromise, createCancelablePromise, Promises, timeout } from 'vs/base/common/async';\nimport { Codicon } from 'vs/base/common/codicons';\nimport { isCancellationError, onUnexpectedError } from 'vs/base/common/errors';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Iterable } from 'vs/base/common/iterator';\nimport { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';\nimport { IThemable } from 'vs/base/common/styler';\n\ninterface IAsyncDataTreeNode {\n\telement: TInput | T;\n\treadonly parent: IAsyncDataTreeNode | null;\n\treadonly children: IAsyncDataTreeNode[];\n\treadonly id?: string | null;\n\trefreshPromise: Promise | undefined;\n\thasChildren: boolean;\n\tstale: boolean;\n\tslow: boolean;\n\tcollapsedByDefault: boolean | undefined;\n}\n\ninterface IAsyncDataTreeNodeRequiredProps extends Partial> {\n\treadonly element: TInput | T;\n\treadonly parent: IAsyncDataTreeNode | null;\n\treadonly hasChildren: boolean;\n}\n\nfunction createAsyncDataTreeNode(props: IAsyncDataTreeNodeRequiredProps): IAsyncDataTreeNode {\n\treturn {\n\t\t...props,\n\t\tchildren: [],\n\t\trefreshPromise: undefined,\n\t\tstale: true,\n\t\tslow: false,\n\t\tcollapsedByDefault: undefined\n\t};\n}\n\nfunction isAncestor(ancestor: IAsyncDataTreeNode, descendant: IAsyncDataTreeNode): boolean {\n\tif (!descendant.parent) {\n\t\treturn false;\n\t} else if (descendant.parent === ancestor) {\n\t\treturn true;\n\t} else {\n\t\treturn isAncestor(ancestor, descendant.parent);\n\t}\n}\n\nfunction intersects(node: IAsyncDataTreeNode, other: IAsyncDataTreeNode): boolean {\n\treturn node === other || isAncestor(node, other) || isAncestor(other, node);\n}\n\ninterface IDataTreeListTemplateData {\n\ttemplateData: T;\n}\n\ntype AsyncDataTreeNodeMapper = WeakMapper | null, TFilterData>, ITreeNode>;\n\nclass AsyncDataTreeNodeWrapper implements ITreeNode {\n\n\tget element(): T { return this.node.element!.element as T; }\n\tget children(): ITreeNode[] { return this.node.children.map(node => new AsyncDataTreeNodeWrapper(node)); }\n\tget depth(): number { return this.node.depth; }\n\tget visibleChildrenCount(): number { return this.node.visibleChildrenCount; }\n\tget visibleChildIndex(): number { return this.node.visibleChildIndex; }\n\tget collapsible(): boolean { return this.node.collapsible; }\n\tget collapsed(): boolean { return this.node.collapsed; }\n\tget visible(): boolean { return this.node.visible; }\n\tget filterData(): TFilterData | undefined { return this.node.filterData; }\n\n\tconstructor(private node: ITreeNode | null, TFilterData>) { }\n}\n\nclass AsyncDataTreeRenderer implements ITreeRenderer, TFilterData, IDataTreeListTemplateData> {\n\n\treadonly templateId: string;\n\tprivate renderedNodes = new Map, IDataTreeListTemplateData>();\n\n\tconstructor(\n\t\tprotected renderer: ITreeRenderer,\n\t\tprotected nodeMapper: AsyncDataTreeNodeMapper,\n\t\treadonly onDidChangeTwistieState: Event>\n\t) {\n\t\tthis.templateId = renderer.templateId;\n\t}\n\n\trenderTemplate(container: HTMLElement): IDataTreeListTemplateData {\n\t\tconst templateData = this.renderer.renderTemplate(container);\n\t\treturn { templateData };\n\t}\n\n\trenderElement(node: ITreeNode, TFilterData>, index: number, templateData: IDataTreeListTemplateData, height: number | undefined): void {\n\t\tthis.renderer.renderElement(this.nodeMapper.map(node) as ITreeNode, index, templateData.templateData, height);\n\t}\n\n\trenderTwistie(element: IAsyncDataTreeNode, twistieElement: HTMLElement): boolean {\n\t\tif (element.slow) {\n\t\t\ttwistieElement.classList.add(...Codicon.treeItemLoading.classNamesArray);\n\t\t\treturn true;\n\t\t} else {\n\t\t\ttwistieElement.classList.remove(...Codicon.treeItemLoading.classNamesArray);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tdisposeElement(node: ITreeNode, TFilterData>, index: number, templateData: IDataTreeListTemplateData, height: number | undefined): void {\n\t\tif (this.renderer.disposeElement) {\n\t\t\tthis.renderer.disposeElement(this.nodeMapper.map(node) as ITreeNode, index, templateData.templateData, height);\n\t\t}\n\t}\n\n\tdisposeTemplate(templateData: IDataTreeListTemplateData): void {\n\t\tthis.renderer.disposeTemplate(templateData.templateData);\n\t}\n\n\tdispose(): void {\n\t\tthis.renderedNodes.clear();\n\t}\n}\n\nfunction asTreeEvent(e: ITreeEvent | null>): ITreeEvent {\n\treturn {\n\t\tbrowserEvent: e.browserEvent,\n\t\telements: e.elements.map(e => e!.element as T)\n\t};\n}\n\nfunction asTreeMouseEvent(e: ITreeMouseEvent | null>): ITreeMouseEvent {\n\treturn {\n\t\tbrowserEvent: e.browserEvent,\n\t\telement: e.element && e.element.element as T,\n\t\ttarget: e.target\n\t};\n}\n\nclass AsyncDataTreeElementsDragAndDropData extends ElementsDragAndDropData {\n\n\tconstructor(private data: ElementsDragAndDropData, TContext>) {\n\t\tsuper(data.elements.map(node => node.element as T));\n\t}\n}\n\nfunction asAsyncDataTreeDragAndDropData(data: IDragAndDropData): IDragAndDropData {\n\tif (data instanceof ElementsDragAndDropData) {\n\t\treturn new AsyncDataTreeElementsDragAndDropData(data);\n\t}\n\n\treturn data;\n}\n\nclass AsyncDataTreeNodeListDragAndDrop implements IListDragAndDrop> {\n\n\tconstructor(private dnd: ITreeDragAndDrop) { }\n\n\tgetDragURI(node: IAsyncDataTreeNode): string | null {\n\t\treturn this.dnd.getDragURI(node.element as T);\n\t}\n\n\tgetDragLabel(nodes: IAsyncDataTreeNode[], originalEvent: DragEvent): string | undefined {\n\t\tif (this.dnd.getDragLabel) {\n\t\t\treturn this.dnd.getDragLabel(nodes.map(node => node.element as T), originalEvent);\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tonDragStart(data: IDragAndDropData, originalEvent: DragEvent): void {\n\t\tif (this.dnd.onDragStart) {\n\t\t\tthis.dnd.onDragStart(asAsyncDataTreeDragAndDropData(data), originalEvent);\n\t\t}\n\t}\n\n\tonDragOver(data: IDragAndDropData, targetNode: IAsyncDataTreeNode | undefined, targetIndex: number | undefined, originalEvent: DragEvent, raw = true): boolean | IListDragOverReaction {\n\t\treturn this.dnd.onDragOver(asAsyncDataTreeDragAndDropData(data), targetNode && targetNode.element as T, targetIndex, originalEvent);\n\t}\n\n\tdrop(data: IDragAndDropData, targetNode: IAsyncDataTreeNode | undefined, targetIndex: number | undefined, originalEvent: DragEvent): void {\n\t\tthis.dnd.drop(asAsyncDataTreeDragAndDropData(data), targetNode && targetNode.element as T, targetIndex, originalEvent);\n\t}\n\n\tonDragEnd(originalEvent: DragEvent): void {\n\t\tif (this.dnd.onDragEnd) {\n\t\t\tthis.dnd.onDragEnd(originalEvent);\n\t\t}\n\t}\n}\n\nfunction asObjectTreeOptions(options?: IAsyncDataTreeOptions): IObjectTreeOptions, TFilterData> | undefined {\n\treturn options && {\n\t\t...options,\n\t\tcollapseByDefault: true,\n\t\tidentityProvider: options.identityProvider && {\n\t\t\tgetId(el) {\n\t\t\t\treturn options.identityProvider!.getId(el.element as T);\n\t\t\t}\n\t\t},\n\t\tdnd: options.dnd && new AsyncDataTreeNodeListDragAndDrop(options.dnd),\n\t\tmultipleSelectionController: options.multipleSelectionController && {\n\t\t\tisSelectionSingleChangeEvent(e) {\n\t\t\t\treturn options.multipleSelectionController!.isSelectionSingleChangeEvent({ ...e, element: e.element } as any);\n\t\t\t},\n\t\t\tisSelectionRangeChangeEvent(e) {\n\t\t\t\treturn options.multipleSelectionController!.isSelectionRangeChangeEvent({ ...e, element: e.element } as any);\n\t\t\t}\n\t\t},\n\t\taccessibilityProvider: options.accessibilityProvider && {\n\t\t\t...options.accessibilityProvider,\n\t\t\tgetPosInSet: undefined,\n\t\t\tgetSetSize: undefined,\n\t\t\tgetRole: options.accessibilityProvider!.getRole ? (el) => {\n\t\t\t\treturn options.accessibilityProvider!.getRole!(el.element as T);\n\t\t\t} : () => 'treeitem',\n\t\t\tisChecked: options.accessibilityProvider!.isChecked ? (e) => {\n\t\t\t\treturn !!(options.accessibilityProvider?.isChecked!(e.element as T));\n\t\t\t} : undefined,\n\t\t\tgetAriaLabel(e) {\n\t\t\t\treturn options.accessibilityProvider!.getAriaLabel(e.element as T);\n\t\t\t},\n\t\t\tgetWidgetAriaLabel() {\n\t\t\t\treturn options.accessibilityProvider!.getWidgetAriaLabel();\n\t\t\t},\n\t\t\tgetWidgetRole: options.accessibilityProvider!.getWidgetRole ? () => options.accessibilityProvider!.getWidgetRole!() : () => 'tree',\n\t\t\tgetAriaLevel: options.accessibilityProvider!.getAriaLevel && (node => {\n\t\t\t\treturn options.accessibilityProvider!.getAriaLevel!(node.element as T);\n\t\t\t}),\n\t\t\tgetActiveDescendantId: options.accessibilityProvider.getActiveDescendantId && (node => {\n\t\t\t\treturn options.accessibilityProvider!.getActiveDescendantId!(node.element as T);\n\t\t\t})\n\t\t},\n\t\tfilter: options.filter && {\n\t\t\tfilter(e, parentVisibility) {\n\t\t\t\treturn options.filter!.filter(e.element as T, parentVisibility);\n\t\t\t}\n\t\t},\n\t\tkeyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && {\n\t\t\t...options.keyboardNavigationLabelProvider,\n\t\t\tgetKeyboardNavigationLabel(e) {\n\t\t\t\treturn options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(e.element as T);\n\t\t\t}\n\t\t},\n\t\tsorter: undefined,\n\t\texpandOnlyOnTwistieClick: typeof options.expandOnlyOnTwistieClick === 'undefined' ? undefined : (\n\t\t\ttypeof options.expandOnlyOnTwistieClick !== 'function' ? options.expandOnlyOnTwistieClick : (\n\t\t\t\te => (options.expandOnlyOnTwistieClick as ((e: T) => boolean))(e.element as T)\n\t\t\t)\n\t\t),\n\t\tadditionalScrollHeight: options.additionalScrollHeight\n\t};\n}\n\nexport interface IAsyncDataTreeOptionsUpdate extends IAbstractTreeOptionsUpdate { }\nexport interface IAsyncDataTreeUpdateChildrenOptions extends IObjectTreeSetChildrenOptions { }\n\nexport interface IAsyncDataTreeOptions extends IAsyncDataTreeOptionsUpdate, Pick, Exclude, 'collapseByDefault'>> {\n\treadonly collapseByDefault?: { (e: T): boolean; };\n\treadonly identityProvider?: IIdentityProvider;\n\treadonly sorter?: ITreeSorter;\n\treadonly autoExpandSingleChildren?: boolean;\n}\n\nexport interface IAsyncDataTreeViewState {\n\treadonly focus?: string[];\n\treadonly selection?: string[];\n\treadonly expanded?: string[];\n\treadonly scrollTop?: number;\n}\n\ninterface IAsyncDataTreeViewStateContext {\n\treadonly viewState: IAsyncDataTreeViewState;\n\treadonly selection: IAsyncDataTreeNode[];\n\treadonly focus: IAsyncDataTreeNode[];\n}\n\nfunction dfs(node: IAsyncDataTreeNode, fn: (node: IAsyncDataTreeNode) => void): void {\n\tfn(node);\n\tnode.children.forEach(child => dfs(child, fn));\n}\n\nexport class AsyncDataTree implements IDisposable, IThemable {\n\n\tprotected readonly tree: ObjectTree, TFilterData>;\n\tprotected readonly root: IAsyncDataTreeNode;\n\tprivate readonly nodes = new Map>();\n\tprivate readonly sorter?: ITreeSorter;\n\tprivate readonly collapseByDefault?: { (e: T): boolean; };\n\n\tprivate readonly subTreeRefreshPromises = new Map, Promise>();\n\tprivate readonly refreshPromises = new Map, CancelablePromise>>();\n\n\tprotected readonly identityProvider?: IIdentityProvider;\n\tprivate readonly autoExpandSingleChildren: boolean;\n\n\tprivate readonly _onDidRender = new Emitter();\n\tprotected readonly _onDidChangeNodeSlowState = new Emitter>();\n\n\tprotected readonly nodeMapper: AsyncDataTreeNodeMapper = new WeakMapper(node => new AsyncDataTreeNodeWrapper(node));\n\n\tprotected readonly disposables = new DisposableStore();\n\n\tget onDidChangeFocus(): Event> { return Event.map(this.tree.onDidChangeFocus, asTreeEvent); }\n\tget onDidChangeSelection(): Event> { return Event.map(this.tree.onDidChangeSelection, asTreeEvent); }\n\tget onMouseDblClick(): Event> { return Event.map(this.tree.onMouseDblClick, asTreeMouseEvent); }\n\tget onPointer(): Event> { return Event.map(this.tree.onPointer, asTreeMouseEvent); }\n\tget onDidFocus(): Event { return this.tree.onDidFocus; }\n\n\tget onDidChangeModel(): Event { return this.tree.onDidChangeModel; }\n\tget onDidChangeCollapseState(): Event | null, TFilterData>> { return this.tree.onDidChangeCollapseState; }\n\n\tget onDidDispose(): Event { return this.tree.onDidDispose; }\n\n\tconstructor(\n\t\tprotected user: string,\n\t\tcontainer: HTMLElement,\n\t\tdelegate: IListVirtualDelegate,\n\t\trenderers: ITreeRenderer[],\n\t\tprivate dataSource: IAsyncDataSource,\n\t\toptions: IAsyncDataTreeOptions = {}\n\t) {\n\t\tthis.identityProvider = options.identityProvider;\n\t\tthis.autoExpandSingleChildren = typeof options.autoExpandSingleChildren === 'undefined' ? false : options.autoExpandSingleChildren;\n\t\tthis.sorter = options.sorter;\n\t\tthis.collapseByDefault = options.collapseByDefault;\n\n\t\tthis.tree = this.createTree(user, container, delegate, renderers, options);\n\n\t\tthis.root = createAsyncDataTreeNode({\n\t\t\telement: undefined!,\n\t\t\tparent: null,\n\t\t\thasChildren: true\n\t\t});\n\n\t\tif (this.identityProvider) {\n\t\t\tthis.root = {\n\t\t\t\t...this.root,\n\t\t\t\tid: null\n\t\t\t};\n\t\t}\n\n\t\tthis.nodes.set(null, this.root);\n\n\t\tthis.tree.onDidChangeCollapseState(this._onDidChangeCollapseState, this, this.disposables);\n\t}\n\n\tprotected createTree(\n\t\tuser: string,\n\t\tcontainer: HTMLElement,\n\t\tdelegate: IListVirtualDelegate,\n\t\trenderers: ITreeRenderer[],\n\t\toptions: IAsyncDataTreeOptions\n\t): ObjectTree, TFilterData> {\n\t\tconst objectTreeDelegate = new ComposedTreeDelegate>(delegate);\n\t\tconst objectTreeRenderers = renderers.map(r => new AsyncDataTreeRenderer(r, this.nodeMapper, this._onDidChangeNodeSlowState.event));\n\t\tconst objectTreeOptions = asObjectTreeOptions(options) || {};\n\n\t\treturn new ObjectTree(user, container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions);\n\t}\n\n\tupdateOptions(options: IAsyncDataTreeOptionsUpdate = {}): void {\n\t\tthis.tree.updateOptions(options);\n\t}\n\n\t// Widget\n\n\tgetHTMLElement(): HTMLElement {\n\t\treturn this.tree.getHTMLElement();\n\t}\n\n\tget scrollTop(): number {\n\t\treturn this.tree.scrollTop;\n\t}\n\n\tset scrollTop(scrollTop: number) {\n\t\tthis.tree.scrollTop = scrollTop;\n\t}\n\n\tdomFocus(): void {\n\t\tthis.tree.domFocus();\n\t}\n\n\tlayout(height?: number, width?: number): void {\n\t\tthis.tree.layout(height, width);\n\t}\n\n\tstyle(styles: IListStyles): void {\n\t\tthis.tree.style(styles);\n\t}\n\n\t// Model\n\n\tgetInput(): TInput | undefined {\n\t\treturn this.root.element as TInput;\n\t}\n\n\tasync setInput(input: TInput, viewState?: IAsyncDataTreeViewState): Promise {\n\t\tthis.refreshPromises.forEach(promise => promise.cancel());\n\t\tthis.refreshPromises.clear();\n\n\t\tthis.root.element = input!;\n\n\t\tconst viewStateContext = viewState && { viewState, focus: [], selection: [] } as IAsyncDataTreeViewStateContext;\n\n\t\tawait this._updateChildren(input, true, false, viewStateContext);\n\n\t\tif (viewStateContext) {\n\t\t\tthis.tree.setFocus(viewStateContext.focus);\n\t\t\tthis.tree.setSelection(viewStateContext.selection);\n\t\t}\n\n\t\tif (viewState && typeof viewState.scrollTop === 'number') {\n\t\t\tthis.scrollTop = viewState.scrollTop;\n\t\t}\n\t}\n\n\tprivate async _updateChildren(element: TInput | T = this.root.element, recursive = true, rerender = false, viewStateContext?: IAsyncDataTreeViewStateContext, options?: IAsyncDataTreeUpdateChildrenOptions): Promise {\n\t\tif (typeof this.root.element === 'undefined') {\n\t\t\tthrow new TreeError(this.user, 'Tree input not set');\n\t\t}\n\n\t\tif (this.root.refreshPromise) {\n\t\t\tawait this.root.refreshPromise;\n\t\t\tawait Event.toPromise(this._onDidRender.event);\n\t\t}\n\n\t\tconst node = this.getDataNode(element);\n\t\tawait this.refreshAndRenderNode(node, recursive, viewStateContext, options);\n\n\t\tif (rerender) {\n\t\t\ttry {\n\t\t\t\tthis.tree.rerender(node);\n\t\t\t} catch {\n\t\t\t\t// missing nodes are fine, this could've resulted from\n\t\t\t\t// parallel refresh calls, removing `node` altogether\n\t\t\t}\n\t\t}\n\t}\n\n\t// View\n\n\trerender(element?: T): void {\n\t\tif (element === undefined || element === this.root.element) {\n\t\t\tthis.tree.rerender();\n\t\t\treturn;\n\t\t}\n\n\t\tconst node = this.getDataNode(element);\n\t\tthis.tree.rerender(node);\n\t}\n\n\t// Tree\n\n\tgetNode(element: TInput | T = this.root.element): ITreeNode {\n\t\tconst dataNode = this.getDataNode(element);\n\t\tconst node = this.tree.getNode(dataNode === this.root ? null : dataNode);\n\t\treturn this.nodeMapper.map(node);\n\t}\n\n\tcollapse(element: T, recursive: boolean = false): boolean {\n\t\tconst node = this.getDataNode(element);\n\t\treturn this.tree.collapse(node === this.root ? null : node, recursive);\n\t}\n\n\tasync expand(element: T, recursive: boolean = false): Promise {\n\t\tif (typeof this.root.element === 'undefined') {\n\t\t\tthrow new TreeError(this.user, 'Tree input not set');\n\t\t}\n\n\t\tif (this.root.refreshPromise) {\n\t\t\tawait this.root.refreshPromise;\n\t\t\tawait Event.toPromise(this._onDidRender.event);\n\t\t}\n\n\t\tconst node = this.getDataNode(element);\n\n\t\tif (this.tree.hasElement(node) && !this.tree.isCollapsible(node)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (node.refreshPromise) {\n\t\t\tawait this.root.refreshPromise;\n\t\t\tawait Event.toPromise(this._onDidRender.event);\n\t\t}\n\n\t\tif (node !== this.root && !node.refreshPromise && !this.tree.isCollapsed(node)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst result = this.tree.expand(node === this.root ? null : node, recursive);\n\n\t\tif (node.refreshPromise) {\n\t\t\tawait this.root.refreshPromise;\n\t\t\tawait Event.toPromise(this._onDidRender.event);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tsetSelection(elements: T[], browserEvent?: UIEvent): void {\n\t\tconst nodes = elements.map(e => this.getDataNode(e));\n\t\tthis.tree.setSelection(nodes, browserEvent);\n\t}\n\n\tgetSelection(): T[] {\n\t\tconst nodes = this.tree.getSelection();\n\t\treturn nodes.map(n => n!.element as T);\n\t}\n\n\tsetFocus(elements: T[], browserEvent?: UIEvent): void {\n\t\tconst nodes = elements.map(e => this.getDataNode(e));\n\t\tthis.tree.setFocus(nodes, browserEvent);\n\t}\n\n\tgetFocus(): T[] {\n\t\tconst nodes = this.tree.getFocus();\n\t\treturn nodes.map(n => n!.element as T);\n\t}\n\n\treveal(element: T, relativeTop?: number): void {\n\t\tthis.tree.reveal(this.getDataNode(element), relativeTop);\n\t}\n\n\t// Tree navigation\n\n\tgetParentElement(element: T): TInput | T {\n\t\tconst node = this.tree.getParentElement(this.getDataNode(element));\n\t\treturn (node && node.element)!;\n\t}\n\n\tgetFirstElementChild(element: TInput | T = this.root.element): TInput | T | undefined {\n\t\tconst dataNode = this.getDataNode(element);\n\t\tconst node = this.tree.getFirstElementChild(dataNode === this.root ? null : dataNode);\n\t\treturn (node && node.element)!;\n\t}\n\n\t// Implementation\n\n\tprivate getDataNode(element: TInput | T): IAsyncDataTreeNode {\n\t\tconst node: IAsyncDataTreeNode | undefined = this.nodes.get((element === this.root.element ? null : element) as T);\n\n\t\tif (!node) {\n\t\t\tthrow new TreeError(this.user, `Data tree node not found: ${element}`);\n\t\t}\n\n\t\treturn node;\n\t}\n\n\tprivate async refreshAndRenderNode(node: IAsyncDataTreeNode, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext, options?: IAsyncDataTreeUpdateChildrenOptions): Promise {\n\t\tawait this.refreshNode(node, recursive, viewStateContext);\n\t\tthis.render(node, viewStateContext, options);\n\t}\n\n\tprivate async refreshNode(node: IAsyncDataTreeNode, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): Promise {\n\t\tlet result: Promise | undefined;\n\n\t\tthis.subTreeRefreshPromises.forEach((refreshPromise, refreshNode) => {\n\t\t\tif (!result && intersects(refreshNode, node)) {\n\t\t\t\tresult = refreshPromise.then(() => this.refreshNode(node, recursive, viewStateContext));\n\t\t\t}\n\t\t});\n\n\t\tif (result) {\n\t\t\treturn result;\n\t\t}\n\n\t\treturn this.doRefreshSubTree(node, recursive, viewStateContext);\n\t}\n\n\tprivate async doRefreshSubTree(node: IAsyncDataTreeNode, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): Promise {\n\t\tlet done: () => void;\n\t\tnode.refreshPromise = new Promise(c => done = c);\n\t\tthis.subTreeRefreshPromises.set(node, node.refreshPromise);\n\n\t\tnode.refreshPromise.finally(() => {\n\t\t\tnode.refreshPromise = undefined;\n\t\t\tthis.subTreeRefreshPromises.delete(node);\n\t\t});\n\n\t\ttry {\n\t\t\tconst childrenToRefresh = await this.doRefreshNode(node, recursive, viewStateContext);\n\t\t\tnode.stale = false;\n\n\t\t\tawait Promises.settled(childrenToRefresh.map(child => this.doRefreshSubTree(child, recursive, viewStateContext)));\n\t\t} finally {\n\t\t\tdone!();\n\t\t}\n\t}\n\n\tprivate async doRefreshNode(node: IAsyncDataTreeNode, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): Promise[]> {\n\t\tnode.hasChildren = !!this.dataSource.hasChildren(node.element!);\n\n\t\tlet childrenPromise: Promise>;\n\n\t\tif (!node.hasChildren) {\n\t\t\tchildrenPromise = Promise.resolve(Iterable.empty());\n\t\t} else {\n\t\t\tconst slowTimeout = timeout(800);\n\n\t\t\tslowTimeout.then(() => {\n\t\t\t\tnode.slow = true;\n\t\t\t\tthis._onDidChangeNodeSlowState.fire(node);\n\t\t\t}, _ => null);\n\n\t\t\tchildrenPromise = this.doGetChildren(node)\n\t\t\t\t.finally(() => slowTimeout.cancel());\n\t\t}\n\n\t\ttry {\n\t\t\tconst children = await childrenPromise;\n\t\t\treturn this.setChildren(node, children, recursive, viewStateContext);\n\t\t} catch (err) {\n\t\t\tif (node !== this.root && this.tree.hasElement(node)) {\n\t\t\t\tthis.tree.collapse(node);\n\t\t\t}\n\n\t\t\tif (isCancellationError(err)) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tthrow err;\n\t\t} finally {\n\t\t\tif (node.slow) {\n\t\t\t\tnode.slow = false;\n\t\t\t\tthis._onDidChangeNodeSlowState.fire(node);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate doGetChildren(node: IAsyncDataTreeNode): Promise> {\n\t\tlet result = this.refreshPromises.get(node);\n\n\t\tif (result) {\n\t\t\treturn result;\n\t\t}\n\n\t\tresult = createCancelablePromise(async () => {\n\t\t\tconst children = await this.dataSource.getChildren(node.element!);\n\t\t\treturn this.processChildren(children);\n\t\t});\n\n\t\tthis.refreshPromises.set(node, result);\n\n\t\treturn result.finally(() => { this.refreshPromises.delete(node); });\n\t}\n\n\tprivate _onDidChangeCollapseState({ node, deep }: ICollapseStateChangeEvent | null, any>): void {\n\t\tif (node.element === null) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!node.collapsed && node.element.stale) {\n\t\t\tif (deep) {\n\t\t\t\tthis.collapse(node.element.element as T);\n\t\t\t} else {\n\t\t\t\tthis.refreshAndRenderNode(node.element, false)\n\t\t\t\t\t.catch(onUnexpectedError);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate setChildren(node: IAsyncDataTreeNode, childrenElementsIterable: Iterable, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): IAsyncDataTreeNode[] {\n\t\tconst childrenElements = [...childrenElementsIterable];\n\n\t\t// perf: if the node was and still is a leaf, avoid all this hassle\n\t\tif (node.children.length === 0 && childrenElements.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst nodesToForget = new Map>();\n\t\tconst childrenTreeNodesById = new Map, collapsed: boolean; }>();\n\n\t\tfor (const child of node.children) {\n\t\t\tnodesToForget.set(child.element as T, child);\n\n\t\t\tif (this.identityProvider) {\n\t\t\t\tconst collapsed = this.tree.isCollapsed(child);\n\t\t\t\tchildrenTreeNodesById.set(child.id!, { node: child, collapsed });\n\t\t\t}\n\t\t}\n\n\t\tconst childrenToRefresh: IAsyncDataTreeNode[] = [];\n\n\t\tconst children = childrenElements.map>(element => {\n\t\t\tconst hasChildren = !!this.dataSource.hasChildren(element);\n\n\t\t\tif (!this.identityProvider) {\n\t\t\t\tconst asyncDataTreeNode = createAsyncDataTreeNode({ element, parent: node, hasChildren });\n\n\t\t\t\tif (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) {\n\t\t\t\t\tasyncDataTreeNode.collapsedByDefault = false;\n\t\t\t\t\tchildrenToRefresh.push(asyncDataTreeNode);\n\t\t\t\t}\n\n\t\t\t\treturn asyncDataTreeNode;\n\t\t\t}\n\n\t\t\tconst id = this.identityProvider.getId(element).toString();\n\t\t\tconst result = childrenTreeNodesById.get(id);\n\n\t\t\tif (result) {\n\t\t\t\tconst asyncDataTreeNode = result.node;\n\n\t\t\t\tnodesToForget.delete(asyncDataTreeNode.element as T);\n\t\t\t\tthis.nodes.delete(asyncDataTreeNode.element as T);\n\t\t\t\tthis.nodes.set(element, asyncDataTreeNode);\n\n\t\t\t\tasyncDataTreeNode.element = element;\n\t\t\t\tasyncDataTreeNode.hasChildren = hasChildren;\n\n\t\t\t\tif (recursive) {\n\t\t\t\t\tif (result.collapsed) {\n\t\t\t\t\t\tasyncDataTreeNode.children.forEach(node => dfs(node, node => this.nodes.delete(node.element as T)));\n\t\t\t\t\t\tasyncDataTreeNode.children.splice(0, asyncDataTreeNode.children.length);\n\t\t\t\t\t\tasyncDataTreeNode.stale = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tchildrenToRefresh.push(asyncDataTreeNode);\n\t\t\t\t\t}\n\t\t\t\t} else if (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) {\n\t\t\t\t\tasyncDataTreeNode.collapsedByDefault = false;\n\t\t\t\t\tchildrenToRefresh.push(asyncDataTreeNode);\n\t\t\t\t}\n\n\t\t\t\treturn asyncDataTreeNode;\n\t\t\t}\n\n\t\t\tconst childAsyncDataTreeNode = createAsyncDataTreeNode({ element, parent: node, id, hasChildren });\n\n\t\t\tif (viewStateContext && viewStateContext.viewState.focus && viewStateContext.viewState.focus.indexOf(id) > -1) {\n\t\t\t\tviewStateContext.focus.push(childAsyncDataTreeNode);\n\t\t\t}\n\n\t\t\tif (viewStateContext && viewStateContext.viewState.selection && viewStateContext.viewState.selection.indexOf(id) > -1) {\n\t\t\t\tviewStateContext.selection.push(childAsyncDataTreeNode);\n\t\t\t}\n\n\t\t\tif (viewStateContext && viewStateContext.viewState.expanded && viewStateContext.viewState.expanded.indexOf(id) > -1) {\n\t\t\t\tchildrenToRefresh.push(childAsyncDataTreeNode);\n\t\t\t} else if (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) {\n\t\t\t\tchildAsyncDataTreeNode.collapsedByDefault = false;\n\t\t\t\tchildrenToRefresh.push(childAsyncDataTreeNode);\n\t\t\t}\n\n\t\t\treturn childAsyncDataTreeNode;\n\t\t});\n\n\t\tfor (const node of nodesToForget.values()) {\n\t\t\tdfs(node, node => this.nodes.delete(node.element as T));\n\t\t}\n\n\t\tfor (const child of children) {\n\t\t\tthis.nodes.set(child.element as T, child);\n\t\t}\n\n\t\tnode.children.splice(0, node.children.length, ...children);\n\n\t\t// TODO@joao this doesn't take filter into account\n\t\tif (node !== this.root && this.autoExpandSingleChildren && children.length === 1 && childrenToRefresh.length === 0) {\n\t\t\tchildren[0].collapsedByDefault = false;\n\t\t\tchildrenToRefresh.push(children[0]);\n\t\t}\n\n\t\treturn childrenToRefresh;\n\t}\n\n\tprotected render(node: IAsyncDataTreeNode, viewStateContext?: IAsyncDataTreeViewStateContext, options?: IAsyncDataTreeUpdateChildrenOptions): void {\n\t\tconst children = node.children.map(node => this.asTreeElement(node, viewStateContext));\n\t\tconst objectTreeOptions: IObjectTreeSetChildrenOptions> | undefined = options && {\n\t\t\t...options,\n\t\t\tdiffIdentityProvider: options!.diffIdentityProvider && {\n\t\t\t\tgetId(node: IAsyncDataTreeNode): { toString(): string; } {\n\t\t\t\t\treturn options!.diffIdentityProvider!.getId(node.element as T);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tthis.tree.setChildren(node === this.root ? null : node, children, objectTreeOptions);\n\n\t\tif (node !== this.root) {\n\t\t\tthis.tree.setCollapsible(node, node.hasChildren);\n\t\t}\n\n\t\tthis._onDidRender.fire();\n\t}\n\n\tprotected asTreeElement(node: IAsyncDataTreeNode, viewStateContext?: IAsyncDataTreeViewStateContext): ITreeElement> {\n\t\tif (node.stale) {\n\t\t\treturn {\n\t\t\t\telement: node,\n\t\t\t\tcollapsible: node.hasChildren,\n\t\t\t\tcollapsed: true\n\t\t\t};\n\t\t}\n\n\t\tlet collapsed: boolean | undefined;\n\n\t\tif (viewStateContext && viewStateContext.viewState.expanded && node.id && viewStateContext.viewState.expanded.indexOf(node.id) > -1) {\n\t\t\tcollapsed = false;\n\t\t} else {\n\t\t\tcollapsed = node.collapsedByDefault;\n\t\t}\n\n\t\tnode.collapsedByDefault = undefined;\n\n\t\treturn {\n\t\t\telement: node,\n\t\t\tchildren: node.hasChildren ? Iterable.map(node.children, child => this.asTreeElement(child, viewStateContext)) : [],\n\t\t\tcollapsible: node.hasChildren,\n\t\t\tcollapsed\n\t\t};\n\t}\n\n\tprotected processChildren(children: Iterable): Iterable {\n\t\tif (this.sorter) {\n\t\t\tchildren = [...children].sort(this.sorter.compare.bind(this.sorter));\n\t\t}\n\n\t\treturn children;\n\t}\n\n\tdispose(): void {\n\t\tthis.disposables.dispose();\n\t}\n}\n\ntype CompressibleAsyncDataTreeNodeMapper = WeakMapper>, TFilterData>, ITreeNode, TFilterData>>;\n\nclass CompressibleAsyncDataTreeNodeWrapper implements ITreeNode, TFilterData> {\n\n\tget element(): ICompressedTreeNode {\n\t\treturn {\n\t\t\telements: this.node.element.elements.map(e => e.element),\n\t\t\tincompressible: this.node.element.incompressible\n\t\t};\n\t}\n\n\tget children(): ITreeNode, TFilterData>[] { return this.node.children.map(node => new CompressibleAsyncDataTreeNodeWrapper(node)); }\n\tget depth(): number { return this.node.depth; }\n\tget visibleChildrenCount(): number { return this.node.visibleChildrenCount; }\n\tget visibleChildIndex(): number { return this.node.visibleChildIndex; }\n\tget collapsible(): boolean { return this.node.collapsible; }\n\tget collapsed(): boolean { return this.node.collapsed; }\n\tget visible(): boolean { return this.node.visible; }\n\tget filterData(): TFilterData | undefined { return this.node.filterData; }\n\n\tconstructor(private node: ITreeNode>, TFilterData>) { }\n}\n\nclass CompressibleAsyncDataTreeRenderer implements ICompressibleTreeRenderer, TFilterData, IDataTreeListTemplateData> {\n\n\treadonly templateId: string;\n\tprivate renderedNodes = new Map, IDataTreeListTemplateData>();\n\tprivate disposables: IDisposable[] = [];\n\n\tconstructor(\n\t\tprotected renderer: ICompressibleTreeRenderer,\n\t\tprotected nodeMapper: AsyncDataTreeNodeMapper,\n\t\tprivate compressibleNodeMapperProvider: () => CompressibleAsyncDataTreeNodeMapper,\n\t\treadonly onDidChangeTwistieState: Event>\n\t) {\n\t\tthis.templateId = renderer.templateId;\n\t}\n\n\trenderTemplate(container: HTMLElement): IDataTreeListTemplateData {\n\t\tconst templateData = this.renderer.renderTemplate(container);\n\t\treturn { templateData };\n\t}\n\n\trenderElement(node: ITreeNode, TFilterData>, index: number, templateData: IDataTreeListTemplateData, height: number | undefined): void {\n\t\tthis.renderer.renderElement(this.nodeMapper.map(node) as ITreeNode, index, templateData.templateData, height);\n\t}\n\n\trenderCompressedElements(node: ITreeNode>, TFilterData>, index: number, templateData: IDataTreeListTemplateData, height: number | undefined): void {\n\t\tthis.renderer.renderCompressedElements(this.compressibleNodeMapperProvider().map(node) as ITreeNode, TFilterData>, index, templateData.templateData, height);\n\t}\n\n\trenderTwistie(element: IAsyncDataTreeNode, twistieElement: HTMLElement): boolean {\n\t\tif (element.slow) {\n\t\t\ttwistieElement.classList.add(...Codicon.treeItemLoading.classNamesArray);\n\t\t\treturn true;\n\t\t} else {\n\t\t\ttwistieElement.classList.remove(...Codicon.treeItemLoading.classNamesArray);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tdisposeElement(node: ITreeNode, TFilterData>, index: number, templateData: IDataTreeListTemplateData, height: number | undefined): void {\n\t\tif (this.renderer.disposeElement) {\n\t\t\tthis.renderer.disposeElement(this.nodeMapper.map(node) as ITreeNode, index, templateData.templateData, height);\n\t\t}\n\t}\n\n\tdisposeCompressedElements(node: ITreeNode>, TFilterData>, index: number, templateData: IDataTreeListTemplateData, height: number | undefined): void {\n\t\tif (this.renderer.disposeCompressedElements) {\n\t\t\tthis.renderer.disposeCompressedElements(this.compressibleNodeMapperProvider().map(node) as ITreeNode, TFilterData>, index, templateData.templateData, height);\n\t\t}\n\t}\n\n\tdisposeTemplate(templateData: IDataTreeListTemplateData): void {\n\t\tthis.renderer.disposeTemplate(templateData.templateData);\n\t}\n\n\tdispose(): void {\n\t\tthis.renderedNodes.clear();\n\t\tthis.disposables = dispose(this.disposables);\n\t}\n}\n\nexport interface ITreeCompressionDelegate {\n\tisIncompressible(element: T): boolean;\n}\n\nfunction asCompressibleObjectTreeOptions(options?: ICompressibleAsyncDataTreeOptions): ICompressibleObjectTreeOptions, TFilterData> | undefined {\n\tconst objectTreeOptions = options && asObjectTreeOptions(options);\n\n\treturn objectTreeOptions && {\n\t\t...objectTreeOptions,\n\t\tkeyboardNavigationLabelProvider: objectTreeOptions.keyboardNavigationLabelProvider && {\n\t\t\t...objectTreeOptions.keyboardNavigationLabelProvider,\n\t\t\tgetCompressedNodeKeyboardNavigationLabel(els) {\n\t\t\t\treturn options!.keyboardNavigationLabelProvider!.getCompressedNodeKeyboardNavigationLabel(els.map(e => e.element as T));\n\t\t\t}\n\t\t}\n\t};\n}\n\nexport interface ICompressibleAsyncDataTreeOptions extends IAsyncDataTreeOptions {\n\treadonly keyboardNavigationLabelProvider?: ICompressibleKeyboardNavigationLabelProvider;\n}\n\nexport interface ICompressibleAsyncDataTreeOptionsUpdate extends IAsyncDataTreeOptionsUpdate {\n}\n\nexport class CompressibleAsyncDataTree extends AsyncDataTree {\n\n\tprotected override readonly tree!: CompressibleObjectTree, TFilterData>;\n\tprotected readonly compressibleNodeMapper: CompressibleAsyncDataTreeNodeMapper = new WeakMapper(node => new CompressibleAsyncDataTreeNodeWrapper(node));\n\tprivate filter?: ITreeFilter;\n\n\tconstructor(\n\t\tuser: string,\n\t\tcontainer: HTMLElement,\n\t\tvirtualDelegate: IListVirtualDelegate,\n\t\tprivate compressionDelegate: ITreeCompressionDelegate,\n\t\trenderers: ICompressibleTreeRenderer[],\n\t\tdataSource: IAsyncDataSource,\n\t\toptions: ICompressibleAsyncDataTreeOptions = {}\n\t) {\n\t\tsuper(user, container, virtualDelegate, renderers, dataSource, options);\n\t\tthis.filter = options.filter;\n\t}\n\n\tprotected override createTree(\n\t\tuser: string,\n\t\tcontainer: HTMLElement,\n\t\tdelegate: IListVirtualDelegate,\n\t\trenderers: ICompressibleTreeRenderer[],\n\t\toptions: ICompressibleAsyncDataTreeOptions\n\t): ObjectTree, TFilterData> {\n\t\tconst objectTreeDelegate = new ComposedTreeDelegate>(delegate);\n\t\tconst objectTreeRenderers = renderers.map(r => new CompressibleAsyncDataTreeRenderer(r, this.nodeMapper, () => this.compressibleNodeMapper, this._onDidChangeNodeSlowState.event));\n\t\tconst objectTreeOptions = asCompressibleObjectTreeOptions(options) || {};\n\n\t\treturn new CompressibleObjectTree(user, container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions);\n\t}\n\n\tprotected override asTreeElement(node: IAsyncDataTreeNode, viewStateContext?: IAsyncDataTreeViewStateContext): ICompressedTreeElement> {\n\t\treturn {\n\t\t\tincompressible: this.compressionDelegate.isIncompressible(node.element as T),\n\t\t\t...super.asTreeElement(node, viewStateContext)\n\t\t};\n\t}\n\n\toverride updateOptions(options: ICompressibleAsyncDataTreeOptionsUpdate = {}): void {\n\t\tthis.tree.updateOptions(options);\n\t}\n\n\tprotected override render(node: IAsyncDataTreeNode, viewStateContext?: IAsyncDataTreeViewStateContext): void {\n\t\tif (!this.identityProvider) {\n\t\t\treturn super.render(node, viewStateContext);\n\t\t}\n\n\t\t// Preserve traits across compressions. Hacky but does the trick.\n\t\t// This is hard to fix properly since it requires rewriting the traits\n\t\t// across trees and lists. Let's just keep it this way for now.\n\t\tconst getId = (element: T) => this.identityProvider!.getId(element).toString();\n\t\tconst getUncompressedIds = (nodes: IAsyncDataTreeNode[]): Set => {\n\t\t\tconst result = new Set();\n\n\t\t\tfor (const node of nodes) {\n\t\t\t\tconst compressedNode = this.tree.getCompressedTreeNode(node === this.root ? null : node);\n\n\t\t\t\tif (!compressedNode.element) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tfor (const node of compressedNode.element.elements) {\n\t\t\t\t\tresult.add(getId(node.element as T));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t};\n\n\t\tconst oldSelection = getUncompressedIds(this.tree.getSelection() as IAsyncDataTreeNode[]);\n\t\tconst oldFocus = getUncompressedIds(this.tree.getFocus() as IAsyncDataTreeNode[]);\n\n\t\tsuper.render(node, viewStateContext);\n\n\t\tconst selection = this.getSelection();\n\t\tlet didChangeSelection = false;\n\n\t\tconst focus = this.getFocus();\n\t\tlet didChangeFocus = false;\n\n\t\tconst visit = (node: ITreeNode> | null, TFilterData>) => {\n\t\t\tconst compressedNode = node.element;\n\n\t\t\tif (compressedNode) {\n\t\t\t\tfor (let i = 0; i < compressedNode.elements.length; i++) {\n\t\t\t\t\tconst id = getId(compressedNode.elements[i].element as T);\n\t\t\t\t\tconst element = compressedNode.elements[compressedNode.elements.length - 1].element as T;\n\n\t\t\t\t\t// github.com/microsoft/vscode/issues/85938\n\t\t\t\t\tif (oldSelection.has(id) && selection.indexOf(element) === -1) {\n\t\t\t\t\t\tselection.push(element);\n\t\t\t\t\t\tdidChangeSelection = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (oldFocus.has(id) && focus.indexOf(element) === -1) {\n\t\t\t\t\t\tfocus.push(element);\n\t\t\t\t\t\tdidChangeFocus = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnode.children.forEach(visit);\n\t\t};\n\n\t\tvisit(this.tree.getCompressedTreeNode(node === this.root ? null : node));\n\n\t\tif (didChangeSelection) {\n\t\t\tthis.setSelection(selection);\n\t\t}\n\n\t\tif (didChangeFocus) {\n\t\t\tthis.setFocus(focus);\n\t\t}\n\t}\n\n\t// For compressed async data trees, `TreeVisibility.Recurse` doesn't currently work\n\t// and we have to filter everything beforehand\n\t// Related to #85193 and #85835\n\tprotected override processChildren(children: Iterable): Iterable {\n\t\tif (this.filter) {\n\t\t\tchildren = Iterable.filter(children, e => {\n\t\t\t\tconst result = this.filter!.filter(e, TreeVisibility.Visible);\n\t\t\t\tconst visibility = getVisibility(result);\n\n\t\t\t\tif (visibility === TreeVisibility.Recurse) {\n\t\t\t\t\tthrow new Error('Recursive tree visibility not supported in async data compressed trees');\n\t\t\t\t}\n\n\t\t\t\treturn visibility === TreeVisibility.Visible;\n\t\t\t});\n\t\t}\n\n\t\treturn super.processChildren(children);\n\t}\n}\n\nfunction getVisibility(filterResult: TreeFilterResult): TreeVisibility {\n\tif (typeof filterResult === 'boolean') {\n\t\treturn filterResult ? TreeVisibility.Visible : TreeVisibility.Hidden;\n\t} else if (isFilterResult(filterResult)) {\n\t\treturn getVisibleState(filterResult.visibility);\n\t} else {\n\t\treturn getVisibleState(filterResult);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport * as nls from 'vs/nls';\n\nexport interface ITelemetryData {\n\t[key: string]: unknown;\n}\n\nexport type WorkbenchActionExecutedClassification = {\n\tid: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };\n\tfrom: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };\n};\n\nexport type WorkbenchActionExecutedEvent = {\n\tid: string;\n\tfrom: string;\n};\n\nexport interface IAction extends IDisposable {\n\treadonly id: string;\n\tlabel: string;\n\ttooltip: string;\n\tclass: string | undefined;\n\tenabled: boolean;\n\tchecked?: boolean;\n\trun(event?: unknown): unknown;\n}\n\nexport interface IActionRunner extends IDisposable {\n\treadonly onDidRun: Event;\n\treadonly onBeforeRun: Event;\n\n\trun(action: IAction, context?: unknown): unknown;\n}\n\nexport interface IActionChangeEvent {\n\treadonly label?: string;\n\treadonly tooltip?: string;\n\treadonly class?: string;\n\treadonly enabled?: boolean;\n\treadonly checked?: boolean;\n}\n\nexport class Action extends Disposable implements IAction {\n\n\tprotected _onDidChange = this._register(new Emitter());\n\treadonly onDidChange = this._onDidChange.event;\n\n\tprotected readonly _id: string;\n\tprotected _label: string;\n\tprotected _tooltip: string | undefined;\n\tprotected _cssClass: string | undefined;\n\tprotected _enabled: boolean = true;\n\tprotected _checked?: boolean;\n\tprotected readonly _actionCallback?: (event?: unknown) => unknown;\n\n\tconstructor(id: string, label: string = '', cssClass: string = '', enabled: boolean = true, actionCallback?: (event?: unknown) => unknown) {\n\t\tsuper();\n\t\tthis._id = id;\n\t\tthis._label = label;\n\t\tthis._cssClass = cssClass;\n\t\tthis._enabled = enabled;\n\t\tthis._actionCallback = actionCallback;\n\t}\n\n\tget id(): string {\n\t\treturn this._id;\n\t}\n\n\tget label(): string {\n\t\treturn this._label;\n\t}\n\n\tset label(value: string) {\n\t\tthis._setLabel(value);\n\t}\n\n\tprivate _setLabel(value: string): void {\n\t\tif (this._label !== value) {\n\t\t\tthis._label = value;\n\t\t\tthis._onDidChange.fire({ label: value });\n\t\t}\n\t}\n\n\tget tooltip(): string {\n\t\treturn this._tooltip || '';\n\t}\n\n\tset tooltip(value: string) {\n\t\tthis._setTooltip(value);\n\t}\n\n\tprotected _setTooltip(value: string): void {\n\t\tif (this._tooltip !== value) {\n\t\t\tthis._tooltip = value;\n\t\t\tthis._onDidChange.fire({ tooltip: value });\n\t\t}\n\t}\n\n\tget class(): string | undefined {\n\t\treturn this._cssClass;\n\t}\n\n\tset class(value: string | undefined) {\n\t\tthis._setClass(value);\n\t}\n\n\tprotected _setClass(value: string | undefined): void {\n\t\tif (this._cssClass !== value) {\n\t\t\tthis._cssClass = value;\n\t\t\tthis._onDidChange.fire({ class: value });\n\t\t}\n\t}\n\n\tget enabled(): boolean {\n\t\treturn this._enabled;\n\t}\n\n\tset enabled(value: boolean) {\n\t\tthis._setEnabled(value);\n\t}\n\n\tprotected _setEnabled(value: boolean): void {\n\t\tif (this._enabled !== value) {\n\t\t\tthis._enabled = value;\n\t\t\tthis._onDidChange.fire({ enabled: value });\n\t\t}\n\t}\n\n\tget checked(): boolean | undefined {\n\t\treturn this._checked;\n\t}\n\n\tset checked(value: boolean | undefined) {\n\t\tthis._setChecked(value);\n\t}\n\n\tprotected _setChecked(value: boolean | undefined): void {\n\t\tif (this._checked !== value) {\n\t\t\tthis._checked = value;\n\t\t\tthis._onDidChange.fire({ checked: value });\n\t\t}\n\t}\n\n\tasync run(event?: unknown, data?: ITelemetryData): Promise {\n\t\tif (this._actionCallback) {\n\t\t\tawait this._actionCallback(event);\n\t\t}\n\t}\n}\n\nexport interface IRunEvent {\n\treadonly action: IAction;\n\treadonly error?: Error;\n}\n\nexport class ActionRunner extends Disposable implements IActionRunner {\n\n\tprivate _onBeforeRun = this._register(new Emitter());\n\treadonly onBeforeRun = this._onBeforeRun.event;\n\n\tprivate _onDidRun = this._register(new Emitter());\n\treadonly onDidRun = this._onDidRun.event;\n\n\tasync run(action: IAction, context?: unknown): Promise {\n\t\tif (!action.enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._onBeforeRun.fire({ action });\n\n\t\tlet error: Error | undefined = undefined;\n\t\ttry {\n\t\t\tawait this.runAction(action, context);\n\t\t} catch (e) {\n\t\t\terror = e;\n\t\t}\n\n\t\tthis._onDidRun.fire({ action, error });\n\t}\n\n\tprotected async runAction(action: IAction, context?: unknown): Promise {\n\t\tawait action.run(context);\n\t}\n}\n\nexport class Separator extends Action {\n\n\tstatic readonly ID = 'vs.actions.separator';\n\n\tconstructor(label?: string) {\n\t\tsuper(Separator.ID, label, label ? 'separator text' : 'separator');\n\n\t\tthis.checked = false;\n\t\tthis.enabled = false;\n\t}\n}\n\nexport class SubmenuAction implements IAction {\n\n\treadonly id: string;\n\treadonly label: string;\n\treadonly class: string | undefined;\n\treadonly tooltip: string = '';\n\treadonly enabled: boolean = true;\n\treadonly checked: undefined = undefined;\n\n\tprivate readonly _actions: readonly IAction[];\n\tget actions(): readonly IAction[] { return this._actions; }\n\n\tconstructor(id: string, label: string, actions: readonly IAction[], cssClass?: string) {\n\t\tthis.id = id;\n\t\tthis.label = label;\n\t\tthis.class = cssClass;\n\t\tthis._actions = actions;\n\t}\n\n\tdispose(): void {\n\t\t// there is NOTHING to dispose and the SubmenuAction should\n\t\t// never have anything to dispose as it is a convenience type\n\t\t// to bridge into the rendering world.\n\t}\n\n\tasync run(): Promise { }\n}\n\nexport class EmptySubmenuAction extends Action {\n\n\tstatic readonly ID = 'vs.actions.empty';\n\n\tconstructor() {\n\t\tsuper(EmptySubmenuAction.ID, nls.localize('submenu.empty', '(empty)'), undefined, false);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { isFirefox } from 'vs/base/browser/browser';\nimport { DataTransfers } from 'vs/base/browser/dnd';\nimport { $, addDisposableListener, append, EventHelper, EventLike, EventType } from 'vs/base/browser/dom';\nimport { EventType as TouchEventType, Gesture } from 'vs/base/browser/touch';\nimport { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';\nimport { Action, ActionRunner, IAction, IActionChangeEvent, IActionRunner, Separator } from 'vs/base/common/actions';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport * as platform from 'vs/base/common/platform';\nimport * as types from 'vs/base/common/types';\nimport 'vs/css!./actionbar';\nimport * as nls from 'vs/nls';\n\nexport interface IBaseActionViewItemOptions {\n\tdraggable?: boolean;\n\tisMenu?: boolean;\n\tuseEventAsContext?: boolean;\n}\n\nexport class BaseActionViewItem extends Disposable implements IActionViewItem {\n\n\telement: HTMLElement | undefined;\n\n\t_context: unknown;\n\t_action: IAction;\n\n\tprivate _actionRunner: IActionRunner | undefined;\n\n\tconstructor(context: unknown, action: IAction, protected options: IBaseActionViewItemOptions = {}) {\n\t\tsuper();\n\n\t\tthis._context = context || this;\n\t\tthis._action = action;\n\n\t\tif (action instanceof Action) {\n\t\t\tthis._register(action.onDidChange(event => {\n\t\t\t\tif (!this.element) {\n\t\t\t\t\t// we have not been rendered yet, so there\n\t\t\t\t\t// is no point in updating the UI\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.handleActionChangeEvent(event);\n\t\t\t}));\n\t\t}\n\t}\n\n\tprivate handleActionChangeEvent(event: IActionChangeEvent): void {\n\t\tif (event.enabled !== undefined) {\n\t\t\tthis.updateEnabled();\n\t\t}\n\n\t\tif (event.checked !== undefined) {\n\t\t\tthis.updateChecked();\n\t\t}\n\n\t\tif (event.class !== undefined) {\n\t\t\tthis.updateClass();\n\t\t}\n\n\t\tif (event.label !== undefined) {\n\t\t\tthis.updateLabel();\n\t\t\tthis.updateTooltip();\n\t\t}\n\n\t\tif (event.tooltip !== undefined) {\n\t\t\tthis.updateTooltip();\n\t\t}\n\t}\n\n\tget actionRunner(): IActionRunner {\n\t\tif (!this._actionRunner) {\n\t\t\tthis._actionRunner = this._register(new ActionRunner());\n\t\t}\n\n\t\treturn this._actionRunner;\n\t}\n\n\tset actionRunner(actionRunner: IActionRunner) {\n\t\tthis._actionRunner = actionRunner;\n\t}\n\n\tgetAction(): IAction {\n\t\treturn this._action;\n\t}\n\n\tisEnabled(): boolean {\n\t\treturn this._action.enabled;\n\t}\n\n\tsetActionContext(newContext: unknown): void {\n\t\tthis._context = newContext;\n\t}\n\n\trender(container: HTMLElement): void {\n\t\tconst element = this.element = container;\n\t\tthis._register(Gesture.addTarget(container));\n\n\t\tconst enableDragging = this.options && this.options.draggable;\n\t\tif (enableDragging) {\n\t\t\tcontainer.draggable = true;\n\n\t\t\tif (isFirefox) {\n\t\t\t\t// Firefox: requires to set a text data transfer to get going\n\t\t\t\tthis._register(addDisposableListener(container, EventType.DRAG_START, e => e.dataTransfer?.setData(DataTransfers.TEXT, this._action.label)));\n\t\t\t}\n\t\t}\n\n\t\tthis._register(addDisposableListener(element, TouchEventType.Tap, e => this.onClick(e, true))); // Preserve focus on tap #125470\n\n\t\tthis._register(addDisposableListener(element, EventType.MOUSE_DOWN, e => {\n\t\t\tif (!enableDragging) {\n\t\t\t\tEventHelper.stop(e, true); // do not run when dragging is on because that would disable it\n\t\t\t}\n\n\t\t\tif (this._action.enabled && e.button === 0) {\n\t\t\t\telement.classList.add('active');\n\t\t\t}\n\t\t}));\n\n\t\tif (platform.isMacintosh) {\n\t\t\t// macOS: allow to trigger the button when holding Ctrl+key and pressing the\n\t\t\t// main mouse button. This is for scenarios where e.g. some interaction forces\n\t\t\t// the Ctrl+key to be pressed and hold but the user still wants to interact\n\t\t\t// with the actions (for example quick access in quick navigation mode).\n\t\t\tthis._register(addDisposableListener(element, EventType.CONTEXT_MENU, e => {\n\t\t\t\tif (e.button === 0 && e.ctrlKey === true) {\n\t\t\t\t\tthis.onClick(e);\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\n\t\tthis._register(addDisposableListener(element, EventType.CLICK, e => {\n\t\t\tEventHelper.stop(e, true);\n\n\t\t\t// menus do not use the click event\n\t\t\tif (!(this.options && this.options.isMenu)) {\n\t\t\t\tthis.onClick(e);\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(addDisposableListener(element, EventType.DBLCLICK, e => {\n\t\t\tEventHelper.stop(e, true);\n\t\t}));\n\n\t\t[EventType.MOUSE_UP, EventType.MOUSE_OUT].forEach(event => {\n\t\t\tthis._register(addDisposableListener(element, event, e => {\n\t\t\t\tEventHelper.stop(e);\n\t\t\t\telement.classList.remove('active');\n\t\t\t}));\n\t\t});\n\t}\n\n\tonClick(event: EventLike, preserveFocus = false): void {\n\t\tEventHelper.stop(event, true);\n\n\t\tconst context = types.isUndefinedOrNull(this._context) ? this.options?.useEventAsContext ? event : { preserveFocus } : this._context;\n\t\tthis.actionRunner.run(this._action, context);\n\t}\n\n\t// Only set the tabIndex on the element once it is about to get focused\n\t// That way this element wont be a tab stop when it is not needed #106441\n\tfocus(): void {\n\t\tif (this.element) {\n\t\t\tthis.element.tabIndex = 0;\n\t\t\tthis.element.focus();\n\t\t\tthis.element.classList.add('focused');\n\t\t}\n\t}\n\n\tblur(): void {\n\t\tif (this.element) {\n\t\t\tthis.element.blur();\n\t\t\tthis.element.tabIndex = -1;\n\t\t\tthis.element.classList.remove('focused');\n\t\t}\n\t}\n\n\tsetFocusable(focusable: boolean): void {\n\t\tif (this.element) {\n\t\t\tthis.element.tabIndex = focusable ? 0 : -1;\n\t\t}\n\t}\n\n\tget trapsArrowNavigation(): boolean {\n\t\treturn false;\n\t}\n\n\tprotected updateEnabled(): void {\n\t\t// implement in subclass\n\t}\n\n\tprotected updateLabel(): void {\n\t\t// implement in subclass\n\t}\n\n\tprotected updateTooltip(): void {\n\t\t// implement in subclass\n\t}\n\n\tprotected updateClass(): void {\n\t\t// implement in subclass\n\t}\n\n\tprotected updateChecked(): void {\n\t\t// implement in subclass\n\t}\n\n\toverride dispose(): void {\n\t\tif (this.element) {\n\t\t\tthis.element.remove();\n\t\t\tthis.element = undefined;\n\t\t}\n\n\t\tsuper.dispose();\n\t}\n}\n\nexport interface IActionViewItemOptions extends IBaseActionViewItemOptions {\n\ticon?: boolean;\n\tlabel?: boolean;\n\tkeybinding?: string | null;\n}\n\nexport class ActionViewItem extends BaseActionViewItem {\n\n\tprotected label: HTMLElement | undefined;\n\tprotected override options: IActionViewItemOptions;\n\n\tprivate cssClass?: string;\n\n\tconstructor(context: unknown, action: IAction, options: IActionViewItemOptions = {}) {\n\t\tsuper(context, action, options);\n\n\t\tthis.options = options;\n\t\tthis.options.icon = options.icon !== undefined ? options.icon : false;\n\t\tthis.options.label = options.label !== undefined ? options.label : true;\n\t\tthis.cssClass = '';\n\t}\n\n\toverride render(container: HTMLElement): void {\n\t\tsuper.render(container);\n\n\t\tif (this.element) {\n\t\t\tthis.label = append(this.element, $('a.action-label'));\n\t\t}\n\n\t\tif (this.label) {\n\t\t\tif (this._action.id === Separator.ID) {\n\t\t\t\tthis.label.setAttribute('role', 'presentation'); // A separator is a presentation item\n\t\t\t} else {\n\t\t\t\tif (this.options.isMenu) {\n\t\t\t\t\tthis.label.setAttribute('role', 'menuitem');\n\t\t\t\t} else {\n\t\t\t\t\tthis.label.setAttribute('role', 'button');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.options.label && this.options.keybinding && this.element) {\n\t\t\tappend(this.element, $('span.keybinding')).textContent = this.options.keybinding;\n\t\t}\n\n\t\tthis.updateClass();\n\t\tthis.updateLabel();\n\t\tthis.updateTooltip();\n\t\tthis.updateEnabled();\n\t\tthis.updateChecked();\n\t}\n\n\t// Only set the tabIndex on the element once it is about to get focused\n\t// That way this element wont be a tab stop when it is not needed #106441\n\toverride focus(): void {\n\t\tif (this.label) {\n\t\t\tthis.label.tabIndex = 0;\n\t\t\tthis.label.focus();\n\t\t}\n\t}\n\n\toverride blur(): void {\n\t\tif (this.label) {\n\t\t\tthis.label.tabIndex = -1;\n\t\t}\n\t}\n\n\toverride setFocusable(focusable: boolean): void {\n\t\tif (this.label) {\n\t\t\tthis.label.tabIndex = focusable ? 0 : -1;\n\t\t}\n\t}\n\n\toverride updateLabel(): void {\n\t\tif (this.options.label && this.label) {\n\t\t\tthis.label.textContent = this.getAction().label;\n\t\t}\n\t}\n\n\toverride updateTooltip(): void {\n\t\tlet title: string | null = null;\n\n\t\tif (this.getAction().tooltip) {\n\t\t\ttitle = this.getAction().tooltip;\n\n\t\t} else if (!this.options.label && this.getAction().label && this.options.icon) {\n\t\t\ttitle = this.getAction().label;\n\n\t\t\tif (this.options.keybinding) {\n\t\t\t\ttitle = nls.localize({ key: 'titleLabel', comment: ['action title', 'action keybinding'] }, \"{0} ({1})\", title, this.options.keybinding);\n\t\t\t}\n\t\t}\n\n\t\tif (title && this.label) {\n\t\t\tthis.label.title = title;\n\t\t}\n\t}\n\n\toverride updateClass(): void {\n\t\tif (this.cssClass && this.label) {\n\t\t\tthis.label.classList.remove(...this.cssClass.split(' '));\n\t\t}\n\n\t\tif (this.options.icon) {\n\t\t\tthis.cssClass = this.getAction().class;\n\n\t\t\tif (this.label) {\n\t\t\t\tthis.label.classList.add('codicon');\n\t\t\t\tif (this.cssClass) {\n\t\t\t\t\tthis.label.classList.add(...this.cssClass.split(' '));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.updateEnabled();\n\t\t} else {\n\t\t\tif (this.label) {\n\t\t\t\tthis.label.classList.remove('codicon');\n\t\t\t}\n\t\t}\n\t}\n\n\toverride updateEnabled(): void {\n\t\tif (this.getAction().enabled) {\n\t\t\tif (this.label) {\n\t\t\t\tthis.label.removeAttribute('aria-disabled');\n\t\t\t\tthis.label.classList.remove('disabled');\n\t\t\t}\n\n\t\t\tif (this.element) {\n\t\t\t\tthis.element.classList.remove('disabled');\n\t\t\t}\n\t\t} else {\n\t\t\tif (this.label) {\n\t\t\t\tthis.label.setAttribute('aria-disabled', 'true');\n\t\t\t\tthis.label.classList.add('disabled');\n\t\t\t}\n\n\t\t\tif (this.element) {\n\t\t\t\tthis.element.classList.add('disabled');\n\t\t\t}\n\t\t}\n\t}\n\n\toverride updateChecked(): void {\n\t\tif (this.label) {\n\t\t\tif (this.getAction().checked) {\n\t\t\t\tthis.label.classList.add('checked');\n\t\t\t} else {\n\t\t\t\tthis.label.classList.remove('checked');\n\t\t\t}\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as DOM from 'vs/base/browser/dom';\nimport { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { ActionViewItem, BaseActionViewItem, IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';\nimport { ActionRunner, IAction, IActionRunner, IRunEvent } from 'vs/base/common/actions';\nimport { Emitter } from 'vs/base/common/event';\nimport { KeyCode, KeyMod } from 'vs/base/common/keyCodes';\nimport { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';\nimport * as types from 'vs/base/common/types';\nimport 'vs/css!./actionbar';\n\nexport interface IActionViewItem extends IDisposable {\n\tactionRunner: IActionRunner;\n\tsetActionContext(context: unknown): void;\n\trender(element: HTMLElement): void;\n\tisEnabled(): boolean;\n\tfocus(fromRight?: boolean): void; // TODO@isidorn what is this?\n\tblur(): void;\n}\n\nexport interface IActionViewItemProvider {\n\t(action: IAction): IActionViewItem | undefined;\n}\n\nexport const enum ActionsOrientation {\n\tHORIZONTAL,\n\tVERTICAL,\n}\n\nexport interface ActionTrigger {\n\tkeys?: KeyCode[];\n\tkeyDown: boolean;\n}\n\nexport interface IActionBarOptions {\n\treadonly orientation?: ActionsOrientation;\n\treadonly context?: unknown;\n\treadonly actionViewItemProvider?: IActionViewItemProvider;\n\treadonly actionRunner?: IActionRunner;\n\treadonly ariaLabel?: string;\n\treadonly animated?: boolean;\n\treadonly triggerKeys?: ActionTrigger;\n\treadonly allowContextMenu?: boolean;\n\treadonly preventLoopNavigation?: boolean;\n\treadonly focusOnlyEnabledItems?: boolean;\n}\n\nexport interface IActionOptions extends IActionViewItemOptions {\n\tindex?: number;\n}\n\nexport class ActionBar extends Disposable implements IActionRunner {\n\n\tprivate readonly options: IActionBarOptions;\n\n\tprivate _actionRunner: IActionRunner;\n\tprivate _context: unknown;\n\tprivate readonly _orientation: ActionsOrientation;\n\tprivate readonly _triggerKeys: {\n\t\tkeys: KeyCode[];\n\t\tkeyDown: boolean;\n\t};\n\tprivate _actionIds: string[];\n\n\t// View Items\n\tviewItems: IActionViewItem[];\n\tprivate previouslyFocusedItem?: number;\n\tprotected focusedItem?: number;\n\tprivate focusTracker: DOM.IFocusTracker;\n\n\t// Trigger Key Tracking\n\tprivate triggerKeyDown: boolean = false;\n\n\tprivate focusable: boolean = true;\n\n\t// Elements\n\tdomNode: HTMLElement;\n\tprotected actionsList: HTMLElement;\n\n\tprivate _onDidBlur = this._register(new Emitter());\n\treadonly onDidBlur = this._onDidBlur.event;\n\n\tprivate _onDidCancel = this._register(new Emitter({ onFirstListenerAdd: () => this.cancelHasListener = true }));\n\treadonly onDidCancel = this._onDidCancel.event;\n\tprivate cancelHasListener = false;\n\n\tprivate _onDidRun = this._register(new Emitter());\n\treadonly onDidRun = this._onDidRun.event;\n\n\tprivate _onBeforeRun = this._register(new Emitter());\n\treadonly onBeforeRun = this._onBeforeRun.event;\n\n\tconstructor(container: HTMLElement, options: IActionBarOptions = {}) {\n\t\tsuper();\n\n\t\tthis.options = options;\n\t\tthis._context = options.context ?? null;\n\t\tthis._orientation = this.options.orientation ?? ActionsOrientation.HORIZONTAL;\n\t\tthis._triggerKeys = {\n\t\t\tkeyDown: this.options.triggerKeys?.keyDown ?? false,\n\t\t\tkeys: this.options.triggerKeys?.keys ?? [KeyCode.Enter, KeyCode.Space]\n\t\t};\n\n\t\tif (this.options.actionRunner) {\n\t\t\tthis._actionRunner = this.options.actionRunner;\n\t\t} else {\n\t\t\tthis._actionRunner = new ActionRunner();\n\t\t\tthis._register(this._actionRunner);\n\t\t}\n\n\t\tthis._register(this._actionRunner.onDidRun(e => this._onDidRun.fire(e)));\n\t\tthis._register(this._actionRunner.onBeforeRun(e => this._onBeforeRun.fire(e)));\n\n\t\tthis._actionIds = [];\n\t\tthis.viewItems = [];\n\t\tthis.focusedItem = undefined;\n\n\t\tthis.domNode = document.createElement('div');\n\t\tthis.domNode.className = 'monaco-action-bar';\n\n\t\tif (options.animated !== false) {\n\t\t\tthis.domNode.classList.add('animated');\n\t\t}\n\n\t\tlet previousKeys: KeyCode[];\n\t\tlet nextKeys: KeyCode[];\n\n\t\tswitch (this._orientation) {\n\t\t\tcase ActionsOrientation.HORIZONTAL:\n\t\t\t\tpreviousKeys = [KeyCode.LeftArrow];\n\t\t\t\tnextKeys = [KeyCode.RightArrow];\n\t\t\t\tbreak;\n\t\t\tcase ActionsOrientation.VERTICAL:\n\t\t\t\tpreviousKeys = [KeyCode.UpArrow];\n\t\t\t\tnextKeys = [KeyCode.DownArrow];\n\t\t\t\tthis.domNode.className += ' vertical';\n\t\t\t\tbreak;\n\t\t}\n\n\t\tthis._register(DOM.addDisposableListener(this.domNode, DOM.EventType.KEY_DOWN, e => {\n\t\t\tconst event = new StandardKeyboardEvent(e);\n\t\t\tlet eventHandled = true;\n\t\t\tconst focusedItem = typeof this.focusedItem === 'number' ? this.viewItems[this.focusedItem] : undefined;\n\n\t\t\tif (previousKeys && (event.equals(previousKeys[0]) || event.equals(previousKeys[1]))) {\n\t\t\t\teventHandled = this.focusPrevious();\n\t\t\t} else if (nextKeys && (event.equals(nextKeys[0]) || event.equals(nextKeys[1]))) {\n\t\t\t\teventHandled = this.focusNext();\n\t\t\t} else if (event.equals(KeyCode.Escape) && this.cancelHasListener) {\n\t\t\t\tthis._onDidCancel.fire();\n\t\t\t} else if (event.equals(KeyCode.Home)) {\n\t\t\t\teventHandled = this.focusFirst();\n\t\t\t} else if (event.equals(KeyCode.End)) {\n\t\t\t\teventHandled = this.focusLast();\n\t\t\t} else if (event.equals(KeyCode.Tab) && focusedItem instanceof BaseActionViewItem && focusedItem.trapsArrowNavigation) {\n\t\t\t\teventHandled = this.focusNext();\n\t\t\t} else if (this.isTriggerKeyEvent(event)) {\n\t\t\t\t// Staying out of the else branch even if not triggered\n\t\t\t\tif (this._triggerKeys.keyDown) {\n\t\t\t\t\tthis.doTrigger(event);\n\t\t\t\t} else {\n\t\t\t\t\tthis.triggerKeyDown = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\teventHandled = false;\n\t\t\t}\n\n\t\t\tif (eventHandled) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(DOM.addDisposableListener(this.domNode, DOM.EventType.KEY_UP, e => {\n\t\t\tconst event = new StandardKeyboardEvent(e);\n\n\t\t\t// Run action on Enter/Space\n\t\t\tif (this.isTriggerKeyEvent(event)) {\n\t\t\t\tif (!this._triggerKeys.keyDown && this.triggerKeyDown) {\n\t\t\t\t\tthis.triggerKeyDown = false;\n\t\t\t\t\tthis.doTrigger(event);\n\t\t\t\t}\n\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\n\t\t\t// Recompute focused item\n\t\t\telse if (event.equals(KeyCode.Tab) || event.equals(KeyMod.Shift | KeyCode.Tab)) {\n\t\t\t\tthis.updateFocusedItem();\n\t\t\t}\n\t\t}));\n\n\t\tthis.focusTracker = this._register(DOM.trackFocus(this.domNode));\n\t\tthis._register(this.focusTracker.onDidBlur(() => {\n\t\t\tif (DOM.getActiveElement() === this.domNode || !DOM.isAncestor(DOM.getActiveElement(), this.domNode)) {\n\t\t\t\tthis._onDidBlur.fire();\n\t\t\t\tthis.focusedItem = undefined;\n\t\t\t\tthis.previouslyFocusedItem = undefined;\n\t\t\t\tthis.triggerKeyDown = false;\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(this.focusTracker.onDidFocus(() => this.updateFocusedItem()));\n\n\t\tthis.actionsList = document.createElement('ul');\n\t\tthis.actionsList.className = 'actions-container';\n\t\tthis.actionsList.setAttribute('role', 'toolbar');\n\n\t\tif (this.options.ariaLabel) {\n\t\t\tthis.actionsList.setAttribute('aria-label', this.options.ariaLabel);\n\t\t}\n\n\t\tthis.domNode.appendChild(this.actionsList);\n\n\t\tcontainer.appendChild(this.domNode);\n\t}\n\n\t// Some action bars should not be focusable at times\n\t// When an action bar is not focusable make sure to make all the elements inside it not focusable\n\t// When an action bar is focusable again, make sure the first item can be focused\n\tsetFocusable(focusable: boolean): void {\n\t\tthis.focusable = focusable;\n\t\tif (this.focusable) {\n\t\t\tconst firstEnabled = this.viewItems.find(vi => vi instanceof BaseActionViewItem && vi.isEnabled());\n\t\t\tif (firstEnabled instanceof BaseActionViewItem) {\n\t\t\t\tfirstEnabled.setFocusable(true);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.viewItems.forEach(vi => {\n\t\t\t\tif (vi instanceof BaseActionViewItem) {\n\t\t\t\t\tvi.setFocusable(false);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate isTriggerKeyEvent(event: StandardKeyboardEvent): boolean {\n\t\tlet ret = false;\n\t\tthis._triggerKeys.keys.forEach(keyCode => {\n\t\t\tret = ret || event.equals(keyCode);\n\t\t});\n\n\t\treturn ret;\n\t}\n\n\tprivate updateFocusedItem(): void {\n\t\tfor (let i = 0; i < this.actionsList.children.length; i++) {\n\t\t\tconst elem = this.actionsList.children[i];\n\t\t\tif (DOM.isAncestor(DOM.getActiveElement(), elem)) {\n\t\t\t\tthis.focusedItem = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tget context(): unknown {\n\t\treturn this._context;\n\t}\n\n\tset context(context: unknown) {\n\t\tthis._context = context;\n\t\tthis.viewItems.forEach(i => i.setActionContext(context));\n\t}\n\n\tget actionRunner(): IActionRunner {\n\t\treturn this._actionRunner;\n\t}\n\n\tset actionRunner(actionRunner: IActionRunner) {\n\t\tif (actionRunner) {\n\t\t\tthis._actionRunner = actionRunner;\n\t\t\tthis.viewItems.forEach(item => item.actionRunner = actionRunner);\n\t\t}\n\t}\n\n\tgetContainer(): HTMLElement {\n\t\treturn this.domNode;\n\t}\n\n\tpush(arg: IAction | ReadonlyArray, options: IActionOptions = {}): void {\n\t\tconst actions: ReadonlyArray = Array.isArray(arg) ? arg : [arg];\n\n\t\tlet index = types.isNumber(options.index) ? options.index : null;\n\n\t\tactions.forEach((action: IAction) => {\n\t\t\tconst actionViewItemElement = document.createElement('li');\n\t\t\tactionViewItemElement.className = 'action-item';\n\t\t\tactionViewItemElement.setAttribute('role', 'presentation');\n\n\t\t\t// Prevent native context menu on actions\n\t\t\tif (!this.options.allowContextMenu) {\n\t\t\t\tthis._register(DOM.addDisposableListener(actionViewItemElement, DOM.EventType.CONTEXT_MENU, (e: DOM.EventLike) => {\n\t\t\t\t\tDOM.EventHelper.stop(e, true);\n\t\t\t\t}));\n\t\t\t}\n\n\t\t\tlet item: IActionViewItem | undefined;\n\n\t\t\tif (this.options.actionViewItemProvider) {\n\t\t\t\titem = this.options.actionViewItemProvider(action);\n\t\t\t}\n\n\t\t\tif (!item) {\n\t\t\t\titem = new ActionViewItem(this.context, action, options);\n\t\t\t}\n\n\t\t\titem.actionRunner = this._actionRunner;\n\t\t\titem.setActionContext(this.context);\n\t\t\titem.render(actionViewItemElement);\n\n\t\t\tif (this.focusable && item instanceof BaseActionViewItem && this.viewItems.length === 0) {\n\t\t\t\t// We need to allow for the first enabled item to be focused on using tab navigation #106441\n\t\t\t\titem.setFocusable(true);\n\t\t\t}\n\n\t\t\tif (index === null || index < 0 || index >= this.actionsList.children.length) {\n\t\t\t\tthis.actionsList.appendChild(actionViewItemElement);\n\t\t\t\tthis.viewItems.push(item);\n\t\t\t\tthis._actionIds.push(action.id);\n\t\t\t} else {\n\t\t\t\tthis.actionsList.insertBefore(actionViewItemElement, this.actionsList.children[index]);\n\t\t\t\tthis.viewItems.splice(index, 0, item);\n\t\t\t\tthis._actionIds.splice(index, 0, action.id);\n\t\t\t\tindex++;\n\t\t\t}\n\t\t});\n\t\tif (typeof this.focusedItem === 'number') {\n\t\t\t// After a clear actions might be re-added to simply toggle some actions. We should preserve focus #97128\n\t\t\tthis.focus(this.focusedItem);\n\t\t}\n\t}\n\n\tclear(): void {\n\t\tdispose(this.viewItems);\n\t\tthis.viewItems = [];\n\t\tthis._actionIds = [];\n\t\tDOM.clearNode(this.actionsList);\n\t}\n\n\tlength(): number {\n\t\treturn this.viewItems.length;\n\t}\n\n\tfocus(index?: number): void;\n\tfocus(selectFirst?: boolean): void;\n\tfocus(arg?: number | boolean): void {\n\t\tlet selectFirst: boolean = false;\n\t\tlet index: number | undefined = undefined;\n\t\tif (arg === undefined) {\n\t\t\tselectFirst = true;\n\t\t} else if (typeof arg === 'number') {\n\t\t\tindex = arg;\n\t\t} else if (typeof arg === 'boolean') {\n\t\t\tselectFirst = arg;\n\t\t}\n\n\t\tif (selectFirst && typeof this.focusedItem === 'undefined') {\n\t\t\tconst firstEnabled = this.viewItems.findIndex(item => item.isEnabled());\n\t\t\t// Focus the first enabled item\n\t\t\tthis.focusedItem = firstEnabled === -1 ? undefined : firstEnabled;\n\t\t\tthis.updateFocus(undefined, undefined, true);\n\t\t} else {\n\t\t\tif (index !== undefined) {\n\t\t\t\tthis.focusedItem = index;\n\t\t\t}\n\n\t\t\tthis.updateFocus(undefined, undefined, true);\n\t\t}\n\t}\n\n\tprivate focusFirst(): boolean {\n\t\tthis.focusedItem = this.length() - 1;\n\t\treturn this.focusNext(true);\n\t}\n\n\tprivate focusLast(): boolean {\n\t\tthis.focusedItem = 0;\n\t\treturn this.focusPrevious(true);\n\t}\n\n\tprotected focusNext(forceLoop?: boolean): boolean {\n\t\tif (typeof this.focusedItem === 'undefined') {\n\t\t\tthis.focusedItem = this.viewItems.length - 1;\n\t\t} else if (this.viewItems.length <= 1) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst startIndex = this.focusedItem;\n\t\tlet item: IActionViewItem;\n\t\tdo {\n\n\t\t\tif (!forceLoop && this.options.preventLoopNavigation && this.focusedItem + 1 >= this.viewItems.length) {\n\t\t\t\tthis.focusedItem = startIndex;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tthis.focusedItem = (this.focusedItem + 1) % this.viewItems.length;\n\t\t\titem = this.viewItems[this.focusedItem];\n\t\t} while (this.focusedItem !== startIndex && this.options.focusOnlyEnabledItems && !item.isEnabled());\n\n\t\tthis.updateFocus();\n\t\treturn true;\n\t}\n\n\tprotected focusPrevious(forceLoop?: boolean): boolean {\n\t\tif (typeof this.focusedItem === 'undefined') {\n\t\t\tthis.focusedItem = 0;\n\t\t} else if (this.viewItems.length <= 1) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst startIndex = this.focusedItem;\n\t\tlet item: IActionViewItem;\n\n\t\tdo {\n\t\t\tthis.focusedItem = this.focusedItem - 1;\n\t\t\tif (this.focusedItem < 0) {\n\t\t\t\tif (!forceLoop && this.options.preventLoopNavigation) {\n\t\t\t\t\tthis.focusedItem = startIndex;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tthis.focusedItem = this.viewItems.length - 1;\n\t\t\t}\n\t\t\titem = this.viewItems[this.focusedItem];\n\t\t} while (this.focusedItem !== startIndex && this.options.focusOnlyEnabledItems && !item.isEnabled());\n\n\n\t\tthis.updateFocus(true);\n\t\treturn true;\n\t}\n\n\tprotected updateFocus(fromRight?: boolean, preventScroll?: boolean, forceFocus: boolean = false): void {\n\t\tif (typeof this.focusedItem === 'undefined') {\n\t\t\tthis.actionsList.focus({ preventScroll });\n\t\t}\n\n\t\tif (this.previouslyFocusedItem !== undefined && this.previouslyFocusedItem !== this.focusedItem) {\n\t\t\tthis.viewItems[this.previouslyFocusedItem]?.blur();\n\t\t}\n\n\t\tconst actionViewItem = this.focusedItem !== undefined && this.viewItems[this.focusedItem];\n\t\tif (actionViewItem) {\n\t\t\tlet focusItem = true;\n\n\t\t\tif (!types.isFunction(actionViewItem.focus)) {\n\t\t\t\tfocusItem = false;\n\t\t\t}\n\n\t\t\tif (this.options.focusOnlyEnabledItems && types.isFunction(actionViewItem.isEnabled) && !actionViewItem.isEnabled()) {\n\t\t\t\tfocusItem = false;\n\t\t\t}\n\n\t\t\tif (!focusItem) {\n\t\t\t\tthis.actionsList.focus({ preventScroll });\n\t\t\t\tthis.previouslyFocusedItem = undefined;\n\t\t\t} else if (forceFocus || this.previouslyFocusedItem !== this.focusedItem) {\n\t\t\t\tactionViewItem.focus(fromRight);\n\t\t\t\tthis.previouslyFocusedItem = this.focusedItem;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate doTrigger(event: StandardKeyboardEvent): void {\n\t\tif (typeof this.focusedItem === 'undefined') {\n\t\t\treturn; //nothing to focus\n\t\t}\n\n\t\t// trigger action\n\t\tconst actionViewItem = this.viewItems[this.focusedItem];\n\t\tif (actionViewItem instanceof BaseActionViewItem) {\n\t\t\tconst context = (actionViewItem._context === null || actionViewItem._context === undefined) ? event : actionViewItem._context;\n\t\t\tthis.run(actionViewItem._action, context);\n\t\t}\n\t}\n\n\tasync run(action: IAction, context?: unknown): Promise {\n\t\tawait this._actionRunner.run(action, context);\n\t}\n\n\toverride dispose(): void {\n\t\tdispose(this.viewItems);\n\t\tthis.viewItems = [];\n\n\t\tthis._actionIds = [];\n\n\t\tthis.getContainer().remove();\n\n\t\tsuper.dispose();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IContextMenuProvider } from 'vs/base/browser/contextmenu';\nimport { $, addDisposableListener, append, EventHelper, EventType } from 'vs/base/browser/dom';\nimport { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { EventType as GestureEventType, Gesture } from 'vs/base/browser/touch';\nimport { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';\nimport { IMenuOptions } from 'vs/base/browser/ui/menu/menu';\nimport { ActionRunner, IAction } from 'vs/base/common/actions';\nimport { Emitter } from 'vs/base/common/event';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport 'vs/css!./dropdown';\n\nexport interface ILabelRenderer {\n\t(container: HTMLElement): IDisposable | null;\n}\n\nexport interface IBaseDropdownOptions {\n\tlabel?: string;\n\tlabelRenderer?: ILabelRenderer;\n}\n\nexport class BaseDropdown extends ActionRunner {\n\tprivate _element: HTMLElement;\n\tprivate boxContainer?: HTMLElement;\n\tprivate _label?: HTMLElement;\n\tprivate contents?: HTMLElement;\n\n\tprivate visible: boolean | undefined;\n\tprivate _onDidChangeVisibility = this._register(new Emitter());\n\treadonly onDidChangeVisibility = this._onDidChangeVisibility.event;\n\n\tconstructor(container: HTMLElement, options: IBaseDropdownOptions) {\n\t\tsuper();\n\n\t\tthis._element = append(container, $('.monaco-dropdown'));\n\n\t\tthis._label = append(this._element, $('.dropdown-label'));\n\n\t\tlet labelRenderer = options.labelRenderer;\n\t\tif (!labelRenderer) {\n\t\t\tlabelRenderer = (container: HTMLElement): IDisposable | null => {\n\t\t\t\tcontainer.textContent = options.label || '';\n\n\t\t\t\treturn null;\n\t\t\t};\n\t\t}\n\n\t\tfor (const event of [EventType.CLICK, EventType.MOUSE_DOWN, GestureEventType.Tap]) {\n\t\t\tthis._register(addDisposableListener(this.element, event, e => EventHelper.stop(e, true))); // prevent default click behaviour to trigger\n\t\t}\n\n\t\tfor (const event of [EventType.MOUSE_DOWN, GestureEventType.Tap]) {\n\t\t\tthis._register(addDisposableListener(this._label, event, e => {\n\t\t\t\tif (e instanceof MouseEvent && e.detail > 1) {\n\t\t\t\t\treturn; // prevent multiple clicks to open multiple context menus (https://github.com/microsoft/vscode/issues/41363)\n\t\t\t\t}\n\n\t\t\t\tif (this.visible) {\n\t\t\t\t\tthis.hide();\n\t\t\t\t} else {\n\t\t\t\t\tthis.show();\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\n\t\tthis._register(addDisposableListener(this._label, EventType.KEY_UP, e => {\n\t\t\tconst event = new StandardKeyboardEvent(e);\n\t\t\tif (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {\n\t\t\t\tEventHelper.stop(e, true); // https://github.com/microsoft/vscode/issues/57997\n\n\t\t\t\tif (this.visible) {\n\t\t\t\t\tthis.hide();\n\t\t\t\t} else {\n\t\t\t\t\tthis.show();\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\n\t\tconst cleanupFn = labelRenderer(this._label);\n\t\tif (cleanupFn) {\n\t\t\tthis._register(cleanupFn);\n\t\t}\n\n\t\tthis._register(Gesture.addTarget(this._label));\n\t}\n\n\tget element(): HTMLElement {\n\t\treturn this._element;\n\t}\n\n\tshow(): void {\n\t\tif (!this.visible) {\n\t\t\tthis.visible = true;\n\t\t\tthis._onDidChangeVisibility.fire(true);\n\t\t}\n\t}\n\n\thide(): void {\n\t\tif (this.visible) {\n\t\t\tthis.visible = false;\n\t\t\tthis._onDidChangeVisibility.fire(false);\n\t\t}\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tthis.hide();\n\n\t\tif (this.boxContainer) {\n\t\t\tthis.boxContainer.remove();\n\t\t\tthis.boxContainer = undefined;\n\t\t}\n\n\t\tif (this.contents) {\n\t\t\tthis.contents.remove();\n\t\t\tthis.contents = undefined;\n\t\t}\n\n\t\tif (this._label) {\n\t\t\tthis._label.remove();\n\t\t\tthis._label = undefined;\n\t\t}\n\t}\n}\n\nexport interface IActionProvider {\n\tgetActions(): readonly IAction[];\n}\n\nexport interface IDropdownMenuOptions extends IBaseDropdownOptions {\n\tcontextMenuProvider: IContextMenuProvider;\n\treadonly actions?: IAction[];\n\treadonly actionProvider?: IActionProvider;\n\tmenuClassName?: string;\n\tmenuAsChild?: boolean; // scope down for #99448\n}\n\nexport class DropdownMenu extends BaseDropdown {\n\tprivate _contextMenuProvider: IContextMenuProvider;\n\tprivate _menuOptions: IMenuOptions | undefined;\n\tprivate _actions: readonly IAction[] = [];\n\tprivate actionProvider?: IActionProvider;\n\tprivate menuClassName: string;\n\tprivate menuAsChild?: boolean;\n\n\tconstructor(container: HTMLElement, options: IDropdownMenuOptions) {\n\t\tsuper(container, options);\n\n\t\tthis._contextMenuProvider = options.contextMenuProvider;\n\t\tthis.actions = options.actions || [];\n\t\tthis.actionProvider = options.actionProvider;\n\t\tthis.menuClassName = options.menuClassName || '';\n\t\tthis.menuAsChild = !!options.menuAsChild;\n\t}\n\n\tset menuOptions(options: IMenuOptions | undefined) {\n\t\tthis._menuOptions = options;\n\t}\n\n\tget menuOptions(): IMenuOptions | undefined {\n\t\treturn this._menuOptions;\n\t}\n\n\tprivate get actions(): readonly IAction[] {\n\t\tif (this.actionProvider) {\n\t\t\treturn this.actionProvider.getActions();\n\t\t}\n\n\t\treturn this._actions;\n\t}\n\n\tprivate set actions(actions: readonly IAction[]) {\n\t\tthis._actions = actions;\n\t}\n\n\toverride show(): void {\n\t\tsuper.show();\n\n\t\tthis.element.classList.add('active');\n\n\t\tthis._contextMenuProvider.showContextMenu({\n\t\t\tgetAnchor: () => this.element,\n\t\t\tgetActions: () => this.actions,\n\t\t\tgetActionsContext: () => this.menuOptions ? this.menuOptions.context : null,\n\t\t\tgetActionViewItem: action => this.menuOptions && this.menuOptions.actionViewItemProvider ? this.menuOptions.actionViewItemProvider(action) : undefined,\n\t\t\tgetKeyBinding: action => this.menuOptions && this.menuOptions.getKeyBinding ? this.menuOptions.getKeyBinding(action) : undefined,\n\t\t\tgetMenuClassName: () => this.menuClassName,\n\t\t\tonHide: () => this.onHide(),\n\t\t\tactionRunner: this.menuOptions ? this.menuOptions.actionRunner : undefined,\n\t\t\tanchorAlignment: this.menuOptions ? this.menuOptions.anchorAlignment : AnchorAlignment.LEFT,\n\t\t\tdomForShadowRoot: this.menuAsChild ? this.element : undefined\n\t\t});\n\t}\n\n\toverride hide(): void {\n\t\tsuper.hide();\n\t}\n\n\tprivate onHide(): void {\n\t\tthis.hide();\n\t\tthis.element.classList.remove('active');\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IContextMenuProvider } from 'vs/base/browser/contextmenu';\nimport { $, append } from 'vs/base/browser/dom';\nimport { IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';\nimport { BaseActionViewItem, IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';\nimport { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';\nimport { DropdownMenu, IActionProvider, IDropdownMenuOptions, ILabelRenderer } from 'vs/base/browser/ui/dropdown/dropdown';\nimport { IAction, IActionRunner } from 'vs/base/common/actions';\nimport { Emitter } from 'vs/base/common/event';\nimport { ResolvedKeybinding } from 'vs/base/common/keybindings';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport 'vs/css!./dropdown';\n\nexport interface IKeybindingProvider {\n\t(action: IAction): ResolvedKeybinding | undefined;\n}\n\nexport interface IAnchorAlignmentProvider {\n\t(): AnchorAlignment;\n}\n\nexport interface IDropdownMenuActionViewItemOptions extends IBaseActionViewItemOptions {\n\treadonly actionViewItemProvider?: IActionViewItemProvider;\n\treadonly keybindingProvider?: IKeybindingProvider;\n\treadonly actionRunner?: IActionRunner;\n\treadonly classNames?: string[] | string;\n\treadonly anchorAlignmentProvider?: IAnchorAlignmentProvider;\n\treadonly menuAsChild?: boolean;\n}\n\nexport class DropdownMenuActionViewItem extends BaseActionViewItem {\n\tprivate menuActionsOrProvider: readonly IAction[] | IActionProvider;\n\tprivate dropdownMenu: DropdownMenu | undefined;\n\tprivate contextMenuProvider: IContextMenuProvider;\n\tprivate actionItem: HTMLElement | null = null;\n\n\tprivate _onDidChangeVisibility = this._register(new Emitter());\n\n\tprotected override readonly options: IDropdownMenuActionViewItemOptions;\n\n\tconstructor(\n\t\taction: IAction,\n\t\tmenuActionsOrProvider: readonly IAction[] | IActionProvider,\n\t\tcontextMenuProvider: IContextMenuProvider,\n\t\toptions: IDropdownMenuActionViewItemOptions = Object.create(null)\n\t) {\n\t\tsuper(null, action, options);\n\n\t\tthis.menuActionsOrProvider = menuActionsOrProvider;\n\t\tthis.contextMenuProvider = contextMenuProvider;\n\t\tthis.options = options;\n\n\t\tif (this.options.actionRunner) {\n\t\t\tthis.actionRunner = this.options.actionRunner;\n\t\t}\n\t}\n\n\toverride render(container: HTMLElement): void {\n\t\tthis.actionItem = container;\n\n\t\tconst labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable | null => {\n\t\t\tthis.element = append(el, $('a.action-label'));\n\n\t\t\tlet classNames: string[] = [];\n\n\t\t\tif (typeof this.options.classNames === 'string') {\n\t\t\t\tclassNames = this.options.classNames.split(/\\s+/g).filter(s => !!s);\n\t\t\t} else if (this.options.classNames) {\n\t\t\t\tclassNames = this.options.classNames;\n\t\t\t}\n\n\t\t\t// todo@aeschli: remove codicon, should come through `this.options.classNames`\n\t\t\tif (!classNames.find(c => c === 'icon')) {\n\t\t\t\tclassNames.push('codicon');\n\t\t\t}\n\n\t\t\tthis.element.classList.add(...classNames);\n\n\t\t\tthis.element.setAttribute('role', 'button');\n\t\t\tthis.element.setAttribute('aria-haspopup', 'true');\n\t\t\tthis.element.setAttribute('aria-expanded', 'false');\n\t\t\tthis.element.title = this._action.label || '';\n\n\t\t\treturn null;\n\t\t};\n\n\t\tconst isActionsArray = Array.isArray(this.menuActionsOrProvider);\n\t\tconst options: IDropdownMenuOptions = {\n\t\t\tcontextMenuProvider: this.contextMenuProvider,\n\t\t\tlabelRenderer: labelRenderer,\n\t\t\tmenuAsChild: this.options.menuAsChild,\n\t\t\tactions: isActionsArray ? this.menuActionsOrProvider as IAction[] : undefined,\n\t\t\tactionProvider: isActionsArray ? undefined : this.menuActionsOrProvider as IActionProvider\n\t\t};\n\n\t\tthis.dropdownMenu = this._register(new DropdownMenu(container, options));\n\t\tthis._register(this.dropdownMenu.onDidChangeVisibility(visible => {\n\t\t\tthis.element?.setAttribute('aria-expanded', `${visible}`);\n\t\t\tthis._onDidChangeVisibility.fire(visible);\n\t\t}));\n\n\t\tthis.dropdownMenu.menuOptions = {\n\t\t\tactionViewItemProvider: this.options.actionViewItemProvider,\n\t\t\tactionRunner: this.actionRunner,\n\t\t\tgetKeyBinding: this.options.keybindingProvider,\n\t\t\tcontext: this._context\n\t\t};\n\n\t\tif (this.options.anchorAlignmentProvider) {\n\t\t\tconst that = this;\n\n\t\t\tthis.dropdownMenu.menuOptions = {\n\t\t\t\t...this.dropdownMenu.menuOptions,\n\t\t\t\tget anchorAlignment(): AnchorAlignment {\n\t\t\t\t\treturn that.options.anchorAlignmentProvider!();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tthis.updateEnabled();\n\t}\n\n\toverride setActionContext(newContext: unknown): void {\n\t\tsuper.setActionContext(newContext);\n\n\t\tif (this.dropdownMenu) {\n\t\t\tif (this.dropdownMenu.menuOptions) {\n\t\t\t\tthis.dropdownMenu.menuOptions.context = newContext;\n\t\t\t} else {\n\t\t\t\tthis.dropdownMenu.menuOptions = { context: newContext };\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected override updateEnabled(): void {\n\t\tconst disabled = !this.getAction().enabled;\n\t\tthis.actionItem?.classList.toggle('disabled', disabled);\n\t\tthis.element?.classList.toggle('disabled', disabled);\n\t}\n}\n\n\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { DomEmitter } from 'vs/base/browser/event';\nimport { renderFormattedText, renderText } from 'vs/base/browser/formattedTextRenderer';\nimport { IHistoryNavigationWidget } from 'vs/base/browser/history';\nimport { MarkdownRenderOptions } from 'vs/base/browser/markdownRenderer';\nimport { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';\nimport * as aria from 'vs/base/browser/ui/aria/aria';\nimport { AnchorAlignment, IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';\nimport { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';\nimport { Widget } from 'vs/base/browser/ui/widget';\nimport { IAction } from 'vs/base/common/actions';\nimport { Color } from 'vs/base/common/color';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { HistoryNavigator } from 'vs/base/common/history';\nimport { mixin } from 'vs/base/common/objects';\nimport { ScrollbarVisibility } from 'vs/base/common/scrollable';\nimport 'vs/css!./inputBox';\nimport * as nls from 'vs/nls';\n\n\nconst $ = dom.$;\n\nexport interface IInputOptions extends IInputBoxStyles {\n\treadonly placeholder?: string;\n\treadonly showPlaceholderOnFocus?: boolean;\n\treadonly tooltip?: string;\n\treadonly ariaLabel?: string;\n\treadonly type?: string;\n\treadonly validationOptions?: IInputValidationOptions;\n\treadonly flexibleHeight?: boolean;\n\treadonly flexibleWidth?: boolean;\n\treadonly flexibleMaxHeight?: number;\n\treadonly actions?: ReadonlyArray;\n}\n\nexport interface IInputBoxStyles {\n\treadonly inputBackground?: Color;\n\treadonly inputForeground?: Color;\n\treadonly inputBorder?: Color;\n\treadonly inputValidationInfoBorder?: Color;\n\treadonly inputValidationInfoBackground?: Color;\n\treadonly inputValidationInfoForeground?: Color;\n\treadonly inputValidationWarningBorder?: Color;\n\treadonly inputValidationWarningBackground?: Color;\n\treadonly inputValidationWarningForeground?: Color;\n\treadonly inputValidationErrorBorder?: Color;\n\treadonly inputValidationErrorBackground?: Color;\n\treadonly inputValidationErrorForeground?: Color;\n}\n\nexport interface IInputValidator {\n\t(value: string): IMessage | null;\n}\n\nexport interface IMessage {\n\treadonly content: string;\n\treadonly formatContent?: boolean; // defaults to false\n\treadonly type?: MessageType;\n}\n\nexport interface IInputValidationOptions {\n\tvalidation?: IInputValidator;\n}\n\nexport const enum MessageType {\n\tINFO = 1,\n\tWARNING = 2,\n\tERROR = 3\n}\n\nexport interface IRange {\n\tstart: number;\n\tend: number;\n}\n\nconst defaultOpts = {\n\tinputBackground: Color.fromHex('#3C3C3C'),\n\tinputForeground: Color.fromHex('#CCCCCC'),\n\tinputValidationInfoBorder: Color.fromHex('#55AAFF'),\n\tinputValidationInfoBackground: Color.fromHex('#063B49'),\n\tinputValidationWarningBorder: Color.fromHex('#B89500'),\n\tinputValidationWarningBackground: Color.fromHex('#352A05'),\n\tinputValidationErrorBorder: Color.fromHex('#BE1100'),\n\tinputValidationErrorBackground: Color.fromHex('#5A1D1D')\n};\n\nexport class InputBox extends Widget {\n\tprivate contextViewProvider?: IContextViewProvider;\n\telement: HTMLElement;\n\tprotected input: HTMLInputElement;\n\tprivate actionbar?: ActionBar;\n\tprivate options: IInputOptions;\n\tprivate message: IMessage | null;\n\tprotected placeholder: string;\n\tprivate tooltip: string;\n\tprivate ariaLabel: string;\n\tprivate validation?: IInputValidator;\n\tprivate state: 'idle' | 'open' | 'closed' = 'idle';\n\n\tprivate mirror: HTMLElement | undefined;\n\tprivate cachedHeight: number | undefined;\n\tprivate cachedContentHeight: number | undefined;\n\tprivate maxHeight: number = Number.POSITIVE_INFINITY;\n\tprivate scrollableElement: ScrollableElement | undefined;\n\n\tprivate inputBackground?: Color;\n\tprivate inputForeground?: Color;\n\tprivate inputBorder?: Color;\n\n\tprivate inputValidationInfoBorder?: Color;\n\tprivate inputValidationInfoBackground?: Color;\n\tprivate inputValidationInfoForeground?: Color;\n\tprivate inputValidationWarningBorder?: Color;\n\tprivate inputValidationWarningBackground?: Color;\n\tprivate inputValidationWarningForeground?: Color;\n\tprivate inputValidationErrorBorder?: Color;\n\tprivate inputValidationErrorBackground?: Color;\n\tprivate inputValidationErrorForeground?: Color;\n\n\tprivate _onDidChange = this._register(new Emitter());\n\tpublic readonly onDidChange: Event = this._onDidChange.event;\n\n\tprivate _onDidHeightChange = this._register(new Emitter());\n\tpublic readonly onDidHeightChange: Event = this._onDidHeightChange.event;\n\n\tconstructor(container: HTMLElement, contextViewProvider: IContextViewProvider | undefined, options?: IInputOptions) {\n\t\tsuper();\n\n\t\tthis.contextViewProvider = contextViewProvider;\n\t\tthis.options = options || Object.create(null);\n\t\tmixin(this.options, defaultOpts, false);\n\t\tthis.message = null;\n\t\tthis.placeholder = this.options.placeholder || '';\n\t\tthis.tooltip = this.options.tooltip ?? (this.placeholder || '');\n\t\tthis.ariaLabel = this.options.ariaLabel || '';\n\n\t\tthis.inputBackground = this.options.inputBackground;\n\t\tthis.inputForeground = this.options.inputForeground;\n\t\tthis.inputBorder = this.options.inputBorder;\n\n\t\tthis.inputValidationInfoBorder = this.options.inputValidationInfoBorder;\n\t\tthis.inputValidationInfoBackground = this.options.inputValidationInfoBackground;\n\t\tthis.inputValidationInfoForeground = this.options.inputValidationInfoForeground;\n\t\tthis.inputValidationWarningBorder = this.options.inputValidationWarningBorder;\n\t\tthis.inputValidationWarningBackground = this.options.inputValidationWarningBackground;\n\t\tthis.inputValidationWarningForeground = this.options.inputValidationWarningForeground;\n\t\tthis.inputValidationErrorBorder = this.options.inputValidationErrorBorder;\n\t\tthis.inputValidationErrorBackground = this.options.inputValidationErrorBackground;\n\t\tthis.inputValidationErrorForeground = this.options.inputValidationErrorForeground;\n\n\t\tif (this.options.validationOptions) {\n\t\t\tthis.validation = this.options.validationOptions.validation;\n\t\t}\n\n\t\tthis.element = dom.append(container, $('.monaco-inputbox.idle'));\n\n\t\tlet tagName = this.options.flexibleHeight ? 'textarea' : 'input';\n\n\t\tlet wrapper = dom.append(this.element, $('.ibwrapper'));\n\t\tthis.input = dom.append(wrapper, $(tagName + '.input.empty'));\n\t\tthis.input.setAttribute('autocorrect', 'off');\n\t\tthis.input.setAttribute('autocapitalize', 'off');\n\t\tthis.input.setAttribute('spellcheck', 'false');\n\n\t\tthis.onfocus(this.input, () => this.element.classList.add('synthetic-focus'));\n\t\tthis.onblur(this.input, () => this.element.classList.remove('synthetic-focus'));\n\n\t\tif (this.options.flexibleHeight) {\n\t\t\tthis.maxHeight = typeof this.options.flexibleMaxHeight === 'number' ? this.options.flexibleMaxHeight : Number.POSITIVE_INFINITY;\n\n\t\t\tthis.mirror = dom.append(wrapper, $('div.mirror'));\n\t\t\tthis.mirror.innerText = '\\u00a0';\n\n\t\t\tthis.scrollableElement = new ScrollableElement(this.element, { vertical: ScrollbarVisibility.Auto });\n\n\t\t\tif (this.options.flexibleWidth) {\n\t\t\t\tthis.input.setAttribute('wrap', 'off');\n\t\t\t\tthis.mirror.style.whiteSpace = 'pre';\n\t\t\t\tthis.mirror.style.wordWrap = 'initial';\n\t\t\t}\n\n\t\t\tdom.append(container, this.scrollableElement.getDomNode());\n\t\t\tthis._register(this.scrollableElement);\n\n\t\t\t// from ScrollableElement to DOM\n\t\t\tthis._register(this.scrollableElement.onScroll(e => this.input.scrollTop = e.scrollTop));\n\n\t\t\tconst onSelectionChange = this._register(new DomEmitter(document, 'selectionchange'));\n\t\t\tconst onAnchoredSelectionChange = Event.filter(onSelectionChange.event, () => {\n\t\t\t\tconst selection = document.getSelection();\n\t\t\t\treturn selection?.anchorNode === wrapper;\n\t\t\t});\n\n\t\t\t// from DOM to ScrollableElement\n\t\t\tthis._register(onAnchoredSelectionChange(this.updateScrollDimensions, this));\n\t\t\tthis._register(this.onDidHeightChange(this.updateScrollDimensions, this));\n\t\t} else {\n\t\t\tthis.input.type = this.options.type || 'text';\n\t\t\tthis.input.setAttribute('wrap', 'off');\n\t\t}\n\n\t\tif (this.ariaLabel) {\n\t\t\tthis.input.setAttribute('aria-label', this.ariaLabel);\n\t\t}\n\n\t\tif (this.placeholder && !this.options.showPlaceholderOnFocus) {\n\t\t\tthis.setPlaceHolder(this.placeholder);\n\t\t}\n\n\t\tif (this.tooltip) {\n\t\t\tthis.setTooltip(this.tooltip);\n\t\t}\n\n\t\tthis.oninput(this.input, () => this.onValueChange());\n\t\tthis.onblur(this.input, () => this.onBlur());\n\t\tthis.onfocus(this.input, () => this.onFocus());\n\n\t\tthis.ignoreGesture(this.input);\n\n\t\tsetTimeout(() => this.updateMirror(), 0);\n\n\t\t// Support actions\n\t\tif (this.options.actions) {\n\t\t\tthis.actionbar = this._register(new ActionBar(this.element));\n\t\t\tthis.actionbar.push(this.options.actions, { icon: true, label: false });\n\t\t}\n\n\t\tthis.applyStyles();\n\t}\n\n\tprivate onBlur(): void {\n\t\tthis._hideMessage();\n\t\tif (this.options.showPlaceholderOnFocus) {\n\t\t\tthis.input.setAttribute('placeholder', '');\n\t\t}\n\t}\n\n\tprivate onFocus(): void {\n\t\tthis._showMessage();\n\t\tif (this.options.showPlaceholderOnFocus) {\n\t\t\tthis.input.setAttribute('placeholder', this.placeholder || '');\n\t\t}\n\t}\n\n\tpublic setPlaceHolder(placeHolder: string): void {\n\t\tthis.placeholder = placeHolder;\n\t\tthis.input.setAttribute('placeholder', placeHolder);\n\t}\n\n\tpublic setTooltip(tooltip: string): void {\n\t\tthis.tooltip = tooltip;\n\t\tthis.input.title = tooltip;\n\t}\n\n\tpublic setAriaLabel(label: string): void {\n\t\tthis.ariaLabel = label;\n\n\t\tif (label) {\n\t\t\tthis.input.setAttribute('aria-label', this.ariaLabel);\n\t\t} else {\n\t\t\tthis.input.removeAttribute('aria-label');\n\t\t}\n\t}\n\n\tpublic getAriaLabel(): string {\n\t\treturn this.ariaLabel;\n\t}\n\n\tpublic get inputElement(): HTMLInputElement {\n\t\treturn this.input;\n\t}\n\n\tpublic get value(): string {\n\t\treturn this.input.value;\n\t}\n\n\tpublic set value(newValue: string) {\n\t\tif (this.input.value !== newValue) {\n\t\t\tthis.input.value = newValue;\n\t\t\tthis.onValueChange();\n\t\t}\n\t}\n\n\tpublic get height(): number {\n\t\treturn typeof this.cachedHeight === 'number' ? this.cachedHeight : dom.getTotalHeight(this.element);\n\t}\n\n\tpublic focus(): void {\n\t\tthis.input.focus();\n\t}\n\n\tpublic blur(): void {\n\t\tthis.input.blur();\n\t}\n\n\tpublic hasFocus(): boolean {\n\t\treturn document.activeElement === this.input;\n\t}\n\n\tpublic select(range: IRange | null = null): void {\n\t\tthis.input.select();\n\n\t\tif (range) {\n\t\t\tthis.input.setSelectionRange(range.start, range.end);\n\t\t\tif (range.end === this.input.value.length) {\n\t\t\t\tthis.input.scrollLeft = this.input.scrollWidth;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic isSelectionAtEnd(): boolean {\n\t\treturn this.input.selectionEnd === this.input.value.length && this.input.selectionStart === this.input.selectionEnd;\n\t}\n\n\tpublic enable(): void {\n\t\tthis.input.removeAttribute('disabled');\n\t}\n\n\tpublic disable(): void {\n\t\tthis.blur();\n\t\tthis.input.disabled = true;\n\t\tthis._hideMessage();\n\t}\n\n\tpublic get width(): number {\n\t\treturn dom.getTotalWidth(this.input);\n\t}\n\n\tpublic set width(width: number) {\n\t\tif (this.options.flexibleHeight && this.options.flexibleWidth) {\n\t\t\t// textarea with horizontal scrolling\n\t\t\tlet horizontalPadding = 0;\n\t\t\tif (this.mirror) {\n\t\t\t\tconst paddingLeft = parseFloat(this.mirror.style.paddingLeft || '') || 0;\n\t\t\t\tconst paddingRight = parseFloat(this.mirror.style.paddingRight || '') || 0;\n\t\t\t\thorizontalPadding = paddingLeft + paddingRight;\n\t\t\t}\n\t\t\tthis.input.style.width = (width - horizontalPadding) + 'px';\n\t\t} else {\n\t\t\tthis.input.style.width = width + 'px';\n\t\t}\n\n\t\tif (this.mirror) {\n\t\t\tthis.mirror.style.width = width + 'px';\n\t\t}\n\t}\n\n\tpublic set paddingRight(paddingRight: number) {\n\t\t// Set width to avoid hint text overlapping buttons\n\t\tthis.input.style.width = `calc(100% - ${paddingRight}px)`;\n\n\t\tif (this.mirror) {\n\t\t\tthis.mirror.style.paddingRight = paddingRight + 'px';\n\t\t}\n\t}\n\n\tprivate updateScrollDimensions(): void {\n\t\tif (typeof this.cachedContentHeight !== 'number' || typeof this.cachedHeight !== 'number' || !this.scrollableElement) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst scrollHeight = this.cachedContentHeight;\n\t\tconst height = this.cachedHeight;\n\t\tconst scrollTop = this.input.scrollTop;\n\n\t\tthis.scrollableElement.setScrollDimensions({ scrollHeight, height });\n\t\tthis.scrollableElement.setScrollPosition({ scrollTop });\n\t}\n\n\tpublic showMessage(message: IMessage, force?: boolean): void {\n\t\tthis.message = message;\n\n\t\tthis.element.classList.remove('idle');\n\t\tthis.element.classList.remove('info');\n\t\tthis.element.classList.remove('warning');\n\t\tthis.element.classList.remove('error');\n\t\tthis.element.classList.add(this.classForType(message.type));\n\n\t\tconst styles = this.stylesForType(this.message.type);\n\t\tthis.element.style.border = styles.border ? `1px solid ${styles.border}` : '';\n\n\t\tif (this.hasFocus() || force) {\n\t\t\tthis._showMessage();\n\t\t}\n\t}\n\n\tpublic hideMessage(): void {\n\t\tthis.message = null;\n\n\t\tthis.element.classList.remove('info');\n\t\tthis.element.classList.remove('warning');\n\t\tthis.element.classList.remove('error');\n\t\tthis.element.classList.add('idle');\n\n\t\tthis._hideMessage();\n\t\tthis.applyStyles();\n\t}\n\n\tpublic validate(): MessageType | undefined {\n\t\tlet errorMsg: IMessage | null = null;\n\n\t\tif (this.validation) {\n\t\t\terrorMsg = this.validation(this.value);\n\n\t\t\tif (errorMsg) {\n\t\t\t\tthis.inputElement.setAttribute('aria-invalid', 'true');\n\t\t\t\tthis.showMessage(errorMsg);\n\t\t\t}\n\t\t\telse if (this.inputElement.hasAttribute('aria-invalid')) {\n\t\t\t\tthis.inputElement.removeAttribute('aria-invalid');\n\t\t\t\tthis.hideMessage();\n\t\t\t}\n\t\t}\n\n\t\treturn errorMsg?.type;\n\t}\n\n\tpublic stylesForType(type: MessageType | undefined): { border: Color | undefined; background: Color | undefined; foreground: Color | undefined } {\n\t\tswitch (type) {\n\t\t\tcase MessageType.INFO: return { border: this.inputValidationInfoBorder, background: this.inputValidationInfoBackground, foreground: this.inputValidationInfoForeground };\n\t\t\tcase MessageType.WARNING: return { border: this.inputValidationWarningBorder, background: this.inputValidationWarningBackground, foreground: this.inputValidationWarningForeground };\n\t\t\tdefault: return { border: this.inputValidationErrorBorder, background: this.inputValidationErrorBackground, foreground: this.inputValidationErrorForeground };\n\t\t}\n\t}\n\n\tprivate classForType(type: MessageType | undefined): string {\n\t\tswitch (type) {\n\t\t\tcase MessageType.INFO: return 'info';\n\t\t\tcase MessageType.WARNING: return 'warning';\n\t\t\tdefault: return 'error';\n\t\t}\n\t}\n\n\tprivate _showMessage(): void {\n\t\tif (!this.contextViewProvider || !this.message) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet div: HTMLElement;\n\t\tlet layout = () => div.style.width = dom.getTotalWidth(this.element) + 'px';\n\n\t\tthis.contextViewProvider.showContextView({\n\t\t\tgetAnchor: () => this.element,\n\t\t\tanchorAlignment: AnchorAlignment.RIGHT,\n\t\t\trender: (container: HTMLElement) => {\n\t\t\t\tif (!this.message) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tdiv = dom.append(container, $('.monaco-inputbox-container'));\n\t\t\t\tlayout();\n\n\t\t\t\tconst renderOptions: MarkdownRenderOptions = {\n\t\t\t\t\tinline: true,\n\t\t\t\t\tclassName: 'monaco-inputbox-message'\n\t\t\t\t};\n\n\t\t\t\tconst spanElement = (this.message.formatContent\n\t\t\t\t\t? renderFormattedText(this.message.content, renderOptions)\n\t\t\t\t\t: renderText(this.message.content, renderOptions));\n\t\t\t\tspanElement.classList.add(this.classForType(this.message.type));\n\n\t\t\t\tconst styles = this.stylesForType(this.message.type);\n\t\t\t\tspanElement.style.backgroundColor = styles.background ? styles.background.toString() : '';\n\t\t\t\tspanElement.style.color = styles.foreground ? styles.foreground.toString() : '';\n\t\t\t\tspanElement.style.border = styles.border ? `1px solid ${styles.border}` : '';\n\n\t\t\t\tdom.append(div, spanElement);\n\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\tonHide: () => {\n\t\t\t\tthis.state = 'closed';\n\t\t\t},\n\t\t\tlayout: layout\n\t\t});\n\n\t\t// ARIA Support\n\t\tlet alertText: string;\n\t\tif (this.message.type === MessageType.ERROR) {\n\t\t\talertText = nls.localize('alertErrorMessage', \"Error: {0}\", this.message.content);\n\t\t} else if (this.message.type === MessageType.WARNING) {\n\t\t\talertText = nls.localize('alertWarningMessage', \"Warning: {0}\", this.message.content);\n\t\t} else {\n\t\t\talertText = nls.localize('alertInfoMessage', \"Info: {0}\", this.message.content);\n\t\t}\n\n\t\taria.alert(alertText);\n\n\t\tthis.state = 'open';\n\t}\n\n\tprivate _hideMessage(): void {\n\t\tif (!this.contextViewProvider) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.state === 'open') {\n\t\t\tthis.contextViewProvider.hideContextView();\n\t\t}\n\n\t\tthis.state = 'idle';\n\t}\n\n\tprivate onValueChange(): void {\n\t\tthis._onDidChange.fire(this.value);\n\n\t\tthis.validate();\n\t\tthis.updateMirror();\n\t\tthis.input.classList.toggle('empty', !this.value);\n\n\t\tif (this.state === 'open' && this.contextViewProvider) {\n\t\t\tthis.contextViewProvider.layout();\n\t\t}\n\t}\n\n\tprivate updateMirror(): void {\n\t\tif (!this.mirror) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst value = this.value;\n\t\tconst lastCharCode = value.charCodeAt(value.length - 1);\n\t\tconst suffix = lastCharCode === 10 ? ' ' : '';\n\t\tconst mirrorTextContent = (value + suffix)\n\t\t\t.replace(/\\u000c/g, ''); // Don't measure with the form feed character, which messes up sizing\n\n\t\tif (mirrorTextContent) {\n\t\t\tthis.mirror.textContent = value + suffix;\n\t\t} else {\n\t\t\tthis.mirror.innerText = '\\u00a0';\n\t\t}\n\n\t\tthis.layout();\n\t}\n\n\tpublic style(styles: IInputBoxStyles): void {\n\t\tthis.inputBackground = styles.inputBackground;\n\t\tthis.inputForeground = styles.inputForeground;\n\t\tthis.inputBorder = styles.inputBorder;\n\n\t\tthis.inputValidationInfoBackground = styles.inputValidationInfoBackground;\n\t\tthis.inputValidationInfoForeground = styles.inputValidationInfoForeground;\n\t\tthis.inputValidationInfoBorder = styles.inputValidationInfoBorder;\n\t\tthis.inputValidationWarningBackground = styles.inputValidationWarningBackground;\n\t\tthis.inputValidationWarningForeground = styles.inputValidationWarningForeground;\n\t\tthis.inputValidationWarningBorder = styles.inputValidationWarningBorder;\n\t\tthis.inputValidationErrorBackground = styles.inputValidationErrorBackground;\n\t\tthis.inputValidationErrorForeground = styles.inputValidationErrorForeground;\n\t\tthis.inputValidationErrorBorder = styles.inputValidationErrorBorder;\n\n\t\tthis.applyStyles();\n\t}\n\n\tprotected applyStyles(): void {\n\t\tconst background = this.inputBackground ? this.inputBackground.toString() : '';\n\t\tconst foreground = this.inputForeground ? this.inputForeground.toString() : '';\n\t\tconst border = this.inputBorder ? this.inputBorder.toString() : '';\n\n\t\tthis.element.style.backgroundColor = background;\n\t\tthis.element.style.color = foreground;\n\t\tthis.input.style.backgroundColor = 'inherit';\n\t\tthis.input.style.color = foreground;\n\n\t\tthis.element.style.borderWidth = border ? '1px' : '';\n\t\tthis.element.style.borderStyle = border ? 'solid' : '';\n\t\tthis.element.style.borderColor = border;\n\t}\n\n\tpublic layout(): void {\n\t\tif (!this.mirror) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst previousHeight = this.cachedContentHeight;\n\t\tthis.cachedContentHeight = dom.getTotalHeight(this.mirror);\n\n\t\tif (previousHeight !== this.cachedContentHeight) {\n\t\t\tthis.cachedHeight = Math.min(this.cachedContentHeight, this.maxHeight);\n\t\t\tthis.input.style.height = this.cachedHeight + 'px';\n\t\t\tthis._onDidHeightChange.fire(this.cachedContentHeight);\n\t\t}\n\t}\n\n\tpublic insertAtCursor(text: string): void {\n\t\tconst inputElement = this.inputElement;\n\t\tconst start = inputElement.selectionStart;\n\t\tconst end = inputElement.selectionEnd;\n\t\tconst content = inputElement.value;\n\n\t\tif (start !== null && end !== null) {\n\t\t\tthis.value = content.substr(0, start) + text + content.substr(end);\n\t\t\tinputElement.setSelectionRange(start + 1, start + 1);\n\t\t\tthis.layout();\n\t\t}\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._hideMessage();\n\n\t\tthis.message = null;\n\n\t\tif (this.actionbar) {\n\t\t\tthis.actionbar.dispose();\n\t\t}\n\n\t\tsuper.dispose();\n\t}\n}\n\nexport interface IHistoryInputOptions extends IInputOptions {\n\thistory: string[];\n\treadonly showHistoryHint?: () => boolean;\n}\n\nexport class HistoryInputBox extends InputBox implements IHistoryNavigationWidget {\n\n\tprivate readonly history: HistoryNavigator;\n\tprivate observer: MutationObserver | undefined;\n\n\tconstructor(container: HTMLElement, contextViewProvider: IContextViewProvider | undefined, options: IHistoryInputOptions) {\n\t\tconst NLS_PLACEHOLDER_HISTORY_HINT = nls.localize({ key: 'history.inputbox.hint', comment: ['Text will be prefixed with \\u21C5 plus a single space, then used as a hint where input field keeps history'] }, \"for history\");\n\t\tconst NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX = ` or \\u21C5 ${NLS_PLACEHOLDER_HISTORY_HINT}`;\n\t\tconst NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS = ` (\\u21C5 ${NLS_PLACEHOLDER_HISTORY_HINT})`;\n\t\tsuper(container, contextViewProvider, options);\n\t\tthis.history = new HistoryNavigator(options.history, 100);\n\n\t\t// Function to append the history suffix to the placeholder if necessary\n\t\tconst addSuffix = () => {\n\t\t\tif (options.showHistoryHint && options.showHistoryHint() && !this.placeholder.endsWith(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX) && !this.placeholder.endsWith(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS) && this.history.getHistory().length) {\n\t\t\t\tconst suffix = this.placeholder.endsWith(')') ? NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX : NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS;\n\t\t\t\tconst suffixedPlaceholder = this.placeholder + suffix;\n\t\t\t\tif (options.showPlaceholderOnFocus && document.activeElement !== this.input) {\n\t\t\t\t\tthis.placeholder = suffixedPlaceholder;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.setPlaceHolder(suffixedPlaceholder);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Spot the change to the textarea class attribute which occurs when it changes between non-empty and empty,\n\t\t// and add the history suffix to the placeholder if not yet present\n\t\tthis.observer = new MutationObserver((mutationList: MutationRecord[], observer: MutationObserver) => {\n\t\t\tmutationList.forEach((mutation: MutationRecord) => {\n\t\t\t\tif (!mutation.target.textContent) {\n\t\t\t\t\taddSuffix();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\tthis.observer.observe(this.input, { attributeFilter: ['class'] });\n\n\t\tthis.onfocus(this.input, () => addSuffix());\n\t\tthis.onblur(this.input, () => {\n\t\t\tconst resetPlaceholder = (historyHint: string) => {\n\t\t\t\tif (!this.placeholder.endsWith(historyHint)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tconst revertedPlaceholder = this.placeholder.slice(0, this.placeholder.length - historyHint.length);\n\t\t\t\t\tif (options.showPlaceholderOnFocus) {\n\t\t\t\t\t\tthis.placeholder = revertedPlaceholder;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.setPlaceHolder(revertedPlaceholder);\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t};\n\t\t\tif (!resetPlaceholder(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS)) {\n\t\t\t\tresetPlaceholder(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX);\n\t\t\t}\n\t\t});\n\t}\n\n\toverride dispose() {\n\t\tsuper.dispose();\n\t\tif (this.observer) {\n\t\t\tthis.observer.disconnect();\n\t\t\tthis.observer = undefined;\n\t\t}\n\t}\n\n\tpublic addToHistory(): void {\n\t\tif (this.value && this.value !== this.getCurrentValue()) {\n\t\t\tthis.history.add(this.value);\n\t\t}\n\t}\n\n\tpublic showNextValue(): void {\n\t\tif (!this.history.has(this.value)) {\n\t\t\tthis.addToHistory();\n\t\t}\n\n\t\tlet next = this.getNextValue();\n\t\tif (next) {\n\t\t\tnext = next === this.value ? this.getNextValue() : next;\n\t\t}\n\n\t\tif (next) {\n\t\t\tthis.value = next;\n\t\t\taria.status(this.value);\n\t\t}\n\t}\n\n\tpublic showPreviousValue(): void {\n\t\tif (!this.history.has(this.value)) {\n\t\t\tthis.addToHistory();\n\t\t}\n\n\t\tlet previous = this.getPreviousValue();\n\t\tif (previous) {\n\t\t\tprevious = previous === this.value ? this.getPreviousValue() : previous;\n\t\t}\n\n\t\tif (previous) {\n\t\t\tthis.value = previous;\n\t\t\taria.status(this.value);\n\t\t}\n\t}\n\n\tprivate getCurrentValue(): string | null {\n\t\tlet currentValue = this.history.current();\n\t\tif (!currentValue) {\n\t\t\tcurrentValue = this.history.last();\n\t\t\tthis.history.next();\n\t\t}\n\t\treturn currentValue;\n\t}\n\n\tprivate getPreviousValue(): string | null {\n\t\treturn this.history.previous() || this.history.first();\n\t}\n\n\tprivate getNextValue(): string | null {\n\t\treturn this.history.next() || this.history.last();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { IMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { ICheckboxStyles } from 'vs/base/browser/ui/checkbox/checkbox';\nimport { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';\nimport { CaseSensitiveCheckbox, RegexCheckbox, WholeWordsCheckbox } from 'vs/base/browser/ui/findinput/findInputCheckboxes';\nimport { HistoryInputBox, IInputBoxStyles, IInputValidator } from 'vs/base/browser/ui/inputbox/inputBox';\nimport { Widget } from 'vs/base/browser/ui/widget';\nimport { Color } from 'vs/base/common/color';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport 'vs/css!./findInput';\nimport * as nls from 'vs/nls';\n\n\nexport interface IFindInputOptions extends IFindInputStyles {\n\treadonly placeholder?: string;\n\treadonly width?: number;\n\treadonly validation?: IInputValidator;\n\treadonly label: string;\n\treadonly flexibleHeight?: boolean;\n\treadonly flexibleWidth?: boolean;\n\treadonly flexibleMaxHeight?: number;\n\n\treadonly appendCaseSensitiveLabel?: string;\n\treadonly appendWholeWordsLabel?: string;\n\treadonly appendRegexLabel?: string;\n\treadonly history?: string[];\n\treadonly showHistoryHint?: () => boolean;\n}\n\nexport interface IFindInputStyles extends IInputBoxStyles {\n\tinputActiveOptionBorder?: Color;\n\tinputActiveOptionForeground?: Color;\n\tinputActiveOptionBackground?: Color;\n}\n\nconst NLS_DEFAULT_LABEL = nls.localize('defaultLabel', \"input\");\n\nexport class FindInput extends Widget {\n\n\tprivate contextViewProvider: IContextViewProvider;\n\tprivate placeholder: string;\n\tprivate validation?: IInputValidator;\n\tprivate label: string;\n\tprivate fixFocusOnOptionClickEnabled = true;\n\tprivate imeSessionInProgress = false;\n\n\tprotected inputActiveOptionBorder?: Color;\n\tprotected inputActiveOptionForeground?: Color;\n\tprotected inputActiveOptionBackground?: Color;\n\tprotected inputBackground?: Color;\n\tprotected inputForeground?: Color;\n\tprotected inputBorder?: Color;\n\n\tprotected inputValidationInfoBorder?: Color;\n\tprotected inputValidationInfoBackground?: Color;\n\tprotected inputValidationInfoForeground?: Color;\n\tprotected inputValidationWarningBorder?: Color;\n\tprotected inputValidationWarningBackground?: Color;\n\tprotected inputValidationWarningForeground?: Color;\n\tprotected inputValidationErrorBorder?: Color;\n\tprotected inputValidationErrorBackground?: Color;\n\tprotected inputValidationErrorForeground?: Color;\n\n\tprotected controls: HTMLDivElement;\n\tprotected regex: RegexCheckbox;\n\tprotected wholeWords: WholeWordsCheckbox;\n\tprotected caseSensitive: CaseSensitiveCheckbox;\n\tpublic domNode: HTMLElement;\n\tpublic inputBox: HistoryInputBox;\n\n\tprivate readonly _onDidOptionChange = this._register(new Emitter());\n\tpublic readonly onDidOptionChange: Event = this._onDidOptionChange.event;\n\n\tprivate readonly _onKeyDown = this._register(new Emitter());\n\tpublic readonly onKeyDown: Event = this._onKeyDown.event;\n\n\tprivate readonly _onMouseDown = this._register(new Emitter());\n\tpublic readonly onMouseDown: Event = this._onMouseDown.event;\n\n\tprivate readonly _onInput = this._register(new Emitter());\n\n\tprivate readonly _onKeyUp = this._register(new Emitter());\n\n\tprivate _onCaseSensitiveKeyDown = this._register(new Emitter());\n\tpublic readonly onCaseSensitiveKeyDown: Event = this._onCaseSensitiveKeyDown.event;\n\n\tprivate _onRegexKeyDown = this._register(new Emitter());\n\tpublic readonly onRegexKeyDown: Event = this._onRegexKeyDown.event;\n\n\tconstructor(parent: HTMLElement | null, contextViewProvider: IContextViewProvider, private readonly _showOptionButtons: boolean, options: IFindInputOptions) {\n\t\tsuper();\n\t\tthis.contextViewProvider = contextViewProvider;\n\t\tthis.placeholder = options.placeholder || '';\n\t\tthis.validation = options.validation;\n\t\tthis.label = options.label || NLS_DEFAULT_LABEL;\n\n\t\tthis.inputActiveOptionBorder = options.inputActiveOptionBorder;\n\t\tthis.inputActiveOptionForeground = options.inputActiveOptionForeground;\n\t\tthis.inputActiveOptionBackground = options.inputActiveOptionBackground;\n\t\tthis.inputBackground = options.inputBackground;\n\t\tthis.inputForeground = options.inputForeground;\n\t\tthis.inputBorder = options.inputBorder;\n\n\t\tthis.inputValidationInfoBorder = options.inputValidationInfoBorder;\n\t\tthis.inputValidationInfoBackground = options.inputValidationInfoBackground;\n\t\tthis.inputValidationInfoForeground = options.inputValidationInfoForeground;\n\t\tthis.inputValidationWarningBorder = options.inputValidationWarningBorder;\n\t\tthis.inputValidationWarningBackground = options.inputValidationWarningBackground;\n\t\tthis.inputValidationWarningForeground = options.inputValidationWarningForeground;\n\t\tthis.inputValidationErrorBorder = options.inputValidationErrorBorder;\n\t\tthis.inputValidationErrorBackground = options.inputValidationErrorBackground;\n\t\tthis.inputValidationErrorForeground = options.inputValidationErrorForeground;\n\n\t\tconst appendCaseSensitiveLabel = options.appendCaseSensitiveLabel || '';\n\t\tconst appendWholeWordsLabel = options.appendWholeWordsLabel || '';\n\t\tconst appendRegexLabel = options.appendRegexLabel || '';\n\t\tconst history = options.history || [];\n\t\tconst flexibleHeight = !!options.flexibleHeight;\n\t\tconst flexibleWidth = !!options.flexibleWidth;\n\t\tconst flexibleMaxHeight = options.flexibleMaxHeight;\n\n\t\tthis.domNode = document.createElement('div');\n\t\tthis.domNode.classList.add('monaco-findInput');\n\n\t\tthis.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, {\n\t\t\tplaceholder: this.placeholder || '',\n\t\t\tariaLabel: this.label || '',\n\t\t\tvalidationOptions: {\n\t\t\t\tvalidation: this.validation\n\t\t\t},\n\t\t\tinputBackground: this.inputBackground,\n\t\t\tinputForeground: this.inputForeground,\n\t\t\tinputBorder: this.inputBorder,\n\t\t\tinputValidationInfoBackground: this.inputValidationInfoBackground,\n\t\t\tinputValidationInfoForeground: this.inputValidationInfoForeground,\n\t\t\tinputValidationInfoBorder: this.inputValidationInfoBorder,\n\t\t\tinputValidationWarningBackground: this.inputValidationWarningBackground,\n\t\t\tinputValidationWarningForeground: this.inputValidationWarningForeground,\n\t\t\tinputValidationWarningBorder: this.inputValidationWarningBorder,\n\t\t\tinputValidationErrorBackground: this.inputValidationErrorBackground,\n\t\t\tinputValidationErrorForeground: this.inputValidationErrorForeground,\n\t\t\tinputValidationErrorBorder: this.inputValidationErrorBorder,\n\t\t\thistory,\n\t\t\tshowHistoryHint: options.showHistoryHint,\n\t\t\tflexibleHeight,\n\t\t\tflexibleWidth,\n\t\t\tflexibleMaxHeight\n\t\t}));\n\n\t\tthis.regex = this._register(new RegexCheckbox({\n\t\t\tappendTitle: appendRegexLabel,\n\t\t\tisChecked: false,\n\t\t\tinputActiveOptionBorder: this.inputActiveOptionBorder,\n\t\t\tinputActiveOptionForeground: this.inputActiveOptionForeground,\n\t\t\tinputActiveOptionBackground: this.inputActiveOptionBackground\n\t\t}));\n\t\tthis._register(this.regex.onChange(viaKeyboard => {\n\t\t\tthis._onDidOptionChange.fire(viaKeyboard);\n\t\t\tif (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {\n\t\t\t\tthis.inputBox.focus();\n\t\t\t}\n\t\t\tthis.validate();\n\t\t}));\n\t\tthis._register(this.regex.onKeyDown(e => {\n\t\t\tthis._onRegexKeyDown.fire(e);\n\t\t}));\n\n\t\tthis.wholeWords = this._register(new WholeWordsCheckbox({\n\t\t\tappendTitle: appendWholeWordsLabel,\n\t\t\tisChecked: false,\n\t\t\tinputActiveOptionBorder: this.inputActiveOptionBorder,\n\t\t\tinputActiveOptionForeground: this.inputActiveOptionForeground,\n\t\t\tinputActiveOptionBackground: this.inputActiveOptionBackground\n\t\t}));\n\t\tthis._register(this.wholeWords.onChange(viaKeyboard => {\n\t\t\tthis._onDidOptionChange.fire(viaKeyboard);\n\t\t\tif (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {\n\t\t\t\tthis.inputBox.focus();\n\t\t\t}\n\t\t\tthis.validate();\n\t\t}));\n\n\t\tthis.caseSensitive = this._register(new CaseSensitiveCheckbox({\n\t\t\tappendTitle: appendCaseSensitiveLabel,\n\t\t\tisChecked: false,\n\t\t\tinputActiveOptionBorder: this.inputActiveOptionBorder,\n\t\t\tinputActiveOptionForeground: this.inputActiveOptionForeground,\n\t\t\tinputActiveOptionBackground: this.inputActiveOptionBackground\n\t\t}));\n\t\tthis._register(this.caseSensitive.onChange(viaKeyboard => {\n\t\t\tthis._onDidOptionChange.fire(viaKeyboard);\n\t\t\tif (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {\n\t\t\t\tthis.inputBox.focus();\n\t\t\t}\n\t\t\tthis.validate();\n\t\t}));\n\t\tthis._register(this.caseSensitive.onKeyDown(e => {\n\t\t\tthis._onCaseSensitiveKeyDown.fire(e);\n\t\t}));\n\n\t\tif (this._showOptionButtons) {\n\t\t\tthis.inputBox.paddingRight = this.caseSensitive.width() + this.wholeWords.width() + this.regex.width();\n\t\t}\n\n\t\t// Arrow-Key support to navigate between options\n\t\tlet indexes = [this.caseSensitive.domNode, this.wholeWords.domNode, this.regex.domNode];\n\t\tthis.onkeydown(this.domNode, (event: IKeyboardEvent) => {\n\t\t\tif (event.equals(KeyCode.LeftArrow) || event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Escape)) {\n\t\t\t\tlet index = indexes.indexOf(document.activeElement);\n\t\t\t\tif (index >= 0) {\n\t\t\t\t\tlet newIndex: number = -1;\n\t\t\t\t\tif (event.equals(KeyCode.RightArrow)) {\n\t\t\t\t\t\tnewIndex = (index + 1) % indexes.length;\n\t\t\t\t\t} else if (event.equals(KeyCode.LeftArrow)) {\n\t\t\t\t\t\tif (index === 0) {\n\t\t\t\t\t\t\tnewIndex = indexes.length - 1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnewIndex = index - 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (event.equals(KeyCode.Escape)) {\n\t\t\t\t\t\tindexes[index].blur();\n\t\t\t\t\t\tthis.inputBox.focus();\n\t\t\t\t\t} else if (newIndex >= 0) {\n\t\t\t\t\t\tindexes[newIndex].focus();\n\t\t\t\t\t}\n\n\t\t\t\t\tdom.EventHelper.stop(event, true);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\n\t\tthis.controls = document.createElement('div');\n\t\tthis.controls.className = 'controls';\n\t\tthis.controls.style.display = this._showOptionButtons ? 'block' : 'none';\n\t\tthis.controls.appendChild(this.caseSensitive.domNode);\n\t\tthis.controls.appendChild(this.wholeWords.domNode);\n\t\tthis.controls.appendChild(this.regex.domNode);\n\n\t\tthis.domNode.appendChild(this.controls);\n\n\t\tif (parent) {\n\t\t\tparent.appendChild(this.domNode);\n\t\t}\n\n\t\tthis._register(dom.addDisposableListener(this.inputBox.inputElement, 'compositionstart', (e: CompositionEvent) => {\n\t\t\tthis.imeSessionInProgress = true;\n\t\t}));\n\t\tthis._register(dom.addDisposableListener(this.inputBox.inputElement, 'compositionend', (e: CompositionEvent) => {\n\t\t\tthis.imeSessionInProgress = false;\n\t\t\tthis._onInput.fire();\n\t\t}));\n\n\t\tthis.onkeydown(this.inputBox.inputElement, (e) => this._onKeyDown.fire(e));\n\t\tthis.onkeyup(this.inputBox.inputElement, (e) => this._onKeyUp.fire(e));\n\t\tthis.oninput(this.inputBox.inputElement, (e) => this._onInput.fire());\n\t\tthis.onmousedown(this.inputBox.inputElement, (e) => this._onMouseDown.fire(e));\n\t}\n\n\tpublic enable(): void {\n\t\tthis.domNode.classList.remove('disabled');\n\t\tthis.inputBox.enable();\n\t\tthis.regex.enable();\n\t\tthis.wholeWords.enable();\n\t\tthis.caseSensitive.enable();\n\t}\n\n\tpublic disable(): void {\n\t\tthis.domNode.classList.add('disabled');\n\t\tthis.inputBox.disable();\n\t\tthis.regex.disable();\n\t\tthis.wholeWords.disable();\n\t\tthis.caseSensitive.disable();\n\t}\n\n\tpublic setFocusInputOnOptionClick(value: boolean): void {\n\t\tthis.fixFocusOnOptionClickEnabled = value;\n\t}\n\n\tpublic setEnabled(enabled: boolean): void {\n\t\tif (enabled) {\n\t\t\tthis.enable();\n\t\t} else {\n\t\t\tthis.disable();\n\t\t}\n\t}\n\n\tpublic getValue(): string {\n\t\treturn this.inputBox.value;\n\t}\n\n\tpublic setValue(value: string): void {\n\t\tif (this.inputBox.value !== value) {\n\t\t\tthis.inputBox.value = value;\n\t\t}\n\t}\n\n\tpublic style(styles: IFindInputStyles): void {\n\t\tthis.inputActiveOptionBorder = styles.inputActiveOptionBorder;\n\t\tthis.inputActiveOptionForeground = styles.inputActiveOptionForeground;\n\t\tthis.inputActiveOptionBackground = styles.inputActiveOptionBackground;\n\t\tthis.inputBackground = styles.inputBackground;\n\t\tthis.inputForeground = styles.inputForeground;\n\t\tthis.inputBorder = styles.inputBorder;\n\n\t\tthis.inputValidationInfoBackground = styles.inputValidationInfoBackground;\n\t\tthis.inputValidationInfoForeground = styles.inputValidationInfoForeground;\n\t\tthis.inputValidationInfoBorder = styles.inputValidationInfoBorder;\n\t\tthis.inputValidationWarningBackground = styles.inputValidationWarningBackground;\n\t\tthis.inputValidationWarningForeground = styles.inputValidationWarningForeground;\n\t\tthis.inputValidationWarningBorder = styles.inputValidationWarningBorder;\n\t\tthis.inputValidationErrorBackground = styles.inputValidationErrorBackground;\n\t\tthis.inputValidationErrorForeground = styles.inputValidationErrorForeground;\n\t\tthis.inputValidationErrorBorder = styles.inputValidationErrorBorder;\n\n\t\tthis.applyStyles();\n\t}\n\n\tprotected applyStyles(): void {\n\t\tif (this.domNode) {\n\t\t\tconst checkBoxStyles: ICheckboxStyles = {\n\t\t\t\tinputActiveOptionBorder: this.inputActiveOptionBorder,\n\t\t\t\tinputActiveOptionForeground: this.inputActiveOptionForeground,\n\t\t\t\tinputActiveOptionBackground: this.inputActiveOptionBackground,\n\t\t\t};\n\t\t\tthis.regex.style(checkBoxStyles);\n\t\t\tthis.wholeWords.style(checkBoxStyles);\n\t\t\tthis.caseSensitive.style(checkBoxStyles);\n\n\t\t\tconst inputBoxStyles: IInputBoxStyles = {\n\t\t\t\tinputBackground: this.inputBackground,\n\t\t\t\tinputForeground: this.inputForeground,\n\t\t\t\tinputBorder: this.inputBorder,\n\t\t\t\tinputValidationInfoBackground: this.inputValidationInfoBackground,\n\t\t\t\tinputValidationInfoForeground: this.inputValidationInfoForeground,\n\t\t\t\tinputValidationInfoBorder: this.inputValidationInfoBorder,\n\t\t\t\tinputValidationWarningBackground: this.inputValidationWarningBackground,\n\t\t\t\tinputValidationWarningForeground: this.inputValidationWarningForeground,\n\t\t\t\tinputValidationWarningBorder: this.inputValidationWarningBorder,\n\t\t\t\tinputValidationErrorBackground: this.inputValidationErrorBackground,\n\t\t\t\tinputValidationErrorForeground: this.inputValidationErrorForeground,\n\t\t\t\tinputValidationErrorBorder: this.inputValidationErrorBorder\n\t\t\t};\n\t\t\tthis.inputBox.style(inputBoxStyles);\n\t\t}\n\t}\n\n\tpublic select(): void {\n\t\tthis.inputBox.select();\n\t}\n\n\tpublic focus(): void {\n\t\tthis.inputBox.focus();\n\t}\n\n\tpublic getCaseSensitive(): boolean {\n\t\treturn this.caseSensitive.checked;\n\t}\n\n\tpublic setCaseSensitive(value: boolean): void {\n\t\tthis.caseSensitive.checked = value;\n\t}\n\n\tpublic getWholeWords(): boolean {\n\t\treturn this.wholeWords.checked;\n\t}\n\n\tpublic setWholeWords(value: boolean): void {\n\t\tthis.wholeWords.checked = value;\n\t}\n\n\tpublic getRegex(): boolean {\n\t\treturn this.regex.checked;\n\t}\n\n\tpublic setRegex(value: boolean): void {\n\t\tthis.regex.checked = value;\n\t\tthis.validate();\n\t}\n\n\tpublic focusOnCaseSensitive(): void {\n\t\tthis.caseSensitive.focus();\n\t}\n\n\tprivate _lastHighlightFindOptions: number = 0;\n\tpublic highlightFindOptions(): void {\n\t\tthis.domNode.classList.remove('highlight-' + (this._lastHighlightFindOptions));\n\t\tthis._lastHighlightFindOptions = 1 - this._lastHighlightFindOptions;\n\t\tthis.domNode.classList.add('highlight-' + (this._lastHighlightFindOptions));\n\t}\n\n\tpublic validate(): void {\n\t\tthis.inputBox.validate();\n\t}\n\n\tpublic clearMessage(): void {\n\t\tthis.inputBox.hideMessage();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { IMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { Checkbox, ICheckboxStyles } from 'vs/base/browser/ui/checkbox/checkbox';\nimport { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';\nimport { IFindInputCheckboxOpts } from 'vs/base/browser/ui/findinput/findInputCheckboxes';\nimport { HistoryInputBox, IInputBoxStyles, IInputValidator } from 'vs/base/browser/ui/inputbox/inputBox';\nimport { Widget } from 'vs/base/browser/ui/widget';\nimport { Codicon } from 'vs/base/common/codicons';\nimport { Color } from 'vs/base/common/color';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport 'vs/css!./findInput';\nimport * as nls from 'vs/nls';\n\n\nexport interface IReplaceInputOptions extends IReplaceInputStyles {\n\treadonly placeholder?: string;\n\treadonly validation?: IInputValidator;\n\treadonly label: string;\n\treadonly flexibleHeight?: boolean;\n\treadonly flexibleWidth?: boolean;\n\treadonly flexibleMaxHeight?: number;\n\n\treadonly appendPreserveCaseLabel?: string;\n\treadonly history?: string[];\n\treadonly showHistoryHint?: () => boolean;\n}\n\nexport interface IReplaceInputStyles extends IInputBoxStyles {\n\tinputActiveOptionBorder?: Color;\n\tinputActiveOptionForeground?: Color;\n\tinputActiveOptionBackground?: Color;\n}\n\nconst NLS_DEFAULT_LABEL = nls.localize('defaultLabel', \"input\");\nconst NLS_PRESERVE_CASE_LABEL = nls.localize('label.preserveCaseCheckbox', \"Preserve Case\");\n\nexport class PreserveCaseCheckbox extends Checkbox {\n\tconstructor(opts: IFindInputCheckboxOpts) {\n\t\tsuper({\n\t\t\t// TODO: does this need its own icon?\n\t\t\ticon: Codicon.preserveCase,\n\t\t\ttitle: NLS_PRESERVE_CASE_LABEL + opts.appendTitle,\n\t\t\tisChecked: opts.isChecked,\n\t\t\tinputActiveOptionBorder: opts.inputActiveOptionBorder,\n\t\t\tinputActiveOptionForeground: opts.inputActiveOptionForeground,\n\t\t\tinputActiveOptionBackground: opts.inputActiveOptionBackground\n\t\t});\n\t}\n}\n\nexport class ReplaceInput extends Widget {\n\n\tprivate contextViewProvider: IContextViewProvider | undefined;\n\tprivate placeholder: string;\n\tprivate validation?: IInputValidator;\n\tprivate label: string;\n\tprivate fixFocusOnOptionClickEnabled = true;\n\n\tprivate inputActiveOptionBorder?: Color;\n\tprivate inputActiveOptionForeground?: Color;\n\tprivate inputActiveOptionBackground?: Color;\n\tprivate inputBackground?: Color;\n\tprivate inputForeground?: Color;\n\tprivate inputBorder?: Color;\n\n\tprivate inputValidationInfoBorder?: Color;\n\tprivate inputValidationInfoBackground?: Color;\n\tprivate inputValidationInfoForeground?: Color;\n\tprivate inputValidationWarningBorder?: Color;\n\tprivate inputValidationWarningBackground?: Color;\n\tprivate inputValidationWarningForeground?: Color;\n\tprivate inputValidationErrorBorder?: Color;\n\tprivate inputValidationErrorBackground?: Color;\n\tprivate inputValidationErrorForeground?: Color;\n\n\tprivate preserveCase: PreserveCaseCheckbox;\n\tprivate cachedOptionsWidth: number = 0;\n\tpublic domNode: HTMLElement;\n\tpublic inputBox: HistoryInputBox;\n\n\tprivate readonly _onDidOptionChange = this._register(new Emitter());\n\tpublic readonly onDidOptionChange: Event = this._onDidOptionChange.event;\n\n\tprivate readonly _onKeyDown = this._register(new Emitter());\n\tpublic readonly onKeyDown: Event = this._onKeyDown.event;\n\n\tprivate readonly _onMouseDown = this._register(new Emitter());\n\n\tprivate readonly _onInput = this._register(new Emitter());\n\n\tprivate readonly _onKeyUp = this._register(new Emitter());\n\n\tprivate _onPreserveCaseKeyDown = this._register(new Emitter());\n\tpublic readonly onPreserveCaseKeyDown: Event = this._onPreserveCaseKeyDown.event;\n\n\tconstructor(parent: HTMLElement | null, contextViewProvider: IContextViewProvider | undefined, private readonly _showOptionButtons: boolean, options: IReplaceInputOptions) {\n\t\tsuper();\n\t\tthis.contextViewProvider = contextViewProvider;\n\t\tthis.placeholder = options.placeholder || '';\n\t\tthis.validation = options.validation;\n\t\tthis.label = options.label || NLS_DEFAULT_LABEL;\n\n\t\tthis.inputActiveOptionBorder = options.inputActiveOptionBorder;\n\t\tthis.inputActiveOptionForeground = options.inputActiveOptionForeground;\n\t\tthis.inputActiveOptionBackground = options.inputActiveOptionBackground;\n\t\tthis.inputBackground = options.inputBackground;\n\t\tthis.inputForeground = options.inputForeground;\n\t\tthis.inputBorder = options.inputBorder;\n\n\t\tthis.inputValidationInfoBorder = options.inputValidationInfoBorder;\n\t\tthis.inputValidationInfoBackground = options.inputValidationInfoBackground;\n\t\tthis.inputValidationInfoForeground = options.inputValidationInfoForeground;\n\t\tthis.inputValidationWarningBorder = options.inputValidationWarningBorder;\n\t\tthis.inputValidationWarningBackground = options.inputValidationWarningBackground;\n\t\tthis.inputValidationWarningForeground = options.inputValidationWarningForeground;\n\t\tthis.inputValidationErrorBorder = options.inputValidationErrorBorder;\n\t\tthis.inputValidationErrorBackground = options.inputValidationErrorBackground;\n\t\tthis.inputValidationErrorForeground = options.inputValidationErrorForeground;\n\n\t\tconst appendPreserveCaseLabel = options.appendPreserveCaseLabel || '';\n\t\tconst history = options.history || [];\n\t\tconst flexibleHeight = !!options.flexibleHeight;\n\t\tconst flexibleWidth = !!options.flexibleWidth;\n\t\tconst flexibleMaxHeight = options.flexibleMaxHeight;\n\n\t\tthis.domNode = document.createElement('div');\n\t\tthis.domNode.classList.add('monaco-findInput');\n\n\t\tthis.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, {\n\t\t\tariaLabel: this.label || '',\n\t\t\tplaceholder: this.placeholder || '',\n\t\t\tvalidationOptions: {\n\t\t\t\tvalidation: this.validation\n\t\t\t},\n\t\t\tinputBackground: this.inputBackground,\n\t\t\tinputForeground: this.inputForeground,\n\t\t\tinputBorder: this.inputBorder,\n\t\t\tinputValidationInfoBackground: this.inputValidationInfoBackground,\n\t\t\tinputValidationInfoForeground: this.inputValidationInfoForeground,\n\t\t\tinputValidationInfoBorder: this.inputValidationInfoBorder,\n\t\t\tinputValidationWarningBackground: this.inputValidationWarningBackground,\n\t\t\tinputValidationWarningForeground: this.inputValidationWarningForeground,\n\t\t\tinputValidationWarningBorder: this.inputValidationWarningBorder,\n\t\t\tinputValidationErrorBackground: this.inputValidationErrorBackground,\n\t\t\tinputValidationErrorForeground: this.inputValidationErrorForeground,\n\t\t\tinputValidationErrorBorder: this.inputValidationErrorBorder,\n\t\t\thistory,\n\t\t\tshowHistoryHint: options.showHistoryHint,\n\t\t\tflexibleHeight,\n\t\t\tflexibleWidth,\n\t\t\tflexibleMaxHeight\n\t\t}));\n\n\t\tthis.preserveCase = this._register(new PreserveCaseCheckbox({\n\t\t\tappendTitle: appendPreserveCaseLabel,\n\t\t\tisChecked: false,\n\t\t\tinputActiveOptionBorder: this.inputActiveOptionBorder,\n\t\t\tinputActiveOptionForeground: this.inputActiveOptionForeground,\n\t\t\tinputActiveOptionBackground: this.inputActiveOptionBackground,\n\t\t}));\n\t\tthis._register(this.preserveCase.onChange(viaKeyboard => {\n\t\t\tthis._onDidOptionChange.fire(viaKeyboard);\n\t\t\tif (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {\n\t\t\t\tthis.inputBox.focus();\n\t\t\t}\n\t\t\tthis.validate();\n\t\t}));\n\t\tthis._register(this.preserveCase.onKeyDown(e => {\n\t\t\tthis._onPreserveCaseKeyDown.fire(e);\n\t\t}));\n\n\t\tif (this._showOptionButtons) {\n\t\t\tthis.cachedOptionsWidth = this.preserveCase.width();\n\t\t} else {\n\t\t\tthis.cachedOptionsWidth = 0;\n\t\t}\n\n\t\t// Arrow-Key support to navigate between options\n\t\tlet indexes = [this.preserveCase.domNode];\n\t\tthis.onkeydown(this.domNode, (event: IKeyboardEvent) => {\n\t\t\tif (event.equals(KeyCode.LeftArrow) || event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Escape)) {\n\t\t\t\tlet index = indexes.indexOf(document.activeElement);\n\t\t\t\tif (index >= 0) {\n\t\t\t\t\tlet newIndex: number = -1;\n\t\t\t\t\tif (event.equals(KeyCode.RightArrow)) {\n\t\t\t\t\t\tnewIndex = (index + 1) % indexes.length;\n\t\t\t\t\t} else if (event.equals(KeyCode.LeftArrow)) {\n\t\t\t\t\t\tif (index === 0) {\n\t\t\t\t\t\t\tnewIndex = indexes.length - 1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnewIndex = index - 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (event.equals(KeyCode.Escape)) {\n\t\t\t\t\t\tindexes[index].blur();\n\t\t\t\t\t\tthis.inputBox.focus();\n\t\t\t\t\t} else if (newIndex >= 0) {\n\t\t\t\t\t\tindexes[newIndex].focus();\n\t\t\t\t\t}\n\n\t\t\t\t\tdom.EventHelper.stop(event, true);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\n\t\tlet controls = document.createElement('div');\n\t\tcontrols.className = 'controls';\n\t\tcontrols.style.display = this._showOptionButtons ? 'block' : 'none';\n\t\tcontrols.appendChild(this.preserveCase.domNode);\n\n\t\tthis.domNode.appendChild(controls);\n\n\t\tif (parent) {\n\t\t\tparent.appendChild(this.domNode);\n\t\t}\n\n\t\tthis.onkeydown(this.inputBox.inputElement, (e) => this._onKeyDown.fire(e));\n\t\tthis.onkeyup(this.inputBox.inputElement, (e) => this._onKeyUp.fire(e));\n\t\tthis.oninput(this.inputBox.inputElement, (e) => this._onInput.fire());\n\t\tthis.onmousedown(this.inputBox.inputElement, (e) => this._onMouseDown.fire(e));\n\t}\n\n\tpublic enable(): void {\n\t\tthis.domNode.classList.remove('disabled');\n\t\tthis.inputBox.enable();\n\t\tthis.preserveCase.enable();\n\t}\n\n\tpublic disable(): void {\n\t\tthis.domNode.classList.add('disabled');\n\t\tthis.inputBox.disable();\n\t\tthis.preserveCase.disable();\n\t}\n\n\tpublic setEnabled(enabled: boolean): void {\n\t\tif (enabled) {\n\t\t\tthis.enable();\n\t\t} else {\n\t\t\tthis.disable();\n\t\t}\n\t}\n\n\tpublic style(styles: IReplaceInputStyles): void {\n\t\tthis.inputActiveOptionBorder = styles.inputActiveOptionBorder;\n\t\tthis.inputActiveOptionForeground = styles.inputActiveOptionForeground;\n\t\tthis.inputActiveOptionBackground = styles.inputActiveOptionBackground;\n\t\tthis.inputBackground = styles.inputBackground;\n\t\tthis.inputForeground = styles.inputForeground;\n\t\tthis.inputBorder = styles.inputBorder;\n\n\t\tthis.inputValidationInfoBackground = styles.inputValidationInfoBackground;\n\t\tthis.inputValidationInfoForeground = styles.inputValidationInfoForeground;\n\t\tthis.inputValidationInfoBorder = styles.inputValidationInfoBorder;\n\t\tthis.inputValidationWarningBackground = styles.inputValidationWarningBackground;\n\t\tthis.inputValidationWarningForeground = styles.inputValidationWarningForeground;\n\t\tthis.inputValidationWarningBorder = styles.inputValidationWarningBorder;\n\t\tthis.inputValidationErrorBackground = styles.inputValidationErrorBackground;\n\t\tthis.inputValidationErrorForeground = styles.inputValidationErrorForeground;\n\t\tthis.inputValidationErrorBorder = styles.inputValidationErrorBorder;\n\n\t\tthis.applyStyles();\n\t}\n\n\tprotected applyStyles(): void {\n\t\tif (this.domNode) {\n\t\t\tconst checkBoxStyles: ICheckboxStyles = {\n\t\t\t\tinputActiveOptionBorder: this.inputActiveOptionBorder,\n\t\t\t\tinputActiveOptionForeground: this.inputActiveOptionForeground,\n\t\t\t\tinputActiveOptionBackground: this.inputActiveOptionBackground,\n\t\t\t};\n\t\t\tthis.preserveCase.style(checkBoxStyles);\n\n\t\t\tconst inputBoxStyles: IInputBoxStyles = {\n\t\t\t\tinputBackground: this.inputBackground,\n\t\t\t\tinputForeground: this.inputForeground,\n\t\t\t\tinputBorder: this.inputBorder,\n\t\t\t\tinputValidationInfoBackground: this.inputValidationInfoBackground,\n\t\t\t\tinputValidationInfoForeground: this.inputValidationInfoForeground,\n\t\t\t\tinputValidationInfoBorder: this.inputValidationInfoBorder,\n\t\t\t\tinputValidationWarningBackground: this.inputValidationWarningBackground,\n\t\t\t\tinputValidationWarningForeground: this.inputValidationWarningForeground,\n\t\t\t\tinputValidationWarningBorder: this.inputValidationWarningBorder,\n\t\t\t\tinputValidationErrorBackground: this.inputValidationErrorBackground,\n\t\t\t\tinputValidationErrorForeground: this.inputValidationErrorForeground,\n\t\t\t\tinputValidationErrorBorder: this.inputValidationErrorBorder\n\t\t\t};\n\t\t\tthis.inputBox.style(inputBoxStyles);\n\t\t}\n\t}\n\n\tpublic select(): void {\n\t\tthis.inputBox.select();\n\t}\n\n\tpublic focus(): void {\n\t\tthis.inputBox.focus();\n\t}\n\n\tpublic getPreserveCase(): boolean {\n\t\treturn this.preserveCase.checked;\n\t}\n\n\tpublic setPreserveCase(value: boolean): void {\n\t\tthis.preserveCase.checked = value;\n\t}\n\n\tpublic focusOnPreserve(): void {\n\t\tthis.preserveCase.focus();\n\t}\n\n\tpublic validate(): void {\n\t\tif (this.inputBox) {\n\t\t\tthis.inputBox.validate();\n\t\t}\n\t}\n\n\tpublic set width(newWidth: number) {\n\t\tthis.inputBox.paddingRight = this.cachedOptionsWidth;\n\t\tthis.inputBox.width = newWidth;\n\t\tthis.domNode.style.width = newWidth + 'px';\n\t}\n\n\tpublic override dispose(): void {\n\t\tsuper.dispose();\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { isFirefox } from 'vs/base/browser/browser';\nimport { EventType as TouchEventType, Gesture } from 'vs/base/browser/touch';\nimport { $, addDisposableListener, append, clearNode, createStyleSheet, Dimension, EventHelper, EventLike, EventType, getActiveElement, IDomNodePagePosition, isAncestor, isInShadowDOM } from 'vs/base/browser/dom';\nimport { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { StandardMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { ActionBar, ActionsOrientation, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';\nimport { ActionViewItem, BaseActionViewItem, IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';\nimport { formatRule } from 'vs/base/browser/ui/codicons/codiconStyles';\nimport { AnchorAlignment, layout, LayoutAnchorPosition } from 'vs/base/browser/ui/contextview/contextview';\nimport { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';\nimport { EmptySubmenuAction, IAction, IActionRunner, Separator, SubmenuAction } from 'vs/base/common/actions';\nimport { RunOnceScheduler } from 'vs/base/common/async';\nimport { Codicon } from 'vs/base/common/codicons';\nimport { Color } from 'vs/base/common/color';\nimport { Event } from 'vs/base/common/event';\nimport { stripIcons } from 'vs/base/common/iconLabels';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { ResolvedKeybinding } from 'vs/base/common/keybindings';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\nimport { isLinux, isMacintosh } from 'vs/base/common/platform';\nimport { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';\nimport * as strings from 'vs/base/common/strings';\n\nexport const MENU_MNEMONIC_REGEX = /\\(&([^\\s&])\\)|(^|[^&])&([^\\s&])/;\nexport const MENU_ESCAPED_MNEMONIC_REGEX = /(&)?(&)([^\\s&])/g;\n\n\n\nexport enum Direction {\n\tRight,\n\tLeft\n}\n\nexport interface IMenuOptions {\n\tcontext?: unknown;\n\tactionViewItemProvider?: IActionViewItemProvider;\n\tactionRunner?: IActionRunner;\n\tgetKeyBinding?: (action: IAction) => ResolvedKeybinding | undefined;\n\tariaLabel?: string;\n\tenableMnemonics?: boolean;\n\tanchorAlignment?: AnchorAlignment;\n\texpandDirection?: Direction;\n\tuseEventAsContext?: boolean;\n\tsubmenuIds?: Set;\n}\n\nexport interface IMenuStyles {\n\tshadowColor?: Color;\n\tborderColor?: Color;\n\tforegroundColor?: Color;\n\tbackgroundColor?: Color;\n\tselectionForegroundColor?: Color;\n\tselectionBackgroundColor?: Color;\n\tselectionBorderColor?: Color;\n\tseparatorColor?: Color;\n\tscrollbarShadow?: Color;\n\tscrollbarSliderBackground?: Color;\n\tscrollbarSliderHoverBackground?: Color;\n\tscrollbarSliderActiveBackground?: Color;\n}\n\ninterface ISubMenuData {\n\tparent: Menu;\n\tsubmenu?: Menu;\n}\n\nexport class Menu extends ActionBar {\n\tprivate mnemonics: Map>;\n\tprivate readonly menuDisposables: DisposableStore;\n\tprivate scrollableElement: DomScrollableElement;\n\tprivate menuElement: HTMLElement;\n\tstatic globalStyleSheet: HTMLStyleElement;\n\tprotected styleSheet: HTMLStyleElement | undefined;\n\n\tconstructor(container: HTMLElement, actions: ReadonlyArray, options: IMenuOptions = {}) {\n\t\tcontainer.classList.add('monaco-menu-container');\n\t\tcontainer.setAttribute('role', 'presentation');\n\t\tconst menuElement = document.createElement('div');\n\t\tmenuElement.classList.add('monaco-menu');\n\t\tmenuElement.setAttribute('role', 'presentation');\n\n\t\tsuper(menuElement, {\n\t\t\torientation: ActionsOrientation.VERTICAL,\n\t\t\tactionViewItemProvider: action => this.doGetActionViewItem(action, options, parentData),\n\t\t\tcontext: options.context,\n\t\t\tactionRunner: options.actionRunner,\n\t\t\tariaLabel: options.ariaLabel,\n\t\t\tfocusOnlyEnabledItems: true,\n\t\t\ttriggerKeys: { keys: [KeyCode.Enter, ...(isMacintosh || isLinux ? [KeyCode.Space] : [])], keyDown: true }\n\t\t});\n\n\t\tthis.menuElement = menuElement;\n\n\t\tthis.actionsList.setAttribute('role', 'menu');\n\n\t\tthis.actionsList.tabIndex = 0;\n\n\t\tthis.menuDisposables = this._register(new DisposableStore());\n\n\t\tthis.initializeOrUpdateStyleSheet(container, {});\n\n\t\tthis._register(Gesture.addTarget(menuElement));\n\n\t\taddDisposableListener(menuElement, EventType.KEY_DOWN, (e) => {\n\t\t\tconst event = new StandardKeyboardEvent(e);\n\n\t\t\t// Stop tab navigation of menus\n\t\t\tif (event.equals(KeyCode.Tab)) {\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t});\n\n\t\tif (options.enableMnemonics) {\n\t\t\tthis.menuDisposables.add(addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => {\n\t\t\t\tconst key = e.key.toLocaleLowerCase();\n\t\t\t\tif (this.mnemonics.has(key)) {\n\t\t\t\t\tEventHelper.stop(e, true);\n\t\t\t\t\tconst actions = this.mnemonics.get(key)!;\n\n\t\t\t\t\tif (actions.length === 1) {\n\t\t\t\t\t\tif (actions[0] instanceof SubmenuMenuActionViewItem && actions[0].container) {\n\t\t\t\t\t\t\tthis.focusItemByElement(actions[0].container);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tactions[0].onClick(e);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (actions.length > 1) {\n\t\t\t\t\t\tconst action = actions.shift();\n\t\t\t\t\t\tif (action && action.container) {\n\t\t\t\t\t\t\tthis.focusItemByElement(action.container);\n\t\t\t\t\t\t\tactions.push(action);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis.mnemonics.set(key, actions);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\n\t\tif (isLinux) {\n\t\t\tthis._register(addDisposableListener(menuElement, EventType.KEY_DOWN, e => {\n\t\t\t\tconst event = new StandardKeyboardEvent(e);\n\n\t\t\t\tif (event.equals(KeyCode.Home) || event.equals(KeyCode.PageUp)) {\n\t\t\t\t\tthis.focusedItem = this.viewItems.length - 1;\n\t\t\t\t\tthis.focusNext();\n\t\t\t\t\tEventHelper.stop(e, true);\n\t\t\t\t} else if (event.equals(KeyCode.End) || event.equals(KeyCode.PageDown)) {\n\t\t\t\t\tthis.focusedItem = 0;\n\t\t\t\t\tthis.focusPrevious();\n\t\t\t\t\tEventHelper.stop(e, true);\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\n\t\tthis._register(addDisposableListener(this.domNode, EventType.MOUSE_OUT, e => {\n\t\t\tlet relatedTarget = e.relatedTarget as HTMLElement;\n\t\t\tif (!isAncestor(relatedTarget, this.domNode)) {\n\t\t\t\tthis.focusedItem = undefined;\n\t\t\t\tthis.updateFocus();\n\t\t\t\te.stopPropagation();\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(addDisposableListener(this.actionsList, EventType.MOUSE_OVER, e => {\n\t\t\tlet target = e.target as HTMLElement;\n\t\t\tif (!target || !isAncestor(target, this.actionsList) || target === this.actionsList) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twhile (target.parentElement !== this.actionsList && target.parentElement !== null) {\n\t\t\t\ttarget = target.parentElement;\n\t\t\t}\n\n\t\t\tif (target.classList.contains('action-item')) {\n\t\t\t\tconst lastFocusedItem = this.focusedItem;\n\t\t\t\tthis.setFocusedItem(target);\n\n\t\t\t\tif (lastFocusedItem !== this.focusedItem) {\n\t\t\t\t\tthis.updateFocus();\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\n\t\t// Support touch on actions list to focus items (needed for submenus)\n\t\tthis._register(Gesture.addTarget(this.actionsList));\n\t\tthis._register(addDisposableListener(this.actionsList, TouchEventType.Tap, e => {\n\t\t\tlet target = e.initialTarget as HTMLElement;\n\t\t\tif (!target || !isAncestor(target, this.actionsList) || target === this.actionsList) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twhile (target.parentElement !== this.actionsList && target.parentElement !== null) {\n\t\t\t\ttarget = target.parentElement;\n\t\t\t}\n\n\t\t\tif (target.classList.contains('action-item')) {\n\t\t\t\tconst lastFocusedItem = this.focusedItem;\n\t\t\t\tthis.setFocusedItem(target);\n\n\t\t\t\tif (lastFocusedItem !== this.focusedItem) {\n\t\t\t\t\tthis.updateFocus();\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\n\n\t\tlet parentData: ISubMenuData = {\n\t\t\tparent: this\n\t\t};\n\n\t\tthis.mnemonics = new Map>();\n\n\t\t// Scroll Logic\n\t\tthis.scrollableElement = this._register(new DomScrollableElement(menuElement, {\n\t\t\talwaysConsumeMouseWheel: true,\n\t\t\thorizontal: ScrollbarVisibility.Hidden,\n\t\t\tvertical: ScrollbarVisibility.Visible,\n\t\t\tverticalScrollbarSize: 7,\n\t\t\thandleMouseWheel: true,\n\t\t\tuseShadows: true\n\t\t}));\n\n\t\tconst scrollElement = this.scrollableElement.getDomNode();\n\t\tscrollElement.style.position = '';\n\n\t\t// Support scroll on menu drag\n\t\tthis._register(addDisposableListener(menuElement, TouchEventType.Change, e => {\n\t\t\tEventHelper.stop(e, true);\n\n\t\t\tconst scrollTop = this.scrollableElement.getScrollPosition().scrollTop;\n\t\t\tthis.scrollableElement.setScrollPosition({ scrollTop: scrollTop - e.translationY });\n\t\t}));\n\n\t\tthis._register(addDisposableListener(scrollElement, EventType.MOUSE_UP, e => {\n\t\t\t// Absorb clicks in menu dead space https://github.com/microsoft/vscode/issues/63575\n\t\t\t// We do this on the scroll element so the scroll bar doesn't dismiss the menu either\n\t\t\te.preventDefault();\n\t\t}));\n\n\t\tmenuElement.style.maxHeight = `${Math.max(10, window.innerHeight - container.getBoundingClientRect().top - 35)}px`;\n\n\t\tactions = actions.filter(a => {\n\t\t\tif (options.submenuIds?.has(a.id)) {\n\t\t\t\tconsole.warn(`Found submenu cycle: ${a.id}`);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t});\n\n\t\tthis.push(actions, { icon: true, label: true, isMenu: true });\n\n\t\tcontainer.appendChild(this.scrollableElement.getDomNode());\n\t\tthis.scrollableElement.scanDomNode();\n\n\t\tthis.viewItems.filter(item => !(item instanceof MenuSeparatorActionViewItem)).forEach((item, index, array) => {\n\t\t\t(item as BaseMenuActionViewItem).updatePositionInSet(index + 1, array.length);\n\t\t});\n\t}\n\n\tprivate initializeOrUpdateStyleSheet(container: HTMLElement, style: IMenuStyles): void {\n\t\tif (!this.styleSheet) {\n\t\t\tif (isInShadowDOM(container)) {\n\t\t\t\tthis.styleSheet = createStyleSheet(container);\n\t\t\t} else {\n\t\t\t\tif (!Menu.globalStyleSheet) {\n\t\t\t\t\tMenu.globalStyleSheet = createStyleSheet();\n\t\t\t\t}\n\t\t\t\tthis.styleSheet = Menu.globalStyleSheet;\n\t\t\t}\n\t\t}\n\t\tthis.styleSheet.textContent = getMenuWidgetCSS(style);\n\t}\n\n\tstyle(style: IMenuStyles): void {\n\t\tconst container = this.getContainer();\n\n\t\tthis.initializeOrUpdateStyleSheet(container, style);\n\n\t\tconst fgColor = style.foregroundColor ? `${style.foregroundColor}` : '';\n\t\tconst bgColor = style.backgroundColor ? `${style.backgroundColor}` : '';\n\t\tconst border = style.borderColor ? `1px solid ${style.borderColor}` : '';\n\t\tconst shadow = style.shadowColor ? `0 2px 4px ${style.shadowColor}` : '';\n\n\t\tcontainer.style.border = border;\n\t\tthis.domNode.style.color = fgColor;\n\t\tthis.domNode.style.backgroundColor = bgColor;\n\t\tcontainer.style.boxShadow = shadow;\n\n\t\tif (this.viewItems) {\n\t\t\tthis.viewItems.forEach(item => {\n\t\t\t\tif (item instanceof BaseMenuActionViewItem || item instanceof MenuSeparatorActionViewItem) {\n\t\t\t\t\titem.style(style);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\toverride getContainer(): HTMLElement {\n\t\treturn this.scrollableElement.getDomNode();\n\t}\n\n\tget onScroll(): Event {\n\t\treturn this.scrollableElement.onScroll;\n\t}\n\n\tprivate focusItemByElement(element: HTMLElement) {\n\t\tconst lastFocusedItem = this.focusedItem;\n\t\tthis.setFocusedItem(element);\n\n\t\tif (lastFocusedItem !== this.focusedItem) {\n\t\t\tthis.updateFocus();\n\t\t}\n\t}\n\n\tprivate setFocusedItem(element: HTMLElement): void {\n\t\tfor (let i = 0; i < this.actionsList.children.length; i++) {\n\t\t\tlet elem = this.actionsList.children[i];\n\t\t\tif (element === elem) {\n\t\t\t\tthis.focusedItem = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected override updateFocus(fromRight?: boolean): void {\n\t\tsuper.updateFocus(fromRight, true, true);\n\n\t\tif (typeof this.focusedItem !== 'undefined') {\n\t\t\t// Workaround for #80047 caused by an issue in chromium\n\t\t\t// https://bugs.chromium.org/p/chromium/issues/detail?id=414283\n\t\t\t// When that's fixed, just call this.scrollableElement.scanDomNode()\n\t\t\tthis.scrollableElement.setScrollPosition({\n\t\t\t\tscrollTop: Math.round(this.menuElement.scrollTop)\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate doGetActionViewItem(action: IAction, options: IMenuOptions, parentData: ISubMenuData): BaseActionViewItem {\n\t\tif (action instanceof Separator) {\n\t\t\treturn new MenuSeparatorActionViewItem(options.context, action, { icon: true });\n\t\t} else if (action instanceof SubmenuAction) {\n\t\t\tconst menuActionViewItem = new SubmenuMenuActionViewItem(action, action.actions, parentData, { ...options, submenuIds: new Set([...(options.submenuIds || []), action.id]) });\n\n\t\t\tif (options.enableMnemonics) {\n\t\t\t\tconst mnemonic = menuActionViewItem.getMnemonic();\n\t\t\t\tif (mnemonic && menuActionViewItem.isEnabled()) {\n\t\t\t\t\tlet actionViewItems: BaseMenuActionViewItem[] = [];\n\t\t\t\t\tif (this.mnemonics.has(mnemonic)) {\n\t\t\t\t\t\tactionViewItems = this.mnemonics.get(mnemonic)!;\n\t\t\t\t\t}\n\n\t\t\t\t\tactionViewItems.push(menuActionViewItem);\n\n\t\t\t\t\tthis.mnemonics.set(mnemonic, actionViewItems);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn menuActionViewItem;\n\t\t} else {\n\t\t\tconst menuItemOptions: IMenuItemOptions = { enableMnemonics: options.enableMnemonics, useEventAsContext: options.useEventAsContext };\n\t\t\tif (options.getKeyBinding) {\n\t\t\t\tconst keybinding = options.getKeyBinding(action);\n\t\t\t\tif (keybinding) {\n\t\t\t\t\tconst keybindingLabel = keybinding.getLabel();\n\n\t\t\t\t\tif (keybindingLabel) {\n\t\t\t\t\t\tmenuItemOptions.keybinding = keybindingLabel;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst menuActionViewItem = new BaseMenuActionViewItem(options.context, action, menuItemOptions);\n\n\t\t\tif (options.enableMnemonics) {\n\t\t\t\tconst mnemonic = menuActionViewItem.getMnemonic();\n\t\t\t\tif (mnemonic && menuActionViewItem.isEnabled()) {\n\t\t\t\t\tlet actionViewItems: BaseMenuActionViewItem[] = [];\n\t\t\t\t\tif (this.mnemonics.has(mnemonic)) {\n\t\t\t\t\t\tactionViewItems = this.mnemonics.get(mnemonic)!;\n\t\t\t\t\t}\n\n\t\t\t\t\tactionViewItems.push(menuActionViewItem);\n\n\t\t\t\t\tthis.mnemonics.set(mnemonic, actionViewItems);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn menuActionViewItem;\n\t\t}\n\t}\n}\n\ninterface IMenuItemOptions extends IActionViewItemOptions {\n\tenableMnemonics?: boolean;\n}\n\nclass BaseMenuActionViewItem extends BaseActionViewItem {\n\n\tpublic container: HTMLElement | undefined;\n\n\tprotected override options: IMenuItemOptions;\n\tprotected item: HTMLElement | undefined;\n\n\tprivate runOnceToEnableMouseUp: RunOnceScheduler;\n\tprivate label: HTMLElement | undefined;\n\tprivate check: HTMLElement | undefined;\n\tprivate mnemonic: string | undefined;\n\tprivate cssClass: string;\n\tprotected menuStyle: IMenuStyles | undefined;\n\n\tconstructor(ctx: unknown, action: IAction, options: IMenuItemOptions = {}) {\n\t\toptions.isMenu = true;\n\t\tsuper(action, action, options);\n\n\t\tthis.options = options;\n\t\tthis.options.icon = options.icon !== undefined ? options.icon : false;\n\t\tthis.options.label = options.label !== undefined ? options.label : true;\n\t\tthis.cssClass = '';\n\n\t\t// Set mnemonic\n\t\tif (this.options.label && options.enableMnemonics) {\n\t\t\tlet label = this.getAction().label;\n\t\t\tif (label) {\n\t\t\t\tlet matches = MENU_MNEMONIC_REGEX.exec(label);\n\t\t\t\tif (matches) {\n\t\t\t\t\tthis.mnemonic = (!!matches[1] ? matches[1] : matches[3]).toLocaleLowerCase();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add mouse up listener later to avoid accidental clicks\n\t\tthis.runOnceToEnableMouseUp = new RunOnceScheduler(() => {\n\t\t\tif (!this.element) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._register(addDisposableListener(this.element, EventType.MOUSE_UP, e => {\n\t\t\t\t// removed default prevention as it conflicts\n\t\t\t\t// with BaseActionViewItem #101537\n\t\t\t\t// add back if issues arise and link new issue\n\t\t\t\tEventHelper.stop(e, true);\n\n\t\t\t\t// See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Interact_with_the_clipboard\n\t\t\t\t// > Writing to the clipboard\n\t\t\t\t// > You can use the \"cut\" and \"copy\" commands without any special\n\t\t\t\t// permission if you are using them in a short-lived event handler\n\t\t\t\t// for a user action (for example, a click handler).\n\n\t\t\t\t// => to get the Copy and Paste context menu actions working on Firefox,\n\t\t\t\t// there should be no timeout here\n\t\t\t\tif (isFirefox) {\n\t\t\t\t\tconst mouseEvent = new StandardMouseEvent(e);\n\n\t\t\t\t\t// Allowing right click to trigger the event causes the issue described below,\n\t\t\t\t\t// but since the solution below does not work in FF, we must disable right click\n\t\t\t\t\tif (mouseEvent.rightButton) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.onClick(e);\n\t\t\t\t}\n\n\t\t\t\t// In all other cases, set timeout to allow context menu cancellation to trigger\n\t\t\t\t// otherwise the action will destroy the menu and a second context menu\n\t\t\t\t// will still trigger for right click.\n\t\t\t\telse {\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tthis.onClick(e);\n\t\t\t\t\t}, 0);\n\t\t\t\t}\n\t\t\t}));\n\n\t\t\tthis._register(addDisposableListener(this.element, EventType.CONTEXT_MENU, e => {\n\t\t\t\tEventHelper.stop(e, true);\n\t\t\t}));\n\t\t}, 100);\n\n\t\tthis._register(this.runOnceToEnableMouseUp);\n\t}\n\n\toverride render(container: HTMLElement): void {\n\t\tsuper.render(container);\n\n\t\tif (!this.element) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.container = container;\n\n\t\tthis.item = append(this.element, $('a.action-menu-item'));\n\t\tif (this._action.id === Separator.ID) {\n\t\t\t// A separator is a presentation item\n\t\t\tthis.item.setAttribute('role', 'presentation');\n\t\t} else {\n\t\t\tthis.item.setAttribute('role', 'menuitem');\n\t\t\tif (this.mnemonic) {\n\t\t\t\tthis.item.setAttribute('aria-keyshortcuts', `${this.mnemonic}`);\n\t\t\t}\n\t\t}\n\n\t\tthis.check = append(this.item, $('span.menu-item-check' + Codicon.menuSelection.cssSelector));\n\t\tthis.check.setAttribute('role', 'none');\n\n\t\tthis.label = append(this.item, $('span.action-label'));\n\n\t\tif (this.options.label && this.options.keybinding) {\n\t\t\tappend(this.item, $('span.keybinding')).textContent = this.options.keybinding;\n\t\t}\n\n\t\t// Adds mouse up listener to actually run the action\n\t\tthis.runOnceToEnableMouseUp.schedule();\n\n\t\tthis.updateClass();\n\t\tthis.updateLabel();\n\t\tthis.updateTooltip();\n\t\tthis.updateEnabled();\n\t\tthis.updateChecked();\n\t}\n\n\toverride blur(): void {\n\t\tsuper.blur();\n\t\tthis.applyStyle();\n\t}\n\n\toverride focus(): void {\n\t\tsuper.focus();\n\n\t\tif (this.item) {\n\t\t\tthis.item.focus();\n\t\t}\n\n\t\tthis.applyStyle();\n\t}\n\n\tupdatePositionInSet(pos: number, setSize: number): void {\n\t\tif (this.item) {\n\t\t\tthis.item.setAttribute('aria-posinset', `${pos}`);\n\t\t\tthis.item.setAttribute('aria-setsize', `${setSize}`);\n\t\t}\n\t}\n\n\toverride updateLabel(): void {\n\t\tif (!this.label) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.options.label) {\n\t\t\tclearNode(this.label);\n\n\t\t\tlet label = stripIcons(this.getAction().label);\n\t\t\tif (label) {\n\t\t\t\tconst cleanLabel = cleanMnemonic(label);\n\t\t\t\tif (!this.options.enableMnemonics) {\n\t\t\t\t\tlabel = cleanLabel;\n\t\t\t\t}\n\n\t\t\t\tthis.label.setAttribute('aria-label', cleanLabel.replace(/&&/g, '&'));\n\n\t\t\t\tconst matches = MENU_MNEMONIC_REGEX.exec(label);\n\n\t\t\t\tif (matches) {\n\t\t\t\t\tlabel = strings.escape(label);\n\n\t\t\t\t\t// This is global, reset it\n\t\t\t\t\tMENU_ESCAPED_MNEMONIC_REGEX.lastIndex = 0;\n\t\t\t\t\tlet escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(label);\n\n\t\t\t\t\t// We can't use negative lookbehind so if we match our negative and skip\n\t\t\t\t\twhile (escMatch && escMatch[1]) {\n\t\t\t\t\t\tescMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(label);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst replaceDoubleEscapes = (str: string) => str.replace(/&&/g, '&');\n\n\t\t\t\t\tif (escMatch) {\n\t\t\t\t\t\tthis.label.append(\n\t\t\t\t\t\t\tstrings.ltrim(replaceDoubleEscapes(label.substr(0, escMatch.index)), ' '),\n\t\t\t\t\t\t\t$('u', { 'aria-hidden': 'true' },\n\t\t\t\t\t\t\t\tescMatch[3]),\n\t\t\t\t\t\t\tstrings.rtrim(replaceDoubleEscapes(label.substr(escMatch.index + escMatch[0].length)), ' '));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.label.innerText = replaceDoubleEscapes(label).trim();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this.item) {\n\t\t\t\t\t\tthis.item.setAttribute('aria-keyshortcuts', (!!matches[1] ? matches[1] : matches[3]).toLocaleLowerCase());\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.label.innerText = label.replace(/&&/g, '&').trim();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\toverride updateTooltip(): void {\n\t\t// menus should function like native menus and they do not have tooltips\n\t}\n\n\toverride updateClass(): void {\n\t\tif (this.cssClass && this.item) {\n\t\t\tthis.item.classList.remove(...this.cssClass.split(' '));\n\t\t}\n\t\tif (this.options.icon && this.label) {\n\t\t\tthis.cssClass = this.getAction().class || '';\n\t\t\tthis.label.classList.add('icon');\n\t\t\tif (this.cssClass) {\n\t\t\t\tthis.label.classList.add(...this.cssClass.split(' '));\n\t\t\t}\n\t\t\tthis.updateEnabled();\n\t\t} else if (this.label) {\n\t\t\tthis.label.classList.remove('icon');\n\t\t}\n\t}\n\n\toverride updateEnabled(): void {\n\t\tif (this.getAction().enabled) {\n\t\t\tif (this.element) {\n\t\t\t\tthis.element.classList.remove('disabled');\n\t\t\t\tthis.element.removeAttribute('aria-disabled');\n\t\t\t}\n\n\t\t\tif (this.item) {\n\t\t\t\tthis.item.classList.remove('disabled');\n\t\t\t\tthis.item.removeAttribute('aria-disabled');\n\t\t\t\tthis.item.tabIndex = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tif (this.element) {\n\t\t\t\tthis.element.classList.add('disabled');\n\t\t\t\tthis.element.setAttribute('aria-disabled', 'true');\n\t\t\t}\n\n\t\t\tif (this.item) {\n\t\t\t\tthis.item.classList.add('disabled');\n\t\t\t\tthis.item.setAttribute('aria-disabled', 'true');\n\t\t\t}\n\t\t}\n\t}\n\n\toverride updateChecked(): void {\n\t\tif (!this.item) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst checked = this.getAction().checked;\n\t\tthis.item.classList.toggle('checked', !!checked);\n\t\tif (checked !== undefined) {\n\t\t\tthis.item.setAttribute('role', 'menuitemcheckbox');\n\t\t\tthis.item.setAttribute('aria-checked', checked ? 'true' : 'false');\n\t\t} else {\n\t\t\tthis.item.setAttribute('role', 'menuitem');\n\t\t\tthis.item.setAttribute('aria-checked', '');\n\t\t}\n\t}\n\n\tgetMnemonic(): string | undefined {\n\t\treturn this.mnemonic;\n\t}\n\n\tprotected applyStyle(): void {\n\t\tif (!this.menuStyle) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isSelected = this.element && this.element.classList.contains('focused');\n\t\tconst fgColor = isSelected && this.menuStyle.selectionForegroundColor ? this.menuStyle.selectionForegroundColor : this.menuStyle.foregroundColor;\n\t\tconst bgColor = isSelected && this.menuStyle.selectionBackgroundColor ? this.menuStyle.selectionBackgroundColor : undefined;\n\t\tconst border = isSelected && this.menuStyle.selectionBorderColor ? `thin solid ${this.menuStyle.selectionBorderColor}` : '';\n\n\t\tif (this.item) {\n\t\t\tthis.item.style.color = fgColor ? fgColor.toString() : '';\n\t\t\tthis.item.style.backgroundColor = bgColor ? bgColor.toString() : '';\n\t\t}\n\n\t\tif (this.check) {\n\t\t\tthis.check.style.color = fgColor ? fgColor.toString() : '';\n\t\t}\n\n\t\tif (this.container) {\n\t\t\tthis.container.style.border = border;\n\t\t}\n\t}\n\n\tstyle(style: IMenuStyles): void {\n\t\tthis.menuStyle = style;\n\t\tthis.applyStyle();\n\t}\n}\n\nclass SubmenuMenuActionViewItem extends BaseMenuActionViewItem {\n\tprivate mysubmenu: Menu | null = null;\n\tprivate submenuContainer: HTMLElement | undefined;\n\tprivate submenuIndicator: HTMLElement | undefined;\n\tprivate readonly submenuDisposables = this._register(new DisposableStore());\n\tprivate mouseOver: boolean = false;\n\tprivate showScheduler: RunOnceScheduler;\n\tprivate hideScheduler: RunOnceScheduler;\n\tprivate expandDirection: Direction;\n\n\tconstructor(\n\t\taction: IAction,\n\t\tprivate submenuActions: ReadonlyArray,\n\t\tprivate parentData: ISubMenuData,\n\t\tprivate submenuOptions?: IMenuOptions\n\t) {\n\t\tsuper(action, action, submenuOptions);\n\n\t\tthis.expandDirection = submenuOptions && submenuOptions.expandDirection !== undefined ? submenuOptions.expandDirection : Direction.Right;\n\n\t\tthis.showScheduler = new RunOnceScheduler(() => {\n\t\t\tif (this.mouseOver) {\n\t\t\t\tthis.cleanupExistingSubmenu(false);\n\t\t\t\tthis.createSubmenu(false);\n\t\t\t}\n\t\t}, 250);\n\n\t\tthis.hideScheduler = new RunOnceScheduler(() => {\n\t\t\tif (this.element && (!isAncestor(getActiveElement(), this.element) && this.parentData.submenu === this.mysubmenu)) {\n\t\t\t\tthis.parentData.parent.focus(false);\n\t\t\t\tthis.cleanupExistingSubmenu(true);\n\t\t\t}\n\t\t}, 750);\n\t}\n\n\toverride render(container: HTMLElement): void {\n\t\tsuper.render(container);\n\n\t\tif (!this.element) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.item) {\n\t\t\tthis.item.classList.add('monaco-submenu-item');\n\t\t\tthis.item.tabIndex = 0;\n\t\t\tthis.item.setAttribute('aria-haspopup', 'true');\n\t\t\tthis.updateAriaExpanded('false');\n\t\t\tthis.submenuIndicator = append(this.item, $('span.submenu-indicator' + Codicon.menuSubmenu.cssSelector));\n\t\t\tthis.submenuIndicator.setAttribute('aria-hidden', 'true');\n\t\t}\n\n\t\tthis._register(addDisposableListener(this.element, EventType.KEY_UP, e => {\n\t\t\tlet event = new StandardKeyboardEvent(e);\n\t\t\tif (event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Enter)) {\n\t\t\t\tEventHelper.stop(e, true);\n\n\t\t\t\tthis.createSubmenu(true);\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(addDisposableListener(this.element, EventType.KEY_DOWN, e => {\n\t\t\tlet event = new StandardKeyboardEvent(e);\n\n\t\t\tif (getActiveElement() === this.item) {\n\t\t\t\tif (event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Enter)) {\n\t\t\t\t\tEventHelper.stop(e, true);\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(addDisposableListener(this.element, EventType.MOUSE_OVER, e => {\n\t\t\tif (!this.mouseOver) {\n\t\t\t\tthis.mouseOver = true;\n\n\t\t\t\tthis.showScheduler.schedule();\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(addDisposableListener(this.element, EventType.MOUSE_LEAVE, e => {\n\t\t\tthis.mouseOver = false;\n\t\t}));\n\n\t\tthis._register(addDisposableListener(this.element, EventType.FOCUS_OUT, e => {\n\t\t\tif (this.element && !isAncestor(getActiveElement(), this.element)) {\n\t\t\t\tthis.hideScheduler.schedule();\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(this.parentData.parent.onScroll(() => {\n\t\t\tthis.parentData.parent.focus(false);\n\t\t\tthis.cleanupExistingSubmenu(false);\n\t\t}));\n\t}\n\n\toverride updateEnabled(): void {\n\t\t// override on submenu entry\n\t\t// native menus do not observe enablement on sumbenus\n\t\t// we mimic that behavior\n\t}\n\n\toverride onClick(e: EventLike): void {\n\t\t// stop clicking from trying to run an action\n\t\tEventHelper.stop(e, true);\n\n\t\tthis.cleanupExistingSubmenu(false);\n\t\tthis.createSubmenu(true);\n\t}\n\n\tprivate cleanupExistingSubmenu(force: boolean): void {\n\t\tif (this.parentData.submenu && (force || (this.parentData.submenu !== this.mysubmenu))) {\n\n\t\t\t// disposal may throw if the submenu has already been removed\n\t\t\ttry {\n\t\t\t\tthis.parentData.submenu.dispose();\n\t\t\t} catch { }\n\n\t\t\tthis.parentData.submenu = undefined;\n\t\t\tthis.updateAriaExpanded('false');\n\t\t\tif (this.submenuContainer) {\n\t\t\t\tthis.submenuDisposables.clear();\n\t\t\t\tthis.submenuContainer = undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate calculateSubmenuMenuLayout(windowDimensions: Dimension, submenu: Dimension, entry: IDomNodePagePosition, expandDirection: Direction): { top: number, left: number } {\n\t\tconst ret = { top: 0, left: 0 };\n\n\t\t// Start with horizontal\n\t\tret.left = layout(windowDimensions.width, submenu.width, { position: expandDirection === Direction.Right ? LayoutAnchorPosition.Before : LayoutAnchorPosition.After, offset: entry.left, size: entry.width });\n\n\t\t// We don't have enough room to layout the menu fully, so we are overlapping the menu\n\t\tif (ret.left >= entry.left && ret.left < entry.left + entry.width) {\n\t\t\tif (entry.left + 10 + submenu.width <= windowDimensions.width) {\n\t\t\t\tret.left = entry.left + 10;\n\t\t\t}\n\n\t\t\tentry.top += 10;\n\t\t\tentry.height = 0;\n\t\t}\n\n\t\t// Now that we have a horizontal position, try layout vertically\n\t\tret.top = layout(windowDimensions.height, submenu.height, { position: LayoutAnchorPosition.Before, offset: entry.top, size: 0 });\n\n\t\t// We didn't have enough room below, but we did above, so we shift down to align the menu\n\t\tif (ret.top + submenu.height === entry.top && ret.top + entry.height + submenu.height <= windowDimensions.height) {\n\t\t\tret.top += entry.height;\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tprivate createSubmenu(selectFirstItem = true): void {\n\t\tif (!this.element) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.parentData.submenu) {\n\t\t\tthis.updateAriaExpanded('true');\n\t\t\tthis.submenuContainer = append(this.element, $('div.monaco-submenu'));\n\t\t\tthis.submenuContainer.classList.add('menubar-menu-items-holder', 'context-view');\n\n\t\t\t// Set the top value of the menu container before construction\n\t\t\t// This allows the menu constructor to calculate the proper max height\n\t\t\tconst computedStyles = getComputedStyle(this.parentData.parent.domNode);\n\t\t\tconst paddingTop = parseFloat(computedStyles.paddingTop || '0') || 0;\n\t\t\t// this.submenuContainer.style.top = `${this.element.offsetTop - this.parentData.parent.scrollOffset - paddingTop}px`;\n\t\t\tthis.submenuContainer.style.zIndex = '1';\n\t\t\tthis.submenuContainer.style.position = 'fixed';\n\t\t\tthis.submenuContainer.style.top = '0';\n\t\t\tthis.submenuContainer.style.left = '0';\n\n\t\t\tthis.parentData.submenu = new Menu(this.submenuContainer, this.submenuActions.length ? this.submenuActions : [new EmptySubmenuAction()], this.submenuOptions);\n\t\t\tif (this.menuStyle) {\n\t\t\t\tthis.parentData.submenu.style(this.menuStyle);\n\t\t\t}\n\n\t\t\t// layout submenu\n\t\t\tconst entryBox = this.element.getBoundingClientRect();\n\t\t\tconst entryBoxUpdated = {\n\t\t\t\ttop: entryBox.top - paddingTop,\n\t\t\t\tleft: entryBox.left,\n\t\t\t\theight: entryBox.height + 2 * paddingTop,\n\t\t\t\twidth: entryBox.width\n\t\t\t};\n\n\t\t\tconst viewBox = this.submenuContainer.getBoundingClientRect();\n\n\t\t\tconst { top, left } = this.calculateSubmenuMenuLayout(new Dimension(window.innerWidth, window.innerHeight), Dimension.lift(viewBox), entryBoxUpdated, this.expandDirection);\n\t\t\t// subtract offsets caused by transform parent\n\t\t\tthis.submenuContainer.style.left = `${left - viewBox.left}px`;\n\t\t\tthis.submenuContainer.style.top = `${top - viewBox.top}px`;\n\n\t\t\tthis.submenuDisposables.add(addDisposableListener(this.submenuContainer, EventType.KEY_UP, e => {\n\t\t\t\tlet event = new StandardKeyboardEvent(e);\n\t\t\t\tif (event.equals(KeyCode.LeftArrow)) {\n\t\t\t\t\tEventHelper.stop(e, true);\n\n\t\t\t\t\tthis.parentData.parent.focus();\n\n\t\t\t\t\tthis.cleanupExistingSubmenu(true);\n\t\t\t\t}\n\t\t\t}));\n\n\t\t\tthis.submenuDisposables.add(addDisposableListener(this.submenuContainer, EventType.KEY_DOWN, e => {\n\t\t\t\tlet event = new StandardKeyboardEvent(e);\n\t\t\t\tif (event.equals(KeyCode.LeftArrow)) {\n\t\t\t\t\tEventHelper.stop(e, true);\n\t\t\t\t}\n\t\t\t}));\n\n\n\t\t\tthis.submenuDisposables.add(this.parentData.submenu.onDidCancel(() => {\n\t\t\t\tthis.parentData.parent.focus();\n\n\t\t\t\tthis.cleanupExistingSubmenu(true);\n\t\t\t}));\n\n\t\t\tthis.parentData.submenu.focus(selectFirstItem);\n\n\t\t\tthis.mysubmenu = this.parentData.submenu;\n\t\t} else {\n\t\t\tthis.parentData.submenu.focus(false);\n\t\t}\n\t}\n\n\tprivate updateAriaExpanded(value: string): void {\n\t\tif (this.item) {\n\t\t\tthis.item?.setAttribute('aria-expanded', value);\n\t\t}\n\t}\n\n\tprotected override applyStyle(): void {\n\t\tsuper.applyStyle();\n\n\t\tif (!this.menuStyle) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isSelected = this.element && this.element.classList.contains('focused');\n\t\tconst fgColor = isSelected && this.menuStyle.selectionForegroundColor ? this.menuStyle.selectionForegroundColor : this.menuStyle.foregroundColor;\n\n\t\tif (this.submenuIndicator) {\n\t\t\tthis.submenuIndicator.style.color = fgColor ? `${fgColor}` : '';\n\t\t}\n\n\t\tif (this.parentData.submenu) {\n\t\t\tthis.parentData.submenu.style(this.menuStyle);\n\t\t}\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\n\t\tthis.hideScheduler.dispose();\n\n\t\tif (this.mysubmenu) {\n\t\t\tthis.mysubmenu.dispose();\n\t\t\tthis.mysubmenu = null;\n\t\t}\n\n\t\tif (this.submenuContainer) {\n\t\t\tthis.submenuContainer = undefined;\n\t\t}\n\t}\n}\n\nclass MenuSeparatorActionViewItem extends ActionViewItem {\n\tstyle(style: IMenuStyles): void {\n\t\tif (this.label) {\n\t\t\tthis.label.style.borderBottomColor = style.separatorColor ? `${style.separatorColor}` : '';\n\t\t}\n\t}\n}\n\nexport function cleanMnemonic(label: string): string {\n\tconst regex = MENU_MNEMONIC_REGEX;\n\n\tconst matches = regex.exec(label);\n\tif (!matches) {\n\t\treturn label;\n\t}\n\n\tconst mnemonicInText = !matches[1];\n\n\treturn label.replace(regex, mnemonicInText ? '$2$3' : '').trim();\n}\n\nfunction getMenuWidgetCSS(style: IMenuStyles): string {\n\tlet result = /* css */`\n.monaco-menu {\n\tfont-size: 13px;\n\n}\n\n${formatRule(Codicon.menuSelection)}\n${formatRule(Codicon.menuSubmenu)}\n\n.monaco-menu .monaco-action-bar {\n\ttext-align: right;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n\n.monaco-menu .monaco-action-bar .actions-container {\n\tdisplay: flex;\n\tmargin: 0 auto;\n\tpadding: 0;\n\twidth: 100%;\n\tjustify-content: flex-end;\n}\n\n.monaco-menu .monaco-action-bar.vertical .actions-container {\n\tdisplay: inline-block;\n}\n\n.monaco-menu .monaco-action-bar.reverse .actions-container {\n\tflex-direction: row-reverse;\n}\n\n.monaco-menu .monaco-action-bar .action-item {\n\tcursor: pointer;\n\tdisplay: inline-block;\n\ttransition: transform 50ms ease;\n\tposition: relative; /* DO NOT REMOVE - this is the key to preventing the ghosting icon bug in Chrome 42 */\n}\n\n.monaco-menu .monaco-action-bar .action-item.disabled {\n\tcursor: default;\n}\n\n.monaco-menu .monaco-action-bar.animated .action-item.active {\n\ttransform: scale(1.272019649, 1.272019649); /* 1.272019649 = √φ */\n}\n\n.monaco-menu .monaco-action-bar .action-item .icon,\n.monaco-menu .monaco-action-bar .action-item .codicon {\n\tdisplay: inline-block;\n}\n\n.monaco-menu .monaco-action-bar .action-item .codicon {\n\tdisplay: flex;\n\talign-items: center;\n}\n\n.monaco-menu .monaco-action-bar .action-label {\n\tfont-size: 11px;\n\tmargin-right: 4px;\n}\n\n.monaco-menu .monaco-action-bar .action-item.disabled .action-label,\n.monaco-menu .monaco-action-bar .action-item.disabled .action-label:hover {\n\topacity: 0.4;\n}\n\n/* Vertical actions */\n\n.monaco-menu .monaco-action-bar.vertical {\n\ttext-align: left;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-item {\n\tdisplay: block;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-label.separator {\n\tdisplay: block;\n\tborder-bottom: 1px solid #bbb;\n\tpadding-top: 1px;\n\tmargin-left: .8em;\n\tmargin-right: .8em;\n}\n\n.monaco-menu .secondary-actions .monaco-action-bar .action-label {\n\tmargin-left: 6px;\n}\n\n/* Action Items */\n.monaco-menu .monaco-action-bar .action-item.select-container {\n\toverflow: hidden; /* somehow the dropdown overflows its container, we prevent it here to not push */\n\tflex: 1;\n\tmax-width: 170px;\n\tmin-width: 60px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tmargin-right: 10px;\n}\n\n.monaco-menu .monaco-action-bar.vertical {\n\tmargin-left: 0;\n\toverflow: visible;\n}\n\n.monaco-menu .monaco-action-bar.vertical .actions-container {\n\tdisplay: block;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-item {\n\tpadding: 0;\n\ttransform: none;\n\tdisplay: flex;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-item.active {\n\ttransform: none;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-menu-item {\n\tflex: 1 1 auto;\n\tdisplay: flex;\n\theight: 2em;\n\talign-items: center;\n\tposition: relative;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-label {\n\tflex: 1 1 auto;\n\ttext-decoration: none;\n\tpadding: 0 1em;\n\tbackground: none;\n\tfont-size: 12px;\n\tline-height: 1;\n}\n\n.monaco-menu .monaco-action-bar.vertical .keybinding,\n.monaco-menu .monaco-action-bar.vertical .submenu-indicator {\n\tdisplay: inline-block;\n\tflex: 2 1 auto;\n\tpadding: 0 1em;\n\ttext-align: right;\n\tfont-size: 12px;\n\tline-height: 1;\n}\n\n.monaco-menu .monaco-action-bar.vertical .submenu-indicator {\n\theight: 100%;\n}\n\n.monaco-menu .monaco-action-bar.vertical .submenu-indicator.codicon {\n\tfont-size: 16px !important;\n\tdisplay: flex;\n\talign-items: center;\n}\n\n.monaco-menu .monaco-action-bar.vertical .submenu-indicator.codicon::before {\n\tmargin-left: auto;\n\tmargin-right: -20px;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-item.disabled .keybinding,\n.monaco-menu .monaco-action-bar.vertical .action-item.disabled .submenu-indicator {\n\topacity: 0.4;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-label:not(.separator) {\n\tdisplay: inline-block;\n\tbox-sizing: border-box;\n\tmargin: 0;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-item {\n\tposition: static;\n\toverflow: visible;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-item .monaco-submenu {\n\tposition: absolute;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-label.separator {\n\tpadding: 0.5em 0 0 0;\n\tmargin-bottom: 0.5em;\n\twidth: 100%;\n\theight: 0px !important;\n\tmargin-left: .8em !important;\n\tmargin-right: .8em !important;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-label.separator.text {\n\tpadding: 0.7em 1em 0.1em 1em;\n\tfont-weight: bold;\n\topacity: 1;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-label:hover {\n\tcolor: inherit;\n}\n\n.monaco-menu .monaco-action-bar.vertical .menu-item-check {\n\tposition: absolute;\n\tvisibility: hidden;\n\twidth: 1em;\n\theight: 100%;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-menu-item.checked .menu-item-check {\n\tvisibility: visible;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n/* Context Menu */\n\n.context-view.monaco-menu-container {\n\toutline: 0;\n\tborder: none;\n\tanimation: fadeIn 0.083s linear;\n\t-webkit-app-region: no-drag;\n}\n\n.context-view.monaco-menu-container :focus,\n.context-view.monaco-menu-container .monaco-action-bar.vertical:focus,\n.context-view.monaco-menu-container .monaco-action-bar.vertical :focus {\n\toutline: 0;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-item {\n\tborder: thin solid transparent; /* prevents jumping behaviour on hover or focus */\n}\n\n\n/* High Contrast Theming */\n:host-context(.hc-black) .context-view.monaco-menu-container {\n\tbox-shadow: none;\n}\n\n:host-context(.hc-black) .monaco-menu .monaco-action-bar.vertical .action-item.focused {\n\tbackground: none;\n}\n\n/* Vertical Action Bar Styles */\n\n.monaco-menu .monaco-action-bar.vertical {\n\tpadding: .5em 0;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-menu-item {\n\theight: 1.8em;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-label:not(.separator),\n.monaco-menu .monaco-action-bar.vertical .keybinding {\n\tfont-size: inherit;\n\tpadding: 0 2em;\n}\n\n.monaco-menu .monaco-action-bar.vertical .menu-item-check {\n\tfont-size: inherit;\n\twidth: 2em;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-label.separator {\n\tfont-size: inherit;\n\tpadding: 0.2em 0 0 0;\n\tmargin-bottom: 0.2em;\n}\n\n:host-context(.linux) .monaco-menu .monaco-action-bar.vertical .action-label.separator {\n\tmargin-left: 0;\n\tmargin-right: 0;\n}\n\n.monaco-menu .monaco-action-bar.vertical .submenu-indicator {\n\tfont-size: 60%;\n\tpadding: 0 1.8em;\n}\n\n:host-context(.linux) .monaco-menu .monaco-action-bar.vertical .submenu-indicator {\n\theight: 100%;\n\tmask-size: 10px 10px;\n\t-webkit-mask-size: 10px 10px;\n}\n\n.monaco-menu .action-item {\n\tcursor: default;\n}\n\n/* Arrows */\n.monaco-scrollable-element > .scrollbar > .scra {\n\tcursor: pointer;\n\tfont-size: 11px !important;\n}\n\n.monaco-scrollable-element > .visible {\n\topacity: 1;\n\n\t/* Background rule added for IE9 - to allow clicks on dom node */\n\tbackground:rgba(0,0,0,0);\n\n\ttransition: opacity 100ms linear;\n}\n.monaco-scrollable-element > .invisible {\n\topacity: 0;\n\tpointer-events: none;\n}\n.monaco-scrollable-element > .invisible.fade {\n\ttransition: opacity 800ms linear;\n}\n\n/* Scrollable Content Inset Shadow */\n.monaco-scrollable-element > .shadow {\n\tposition: absolute;\n\tdisplay: none;\n}\n.monaco-scrollable-element > .shadow.top {\n\tdisplay: block;\n\ttop: 0;\n\tleft: 3px;\n\theight: 3px;\n\twidth: 100%;\n}\n.monaco-scrollable-element > .shadow.left {\n\tdisplay: block;\n\ttop: 3px;\n\tleft: 0;\n\theight: 100%;\n\twidth: 3px;\n}\n.monaco-scrollable-element > .shadow.top-left-corner {\n\tdisplay: block;\n\ttop: 0;\n\tleft: 0;\n\theight: 3px;\n\twidth: 3px;\n}\n`;\n\n\t// Scrollbars\n\tconst scrollbarShadowColor = style.scrollbarShadow;\n\tif (scrollbarShadowColor) {\n\t\tresult += `\n\t\t\t.monaco-scrollable-element > .shadow.top {\n\t\t\t\tbox-shadow: ${scrollbarShadowColor} 0 6px 6px -6px inset;\n\t\t\t}\n\n\t\t\t.monaco-scrollable-element > .shadow.left {\n\t\t\t\tbox-shadow: ${scrollbarShadowColor} 6px 0 6px -6px inset;\n\t\t\t}\n\n\t\t\t.monaco-scrollable-element > .shadow.top.left {\n\t\t\t\tbox-shadow: ${scrollbarShadowColor} 6px 6px 6px -6px inset;\n\t\t\t}\n\t\t`;\n\t}\n\n\tconst scrollbarSliderBackgroundColor = style.scrollbarSliderBackground;\n\tif (scrollbarSliderBackgroundColor) {\n\t\tresult += `\n\t\t\t.monaco-scrollable-element > .scrollbar > .slider {\n\t\t\t\tbackground: ${scrollbarSliderBackgroundColor};\n\t\t\t}\n\t\t`;\n\t}\n\n\tconst scrollbarSliderHoverBackgroundColor = style.scrollbarSliderHoverBackground;\n\tif (scrollbarSliderHoverBackgroundColor) {\n\t\tresult += `\n\t\t\t.monaco-scrollable-element > .scrollbar > .slider:hover {\n\t\t\t\tbackground: ${scrollbarSliderHoverBackgroundColor};\n\t\t\t}\n\t\t`;\n\t}\n\n\tconst scrollbarSliderActiveBackgroundColor = style.scrollbarSliderActiveBackground;\n\tif (scrollbarSliderActiveBackgroundColor) {\n\t\tresult += `\n\t\t\t.monaco-scrollable-element > .scrollbar > .slider.active {\n\t\t\t\tbackground: ${scrollbarSliderActiveBackgroundColor};\n\t\t\t}\n\t\t`;\n\t}\n\n\treturn result;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { StandardMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { IInputBoxStyles, InputBox, IRange, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport Severity from 'vs/base/common/severity';\nimport 'vs/css!./media/quickInput';\n\nconst $ = dom.$;\n\nexport class QuickInputBox extends Disposable {\n\n\tprivate container: HTMLElement;\n\tprivate inputBox: InputBox;\n\n\tconstructor(\n\t\tprivate parent: HTMLElement\n\t) {\n\t\tsuper();\n\t\tthis.container = dom.append(this.parent, $('.quick-input-box'));\n\t\tthis.inputBox = this._register(new InputBox(this.container, undefined));\n\t}\n\n\tonKeyDown = (handler: (event: StandardKeyboardEvent) => void): IDisposable => {\n\t\treturn dom.addDisposableListener(this.inputBox.inputElement, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {\n\t\t\thandler(new StandardKeyboardEvent(e));\n\t\t});\n\t};\n\n\tonMouseDown = (handler: (event: StandardMouseEvent) => void): IDisposable => {\n\t\treturn dom.addDisposableListener(this.inputBox.inputElement, dom.EventType.MOUSE_DOWN, (e: MouseEvent) => {\n\t\t\thandler(new StandardMouseEvent(e));\n\t\t});\n\t};\n\n\tonDidChange = (handler: (event: string) => void): IDisposable => {\n\t\treturn this.inputBox.onDidChange(handler);\n\t};\n\n\tget value() {\n\t\treturn this.inputBox.value;\n\t}\n\n\tset value(value: string) {\n\t\tthis.inputBox.value = value;\n\t}\n\n\tselect(range: IRange | null = null): void {\n\t\tthis.inputBox.select(range);\n\t}\n\n\tisSelectionAtEnd(): boolean {\n\t\treturn this.inputBox.isSelectionAtEnd();\n\t}\n\n\tget placeholder() {\n\t\treturn this.inputBox.inputElement.getAttribute('placeholder') || '';\n\t}\n\n\tset placeholder(placeholder: string) {\n\t\tthis.inputBox.setPlaceHolder(placeholder);\n\t}\n\n\tget ariaLabel() {\n\t\treturn this.inputBox.getAriaLabel();\n\t}\n\n\tset ariaLabel(ariaLabel: string) {\n\t\tthis.inputBox.setAriaLabel(ariaLabel);\n\t}\n\n\tget password() {\n\t\treturn this.inputBox.inputElement.type === 'password';\n\t}\n\n\tset password(password: boolean) {\n\t\tthis.inputBox.inputElement.type = password ? 'password' : 'text';\n\t}\n\n\tsetAttribute(name: string, value: string): void {\n\t\tthis.inputBox.inputElement.setAttribute(name, value);\n\t}\n\n\tremoveAttribute(name: string): void {\n\t\tthis.inputBox.inputElement.removeAttribute(name);\n\t}\n\n\tshowDecoration(decoration: Severity): void {\n\t\tif (decoration === Severity.Ignore) {\n\t\t\tthis.inputBox.hideMessage();\n\t\t} else {\n\t\t\tthis.inputBox.showMessage({ type: decoration === Severity.Info ? MessageType.INFO : decoration === Severity.Warning ? MessageType.WARNING : MessageType.ERROR, content: '' });\n\t\t}\n\t}\n\n\tstylesForType(decoration: Severity) {\n\t\treturn this.inputBox.stylesForType(decoration === Severity.Info ? MessageType.INFO : decoration === Severity.Warning ? MessageType.WARNING : MessageType.ERROR);\n\t}\n\n\tsetFocus(): void {\n\t\tthis.inputBox.focus();\n\t}\n\n\tlayout(): void {\n\t\tthis.inputBox.layout();\n\t}\n\n\tstyle(styles: IInputBoxStyles): void {\n\t\tthis.inputBox.style(styles);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as arrays from 'vs/base/common/arrays';\nimport * as types from 'vs/base/common/types';\nimport * as nls from 'vs/nls';\n\nfunction exceptionToErrorMessage(exception: any, verbose: boolean): string {\n\tif (verbose && (exception.stack || exception.stacktrace)) {\n\t\treturn nls.localize('stackTrace.format', \"{0}: {1}\", detectSystemErrorMessage(exception), stackToString(exception.stack) || stackToString(exception.stacktrace));\n\t}\n\n\treturn detectSystemErrorMessage(exception);\n}\n\nfunction stackToString(stack: string[] | string | undefined): string | undefined {\n\tif (Array.isArray(stack)) {\n\t\treturn stack.join('\\n');\n\t}\n\n\treturn stack;\n}\n\nfunction detectSystemErrorMessage(exception: any): string {\n\n\t// See https://nodejs.org/api/errors.html#errors_class_system_error\n\tif (typeof exception.code === 'string' && typeof exception.errno === 'number' && typeof exception.syscall === 'string') {\n\t\treturn nls.localize('nodeExceptionMessage', \"A system error occurred ({0})\", exception.message);\n\t}\n\n\treturn exception.message || nls.localize('error.defaultMessage', \"An unknown error occurred. Please consult the log for more details.\");\n}\n\n/**\n * Tries to generate a human readable error message out of the error. If the verbose parameter\n * is set to true, the error message will include stacktrace details if provided.\n *\n * @returns A string containing the error message.\n */\nexport function toErrorMessage(error: any = null, verbose: boolean = false): string {\n\tif (!error) {\n\t\treturn nls.localize('error.defaultMessage', \"An unknown error occurred. Please consult the log for more details.\");\n\t}\n\n\tif (Array.isArray(error)) {\n\t\tconst errors: any[] = arrays.coalesce(error);\n\t\tconst msg = toErrorMessage(errors[0], verbose);\n\n\t\tif (errors.length > 1) {\n\t\t\treturn nls.localize('error.moreErrors', \"{0} ({1} errors in total)\", msg, errors.length);\n\t\t}\n\n\t\treturn msg;\n\t}\n\n\tif (types.isString(error)) {\n\t\treturn error;\n\t}\n\n\tif (error.detail) {\n\t\tconst detail = error.detail;\n\n\t\tif (detail.error) {\n\t\t\treturn exceptionToErrorMessage(detail.error, verbose);\n\t\t}\n\n\t\tif (detail.exception) {\n\t\t\treturn exceptionToErrorMessage(detail.exception, verbose);\n\t\t}\n\t}\n\n\tif (error.stack) {\n\t\treturn exceptionToErrorMessage(error, verbose);\n\t}\n\n\tif (error.message) {\n\t\treturn error.message;\n\t}\n\n\treturn nls.localize('error.defaultMessage', \"An unknown error occurred. Please consult the log for more details.\");\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Modifiers } from 'vs/base/common/keybindings';\nimport { OperatingSystem } from 'vs/base/common/platform';\nimport * as nls from 'vs/nls';\n\nexport interface ModifierLabels {\n\treadonly ctrlKey: string;\n\treadonly shiftKey: string;\n\treadonly altKey: string;\n\treadonly metaKey: string;\n\treadonly separator: string;\n}\n\nexport interface KeyLabelProvider {\n\t(keybinding: T): string | null;\n}\n\nexport class ModifierLabelProvider {\n\n\tpublic readonly modifierLabels: ModifierLabels[];\n\n\tconstructor(mac: ModifierLabels, windows: ModifierLabels, linux: ModifierLabels = windows) {\n\t\tthis.modifierLabels = [null!]; // index 0 will never me accessed.\n\t\tthis.modifierLabels[OperatingSystem.Macintosh] = mac;\n\t\tthis.modifierLabels[OperatingSystem.Windows] = windows;\n\t\tthis.modifierLabels[OperatingSystem.Linux] = linux;\n\t}\n\n\tpublic toLabel(OS: OperatingSystem, parts: T[], keyLabelProvider: KeyLabelProvider): string | null {\n\t\tif (parts.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst result: string[] = [];\n\t\tfor (let i = 0, len = parts.length; i < len; i++) {\n\t\t\tconst part = parts[i];\n\t\t\tconst keyLabel = keyLabelProvider(part);\n\t\t\tif (keyLabel === null) {\n\t\t\t\t// this keybinding cannot be expressed...\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tresult[i] = _simpleAsString(part, keyLabel, this.modifierLabels[OS]);\n\t\t}\n\t\treturn result.join(' ');\n\t}\n}\n\n/**\n * A label provider that prints modifiers in a suitable format for displaying in the UI.\n */\nexport const UILabelProvider = new ModifierLabelProvider(\n\t{\n\t\tctrlKey: '\\u2303',\n\t\tshiftKey: '⇧',\n\t\taltKey: '⌥',\n\t\tmetaKey: '⌘',\n\t\tseparator: '',\n\t},\n\t{\n\t\tctrlKey: nls.localize({ key: 'ctrlKey', comment: ['This is the short form for the Control key on the keyboard'] }, \"Ctrl\"),\n\t\tshiftKey: nls.localize({ key: 'shiftKey', comment: ['This is the short form for the Shift key on the keyboard'] }, \"Shift\"),\n\t\taltKey: nls.localize({ key: 'altKey', comment: ['This is the short form for the Alt key on the keyboard'] }, \"Alt\"),\n\t\tmetaKey: nls.localize({ key: 'windowsKey', comment: ['This is the short form for the Windows key on the keyboard'] }, \"Windows\"),\n\t\tseparator: '+',\n\t},\n\t{\n\t\tctrlKey: nls.localize({ key: 'ctrlKey', comment: ['This is the short form for the Control key on the keyboard'] }, \"Ctrl\"),\n\t\tshiftKey: nls.localize({ key: 'shiftKey', comment: ['This is the short form for the Shift key on the keyboard'] }, \"Shift\"),\n\t\taltKey: nls.localize({ key: 'altKey', comment: ['This is the short form for the Alt key on the keyboard'] }, \"Alt\"),\n\t\tmetaKey: nls.localize({ key: 'superKey', comment: ['This is the short form for the Super key on the keyboard'] }, \"Super\"),\n\t\tseparator: '+',\n\t}\n);\n\n/**\n * A label provider that prints modifiers in a suitable format for ARIA.\n */\nexport const AriaLabelProvider = new ModifierLabelProvider(\n\t{\n\t\tctrlKey: nls.localize({ key: 'ctrlKey.long', comment: ['This is the long form for the Control key on the keyboard'] }, \"Control\"),\n\t\tshiftKey: nls.localize({ key: 'shiftKey.long', comment: ['This is the long form for the Shift key on the keyboard'] }, \"Shift\"),\n\t\taltKey: nls.localize({ key: 'optKey.long', comment: ['This is the long form for the Alt/Option key on the keyboard'] }, \"Option\"),\n\t\tmetaKey: nls.localize({ key: 'cmdKey.long', comment: ['This is the long form for the Command key on the keyboard'] }, \"Command\"),\n\t\tseparator: '+',\n\t},\n\t{\n\t\tctrlKey: nls.localize({ key: 'ctrlKey.long', comment: ['This is the long form for the Control key on the keyboard'] }, \"Control\"),\n\t\tshiftKey: nls.localize({ key: 'shiftKey.long', comment: ['This is the long form for the Shift key on the keyboard'] }, \"Shift\"),\n\t\taltKey: nls.localize({ key: 'altKey.long', comment: ['This is the long form for the Alt key on the keyboard'] }, \"Alt\"),\n\t\tmetaKey: nls.localize({ key: 'windowsKey.long', comment: ['This is the long form for the Windows key on the keyboard'] }, \"Windows\"),\n\t\tseparator: '+',\n\t},\n\t{\n\t\tctrlKey: nls.localize({ key: 'ctrlKey.long', comment: ['This is the long form for the Control key on the keyboard'] }, \"Control\"),\n\t\tshiftKey: nls.localize({ key: 'shiftKey.long', comment: ['This is the long form for the Shift key on the keyboard'] }, \"Shift\"),\n\t\taltKey: nls.localize({ key: 'altKey.long', comment: ['This is the long form for the Alt key on the keyboard'] }, \"Alt\"),\n\t\tmetaKey: nls.localize({ key: 'superKey.long', comment: ['This is the long form for the Super key on the keyboard'] }, \"Super\"),\n\t\tseparator: '+',\n\t}\n);\n\n/**\n * A label provider that prints modifiers in a suitable format for Electron Accelerators.\n * See https://github.com/electron/electron/blob/master/docs/api/accelerator.md\n */\nexport const ElectronAcceleratorLabelProvider = new ModifierLabelProvider(\n\t{\n\t\tctrlKey: 'Ctrl',\n\t\tshiftKey: 'Shift',\n\t\taltKey: 'Alt',\n\t\tmetaKey: 'Cmd',\n\t\tseparator: '+',\n\t},\n\t{\n\t\tctrlKey: 'Ctrl',\n\t\tshiftKey: 'Shift',\n\t\taltKey: 'Alt',\n\t\tmetaKey: 'Super',\n\t\tseparator: '+',\n\t}\n);\n\n/**\n * A label provider that prints modifiers in a suitable format for user settings.\n */\nexport const UserSettingsLabelProvider = new ModifierLabelProvider(\n\t{\n\t\tctrlKey: 'ctrl',\n\t\tshiftKey: 'shift',\n\t\taltKey: 'alt',\n\t\tmetaKey: 'cmd',\n\t\tseparator: '+',\n\t},\n\t{\n\t\tctrlKey: 'ctrl',\n\t\tshiftKey: 'shift',\n\t\taltKey: 'alt',\n\t\tmetaKey: 'win',\n\t\tseparator: '+',\n\t},\n\t{\n\t\tctrlKey: 'ctrl',\n\t\tshiftKey: 'shift',\n\t\taltKey: 'alt',\n\t\tmetaKey: 'meta',\n\t\tseparator: '+',\n\t}\n);\n\nfunction _simpleAsString(modifiers: Modifiers, key: string, labels: ModifierLabels): string {\n\tif (key === null) {\n\t\treturn '';\n\t}\n\n\tconst result: string[] = [];\n\n\t// translate modifier keys: Ctrl-Shift-Alt-Meta\n\tif (modifiers.ctrlKey) {\n\t\tresult.push(labels.ctrlKey);\n\t}\n\n\tif (modifiers.shiftKey) {\n\t\tresult.push(labels.shiftKey);\n\t}\n\n\tif (modifiers.altKey) {\n\t\tresult.push(labels.altKey);\n\t}\n\n\tif (modifiers.metaKey) {\n\t\tresult.push(labels.metaKey);\n\t}\n\n\t// the actual key\n\tif (key !== '') {\n\t\tresult.push(key);\n\t}\n\n\treturn result.join(labels.separator);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { Color } from 'vs/base/common/color';\nimport { UILabelProvider } from 'vs/base/common/keybindingLabels';\nimport { ResolvedKeybinding, ResolvedKeybindingPart } from 'vs/base/common/keybindings';\nimport { equals } from 'vs/base/common/objects';\nimport { OperatingSystem } from 'vs/base/common/platform';\nimport { IThemable } from 'vs/base/common/styler';\nimport 'vs/css!./keybindingLabel';\nimport { localize } from 'vs/nls';\n\nconst $ = dom.$;\n\nexport interface PartMatches {\n\tctrlKey?: boolean;\n\tshiftKey?: boolean;\n\taltKey?: boolean;\n\tmetaKey?: boolean;\n\tkeyCode?: boolean;\n}\n\nexport interface Matches {\n\tfirstPart: PartMatches;\n\tchordPart: PartMatches;\n}\n\nexport interface KeybindingLabelOptions extends IKeybindingLabelStyles {\n\trenderUnboundKeybindings?: boolean;\n}\n\nexport interface IKeybindingLabelStyles {\n\tkeybindingLabelBackground?: Color;\n\tkeybindingLabelForeground?: Color;\n\tkeybindingLabelBorder?: Color;\n\tkeybindingLabelBottomBorder?: Color;\n\tkeybindingLabelShadow?: Color;\n}\n\nexport class KeybindingLabel implements IThemable {\n\n\tprivate domNode: HTMLElement;\n\tprivate options: KeybindingLabelOptions;\n\n\tprivate readonly keyElements = new Set();\n\n\tprivate keybinding: ResolvedKeybinding | undefined;\n\tprivate matches: Matches | undefined;\n\tprivate didEverRender: boolean;\n\n\tprivate labelBackground: Color | undefined;\n\tprivate labelForeground: Color | undefined;\n\tprivate labelBorder: Color | undefined;\n\tprivate labelBottomBorder: Color | undefined;\n\tprivate labelShadow: Color | undefined;\n\n\tconstructor(container: HTMLElement, private os: OperatingSystem, options?: KeybindingLabelOptions) {\n\t\tthis.options = options || Object.create(null);\n\n\t\tthis.labelBackground = this.options.keybindingLabelBackground;\n\t\tthis.labelForeground = this.options.keybindingLabelForeground;\n\t\tthis.labelBorder = this.options.keybindingLabelBorder;\n\t\tthis.labelBottomBorder = this.options.keybindingLabelBottomBorder;\n\t\tthis.labelShadow = this.options.keybindingLabelShadow;\n\n\t\tthis.domNode = dom.append(container, $('.monaco-keybinding'));\n\t\tthis.didEverRender = false;\n\t\tcontainer.appendChild(this.domNode);\n\t}\n\n\tget element(): HTMLElement {\n\t\treturn this.domNode;\n\t}\n\n\tset(keybinding: ResolvedKeybinding | undefined, matches?: Matches) {\n\t\tif (this.didEverRender && this.keybinding === keybinding && KeybindingLabel.areSame(this.matches, matches)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.keybinding = keybinding;\n\t\tthis.matches = matches;\n\t\tthis.render();\n\t}\n\n\tprivate render() {\n\t\tthis.clear();\n\n\t\tif (this.keybinding) {\n\t\t\tlet [firstPart, chordPart] = this.keybinding.getParts();\n\t\t\tif (firstPart) {\n\t\t\t\tthis.renderPart(this.domNode, firstPart, this.matches ? this.matches.firstPart : null);\n\t\t\t}\n\t\t\tif (chordPart) {\n\t\t\t\tdom.append(this.domNode, $('span.monaco-keybinding-key-chord-separator', undefined, ' '));\n\t\t\t\tthis.renderPart(this.domNode, chordPart, this.matches ? this.matches.chordPart : null);\n\t\t\t}\n\t\t\tthis.domNode.title = this.keybinding.getAriaLabel() || '';\n\t\t} else if (this.options && this.options.renderUnboundKeybindings) {\n\t\t\tthis.renderUnbound(this.domNode);\n\t\t}\n\n\t\tthis.applyStyles();\n\n\t\tthis.didEverRender = true;\n\t}\n\n\tprivate clear(): void {\n\t\tdom.clearNode(this.domNode);\n\t\tthis.keyElements.clear();\n\t}\n\n\tprivate renderPart(parent: HTMLElement, part: ResolvedKeybindingPart, match: PartMatches | null) {\n\t\tconst modifierLabels = UILabelProvider.modifierLabels[this.os];\n\t\tif (part.ctrlKey) {\n\t\t\tthis.renderKey(parent, modifierLabels.ctrlKey, Boolean(match?.ctrlKey), modifierLabels.separator);\n\t\t}\n\t\tif (part.shiftKey) {\n\t\t\tthis.renderKey(parent, modifierLabels.shiftKey, Boolean(match?.shiftKey), modifierLabels.separator);\n\t\t}\n\t\tif (part.altKey) {\n\t\t\tthis.renderKey(parent, modifierLabels.altKey, Boolean(match?.altKey), modifierLabels.separator);\n\t\t}\n\t\tif (part.metaKey) {\n\t\t\tthis.renderKey(parent, modifierLabels.metaKey, Boolean(match?.metaKey), modifierLabels.separator);\n\t\t}\n\t\tconst keyLabel = part.keyLabel;\n\t\tif (keyLabel) {\n\t\t\tthis.renderKey(parent, keyLabel, Boolean(match?.keyCode), '');\n\t\t}\n\t}\n\n\tprivate renderKey(parent: HTMLElement, label: string, highlight: boolean, separator: string): void {\n\t\tdom.append(parent, this.createKeyElement(label, highlight ? '.highlight' : ''));\n\t\tif (separator) {\n\t\t\tdom.append(parent, $('span.monaco-keybinding-key-separator', undefined, separator));\n\t\t}\n\t}\n\n\tprivate renderUnbound(parent: HTMLElement): void {\n\t\tdom.append(parent, this.createKeyElement(localize('unbound', \"Unbound\")));\n\t}\n\n\tprivate createKeyElement(label: string, extraClass = ''): HTMLElement {\n\t\tconst keyElement = $('span.monaco-keybinding-key' + extraClass, undefined, label);\n\t\tthis.keyElements.add(keyElement);\n\n\t\treturn keyElement;\n\t}\n\n\tstyle(styles: IKeybindingLabelStyles): void {\n\t\tthis.labelBackground = styles.keybindingLabelBackground;\n\t\tthis.labelForeground = styles.keybindingLabelForeground;\n\t\tthis.labelBorder = styles.keybindingLabelBorder;\n\t\tthis.labelBottomBorder = styles.keybindingLabelBottomBorder;\n\t\tthis.labelShadow = styles.keybindingLabelShadow;\n\n\t\tthis.applyStyles();\n\t}\n\n\tprivate applyStyles() {\n\t\tif (this.element) {\n\t\t\tfor (const keyElement of this.keyElements) {\n\t\t\t\tif (this.labelBackground) {\n\t\t\t\t\tkeyElement.style.backgroundColor = this.labelBackground?.toString();\n\t\t\t\t}\n\t\t\t\tif (this.labelBorder) {\n\t\t\t\t\tkeyElement.style.borderColor = this.labelBorder.toString();\n\t\t\t\t}\n\t\t\t\tif (this.labelBottomBorder) {\n\t\t\t\t\tkeyElement.style.borderBottomColor = this.labelBottomBorder.toString();\n\t\t\t\t}\n\t\t\t\tif (this.labelShadow) {\n\t\t\t\t\tkeyElement.style.boxShadow = `inset 0 -1px 0 ${this.labelShadow}`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.labelForeground) {\n\t\t\t\tthis.element.style.color = this.labelForeground.toString();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static areSame(a: Matches | undefined, b: Matches | undefined): boolean {\n\t\tif (a === b || (!a && !b)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn !!a && !!b && equals(a.firstPart, b.firstPart) && equals(a.chordPart, b.chordPart);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';\nimport { IconLabel, IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel';\nimport { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel';\nimport { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';\nimport { IListAccessibilityProvider, IListOptions, IListStyles, List } from 'vs/base/browser/ui/list/listWidget';\nimport { Action } from 'vs/base/common/actions';\nimport { range } from 'vs/base/common/arrays';\nimport { getCodiconAriaLabel } from 'vs/base/common/codicons';\nimport { compareAnything } from 'vs/base/common/comparers';\nimport { memoize } from 'vs/base/common/decorators';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { IMatch } from 'vs/base/common/filters';\nimport { matchesFuzzyIconAware, parseLabelWithIcons } from 'vs/base/common/iconLabels';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { dispose, IDisposable } from 'vs/base/common/lifecycle';\nimport * as platform from 'vs/base/common/platform';\nimport { withNullAsUndefined } from 'vs/base/common/types';\nimport { IQuickInputOptions } from 'vs/base/parts/quickinput/browser/quickInput';\nimport { getIconClass } from 'vs/base/parts/quickinput/browser/quickInputUtils';\nimport { IQuickPickItem, IQuickPickItemButtonEvent, IQuickPickSeparator } from 'vs/base/parts/quickinput/common/quickInput';\nimport 'vs/css!./media/quickInput';\nimport { localize } from 'vs/nls';\n\nconst $ = dom.$;\n\ninterface IListElement {\n\treadonly index: number;\n\treadonly item: IQuickPickItem;\n\treadonly saneLabel: string;\n\treadonly saneMeta?: string;\n\treadonly saneAriaLabel: string;\n\treadonly saneDescription?: string;\n\treadonly saneDetail?: string;\n\treadonly labelHighlights?: IMatch[];\n\treadonly descriptionHighlights?: IMatch[];\n\treadonly detailHighlights?: IMatch[];\n\treadonly checked: boolean;\n\treadonly separator?: IQuickPickSeparator;\n\treadonly fireButtonTriggered: (event: IQuickPickItemButtonEvent) => void;\n}\n\nclass ListElement implements IListElement, IDisposable {\n\tindex!: number;\n\titem!: IQuickPickItem;\n\tsaneLabel!: string;\n\tsaneMeta!: string;\n\tsaneAriaLabel!: string;\n\tsaneDescription?: string;\n\tsaneDetail?: string;\n\thidden = false;\n\tprivate readonly _onChecked = new Emitter();\n\tonChecked = this._onChecked.event;\n\t_checked?: boolean;\n\tget checked() {\n\t\treturn !!this._checked;\n\t}\n\tset checked(value: boolean) {\n\t\tif (value !== this._checked) {\n\t\t\tthis._checked = value;\n\t\t\tthis._onChecked.fire(value);\n\t\t}\n\t}\n\tseparator?: IQuickPickSeparator;\n\tlabelHighlights?: IMatch[];\n\tdescriptionHighlights?: IMatch[];\n\tdetailHighlights?: IMatch[];\n\tfireButtonTriggered!: (event: IQuickPickItemButtonEvent) => void;\n\n\tconstructor(init: IListElement) {\n\t\tObject.assign(this, init);\n\t}\n\n\tdispose() {\n\t\tthis._onChecked.dispose();\n\t}\n}\n\ninterface IListElementTemplateData {\n\tentry: HTMLDivElement;\n\tcheckbox: HTMLInputElement;\n\tlabel: IconLabel;\n\tkeybinding: KeybindingLabel;\n\tdetail: IconLabel;\n\tseparator: HTMLDivElement;\n\tactionBar: ActionBar;\n\telement: ListElement;\n\ttoDisposeElement: IDisposable[];\n\ttoDisposeTemplate: IDisposable[];\n}\n\nclass ListElementRenderer implements IListRenderer {\n\n\tstatic readonly ID = 'listelement';\n\n\tget templateId() {\n\t\treturn ListElementRenderer.ID;\n\t}\n\n\trenderTemplate(container: HTMLElement): IListElementTemplateData {\n\t\tconst data: IListElementTemplateData = Object.create(null);\n\t\tdata.toDisposeElement = [];\n\t\tdata.toDisposeTemplate = [];\n\n\t\tdata.entry = dom.append(container, $('.quick-input-list-entry'));\n\n\t\t// Checkbox\n\t\tconst label = dom.append(data.entry, $('label.quick-input-list-label'));\n\t\tdata.toDisposeTemplate.push(dom.addStandardDisposableListener(label, dom.EventType.CLICK, e => {\n\t\t\tif (!data.checkbox.offsetParent) { // If checkbox not visible:\n\t\t\t\te.preventDefault(); // Prevent toggle of checkbox when it is immediately shown afterwards. #91740\n\t\t\t}\n\t\t}));\n\t\tdata.checkbox = dom.append(label, $('input.quick-input-list-checkbox'));\n\t\tdata.checkbox.type = 'checkbox';\n\t\tdata.toDisposeTemplate.push(dom.addStandardDisposableListener(data.checkbox, dom.EventType.CHANGE, e => {\n\t\t\tdata.element.checked = data.checkbox.checked;\n\t\t}));\n\n\t\t// Rows\n\t\tconst rows = dom.append(label, $('.quick-input-list-rows'));\n\t\tconst row1 = dom.append(rows, $('.quick-input-list-row'));\n\t\tconst row2 = dom.append(rows, $('.quick-input-list-row'));\n\n\t\t// Label\n\t\tdata.label = new IconLabel(row1, { supportHighlights: true, supportDescriptionHighlights: true, supportIcons: true });\n\n\t\t// Keybinding\n\t\tconst keybindingContainer = dom.append(row1, $('.quick-input-list-entry-keybinding'));\n\t\tdata.keybinding = new KeybindingLabel(keybindingContainer, platform.OS);\n\n\t\t// Detail\n\t\tconst detailContainer = dom.append(row2, $('.quick-input-list-label-meta'));\n\t\tdata.detail = new IconLabel(detailContainer, { supportHighlights: true, supportIcons: true });\n\n\t\t// Separator\n\t\tdata.separator = dom.append(data.entry, $('.quick-input-list-separator'));\n\n\t\t// Actions\n\t\tdata.actionBar = new ActionBar(data.entry);\n\t\tdata.actionBar.domNode.classList.add('quick-input-list-entry-action-bar');\n\t\tdata.toDisposeTemplate.push(data.actionBar);\n\n\t\treturn data;\n\t}\n\n\trenderElement(element: ListElement, index: number, data: IListElementTemplateData): void {\n\t\tdata.toDisposeElement = dispose(data.toDisposeElement);\n\t\tdata.element = element;\n\t\tdata.checkbox.checked = element.checked;\n\t\tdata.toDisposeElement.push(element.onChecked(checked => data.checkbox.checked = checked));\n\n\t\tconst { labelHighlights, descriptionHighlights, detailHighlights } = element;\n\n\t\t// Label\n\t\tconst options: IIconLabelValueOptions = Object.create(null);\n\t\toptions.matches = labelHighlights || [];\n\t\toptions.descriptionTitle = element.saneDescription;\n\t\toptions.descriptionMatches = descriptionHighlights || [];\n\t\toptions.extraClasses = element.item.iconClasses;\n\t\toptions.italic = element.item.italic;\n\t\toptions.strikethrough = element.item.strikethrough;\n\t\tdata.label.setLabel(element.saneLabel, element.saneDescription, options);\n\n\t\t// Keybinding\n\t\tdata.keybinding.set(element.item.keybinding);\n\n\t\t// Meta\n\t\tif (element.saneDetail) {\n\t\t\tdata.detail.setLabel(element.saneDetail, undefined, {\n\t\t\t\tmatches: detailHighlights,\n\t\t\t\ttitle: element.saneDetail\n\t\t\t});\n\t\t}\n\n\t\t// Separator\n\t\tif (element.separator && element.separator.label) {\n\t\t\tdata.separator.textContent = element.separator.label;\n\t\t\tdata.separator.style.display = '';\n\t\t} else {\n\t\t\tdata.separator.style.display = 'none';\n\t\t}\n\t\tdata.entry.classList.toggle('quick-input-list-separator-border', !!element.separator);\n\n\t\t// Actions\n\t\tdata.actionBar.clear();\n\t\tconst buttons = element.item.buttons;\n\t\tif (buttons && buttons.length) {\n\t\t\tdata.actionBar.push(buttons.map((button, index) => {\n\t\t\t\tlet cssClasses = button.iconClass || (button.iconPath ? getIconClass(button.iconPath) : undefined);\n\t\t\t\tif (button.alwaysVisible) {\n\t\t\t\t\tcssClasses = cssClasses ? `${cssClasses} always-visible` : 'always-visible';\n\t\t\t\t}\n\t\t\t\tconst action = new Action(`id-${index}`, '', cssClasses, true, async () => {\n\t\t\t\t\telement.fireButtonTriggered({\n\t\t\t\t\t\tbutton,\n\t\t\t\t\t\titem: element.item\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\taction.tooltip = button.tooltip || '';\n\t\t\t\treturn action;\n\t\t\t}), { icon: true, label: false });\n\t\t\tdata.entry.classList.add('has-actions');\n\t\t} else {\n\t\t\tdata.entry.classList.remove('has-actions');\n\t\t}\n\t}\n\n\tdisposeElement(element: ListElement, index: number, data: IListElementTemplateData): void {\n\t\tdata.toDisposeElement = dispose(data.toDisposeElement);\n\t}\n\n\tdisposeTemplate(data: IListElementTemplateData): void {\n\t\tdata.toDisposeElement = dispose(data.toDisposeElement);\n\t\tdata.toDisposeTemplate = dispose(data.toDisposeTemplate);\n\t}\n}\n\nclass ListElementDelegate implements IListVirtualDelegate {\n\n\tgetHeight(element: ListElement): number {\n\t\treturn element.saneDetail ? 44 : 22;\n\t}\n\n\tgetTemplateId(element: ListElement): string {\n\t\treturn ListElementRenderer.ID;\n\t}\n}\n\nexport enum QuickInputListFocus {\n\tFirst = 1,\n\tSecond,\n\tLast,\n\tNext,\n\tPrevious,\n\tNextPage,\n\tPreviousPage\n}\n\nexport class QuickInputList {\n\n\treadonly id: string;\n\tprivate container: HTMLElement;\n\tprivate list: List;\n\tprivate inputElements: Array = [];\n\tprivate elements: ListElement[] = [];\n\tprivate elementsToIndexes = new Map();\n\tmatchOnDescription = false;\n\tmatchOnDetail = false;\n\tmatchOnLabel = true;\n\tmatchOnMeta = true;\n\tsortByLabel = true;\n\tprivate readonly _onChangedAllVisibleChecked = new Emitter();\n\tonChangedAllVisibleChecked: Event = this._onChangedAllVisibleChecked.event;\n\tprivate readonly _onChangedCheckedCount = new Emitter();\n\tonChangedCheckedCount: Event = this._onChangedCheckedCount.event;\n\tprivate readonly _onChangedVisibleCount = new Emitter();\n\tonChangedVisibleCount: Event = this._onChangedVisibleCount.event;\n\tprivate readonly _onChangedCheckedElements = new Emitter();\n\tonChangedCheckedElements: Event = this._onChangedCheckedElements.event;\n\tprivate readonly _onButtonTriggered = new Emitter>();\n\tonButtonTriggered = this._onButtonTriggered.event;\n\tprivate readonly _onKeyDown = new Emitter();\n\tonKeyDown: Event = this._onKeyDown.event;\n\tprivate readonly _onLeave = new Emitter();\n\tonLeave: Event = this._onLeave.event;\n\tprivate _fireCheckedEvents = true;\n\tprivate elementDisposables: IDisposable[] = [];\n\tprivate disposables: IDisposable[] = [];\n\n\tconstructor(\n\t\tprivate parent: HTMLElement,\n\t\tid: string,\n\t\toptions: IQuickInputOptions,\n\t) {\n\t\tthis.id = id;\n\t\tthis.container = dom.append(this.parent, $('.quick-input-list'));\n\t\tconst delegate = new ListElementDelegate();\n\t\tconst accessibilityProvider = new QuickInputAccessibilityProvider();\n\t\tthis.list = options.createList('QuickInput', this.container, delegate, [new ListElementRenderer()], {\n\t\t\tidentityProvider: { getId: element => element.saneLabel },\n\t\t\tsetRowLineHeight: false,\n\t\t\tmultipleSelectionSupport: false,\n\t\t\thorizontalScrolling: false,\n\t\t\taccessibilityProvider\n\t\t} as IListOptions);\n\t\tthis.list.getHTMLElement().id = id;\n\t\tthis.disposables.push(this.list);\n\t\tthis.disposables.push(this.list.onKeyDown(e => {\n\t\t\tconst event = new StandardKeyboardEvent(e);\n\t\t\tswitch (event.keyCode) {\n\t\t\t\tcase KeyCode.Space:\n\t\t\t\t\tthis.toggleCheckbox();\n\t\t\t\t\tbreak;\n\t\t\t\tcase KeyCode.KeyA:\n\t\t\t\t\tif (platform.isMacintosh ? e.metaKey : e.ctrlKey) {\n\t\t\t\t\t\tthis.list.setFocus(range(this.list.length));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase KeyCode.UpArrow: {\n\t\t\t\t\tconst focus1 = this.list.getFocus();\n\t\t\t\t\tif (focus1.length === 1 && focus1[0] === 0) {\n\t\t\t\t\t\tthis._onLeave.fire();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase KeyCode.DownArrow: {\n\t\t\t\t\tconst focus2 = this.list.getFocus();\n\t\t\t\t\tif (focus2.length === 1 && focus2[0] === this.list.length - 1) {\n\t\t\t\t\t\tthis._onLeave.fire();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._onKeyDown.fire(event);\n\t\t}));\n\t\tthis.disposables.push(this.list.onMouseDown(e => {\n\t\t\tif (e.browserEvent.button !== 2) {\n\t\t\t\t// Works around / fixes #64350.\n\t\t\t\te.browserEvent.preventDefault();\n\t\t\t}\n\t\t}));\n\t\tthis.disposables.push(dom.addDisposableListener(this.container, dom.EventType.CLICK, e => {\n\t\t\tif (e.x || e.y) { // Avoid 'click' triggered by 'space' on checkbox.\n\t\t\t\tthis._onLeave.fire();\n\t\t\t}\n\t\t}));\n\t\tthis.disposables.push(this.list.onMouseMiddleClick(e => {\n\t\t\tthis._onLeave.fire();\n\t\t}));\n\t\tthis.disposables.push(this.list.onContextMenu(e => {\n\t\t\tif (typeof e.index === 'number') {\n\t\t\t\te.browserEvent.preventDefault();\n\n\t\t\t\t// we want to treat a context menu event as\n\t\t\t\t// a gesture to open the item at the index\n\t\t\t\t// since we do not have any context menu\n\t\t\t\t// this enables for example macOS to Ctrl-\n\t\t\t\t// click on an item to open it.\n\t\t\t\tthis.list.setSelection([e.index]);\n\t\t\t}\n\t\t}));\n\t\tthis.disposables.push(\n\t\t\tthis._onChangedAllVisibleChecked,\n\t\t\tthis._onChangedCheckedCount,\n\t\t\tthis._onChangedVisibleCount,\n\t\t\tthis._onChangedCheckedElements,\n\t\t\tthis._onButtonTriggered,\n\t\t\tthis._onLeave,\n\t\t\tthis._onKeyDown\n\t\t);\n\t}\n\n\t@memoize\n\tget onDidChangeFocus() {\n\t\treturn Event.map(this.list.onDidChangeFocus, e => e.elements.map(e => e.item));\n\t}\n\n\t@memoize\n\tget onDidChangeSelection() {\n\t\treturn Event.map(this.list.onDidChangeSelection, e => ({ items: e.elements.map(e => e.item), event: e.browserEvent }));\n\t}\n\n\tget scrollTop() {\n\t\treturn this.list.scrollTop;\n\t}\n\n\tset scrollTop(scrollTop: number) {\n\t\tthis.list.scrollTop = scrollTop;\n\t}\n\n\tgetAllVisibleChecked() {\n\t\treturn this.allVisibleChecked(this.elements, false);\n\t}\n\n\tprivate allVisibleChecked(elements: ListElement[], whenNoneVisible = true) {\n\t\tfor (let i = 0, n = elements.length; i < n; i++) {\n\t\t\tconst element = elements[i];\n\t\t\tif (!element.hidden) {\n\t\t\t\tif (!element.checked) {\n\t\t\t\t\treturn false;\n\t\t\t\t} else {\n\t\t\t\t\twhenNoneVisible = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn whenNoneVisible;\n\t}\n\n\tgetCheckedCount() {\n\t\tlet count = 0;\n\t\tconst elements = this.elements;\n\t\tfor (let i = 0, n = elements.length; i < n; i++) {\n\t\t\tif (elements[i].checked) {\n\t\t\t\tcount++;\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n\n\tgetVisibleCount() {\n\t\tlet count = 0;\n\t\tconst elements = this.elements;\n\t\tfor (let i = 0, n = elements.length; i < n; i++) {\n\t\t\tif (!elements[i].hidden) {\n\t\t\t\tcount++;\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n\n\tsetAllVisibleChecked(checked: boolean) {\n\t\ttry {\n\t\t\tthis._fireCheckedEvents = false;\n\t\t\tthis.elements.forEach(element => {\n\t\t\t\tif (!element.hidden) {\n\t\t\t\t\telement.checked = checked;\n\t\t\t\t}\n\t\t\t});\n\t\t} finally {\n\t\t\tthis._fireCheckedEvents = true;\n\t\t\tthis.fireCheckedEvents();\n\t\t}\n\t}\n\n\tsetElements(inputElements: Array): void {\n\t\tthis.elementDisposables = dispose(this.elementDisposables);\n\t\tconst fireButtonTriggered = (event: IQuickPickItemButtonEvent) => this.fireButtonTriggered(event);\n\t\tthis.inputElements = inputElements;\n\t\tthis.elements = inputElements.reduce((result, item, index) => {\n\t\t\tif (item.type !== 'separator') {\n\t\t\t\tconst previous = index && inputElements[index - 1];\n\t\t\t\tconst saneLabel = item.label && item.label.replace(/\\r?\\n/g, ' ');\n\t\t\t\tconst saneMeta = item.meta && item.meta.replace(/\\r?\\n/g, ' ');\n\t\t\t\tconst saneDescription = item.description && item.description.replace(/\\r?\\n/g, ' ');\n\t\t\t\tconst saneDetail = item.detail && item.detail.replace(/\\r?\\n/g, ' ');\n\t\t\t\tconst saneAriaLabel = item.ariaLabel || [saneLabel, saneDescription, saneDetail]\n\t\t\t\t\t.map(s => getCodiconAriaLabel(s))\n\t\t\t\t\t.filter(s => !!s)\n\t\t\t\t\t.join(', ');\n\n\t\t\t\tresult.push(new ListElement({\n\t\t\t\t\tindex,\n\t\t\t\t\titem,\n\t\t\t\t\tsaneLabel,\n\t\t\t\t\tsaneMeta,\n\t\t\t\t\tsaneAriaLabel,\n\t\t\t\t\tsaneDescription,\n\t\t\t\t\tsaneDetail,\n\t\t\t\t\tlabelHighlights: item.highlights?.label,\n\t\t\t\t\tdescriptionHighlights: item.highlights?.description,\n\t\t\t\t\tdetailHighlights: item.highlights?.detail,\n\t\t\t\t\tchecked: false,\n\t\t\t\t\tseparator: previous && previous.type === 'separator' ? previous : undefined,\n\t\t\t\t\tfireButtonTriggered\n\t\t\t\t}));\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as ListElement[]);\n\t\tthis.elementDisposables.push(...this.elements);\n\t\tthis.elementDisposables.push(...this.elements.map(element => element.onChecked(() => this.fireCheckedEvents())));\n\n\t\tthis.elementsToIndexes = this.elements.reduce((map, element, index) => {\n\t\t\tmap.set(element.item, index);\n\t\t\treturn map;\n\t\t}, new Map());\n\t\tthis.list.splice(0, this.list.length); // Clear focus and selection first, sending the events when the list is empty.\n\t\tthis.list.splice(0, this.list.length, this.elements);\n\t\tthis._onChangedVisibleCount.fire(this.elements.length);\n\t}\n\n\tgetFocusedElements() {\n\t\treturn this.list.getFocusedElements()\n\t\t\t.map(e => e.item);\n\t}\n\n\tsetFocusedElements(items: IQuickPickItem[]) {\n\t\tthis.list.setFocus(items\n\t\t\t.filter(item => this.elementsToIndexes.has(item))\n\t\t\t.map(item => this.elementsToIndexes.get(item)!));\n\t\tif (items.length > 0) {\n\t\t\tconst focused = this.list.getFocus()[0];\n\t\t\tif (typeof focused === 'number') {\n\t\t\t\tthis.list.reveal(focused);\n\t\t\t}\n\t\t}\n\t}\n\n\tgetActiveDescendant() {\n\t\treturn this.list.getHTMLElement().getAttribute('aria-activedescendant');\n\t}\n\n\tsetSelectedElements(items: IQuickPickItem[]) {\n\t\tthis.list.setSelection(items\n\t\t\t.filter(item => this.elementsToIndexes.has(item))\n\t\t\t.map(item => this.elementsToIndexes.get(item)!));\n\t}\n\n\tgetCheckedElements() {\n\t\treturn this.elements.filter(e => e.checked)\n\t\t\t.map(e => e.item);\n\t}\n\n\tsetCheckedElements(items: IQuickPickItem[]) {\n\t\ttry {\n\t\t\tthis._fireCheckedEvents = false;\n\t\t\tconst checked = new Set();\n\t\t\tfor (const item of items) {\n\t\t\t\tchecked.add(item);\n\t\t\t}\n\t\t\tfor (const element of this.elements) {\n\t\t\t\telement.checked = checked.has(element.item);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis._fireCheckedEvents = true;\n\t\t\tthis.fireCheckedEvents();\n\t\t}\n\t}\n\n\tset enabled(value: boolean) {\n\t\tthis.list.getHTMLElement().style.pointerEvents = value ? '' : 'none';\n\t}\n\n\tfocus(what: QuickInputListFocus): void {\n\t\tif (!this.list.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (what === QuickInputListFocus.Next && this.list.getFocus()[0] === this.list.length - 1) {\n\t\t\twhat = QuickInputListFocus.First;\n\t\t}\n\n\t\tif (what === QuickInputListFocus.Previous && this.list.getFocus()[0] === 0) {\n\t\t\twhat = QuickInputListFocus.Last;\n\t\t}\n\n\t\tif (what === QuickInputListFocus.Second && this.list.length < 2) {\n\t\t\twhat = QuickInputListFocus.First;\n\t\t}\n\n\t\tswitch (what) {\n\t\t\tcase QuickInputListFocus.First:\n\t\t\t\tthis.list.focusFirst();\n\t\t\t\tbreak;\n\t\t\tcase QuickInputListFocus.Second:\n\t\t\t\tthis.list.focusNth(1);\n\t\t\t\tbreak;\n\t\t\tcase QuickInputListFocus.Last:\n\t\t\t\tthis.list.focusLast();\n\t\t\t\tbreak;\n\t\t\tcase QuickInputListFocus.Next:\n\t\t\t\tthis.list.focusNext();\n\t\t\t\tbreak;\n\t\t\tcase QuickInputListFocus.Previous:\n\t\t\t\tthis.list.focusPrevious();\n\t\t\t\tbreak;\n\t\t\tcase QuickInputListFocus.NextPage:\n\t\t\t\tthis.list.focusNextPage();\n\t\t\t\tbreak;\n\t\t\tcase QuickInputListFocus.PreviousPage:\n\t\t\t\tthis.list.focusPreviousPage();\n\t\t\t\tbreak;\n\t\t}\n\n\t\tconst focused = this.list.getFocus()[0];\n\t\tif (typeof focused === 'number') {\n\t\t\tthis.list.reveal(focused);\n\t\t}\n\t}\n\n\tclearFocus() {\n\t\tthis.list.setFocus([]);\n\t}\n\n\tdomFocus() {\n\t\tthis.list.domFocus();\n\t}\n\n\tlayout(maxHeight?: number): void {\n\t\tthis.list.getHTMLElement().style.maxHeight = maxHeight ? `calc(${Math.floor(maxHeight / 44) * 44}px)` : '';\n\t\tthis.list.layout();\n\t}\n\n\tfilter(query: string): boolean {\n\t\tif (!(this.sortByLabel || this.matchOnLabel || this.matchOnDescription || this.matchOnDetail)) {\n\t\t\tthis.list.layout();\n\t\t\treturn false;\n\t\t}\n\t\tquery = query.trim();\n\n\t\t// Reset filtering\n\t\tif (!query || !(this.matchOnLabel || this.matchOnDescription || this.matchOnDetail)) {\n\t\t\tthis.elements.forEach(element => {\n\t\t\t\telement.labelHighlights = undefined;\n\t\t\t\telement.descriptionHighlights = undefined;\n\t\t\t\telement.detailHighlights = undefined;\n\t\t\t\telement.hidden = false;\n\t\t\t\tconst previous = element.index && this.inputElements[element.index - 1];\n\t\t\t\telement.separator = previous && previous.type === 'separator' ? previous : undefined;\n\t\t\t});\n\t\t}\n\n\t\t// Filter by value (since we support icons in labels, use $(..) aware fuzzy matching)\n\t\telse {\n\t\t\tlet currentSeparator: IQuickPickSeparator | undefined;\n\t\t\tthis.elements.forEach(element => {\n\t\t\t\tconst labelHighlights = this.matchOnLabel ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneLabel))) : undefined;\n\t\t\t\tconst descriptionHighlights = this.matchOnDescription ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneDescription || ''))) : undefined;\n\t\t\t\tconst detailHighlights = this.matchOnDetail ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneDetail || ''))) : undefined;\n\t\t\t\tconst metaHighlights = this.matchOnMeta ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneMeta || ''))) : undefined;\n\n\t\t\t\tif (labelHighlights || descriptionHighlights || detailHighlights || metaHighlights) {\n\t\t\t\t\telement.labelHighlights = labelHighlights;\n\t\t\t\t\telement.descriptionHighlights = descriptionHighlights;\n\t\t\t\t\telement.detailHighlights = detailHighlights;\n\t\t\t\t\telement.hidden = false;\n\t\t\t\t} else {\n\t\t\t\t\telement.labelHighlights = undefined;\n\t\t\t\t\telement.descriptionHighlights = undefined;\n\t\t\t\t\telement.detailHighlights = undefined;\n\t\t\t\t\telement.hidden = !element.item.alwaysShow;\n\t\t\t\t}\n\t\t\t\telement.separator = undefined;\n\n\t\t\t\t// we can show the separator unless the list gets sorted by match\n\t\t\t\tif (!this.sortByLabel) {\n\t\t\t\t\tconst previous = element.index && this.inputElements[element.index - 1];\n\t\t\t\t\tcurrentSeparator = previous && previous.type === 'separator' ? previous : currentSeparator;\n\t\t\t\t\tif (currentSeparator && !element.hidden) {\n\t\t\t\t\t\telement.separator = currentSeparator;\n\t\t\t\t\t\tcurrentSeparator = undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tconst shownElements = this.elements.filter(element => !element.hidden);\n\n\t\t// Sort by value\n\t\tif (this.sortByLabel && query) {\n\t\t\tconst normalizedSearchValue = query.toLowerCase();\n\t\t\tshownElements.sort((a, b) => {\n\t\t\t\treturn compareEntries(a, b, normalizedSearchValue);\n\t\t\t});\n\t\t}\n\n\t\tthis.elementsToIndexes = shownElements.reduce((map, element, index) => {\n\t\t\tmap.set(element.item, index);\n\t\t\treturn map;\n\t\t}, new Map());\n\t\tthis.list.splice(0, this.list.length, shownElements);\n\t\tthis.list.setFocus([]);\n\t\tthis.list.layout();\n\n\t\tthis._onChangedAllVisibleChecked.fire(this.getAllVisibleChecked());\n\t\tthis._onChangedVisibleCount.fire(shownElements.length);\n\n\t\treturn true;\n\t}\n\n\ttoggleCheckbox() {\n\t\ttry {\n\t\t\tthis._fireCheckedEvents = false;\n\t\t\tconst elements = this.list.getFocusedElements();\n\t\t\tconst allChecked = this.allVisibleChecked(elements);\n\t\t\tfor (const element of elements) {\n\t\t\t\telement.checked = !allChecked;\n\t\t\t}\n\t\t} finally {\n\t\t\tthis._fireCheckedEvents = true;\n\t\t\tthis.fireCheckedEvents();\n\t\t}\n\t}\n\n\tdisplay(display: boolean) {\n\t\tthis.container.style.display = display ? '' : 'none';\n\t}\n\n\tisDisplayed() {\n\t\treturn this.container.style.display !== 'none';\n\t}\n\n\tdispose() {\n\t\tthis.elementDisposables = dispose(this.elementDisposables);\n\t\tthis.disposables = dispose(this.disposables);\n\t}\n\n\tprivate fireCheckedEvents() {\n\t\tif (this._fireCheckedEvents) {\n\t\t\tthis._onChangedAllVisibleChecked.fire(this.getAllVisibleChecked());\n\t\t\tthis._onChangedCheckedCount.fire(this.getCheckedCount());\n\t\t\tthis._onChangedCheckedElements.fire(this.getCheckedElements());\n\t\t}\n\t}\n\n\tprivate fireButtonTriggered(event: IQuickPickItemButtonEvent) {\n\t\tthis._onButtonTriggered.fire(event);\n\t}\n\n\tstyle(styles: IListStyles) {\n\t\tthis.list.style(styles);\n\t}\n}\n\nfunction compareEntries(elementA: ListElement, elementB: ListElement, lookFor: string): number {\n\n\tconst labelHighlightsA = elementA.labelHighlights || [];\n\tconst labelHighlightsB = elementB.labelHighlights || [];\n\tif (labelHighlightsA.length && !labelHighlightsB.length) {\n\t\treturn -1;\n\t}\n\n\tif (!labelHighlightsA.length && labelHighlightsB.length) {\n\t\treturn 1;\n\t}\n\n\tif (labelHighlightsA.length === 0 && labelHighlightsB.length === 0) {\n\t\treturn 0;\n\t}\n\n\treturn compareAnything(elementA.saneLabel, elementB.saneLabel, lookFor);\n}\n\nclass QuickInputAccessibilityProvider implements IListAccessibilityProvider {\n\n\tgetWidgetAriaLabel(): string {\n\t\treturn localize('quickInput', \"Quick Input\");\n\t}\n\n\tgetAriaLabel(element: ListElement): string | null {\n\t\treturn element.saneAriaLabel;\n\t}\n\n\tgetWidgetRole() {\n\t\treturn 'listbox';\n\t}\n\n\tgetRole() {\n\t\treturn 'option';\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';\nimport { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';\nimport { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';\nimport { Button, IButtonStyles } from 'vs/base/browser/ui/button/button';\nimport { CountBadge, ICountBadgetyles } from 'vs/base/browser/ui/countBadge/countBadge';\nimport { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';\nimport { IInputBoxStyles } from 'vs/base/browser/ui/inputbox/inputBox';\nimport { IKeybindingLabelStyles } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel';\nimport { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';\nimport { IListOptions, IListStyles, List } from 'vs/base/browser/ui/list/listWidget';\nimport { IProgressBarStyles, ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';\nimport { Action } from 'vs/base/common/actions';\nimport { equals } from 'vs/base/common/arrays';\nimport { TimeoutTimer } from 'vs/base/common/async';\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { Codicon } from 'vs/base/common/codicons';\nimport { Color } from 'vs/base/common/color';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { Disposable, DisposableStore, dispose } from 'vs/base/common/lifecycle';\nimport { isIOS } from 'vs/base/common/platform';\nimport Severity from 'vs/base/common/severity';\nimport { withNullAsUndefined } from 'vs/base/common/types';\nimport { getIconClass } from 'vs/base/parts/quickinput/browser/quickInputUtils';\nimport { IKeyMods, IPickOptions, IQuickInput, IQuickInputButton, IQuickInputHideEvent, IQuickNavigateConfiguration, IQuickPick, IQuickPickDidAcceptEvent, IQuickPickItem, IQuickPickItemButtonEvent, IQuickPickSeparator, IQuickPickWillAcceptEvent, ItemActivation, NO_KEY_MODS, QuickInputHideReason, QuickPickInput } from 'vs/base/parts/quickinput/common/quickInput';\nimport 'vs/css!./media/quickInput';\nimport { localize } from 'vs/nls';\nimport { QuickInputBox } from './quickInputBox';\nimport { QuickInputList, QuickInputListFocus } from './quickInputList';\n\nexport interface IQuickInputOptions {\n\tidPrefix: string;\n\tcontainer: HTMLElement;\n\tignoreFocusOut(): boolean;\n\tisScreenReaderOptimized(): boolean;\n\tbackKeybindingLabel(): string | undefined;\n\tsetContextKey(id?: string): void;\n\treturnFocus(): void;\n\tcreateList(\n\t\tuser: string,\n\t\tcontainer: HTMLElement,\n\t\tdelegate: IListVirtualDelegate,\n\t\trenderers: IListRenderer[],\n\t\toptions: IListOptions,\n\t): List;\n\tstyles: IQuickInputStyles;\n}\n\nexport interface IQuickInputStyles {\n\twidget: IQuickInputWidgetStyles;\n\tinputBox: IInputBoxStyles;\n\tcountBadge: ICountBadgetyles;\n\tbutton: IButtonStyles;\n\tprogressBar: IProgressBarStyles;\n\tkeybindingLabel: IKeybindingLabelStyles;\n\tlist: IListStyles & { pickerGroupBorder?: Color; pickerGroupForeground?: Color; };\n}\n\nexport interface IQuickInputWidgetStyles {\n\tquickInputBackground?: Color;\n\tquickInputForeground?: Color;\n\tquickInputTitleBackground?: Color;\n\tcontrastBorder?: Color;\n\twidgetShadow?: Color;\n}\n\nconst $ = dom.$;\n\ntype Writeable = { -readonly [P in keyof T]: T[P] };\n\nconst backButton = {\n\ticonClass: Codicon.quickInputBack.classNames,\n\ttooltip: localize('quickInput.back', \"Back\"),\n\thandle: -1 // TODO\n};\n\ninterface QuickInputUI {\n\tcontainer: HTMLElement;\n\tstyleSheet: HTMLStyleElement;\n\tleftActionBar: ActionBar;\n\ttitleBar: HTMLElement;\n\ttitle: HTMLElement;\n\tdescription1: HTMLElement;\n\tdescription2: HTMLElement;\n\trightActionBar: ActionBar;\n\tcheckAll: HTMLInputElement;\n\tfilterContainer: HTMLElement;\n\tinputBox: QuickInputBox;\n\tvisibleCountContainer: HTMLElement;\n\tvisibleCount: CountBadge;\n\tcountContainer: HTMLElement;\n\tcount: CountBadge;\n\tokContainer: HTMLElement;\n\tok: Button;\n\tmessage: HTMLElement;\n\tcustomButtonContainer: HTMLElement;\n\tcustomButton: Button;\n\tprogressBar: ProgressBar;\n\tlist: QuickInputList;\n\tonDidAccept: Event;\n\tonDidCustom: Event;\n\tonDidTriggerButton: Event;\n\tignoreFocusOut: boolean;\n\tkeyMods: Writeable;\n\tisScreenReaderOptimized(): boolean;\n\tshow(controller: QuickInput): void;\n\tsetVisibilities(visibilities: Visibilities): void;\n\tsetComboboxAccessibility(enabled: boolean): void;\n\tsetEnabled(enabled: boolean): void;\n\tsetContextKey(contextKey?: string): void;\n\thide(): void;\n}\n\ntype Visibilities = {\n\ttitle?: boolean;\n\tdescription?: boolean;\n\tcheckAll?: boolean;\n\tinputBox?: boolean;\n\tcheckBox?: boolean;\n\tvisibleCount?: boolean;\n\tcount?: boolean;\n\tmessage?: boolean;\n\tlist?: boolean;\n\tok?: boolean;\n\tcustomButton?: boolean;\n\tprogressBar?: boolean;\n};\n\nclass QuickInput extends Disposable implements IQuickInput {\n\tprotected static readonly noPromptMessage = localize('inputModeEntry', \"Press 'Enter' to confirm your input or 'Escape' to cancel\");\n\n\tprivate _title: string | undefined;\n\tprivate _description: string | undefined;\n\tprivate _steps: number | undefined;\n\tprivate _totalSteps: number | undefined;\n\tprotected visible = false;\n\tprivate _enabled = true;\n\tprivate _contextKey: string | undefined;\n\tprivate _busy = false;\n\tprivate _ignoreFocusOut = false;\n\tprivate _buttons: IQuickInputButton[] = [];\n\tprotected noValidationMessage = QuickInput.noPromptMessage;\n\tprivate _validationMessage: string | undefined;\n\tprivate _lastValidationMessage: string | undefined;\n\tprivate _severity: Severity = Severity.Ignore;\n\tprivate _lastSeverity: Severity | undefined;\n\tprivate buttonsUpdated = false;\n\tprivate readonly onDidTriggerButtonEmitter = this._register(new Emitter());\n\tprivate readonly onDidHideEmitter = this._register(new Emitter());\n\tprivate readonly onDisposeEmitter = this._register(new Emitter());\n\n\tprotected readonly visibleDisposables = this._register(new DisposableStore());\n\n\tprivate busyDelay: TimeoutTimer | undefined;\n\n\tconstructor(\n\t\tprotected ui: QuickInputUI\n\t) {\n\t\tsuper();\n\t}\n\n\tget title() {\n\t\treturn this._title;\n\t}\n\n\tset title(title: string | undefined) {\n\t\tthis._title = title;\n\t\tthis.update();\n\t}\n\n\tget description() {\n\t\treturn this._description;\n\t}\n\n\tset description(description: string | undefined) {\n\t\tthis._description = description;\n\t\tthis.update();\n\t}\n\n\tget step() {\n\t\treturn this._steps;\n\t}\n\n\tset step(step: number | undefined) {\n\t\tthis._steps = step;\n\t\tthis.update();\n\t}\n\n\tget totalSteps() {\n\t\treturn this._totalSteps;\n\t}\n\n\tset totalSteps(totalSteps: number | undefined) {\n\t\tthis._totalSteps = totalSteps;\n\t\tthis.update();\n\t}\n\n\tget enabled() {\n\t\treturn this._enabled;\n\t}\n\n\tset enabled(enabled: boolean) {\n\t\tthis._enabled = enabled;\n\t\tthis.update();\n\t}\n\n\tget contextKey() {\n\t\treturn this._contextKey;\n\t}\n\n\tset contextKey(contextKey: string | undefined) {\n\t\tthis._contextKey = contextKey;\n\t\tthis.update();\n\t}\n\n\tget busy() {\n\t\treturn this._busy;\n\t}\n\n\tset busy(busy: boolean) {\n\t\tthis._busy = busy;\n\t\tthis.update();\n\t}\n\n\tget ignoreFocusOut() {\n\t\treturn this._ignoreFocusOut;\n\t}\n\n\tset ignoreFocusOut(ignoreFocusOut: boolean) {\n\t\tconst shouldUpdate = this._ignoreFocusOut !== ignoreFocusOut && !isIOS;\n\t\tthis._ignoreFocusOut = ignoreFocusOut && !isIOS;\n\t\tif (shouldUpdate) {\n\t\t\tthis.update();\n\t\t}\n\t}\n\n\tget buttons() {\n\t\treturn this._buttons;\n\t}\n\n\tset buttons(buttons: IQuickInputButton[]) {\n\t\tthis._buttons = buttons;\n\t\tthis.buttonsUpdated = true;\n\t\tthis.update();\n\t}\n\n\tget validationMessage() {\n\t\treturn this._validationMessage;\n\t}\n\n\tset validationMessage(validationMessage: string | undefined) {\n\t\tthis._validationMessage = validationMessage;\n\t\tthis.update();\n\t}\n\n\tget severity() {\n\t\treturn this._severity;\n\t}\n\n\tset severity(severity: Severity) {\n\t\tthis._severity = severity;\n\t\tthis.update();\n\t}\n\n\tshow(): void {\n\t\tif (this.visible) {\n\t\t\treturn;\n\t\t}\n\t\tthis.visibleDisposables.add(\n\t\t\tthis.ui.onDidTriggerButton(button => {\n\t\t\t\tif (this.buttons.indexOf(button) !== -1) {\n\t\t\t\t\tthis.onDidTriggerButtonEmitter.fire(button);\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t\tthis.ui.show(this);\n\n\t\t// update properties in the controller that get reset in the ui.show() call\n\t\tthis.visible = true;\n\t\t// This ensures the message/prompt gets rendered\n\t\tthis._lastValidationMessage = undefined;\n\t\t// This ensures the input box has the right severity applied\n\t\tthis._lastSeverity = undefined;\n\t\tif (this.buttons.length) {\n\t\t\t// if there are buttons, the ui.show() clears them out of the UI so we should\n\t\t\t// rerender them.\n\t\t\tthis.buttonsUpdated = true;\n\t\t}\n\n\t\tthis.update();\n\t}\n\n\thide(): void {\n\t\tif (!this.visible) {\n\t\t\treturn;\n\t\t}\n\t\tthis.ui.hide();\n\t}\n\n\tdidHide(reason = QuickInputHideReason.Other): void {\n\t\tthis.visible = false;\n\t\tthis.visibleDisposables.clear();\n\t\tthis.onDidHideEmitter.fire({ reason });\n\t}\n\n\treadonly onDidHide = this.onDidHideEmitter.event;\n\n\tprotected update() {\n\t\tif (!this.visible) {\n\t\t\treturn;\n\t\t}\n\t\tconst title = this.getTitle();\n\t\tif (title && this.ui.title.textContent !== title) {\n\t\t\tthis.ui.title.textContent = title;\n\t\t} else if (!title && this.ui.title.innerHTML !== ' ') {\n\t\t\tthis.ui.title.innerText = '\\u00a0';\n\t\t}\n\t\tconst description = this.getDescription();\n\t\tif (this.ui.description1.textContent !== description) {\n\t\t\tthis.ui.description1.textContent = description;\n\t\t}\n\t\tif (this.ui.description2.textContent !== description) {\n\t\t\tthis.ui.description2.textContent = description;\n\t\t}\n\t\tif (this.busy && !this.busyDelay) {\n\t\t\tthis.busyDelay = new TimeoutTimer();\n\t\t\tthis.busyDelay.setIfNotSet(() => {\n\t\t\t\tif (this.visible) {\n\t\t\t\t\tthis.ui.progressBar.infinite();\n\t\t\t\t}\n\t\t\t}, 800);\n\t\t}\n\t\tif (!this.busy && this.busyDelay) {\n\t\t\tthis.ui.progressBar.stop();\n\t\t\tthis.busyDelay.cancel();\n\t\t\tthis.busyDelay = undefined;\n\t\t}\n\t\tif (this.buttonsUpdated) {\n\t\t\tthis.buttonsUpdated = false;\n\t\t\tthis.ui.leftActionBar.clear();\n\t\t\tconst leftButtons = this.buttons.filter(button => button === backButton);\n\t\t\tthis.ui.leftActionBar.push(leftButtons.map((button, index) => {\n\t\t\t\tconst action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, async () => {\n\t\t\t\t\tthis.onDidTriggerButtonEmitter.fire(button);\n\t\t\t\t});\n\t\t\t\taction.tooltip = button.tooltip || '';\n\t\t\t\treturn action;\n\t\t\t}), { icon: true, label: false });\n\t\t\tthis.ui.rightActionBar.clear();\n\t\t\tconst rightButtons = this.buttons.filter(button => button !== backButton);\n\t\t\tthis.ui.rightActionBar.push(rightButtons.map((button, index) => {\n\t\t\t\tconst action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, async () => {\n\t\t\t\t\tthis.onDidTriggerButtonEmitter.fire(button);\n\t\t\t\t});\n\t\t\t\taction.tooltip = button.tooltip || '';\n\t\t\t\treturn action;\n\t\t\t}), { icon: true, label: false });\n\t\t}\n\t\tthis.ui.ignoreFocusOut = this.ignoreFocusOut;\n\t\tthis.ui.setEnabled(this.enabled);\n\t\tthis.ui.setContextKey(this.contextKey);\n\n\t\tconst validationMessage = this.validationMessage || this.noValidationMessage;\n\t\tif (this._lastValidationMessage !== validationMessage) {\n\t\t\tthis._lastValidationMessage = validationMessage;\n\t\t\tdom.reset(this.ui.message, ...renderLabelWithIcons(validationMessage));\n\t\t}\n\t\tif (this._lastSeverity !== this.severity) {\n\t\t\tthis._lastSeverity = this.severity;\n\t\t\tthis.showMessageDecoration(this.severity);\n\t\t}\n\t}\n\n\tprivate getTitle() {\n\t\tif (this.title && this.step) {\n\t\t\treturn `${this.title} (${this.getSteps()})`;\n\t\t}\n\t\tif (this.title) {\n\t\t\treturn this.title;\n\t\t}\n\t\tif (this.step) {\n\t\t\treturn this.getSteps();\n\t\t}\n\t\treturn '';\n\t}\n\n\tprivate getDescription() {\n\t\treturn this.description || '';\n\t}\n\n\tprivate getSteps() {\n\t\tif (this.step && this.totalSteps) {\n\t\t\treturn localize('quickInput.steps', \"{0}/{1}\", this.step, this.totalSteps);\n\t\t}\n\t\tif (this.step) {\n\t\t\treturn String(this.step);\n\t\t}\n\t\treturn '';\n\t}\n\n\tprotected showMessageDecoration(severity: Severity) {\n\t\tthis.ui.inputBox.showDecoration(severity);\n\t\tif (severity !== Severity.Ignore) {\n\t\t\tconst styles = this.ui.inputBox.stylesForType(severity);\n\t\t\tthis.ui.message.style.color = styles.foreground ? `${styles.foreground}` : '';\n\t\t\tthis.ui.message.style.backgroundColor = styles.background ? `${styles.background}` : '';\n\t\t\tthis.ui.message.style.border = styles.border ? `1px solid ${styles.border}` : '';\n\t\t\tthis.ui.message.style.marginBottom = '-2px';\n\t\t} else {\n\t\t\tthis.ui.message.style.color = '';\n\t\t\tthis.ui.message.style.backgroundColor = '';\n\t\t\tthis.ui.message.style.border = '';\n\t\t\tthis.ui.message.style.marginBottom = '';\n\t\t}\n\t}\n\n\toverride dispose(): void {\n\t\tthis.hide();\n\t\tthis.onDisposeEmitter.fire();\n\n\t\tsuper.dispose();\n\t}\n}\n\nclass QuickPick extends QuickInput implements IQuickPick {\n\n\tprivate static readonly DEFAULT_ARIA_LABEL = localize('quickInputBox.ariaLabel', \"Type to narrow down results.\");\n\n\tprivate _value = '';\n\tprivate _ariaLabel: string | undefined;\n\tprivate _placeholder: string | undefined;\n\tprivate readonly onDidChangeValueEmitter = this._register(new Emitter());\n\tprivate readonly onWillAcceptEmitter = this._register(new Emitter());\n\tprivate readonly onDidAcceptEmitter = this._register(new Emitter());\n\tprivate readonly onDidCustomEmitter = this._register(new Emitter());\n\tprivate _items: Array = [];\n\tprivate itemsUpdated = false;\n\tprivate _canSelectMany = false;\n\tprivate _canAcceptInBackground = false;\n\tprivate _matchOnDescription = false;\n\tprivate _matchOnDetail = false;\n\tprivate _matchOnLabel = true;\n\tprivate _sortByLabel = true;\n\tprivate _autoFocusOnList = true;\n\tprivate _keepScrollPosition = false;\n\tprivate _itemActivation = this.ui.isScreenReaderOptimized() ? ItemActivation.NONE /* https://github.com/microsoft/vscode/issues/57501 */ : ItemActivation.FIRST;\n\tprivate _activeItems: T[] = [];\n\tprivate activeItemsUpdated = false;\n\tprivate activeItemsToConfirm: T[] | null = [];\n\tprivate readonly onDidChangeActiveEmitter = this._register(new Emitter());\n\tprivate _selectedItems: T[] = [];\n\tprivate selectedItemsUpdated = false;\n\tprivate selectedItemsToConfirm: T[] | null = [];\n\tprivate readonly onDidChangeSelectionEmitter = this._register(new Emitter());\n\tprivate readonly onDidTriggerItemButtonEmitter = this._register(new Emitter>());\n\tprivate _valueSelection: Readonly<[number, number]> | undefined;\n\tprivate valueSelectionUpdated = true;\n\tprivate _ok: boolean | 'default' = 'default';\n\tprivate _customButton = false;\n\tprivate _customButtonLabel: string | undefined;\n\tprivate _customButtonHover: string | undefined;\n\tprivate _quickNavigate: IQuickNavigateConfiguration | undefined;\n\tprivate _hideInput: boolean | undefined;\n\tprivate _hideCheckAll: boolean | undefined;\n\n\tget quickNavigate() {\n\t\treturn this._quickNavigate;\n\t}\n\n\tset quickNavigate(quickNavigate: IQuickNavigateConfiguration | undefined) {\n\t\tthis._quickNavigate = quickNavigate;\n\t\tthis.update();\n\t}\n\n\tget value() {\n\t\treturn this._value;\n\t}\n\n\tset value(value: string) {\n\t\tthis.doSetValue(value);\n\t}\n\n\tprivate doSetValue(value: string, skipUpdate?: boolean): void {\n\t\tif (this._value !== value) {\n\t\t\tthis._value = value;\n\t\t\tif (!skipUpdate) {\n\t\t\t\tthis.update();\n\t\t\t}\n\t\t\tif (this.visible) {\n\t\t\t\tconst didFilter = this.ui.list.filter(this.filterValue(this._value));\n\t\t\t\tif (didFilter) {\n\t\t\t\t\tthis.trySelectFirst();\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.onDidChangeValueEmitter.fire(this._value);\n\t\t}\n\t}\n\n\tfilterValue = (value: string) => value;\n\n\tset ariaLabel(ariaLabel: string | undefined) {\n\t\tthis._ariaLabel = ariaLabel;\n\t\tthis.update();\n\t}\n\n\tget ariaLabel() {\n\t\treturn this._ariaLabel;\n\t}\n\n\tget placeholder() {\n\t\treturn this._placeholder;\n\t}\n\n\tset placeholder(placeholder: string | undefined) {\n\t\tthis._placeholder = placeholder;\n\t\tthis.update();\n\t}\n\n\tonDidChangeValue = this.onDidChangeValueEmitter.event;\n\n\tonWillAccept = this.onWillAcceptEmitter.event;\n\tonDidAccept = this.onDidAcceptEmitter.event;\n\n\tget items() {\n\t\treturn this._items;\n\t}\n\n\tprivate get scrollTop() {\n\t\treturn this.ui.list.scrollTop;\n\t}\n\n\tprivate set scrollTop(scrollTop: number) {\n\t\tthis.ui.list.scrollTop = scrollTop;\n\t}\n\n\tset items(items: Array) {\n\t\tthis._items = items;\n\t\tthis.itemsUpdated = true;\n\t\tthis.update();\n\t}\n\n\tget canSelectMany() {\n\t\treturn this._canSelectMany;\n\t}\n\n\tset canSelectMany(canSelectMany: boolean) {\n\t\tthis._canSelectMany = canSelectMany;\n\t\tthis.update();\n\t}\n\n\tget canAcceptInBackground() {\n\t\treturn this._canAcceptInBackground;\n\t}\n\n\tset canAcceptInBackground(canAcceptInBackground: boolean) {\n\t\tthis._canAcceptInBackground = canAcceptInBackground;\n\t}\n\n\tget matchOnDescription() {\n\t\treturn this._matchOnDescription;\n\t}\n\n\tset matchOnDescription(matchOnDescription: boolean) {\n\t\tthis._matchOnDescription = matchOnDescription;\n\t\tthis.update();\n\t}\n\n\tget matchOnDetail() {\n\t\treturn this._matchOnDetail;\n\t}\n\n\tset matchOnDetail(matchOnDetail: boolean) {\n\t\tthis._matchOnDetail = matchOnDetail;\n\t\tthis.update();\n\t}\n\n\tget matchOnLabel() {\n\t\treturn this._matchOnLabel;\n\t}\n\n\tset matchOnLabel(matchOnLabel: boolean) {\n\t\tthis._matchOnLabel = matchOnLabel;\n\t\tthis.update();\n\t}\n\n\tget sortByLabel() {\n\t\treturn this._sortByLabel;\n\t}\n\n\tset sortByLabel(sortByLabel: boolean) {\n\t\tthis._sortByLabel = sortByLabel;\n\t\tthis.update();\n\t}\n\n\tget autoFocusOnList() {\n\t\treturn this._autoFocusOnList;\n\t}\n\n\tset autoFocusOnList(autoFocusOnList: boolean) {\n\t\tthis._autoFocusOnList = autoFocusOnList;\n\t\tthis.update();\n\t}\n\n\tget keepScrollPosition() {\n\t\treturn this._keepScrollPosition;\n\t}\n\n\tset keepScrollPosition(keepScrollPosition: boolean) {\n\t\tthis._keepScrollPosition = keepScrollPosition;\n\t}\n\n\tget itemActivation() {\n\t\treturn this._itemActivation;\n\t}\n\n\tset itemActivation(itemActivation: ItemActivation) {\n\t\tthis._itemActivation = itemActivation;\n\t}\n\n\tget activeItems() {\n\t\treturn this._activeItems;\n\t}\n\n\tset activeItems(activeItems: T[]) {\n\t\tthis._activeItems = activeItems;\n\t\tthis.activeItemsUpdated = true;\n\t\tthis.update();\n\t}\n\n\tonDidChangeActive = this.onDidChangeActiveEmitter.event;\n\n\tget selectedItems() {\n\t\treturn this._selectedItems;\n\t}\n\n\tset selectedItems(selectedItems: T[]) {\n\t\tthis._selectedItems = selectedItems;\n\t\tthis.selectedItemsUpdated = true;\n\t\tthis.update();\n\t}\n\n\tget keyMods() {\n\t\tif (this._quickNavigate) {\n\t\t\t// Disable keyMods when quick navigate is enabled\n\t\t\t// because in this model the interaction is purely\n\t\t\t// keyboard driven and Ctrl/Alt are typically\n\t\t\t// pressed and hold during this interaction.\n\t\t\treturn NO_KEY_MODS;\n\t\t}\n\t\treturn this.ui.keyMods;\n\t}\n\n\tset valueSelection(valueSelection: Readonly<[number, number]>) {\n\t\tthis._valueSelection = valueSelection;\n\t\tthis.valueSelectionUpdated = true;\n\t\tthis.update();\n\t}\n\n\tget customButton() {\n\t\treturn this._customButton;\n\t}\n\n\tset customButton(showCustomButton: boolean) {\n\t\tthis._customButton = showCustomButton;\n\t\tthis.update();\n\t}\n\n\tget customLabel() {\n\t\treturn this._customButtonLabel;\n\t}\n\n\tset customLabel(label: string | undefined) {\n\t\tthis._customButtonLabel = label;\n\t\tthis.update();\n\t}\n\n\tget customHover() {\n\t\treturn this._customButtonHover;\n\t}\n\n\tset customHover(hover: string | undefined) {\n\t\tthis._customButtonHover = hover;\n\t\tthis.update();\n\t}\n\n\tget ok() {\n\t\treturn this._ok;\n\t}\n\n\tset ok(showOkButton: boolean | 'default') {\n\t\tthis._ok = showOkButton;\n\t\tthis.update();\n\t}\n\n\tget hideInput() {\n\t\treturn !!this._hideInput;\n\t}\n\n\tset hideInput(hideInput: boolean) {\n\t\tthis._hideInput = hideInput;\n\t\tthis.update();\n\t}\n\n\tonDidChangeSelection = this.onDidChangeSelectionEmitter.event;\n\n\tonDidTriggerItemButton = this.onDidTriggerItemButtonEmitter.event;\n\n\tprivate trySelectFirst() {\n\t\tif (this.autoFocusOnList) {\n\t\t\tif (!this.canSelectMany) {\n\t\t\t\tthis.ui.list.focus(QuickInputListFocus.First);\n\t\t\t}\n\t\t}\n\t}\n\n\toverride show() {\n\t\tif (!this.visible) {\n\t\t\tthis.visibleDisposables.add(\n\t\t\t\tthis.ui.inputBox.onDidChange(value => {\n\t\t\t\t\tthis.doSetValue(value, true /* skip update since this originates from the UI */);\n\t\t\t\t}));\n\t\t\tthis.visibleDisposables.add(this.ui.inputBox.onMouseDown(event => {\n\t\t\t\tif (!this.autoFocusOnList) {\n\t\t\t\t\tthis.ui.list.clearFocus();\n\t\t\t\t}\n\t\t\t}));\n\t\t\tthis.visibleDisposables.add((this._hideInput ? this.ui.list : this.ui.inputBox).onKeyDown((event: KeyboardEvent | StandardKeyboardEvent) => {\n\t\t\t\tswitch (event.keyCode) {\n\t\t\t\t\tcase KeyCode.DownArrow:\n\t\t\t\t\t\tthis.ui.list.focus(QuickInputListFocus.Next);\n\t\t\t\t\t\tif (this.canSelectMany) {\n\t\t\t\t\t\t\tthis.ui.list.domFocus();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdom.EventHelper.stop(event, true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase KeyCode.UpArrow:\n\t\t\t\t\t\tif (this.ui.list.getFocusedElements().length) {\n\t\t\t\t\t\t\tthis.ui.list.focus(QuickInputListFocus.Previous);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.ui.list.focus(QuickInputListFocus.Last);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (this.canSelectMany) {\n\t\t\t\t\t\t\tthis.ui.list.domFocus();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdom.EventHelper.stop(event, true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase KeyCode.PageDown:\n\t\t\t\t\t\tthis.ui.list.focus(QuickInputListFocus.NextPage);\n\t\t\t\t\t\tif (this.canSelectMany) {\n\t\t\t\t\t\t\tthis.ui.list.domFocus();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdom.EventHelper.stop(event, true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase KeyCode.PageUp:\n\t\t\t\t\t\tthis.ui.list.focus(QuickInputListFocus.PreviousPage);\n\t\t\t\t\t\tif (this.canSelectMany) {\n\t\t\t\t\t\t\tthis.ui.list.domFocus();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdom.EventHelper.stop(event, true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase KeyCode.RightArrow:\n\t\t\t\t\t\tif (!this._canAcceptInBackground) {\n\t\t\t\t\t\t\treturn; // needs to be enabled\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!this.ui.inputBox.isSelectionAtEnd()) {\n\t\t\t\t\t\t\treturn; // ensure input box selection at end\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (this.activeItems[0]) {\n\t\t\t\t\t\t\tthis._selectedItems = [this.activeItems[0]];\n\t\t\t\t\t\t\tthis.onDidChangeSelectionEmitter.fire(this.selectedItems);\n\t\t\t\t\t\t\tthis.handleAccept(true);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase KeyCode.Home:\n\t\t\t\t\t\tif ((event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey) {\n\t\t\t\t\t\t\tthis.ui.list.focus(QuickInputListFocus.First);\n\t\t\t\t\t\t\tdom.EventHelper.stop(event, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase KeyCode.End:\n\t\t\t\t\t\tif ((event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey) {\n\t\t\t\t\t\t\tthis.ui.list.focus(QuickInputListFocus.Last);\n\t\t\t\t\t\t\tdom.EventHelper.stop(event, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}));\n\t\t\tthis.visibleDisposables.add(this.ui.onDidAccept(() => {\n\t\t\t\tif (this.canSelectMany) {\n\t\t\t\t\t// if there are no checked elements, it means that an onDidChangeSelection never fired to overwrite\n\t\t\t\t\t// `_selectedItems`. In that case, we should emit one with an empty array to ensure that\n\t\t\t\t\t// `.selectedItems` is up to date.\n\t\t\t\t\tif (!this.ui.list.getCheckedElements().length) {\n\t\t\t\t\t\tthis._selectedItems = [];\n\t\t\t\t\t\tthis.onDidChangeSelectionEmitter.fire(this.selectedItems);\n\t\t\t\t\t}\n\t\t\t\t} else if (this.activeItems[0]) {\n\t\t\t\t\t// For single-select, we set `selectedItems` to the item that was accepted.\n\t\t\t\t\tthis._selectedItems = [this.activeItems[0]];\n\t\t\t\t\tthis.onDidChangeSelectionEmitter.fire(this.selectedItems);\n\t\t\t\t}\n\t\t\t\tthis.handleAccept(false);\n\t\t\t}));\n\t\t\tthis.visibleDisposables.add(this.ui.onDidCustom(() => {\n\t\t\t\tthis.onDidCustomEmitter.fire();\n\t\t\t}));\n\t\t\tthis.visibleDisposables.add(this.ui.list.onDidChangeFocus(focusedItems => {\n\t\t\t\tif (this.activeItemsUpdated) {\n\t\t\t\t\treturn; // Expect another event.\n\t\t\t\t}\n\t\t\t\tif (this.activeItemsToConfirm !== this._activeItems && equals(focusedItems, this._activeItems, (a, b) => a === b)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._activeItems = focusedItems as T[];\n\t\t\t\tthis.onDidChangeActiveEmitter.fire(focusedItems as T[]);\n\t\t\t}));\n\t\t\tthis.visibleDisposables.add(this.ui.list.onDidChangeSelection(({ items: selectedItems, event }) => {\n\t\t\t\tif (this.canSelectMany) {\n\t\t\t\t\tif (selectedItems.length) {\n\t\t\t\t\t\tthis.ui.list.setSelectedElements([]);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (this.selectedItemsToConfirm !== this._selectedItems && equals(selectedItems, this._selectedItems, (a, b) => a === b)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._selectedItems = selectedItems as T[];\n\t\t\t\tthis.onDidChangeSelectionEmitter.fire(selectedItems as T[]);\n\t\t\t\tif (selectedItems.length) {\n\t\t\t\t\tthis.handleAccept(event instanceof MouseEvent && event.button === 1 /* mouse middle click */);\n\t\t\t\t}\n\t\t\t}));\n\t\t\tthis.visibleDisposables.add(this.ui.list.onChangedCheckedElements(checkedItems => {\n\t\t\t\tif (!this.canSelectMany) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (this.selectedItemsToConfirm !== this._selectedItems && equals(checkedItems, this._selectedItems, (a, b) => a === b)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._selectedItems = checkedItems as T[];\n\t\t\t\tthis.onDidChangeSelectionEmitter.fire(checkedItems as T[]);\n\t\t\t}));\n\t\t\tthis.visibleDisposables.add(this.ui.list.onButtonTriggered(event => this.onDidTriggerItemButtonEmitter.fire(event as IQuickPickItemButtonEvent)));\n\t\t\tthis.visibleDisposables.add(this.registerQuickNavigation());\n\t\t\tthis.valueSelectionUpdated = true;\n\t\t}\n\t\tsuper.show(); // TODO: Why have show() bubble up while update() trickles down? (Could move setComboboxAccessibility() here.)\n\t}\n\n\tprivate handleAccept(inBackground: boolean): void {\n\n\t\t// Figure out veto via `onWillAccept` event\n\t\tlet veto = false;\n\t\tthis.onWillAcceptEmitter.fire({ veto: () => veto = true });\n\n\t\t// Continue with `onDidAccept` if no veto\n\t\tif (!veto) {\n\t\t\tthis.onDidAcceptEmitter.fire({ inBackground });\n\t\t}\n\t}\n\n\tprivate registerQuickNavigation() {\n\t\treturn dom.addDisposableListener(this.ui.container, dom.EventType.KEY_UP, e => {\n\t\t\tif (this.canSelectMany || !this._quickNavigate) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e);\n\t\t\tconst keyCode = keyboardEvent.keyCode;\n\n\t\t\t// Select element when keys are pressed that signal it\n\t\t\tconst quickNavKeys = this._quickNavigate.keybindings;\n\t\t\tconst wasTriggerKeyPressed = quickNavKeys.some(k => {\n\t\t\t\tconst [firstPart, chordPart] = k.getParts();\n\t\t\t\tif (chordPart) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif (firstPart.shiftKey && keyCode === KeyCode.Shift) {\n\t\t\t\t\tif (keyboardEvent.ctrlKey || keyboardEvent.altKey || keyboardEvent.metaKey) {\n\t\t\t\t\t\treturn false; // this is an optimistic check for the shift key being used to navigate back in quick input\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tif (firstPart.altKey && keyCode === KeyCode.Alt) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tif (firstPart.ctrlKey && keyCode === KeyCode.Ctrl) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tif (firstPart.metaKey && keyCode === KeyCode.Meta) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t});\n\n\t\t\tif (wasTriggerKeyPressed) {\n\t\t\t\tif (this.activeItems[0]) {\n\t\t\t\t\tthis._selectedItems = [this.activeItems[0]];\n\t\t\t\t\tthis.onDidChangeSelectionEmitter.fire(this.selectedItems);\n\t\t\t\t\tthis.handleAccept(false);\n\t\t\t\t}\n\t\t\t\t// Unset quick navigate after press. It is only valid once\n\t\t\t\t// and should not result in any behaviour change afterwards\n\t\t\t\t// if the picker remains open because there was no active item\n\t\t\t\tthis._quickNavigate = undefined;\n\t\t\t}\n\t\t});\n\t}\n\n\tprotected override update() {\n\t\tif (!this.visible) {\n\t\t\treturn;\n\t\t}\n\t\t// store the scrollTop before it is reset\n\t\tconst scrollTopBefore = this.keepScrollPosition ? this.scrollTop : 0;\n\t\tconst hideInput = !!this._hideInput && this._items.length > 0;\n\t\tthis.ui.container.classList.toggle('hidden-input', hideInput && !this.description);\n\t\tconst visibilities: Visibilities = {\n\t\t\ttitle: !!this.title || !!this.step || !!this.buttons.length,\n\t\t\tdescription: !!this.description,\n\t\t\tcheckAll: this.canSelectMany && !this._hideCheckAll,\n\t\t\tcheckBox: this.canSelectMany,\n\t\t\tinputBox: !hideInput,\n\t\t\tprogressBar: !hideInput,\n\t\t\tvisibleCount: true,\n\t\t\tcount: this.canSelectMany,\n\t\t\tok: this.ok === 'default' ? this.canSelectMany : this.ok,\n\t\t\tlist: true,\n\t\t\tmessage: !!this.validationMessage,\n\t\t\tcustomButton: this.customButton\n\t\t};\n\t\tthis.ui.setVisibilities(visibilities);\n\t\tsuper.update();\n\t\tif (this.ui.inputBox.value !== this.value) {\n\t\t\tthis.ui.inputBox.value = this.value;\n\t\t}\n\t\tif (this.valueSelectionUpdated) {\n\t\t\tthis.valueSelectionUpdated = false;\n\t\t\tthis.ui.inputBox.select(this._valueSelection && { start: this._valueSelection[0], end: this._valueSelection[1] });\n\t\t}\n\t\tif (this.ui.inputBox.placeholder !== (this.placeholder || '')) {\n\t\t\tthis.ui.inputBox.placeholder = (this.placeholder || '');\n\t\t}\n\t\tconst ariaLabel = this.ariaLabel || this.placeholder || QuickPick.DEFAULT_ARIA_LABEL;\n\t\tif (this.ui.inputBox.ariaLabel !== ariaLabel) {\n\t\t\tthis.ui.inputBox.ariaLabel = ariaLabel;\n\t\t}\n\t\tthis.ui.list.matchOnDescription = this.matchOnDescription;\n\t\tthis.ui.list.matchOnDetail = this.matchOnDetail;\n\t\tthis.ui.list.matchOnLabel = this.matchOnLabel;\n\t\tthis.ui.list.sortByLabel = this.sortByLabel;\n\t\tif (this.itemsUpdated) {\n\t\t\tthis.itemsUpdated = false;\n\t\t\tthis.ui.list.setElements(this.items);\n\t\t\tthis.ui.list.filter(this.filterValue(this.ui.inputBox.value));\n\t\t\tthis.ui.checkAll.checked = this.ui.list.getAllVisibleChecked();\n\t\t\tthis.ui.visibleCount.setCount(this.ui.list.getVisibleCount());\n\t\t\tthis.ui.count.setCount(this.ui.list.getCheckedCount());\n\t\t\tswitch (this._itemActivation) {\n\t\t\t\tcase ItemActivation.NONE:\n\t\t\t\t\tthis._itemActivation = ItemActivation.FIRST; // only valid once, then unset\n\t\t\t\t\tbreak;\n\t\t\t\tcase ItemActivation.SECOND:\n\t\t\t\t\tthis.ui.list.focus(QuickInputListFocus.Second);\n\t\t\t\t\tthis._itemActivation = ItemActivation.FIRST; // only valid once, then unset\n\t\t\t\t\tbreak;\n\t\t\t\tcase ItemActivation.LAST:\n\t\t\t\t\tthis.ui.list.focus(QuickInputListFocus.Last);\n\t\t\t\t\tthis._itemActivation = ItemActivation.FIRST; // only valid once, then unset\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthis.trySelectFirst();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (this.ui.container.classList.contains('show-checkboxes') !== !!this.canSelectMany) {\n\t\t\tif (this.canSelectMany) {\n\t\t\t\tthis.ui.list.clearFocus();\n\t\t\t} else {\n\t\t\t\tthis.trySelectFirst();\n\t\t\t}\n\t\t}\n\t\tif (this.activeItemsUpdated) {\n\t\t\tthis.activeItemsUpdated = false;\n\t\t\tthis.activeItemsToConfirm = this._activeItems;\n\t\t\tthis.ui.list.setFocusedElements(this.activeItems);\n\t\t\tif (this.activeItemsToConfirm === this._activeItems) {\n\t\t\t\tthis.activeItemsToConfirm = null;\n\t\t\t}\n\t\t}\n\t\tif (this.selectedItemsUpdated) {\n\t\t\tthis.selectedItemsUpdated = false;\n\t\t\tthis.selectedItemsToConfirm = this._selectedItems;\n\t\t\tif (this.canSelectMany) {\n\t\t\t\tthis.ui.list.setCheckedElements(this.selectedItems);\n\t\t\t} else {\n\t\t\t\tthis.ui.list.setSelectedElements(this.selectedItems);\n\t\t\t}\n\t\t\tif (this.selectedItemsToConfirm === this._selectedItems) {\n\t\t\t\tthis.selectedItemsToConfirm = null;\n\t\t\t}\n\t\t}\n\t\tthis.ui.customButton.label = this.customLabel || '';\n\t\tthis.ui.customButton.element.title = this.customHover || '';\n\t\tthis.ui.setComboboxAccessibility(true);\n\t\tif (!visibilities.inputBox) {\n\t\t\t// we need to move focus into the tree to detect keybindings\n\t\t\t// properly when the input box is not visible (quick nav)\n\t\t\tthis.ui.list.domFocus();\n\n\t\t\t// Focus the first element in the list if multiselect is enabled\n\t\t\tif (this.canSelectMany) {\n\t\t\t\tthis.ui.list.focus(QuickInputListFocus.First);\n\t\t\t}\n\t\t}\n\n\t\t// Set the scroll position to what it was before updating the items\n\t\tif (this.keepScrollPosition) {\n\t\t\tthis.scrollTop = scrollTopBefore;\n\t\t}\n\t}\n}\n\nexport class QuickInputController extends Disposable {\n\tprivate static readonly MAX_WIDTH = 600; // Max total width of quick input widget\n\n\tprivate idPrefix: string;\n\tprivate ui: QuickInputUI | undefined;\n\tprivate dimension?: dom.IDimension;\n\tprivate titleBarOffset?: number;\n\tprivate comboboxAccessibility = false;\n\tprivate enabled = true;\n\tprivate readonly onDidAcceptEmitter = this._register(new Emitter());\n\tprivate readonly onDidCustomEmitter = this._register(new Emitter());\n\tprivate readonly onDidTriggerButtonEmitter = this._register(new Emitter());\n\tprivate keyMods: Writeable = { ctrlCmd: false, alt: false };\n\n\tprivate controller: QuickInput | null = null;\n\n\tprivate parentElement: HTMLElement;\n\tprivate styles: IQuickInputStyles;\n\n\tprivate onShowEmitter = this._register(new Emitter());\n\treadonly onShow = this.onShowEmitter.event;\n\n\tprivate onHideEmitter = this._register(new Emitter());\n\treadonly onHide = this.onHideEmitter.event;\n\n\tprivate previousFocusElement?: HTMLElement;\n\n\tconstructor(private options: IQuickInputOptions) {\n\t\tsuper();\n\t\tthis.idPrefix = options.idPrefix;\n\t\tthis.parentElement = options.container;\n\t\tthis.styles = options.styles;\n\t\tthis.registerKeyModsListeners();\n\t}\n\n\tprivate registerKeyModsListeners() {\n\t\tconst listener = (e: KeyboardEvent | MouseEvent) => {\n\t\t\tthis.keyMods.ctrlCmd = e.ctrlKey || e.metaKey;\n\t\t\tthis.keyMods.alt = e.altKey;\n\t\t};\n\t\tthis._register(dom.addDisposableListener(window, dom.EventType.KEY_DOWN, listener, true));\n\t\tthis._register(dom.addDisposableListener(window, dom.EventType.KEY_UP, listener, true));\n\t\tthis._register(dom.addDisposableListener(window, dom.EventType.MOUSE_DOWN, listener, true));\n\t}\n\n\tprivate getUI() {\n\t\tif (this.ui) {\n\t\t\treturn this.ui;\n\t\t}\n\n\t\tconst container = dom.append(this.parentElement, $('.quick-input-widget.show-file-icons'));\n\t\tcontainer.tabIndex = -1;\n\t\tcontainer.style.display = 'none';\n\n\t\tconst styleSheet = dom.createStyleSheet(container);\n\n\t\tconst titleBar = dom.append(container, $('.quick-input-titlebar'));\n\n\t\tconst leftActionBar = this._register(new ActionBar(titleBar));\n\t\tleftActionBar.domNode.classList.add('quick-input-left-action-bar');\n\n\t\tconst title = dom.append(titleBar, $('.quick-input-title'));\n\n\t\tconst rightActionBar = this._register(new ActionBar(titleBar));\n\t\trightActionBar.domNode.classList.add('quick-input-right-action-bar');\n\n\t\tconst description1 = dom.append(container, $('.quick-input-description'));\n\t\tconst headerContainer = dom.append(container, $('.quick-input-header'));\n\n\t\tconst checkAll = dom.append(headerContainer, $('input.quick-input-check-all'));\n\t\tcheckAll.type = 'checkbox';\n\t\tthis._register(dom.addStandardDisposableListener(checkAll, dom.EventType.CHANGE, e => {\n\t\t\tconst checked = checkAll.checked;\n\t\t\tlist.setAllVisibleChecked(checked);\n\t\t}));\n\t\tthis._register(dom.addDisposableListener(checkAll, dom.EventType.CLICK, e => {\n\t\t\tif (e.x || e.y) { // Avoid 'click' triggered by 'space'...\n\t\t\t\tinputBox.setFocus();\n\t\t\t}\n\t\t}));\n\n\t\tconst description2 = dom.append(headerContainer, $('.quick-input-description'));\n\t\tconst extraContainer = dom.append(headerContainer, $('.quick-input-and-message'));\n\t\tconst filterContainer = dom.append(extraContainer, $('.quick-input-filter'));\n\n\t\tconst inputBox = this._register(new QuickInputBox(filterContainer));\n\t\tinputBox.setAttribute('aria-describedby', `${this.idPrefix}message`);\n\n\t\tconst visibleCountContainer = dom.append(filterContainer, $('.quick-input-visible-count'));\n\t\tvisibleCountContainer.setAttribute('aria-live', 'polite');\n\t\tvisibleCountContainer.setAttribute('aria-atomic', 'true');\n\t\tconst visibleCount = new CountBadge(visibleCountContainer, { countFormat: localize({ key: 'quickInput.visibleCount', comment: ['This tells the user how many items are shown in a list of items to select from. The items can be anything. Currently not visible, but read by screen readers.'] }, \"{0} Results\") });\n\n\t\tconst countContainer = dom.append(filterContainer, $('.quick-input-count'));\n\t\tcountContainer.setAttribute('aria-live', 'polite');\n\t\tconst count = new CountBadge(countContainer, { countFormat: localize({ key: 'quickInput.countSelected', comment: ['This tells the user how many items are selected in a list of items to select from. The items can be anything.'] }, \"{0} Selected\") });\n\n\t\tconst okContainer = dom.append(headerContainer, $('.quick-input-action'));\n\t\tconst ok = new Button(okContainer);\n\t\tok.label = localize('ok', \"OK\");\n\t\tthis._register(ok.onDidClick(e => {\n\t\t\tthis.onDidAcceptEmitter.fire();\n\t\t}));\n\n\t\tconst customButtonContainer = dom.append(headerContainer, $('.quick-input-action'));\n\t\tconst customButton = new Button(customButtonContainer);\n\t\tcustomButton.label = localize('custom', \"Custom\");\n\t\tthis._register(customButton.onDidClick(e => {\n\t\t\tthis.onDidCustomEmitter.fire();\n\t\t}));\n\n\t\tconst message = dom.append(extraContainer, $(`#${this.idPrefix}message.quick-input-message`));\n\n\t\tconst list = this._register(new QuickInputList(container, this.idPrefix + 'list', this.options));\n\t\tthis._register(list.onChangedAllVisibleChecked(checked => {\n\t\t\tcheckAll.checked = checked;\n\t\t}));\n\t\tthis._register(list.onChangedVisibleCount(c => {\n\t\t\tvisibleCount.setCount(c);\n\t\t}));\n\t\tthis._register(list.onChangedCheckedCount(c => {\n\t\t\tcount.setCount(c);\n\t\t}));\n\t\tthis._register(list.onLeave(() => {\n\t\t\t// Defer to avoid the input field reacting to the triggering key.\n\t\t\tsetTimeout(() => {\n\t\t\t\tinputBox.setFocus();\n\t\t\t\tif (this.controller instanceof QuickPick && this.controller.canSelectMany) {\n\t\t\t\t\tlist.clearFocus();\n\t\t\t\t}\n\t\t\t}, 0);\n\t\t}));\n\t\tthis._register(list.onDidChangeFocus(() => {\n\t\t\tif (this.comboboxAccessibility) {\n\t\t\t\tthis.getUI().inputBox.setAttribute('aria-activedescendant', this.getUI().list.getActiveDescendant() || '');\n\t\t\t}\n\t\t}));\n\n\t\tconst progressBar = new ProgressBar(container);\n\t\tprogressBar.getContainer().classList.add('quick-input-progress');\n\n\t\tconst focusTracker = dom.trackFocus(container);\n\t\tthis._register(focusTracker);\n\t\tthis._register(dom.addDisposableListener(container, dom.EventType.FOCUS, e => {\n\t\t\tthis.previousFocusElement = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : undefined;\n\t\t}, true));\n\t\tthis._register(focusTracker.onDidBlur(() => {\n\t\t\tif (!this.getUI().ignoreFocusOut && !this.options.ignoreFocusOut()) {\n\t\t\t\tthis.hide(QuickInputHideReason.Blur);\n\t\t\t}\n\t\t\tthis.previousFocusElement = undefined;\n\t\t}));\n\t\tthis._register(dom.addDisposableListener(container, dom.EventType.FOCUS, (e: FocusEvent) => {\n\t\t\tinputBox.setFocus();\n\t\t}));\n\t\tthis._register(dom.addDisposableListener(container, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {\n\t\t\tconst event = new StandardKeyboardEvent(e);\n\t\t\tswitch (event.keyCode) {\n\t\t\t\tcase KeyCode.Enter:\n\t\t\t\t\tdom.EventHelper.stop(e, true);\n\t\t\t\t\tthis.onDidAcceptEmitter.fire();\n\t\t\t\t\tbreak;\n\t\t\t\tcase KeyCode.Escape:\n\t\t\t\t\tdom.EventHelper.stop(e, true);\n\t\t\t\t\tthis.hide(QuickInputHideReason.Gesture);\n\t\t\t\t\tbreak;\n\t\t\t\tcase KeyCode.Tab:\n\t\t\t\t\tif (!event.altKey && !event.ctrlKey && !event.metaKey) {\n\t\t\t\t\t\tconst selectors = ['.action-label.codicon'];\n\t\t\t\t\t\tif (container.classList.contains('show-checkboxes')) {\n\t\t\t\t\t\t\tselectors.push('input');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselectors.push('input[type=text]');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (this.getUI().list.isDisplayed()) {\n\t\t\t\t\t\t\tselectors.push('.monaco-list');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst stops = container.querySelectorAll(selectors.join(', '));\n\t\t\t\t\t\tif (event.shiftKey && event.target === stops[0]) {\n\t\t\t\t\t\t\tdom.EventHelper.stop(e, true);\n\t\t\t\t\t\t\tstops[stops.length - 1].focus();\n\t\t\t\t\t\t} else if (!event.shiftKey && event.target === stops[stops.length - 1]) {\n\t\t\t\t\t\t\tdom.EventHelper.stop(e, true);\n\t\t\t\t\t\t\tstops[0].focus();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}));\n\n\t\tthis.ui = {\n\t\t\tcontainer,\n\t\t\tstyleSheet,\n\t\t\tleftActionBar,\n\t\t\ttitleBar,\n\t\t\ttitle,\n\t\t\tdescription1,\n\t\t\tdescription2,\n\t\t\trightActionBar,\n\t\t\tcheckAll,\n\t\t\tfilterContainer,\n\t\t\tinputBox,\n\t\t\tvisibleCountContainer,\n\t\t\tvisibleCount,\n\t\t\tcountContainer,\n\t\t\tcount,\n\t\t\tokContainer,\n\t\t\tok,\n\t\t\tmessage,\n\t\t\tcustomButtonContainer,\n\t\t\tcustomButton,\n\t\t\tlist,\n\t\t\tprogressBar,\n\t\t\tonDidAccept: this.onDidAcceptEmitter.event,\n\t\t\tonDidCustom: this.onDidCustomEmitter.event,\n\t\t\tonDidTriggerButton: this.onDidTriggerButtonEmitter.event,\n\t\t\tignoreFocusOut: false,\n\t\t\tkeyMods: this.keyMods,\n\t\t\tisScreenReaderOptimized: () => this.options.isScreenReaderOptimized(),\n\t\t\tshow: controller => this.show(controller),\n\t\t\thide: () => this.hide(),\n\t\t\tsetVisibilities: visibilities => this.setVisibilities(visibilities),\n\t\t\tsetComboboxAccessibility: enabled => this.setComboboxAccessibility(enabled),\n\t\t\tsetEnabled: enabled => this.setEnabled(enabled),\n\t\t\tsetContextKey: contextKey => this.options.setContextKey(contextKey),\n\t\t};\n\t\tthis.updateStyles();\n\t\treturn this.ui;\n\t}\n\n\tpick>(picks: Promise[]> | QuickPickInput[], options: O = {}, token: CancellationToken = CancellationToken.None): Promise<(O extends { canPickMany: true } ? T[] : T) | undefined> {\n\t\ttype R = (O extends { canPickMany: true } ? T[] : T) | undefined;\n\t\treturn new Promise((doResolve, reject) => {\n\t\t\tlet resolve = (result: R) => {\n\t\t\t\tresolve = doResolve;\n\t\t\t\tif (options.onKeyMods) {\n\t\t\t\t\toptions.onKeyMods(input.keyMods);\n\t\t\t\t}\n\t\t\t\tdoResolve(result);\n\t\t\t};\n\t\t\tif (token.isCancellationRequested) {\n\t\t\t\tresolve(undefined);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst input = this.createQuickPick();\n\t\t\tlet activeItem: T | undefined;\n\t\t\tconst disposables = [\n\t\t\t\tinput,\n\t\t\t\tinput.onDidAccept(() => {\n\t\t\t\t\tif (input.canSelectMany) {\n\t\t\t\t\t\tresolve(input.selectedItems.slice());\n\t\t\t\t\t\tinput.hide();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst result = input.activeItems[0];\n\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\tresolve(result);\n\t\t\t\t\t\t\tinput.hide();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\tinput.onDidChangeActive(items => {\n\t\t\t\t\tconst focused = items[0];\n\t\t\t\t\tif (focused && options.onDidFocus) {\n\t\t\t\t\t\toptions.onDidFocus(focused);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\tinput.onDidChangeSelection(items => {\n\t\t\t\t\tif (!input.canSelectMany) {\n\t\t\t\t\t\tconst result = items[0];\n\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\tresolve(result);\n\t\t\t\t\t\t\tinput.hide();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\tinput.onDidTriggerItemButton(event => options.onDidTriggerItemButton && options.onDidTriggerItemButton({\n\t\t\t\t\t...event,\n\t\t\t\t\tremoveItem: () => {\n\t\t\t\t\t\tconst index = input.items.indexOf(event.item);\n\t\t\t\t\t\tif (index !== -1) {\n\t\t\t\t\t\t\tconst items = input.items.slice();\n\t\t\t\t\t\t\tconst removed = items.splice(index, 1);\n\t\t\t\t\t\t\tconst activeItems = input.activeItems.filter(activeItem => activeItem !== removed[0]);\n\t\t\t\t\t\t\tconst keepScrollPositionBefore = input.keepScrollPosition;\n\t\t\t\t\t\t\tinput.keepScrollPosition = true;\n\t\t\t\t\t\t\tinput.items = items;\n\t\t\t\t\t\t\tif (activeItems) {\n\t\t\t\t\t\t\t\tinput.activeItems = activeItems;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tinput.keepScrollPosition = keepScrollPositionBefore;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})),\n\t\t\t\tinput.onDidChangeValue(value => {\n\t\t\t\t\tif (activeItem && !value && (input.activeItems.length !== 1 || input.activeItems[0] !== activeItem)) {\n\t\t\t\t\t\tinput.activeItems = [activeItem];\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\ttoken.onCancellationRequested(() => {\n\t\t\t\t\tinput.hide();\n\t\t\t\t}),\n\t\t\t\tinput.onDidHide(() => {\n\t\t\t\t\tdispose(disposables);\n\t\t\t\t\tresolve(undefined);\n\t\t\t\t}),\n\t\t\t];\n\t\t\tinput.title = options.title;\n\t\t\tinput.canSelectMany = !!options.canPickMany;\n\t\t\tinput.placeholder = options.placeHolder;\n\t\t\tinput.ignoreFocusOut = !!options.ignoreFocusLost;\n\t\t\tinput.matchOnDescription = !!options.matchOnDescription;\n\t\t\tinput.matchOnDetail = !!options.matchOnDetail;\n\t\t\tinput.matchOnLabel = (options.matchOnLabel === undefined) || options.matchOnLabel; // default to true\n\t\t\tinput.autoFocusOnList = (options.autoFocusOnList === undefined) || options.autoFocusOnList; // default to true\n\t\t\tinput.quickNavigate = options.quickNavigate;\n\t\t\tinput.contextKey = options.contextKey;\n\t\t\tinput.busy = true;\n\t\t\tPromise.all([picks, options.activeItem])\n\t\t\t\t.then(([items, _activeItem]) => {\n\t\t\t\t\tactiveItem = _activeItem;\n\t\t\t\t\tinput.busy = false;\n\t\t\t\t\tinput.items = items;\n\t\t\t\t\tif (input.canSelectMany) {\n\t\t\t\t\t\tinput.selectedItems = items.filter(item => item.type !== 'separator' && item.picked) as T[];\n\t\t\t\t\t}\n\t\t\t\t\tif (activeItem) {\n\t\t\t\t\t\tinput.activeItems = [activeItem];\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\tinput.show();\n\t\t\tPromise.resolve(picks).then(undefined, err => {\n\t\t\t\treject(err);\n\t\t\t\tinput.hide();\n\t\t\t});\n\t\t});\n\t}\n\n\tcreateQuickPick(): IQuickPick {\n\t\tconst ui = this.getUI();\n\t\treturn new QuickPick(ui);\n\t}\n\n\tprivate show(controller: QuickInput) {\n\t\tconst ui = this.getUI();\n\t\tthis.onShowEmitter.fire();\n\t\tconst oldController = this.controller;\n\t\tthis.controller = controller;\n\t\tif (oldController) {\n\t\t\toldController.didHide();\n\t\t}\n\n\t\tthis.setEnabled(true);\n\t\tui.leftActionBar.clear();\n\t\tui.title.textContent = '';\n\t\tui.description1.textContent = '';\n\t\tui.description2.textContent = '';\n\t\tui.rightActionBar.clear();\n\t\tui.checkAll.checked = false;\n\t\t// ui.inputBox.value = ''; Avoid triggering an event.\n\t\tui.inputBox.placeholder = '';\n\t\tui.inputBox.password = false;\n\t\tui.inputBox.showDecoration(Severity.Ignore);\n\t\tui.visibleCount.setCount(0);\n\t\tui.count.setCount(0);\n\t\tdom.reset(ui.message);\n\t\tui.progressBar.stop();\n\t\tui.list.setElements([]);\n\t\tui.list.matchOnDescription = false;\n\t\tui.list.matchOnDetail = false;\n\t\tui.list.matchOnLabel = true;\n\t\tui.list.sortByLabel = true;\n\t\tui.ignoreFocusOut = false;\n\t\tthis.setComboboxAccessibility(false);\n\t\tui.inputBox.ariaLabel = '';\n\n\t\tconst backKeybindingLabel = this.options.backKeybindingLabel();\n\t\tbackButton.tooltip = backKeybindingLabel ? localize('quickInput.backWithKeybinding', \"Back ({0})\", backKeybindingLabel) : localize('quickInput.back', \"Back\");\n\n\t\tui.container.style.display = '';\n\t\tthis.updateLayout();\n\t\tui.inputBox.setFocus();\n\t}\n\n\tprivate setVisibilities(visibilities: Visibilities) {\n\t\tconst ui = this.getUI();\n\t\tui.title.style.display = visibilities.title ? '' : 'none';\n\t\tui.description1.style.display = visibilities.description && (visibilities.inputBox || visibilities.checkAll) ? '' : 'none';\n\t\tui.description2.style.display = visibilities.description && !(visibilities.inputBox || visibilities.checkAll) ? '' : 'none';\n\t\tui.checkAll.style.display = visibilities.checkAll ? '' : 'none';\n\t\tui.filterContainer.style.display = visibilities.inputBox ? '' : 'none';\n\t\tui.visibleCountContainer.style.display = visibilities.visibleCount ? '' : 'none';\n\t\tui.countContainer.style.display = visibilities.count ? '' : 'none';\n\t\tui.okContainer.style.display = visibilities.ok ? '' : 'none';\n\t\tui.customButtonContainer.style.display = visibilities.customButton ? '' : 'none';\n\t\tui.message.style.display = visibilities.message ? '' : 'none';\n\t\tui.progressBar.getContainer().style.display = visibilities.progressBar ? '' : 'none';\n\t\tui.list.display(!!visibilities.list);\n\t\tui.container.classList[visibilities.checkBox ? 'add' : 'remove']('show-checkboxes');\n\t\tthis.updateLayout(); // TODO\n\t}\n\n\tprivate setComboboxAccessibility(enabled: boolean) {\n\t\tif (enabled !== this.comboboxAccessibility) {\n\t\t\tconst ui = this.getUI();\n\t\t\tthis.comboboxAccessibility = enabled;\n\t\t\tif (this.comboboxAccessibility) {\n\t\t\t\tui.inputBox.setAttribute('role', 'combobox');\n\t\t\t\tui.inputBox.setAttribute('aria-haspopup', 'true');\n\t\t\t\tui.inputBox.setAttribute('aria-autocomplete', 'list');\n\t\t\t\tui.inputBox.setAttribute('aria-activedescendant', ui.list.getActiveDescendant() || '');\n\t\t\t} else {\n\t\t\t\tui.inputBox.removeAttribute('role');\n\t\t\t\tui.inputBox.removeAttribute('aria-haspopup');\n\t\t\t\tui.inputBox.removeAttribute('aria-autocomplete');\n\t\t\t\tui.inputBox.removeAttribute('aria-activedescendant');\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate setEnabled(enabled: boolean) {\n\t\tif (enabled !== this.enabled) {\n\t\t\tthis.enabled = enabled;\n\t\t\tfor (const item of this.getUI().leftActionBar.viewItems) {\n\t\t\t\t(item as ActionViewItem).getAction().enabled = enabled;\n\t\t\t}\n\t\t\tfor (const item of this.getUI().rightActionBar.viewItems) {\n\t\t\t\t(item as ActionViewItem).getAction().enabled = enabled;\n\t\t\t}\n\t\t\tthis.getUI().checkAll.disabled = !enabled;\n\t\t\t// this.getUI().inputBox.enabled = enabled; Avoid loosing focus.\n\t\t\tthis.getUI().ok.enabled = enabled;\n\t\t\tthis.getUI().list.enabled = enabled;\n\t\t}\n\t}\n\n\thide(reason?: QuickInputHideReason) {\n\t\tconst controller = this.controller;\n\t\tif (controller) {\n\t\t\tconst focusChanged = !this.ui?.container.contains(document.activeElement);\n\t\t\tthis.controller = null;\n\t\t\tthis.onHideEmitter.fire();\n\t\t\tthis.getUI().container.style.display = 'none';\n\t\t\tif (!focusChanged) {\n\t\t\t\tlet currentElement = this.previousFocusElement;\n\t\t\t\twhile (currentElement && !currentElement.offsetParent) {\n\t\t\t\t\tcurrentElement = withNullAsUndefined(currentElement.parentElement);\n\t\t\t\t}\n\t\t\t\tif (currentElement?.offsetParent) {\n\t\t\t\t\tcurrentElement.focus();\n\t\t\t\t\tthis.previousFocusElement = undefined;\n\t\t\t\t} else {\n\t\t\t\t\tthis.options.returnFocus();\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontroller.didHide(reason);\n\t\t}\n\t}\n\n\tlayout(dimension: dom.IDimension, titleBarOffset: number): void {\n\t\tthis.dimension = dimension;\n\t\tthis.titleBarOffset = titleBarOffset;\n\t\tthis.updateLayout();\n\t}\n\n\tprivate updateLayout() {\n\t\tif (this.ui) {\n\t\t\tthis.ui.container.style.top = `${this.titleBarOffset}px`;\n\n\t\t\tconst style = this.ui.container.style;\n\t\t\tconst width = Math.min(this.dimension!.width * 0.62 /* golden cut */, QuickInputController.MAX_WIDTH);\n\t\t\tstyle.width = width + 'px';\n\t\t\tstyle.marginLeft = '-' + (width / 2) + 'px';\n\n\t\t\tthis.ui.inputBox.layout();\n\t\t\tthis.ui.list.layout(this.dimension && this.dimension.height * 0.4);\n\t\t}\n\t}\n\n\tapplyStyles(styles: IQuickInputStyles) {\n\t\tthis.styles = styles;\n\t\tthis.updateStyles();\n\t}\n\n\tprivate updateStyles() {\n\t\tif (this.ui) {\n\t\t\tconst {\n\t\t\t\tquickInputTitleBackground,\n\t\t\t\tquickInputBackground,\n\t\t\t\tquickInputForeground,\n\t\t\t\tcontrastBorder,\n\t\t\t\twidgetShadow,\n\t\t\t} = this.styles.widget;\n\t\t\tthis.ui.titleBar.style.backgroundColor = quickInputTitleBackground ? quickInputTitleBackground.toString() : '';\n\t\t\tthis.ui.container.style.backgroundColor = quickInputBackground ? quickInputBackground.toString() : '';\n\t\t\tthis.ui.container.style.color = quickInputForeground ? quickInputForeground.toString() : '';\n\t\t\tthis.ui.container.style.border = contrastBorder ? `1px solid ${contrastBorder}` : '';\n\t\t\tthis.ui.container.style.boxShadow = widgetShadow ? `0 0 8px 2px ${widgetShadow}` : '';\n\t\t\tthis.ui.inputBox.style(this.styles.inputBox);\n\t\t\tthis.ui.count.style(this.styles.countBadge);\n\t\t\tthis.ui.ok.style(this.styles.button);\n\t\t\tthis.ui.customButton.style(this.styles.button);\n\t\t\tthis.ui.progressBar.style(this.styles.progressBar);\n\t\t\tthis.ui.list.style(this.styles.list);\n\n\t\t\tconst content: string[] = [];\n\t\t\tif (this.styles.list.pickerGroupBorder) {\n\t\t\t\tcontent.push(`.quick-input-list .quick-input-list-entry { border-top-color: ${this.styles.list.pickerGroupBorder}; }`);\n\t\t\t}\n\t\t\tif (this.styles.list.pickerGroupForeground) {\n\t\t\t\tcontent.push(`.quick-input-list .quick-input-list-separator { color: ${this.styles.list.pickerGroupForeground}; }`);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tthis.styles.keybindingLabel.keybindingLabelBackground ||\n\t\t\t\tthis.styles.keybindingLabel.keybindingLabelBorder ||\n\t\t\t\tthis.styles.keybindingLabel.keybindingLabelBottomBorder ||\n\t\t\t\tthis.styles.keybindingLabel.keybindingLabelShadow ||\n\t\t\t\tthis.styles.keybindingLabel.keybindingLabelForeground\n\t\t\t) {\n\t\t\t\tcontent.push('.quick-input-list .monaco-keybinding > .monaco-keybinding-key {');\n\t\t\t\tif (this.styles.keybindingLabel.keybindingLabelBackground) {\n\t\t\t\t\tcontent.push(`background-color: ${this.styles.keybindingLabel.keybindingLabelBackground};`);\n\t\t\t\t}\n\t\t\t\tif (this.styles.keybindingLabel.keybindingLabelBorder) {\n\t\t\t\t\t// Order matters here. `border-color` must come before `border-bottom-color`.\n\t\t\t\t\tcontent.push(`border-color: ${this.styles.keybindingLabel.keybindingLabelBorder};`);\n\t\t\t\t}\n\t\t\t\tif (this.styles.keybindingLabel.keybindingLabelBottomBorder) {\n\t\t\t\t\tcontent.push(`border-bottom-color: ${this.styles.keybindingLabel.keybindingLabelBottomBorder};`);\n\t\t\t\t}\n\t\t\t\tif (this.styles.keybindingLabel.keybindingLabelShadow) {\n\t\t\t\t\tcontent.push(`box-shadow: inset 0 -1px 0 ${this.styles.keybindingLabel.keybindingLabelShadow};`);\n\t\t\t\t}\n\t\t\t\tif (this.styles.keybindingLabel.keybindingLabelForeground) {\n\t\t\t\t\tcontent.push(`color: ${this.styles.keybindingLabel.keybindingLabelForeground};`);\n\t\t\t\t}\n\t\t\t\tcontent.push('}');\n\t\t\t}\n\n\t\t\tconst newStyles = content.join('\\n');\n\t\t\tif (newStyles !== this.ui.styleSheet.textContent) {\n\t\t\t\tthis.ui.styleSheet.textContent = newStyles;\n\t\t\t}\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as nls from 'vs/nls';\nimport * as dom from 'vs/base/browser/dom';\nimport { Action } from 'vs/base/common/actions';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { IContextMenuService } from 'vs/platform/contextview/browser/contextView';\nimport { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';\nimport { IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';\nimport { Range } from 'vs/editor/common/core/range';\nimport { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { Codicon } from 'vs/base/common/codicons';\nimport { EndOfLineSequence, ITextModel } from 'vs/editor/common/model';\n\nexport interface IDiffLinesChange {\n\treadonly originalStartLineNumber: number;\n\treadonly originalEndLineNumber: number;\n\treadonly modifiedStartLineNumber: number;\n\treadonly modifiedEndLineNumber: number;\n\treadonly originalModel: ITextModel;\n\tviewLineCounts: number[] | null;\n}\n\nexport class InlineDiffMargin extends Disposable {\n\tprivate readonly _diffActions: HTMLElement;\n\n\tprivate _visibility: boolean = false;\n\n\tget visibility(): boolean {\n\t\treturn this._visibility;\n\t}\n\n\tset visibility(_visibility: boolean) {\n\t\tif (this._visibility !== _visibility) {\n\t\t\tthis._visibility = _visibility;\n\n\t\t\tif (_visibility) {\n\t\t\t\tthis._diffActions.style.visibility = 'visible';\n\t\t\t} else {\n\t\t\t\tthis._diffActions.style.visibility = 'hidden';\n\t\t\t}\n\t\t}\n\t}\n\n\tconstructor(\n\t\tprivate readonly _viewZoneId: string,\n\t\tprivate readonly _marginDomNode: HTMLElement,\n\t\tpublic readonly editor: CodeEditorWidget,\n\t\tpublic readonly diff: IDiffLinesChange,\n\t\tprivate readonly _contextMenuService: IContextMenuService,\n\t\tprivate readonly _clipboardService: IClipboardService\n\t) {\n\t\tsuper();\n\n\t\t// make sure the diff margin shows above overlay.\n\t\tthis._marginDomNode.style.zIndex = '10';\n\n\t\tthis._diffActions = document.createElement('div');\n\t\tthis._diffActions.className = Codicon.lightBulb.classNames + ' lightbulb-glyph';\n\t\tthis._diffActions.style.position = 'absolute';\n\t\tconst lineHeight = editor.getOption(EditorOption.lineHeight);\n\t\tconst lineFeed = editor.getModel()!.getEOL();\n\t\tthis._diffActions.style.right = '0px';\n\t\tthis._diffActions.style.visibility = 'hidden';\n\t\tthis._diffActions.style.height = `${lineHeight}px`;\n\t\tthis._diffActions.style.lineHeight = `${lineHeight}px`;\n\t\tthis._marginDomNode.appendChild(this._diffActions);\n\n\t\tconst actions: Action[] = [];\n\t\tconst isDeletion = diff.modifiedEndLineNumber === 0;\n\n\t\t// default action\n\t\tactions.push(new Action(\n\t\t\t'diff.clipboard.copyDeletedContent',\n\t\t\tisDeletion\n\t\t\t\t? (diff.originalEndLineNumber > diff.modifiedStartLineNumber\n\t\t\t\t\t? nls.localize('diff.clipboard.copyDeletedLinesContent.label', \"Copy deleted lines\")\n\t\t\t\t\t: nls.localize('diff.clipboard.copyDeletedLinesContent.single.label', \"Copy deleted line\"))\n\t\t\t\t: (diff.originalEndLineNumber > diff.modifiedStartLineNumber\n\t\t\t\t\t? nls.localize('diff.clipboard.copyChangedLinesContent.label', \"Copy changed lines\")\n\t\t\t\t\t: nls.localize('diff.clipboard.copyChangedLinesContent.single.label', \"Copy changed line\")),\n\t\t\tundefined,\n\t\t\ttrue,\n\t\t\tasync () => {\n\t\t\t\tconst range = new Range(diff.originalStartLineNumber, 1, diff.originalEndLineNumber + 1, 1);\n\t\t\t\tconst deletedText = diff.originalModel.getValueInRange(range);\n\t\t\t\tawait this._clipboardService.writeText(deletedText);\n\t\t\t}\n\t\t));\n\n\t\tlet currentLineNumberOffset = 0;\n\t\tlet copyLineAction: Action | undefined = undefined;\n\t\tif (diff.originalEndLineNumber > diff.modifiedStartLineNumber) {\n\t\t\tcopyLineAction = new Action(\n\t\t\t\t'diff.clipboard.copyDeletedLineContent',\n\t\t\t\tisDeletion\n\t\t\t\t\t? nls.localize('diff.clipboard.copyDeletedLineContent.label', \"Copy deleted line ({0})\", diff.originalStartLineNumber)\n\t\t\t\t\t: nls.localize('diff.clipboard.copyChangedLineContent.label', \"Copy changed line ({0})\", diff.originalStartLineNumber),\n\t\t\t\tundefined,\n\t\t\t\ttrue,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst lineContent = diff.originalModel.getLineContent(diff.originalStartLineNumber + currentLineNumberOffset);\n\t\t\t\t\tif (lineContent === '') {\n\t\t\t\t\t\t// empty line\n\t\t\t\t\t\tconst eof = diff.originalModel.getEndOfLineSequence();\n\t\t\t\t\t\tawait this._clipboardService.writeText(eof === EndOfLineSequence.LF ? '\\n' : '\\r\\n');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this._clipboardService.writeText(lineContent);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\n\t\t\tactions.push(copyLineAction);\n\t\t}\n\n\t\tconst readOnly = editor.getOption(EditorOption.readOnly);\n\t\tif (!readOnly) {\n\t\t\tactions.push(new Action('diff.inline.revertChange', nls.localize('diff.inline.revertChange.label', \"Revert this change\"), undefined, true, async () => {\n\t\t\t\tconst range = new Range(diff.originalStartLineNumber, 1, diff.originalEndLineNumber, diff.originalModel.getLineMaxColumn(diff.originalEndLineNumber));\n\t\t\t\tconst deletedText = diff.originalModel.getValueInRange(range);\n\t\t\t\tif (diff.modifiedEndLineNumber === 0) {\n\t\t\t\t\t// deletion only\n\t\t\t\t\tconst column = editor.getModel()!.getLineMaxColumn(diff.modifiedStartLineNumber);\n\t\t\t\t\teditor.executeEdits('diffEditor', [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trange: new Range(diff.modifiedStartLineNumber, column, diff.modifiedStartLineNumber, column),\n\t\t\t\t\t\t\ttext: lineFeed + deletedText\n\t\t\t\t\t\t}\n\t\t\t\t\t]);\n\t\t\t\t} else {\n\t\t\t\t\tconst column = editor.getModel()!.getLineMaxColumn(diff.modifiedEndLineNumber);\n\t\t\t\t\teditor.executeEdits('diffEditor', [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trange: new Range(diff.modifiedStartLineNumber, 1, diff.modifiedEndLineNumber, column),\n\t\t\t\t\t\t\ttext: deletedText\n\t\t\t\t\t\t}\n\t\t\t\t\t]);\n\t\t\t\t}\n\n\t\t\t}));\n\t\t}\n\n\t\tconst showContextMenu = (x: number, y: number) => {\n\t\t\tthis._contextMenuService.showContextMenu({\n\t\t\t\tgetAnchor: () => {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tx,\n\t\t\t\t\t\ty\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\tgetActions: () => {\n\t\t\t\t\tif (copyLineAction) {\n\t\t\t\t\t\tcopyLineAction.label =\n\t\t\t\t\t\t\tisDeletion\n\t\t\t\t\t\t\t\t? nls.localize('diff.clipboard.copyDeletedLineContent.label', \"Copy deleted line ({0})\", diff.originalStartLineNumber + currentLineNumberOffset)\n\t\t\t\t\t\t\t\t: nls.localize('diff.clipboard.copyChangedLineContent.label', \"Copy changed line ({0})\", diff.originalStartLineNumber + currentLineNumberOffset);\n\t\t\t\t\t}\n\t\t\t\t\treturn actions;\n\t\t\t\t},\n\t\t\t\tautoSelectFirstItem: true\n\t\t\t});\n\t\t};\n\n\t\tthis._register(dom.addStandardDisposableListener(this._diffActions, 'mousedown', e => {\n\t\t\tconst { top, height } = dom.getDomNodePagePosition(this._diffActions);\n\t\t\tconst pad = Math.floor(lineHeight / 3);\n\t\t\te.preventDefault();\n\n\t\t\tshowContextMenu(e.posx, top + height + pad);\n\n\t\t}));\n\n\t\tthis._register(editor.onMouseMove((e: IEditorMouseEvent) => {\n\t\t\tif (e.target.type === MouseTargetType.CONTENT_VIEW_ZONE || e.target.type === MouseTargetType.GUTTER_VIEW_ZONE) {\n\t\t\t\tconst viewZoneId = e.target.detail.viewZoneId;\n\n\t\t\t\tif (viewZoneId === this._viewZoneId) {\n\t\t\t\t\tthis.visibility = true;\n\t\t\t\t\tcurrentLineNumberOffset = this._updateLightBulbPosition(this._marginDomNode, e.event.browserEvent.y, lineHeight);\n\t\t\t\t} else {\n\t\t\t\t\tthis.visibility = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.visibility = false;\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(editor.onMouseDown((e: IEditorMouseEvent) => {\n\t\t\tif (!e.event.rightButton) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (e.target.type === MouseTargetType.CONTENT_VIEW_ZONE || e.target.type === MouseTargetType.GUTTER_VIEW_ZONE) {\n\t\t\t\tconst viewZoneId = e.target.detail.viewZoneId;\n\n\t\t\t\tif (viewZoneId === this._viewZoneId) {\n\t\t\t\t\te.event.preventDefault();\n\t\t\t\t\tcurrentLineNumberOffset = this._updateLightBulbPosition(this._marginDomNode, e.event.browserEvent.y, lineHeight);\n\t\t\t\t\tshowContextMenu(e.event.posx, e.event.posy + lineHeight);\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\t}\n\n\tprivate _updateLightBulbPosition(marginDomNode: HTMLElement, y: number, lineHeight: number): number {\n\t\tconst { top } = dom.getDomNodePagePosition(marginDomNode);\n\t\tconst offset = y - top;\n\t\tconst lineNumberOffset = Math.floor(offset / lineHeight);\n\t\tconst newTop = lineNumberOffset * lineHeight;\n\t\tthis._diffActions.style.top = `${newTop}px`;\n\t\tif (this.diff.viewLineCounts) {\n\t\t\tlet acc = 0;\n\t\t\tfor (let i = 0; i < this.diff.viewLineCounts.length; i++) {\n\t\t\t\tacc += this.diff.viewLineCounts[i];\n\t\t\t\tif (lineNumberOffset < acc) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn lineNumberOffset;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as nls from 'vs/nls';\nimport * as platform from 'vs/base/common/platform';\nimport { ScrollbarVisibility } from 'vs/base/common/scrollable';\nimport { FontInfo } from 'vs/editor/common/config/fontInfo';\nimport { Constants } from 'vs/base/common/uint';\nimport { USUAL_WORD_SEPARATORS } from 'vs/editor/common/core/wordHelper';\nimport { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';\nimport { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';\nimport { IJSONSchema } from 'vs/base/common/jsonSchema';\nimport * as arrays from 'vs/base/common/arrays';\nimport * as objects from 'vs/base/common/objects';\nimport { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/core/textModelDefaults';\n\n//#region typed options\n\n/**\n * Configuration options for auto closing quotes and brackets\n */\nexport type EditorAutoClosingStrategy = 'always' | 'languageDefined' | 'beforeWhitespace' | 'never';\n\n/**\n * Configuration options for auto wrapping quotes and brackets\n */\nexport type EditorAutoSurroundStrategy = 'languageDefined' | 'quotes' | 'brackets' | 'never';\n\n/**\n * Configuration options for typing over closing quotes or brackets\n */\nexport type EditorAutoClosingEditStrategy = 'always' | 'auto' | 'never';\n\n/**\n * Configuration options for auto indentation in the editor\n */\nexport const enum EditorAutoIndentStrategy {\n\tNone = 0,\n\tKeep = 1,\n\tBrackets = 2,\n\tAdvanced = 3,\n\tFull = 4\n}\n\n/**\n * Configuration options for the editor.\n */\nexport interface IEditorOptions {\n\t/**\n\t * This editor is used inside a diff editor.\n\t */\n\tinDiffEditor?: boolean;\n\t/**\n\t * The aria label for the editor's textarea (when it is focused).\n\t */\n\tariaLabel?: string;\n\t/**\n\t * The `tabindex` property of the editor's textarea\n\t */\n\ttabIndex?: number;\n\t/**\n\t * Render vertical lines at the specified columns.\n\t * Defaults to empty array.\n\t */\n\trulers?: (number | IRulerOption)[];\n\t/**\n\t * A string containing the word separators used when doing word navigation.\n\t * Defaults to `~!@#$%^&*()-=+[{]}\\\\|;:\\'\",.<>/?\n\t */\n\twordSeparators?: string;\n\t/**\n\t * Enable Linux primary clipboard.\n\t * Defaults to true.\n\t */\n\tselectionClipboard?: boolean;\n\t/**\n\t * Control the rendering of line numbers.\n\t * If it is a function, it will be invoked when rendering a line number and the return value will be rendered.\n\t * Otherwise, if it is a truthy, line numbers will be rendered normally (equivalent of using an identity function).\n\t * Otherwise, line numbers will not be rendered.\n\t * Defaults to `on`.\n\t */\n\tlineNumbers?: LineNumbersType;\n\t/**\n\t * Controls the minimal number of visible leading and trailing lines surrounding the cursor.\n\t * Defaults to 0.\n\t*/\n\tcursorSurroundingLines?: number;\n\t/**\n\t * Controls when `cursorSurroundingLines` should be enforced\n\t * Defaults to `default`, `cursorSurroundingLines` is not enforced when cursor position is changed\n\t * by mouse.\n\t*/\n\tcursorSurroundingLinesStyle?: 'default' | 'all';\n\t/**\n\t * Render last line number when the file ends with a newline.\n\t * Defaults to true.\n\t*/\n\trenderFinalNewline?: boolean;\n\t/**\n\t * Remove unusual line terminators like LINE SEPARATOR (LS), PARAGRAPH SEPARATOR (PS).\n\t * Defaults to 'prompt'.\n\t */\n\tunusualLineTerminators?: 'auto' | 'off' | 'prompt';\n\t/**\n\t * Should the corresponding line be selected when clicking on the line number?\n\t * Defaults to true.\n\t */\n\tselectOnLineNumbers?: boolean;\n\t/**\n\t * Control the width of line numbers, by reserving horizontal space for rendering at least an amount of digits.\n\t * Defaults to 5.\n\t */\n\tlineNumbersMinChars?: number;\n\t/**\n\t * Enable the rendering of the glyph margin.\n\t * Defaults to true in vscode and to false in monaco-editor.\n\t */\n\tglyphMargin?: boolean;\n\t/**\n\t * The width reserved for line decorations (in px).\n\t * Line decorations are placed between line numbers and the editor content.\n\t * You can pass in a string in the format floating point followed by \"ch\". e.g. 1.3ch.\n\t * Defaults to 10.\n\t */\n\tlineDecorationsWidth?: number | string;\n\t/**\n\t * When revealing the cursor, a virtual padding (px) is added to the cursor, turning it into a rectangle.\n\t * This virtual padding ensures that the cursor gets revealed before hitting the edge of the viewport.\n\t * Defaults to 30 (px).\n\t */\n\trevealHorizontalRightPadding?: number;\n\t/**\n\t * Render the editor selection with rounded borders.\n\t * Defaults to true.\n\t */\n\troundedSelection?: boolean;\n\t/**\n\t * Class name to be added to the editor.\n\t */\n\textraEditorClassName?: string;\n\t/**\n\t * Should the editor be read only. See also `domReadOnly`.\n\t * Defaults to false.\n\t */\n\treadOnly?: boolean;\n\t/**\n\t * Should the textarea used for input use the DOM `readonly` attribute.\n\t * Defaults to false.\n\t */\n\tdomReadOnly?: boolean;\n\t/**\n\t * Enable linked editing.\n\t * Defaults to false.\n\t */\n\tlinkedEditing?: boolean;\n\t/**\n\t * deprecated, use linkedEditing instead\n\t */\n\trenameOnType?: boolean;\n\t/**\n\t * Should the editor render validation decorations.\n\t * Defaults to editable.\n\t */\n\trenderValidationDecorations?: 'editable' | 'on' | 'off';\n\t/**\n\t * Control the behavior and rendering of the scrollbars.\n\t */\n\tscrollbar?: IEditorScrollbarOptions;\n\t/**\n\t * Control the behavior and rendering of the minimap.\n\t */\n\tminimap?: IEditorMinimapOptions;\n\t/**\n\t * Control the behavior of the find widget.\n\t */\n\tfind?: IEditorFindOptions;\n\t/**\n\t * Display overflow widgets as `fixed`.\n\t * Defaults to `false`.\n\t */\n\tfixedOverflowWidgets?: boolean;\n\t/**\n\t * The number of vertical lanes the overview ruler should render.\n\t * Defaults to 3.\n\t */\n\toverviewRulerLanes?: number;\n\t/**\n\t * Controls if a border should be drawn around the overview ruler.\n\t * Defaults to `true`.\n\t */\n\toverviewRulerBorder?: boolean;\n\t/**\n\t * Control the cursor animation style, possible values are 'blink', 'smooth', 'phase', 'expand' and 'solid'.\n\t * Defaults to 'blink'.\n\t */\n\tcursorBlinking?: 'blink' | 'smooth' | 'phase' | 'expand' | 'solid';\n\t/**\n\t * Zoom the font in the editor when using the mouse wheel in combination with holding Ctrl.\n\t * Defaults to false.\n\t */\n\tmouseWheelZoom?: boolean;\n\t/**\n\t * Control the mouse pointer style, either 'text' or 'default' or 'copy'\n\t * Defaults to 'text'\n\t */\n\tmouseStyle?: 'text' | 'default' | 'copy';\n\t/**\n\t * Enable smooth caret animation.\n\t * Defaults to false.\n\t */\n\tcursorSmoothCaretAnimation?: boolean;\n\t/**\n\t * Control the cursor style, either 'block' or 'line'.\n\t * Defaults to 'line'.\n\t */\n\tcursorStyle?: 'line' | 'block' | 'underline' | 'line-thin' | 'block-outline' | 'underline-thin';\n\t/**\n\t * Control the width of the cursor when cursorStyle is set to 'line'\n\t */\n\tcursorWidth?: number;\n\t/**\n\t * Enable font ligatures.\n\t * Defaults to false.\n\t */\n\tfontLigatures?: boolean | string;\n\t/**\n\t * Disable the use of `transform: translate3d(0px, 0px, 0px)` for the editor margin and lines layers.\n\t * The usage of `transform: translate3d(0px, 0px, 0px)` acts as a hint for browsers to create an extra layer.\n\t * Defaults to false.\n\t */\n\tdisableLayerHinting?: boolean;\n\t/**\n\t * Disable the optimizations for monospace fonts.\n\t * Defaults to false.\n\t */\n\tdisableMonospaceOptimizations?: boolean;\n\t/**\n\t * Should the cursor be hidden in the overview ruler.\n\t * Defaults to false.\n\t */\n\thideCursorInOverviewRuler?: boolean;\n\t/**\n\t * Enable that scrolling can go one screen size after the last line.\n\t * Defaults to true.\n\t */\n\tscrollBeyondLastLine?: boolean;\n\t/**\n\t * Enable that scrolling can go beyond the last column by a number of columns.\n\t * Defaults to 5.\n\t */\n\tscrollBeyondLastColumn?: number;\n\t/**\n\t * Enable that the editor animates scrolling to a position.\n\t * Defaults to false.\n\t */\n\tsmoothScrolling?: boolean;\n\t/**\n\t * Enable that the editor will install an interval to check if its container dom node size has changed.\n\t * Enabling this might have a severe performance impact.\n\t * Defaults to false.\n\t */\n\tautomaticLayout?: boolean;\n\t/**\n\t * Control the wrapping of the editor.\n\t * When `wordWrap` = \"off\", the lines will never wrap.\n\t * When `wordWrap` = \"on\", the lines will wrap at the viewport width.\n\t * When `wordWrap` = \"wordWrapColumn\", the lines will wrap at `wordWrapColumn`.\n\t * When `wordWrap` = \"bounded\", the lines will wrap at min(viewport width, wordWrapColumn).\n\t * Defaults to \"off\".\n\t */\n\twordWrap?: 'off' | 'on' | 'wordWrapColumn' | 'bounded';\n\t/**\n\t * Override the `wordWrap` setting.\n\t */\n\twordWrapOverride1?: 'off' | 'on' | 'inherit';\n\t/**\n\t * Override the `wordWrapOverride1` setting.\n\t */\n\twordWrapOverride2?: 'off' | 'on' | 'inherit';\n\t/**\n\t * Control the wrapping of the editor.\n\t * When `wordWrap` = \"off\", the lines will never wrap.\n\t * When `wordWrap` = \"on\", the lines will wrap at the viewport width.\n\t * When `wordWrap` = \"wordWrapColumn\", the lines will wrap at `wordWrapColumn`.\n\t * When `wordWrap` = \"bounded\", the lines will wrap at min(viewport width, wordWrapColumn).\n\t * Defaults to 80.\n\t */\n\twordWrapColumn?: number;\n\t/**\n\t * Control indentation of wrapped lines. Can be: 'none', 'same', 'indent' or 'deepIndent'.\n\t * Defaults to 'same' in vscode and to 'none' in monaco-editor.\n\t */\n\twrappingIndent?: 'none' | 'same' | 'indent' | 'deepIndent';\n\t/**\n\t * Controls the wrapping strategy to use.\n\t * Defaults to 'simple'.\n\t */\n\twrappingStrategy?: 'simple' | 'advanced';\n\t/**\n\t * Configure word wrapping characters. A break will be introduced before these characters.\n\t */\n\twordWrapBreakBeforeCharacters?: string;\n\t/**\n\t * Configure word wrapping characters. A break will be introduced after these characters.\n\t */\n\twordWrapBreakAfterCharacters?: string;\n\t/**\n\t * Performance guard: Stop rendering a line after x characters.\n\t * Defaults to 10000.\n\t * Use -1 to never stop rendering\n\t */\n\tstopRenderingLineAfter?: number;\n\t/**\n\t * Configure the editor's hover.\n\t */\n\thover?: IEditorHoverOptions;\n\t/**\n\t * Enable detecting links and making them clickable.\n\t * Defaults to true.\n\t */\n\tlinks?: boolean;\n\t/**\n\t * Enable inline color decorators and color picker rendering.\n\t */\n\tcolorDecorators?: boolean;\n\t/**\n\t * Control the behaviour of comments in the editor.\n\t */\n\tcomments?: IEditorCommentsOptions;\n\t/**\n\t * Enable custom contextmenu.\n\t * Defaults to true.\n\t */\n\tcontextmenu?: boolean;\n\t/**\n\t * A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.\n\t * Defaults to 1.\n\t */\n\tmouseWheelScrollSensitivity?: number;\n\t/**\n\t * FastScrolling mulitplier speed when pressing `Alt`\n\t * Defaults to 5.\n\t */\n\tfastScrollSensitivity?: number;\n\t/**\n\t * Enable that the editor scrolls only the predominant axis. Prevents horizontal drift when scrolling vertically on a trackpad.\n\t * Defaults to true.\n\t */\n\tscrollPredominantAxis?: boolean;\n\t/**\n\t * Enable that the selection with the mouse and keys is doing column selection.\n\t * Defaults to false.\n\t */\n\tcolumnSelection?: boolean;\n\t/**\n\t * The modifier to be used to add multiple cursors with the mouse.\n\t * Defaults to 'alt'\n\t */\n\tmultiCursorModifier?: 'ctrlCmd' | 'alt';\n\t/**\n\t * Merge overlapping selections.\n\t * Defaults to true\n\t */\n\tmultiCursorMergeOverlapping?: boolean;\n\t/**\n\t * Configure the behaviour when pasting a text with the line count equal to the cursor count.\n\t * Defaults to 'spread'.\n\t */\n\tmultiCursorPaste?: 'spread' | 'full';\n\t/**\n\t * Configure the editor's accessibility support.\n\t * Defaults to 'auto'. It is best to leave this to 'auto'.\n\t */\n\taccessibilitySupport?: 'auto' | 'off' | 'on';\n\t/**\n\t * Controls the number of lines in the editor that can be read out by a screen reader\n\t */\n\taccessibilityPageSize?: number;\n\t/**\n\t * Suggest options.\n\t */\n\tsuggest?: ISuggestOptions;\n\tinlineSuggest?: IInlineSuggestOptions;\n\t/**\n\t * Smart select options.\n\t */\n\tsmartSelect?: ISmartSelectOptions;\n\t/**\n\t *\n\t */\n\tgotoLocation?: IGotoLocationOptions;\n\t/**\n\t * Enable quick suggestions (shadow suggestions)\n\t * Defaults to true.\n\t */\n\tquickSuggestions?: boolean | IQuickSuggestionsOptions;\n\t/**\n\t * Quick suggestions show delay (in ms)\n\t * Defaults to 10 (ms)\n\t */\n\tquickSuggestionsDelay?: number;\n\t/**\n\t * Controls the spacing around the editor.\n\t */\n\tpadding?: IEditorPaddingOptions;\n\t/**\n\t * Parameter hint options.\n\t */\n\tparameterHints?: IEditorParameterHintOptions;\n\t/**\n\t * Options for auto closing brackets.\n\t * Defaults to language defined behavior.\n\t */\n\tautoClosingBrackets?: EditorAutoClosingStrategy;\n\t/**\n\t * Options for auto closing quotes.\n\t * Defaults to language defined behavior.\n\t */\n\tautoClosingQuotes?: EditorAutoClosingStrategy;\n\t/**\n\t * Options for pressing backspace near quotes or bracket pairs.\n\t */\n\tautoClosingDelete?: EditorAutoClosingEditStrategy;\n\t/**\n\t * Options for typing over closing quotes or brackets.\n\t */\n\tautoClosingOvertype?: EditorAutoClosingEditStrategy;\n\t/**\n\t * Options for auto surrounding.\n\t * Defaults to always allowing auto surrounding.\n\t */\n\tautoSurround?: EditorAutoSurroundStrategy;\n\t/**\n\t * Controls whether the editor should automatically adjust the indentation when users type, paste, move or indent lines.\n\t * Defaults to advanced.\n\t */\n\tautoIndent?: 'none' | 'keep' | 'brackets' | 'advanced' | 'full';\n\t/**\n\t * Emulate selection behaviour of tab characters when using spaces for indentation.\n\t * This means selection will stick to tab stops.\n\t */\n\tstickyTabStops?: boolean;\n\t/**\n\t * Enable format on type.\n\t * Defaults to false.\n\t */\n\tformatOnType?: boolean;\n\t/**\n\t * Enable format on paste.\n\t * Defaults to false.\n\t */\n\tformatOnPaste?: boolean;\n\t/**\n\t * Controls if the editor should allow to move selections via drag and drop.\n\t * Defaults to false.\n\t */\n\tdragAndDrop?: boolean;\n\t/**\n\t * Enable the suggestion box to pop-up on trigger characters.\n\t * Defaults to true.\n\t */\n\tsuggestOnTriggerCharacters?: boolean;\n\t/**\n\t * Accept suggestions on ENTER.\n\t * Defaults to 'on'.\n\t */\n\tacceptSuggestionOnEnter?: 'on' | 'smart' | 'off';\n\t/**\n\t * Accept suggestions on provider defined characters.\n\t * Defaults to true.\n\t */\n\tacceptSuggestionOnCommitCharacter?: boolean;\n\t/**\n\t * Enable snippet suggestions. Default to 'true'.\n\t */\n\tsnippetSuggestions?: 'top' | 'bottom' | 'inline' | 'none';\n\t/**\n\t * Copying without a selection copies the current line.\n\t */\n\temptySelectionClipboard?: boolean;\n\t/**\n\t * Syntax highlighting is copied.\n\t */\n\tcopyWithSyntaxHighlighting?: boolean;\n\t/**\n\t * The history mode for suggestions.\n\t */\n\tsuggestSelection?: 'first' | 'recentlyUsed' | 'recentlyUsedByPrefix';\n\t/**\n\t * The font size for the suggest widget.\n\t * Defaults to the editor font size.\n\t */\n\tsuggestFontSize?: number;\n\t/**\n\t * The line height for the suggest widget.\n\t * Defaults to the editor line height.\n\t */\n\tsuggestLineHeight?: number;\n\t/**\n\t * Enable tab completion.\n\t */\n\ttabCompletion?: 'on' | 'off' | 'onlySnippets';\n\t/**\n\t * Enable selection highlight.\n\t * Defaults to true.\n\t */\n\tselectionHighlight?: boolean;\n\t/**\n\t * Enable semantic occurrences highlight.\n\t * Defaults to true.\n\t */\n\toccurrencesHighlight?: boolean;\n\t/**\n\t * Show code lens\n\t * Defaults to true.\n\t */\n\tcodeLens?: boolean;\n\t/**\n\t * Code lens font family. Defaults to editor font family.\n\t */\n\tcodeLensFontFamily?: string;\n\t/**\n\t * Code lens font size. Default to 90% of the editor font size\n\t */\n\tcodeLensFontSize?: number;\n\t/**\n\t * Control the behavior and rendering of the code action lightbulb.\n\t */\n\tlightbulb?: IEditorLightbulbOptions;\n\t/**\n\t * Timeout for running code actions on save.\n\t */\n\tcodeActionsOnSaveTimeout?: number;\n\t/**\n\t * Enable code folding.\n\t * Defaults to true.\n\t */\n\tfolding?: boolean;\n\t/**\n\t * Selects the folding strategy. 'auto' uses the strategies contributed for the current document, 'indentation' uses the indentation based folding strategy.\n\t * Defaults to 'auto'.\n\t */\n\tfoldingStrategy?: 'auto' | 'indentation';\n\t/**\n\t * Enable highlight for folded regions.\n\t * Defaults to true.\n\t */\n\tfoldingHighlight?: boolean;\n\t/**\n\t * Auto fold imports folding regions.\n\t * Defaults to true.\n\t */\n\tfoldingImportsByDefault?: boolean;\n\t/**\n\t * Maximum number of foldable regions.\n\t * Defaults to 5000.\n\t */\n\tfoldingMaximumRegions?: number;\n\t/**\n\t * Controls whether the fold actions in the gutter stay always visible or hide unless the mouse is over the gutter.\n\t * Defaults to 'mouseover'.\n\t */\n\tshowFoldingControls?: 'always' | 'mouseover';\n\t/**\n\t * Controls whether clicking on the empty content after a folded line will unfold the line.\n\t * Defaults to false.\n\t */\n\tunfoldOnClickAfterEndOfLine?: boolean;\n\t/**\n\t * Enable highlighting of matching brackets.\n\t * Defaults to 'always'.\n\t */\n\tmatchBrackets?: 'never' | 'near' | 'always';\n\t/**\n\t * Enable rendering of whitespace.\n\t * Defaults to 'selection'.\n\t */\n\trenderWhitespace?: 'none' | 'boundary' | 'selection' | 'trailing' | 'all';\n\t/**\n\t * Enable rendering of control characters.\n\t * Defaults to true.\n\t */\n\trenderControlCharacters?: boolean;\n\t/**\n\t * Enable rendering of current line highlight.\n\t * Defaults to all.\n\t */\n\trenderLineHighlight?: 'none' | 'gutter' | 'line' | 'all';\n\t/**\n\t * Control if the current line highlight should be rendered only the editor is focused.\n\t * Defaults to false.\n\t */\n\trenderLineHighlightOnlyWhenFocus?: boolean;\n\t/**\n\t * Inserting and deleting whitespace follows tab stops.\n\t */\n\tuseTabStops?: boolean;\n\t/**\n\t * The font family\n\t */\n\tfontFamily?: string;\n\t/**\n\t * The font weight\n\t */\n\tfontWeight?: string;\n\t/**\n\t * The font size\n\t */\n\tfontSize?: number;\n\t/**\n\t * The line height\n\t */\n\tlineHeight?: number;\n\t/**\n\t * The letter spacing\n\t */\n\tletterSpacing?: number;\n\t/**\n\t * Controls fading out of unused variables.\n\t */\n\tshowUnused?: boolean;\n\t/**\n\t * Controls whether to focus the inline editor in the peek widget by default.\n\t * Defaults to false.\n\t */\n\tpeekWidgetDefaultFocus?: 'tree' | 'editor';\n\t/**\n\t * Controls whether the definition link opens element in the peek widget.\n\t * Defaults to false.\n\t */\n\tdefinitionLinkOpensInPeek?: boolean;\n\t/**\n\t * Controls strikethrough deprecated variables.\n\t */\n\tshowDeprecated?: boolean;\n\t/**\n\t * Control the behavior and rendering of the inline hints.\n\t */\n\tinlayHints?: IEditorInlayHintsOptions;\n\t/**\n\t * Control if the editor should use shadow DOM.\n\t */\n\tuseShadowDOM?: boolean;\n\t/**\n\t * Controls the behavior of editor guides.\n\t*/\n\tguides?: IGuidesOptions;\n\n\tunicodeHighlight?: IUnicodeHighlightOptions;\n\n\tbracketPairColorization?: IBracketPairColorizationOptions;\n}\n\n/**\n * @internal\n * The width of the minimap gutter, in pixels.\n */\nexport const MINIMAP_GUTTER_WIDTH = 8;\n\nexport interface IDiffEditorBaseOptions {\n\t/**\n\t * Allow the user to resize the diff editor split view.\n\t * Defaults to true.\n\t */\n\tenableSplitViewResizing?: boolean;\n\t/**\n\t * Render the differences in two side-by-side editors.\n\t * Defaults to true.\n\t */\n\trenderSideBySide?: boolean;\n\t/**\n\t * Timeout in milliseconds after which diff computation is cancelled.\n\t * Defaults to 5000.\n\t */\n\tmaxComputationTime?: number;\n\t/**\n\t * Maximum supported file size in MB.\n\t * Defaults to 50.\n\t */\n\tmaxFileSize?: number;\n\t/**\n\t * Compute the diff by ignoring leading/trailing whitespace\n\t * Defaults to true.\n\t */\n\tignoreTrimWhitespace?: boolean;\n\t/**\n\t * Render +/- indicators for added/deleted changes.\n\t * Defaults to true.\n\t */\n\trenderIndicators?: boolean;\n\t/**\n\t * Original model should be editable?\n\t * Defaults to false.\n\t */\n\toriginalEditable?: boolean;\n\t/**\n\t * Should the diff editor enable code lens?\n\t * Defaults to false.\n\t */\n\tdiffCodeLens?: boolean;\n\t/**\n\t * Is the diff editor should render overview ruler\n\t * Defaults to true\n\t */\n\trenderOverviewRuler?: boolean;\n\t/**\n\t * Control the wrapping of the diff editor.\n\t */\n\tdiffWordWrap?: 'off' | 'on' | 'inherit';\n}\n\n/**\n * Configuration options for the diff editor.\n */\nexport interface IDiffEditorOptions extends IEditorOptions, IDiffEditorBaseOptions {\n}\n\n/**\n * @internal\n */\nexport type ValidDiffEditorBaseOptions = Readonly>;\n\n//#endregion\n\n/**\n * An event describing that the configuration of the editor has changed.\n */\nexport class ConfigurationChangedEvent {\n\tprivate readonly _values: boolean[];\n\t/**\n\t * @internal\n\t */\n\tconstructor(values: boolean[]) {\n\t\tthis._values = values;\n\t}\n\tpublic hasChanged(id: EditorOption): boolean {\n\t\treturn this._values[id];\n\t}\n}\n\n/**\n * All computed editor options.\n */\nexport interface IComputedEditorOptions {\n\tget(id: T): FindComputedEditorOptionValueById;\n}\n\n//#region IEditorOption\n\n/**\n * @internal\n */\nexport interface IEnvironmentalOptions {\n\treadonly memory: ComputeOptionsMemory | null;\n\treadonly outerWidth: number;\n\treadonly outerHeight: number;\n\treadonly fontInfo: FontInfo;\n\treadonly extraEditorClassName: string;\n\treadonly isDominatedByLongLines: boolean;\n\treadonly viewLineCount: number;\n\treadonly lineNumbersDigitCount: number;\n\treadonly emptySelectionClipboard: boolean;\n\treadonly pixelRatio: number;\n\treadonly tabFocusMode: boolean;\n\treadonly accessibilitySupport: AccessibilitySupport;\n}\n\n/**\n * @internal\n */\nexport class ComputeOptionsMemory {\n\n\tpublic stableMinimapLayoutInput: IMinimapLayoutInput | null;\n\tpublic stableFitMaxMinimapScale: number;\n\tpublic stableFitRemainingWidth: number;\n\n\tconstructor() {\n\t\tthis.stableMinimapLayoutInput = null;\n\t\tthis.stableFitMaxMinimapScale = 0;\n\t\tthis.stableFitRemainingWidth = 0;\n\t}\n}\n\nexport interface IEditorOption {\n\treadonly id: K;\n\treadonly name: string;\n\tdefaultValue: V;\n\t/**\n\t * @internal\n\t */\n\treadonly schema: IConfigurationPropertySchema | { [path: string]: IConfigurationPropertySchema; } | undefined;\n\t/**\n\t * @internal\n\t */\n\tvalidate(input: any): V;\n\t/**\n\t * @internal\n\t */\n\tcompute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: V): V;\n\n\t/**\n\t * Might modify `value`.\n\t*/\n\tapplyUpdate(value: V, update: V): ApplyUpdateResult;\n}\n\n/**\n * @internal\n */\ntype PossibleKeyName0 = { [K in keyof IEditorOptions]: IEditorOptions[K] extends V | undefined ? K : never }[keyof IEditorOptions];\n/**\n * @internal\n */\ntype PossibleKeyName = NonNullable>;\n\n/**\n * @internal\n */\nabstract class BaseEditorOption implements IEditorOption {\n\n\tpublic readonly id: K;\n\tpublic readonly name: string;\n\tpublic readonly defaultValue: V;\n\tpublic readonly schema: IConfigurationPropertySchema | { [path: string]: IConfigurationPropertySchema; } | undefined;\n\n\tconstructor(id: K, name: PossibleKeyName, defaultValue: V, schema?: IConfigurationPropertySchema | { [path: string]: IConfigurationPropertySchema; }) {\n\t\tthis.id = id;\n\t\tthis.name = name;\n\t\tthis.defaultValue = defaultValue;\n\t\tthis.schema = schema;\n\t}\n\n\tpublic applyUpdate(value: V, update: V): ApplyUpdateResult {\n\t\treturn applyUpdate(value, update);\n\t}\n\n\tpublic abstract validate(input: any): V;\n\n\tpublic compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: V): V {\n\t\treturn value;\n\t}\n}\n\nexport class ApplyUpdateResult {\n\tconstructor(\n\t\tpublic readonly newValue: T,\n\t\tpublic readonly didChange: boolean\n\t) { }\n}\n\nfunction applyUpdate(value: T, update: T): ApplyUpdateResult {\n\tif (typeof value !== 'object' || typeof update !== 'object' || !value || !update) {\n\t\treturn new ApplyUpdateResult(update, value !== update);\n\t}\n\tif (Array.isArray(value) || Array.isArray(update)) {\n\t\tconst arrayEquals = Array.isArray(value) && Array.isArray(update) && arrays.equals(value, update);\n\t\treturn new ApplyUpdateResult(update, arrayEquals);\n\t}\n\tlet didChange = false;\n\tfor (const key in update) {\n\t\tif ((update as T & object).hasOwnProperty(key)) {\n\t\t\tconst result = applyUpdate(value[key], update[key]);\n\t\t\tif (result.didChange) {\n\t\t\t\tvalue[key] = result.newValue;\n\t\t\t\tdidChange = true;\n\t\t\t}\n\t\t}\n\t}\n\treturn new ApplyUpdateResult(value, didChange);\n}\n\n/**\n * @internal\n */\nabstract class ComputedEditorOption implements IEditorOption {\n\n\tpublic readonly id: K;\n\tpublic readonly name: '_never_';\n\tpublic readonly defaultValue: V;\n\tpublic readonly schema: IConfigurationPropertySchema | undefined = undefined;\n\n\tconstructor(id: K) {\n\t\tthis.id = id;\n\t\tthis.name = '_never_';\n\t\tthis.defaultValue = undefined;\n\t}\n\n\tpublic applyUpdate(value: V, update: V): ApplyUpdateResult {\n\t\treturn applyUpdate(value, update);\n\t}\n\n\tpublic validate(input: any): V {\n\t\treturn this.defaultValue;\n\t}\n\n\tpublic abstract compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: V): V;\n}\n\nclass SimpleEditorOption implements IEditorOption {\n\n\tpublic readonly id: K;\n\tpublic readonly name: PossibleKeyName;\n\tpublic readonly defaultValue: V;\n\tpublic readonly schema: IConfigurationPropertySchema | undefined;\n\n\tconstructor(id: K, name: PossibleKeyName, defaultValue: V, schema?: IConfigurationPropertySchema) {\n\t\tthis.id = id;\n\t\tthis.name = name;\n\t\tthis.defaultValue = defaultValue;\n\t\tthis.schema = schema;\n\t}\n\n\tpublic applyUpdate(value: V, update: V): ApplyUpdateResult {\n\t\treturn applyUpdate(value, update);\n\t}\n\n\tpublic validate(input: any): V {\n\t\tif (typeof input === 'undefined') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\treturn input as any;\n\t}\n\n\tpublic compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: V): V {\n\t\treturn value;\n\t}\n}\n\n/**\n * @internal\n */\nexport function boolean(value: any, defaultValue: boolean): boolean {\n\tif (typeof value === 'undefined') {\n\t\treturn defaultValue;\n\t}\n\tif (value === 'false') {\n\t\t// treat the string 'false' as false\n\t\treturn false;\n\t}\n\treturn Boolean(value);\n}\n\nclass EditorBooleanOption extends SimpleEditorOption {\n\n\tconstructor(id: K, name: PossibleKeyName, defaultValue: boolean, schema: IConfigurationPropertySchema | undefined = undefined) {\n\t\tif (typeof schema !== 'undefined') {\n\t\t\tschema.type = 'boolean';\n\t\t\tschema.default = defaultValue;\n\t\t}\n\t\tsuper(id, name, defaultValue, schema);\n\t}\n\n\tpublic override validate(input: any): boolean {\n\t\treturn boolean(input, this.defaultValue);\n\t}\n}\n\n/**\n * @internal\n */\nexport function clampedInt(value: any, defaultValue: T, minimum: number, maximum: number): number | T {\n\tif (typeof value === 'undefined') {\n\t\treturn defaultValue;\n\t}\n\tlet r = parseInt(value, 10);\n\tif (isNaN(r)) {\n\t\treturn defaultValue;\n\t}\n\tr = Math.max(minimum, r);\n\tr = Math.min(maximum, r);\n\treturn r | 0;\n}\n\nclass EditorIntOption extends SimpleEditorOption {\n\n\tpublic static clampedInt(value: any, defaultValue: T, minimum: number, maximum: number): number | T {\n\t\treturn clampedInt(value, defaultValue, minimum, maximum);\n\t}\n\n\tpublic readonly minimum: number;\n\tpublic readonly maximum: number;\n\n\tconstructor(id: K, name: PossibleKeyName, defaultValue: number, minimum: number, maximum: number, schema: IConfigurationPropertySchema | undefined = undefined) {\n\t\tif (typeof schema !== 'undefined') {\n\t\t\tschema.type = 'integer';\n\t\t\tschema.default = defaultValue;\n\t\t\tschema.minimum = minimum;\n\t\t\tschema.maximum = maximum;\n\t\t}\n\t\tsuper(id, name, defaultValue, schema);\n\t\tthis.minimum = minimum;\n\t\tthis.maximum = maximum;\n\t}\n\n\tpublic override validate(input: any): number {\n\t\treturn EditorIntOption.clampedInt(input, this.defaultValue, this.minimum, this.maximum);\n\t}\n}\n\nclass EditorFloatOption extends SimpleEditorOption {\n\n\tpublic static clamp(n: number, min: number, max: number): number {\n\t\tif (n < min) {\n\t\t\treturn min;\n\t\t}\n\t\tif (n > max) {\n\t\t\treturn max;\n\t\t}\n\t\treturn n;\n\t}\n\n\tpublic static float(value: any, defaultValue: number): number {\n\t\tif (typeof value === 'number') {\n\t\t\treturn value;\n\t\t}\n\t\tif (typeof value === 'undefined') {\n\t\t\treturn defaultValue;\n\t\t}\n\t\tconst r = parseFloat(value);\n\t\treturn (isNaN(r) ? defaultValue : r);\n\t}\n\n\tpublic readonly validationFn: (value: number) => number;\n\n\tconstructor(id: K, name: PossibleKeyName, defaultValue: number, validationFn: (value: number) => number, schema?: IConfigurationPropertySchema) {\n\t\tif (typeof schema !== 'undefined') {\n\t\t\tschema.type = 'number';\n\t\t\tschema.default = defaultValue;\n\t\t}\n\t\tsuper(id, name, defaultValue, schema);\n\t\tthis.validationFn = validationFn;\n\t}\n\n\tpublic override validate(input: any): number {\n\t\treturn this.validationFn(EditorFloatOption.float(input, this.defaultValue));\n\t}\n}\n\nclass EditorStringOption extends SimpleEditorOption {\n\n\tpublic static string(value: any, defaultValue: string): string {\n\t\tif (typeof value !== 'string') {\n\t\t\treturn defaultValue;\n\t\t}\n\t\treturn value;\n\t}\n\n\tconstructor(id: K, name: PossibleKeyName, defaultValue: string, schema: IConfigurationPropertySchema | undefined = undefined) {\n\t\tif (typeof schema !== 'undefined') {\n\t\t\tschema.type = 'string';\n\t\t\tschema.default = defaultValue;\n\t\t}\n\t\tsuper(id, name, defaultValue, schema);\n\t}\n\n\tpublic override validate(input: any): string {\n\t\treturn EditorStringOption.string(input, this.defaultValue);\n\t}\n}\n\n/**\n * @internal\n */\nexport function stringSet(value: T | undefined, defaultValue: T, allowedValues: ReadonlyArray): T {\n\tif (typeof value !== 'string') {\n\t\treturn defaultValue;\n\t}\n\tif (allowedValues.indexOf(value) === -1) {\n\t\treturn defaultValue;\n\t}\n\treturn value;\n}\n\nclass EditorStringEnumOption extends SimpleEditorOption {\n\n\tprivate readonly _allowedValues: ReadonlyArray;\n\n\tconstructor(id: K, name: PossibleKeyName, defaultValue: V, allowedValues: ReadonlyArray, schema: IConfigurationPropertySchema | undefined = undefined) {\n\t\tif (typeof schema !== 'undefined') {\n\t\t\tschema.type = 'string';\n\t\t\tschema.enum = allowedValues;\n\t\t\tschema.default = defaultValue;\n\t\t}\n\t\tsuper(id, name, defaultValue, schema);\n\t\tthis._allowedValues = allowedValues;\n\t}\n\n\tpublic override validate(input: any): V {\n\t\treturn stringSet(input, this.defaultValue, this._allowedValues);\n\t}\n}\n\nclass EditorEnumOption extends BaseEditorOption {\n\n\tprivate readonly _allowedValues: T[];\n\tprivate readonly _convert: (value: T) => V;\n\n\tconstructor(id: K, name: PossibleKeyName, defaultValue: V, defaultStringValue: string, allowedValues: T[], convert: (value: T) => V, schema: IConfigurationPropertySchema | undefined = undefined) {\n\t\tif (typeof schema !== 'undefined') {\n\t\t\tschema.type = 'string';\n\t\t\tschema.enum = allowedValues;\n\t\t\tschema.default = defaultStringValue;\n\t\t}\n\t\tsuper(id, name, defaultValue, schema);\n\t\tthis._allowedValues = allowedValues;\n\t\tthis._convert = convert;\n\t}\n\n\tpublic validate(input: any): V {\n\t\tif (typeof input !== 'string') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tif (this._allowedValues.indexOf(input) === -1) {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\treturn this._convert(input);\n\t}\n}\n\n//#endregion\n\n//#region autoIndent\n\nfunction _autoIndentFromString(autoIndent: 'none' | 'keep' | 'brackets' | 'advanced' | 'full'): EditorAutoIndentStrategy {\n\tswitch (autoIndent) {\n\t\tcase 'none': return EditorAutoIndentStrategy.None;\n\t\tcase 'keep': return EditorAutoIndentStrategy.Keep;\n\t\tcase 'brackets': return EditorAutoIndentStrategy.Brackets;\n\t\tcase 'advanced': return EditorAutoIndentStrategy.Advanced;\n\t\tcase 'full': return EditorAutoIndentStrategy.Full;\n\t}\n}\n\n//#endregion\n\n//#region accessibilitySupport\n\nclass EditorAccessibilitySupport extends BaseEditorOption {\n\n\tconstructor() {\n\t\tsuper(\n\t\t\tEditorOption.accessibilitySupport, 'accessibilitySupport', AccessibilitySupport.Unknown,\n\t\t\t{\n\t\t\t\ttype: 'string',\n\t\t\t\tenum: ['auto', 'on', 'off'],\n\t\t\t\tenumDescriptions: [\n\t\t\t\t\tnls.localize('accessibilitySupport.auto', \"The editor will use platform APIs to detect when a Screen Reader is attached.\"),\n\t\t\t\t\tnls.localize('accessibilitySupport.on', \"The editor will be permanently optimized for usage with a Screen Reader. Word wrapping will be disabled.\"),\n\t\t\t\t\tnls.localize('accessibilitySupport.off', \"The editor will never be optimized for usage with a Screen Reader.\"),\n\t\t\t\t],\n\t\t\t\tdefault: 'auto',\n\t\t\t\tdescription: nls.localize('accessibilitySupport', \"Controls whether the editor should run in a mode where it is optimized for screen readers. Setting to on will disable word wrapping.\")\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(input: any): AccessibilitySupport {\n\t\tswitch (input) {\n\t\t\tcase 'auto': return AccessibilitySupport.Unknown;\n\t\t\tcase 'off': return AccessibilitySupport.Disabled;\n\t\t\tcase 'on': return AccessibilitySupport.Enabled;\n\t\t}\n\t\treturn this.defaultValue;\n\t}\n\n\tpublic override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: AccessibilitySupport): AccessibilitySupport {\n\t\tif (value === AccessibilitySupport.Unknown) {\n\t\t\t// The editor reads the `accessibilitySupport` from the environment\n\t\t\treturn env.accessibilitySupport;\n\t\t}\n\t\treturn value;\n\t}\n}\n\n//#endregion\n\n//#region comments\n\n/**\n * Configuration options for editor comments\n */\nexport interface IEditorCommentsOptions {\n\t/**\n\t * Insert a space after the line comment token and inside the block comments tokens.\n\t * Defaults to true.\n\t */\n\tinsertSpace?: boolean;\n\t/**\n\t * Ignore empty lines when inserting line comments.\n\t * Defaults to true.\n\t */\n\tignoreEmptyLines?: boolean;\n}\n\n/**\n * @internal\n */\nexport type EditorCommentsOptions = Readonly>;\n\nclass EditorComments extends BaseEditorOption {\n\n\tconstructor() {\n\t\tconst defaults: EditorCommentsOptions = {\n\t\t\tinsertSpace: true,\n\t\t\tignoreEmptyLines: true,\n\t\t};\n\t\tsuper(\n\t\t\tEditorOption.comments, 'comments', defaults,\n\t\t\t{\n\t\t\t\t'editor.comments.insertSpace': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.insertSpace,\n\t\t\t\t\tdescription: nls.localize('comments.insertSpace', \"Controls whether a space character is inserted when commenting.\")\n\t\t\t\t},\n\t\t\t\t'editor.comments.ignoreEmptyLines': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.ignoreEmptyLines,\n\t\t\t\t\tdescription: nls.localize('comments.ignoreEmptyLines', 'Controls if empty lines should be ignored with toggle, add or remove actions for line comments.')\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): EditorCommentsOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IEditorCommentsOptions;\n\t\treturn {\n\t\t\tinsertSpace: boolean(input.insertSpace, this.defaultValue.insertSpace),\n\t\t\tignoreEmptyLines: boolean(input.ignoreEmptyLines, this.defaultValue.ignoreEmptyLines),\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region cursorBlinking\n\n/**\n * The kind of animation in which the editor's cursor should be rendered.\n */\nexport const enum TextEditorCursorBlinkingStyle {\n\t/**\n\t * Hidden\n\t */\n\tHidden = 0,\n\t/**\n\t * Blinking\n\t */\n\tBlink = 1,\n\t/**\n\t * Blinking with smooth fading\n\t */\n\tSmooth = 2,\n\t/**\n\t * Blinking with prolonged filled state and smooth fading\n\t */\n\tPhase = 3,\n\t/**\n\t * Expand collapse animation on the y axis\n\t */\n\tExpand = 4,\n\t/**\n\t * No-Blinking\n\t */\n\tSolid = 5\n}\n\nfunction _cursorBlinkingStyleFromString(cursorBlinkingStyle: 'blink' | 'smooth' | 'phase' | 'expand' | 'solid'): TextEditorCursorBlinkingStyle {\n\tswitch (cursorBlinkingStyle) {\n\t\tcase 'blink': return TextEditorCursorBlinkingStyle.Blink;\n\t\tcase 'smooth': return TextEditorCursorBlinkingStyle.Smooth;\n\t\tcase 'phase': return TextEditorCursorBlinkingStyle.Phase;\n\t\tcase 'expand': return TextEditorCursorBlinkingStyle.Expand;\n\t\tcase 'solid': return TextEditorCursorBlinkingStyle.Solid;\n\t}\n}\n\n//#endregion\n\n//#region cursorStyle\n\n/**\n * The style in which the editor's cursor should be rendered.\n */\nexport enum TextEditorCursorStyle {\n\t/**\n\t * As a vertical line (sitting between two characters).\n\t */\n\tLine = 1,\n\t/**\n\t * As a block (sitting on top of a character).\n\t */\n\tBlock = 2,\n\t/**\n\t * As a horizontal line (sitting under a character).\n\t */\n\tUnderline = 3,\n\t/**\n\t * As a thin vertical line (sitting between two characters).\n\t */\n\tLineThin = 4,\n\t/**\n\t * As an outlined block (sitting on top of a character).\n\t */\n\tBlockOutline = 5,\n\t/**\n\t * As a thin horizontal line (sitting under a character).\n\t */\n\tUnderlineThin = 6\n}\n\nfunction _cursorStyleFromString(cursorStyle: 'line' | 'block' | 'underline' | 'line-thin' | 'block-outline' | 'underline-thin'): TextEditorCursorStyle {\n\tswitch (cursorStyle) {\n\t\tcase 'line': return TextEditorCursorStyle.Line;\n\t\tcase 'block': return TextEditorCursorStyle.Block;\n\t\tcase 'underline': return TextEditorCursorStyle.Underline;\n\t\tcase 'line-thin': return TextEditorCursorStyle.LineThin;\n\t\tcase 'block-outline': return TextEditorCursorStyle.BlockOutline;\n\t\tcase 'underline-thin': return TextEditorCursorStyle.UnderlineThin;\n\t}\n}\n\n//#endregion\n\n//#region editorClassName\n\nclass EditorClassName extends ComputedEditorOption {\n\n\tconstructor() {\n\t\tsuper(EditorOption.editorClassName);\n\t}\n\n\tpublic compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: string): string {\n\t\tconst classNames = ['monaco-editor'];\n\t\tif (options.get(EditorOption.extraEditorClassName)) {\n\t\t\tclassNames.push(options.get(EditorOption.extraEditorClassName));\n\t\t}\n\t\tif (env.extraEditorClassName) {\n\t\t\tclassNames.push(env.extraEditorClassName);\n\t\t}\n\t\tif (options.get(EditorOption.mouseStyle) === 'default') {\n\t\t\tclassNames.push('mouse-default');\n\t\t} else if (options.get(EditorOption.mouseStyle) === 'copy') {\n\t\t\tclassNames.push('mouse-copy');\n\t\t}\n\n\t\tif (options.get(EditorOption.showUnused)) {\n\t\t\tclassNames.push('showUnused');\n\t\t}\n\n\t\tif (options.get(EditorOption.showDeprecated)) {\n\t\t\tclassNames.push('showDeprecated');\n\t\t}\n\n\t\treturn classNames.join(' ');\n\t}\n}\n\n//#endregion\n\n//#region emptySelectionClipboard\n\nclass EditorEmptySelectionClipboard extends EditorBooleanOption {\n\n\tconstructor() {\n\t\tsuper(\n\t\t\tEditorOption.emptySelectionClipboard, 'emptySelectionClipboard', true,\n\t\t\t{ description: nls.localize('emptySelectionClipboard', \"Controls whether copying without a selection copies the current line.\") }\n\t\t);\n\t}\n\n\tpublic override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: boolean): boolean {\n\t\treturn value && env.emptySelectionClipboard;\n\t}\n}\n\n//#endregion\n\n//#region find\n\n/**\n * Configuration options for editor find widget\n */\nexport interface IEditorFindOptions {\n\t/**\n\t* Controls whether the cursor should move to find matches while typing.\n\t*/\n\tcursorMoveOnType?: boolean;\n\t/**\n\t * Controls if we seed search string in the Find Widget with editor selection.\n\t */\n\tseedSearchStringFromSelection?: 'never' | 'always' | 'selection';\n\t/**\n\t * Controls if Find in Selection flag is turned on in the editor.\n\t */\n\tautoFindInSelection?: 'never' | 'always' | 'multiline';\n\t/*\n\t * Controls whether the Find Widget should add extra lines on top of the editor.\n\t */\n\taddExtraSpaceOnTop?: boolean;\n\t/**\n\t * @internal\n\t * Controls if the Find Widget should read or modify the shared find clipboard on macOS\n\t */\n\tglobalFindClipboard?: boolean;\n\t/**\n\t * Controls whether the search automatically restarts from the beginning (or the end) when no further matches can be found\n\t */\n\tloop?: boolean;\n}\n\n/**\n * @internal\n */\nexport type EditorFindOptions = Readonly>;\n\nclass EditorFind extends BaseEditorOption {\n\n\tconstructor() {\n\t\tconst defaults: EditorFindOptions = {\n\t\t\tcursorMoveOnType: true,\n\t\t\tseedSearchStringFromSelection: 'always',\n\t\t\tautoFindInSelection: 'never',\n\t\t\tglobalFindClipboard: false,\n\t\t\taddExtraSpaceOnTop: true,\n\t\t\tloop: true\n\t\t};\n\t\tsuper(\n\t\t\tEditorOption.find, 'find', defaults,\n\t\t\t{\n\t\t\t\t'editor.find.cursorMoveOnType': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.cursorMoveOnType,\n\t\t\t\t\tdescription: nls.localize('find.cursorMoveOnType', \"Controls whether the cursor should jump to find matches while typing.\")\n\t\t\t\t},\n\t\t\t\t'editor.find.seedSearchStringFromSelection': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tenum: ['never', 'always', 'selection'],\n\t\t\t\t\tdefault: defaults.seedSearchStringFromSelection,\n\t\t\t\t\tenumDescriptions: [\n\t\t\t\t\t\tnls.localize('editor.find.seedSearchStringFromSelection.never', 'Never seed search string from the editor selection.'),\n\t\t\t\t\t\tnls.localize('editor.find.seedSearchStringFromSelection.always', 'Always seed search string from the editor selection, including word at cursor position.'),\n\t\t\t\t\t\tnls.localize('editor.find.seedSearchStringFromSelection.selection', 'Only seed search string from the editor selection.')\n\t\t\t\t\t],\n\t\t\t\t\tdescription: nls.localize('find.seedSearchStringFromSelection', \"Controls whether the search string in the Find Widget is seeded from the editor selection.\")\n\t\t\t\t},\n\t\t\t\t'editor.find.autoFindInSelection': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tenum: ['never', 'always', 'multiline'],\n\t\t\t\t\tdefault: defaults.autoFindInSelection,\n\t\t\t\t\tenumDescriptions: [\n\t\t\t\t\t\tnls.localize('editor.find.autoFindInSelection.never', 'Never turn on Find in Selection automatically (default).'),\n\t\t\t\t\t\tnls.localize('editor.find.autoFindInSelection.always', 'Always turn on Find in Selection automatically.'),\n\t\t\t\t\t\tnls.localize('editor.find.autoFindInSelection.multiline', 'Turn on Find in Selection automatically when multiple lines of content are selected.')\n\t\t\t\t\t],\n\t\t\t\t\tdescription: nls.localize('find.autoFindInSelection', \"Controls the condition for turning on Find in Selection automatically.\")\n\t\t\t\t},\n\t\t\t\t'editor.find.globalFindClipboard': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.globalFindClipboard,\n\t\t\t\t\tdescription: nls.localize('find.globalFindClipboard', \"Controls whether the Find Widget should read or modify the shared find clipboard on macOS.\"),\n\t\t\t\t\tincluded: platform.isMacintosh\n\t\t\t\t},\n\t\t\t\t'editor.find.addExtraSpaceOnTop': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.addExtraSpaceOnTop,\n\t\t\t\t\tdescription: nls.localize('find.addExtraSpaceOnTop', \"Controls whether the Find Widget should add extra lines on top of the editor. When true, you can scroll beyond the first line when the Find Widget is visible.\")\n\t\t\t\t},\n\t\t\t\t'editor.find.loop': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.loop,\n\t\t\t\t\tdescription: nls.localize('find.loop', \"Controls whether the search automatically restarts from the beginning (or the end) when no further matches can be found.\")\n\t\t\t\t},\n\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): EditorFindOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IEditorFindOptions;\n\t\treturn {\n\t\t\tcursorMoveOnType: boolean(input.cursorMoveOnType, this.defaultValue.cursorMoveOnType),\n\t\t\tseedSearchStringFromSelection: typeof _input.seedSearchStringFromSelection === 'boolean'\n\t\t\t\t? (_input.seedSearchStringFromSelection ? 'always' : 'never')\n\t\t\t\t: stringSet<'never' | 'always' | 'selection'>(input.seedSearchStringFromSelection, this.defaultValue.seedSearchStringFromSelection, ['never', 'always', 'selection']),\n\t\t\tautoFindInSelection: typeof _input.autoFindInSelection === 'boolean'\n\t\t\t\t? (_input.autoFindInSelection ? 'always' : 'never')\n\t\t\t\t: stringSet<'never' | 'always' | 'multiline'>(input.autoFindInSelection, this.defaultValue.autoFindInSelection, ['never', 'always', 'multiline']),\n\t\t\tglobalFindClipboard: boolean(input.globalFindClipboard, this.defaultValue.globalFindClipboard),\n\t\t\taddExtraSpaceOnTop: boolean(input.addExtraSpaceOnTop, this.defaultValue.addExtraSpaceOnTop),\n\t\t\tloop: boolean(input.loop, this.defaultValue.loop),\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region fontLigatures\n\n/**\n * @internal\n */\nexport class EditorFontLigatures extends BaseEditorOption {\n\n\tpublic static OFF = '\"liga\" off, \"calt\" off';\n\tpublic static ON = '\"liga\" on, \"calt\" on';\n\n\tconstructor() {\n\t\tsuper(\n\t\t\tEditorOption.fontLigatures, 'fontLigatures', EditorFontLigatures.OFF,\n\t\t\t{\n\t\t\t\tanyOf: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tdescription: nls.localize('fontLigatures', \"Enables/Disables font ligatures ('calt' and 'liga' font features). Change this to a string for fine-grained control of the 'font-feature-settings' CSS property.\"),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: nls.localize('fontFeatureSettings', \"Explicit 'font-feature-settings' CSS property. A boolean can be passed instead if one only needs to turn on/off ligatures.\")\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tdescription: nls.localize('fontLigaturesGeneral', \"Configures font ligatures or font features. Can be either a boolean to enable/disable ligatures or a string for the value of the CSS 'font-feature-settings' property.\"),\n\t\t\t\tdefault: false\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(input: any): string {\n\t\tif (typeof input === 'undefined') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tif (typeof input === 'string') {\n\t\t\tif (input === 'false') {\n\t\t\t\treturn EditorFontLigatures.OFF;\n\t\t\t}\n\t\t\tif (input === 'true') {\n\t\t\t\treturn EditorFontLigatures.ON;\n\t\t\t}\n\t\t\treturn input;\n\t\t}\n\t\tif (Boolean(input)) {\n\t\t\treturn EditorFontLigatures.ON;\n\t\t}\n\t\treturn EditorFontLigatures.OFF;\n\t}\n}\n\n//#endregion\n\n//#region fontInfo\n\nclass EditorFontInfo extends ComputedEditorOption {\n\n\tconstructor() {\n\t\tsuper(EditorOption.fontInfo);\n\t}\n\n\tpublic compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: FontInfo): FontInfo {\n\t\treturn env.fontInfo;\n\t}\n}\n\n//#endregion\n\n//#region fontSize\n\nclass EditorFontSize extends SimpleEditorOption {\n\n\tconstructor() {\n\t\tsuper(\n\t\t\tEditorOption.fontSize, 'fontSize', EDITOR_FONT_DEFAULTS.fontSize,\n\t\t\t{\n\t\t\t\ttype: 'number',\n\t\t\t\tminimum: 6,\n\t\t\t\tmaximum: 100,\n\t\t\t\tdefault: EDITOR_FONT_DEFAULTS.fontSize,\n\t\t\t\tdescription: nls.localize('fontSize', \"Controls the font size in pixels.\")\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic override validate(input: any): number {\n\t\tconst r = EditorFloatOption.float(input, this.defaultValue);\n\t\tif (r === 0) {\n\t\t\treturn EDITOR_FONT_DEFAULTS.fontSize;\n\t\t}\n\t\treturn EditorFloatOption.clamp(r, 6, 100);\n\t}\n\tpublic override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: number): number {\n\t\t// The final fontSize respects the editor zoom level.\n\t\t// So take the result from env.fontInfo\n\t\treturn env.fontInfo.fontSize;\n\t}\n}\n\n//#endregion\n\n//#region fontWeight\n\nclass EditorFontWeight extends BaseEditorOption {\n\tprivate static SUGGESTION_VALUES = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'];\n\tprivate static MINIMUM_VALUE = 1;\n\tprivate static MAXIMUM_VALUE = 1000;\n\n\tconstructor() {\n\t\tsuper(\n\t\t\tEditorOption.fontWeight, 'fontWeight', EDITOR_FONT_DEFAULTS.fontWeight,\n\t\t\t{\n\t\t\t\tanyOf: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tminimum: EditorFontWeight.MINIMUM_VALUE,\n\t\t\t\t\t\tmaximum: EditorFontWeight.MAXIMUM_VALUE,\n\t\t\t\t\t\terrorMessage: nls.localize('fontWeightErrorMessage', \"Only \\\"normal\\\" and \\\"bold\\\" keywords or numbers between 1 and 1000 are allowed.\")\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tpattern: '^(normal|bold|1000|[1-9][0-9]{0,2})$'\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tenum: EditorFontWeight.SUGGESTION_VALUES\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tdefault: EDITOR_FONT_DEFAULTS.fontWeight,\n\t\t\t\tdescription: nls.localize('fontWeight', \"Controls the font weight. Accepts \\\"normal\\\" and \\\"bold\\\" keywords or numbers between 1 and 1000.\")\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(input: any): string {\n\t\tif (input === 'normal' || input === 'bold') {\n\t\t\treturn input;\n\t\t}\n\t\treturn String(EditorIntOption.clampedInt(input, EDITOR_FONT_DEFAULTS.fontWeight, EditorFontWeight.MINIMUM_VALUE, EditorFontWeight.MAXIMUM_VALUE));\n\t}\n}\n\n//#endregion\n\n//#region gotoLocation\n\nexport type GoToLocationValues = 'peek' | 'gotoAndPeek' | 'goto';\n\n/**\n * Configuration options for go to location\n */\nexport interface IGotoLocationOptions {\n\n\tmultiple?: GoToLocationValues;\n\n\tmultipleDefinitions?: GoToLocationValues;\n\tmultipleTypeDefinitions?: GoToLocationValues;\n\tmultipleDeclarations?: GoToLocationValues;\n\tmultipleImplementations?: GoToLocationValues;\n\tmultipleReferences?: GoToLocationValues;\n\n\talternativeDefinitionCommand?: string;\n\talternativeTypeDefinitionCommand?: string;\n\talternativeDeclarationCommand?: string;\n\talternativeImplementationCommand?: string;\n\talternativeReferenceCommand?: string;\n}\n\n/**\n * @internal\n */\nexport type GoToLocationOptions = Readonly>;\n\nclass EditorGoToLocation extends BaseEditorOption {\n\n\tconstructor() {\n\t\tconst defaults: GoToLocationOptions = {\n\t\t\tmultiple: 'peek',\n\t\t\tmultipleDefinitions: 'peek',\n\t\t\tmultipleTypeDefinitions: 'peek',\n\t\t\tmultipleDeclarations: 'peek',\n\t\t\tmultipleImplementations: 'peek',\n\t\t\tmultipleReferences: 'peek',\n\t\t\talternativeDefinitionCommand: 'editor.action.goToReferences',\n\t\t\talternativeTypeDefinitionCommand: 'editor.action.goToReferences',\n\t\t\talternativeDeclarationCommand: 'editor.action.goToReferences',\n\t\t\talternativeImplementationCommand: '',\n\t\t\talternativeReferenceCommand: '',\n\t\t};\n\t\tconst jsonSubset: IJSONSchema = {\n\t\t\ttype: 'string',\n\t\t\tenum: ['peek', 'gotoAndPeek', 'goto'],\n\t\t\tdefault: defaults.multiple,\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('editor.gotoLocation.multiple.peek', 'Show peek view of the results (default)'),\n\t\t\t\tnls.localize('editor.gotoLocation.multiple.gotoAndPeek', 'Go to the primary result and show a peek view'),\n\t\t\t\tnls.localize('editor.gotoLocation.multiple.goto', 'Go to the primary result and enable peek-less navigation to others')\n\t\t\t]\n\t\t};\n\t\tconst alternativeCommandOptions = ['', 'editor.action.referenceSearch.trigger', 'editor.action.goToReferences', 'editor.action.peekImplementation', 'editor.action.goToImplementation', 'editor.action.peekTypeDefinition', 'editor.action.goToTypeDefinition', 'editor.action.peekDeclaration', 'editor.action.revealDeclaration', 'editor.action.peekDefinition', 'editor.action.revealDefinitionAside', 'editor.action.revealDefinition'];\n\t\tsuper(\n\t\t\tEditorOption.gotoLocation, 'gotoLocation', defaults,\n\t\t\t{\n\t\t\t\t'editor.gotoLocation.multiple': {\n\t\t\t\t\tdeprecationMessage: nls.localize('editor.gotoLocation.multiple.deprecated', \"This setting is deprecated, please use separate settings like 'editor.editor.gotoLocation.multipleDefinitions' or 'editor.editor.gotoLocation.multipleImplementations' instead.\"),\n\t\t\t\t},\n\t\t\t\t'editor.gotoLocation.multipleDefinitions': {\n\t\t\t\t\tdescription: nls.localize('editor.editor.gotoLocation.multipleDefinitions', \"Controls the behavior the 'Go to Definition'-command when multiple target locations exist.\"),\n\t\t\t\t\t...jsonSubset,\n\t\t\t\t},\n\t\t\t\t'editor.gotoLocation.multipleTypeDefinitions': {\n\t\t\t\t\tdescription: nls.localize('editor.editor.gotoLocation.multipleTypeDefinitions', \"Controls the behavior the 'Go to Type Definition'-command when multiple target locations exist.\"),\n\t\t\t\t\t...jsonSubset,\n\t\t\t\t},\n\t\t\t\t'editor.gotoLocation.multipleDeclarations': {\n\t\t\t\t\tdescription: nls.localize('editor.editor.gotoLocation.multipleDeclarations', \"Controls the behavior the 'Go to Declaration'-command when multiple target locations exist.\"),\n\t\t\t\t\t...jsonSubset,\n\t\t\t\t},\n\t\t\t\t'editor.gotoLocation.multipleImplementations': {\n\t\t\t\t\tdescription: nls.localize('editor.editor.gotoLocation.multipleImplemenattions', \"Controls the behavior the 'Go to Implementations'-command when multiple target locations exist.\"),\n\t\t\t\t\t...jsonSubset,\n\t\t\t\t},\n\t\t\t\t'editor.gotoLocation.multipleReferences': {\n\t\t\t\t\tdescription: nls.localize('editor.editor.gotoLocation.multipleReferences', \"Controls the behavior the 'Go to References'-command when multiple target locations exist.\"),\n\t\t\t\t\t...jsonSubset,\n\t\t\t\t},\n\t\t\t\t'editor.gotoLocation.alternativeDefinitionCommand': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: defaults.alternativeDefinitionCommand,\n\t\t\t\t\tenum: alternativeCommandOptions,\n\t\t\t\t\tdescription: nls.localize('alternativeDefinitionCommand', \"Alternative command id that is being executed when the result of 'Go to Definition' is the current location.\")\n\t\t\t\t},\n\t\t\t\t'editor.gotoLocation.alternativeTypeDefinitionCommand': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: defaults.alternativeTypeDefinitionCommand,\n\t\t\t\t\tenum: alternativeCommandOptions,\n\t\t\t\t\tdescription: nls.localize('alternativeTypeDefinitionCommand', \"Alternative command id that is being executed when the result of 'Go to Type Definition' is the current location.\")\n\t\t\t\t},\n\t\t\t\t'editor.gotoLocation.alternativeDeclarationCommand': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: defaults.alternativeDeclarationCommand,\n\t\t\t\t\tenum: alternativeCommandOptions,\n\t\t\t\t\tdescription: nls.localize('alternativeDeclarationCommand', \"Alternative command id that is being executed when the result of 'Go to Declaration' is the current location.\")\n\t\t\t\t},\n\t\t\t\t'editor.gotoLocation.alternativeImplementationCommand': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: defaults.alternativeImplementationCommand,\n\t\t\t\t\tenum: alternativeCommandOptions,\n\t\t\t\t\tdescription: nls.localize('alternativeImplementationCommand', \"Alternative command id that is being executed when the result of 'Go to Implementation' is the current location.\")\n\t\t\t\t},\n\t\t\t\t'editor.gotoLocation.alternativeReferenceCommand': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: defaults.alternativeReferenceCommand,\n\t\t\t\t\tenum: alternativeCommandOptions,\n\t\t\t\t\tdescription: nls.localize('alternativeReferenceCommand', \"Alternative command id that is being executed when the result of 'Go to Reference' is the current location.\")\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): GoToLocationOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IGotoLocationOptions;\n\t\treturn {\n\t\t\tmultiple: stringSet(input.multiple, this.defaultValue.multiple!, ['peek', 'gotoAndPeek', 'goto']),\n\t\t\tmultipleDefinitions: input.multipleDefinitions ?? stringSet(input.multipleDefinitions, 'peek', ['peek', 'gotoAndPeek', 'goto']),\n\t\t\tmultipleTypeDefinitions: input.multipleTypeDefinitions ?? stringSet(input.multipleTypeDefinitions, 'peek', ['peek', 'gotoAndPeek', 'goto']),\n\t\t\tmultipleDeclarations: input.multipleDeclarations ?? stringSet(input.multipleDeclarations, 'peek', ['peek', 'gotoAndPeek', 'goto']),\n\t\t\tmultipleImplementations: input.multipleImplementations ?? stringSet(input.multipleImplementations, 'peek', ['peek', 'gotoAndPeek', 'goto']),\n\t\t\tmultipleReferences: input.multipleReferences ?? stringSet(input.multipleReferences, 'peek', ['peek', 'gotoAndPeek', 'goto']),\n\t\t\talternativeDefinitionCommand: EditorStringOption.string(input.alternativeDefinitionCommand, this.defaultValue.alternativeDefinitionCommand),\n\t\t\talternativeTypeDefinitionCommand: EditorStringOption.string(input.alternativeTypeDefinitionCommand, this.defaultValue.alternativeTypeDefinitionCommand),\n\t\t\talternativeDeclarationCommand: EditorStringOption.string(input.alternativeDeclarationCommand, this.defaultValue.alternativeDeclarationCommand),\n\t\t\talternativeImplementationCommand: EditorStringOption.string(input.alternativeImplementationCommand, this.defaultValue.alternativeImplementationCommand),\n\t\t\talternativeReferenceCommand: EditorStringOption.string(input.alternativeReferenceCommand, this.defaultValue.alternativeReferenceCommand),\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region hover\n\n/**\n * Configuration options for editor hover\n */\nexport interface IEditorHoverOptions {\n\t/**\n\t * Enable the hover.\n\t * Defaults to true.\n\t */\n\tenabled?: boolean;\n\t/**\n\t * Delay for showing the hover.\n\t * Defaults to 300.\n\t */\n\tdelay?: number;\n\t/**\n\t * Is the hover sticky such that it can be clicked and its contents selected?\n\t * Defaults to true.\n\t */\n\tsticky?: boolean;\n\t/**\n\t * Should the hover be shown above the line if possible?\n\t * Defaults to false.\n\t */\n\tabove?: boolean;\n}\n\n/**\n * @internal\n */\nexport type EditorHoverOptions = Readonly>;\n\nclass EditorHover extends BaseEditorOption {\n\n\tconstructor() {\n\t\tconst defaults: EditorHoverOptions = {\n\t\t\tenabled: true,\n\t\t\tdelay: 300,\n\t\t\tsticky: true,\n\t\t\tabove: true,\n\t\t};\n\t\tsuper(\n\t\t\tEditorOption.hover, 'hover', defaults,\n\t\t\t{\n\t\t\t\t'editor.hover.enabled': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.enabled,\n\t\t\t\t\tdescription: nls.localize('hover.enabled', \"Controls whether the hover is shown.\")\n\t\t\t\t},\n\t\t\t\t'editor.hover.delay': {\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: defaults.delay,\n\t\t\t\t\tminimum: 0,\n\t\t\t\t\tmaximum: 10000,\n\t\t\t\t\tdescription: nls.localize('hover.delay', \"Controls the delay in milliseconds after which the hover is shown.\")\n\t\t\t\t},\n\t\t\t\t'editor.hover.sticky': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.sticky,\n\t\t\t\t\tdescription: nls.localize('hover.sticky', \"Controls whether the hover should remain visible when mouse is moved over it.\")\n\t\t\t\t},\n\t\t\t\t'editor.hover.above': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.above,\n\t\t\t\t\tdescription: nls.localize('hover.above', \"Prefer showing hovers above the line, if there's space.\")\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): EditorHoverOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IEditorHoverOptions;\n\t\treturn {\n\t\t\tenabled: boolean(input.enabled, this.defaultValue.enabled),\n\t\t\tdelay: EditorIntOption.clampedInt(input.delay, this.defaultValue.delay, 0, 10000),\n\t\t\tsticky: boolean(input.sticky, this.defaultValue.sticky),\n\t\t\tabove: boolean(input.above, this.defaultValue.above),\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region layoutInfo\n\n/**\n * A description for the overview ruler position.\n */\nexport interface OverviewRulerPosition {\n\t/**\n\t * Width of the overview ruler\n\t */\n\treadonly width: number;\n\t/**\n\t * Height of the overview ruler\n\t */\n\treadonly height: number;\n\t/**\n\t * Top position for the overview ruler\n\t */\n\treadonly top: number;\n\t/**\n\t * Right position for the overview ruler\n\t */\n\treadonly right: number;\n}\n\nexport const enum RenderMinimap {\n\tNone = 0,\n\tText = 1,\n\tBlocks = 2,\n}\n\n/**\n * The internal layout details of the editor.\n */\nexport interface EditorLayoutInfo {\n\n\t/**\n\t * Full editor width.\n\t */\n\treadonly width: number;\n\t/**\n\t * Full editor height.\n\t */\n\treadonly height: number;\n\n\t/**\n\t * Left position for the glyph margin.\n\t */\n\treadonly glyphMarginLeft: number;\n\t/**\n\t * The width of the glyph margin.\n\t */\n\treadonly glyphMarginWidth: number;\n\n\t/**\n\t * Left position for the line numbers.\n\t */\n\treadonly lineNumbersLeft: number;\n\t/**\n\t * The width of the line numbers.\n\t */\n\treadonly lineNumbersWidth: number;\n\n\t/**\n\t * Left position for the line decorations.\n\t */\n\treadonly decorationsLeft: number;\n\t/**\n\t * The width of the line decorations.\n\t */\n\treadonly decorationsWidth: number;\n\n\t/**\n\t * Left position for the content (actual text)\n\t */\n\treadonly contentLeft: number;\n\t/**\n\t * The width of the content (actual text)\n\t */\n\treadonly contentWidth: number;\n\n\t/**\n\t * Layout information for the minimap\n\t */\n\treadonly minimap: EditorMinimapLayoutInfo;\n\n\t/**\n\t * The number of columns (of typical characters) fitting on a viewport line.\n\t */\n\treadonly viewportColumn: number;\n\n\treadonly isWordWrapMinified: boolean;\n\treadonly isViewportWrapping: boolean;\n\treadonly wrappingColumn: number;\n\n\t/**\n\t * The width of the vertical scrollbar.\n\t */\n\treadonly verticalScrollbarWidth: number;\n\t/**\n\t * The height of the horizontal scrollbar.\n\t */\n\treadonly horizontalScrollbarHeight: number;\n\n\t/**\n\t * The position of the overview ruler.\n\t */\n\treadonly overviewRuler: OverviewRulerPosition;\n}\n\n/**\n * The internal layout details of the editor.\n */\nexport interface EditorMinimapLayoutInfo {\n\treadonly renderMinimap: RenderMinimap;\n\treadonly minimapLeft: number;\n\treadonly minimapWidth: number;\n\treadonly minimapHeightIsEditorHeight: boolean;\n\treadonly minimapIsSampling: boolean;\n\treadonly minimapScale: number;\n\treadonly minimapLineHeight: number;\n\treadonly minimapCanvasInnerWidth: number;\n\treadonly minimapCanvasInnerHeight: number;\n\treadonly minimapCanvasOuterWidth: number;\n\treadonly minimapCanvasOuterHeight: number;\n}\n\n/**\n * @internal\n */\nexport interface EditorLayoutInfoComputerEnv {\n\treadonly memory: ComputeOptionsMemory | null;\n\treadonly outerWidth: number;\n\treadonly outerHeight: number;\n\treadonly isDominatedByLongLines: boolean;\n\treadonly lineHeight: number;\n\treadonly viewLineCount: number;\n\treadonly lineNumbersDigitCount: number;\n\treadonly typicalHalfwidthCharacterWidth: number;\n\treadonly maxDigitWidth: number;\n\treadonly pixelRatio: number;\n}\n\n/**\n * @internal\n */\nexport interface IMinimapLayoutInput {\n\treadonly outerWidth: number;\n\treadonly outerHeight: number;\n\treadonly lineHeight: number;\n\treadonly typicalHalfwidthCharacterWidth: number;\n\treadonly pixelRatio: number;\n\treadonly scrollBeyondLastLine: boolean;\n\treadonly minimap: Readonly>;\n\treadonly verticalScrollbarWidth: number;\n\treadonly viewLineCount: number;\n\treadonly remainingWidth: number;\n\treadonly isViewportWrapping: boolean;\n}\n\n/**\n * @internal\n */\nexport class EditorLayoutInfoComputer extends ComputedEditorOption {\n\n\tconstructor() {\n\t\tsuper(EditorOption.layoutInfo);\n\t}\n\n\tpublic compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: EditorLayoutInfo): EditorLayoutInfo {\n\t\treturn EditorLayoutInfoComputer.computeLayout(options, {\n\t\t\tmemory: env.memory,\n\t\t\touterWidth: env.outerWidth,\n\t\t\touterHeight: env.outerHeight,\n\t\t\tisDominatedByLongLines: env.isDominatedByLongLines,\n\t\t\tlineHeight: env.fontInfo.lineHeight,\n\t\t\tviewLineCount: env.viewLineCount,\n\t\t\tlineNumbersDigitCount: env.lineNumbersDigitCount,\n\t\t\ttypicalHalfwidthCharacterWidth: env.fontInfo.typicalHalfwidthCharacterWidth,\n\t\t\tmaxDigitWidth: env.fontInfo.maxDigitWidth,\n\t\t\tpixelRatio: env.pixelRatio\n\t\t});\n\t}\n\n\tpublic static computeContainedMinimapLineCount(input: {\n\t\tviewLineCount: number;\n\t\tscrollBeyondLastLine: boolean;\n\t\theight: number;\n\t\tlineHeight: number;\n\t\tpixelRatio: number;\n\t}): { typicalViewportLineCount: number; extraLinesBeyondLastLine: number; desiredRatio: number; minimapLineCount: number; } {\n\t\tconst typicalViewportLineCount = input.height / input.lineHeight;\n\t\tconst extraLinesBeyondLastLine = input.scrollBeyondLastLine ? (typicalViewportLineCount - 1) : 0;\n\t\tconst desiredRatio = (input.viewLineCount + extraLinesBeyondLastLine) / (input.pixelRatio * input.height);\n\t\tconst minimapLineCount = Math.floor(input.viewLineCount / desiredRatio);\n\t\treturn { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount };\n\t}\n\n\tprivate static _computeMinimapLayout(input: IMinimapLayoutInput, memory: ComputeOptionsMemory): EditorMinimapLayoutInfo {\n\t\tconst outerWidth = input.outerWidth;\n\t\tconst outerHeight = input.outerHeight;\n\t\tconst pixelRatio = input.pixelRatio;\n\n\t\tif (!input.minimap.enabled) {\n\t\t\treturn {\n\t\t\t\trenderMinimap: RenderMinimap.None,\n\t\t\t\tminimapLeft: 0,\n\t\t\t\tminimapWidth: 0,\n\t\t\t\tminimapHeightIsEditorHeight: false,\n\t\t\t\tminimapIsSampling: false,\n\t\t\t\tminimapScale: 1,\n\t\t\t\tminimapLineHeight: 1,\n\t\t\t\tminimapCanvasInnerWidth: 0,\n\t\t\t\tminimapCanvasInnerHeight: Math.floor(pixelRatio * outerHeight),\n\t\t\t\tminimapCanvasOuterWidth: 0,\n\t\t\t\tminimapCanvasOuterHeight: outerHeight,\n\t\t\t};\n\t\t}\n\n\t\t// Can use memory if only the `viewLineCount` and `remainingWidth` have changed\n\t\tconst stableMinimapLayoutInput = memory.stableMinimapLayoutInput;\n\t\tconst couldUseMemory = (\n\t\t\tstableMinimapLayoutInput\n\t\t\t// && input.outerWidth === lastMinimapLayoutInput.outerWidth !!! INTENTIONAL OMITTED\n\t\t\t&& input.outerHeight === stableMinimapLayoutInput.outerHeight\n\t\t\t&& input.lineHeight === stableMinimapLayoutInput.lineHeight\n\t\t\t&& input.typicalHalfwidthCharacterWidth === stableMinimapLayoutInput.typicalHalfwidthCharacterWidth\n\t\t\t&& input.pixelRatio === stableMinimapLayoutInput.pixelRatio\n\t\t\t&& input.scrollBeyondLastLine === stableMinimapLayoutInput.scrollBeyondLastLine\n\t\t\t&& input.minimap.enabled === stableMinimapLayoutInput.minimap.enabled\n\t\t\t&& input.minimap.side === stableMinimapLayoutInput.minimap.side\n\t\t\t&& input.minimap.size === stableMinimapLayoutInput.minimap.size\n\t\t\t&& input.minimap.showSlider === stableMinimapLayoutInput.minimap.showSlider\n\t\t\t&& input.minimap.renderCharacters === stableMinimapLayoutInput.minimap.renderCharacters\n\t\t\t&& input.minimap.maxColumn === stableMinimapLayoutInput.minimap.maxColumn\n\t\t\t&& input.minimap.scale === stableMinimapLayoutInput.minimap.scale\n\t\t\t&& input.verticalScrollbarWidth === stableMinimapLayoutInput.verticalScrollbarWidth\n\t\t\t// && input.viewLineCount === lastMinimapLayoutInput.viewLineCount !!! INTENTIONAL OMITTED\n\t\t\t// && input.remainingWidth === lastMinimapLayoutInput.remainingWidth !!! INTENTIONAL OMITTED\n\t\t\t&& input.isViewportWrapping === stableMinimapLayoutInput.isViewportWrapping\n\t\t);\n\n\t\tconst lineHeight = input.lineHeight;\n\t\tconst typicalHalfwidthCharacterWidth = input.typicalHalfwidthCharacterWidth;\n\t\tconst scrollBeyondLastLine = input.scrollBeyondLastLine;\n\t\tconst minimapRenderCharacters = input.minimap.renderCharacters;\n\t\tlet minimapScale = (pixelRatio >= 2 ? Math.round(input.minimap.scale * 2) : input.minimap.scale);\n\t\tconst minimapMaxColumn = input.minimap.maxColumn;\n\t\tconst minimapSize = input.minimap.size;\n\t\tconst minimapSide = input.minimap.side;\n\t\tconst verticalScrollbarWidth = input.verticalScrollbarWidth;\n\t\tconst viewLineCount = input.viewLineCount;\n\t\tconst remainingWidth = input.remainingWidth;\n\t\tconst isViewportWrapping = input.isViewportWrapping;\n\n\t\tconst baseCharHeight = minimapRenderCharacters ? 2 : 3;\n\t\tlet minimapCanvasInnerHeight = Math.floor(pixelRatio * outerHeight);\n\t\tconst minimapCanvasOuterHeight = minimapCanvasInnerHeight / pixelRatio;\n\t\tlet minimapHeightIsEditorHeight = false;\n\t\tlet minimapIsSampling = false;\n\t\tlet minimapLineHeight = baseCharHeight * minimapScale;\n\t\tlet minimapCharWidth = minimapScale / pixelRatio;\n\t\tlet minimapWidthMultiplier: number = 1;\n\n\t\tif (minimapSize === 'fill' || minimapSize === 'fit') {\n\t\t\tconst { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({\n\t\t\t\tviewLineCount: viewLineCount,\n\t\t\t\tscrollBeyondLastLine: scrollBeyondLastLine,\n\t\t\t\theight: outerHeight,\n\t\t\t\tlineHeight: lineHeight,\n\t\t\t\tpixelRatio: pixelRatio\n\t\t\t});\n\t\t\t// ratio is intentionally not part of the layout to avoid the layout changing all the time\n\t\t\t// when doing sampling\n\t\t\tconst ratio = viewLineCount / minimapLineCount;\n\n\t\t\tif (ratio > 1) {\n\t\t\t\tminimapHeightIsEditorHeight = true;\n\t\t\t\tminimapIsSampling = true;\n\t\t\t\tminimapScale = 1;\n\t\t\t\tminimapLineHeight = 1;\n\t\t\t\tminimapCharWidth = minimapScale / pixelRatio;\n\t\t\t} else {\n\t\t\t\tlet fitBecomesFill = false;\n\t\t\t\tlet maxMinimapScale = minimapScale + 1;\n\n\t\t\t\tif (minimapSize === 'fit') {\n\t\t\t\t\tconst effectiveMinimapHeight = Math.ceil((viewLineCount + extraLinesBeyondLastLine) * minimapLineHeight);\n\t\t\t\t\tif (isViewportWrapping && couldUseMemory && remainingWidth <= memory.stableFitRemainingWidth) {\n\t\t\t\t\t\t// There is a loop when using `fit` and viewport wrapping:\n\t\t\t\t\t\t// - view line count impacts minimap layout\n\t\t\t\t\t\t// - minimap layout impacts viewport width\n\t\t\t\t\t\t// - viewport width impacts view line count\n\t\t\t\t\t\t// To break the loop, once we go to a smaller minimap scale, we try to stick with it.\n\t\t\t\t\t\tfitBecomesFill = true;\n\t\t\t\t\t\tmaxMinimapScale = memory.stableFitMaxMinimapScale;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfitBecomesFill = (effectiveMinimapHeight > minimapCanvasInnerHeight);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (minimapSize === 'fill' || fitBecomesFill) {\n\t\t\t\t\tminimapHeightIsEditorHeight = true;\n\t\t\t\t\tconst configuredMinimapScale = minimapScale;\n\t\t\t\t\tminimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio)));\n\t\t\t\t\tif (isViewportWrapping && couldUseMemory && remainingWidth <= memory.stableFitRemainingWidth) {\n\t\t\t\t\t\t// There is a loop when using `fill` and viewport wrapping:\n\t\t\t\t\t\t// - view line count impacts minimap layout\n\t\t\t\t\t\t// - minimap layout impacts viewport width\n\t\t\t\t\t\t// - viewport width impacts view line count\n\t\t\t\t\t\t// To break the loop, once we go to a smaller minimap scale, we try to stick with it.\n\t\t\t\t\t\tmaxMinimapScale = memory.stableFitMaxMinimapScale;\n\t\t\t\t\t}\n\t\t\t\t\tminimapScale = Math.min(maxMinimapScale, Math.max(1, Math.floor(minimapLineHeight / baseCharHeight)));\n\t\t\t\t\tif (minimapScale > configuredMinimapScale) {\n\t\t\t\t\t\tminimapWidthMultiplier = Math.min(2, minimapScale / configuredMinimapScale);\n\t\t\t\t\t}\n\t\t\t\t\tminimapCharWidth = minimapScale / pixelRatio / minimapWidthMultiplier;\n\t\t\t\t\tminimapCanvasInnerHeight = Math.ceil((Math.max(typicalViewportLineCount, viewLineCount + extraLinesBeyondLastLine)) * minimapLineHeight);\n\t\t\t\t\tif (isViewportWrapping) {\n\t\t\t\t\t\t// remember for next time\n\t\t\t\t\t\tmemory.stableMinimapLayoutInput = input;\n\t\t\t\t\t\tmemory.stableFitRemainingWidth = remainingWidth;\n\t\t\t\t\t\tmemory.stableFitMaxMinimapScale = minimapScale;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmemory.stableMinimapLayoutInput = null;\n\t\t\t\t\t\tmemory.stableFitRemainingWidth = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Given:\n\t\t// (leaving 2px for the cursor to have space after the last character)\n\t\t// viewportColumn = (contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth\n\t\t// minimapWidth = viewportColumn * minimapCharWidth\n\t\t// contentWidth = remainingWidth - minimapWidth\n\t\t// What are good values for contentWidth and minimapWidth ?\n\n\t\t// minimapWidth = ((contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth) * minimapCharWidth\n\t\t// typicalHalfwidthCharacterWidth * minimapWidth = (contentWidth - verticalScrollbarWidth - 2) * minimapCharWidth\n\t\t// typicalHalfwidthCharacterWidth * minimapWidth = (remainingWidth - minimapWidth - verticalScrollbarWidth - 2) * minimapCharWidth\n\t\t// (typicalHalfwidthCharacterWidth + minimapCharWidth) * minimapWidth = (remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth\n\t\t// minimapWidth = ((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth)\n\n\t\tconst minimapMaxWidth = Math.floor(minimapMaxColumn * minimapCharWidth);\n\t\tconst minimapWidth = Math.min(minimapMaxWidth, Math.max(0, Math.floor(((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth))) + MINIMAP_GUTTER_WIDTH);\n\n\t\tlet minimapCanvasInnerWidth = Math.floor(pixelRatio * minimapWidth);\n\t\tconst minimapCanvasOuterWidth = minimapCanvasInnerWidth / pixelRatio;\n\t\tminimapCanvasInnerWidth = Math.floor(minimapCanvasInnerWidth * minimapWidthMultiplier);\n\n\t\tconst renderMinimap = (minimapRenderCharacters ? RenderMinimap.Text : RenderMinimap.Blocks);\n\t\tconst minimapLeft = (minimapSide === 'left' ? 0 : (outerWidth - minimapWidth - verticalScrollbarWidth));\n\n\t\treturn {\n\t\t\trenderMinimap,\n\t\t\tminimapLeft,\n\t\t\tminimapWidth,\n\t\t\tminimapHeightIsEditorHeight,\n\t\t\tminimapIsSampling,\n\t\t\tminimapScale,\n\t\t\tminimapLineHeight,\n\t\t\tminimapCanvasInnerWidth,\n\t\t\tminimapCanvasInnerHeight,\n\t\t\tminimapCanvasOuterWidth,\n\t\t\tminimapCanvasOuterHeight,\n\t\t};\n\t}\n\n\tpublic static computeLayout(options: IComputedEditorOptions, env: EditorLayoutInfoComputerEnv): EditorLayoutInfo {\n\t\tconst outerWidth = env.outerWidth | 0;\n\t\tconst outerHeight = env.outerHeight | 0;\n\t\tconst lineHeight = env.lineHeight | 0;\n\t\tconst lineNumbersDigitCount = env.lineNumbersDigitCount | 0;\n\t\tconst typicalHalfwidthCharacterWidth = env.typicalHalfwidthCharacterWidth;\n\t\tconst maxDigitWidth = env.maxDigitWidth;\n\t\tconst pixelRatio = env.pixelRatio;\n\t\tconst viewLineCount = env.viewLineCount;\n\n\t\tconst wordWrapOverride2 = options.get(EditorOption.wordWrapOverride2);\n\t\tconst wordWrapOverride1 = (wordWrapOverride2 === 'inherit' ? options.get(EditorOption.wordWrapOverride1) : wordWrapOverride2);\n\t\tconst wordWrap = (wordWrapOverride1 === 'inherit' ? options.get(EditorOption.wordWrap) : wordWrapOverride1);\n\n\t\tconst wordWrapColumn = options.get(EditorOption.wordWrapColumn);\n\t\tconst accessibilitySupport = options.get(EditorOption.accessibilitySupport);\n\t\tconst isDominatedByLongLines = env.isDominatedByLongLines;\n\n\t\tconst showGlyphMargin = options.get(EditorOption.glyphMargin);\n\t\tconst showLineNumbers = (options.get(EditorOption.lineNumbers).renderType !== RenderLineNumbersType.Off);\n\t\tconst lineNumbersMinChars = options.get(EditorOption.lineNumbersMinChars);\n\t\tconst scrollBeyondLastLine = options.get(EditorOption.scrollBeyondLastLine);\n\t\tconst minimap = options.get(EditorOption.minimap);\n\n\t\tconst scrollbar = options.get(EditorOption.scrollbar);\n\t\tconst verticalScrollbarWidth = scrollbar.verticalScrollbarSize;\n\t\tconst verticalScrollbarHasArrows = scrollbar.verticalHasArrows;\n\t\tconst scrollbarArrowSize = scrollbar.arrowSize;\n\t\tconst horizontalScrollbarHeight = scrollbar.horizontalScrollbarSize;\n\n\t\tconst rawLineDecorationsWidth = options.get(EditorOption.lineDecorationsWidth);\n\t\tconst folding = options.get(EditorOption.folding);\n\n\t\tlet lineDecorationsWidth: number;\n\t\tif (typeof rawLineDecorationsWidth === 'string' && /^\\d+(\\.\\d+)?ch$/.test(rawLineDecorationsWidth)) {\n\t\t\tconst multiple = parseFloat(rawLineDecorationsWidth.substr(0, rawLineDecorationsWidth.length - 2));\n\t\t\tlineDecorationsWidth = EditorIntOption.clampedInt(multiple * typicalHalfwidthCharacterWidth, 0, 0, 1000);\n\t\t} else {\n\t\t\tlineDecorationsWidth = EditorIntOption.clampedInt(rawLineDecorationsWidth, 0, 0, 1000);\n\t\t}\n\t\tif (folding) {\n\t\t\tlineDecorationsWidth += 16;\n\t\t}\n\n\t\tlet lineNumbersWidth = 0;\n\t\tif (showLineNumbers) {\n\t\t\tconst digitCount = Math.max(lineNumbersDigitCount, lineNumbersMinChars);\n\t\t\tlineNumbersWidth = Math.round(digitCount * maxDigitWidth);\n\t\t}\n\n\t\tlet glyphMarginWidth = 0;\n\t\tif (showGlyphMargin) {\n\t\t\tglyphMarginWidth = lineHeight;\n\t\t}\n\n\t\tlet glyphMarginLeft = 0;\n\t\tlet lineNumbersLeft = glyphMarginLeft + glyphMarginWidth;\n\t\tlet decorationsLeft = lineNumbersLeft + lineNumbersWidth;\n\t\tlet contentLeft = decorationsLeft + lineDecorationsWidth;\n\n\t\tconst remainingWidth = outerWidth - glyphMarginWidth - lineNumbersWidth - lineDecorationsWidth;\n\n\t\tlet isWordWrapMinified = false;\n\t\tlet isViewportWrapping = false;\n\t\tlet wrappingColumn = -1;\n\n\t\tif (accessibilitySupport !== AccessibilitySupport.Enabled) {\n\t\t\t// See https://github.com/microsoft/vscode/issues/27766\n\t\t\t// Never enable wrapping when a screen reader is attached\n\t\t\t// because arrow down etc. will not move the cursor in the way\n\t\t\t// a screen reader expects.\n\t\t\tif (wordWrapOverride1 === 'inherit' && isDominatedByLongLines) {\n\t\t\t\t// Force viewport width wrapping if model is dominated by long lines\n\t\t\t\tisWordWrapMinified = true;\n\t\t\t\tisViewportWrapping = true;\n\t\t\t} else if (wordWrap === 'on' || wordWrap === 'bounded') {\n\t\t\t\tisViewportWrapping = true;\n\t\t\t} else if (wordWrap === 'wordWrapColumn') {\n\t\t\t\twrappingColumn = wordWrapColumn;\n\t\t\t}\n\t\t}\n\n\t\tconst minimapLayout = EditorLayoutInfoComputer._computeMinimapLayout({\n\t\t\touterWidth: outerWidth,\n\t\t\touterHeight: outerHeight,\n\t\t\tlineHeight: lineHeight,\n\t\t\ttypicalHalfwidthCharacterWidth: typicalHalfwidthCharacterWidth,\n\t\t\tpixelRatio: pixelRatio,\n\t\t\tscrollBeyondLastLine: scrollBeyondLastLine,\n\t\t\tminimap: minimap,\n\t\t\tverticalScrollbarWidth: verticalScrollbarWidth,\n\t\t\tviewLineCount: viewLineCount,\n\t\t\tremainingWidth: remainingWidth,\n\t\t\tisViewportWrapping: isViewportWrapping,\n\t\t}, env.memory || new ComputeOptionsMemory());\n\n\t\tif (minimapLayout.renderMinimap !== RenderMinimap.None && minimapLayout.minimapLeft === 0) {\n\t\t\t// the minimap is rendered to the left, so move everything to the right\n\t\t\tglyphMarginLeft += minimapLayout.minimapWidth;\n\t\t\tlineNumbersLeft += minimapLayout.minimapWidth;\n\t\t\tdecorationsLeft += minimapLayout.minimapWidth;\n\t\t\tcontentLeft += minimapLayout.minimapWidth;\n\t\t}\n\t\tconst contentWidth = remainingWidth - minimapLayout.minimapWidth;\n\n\t\t// (leaving 2px for the cursor to have space after the last character)\n\t\tconst viewportColumn = Math.max(1, Math.floor((contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth));\n\n\t\tconst verticalArrowSize = (verticalScrollbarHasArrows ? scrollbarArrowSize : 0);\n\n\t\tif (isViewportWrapping) {\n\t\t\t// compute the actual wrappingColumn\n\t\t\twrappingColumn = Math.max(1, viewportColumn);\n\t\t\tif (wordWrap === 'bounded') {\n\t\t\t\twrappingColumn = Math.min(wrappingColumn, wordWrapColumn);\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\twidth: outerWidth,\n\t\t\theight: outerHeight,\n\n\t\t\tglyphMarginLeft: glyphMarginLeft,\n\t\t\tglyphMarginWidth: glyphMarginWidth,\n\n\t\t\tlineNumbersLeft: lineNumbersLeft,\n\t\t\tlineNumbersWidth: lineNumbersWidth,\n\n\t\t\tdecorationsLeft: decorationsLeft,\n\t\t\tdecorationsWidth: lineDecorationsWidth,\n\n\t\t\tcontentLeft: contentLeft,\n\t\t\tcontentWidth: contentWidth,\n\n\t\t\tminimap: minimapLayout,\n\n\t\t\tviewportColumn: viewportColumn,\n\n\t\t\tisWordWrapMinified: isWordWrapMinified,\n\t\t\tisViewportWrapping: isViewportWrapping,\n\t\t\twrappingColumn: wrappingColumn,\n\n\t\t\tverticalScrollbarWidth: verticalScrollbarWidth,\n\t\t\thorizontalScrollbarHeight: horizontalScrollbarHeight,\n\n\t\t\toverviewRuler: {\n\t\t\t\ttop: verticalArrowSize,\n\t\t\t\twidth: verticalScrollbarWidth,\n\t\t\t\theight: (outerHeight - 2 * verticalArrowSize),\n\t\t\t\tright: 0\n\t\t\t}\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region lightbulb\n\n/**\n * Configuration options for editor lightbulb\n */\nexport interface IEditorLightbulbOptions {\n\t/**\n\t * Enable the lightbulb code action.\n\t * Defaults to true.\n\t */\n\tenabled?: boolean;\n}\n\n/**\n * @internal\n */\nexport type EditorLightbulbOptions = Readonly>;\n\nclass EditorLightbulb extends BaseEditorOption {\n\n\tconstructor() {\n\t\tconst defaults: EditorLightbulbOptions = { enabled: true };\n\t\tsuper(\n\t\t\tEditorOption.lightbulb, 'lightbulb', defaults,\n\t\t\t{\n\t\t\t\t'editor.lightbulb.enabled': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.enabled,\n\t\t\t\t\tdescription: nls.localize('codeActions', \"Enables the code action lightbulb in the editor.\")\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): EditorLightbulbOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IEditorLightbulbOptions;\n\t\treturn {\n\t\t\tenabled: boolean(input.enabled, this.defaultValue.enabled)\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region inlayHints\n\n/**\n * Configuration options for editor inlayHints\n */\nexport interface IEditorInlayHintsOptions {\n\t/**\n\t * Enable the inline hints.\n\t * Defaults to true.\n\t */\n\tenabled?: boolean;\n\n\t/**\n\t * Font size of inline hints.\n\t * Default to 90% of the editor font size.\n\t */\n\tfontSize?: number;\n\n\t/**\n\t * Font family of inline hints.\n\t * Defaults to editor font family.\n\t */\n\tfontFamily?: string;\n}\n\n/**\n * @internal\n */\nexport type EditorInlayHintsOptions = Readonly>;\n\nclass EditorInlayHints extends BaseEditorOption {\n\n\tconstructor() {\n\t\tconst defaults: EditorInlayHintsOptions = { enabled: true, fontSize: 0, fontFamily: '' };\n\t\tsuper(\n\t\t\tEditorOption.inlayHints, 'inlayHints', defaults,\n\t\t\t{\n\t\t\t\t'editor.inlayHints.enabled': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.enabled,\n\t\t\t\t\tdescription: nls.localize('inlayHints.enable', \"Enables the inlay hints in the editor.\")\n\t\t\t\t},\n\t\t\t\t'editor.inlayHints.fontSize': {\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: defaults.fontSize,\n\t\t\t\t\tmarkdownDescription: nls.localize('inlayHints.fontSize', \"Controls font size of inlay hints in the editor. A default of 90% of `#editor.fontSize#` is used when the configured value is less than `5` or greater than the editor font size.\")\n\t\t\t\t},\n\t\t\t\t'editor.inlayHints.fontFamily': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: defaults.fontFamily,\n\t\t\t\t\tmarkdownDescription: nls.localize('inlayHints.fontFamily', \"Controls font family of inlay hints in the editor. When set to empty, the `#editor.fontFamily#` is used.\")\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): EditorInlayHintsOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IEditorInlayHintsOptions;\n\t\treturn {\n\t\t\tenabled: boolean(input.enabled, this.defaultValue.enabled),\n\t\t\tfontSize: EditorIntOption.clampedInt(input.fontSize, this.defaultValue.fontSize, 0, 100),\n\t\t\tfontFamily: EditorStringOption.string(input.fontFamily, this.defaultValue.fontFamily)\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region lineHeight\n\nclass EditorLineHeight extends EditorFloatOption {\n\n\tconstructor() {\n\t\tsuper(\n\t\t\tEditorOption.lineHeight, 'lineHeight',\n\t\t\tEDITOR_FONT_DEFAULTS.lineHeight,\n\t\t\tx => EditorFloatOption.clamp(x, 0, 150),\n\t\t\t{ markdownDescription: nls.localize('lineHeight', \"Controls the line height. \\n - Use 0 to automatically compute the line height from the font size.\\n - Values between 0 and 8 will be used as a multiplier with the font size.\\n - Values greater than or equal to 8 will be used as effective values.\") }\n\t\t);\n\t}\n\n\tpublic override compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: number): number {\n\t\t// The lineHeight is computed from the fontSize if it is 0.\n\t\t// Moreover, the final lineHeight respects the editor zoom level.\n\t\t// So take the result from env.fontInfo\n\t\treturn env.fontInfo.lineHeight;\n\t}\n}\n\n//#endregion\n\n//#region minimap\n\n/**\n * Configuration options for editor minimap\n */\nexport interface IEditorMinimapOptions {\n\t/**\n\t * Enable the rendering of the minimap.\n\t * Defaults to true.\n\t */\n\tenabled?: boolean;\n\t/**\n\t * Control the side of the minimap in editor.\n\t * Defaults to 'right'.\n\t */\n\tside?: 'right' | 'left';\n\t/**\n\t * Control the minimap rendering mode.\n\t * Defaults to 'actual'.\n\t */\n\tsize?: 'proportional' | 'fill' | 'fit';\n\t/**\n\t * Control the rendering of the minimap slider.\n\t * Defaults to 'mouseover'.\n\t */\n\tshowSlider?: 'always' | 'mouseover';\n\t/**\n\t * Render the actual text on a line (as opposed to color blocks).\n\t * Defaults to true.\n\t */\n\trenderCharacters?: boolean;\n\t/**\n\t * Limit the width of the minimap to render at most a certain number of columns.\n\t * Defaults to 120.\n\t */\n\tmaxColumn?: number;\n\t/**\n\t * Relative size of the font in the minimap. Defaults to 1.\n\t */\n\tscale?: number;\n}\n\n/**\n * @internal\n */\nexport type EditorMinimapOptions = Readonly>;\n\nclass EditorMinimap extends BaseEditorOption {\n\n\tconstructor() {\n\t\tconst defaults: EditorMinimapOptions = {\n\t\t\tenabled: true,\n\t\t\tsize: 'proportional',\n\t\t\tside: 'right',\n\t\t\tshowSlider: 'mouseover',\n\t\t\trenderCharacters: true,\n\t\t\tmaxColumn: 120,\n\t\t\tscale: 1,\n\t\t};\n\t\tsuper(\n\t\t\tEditorOption.minimap, 'minimap', defaults,\n\t\t\t{\n\t\t\t\t'editor.minimap.enabled': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.enabled,\n\t\t\t\t\tdescription: nls.localize('minimap.enabled', \"Controls whether the minimap is shown.\")\n\t\t\t\t},\n\t\t\t\t'editor.minimap.size': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tenum: ['proportional', 'fill', 'fit'],\n\t\t\t\t\tenumDescriptions: [\n\t\t\t\t\t\tnls.localize('minimap.size.proportional', \"The minimap has the same size as the editor contents (and might scroll).\"),\n\t\t\t\t\t\tnls.localize('minimap.size.fill', \"The minimap will stretch or shrink as necessary to fill the height of the editor (no scrolling).\"),\n\t\t\t\t\t\tnls.localize('minimap.size.fit', \"The minimap will shrink as necessary to never be larger than the editor (no scrolling).\"),\n\t\t\t\t\t],\n\t\t\t\t\tdefault: defaults.size,\n\t\t\t\t\tdescription: nls.localize('minimap.size', \"Controls the size of the minimap.\")\n\t\t\t\t},\n\t\t\t\t'editor.minimap.side': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tenum: ['left', 'right'],\n\t\t\t\t\tdefault: defaults.side,\n\t\t\t\t\tdescription: nls.localize('minimap.side', \"Controls the side where to render the minimap.\")\n\t\t\t\t},\n\t\t\t\t'editor.minimap.showSlider': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tenum: ['always', 'mouseover'],\n\t\t\t\t\tdefault: defaults.showSlider,\n\t\t\t\t\tdescription: nls.localize('minimap.showSlider', \"Controls when the minimap slider is shown.\")\n\t\t\t\t},\n\t\t\t\t'editor.minimap.scale': {\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: defaults.scale,\n\t\t\t\t\tminimum: 1,\n\t\t\t\t\tmaximum: 3,\n\t\t\t\t\tenum: [1, 2, 3],\n\t\t\t\t\tdescription: nls.localize('minimap.scale', \"Scale of content drawn in the minimap: 1, 2 or 3.\")\n\t\t\t\t},\n\t\t\t\t'editor.minimap.renderCharacters': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.renderCharacters,\n\t\t\t\t\tdescription: nls.localize('minimap.renderCharacters', \"Render the actual characters on a line as opposed to color blocks.\")\n\t\t\t\t},\n\t\t\t\t'editor.minimap.maxColumn': {\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: defaults.maxColumn,\n\t\t\t\t\tdescription: nls.localize('minimap.maxColumn', \"Limit the width of the minimap to render at most a certain number of columns.\")\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): EditorMinimapOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IEditorMinimapOptions;\n\t\treturn {\n\t\t\tenabled: boolean(input.enabled, this.defaultValue.enabled),\n\t\t\tsize: stringSet<'proportional' | 'fill' | 'fit'>(input.size, this.defaultValue.size, ['proportional', 'fill', 'fit']),\n\t\t\tside: stringSet<'right' | 'left'>(input.side, this.defaultValue.side, ['right', 'left']),\n\t\t\tshowSlider: stringSet<'always' | 'mouseover'>(input.showSlider, this.defaultValue.showSlider, ['always', 'mouseover']),\n\t\t\trenderCharacters: boolean(input.renderCharacters, this.defaultValue.renderCharacters),\n\t\t\tscale: EditorIntOption.clampedInt(input.scale, 1, 1, 3),\n\t\t\tmaxColumn: EditorIntOption.clampedInt(input.maxColumn, this.defaultValue.maxColumn, 1, 10000),\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region multiCursorModifier\n\nfunction _multiCursorModifierFromString(multiCursorModifier: 'ctrlCmd' | 'alt'): 'altKey' | 'metaKey' | 'ctrlKey' {\n\tif (multiCursorModifier === 'ctrlCmd') {\n\t\treturn (platform.isMacintosh ? 'metaKey' : 'ctrlKey');\n\t}\n\treturn 'altKey';\n}\n\n//#endregion\n\n//#region padding\n\n/**\n * Configuration options for editor padding\n */\nexport interface IEditorPaddingOptions {\n\t/**\n\t * Spacing between top edge of editor and first line.\n\t */\n\ttop?: number;\n\t/**\n\t * Spacing between bottom edge of editor and last line.\n\t */\n\tbottom?: number;\n}\n\n/**\n * @internal\n */\nexport type InternalEditorPaddingOptions = Readonly>;\n\nclass EditorPadding extends BaseEditorOption {\n\n\tconstructor() {\n\t\tsuper(\n\t\t\tEditorOption.padding, 'padding', { top: 0, bottom: 0 },\n\t\t\t{\n\t\t\t\t'editor.padding.top': {\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: 0,\n\t\t\t\t\tminimum: 0,\n\t\t\t\t\tmaximum: 1000,\n\t\t\t\t\tdescription: nls.localize('padding.top', \"Controls the amount of space between the top edge of the editor and the first line.\")\n\t\t\t\t},\n\t\t\t\t'editor.padding.bottom': {\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: 0,\n\t\t\t\t\tminimum: 0,\n\t\t\t\t\tmaximum: 1000,\n\t\t\t\t\tdescription: nls.localize('padding.bottom', \"Controls the amount of space between the bottom edge of the editor and the last line.\")\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): InternalEditorPaddingOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IEditorPaddingOptions;\n\n\t\treturn {\n\t\t\ttop: EditorIntOption.clampedInt(input.top, 0, 0, 1000),\n\t\t\tbottom: EditorIntOption.clampedInt(input.bottom, 0, 0, 1000)\n\t\t};\n\t}\n}\n//#endregion\n\n//#region parameterHints\n\n/**\n * Configuration options for parameter hints\n */\nexport interface IEditorParameterHintOptions {\n\t/**\n\t * Enable parameter hints.\n\t * Defaults to true.\n\t */\n\tenabled?: boolean;\n\t/**\n\t * Enable cycling of parameter hints.\n\t * Defaults to false.\n\t */\n\tcycle?: boolean;\n}\n\n/**\n * @internal\n */\nexport type InternalParameterHintOptions = Readonly>;\n\nclass EditorParameterHints extends BaseEditorOption {\n\n\tconstructor() {\n\t\tconst defaults: InternalParameterHintOptions = {\n\t\t\tenabled: true,\n\t\t\tcycle: false\n\t\t};\n\t\tsuper(\n\t\t\tEditorOption.parameterHints, 'parameterHints', defaults,\n\t\t\t{\n\t\t\t\t'editor.parameterHints.enabled': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.enabled,\n\t\t\t\t\tdescription: nls.localize('parameterHints.enabled', \"Enables a pop-up that shows parameter documentation and type information as you type.\")\n\t\t\t\t},\n\t\t\t\t'editor.parameterHints.cycle': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.cycle,\n\t\t\t\t\tdescription: nls.localize('parameterHints.cycle', \"Controls whether the parameter hints menu cycles or closes when reaching the end of the list.\")\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): InternalParameterHintOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IEditorParameterHintOptions;\n\t\treturn {\n\t\t\tenabled: boolean(input.enabled, this.defaultValue.enabled),\n\t\t\tcycle: boolean(input.cycle, this.defaultValue.cycle)\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region pixelRatio\n\nclass EditorPixelRatio extends ComputedEditorOption {\n\n\tconstructor() {\n\t\tsuper(EditorOption.pixelRatio);\n\t}\n\n\tpublic compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: number): number {\n\t\treturn env.pixelRatio;\n\t}\n}\n\n//#endregion\n\n//#region quickSuggestions\n\n/**\n * Configuration options for quick suggestions\n */\nexport interface IQuickSuggestionsOptions {\n\tother?: boolean;\n\tcomments?: boolean;\n\tstrings?: boolean;\n}\n\n/**\n * @internal\n */\nexport type ValidQuickSuggestionsOptions = boolean | Readonly>;\n\nclass EditorQuickSuggestions extends BaseEditorOption {\n\n\tpublic override readonly defaultValue: Readonly>;\n\n\tconstructor() {\n\t\tconst defaults: ValidQuickSuggestionsOptions = {\n\t\t\tother: true,\n\t\t\tcomments: false,\n\t\t\tstrings: false\n\t\t};\n\t\tsuper(\n\t\t\tEditorOption.quickSuggestions, 'quickSuggestions', defaults,\n\t\t\t{\n\t\t\t\tanyOf: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tstrings: {\n\t\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\t\tdefault: defaults.strings,\n\t\t\t\t\t\t\t\tdescription: nls.localize('quickSuggestions.strings', \"Enable quick suggestions inside strings.\")\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tcomments: {\n\t\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\t\tdefault: defaults.comments,\n\t\t\t\t\t\t\t\tdescription: nls.localize('quickSuggestions.comments', \"Enable quick suggestions inside comments.\")\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tother: {\n\t\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\t\tdefault: defaults.other,\n\t\t\t\t\t\t\t\tdescription: nls.localize('quickSuggestions.other', \"Enable quick suggestions outside of strings and comments.\")\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tdefault: defaults,\n\t\t\t\tdescription: nls.localize('quickSuggestions', \"Controls whether suggestions should automatically show up while typing.\")\n\t\t\t}\n\t\t);\n\t\tthis.defaultValue = defaults;\n\t}\n\n\tpublic validate(_input: any): ValidQuickSuggestionsOptions {\n\t\tif (typeof _input === 'boolean') {\n\t\t\treturn _input;\n\t\t}\n\t\tif (_input && typeof _input === 'object') {\n\t\t\tconst input = _input as IQuickSuggestionsOptions;\n\t\t\tconst opts = {\n\t\t\t\tother: boolean(input.other, this.defaultValue.other),\n\t\t\t\tcomments: boolean(input.comments, this.defaultValue.comments),\n\t\t\t\tstrings: boolean(input.strings, this.defaultValue.strings),\n\t\t\t};\n\t\t\tif (opts.other && opts.comments && opts.strings) {\n\t\t\t\treturn true; // all on\n\t\t\t} else if (!opts.other && !opts.comments && !opts.strings) {\n\t\t\t\treturn false; // all off\n\t\t\t} else {\n\t\t\t\treturn opts;\n\t\t\t}\n\t\t}\n\t\treturn this.defaultValue;\n\t}\n}\n\n//#endregion\n\n//#region renderLineNumbers\n\nexport type LineNumbersType = 'on' | 'off' | 'relative' | 'interval' | ((lineNumber: number) => string);\n\nexport const enum RenderLineNumbersType {\n\tOff = 0,\n\tOn = 1,\n\tRelative = 2,\n\tInterval = 3,\n\tCustom = 4\n}\n\nexport interface InternalEditorRenderLineNumbersOptions {\n\treadonly renderType: RenderLineNumbersType;\n\treadonly renderFn: ((lineNumber: number) => string) | null;\n}\n\nclass EditorRenderLineNumbersOption extends BaseEditorOption {\n\n\tconstructor() {\n\t\tsuper(\n\t\t\tEditorOption.lineNumbers, 'lineNumbers', { renderType: RenderLineNumbersType.On, renderFn: null },\n\t\t\t{\n\t\t\t\ttype: 'string',\n\t\t\t\tenum: ['off', 'on', 'relative', 'interval'],\n\t\t\t\tenumDescriptions: [\n\t\t\t\t\tnls.localize('lineNumbers.off', \"Line numbers are not rendered.\"),\n\t\t\t\t\tnls.localize('lineNumbers.on', \"Line numbers are rendered as absolute number.\"),\n\t\t\t\t\tnls.localize('lineNumbers.relative', \"Line numbers are rendered as distance in lines to cursor position.\"),\n\t\t\t\t\tnls.localize('lineNumbers.interval', \"Line numbers are rendered every 10 lines.\")\n\t\t\t\t],\n\t\t\t\tdefault: 'on',\n\t\t\t\tdescription: nls.localize('lineNumbers', \"Controls the display of line numbers.\")\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(lineNumbers: any): InternalEditorRenderLineNumbersOptions {\n\t\tlet renderType: RenderLineNumbersType = this.defaultValue.renderType;\n\t\tlet renderFn: ((lineNumber: number) => string) | null = this.defaultValue.renderFn;\n\n\t\tif (typeof lineNumbers !== 'undefined') {\n\t\t\tif (typeof lineNumbers === 'function') {\n\t\t\t\trenderType = RenderLineNumbersType.Custom;\n\t\t\t\trenderFn = lineNumbers;\n\t\t\t} else if (lineNumbers === 'interval') {\n\t\t\t\trenderType = RenderLineNumbersType.Interval;\n\t\t\t} else if (lineNumbers === 'relative') {\n\t\t\t\trenderType = RenderLineNumbersType.Relative;\n\t\t\t} else if (lineNumbers === 'on') {\n\t\t\t\trenderType = RenderLineNumbersType.On;\n\t\t\t} else {\n\t\t\t\trenderType = RenderLineNumbersType.Off;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\trenderType,\n\t\t\trenderFn\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region renderValidationDecorations\n\n/**\n * @internal\n */\nexport function filterValidationDecorations(options: IComputedEditorOptions): boolean {\n\tconst renderValidationDecorations = options.get(EditorOption.renderValidationDecorations);\n\tif (renderValidationDecorations === 'editable') {\n\t\treturn options.get(EditorOption.readOnly);\n\t}\n\treturn renderValidationDecorations === 'on' ? false : true;\n}\n\n//#endregion\n\n//#region rulers\n\nexport interface IRulerOption {\n\treadonly column: number;\n\treadonly color: string | null;\n}\n\nclass EditorRulers extends BaseEditorOption {\n\n\tconstructor() {\n\t\tconst defaults: IRulerOption[] = [];\n\t\tconst columnSchema: IJSONSchema = { type: 'number', description: nls.localize('rulers.size', \"Number of monospace characters at which this editor ruler will render.\") };\n\t\tsuper(\n\t\t\tEditorOption.rulers, 'rulers', defaults,\n\t\t\t{\n\t\t\t\ttype: 'array',\n\t\t\t\titems: {\n\t\t\t\t\tanyOf: [\n\t\t\t\t\t\tcolumnSchema,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: [\n\t\t\t\t\t\t\t\t'object'\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\tcolumn: columnSchema,\n\t\t\t\t\t\t\t\tcolor: {\n\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\tdescription: nls.localize('rulers.color', \"Color of this editor ruler.\"),\n\t\t\t\t\t\t\t\t\tformat: 'color-hex'\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\tdefault: defaults,\n\t\t\t\tdescription: nls.localize('rulers', \"Render vertical rulers after a certain number of monospace characters. Use multiple values for multiple rulers. No rulers are drawn if array is empty.\")\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(input: any): IRulerOption[] {\n\t\tif (Array.isArray(input)) {\n\t\t\tconst rulers: IRulerOption[] = [];\n\t\t\tfor (let _element of input) {\n\t\t\t\tif (typeof _element === 'number') {\n\t\t\t\t\trulers.push({\n\t\t\t\t\t\tcolumn: EditorIntOption.clampedInt(_element, 0, 0, 10000),\n\t\t\t\t\t\tcolor: null\n\t\t\t\t\t});\n\t\t\t\t} else if (_element && typeof _element === 'object') {\n\t\t\t\t\tconst element = _element as IRulerOption;\n\t\t\t\t\trulers.push({\n\t\t\t\t\t\tcolumn: EditorIntOption.clampedInt(element.column, 0, 0, 10000),\n\t\t\t\t\t\tcolor: element.color\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\trulers.sort((a, b) => a.column - b.column);\n\t\t\treturn rulers;\n\t\t}\n\t\treturn this.defaultValue;\n\t}\n}\n\n//#endregion\n\n//#region scrollbar\n\n/**\n * Configuration options for editor scrollbars\n */\nexport interface IEditorScrollbarOptions {\n\t/**\n\t * The size of arrows (if displayed).\n\t * Defaults to 11.\n\t * **NOTE**: This option cannot be updated using `updateOptions()`\n\t */\n\tarrowSize?: number;\n\t/**\n\t * Render vertical scrollbar.\n\t * Defaults to 'auto'.\n\t */\n\tvertical?: 'auto' | 'visible' | 'hidden';\n\t/**\n\t * Render horizontal scrollbar.\n\t * Defaults to 'auto'.\n\t */\n\thorizontal?: 'auto' | 'visible' | 'hidden';\n\t/**\n\t * Cast horizontal and vertical shadows when the content is scrolled.\n\t * Defaults to true.\n\t * **NOTE**: This option cannot be updated using `updateOptions()`\n\t */\n\tuseShadows?: boolean;\n\t/**\n\t * Render arrows at the top and bottom of the vertical scrollbar.\n\t * Defaults to false.\n\t * **NOTE**: This option cannot be updated using `updateOptions()`\n\t */\n\tverticalHasArrows?: boolean;\n\t/**\n\t * Render arrows at the left and right of the horizontal scrollbar.\n\t * Defaults to false.\n\t * **NOTE**: This option cannot be updated using `updateOptions()`\n\t */\n\thorizontalHasArrows?: boolean;\n\t/**\n\t * Listen to mouse wheel events and react to them by scrolling.\n\t * Defaults to true.\n\t */\n\thandleMouseWheel?: boolean;\n\t/**\n\t * Always consume mouse wheel events (always call preventDefault() and stopPropagation() on the browser events).\n\t * Defaults to true.\n\t * **NOTE**: This option cannot be updated using `updateOptions()`\n\t */\n\talwaysConsumeMouseWheel?: boolean;\n\t/**\n\t * Height in pixels for the horizontal scrollbar.\n\t * Defaults to 10 (px).\n\t */\n\thorizontalScrollbarSize?: number;\n\t/**\n\t * Width in pixels for the vertical scrollbar.\n\t * Defaults to 10 (px).\n\t */\n\tverticalScrollbarSize?: number;\n\t/**\n\t * Width in pixels for the vertical slider.\n\t * Defaults to `verticalScrollbarSize`.\n\t * **NOTE**: This option cannot be updated using `updateOptions()`\n\t */\n\tverticalSliderSize?: number;\n\t/**\n\t * Height in pixels for the horizontal slider.\n\t * Defaults to `horizontalScrollbarSize`.\n\t * **NOTE**: This option cannot be updated using `updateOptions()`\n\t */\n\thorizontalSliderSize?: number;\n\t/**\n\t * Scroll gutter clicks move by page vs jump to position.\n\t * Defaults to false.\n\t */\n\tscrollByPage?: boolean;\n}\n\nexport interface InternalEditorScrollbarOptions {\n\treadonly arrowSize: number;\n\treadonly vertical: ScrollbarVisibility;\n\treadonly horizontal: ScrollbarVisibility;\n\treadonly useShadows: boolean;\n\treadonly verticalHasArrows: boolean;\n\treadonly horizontalHasArrows: boolean;\n\treadonly handleMouseWheel: boolean;\n\treadonly alwaysConsumeMouseWheel: boolean;\n\treadonly horizontalScrollbarSize: number;\n\treadonly horizontalSliderSize: number;\n\treadonly verticalScrollbarSize: number;\n\treadonly verticalSliderSize: number;\n\treadonly scrollByPage: boolean;\n}\n\nfunction _scrollbarVisibilityFromString(visibility: string | undefined, defaultValue: ScrollbarVisibility): ScrollbarVisibility {\n\tif (typeof visibility !== 'string') {\n\t\treturn defaultValue;\n\t}\n\tswitch (visibility) {\n\t\tcase 'hidden': return ScrollbarVisibility.Hidden;\n\t\tcase 'visible': return ScrollbarVisibility.Visible;\n\t\tdefault: return ScrollbarVisibility.Auto;\n\t}\n}\n\nclass EditorScrollbar extends BaseEditorOption {\n\n\tconstructor() {\n\t\tconst defaults: InternalEditorScrollbarOptions = {\n\t\t\tvertical: ScrollbarVisibility.Auto,\n\t\t\thorizontal: ScrollbarVisibility.Auto,\n\t\t\tarrowSize: 11,\n\t\t\tuseShadows: true,\n\t\t\tverticalHasArrows: false,\n\t\t\thorizontalHasArrows: false,\n\t\t\thorizontalScrollbarSize: 12,\n\t\t\thorizontalSliderSize: 12,\n\t\t\tverticalScrollbarSize: 14,\n\t\t\tverticalSliderSize: 14,\n\t\t\thandleMouseWheel: true,\n\t\t\talwaysConsumeMouseWheel: true,\n\t\t\tscrollByPage: false\n\t\t};\n\t\tsuper(\n\t\t\tEditorOption.scrollbar, 'scrollbar', defaults,\n\t\t\t{\n\t\t\t\t'editor.scrollbar.vertical': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tenum: ['auto', 'visible', 'hidden'],\n\t\t\t\t\tenumDescriptions: [\n\t\t\t\t\t\tnls.localize('scrollbar.vertical.auto', \"The vertical scrollbar will be visible only when necessary.\"),\n\t\t\t\t\t\tnls.localize('scrollbar.vertical.visible', \"The vertical scrollbar will always be visible.\"),\n\t\t\t\t\t\tnls.localize('scrollbar.vertical.fit', \"The vertical scrollbar will always be hidden.\"),\n\t\t\t\t\t],\n\t\t\t\t\tdefault: 'auto',\n\t\t\t\t\tdescription: nls.localize('scrollbar.vertical', \"Controls the visibility of the vertical scrollbar.\")\n\t\t\t\t},\n\t\t\t\t'editor.scrollbar.horizontal': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tenum: ['auto', 'visible', 'hidden'],\n\t\t\t\t\tenumDescriptions: [\n\t\t\t\t\t\tnls.localize('scrollbar.horizontal.auto', \"The horizontal scrollbar will be visible only when necessary.\"),\n\t\t\t\t\t\tnls.localize('scrollbar.horizontal.visible', \"The horizontal scrollbar will always be visible.\"),\n\t\t\t\t\t\tnls.localize('scrollbar.horizontal.fit', \"The horizontal scrollbar will always be hidden.\"),\n\t\t\t\t\t],\n\t\t\t\t\tdefault: 'auto',\n\t\t\t\t\tdescription: nls.localize('scrollbar.horizontal', \"Controls the visibility of the horizontal scrollbar.\")\n\t\t\t\t},\n\t\t\t\t'editor.scrollbar.verticalScrollbarSize': {\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: defaults.verticalScrollbarSize,\n\t\t\t\t\tdescription: nls.localize('scrollbar.verticalScrollbarSize', \"The width of the vertical scrollbar.\")\n\t\t\t\t},\n\t\t\t\t'editor.scrollbar.horizontalScrollbarSize': {\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: defaults.horizontalScrollbarSize,\n\t\t\t\t\tdescription: nls.localize('scrollbar.horizontalScrollbarSize', \"The height of the horizontal scrollbar.\")\n\t\t\t\t},\n\t\t\t\t'editor.scrollbar.scrollByPage': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.scrollByPage,\n\t\t\t\t\tdescription: nls.localize('scrollbar.scrollByPage', \"Controls whether clicks scroll by page or jump to click position.\")\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): InternalEditorScrollbarOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IEditorScrollbarOptions;\n\t\tconst horizontalScrollbarSize = EditorIntOption.clampedInt(input.horizontalScrollbarSize, this.defaultValue.horizontalScrollbarSize, 0, 1000);\n\t\tconst verticalScrollbarSize = EditorIntOption.clampedInt(input.verticalScrollbarSize, this.defaultValue.verticalScrollbarSize, 0, 1000);\n\t\treturn {\n\t\t\tarrowSize: EditorIntOption.clampedInt(input.arrowSize, this.defaultValue.arrowSize, 0, 1000),\n\t\t\tvertical: _scrollbarVisibilityFromString(input.vertical, this.defaultValue.vertical),\n\t\t\thorizontal: _scrollbarVisibilityFromString(input.horizontal, this.defaultValue.horizontal),\n\t\t\tuseShadows: boolean(input.useShadows, this.defaultValue.useShadows),\n\t\t\tverticalHasArrows: boolean(input.verticalHasArrows, this.defaultValue.verticalHasArrows),\n\t\t\thorizontalHasArrows: boolean(input.horizontalHasArrows, this.defaultValue.horizontalHasArrows),\n\t\t\thandleMouseWheel: boolean(input.handleMouseWheel, this.defaultValue.handleMouseWheel),\n\t\t\talwaysConsumeMouseWheel: boolean(input.alwaysConsumeMouseWheel, this.defaultValue.alwaysConsumeMouseWheel),\n\t\t\thorizontalScrollbarSize: horizontalScrollbarSize,\n\t\t\thorizontalSliderSize: EditorIntOption.clampedInt(input.horizontalSliderSize, horizontalScrollbarSize, 0, 1000),\n\t\t\tverticalScrollbarSize: verticalScrollbarSize,\n\t\t\tverticalSliderSize: EditorIntOption.clampedInt(input.verticalSliderSize, verticalScrollbarSize, 0, 1000),\n\t\t\tscrollByPage: boolean(input.scrollByPage, this.defaultValue.scrollByPage),\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region UnicodeHighlight\n\nexport type InUntrustedWorkspace = 'inUntrustedWorkspace';\n\n/**\n * @internal\n*/\nexport const inUntrustedWorkspace: InUntrustedWorkspace = 'inUntrustedWorkspace';\n\n/**\n * Configuration options for unicode highlighting.\n */\nexport interface IUnicodeHighlightOptions {\n\tnonBasicASCII?: boolean | InUntrustedWorkspace;\n\tinvisibleCharacters?: boolean;\n\tambiguousCharacters?: boolean;\n\tincludeComments?: boolean | InUntrustedWorkspace;\n\tincludeStrings?: boolean | InUntrustedWorkspace;\n\n\t/**\n\t * A map of allowed characters (true: allowed).\n\t*/\n\tallowedCharacters?: Record;\n\tallowedLocales?: Record;\n}\n\n/**\n * @internal\n */\nexport type InternalUnicodeHighlightOptions = Required>;\n\n/**\n * @internal\n */\nexport const unicodeHighlightConfigKeys = {\n\tallowedCharacters: 'editor.unicodeHighlight.allowedCharacters',\n\tinvisibleCharacters: 'editor.unicodeHighlight.invisibleCharacters',\n\tnonBasicASCII: 'editor.unicodeHighlight.nonBasicASCII',\n\tambiguousCharacters: 'editor.unicodeHighlight.ambiguousCharacters',\n\tincludeComments: 'editor.unicodeHighlight.includeComments',\n\tincludeStrings: 'editor.unicodeHighlight.includeStrings',\n\tallowedLocales: 'editor.unicodeHighlight.allowedLocales',\n};\n\nclass UnicodeHighlight extends BaseEditorOption {\n\tconstructor() {\n\t\tconst defaults: InternalUnicodeHighlightOptions = {\n\t\t\tnonBasicASCII: inUntrustedWorkspace,\n\t\t\tinvisibleCharacters: true,\n\t\t\tambiguousCharacters: true,\n\t\t\tincludeComments: inUntrustedWorkspace,\n\t\t\tincludeStrings: true,\n\t\t\tallowedCharacters: {},\n\t\t\tallowedLocales: { _os: true, _vscode: true },\n\t\t};\n\n\t\tsuper(\n\t\t\tEditorOption.unicodeHighlighting, 'unicodeHighlight', defaults,\n\t\t\t{\n\t\t\t\t[unicodeHighlightConfigKeys.nonBasicASCII]: {\n\t\t\t\t\trestricted: true,\n\t\t\t\t\ttype: ['boolean', 'string'],\n\t\t\t\t\tenum: [true, false, inUntrustedWorkspace],\n\t\t\t\t\tdefault: defaults.nonBasicASCII,\n\t\t\t\t\tdescription: nls.localize('unicodeHighlight.nonBasicASCII', \"Controls whether all non-basic ASCII characters are highlighted. Only characters between U+0020 and U+007E, tab, line-feed and carriage-return are considered basic ASCII.\")\n\t\t\t\t},\n\t\t\t\t[unicodeHighlightConfigKeys.invisibleCharacters]: {\n\t\t\t\t\trestricted: true,\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.invisibleCharacters,\n\t\t\t\t\tdescription: nls.localize('unicodeHighlight.invisibleCharacters', \"Controls whether characters that just reserve space or have no width at all are highlighted.\")\n\t\t\t\t},\n\t\t\t\t[unicodeHighlightConfigKeys.ambiguousCharacters]: {\n\t\t\t\t\trestricted: true,\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.ambiguousCharacters,\n\t\t\t\t\tdescription: nls.localize('unicodeHighlight.ambiguousCharacters', \"Controls whether characters are highlighted that can be confused with basic ASCII characters, except those that are common in the current user locale.\")\n\t\t\t\t},\n\t\t\t\t[unicodeHighlightConfigKeys.includeComments]: {\n\t\t\t\t\trestricted: true,\n\t\t\t\t\ttype: ['boolean', 'string'],\n\t\t\t\t\tenum: [true, false, inUntrustedWorkspace],\n\t\t\t\t\tdefault: defaults.includeComments,\n\t\t\t\t\tdescription: nls.localize('unicodeHighlight.includeComments', \"Controls whether characters in comments should also be subject to unicode highlighting.\")\n\t\t\t\t},\n\t\t\t\t[unicodeHighlightConfigKeys.includeStrings]: {\n\t\t\t\t\trestricted: true,\n\t\t\t\t\ttype: ['boolean', 'string'],\n\t\t\t\t\tenum: [true, false, inUntrustedWorkspace],\n\t\t\t\t\tdefault: defaults.includeStrings,\n\t\t\t\t\tdescription: nls.localize('unicodeHighlight.includeStrings', \"Controls whether characters in strings should also be subject to unicode highlighting.\")\n\t\t\t\t},\n\t\t\t\t[unicodeHighlightConfigKeys.allowedCharacters]: {\n\t\t\t\t\trestricted: true,\n\t\t\t\t\ttype: 'object',\n\t\t\t\t\tdefault: defaults.allowedCharacters,\n\t\t\t\t\tdescription: nls.localize('unicodeHighlight.allowedCharacters', \"Defines allowed characters that are not being highlighted.\"),\n\t\t\t\t\tadditionalProperties: {\n\t\t\t\t\t\ttype: 'boolean'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t[unicodeHighlightConfigKeys.allowedLocales]: {\n\t\t\t\t\trestricted: true,\n\t\t\t\t\ttype: 'object',\n\t\t\t\t\tadditionalProperties: {\n\t\t\t\t\t\ttype: 'boolean'\n\t\t\t\t\t},\n\t\t\t\t\tdefault: defaults.allowedLocales,\n\t\t\t\t\tdescription: nls.localize('unicodeHighlight.allowedLocales', \"Unicode characters that are common in allowed locales are not being highlighted.\")\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic override applyUpdate(value: Required>, update: Required>): ApplyUpdateResult>> {\n\t\tlet didChange = false;\n\t\tif (update.allowedCharacters) {\n\t\t\t// Treat allowedCharacters atomically\n\t\t\tif (!objects.equals(value.allowedCharacters, update.allowedCharacters)) {\n\t\t\t\tvalue = { ...value, allowedCharacters: update.allowedCharacters };\n\t\t\t\tdidChange = true;\n\t\t\t}\n\t\t}\n\t\tif (update.allowedLocales) {\n\t\t\t// Treat allowedLocales atomically\n\t\t\tif (!objects.equals(value.allowedLocales, update.allowedLocales)) {\n\t\t\t\tvalue = { ...value, allowedLocales: update.allowedLocales };\n\t\t\t\tdidChange = true;\n\t\t\t}\n\t\t}\n\n\t\tconst result = super.applyUpdate(value, update);\n\t\tif (didChange) {\n\t\t\treturn new ApplyUpdateResult(result.newValue, true);\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic validate(_input: any): InternalUnicodeHighlightOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IUnicodeHighlightOptions;\n\t\treturn {\n\t\t\tnonBasicASCII: primitiveSet(input.nonBasicASCII, inUntrustedWorkspace, [true, false, inUntrustedWorkspace]),\n\t\t\tinvisibleCharacters: boolean(input.invisibleCharacters, this.defaultValue.invisibleCharacters),\n\t\t\tambiguousCharacters: boolean(input.ambiguousCharacters, this.defaultValue.ambiguousCharacters),\n\t\t\tincludeComments: primitiveSet(input.includeComments, inUntrustedWorkspace, [true, false, inUntrustedWorkspace]),\n\t\t\tincludeStrings: primitiveSet(input.includeStrings, inUntrustedWorkspace, [true, false, inUntrustedWorkspace]),\n\t\t\tallowedCharacters: this.validateBooleanMap(_input.allowedCharacters, this.defaultValue.allowedCharacters),\n\t\t\tallowedLocales: this.validateBooleanMap(_input.allowedLocales, this.defaultValue.allowedLocales),\n\t\t};\n\t}\n\n\tprivate validateBooleanMap(map: unknown, defaultValue: Record): Record {\n\t\tif ((typeof map !== 'object') || !map) {\n\t\t\treturn defaultValue;\n\t\t}\n\t\tconst result: Record = {};\n\t\tfor (const [key, value] of Object.entries(map)) {\n\t\t\tif (value === true) {\n\t\t\t\tresult[key] = true;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n}\n\n//#endregion\n\n//#region inlineSuggest\n\nexport interface IInlineSuggestOptions {\n\t/**\n\t * Enable or disable the rendering of automatic inline completions.\n\t*/\n\tenabled?: boolean;\n\n\t/**\n\t * Configures the mode.\n\t * Use `prefix` to only show ghost text if the text to replace is a prefix of the suggestion text.\n\t * Use `subword` to only show ghost text if the replace text is a subword of the suggestion text.\n\t * Use `subwordSmart` to only show ghost text if the replace text is a subword of the suggestion text, but the subword must start after the cursor position.\n\t * Defaults to `prefix`.\n\t*/\n\tmode?: 'prefix' | 'subword' | 'subwordSmart';\n}\n\n/**\n * @internal\n */\nexport type InternalInlineSuggestOptions = Readonly>;\n\n/**\n * Configuration options for inline suggestions\n */\nclass InlineEditorSuggest extends BaseEditorOption {\n\tconstructor() {\n\t\tconst defaults: InternalInlineSuggestOptions = {\n\t\t\tenabled: true,\n\t\t\tmode: 'subwordSmart'\n\t\t};\n\n\t\tsuper(\n\t\t\tEditorOption.inlineSuggest, 'inlineSuggest', defaults,\n\t\t\t{\n\t\t\t\t'editor.inlineSuggest.enabled': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.enabled,\n\t\t\t\t\tdescription: nls.localize('inlineSuggest.enabled', \"Controls whether to automatically show inline suggestions in the editor.\")\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): InternalInlineSuggestOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IInlineSuggestOptions;\n\t\treturn {\n\t\t\tenabled: boolean(input.enabled, this.defaultValue.enabled),\n\t\t\tmode: stringSet(input.mode, this.defaultValue.mode, ['prefix', 'subword', 'subwordSmart']),\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region bracketPairColorization\n\nexport interface IBracketPairColorizationOptions {\n\t/**\n\t * Enable or disable bracket pair colorization.\n\t*/\n\tenabled?: boolean;\n}\n\n/**\n * @internal\n */\nexport type InternalBracketPairColorizationOptions = Readonly>;\n\n/**\n * Configuration options for inline suggestions\n */\nclass BracketPairColorization extends BaseEditorOption {\n\tconstructor() {\n\t\tconst defaults: InternalBracketPairColorizationOptions = {\n\t\t\tenabled: EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions.enabled\n\t\t};\n\n\t\tsuper(\n\t\t\tEditorOption.bracketPairColorization, 'bracketPairColorization', defaults,\n\t\t\t{\n\t\t\t\t'editor.bracketPairColorization.enabled': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.enabled,\n\t\t\t\t\tdescription: nls.localize('bracketPairColorization.enabled', \"Controls whether bracket pair colorization is enabled or not. Use 'workbench.colorCustomizations' to override the bracket highlight colors.\")\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): InternalBracketPairColorizationOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IBracketPairColorizationOptions;\n\t\treturn {\n\t\t\tenabled: boolean(input.enabled, this.defaultValue.enabled)\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region guides\n\nexport interface IGuidesOptions {\n\t/**\n\t * Enable rendering of bracket pair guides.\n\t * Defaults to false.\n\t*/\n\tbracketPairs?: boolean | 'active';\n\n\t/**\n\t * Enable rendering of vertical bracket pair guides.\n\t * Defaults to 'active'.\n\t */\n\tbracketPairsHorizontal?: boolean | 'active';\n\n\t/**\n\t * Enable highlighting of the active bracket pair.\n\t * Defaults to true.\n\t*/\n\thighlightActiveBracketPair?: boolean;\n\n\t/**\n\t * Enable rendering of indent guides.\n\t * Defaults to true.\n\t */\n\tindentation?: boolean;\n\n\t/**\n\t * Enable highlighting of the active indent guide.\n\t * Defaults to true.\n\t */\n\thighlightActiveIndentation?: boolean;\n}\n\n/**\n * @internal\n */\nexport type InternalGuidesOptions = Readonly>;\n\n/**\n * Configuration options for inline suggestions\n */\nclass GuideOptions extends BaseEditorOption {\n\tconstructor() {\n\t\tconst defaults: InternalGuidesOptions = {\n\t\t\tbracketPairs: false,\n\t\t\tbracketPairsHorizontal: 'active',\n\t\t\thighlightActiveBracketPair: true,\n\n\t\t\tindentation: true,\n\t\t\thighlightActiveIndentation: true\n\t\t};\n\n\t\tsuper(\n\t\t\tEditorOption.guides, 'guides', defaults,\n\t\t\t{\n\t\t\t\t'editor.guides.bracketPairs': {\n\t\t\t\t\ttype: ['boolean', 'string'],\n\t\t\t\t\tenum: [true, 'active', false],\n\t\t\t\t\tenumDescriptions: [\n\t\t\t\t\t\tnls.localize('editor.guides.bracketPairs.true', \"Enables bracket pair guides.\"),\n\t\t\t\t\t\tnls.localize('editor.guides.bracketPairs.active', \"Enables bracket pair guides only for the active bracket pair.\"),\n\t\t\t\t\t\tnls.localize('editor.guides.bracketPairs.false', \"Disables bracket pair guides.\"),\n\t\t\t\t\t],\n\t\t\t\t\tdefault: defaults.bracketPairs,\n\t\t\t\t\tdescription: nls.localize('editor.guides.bracketPairs', \"Controls whether bracket pair guides are enabled or not.\")\n\t\t\t\t},\n\t\t\t\t'editor.guides.bracketPairsHorizontal': {\n\t\t\t\t\ttype: ['boolean', 'string'],\n\t\t\t\t\tenum: [true, 'active', false],\n\t\t\t\t\tenumDescriptions: [\n\t\t\t\t\t\tnls.localize('editor.guides.bracketPairsHorizontal.true', \"Enables horizontal guides as addition to vertical bracket pair guides.\"),\n\t\t\t\t\t\tnls.localize('editor.guides.bracketPairsHorizontal.active', \"Enables horizontal guides only for the active bracket pair.\"),\n\t\t\t\t\t\tnls.localize('editor.guides.bracketPairsHorizontal.false', \"Disables horizontal bracket pair guides.\"),\n\t\t\t\t\t],\n\t\t\t\t\tdefault: defaults.bracketPairsHorizontal,\n\t\t\t\t\tdescription: nls.localize('editor.guides.bracketPairsHorizontal', \"Controls whether horizontal bracket pair guides are enabled or not.\")\n\t\t\t\t},\n\t\t\t\t'editor.guides.highlightActiveBracketPair': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.highlightActiveBracketPair,\n\t\t\t\t\tdescription: nls.localize('editor.guides.highlightActiveBracketPair', \"Controls whether bracket pair guides are enabled or not.\")\n\t\t\t\t},\n\t\t\t\t'editor.guides.indentation': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.indentation,\n\t\t\t\t\tdescription: nls.localize('editor.guides.indentation', \"Controls whether the editor should render indent guides.\")\n\t\t\t\t},\n\t\t\t\t'editor.guides.highlightActiveIndentation': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.highlightActiveIndentation,\n\t\t\t\t\tdescription: nls.localize('editor.guides.highlightActiveIndentation', \"Controls whether the editor should highlight the active indent guide.\")\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): InternalGuidesOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as IGuidesOptions;\n\t\treturn {\n\t\t\tbracketPairs: primitiveSet(input.bracketPairs, this.defaultValue.bracketPairs, [true, false, 'active']),\n\t\t\tbracketPairsHorizontal: primitiveSet(input.bracketPairsHorizontal, this.defaultValue.bracketPairsHorizontal, [true, false, 'active']),\n\t\t\thighlightActiveBracketPair: boolean(input.highlightActiveBracketPair, this.defaultValue.highlightActiveBracketPair),\n\n\t\t\tindentation: boolean(input.indentation, this.defaultValue.indentation),\n\t\t\thighlightActiveIndentation: boolean(input.highlightActiveIndentation, this.defaultValue.highlightActiveIndentation),\n\t\t};\n\t}\n}\n\nfunction primitiveSet(value: unknown, defaultValue: T, allowedValues: T[]): T {\n\tconst idx = allowedValues.indexOf(value as any);\n\tif (idx === -1) {\n\t\treturn defaultValue;\n\t}\n\treturn allowedValues[idx];\n}\n\n//#endregion\n\n//#region suggest\n\n/**\n * Configuration options for editor suggest widget\n */\nexport interface ISuggestOptions {\n\t/**\n\t * Overwrite word ends on accept. Default to false.\n\t */\n\tinsertMode?: 'insert' | 'replace';\n\t/**\n\t * Enable graceful matching. Defaults to true.\n\t */\n\tfilterGraceful?: boolean;\n\t/**\n\t * Prevent quick suggestions when a snippet is active. Defaults to true.\n\t */\n\tsnippetsPreventQuickSuggestions?: boolean;\n\t/**\n\t * Favors words that appear close to the cursor.\n\t */\n\tlocalityBonus?: boolean;\n\t/**\n\t * Enable using global storage for remembering suggestions.\n\t */\n\tshareSuggestSelections?: boolean;\n\t/**\n\t * Enable or disable icons in suggestions. Defaults to true.\n\t */\n\tshowIcons?: boolean;\n\t/**\n\t * Enable or disable the suggest status bar.\n\t */\n\tshowStatusBar?: boolean;\n\t/**\n\t * Enable or disable the rendering of the suggestion preview.\n\t */\n\tpreview?: boolean;\n\t/**\n\t * Configures the mode of the preview.\n\t*/\n\tpreviewMode?: 'prefix' | 'subword' | 'subwordSmart';\n\t/**\n\t * Show details inline with the label. Defaults to true.\n\t */\n\tshowInlineDetails?: boolean;\n\t/**\n\t * Show method-suggestions.\n\t */\n\tshowMethods?: boolean;\n\t/**\n\t * Show function-suggestions.\n\t */\n\tshowFunctions?: boolean;\n\t/**\n\t * Show constructor-suggestions.\n\t */\n\tshowConstructors?: boolean;\n\t/**\n\t * Show deprecated-suggestions.\n\t */\n\tshowDeprecated?: boolean;\n\t/**\n\t * Show field-suggestions.\n\t */\n\tshowFields?: boolean;\n\t/**\n\t * Show variable-suggestions.\n\t */\n\tshowVariables?: boolean;\n\t/**\n\t * Show class-suggestions.\n\t */\n\tshowClasses?: boolean;\n\t/**\n\t * Show struct-suggestions.\n\t */\n\tshowStructs?: boolean;\n\t/**\n\t * Show interface-suggestions.\n\t */\n\tshowInterfaces?: boolean;\n\t/**\n\t * Show module-suggestions.\n\t */\n\tshowModules?: boolean;\n\t/**\n\t * Show property-suggestions.\n\t */\n\tshowProperties?: boolean;\n\t/**\n\t * Show event-suggestions.\n\t */\n\tshowEvents?: boolean;\n\t/**\n\t * Show operator-suggestions.\n\t */\n\tshowOperators?: boolean;\n\t/**\n\t * Show unit-suggestions.\n\t */\n\tshowUnits?: boolean;\n\t/**\n\t * Show value-suggestions.\n\t */\n\tshowValues?: boolean;\n\t/**\n\t * Show constant-suggestions.\n\t */\n\tshowConstants?: boolean;\n\t/**\n\t * Show enum-suggestions.\n\t */\n\tshowEnums?: boolean;\n\t/**\n\t * Show enumMember-suggestions.\n\t */\n\tshowEnumMembers?: boolean;\n\t/**\n\t * Show keyword-suggestions.\n\t */\n\tshowKeywords?: boolean;\n\t/**\n\t * Show text-suggestions.\n\t */\n\tshowWords?: boolean;\n\t/**\n\t * Show color-suggestions.\n\t */\n\tshowColors?: boolean;\n\t/**\n\t * Show file-suggestions.\n\t */\n\tshowFiles?: boolean;\n\t/**\n\t * Show reference-suggestions.\n\t */\n\tshowReferences?: boolean;\n\t/**\n\t * Show folder-suggestions.\n\t */\n\tshowFolders?: boolean;\n\t/**\n\t * Show typeParameter-suggestions.\n\t */\n\tshowTypeParameters?: boolean;\n\t/**\n\t * Show issue-suggestions.\n\t */\n\tshowIssues?: boolean;\n\t/**\n\t * Show user-suggestions.\n\t */\n\tshowUsers?: boolean;\n\t/**\n\t * Show snippet-suggestions.\n\t */\n\tshowSnippets?: boolean;\n}\n\n/**\n * @internal\n */\nexport type InternalSuggestOptions = Readonly>;\n\nclass EditorSuggest extends BaseEditorOption {\n\n\tconstructor() {\n\t\tconst defaults: InternalSuggestOptions = {\n\t\t\tinsertMode: 'insert',\n\t\t\tfilterGraceful: true,\n\t\t\tsnippetsPreventQuickSuggestions: true,\n\t\t\tlocalityBonus: false,\n\t\t\tshareSuggestSelections: false,\n\t\t\tshowIcons: true,\n\t\t\tshowStatusBar: false,\n\t\t\tpreview: false,\n\t\t\tpreviewMode: 'subwordSmart',\n\t\t\tshowInlineDetails: true,\n\t\t\tshowMethods: true,\n\t\t\tshowFunctions: true,\n\t\t\tshowConstructors: true,\n\t\t\tshowDeprecated: true,\n\t\t\tshowFields: true,\n\t\t\tshowVariables: true,\n\t\t\tshowClasses: true,\n\t\t\tshowStructs: true,\n\t\t\tshowInterfaces: true,\n\t\t\tshowModules: true,\n\t\t\tshowProperties: true,\n\t\t\tshowEvents: true,\n\t\t\tshowOperators: true,\n\t\t\tshowUnits: true,\n\t\t\tshowValues: true,\n\t\t\tshowConstants: true,\n\t\t\tshowEnums: true,\n\t\t\tshowEnumMembers: true,\n\t\t\tshowKeywords: true,\n\t\t\tshowWords: true,\n\t\t\tshowColors: true,\n\t\t\tshowFiles: true,\n\t\t\tshowReferences: true,\n\t\t\tshowFolders: true,\n\t\t\tshowTypeParameters: true,\n\t\t\tshowSnippets: true,\n\t\t\tshowUsers: true,\n\t\t\tshowIssues: true,\n\t\t};\n\t\tsuper(\n\t\t\tEditorOption.suggest, 'suggest', defaults,\n\t\t\t{\n\t\t\t\t'editor.suggest.insertMode': {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tenum: ['insert', 'replace'],\n\t\t\t\t\tenumDescriptions: [\n\t\t\t\t\t\tnls.localize('suggest.insertMode.insert', \"Insert suggestion without overwriting text right of the cursor.\"),\n\t\t\t\t\t\tnls.localize('suggest.insertMode.replace', \"Insert suggestion and overwrite text right of the cursor.\"),\n\t\t\t\t\t],\n\t\t\t\t\tdefault: defaults.insertMode,\n\t\t\t\t\tdescription: nls.localize('suggest.insertMode', \"Controls whether words are overwritten when accepting completions. Note that this depends on extensions opting into this feature.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.filterGraceful': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.filterGraceful,\n\t\t\t\t\tdescription: nls.localize('suggest.filterGraceful', \"Controls whether filtering and sorting suggestions accounts for small typos.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.localityBonus': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.localityBonus,\n\t\t\t\t\tdescription: nls.localize('suggest.localityBonus', \"Controls whether sorting favors words that appear close to the cursor.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.shareSuggestSelections': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.shareSuggestSelections,\n\t\t\t\t\tmarkdownDescription: nls.localize('suggest.shareSuggestSelections', \"Controls whether remembered suggestion selections are shared between multiple workspaces and windows (needs `#editor.suggestSelection#`).\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.snippetsPreventQuickSuggestions': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.snippetsPreventQuickSuggestions,\n\t\t\t\t\tdescription: nls.localize('suggest.snippetsPreventQuickSuggestions', \"Controls whether an active snippet prevents quick suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showIcons': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.showIcons,\n\t\t\t\t\tdescription: nls.localize('suggest.showIcons', \"Controls whether to show or hide icons in suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showStatusBar': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.showStatusBar,\n\t\t\t\t\tdescription: nls.localize('suggest.showStatusBar', \"Controls the visibility of the status bar at the bottom of the suggest widget.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.preview': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.preview,\n\t\t\t\t\tdescription: nls.localize('suggest.preview', \"Controls whether to preview the suggestion outcome in the editor.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showInlineDetails': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: defaults.showInlineDetails,\n\t\t\t\t\tdescription: nls.localize('suggest.showInlineDetails', \"Controls whether suggest details show inline with the label or only in the details widget\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.maxVisibleSuggestions': {\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdeprecationMessage: nls.localize('suggest.maxVisibleSuggestions.dep', \"This setting is deprecated. The suggest widget can now be resized.\"),\n\t\t\t\t},\n\t\t\t\t'editor.suggest.filteredTypes': {\n\t\t\t\t\ttype: 'object',\n\t\t\t\t\tdeprecationMessage: nls.localize('deprecated', \"This setting is deprecated, please use separate settings like 'editor.suggest.showKeywords' or 'editor.suggest.showSnippets' instead.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showMethods': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showMethods', \"When enabled IntelliSense shows `method`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showFunctions': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showFunctions', \"When enabled IntelliSense shows `function`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showConstructors': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showConstructors', \"When enabled IntelliSense shows `constructor`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showDeprecated': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showDeprecated', \"When enabled IntelliSense shows `deprecated`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showFields': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showFields', \"When enabled IntelliSense shows `field`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showVariables': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showVariables', \"When enabled IntelliSense shows `variable`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showClasses': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showClasss', \"When enabled IntelliSense shows `class`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showStructs': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showStructs', \"When enabled IntelliSense shows `struct`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showInterfaces': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showInterfaces', \"When enabled IntelliSense shows `interface`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showModules': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showModules', \"When enabled IntelliSense shows `module`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showProperties': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showPropertys', \"When enabled IntelliSense shows `property`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showEvents': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showEvents', \"When enabled IntelliSense shows `event`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showOperators': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showOperators', \"When enabled IntelliSense shows `operator`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showUnits': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showUnits', \"When enabled IntelliSense shows `unit`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showValues': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showValues', \"When enabled IntelliSense shows `value`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showConstants': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showConstants', \"When enabled IntelliSense shows `constant`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showEnums': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showEnums', \"When enabled IntelliSense shows `enum`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showEnumMembers': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showEnumMembers', \"When enabled IntelliSense shows `enumMember`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showKeywords': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showKeywords', \"When enabled IntelliSense shows `keyword`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showWords': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showTexts', \"When enabled IntelliSense shows `text`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showColors': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showColors', \"When enabled IntelliSense shows `color`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showFiles': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showFiles', \"When enabled IntelliSense shows `file`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showReferences': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showReferences', \"When enabled IntelliSense shows `reference`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showCustomcolors': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showCustomcolors', \"When enabled IntelliSense shows `customcolor`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showFolders': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showFolders', \"When enabled IntelliSense shows `folder`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showTypeParameters': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showTypeParameters', \"When enabled IntelliSense shows `typeParameter`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showSnippets': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showSnippets', \"When enabled IntelliSense shows `snippet`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showUsers': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showUsers', \"When enabled IntelliSense shows `user`-suggestions.\")\n\t\t\t\t},\n\t\t\t\t'editor.suggest.showIssues': {\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: true,\n\t\t\t\t\tmarkdownDescription: nls.localize('editor.suggest.showIssues', \"When enabled IntelliSense shows `issues`-suggestions.\")\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(_input: any): InternalSuggestOptions {\n\t\tif (!_input || typeof _input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\tconst input = _input as ISuggestOptions;\n\t\treturn {\n\t\t\tinsertMode: stringSet(input.insertMode, this.defaultValue.insertMode, ['insert', 'replace']),\n\t\t\tfilterGraceful: boolean(input.filterGraceful, this.defaultValue.filterGraceful),\n\t\t\tsnippetsPreventQuickSuggestions: boolean(input.snippetsPreventQuickSuggestions, this.defaultValue.filterGraceful),\n\t\t\tlocalityBonus: boolean(input.localityBonus, this.defaultValue.localityBonus),\n\t\t\tshareSuggestSelections: boolean(input.shareSuggestSelections, this.defaultValue.shareSuggestSelections),\n\t\t\tshowIcons: boolean(input.showIcons, this.defaultValue.showIcons),\n\t\t\tshowStatusBar: boolean(input.showStatusBar, this.defaultValue.showStatusBar),\n\t\t\tpreview: boolean(input.preview, this.defaultValue.preview),\n\t\t\tpreviewMode: stringSet(input.previewMode, this.defaultValue.previewMode, ['prefix', 'subword', 'subwordSmart']),\n\t\t\tshowInlineDetails: boolean(input.showInlineDetails, this.defaultValue.showInlineDetails),\n\t\t\tshowMethods: boolean(input.showMethods, this.defaultValue.showMethods),\n\t\t\tshowFunctions: boolean(input.showFunctions, this.defaultValue.showFunctions),\n\t\t\tshowConstructors: boolean(input.showConstructors, this.defaultValue.showConstructors),\n\t\t\tshowDeprecated: boolean(input.showDeprecated, this.defaultValue.showDeprecated),\n\t\t\tshowFields: boolean(input.showFields, this.defaultValue.showFields),\n\t\t\tshowVariables: boolean(input.showVariables, this.defaultValue.showVariables),\n\t\t\tshowClasses: boolean(input.showClasses, this.defaultValue.showClasses),\n\t\t\tshowStructs: boolean(input.showStructs, this.defaultValue.showStructs),\n\t\t\tshowInterfaces: boolean(input.showInterfaces, this.defaultValue.showInterfaces),\n\t\t\tshowModules: boolean(input.showModules, this.defaultValue.showModules),\n\t\t\tshowProperties: boolean(input.showProperties, this.defaultValue.showProperties),\n\t\t\tshowEvents: boolean(input.showEvents, this.defaultValue.showEvents),\n\t\t\tshowOperators: boolean(input.showOperators, this.defaultValue.showOperators),\n\t\t\tshowUnits: boolean(input.showUnits, this.defaultValue.showUnits),\n\t\t\tshowValues: boolean(input.showValues, this.defaultValue.showValues),\n\t\t\tshowConstants: boolean(input.showConstants, this.defaultValue.showConstants),\n\t\t\tshowEnums: boolean(input.showEnums, this.defaultValue.showEnums),\n\t\t\tshowEnumMembers: boolean(input.showEnumMembers, this.defaultValue.showEnumMembers),\n\t\t\tshowKeywords: boolean(input.showKeywords, this.defaultValue.showKeywords),\n\t\t\tshowWords: boolean(input.showWords, this.defaultValue.showWords),\n\t\t\tshowColors: boolean(input.showColors, this.defaultValue.showColors),\n\t\t\tshowFiles: boolean(input.showFiles, this.defaultValue.showFiles),\n\t\t\tshowReferences: boolean(input.showReferences, this.defaultValue.showReferences),\n\t\t\tshowFolders: boolean(input.showFolders, this.defaultValue.showFolders),\n\t\t\tshowTypeParameters: boolean(input.showTypeParameters, this.defaultValue.showTypeParameters),\n\t\t\tshowSnippets: boolean(input.showSnippets, this.defaultValue.showSnippets),\n\t\t\tshowUsers: boolean(input.showUsers, this.defaultValue.showUsers),\n\t\t\tshowIssues: boolean(input.showIssues, this.defaultValue.showIssues),\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region smart select\n\nexport interface ISmartSelectOptions {\n\tselectLeadingAndTrailingWhitespace?: boolean\n}\n\n/**\n * @internal\n */\nexport type SmartSelectOptions = Readonly>;\n\nclass SmartSelect extends BaseEditorOption {\n\n\tconstructor() {\n\t\tsuper(\n\t\t\tEditorOption.smartSelect, 'smartSelect',\n\t\t\t{\n\t\t\t\tselectLeadingAndTrailingWhitespace: true\n\t\t\t},\n\t\t\t{\n\t\t\t\t'editor.smartSelect.selectLeadingAndTrailingWhitespace': {\n\t\t\t\t\tdescription: nls.localize('selectLeadingAndTrailingWhitespace', \"Whether leading and trailing whitespace should always be selected.\"),\n\t\t\t\t\tdefault: true,\n\t\t\t\t\ttype: 'boolean'\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic validate(input: any): Readonly> {\n\t\tif (!input || typeof input !== 'object') {\n\t\t\treturn this.defaultValue;\n\t\t}\n\t\treturn {\n\t\t\tselectLeadingAndTrailingWhitespace: boolean((input as ISmartSelectOptions).selectLeadingAndTrailingWhitespace, this.defaultValue.selectLeadingAndTrailingWhitespace)\n\t\t};\n\t}\n}\n\n//#endregion\n\n//#region tabFocusMode\n\nclass EditorTabFocusMode extends ComputedEditorOption {\n\n\tconstructor() {\n\t\tsuper(EditorOption.tabFocusMode);\n\t}\n\n\tpublic compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: boolean): boolean {\n\t\tconst readOnly = options.get(EditorOption.readOnly);\n\t\treturn (readOnly ? true : env.tabFocusMode);\n\t}\n}\n\n//#endregion\n\n//#region wrappingIndent\n\n/**\n * Describes how to indent wrapped lines.\n */\nexport const enum WrappingIndent {\n\t/**\n\t * No indentation => wrapped lines begin at column 1.\n\t */\n\tNone = 0,\n\t/**\n\t * Same => wrapped lines get the same indentation as the parent.\n\t */\n\tSame = 1,\n\t/**\n\t * Indent => wrapped lines get +1 indentation toward the parent.\n\t */\n\tIndent = 2,\n\t/**\n\t * DeepIndent => wrapped lines get +2 indentation toward the parent.\n\t */\n\tDeepIndent = 3\n}\n\nfunction _wrappingIndentFromString(wrappingIndent: 'none' | 'same' | 'indent' | 'deepIndent'): WrappingIndent {\n\tswitch (wrappingIndent) {\n\t\tcase 'none': return WrappingIndent.None;\n\t\tcase 'same': return WrappingIndent.Same;\n\t\tcase 'indent': return WrappingIndent.Indent;\n\t\tcase 'deepIndent': return WrappingIndent.DeepIndent;\n\t}\n}\n\n//#endregion\n\n//#region wrappingInfo\n\nexport interface EditorWrappingInfo {\n\treadonly isDominatedByLongLines: boolean;\n\treadonly isWordWrapMinified: boolean;\n\treadonly isViewportWrapping: boolean;\n\treadonly wrappingColumn: number;\n}\n\nclass EditorWrappingInfoComputer extends ComputedEditorOption {\n\n\tconstructor() {\n\t\tsuper(EditorOption.wrappingInfo);\n\t}\n\n\tpublic compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: EditorWrappingInfo): EditorWrappingInfo {\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\n\t\treturn {\n\t\t\tisDominatedByLongLines: env.isDominatedByLongLines,\n\t\t\tisWordWrapMinified: layoutInfo.isWordWrapMinified,\n\t\t\tisViewportWrapping: layoutInfo.isViewportWrapping,\n\t\t\twrappingColumn: layoutInfo.wrappingColumn,\n\t\t};\n\t}\n}\n\n//#endregion\n\nconst DEFAULT_WINDOWS_FONT_FAMILY = 'Consolas, \\'Courier New\\', monospace';\nconst DEFAULT_MAC_FONT_FAMILY = 'Menlo, Monaco, \\'Courier New\\', monospace';\nconst DEFAULT_LINUX_FONT_FAMILY = '\\'Droid Sans Mono\\', \\'monospace\\', monospace';\n\n/**\n * @internal\n */\nexport const EDITOR_FONT_DEFAULTS = {\n\tfontFamily: (\n\t\tplatform.isMacintosh ? DEFAULT_MAC_FONT_FAMILY : (platform.isLinux ? DEFAULT_LINUX_FONT_FAMILY : DEFAULT_WINDOWS_FONT_FAMILY)\n\t),\n\tfontWeight: 'normal',\n\tfontSize: (\n\t\tplatform.isMacintosh ? 12 : 14\n\t),\n\tlineHeight: 0,\n\tletterSpacing: 0,\n};\n\n/**\n * @internal\n */\nexport const editorOptionsRegistry: IEditorOption[] = [];\n\nfunction register(option: IEditorOption): IEditorOption {\n\teditorOptionsRegistry[option.id] = option;\n\treturn option;\n}\n\nexport const enum EditorOption {\n\tacceptSuggestionOnCommitCharacter,\n\tacceptSuggestionOnEnter,\n\taccessibilitySupport,\n\taccessibilityPageSize,\n\tariaLabel,\n\tautoClosingBrackets,\n\tautoClosingDelete,\n\tautoClosingOvertype,\n\tautoClosingQuotes,\n\tautoIndent,\n\tautomaticLayout,\n\tautoSurround,\n\tbracketPairColorization,\n\tguides,\n\tcodeLens,\n\tcodeLensFontFamily,\n\tcodeLensFontSize,\n\tcolorDecorators,\n\tcolumnSelection,\n\tcomments,\n\tcontextmenu,\n\tcopyWithSyntaxHighlighting,\n\tcursorBlinking,\n\tcursorSmoothCaretAnimation,\n\tcursorStyle,\n\tcursorSurroundingLines,\n\tcursorSurroundingLinesStyle,\n\tcursorWidth,\n\tdisableLayerHinting,\n\tdisableMonospaceOptimizations,\n\tdomReadOnly,\n\tdragAndDrop,\n\temptySelectionClipboard,\n\textraEditorClassName,\n\tfastScrollSensitivity,\n\tfind,\n\tfixedOverflowWidgets,\n\tfolding,\n\tfoldingStrategy,\n\tfoldingHighlight,\n\tfoldingImportsByDefault,\n\tfoldingMaximumRegions,\n\tunfoldOnClickAfterEndOfLine,\n\tfontFamily,\n\tfontInfo,\n\tfontLigatures,\n\tfontSize,\n\tfontWeight,\n\tformatOnPaste,\n\tformatOnType,\n\tglyphMargin,\n\tgotoLocation,\n\thideCursorInOverviewRuler,\n\thover,\n\tinDiffEditor,\n\tinlineSuggest,\n\tletterSpacing,\n\tlightbulb,\n\tlineDecorationsWidth,\n\tlineHeight,\n\tlineNumbers,\n\tlineNumbersMinChars,\n\tlinkedEditing,\n\tlinks,\n\tmatchBrackets,\n\tminimap,\n\tmouseStyle,\n\tmouseWheelScrollSensitivity,\n\tmouseWheelZoom,\n\tmultiCursorMergeOverlapping,\n\tmultiCursorModifier,\n\tmultiCursorPaste,\n\toccurrencesHighlight,\n\toverviewRulerBorder,\n\toverviewRulerLanes,\n\tpadding,\n\tparameterHints,\n\tpeekWidgetDefaultFocus,\n\tdefinitionLinkOpensInPeek,\n\tquickSuggestions,\n\tquickSuggestionsDelay,\n\treadOnly,\n\trenameOnType,\n\trenderControlCharacters,\n\trenderFinalNewline,\n\trenderLineHighlight,\n\trenderLineHighlightOnlyWhenFocus,\n\trenderValidationDecorations,\n\trenderWhitespace,\n\trevealHorizontalRightPadding,\n\troundedSelection,\n\trulers,\n\tscrollbar,\n\tscrollBeyondLastColumn,\n\tscrollBeyondLastLine,\n\tscrollPredominantAxis,\n\tselectionClipboard,\n\tselectionHighlight,\n\tselectOnLineNumbers,\n\tshowFoldingControls,\n\tshowUnused,\n\tsnippetSuggestions,\n\tsmartSelect,\n\tsmoothScrolling,\n\tstickyTabStops,\n\tstopRenderingLineAfter,\n\tsuggest,\n\tsuggestFontSize,\n\tsuggestLineHeight,\n\tsuggestOnTriggerCharacters,\n\tsuggestSelection,\n\ttabCompletion,\n\ttabIndex,\n\tunicodeHighlighting,\n\tunusualLineTerminators,\n\tuseShadowDOM,\n\tuseTabStops,\n\twordSeparators,\n\twordWrap,\n\twordWrapBreakAfterCharacters,\n\twordWrapBreakBeforeCharacters,\n\twordWrapColumn,\n\twordWrapOverride1,\n\twordWrapOverride2,\n\twrappingIndent,\n\twrappingStrategy,\n\tshowDeprecated,\n\tinlayHints,\n\t// Leave these at the end (because they have dependencies!)\n\teditorClassName,\n\tpixelRatio,\n\ttabFocusMode,\n\tlayoutInfo,\n\twrappingInfo,\n}\n\nexport const EditorOptions = {\n\tacceptSuggestionOnCommitCharacter: register(new EditorBooleanOption(\n\t\tEditorOption.acceptSuggestionOnCommitCharacter, 'acceptSuggestionOnCommitCharacter', true,\n\t\t{ markdownDescription: nls.localize('acceptSuggestionOnCommitCharacter', \"Controls whether suggestions should be accepted on commit characters. For example, in JavaScript, the semi-colon (`;`) can be a commit character that accepts a suggestion and types that character.\") }\n\t)),\n\tacceptSuggestionOnEnter: register(new EditorStringEnumOption(\n\t\tEditorOption.acceptSuggestionOnEnter, 'acceptSuggestionOnEnter',\n\t\t'on' as 'on' | 'smart' | 'off',\n\t\t['on', 'smart', 'off'] as const,\n\t\t{\n\t\t\tmarkdownEnumDescriptions: [\n\t\t\t\t'',\n\t\t\t\tnls.localize('acceptSuggestionOnEnterSmart', \"Only accept a suggestion with `Enter` when it makes a textual change.\"),\n\t\t\t\t''\n\t\t\t],\n\t\t\tmarkdownDescription: nls.localize('acceptSuggestionOnEnter', \"Controls whether suggestions should be accepted on `Enter`, in addition to `Tab`. Helps to avoid ambiguity between inserting new lines or accepting suggestions.\")\n\t\t}\n\t)),\n\taccessibilitySupport: register(new EditorAccessibilitySupport()),\n\taccessibilityPageSize: register(new EditorIntOption(EditorOption.accessibilityPageSize, 'accessibilityPageSize', 10, 1, Constants.MAX_SAFE_SMALL_INTEGER,\n\t\t{\n\t\t\tdescription: nls.localize('accessibilityPageSize', \"Controls the number of lines in the editor that can be read out by a screen reader at once. When we detect a screen reader we automatically set the default to be 500. Warning: this has a performance implication for numbers larger than the default.\")\n\t\t})),\n\tariaLabel: register(new EditorStringOption(\n\t\tEditorOption.ariaLabel, 'ariaLabel', nls.localize('editorViewAccessibleLabel', \"Editor content\")\n\t)),\n\tautoClosingBrackets: register(new EditorStringEnumOption(\n\t\tEditorOption.autoClosingBrackets, 'autoClosingBrackets',\n\t\t'languageDefined' as 'always' | 'languageDefined' | 'beforeWhitespace' | 'never',\n\t\t['always', 'languageDefined', 'beforeWhitespace', 'never'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\t'',\n\t\t\t\tnls.localize('editor.autoClosingBrackets.languageDefined', \"Use language configurations to determine when to autoclose brackets.\"),\n\t\t\t\tnls.localize('editor.autoClosingBrackets.beforeWhitespace', \"Autoclose brackets only when the cursor is to the left of whitespace.\"),\n\t\t\t\t'',\n\t\t\t],\n\t\t\tdescription: nls.localize('autoClosingBrackets', \"Controls whether the editor should automatically close brackets after the user adds an opening bracket.\")\n\t\t}\n\t)),\n\tautoClosingDelete: register(new EditorStringEnumOption(\n\t\tEditorOption.autoClosingDelete, 'autoClosingDelete',\n\t\t'auto' as 'always' | 'auto' | 'never',\n\t\t['always', 'auto', 'never'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\t'',\n\t\t\t\tnls.localize('editor.autoClosingDelete.auto', \"Remove adjacent closing quotes or brackets only if they were automatically inserted.\"),\n\t\t\t\t'',\n\t\t\t],\n\t\t\tdescription: nls.localize('autoClosingDelete', \"Controls whether the editor should remove adjacent closing quotes or brackets when deleting.\")\n\t\t}\n\t)),\n\tautoClosingOvertype: register(new EditorStringEnumOption(\n\t\tEditorOption.autoClosingOvertype, 'autoClosingOvertype',\n\t\t'auto' as 'always' | 'auto' | 'never',\n\t\t['always', 'auto', 'never'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\t'',\n\t\t\t\tnls.localize('editor.autoClosingOvertype.auto', \"Type over closing quotes or brackets only if they were automatically inserted.\"),\n\t\t\t\t'',\n\t\t\t],\n\t\t\tdescription: nls.localize('autoClosingOvertype', \"Controls whether the editor should type over closing quotes or brackets.\")\n\t\t}\n\t)),\n\tautoClosingQuotes: register(new EditorStringEnumOption(\n\t\tEditorOption.autoClosingQuotes, 'autoClosingQuotes',\n\t\t'languageDefined' as 'always' | 'languageDefined' | 'beforeWhitespace' | 'never',\n\t\t['always', 'languageDefined', 'beforeWhitespace', 'never'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\t'',\n\t\t\t\tnls.localize('editor.autoClosingQuotes.languageDefined', \"Use language configurations to determine when to autoclose quotes.\"),\n\t\t\t\tnls.localize('editor.autoClosingQuotes.beforeWhitespace', \"Autoclose quotes only when the cursor is to the left of whitespace.\"),\n\t\t\t\t'',\n\t\t\t],\n\t\t\tdescription: nls.localize('autoClosingQuotes', \"Controls whether the editor should automatically close quotes after the user adds an opening quote.\")\n\t\t}\n\t)),\n\tautoIndent: register(new EditorEnumOption(\n\t\tEditorOption.autoIndent, 'autoIndent',\n\t\tEditorAutoIndentStrategy.Full, 'full',\n\t\t['none', 'keep', 'brackets', 'advanced', 'full'],\n\t\t_autoIndentFromString,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('editor.autoIndent.none', \"The editor will not insert indentation automatically.\"),\n\t\t\t\tnls.localize('editor.autoIndent.keep', \"The editor will keep the current line's indentation.\"),\n\t\t\t\tnls.localize('editor.autoIndent.brackets', \"The editor will keep the current line's indentation and honor language defined brackets.\"),\n\t\t\t\tnls.localize('editor.autoIndent.advanced', \"The editor will keep the current line's indentation, honor language defined brackets and invoke special onEnterRules defined by languages.\"),\n\t\t\t\tnls.localize('editor.autoIndent.full', \"The editor will keep the current line's indentation, honor language defined brackets, invoke special onEnterRules defined by languages, and honor indentationRules defined by languages.\"),\n\t\t\t],\n\t\t\tdescription: nls.localize('autoIndent', \"Controls whether the editor should automatically adjust the indentation when users type, paste, move or indent lines.\")\n\t\t}\n\t)),\n\tautomaticLayout: register(new EditorBooleanOption(\n\t\tEditorOption.automaticLayout, 'automaticLayout', false,\n\t)),\n\tautoSurround: register(new EditorStringEnumOption(\n\t\tEditorOption.autoSurround, 'autoSurround',\n\t\t'languageDefined' as 'languageDefined' | 'quotes' | 'brackets' | 'never',\n\t\t['languageDefined', 'quotes', 'brackets', 'never'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('editor.autoSurround.languageDefined', \"Use language configurations to determine when to automatically surround selections.\"),\n\t\t\t\tnls.localize('editor.autoSurround.quotes', \"Surround with quotes but not brackets.\"),\n\t\t\t\tnls.localize('editor.autoSurround.brackets', \"Surround with brackets but not quotes.\"),\n\t\t\t\t''\n\t\t\t],\n\t\t\tdescription: nls.localize('autoSurround', \"Controls whether the editor should automatically surround selections when typing quotes or brackets.\")\n\t\t}\n\t)),\n\tbracketPairColorization: register(new BracketPairColorization()),\n\tbracketPairGuides: register(new GuideOptions()),\n\tstickyTabStops: register(new EditorBooleanOption(\n\t\tEditorOption.stickyTabStops, 'stickyTabStops', false,\n\t\t{ description: nls.localize('stickyTabStops', \"Emulate selection behavior of tab characters when using spaces for indentation. Selection will stick to tab stops.\") }\n\t)),\n\tcodeLens: register(new EditorBooleanOption(\n\t\tEditorOption.codeLens, 'codeLens', true,\n\t\t{ description: nls.localize('codeLens', \"Controls whether the editor shows CodeLens.\") }\n\t)),\n\tcodeLensFontFamily: register(new EditorStringOption(\n\t\tEditorOption.codeLensFontFamily, 'codeLensFontFamily', '',\n\t\t{ description: nls.localize('codeLensFontFamily', \"Controls the font family for CodeLens.\") }\n\t)),\n\tcodeLensFontSize: register(new EditorIntOption(EditorOption.codeLensFontSize, 'codeLensFontSize', 0, 0, 100, {\n\t\ttype: 'number',\n\t\tdefault: 0,\n\t\tminimum: 0,\n\t\tmaximum: 100,\n\t\tmarkdownDescription: nls.localize('codeLensFontSize', \"Controls the font size in pixels for CodeLens. When set to `0`, 90% of `#editor.fontSize#` is used.\")\n\t})),\n\tcolorDecorators: register(new EditorBooleanOption(\n\t\tEditorOption.colorDecorators, 'colorDecorators', true,\n\t\t{ description: nls.localize('colorDecorators', \"Controls whether the editor should render the inline color decorators and color picker.\") }\n\t)),\n\tcolumnSelection: register(new EditorBooleanOption(\n\t\tEditorOption.columnSelection, 'columnSelection', false,\n\t\t{ description: nls.localize('columnSelection', \"Enable that the selection with the mouse and keys is doing column selection.\") }\n\t)),\n\tcomments: register(new EditorComments()),\n\tcontextmenu: register(new EditorBooleanOption(\n\t\tEditorOption.contextmenu, 'contextmenu', true,\n\t)),\n\tcopyWithSyntaxHighlighting: register(new EditorBooleanOption(\n\t\tEditorOption.copyWithSyntaxHighlighting, 'copyWithSyntaxHighlighting', true,\n\t\t{ description: nls.localize('copyWithSyntaxHighlighting', \"Controls whether syntax highlighting should be copied into the clipboard.\") }\n\t)),\n\tcursorBlinking: register(new EditorEnumOption(\n\t\tEditorOption.cursorBlinking, 'cursorBlinking',\n\t\tTextEditorCursorBlinkingStyle.Blink, 'blink',\n\t\t['blink', 'smooth', 'phase', 'expand', 'solid'],\n\t\t_cursorBlinkingStyleFromString,\n\t\t{ description: nls.localize('cursorBlinking', \"Control the cursor animation style.\") }\n\t)),\n\tcursorSmoothCaretAnimation: register(new EditorBooleanOption(\n\t\tEditorOption.cursorSmoothCaretAnimation, 'cursorSmoothCaretAnimation', false,\n\t\t{ description: nls.localize('cursorSmoothCaretAnimation', \"Controls whether the smooth caret animation should be enabled.\") }\n\t)),\n\tcursorStyle: register(new EditorEnumOption(\n\t\tEditorOption.cursorStyle, 'cursorStyle',\n\t\tTextEditorCursorStyle.Line, 'line',\n\t\t['line', 'block', 'underline', 'line-thin', 'block-outline', 'underline-thin'],\n\t\t_cursorStyleFromString,\n\t\t{ description: nls.localize('cursorStyle', \"Controls the cursor style.\") }\n\t)),\n\tcursorSurroundingLines: register(new EditorIntOption(\n\t\tEditorOption.cursorSurroundingLines, 'cursorSurroundingLines',\n\t\t0, 0, Constants.MAX_SAFE_SMALL_INTEGER,\n\t\t{ description: nls.localize('cursorSurroundingLines', \"Controls the minimal number of visible leading and trailing lines surrounding the cursor. Known as 'scrollOff' or 'scrollOffset' in some other editors.\") }\n\t)),\n\tcursorSurroundingLinesStyle: register(new EditorStringEnumOption(\n\t\tEditorOption.cursorSurroundingLinesStyle, 'cursorSurroundingLinesStyle',\n\t\t'default' as 'default' | 'all',\n\t\t['default', 'all'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('cursorSurroundingLinesStyle.default', \"`cursorSurroundingLines` is enforced only when triggered via the keyboard or API.\"),\n\t\t\t\tnls.localize('cursorSurroundingLinesStyle.all', \"`cursorSurroundingLines` is enforced always.\")\n\t\t\t],\n\t\t\tdescription: nls.localize('cursorSurroundingLinesStyle', \"Controls when `cursorSurroundingLines` should be enforced.\")\n\t\t}\n\t)),\n\tcursorWidth: register(new EditorIntOption(\n\t\tEditorOption.cursorWidth, 'cursorWidth',\n\t\t0, 0, Constants.MAX_SAFE_SMALL_INTEGER,\n\t\t{ markdownDescription: nls.localize('cursorWidth', \"Controls the width of the cursor when `#editor.cursorStyle#` is set to `line`.\") }\n\t)),\n\tdisableLayerHinting: register(new EditorBooleanOption(\n\t\tEditorOption.disableLayerHinting, 'disableLayerHinting', false,\n\t)),\n\tdisableMonospaceOptimizations: register(new EditorBooleanOption(\n\t\tEditorOption.disableMonospaceOptimizations, 'disableMonospaceOptimizations', false\n\t)),\n\tdomReadOnly: register(new EditorBooleanOption(\n\t\tEditorOption.domReadOnly, 'domReadOnly', false,\n\t)),\n\tdragAndDrop: register(new EditorBooleanOption(\n\t\tEditorOption.dragAndDrop, 'dragAndDrop', true,\n\t\t{ description: nls.localize('dragAndDrop', \"Controls whether the editor should allow moving selections via drag and drop.\") }\n\t)),\n\temptySelectionClipboard: register(new EditorEmptySelectionClipboard()),\n\textraEditorClassName: register(new EditorStringOption(\n\t\tEditorOption.extraEditorClassName, 'extraEditorClassName', '',\n\t)),\n\tfastScrollSensitivity: register(new EditorFloatOption(\n\t\tEditorOption.fastScrollSensitivity, 'fastScrollSensitivity',\n\t\t5, x => (x <= 0 ? 5 : x),\n\t\t{ markdownDescription: nls.localize('fastScrollSensitivity', \"Scrolling speed multiplier when pressing `Alt`.\") }\n\t)),\n\tfind: register(new EditorFind()),\n\tfixedOverflowWidgets: register(new EditorBooleanOption(\n\t\tEditorOption.fixedOverflowWidgets, 'fixedOverflowWidgets', false,\n\t)),\n\tfolding: register(new EditorBooleanOption(\n\t\tEditorOption.folding, 'folding', true,\n\t\t{ description: nls.localize('folding', \"Controls whether the editor has code folding enabled.\") }\n\t)),\n\tfoldingStrategy: register(new EditorStringEnumOption(\n\t\tEditorOption.foldingStrategy, 'foldingStrategy',\n\t\t'auto' as 'auto' | 'indentation',\n\t\t['auto', 'indentation'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('foldingStrategy.auto', \"Use a language-specific folding strategy if available, else the indentation-based one.\"),\n\t\t\t\tnls.localize('foldingStrategy.indentation', \"Use the indentation-based folding strategy.\"),\n\t\t\t],\n\t\t\tdescription: nls.localize('foldingStrategy', \"Controls the strategy for computing folding ranges.\")\n\t\t}\n\t)),\n\tfoldingHighlight: register(new EditorBooleanOption(\n\t\tEditorOption.foldingHighlight, 'foldingHighlight', true,\n\t\t{ description: nls.localize('foldingHighlight', \"Controls whether the editor should highlight folded ranges.\") }\n\t)),\n\tfoldingImportsByDefault: register(new EditorBooleanOption(\n\t\tEditorOption.foldingImportsByDefault, 'foldingImportsByDefault', false,\n\t\t{ description: nls.localize('foldingImportsByDefault', \"Controls whether the editor automatically collapses import ranges.\") }\n\t)),\n\tfoldingMaximumRegions: register(new EditorIntOption(\n\t\tEditorOption.foldingMaximumRegions, 'foldingMaximumRegions',\n\t\t5000, 10, 65000, // limit must be less than foldingRanges MAX_FOLDING_REGIONS\n\t\t{ description: nls.localize('foldingMaximumRegions', \"The maximum number of foldable regions. Increasing this value may result in the editor becoming less responsive when the current source has a large number of foldable regions.\") }\n\t)),\n\tunfoldOnClickAfterEndOfLine: register(new EditorBooleanOption(\n\t\tEditorOption.unfoldOnClickAfterEndOfLine, 'unfoldOnClickAfterEndOfLine', false,\n\t\t{ description: nls.localize('unfoldOnClickAfterEndOfLine', \"Controls whether clicking on the empty content after a folded line will unfold the line.\") }\n\t)),\n\tfontFamily: register(new EditorStringOption(\n\t\tEditorOption.fontFamily, 'fontFamily', EDITOR_FONT_DEFAULTS.fontFamily,\n\t\t{ description: nls.localize('fontFamily', \"Controls the font family.\") }\n\t)),\n\tfontInfo: register(new EditorFontInfo()),\n\tfontLigatures2: register(new EditorFontLigatures()),\n\tfontSize: register(new EditorFontSize()),\n\tfontWeight: register(new EditorFontWeight()),\n\tformatOnPaste: register(new EditorBooleanOption(\n\t\tEditorOption.formatOnPaste, 'formatOnPaste', false,\n\t\t{ description: nls.localize('formatOnPaste', \"Controls whether the editor should automatically format the pasted content. A formatter must be available and the formatter should be able to format a range in a document.\") }\n\t)),\n\tformatOnType: register(new EditorBooleanOption(\n\t\tEditorOption.formatOnType, 'formatOnType', false,\n\t\t{ description: nls.localize('formatOnType', \"Controls whether the editor should automatically format the line after typing.\") }\n\t)),\n\tglyphMargin: register(new EditorBooleanOption(\n\t\tEditorOption.glyphMargin, 'glyphMargin', true,\n\t\t{ description: nls.localize('glyphMargin', \"Controls whether the editor should render the vertical glyph margin. Glyph margin is mostly used for debugging.\") }\n\t)),\n\tgotoLocation: register(new EditorGoToLocation()),\n\thideCursorInOverviewRuler: register(new EditorBooleanOption(\n\t\tEditorOption.hideCursorInOverviewRuler, 'hideCursorInOverviewRuler', false,\n\t\t{ description: nls.localize('hideCursorInOverviewRuler', \"Controls whether the cursor should be hidden in the overview ruler.\") }\n\t)),\n\thover: register(new EditorHover()),\n\tinDiffEditor: register(new EditorBooleanOption(\n\t\tEditorOption.inDiffEditor, 'inDiffEditor', false\n\t)),\n\tletterSpacing: register(new EditorFloatOption(\n\t\tEditorOption.letterSpacing, 'letterSpacing',\n\t\tEDITOR_FONT_DEFAULTS.letterSpacing, x => EditorFloatOption.clamp(x, -5, 20),\n\t\t{ description: nls.localize('letterSpacing', \"Controls the letter spacing in pixels.\") }\n\t)),\n\tlightbulb: register(new EditorLightbulb()),\n\tlineDecorationsWidth: register(new SimpleEditorOption(EditorOption.lineDecorationsWidth, 'lineDecorationsWidth', 10 as number | string)),\n\tlineHeight: register(new EditorLineHeight()),\n\tlineNumbers: register(new EditorRenderLineNumbersOption()),\n\tlineNumbersMinChars: register(new EditorIntOption(\n\t\tEditorOption.lineNumbersMinChars, 'lineNumbersMinChars',\n\t\t5, 1, 300\n\t)),\n\tlinkedEditing: register(new EditorBooleanOption(\n\t\tEditorOption.linkedEditing, 'linkedEditing', false,\n\t\t{ description: nls.localize('linkedEditing', \"Controls whether the editor has linked editing enabled. Depending on the language, related symbols, e.g. HTML tags, are updated while editing.\") }\n\t)),\n\tlinks: register(new EditorBooleanOption(\n\t\tEditorOption.links, 'links', true,\n\t\t{ description: nls.localize('links', \"Controls whether the editor should detect links and make them clickable.\") }\n\t)),\n\tmatchBrackets: register(new EditorStringEnumOption(\n\t\tEditorOption.matchBrackets, 'matchBrackets',\n\t\t'always' as 'never' | 'near' | 'always',\n\t\t['always', 'near', 'never'] as const,\n\t\t{ description: nls.localize('matchBrackets', \"Highlight matching brackets.\") }\n\t)),\n\tminimap: register(new EditorMinimap()),\n\tmouseStyle: register(new EditorStringEnumOption(\n\t\tEditorOption.mouseStyle, 'mouseStyle',\n\t\t'text' as 'text' | 'default' | 'copy',\n\t\t['text', 'default', 'copy'] as const,\n\t)),\n\tmouseWheelScrollSensitivity: register(new EditorFloatOption(\n\t\tEditorOption.mouseWheelScrollSensitivity, 'mouseWheelScrollSensitivity',\n\t\t1, x => (x === 0 ? 1 : x),\n\t\t{ markdownDescription: nls.localize('mouseWheelScrollSensitivity', \"A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.\") }\n\t)),\n\tmouseWheelZoom: register(new EditorBooleanOption(\n\t\tEditorOption.mouseWheelZoom, 'mouseWheelZoom', false,\n\t\t{ markdownDescription: nls.localize('mouseWheelZoom', \"Zoom the font of the editor when using mouse wheel and holding `Ctrl`.\") }\n\t)),\n\tmultiCursorMergeOverlapping: register(new EditorBooleanOption(\n\t\tEditorOption.multiCursorMergeOverlapping, 'multiCursorMergeOverlapping', true,\n\t\t{ description: nls.localize('multiCursorMergeOverlapping', \"Merge multiple cursors when they are overlapping.\") }\n\t)),\n\tmultiCursorModifier: register(new EditorEnumOption(\n\t\tEditorOption.multiCursorModifier, 'multiCursorModifier',\n\t\t'altKey', 'alt',\n\t\t['ctrlCmd', 'alt'],\n\t\t_multiCursorModifierFromString,\n\t\t{\n\t\t\tmarkdownEnumDescriptions: [\n\t\t\t\tnls.localize('multiCursorModifier.ctrlCmd', \"Maps to `Control` on Windows and Linux and to `Command` on macOS.\"),\n\t\t\t\tnls.localize('multiCursorModifier.alt', \"Maps to `Alt` on Windows and Linux and to `Option` on macOS.\")\n\t\t\t],\n\t\t\tmarkdownDescription: nls.localize({\n\t\t\t\tkey: 'multiCursorModifier',\n\t\t\t\tcomment: [\n\t\t\t\t\t'- `ctrlCmd` refers to a value the setting can take and should not be localized.',\n\t\t\t\t\t'- `Control` and `Command` refer to the modifier keys Ctrl or Cmd on the keyboard and can be localized.'\n\t\t\t\t]\n\t\t\t}, \"The modifier to be used to add multiple cursors with the mouse. The Go to Definition and Open Link mouse gestures will adapt such that they do not conflict with the multicursor modifier. [Read more](https://code.visualstudio.com/docs/editor/codebasics#_multicursor-modifier).\")\n\t\t}\n\t)),\n\tmultiCursorPaste: register(new EditorStringEnumOption(\n\t\tEditorOption.multiCursorPaste, 'multiCursorPaste',\n\t\t'spread' as 'spread' | 'full',\n\t\t['spread', 'full'] as const,\n\t\t{\n\t\t\tmarkdownEnumDescriptions: [\n\t\t\t\tnls.localize('multiCursorPaste.spread', \"Each cursor pastes a single line of the text.\"),\n\t\t\t\tnls.localize('multiCursorPaste.full', \"Each cursor pastes the full text.\")\n\t\t\t],\n\t\t\tmarkdownDescription: nls.localize('multiCursorPaste', \"Controls pasting when the line count of the pasted text matches the cursor count.\")\n\t\t}\n\t)),\n\toccurrencesHighlight: register(new EditorBooleanOption(\n\t\tEditorOption.occurrencesHighlight, 'occurrencesHighlight', true,\n\t\t{ description: nls.localize('occurrencesHighlight', \"Controls whether the editor should highlight semantic symbol occurrences.\") }\n\t)),\n\toverviewRulerBorder: register(new EditorBooleanOption(\n\t\tEditorOption.overviewRulerBorder, 'overviewRulerBorder', true,\n\t\t{ description: nls.localize('overviewRulerBorder', \"Controls whether a border should be drawn around the overview ruler.\") }\n\t)),\n\toverviewRulerLanes: register(new EditorIntOption(\n\t\tEditorOption.overviewRulerLanes, 'overviewRulerLanes',\n\t\t3, 0, 3\n\t)),\n\tpadding: register(new EditorPadding()),\n\tparameterHints: register(new EditorParameterHints()),\n\tpeekWidgetDefaultFocus: register(new EditorStringEnumOption(\n\t\tEditorOption.peekWidgetDefaultFocus, 'peekWidgetDefaultFocus',\n\t\t'tree' as 'tree' | 'editor',\n\t\t['tree', 'editor'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('peekWidgetDefaultFocus.tree', \"Focus the tree when opening peek\"),\n\t\t\t\tnls.localize('peekWidgetDefaultFocus.editor', \"Focus the editor when opening peek\")\n\t\t\t],\n\t\t\tdescription: nls.localize('peekWidgetDefaultFocus', \"Controls whether to focus the inline editor or the tree in the peek widget.\")\n\t\t}\n\t)),\n\tdefinitionLinkOpensInPeek: register(new EditorBooleanOption(\n\t\tEditorOption.definitionLinkOpensInPeek, 'definitionLinkOpensInPeek', false,\n\t\t{ description: nls.localize('definitionLinkOpensInPeek', \"Controls whether the Go to Definition mouse gesture always opens the peek widget.\") }\n\t)),\n\tquickSuggestions: register(new EditorQuickSuggestions()),\n\tquickSuggestionsDelay: register(new EditorIntOption(\n\t\tEditorOption.quickSuggestionsDelay, 'quickSuggestionsDelay',\n\t\t10, 0, Constants.MAX_SAFE_SMALL_INTEGER,\n\t\t{ description: nls.localize('quickSuggestionsDelay', \"Controls the delay in milliseconds after which quick suggestions will show up.\") }\n\t)),\n\treadOnly: register(new EditorBooleanOption(\n\t\tEditorOption.readOnly, 'readOnly', false,\n\t)),\n\trenameOnType: register(new EditorBooleanOption(\n\t\tEditorOption.renameOnType, 'renameOnType', false,\n\t\t{ description: nls.localize('renameOnType', \"Controls whether the editor auto renames on type.\"), markdownDeprecationMessage: nls.localize('renameOnTypeDeprecate', \"Deprecated, use `editor.linkedEditing` instead.\") }\n\t)),\n\trenderControlCharacters: register(new EditorBooleanOption(\n\t\tEditorOption.renderControlCharacters, 'renderControlCharacters', true,\n\t\t{ description: nls.localize('renderControlCharacters', \"Controls whether the editor should render control characters.\"), restricted: true }\n\t)),\n\trenderFinalNewline: register(new EditorBooleanOption(\n\t\tEditorOption.renderFinalNewline, 'renderFinalNewline', true,\n\t\t{ description: nls.localize('renderFinalNewline', \"Render last line number when the file ends with a newline.\") }\n\t)),\n\trenderLineHighlight: register(new EditorStringEnumOption(\n\t\tEditorOption.renderLineHighlight, 'renderLineHighlight',\n\t\t'line' as 'none' | 'gutter' | 'line' | 'all',\n\t\t['none', 'gutter', 'line', 'all'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\t'',\n\t\t\t\t'',\n\t\t\t\t'',\n\t\t\t\tnls.localize('renderLineHighlight.all', \"Highlights both the gutter and the current line.\"),\n\t\t\t],\n\t\t\tdescription: nls.localize('renderLineHighlight', \"Controls how the editor should render the current line highlight.\")\n\t\t}\n\t)),\n\trenderLineHighlightOnlyWhenFocus: register(new EditorBooleanOption(\n\t\tEditorOption.renderLineHighlightOnlyWhenFocus, 'renderLineHighlightOnlyWhenFocus', false,\n\t\t{ description: nls.localize('renderLineHighlightOnlyWhenFocus', \"Controls if the editor should render the current line highlight only when the editor is focused.\") }\n\t)),\n\trenderValidationDecorations: register(new EditorStringEnumOption(\n\t\tEditorOption.renderValidationDecorations, 'renderValidationDecorations',\n\t\t'editable' as 'editable' | 'on' | 'off',\n\t\t['editable', 'on', 'off'] as const\n\t)),\n\trenderWhitespace: register(new EditorStringEnumOption(\n\t\tEditorOption.renderWhitespace, 'renderWhitespace',\n\t\t'selection' as 'selection' | 'none' | 'boundary' | 'trailing' | 'all',\n\t\t['none', 'boundary', 'selection', 'trailing', 'all'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\t'',\n\t\t\t\tnls.localize('renderWhitespace.boundary', \"Render whitespace characters except for single spaces between words.\"),\n\t\t\t\tnls.localize('renderWhitespace.selection', \"Render whitespace characters only on selected text.\"),\n\t\t\t\tnls.localize('renderWhitespace.trailing', \"Render only trailing whitespace characters.\"),\n\t\t\t\t''\n\t\t\t],\n\t\t\tdescription: nls.localize('renderWhitespace', \"Controls how the editor should render whitespace characters.\")\n\t\t}\n\t)),\n\trevealHorizontalRightPadding: register(new EditorIntOption(\n\t\tEditorOption.revealHorizontalRightPadding, 'revealHorizontalRightPadding',\n\t\t30, 0, 1000,\n\t)),\n\troundedSelection: register(new EditorBooleanOption(\n\t\tEditorOption.roundedSelection, 'roundedSelection', true,\n\t\t{ description: nls.localize('roundedSelection', \"Controls whether selections should have rounded corners.\") }\n\t)),\n\trulers: register(new EditorRulers()),\n\tscrollbar: register(new EditorScrollbar()),\n\tscrollBeyondLastColumn: register(new EditorIntOption(\n\t\tEditorOption.scrollBeyondLastColumn, 'scrollBeyondLastColumn',\n\t\t5, 0, Constants.MAX_SAFE_SMALL_INTEGER,\n\t\t{ description: nls.localize('scrollBeyondLastColumn', \"Controls the number of extra characters beyond which the editor will scroll horizontally.\") }\n\t)),\n\tscrollBeyondLastLine: register(new EditorBooleanOption(\n\t\tEditorOption.scrollBeyondLastLine, 'scrollBeyondLastLine', true,\n\t\t{ description: nls.localize('scrollBeyondLastLine', \"Controls whether the editor will scroll beyond the last line.\") }\n\t)),\n\tscrollPredominantAxis: register(new EditorBooleanOption(\n\t\tEditorOption.scrollPredominantAxis, 'scrollPredominantAxis', true,\n\t\t{ description: nls.localize('scrollPredominantAxis', \"Scroll only along the predominant axis when scrolling both vertically and horizontally at the same time. Prevents horizontal drift when scrolling vertically on a trackpad.\") }\n\t)),\n\tselectionClipboard: register(new EditorBooleanOption(\n\t\tEditorOption.selectionClipboard, 'selectionClipboard', true,\n\t\t{\n\t\t\tdescription: nls.localize('selectionClipboard', \"Controls whether the Linux primary clipboard should be supported.\"),\n\t\t\tincluded: platform.isLinux\n\t\t}\n\t)),\n\tselectionHighlight: register(new EditorBooleanOption(\n\t\tEditorOption.selectionHighlight, 'selectionHighlight', true,\n\t\t{ description: nls.localize('selectionHighlight', \"Controls whether the editor should highlight matches similar to the selection.\") }\n\t)),\n\tselectOnLineNumbers: register(new EditorBooleanOption(\n\t\tEditorOption.selectOnLineNumbers, 'selectOnLineNumbers', true,\n\t)),\n\tshowFoldingControls: register(new EditorStringEnumOption(\n\t\tEditorOption.showFoldingControls, 'showFoldingControls',\n\t\t'mouseover' as 'always' | 'mouseover',\n\t\t['always', 'mouseover'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('showFoldingControls.always', \"Always show the folding controls.\"),\n\t\t\t\tnls.localize('showFoldingControls.mouseover', \"Only show the folding controls when the mouse is over the gutter.\"),\n\t\t\t],\n\t\t\tdescription: nls.localize('showFoldingControls', \"Controls when the folding controls on the gutter are shown.\")\n\t\t}\n\t)),\n\tshowUnused: register(new EditorBooleanOption(\n\t\tEditorOption.showUnused, 'showUnused', true,\n\t\t{ description: nls.localize('showUnused', \"Controls fading out of unused code.\") }\n\t)),\n\tshowDeprecated: register(new EditorBooleanOption(\n\t\tEditorOption.showDeprecated, 'showDeprecated', true,\n\t\t{ description: nls.localize('showDeprecated', \"Controls strikethrough deprecated variables.\") }\n\t)),\n\tinlayHints: register(new EditorInlayHints()),\n\tsnippetSuggestions: register(new EditorStringEnumOption(\n\t\tEditorOption.snippetSuggestions, 'snippetSuggestions',\n\t\t'inline' as 'top' | 'bottom' | 'inline' | 'none',\n\t\t['top', 'bottom', 'inline', 'none'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('snippetSuggestions.top', \"Show snippet suggestions on top of other suggestions.\"),\n\t\t\t\tnls.localize('snippetSuggestions.bottom', \"Show snippet suggestions below other suggestions.\"),\n\t\t\t\tnls.localize('snippetSuggestions.inline', \"Show snippets suggestions with other suggestions.\"),\n\t\t\t\tnls.localize('snippetSuggestions.none', \"Do not show snippet suggestions.\"),\n\t\t\t],\n\t\t\tdescription: nls.localize('snippetSuggestions', \"Controls whether snippets are shown with other suggestions and how they are sorted.\")\n\t\t}\n\t)),\n\tsmartSelect: register(new SmartSelect()),\n\tsmoothScrolling: register(new EditorBooleanOption(\n\t\tEditorOption.smoothScrolling, 'smoothScrolling', false,\n\t\t{ description: nls.localize('smoothScrolling', \"Controls whether the editor will scroll using an animation.\") }\n\t)),\n\tstopRenderingLineAfter: register(new EditorIntOption(\n\t\tEditorOption.stopRenderingLineAfter, 'stopRenderingLineAfter',\n\t\t10000, -1, Constants.MAX_SAFE_SMALL_INTEGER,\n\t)),\n\tsuggest: register(new EditorSuggest()),\n\tinlineSuggest: register(new InlineEditorSuggest()),\n\tsuggestFontSize: register(new EditorIntOption(\n\t\tEditorOption.suggestFontSize, 'suggestFontSize',\n\t\t0, 0, 1000,\n\t\t{ markdownDescription: nls.localize('suggestFontSize', \"Font size for the suggest widget. When set to `0`, the value of `#editor.fontSize#` is used.\") }\n\t)),\n\tsuggestLineHeight: register(new EditorIntOption(\n\t\tEditorOption.suggestLineHeight, 'suggestLineHeight',\n\t\t0, 0, 1000,\n\t\t{ markdownDescription: nls.localize('suggestLineHeight', \"Line height for the suggest widget. When set to `0`, the value of `#editor.lineHeight#` is used. The minimum value is 8.\") }\n\t)),\n\tsuggestOnTriggerCharacters: register(new EditorBooleanOption(\n\t\tEditorOption.suggestOnTriggerCharacters, 'suggestOnTriggerCharacters', true,\n\t\t{ description: nls.localize('suggestOnTriggerCharacters', \"Controls whether suggestions should automatically show up when typing trigger characters.\") }\n\t)),\n\tsuggestSelection: register(new EditorStringEnumOption(\n\t\tEditorOption.suggestSelection, 'suggestSelection',\n\t\t'first' as 'first' | 'recentlyUsed' | 'recentlyUsedByPrefix',\n\t\t['first', 'recentlyUsed', 'recentlyUsedByPrefix'] as const,\n\t\t{\n\t\t\tmarkdownEnumDescriptions: [\n\t\t\t\tnls.localize('suggestSelection.first', \"Always select the first suggestion.\"),\n\t\t\t\tnls.localize('suggestSelection.recentlyUsed', \"Select recent suggestions unless further typing selects one, e.g. `console.| -> console.log` because `log` has been completed recently.\"),\n\t\t\t\tnls.localize('suggestSelection.recentlyUsedByPrefix', \"Select suggestions based on previous prefixes that have completed those suggestions, e.g. `co -> console` and `con -> const`.\"),\n\t\t\t],\n\t\t\tdescription: nls.localize('suggestSelection', \"Controls how suggestions are pre-selected when showing the suggest list.\")\n\t\t}\n\t)),\n\ttabCompletion: register(new EditorStringEnumOption(\n\t\tEditorOption.tabCompletion, 'tabCompletion',\n\t\t'off' as 'on' | 'off' | 'onlySnippets',\n\t\t['on', 'off', 'onlySnippets'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('tabCompletion.on', \"Tab complete will insert the best matching suggestion when pressing tab.\"),\n\t\t\t\tnls.localize('tabCompletion.off', \"Disable tab completions.\"),\n\t\t\t\tnls.localize('tabCompletion.onlySnippets', \"Tab complete snippets when their prefix match. Works best when 'quickSuggestions' aren't enabled.\"),\n\t\t\t],\n\t\t\tdescription: nls.localize('tabCompletion', \"Enables tab completions.\")\n\t\t}\n\t)),\n\ttabIndex: register(new EditorIntOption(\n\t\tEditorOption.tabIndex, 'tabIndex',\n\t\t0, -1, Constants.MAX_SAFE_SMALL_INTEGER\n\t)),\n\tunicodeHighlight: register(new UnicodeHighlight()),\n\tunusualLineTerminators: register(new EditorStringEnumOption(\n\t\tEditorOption.unusualLineTerminators, 'unusualLineTerminators',\n\t\t'prompt' as 'auto' | 'off' | 'prompt',\n\t\t['auto', 'off', 'prompt'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('unusualLineTerminators.auto', \"Unusual line terminators are automatically removed.\"),\n\t\t\t\tnls.localize('unusualLineTerminators.off', \"Unusual line terminators are ignored.\"),\n\t\t\t\tnls.localize('unusualLineTerminators.prompt', \"Unusual line terminators prompt to be removed.\"),\n\t\t\t],\n\t\t\tdescription: nls.localize('unusualLineTerminators', \"Remove unusual line terminators that might cause problems.\")\n\t\t}\n\t)),\n\tuseShadowDOM: register(new EditorBooleanOption(\n\t\tEditorOption.useShadowDOM, 'useShadowDOM', true\n\t)),\n\tuseTabStops: register(new EditorBooleanOption(\n\t\tEditorOption.useTabStops, 'useTabStops', true,\n\t\t{ description: nls.localize('useTabStops', \"Inserting and deleting whitespace follows tab stops.\") }\n\t)),\n\twordSeparators: register(new EditorStringOption(\n\t\tEditorOption.wordSeparators, 'wordSeparators', USUAL_WORD_SEPARATORS,\n\t\t{ description: nls.localize('wordSeparators', \"Characters that will be used as word separators when doing word related navigations or operations.\") }\n\t)),\n\twordWrap: register(new EditorStringEnumOption(\n\t\tEditorOption.wordWrap, 'wordWrap',\n\t\t'off' as 'off' | 'on' | 'wordWrapColumn' | 'bounded',\n\t\t['off', 'on', 'wordWrapColumn', 'bounded'] as const,\n\t\t{\n\t\t\tmarkdownEnumDescriptions: [\n\t\t\t\tnls.localize('wordWrap.off', \"Lines will never wrap.\"),\n\t\t\t\tnls.localize('wordWrap.on', \"Lines will wrap at the viewport width.\"),\n\t\t\t\tnls.localize({\n\t\t\t\t\tkey: 'wordWrap.wordWrapColumn',\n\t\t\t\t\tcomment: [\n\t\t\t\t\t\t'- `editor.wordWrapColumn` refers to a different setting and should not be localized.'\n\t\t\t\t\t]\n\t\t\t\t}, \"Lines will wrap at `#editor.wordWrapColumn#`.\"),\n\t\t\t\tnls.localize({\n\t\t\t\t\tkey: 'wordWrap.bounded',\n\t\t\t\t\tcomment: [\n\t\t\t\t\t\t'- viewport means the edge of the visible window size.',\n\t\t\t\t\t\t'- `editor.wordWrapColumn` refers to a different setting and should not be localized.'\n\t\t\t\t\t]\n\t\t\t\t}, \"Lines will wrap at the minimum of viewport and `#editor.wordWrapColumn#`.\"),\n\t\t\t],\n\t\t\tdescription: nls.localize({\n\t\t\t\tkey: 'wordWrap',\n\t\t\t\tcomment: [\n\t\t\t\t\t'- \\'off\\', \\'on\\', \\'wordWrapColumn\\' and \\'bounded\\' refer to values the setting can take and should not be localized.',\n\t\t\t\t\t'- `editor.wordWrapColumn` refers to a different setting and should not be localized.'\n\t\t\t\t]\n\t\t\t}, \"Controls how lines should wrap.\")\n\t\t}\n\t)),\n\twordWrapBreakAfterCharacters: register(new EditorStringOption(\n\t\tEditorOption.wordWrapBreakAfterCharacters, 'wordWrapBreakAfterCharacters',\n\t\t// allow-any-unicode-next-line\n\t\t' \\t})]?|/&.,;¢°′″‰℃、。。、¢,.:;?!%・・ゝゞヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻ァィゥェォャュョッー”〉》」』】〕)]}」',\n\t)),\n\twordWrapBreakBeforeCharacters: register(new EditorStringOption(\n\t\tEditorOption.wordWrapBreakBeforeCharacters, 'wordWrapBreakBeforeCharacters',\n\t\t// allow-any-unicode-next-line\n\t\t'([{‘“〈《「『【〔([{「£¥$£¥++'\n\t)),\n\twordWrapColumn: register(new EditorIntOption(\n\t\tEditorOption.wordWrapColumn, 'wordWrapColumn',\n\t\t80, 1, Constants.MAX_SAFE_SMALL_INTEGER,\n\t\t{\n\t\t\tmarkdownDescription: nls.localize({\n\t\t\t\tkey: 'wordWrapColumn',\n\t\t\t\tcomment: [\n\t\t\t\t\t'- `editor.wordWrap` refers to a different setting and should not be localized.',\n\t\t\t\t\t'- \\'wordWrapColumn\\' and \\'bounded\\' refer to values the different setting can take and should not be localized.'\n\t\t\t\t]\n\t\t\t}, \"Controls the wrapping column of the editor when `#editor.wordWrap#` is `wordWrapColumn` or `bounded`.\")\n\t\t}\n\t)),\n\twordWrapOverride1: register(new EditorStringEnumOption(\n\t\tEditorOption.wordWrapOverride1, 'wordWrapOverride1',\n\t\t'inherit' as 'off' | 'on' | 'inherit',\n\t\t['off', 'on', 'inherit'] as const\n\t)),\n\twordWrapOverride2: register(new EditorStringEnumOption(\n\t\tEditorOption.wordWrapOverride2, 'wordWrapOverride2',\n\t\t'inherit' as 'off' | 'on' | 'inherit',\n\t\t['off', 'on', 'inherit'] as const\n\t)),\n\twrappingIndent: register(new EditorEnumOption(\n\t\tEditorOption.wrappingIndent, 'wrappingIndent',\n\t\tWrappingIndent.Same, 'same',\n\t\t['none', 'same', 'indent', 'deepIndent'],\n\t\t_wrappingIndentFromString,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('wrappingIndent.none', \"No indentation. Wrapped lines begin at column 1.\"),\n\t\t\t\tnls.localize('wrappingIndent.same', \"Wrapped lines get the same indentation as the parent.\"),\n\t\t\t\tnls.localize('wrappingIndent.indent', \"Wrapped lines get +1 indentation toward the parent.\"),\n\t\t\t\tnls.localize('wrappingIndent.deepIndent', \"Wrapped lines get +2 indentation toward the parent.\"),\n\t\t\t],\n\t\t\tdescription: nls.localize('wrappingIndent', \"Controls the indentation of wrapped lines.\"),\n\t\t}\n\t)),\n\twrappingStrategy: register(new EditorStringEnumOption(\n\t\tEditorOption.wrappingStrategy, 'wrappingStrategy',\n\t\t'simple' as 'simple' | 'advanced',\n\t\t['simple', 'advanced'] as const,\n\t\t{\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('wrappingStrategy.simple', \"Assumes that all characters are of the same width. This is a fast algorithm that works correctly for monospace fonts and certain scripts (like Latin characters) where glyphs are of equal width.\"),\n\t\t\t\tnls.localize('wrappingStrategy.advanced', \"Delegates wrapping points computation to the browser. This is a slow algorithm, that might cause freezes for large files, but it works correctly in all cases.\")\n\t\t\t],\n\t\t\tdescription: nls.localize('wrappingStrategy', \"Controls the algorithm that computes wrapping points.\")\n\t\t}\n\t)),\n\n\t// Leave these at the end (because they have dependencies!)\n\teditorClassName: register(new EditorClassName()),\n\tpixelRatio: register(new EditorPixelRatio()),\n\ttabFocusMode: register(new EditorTabFocusMode()),\n\tlayoutInfo: register(new EditorLayoutInfoComputer()),\n\twrappingInfo: register(new EditorWrappingInfoComputer())\n};\n\ntype EditorOptionsType = typeof EditorOptions;\ntype FindEditorOptionsKeyById = { [K in keyof EditorOptionsType]: EditorOptionsType[K]['id'] extends T ? K : never }[keyof EditorOptionsType];\ntype ComputedEditorOptionValue> = T extends IEditorOption ? R : never;\nexport type FindComputedEditorOptionValueById = NonNullable]>>;\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as browser from 'vs/base/browser/browser';\nimport { FastDomNode } from 'vs/base/browser/fastDomNode';\nimport { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions';\nimport { BareFontInfo } from 'vs/editor/common/config/fontInfo';\n\nexport function applyFontInfo(domNode: FastDomNode | HTMLElement, fontInfo: BareFontInfo): void {\n\tif (domNode instanceof FastDomNode) {\n\t\tdomNode.setFontFamily(fontInfo.getMassagedFontFamily(browser.isSafari ? EDITOR_FONT_DEFAULTS.fontFamily : null));\n\t\tdomNode.setFontWeight(fontInfo.fontWeight);\n\t\tdomNode.setFontSize(fontInfo.fontSize);\n\t\tdomNode.setFontFeatureSettings(fontInfo.fontFeatureSettings);\n\t\tdomNode.setLineHeight(fontInfo.lineHeight);\n\t\tdomNode.setLetterSpacing(fontInfo.letterSpacing);\n\t} else {\n\t\tdomNode.style.fontFamily = fontInfo.getMassagedFontFamily(browser.isSafari ? EDITOR_FONT_DEFAULTS.fontFamily : null);\n\t\tdomNode.style.fontWeight = fontInfo.fontWeight;\n\t\tdomNode.style.fontSize = fontInfo.fontSize + 'px';\n\t\tdomNode.style.fontFeatureSettings = fontInfo.fontFeatureSettings;\n\t\tdomNode.style.lineHeight = fontInfo.lineHeight + 'px';\n\t\tdomNode.style.letterSpacing = fontInfo.letterSpacing + 'px';\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { applyFontInfo } from 'vs/editor/browser/config/domFontInfo';\nimport { BareFontInfo } from 'vs/editor/common/config/fontInfo';\n\nexport const enum CharWidthRequestType {\n\tRegular = 0,\n\tItalic = 1,\n\tBold = 2\n}\n\nexport class CharWidthRequest {\n\n\tpublic readonly chr: string;\n\tpublic readonly type: CharWidthRequestType;\n\tpublic width: number;\n\n\tconstructor(chr: string, type: CharWidthRequestType) {\n\t\tthis.chr = chr;\n\t\tthis.type = type;\n\t\tthis.width = 0;\n\t}\n\n\tpublic fulfill(width: number) {\n\t\tthis.width = width;\n\t}\n}\n\nclass DomCharWidthReader {\n\n\tprivate readonly _bareFontInfo: BareFontInfo;\n\tprivate readonly _requests: CharWidthRequest[];\n\n\tprivate _container: HTMLElement | null;\n\tprivate _testElements: HTMLSpanElement[] | null;\n\n\tconstructor(bareFontInfo: BareFontInfo, requests: CharWidthRequest[]) {\n\t\tthis._bareFontInfo = bareFontInfo;\n\t\tthis._requests = requests;\n\n\t\tthis._container = null;\n\t\tthis._testElements = null;\n\t}\n\n\tpublic read(): void {\n\t\t// Create a test container with all these test elements\n\t\tthis._createDomElements();\n\n\t\t// Add the container to the DOM\n\t\tdocument.body.appendChild(this._container!);\n\n\t\t// Read character widths\n\t\tthis._readFromDomElements();\n\n\t\t// Remove the container from the DOM\n\t\tdocument.body.removeChild(this._container!);\n\n\t\tthis._container = null;\n\t\tthis._testElements = null;\n\t}\n\n\tprivate _createDomElements(): void {\n\t\tconst container = document.createElement('div');\n\t\tcontainer.style.position = 'absolute';\n\t\tcontainer.style.top = '-50000px';\n\t\tcontainer.style.width = '50000px';\n\n\t\tconst regularDomNode = document.createElement('div');\n\t\tapplyFontInfo(regularDomNode, this._bareFontInfo);\n\t\tcontainer.appendChild(regularDomNode);\n\n\t\tconst boldDomNode = document.createElement('div');\n\t\tapplyFontInfo(boldDomNode, this._bareFontInfo);\n\t\tboldDomNode.style.fontWeight = 'bold';\n\t\tcontainer.appendChild(boldDomNode);\n\n\t\tconst italicDomNode = document.createElement('div');\n\t\tapplyFontInfo(italicDomNode, this._bareFontInfo);\n\t\titalicDomNode.style.fontStyle = 'italic';\n\t\tcontainer.appendChild(italicDomNode);\n\n\t\tconst testElements: HTMLSpanElement[] = [];\n\t\tfor (const request of this._requests) {\n\n\t\t\tlet parent: HTMLElement;\n\t\t\tif (request.type === CharWidthRequestType.Regular) {\n\t\t\t\tparent = regularDomNode;\n\t\t\t}\n\t\t\tif (request.type === CharWidthRequestType.Bold) {\n\t\t\t\tparent = boldDomNode;\n\t\t\t}\n\t\t\tif (request.type === CharWidthRequestType.Italic) {\n\t\t\t\tparent = italicDomNode;\n\t\t\t}\n\n\t\t\tparent!.appendChild(document.createElement('br'));\n\n\t\t\tconst testElement = document.createElement('span');\n\t\t\tDomCharWidthReader._render(testElement, request);\n\t\t\tparent!.appendChild(testElement);\n\n\t\t\ttestElements.push(testElement);\n\t\t}\n\n\t\tthis._container = container;\n\t\tthis._testElements = testElements;\n\t}\n\n\tprivate static _render(testElement: HTMLElement, request: CharWidthRequest): void {\n\t\tif (request.chr === ' ') {\n\t\t\tlet htmlString = '\\u00a0';\n\t\t\t// Repeat character 256 (2^8) times\n\t\t\tfor (let i = 0; i < 8; i++) {\n\t\t\t\thtmlString += htmlString;\n\t\t\t}\n\t\t\ttestElement.innerText = htmlString;\n\t\t} else {\n\t\t\tlet testString = request.chr;\n\t\t\t// Repeat character 256 (2^8) times\n\t\t\tfor (let i = 0; i < 8; i++) {\n\t\t\t\ttestString += testString;\n\t\t\t}\n\t\t\ttestElement.textContent = testString;\n\t\t}\n\t}\n\n\tprivate _readFromDomElements(): void {\n\t\tfor (let i = 0, len = this._requests.length; i < len; i++) {\n\t\t\tconst request = this._requests[i];\n\t\t\tconst testElement = this._testElements![i];\n\n\t\t\trequest.fulfill(testElement.offsetWidth / 256);\n\t\t}\n\t}\n}\n\nexport function readCharWidths(bareFontInfo: BareFontInfo, requests: CharWidthRequest[]): void {\n\tconst reader = new DomCharWidthReader(bareFontInfo, requests);\n\treader.read();\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as browser from 'vs/base/browser/browser';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { CharWidthRequest, CharWidthRequestType, readCharWidths } from 'vs/editor/browser/config/charWidthReader';\nimport { EditorFontLigatures } from 'vs/editor/common/config/editorOptions';\nimport { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo';\n\nclass FontMeasurementsImpl extends Disposable {\n\n\tprivate _cache: FontMeasurementsCache;\n\tprivate _evictUntrustedReadingsTimeout: number;\n\n\tprivate readonly _onDidChange = this._register(new Emitter());\n\tpublic readonly onDidChange: Event = this._onDidChange.event;\n\n\tconstructor() {\n\t\tsuper();\n\n\t\tthis._cache = new FontMeasurementsCache();\n\t\tthis._evictUntrustedReadingsTimeout = -1;\n\t}\n\n\tpublic override dispose(): void {\n\t\tif (this._evictUntrustedReadingsTimeout !== -1) {\n\t\t\twindow.clearTimeout(this._evictUntrustedReadingsTimeout);\n\t\t\tthis._evictUntrustedReadingsTimeout = -1;\n\t\t}\n\t\tsuper.dispose();\n\t}\n\n\t/**\n\t * Clear all cached font information and trigger a change event.\n\t */\n\tpublic clearAllFontInfos(): void {\n\t\tthis._cache = new FontMeasurementsCache();\n\t\tthis._onDidChange.fire();\n\t}\n\n\tprivate _writeToCache(item: BareFontInfo, value: FontInfo): void {\n\t\tthis._cache.put(item, value);\n\n\t\tif (!value.isTrusted && this._evictUntrustedReadingsTimeout === -1) {\n\t\t\t// Try reading again after some time\n\t\t\tthis._evictUntrustedReadingsTimeout = window.setTimeout(() => {\n\t\t\t\tthis._evictUntrustedReadingsTimeout = -1;\n\t\t\t\tthis._evictUntrustedReadings();\n\t\t\t}, 5000);\n\t\t}\n\t}\n\n\tprivate _evictUntrustedReadings(): void {\n\t\tconst values = this._cache.getValues();\n\t\tlet somethingRemoved = false;\n\t\tfor (const item of values) {\n\t\t\tif (!item.isTrusted) {\n\t\t\t\tsomethingRemoved = true;\n\t\t\t\tthis._cache.remove(item);\n\t\t\t}\n\t\t}\n\t\tif (somethingRemoved) {\n\t\t\tthis._onDidChange.fire();\n\t\t}\n\t}\n\n\t/**\n\t * Read font information.\n\t */\n\tpublic readFontInfo(bareFontInfo: BareFontInfo): FontInfo {\n\t\tif (!this._cache.has(bareFontInfo)) {\n\t\t\tlet readConfig = this._actualReadFontInfo(bareFontInfo);\n\n\t\t\tif (readConfig.typicalHalfwidthCharacterWidth <= 2 || readConfig.typicalFullwidthCharacterWidth <= 2 || readConfig.spaceWidth <= 2 || readConfig.maxDigitWidth <= 2) {\n\t\t\t\t// Hey, it's Bug 14341 ... we couldn't read\n\t\t\t\treadConfig = new FontInfo({\n\t\t\t\t\tpixelRatio: browser.PixelRatio.value,\n\t\t\t\t\tfontFamily: readConfig.fontFamily,\n\t\t\t\t\tfontWeight: readConfig.fontWeight,\n\t\t\t\t\tfontSize: readConfig.fontSize,\n\t\t\t\t\tfontFeatureSettings: readConfig.fontFeatureSettings,\n\t\t\t\t\tlineHeight: readConfig.lineHeight,\n\t\t\t\t\tletterSpacing: readConfig.letterSpacing,\n\t\t\t\t\tisMonospace: readConfig.isMonospace,\n\t\t\t\t\ttypicalHalfwidthCharacterWidth: Math.max(readConfig.typicalHalfwidthCharacterWidth, 5),\n\t\t\t\t\ttypicalFullwidthCharacterWidth: Math.max(readConfig.typicalFullwidthCharacterWidth, 5),\n\t\t\t\t\tcanUseHalfwidthRightwardsArrow: readConfig.canUseHalfwidthRightwardsArrow,\n\t\t\t\t\tspaceWidth: Math.max(readConfig.spaceWidth, 5),\n\t\t\t\t\tmiddotWidth: Math.max(readConfig.middotWidth, 5),\n\t\t\t\t\twsmiddotWidth: Math.max(readConfig.wsmiddotWidth, 5),\n\t\t\t\t\tmaxDigitWidth: Math.max(readConfig.maxDigitWidth, 5),\n\t\t\t\t}, false);\n\t\t\t}\n\n\t\t\tthis._writeToCache(bareFontInfo, readConfig);\n\t\t}\n\t\treturn this._cache.get(bareFontInfo);\n\t}\n\n\tprivate _createRequest(chr: string, type: CharWidthRequestType, all: CharWidthRequest[], monospace: CharWidthRequest[] | null): CharWidthRequest {\n\t\tconst result = new CharWidthRequest(chr, type);\n\t\tall.push(result);\n\t\tif (monospace) {\n\t\t\tmonospace.push(result);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate _actualReadFontInfo(bareFontInfo: BareFontInfo): FontInfo {\n\t\tconst all: CharWidthRequest[] = [];\n\t\tconst monospace: CharWidthRequest[] = [];\n\n\t\tconst typicalHalfwidthCharacter = this._createRequest('n', CharWidthRequestType.Regular, all, monospace);\n\t\tconst typicalFullwidthCharacter = this._createRequest('\\uff4d', CharWidthRequestType.Regular, all, null);\n\t\tconst space = this._createRequest(' ', CharWidthRequestType.Regular, all, monospace);\n\t\tconst digit0 = this._createRequest('0', CharWidthRequestType.Regular, all, monospace);\n\t\tconst digit1 = this._createRequest('1', CharWidthRequestType.Regular, all, monospace);\n\t\tconst digit2 = this._createRequest('2', CharWidthRequestType.Regular, all, monospace);\n\t\tconst digit3 = this._createRequest('3', CharWidthRequestType.Regular, all, monospace);\n\t\tconst digit4 = this._createRequest('4', CharWidthRequestType.Regular, all, monospace);\n\t\tconst digit5 = this._createRequest('5', CharWidthRequestType.Regular, all, monospace);\n\t\tconst digit6 = this._createRequest('6', CharWidthRequestType.Regular, all, monospace);\n\t\tconst digit7 = this._createRequest('7', CharWidthRequestType.Regular, all, monospace);\n\t\tconst digit8 = this._createRequest('8', CharWidthRequestType.Regular, all, monospace);\n\t\tconst digit9 = this._createRequest('9', CharWidthRequestType.Regular, all, monospace);\n\n\t\t// monospace test: used for whitespace rendering\n\t\tconst rightwardsArrow = this._createRequest('→', CharWidthRequestType.Regular, all, monospace);\n\t\tconst halfwidthRightwardsArrow = this._createRequest('→', CharWidthRequestType.Regular, all, null);\n\n\t\t// U+00B7 - MIDDLE DOT\n\t\tconst middot = this._createRequest('·', CharWidthRequestType.Regular, all, monospace);\n\n\t\t// U+2E31 - WORD SEPARATOR MIDDLE DOT\n\t\tconst wsmiddotWidth = this._createRequest(String.fromCharCode(0x2E31), CharWidthRequestType.Regular, all, null);\n\n\t\t// monospace test: some characters\n\t\tconst monospaceTestChars = '|/-_ilm%';\n\t\tfor (let i = 0, len = monospaceTestChars.length; i < len; i++) {\n\t\t\tthis._createRequest(monospaceTestChars.charAt(i), CharWidthRequestType.Regular, all, monospace);\n\t\t\tthis._createRequest(monospaceTestChars.charAt(i), CharWidthRequestType.Italic, all, monospace);\n\t\t\tthis._createRequest(monospaceTestChars.charAt(i), CharWidthRequestType.Bold, all, monospace);\n\t\t}\n\n\t\treadCharWidths(bareFontInfo, all);\n\n\t\tconst maxDigitWidth = Math.max(digit0.width, digit1.width, digit2.width, digit3.width, digit4.width, digit5.width, digit6.width, digit7.width, digit8.width, digit9.width);\n\n\t\tlet isMonospace = (bareFontInfo.fontFeatureSettings === EditorFontLigatures.OFF);\n\t\tconst referenceWidth = monospace[0].width;\n\t\tfor (let i = 1, len = monospace.length; isMonospace && i < len; i++) {\n\t\t\tconst diff = referenceWidth - monospace[i].width;\n\t\t\tif (diff < -0.001 || diff > 0.001) {\n\t\t\t\tisMonospace = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tlet canUseHalfwidthRightwardsArrow = true;\n\t\tif (isMonospace && halfwidthRightwardsArrow.width !== referenceWidth) {\n\t\t\t// using a halfwidth rightwards arrow would break monospace...\n\t\t\tcanUseHalfwidthRightwardsArrow = false;\n\t\t}\n\t\tif (halfwidthRightwardsArrow.width > rightwardsArrow.width) {\n\t\t\t// using a halfwidth rightwards arrow would paint a larger arrow than a regular rightwards arrow\n\t\t\tcanUseHalfwidthRightwardsArrow = false;\n\t\t}\n\n\t\treturn new FontInfo({\n\t\t\tpixelRatio: browser.PixelRatio.value,\n\t\t\tfontFamily: bareFontInfo.fontFamily,\n\t\t\tfontWeight: bareFontInfo.fontWeight,\n\t\t\tfontSize: bareFontInfo.fontSize,\n\t\t\tfontFeatureSettings: bareFontInfo.fontFeatureSettings,\n\t\t\tlineHeight: bareFontInfo.lineHeight,\n\t\t\tletterSpacing: bareFontInfo.letterSpacing,\n\t\t\tisMonospace: isMonospace,\n\t\t\ttypicalHalfwidthCharacterWidth: typicalHalfwidthCharacter.width,\n\t\t\ttypicalFullwidthCharacterWidth: typicalFullwidthCharacter.width,\n\t\t\tcanUseHalfwidthRightwardsArrow: canUseHalfwidthRightwardsArrow,\n\t\t\tspaceWidth: space.width,\n\t\t\tmiddotWidth: middot.width,\n\t\t\twsmiddotWidth: wsmiddotWidth.width,\n\t\t\tmaxDigitWidth: maxDigitWidth\n\t\t}, true);\n\t}\n}\n\nclass FontMeasurementsCache {\n\n\tprivate readonly _keys: { [key: string]: BareFontInfo; };\n\tprivate readonly _values: { [key: string]: FontInfo; };\n\n\tconstructor() {\n\t\tthis._keys = Object.create(null);\n\t\tthis._values = Object.create(null);\n\t}\n\n\tpublic has(item: BareFontInfo): boolean {\n\t\tconst itemId = item.getId();\n\t\treturn !!this._values[itemId];\n\t}\n\n\tpublic get(item: BareFontInfo): FontInfo {\n\t\tconst itemId = item.getId();\n\t\treturn this._values[itemId];\n\t}\n\n\tpublic put(item: BareFontInfo, value: FontInfo): void {\n\t\tconst itemId = item.getId();\n\t\tthis._keys[itemId] = item;\n\t\tthis._values[itemId] = value;\n\t}\n\n\tpublic remove(item: BareFontInfo): void {\n\t\tconst itemId = item.getId();\n\t\tdelete this._keys[itemId];\n\t\tdelete this._values[itemId];\n\t}\n\n\tpublic getValues(): FontInfo[] {\n\t\treturn Object.keys(this._keys).map(id => this._values[id]);\n\t}\n}\n\nexport const FontMeasurements = new FontMeasurementsImpl();\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { WrappingIndent } from 'vs/editor/common/config/editorOptions';\nimport { FontInfo } from 'vs/editor/common/config/fontInfo';\nimport { createStringBuilder, IStringBuilder } from 'vs/editor/common/core/stringBuilder';\nimport { CharCode } from 'vs/base/common/charCode';\nimport * as strings from 'vs/base/common/strings';\nimport { applyFontInfo } from 'vs/editor/browser/config/domFontInfo';\nimport { LineInjectedText } from 'vs/editor/common/textModelEvents';\nimport { InjectedTextOptions } from 'vs/editor/common/model';\nimport { ILineBreaksComputer, ILineBreaksComputerFactory, ModelLineProjectionData } from 'vs/editor/common/viewModel/modelLineProjectionData';\n\nconst ttPolicy = window.trustedTypes?.createPolicy('domLineBreaksComputer', { createHTML: value => value });\n\nexport class DOMLineBreaksComputerFactory implements ILineBreaksComputerFactory {\n\n\tpublic static create(): DOMLineBreaksComputerFactory {\n\t\treturn new DOMLineBreaksComputerFactory();\n\t}\n\n\tconstructor() {\n\t}\n\n\tpublic createLineBreaksComputer(fontInfo: FontInfo, tabSize: number, wrappingColumn: number, wrappingIndent: WrappingIndent): ILineBreaksComputer {\n\t\tconst requests: string[] = [];\n\t\tconst injectedTexts: (LineInjectedText[] | null)[] = [];\n\t\treturn {\n\t\t\taddRequest: (lineText: string, injectedText: LineInjectedText[] | null, previousLineBreakData: ModelLineProjectionData | null) => {\n\t\t\t\trequests.push(lineText);\n\t\t\t\tinjectedTexts.push(injectedText);\n\t\t\t},\n\t\t\tfinalize: () => {\n\t\t\t\treturn createLineBreaks(requests, fontInfo, tabSize, wrappingColumn, wrappingIndent, injectedTexts);\n\t\t\t}\n\t\t};\n\t}\n}\n\nfunction createLineBreaks(requests: string[], fontInfo: FontInfo, tabSize: number, firstLineBreakColumn: number, wrappingIndent: WrappingIndent, injectedTextsPerLine: (LineInjectedText[] | null)[]): (ModelLineProjectionData | null)[] {\n\tfunction createEmptyLineBreakWithPossiblyInjectedText(requestIdx: number): ModelLineProjectionData | null {\n\t\tconst injectedTexts = injectedTextsPerLine[requestIdx];\n\t\tif (injectedTexts) {\n\t\t\tconst lineText = LineInjectedText.applyInjectedText(requests[requestIdx], injectedTexts);\n\n\t\t\tconst injectionOptions = injectedTexts.map(t => t.options);\n\t\t\tconst injectionOffsets = injectedTexts.map(text => text.column - 1);\n\n\t\t\t// creating a `LineBreakData` with an invalid `breakOffsetsVisibleColumn` is OK\n\t\t\t// because `breakOffsetsVisibleColumn` will never be used because it contains injected text\n\t\t\treturn new ModelLineProjectionData(injectionOffsets, injectionOptions, [lineText.length], [], 0);\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tif (firstLineBreakColumn === -1) {\n\t\tconst result: (ModelLineProjectionData | null)[] = [];\n\t\tfor (let i = 0, len = requests.length; i < len; i++) {\n\t\t\tresult[i] = createEmptyLineBreakWithPossiblyInjectedText(i);\n\t\t}\n\t\treturn result;\n\t}\n\n\tconst overallWidth = Math.round(firstLineBreakColumn * fontInfo.typicalHalfwidthCharacterWidth);\n\tconst additionalIndent = (wrappingIndent === WrappingIndent.DeepIndent ? 2 : wrappingIndent === WrappingIndent.Indent ? 1 : 0);\n\tconst additionalIndentSize = Math.round(tabSize * additionalIndent);\n\tconst additionalIndentLength = Math.ceil(fontInfo.spaceWidth * additionalIndentSize);\n\n\tconst containerDomNode = document.createElement('div');\n\tapplyFontInfo(containerDomNode, fontInfo);\n\n\tconst sb = createStringBuilder(10000);\n\tconst firstNonWhitespaceIndices: number[] = [];\n\tconst wrappedTextIndentLengths: number[] = [];\n\tconst renderLineContents: string[] = [];\n\tconst allCharOffsets: number[][] = [];\n\tconst allVisibleColumns: number[][] = [];\n\tfor (let i = 0; i < requests.length; i++) {\n\t\tconst lineContent = LineInjectedText.applyInjectedText(requests[i], injectedTextsPerLine[i]);\n\n\t\tlet firstNonWhitespaceIndex = 0;\n\t\tlet wrappedTextIndentLength = 0;\n\t\tlet width = overallWidth;\n\n\t\tif (wrappingIndent !== WrappingIndent.None) {\n\t\t\tfirstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineContent);\n\t\t\tif (firstNonWhitespaceIndex === -1) {\n\t\t\t\t// all whitespace line\n\t\t\t\tfirstNonWhitespaceIndex = 0;\n\n\t\t\t} else {\n\t\t\t\t// Track existing indent\n\n\t\t\t\tfor (let i = 0; i < firstNonWhitespaceIndex; i++) {\n\t\t\t\t\tconst charWidth = (\n\t\t\t\t\t\tlineContent.charCodeAt(i) === CharCode.Tab\n\t\t\t\t\t\t\t? (tabSize - (wrappedTextIndentLength % tabSize))\n\t\t\t\t\t\t\t: 1\n\t\t\t\t\t);\n\t\t\t\t\twrappedTextIndentLength += charWidth;\n\t\t\t\t}\n\n\t\t\t\tconst indentWidth = Math.ceil(fontInfo.spaceWidth * wrappedTextIndentLength);\n\n\t\t\t\t// Force sticking to beginning of line if no character would fit except for the indentation\n\t\t\t\tif (indentWidth + fontInfo.typicalFullwidthCharacterWidth > overallWidth) {\n\t\t\t\t\tfirstNonWhitespaceIndex = 0;\n\t\t\t\t\twrappedTextIndentLength = 0;\n\t\t\t\t} else {\n\t\t\t\t\twidth = overallWidth - indentWidth;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst renderLineContent = lineContent.substr(firstNonWhitespaceIndex);\n\t\tconst tmp = renderLine(renderLineContent, wrappedTextIndentLength, tabSize, width, sb, additionalIndentLength);\n\t\tfirstNonWhitespaceIndices[i] = firstNonWhitespaceIndex;\n\t\twrappedTextIndentLengths[i] = wrappedTextIndentLength;\n\t\trenderLineContents[i] = renderLineContent;\n\t\tallCharOffsets[i] = tmp[0];\n\t\tallVisibleColumns[i] = tmp[1];\n\t}\n\tconst html = sb.build();\n\tconst trustedhtml = ttPolicy?.createHTML(html) ?? html;\n\tcontainerDomNode.innerHTML = trustedhtml as string;\n\n\tcontainerDomNode.style.position = 'absolute';\n\tcontainerDomNode.style.top = '10000';\n\tcontainerDomNode.style.wordWrap = 'break-word';\n\tdocument.body.appendChild(containerDomNode);\n\n\tconst range = document.createRange();\n\tconst lineDomNodes = Array.prototype.slice.call(containerDomNode.children, 0);\n\n\tconst result: (ModelLineProjectionData | null)[] = [];\n\tfor (let i = 0; i < requests.length; i++) {\n\t\tconst lineDomNode = lineDomNodes[i];\n\t\tconst breakOffsets: number[] | null = readLineBreaks(range, lineDomNode, renderLineContents[i], allCharOffsets[i]);\n\t\tif (breakOffsets === null) {\n\t\t\tresult[i] = createEmptyLineBreakWithPossiblyInjectedText(i);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst firstNonWhitespaceIndex = firstNonWhitespaceIndices[i];\n\t\tconst wrappedTextIndentLength = wrappedTextIndentLengths[i] + additionalIndentSize;\n\t\tconst visibleColumns = allVisibleColumns[i];\n\n\t\tconst breakOffsetsVisibleColumn: number[] = [];\n\t\tfor (let j = 0, len = breakOffsets.length; j < len; j++) {\n\t\t\tbreakOffsetsVisibleColumn[j] = visibleColumns[breakOffsets[j]];\n\t\t}\n\n\t\tif (firstNonWhitespaceIndex !== 0) {\n\t\t\t// All break offsets are relative to the renderLineContent, make them absolute again\n\t\t\tfor (let j = 0, len = breakOffsets.length; j < len; j++) {\n\t\t\t\tbreakOffsets[j] += firstNonWhitespaceIndex;\n\t\t\t}\n\t\t}\n\n\t\tlet injectionOptions: InjectedTextOptions[] | null;\n\t\tlet injectionOffsets: number[] | null;\n\t\tconst curInjectedTexts = injectedTextsPerLine[i];\n\t\tif (curInjectedTexts) {\n\t\t\tinjectionOptions = curInjectedTexts.map(t => t.options);\n\t\t\tinjectionOffsets = curInjectedTexts.map(text => text.column - 1);\n\t\t} else {\n\t\t\tinjectionOptions = null;\n\t\t\tinjectionOffsets = null;\n\t\t}\n\n\t\tresult[i] = new ModelLineProjectionData(injectionOffsets, injectionOptions, breakOffsets, breakOffsetsVisibleColumn, wrappedTextIndentLength);\n\t}\n\n\tdocument.body.removeChild(containerDomNode);\n\treturn result;\n}\n\nconst enum Constants {\n\tSPAN_MODULO_LIMIT = 16384\n}\n\nfunction renderLine(lineContent: string, initialVisibleColumn: number, tabSize: number, width: number, sb: IStringBuilder, wrappingIndentLength: number): [number[], number[]] {\n\n\tif (wrappingIndentLength !== 0) {\n\t\tconst hangingOffset = String(wrappingIndentLength);\n\t\tsb.appendASCIIString('
    ');\n\t// if (containsRTL) {\n\t// \tsb.appendASCIIString('\" dir=\"ltr');\n\t// }\n\n\tconst len = lineContent.length;\n\tlet visibleColumn = initialVisibleColumn;\n\tlet charOffset = 0;\n\tconst charOffsets: number[] = [];\n\tconst visibleColumns: number[] = [];\n\tlet nextCharCode = (0 < len ? lineContent.charCodeAt(0) : CharCode.Null);\n\n\tsb.appendASCIIString('');\n\tfor (let charIndex = 0; charIndex < len; charIndex++) {\n\t\tif (charIndex !== 0 && charIndex % Constants.SPAN_MODULO_LIMIT === 0) {\n\t\t\tsb.appendASCIIString('');\n\t\t}\n\t\tcharOffsets[charIndex] = charOffset;\n\t\tvisibleColumns[charIndex] = visibleColumn;\n\t\tconst charCode = nextCharCode;\n\t\tnextCharCode = (charIndex + 1 < len ? lineContent.charCodeAt(charIndex + 1) : CharCode.Null);\n\t\tlet producedCharacters = 1;\n\t\tlet charWidth = 1;\n\t\tswitch (charCode) {\n\t\t\tcase CharCode.Tab:\n\t\t\t\tproducedCharacters = (tabSize - (visibleColumn % tabSize));\n\t\t\t\tcharWidth = producedCharacters;\n\t\t\t\tfor (let space = 1; space <= producedCharacters; space++) {\n\t\t\t\t\tif (space < producedCharacters) {\n\t\t\t\t\t\tsb.write1(0xA0); //  \n\t\t\t\t\t} else {\n\t\t\t\t\t\tsb.appendASCII(CharCode.Space);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase CharCode.Space:\n\t\t\t\tif (nextCharCode === CharCode.Space) {\n\t\t\t\t\tsb.write1(0xA0); //  \n\t\t\t\t} else {\n\t\t\t\t\tsb.appendASCII(CharCode.Space);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase CharCode.LessThan:\n\t\t\t\tsb.appendASCIIString('<');\n\t\t\t\tbreak;\n\n\t\t\tcase CharCode.GreaterThan:\n\t\t\t\tsb.appendASCIIString('>');\n\t\t\t\tbreak;\n\n\t\t\tcase CharCode.Ampersand:\n\t\t\t\tsb.appendASCIIString('&');\n\t\t\t\tbreak;\n\n\t\t\tcase CharCode.Null:\n\t\t\t\tsb.appendASCIIString('�');\n\t\t\t\tbreak;\n\n\t\t\tcase CharCode.UTF8_BOM:\n\t\t\tcase CharCode.LINE_SEPARATOR:\n\t\t\tcase CharCode.PARAGRAPH_SEPARATOR:\n\t\t\tcase CharCode.NEXT_LINE:\n\t\t\t\tsb.write1(0xFFFD);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tif (strings.isFullWidthCharacter(charCode)) {\n\t\t\t\t\tcharWidth++;\n\t\t\t\t}\n\t\t\t\tif (charCode < 32) {\n\t\t\t\t\tsb.write1(9216 + charCode);\n\t\t\t\t} else {\n\t\t\t\t\tsb.write1(charCode);\n\t\t\t\t}\n\t\t}\n\n\t\tcharOffset += producedCharacters;\n\t\tvisibleColumn += charWidth;\n\t}\n\tsb.appendASCIIString('');\n\n\tcharOffsets[lineContent.length] = charOffset;\n\tvisibleColumns[lineContent.length] = visibleColumn;\n\n\tsb.appendASCIIString('
    ');\n\n\treturn [charOffsets, visibleColumns];\n}\n\nfunction readLineBreaks(range: Range, lineDomNode: HTMLDivElement, lineContent: string, charOffsets: number[]): number[] | null {\n\tif (lineContent.length <= 1) {\n\t\treturn null;\n\t}\n\tconst spans = Array.prototype.slice.call(lineDomNode.children, 0);\n\n\tconst breakOffsets: number[] = [];\n\ttry {\n\t\tdiscoverBreaks(range, spans, charOffsets, 0, null, lineContent.length - 1, null, breakOffsets);\n\t} catch (err) {\n\t\tconsole.log(err);\n\t\treturn null;\n\t}\n\n\tif (breakOffsets.length === 0) {\n\t\treturn null;\n\t}\n\n\tbreakOffsets.push(lineContent.length);\n\treturn breakOffsets;\n}\n\nfunction discoverBreaks(range: Range, spans: HTMLSpanElement[], charOffsets: number[], low: number, lowRects: DOMRectList | null, high: number, highRects: DOMRectList | null, result: number[]): void {\n\tif (low === high) {\n\t\treturn;\n\t}\n\n\tlowRects = lowRects || readClientRect(range, spans, charOffsets[low], charOffsets[low + 1]);\n\thighRects = highRects || readClientRect(range, spans, charOffsets[high], charOffsets[high + 1]);\n\n\tif (Math.abs(lowRects[0].top - highRects[0].top) <= 0.1) {\n\t\t// same line\n\t\treturn;\n\t}\n\n\t// there is at least one line break between these two offsets\n\tif (low + 1 === high) {\n\t\t// the two characters are adjacent, so the line break must be exactly between them\n\t\tresult.push(high);\n\t\treturn;\n\t}\n\n\tconst mid = low + ((high - low) / 2) | 0;\n\tconst midRects = readClientRect(range, spans, charOffsets[mid], charOffsets[mid + 1]);\n\tdiscoverBreaks(range, spans, charOffsets, low, lowRects, mid, midRects, result);\n\tdiscoverBreaks(range, spans, charOffsets, mid, midRects, high, highRects, result);\n}\n\nfunction readClientRect(range: Range, spans: HTMLSpanElement[], startOffset: number, endOffset: number): DOMRectList {\n\trange.setStart(spans[(startOffset / Constants.SPAN_MODULO_LIMIT) | 0].firstChild!, startOffset % Constants.SPAN_MODULO_LIMIT);\n\trange.setEnd(spans[(endOffset / Constants.SPAN_MODULO_LIMIT) | 0].firstChild!, endOffset % Constants.SPAN_MODULO_LIMIT);\n\treturn range.getClientRects();\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';\nimport { applyFontInfo } from 'vs/editor/browser/config/domFontInfo';\nimport { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';\nimport { IVisibleLine, IVisibleLinesHost, VisibleLinesCollection } from 'vs/editor/browser/view/viewLayer';\nimport { ViewPart } from 'vs/editor/browser/view/viewPart';\nimport { IStringBuilder } from 'vs/editor/common/core/stringBuilder';\nimport { IEditorConfiguration } from 'vs/editor/common/config/editorConfiguration';\nimport { RenderingContext, RestrictedRenderingContext } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\nimport { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\n\nexport class ViewOverlays extends ViewPart implements IVisibleLinesHost {\n\n\tprivate readonly _visibleLines: VisibleLinesCollection;\n\tprotected readonly domNode: FastDomNode;\n\tprivate _dynamicOverlays: DynamicViewOverlay[];\n\tprivate _isFocused: boolean;\n\n\tconstructor(context: ViewContext) {\n\t\tsuper(context);\n\n\t\tthis._visibleLines = new VisibleLinesCollection(this);\n\t\tthis.domNode = this._visibleLines.domNode;\n\n\t\tthis._dynamicOverlays = [];\n\t\tthis._isFocused = false;\n\n\t\tthis.domNode.setClassName('view-overlays');\n\t}\n\n\tpublic override shouldRender(): boolean {\n\t\tif (super.shouldRender()) {\n\t\t\treturn true;\n\t\t}\n\n\t\tfor (let i = 0, len = this._dynamicOverlays.length; i < len; i++) {\n\t\t\tconst dynamicOverlay = this._dynamicOverlays[i];\n\t\t\tif (dynamicOverlay.shouldRender()) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic override dispose(): void {\n\t\tsuper.dispose();\n\n\t\tfor (let i = 0, len = this._dynamicOverlays.length; i < len; i++) {\n\t\t\tconst dynamicOverlay = this._dynamicOverlays[i];\n\t\t\tdynamicOverlay.dispose();\n\t\t}\n\t\tthis._dynamicOverlays = [];\n\t}\n\n\tpublic getDomNode(): FastDomNode {\n\t\treturn this.domNode;\n\t}\n\n\t// ---- begin IVisibleLinesHost\n\n\tpublic createVisibleLine(): ViewOverlayLine {\n\t\treturn new ViewOverlayLine(this._context.configuration, this._dynamicOverlays);\n\t}\n\n\t// ---- end IVisibleLinesHost\n\n\tpublic addDynamicOverlay(overlay: DynamicViewOverlay): void {\n\t\tthis._dynamicOverlays.push(overlay);\n\t}\n\n\t// ----- event handlers\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tthis._visibleLines.onConfigurationChanged(e);\n\t\tconst startLineNumber = this._visibleLines.getStartLineNumber();\n\t\tconst endLineNumber = this._visibleLines.getEndLineNumber();\n\t\tfor (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n\t\t\tconst line = this._visibleLines.getVisibleLine(lineNumber);\n\t\t\tline.onConfigurationChanged(e);\n\t\t}\n\t\treturn true;\n\t}\n\tpublic override onFlushed(e: viewEvents.ViewFlushedEvent): boolean {\n\t\treturn this._visibleLines.onFlushed(e);\n\t}\n\tpublic override onFocusChanged(e: viewEvents.ViewFocusChangedEvent): boolean {\n\t\tthis._isFocused = e.isFocused;\n\t\treturn true;\n\t}\n\tpublic override onLinesChanged(e: viewEvents.ViewLinesChangedEvent): boolean {\n\t\treturn this._visibleLines.onLinesChanged(e);\n\t}\n\tpublic override onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean {\n\t\treturn this._visibleLines.onLinesDeleted(e);\n\t}\n\tpublic override onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean {\n\t\treturn this._visibleLines.onLinesInserted(e);\n\t}\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn this._visibleLines.onScrollChanged(e) || true;\n\t}\n\tpublic override onTokensChanged(e: viewEvents.ViewTokensChangedEvent): boolean {\n\t\treturn this._visibleLines.onTokensChanged(e);\n\t}\n\tpublic override onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {\n\t\treturn this._visibleLines.onZonesChanged(e);\n\t}\n\n\t// ----- end event handlers\n\n\tpublic prepareRender(ctx: RenderingContext): void {\n\t\tconst toRender = this._dynamicOverlays.filter(overlay => overlay.shouldRender());\n\n\t\tfor (let i = 0, len = toRender.length; i < len; i++) {\n\t\t\tconst dynamicOverlay = toRender[i];\n\t\t\tdynamicOverlay.prepareRender(ctx);\n\t\t\tdynamicOverlay.onDidRender();\n\t\t}\n\t}\n\n\tpublic render(ctx: RestrictedRenderingContext): void {\n\t\t// Overwriting to bypass `shouldRender` flag\n\t\tthis._viewOverlaysRender(ctx);\n\n\t\tthis.domNode.toggleClassName('focused', this._isFocused);\n\t}\n\n\t_viewOverlaysRender(ctx: RestrictedRenderingContext): void {\n\t\tthis._visibleLines.renderLines(ctx.viewportData);\n\t}\n}\n\nexport class ViewOverlayLine implements IVisibleLine {\n\n\tprivate readonly _configuration: IEditorConfiguration;\n\tprivate readonly _dynamicOverlays: DynamicViewOverlay[];\n\tprivate _domNode: FastDomNode | null;\n\tprivate _renderedContent: string | null;\n\tprivate _lineHeight: number;\n\n\tconstructor(configuration: IEditorConfiguration, dynamicOverlays: DynamicViewOverlay[]) {\n\t\tthis._configuration = configuration;\n\t\tthis._lineHeight = this._configuration.options.get(EditorOption.lineHeight);\n\t\tthis._dynamicOverlays = dynamicOverlays;\n\n\t\tthis._domNode = null;\n\t\tthis._renderedContent = null;\n\t}\n\n\tpublic getDomNode(): HTMLElement | null {\n\t\tif (!this._domNode) {\n\t\t\treturn null;\n\t\t}\n\t\treturn this._domNode.domNode;\n\t}\n\tpublic setDomNode(domNode: HTMLElement): void {\n\t\tthis._domNode = createFastDomNode(domNode);\n\t}\n\n\tpublic onContentChanged(): void {\n\t\t// Nothing\n\t}\n\tpublic onTokensChanged(): void {\n\t\t// Nothing\n\t}\n\tpublic onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): void {\n\t\tthis._lineHeight = this._configuration.options.get(EditorOption.lineHeight);\n\t}\n\n\tpublic renderLine(lineNumber: number, deltaTop: number, viewportData: ViewportData, sb: IStringBuilder): boolean {\n\t\tlet result = '';\n\t\tfor (let i = 0, len = this._dynamicOverlays.length; i < len; i++) {\n\t\t\tconst dynamicOverlay = this._dynamicOverlays[i];\n\t\t\tresult += dynamicOverlay.render(viewportData.startLineNumber, lineNumber);\n\t\t}\n\n\t\tif (this._renderedContent === result) {\n\t\t\t// No rendering needed\n\t\t\treturn false;\n\t\t}\n\n\t\tthis._renderedContent = result;\n\n\t\tsb.appendASCIIString('
    ');\n\t\tsb.appendASCIIString(result);\n\t\tsb.appendASCIIString('
    ');\n\n\t\treturn true;\n\t}\n\n\tpublic layoutLine(lineNumber: number, deltaTop: number): void {\n\t\tif (this._domNode) {\n\t\t\tthis._domNode.setTop(deltaTop);\n\t\t\tthis._domNode.setHeight(this._lineHeight);\n\t\t}\n\t}\n}\n\nexport class ContentViewOverlays extends ViewOverlays {\n\n\tprivate _contentWidth: number;\n\n\tconstructor(context: ViewContext) {\n\t\tsuper(context);\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\t\tthis._contentWidth = layoutInfo.contentWidth;\n\n\t\tthis.domNode.setHeight(0);\n\t}\n\n\t// --- begin event handlers\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\t\tthis._contentWidth = layoutInfo.contentWidth;\n\t\treturn super.onConfigurationChanged(e) || true;\n\t}\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn super.onScrollChanged(e) || e.scrollWidthChanged;\n\t}\n\n\t// --- end event handlers\n\n\toverride _viewOverlaysRender(ctx: RestrictedRenderingContext): void {\n\t\tsuper._viewOverlaysRender(ctx);\n\n\t\tthis.domNode.setWidth(Math.max(ctx.scrollWidth, this._contentWidth));\n\t}\n}\n\nexport class MarginViewOverlays extends ViewOverlays {\n\n\tprivate _contentLeft: number;\n\n\tconstructor(context: ViewContext) {\n\t\tsuper(context);\n\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\t\tthis._contentLeft = layoutInfo.contentLeft;\n\n\t\tthis.domNode.setClassName('margin-view-overlays');\n\t\tthis.domNode.setWidth(1);\n\n\t\tapplyFontInfo(this.domNode, options.get(EditorOption.fontInfo));\n\t}\n\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tconst options = this._context.configuration.options;\n\t\tapplyFontInfo(this.domNode, options.get(EditorOption.fontInfo));\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\t\tthis._contentLeft = layoutInfo.contentLeft;\n\t\treturn super.onConfigurationChanged(e) || true;\n\t}\n\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\treturn super.onScrollChanged(e) || e.scrollHeightChanged;\n\t}\n\n\toverride _viewOverlaysRender(ctx: RestrictedRenderingContext): void {\n\t\tsuper._viewOverlaysRender(ctx);\n\t\tconst height = Math.min(ctx.scrollHeight, 1000000);\n\t\tthis.domNode.setHeight(height);\n\t\tthis.domNode.setWidth(this._contentLeft);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';\nimport * as strings from 'vs/base/common/strings';\nimport { applyFontInfo } from 'vs/editor/browser/config/domFontInfo';\nimport { TextEditorCursorStyle, EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { RenderingContext, RestrictedRenderingContext } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\nimport { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor';\n\nexport interface IViewCursorRenderData {\n\tdomNode: HTMLElement;\n\tposition: Position;\n\tcontentLeft: number;\n\twidth: number;\n\theight: number;\n}\n\nclass ViewCursorRenderData {\n\tconstructor(\n\t\tpublic readonly top: number,\n\t\tpublic readonly left: number,\n\t\tpublic readonly width: number,\n\t\tpublic readonly height: number,\n\t\tpublic readonly textContent: string,\n\t\tpublic readonly textContentClassName: string\n\t) { }\n}\n\nexport class ViewCursor {\n\tprivate readonly _context: ViewContext;\n\tprivate readonly _domNode: FastDomNode;\n\n\tprivate _cursorStyle: TextEditorCursorStyle;\n\tprivate _lineCursorWidth: number;\n\tprivate _lineHeight: number;\n\tprivate _typicalHalfwidthCharacterWidth: number;\n\n\tprivate _isVisible: boolean;\n\n\tprivate _position: Position;\n\n\tprivate _lastRenderedContent: string;\n\tprivate _renderData: ViewCursorRenderData | null;\n\n\tconstructor(context: ViewContext) {\n\t\tthis._context = context;\n\t\tconst options = this._context.configuration.options;\n\t\tconst fontInfo = options.get(EditorOption.fontInfo);\n\n\t\tthis._cursorStyle = options.get(EditorOption.cursorStyle);\n\t\tthis._lineHeight = options.get(EditorOption.lineHeight);\n\t\tthis._typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;\n\t\tthis._lineCursorWidth = Math.min(options.get(EditorOption.cursorWidth), this._typicalHalfwidthCharacterWidth);\n\n\t\tthis._isVisible = true;\n\n\t\t// Create the dom node\n\t\tthis._domNode = createFastDomNode(document.createElement('div'));\n\t\tthis._domNode.setClassName(`cursor ${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`);\n\t\tthis._domNode.setHeight(this._lineHeight);\n\t\tthis._domNode.setTop(0);\n\t\tthis._domNode.setLeft(0);\n\t\tapplyFontInfo(this._domNode, fontInfo);\n\t\tthis._domNode.setDisplay('none');\n\n\t\tthis._position = new Position(1, 1);\n\n\t\tthis._lastRenderedContent = '';\n\t\tthis._renderData = null;\n\t}\n\n\tpublic getDomNode(): FastDomNode {\n\t\treturn this._domNode;\n\t}\n\n\tpublic getPosition(): Position {\n\t\treturn this._position;\n\t}\n\n\tpublic show(): void {\n\t\tif (!this._isVisible) {\n\t\t\tthis._domNode.setVisibility('inherit');\n\t\t\tthis._isVisible = true;\n\t\t}\n\t}\n\n\tpublic hide(): void {\n\t\tif (this._isVisible) {\n\t\t\tthis._domNode.setVisibility('hidden');\n\t\t\tthis._isVisible = false;\n\t\t}\n\t}\n\n\tpublic onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tconst options = this._context.configuration.options;\n\t\tconst fontInfo = options.get(EditorOption.fontInfo);\n\n\t\tthis._cursorStyle = options.get(EditorOption.cursorStyle);\n\t\tthis._lineHeight = options.get(EditorOption.lineHeight);\n\t\tthis._typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;\n\t\tthis._lineCursorWidth = Math.min(options.get(EditorOption.cursorWidth), this._typicalHalfwidthCharacterWidth);\n\t\tapplyFontInfo(this._domNode, fontInfo);\n\n\t\treturn true;\n\t}\n\n\tpublic onCursorPositionChanged(position: Position): boolean {\n\t\tthis._position = position;\n\t\treturn true;\n\t}\n\n\t/**\n\t * If `this._position` is inside a grapheme, returns the position where the grapheme starts.\n\t * Also returns the next grapheme.\n\t */\n\tprivate _getGraphemeAwarePosition(): [Position, string] {\n\t\tconst { lineNumber, column } = this._position;\n\t\tconst lineContent = this._context.model.getLineContent(lineNumber);\n\t\tconst [startOffset, endOffset] = strings.getCharContainingOffset(lineContent, column - 1);\n\t\treturn [new Position(lineNumber, startOffset + 1), lineContent.substring(startOffset, endOffset)];\n\t}\n\n\tprivate _prepareRender(ctx: RenderingContext): ViewCursorRenderData | null {\n\t\tlet textContent = '';\n\t\tconst [position, nextGrapheme] = this._getGraphemeAwarePosition();\n\n\t\tif (this._cursorStyle === TextEditorCursorStyle.Line || this._cursorStyle === TextEditorCursorStyle.LineThin) {\n\t\t\tconst visibleRange = ctx.visibleRangeForPosition(position);\n\t\t\tif (!visibleRange || visibleRange.outsideRenderedLine) {\n\t\t\t\t// Outside viewport\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tlet width: number;\n\t\t\tif (this._cursorStyle === TextEditorCursorStyle.Line) {\n\t\t\t\twidth = dom.computeScreenAwareSize(this._lineCursorWidth > 0 ? this._lineCursorWidth : 2);\n\t\t\t\tif (width > 2) {\n\t\t\t\t\ttextContent = nextGrapheme;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twidth = dom.computeScreenAwareSize(1);\n\t\t\t}\n\n\t\t\tlet left = visibleRange.left;\n\t\t\tif (width >= 2 && left >= 1) {\n\t\t\t\t// try to center cursor\n\t\t\t\tleft -= 1;\n\t\t\t}\n\n\t\t\tconst top = ctx.getVerticalOffsetForLineNumber(position.lineNumber) - ctx.bigNumbersDelta;\n\t\t\treturn new ViewCursorRenderData(top, left, width, this._lineHeight, textContent, '');\n\t\t}\n\n\t\tconst visibleRangeForCharacter = ctx.linesVisibleRangesForRange(new Range(position.lineNumber, position.column, position.lineNumber, position.column + nextGrapheme.length), false);\n\t\tif (!visibleRangeForCharacter || visibleRangeForCharacter.length === 0) {\n\t\t\t// Outside viewport\n\t\t\treturn null;\n\t\t}\n\n\t\tconst firstVisibleRangeForCharacter = visibleRangeForCharacter[0];\n\t\tif (firstVisibleRangeForCharacter.outsideRenderedLine || firstVisibleRangeForCharacter.ranges.length === 0) {\n\t\t\t// Outside viewport\n\t\t\treturn null;\n\t\t}\n\n\t\tconst range = firstVisibleRangeForCharacter.ranges[0];\n\t\tconst width = range.width < 1 ? this._typicalHalfwidthCharacterWidth : range.width;\n\n\t\tlet textContentClassName = '';\n\t\tif (this._cursorStyle === TextEditorCursorStyle.Block) {\n\t\t\tconst lineData = this._context.model.getViewLineData(position.lineNumber);\n\t\t\ttextContent = nextGrapheme;\n\t\t\tconst tokenIndex = lineData.tokens.findTokenIndexAtOffset(position.column - 1);\n\t\t\ttextContentClassName = lineData.tokens.getClassName(tokenIndex);\n\t\t}\n\n\t\tlet top = ctx.getVerticalOffsetForLineNumber(position.lineNumber) - ctx.bigNumbersDelta;\n\t\tlet height = this._lineHeight;\n\n\t\t// Underline might interfere with clicking\n\t\tif (this._cursorStyle === TextEditorCursorStyle.Underline || this._cursorStyle === TextEditorCursorStyle.UnderlineThin) {\n\t\t\ttop += this._lineHeight - 2;\n\t\t\theight = 2;\n\t\t}\n\n\t\treturn new ViewCursorRenderData(top, range.left, width, height, textContent, textContentClassName);\n\t}\n\n\tpublic prepareRender(ctx: RenderingContext): void {\n\t\tthis._renderData = this._prepareRender(ctx);\n\t}\n\n\tpublic render(ctx: RestrictedRenderingContext): IViewCursorRenderData | null {\n\t\tif (!this._renderData) {\n\t\t\tthis._domNode.setDisplay('none');\n\t\t\treturn null;\n\t\t}\n\n\t\tif (this._lastRenderedContent !== this._renderData.textContent) {\n\t\t\tthis._lastRenderedContent = this._renderData.textContent;\n\t\t\tthis._domNode.domNode.textContent = this._lastRenderedContent;\n\t\t}\n\n\t\tthis._domNode.setClassName(`cursor ${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME} ${this._renderData.textContentClassName}`);\n\n\t\tthis._domNode.setDisplay('block');\n\t\tthis._domNode.setTop(this._renderData.top);\n\t\tthis._domNode.setLeft(this._renderData.left);\n\t\tthis._domNode.setWidth(this._renderData.width);\n\t\tthis._domNode.setLineHeight(this._renderData.height);\n\t\tthis._domNode.setHeight(this._renderData.height);\n\n\t\treturn {\n\t\t\tdomNode: this._domNode.domNode,\n\t\t\tposition: this._position,\n\t\t\tcontentLeft: this._renderData.left,\n\t\t\theight: this._renderData.height,\n\t\t\twidth: 2\n\t\t};\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { IEditorConfiguration } from 'vs/editor/common/config/editorConfiguration';\nimport { IModelDecoration, ITextModel, PositionAffinity } from 'vs/editor/common/model';\nimport { IViewModelLines } from 'vs/editor/common/viewModel/viewModelLines';\nimport { ICoordinatesConverter, InlineDecoration, InlineDecorationType, ViewModelDecoration } from 'vs/editor/common/viewModel/viewModel';\nimport { filterValidationDecorations } from 'vs/editor/common/config/editorOptions';\nimport { StandardTokenType } from 'vs/editor/common/languages';\n\nexport interface IDecorationsViewportData {\n\t/**\n\t * decorations in the viewport.\n\t */\n\treadonly decorations: ViewModelDecoration[];\n\t/**\n\t * inline decorations grouped by each line in the viewport.\n\t */\n\treadonly inlineDecorations: InlineDecoration[][];\n}\n\nexport class ViewModelDecorations implements IDisposable {\n\n\tprivate readonly editorId: number;\n\tprivate readonly model: ITextModel;\n\tprivate readonly configuration: IEditorConfiguration;\n\tprivate readonly _linesCollection: IViewModelLines;\n\tprivate readonly _coordinatesConverter: ICoordinatesConverter;\n\n\tprivate _decorationsCache: { [decorationId: string]: ViewModelDecoration; };\n\n\tprivate _cachedModelDecorationsResolver: IDecorationsViewportData | null;\n\tprivate _cachedModelDecorationsResolverViewRange: Range | null;\n\n\tconstructor(editorId: number, model: ITextModel, configuration: IEditorConfiguration, linesCollection: IViewModelLines, coordinatesConverter: ICoordinatesConverter) {\n\t\tthis.editorId = editorId;\n\t\tthis.model = model;\n\t\tthis.configuration = configuration;\n\t\tthis._linesCollection = linesCollection;\n\t\tthis._coordinatesConverter = coordinatesConverter;\n\t\tthis._decorationsCache = Object.create(null);\n\t\tthis._cachedModelDecorationsResolver = null;\n\t\tthis._cachedModelDecorationsResolverViewRange = null;\n\t}\n\n\tprivate _clearCachedModelDecorationsResolver(): void {\n\t\tthis._cachedModelDecorationsResolver = null;\n\t\tthis._cachedModelDecorationsResolverViewRange = null;\n\t}\n\n\tpublic dispose(): void {\n\t\tthis._decorationsCache = Object.create(null);\n\t\tthis._clearCachedModelDecorationsResolver();\n\t}\n\n\tpublic reset(): void {\n\t\tthis._decorationsCache = Object.create(null);\n\t\tthis._clearCachedModelDecorationsResolver();\n\t}\n\n\tpublic onModelDecorationsChanged(): void {\n\t\tthis._decorationsCache = Object.create(null);\n\t\tthis._clearCachedModelDecorationsResolver();\n\t}\n\n\tpublic onLineMappingChanged(): void {\n\t\tthis._decorationsCache = Object.create(null);\n\n\t\tthis._clearCachedModelDecorationsResolver();\n\t}\n\n\tprivate _getOrCreateViewModelDecoration(modelDecoration: IModelDecoration): ViewModelDecoration {\n\t\tconst id = modelDecoration.id;\n\t\tlet r = this._decorationsCache[id];\n\t\tif (!r) {\n\t\t\tconst modelRange = modelDecoration.range;\n\t\t\tconst options = modelDecoration.options;\n\t\t\tlet viewRange: Range;\n\t\t\tif (options.isWholeLine) {\n\t\t\t\tconst start = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.startLineNumber, 1), PositionAffinity.Left);\n\t\t\t\tconst end = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.endLineNumber, this.model.getLineMaxColumn(modelRange.endLineNumber)), PositionAffinity.Right);\n\t\t\t\tviewRange = new Range(start.lineNumber, start.column, end.lineNumber, end.column);\n\t\t\t} else {\n\t\t\t\t// For backwards compatibility reasons, we want injected text before any decoration.\n\t\t\t\t// Thus, move decorations to the right.\n\t\t\t\tviewRange = this._coordinatesConverter.convertModelRangeToViewRange(modelRange, PositionAffinity.Right);\n\t\t\t}\n\t\t\tr = new ViewModelDecoration(viewRange, options);\n\t\t\tthis._decorationsCache[id] = r;\n\t\t}\n\t\treturn r;\n\t}\n\n\tpublic getDecorationsViewportData(viewRange: Range): IDecorationsViewportData {\n\t\tlet cacheIsValid = (this._cachedModelDecorationsResolver !== null);\n\t\tcacheIsValid = cacheIsValid && (viewRange.equalsRange(this._cachedModelDecorationsResolverViewRange));\n\t\tif (!cacheIsValid) {\n\t\t\tthis._cachedModelDecorationsResolver = this._getDecorationsViewportData(viewRange);\n\t\t\tthis._cachedModelDecorationsResolverViewRange = viewRange;\n\t\t}\n\t\treturn this._cachedModelDecorationsResolver!;\n\t}\n\n\tprivate _getDecorationsViewportData(viewportRange: Range): IDecorationsViewportData {\n\t\tconst modelDecorations = this._linesCollection.getDecorationsInRange(viewportRange, this.editorId, filterValidationDecorations(this.configuration.options));\n\n\t\tconst startLineNumber = viewportRange.startLineNumber;\n\t\tconst endLineNumber = viewportRange.endLineNumber;\n\n\t\tconst decorationsInViewport: ViewModelDecoration[] = [];\n\t\tlet decorationsInViewportLen = 0;\n\t\tconst inlineDecorations: InlineDecoration[][] = [];\n\t\tfor (let j = startLineNumber; j <= endLineNumber; j++) {\n\t\t\tinlineDecorations[j - startLineNumber] = [];\n\t\t}\n\n\t\tfor (let i = 0, len = modelDecorations.length; i < len; i++) {\n\t\t\tconst modelDecoration = modelDecorations[i];\n\t\t\tconst decorationOptions = modelDecoration.options;\n\n\t\t\tif (!isModelDecorationVisible(this.model, modelDecoration)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst viewModelDecoration = this._getOrCreateViewModelDecoration(modelDecoration);\n\t\t\tconst viewRange = viewModelDecoration.range;\n\n\t\t\tdecorationsInViewport[decorationsInViewportLen++] = viewModelDecoration;\n\n\t\t\tif (decorationOptions.inlineClassName) {\n\t\t\t\tconst inlineDecoration = new InlineDecoration(viewRange, decorationOptions.inlineClassName, decorationOptions.inlineClassNameAffectsLetterSpacing ? InlineDecorationType.RegularAffectingLetterSpacing : InlineDecorationType.Regular);\n\t\t\t\tconst intersectedStartLineNumber = Math.max(startLineNumber, viewRange.startLineNumber);\n\t\t\t\tconst intersectedEndLineNumber = Math.min(endLineNumber, viewRange.endLineNumber);\n\t\t\t\tfor (let j = intersectedStartLineNumber; j <= intersectedEndLineNumber; j++) {\n\t\t\t\t\tinlineDecorations[j - startLineNumber].push(inlineDecoration);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (decorationOptions.beforeContentClassName) {\n\t\t\t\tif (startLineNumber <= viewRange.startLineNumber && viewRange.startLineNumber <= endLineNumber) {\n\t\t\t\t\tconst inlineDecoration = new InlineDecoration(\n\t\t\t\t\t\tnew Range(viewRange.startLineNumber, viewRange.startColumn, viewRange.startLineNumber, viewRange.startColumn),\n\t\t\t\t\t\tdecorationOptions.beforeContentClassName,\n\t\t\t\t\t\tInlineDecorationType.Before\n\t\t\t\t\t);\n\t\t\t\t\tinlineDecorations[viewRange.startLineNumber - startLineNumber].push(inlineDecoration);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (decorationOptions.afterContentClassName) {\n\t\t\t\tif (startLineNumber <= viewRange.endLineNumber && viewRange.endLineNumber <= endLineNumber) {\n\t\t\t\t\tconst inlineDecoration = new InlineDecoration(\n\t\t\t\t\t\tnew Range(viewRange.endLineNumber, viewRange.endColumn, viewRange.endLineNumber, viewRange.endColumn),\n\t\t\t\t\t\tdecorationOptions.afterContentClassName,\n\t\t\t\t\t\tInlineDecorationType.After\n\t\t\t\t\t);\n\t\t\t\t\tinlineDecorations[viewRange.endLineNumber - startLineNumber].push(inlineDecoration);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tdecorations: decorationsInViewport,\n\t\t\tinlineDecorations: inlineDecorations\n\t\t};\n\t}\n}\n\nexport function isModelDecorationVisible(model: ITextModel, decoration: IModelDecoration): boolean {\n\tif (decoration.options.hideInCommentTokens && isModelDecorationInComment(model, decoration)) {\n\t\treturn false;\n\t}\n\n\tif (decoration.options.hideInStringTokens && isModelDecorationInString(model, decoration)) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nexport function isModelDecorationInComment(model: ITextModel, decoration: IModelDecoration): boolean {\n\treturn testTokensInRange(\n\t\tmodel,\n\t\tdecoration.range,\n\t\t(tokenType) => tokenType === StandardTokenType.Comment\n\t);\n}\n\nexport function isModelDecorationInString(model: ITextModel, decoration: IModelDecoration): boolean {\n\treturn testTokensInRange(\n\t\tmodel,\n\t\tdecoration.range,\n\t\t(tokenType) => tokenType === StandardTokenType.String\n\t);\n}\n\n/**\n * Calls the callback for every token that intersects the range.\n * If the callback returns `false`, iteration stops and `false` is returned.\n * Otherwise, `true` is returned.\n */\nfunction testTokensInRange(model: ITextModel, range: Range, callback: (tokenType: StandardTokenType) => boolean): boolean {\n\tfor (let lineNumber = range.startLineNumber; lineNumber <= range.endLineNumber; lineNumber++) {\n\t\tconst lineTokens = model.getLineTokens(lineNumber);\n\t\tconst isFirstLine = lineNumber === range.startLineNumber;\n\t\tconst isEndLine = lineNumber === range.endLineNumber;\n\n\t\tlet tokenIdx = isFirstLine ? lineTokens.findTokenIndexAtOffset(range.startColumn - 1) : 0;\n\t\twhile (tokenIdx < lineTokens.getCount()) {\n\t\t\tif (isEndLine) {\n\t\t\t\tconst startOffset = lineTokens.getStartOffset(tokenIdx);\n\t\t\t\tif (startOffset > range.endColumn - 1) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst callbackResult = callback(lineTokens.getStandardTokenType(tokenIdx));\n\t\t\tif (!callbackResult) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\ttokenIdx++;\n\t\t}\n\t}\n\treturn true;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as nls from 'vs/nls';\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { EndOfLineSequence, ICursorStateComputer, IIdentifiedSingleEditOperation, IValidEditOperation, ITextModel } from 'vs/editor/common/model';\nimport { TextModel } from 'vs/editor/common/model/textModel';\nimport { IUndoRedoService, IResourceUndoRedoElement, UndoRedoElementType, IWorkspaceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';\nimport { URI } from 'vs/base/common/uri';\nimport { TextChange, compressConsecutiveTextChanges } from 'vs/editor/common/core/textChange';\nimport * as buffer from 'vs/base/common/buffer';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { basename } from 'vs/base/common/resources';\n\nfunction uriGetComparisonKey(resource: URI): string {\n\treturn resource.toString();\n}\n\nexport class SingleModelEditStackData {\n\n\tpublic static create(model: ITextModel, beforeCursorState: Selection[] | null): SingleModelEditStackData {\n\t\tconst alternativeVersionId = model.getAlternativeVersionId();\n\t\tconst eol = getModelEOL(model);\n\t\treturn new SingleModelEditStackData(\n\t\t\talternativeVersionId,\n\t\t\talternativeVersionId,\n\t\t\teol,\n\t\t\teol,\n\t\t\tbeforeCursorState,\n\t\t\tbeforeCursorState,\n\t\t\t[]\n\t\t);\n\t}\n\n\tconstructor(\n\t\tpublic readonly beforeVersionId: number,\n\t\tpublic afterVersionId: number,\n\t\tpublic readonly beforeEOL: EndOfLineSequence,\n\t\tpublic afterEOL: EndOfLineSequence,\n\t\tpublic readonly beforeCursorState: Selection[] | null,\n\t\tpublic afterCursorState: Selection[] | null,\n\t\tpublic changes: TextChange[]\n\t) { }\n\n\tpublic append(model: ITextModel, textChanges: TextChange[], afterEOL: EndOfLineSequence, afterVersionId: number, afterCursorState: Selection[] | null): void {\n\t\tif (textChanges.length > 0) {\n\t\t\tthis.changes = compressConsecutiveTextChanges(this.changes, textChanges);\n\t\t}\n\t\tthis.afterEOL = afterEOL;\n\t\tthis.afterVersionId = afterVersionId;\n\t\tthis.afterCursorState = afterCursorState;\n\t}\n\n\tprivate static _writeSelectionsSize(selections: Selection[] | null): number {\n\t\treturn 4 + 4 * 4 * (selections ? selections.length : 0);\n\t}\n\n\tprivate static _writeSelections(b: Uint8Array, selections: Selection[] | null, offset: number): number {\n\t\tbuffer.writeUInt32BE(b, (selections ? selections.length : 0), offset); offset += 4;\n\t\tif (selections) {\n\t\t\tfor (const selection of selections) {\n\t\t\t\tbuffer.writeUInt32BE(b, selection.selectionStartLineNumber, offset); offset += 4;\n\t\t\t\tbuffer.writeUInt32BE(b, selection.selectionStartColumn, offset); offset += 4;\n\t\t\t\tbuffer.writeUInt32BE(b, selection.positionLineNumber, offset); offset += 4;\n\t\t\t\tbuffer.writeUInt32BE(b, selection.positionColumn, offset); offset += 4;\n\t\t\t}\n\t\t}\n\t\treturn offset;\n\t}\n\n\tprivate static _readSelections(b: Uint8Array, offset: number, dest: Selection[]): number {\n\t\tconst count = buffer.readUInt32BE(b, offset); offset += 4;\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tconst selectionStartLineNumber = buffer.readUInt32BE(b, offset); offset += 4;\n\t\t\tconst selectionStartColumn = buffer.readUInt32BE(b, offset); offset += 4;\n\t\t\tconst positionLineNumber = buffer.readUInt32BE(b, offset); offset += 4;\n\t\t\tconst positionColumn = buffer.readUInt32BE(b, offset); offset += 4;\n\t\t\tdest.push(new Selection(selectionStartLineNumber, selectionStartColumn, positionLineNumber, positionColumn));\n\t\t}\n\t\treturn offset;\n\t}\n\n\tpublic serialize(): ArrayBuffer {\n\t\tlet necessarySize = (\n\t\t\t+ 4 // beforeVersionId\n\t\t\t+ 4 // afterVersionId\n\t\t\t+ 1 // beforeEOL\n\t\t\t+ 1 // afterEOL\n\t\t\t+ SingleModelEditStackData._writeSelectionsSize(this.beforeCursorState)\n\t\t\t+ SingleModelEditStackData._writeSelectionsSize(this.afterCursorState)\n\t\t\t+ 4 // change count\n\t\t);\n\t\tfor (const change of this.changes) {\n\t\t\tnecessarySize += change.writeSize();\n\t\t}\n\n\t\tconst b = new Uint8Array(necessarySize);\n\t\tlet offset = 0;\n\t\tbuffer.writeUInt32BE(b, this.beforeVersionId, offset); offset += 4;\n\t\tbuffer.writeUInt32BE(b, this.afterVersionId, offset); offset += 4;\n\t\tbuffer.writeUInt8(b, this.beforeEOL, offset); offset += 1;\n\t\tbuffer.writeUInt8(b, this.afterEOL, offset); offset += 1;\n\t\toffset = SingleModelEditStackData._writeSelections(b, this.beforeCursorState, offset);\n\t\toffset = SingleModelEditStackData._writeSelections(b, this.afterCursorState, offset);\n\t\tbuffer.writeUInt32BE(b, this.changes.length, offset); offset += 4;\n\t\tfor (const change of this.changes) {\n\t\t\toffset = change.write(b, offset);\n\t\t}\n\t\treturn b.buffer;\n\t}\n\n\tpublic static deserialize(source: ArrayBuffer): SingleModelEditStackData {\n\t\tconst b = new Uint8Array(source);\n\t\tlet offset = 0;\n\t\tconst beforeVersionId = buffer.readUInt32BE(b, offset); offset += 4;\n\t\tconst afterVersionId = buffer.readUInt32BE(b, offset); offset += 4;\n\t\tconst beforeEOL = buffer.readUInt8(b, offset); offset += 1;\n\t\tconst afterEOL = buffer.readUInt8(b, offset); offset += 1;\n\t\tconst beforeCursorState: Selection[] = [];\n\t\toffset = SingleModelEditStackData._readSelections(b, offset, beforeCursorState);\n\t\tconst afterCursorState: Selection[] = [];\n\t\toffset = SingleModelEditStackData._readSelections(b, offset, afterCursorState);\n\t\tconst changeCount = buffer.readUInt32BE(b, offset); offset += 4;\n\t\tconst changes: TextChange[] = [];\n\t\tfor (let i = 0; i < changeCount; i++) {\n\t\t\toffset = TextChange.read(b, offset, changes);\n\t\t}\n\t\treturn new SingleModelEditStackData(\n\t\t\tbeforeVersionId,\n\t\t\tafterVersionId,\n\t\t\tbeforeEOL,\n\t\t\tafterEOL,\n\t\t\tbeforeCursorState,\n\t\t\tafterCursorState,\n\t\t\tchanges\n\t\t);\n\t}\n}\n\nexport interface IUndoRedoDelegate {\n\tprepareUndoRedo(element: MultiModelEditStackElement): Promise | IDisposable | void;\n}\n\nexport class SingleModelEditStackElement implements IResourceUndoRedoElement {\n\n\tpublic model: ITextModel | URI;\n\tprivate _data: SingleModelEditStackData | ArrayBuffer;\n\n\tpublic get type(): UndoRedoElementType.Resource {\n\t\treturn UndoRedoElementType.Resource;\n\t}\n\n\tpublic get resource(): URI {\n\t\tif (URI.isUri(this.model)) {\n\t\t\treturn this.model;\n\t\t}\n\t\treturn this.model.uri;\n\t}\n\n\tpublic get label(): string {\n\t\treturn nls.localize('edit', \"Typing\");\n\t}\n\n\tconstructor(model: ITextModel, beforeCursorState: Selection[] | null) {\n\t\tthis.model = model;\n\t\tthis._data = SingleModelEditStackData.create(model, beforeCursorState);\n\t}\n\n\tpublic toString(): string {\n\t\tconst data = (this._data instanceof SingleModelEditStackData ? this._data : SingleModelEditStackData.deserialize(this._data));\n\t\treturn data.changes.map(change => change.toString()).join(', ');\n\t}\n\n\tpublic matchesResource(resource: URI): boolean {\n\t\tconst uri = (URI.isUri(this.model) ? this.model : this.model.uri);\n\t\treturn (uri.toString() === resource.toString());\n\t}\n\n\tpublic setModel(model: ITextModel | URI): void {\n\t\tthis.model = model;\n\t}\n\n\tpublic canAppend(model: ITextModel): boolean {\n\t\treturn (this.model === model && this._data instanceof SingleModelEditStackData);\n\t}\n\n\tpublic append(model: ITextModel, textChanges: TextChange[], afterEOL: EndOfLineSequence, afterVersionId: number, afterCursorState: Selection[] | null): void {\n\t\tif (this._data instanceof SingleModelEditStackData) {\n\t\t\tthis._data.append(model, textChanges, afterEOL, afterVersionId, afterCursorState);\n\t\t}\n\t}\n\n\tpublic close(): void {\n\t\tif (this._data instanceof SingleModelEditStackData) {\n\t\t\tthis._data = this._data.serialize();\n\t\t}\n\t}\n\n\tpublic open(): void {\n\t\tif (!(this._data instanceof SingleModelEditStackData)) {\n\t\t\tthis._data = SingleModelEditStackData.deserialize(this._data);\n\t\t}\n\t}\n\n\tpublic undo(): void {\n\t\tif (URI.isUri(this.model)) {\n\t\t\t// don't have a model\n\t\t\tthrow new Error(`Invalid SingleModelEditStackElement`);\n\t\t}\n\t\tif (this._data instanceof SingleModelEditStackData) {\n\t\t\tthis._data = this._data.serialize();\n\t\t}\n\t\tconst data = SingleModelEditStackData.deserialize(this._data);\n\t\tthis.model._applyUndo(data.changes, data.beforeEOL, data.beforeVersionId, data.beforeCursorState);\n\t}\n\n\tpublic redo(): void {\n\t\tif (URI.isUri(this.model)) {\n\t\t\t// don't have a model\n\t\t\tthrow new Error(`Invalid SingleModelEditStackElement`);\n\t\t}\n\t\tif (this._data instanceof SingleModelEditStackData) {\n\t\t\tthis._data = this._data.serialize();\n\t\t}\n\t\tconst data = SingleModelEditStackData.deserialize(this._data);\n\t\tthis.model._applyRedo(data.changes, data.afterEOL, data.afterVersionId, data.afterCursorState);\n\t}\n\n\tpublic heapSize(): number {\n\t\tif (this._data instanceof SingleModelEditStackData) {\n\t\t\tthis._data = this._data.serialize();\n\t\t}\n\t\treturn this._data.byteLength + 168/*heap overhead*/;\n\t}\n}\n\nexport class MultiModelEditStackElement implements IWorkspaceUndoRedoElement {\n\n\tpublic readonly type = UndoRedoElementType.Workspace;\n\tpublic readonly label: string;\n\tprivate _isOpen: boolean;\n\n\tprivate readonly _editStackElementsArr: SingleModelEditStackElement[];\n\tprivate readonly _editStackElementsMap: Map;\n\n\tprivate _delegate: IUndoRedoDelegate | null;\n\n\tpublic get resources(): readonly URI[] {\n\t\treturn this._editStackElementsArr.map(editStackElement => editStackElement.resource);\n\t}\n\n\tconstructor(\n\t\tlabel: string,\n\t\teditStackElements: SingleModelEditStackElement[]\n\t) {\n\t\tthis.label = label;\n\t\tthis._isOpen = true;\n\t\tthis._editStackElementsArr = editStackElements.slice(0);\n\t\tthis._editStackElementsMap = new Map();\n\t\tfor (const editStackElement of this._editStackElementsArr) {\n\t\t\tconst key = uriGetComparisonKey(editStackElement.resource);\n\t\t\tthis._editStackElementsMap.set(key, editStackElement);\n\t\t}\n\t\tthis._delegate = null;\n\t}\n\n\tpublic prepareUndoRedo(): Promise | IDisposable | void {\n\t\tif (this._delegate) {\n\t\t\treturn this._delegate.prepareUndoRedo(this);\n\t\t}\n\t}\n\n\tpublic matchesResource(resource: URI): boolean {\n\t\tconst key = uriGetComparisonKey(resource);\n\t\treturn (this._editStackElementsMap.has(key));\n\t}\n\n\tpublic setModel(model: ITextModel | URI): void {\n\t\tconst key = uriGetComparisonKey(URI.isUri(model) ? model : model.uri);\n\t\tif (this._editStackElementsMap.has(key)) {\n\t\t\tthis._editStackElementsMap.get(key)!.setModel(model);\n\t\t}\n\t}\n\n\tpublic canAppend(model: ITextModel): boolean {\n\t\tif (!this._isOpen) {\n\t\t\treturn false;\n\t\t}\n\t\tconst key = uriGetComparisonKey(model.uri);\n\t\tif (this._editStackElementsMap.has(key)) {\n\t\t\tconst editStackElement = this._editStackElementsMap.get(key)!;\n\t\t\treturn editStackElement.canAppend(model);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic append(model: ITextModel, textChanges: TextChange[], afterEOL: EndOfLineSequence, afterVersionId: number, afterCursorState: Selection[] | null): void {\n\t\tconst key = uriGetComparisonKey(model.uri);\n\t\tconst editStackElement = this._editStackElementsMap.get(key)!;\n\t\teditStackElement.append(model, textChanges, afterEOL, afterVersionId, afterCursorState);\n\t}\n\n\tpublic close(): void {\n\t\tthis._isOpen = false;\n\t}\n\n\tpublic open(): void {\n\t\t// cannot reopen\n\t}\n\n\tpublic undo(): void {\n\t\tthis._isOpen = false;\n\n\t\tfor (const editStackElement of this._editStackElementsArr) {\n\t\t\teditStackElement.undo();\n\t\t}\n\t}\n\n\tpublic redo(): void {\n\t\tfor (const editStackElement of this._editStackElementsArr) {\n\t\t\teditStackElement.redo();\n\t\t}\n\t}\n\n\tpublic heapSize(resource: URI): number {\n\t\tconst key = uriGetComparisonKey(resource);\n\t\tif (this._editStackElementsMap.has(key)) {\n\t\t\tconst editStackElement = this._editStackElementsMap.get(key)!;\n\t\t\treturn editStackElement.heapSize();\n\t\t}\n\t\treturn 0;\n\t}\n\n\tpublic split(): IResourceUndoRedoElement[] {\n\t\treturn this._editStackElementsArr;\n\t}\n\n\tpublic toString(): string {\n\t\tlet result: string[] = [];\n\t\tfor (const editStackElement of this._editStackElementsArr) {\n\t\t\tresult.push(`${basename(editStackElement.resource)}: ${editStackElement}`);\n\t\t}\n\t\treturn `{${result.join(', ')}}`;\n\t}\n}\n\nexport type EditStackElement = SingleModelEditStackElement | MultiModelEditStackElement;\n\nfunction getModelEOL(model: ITextModel): EndOfLineSequence {\n\tconst eol = model.getEOL();\n\tif (eol === '\\n') {\n\t\treturn EndOfLineSequence.LF;\n\t} else {\n\t\treturn EndOfLineSequence.CRLF;\n\t}\n}\n\nexport function isEditStackElement(element: IResourceUndoRedoElement | IWorkspaceUndoRedoElement | null): element is EditStackElement {\n\tif (!element) {\n\t\treturn false;\n\t}\n\treturn ((element instanceof SingleModelEditStackElement) || (element instanceof MultiModelEditStackElement));\n}\n\nexport class EditStack {\n\n\tprivate readonly _model: TextModel;\n\tprivate readonly _undoRedoService: IUndoRedoService;\n\n\tconstructor(model: TextModel, undoRedoService: IUndoRedoService) {\n\t\tthis._model = model;\n\t\tthis._undoRedoService = undoRedoService;\n\t}\n\n\tpublic pushStackElement(): void {\n\t\tconst lastElement = this._undoRedoService.getLastElement(this._model.uri);\n\t\tif (isEditStackElement(lastElement)) {\n\t\t\tlastElement.close();\n\t\t}\n\t}\n\n\tpublic popStackElement(): void {\n\t\tconst lastElement = this._undoRedoService.getLastElement(this._model.uri);\n\t\tif (isEditStackElement(lastElement)) {\n\t\t\tlastElement.open();\n\t\t}\n\t}\n\n\tpublic clear(): void {\n\t\tthis._undoRedoService.removeElements(this._model.uri);\n\t}\n\n\tprivate _getOrCreateEditStackElement(beforeCursorState: Selection[] | null): EditStackElement {\n\t\tconst lastElement = this._undoRedoService.getLastElement(this._model.uri);\n\t\tif (isEditStackElement(lastElement) && lastElement.canAppend(this._model)) {\n\t\t\treturn lastElement;\n\t\t}\n\t\tconst newElement = new SingleModelEditStackElement(this._model, beforeCursorState);\n\t\tthis._undoRedoService.pushElement(newElement);\n\t\treturn newElement;\n\t}\n\n\tpublic pushEOL(eol: EndOfLineSequence): void {\n\t\tconst editStackElement = this._getOrCreateEditStackElement(null);\n\t\tthis._model.setEOL(eol);\n\t\teditStackElement.append(this._model, [], getModelEOL(this._model), this._model.getAlternativeVersionId(), null);\n\t}\n\n\tpublic pushEditOperation(beforeCursorState: Selection[] | null, editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer | null): Selection[] | null {\n\t\tconst editStackElement = this._getOrCreateEditStackElement(beforeCursorState);\n\t\tconst inverseEditOperations = this._model.applyEdits(editOperations, true);\n\t\tconst afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperations);\n\t\tconst textChanges = inverseEditOperations.map((op, index) => ({ index: index, textChange: op.textChange }));\n\t\ttextChanges.sort((a, b) => {\n\t\t\tif (a.textChange.oldPosition === b.textChange.oldPosition) {\n\t\t\t\treturn a.index - b.index;\n\t\t\t}\n\t\t\treturn a.textChange.oldPosition - b.textChange.oldPosition;\n\t\t});\n\t\teditStackElement.append(this._model, textChanges.map(op => op.textChange), getModelEOL(this._model), this._model.getAlternativeVersionId(), afterCursorState);\n\t\treturn afterCursorState;\n\t}\n\n\tprivate static _computeCursorState(cursorStateComputer: ICursorStateComputer | null, inverseEditOperations: IValidEditOperation[]): Selection[] | null {\n\t\ttry {\n\t\t\treturn cursorStateComputer ? cursorStateComputer(inverseEditOperations) : null;\n\t\t} catch (e) {\n\t\t\tonUnexpectedError(e);\n\t\t\treturn null;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as nls from 'vs/nls';\n\nexport namespace AccessibilityHelpNLS {\n\texport const noSelection = nls.localize(\"noSelection\", \"No selection\");\n\texport const singleSelectionRange = nls.localize(\"singleSelectionRange\", \"Line {0}, Column {1} ({2} selected)\");\n\texport const singleSelection = nls.localize(\"singleSelection\", \"Line {0}, Column {1}\");\n\texport const multiSelectionRange = nls.localize(\"multiSelectionRange\", \"{0} selections ({1} characters selected)\");\n\texport const multiSelection = nls.localize(\"multiSelection\", \"{0} selections\");\n\texport const emergencyConfOn = nls.localize(\"emergencyConfOn\", \"Now changing the setting `accessibilitySupport` to 'on'.\");\n\texport const openingDocs = nls.localize(\"openingDocs\", \"Now opening the Editor Accessibility documentation page.\");\n\texport const readonlyDiffEditor = nls.localize(\"readonlyDiffEditor\", \" in a read-only pane of a diff editor.\");\n\texport const editableDiffEditor = nls.localize(\"editableDiffEditor\", \" in a pane of a diff editor.\");\n\texport const readonlyEditor = nls.localize(\"readonlyEditor\", \" in a read-only code editor\");\n\texport const editableEditor = nls.localize(\"editableEditor\", \" in a code editor\");\n\texport const changeConfigToOnMac = nls.localize(\"changeConfigToOnMac\", \"To configure the editor to be optimized for usage with a Screen Reader press Command+E now.\");\n\texport const changeConfigToOnWinLinux = nls.localize(\"changeConfigToOnWinLinux\", \"To configure the editor to be optimized for usage with a Screen Reader press Control+E now.\");\n\texport const auto_on = nls.localize(\"auto_on\", \"The editor is configured to be optimized for usage with a Screen Reader.\");\n\texport const auto_off = nls.localize(\"auto_off\", \"The editor is configured to never be optimized for usage with a Screen Reader, which is not the case at this time.\");\n\texport const tabFocusModeOnMsg = nls.localize(\"tabFocusModeOnMsg\", \"Pressing Tab in the current editor will move focus to the next focusable element. Toggle this behavior by pressing {0}.\");\n\texport const tabFocusModeOnMsgNoKb = nls.localize(\"tabFocusModeOnMsgNoKb\", \"Pressing Tab in the current editor will move focus to the next focusable element. The command {0} is currently not triggerable by a keybinding.\");\n\texport const tabFocusModeOffMsg = nls.localize(\"tabFocusModeOffMsg\", \"Pressing Tab in the current editor will insert the tab character. Toggle this behavior by pressing {0}.\");\n\texport const tabFocusModeOffMsgNoKb = nls.localize(\"tabFocusModeOffMsgNoKb\", \"Pressing Tab in the current editor will insert the tab character. The command {0} is currently not triggerable by a keybinding.\");\n\texport const openDocMac = nls.localize(\"openDocMac\", \"Press Command+H now to open a browser window with more information related to editor accessibility.\");\n\texport const openDocWinLinux = nls.localize(\"openDocWinLinux\", \"Press Control+H now to open a browser window with more information related to editor accessibility.\");\n\texport const outroMsg = nls.localize(\"outroMsg\", \"You can dismiss this tooltip and return to the editor by pressing Escape or Shift+Escape.\");\n\texport const showAccessibilityHelpAction = nls.localize(\"showAccessibilityHelpAction\", \"Show Accessibility Help\");\n}\n\nexport namespace InspectTokensNLS {\n\texport const inspectTokensAction = nls.localize('inspectTokens', \"Developer: Inspect Tokens\");\n}\n\nexport namespace GoToLineNLS {\n\texport const gotoLineActionLabel = nls.localize('gotoLineActionLabel', \"Go to Line/Column...\");\n}\n\nexport namespace QuickHelpNLS {\n\texport const helpQuickAccessActionLabel = nls.localize('helpQuickAccess', \"Show all Quick Access Providers\");\n}\n\nexport namespace QuickCommandNLS {\n\texport const quickCommandActionLabel = nls.localize('quickCommandActionLabel', \"Command Palette\");\n\texport const quickCommandHelp = nls.localize('quickCommandActionHelp', \"Show And Run Commands\");\n}\n\nexport namespace QuickOutlineNLS {\n\texport const quickOutlineActionLabel = nls.localize('quickOutlineActionLabel', \"Go to Symbol...\");\n\texport const quickOutlineByCategoryActionLabel = nls.localize('quickOutlineByCategoryActionLabel', \"Go to Symbol by Category...\");\n}\n\nexport namespace StandaloneCodeEditorNLS {\n\texport const editorViewAccessibleLabel = nls.localize('editorViewAccessibleLabel', \"Editor content\");\n\texport const accessibilityHelpMessage = nls.localize('accessibilityHelpMessage', \"Press Alt+F1 for Accessibility Options.\");\n}\n\nexport namespace ToggleHighContrastNLS {\n\texport const toggleHighContrast = nls.localize('toggleHighContrast', \"Toggle High Contrast Theme\");\n}\n\nexport namespace StandaloneServicesNLS {\n\texport const bulkEditServiceSummary = nls.localize('bulkEditServiceSummary', \"Made {0} edits in {1} files\");\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { IMatch } from 'vs/base/common/filters';\nimport { defaultGenerator } from 'vs/base/common/idGenerator';\nimport { dispose, IDisposable, IReference } from 'vs/base/common/lifecycle';\nimport { ResourceMap } from 'vs/base/common/map';\nimport { basename, extUri } from 'vs/base/common/resources';\nimport * as strings from 'vs/base/common/strings';\nimport { Constants } from 'vs/base/common/uint';\nimport { URI } from 'vs/base/common/uri';\nimport { Position } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { Location, LocationLink } from 'vs/editor/common/languages';\nimport { ITextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService';\nimport { localize } from 'vs/nls';\n\nexport class OneReference {\n\n\treadonly id: string = defaultGenerator.nextId();\n\n\tprivate _range?: IRange;\n\n\tconstructor(\n\t\treadonly isProviderFirst: boolean,\n\t\treadonly parent: FileReferences,\n\t\treadonly link: LocationLink,\n\t\tprivate _rangeCallback: (ref: OneReference) => void\n\t) { }\n\n\tget uri() {\n\t\treturn this.link.uri;\n\t}\n\n\tget range(): IRange {\n\t\treturn this._range ?? this.link.targetSelectionRange ?? this.link.range;\n\t}\n\n\tset range(value: IRange) {\n\t\tthis._range = value;\n\t\tthis._rangeCallback(this);\n\t}\n\n\tget ariaMessage(): string {\n\n\t\tconst preview = this.parent.getPreview(this)?.preview(this.range);\n\n\t\tif (!preview) {\n\t\t\treturn localize(\n\t\t\t\t'aria.oneReference', \"symbol in {0} on line {1} at column {2}\",\n\t\t\t\tbasename(this.uri), this.range.startLineNumber, this.range.startColumn\n\t\t\t);\n\t\t} else {\n\t\t\treturn localize(\n\t\t\t\t{ key: 'aria.oneReference.preview', comment: ['Placeholders are: 0: filename, 1:line number, 2: column number, 3: preview snippet of source code'] }, \"symbol in {0} on line {1} at column {2}, {3}\",\n\t\t\t\tbasename(this.uri), this.range.startLineNumber, this.range.startColumn, preview.value\n\t\t\t);\n\t\t}\n\t}\n}\n\nexport class FilePreview implements IDisposable {\n\n\tconstructor(\n\t\tprivate readonly _modelReference: IReference\n\t) { }\n\n\tdispose(): void {\n\t\tthis._modelReference.dispose();\n\t}\n\n\tpreview(range: IRange, n: number = 8): { value: string; highlight: IMatch } | undefined {\n\t\tconst model = this._modelReference.object.textEditorModel;\n\n\t\tif (!model) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst { startLineNumber, startColumn, endLineNumber, endColumn } = range;\n\t\tconst word = model.getWordUntilPosition({ lineNumber: startLineNumber, column: startColumn - n });\n\t\tconst beforeRange = new Range(startLineNumber, word.startColumn, startLineNumber, startColumn);\n\t\tconst afterRange = new Range(endLineNumber, endColumn, endLineNumber, Constants.MAX_SAFE_SMALL_INTEGER);\n\n\t\tconst before = model.getValueInRange(beforeRange).replace(/^\\s+/, '');\n\t\tconst inside = model.getValueInRange(range);\n\t\tconst after = model.getValueInRange(afterRange).replace(/\\s+$/, '');\n\n\t\treturn {\n\t\t\tvalue: before + inside + after,\n\t\t\thighlight: { start: before.length, end: before.length + inside.length }\n\t\t};\n\t}\n}\n\nexport class FileReferences implements IDisposable {\n\n\treadonly children: OneReference[] = [];\n\n\tprivate _previews = new ResourceMap();\n\n\tconstructor(\n\t\treadonly parent: ReferencesModel,\n\t\treadonly uri: URI\n\t) { }\n\n\tdispose(): void {\n\t\tdispose(this._previews.values());\n\t\tthis._previews.clear();\n\t}\n\n\tgetPreview(child: OneReference): FilePreview | undefined {\n\t\treturn this._previews.get(child.uri);\n\t}\n\n\tget ariaMessage(): string {\n\t\tconst len = this.children.length;\n\t\tif (len === 1) {\n\t\t\treturn localize('aria.fileReferences.1', \"1 symbol in {0}, full path {1}\", basename(this.uri), this.uri.fsPath);\n\t\t} else {\n\t\t\treturn localize('aria.fileReferences.N', \"{0} symbols in {1}, full path {2}\", len, basename(this.uri), this.uri.fsPath);\n\t\t}\n\t}\n\n\tasync resolve(textModelResolverService: ITextModelService): Promise {\n\t\tif (this._previews.size !== 0) {\n\t\t\treturn this;\n\t\t}\n\t\tfor (let child of this.children) {\n\t\t\tif (this._previews.has(child.uri)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst ref = await textModelResolverService.createModelReference(child.uri);\n\t\t\t\tthis._previews.set(child.uri, new FilePreview(ref));\n\t\t\t} catch (err) {\n\t\t\t\tonUnexpectedError(err);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n}\n\nexport class ReferencesModel implements IDisposable {\n\n\tprivate readonly _links: LocationLink[];\n\tprivate readonly _title: string;\n\n\treadonly groups: FileReferences[] = [];\n\treadonly references: OneReference[] = [];\n\n\treadonly _onDidChangeReferenceRange = new Emitter();\n\treadonly onDidChangeReferenceRange: Event = this._onDidChangeReferenceRange.event;\n\n\tconstructor(links: LocationLink[], title: string) {\n\t\tthis._links = links;\n\t\tthis._title = title;\n\n\t\t// grouping and sorting\n\t\tconst [providersFirst] = links;\n\t\tlinks.sort(ReferencesModel._compareReferences);\n\n\t\tlet current: FileReferences | undefined;\n\t\tfor (let link of links) {\n\t\t\tif (!current || !extUri.isEqual(current.uri, link.uri, true)) {\n\t\t\t\t// new group\n\t\t\t\tcurrent = new FileReferences(this, link.uri);\n\t\t\t\tthis.groups.push(current);\n\t\t\t}\n\n\t\t\t// append, check for equality first!\n\t\t\tif (current.children.length === 0 || ReferencesModel._compareReferences(link, current.children[current.children.length - 1]) !== 0) {\n\n\t\t\t\tconst oneRef = new OneReference(\n\t\t\t\t\tprovidersFirst === link,\n\t\t\t\t\tcurrent,\n\t\t\t\t\tlink,\n\t\t\t\t\tref => this._onDidChangeReferenceRange.fire(ref)\n\t\t\t\t);\n\t\t\t\tthis.references.push(oneRef);\n\t\t\t\tcurrent.children.push(oneRef);\n\t\t\t}\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tdispose(this.groups);\n\t\tthis._onDidChangeReferenceRange.dispose();\n\t\tthis.groups.length = 0;\n\t}\n\n\tclone(): ReferencesModel {\n\t\treturn new ReferencesModel(this._links, this._title);\n\t}\n\n\tget title(): string {\n\t\treturn this._title;\n\t}\n\n\tget isEmpty(): boolean {\n\t\treturn this.groups.length === 0;\n\t}\n\n\tget ariaMessage(): string {\n\t\tif (this.isEmpty) {\n\t\t\treturn localize('aria.result.0', \"No results found\");\n\t\t} else if (this.references.length === 1) {\n\t\t\treturn localize('aria.result.1', \"Found 1 symbol in {0}\", this.references[0].uri.fsPath);\n\t\t} else if (this.groups.length === 1) {\n\t\t\treturn localize('aria.result.n1', \"Found {0} symbols in {1}\", this.references.length, this.groups[0].uri.fsPath);\n\t\t} else {\n\t\t\treturn localize('aria.result.nm', \"Found {0} symbols in {1} files\", this.references.length, this.groups.length);\n\t\t}\n\t}\n\n\tnextOrPreviousReference(reference: OneReference, next: boolean): OneReference {\n\n\t\tlet { parent } = reference;\n\n\t\tlet idx = parent.children.indexOf(reference);\n\t\tlet childCount = parent.children.length;\n\t\tlet groupCount = parent.parent.groups.length;\n\n\t\tif (groupCount === 1 || next && idx + 1 < childCount || !next && idx > 0) {\n\t\t\t// cycling within one file\n\t\t\tif (next) {\n\t\t\t\tidx = (idx + 1) % childCount;\n\t\t\t} else {\n\t\t\t\tidx = (idx + childCount - 1) % childCount;\n\t\t\t}\n\t\t\treturn parent.children[idx];\n\t\t}\n\n\t\tidx = parent.parent.groups.indexOf(parent);\n\t\tif (next) {\n\t\t\tidx = (idx + 1) % groupCount;\n\t\t\treturn parent.parent.groups[idx].children[0];\n\t\t} else {\n\t\t\tidx = (idx + groupCount - 1) % groupCount;\n\t\t\treturn parent.parent.groups[idx].children[parent.parent.groups[idx].children.length - 1];\n\t\t}\n\t}\n\n\tnearestReference(resource: URI, position: Position): OneReference | undefined {\n\n\t\tconst nearest = this.references.map((ref, idx) => {\n\t\t\treturn {\n\t\t\t\tidx,\n\t\t\t\tprefixLen: strings.commonPrefixLength(ref.uri.toString(), resource.toString()),\n\t\t\t\toffsetDist: Math.abs(ref.range.startLineNumber - position.lineNumber) * 100 + Math.abs(ref.range.startColumn - position.column)\n\t\t\t};\n\t\t}).sort((a, b) => {\n\t\t\tif (a.prefixLen > b.prefixLen) {\n\t\t\t\treturn -1;\n\t\t\t} else if (a.prefixLen < b.prefixLen) {\n\t\t\t\treturn 1;\n\t\t\t} else if (a.offsetDist < b.offsetDist) {\n\t\t\t\treturn -1;\n\t\t\t} else if (a.offsetDist > b.offsetDist) {\n\t\t\t\treturn 1;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t})[0];\n\n\t\tif (nearest) {\n\t\t\treturn this.references[nearest.idx];\n\t\t}\n\t\treturn undefined;\n\t}\n\n\treferenceAt(resource: URI, position: Position): OneReference | undefined {\n\t\tfor (const ref of this.references) {\n\t\t\tif (ref.uri.toString() === resource.toString()) {\n\t\t\t\tif (Range.containsPosition(ref.range, position)) {\n\t\t\t\t\treturn ref;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tfirstReference(): OneReference | undefined {\n\t\tfor (const ref of this.references) {\n\t\t\tif (ref.isProviderFirst) {\n\t\t\t\treturn ref;\n\t\t\t}\n\t\t}\n\t\treturn this.references[0];\n\t}\n\n\tprivate static _compareReferences(a: Location, b: Location): number {\n\t\treturn extUri.compare(a.uri, b.uri) || Range.compareRangesUsingStarts(a.range, b.range);\n\t}\n}\n","\nimport { URI } from 'vs/base/common/uri';\n\nexport interface IEditorModel {\n\n\t/**\n\t * Dispose associated resources\n\t */\n\tdispose(): void;\n}\n\nexport interface IBaseUntypedEditorInput {\n}\n\nexport interface IBaseResourceEditorInput extends IBaseUntypedEditorInput {\n}\n\nexport interface IBaseTextResourceEditorInput extends IBaseResourceEditorInput {\n}\n\nexport interface IResourceEditorInput extends IBaseResourceEditorInput {\n\n\t/**\n\t * The resource URI of the resource to open.\n\t */\n\treadonly resource: URI;\n}\n\nexport interface ITextResourceEditorInput extends IResourceEditorInput, IBaseTextResourceEditorInput {\n\n\t/**\n\t * Optional options to use when opening the text input.\n\t */\n\toptions?: ITextEditorOptions;\n}\n\nexport enum EditorOpenContext {\n\n\t/**\n\t * Default: the editor is opening via a programmatic call\n\t * to the editor service API.\n\t */\n\tAPI,\n\n\t/**\n\t * Indicates that a user action triggered the opening, e.g.\n\t * via mouse or keyboard use.\n\t */\n\tUSER\n}\n\nexport interface IEditorOptions {\n\n\t/**\n\t * Tells the editor to not receive keyboard focus when the editor is being opened.\n\t *\n\t * Will also not activate the group the editor opens in unless the group is already\n\t * the active one. This behaviour can be overridden via the `activation` option.\n\t */\n\tpreserveFocus?: boolean;\n\n\t/**\n\t * Will reveal the editor if it is already opened and visible in any of the opened editor groups.\n\t *\n\t * Note that this option is just a hint that might be ignored if the user wants to open an editor explicitly\n\t * to the side of another one or into a specific editor group.\n\t */\n\trevealIfVisible?: boolean;\n\n\t/**\n\t * Will reveal the editor if it is already opened (even when not visible) in any of the opened editor groups.\n\t *\n\t * Note that this option is just a hint that might be ignored if the user wants to open an editor explicitly\n\t * to the side of another one or into a specific editor group.\n\t */\n\trevealIfOpened?: boolean;\n\n\t/**\n\t * An editor that is pinned remains in the editor stack even when another editor is being opened.\n\t * An editor that is not pinned will always get replaced by another editor that is not pinned.\n\t */\n\tpinned?: boolean;\n\n\t/**\n\t * A optional hint to signal in which context the editor opens.\n\t *\n\t * If configured to be `EditorOpenContext.USER`, this hint can be\n\t * used in various places to control the experience. For example,\n\t * if the editor to open fails with an error, a notification could\n\t * inform about this in a modal dialog. If the editor opened through\n\t * some background task, the notification would show in the background,\n\t * not as a modal dialog.\n\t */\n\tcontext?: EditorOpenContext;\n}\n\nexport interface ITextEditorSelection {\n\treadonly startLineNumber: number;\n\treadonly startColumn: number;\n}\n\nexport const enum TextEditorSelectionRevealType {\n\t/**\n\t * Option to scroll vertically or horizontally as necessary and reveal a range centered vertically.\n\t */\n\tCenter = 0,\n\n\t/**\n\t * Option to scroll vertically or horizontally as necessary and reveal a range centered vertically only if it lies outside the viewport.\n\t */\n\tCenterIfOutsideViewport = 1,\n\n\t/**\n\t * Option to scroll vertically or horizontally as necessary and reveal a range close to the top of the viewport, but not quite at the top.\n\t */\n\tNearTop = 2,\n\n\t/**\n\t * Option to scroll vertically or horizontally as necessary and reveal a range close to the top of the viewport, but not quite at the top.\n\t * Only if it lies outside the viewport\n\t */\n\tNearTopIfOutsideViewport = 3,\n}\n\nexport interface ITextEditorOptions extends IEditorOptions {\n\n\t/**\n\t * Text editor selection.\n\t */\n\tselection?: ITextEditorSelection;\n\n\t/**\n\t * Option to control the text editor selection reveal type.\n\t * Defaults to TextEditorSelectionRevealType.Center\n\t */\n\tselectionRevealType?: TextEditorSelectionRevealType;\n}\n","\n\n/**\n * **!Do not construct directly!**\n *\n * **!Only static methods because it gets serialized!**\n *\n * This represents the \"canonical\" version for an extension identifier. Extension ids\n * have to be case-insensitive (due to the marketplace), but we must ensure case\n * preservation because the extension API is already public at this time.\n *\n * For example, given an extension with the publisher `\"Hello\"` and the name `\"World\"`,\n * its canonical extension identifier is `\"Hello.World\"`. This extension could be\n * referenced in some other extension's dependencies using the string `\"hello.world\"`.\n *\n * To make matters more complicated, an extension can optionally have an UUID. When two\n * extensions have the same UUID, they are considered equal even if their identifier is different.\n */\nexport class ExtensionIdentifier {\n\tpublic readonly value: string;\n\tprivate readonly _lower: string;\n\n\tconstructor(value: string) {\n\t\tthis.value = value;\n\t\tthis._lower = value.toLowerCase();\n\t}\n\n\t/**\n\t * Gives the value by which to index (for equality).\n\t */\n\tpublic static toKey(id: ExtensionIdentifier | string): string {\n\t\tif (typeof id === 'string') {\n\t\t\treturn id.toLowerCase();\n\t\t}\n\t\treturn id._lower;\n\t}\n}\n","\n\n//#endregion\n\n//#region Utilities\n\nexport enum FileKind {\n\tFILE,\n\tFOLDER,\n\tROOT_FOLDER\n}\n\n//#endregion\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';\n\nexport function showHistoryKeybindingHint(keybindingService: IKeybindingService): boolean {\n\treturn keybindingService.lookupKeybinding('history.showPrevious')?.getElectronAccelerator() === 'Up' && keybindingService.lookupKeybinding('history.showNext')?.getElectronAccelerator() === 'Down';\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport class SyncDescriptor {\n\n\treadonly ctor: any;\n\treadonly staticArguments: any[];\n\treadonly supportsDelayedInstantiation: boolean;\n\n\tconstructor(ctor: new (...args: any[]) => T, staticArguments: any[] = [], supportsDelayedInstantiation: boolean = false) {\n\t\tthis.ctor = ctor;\n\t\tthis.staticArguments = staticArguments;\n\t\tthis.supportsDelayedInstantiation = supportsDelayedInstantiation;\n\t}\n}\n\nexport interface SyncDescriptor0 {\n\tctor: any;\n\tbind(): SyncDescriptor0;\n}\nexport interface SyncDescriptor1 {\n\tctor: any;\n\tbind(a1: A1): SyncDescriptor0;\n}\nexport interface SyncDescriptor2 {\n\tctor: any;\n\tbind(a1: A1): SyncDescriptor1;\n\tbind(a1: A1, a2: A2): SyncDescriptor0;\n}\nexport interface SyncDescriptor3 {\n\tctor: any;\n\tbind(a1: A1): SyncDescriptor2;\n\tbind(a1: A1, a2: A2): SyncDescriptor1;\n\tbind(a1: A1, a2: A2, a3: A3): SyncDescriptor0;\n}\nexport interface SyncDescriptor4 {\n\tctor: any;\n\tbind(a1: A1): SyncDescriptor3;\n\tbind(a1: A1, a2: A2): SyncDescriptor2;\n\tbind(a1: A1, a2: A2, a3: A3): SyncDescriptor1;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4): SyncDescriptor0;\n}\nexport interface SyncDescriptor5 {\n\tctor: any;\n\tbind(a1: A1): SyncDescriptor4;\n\tbind(a1: A1, a2: A2): SyncDescriptor3;\n\tbind(a1: A1, a2: A2, a3: A3): SyncDescriptor2;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4): SyncDescriptor1;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4, a5: A5): SyncDescriptor0;\n}\nexport interface SyncDescriptor6 {\n\tctor: any;\n\tbind(a1: A1): SyncDescriptor5;\n\tbind(a1: A1, a2: A2): SyncDescriptor4;\n\tbind(a1: A1, a2: A2, a3: A3): SyncDescriptor3;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4): SyncDescriptor2;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4, a5: A5): SyncDescriptor1;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6): SyncDescriptor0;\n}\nexport interface SyncDescriptor7 {\n\tctor: any;\n\tbind(a1: A1): SyncDescriptor6;\n\tbind(a1: A1, a2: A2): SyncDescriptor5;\n\tbind(a1: A1, a2: A2, a3: A3): SyncDescriptor4;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4): SyncDescriptor3;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4, a5: A5): SyncDescriptor2;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6): SyncDescriptor1;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7): SyncDescriptor0;\n}\nexport interface SyncDescriptor8 {\n\tctor: any;\n\tbind(a1: A1): SyncDescriptor7;\n\tbind(a1: A1, a2: A2): SyncDescriptor6;\n\tbind(a1: A1, a2: A2, a3: A3): SyncDescriptor5;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4): SyncDescriptor4;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4, a5: A5): SyncDescriptor3;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6): SyncDescriptor2;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7): SyncDescriptor1;\n\tbind(a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7, a8: A8): SyncDescriptor0;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { SyncDescriptor } from './descriptors';\nimport { BrandedService, ServiceIdentifier } from './instantiation';\n\nconst _registry: [ServiceIdentifier, SyncDescriptor][] = [];\n\nexport function registerSingleton(id: ServiceIdentifier, ctor: new (...services: Services) => T, supportsDelayedInstantiation?: boolean): void;\nexport function registerSingleton(id: ServiceIdentifier, descriptor: SyncDescriptor): void;\nexport function registerSingleton(id: ServiceIdentifier, ctorOrDescriptor: { new(...services: Services): T } | SyncDescriptor, supportsDelayedInstantiation?: boolean): void {\n\tif (!(ctorOrDescriptor instanceof SyncDescriptor)) {\n\t\tctorOrDescriptor = new SyncDescriptor(ctorOrDescriptor as new (...args: any[]) => T, [], supportsDelayedInstantiation);\n\t}\n\n\t_registry.push([id, ctorOrDescriptor]);\n}\n\nexport function getSingletonServiceDescriptors(): [ServiceIdentifier, SyncDescriptor][] {\n\treturn _registry;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport class Node {\n\n\treadonly data: T;\n\treadonly incoming = new Map>();\n\treadonly outgoing = new Map>();\n\n\tconstructor(data: T) {\n\t\tthis.data = data;\n\t}\n}\n\nexport class Graph {\n\n\tprivate readonly _nodes = new Map>();\n\n\tconstructor(private readonly _hashFn: (element: T) => string) {\n\t\t// empty\n\t}\n\n\troots(): Node[] {\n\t\tconst ret: Node[] = [];\n\t\tfor (let node of this._nodes.values()) {\n\t\t\tif (node.outgoing.size === 0) {\n\t\t\t\tret.push(node);\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t}\n\n\tinsertEdge(from: T, to: T): void {\n\t\tconst fromNode = this.lookupOrInsertNode(from);\n\t\tconst toNode = this.lookupOrInsertNode(to);\n\n\t\tfromNode.outgoing.set(this._hashFn(to), toNode);\n\t\ttoNode.incoming.set(this._hashFn(from), fromNode);\n\t}\n\n\tremoveNode(data: T): void {\n\t\tconst key = this._hashFn(data);\n\t\tthis._nodes.delete(key);\n\t\tfor (let node of this._nodes.values()) {\n\t\t\tnode.outgoing.delete(key);\n\t\t\tnode.incoming.delete(key);\n\t\t}\n\t}\n\n\tlookupOrInsertNode(data: T): Node {\n\t\tconst key = this._hashFn(data);\n\t\tlet node = this._nodes.get(key);\n\n\t\tif (!node) {\n\t\t\tnode = new Node(data);\n\t\t\tthis._nodes.set(key, node);\n\t\t}\n\n\t\treturn node;\n\t}\n\n\tisEmpty(): boolean {\n\t\treturn this._nodes.size === 0;\n\t}\n\n\ttoString(): string {\n\t\tlet data: string[] = [];\n\t\tfor (let [key, value] of this._nodes) {\n\t\t\tdata.push(`${key}, (incoming)[${[...value.incoming.keys()].join(', ')}], (outgoing)[${[...value.outgoing.keys()].join(',')}]`);\n\n\t\t}\n\t\treturn data.join('\\n');\n\t}\n\n\t/**\n\t * This is brute force and slow and **only** be used\n\t * to trouble shoot.\n\t */\n\tfindCycleSlow() {\n\t\tfor (let [id, node] of this._nodes) {\n\t\t\tconst seen = new Set([id]);\n\t\t\tconst res = this._findCycle(node, seen);\n\t\t\tif (res) {\n\t\t\t\treturn res;\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate _findCycle(node: Node, seen: Set): string | undefined {\n\t\tfor (let [id, outgoing] of node.outgoing) {\n\t\t\tif (seen.has(id)) {\n\t\t\t\treturn [...seen, id].join(' -> ');\n\t\t\t}\n\t\t\tseen.add(id);\n\t\t\tconst value = this._findCycle(outgoing, seen);\n\t\t\tif (value) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\tseen.delete(id);\n\t\t}\n\t\treturn undefined;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as descriptors from './descriptors';\nimport { ServiceCollection } from './serviceCollection';\n\n// ------ internal util\n\nexport namespace _util {\n\n\texport const serviceIds = new Map>();\n\n\texport const DI_TARGET = '$di$target';\n\texport const DI_DEPENDENCIES = '$di$dependencies';\n\n\texport function getServiceDependencies(ctor: any): { id: ServiceIdentifier, index: number, optional: boolean }[] {\n\t\treturn ctor[DI_DEPENDENCIES] || [];\n\t}\n}\n\n// --- interfaces ------\n\nexport type BrandedService = { _serviceBrand: undefined };\n\nexport interface IConstructorSignature1 {\n\tnew (first: A1, ...services: Services): T;\n}\n\nexport interface ServicesAccessor {\n\tget(id: ServiceIdentifier): T;\n}\n\nexport const IInstantiationService = createDecorator('instantiationService');\n\n/**\n * Given a list of arguments as a tuple, attempt to extract the leading, non-service arguments\n * to their own tuple.\n */\ntype GetLeadingNonServiceArgs =\n\tArgs extends [...BrandedService[]] ? []\n\t: Args extends [infer A1, ...BrandedService[]] ? [A1]\n\t: Args extends [infer A1, infer A2, ...BrandedService[]] ? [A1, A2]\n\t: Args extends [infer A1, infer A2, infer A3, ...BrandedService[]] ? [A1, A2, A3]\n\t: Args extends [infer A1, infer A2, infer A3, infer A4, ...BrandedService[]] ? [A1, A2, A3, A4]\n\t: Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, ...BrandedService[]] ? [A1, A2, A3, A4, A5]\n\t: Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, ...BrandedService[]] ? [A1, A2, A3, A4, A5, A6]\n\t: Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7, ...BrandedService[]] ? [A1, A2, A3, A4, A5, A6, A7]\n\t: Args extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7, infer A8, ...BrandedService[]] ? [A1, A2, A3, A4, A5, A6, A7, A8]\n\t: never;\n\nexport interface IInstantiationService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Synchronously creates an instance that is denoted by\n\t * the descriptor\n\t */\n\tcreateInstance(descriptor: descriptors.SyncDescriptor0): T;\n\tcreateInstance(descriptor: descriptors.SyncDescriptor1, a1: A1): T;\n\tcreateInstance(descriptor: descriptors.SyncDescriptor2, a1: A1, a2: A2): T;\n\tcreateInstance(descriptor: descriptors.SyncDescriptor3, a1: A1, a2: A2, a3: A3): T;\n\tcreateInstance(descriptor: descriptors.SyncDescriptor4, a1: A1, a2: A2, a3: A3, a4: A4): T;\n\tcreateInstance(descriptor: descriptors.SyncDescriptor5, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5): T;\n\tcreateInstance(descriptor: descriptors.SyncDescriptor6, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6): T;\n\tcreateInstance(descriptor: descriptors.SyncDescriptor7, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7): T;\n\tcreateInstance(descriptor: descriptors.SyncDescriptor8, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7, a8: A8): T;\n\n\tcreateInstance any, R extends InstanceType>(t: Ctor, ...args: GetLeadingNonServiceArgs>): R;\n\n\t/**\n\t *\n\t */\n\tinvokeFunction(fn: (accessor: ServicesAccessor, ...args: TS) => R, ...args: TS): R;\n\n\t/**\n\t * Creates a child of this service which inherts all current services\n\t * and adds/overwrites the given services\n\t */\n\tcreateChild(services: ServiceCollection): IInstantiationService;\n}\n\n\n/**\n * Identifies a service of type T\n */\nexport interface ServiceIdentifier {\n\t(...args: any[]): void;\n\ttype: T;\n}\n\nfunction storeServiceDependency(id: Function, target: Function, index: number, optional: boolean): void {\n\tif ((target as any)[_util.DI_TARGET] === target) {\n\t\t(target as any)[_util.DI_DEPENDENCIES].push({ id, index, optional });\n\t} else {\n\t\t(target as any)[_util.DI_DEPENDENCIES] = [{ id, index, optional }];\n\t\t(target as any)[_util.DI_TARGET] = target;\n\t}\n}\n\n/**\n * The *only* valid way to create a {{ServiceIdentifier}}.\n */\nexport function createDecorator(serviceId: string): ServiceIdentifier {\n\n\tif (_util.serviceIds.has(serviceId)) {\n\t\treturn _util.serviceIds.get(serviceId)!;\n\t}\n\n\tconst id = function (target: Function, key: string, index: number): any {\n\t\tif (arguments.length !== 3) {\n\t\t\tthrow new Error('@IServiceName-decorator can only be used to decorate a parameter');\n\t\t}\n\t\tstoreServiceDependency(id, target, index, false);\n\t};\n\n\tid.toString = () => serviceId;\n\n\t_util.serviceIds.set(serviceId, id);\n\treturn id;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { TextEdit, WorkspaceEdit, WorkspaceEditMetadata, WorkspaceFileEdit, WorkspaceFileEditOptions, WorkspaceTextEdit } from 'vs/editor/common/languages';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { URI } from 'vs/base/common/uri';\nimport { isObject } from 'vs/base/common/types';\n\nexport const IBulkEditService = createDecorator('IWorkspaceEditService');\n\nfunction isWorkspaceFileEdit(thing: any): thing is WorkspaceFileEdit {\n\treturn isObject(thing) && (Boolean((thing).newUri) || Boolean((thing).oldUri));\n}\n\nfunction isWorkspaceTextEdit(thing: any): thing is WorkspaceTextEdit {\n\treturn isObject(thing) && URI.isUri((thing).resource) && isObject((thing).edit);\n}\n\nexport class ResourceEdit {\n\n\tprotected constructor(readonly metadata?: WorkspaceEditMetadata) { }\n\n\tstatic convert(edit: WorkspaceEdit): ResourceEdit[] {\n\n\n\t\treturn edit.edits.map(edit => {\n\t\t\tif (isWorkspaceTextEdit(edit)) {\n\t\t\t\treturn new ResourceTextEdit(edit.resource, edit.edit, edit.modelVersionId, edit.metadata);\n\t\t\t}\n\t\t\tif (isWorkspaceFileEdit(edit)) {\n\t\t\t\treturn new ResourceFileEdit(edit.oldUri, edit.newUri, edit.options, edit.metadata);\n\t\t\t}\n\t\t\tthrow new Error('Unsupported edit');\n\t\t});\n\t}\n}\n\nexport class ResourceTextEdit extends ResourceEdit {\n\tconstructor(\n\t\treadonly resource: URI,\n\t\treadonly textEdit: TextEdit,\n\t\treadonly versionId?: number,\n\t\tmetadata?: WorkspaceEditMetadata\n\t) {\n\t\tsuper(metadata);\n\t}\n}\n\nexport class ResourceFileEdit extends ResourceEdit {\n\tconstructor(\n\t\treadonly oldResource: URI | undefined,\n\t\treadonly newResource: URI | undefined,\n\t\treadonly options?: WorkspaceFileEditOptions,\n\t\tmetadata?: WorkspaceEditMetadata\n\t) {\n\t\tsuper(metadata);\n\t}\n}\n\nexport interface IBulkEditOptions {\n\teditor?: ICodeEditor;\n\tshowPreview?: boolean;\n\tlabel?: string;\n\tquotableLabel?: string;\n}\n\nexport interface IBulkEditResult {\n\tariaSummary: string;\n}\n\nexport interface IBulkEditService {\n\treadonly _serviceBrand: undefined;\n\n\thasPreviewHandler(): boolean;\n\n\tapply(edit: ResourceEdit[], options?: IBulkEditOptions): Promise;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';\nimport { ITextResourceEditorInput } from 'vs/platform/editor/common/editor';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { URI } from 'vs/base/common/uri';\n\nexport const ICodeEditorService = createDecorator('codeEditorService');\n\nexport interface ICodeEditorService {\n\treadonly _serviceBrand: undefined;\n\n\treadonly onCodeEditorAdd: Event;\n\treadonly onCodeEditorRemove: Event;\n\n\treadonly onDiffEditorAdd: Event;\n\treadonly onDiffEditorRemove: Event;\n\n\n\taddCodeEditor(editor: ICodeEditor): void;\n\tremoveCodeEditor(editor: ICodeEditor): void;\n\tlistCodeEditors(): readonly ICodeEditor[];\n\n\taddDiffEditor(editor: IDiffEditor): void;\n\tremoveDiffEditor(editor: IDiffEditor): void;\n\tlistDiffEditors(): readonly IDiffEditor[];\n\n\t/**\n\t * Returns the current focused code editor (if the focus is in the editor or in an editor widget) or null.\n\t */\n\tgetFocusedCodeEditor(): ICodeEditor | null;\n\tremoveDecorationType(key: string): void;\n\n\tsetModelProperty(resource: URI, key: string, value: any): void;\n\tgetModelProperty(resource: URI, key: string): any;\n\n\tgetActiveCodeEditor(): ICodeEditor | null;\n\topenCodeEditor(input: ITextResourceEditorInput, source: ICodeEditor | null, sideBySide?: boolean): Promise;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { URI } from 'vs/base/common/uri';\nimport { IRange } from 'vs/editor/common/core/range';\nimport { IDiffComputationResult } from 'vs/editor/common/diff/diffComputer';\nimport { IInplaceReplaceSupportResult, TextEdit } from 'vs/editor/common/languages';\nimport { UnicodeHighlighterOptions } from 'vs/editor/common/languages/unicodeTextModelHighlighter';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const ID_EDITOR_WORKER_SERVICE = 'editorWorkerService';\nexport const IEditorWorkerService = createDecorator(ID_EDITOR_WORKER_SERVICE);\n\nexport interface IEditorWorkerService {\n\treadonly _serviceBrand: undefined;\n\n\tcanComputeUnicodeHighlights(uri: URI): boolean;\n\tcomputedUnicodeHighlights(uri: URI, options: UnicodeHighlighterOptions, range?: IRange): Promise;\n\n\tcomputeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean, maxComputationTime: number): Promise;\n\n\tcomputeMoreMinimalEdits(resource: URI, edits: TextEdit[] | null | undefined): Promise;\n\n\tcanComputeWordRanges(resource: URI): boolean;\n\tcomputeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] } | null>;\n\n\tcanNavigateValueSet(resource: URI): boolean;\n\tnavigateValueSet(resource: URI, range: IRange, up: boolean): Promise;\n}\n\nexport interface IUnicodeHighlightsResult {\n\tranges: IRange[];\n\thasMore: boolean;\n\tnonBasicAsciiCharacterCount: number;\n\tinvisibleCharacterCount: number;\n\tambiguousCharacterCount: number;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport { URI } from 'vs/base/common/uri';\nimport { ILanguageIdCodec } from 'vs/editor/common/languages';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const ILanguageService = createDecorator('languageService');\n\nexport interface ILanguageExtensionPoint {\n\tid: string;\n\textensions?: string[];\n\tfilenames?: string[];\n\tfilenamePatterns?: string[];\n\tfirstLine?: string;\n\taliases?: string[];\n\tmimetypes?: string[];\n\tconfiguration?: URI;\n\t/**\n\t * @internal\n\t */\n\ticon?: ILanguageIcon;\n}\n\nexport interface ILanguageSelection {\n\treadonly languageId: string;\n\treadonly onDidChange: Event;\n}\n\nexport interface ILanguageIcon {\n}\n\nexport interface ILanguageService {\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * A codec which can encode and decode a string `languageId` as a number.\n\t */\n\treadonly languageIdCodec: ILanguageIdCodec;\n\n\t/**\n\t * An event emitted when a language is needed for the first time.\n\t */\n\tonDidEncounterLanguage: Event;\n\n\t/**\n\t * Check if `languageId` is registered.\n\t */\n\tisRegisteredLanguageId(languageId: string): boolean;\n\n\t/**\n\t * Look up a language by its name case insensitive.\n\t */\n\tgetLanguageIdByLanguageName(languageName: string): string | null;\n\n\t/**\n\t * Look up a language by its mime type.\n\t */\n\tgetLanguageIdByMimeType(mimeType: string | null | undefined): string | null;\n\n\t/**\n\t * Guess the language id for a resource.\n\t */\n\tguessLanguageIdByFilepathOrFirstLine(resource: URI, firstLine?: string): string | null;\n\n\t/**\n\t * Will fall back to 'plaintext' if `languageId` is unknown.\n\t */\n\tcreateById(languageId: string | null | undefined): ILanguageSelection;\n\n\t/**\n\t * Will fall back to 'plaintext' if the `languageId` cannot be determined.\n\t */\n\tcreateByFilepathOrFirstLine(resource: URI | null, firstLine?: string): ILanguageSelection;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IModelDecoration } from 'vs/editor/common/model';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { IMarker } from 'vs/platform/markers/common/markers';\nimport { URI } from 'vs/base/common/uri';\n\nexport const IMarkerDecorationsService = createDecorator('markerDecorationsService');\n\nexport interface IMarkerDecorationsService {\n\treadonly _serviceBrand: undefined;\n\n\tgetMarker(uri: URI, decoration: IModelDecoration): IMarker | null;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport { URI } from 'vs/base/common/uri';\nimport { ITextBufferFactory, ITextModel, ITextModelCreationOptions } from 'vs/editor/common/model';\nimport { ILanguageSelection } from 'vs/editor/common/services/language';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { DocumentSemanticTokensProvider, DocumentRangeSemanticTokensProvider } from 'vs/editor/common/languages';\nimport { SemanticTokensProviderStyling } from 'vs/editor/common/services/semanticTokensProviderStyling';\n\nexport const IModelService = createDecorator('modelService');\n\nexport type DocumentTokensProvider = DocumentSemanticTokensProvider | DocumentRangeSemanticTokensProvider;\n\nexport interface IModelService {\n\treadonly _serviceBrand: undefined;\n\n\tcreateModel(value: string | ITextBufferFactory, languageSelection: ILanguageSelection | null, resource?: URI, isForSimpleWidget?: boolean): ITextModel;\n\n\tsetMode(model: ITextModel, languageSelection: ILanguageSelection): void;\n\n\tgetModels(): ITextModel[];\n\n\tgetCreationOptions(language: string, resource: URI, isForSimpleWidget: boolean): ITextModelCreationOptions;\n\n\tgetModel(resource: URI): ITextModel | null;\n\n\tgetSemanticTokensProviderStyling(provider: DocumentTokensProvider): SemanticTokensProviderStyling;\n\n\tonModelAdded: Event;\n\n\tonModelRemoved: Event;\n\n\tonModelLanguageChanged: Event<{ model: ITextModel; oldLanguageId: string; }>;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IReference } from 'vs/base/common/lifecycle';\nimport { URI } from 'vs/base/common/uri';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { IEditorModel } from 'vs/platform/editor/common/editor';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const ITextModelService = createDecorator('textModelService');\n\nexport interface ITextModelService {\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Provided a resource URI, it will return a model reference\n\t * which should be disposed once not needed anymore.\n\t */\n\tcreateModelReference(resource: URI): Promise>;\n}\n\nexport interface ITextEditorModel extends IEditorModel {\n\n\t/**\n\t * Provides access to the underlying `ITextModel`.\n\t */\n\treadonly textEditorModel: ITextModel | null;\n}\n\nexport interface IResolvedTextEditorModel extends ITextEditorModel {\n\n\t/**\n\t * Same as ITextEditorModel#textEditorModel, but never null.\n\t */\n\treadonly textEditorModel: ITextModel;\n}\n","\nimport { URI } from 'vs/base/common/uri';\nimport { IPosition } from 'vs/editor/common/core/position';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const ITextResourceConfigurationService = createDecorator('textResourceConfigurationService');\n\nexport interface ITextResourceConfigurationChangeEvent {\n\n\t/**\n\t * All affected keys. Also includes language overrides and keys changed under language overrides.\n\t */\n\treadonly affectedKeys: string[];\n\n\t/**\n\t * Returns `true` if the given section has changed for the given resource.\n\t *\n\t * Example: To check if the configuration section has changed for a given resource use `e.affectsConfiguration(resource, section)`.\n\t *\n\t * @param resource Resource for which the configuration has to be checked.\n\t * @param section Section of the configuration\n\t */\n\taffectsConfiguration(resource: URI, section: string): boolean;\n}\n\nexport interface ITextResourceConfigurationService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Fetches the value of the section for the given resource by applying language overrides.\n\t * Value can be of native type or an object keyed off the section name.\n\t *\n\t * @param resource - Resource for which the configuration has to be fetched.\n\t * @param position - Position in the resource for which configuration has to be fetched.\n\t * @param section - Section of the configuraion.\n\t *\n\t */\n\tgetValue(resource: URI | undefined, section?: string): T;\n\tgetValue(resource: URI | undefined, position?: IPosition, section?: string): T;\n\n}\n\nexport const ITextResourcePropertiesService = createDecorator('textResourcePropertiesService');\n\nexport interface ITextResourcePropertiesService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Returns the End of Line characters for the given resource\n\t */\n\tgetEOL(resource: URI, language?: string): string;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Color } from 'vs/base/common/color';\nimport { ITokenThemeRule, TokenTheme } from 'vs/editor/common/languages/supports/tokenization';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';\n\nexport const IStandaloneThemeService = createDecorator('themeService');\n\nexport type BuiltinTheme = 'vs' | 'vs-dark' | 'hc-black';\nexport type IColors = { [colorId: string]: string; };\n\nexport interface IStandaloneThemeData {\n\tbase: BuiltinTheme;\n\tinherit: boolean;\n\trules: ITokenThemeRule[];\n\tencodedTokensColors?: string[];\n\tcolors: IColors;\n}\n\nexport interface IStandaloneTheme extends IColorTheme {\n\ttokenTheme: TokenTheme;\n\tthemeName: string;\n}\n\nexport interface IStandaloneThemeService extends IThemeService {\n\treadonly _serviceBrand: undefined;\n\n\tsetTheme(themeName: string): void;\n\n\tsetAutoDetectHighContrast(autoDetectHighContrast: boolean): void;\n\n\tdefineTheme(themeName: string, themeData: IStandaloneThemeData): void;\n\n\tgetColorTheme(): IStandaloneTheme;\n\n\tsetColorMapOverride(colorMapOverride: Color[] | null): void;\n\n}\n","\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const IClipboardService = createDecorator('clipboardService');\n\nexport interface IClipboardService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Writes text to the system clipboard.\n\t */\n\twriteText(text: string, type?: string): Promise;\n\n\t/**\n\t * Reads the content of the clipboard in plain text\n\t */\n\treadText(type?: string): Promise;\n\n\t/**\n\t * Reads text from the system find pasteboard.\n\t */\n\treadFindText(): Promise;\n\n\t/**\n\t * Writes text to the system find pasteboard.\n\t */\n\twriteFindText(text: string): Promise;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Iterable } from 'vs/base/common/iterator';\nimport { IJSONSchema } from 'vs/base/common/jsonSchema';\nimport { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { LinkedList } from 'vs/base/common/linkedList';\nimport { TypeConstraint, validateConstraints } from 'vs/base/common/types';\nimport { createDecorator, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';\n\nexport const ICommandService = createDecorator('commandService');\n\nexport interface ICommandEvent {\n\tcommandId: string;\n\targs: any[];\n}\n\nexport interface ICommandService {\n\treadonly _serviceBrand: undefined;\n\tonWillExecuteCommand: Event;\n\tonDidExecuteCommand: Event;\n\texecuteCommand(commandId: string, ...args: any[]): Promise;\n}\n\nexport type ICommandsMap = Map;\n\nexport interface ICommandHandler {\n\t(accessor: ServicesAccessor, ...args: any[]): void;\n}\n\nexport interface ICommand {\n\tid: string;\n\thandler: ICommandHandler;\n\tdescription?: ICommandHandlerDescription | null;\n}\n\nexport interface ICommandHandlerDescription {\n\treadonly description: string;\n\treadonly args: ReadonlyArray<{\n\t\treadonly name: string;\n\t\treadonly isOptional?: boolean;\n\t\treadonly description?: string;\n\t\treadonly constraint?: TypeConstraint;\n\t\treadonly schema?: IJSONSchema;\n\t}>;\n}\n\nexport interface ICommandRegistry {\n\tregisterCommand(id: string, command: ICommandHandler): IDisposable;\n\tregisterCommand(command: ICommand): IDisposable;\n\tregisterCommandAlias(oldId: string, newId: string): IDisposable;\n\tgetCommand(id: string): ICommand | undefined;\n}\n\nexport const CommandsRegistry: ICommandRegistry = new class implements ICommandRegistry {\n\n\tprivate readonly _commands = new Map>();\n\n\tprivate readonly _onDidRegisterCommand = new Emitter();\n\treadonly onDidRegisterCommand: Event = this._onDidRegisterCommand.event;\n\n\tregisterCommand(idOrCommand: string | ICommand, handler?: ICommandHandler): IDisposable {\n\n\t\tif (!idOrCommand) {\n\t\t\tthrow new Error(`invalid command`);\n\t\t}\n\n\t\tif (typeof idOrCommand === 'string') {\n\t\t\tif (!handler) {\n\t\t\t\tthrow new Error(`invalid command`);\n\t\t\t}\n\t\t\treturn this.registerCommand({ id: idOrCommand, handler });\n\t\t}\n\n\t\t// add argument validation if rich command metadata is provided\n\t\tif (idOrCommand.description) {\n\t\t\tconst constraints: Array = [];\n\t\t\tfor (let arg of idOrCommand.description.args) {\n\t\t\t\tconstraints.push(arg.constraint);\n\t\t\t}\n\t\t\tconst actualHandler = idOrCommand.handler;\n\t\t\tidOrCommand.handler = function (accessor, ...args: any[]) {\n\t\t\t\tvalidateConstraints(args, constraints);\n\t\t\t\treturn actualHandler(accessor, ...args);\n\t\t\t};\n\t\t}\n\n\t\t// find a place to store the command\n\t\tconst { id } = idOrCommand;\n\n\t\tlet commands = this._commands.get(id);\n\t\tif (!commands) {\n\t\t\tcommands = new LinkedList();\n\t\t\tthis._commands.set(id, commands);\n\t\t}\n\n\t\tlet removeFn = commands.unshift(idOrCommand);\n\n\t\tlet ret = toDisposable(() => {\n\t\t\tremoveFn();\n\t\t\tconst command = this._commands.get(id);\n\t\t\tif (command?.isEmpty()) {\n\t\t\t\tthis._commands.delete(id);\n\t\t\t}\n\t\t});\n\n\t\t// tell the world about this command\n\t\tthis._onDidRegisterCommand.fire(id);\n\n\t\treturn ret;\n\t}\n\n\tregisterCommandAlias(oldId: string, newId: string): IDisposable {\n\t\treturn CommandsRegistry.registerCommand(oldId, (accessor, ...args) => accessor.get(ICommandService).executeCommand(newId, ...args));\n\t}\n\n\tgetCommand(id: string): ICommand | undefined {\n\t\tconst list = this._commands.get(id);\n\t\tif (!list || list.isEmpty()) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn Iterable.first(list);\n\t}\n\n\tgetCommands(): ICommandsMap {\n\t\tconst result = new Map();\n\t\tfor (const key of this._commands.keys()) {\n\t\t\tconst command = this.getCommand(key);\n\t\t\tif (command) {\n\t\t\t\tresult.set(key, command);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n};\n\nexport const NullCommandService: ICommandService = {\n\t_serviceBrand: undefined,\n\tonWillExecuteCommand: () => Disposable.None,\n\tonDidExecuteCommand: () => Disposable.None,\n\texecuteCommand() {\n\t\treturn Promise.resolve(undefined);\n\t}\n};\n\nCommandsRegistry.registerCommand('noop', () => { });\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { onUnexpectedExternalError } from 'vs/base/common/errors';\nimport { URI } from 'vs/base/common/uri';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { DocumentSemanticTokensProviderRegistry, DocumentSemanticTokensProvider, SemanticTokens, SemanticTokensEdits, SemanticTokensLegend, DocumentRangeSemanticTokensProviderRegistry, DocumentRangeSemanticTokensProvider } from 'vs/editor/common/languages';\nimport { IModelService } from 'vs/editor/common/services/model';\nimport { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';\nimport { assertType } from 'vs/base/common/types';\nimport { VSBuffer } from 'vs/base/common/buffer';\nimport { encodeSemanticTokensDto } from 'vs/editor/common/services/semanticTokensDto';\nimport { Range } from 'vs/editor/common/core/range';\n\nexport function isSemanticTokens(v: SemanticTokens | SemanticTokensEdits): v is SemanticTokens {\n\treturn v && !!((v).data);\n}\n\nexport function isSemanticTokensEdits(v: SemanticTokens | SemanticTokensEdits): v is SemanticTokensEdits {\n\treturn v && Array.isArray((v).edits);\n}\n\nexport class DocumentSemanticTokensResult {\n\tconstructor(\n\t\tpublic readonly provider: DocumentSemanticTokensProvider,\n\t\tpublic readonly tokens: SemanticTokens | SemanticTokensEdits | null,\n\t\tpublic readonly error: any\n\t) { }\n}\n\nexport function hasDocumentSemanticTokensProvider(model: ITextModel): boolean {\n\treturn DocumentSemanticTokensProviderRegistry.has(model);\n}\n\nfunction getDocumentSemanticTokensProviders(model: ITextModel): DocumentSemanticTokensProvider[] {\n\tconst groups = DocumentSemanticTokensProviderRegistry.orderedGroups(model);\n\treturn (groups.length > 0 ? groups[0] : []);\n}\n\nexport async function getDocumentSemanticTokens(model: ITextModel, lastProvider: DocumentSemanticTokensProvider | null, lastResultId: string | null, token: CancellationToken): Promise {\n\tconst providers = getDocumentSemanticTokensProviders(model);\n\n\t// Get tokens from all providers at the same time.\n\tconst results = await Promise.all(providers.map(async (provider) => {\n\t\tlet result: SemanticTokens | SemanticTokensEdits | null | undefined;\n\t\tlet error: any = null;\n\t\ttry {\n\t\t\tresult = await provider.provideDocumentSemanticTokens(model, (provider === lastProvider ? lastResultId : null), token);\n\t\t} catch (err) {\n\t\t\terror = err;\n\t\t\tresult = null;\n\t\t}\n\n\t\tif (!result || (!isSemanticTokens(result) && !isSemanticTokensEdits(result))) {\n\t\t\tresult = null;\n\t\t}\n\n\t\treturn new DocumentSemanticTokensResult(provider, result, error);\n\t}));\n\n\t// Try to return the first result with actual tokens or\n\t// the first result which threw an error (!!)\n\tfor (const result of results) {\n\t\tif (result.error) {\n\t\t\tthrow result.error;\n\t\t}\n\t\tif (result.tokens) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\t// Return the first result, even if it doesn't have tokens\n\tif (results.length > 0) {\n\t\treturn results[0];\n\t}\n\n\treturn null;\n}\n\nfunction _getDocumentSemanticTokensProviderHighestGroup(model: ITextModel): DocumentSemanticTokensProvider[] | null {\n\tconst result = DocumentSemanticTokensProviderRegistry.orderedGroups(model);\n\treturn (result.length > 0 ? result[0] : null);\n}\n\nclass DocumentRangeSemanticTokensResult {\n\tconstructor(\n\t\tpublic readonly provider: DocumentRangeSemanticTokensProvider,\n\t\tpublic readonly tokens: SemanticTokens | null,\n\t) { }\n}\n\nexport function hasDocumentRangeSemanticTokensProvider(model: ITextModel): boolean {\n\treturn DocumentRangeSemanticTokensProviderRegistry.has(model);\n}\n\nfunction getDocumentRangeSemanticTokensProviders(model: ITextModel): DocumentRangeSemanticTokensProvider[] {\n\tconst groups = DocumentRangeSemanticTokensProviderRegistry.orderedGroups(model);\n\treturn (groups.length > 0 ? groups[0] : []);\n}\n\nexport async function getDocumentRangeSemanticTokens(model: ITextModel, range: Range, token: CancellationToken): Promise {\n\tconst providers = getDocumentRangeSemanticTokensProviders(model);\n\n\t// Get tokens from all providers at the same time.\n\tconst results = await Promise.all(providers.map(async (provider) => {\n\t\tlet result: SemanticTokens | null | undefined;\n\t\ttry {\n\t\t\tresult = await provider.provideDocumentRangeSemanticTokens(model, range, token);\n\t\t} catch (err) {\n\t\t\tonUnexpectedExternalError(err);\n\t\t\tresult = null;\n\t\t}\n\n\t\tif (!result || !isSemanticTokens(result)) {\n\t\t\tresult = null;\n\t\t}\n\n\t\treturn new DocumentRangeSemanticTokensResult(provider, result);\n\t}));\n\n\t// Try to return the first result with actual tokens\n\tfor (const result of results) {\n\t\tif (result.tokens) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\t// Return the first result, even if it doesn't have tokens\n\tif (results.length > 0) {\n\t\treturn results[0];\n\t}\n\n\treturn null;\n}\n\nCommandsRegistry.registerCommand('_provideDocumentSemanticTokensLegend', async (accessor, ...args): Promise => {\n\tconst [uri] = args;\n\tassertType(uri instanceof URI);\n\n\tconst model = accessor.get(IModelService).getModel(uri);\n\tif (!model) {\n\t\treturn undefined;\n\t}\n\n\tconst providers = _getDocumentSemanticTokensProviderHighestGroup(model);\n\tif (!providers) {\n\t\t// there is no provider => fall back to a document range semantic tokens provider\n\t\treturn accessor.get(ICommandService).executeCommand('_provideDocumentRangeSemanticTokensLegend', uri);\n\t}\n\n\treturn providers[0].getLegend();\n});\n\nCommandsRegistry.registerCommand('_provideDocumentSemanticTokens', async (accessor, ...args): Promise => {\n\tconst [uri] = args;\n\tassertType(uri instanceof URI);\n\n\tconst model = accessor.get(IModelService).getModel(uri);\n\tif (!model) {\n\t\treturn undefined;\n\t}\n\n\tif (!hasDocumentSemanticTokensProvider(model)) {\n\t\t// there is no provider => fall back to a document range semantic tokens provider\n\t\treturn accessor.get(ICommandService).executeCommand('_provideDocumentRangeSemanticTokens', uri, model.getFullModelRange());\n\t}\n\n\tconst r = await getDocumentSemanticTokens(model, null, null, CancellationToken.None);\n\tif (!r) {\n\t\treturn undefined;\n\t}\n\n\tconst { provider, tokens } = r;\n\n\tif (!tokens || !isSemanticTokens(tokens)) {\n\t\treturn undefined;\n\t}\n\n\tconst buff = encodeSemanticTokensDto({\n\t\tid: 0,\n\t\ttype: 'full',\n\t\tdata: tokens.data\n\t});\n\tif (tokens.resultId) {\n\t\tprovider.releaseDocumentSemanticTokens(tokens.resultId);\n\t}\n\treturn buff;\n});\n\nCommandsRegistry.registerCommand('_provideDocumentRangeSemanticTokensLegend', async (accessor, ...args): Promise => {\n\tconst [uri, range] = args;\n\tassertType(uri instanceof URI);\n\n\tconst model = accessor.get(IModelService).getModel(uri);\n\tif (!model) {\n\t\treturn undefined;\n\t}\n\n\tconst providers = getDocumentRangeSemanticTokensProviders(model);\n\tif (providers.length === 0) {\n\t\t// no providers\n\t\treturn undefined;\n\t}\n\n\tif (providers.length === 1) {\n\t\t// straight forward case, just a single provider\n\t\treturn providers[0].getLegend();\n\t}\n\n\tif (!range || !Range.isIRange(range)) {\n\t\t// if no range is provided, we cannot support multiple providers\n\t\t// as we cannot fall back to the one which would give results\n\t\t// => return the first legend for backwards compatibility and print a warning\n\t\tconsole.warn(`provideDocumentRangeSemanticTokensLegend might be out-of-sync with provideDocumentRangeSemanticTokens unless a range argument is passed in`);\n\t\treturn providers[0].getLegend();\n\t}\n\n\tconst result = await getDocumentRangeSemanticTokens(model, Range.lift(range), CancellationToken.None);\n\tif (!result) {\n\t\treturn undefined;\n\t}\n\n\treturn result.provider.getLegend();\n});\n\nCommandsRegistry.registerCommand('_provideDocumentRangeSemanticTokens', async (accessor, ...args): Promise => {\n\tconst [uri, range] = args;\n\tassertType(uri instanceof URI);\n\tassertType(Range.isIRange(range));\n\n\tconst model = accessor.get(IModelService).getModel(uri);\n\tif (!model) {\n\t\treturn undefined;\n\t}\n\n\tconst result = await getDocumentRangeSemanticTokens(model, Range.lift(range), CancellationToken.None);\n\tif (!result || !result.tokens) {\n\t\t// there is no provider or it didn't return tokens\n\t\treturn undefined;\n\t}\n\n\treturn encodeSemanticTokensDto({\n\t\tid: 0,\n\t\ttype: 'full',\n\t\tdata: result.tokens.data\n\t});\n});\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { illegalArgument, onUnexpectedExternalError } from 'vs/base/common/errors';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\nimport { assertType } from 'vs/base/common/types';\nimport { URI } from 'vs/base/common/uri';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { CodeLens, CodeLensList, CodeLensProvider, CodeLensProviderRegistry } from 'vs/editor/common/languages';\nimport { IModelService } from 'vs/editor/common/services/model';\nimport { CommandsRegistry } from 'vs/platform/commands/common/commands';\n\nexport interface CodeLensItem {\n\tsymbol: CodeLens;\n\tprovider: CodeLensProvider;\n}\n\nexport class CodeLensModel {\n\n\tlenses: CodeLensItem[] = [];\n\n\tprivate readonly _disposables = new DisposableStore();\n\n\tdispose(): void {\n\t\tthis._disposables.dispose();\n\t}\n\n\tget isDisposed(): boolean {\n\t\treturn this._disposables.isDisposed;\n\t}\n\n\tadd(list: CodeLensList, provider: CodeLensProvider): void {\n\t\tthis._disposables.add(list);\n\t\tfor (const symbol of list.lenses) {\n\t\t\tthis.lenses.push({ symbol, provider });\n\t\t}\n\t}\n}\n\nexport async function getCodeLensModel(model: ITextModel, token: CancellationToken): Promise {\n\n\tconst provider = CodeLensProviderRegistry.ordered(model);\n\tconst providerRanks = new Map();\n\tconst result = new CodeLensModel();\n\n\tconst promises = provider.map(async (provider, i) => {\n\n\t\tproviderRanks.set(provider, i);\n\n\t\ttry {\n\t\t\tconst list = await Promise.resolve(provider.provideCodeLenses(model, token));\n\t\t\tif (list) {\n\t\t\t\tresult.add(list, provider);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tonUnexpectedExternalError(err);\n\t\t}\n\t});\n\n\tawait Promise.all(promises);\n\n\tresult.lenses = result.lenses.sort((a, b) => {\n\t\t// sort by lineNumber, provider-rank, and column\n\t\tif (a.symbol.range.startLineNumber < b.symbol.range.startLineNumber) {\n\t\t\treturn -1;\n\t\t} else if (a.symbol.range.startLineNumber > b.symbol.range.startLineNumber) {\n\t\t\treturn 1;\n\t\t} else if ((providerRanks.get(a.provider)!) < (providerRanks.get(b.provider)!)) {\n\t\t\treturn -1;\n\t\t} else if ((providerRanks.get(a.provider)!) > (providerRanks.get(b.provider)!)) {\n\t\t\treturn 1;\n\t\t} else if (a.symbol.range.startColumn < b.symbol.range.startColumn) {\n\t\t\treturn -1;\n\t\t} else if (a.symbol.range.startColumn > b.symbol.range.startColumn) {\n\t\t\treturn 1;\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t});\n\treturn result;\n}\n\nCommandsRegistry.registerCommand('_executeCodeLensProvider', function (accessor, ...args: [URI, number | undefined | null]) {\n\tlet [uri, itemResolveCount] = args;\n\tassertType(URI.isUri(uri));\n\tassertType(typeof itemResolveCount === 'number' || !itemResolveCount);\n\n\tconst model = accessor.get(IModelService).getModel(uri);\n\tif (!model) {\n\t\tthrow illegalArgument();\n\t}\n\n\tconst result: CodeLens[] = [];\n\tconst disposables = new DisposableStore();\n\treturn getCodeLensModel(model, CancellationToken.None).then(value => {\n\n\t\tdisposables.add(value);\n\t\tlet resolve: Promise[] = [];\n\n\t\tfor (const item of value.lenses) {\n\t\t\tif (itemResolveCount === undefined || itemResolveCount === null || Boolean(item.symbol.command)) {\n\t\t\t\tresult.push(item.symbol);\n\t\t\t} else if (itemResolveCount-- > 0 && item.provider.resolveCodeLens) {\n\t\t\t\tresolve.push(Promise.resolve(item.provider.resolveCodeLens(model, item.symbol, CancellationToken.None)).then(symbol => result.push(symbol || item.symbol)));\n\t\t\t}\n\t\t}\n\n\t\treturn Promise.all(resolve);\n\n\t}).then(() => {\n\t\treturn result;\n\t}).finally(() => {\n\t\t// make sure to return results, then (on next tick)\n\t\t// dispose the results\n\t\tsetTimeout(() => disposables.dispose(), 100);\n\t});\n});\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { illegalArgument } from 'vs/base/common/errors';\nimport { URI } from 'vs/base/common/uri';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { ColorProviderRegistry, DocumentColorProvider, IColorInformation, IColorPresentation } from 'vs/editor/common/languages';\nimport { IModelService } from 'vs/editor/common/services/model';\nimport { CommandsRegistry } from 'vs/platform/commands/common/commands';\n\n\nexport interface IColorData {\n\tcolorInfo: IColorInformation;\n\tprovider: DocumentColorProvider;\n}\n\nexport function getColors(model: ITextModel, token: CancellationToken): Promise {\n\tconst colors: IColorData[] = [];\n\tconst providers = ColorProviderRegistry.ordered(model).reverse();\n\tconst promises = providers.map(provider => Promise.resolve(provider.provideDocumentColors(model, token)).then(result => {\n\t\tif (Array.isArray(result)) {\n\t\t\tfor (let colorInfo of result) {\n\t\t\t\tcolors.push({ colorInfo, provider });\n\t\t\t}\n\t\t}\n\t}));\n\n\treturn Promise.all(promises).then(() => colors);\n}\n\nexport function getColorPresentations(model: ITextModel, colorInfo: IColorInformation, provider: DocumentColorProvider, token: CancellationToken): Promise {\n\treturn Promise.resolve(provider.provideColorPresentations(model, colorInfo, token));\n}\n\nCommandsRegistry.registerCommand('_executeDocumentColorProvider', function (accessor, ...args) {\n\n\tconst [resource] = args;\n\tif (!(resource instanceof URI)) {\n\t\tthrow illegalArgument();\n\t}\n\n\tconst model = accessor.get(IModelService).getModel(resource);\n\tif (!model) {\n\t\tthrow illegalArgument();\n\t}\n\n\tconst rawCIs: { range: IRange, color: [number, number, number, number] }[] = [];\n\tconst providers = ColorProviderRegistry.ordered(model).reverse();\n\tconst promises = providers.map(provider => Promise.resolve(provider.provideDocumentColors(model, CancellationToken.None)).then(result => {\n\t\tif (Array.isArray(result)) {\n\t\t\tfor (let ci of result) {\n\t\t\t\trawCIs.push({ range: ci.range, color: [ci.color.red, ci.color.green, ci.color.blue, ci.color.alpha] });\n\t\t\t}\n\t\t}\n\t}));\n\n\treturn Promise.all(promises).then(() => rawCIs);\n});\n\n\nCommandsRegistry.registerCommand('_executeColorPresentationProvider', function (accessor, ...args) {\n\n\tconst [color, context] = args;\n\tconst { uri, range } = context;\n\tif (!(uri instanceof URI) || !Array.isArray(color) || color.length !== 4 || !Range.isIRange(range)) {\n\t\tthrow illegalArgument();\n\t}\n\tconst [red, green, blue, alpha] = color;\n\n\tconst model = accessor.get(IModelService).getModel(uri);\n\tif (!model) {\n\t\tthrow illegalArgument();\n\t}\n\n\tconst colorInfo = {\n\t\trange,\n\t\tcolor: { red, green, blue, alpha }\n\t};\n\n\tconst presentations: IColorPresentation[] = [];\n\tconst providers = ColorProviderRegistry.ordered(model).reverse();\n\tconst promises = providers.map(provider => Promise.resolve(provider.provideColorPresentations(model, colorInfo, CancellationToken.None)).then(result => {\n\t\tif (Array.isArray(result)) {\n\t\t\tpresentations.push(...result);\n\t\t}\n\t}));\n\treturn Promise.all(promises).then(() => presentations);\n});\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { coalesce } from 'vs/base/common/arrays';\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { onUnexpectedExternalError } from 'vs/base/common/errors';\nimport { DisposableStore, isDisposable } from 'vs/base/common/lifecycle';\nimport { assertType } from 'vs/base/common/types';\nimport { URI } from 'vs/base/common/uri';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { ILink, ILinksList, LinkProvider, LinkProviderRegistry } from 'vs/editor/common/languages';\nimport { IModelService } from 'vs/editor/common/services/model';\nimport { CommandsRegistry } from 'vs/platform/commands/common/commands';\n\nexport class Link implements ILink {\n\n\tprivate _link: ILink;\n\tprivate readonly _provider: LinkProvider;\n\n\tconstructor(link: ILink, provider: LinkProvider) {\n\t\tthis._link = link;\n\t\tthis._provider = provider;\n\t}\n\n\ttoJSON(): ILink {\n\t\treturn {\n\t\t\trange: this.range,\n\t\t\turl: this.url,\n\t\t\ttooltip: this.tooltip\n\t\t};\n\t}\n\n\tget range(): IRange {\n\t\treturn this._link.range;\n\t}\n\n\tget url(): URI | string | undefined {\n\t\treturn this._link.url;\n\t}\n\n\tget tooltip(): string | undefined {\n\t\treturn this._link.tooltip;\n\t}\n\n\tasync resolve(token: CancellationToken): Promise {\n\t\tif (this._link.url) {\n\t\t\treturn this._link.url;\n\t\t}\n\n\t\tif (typeof this._provider.resolveLink === 'function') {\n\t\t\treturn Promise.resolve(this._provider.resolveLink(this._link, token)).then(value => {\n\t\t\t\tthis._link = value || this._link;\n\t\t\t\tif (this._link.url) {\n\t\t\t\t\t// recurse\n\t\t\t\t\treturn this.resolve(token);\n\t\t\t\t}\n\n\t\t\t\treturn Promise.reject(new Error('missing'));\n\t\t\t});\n\t\t}\n\n\t\treturn Promise.reject(new Error('missing'));\n\t}\n}\n\nexport class LinksList {\n\n\treadonly links: Link[];\n\n\tprivate readonly _disposables = new DisposableStore();\n\n\tconstructor(tuples: [ILinksList, LinkProvider][]) {\n\n\t\tlet links: Link[] = [];\n\t\tfor (const [list, provider] of tuples) {\n\t\t\t// merge all links\n\t\t\tconst newLinks = list.links.map(link => new Link(link, provider));\n\t\t\tlinks = LinksList._union(links, newLinks);\n\t\t\t// register disposables\n\t\t\tif (isDisposable(list)) {\n\t\t\t\tthis._disposables.add(list);\n\t\t\t}\n\t\t}\n\t\tthis.links = links;\n\t}\n\n\tdispose(): void {\n\t\tthis._disposables.dispose();\n\t\tthis.links.length = 0;\n\t}\n\n\tprivate static _union(oldLinks: Link[], newLinks: Link[]): Link[] {\n\t\t// reunite oldLinks with newLinks and remove duplicates\n\t\tlet result: Link[] = [];\n\t\tlet oldIndex: number;\n\t\tlet oldLen: number;\n\t\tlet newIndex: number;\n\t\tlet newLen: number;\n\n\t\tfor (oldIndex = 0, newIndex = 0, oldLen = oldLinks.length, newLen = newLinks.length; oldIndex < oldLen && newIndex < newLen;) {\n\t\t\tconst oldLink = oldLinks[oldIndex];\n\t\t\tconst newLink = newLinks[newIndex];\n\n\t\t\tif (Range.areIntersectingOrTouching(oldLink.range, newLink.range)) {\n\t\t\t\t// Remove the oldLink\n\t\t\t\toldIndex++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst comparisonResult = Range.compareRangesUsingStarts(oldLink.range, newLink.range);\n\n\t\t\tif (comparisonResult < 0) {\n\t\t\t\t// oldLink is before\n\t\t\t\tresult.push(oldLink);\n\t\t\t\toldIndex++;\n\t\t\t} else {\n\t\t\t\t// newLink is before\n\t\t\t\tresult.push(newLink);\n\t\t\t\tnewIndex++;\n\t\t\t}\n\t\t}\n\n\t\tfor (; oldIndex < oldLen; oldIndex++) {\n\t\t\tresult.push(oldLinks[oldIndex]);\n\t\t}\n\t\tfor (; newIndex < newLen; newIndex++) {\n\t\t\tresult.push(newLinks[newIndex]);\n\t\t}\n\n\t\treturn result;\n\t}\n\n}\n\nexport function getLinks(model: ITextModel, token: CancellationToken): Promise {\n\n\tconst lists: [ILinksList, LinkProvider][] = [];\n\n\t// ask all providers for links in parallel\n\tconst promises = LinkProviderRegistry.ordered(model).reverse().map((provider, i) => {\n\t\treturn Promise.resolve(provider.provideLinks(model, token)).then(result => {\n\t\t\tif (result) {\n\t\t\t\tlists[i] = [result, provider];\n\t\t\t}\n\t\t}, onUnexpectedExternalError);\n\t});\n\n\treturn Promise.all(promises).then(() => {\n\t\tconst result = new LinksList(coalesce(lists));\n\t\tif (!token.isCancellationRequested) {\n\t\t\treturn result;\n\t\t}\n\t\tresult.dispose();\n\t\treturn new LinksList([]);\n\t});\n}\n\n\nCommandsRegistry.registerCommand('_executeLinkProvider', async (accessor, ...args): Promise => {\n\tlet [uri, resolveCount] = args;\n\tassertType(uri instanceof URI);\n\n\tif (typeof resolveCount !== 'number') {\n\t\tresolveCount = 0;\n\t}\n\n\tconst model = accessor.get(IModelService).getModel(uri);\n\tif (!model) {\n\t\treturn [];\n\t}\n\tconst list = await getLinks(model, CancellationToken.None);\n\tif (!list) {\n\t\treturn [];\n\t}\n\n\t// resolve links\n\tfor (let i = 0; i < Math.min(resolveCount, list.links.length); i++) {\n\t\tawait list.links[i].resolve(CancellationToken.None);\n\t}\n\n\tconst result = list.links.slice(0);\n\tlist.dispose();\n\treturn result;\n});\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport { URI, UriComponents } from 'vs/base/common/uri';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const IConfigurationService = createDecorator('configurationService');\n\nexport interface IConfigurationOverrides {\n\toverrideIdentifier?: string | null;\n\tresource?: URI | null;\n}\n\nexport type IConfigurationUpdateOverrides = Omit & { overrideIdentifiers?: string[] | null; };\n\nexport const enum ConfigurationTarget {\n\tUSER = 1,\n\tUSER_LOCAL,\n\tUSER_REMOTE,\n\tWORKSPACE,\n\tWORKSPACE_FOLDER,\n\tDEFAULT,\n\tMEMORY\n}\n\nexport interface IConfigurationChange {\n\tkeys: string[];\n\toverrides: [string, string[]][];\n}\n\nexport interface IConfigurationChangeEvent {\n\n\treadonly source: ConfigurationTarget;\n\treadonly affectedKeys: string[];\n\treadonly change: IConfigurationChange;\n\n\taffectsConfiguration(configuration: string, overrides?: IConfigurationOverrides): boolean;\n}\n\nexport interface IConfigurationValue {\n\n\treadonly defaultValue?: T;\n\treadonly userValue?: T;\n\treadonly userLocalValue?: T;\n\treadonly userRemoteValue?: T;\n\treadonly workspaceValue?: T;\n\treadonly workspaceFolderValue?: T;\n\treadonly memoryValue?: T;\n\treadonly value?: T;\n\n\treadonly default?: { value?: T, override?: T };\n\treadonly user?: { value?: T, override?: T };\n\treadonly userLocal?: { value?: T, override?: T };\n\treadonly userRemote?: { value?: T, override?: T };\n\treadonly workspace?: { value?: T, override?: T };\n\treadonly workspaceFolder?: { value?: T, override?: T };\n\treadonly memory?: { value?: T, override?: T };\n\n\treadonly overrideIdentifiers?: string[];\n}\n\nexport interface IConfigurationService {\n\treadonly _serviceBrand: undefined;\n\n\tonDidChangeConfiguration: Event;\n\n\t/**\n\t * Fetches the value of the section for the given overrides.\n\t * Value can be of native type or an object keyed off the section name.\n\t *\n\t * @param section - Section of the configuraion. Can be `null` or `undefined`.\n\t * @param overrides - Overrides that has to be applied while fetching\n\t *\n\t */\n\tgetValue(): T;\n\tgetValue(section: string): T;\n\tgetValue(overrides: IConfigurationOverrides): T;\n\tgetValue(section: string, overrides: IConfigurationOverrides): T;\n\n\t/**\n\t * Update a configuration value.\n\t *\n\t * Use `target` to update the configuration in a specific `ConfigurationTarget`.\n\t *\n\t * Use `overrides` to update the configuration for a resource or for override identifiers or both.\n\t *\n\t * Passing a resource through overrides will update the configuration in the workspace folder containing that resource.\n\t *\n\t * *Note 1:* Updating configuraiton to a default value will remove the configuration from the requested target. If not target is passed, it will be removed from all writeable targets.\n\t *\n\t * *Note 2:* Use `undefined` value to remove the configuration from the given target. If not target is passed, it will be removed from all writeable targets.\n\t *\n\t * Use `donotNotifyError` and set it to `true` to surpresss errors.\n\t *\n\t * @param key setting to be updated\n\t * @param value The new value\n\t */\n\tupdateValue(key: string, value: any): Promise;\n\tupdateValue(key: string, value: any, target: ConfigurationTarget): Promise;\n\tupdateValue(key: string, value: any, overrides: IConfigurationOverrides | IConfigurationUpdateOverrides): Promise;\n\tupdateValue(key: string, value: any, overrides: IConfigurationOverrides | IConfigurationUpdateOverrides, target: ConfigurationTarget, donotNotifyError?: boolean): Promise;\n\n\tinspect(key: string, overrides?: IConfigurationOverrides): IConfigurationValue>;\n}\n\nexport interface IConfigurationModel {\n\tcontents: any;\n\tkeys: string[];\n\toverrides: IOverrides[];\n}\n\nexport interface IOverrides {\n\tkeys: string[];\n\tcontents: any;\n\tidentifiers: string[];\n}\n\nexport interface IConfigurationData {\n\tdefaults: IConfigurationModel;\n\tuser: IConfigurationModel;\n\tworkspace: IConfigurationModel;\n\tfolders: [UriComponents, IConfigurationModel][];\n}\n\nexport function toValuesTree(properties: { [qualifiedKey: string]: any }, conflictReporter: (message: string) => void): any {\n\tconst root = Object.create(null);\n\n\tfor (let key in properties) {\n\t\taddToValueTree(root, key, properties[key], conflictReporter);\n\t}\n\n\treturn root;\n}\n\nexport function addToValueTree(settingsTreeRoot: any, key: string, value: any, conflictReporter: (message: string) => void): void {\n\tconst segments = key.split('.');\n\tconst last = segments.pop()!;\n\n\tlet curr = settingsTreeRoot;\n\tfor (let i = 0; i < segments.length; i++) {\n\t\tlet s = segments[i];\n\t\tlet obj = curr[s];\n\t\tswitch (typeof obj) {\n\t\t\tcase 'undefined':\n\t\t\t\tobj = curr[s] = Object.create(null);\n\t\t\t\tbreak;\n\t\t\tcase 'object':\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tconflictReporter(`Ignoring ${key} as ${segments.slice(0, i + 1).join('.')} is ${JSON.stringify(obj)}`);\n\t\t\t\treturn;\n\t\t}\n\t\tcurr = obj;\n\t}\n\n\tif (typeof curr === 'object' && curr !== null) {\n\t\ttry {\n\t\t\tcurr[last] = value; // workaround https://github.com/microsoft/vscode/issues/13606\n\t\t} catch (e) {\n\t\t\tconflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`);\n\t\t}\n\t} else {\n\t\tconflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`);\n\t}\n}\n\nexport function removeFromValueTree(valueTree: any, key: string): void {\n\tconst segments = key.split('.');\n\tdoRemoveFromValueTree(valueTree, segments);\n}\n\nfunction doRemoveFromValueTree(valueTree: any, segments: string[]): void {\n\tconst first = segments.shift()!;\n\tif (segments.length === 0) {\n\t\t// Reached last segment\n\t\tdelete valueTree[first];\n\t\treturn;\n\t}\n\n\tif (Object.keys(valueTree).indexOf(first) !== -1) {\n\t\tconst value = valueTree[first];\n\t\tif (typeof value === 'object' && !Array.isArray(value)) {\n\t\t\tdoRemoveFromValueTree(value, segments);\n\t\t\tif (Object.keys(value).length === 0) {\n\t\t\t\tdelete valueTree[first];\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * A helper function to get the configuration value with a specific settings path (e.g. config.some.setting)\n */\nexport function getConfigurationValue(config: any, settingPath: string, defaultValue?: T): T {\n\tfunction accessSetting(config: any, path: string[]): any {\n\t\tlet current = config;\n\t\tfor (const component of path) {\n\t\t\tif (typeof current !== 'object' || current === null) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tcurrent = current[component];\n\t\t}\n\t\treturn current;\n\t}\n\n\tconst path = settingPath.split('.');\n\tconst result = accessSetting(config, path);\n\n\treturn typeof result === 'undefined' ? defaultValue : result;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport * as strings from 'vs/base/common/strings';\nimport { LineTokens } from 'vs/editor/common/tokens/lineTokens';\nimport { Range } from 'vs/editor/common/core/range';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { DEFAULT_WORD_REGEXP, ensureValidWordDefinition } from 'vs/editor/common/core/wordHelper';\nimport { EnterAction, FoldingRules, IAutoClosingPair, IndentAction, IndentationRule, LanguageConfiguration, CompleteEnterAction, AutoClosingPairs, CharacterPair, ExplicitLanguageConfiguration } from 'vs/editor/common/languages/languageConfiguration';\nimport { createScopedLineTokens, ScopedLineTokens } from 'vs/editor/common/languages/supports';\nimport { CharacterPairSupport } from 'vs/editor/common/languages/supports/characterPair';\nimport { BracketElectricCharacterSupport } from 'vs/editor/common/languages/supports/electricCharacter';\nimport { IndentConsts, IndentRulesSupport } from 'vs/editor/common/languages/supports/indentRules';\nimport { OnEnterSupport } from 'vs/editor/common/languages/supports/onEnter';\nimport { RichEditBrackets } from 'vs/editor/common/languages/supports/richEditBrackets';\nimport { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { IConfigurationService } from 'vs/platform/configuration/common/configuration';\nimport { ILanguageService } from 'vs/editor/common/services/language';\nimport { registerSingleton } from 'vs/platform/instantiation/common/extensions';\n\n/**\n * Interface used to support insertion of mode specific comments.\n */\nexport interface ICommentsConfiguration {\n\tlineCommentToken?: string;\n\tblockCommentStartToken?: string;\n\tblockCommentEndToken?: string;\n}\n\nexport interface IVirtualModel {\n\tgetLineTokens(lineNumber: number): LineTokens;\n\tgetLanguageId(): string;\n\tgetLanguageIdAtPosition(lineNumber: number, column: number): string;\n\tgetLineContent(lineNumber: number): string;\n}\n\nexport interface IIndentConverter {\n\tshiftIndent(indentation: string): string;\n\tunshiftIndent(indentation: string): string;\n\tnormalizeIndentation?(indentation: string): string;\n}\n\nexport interface ILanguageConfigurationService {\n\treadonly _serviceBrand: undefined;\n\n\tonDidChange: Event;\n\tgetLanguageConfiguration(languageId: string): ResolvedLanguageConfiguration;\n}\n\nexport class LanguageConfigurationServiceChangeEvent {\n\tconstructor(public readonly languageId: string | undefined) { }\n\n\tpublic affects(languageId: string): boolean {\n\t\treturn !this.languageId ? true : this.languageId === languageId;\n\t}\n}\n\nexport const ILanguageConfigurationService = createDecorator('languageConfigurationService');\n\nexport class LanguageConfigurationService extends Disposable implements ILanguageConfigurationService {\n\t_serviceBrand: undefined;\n\n\tprivate readonly onDidChangeEmitter = this._register(new Emitter());\n\tpublic readonly onDidChange = this.onDidChangeEmitter.event;\n\n\tprivate readonly configurations = new Map();\n\n\tconstructor(\n\t\t@IConfigurationService private readonly configurationService: IConfigurationService,\n\t\t@ILanguageService private readonly languageService: ILanguageService\n\t) {\n\t\tsuper();\n\n\t\tconst languageConfigKeys = new Set(Object.values(customizedLanguageConfigKeys));\n\n\t\tthis._register(this.configurationService.onDidChangeConfiguration((e) => {\n\t\t\tconst globalConfigChanged = e.change.keys.some((k) =>\n\t\t\t\tlanguageConfigKeys.has(k)\n\t\t\t);\n\t\t\tconst localConfigChanged = e.change.overrides\n\t\t\t\t.filter(([overrideLangName, keys]) =>\n\t\t\t\t\tkeys.some((k) => languageConfigKeys.has(k))\n\t\t\t\t)\n\t\t\t\t.map(([overrideLangName]) => overrideLangName);\n\n\t\t\tif (globalConfigChanged) {\n\t\t\t\tthis.configurations.clear();\n\t\t\t\tthis.onDidChangeEmitter.fire(new LanguageConfigurationServiceChangeEvent(undefined));\n\t\t\t} else {\n\t\t\t\tfor (const languageId of localConfigChanged) {\n\t\t\t\t\tif (this.languageService.isRegisteredLanguageId(languageId)) {\n\t\t\t\t\t\tthis.configurations.delete(languageId);\n\t\t\t\t\t\tthis.onDidChangeEmitter.fire(new LanguageConfigurationServiceChangeEvent(languageId));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(LanguageConfigurationRegistry.onDidChange((e) => {\n\t\t\tthis.configurations.delete(e.languageId);\n\t\t\tthis.onDidChangeEmitter.fire(new LanguageConfigurationServiceChangeEvent(e.languageId));\n\t\t}));\n\t}\n\n\tpublic getLanguageConfiguration(languageId: string): ResolvedLanguageConfiguration {\n\t\tlet result = this.configurations.get(languageId);\n\t\tif (!result) {\n\t\t\tresult = computeConfig(languageId, this.configurationService, this.languageService);\n\t\t\tthis.configurations.set(languageId, result);\n\t\t}\n\t\treturn result;\n\t}\n}\n\nfunction computeConfig(\n\tlanguageId: string,\n\tconfigurationService: IConfigurationService,\n\tlanguageService: ILanguageService,\n): ResolvedLanguageConfiguration {\n\tlet languageConfig = LanguageConfigurationRegistry.getLanguageConfiguration(languageId);\n\n\tif (!languageConfig) {\n\t\tif (!languageService.isRegisteredLanguageId(languageId)) {\n\t\t\tthrow new Error('Unexpected languageId');\n\t\t}\n\t\tlanguageConfig = new ResolvedLanguageConfiguration(languageId, {});\n\t}\n\n\tconst customizedConfig = getCustomizedLanguageConfig(languageConfig.languageId, configurationService);\n\tconst data = combineLanguageConfigurations([languageConfig.underlyingConfig, customizedConfig]);\n\tconst config = new ResolvedLanguageConfiguration(languageConfig.languageId, data);\n\treturn config;\n}\n\nconst customizedLanguageConfigKeys = {\n\tbrackets: 'editor.language.brackets',\n\tcolorizedBracketPairs: 'editor.language.colorizedBracketPairs'\n};\n\nfunction getCustomizedLanguageConfig(languageId: string, configurationService: IConfigurationService): LanguageConfiguration {\n\tconst brackets = configurationService.getValue(customizedLanguageConfigKeys.brackets, {\n\t\toverrideIdentifier: languageId,\n\t});\n\n\tconst colorizedBracketPairs = configurationService.getValue(customizedLanguageConfigKeys.colorizedBracketPairs, {\n\t\toverrideIdentifier: languageId,\n\t});\n\n\treturn {\n\t\tbrackets: validateBracketPairs(brackets),\n\t\tcolorizedBracketPairs: validateBracketPairs(colorizedBracketPairs),\n\t};\n}\n\nfunction validateBracketPairs(data: unknown): CharacterPair[] | undefined {\n\tif (!Array.isArray(data)) {\n\t\treturn undefined;\n\t}\n\treturn data.map(pair => {\n\t\tif (!Array.isArray(pair) || pair.length !== 2) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [pair[0], pair[1]] as CharacterPair;\n\t}).filter((p): p is CharacterPair => !!p);\n}\n\nexport class LanguageConfigurationChangeEvent {\n\tconstructor(public readonly languageId: string) { }\n}\n\nexport class LanguageConfigurationRegistryImpl {\n\tprivate readonly _entries = new Map();\n\n\tprivate readonly _onDidChange = new Emitter();\n\tpublic readonly onDidChange: Event = this._onDidChange.event;\n\n\t/**\n\t * @param priority Use a higher number for higher priority\n\t */\n\tpublic register(languageId: string, configuration: LanguageConfiguration, priority: number = 0): IDisposable {\n\t\tlet entries = this._entries.get(languageId);\n\t\tif (!entries) {\n\t\t\tentries = new ComposedLanguageConfiguration(languageId);\n\t\t\tthis._entries.set(languageId, entries);\n\t\t}\n\n\t\tconst disposable = entries.register(configuration, priority);\n\t\tthis._onDidChange.fire(new LanguageConfigurationChangeEvent(languageId));\n\n\t\treturn toDisposable(() => {\n\t\t\tdisposable.dispose();\n\t\t\tthis._onDidChange.fire(new LanguageConfigurationChangeEvent(languageId));\n\t\t});\n\t}\n\n\tpublic getLanguageConfiguration(languageId: string): ResolvedLanguageConfiguration | null {\n\t\tconst entries = this._entries.get(languageId);\n\t\treturn entries?.getResolvedConfiguration() || null;\n\t}\n\n\tpublic getComments(languageId: string): ICommentsConfiguration | null {\n\t\tconst value = this.getLanguageConfiguration(languageId);\n\t\tif (!value) {\n\t\t\treturn null;\n\t\t}\n\t\treturn value.comments || null;\n\t}\n\n\t// begin Indent Rules\n\n\tpublic getIndentRulesSupport(languageId: string): IndentRulesSupport | null {\n\t\tconst value = this.getLanguageConfiguration(languageId);\n\t\tif (!value) {\n\t\t\treturn null;\n\t\t}\n\t\treturn value.indentRulesSupport || null;\n\t}\n\n\t/**\n\t * Get nearest preceding line which doesn't match unIndentPattern or contains all whitespace.\n\t * Result:\n\t * -1: run into the boundary of embedded languages\n\t * 0: every line above are invalid\n\t * else: nearest preceding line of the same language\n\t */\n\tprivate getPrecedingValidLine(model: IVirtualModel, lineNumber: number, indentRulesSupport: IndentRulesSupport) {\n\t\tconst languageId = model.getLanguageIdAtPosition(lineNumber, 0);\n\t\tif (lineNumber > 1) {\n\t\t\tlet lastLineNumber: number;\n\t\t\tlet resultLineNumber = -1;\n\n\t\t\tfor (lastLineNumber = lineNumber - 1; lastLineNumber >= 1; lastLineNumber--) {\n\t\t\t\tif (model.getLanguageIdAtPosition(lastLineNumber, 0) !== languageId) {\n\t\t\t\t\treturn resultLineNumber;\n\t\t\t\t}\n\t\t\t\tconst text = model.getLineContent(lastLineNumber);\n\t\t\t\tif (indentRulesSupport.shouldIgnore(text) || /^\\s+$/.test(text) || text === '') {\n\t\t\t\t\tresultLineNumber = lastLineNumber;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\treturn lastLineNumber;\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t/**\n\t * Get inherited indentation from above lines.\n\t * 1. Find the nearest preceding line which doesn't match unIndentedLinePattern.\n\t * 2. If this line matches indentNextLinePattern or increaseIndentPattern, it means that the indent level of `lineNumber` should be 1 greater than this line.\n\t * 3. If this line doesn't match any indent rules\n\t * a. check whether the line above it matches indentNextLinePattern\n\t * b. If not, the indent level of this line is the result\n\t * c. If so, it means the indent of this line is *temporary*, go upward utill we find a line whose indent is not temporary (the same workflow a -> b -> c).\n\t * 4. Otherwise, we fail to get an inherited indent from aboves. Return null and we should not touch the indent of `lineNumber`\n\t *\n\t * This function only return the inherited indent based on above lines, it doesn't check whether current line should decrease or not.\n\t */\n\tpublic getInheritIndentForLine(autoIndent: EditorAutoIndentStrategy, model: IVirtualModel, lineNumber: number, honorIntentialIndent: boolean = true): { indentation: string; action: IndentAction | null; line?: number; } | null {\n\t\tif (autoIndent < EditorAutoIndentStrategy.Full) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst indentRulesSupport = this.getIndentRulesSupport(model.getLanguageId());\n\t\tif (!indentRulesSupport) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (lineNumber <= 1) {\n\t\t\treturn {\n\t\t\t\tindentation: '',\n\t\t\t\taction: null\n\t\t\t};\n\t\t}\n\n\t\tconst precedingUnIgnoredLine = this.getPrecedingValidLine(model, lineNumber, indentRulesSupport);\n\t\tif (precedingUnIgnoredLine < 0) {\n\t\t\treturn null;\n\t\t} else if (precedingUnIgnoredLine < 1) {\n\t\t\treturn {\n\t\t\t\tindentation: '',\n\t\t\t\taction: null\n\t\t\t};\n\t\t}\n\n\t\tconst precedingUnIgnoredLineContent = model.getLineContent(precedingUnIgnoredLine);\n\t\tif (indentRulesSupport.shouldIncrease(precedingUnIgnoredLineContent) || indentRulesSupport.shouldIndentNextLine(precedingUnIgnoredLineContent)) {\n\t\t\treturn {\n\t\t\t\tindentation: strings.getLeadingWhitespace(precedingUnIgnoredLineContent),\n\t\t\t\taction: IndentAction.Indent,\n\t\t\t\tline: precedingUnIgnoredLine\n\t\t\t};\n\t\t} else if (indentRulesSupport.shouldDecrease(precedingUnIgnoredLineContent)) {\n\t\t\treturn {\n\t\t\t\tindentation: strings.getLeadingWhitespace(precedingUnIgnoredLineContent),\n\t\t\t\taction: null,\n\t\t\t\tline: precedingUnIgnoredLine\n\t\t\t};\n\t\t} else {\n\t\t\t// precedingUnIgnoredLine can not be ignored.\n\t\t\t// it doesn't increase indent of following lines\n\t\t\t// it doesn't increase just next line\n\t\t\t// so current line is not affect by precedingUnIgnoredLine\n\t\t\t// and then we should get a correct inheritted indentation from above lines\n\t\t\tif (precedingUnIgnoredLine === 1) {\n\t\t\t\treturn {\n\t\t\t\t\tindentation: strings.getLeadingWhitespace(model.getLineContent(precedingUnIgnoredLine)),\n\t\t\t\t\taction: null,\n\t\t\t\t\tline: precedingUnIgnoredLine\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst previousLine = precedingUnIgnoredLine - 1;\n\n\t\t\tconst previousLineIndentMetadata = indentRulesSupport.getIndentMetadata(model.getLineContent(previousLine));\n\t\t\tif (!(previousLineIndentMetadata & (IndentConsts.INCREASE_MASK | IndentConsts.DECREASE_MASK)) &&\n\t\t\t\t(previousLineIndentMetadata & IndentConsts.INDENT_NEXTLINE_MASK)) {\n\t\t\t\tlet stopLine = 0;\n\t\t\t\tfor (let i = previousLine - 1; i > 0; i--) {\n\t\t\t\t\tif (indentRulesSupport.shouldIndentNextLine(model.getLineContent(i))) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tstopLine = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tindentation: strings.getLeadingWhitespace(model.getLineContent(stopLine + 1)),\n\t\t\t\t\taction: null,\n\t\t\t\t\tline: stopLine + 1\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (honorIntentialIndent) {\n\t\t\t\treturn {\n\t\t\t\t\tindentation: strings.getLeadingWhitespace(model.getLineContent(precedingUnIgnoredLine)),\n\t\t\t\t\taction: null,\n\t\t\t\t\tline: precedingUnIgnoredLine\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\t// search from precedingUnIgnoredLine until we find one whose indent is not temporary\n\t\t\t\tfor (let i = precedingUnIgnoredLine; i > 0; i--) {\n\t\t\t\t\tconst lineContent = model.getLineContent(i);\n\t\t\t\t\tif (indentRulesSupport.shouldIncrease(lineContent)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tindentation: strings.getLeadingWhitespace(lineContent),\n\t\t\t\t\t\t\taction: IndentAction.Indent,\n\t\t\t\t\t\t\tline: i\n\t\t\t\t\t\t};\n\t\t\t\t\t} else if (indentRulesSupport.shouldIndentNextLine(lineContent)) {\n\t\t\t\t\t\tlet stopLine = 0;\n\t\t\t\t\t\tfor (let j = i - 1; j > 0; j--) {\n\t\t\t\t\t\t\tif (indentRulesSupport.shouldIndentNextLine(model.getLineContent(i))) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopLine = j;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tindentation: strings.getLeadingWhitespace(model.getLineContent(stopLine + 1)),\n\t\t\t\t\t\t\taction: null,\n\t\t\t\t\t\t\tline: stopLine + 1\n\t\t\t\t\t\t};\n\t\t\t\t\t} else if (indentRulesSupport.shouldDecrease(lineContent)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tindentation: strings.getLeadingWhitespace(lineContent),\n\t\t\t\t\t\t\taction: null,\n\t\t\t\t\t\t\tline: i\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tindentation: strings.getLeadingWhitespace(model.getLineContent(1)),\n\t\t\t\t\taction: null,\n\t\t\t\t\tline: 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic getGoodIndentForLine(autoIndent: EditorAutoIndentStrategy, virtualModel: IVirtualModel, languageId: string, lineNumber: number, indentConverter: IIndentConverter): string | null {\n\t\tif (autoIndent < EditorAutoIndentStrategy.Full) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst richEditSupport = this.getLanguageConfiguration(languageId);\n\t\tif (!richEditSupport) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst indentRulesSupport = this.getIndentRulesSupport(languageId);\n\t\tif (!indentRulesSupport) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst indent = this.getInheritIndentForLine(autoIndent, virtualModel, lineNumber);\n\t\tconst lineContent = virtualModel.getLineContent(lineNumber);\n\n\t\tif (indent) {\n\t\t\tconst inheritLine = indent.line;\n\t\t\tif (inheritLine !== undefined) {\n\t\t\t\tconst enterResult = richEditSupport.onEnter(autoIndent, '', virtualModel.getLineContent(inheritLine), '');\n\n\t\t\t\tif (enterResult) {\n\t\t\t\t\tlet indentation = strings.getLeadingWhitespace(virtualModel.getLineContent(inheritLine));\n\n\t\t\t\t\tif (enterResult.removeText) {\n\t\t\t\t\t\tindentation = indentation.substring(0, indentation.length - enterResult.removeText);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t(enterResult.indentAction === IndentAction.Indent) ||\n\t\t\t\t\t\t(enterResult.indentAction === IndentAction.IndentOutdent)\n\t\t\t\t\t) {\n\t\t\t\t\t\tindentation = indentConverter.shiftIndent(indentation);\n\t\t\t\t\t} else if (enterResult.indentAction === IndentAction.Outdent) {\n\t\t\t\t\t\tindentation = indentConverter.unshiftIndent(indentation);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (indentRulesSupport.shouldDecrease(lineContent)) {\n\t\t\t\t\t\tindentation = indentConverter.unshiftIndent(indentation);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (enterResult.appendText) {\n\t\t\t\t\t\tindentation += enterResult.appendText;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn strings.getLeadingWhitespace(indentation);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (indentRulesSupport.shouldDecrease(lineContent)) {\n\t\t\t\tif (indent.action === IndentAction.Indent) {\n\t\t\t\t\treturn indent.indentation;\n\t\t\t\t} else {\n\t\t\t\t\treturn indentConverter.unshiftIndent(indent.indentation);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (indent.action === IndentAction.Indent) {\n\t\t\t\t\treturn indentConverter.shiftIndent(indent.indentation);\n\t\t\t\t} else {\n\t\t\t\t\treturn indent.indentation;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic getIndentForEnter(autoIndent: EditorAutoIndentStrategy, model: ITextModel, range: Range, indentConverter: IIndentConverter): { beforeEnter: string, afterEnter: string } | null {\n\t\tif (autoIndent < EditorAutoIndentStrategy.Full) {\n\t\t\treturn null;\n\t\t}\n\t\tmodel.forceTokenization(range.startLineNumber);\n\t\tconst lineTokens = model.getLineTokens(range.startLineNumber);\n\t\tconst scopedLineTokens = createScopedLineTokens(lineTokens, range.startColumn - 1);\n\t\tconst scopedLineText = scopedLineTokens.getLineContent();\n\n\t\tlet embeddedLanguage = false;\n\t\tlet beforeEnterText: string;\n\t\tif (scopedLineTokens.firstCharOffset > 0 && lineTokens.getLanguageId(0) !== scopedLineTokens.languageId) {\n\t\t\t// we are in the embeded language content\n\t\t\tembeddedLanguage = true; // if embeddedLanguage is true, then we don't touch the indentation of current line\n\t\t\tbeforeEnterText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n\t\t} else {\n\t\t\tbeforeEnterText = lineTokens.getLineContent().substring(0, range.startColumn - 1);\n\t\t}\n\n\t\tlet afterEnterText: string;\n\t\tif (range.isEmpty()) {\n\t\t\tafterEnterText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n\t\t} else {\n\t\t\tconst endScopedLineTokens = this.getScopedLineTokens(model, range.endLineNumber, range.endColumn);\n\t\t\tafterEnterText = endScopedLineTokens.getLineContent().substr(range.endColumn - 1 - scopedLineTokens.firstCharOffset);\n\t\t}\n\n\t\tconst indentRulesSupport = this.getIndentRulesSupport(scopedLineTokens.languageId);\n\t\tif (!indentRulesSupport) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst beforeEnterResult = beforeEnterText;\n\t\tconst beforeEnterIndent = strings.getLeadingWhitespace(beforeEnterText);\n\n\t\tconst virtualModel: IVirtualModel = {\n\t\t\tgetLineTokens: (lineNumber: number) => {\n\t\t\t\treturn model.getLineTokens(lineNumber);\n\t\t\t},\n\t\t\tgetLanguageId: () => {\n\t\t\t\treturn model.getLanguageId();\n\t\t\t},\n\t\t\tgetLanguageIdAtPosition: (lineNumber: number, column: number) => {\n\t\t\t\treturn model.getLanguageIdAtPosition(lineNumber, column);\n\t\t\t},\n\t\t\tgetLineContent: (lineNumber: number) => {\n\t\t\t\tif (lineNumber === range.startLineNumber) {\n\t\t\t\t\treturn beforeEnterResult;\n\t\t\t\t} else {\n\t\t\t\t\treturn model.getLineContent(lineNumber);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tconst currentLineIndent = strings.getLeadingWhitespace(lineTokens.getLineContent());\n\t\tconst afterEnterAction = this.getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1);\n\t\tif (!afterEnterAction) {\n\t\t\tconst beforeEnter = embeddedLanguage ? currentLineIndent : beforeEnterIndent;\n\t\t\treturn {\n\t\t\t\tbeforeEnter: beforeEnter,\n\t\t\t\tafterEnter: beforeEnter\n\t\t\t};\n\t\t}\n\n\t\tlet afterEnterIndent = embeddedLanguage ? currentLineIndent : afterEnterAction.indentation;\n\n\t\tif (afterEnterAction.action === IndentAction.Indent) {\n\t\t\tafterEnterIndent = indentConverter.shiftIndent(afterEnterIndent);\n\t\t}\n\n\t\tif (indentRulesSupport.shouldDecrease(afterEnterText)) {\n\t\t\tafterEnterIndent = indentConverter.unshiftIndent(afterEnterIndent);\n\t\t}\n\n\t\treturn {\n\t\t\tbeforeEnter: embeddedLanguage ? currentLineIndent : beforeEnterIndent,\n\t\t\tafterEnter: afterEnterIndent\n\t\t};\n\t}\n\n\t/**\n\t * We should always allow intentional indentation. It means, if users change the indentation of `lineNumber` and the content of\n\t * this line doesn't match decreaseIndentPattern, we should not adjust the indentation.\n\t */\n\tpublic getIndentActionForType(autoIndent: EditorAutoIndentStrategy, model: ITextModel, range: Range, ch: string, indentConverter: IIndentConverter): string | null {\n\t\tif (autoIndent < EditorAutoIndentStrategy.Full) {\n\t\t\treturn null;\n\t\t}\n\t\tconst scopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber, range.startColumn);\n\n\t\tif (scopedLineTokens.firstCharOffset) {\n\t\t\t// this line has mixed languages and indentation rules will not work\n\t\t\treturn null;\n\t\t}\n\n\t\tconst indentRulesSupport = this.getIndentRulesSupport(scopedLineTokens.languageId);\n\t\tif (!indentRulesSupport) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst scopedLineText = scopedLineTokens.getLineContent();\n\t\tconst beforeTypeText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n\n\t\t// selection support\n\t\tlet afterTypeText: string;\n\t\tif (range.isEmpty()) {\n\t\t\tafterTypeText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n\t\t} else {\n\t\t\tconst endScopedLineTokens = this.getScopedLineTokens(model, range.endLineNumber, range.endColumn);\n\t\t\tafterTypeText = endScopedLineTokens.getLineContent().substr(range.endColumn - 1 - scopedLineTokens.firstCharOffset);\n\t\t}\n\n\t\t// If previous content already matches decreaseIndentPattern, it means indentation of this line should already be adjusted\n\t\t// Users might change the indentation by purpose and we should honor that instead of readjusting.\n\t\tif (!indentRulesSupport.shouldDecrease(beforeTypeText + afterTypeText) && indentRulesSupport.shouldDecrease(beforeTypeText + ch + afterTypeText)) {\n\t\t\t// after typing `ch`, the content matches decreaseIndentPattern, we should adjust the indent to a good manner.\n\t\t\t// 1. Get inherited indent action\n\t\t\tconst r = this.getInheritIndentForLine(autoIndent, model, range.startLineNumber, false);\n\t\t\tif (!r) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tlet indentation = r.indentation;\n\t\t\tif (r.action !== IndentAction.Indent) {\n\t\t\t\tindentation = indentConverter.unshiftIndent(indentation);\n\t\t\t}\n\n\t\t\treturn indentation;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic getIndentMetadata(model: ITextModel, lineNumber: number): number | null {\n\t\tconst indentRulesSupport = this.getIndentRulesSupport(model.getLanguageId());\n\t\tif (!indentRulesSupport) {\n\t\t\treturn null;\n\t\t}\n\t\tif (lineNumber < 1 || lineNumber > model.getLineCount()) {\n\t\t\treturn null;\n\t\t}\n\t\treturn indentRulesSupport.getIndentMetadata(model.getLineContent(lineNumber));\n\t}\n\n\t// end Indent Rules\n\n\t// begin onEnter\n\n\tpublic getEnterAction(autoIndent: EditorAutoIndentStrategy, model: ITextModel, range: Range): CompleteEnterAction | null {\n\t\tconst scopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber, range.startColumn);\n\t\tconst richEditSupport = this.getLanguageConfiguration(scopedLineTokens.languageId);\n\t\tif (!richEditSupport) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst scopedLineText = scopedLineTokens.getLineContent();\n\t\tconst beforeEnterText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n\n\t\t// selection support\n\t\tlet afterEnterText: string;\n\t\tif (range.isEmpty()) {\n\t\t\tafterEnterText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n\t\t} else {\n\t\t\tconst endScopedLineTokens = this.getScopedLineTokens(model, range.endLineNumber, range.endColumn);\n\t\t\tafterEnterText = endScopedLineTokens.getLineContent().substr(range.endColumn - 1 - scopedLineTokens.firstCharOffset);\n\t\t}\n\n\t\tlet previousLineText = '';\n\t\tif (range.startLineNumber > 1 && scopedLineTokens.firstCharOffset === 0) {\n\t\t\t// This is not the first line and the entire line belongs to this mode\n\t\t\tconst oneLineAboveScopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber - 1);\n\t\t\tif (oneLineAboveScopedLineTokens.languageId === scopedLineTokens.languageId) {\n\t\t\t\t// The line above ends with text belonging to the same mode\n\t\t\t\tpreviousLineText = oneLineAboveScopedLineTokens.getLineContent();\n\t\t\t}\n\t\t}\n\n\t\tconst enterResult = richEditSupport.onEnter(autoIndent, previousLineText, beforeEnterText, afterEnterText);\n\t\tif (!enterResult) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst indentAction = enterResult.indentAction;\n\t\tlet appendText = enterResult.appendText;\n\t\tconst removeText = enterResult.removeText || 0;\n\n\t\t// Here we add `\\t` to appendText first because enterAction is leveraging appendText and removeText to change indentation.\n\t\tif (!appendText) {\n\t\t\tif (\n\t\t\t\t(indentAction === IndentAction.Indent) ||\n\t\t\t\t(indentAction === IndentAction.IndentOutdent)\n\t\t\t) {\n\t\t\t\tappendText = '\\t';\n\t\t\t} else {\n\t\t\t\tappendText = '';\n\t\t\t}\n\t\t} else if (indentAction === IndentAction.Indent) {\n\t\t\tappendText = '\\t' + appendText;\n\t\t}\n\n\t\tlet indentation = this.getIndentationAtPosition(model, range.startLineNumber, range.startColumn);\n\t\tif (removeText) {\n\t\t\tindentation = indentation.substring(0, indentation.length - removeText);\n\t\t}\n\n\t\treturn {\n\t\t\tindentAction: indentAction,\n\t\t\tappendText: appendText,\n\t\t\tremoveText: removeText,\n\t\t\tindentation: indentation\n\t\t};\n\t}\n\n\tpublic getIndentationAtPosition(model: ITextModel, lineNumber: number, column: number): string {\n\t\tconst lineText = model.getLineContent(lineNumber);\n\t\tlet indentation = strings.getLeadingWhitespace(lineText);\n\t\tif (indentation.length > column - 1) {\n\t\t\tindentation = indentation.substring(0, column - 1);\n\t\t}\n\t\treturn indentation;\n\t}\n\n\tprivate getScopedLineTokens(model: ITextModel, lineNumber: number, columnNumber?: number): ScopedLineTokens {\n\t\tmodel.forceTokenization(lineNumber);\n\t\tconst lineTokens = model.getLineTokens(lineNumber);\n\t\tconst column = (typeof columnNumber === 'undefined' ? model.getLineMaxColumn(lineNumber) - 1 : columnNumber - 1);\n\t\treturn createScopedLineTokens(lineTokens, column);\n\t}\n}\n\n/**\n * @deprecated Use ILanguageConfigurationService instead.\n*/\nexport const LanguageConfigurationRegistry = new LanguageConfigurationRegistryImpl();\n\nclass ComposedLanguageConfiguration {\n\tprivate readonly _entries: LanguageConfigurationContribution[];\n\tprivate _order: number;\n\tprivate _resolved: ResolvedLanguageConfiguration | null = null;\n\n\tconstructor(public readonly languageId: string) {\n\t\tthis._entries = [];\n\t\tthis._order = 0;\n\t\tthis._resolved = null;\n\t}\n\n\tpublic register(\n\t\tconfiguration: LanguageConfiguration,\n\t\tpriority: number\n\t): IDisposable {\n\t\tconst entry = new LanguageConfigurationContribution(\n\t\t\tconfiguration,\n\t\t\tpriority,\n\t\t\t++this._order\n\t\t);\n\t\tthis._entries.push(entry);\n\t\tthis._resolved = null;\n\t\treturn toDisposable(() => {\n\t\t\tfor (let i = 0; i < this._entries.length; i++) {\n\t\t\t\tif (this._entries[i] === entry) {\n\t\t\t\t\tthis._entries.splice(i, 1);\n\t\t\t\t\tthis._resolved = null;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic getResolvedConfiguration(): ResolvedLanguageConfiguration | null {\n\t\tif (!this._resolved) {\n\t\t\tconst config = this._resolve();\n\t\t\tif (config) {\n\t\t\t\tthis._resolved = new ResolvedLanguageConfiguration(\n\t\t\t\t\tthis.languageId,\n\t\t\t\t\tconfig\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn this._resolved;\n\t}\n\n\tprivate _resolve(): LanguageConfiguration | null {\n\t\tif (this._entries.length === 0) {\n\t\t\treturn null;\n\t\t}\n\t\tthis._entries.sort(LanguageConfigurationContribution.cmp);\n\t\treturn combineLanguageConfigurations(this._entries.map(e => e.configuration));\n\t}\n}\n\nfunction combineLanguageConfigurations(configs: LanguageConfiguration[]): LanguageConfiguration {\n\tlet result: ExplicitLanguageConfiguration = {\n\t\tcomments: undefined,\n\t\tbrackets: undefined,\n\t\twordPattern: undefined,\n\t\tindentationRules: undefined,\n\t\tonEnterRules: undefined,\n\t\tautoClosingPairs: undefined,\n\t\tsurroundingPairs: undefined,\n\t\tautoCloseBefore: undefined,\n\t\tfolding: undefined,\n\t\tcolorizedBracketPairs: undefined,\n\t\t__electricCharacterSupport: undefined,\n\t};\n\tfor (const entry of configs) {\n\t\tresult = {\n\t\t\tcomments: entry.comments || result.comments,\n\t\t\tbrackets: entry.brackets || result.brackets,\n\t\t\twordPattern: entry.wordPattern || result.wordPattern,\n\t\t\tindentationRules: entry.indentationRules || result.indentationRules,\n\t\t\tonEnterRules: entry.onEnterRules || result.onEnterRules,\n\t\t\tautoClosingPairs: entry.autoClosingPairs || result.autoClosingPairs,\n\t\t\tsurroundingPairs: entry.surroundingPairs || result.surroundingPairs,\n\t\t\tautoCloseBefore: entry.autoCloseBefore || result.autoCloseBefore,\n\t\t\tfolding: entry.folding || result.folding,\n\t\t\tcolorizedBracketPairs: entry.colorizedBracketPairs || result.colorizedBracketPairs,\n\t\t\t__electricCharacterSupport: entry.__electricCharacterSupport || result.__electricCharacterSupport,\n\t\t};\n\t}\n\n\treturn result;\n}\n\nclass LanguageConfigurationContribution {\n\tconstructor(\n\t\tpublic readonly configuration: LanguageConfiguration,\n\t\tpublic readonly priority: number,\n\t\tpublic readonly order: number\n\t) { }\n\n\tpublic static cmp(a: LanguageConfigurationContribution, b: LanguageConfigurationContribution) {\n\t\tif (a.priority === b.priority) {\n\t\t\t// higher order last\n\t\t\treturn a.order - b.order;\n\t\t}\n\t\t// higher priority last\n\t\treturn a.priority - b.priority;\n\t}\n}\n\n/**\n * Immutable.\n*/\nexport class ResolvedLanguageConfiguration {\n\tprivate _brackets: RichEditBrackets | null;\n\tprivate _electricCharacter: BracketElectricCharacterSupport | null;\n\tprivate readonly _onEnterSupport: OnEnterSupport | null;\n\n\tpublic readonly comments: ICommentsConfiguration | null;\n\tpublic readonly characterPair: CharacterPairSupport;\n\tpublic readonly wordDefinition: RegExp;\n\tpublic readonly indentRulesSupport: IndentRulesSupport | null;\n\tpublic readonly indentationRules: IndentationRule | undefined;\n\tpublic readonly foldingRules: FoldingRules;\n\n\tconstructor(\n\t\tpublic readonly languageId: string,\n\t\tpublic readonly underlyingConfig: LanguageConfiguration\n\t) {\n\t\tthis._brackets = null;\n\t\tthis._electricCharacter = null;\n\t\tthis._onEnterSupport =\n\t\t\tthis.underlyingConfig.brackets ||\n\t\t\t\tthis.underlyingConfig.indentationRules ||\n\t\t\t\tthis.underlyingConfig.onEnterRules\n\t\t\t\t? new OnEnterSupport(this.underlyingConfig)\n\t\t\t\t: null;\n\t\tthis.comments = ResolvedLanguageConfiguration._handleComments(this.underlyingConfig);\n\t\tthis.characterPair = new CharacterPairSupport(this.underlyingConfig);\n\n\t\tthis.wordDefinition = this.underlyingConfig.wordPattern || DEFAULT_WORD_REGEXP;\n\t\tthis.indentationRules = this.underlyingConfig.indentationRules;\n\t\tif (this.underlyingConfig.indentationRules) {\n\t\t\tthis.indentRulesSupport = new IndentRulesSupport(\n\t\t\t\tthis.underlyingConfig.indentationRules\n\t\t\t);\n\t\t} else {\n\t\t\tthis.indentRulesSupport = null;\n\t\t}\n\t\tthis.foldingRules = this.underlyingConfig.folding || {};\n\t}\n\n\tpublic getWordDefinition(): RegExp {\n\t\treturn ensureValidWordDefinition(this.wordDefinition);\n\t}\n\n\tpublic get brackets(): RichEditBrackets | null {\n\t\tif (!this._brackets && this.underlyingConfig.brackets) {\n\t\t\tthis._brackets = new RichEditBrackets(\n\t\t\t\tthis.languageId,\n\t\t\t\tthis.underlyingConfig.brackets\n\t\t\t);\n\t\t}\n\t\treturn this._brackets;\n\t}\n\n\tpublic get electricCharacter(): BracketElectricCharacterSupport | null {\n\t\tif (!this._electricCharacter) {\n\t\t\tthis._electricCharacter = new BracketElectricCharacterSupport(\n\t\t\t\tthis.brackets\n\t\t\t);\n\t\t}\n\t\treturn this._electricCharacter;\n\t}\n\n\tpublic onEnter(\n\t\tautoIndent: EditorAutoIndentStrategy,\n\t\tpreviousLineText: string,\n\t\tbeforeEnterText: string,\n\t\tafterEnterText: string\n\t): EnterAction | null {\n\t\tif (!this._onEnterSupport) {\n\t\t\treturn null;\n\t\t}\n\t\treturn this._onEnterSupport.onEnter(\n\t\t\tautoIndent,\n\t\t\tpreviousLineText,\n\t\t\tbeforeEnterText,\n\t\t\tafterEnterText\n\t\t);\n\t}\n\n\tpublic getAutoClosingPairs(): AutoClosingPairs {\n\t\treturn new AutoClosingPairs(this.characterPair.getAutoClosingPairs());\n\t}\n\n\tpublic getAutoCloseBeforeSet(): string {\n\t\treturn this.characterPair.getAutoCloseBeforeSet();\n\t}\n\n\tpublic getSurroundingPairs(): IAutoClosingPair[] {\n\t\treturn this.characterPair.getSurroundingPairs();\n\t}\n\n\tprivate static _handleComments(\n\t\tconf: LanguageConfiguration\n\t): ICommentsConfiguration | null {\n\t\tconst commentRule = conf.comments;\n\t\tif (!commentRule) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// comment configuration\n\t\tconst comments: ICommentsConfiguration = {};\n\n\t\tif (commentRule.lineComment) {\n\t\t\tcomments.lineCommentToken = commentRule.lineComment;\n\t\t}\n\t\tif (commentRule.blockComment) {\n\t\t\tconst [blockStart, blockEnd] = commentRule.blockComment;\n\t\t\tcomments.blockCommentStartToken = blockStart;\n\t\t\tcomments.blockCommentEndToken = blockEnd;\n\t\t}\n\n\t\treturn comments;\n\t}\n}\n\nregisterSingleton(ILanguageConfigurationService, LanguageConfigurationService);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport * as strings from 'vs/base/common/strings';\nimport { CursorColumns } from 'vs/editor/common/core/cursorColumns';\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection, SelectionDirection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { LanguageConfigurationRegistry } from 'vs/editor/common/languages/languageConfigurationRegistry';\nimport { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';\n\nexport interface IShiftCommandOpts {\n\tisUnshift: boolean;\n\ttabSize: number;\n\tindentSize: number;\n\tinsertSpaces: boolean;\n\tuseTabStops: boolean;\n\tautoIndent: EditorAutoIndentStrategy;\n}\n\nconst repeatCache: { [str: string]: string[]; } = Object.create(null);\nexport function cachedStringRepeat(str: string, count: number): string {\n\tif (count <= 0) {\n\t\treturn '';\n\t}\n\tif (!repeatCache[str]) {\n\t\trepeatCache[str] = ['', str];\n\t}\n\tconst cache = repeatCache[str];\n\tfor (let i = cache.length; i <= count; i++) {\n\t\tcache[i] = cache[i - 1] + str;\n\t}\n\treturn cache[count];\n}\n\nexport class ShiftCommand implements ICommand {\n\n\tpublic static unshiftIndent(line: string, column: number, tabSize: number, indentSize: number, insertSpaces: boolean): string {\n\t\t// Determine the visible column where the content starts\n\t\tconst contentStartVisibleColumn = CursorColumns.visibleColumnFromColumn(line, column, tabSize);\n\n\t\tif (insertSpaces) {\n\t\t\tconst indent = cachedStringRepeat(' ', indentSize);\n\t\t\tconst desiredTabStop = CursorColumns.prevIndentTabStop(contentStartVisibleColumn, indentSize);\n\t\t\tconst indentCount = desiredTabStop / indentSize; // will be an integer\n\t\t\treturn cachedStringRepeat(indent, indentCount);\n\t\t} else {\n\t\t\tconst indent = '\\t';\n\t\t\tconst desiredTabStop = CursorColumns.prevRenderTabStop(contentStartVisibleColumn, tabSize);\n\t\t\tconst indentCount = desiredTabStop / tabSize; // will be an integer\n\t\t\treturn cachedStringRepeat(indent, indentCount);\n\t\t}\n\t}\n\n\tpublic static shiftIndent(line: string, column: number, tabSize: number, indentSize: number, insertSpaces: boolean): string {\n\t\t// Determine the visible column where the content starts\n\t\tconst contentStartVisibleColumn = CursorColumns.visibleColumnFromColumn(line, column, tabSize);\n\n\t\tif (insertSpaces) {\n\t\t\tconst indent = cachedStringRepeat(' ', indentSize);\n\t\t\tconst desiredTabStop = CursorColumns.nextIndentTabStop(contentStartVisibleColumn, indentSize);\n\t\t\tconst indentCount = desiredTabStop / indentSize; // will be an integer\n\t\t\treturn cachedStringRepeat(indent, indentCount);\n\t\t} else {\n\t\t\tconst indent = '\\t';\n\t\t\tconst desiredTabStop = CursorColumns.nextRenderTabStop(contentStartVisibleColumn, tabSize);\n\t\t\tconst indentCount = desiredTabStop / tabSize; // will be an integer\n\t\t\treturn cachedStringRepeat(indent, indentCount);\n\t\t}\n\t}\n\n\tprivate readonly _opts: IShiftCommandOpts;\n\tprivate readonly _selection: Selection;\n\tprivate _selectionId: string | null;\n\tprivate _useLastEditRangeForCursorEndPosition: boolean;\n\tprivate _selectionStartColumnStaysPut: boolean;\n\n\tconstructor(range: Selection, opts: IShiftCommandOpts) {\n\t\tthis._opts = opts;\n\t\tthis._selection = range;\n\t\tthis._selectionId = null;\n\t\tthis._useLastEditRangeForCursorEndPosition = false;\n\t\tthis._selectionStartColumnStaysPut = false;\n\t}\n\n\tprivate _addEditOperation(builder: IEditOperationBuilder, range: Range, text: string) {\n\t\tif (this._useLastEditRangeForCursorEndPosition) {\n\t\t\tbuilder.addTrackedEditOperation(range, text);\n\t\t} else {\n\t\t\tbuilder.addEditOperation(range, text);\n\t\t}\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\t\tconst startLine = this._selection.startLineNumber;\n\n\t\tlet endLine = this._selection.endLineNumber;\n\t\tif (this._selection.endColumn === 1 && startLine !== endLine) {\n\t\t\tendLine = endLine - 1;\n\t\t}\n\n\t\tconst { tabSize, indentSize, insertSpaces } = this._opts;\n\t\tconst shouldIndentEmptyLines = (startLine === endLine);\n\n\t\tif (this._opts.useTabStops) {\n\t\t\t// if indenting or outdenting on a whitespace only line\n\t\t\tif (this._selection.isEmpty()) {\n\t\t\t\tif (/^\\s*$/.test(model.getLineContent(startLine))) {\n\t\t\t\t\tthis._useLastEditRangeForCursorEndPosition = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// keep track of previous line's \"miss-alignment\"\n\t\t\tlet previousLineExtraSpaces = 0, extraSpaces = 0;\n\t\t\tfor (let lineNumber = startLine; lineNumber <= endLine; lineNumber++, previousLineExtraSpaces = extraSpaces) {\n\t\t\t\textraSpaces = 0;\n\t\t\t\tconst lineText = model.getLineContent(lineNumber);\n\t\t\t\tlet indentationEndIndex = strings.firstNonWhitespaceIndex(lineText);\n\n\t\t\t\tif (this._opts.isUnshift && (lineText.length === 0 || indentationEndIndex === 0)) {\n\t\t\t\t\t// empty line or line with no leading whitespace => nothing to do\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!shouldIndentEmptyLines && !this._opts.isUnshift && lineText.length === 0) {\n\t\t\t\t\t// do not indent empty lines => nothing to do\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (indentationEndIndex === -1) {\n\t\t\t\t\t// the entire line is whitespace\n\t\t\t\t\tindentationEndIndex = lineText.length;\n\t\t\t\t}\n\n\t\t\t\tif (lineNumber > 1) {\n\t\t\t\t\tconst contentStartVisibleColumn = CursorColumns.visibleColumnFromColumn(lineText, indentationEndIndex + 1, tabSize);\n\t\t\t\t\tif (contentStartVisibleColumn % indentSize !== 0) {\n\t\t\t\t\t\t// The current line is \"miss-aligned\", so let's see if this is expected...\n\t\t\t\t\t\t// This can only happen when it has trailing commas in the indent\n\t\t\t\t\t\tif (model.isCheapToTokenize(lineNumber - 1)) {\n\t\t\t\t\t\t\tconst enterAction = LanguageConfigurationRegistry.getEnterAction(this._opts.autoIndent, model, new Range(lineNumber - 1, model.getLineMaxColumn(lineNumber - 1), lineNumber - 1, model.getLineMaxColumn(lineNumber - 1)));\n\t\t\t\t\t\t\tif (enterAction) {\n\t\t\t\t\t\t\t\textraSpaces = previousLineExtraSpaces;\n\t\t\t\t\t\t\t\tif (enterAction.appendText) {\n\t\t\t\t\t\t\t\t\tfor (let j = 0, lenJ = enterAction.appendText.length; j < lenJ && extraSpaces < indentSize; j++) {\n\t\t\t\t\t\t\t\t\t\tif (enterAction.appendText.charCodeAt(j) === CharCode.Space) {\n\t\t\t\t\t\t\t\t\t\t\textraSpaces++;\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (enterAction.removeText) {\n\t\t\t\t\t\t\t\t\textraSpaces = Math.max(0, extraSpaces - enterAction.removeText);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Act as if `prefixSpaces` is not part of the indentation\n\t\t\t\t\t\t\t\tfor (let j = 0; j < extraSpaces; j++) {\n\t\t\t\t\t\t\t\t\tif (indentationEndIndex === 0 || lineText.charCodeAt(indentationEndIndex - 1) !== CharCode.Space) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tindentationEndIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\tif (this._opts.isUnshift && indentationEndIndex === 0) {\n\t\t\t\t\t// line with no leading whitespace => nothing to do\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tlet desiredIndent: string;\n\t\t\t\tif (this._opts.isUnshift) {\n\t\t\t\t\tdesiredIndent = ShiftCommand.unshiftIndent(lineText, indentationEndIndex + 1, tabSize, indentSize, insertSpaces);\n\t\t\t\t} else {\n\t\t\t\t\tdesiredIndent = ShiftCommand.shiftIndent(lineText, indentationEndIndex + 1, tabSize, indentSize, insertSpaces);\n\t\t\t\t}\n\n\t\t\t\tthis._addEditOperation(builder, new Range(lineNumber, 1, lineNumber, indentationEndIndex + 1), desiredIndent);\n\t\t\t\tif (lineNumber === startLine && !this._selection.isEmpty()) {\n\t\t\t\t\t// Force the startColumn to stay put because we're inserting after it\n\t\t\t\t\tthis._selectionStartColumnStaysPut = (this._selection.startColumn <= indentationEndIndex + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\t// if indenting or outdenting on a whitespace only line\n\t\t\tif (!this._opts.isUnshift && this._selection.isEmpty() && model.getLineLength(startLine) === 0) {\n\t\t\t\tthis._useLastEditRangeForCursorEndPosition = true;\n\t\t\t}\n\n\t\t\tconst oneIndent = (insertSpaces ? cachedStringRepeat(' ', indentSize) : '\\t');\n\n\t\t\tfor (let lineNumber = startLine; lineNumber <= endLine; lineNumber++) {\n\t\t\t\tconst lineText = model.getLineContent(lineNumber);\n\t\t\t\tlet indentationEndIndex = strings.firstNonWhitespaceIndex(lineText);\n\n\t\t\t\tif (this._opts.isUnshift && (lineText.length === 0 || indentationEndIndex === 0)) {\n\t\t\t\t\t// empty line or line with no leading whitespace => nothing to do\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!shouldIndentEmptyLines && !this._opts.isUnshift && lineText.length === 0) {\n\t\t\t\t\t// do not indent empty lines => nothing to do\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (indentationEndIndex === -1) {\n\t\t\t\t\t// the entire line is whitespace\n\t\t\t\t\tindentationEndIndex = lineText.length;\n\t\t\t\t}\n\n\t\t\t\tif (this._opts.isUnshift && indentationEndIndex === 0) {\n\t\t\t\t\t// line with no leading whitespace => nothing to do\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (this._opts.isUnshift) {\n\n\t\t\t\t\tindentationEndIndex = Math.min(indentationEndIndex, indentSize);\n\t\t\t\t\tfor (let i = 0; i < indentationEndIndex; i++) {\n\t\t\t\t\t\tconst chr = lineText.charCodeAt(i);\n\t\t\t\t\t\tif (chr === CharCode.Tab) {\n\t\t\t\t\t\t\tindentationEndIndex = i + 1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._addEditOperation(builder, new Range(lineNumber, 1, lineNumber, indentationEndIndex + 1), '');\n\t\t\t\t} else {\n\t\t\t\t\tthis._addEditOperation(builder, new Range(lineNumber, 1, lineNumber, 1), oneIndent);\n\t\t\t\t\tif (lineNumber === startLine && !this._selection.isEmpty()) {\n\t\t\t\t\t\t// Force the startColumn to stay put because we're inserting after it\n\t\t\t\t\t\tthis._selectionStartColumnStaysPut = (this._selection.startColumn === 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._selectionId = builder.trackSelection(this._selection);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tif (this._useLastEditRangeForCursorEndPosition) {\n\t\t\tconst lastOp = helper.getInverseEditOperations()[0];\n\t\t\treturn new Selection(lastOp.range.endLineNumber, lastOp.range.endColumn, lastOp.range.endLineNumber, lastOp.range.endColumn);\n\t\t}\n\t\tconst result = helper.getTrackedSelection(this._selectionId!);\n\n\t\tif (this._selectionStartColumnStaysPut) {\n\t\t\t// The selection start should not move\n\t\t\tconst initialStartColumn = this._selection.startColumn;\n\t\t\tconst resultStartColumn = result.startColumn;\n\t\t\tif (resultStartColumn <= initialStartColumn) {\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tif (result.getDirection() === SelectionDirection.LTR) {\n\t\t\t\treturn new Selection(result.startLineNumber, initialStartColumn, result.endLineNumber, result.endColumn);\n\t\t\t}\n\t\t\treturn new Selection(result.endLineNumber, result.endColumn, result.startLineNumber, initialStartColumn);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport * as strings from 'vs/base/common/strings';\nimport { Constants } from 'vs/base/common/uint';\nimport { EditOperation } from 'vs/editor/common/core/editOperation';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model';\nimport { ILanguageConfigurationService, LanguageConfigurationRegistry } from 'vs/editor/common/languages/languageConfigurationRegistry';\nimport { BlockCommentCommand } from 'vs/editor/contrib/comment/browser/blockCommentCommand';\n\nexport interface IInsertionPoint {\n\tignore: boolean;\n\tcommentStrOffset: number;\n}\n\nexport interface ILinePreflightData {\n\tignore: boolean;\n\tcommentStr: string;\n\tcommentStrOffset: number;\n\tcommentStrLength: number;\n}\n\nexport interface IPreflightDataSupported {\n\tsupported: true;\n\tshouldRemoveComments: boolean;\n\tlines: ILinePreflightData[];\n}\nexport interface IPreflightDataUnsupported {\n\tsupported: false;\n}\nexport type IPreflightData = IPreflightDataSupported | IPreflightDataUnsupported;\n\nexport interface ISimpleModel {\n\tgetLineContent(lineNumber: number): string;\n}\n\nexport const enum Type {\n\tToggle = 0,\n\tForceAdd = 1,\n\tForceRemove = 2\n}\n\nexport class LineCommentCommand implements ICommand {\n\n\tprivate readonly _selection: Selection;\n\tprivate readonly _tabSize: number;\n\tprivate readonly _type: Type;\n\tprivate readonly _insertSpace: boolean;\n\tprivate readonly _ignoreEmptyLines: boolean;\n\tprivate _selectionId: string | null;\n\tprivate _deltaColumn: number;\n\tprivate _moveEndPositionDown: boolean;\n\tprivate _ignoreFirstLine: boolean;\n\n\tconstructor(\n\t\tprivate readonly languageConfigurationService: ILanguageConfigurationService,\n\t\tselection: Selection,\n\t\ttabSize: number,\n\t\ttype: Type,\n\t\tinsertSpace: boolean,\n\t\tignoreEmptyLines: boolean,\n\t\tignoreFirstLine?: boolean,\n\t) {\n\t\tthis._selection = selection;\n\t\tthis._tabSize = tabSize;\n\t\tthis._type = type;\n\t\tthis._insertSpace = insertSpace;\n\t\tthis._selectionId = null;\n\t\tthis._deltaColumn = 0;\n\t\tthis._moveEndPositionDown = false;\n\t\tthis._ignoreEmptyLines = ignoreEmptyLines;\n\t\tthis._ignoreFirstLine = ignoreFirstLine || false;\n\t}\n\n\t/**\n\t * Do an initial pass over the lines and gather info about the line comment string.\n\t * Returns null if any of the lines doesn't support a line comment string.\n\t */\n\tprivate static _gatherPreflightCommentStrings(model: ITextModel, startLineNumber: number, endLineNumber: number, languageConfigurationService: ILanguageConfigurationService): ILinePreflightData[] | null {\n\n\t\tmodel.tokenizeIfCheap(startLineNumber);\n\t\tconst languageId = model.getLanguageIdAtPosition(startLineNumber, 1);\n\n\t\tconst config = languageConfigurationService.getLanguageConfiguration(languageId).comments;\n\t\tconst commentStr = (config ? config.lineCommentToken : null);\n\t\tif (!commentStr) {\n\t\t\t// Mode does not support line comments\n\t\t\treturn null;\n\t\t}\n\n\t\tlet lines: ILinePreflightData[] = [];\n\t\tfor (let i = 0, lineCount = endLineNumber - startLineNumber + 1; i < lineCount; i++) {\n\t\t\tlines[i] = {\n\t\t\t\tignore: false,\n\t\t\t\tcommentStr: commentStr,\n\t\t\t\tcommentStrOffset: 0,\n\t\t\t\tcommentStrLength: commentStr.length\n\t\t\t};\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Analyze lines and decide which lines are relevant and what the toggle should do.\n\t * Also, build up several offsets and lengths useful in the generation of editor operations.\n\t */\n\tpublic static _analyzeLines(type: Type, insertSpace: boolean, model: ISimpleModel, lines: ILinePreflightData[], startLineNumber: number, ignoreEmptyLines: boolean, ignoreFirstLine: boolean, languageConfigurationService: ILanguageConfigurationService): IPreflightData {\n\t\tlet onlyWhitespaceLines = true;\n\n\t\tlet shouldRemoveComments: boolean;\n\t\tif (type === Type.Toggle) {\n\t\t\tshouldRemoveComments = true;\n\t\t} else if (type === Type.ForceAdd) {\n\t\t\tshouldRemoveComments = false;\n\t\t} else {\n\t\t\tshouldRemoveComments = true;\n\t\t}\n\n\t\tfor (let i = 0, lineCount = lines.length; i < lineCount; i++) {\n\t\t\tconst lineData = lines[i];\n\t\t\tconst lineNumber = startLineNumber + i;\n\n\t\t\tif (lineNumber === startLineNumber && ignoreFirstLine) {\n\t\t\t\t// first line ignored\n\t\t\t\tlineData.ignore = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst lineContent = model.getLineContent(lineNumber);\n\t\t\tconst lineContentStartOffset = strings.firstNonWhitespaceIndex(lineContent);\n\n\t\t\tif (lineContentStartOffset === -1) {\n\t\t\t\t// Empty or whitespace only line\n\t\t\t\tlineData.ignore = ignoreEmptyLines;\n\t\t\t\tlineData.commentStrOffset = lineContent.length;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tonlyWhitespaceLines = false;\n\t\t\tlineData.ignore = false;\n\t\t\tlineData.commentStrOffset = lineContentStartOffset;\n\n\t\t\tif (shouldRemoveComments && !BlockCommentCommand._haystackHasNeedleAtOffset(lineContent, lineData.commentStr, lineContentStartOffset)) {\n\t\t\t\tif (type === Type.Toggle) {\n\t\t\t\t\t// Every line so far has been a line comment, but this one is not\n\t\t\t\t\tshouldRemoveComments = false;\n\t\t\t\t} else if (type === Type.ForceAdd) {\n\t\t\t\t\t// Will not happen\n\t\t\t\t} else {\n\t\t\t\t\tlineData.ignore = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (shouldRemoveComments && insertSpace) {\n\t\t\t\t// Remove a following space if present\n\t\t\t\tconst commentStrEndOffset = lineContentStartOffset + lineData.commentStrLength;\n\t\t\t\tif (commentStrEndOffset < lineContent.length && lineContent.charCodeAt(commentStrEndOffset) === CharCode.Space) {\n\t\t\t\t\tlineData.commentStrLength += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (type === Type.Toggle && onlyWhitespaceLines) {\n\t\t\t// For only whitespace lines, we insert comments\n\t\t\tshouldRemoveComments = false;\n\n\t\t\t// Also, no longer ignore them\n\t\t\tfor (let i = 0, lineCount = lines.length; i < lineCount; i++) {\n\t\t\t\tlines[i].ignore = false;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tsupported: true,\n\t\t\tshouldRemoveComments: shouldRemoveComments,\n\t\t\tlines: lines\n\t\t};\n\t}\n\n\t/**\n\t * Analyze all lines and decide exactly what to do => not supported | insert line comments | remove line comments\n\t */\n\tpublic static _gatherPreflightData(type: Type, insertSpace: boolean, model: ITextModel, startLineNumber: number, endLineNumber: number, ignoreEmptyLines: boolean, ignoreFirstLine: boolean, languageConfigurationService: ILanguageConfigurationService): IPreflightData {\n\t\tconst lines = LineCommentCommand._gatherPreflightCommentStrings(model, startLineNumber, endLineNumber, languageConfigurationService);\n\t\tif (lines === null) {\n\t\t\treturn {\n\t\t\t\tsupported: false\n\t\t\t};\n\t\t}\n\n\t\treturn LineCommentCommand._analyzeLines(type, insertSpace, model, lines, startLineNumber, ignoreEmptyLines, ignoreFirstLine, languageConfigurationService);\n\t}\n\n\t/**\n\t * Given a successful analysis, execute either insert line comments, either remove line comments\n\t */\n\tprivate _executeLineComments(model: ISimpleModel, builder: IEditOperationBuilder, data: IPreflightDataSupported, s: Selection): void {\n\n\t\tlet ops: IIdentifiedSingleEditOperation[];\n\n\t\tif (data.shouldRemoveComments) {\n\t\t\tops = LineCommentCommand._createRemoveLineCommentsOperations(data.lines, s.startLineNumber);\n\t\t} else {\n\t\t\tLineCommentCommand._normalizeInsertionPoint(model, data.lines, s.startLineNumber, this._tabSize);\n\t\t\tops = this._createAddLineCommentsOperations(data.lines, s.startLineNumber);\n\t\t}\n\n\t\tconst cursorPosition = new Position(s.positionLineNumber, s.positionColumn);\n\n\t\tfor (let i = 0, len = ops.length; i < len; i++) {\n\t\t\tbuilder.addEditOperation(ops[i].range, ops[i].text);\n\t\t\tif (Range.isEmpty(ops[i].range) && Range.getStartPosition(ops[i].range).equals(cursorPosition)) {\n\t\t\t\tconst lineContent = model.getLineContent(cursorPosition.lineNumber);\n\t\t\t\tif (lineContent.length + 1 === cursorPosition.column) {\n\t\t\t\t\tthis._deltaColumn = (ops[i].text || '').length;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._selectionId = builder.trackSelection(s);\n\t}\n\n\tprivate _attemptRemoveBlockComment(model: ITextModel, s: Selection, startToken: string, endToken: string): IIdentifiedSingleEditOperation[] | null {\n\t\tlet startLineNumber = s.startLineNumber;\n\t\tlet endLineNumber = s.endLineNumber;\n\n\t\tlet startTokenAllowedBeforeColumn = endToken.length + Math.max(\n\t\t\tmodel.getLineFirstNonWhitespaceColumn(s.startLineNumber),\n\t\t\ts.startColumn\n\t\t);\n\n\t\tlet startTokenIndex = model.getLineContent(startLineNumber).lastIndexOf(startToken, startTokenAllowedBeforeColumn - 1);\n\t\tlet endTokenIndex = model.getLineContent(endLineNumber).indexOf(endToken, s.endColumn - 1 - startToken.length);\n\n\t\tif (startTokenIndex !== -1 && endTokenIndex === -1) {\n\t\t\tendTokenIndex = model.getLineContent(startLineNumber).indexOf(endToken, startTokenIndex + startToken.length);\n\t\t\tendLineNumber = startLineNumber;\n\t\t}\n\n\t\tif (startTokenIndex === -1 && endTokenIndex !== -1) {\n\t\t\tstartTokenIndex = model.getLineContent(endLineNumber).lastIndexOf(startToken, endTokenIndex);\n\t\t\tstartLineNumber = endLineNumber;\n\t\t}\n\n\t\tif (s.isEmpty() && (startTokenIndex === -1 || endTokenIndex === -1)) {\n\t\t\tstartTokenIndex = model.getLineContent(startLineNumber).indexOf(startToken);\n\t\t\tif (startTokenIndex !== -1) {\n\t\t\t\tendTokenIndex = model.getLineContent(startLineNumber).indexOf(endToken, startTokenIndex + startToken.length);\n\t\t\t}\n\t\t}\n\n\t\t// We have to adjust to possible inner white space.\n\t\t// For Space after startToken, add Space to startToken - range math will work out.\n\t\tif (startTokenIndex !== -1 && model.getLineContent(startLineNumber).charCodeAt(startTokenIndex + startToken.length) === CharCode.Space) {\n\t\t\tstartToken += ' ';\n\t\t}\n\n\t\t// For Space before endToken, add Space before endToken and shift index one left.\n\t\tif (endTokenIndex !== -1 && model.getLineContent(endLineNumber).charCodeAt(endTokenIndex - 1) === CharCode.Space) {\n\t\t\tendToken = ' ' + endToken;\n\t\t\tendTokenIndex -= 1;\n\t\t}\n\n\t\tif (startTokenIndex !== -1 && endTokenIndex !== -1) {\n\t\t\treturn BlockCommentCommand._createRemoveBlockCommentOperations(\n\t\t\t\tnew Range(startLineNumber, startTokenIndex + startToken.length + 1, endLineNumber, endTokenIndex + 1), startToken, endToken\n\t\t\t);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Given an unsuccessful analysis, delegate to the block comment command\n\t */\n\tprivate _executeBlockComment(model: ITextModel, builder: IEditOperationBuilder, s: Selection): void {\n\t\tmodel.tokenizeIfCheap(s.startLineNumber);\n\t\tlet languageId = model.getLanguageIdAtPosition(s.startLineNumber, 1);\n\t\tlet config = LanguageConfigurationRegistry.getComments(languageId);\n\t\tif (!config || !config.blockCommentStartToken || !config.blockCommentEndToken) {\n\t\t\t// Mode does not support block comments\n\t\t\treturn;\n\t\t}\n\n\t\tconst startToken = config.blockCommentStartToken;\n\t\tconst endToken = config.blockCommentEndToken;\n\n\t\tlet ops = this._attemptRemoveBlockComment(model, s, startToken, endToken);\n\t\tif (!ops) {\n\t\t\tif (s.isEmpty()) {\n\t\t\t\tconst lineContent = model.getLineContent(s.startLineNumber);\n\t\t\t\tlet firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineContent);\n\t\t\t\tif (firstNonWhitespaceIndex === -1) {\n\t\t\t\t\t// Line is empty or contains only whitespace\n\t\t\t\t\tfirstNonWhitespaceIndex = lineContent.length;\n\t\t\t\t}\n\t\t\t\tops = BlockCommentCommand._createAddBlockCommentOperations(\n\t\t\t\t\tnew Range(s.startLineNumber, firstNonWhitespaceIndex + 1, s.startLineNumber, lineContent.length + 1),\n\t\t\t\t\tstartToken,\n\t\t\t\t\tendToken,\n\t\t\t\t\tthis._insertSpace\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tops = BlockCommentCommand._createAddBlockCommentOperations(\n\t\t\t\t\tnew Range(s.startLineNumber, model.getLineFirstNonWhitespaceColumn(s.startLineNumber), s.endLineNumber, model.getLineMaxColumn(s.endLineNumber)),\n\t\t\t\t\tstartToken,\n\t\t\t\t\tendToken,\n\t\t\t\t\tthis._insertSpace\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (ops.length === 1) {\n\t\t\t\t// Leave cursor after token and Space\n\t\t\t\tthis._deltaColumn = startToken.length + 1;\n\t\t\t}\n\t\t}\n\t\tthis._selectionId = builder.trackSelection(s);\n\t\tfor (const op of ops) {\n\t\t\tbuilder.addEditOperation(op.range, op.text);\n\t\t}\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\n\t\tlet s = this._selection;\n\t\tthis._moveEndPositionDown = false;\n\n\t\tif (s.startLineNumber === s.endLineNumber && this._ignoreFirstLine) {\n\t\t\tbuilder.addEditOperation(new Range(s.startLineNumber, model.getLineMaxColumn(s.startLineNumber), s.startLineNumber + 1, 1), s.startLineNumber === model.getLineCount() ? '' : '\\n');\n\t\t\tthis._selectionId = builder.trackSelection(s);\n\t\t\treturn;\n\t\t}\n\n\t\tif (s.startLineNumber < s.endLineNumber && s.endColumn === 1) {\n\t\t\tthis._moveEndPositionDown = true;\n\t\t\ts = s.setEndPosition(s.endLineNumber - 1, model.getLineMaxColumn(s.endLineNumber - 1));\n\t\t}\n\n\t\tconst data = LineCommentCommand._gatherPreflightData(\n\t\t\tthis._type,\n\t\t\tthis._insertSpace,\n\t\t\tmodel,\n\t\t\ts.startLineNumber,\n\t\t\ts.endLineNumber,\n\t\t\tthis._ignoreEmptyLines,\n\t\t\tthis._ignoreFirstLine,\n\t\t\tthis.languageConfigurationService\n\t\t);\n\n\t\tif (data.supported) {\n\t\t\treturn this._executeLineComments(model, builder, data, s);\n\t\t}\n\n\t\treturn this._executeBlockComment(model, builder, s);\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tlet result = helper.getTrackedSelection(this._selectionId!);\n\n\t\tif (this._moveEndPositionDown) {\n\t\t\tresult = result.setEndPosition(result.endLineNumber + 1, 1);\n\t\t}\n\n\t\treturn new Selection(\n\t\t\tresult.selectionStartLineNumber,\n\t\t\tresult.selectionStartColumn + this._deltaColumn,\n\t\t\tresult.positionLineNumber,\n\t\t\tresult.positionColumn + this._deltaColumn\n\t\t);\n\t}\n\n\t/**\n\t * Generate edit operations in the remove line comment case\n\t */\n\tpublic static _createRemoveLineCommentsOperations(lines: ILinePreflightData[], startLineNumber: number): IIdentifiedSingleEditOperation[] {\n\t\tlet res: IIdentifiedSingleEditOperation[] = [];\n\n\t\tfor (let i = 0, len = lines.length; i < len; i++) {\n\t\t\tconst lineData = lines[i];\n\n\t\t\tif (lineData.ignore) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tres.push(EditOperation.delete(new Range(\n\t\t\t\tstartLineNumber + i, lineData.commentStrOffset + 1,\n\t\t\t\tstartLineNumber + i, lineData.commentStrOffset + lineData.commentStrLength + 1\n\t\t\t)));\n\t\t}\n\n\t\treturn res;\n\t}\n\n\t/**\n\t * Generate edit operations in the add line comment case\n\t */\n\tprivate _createAddLineCommentsOperations(lines: ILinePreflightData[], startLineNumber: number): IIdentifiedSingleEditOperation[] {\n\t\tlet res: IIdentifiedSingleEditOperation[] = [];\n\t\tconst afterCommentStr = this._insertSpace ? ' ' : '';\n\n\n\t\tfor (let i = 0, len = lines.length; i < len; i++) {\n\t\t\tconst lineData = lines[i];\n\n\t\t\tif (lineData.ignore) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tres.push(EditOperation.insert(new Position(startLineNumber + i, lineData.commentStrOffset + 1), lineData.commentStr + afterCommentStr));\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tprivate static nextVisibleColumn(currentVisibleColumn: number, tabSize: number, isTab: boolean, columnSize: number): number {\n\t\tif (isTab) {\n\t\t\treturn currentVisibleColumn + (tabSize - (currentVisibleColumn % tabSize));\n\t\t}\n\t\treturn currentVisibleColumn + columnSize;\n\t}\n\n\t/**\n\t * Adjust insertion points to have them vertically aligned in the add line comment case\n\t */\n\tpublic static _normalizeInsertionPoint(model: ISimpleModel, lines: IInsertionPoint[], startLineNumber: number, tabSize: number): void {\n\t\tlet minVisibleColumn = Constants.MAX_SAFE_SMALL_INTEGER;\n\t\tlet j: number;\n\t\tlet lenJ: number;\n\n\t\tfor (let i = 0, len = lines.length; i < len; i++) {\n\t\t\tif (lines[i].ignore) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst lineContent = model.getLineContent(startLineNumber + i);\n\n\t\t\tlet currentVisibleColumn = 0;\n\t\t\tfor (let j = 0, lenJ = lines[i].commentStrOffset; currentVisibleColumn < minVisibleColumn && j < lenJ; j++) {\n\t\t\t\tcurrentVisibleColumn = LineCommentCommand.nextVisibleColumn(currentVisibleColumn, tabSize, lineContent.charCodeAt(j) === CharCode.Tab, 1);\n\t\t\t}\n\n\t\t\tif (currentVisibleColumn < minVisibleColumn) {\n\t\t\t\tminVisibleColumn = currentVisibleColumn;\n\t\t\t}\n\t\t}\n\n\t\tminVisibleColumn = Math.floor(minVisibleColumn / tabSize) * tabSize;\n\n\t\tfor (let i = 0, len = lines.length; i < len; i++) {\n\t\t\tif (lines[i].ignore) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst lineContent = model.getLineContent(startLineNumber + i);\n\n\t\t\tlet currentVisibleColumn = 0;\n\t\t\tfor (j = 0, lenJ = lines[i].commentStrOffset; currentVisibleColumn < minVisibleColumn && j < lenJ; j++) {\n\t\t\t\tcurrentVisibleColumn = LineCommentCommand.nextVisibleColumn(currentVisibleColumn, tabSize, lineContent.charCodeAt(j) === CharCode.Tab, 1);\n\t\t\t}\n\n\t\t\tif (currentVisibleColumn > minVisibleColumn) {\n\t\t\t\tlines[i].commentStrOffset = j - 1;\n\t\t\t} else {\n\t\t\t\tlines[i].commentStrOffset = j;\n\t\t\t}\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as strings from 'vs/base/common/strings';\nimport { ShiftCommand } from 'vs/editor/common/commands/shiftCommand';\nimport { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';\nimport { Range } from 'vs/editor/common/core/range';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { CompleteEnterAction, IndentAction } from 'vs/editor/common/languages/languageConfiguration';\nimport { IIndentConverter, LanguageConfigurationRegistry } from 'vs/editor/common/languages/languageConfigurationRegistry';\nimport { IndentConsts } from 'vs/editor/common/languages/supports/indentRules';\nimport * as indentUtils from 'vs/editor/contrib/indentation/browser/indentUtils';\n\nexport class MoveLinesCommand implements ICommand {\n\n\tprivate readonly _selection: Selection;\n\tprivate readonly _isMovingDown: boolean;\n\tprivate readonly _autoIndent: EditorAutoIndentStrategy;\n\n\tprivate _selectionId: string | null;\n\tprivate _moveEndPositionDown?: boolean;\n\tprivate _moveEndLineSelectionShrink: boolean;\n\n\tconstructor(selection: Selection, isMovingDown: boolean, autoIndent: EditorAutoIndentStrategy) {\n\t\tthis._selection = selection;\n\t\tthis._isMovingDown = isMovingDown;\n\t\tthis._autoIndent = autoIndent;\n\t\tthis._selectionId = null;\n\t\tthis._moveEndLineSelectionShrink = false;\n\t}\n\n\tpublic getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {\n\n\t\tlet modelLineCount = model.getLineCount();\n\n\t\tif (this._isMovingDown && this._selection.endLineNumber === modelLineCount) {\n\t\t\tthis._selectionId = builder.trackSelection(this._selection);\n\t\t\treturn;\n\t\t}\n\t\tif (!this._isMovingDown && this._selection.startLineNumber === 1) {\n\t\t\tthis._selectionId = builder.trackSelection(this._selection);\n\t\t\treturn;\n\t\t}\n\n\t\tthis._moveEndPositionDown = false;\n\t\tlet s = this._selection;\n\n\t\tif (s.startLineNumber < s.endLineNumber && s.endColumn === 1) {\n\t\t\tthis._moveEndPositionDown = true;\n\t\t\ts = s.setEndPosition(s.endLineNumber - 1, model.getLineMaxColumn(s.endLineNumber - 1));\n\t\t}\n\n\t\tconst { tabSize, indentSize, insertSpaces } = model.getOptions();\n\t\tlet indentConverter = this.buildIndentConverter(tabSize, indentSize, insertSpaces);\n\t\tlet virtualModel = {\n\t\t\tgetLineTokens: (lineNumber: number) => {\n\t\t\t\treturn model.getLineTokens(lineNumber);\n\t\t\t},\n\t\t\tgetLanguageId: () => {\n\t\t\t\treturn model.getLanguageId();\n\t\t\t},\n\t\t\tgetLanguageIdAtPosition: (lineNumber: number, column: number) => {\n\t\t\t\treturn model.getLanguageIdAtPosition(lineNumber, column);\n\t\t\t},\n\t\t\tgetLineContent: null as unknown as (lineNumber: number) => string,\n\t\t};\n\n\t\tif (s.startLineNumber === s.endLineNumber && model.getLineMaxColumn(s.startLineNumber) === 1) {\n\t\t\t// Current line is empty\n\t\t\tlet lineNumber = s.startLineNumber;\n\t\t\tlet otherLineNumber = (this._isMovingDown ? lineNumber + 1 : lineNumber - 1);\n\n\t\t\tif (model.getLineMaxColumn(otherLineNumber) === 1) {\n\t\t\t\t// Other line number is empty too, so no editing is needed\n\t\t\t\t// Add a no-op to force running by the model\n\t\t\t\tbuilder.addEditOperation(new Range(1, 1, 1, 1), null);\n\t\t\t} else {\n\t\t\t\t// Type content from other line number on line number\n\t\t\t\tbuilder.addEditOperation(new Range(lineNumber, 1, lineNumber, 1), model.getLineContent(otherLineNumber));\n\n\t\t\t\t// Remove content from other line number\n\t\t\t\tbuilder.addEditOperation(new Range(otherLineNumber, 1, otherLineNumber, model.getLineMaxColumn(otherLineNumber)), null);\n\t\t\t}\n\t\t\t// Track selection at the other line number\n\t\t\ts = new Selection(otherLineNumber, 1, otherLineNumber, 1);\n\n\t\t} else {\n\n\t\t\tlet movingLineNumber: number;\n\t\t\tlet movingLineText: string;\n\n\t\t\tif (this._isMovingDown) {\n\t\t\t\tmovingLineNumber = s.endLineNumber + 1;\n\t\t\t\tmovingLineText = model.getLineContent(movingLineNumber);\n\t\t\t\t// Delete line that needs to be moved\n\t\t\t\tbuilder.addEditOperation(new Range(movingLineNumber - 1, model.getLineMaxColumn(movingLineNumber - 1), movingLineNumber, model.getLineMaxColumn(movingLineNumber)), null);\n\n\t\t\t\tlet insertingText = movingLineText;\n\n\t\t\t\tif (this.shouldAutoIndent(model, s)) {\n\t\t\t\t\tlet movingLineMatchResult = this.matchEnterRule(model, indentConverter, tabSize, movingLineNumber, s.startLineNumber - 1);\n\t\t\t\t\t// if s.startLineNumber - 1 matches onEnter rule, we still honor that.\n\t\t\t\t\tif (movingLineMatchResult !== null) {\n\t\t\t\t\t\tlet oldIndentation = strings.getLeadingWhitespace(model.getLineContent(movingLineNumber));\n\t\t\t\t\t\tlet newSpaceCnt = movingLineMatchResult + indentUtils.getSpaceCnt(oldIndentation, tabSize);\n\t\t\t\t\t\tlet newIndentation = indentUtils.generateIndent(newSpaceCnt, tabSize, insertSpaces);\n\t\t\t\t\t\tinsertingText = newIndentation + this.trimLeft(movingLineText);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// no enter rule matches, let's check indentatin rules then.\n\t\t\t\t\t\tvirtualModel.getLineContent = (lineNumber: number) => {\n\t\t\t\t\t\t\tif (lineNumber === s.startLineNumber) {\n\t\t\t\t\t\t\t\treturn model.getLineContent(movingLineNumber);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn model.getLineContent(lineNumber);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t\tlet indentOfMovingLine = LanguageConfigurationRegistry.getGoodIndentForLine(this._autoIndent, virtualModel, model.getLanguageIdAtPosition(\n\t\t\t\t\t\t\tmovingLineNumber, 1), s.startLineNumber, indentConverter);\n\t\t\t\t\t\tif (indentOfMovingLine !== null) {\n\t\t\t\t\t\t\tlet oldIndentation = strings.getLeadingWhitespace(model.getLineContent(movingLineNumber));\n\t\t\t\t\t\t\tlet newSpaceCnt = indentUtils.getSpaceCnt(indentOfMovingLine, tabSize);\n\t\t\t\t\t\t\tlet oldSpaceCnt = indentUtils.getSpaceCnt(oldIndentation, tabSize);\n\t\t\t\t\t\t\tif (newSpaceCnt !== oldSpaceCnt) {\n\t\t\t\t\t\t\t\tlet newIndentation = indentUtils.generateIndent(newSpaceCnt, tabSize, insertSpaces);\n\t\t\t\t\t\t\t\tinsertingText = newIndentation + this.trimLeft(movingLineText);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// add edit operations for moving line first to make sure it's executed after we make indentation change\n\t\t\t\t\t// to s.startLineNumber\n\t\t\t\t\tbuilder.addEditOperation(new Range(s.startLineNumber, 1, s.startLineNumber, 1), insertingText + '\\n');\n\n\t\t\t\t\tlet ret = this.matchEnterRuleMovingDown(model, indentConverter, tabSize, s.startLineNumber, movingLineNumber, insertingText);\n\n\t\t\t\t\t// check if the line being moved before matches onEnter rules, if so let's adjust the indentation by onEnter rules.\n\t\t\t\t\tif (ret !== null) {\n\t\t\t\t\t\tif (ret !== 0) {\n\t\t\t\t\t\t\tthis.getIndentEditsOfMovingBlock(model, builder, s, tabSize, insertSpaces, ret);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// it doesn't match onEnter rules, let's check indentation rules then.\n\t\t\t\t\t\tvirtualModel.getLineContent = (lineNumber: number) => {\n\t\t\t\t\t\t\tif (lineNumber === s.startLineNumber) {\n\t\t\t\t\t\t\t\treturn insertingText;\n\t\t\t\t\t\t\t} else if (lineNumber >= s.startLineNumber + 1 && lineNumber <= s.endLineNumber + 1) {\n\t\t\t\t\t\t\t\treturn model.getLineContent(lineNumber - 1);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn model.getLineContent(lineNumber);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tlet newIndentatOfMovingBlock = LanguageConfigurationRegistry.getGoodIndentForLine(this._autoIndent, virtualModel, model.getLanguageIdAtPosition(\n\t\t\t\t\t\t\tmovingLineNumber, 1), s.startLineNumber + 1, indentConverter);\n\n\t\t\t\t\t\tif (newIndentatOfMovingBlock !== null) {\n\t\t\t\t\t\t\tconst oldIndentation = strings.getLeadingWhitespace(model.getLineContent(s.startLineNumber));\n\t\t\t\t\t\t\tconst newSpaceCnt = indentUtils.getSpaceCnt(newIndentatOfMovingBlock, tabSize);\n\t\t\t\t\t\t\tconst oldSpaceCnt = indentUtils.getSpaceCnt(oldIndentation, tabSize);\n\t\t\t\t\t\t\tif (newSpaceCnt !== oldSpaceCnt) {\n\t\t\t\t\t\t\t\tconst spaceCntOffset = newSpaceCnt - oldSpaceCnt;\n\n\t\t\t\t\t\t\t\tthis.getIndentEditsOfMovingBlock(model, builder, s, tabSize, insertSpaces, spaceCntOffset);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Insert line that needs to be moved before\n\t\t\t\t\tbuilder.addEditOperation(new Range(s.startLineNumber, 1, s.startLineNumber, 1), insertingText + '\\n');\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmovingLineNumber = s.startLineNumber - 1;\n\t\t\t\tmovingLineText = model.getLineContent(movingLineNumber);\n\n\t\t\t\t// Delete line that needs to be moved\n\t\t\t\tbuilder.addEditOperation(new Range(movingLineNumber, 1, movingLineNumber + 1, 1), null);\n\n\t\t\t\t// Insert line that needs to be moved after\n\t\t\t\tbuilder.addEditOperation(new Range(s.endLineNumber, model.getLineMaxColumn(s.endLineNumber), s.endLineNumber, model.getLineMaxColumn(s.endLineNumber)), '\\n' + movingLineText);\n\n\t\t\t\tif (this.shouldAutoIndent(model, s)) {\n\t\t\t\t\tvirtualModel.getLineContent = (lineNumber: number) => {\n\t\t\t\t\t\tif (lineNumber === movingLineNumber) {\n\t\t\t\t\t\t\treturn model.getLineContent(s.startLineNumber);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn model.getLineContent(lineNumber);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tlet ret = this.matchEnterRule(model, indentConverter, tabSize, s.startLineNumber, s.startLineNumber - 2);\n\t\t\t\t\t// check if s.startLineNumber - 2 matches onEnter rules, if so adjust the moving block by onEnter rules.\n\t\t\t\t\tif (ret !== null) {\n\t\t\t\t\t\tif (ret !== 0) {\n\t\t\t\t\t\t\tthis.getIndentEditsOfMovingBlock(model, builder, s, tabSize, insertSpaces, ret);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// it doesn't match any onEnter rule, let's check indentation rules then.\n\t\t\t\t\t\tlet indentOfFirstLine = LanguageConfigurationRegistry.getGoodIndentForLine(this._autoIndent, virtualModel, model.getLanguageIdAtPosition(s.startLineNumber, 1), movingLineNumber, indentConverter);\n\t\t\t\t\t\tif (indentOfFirstLine !== null) {\n\t\t\t\t\t\t\t// adjust the indentation of the moving block\n\t\t\t\t\t\t\tlet oldIndent = strings.getLeadingWhitespace(model.getLineContent(s.startLineNumber));\n\t\t\t\t\t\t\tlet newSpaceCnt = indentUtils.getSpaceCnt(indentOfFirstLine, tabSize);\n\t\t\t\t\t\t\tlet oldSpaceCnt = indentUtils.getSpaceCnt(oldIndent, tabSize);\n\t\t\t\t\t\t\tif (newSpaceCnt !== oldSpaceCnt) {\n\t\t\t\t\t\t\t\tlet spaceCntOffset = newSpaceCnt - oldSpaceCnt;\n\n\t\t\t\t\t\t\t\tthis.getIndentEditsOfMovingBlock(model, builder, s, tabSize, insertSpaces, spaceCntOffset);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._selectionId = builder.trackSelection(s);\n\t}\n\n\tprivate buildIndentConverter(tabSize: number, indentSize: number, insertSpaces: boolean): IIndentConverter {\n\t\treturn {\n\t\t\tshiftIndent: (indentation) => {\n\t\t\t\treturn ShiftCommand.shiftIndent(indentation, indentation.length + 1, tabSize, indentSize, insertSpaces);\n\t\t\t},\n\t\t\tunshiftIndent: (indentation) => {\n\t\t\t\treturn ShiftCommand.unshiftIndent(indentation, indentation.length + 1, tabSize, indentSize, insertSpaces);\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate parseEnterResult(model: ITextModel, indentConverter: IIndentConverter, tabSize: number, line: number, enter: CompleteEnterAction | null) {\n\t\tif (enter) {\n\t\t\tlet enterPrefix = enter.indentation;\n\n\t\t\tif (enter.indentAction === IndentAction.None) {\n\t\t\t\tenterPrefix = enter.indentation + enter.appendText;\n\t\t\t} else if (enter.indentAction === IndentAction.Indent) {\n\t\t\t\tenterPrefix = enter.indentation + enter.appendText;\n\t\t\t} else if (enter.indentAction === IndentAction.IndentOutdent) {\n\t\t\t\tenterPrefix = enter.indentation;\n\t\t\t} else if (enter.indentAction === IndentAction.Outdent) {\n\t\t\t\tenterPrefix = indentConverter.unshiftIndent(enter.indentation) + enter.appendText;\n\t\t\t}\n\t\t\tlet movingLineText = model.getLineContent(line);\n\t\t\tif (this.trimLeft(movingLineText).indexOf(this.trimLeft(enterPrefix)) >= 0) {\n\t\t\t\tlet oldIndentation = strings.getLeadingWhitespace(model.getLineContent(line));\n\t\t\t\tlet newIndentation = strings.getLeadingWhitespace(enterPrefix);\n\t\t\t\tlet indentMetadataOfMovelingLine = LanguageConfigurationRegistry.getIndentMetadata(model, line);\n\t\t\t\tif (indentMetadataOfMovelingLine !== null && indentMetadataOfMovelingLine & IndentConsts.DECREASE_MASK) {\n\t\t\t\t\tnewIndentation = indentConverter.unshiftIndent(newIndentation);\n\t\t\t\t}\n\t\t\t\tlet newSpaceCnt = indentUtils.getSpaceCnt(newIndentation, tabSize);\n\t\t\t\tlet oldSpaceCnt = indentUtils.getSpaceCnt(oldIndentation, tabSize);\n\t\t\t\treturn newSpaceCnt - oldSpaceCnt;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t *\n\t * @param model\n\t * @param indentConverter\n\t * @param tabSize\n\t * @param line the line moving down\n\t * @param futureAboveLineNumber the line which will be at the `line` position\n\t * @param futureAboveLineText\n\t */\n\tprivate matchEnterRuleMovingDown(model: ITextModel, indentConverter: IIndentConverter, tabSize: number, line: number, futureAboveLineNumber: number, futureAboveLineText: string) {\n\t\tif (strings.lastNonWhitespaceIndex(futureAboveLineText) >= 0) {\n\t\t\t// break\n\t\t\tlet maxColumn = model.getLineMaxColumn(futureAboveLineNumber);\n\t\t\tlet enter = LanguageConfigurationRegistry.getEnterAction(this._autoIndent, model, new Range(futureAboveLineNumber, maxColumn, futureAboveLineNumber, maxColumn));\n\t\t\treturn this.parseEnterResult(model, indentConverter, tabSize, line, enter);\n\t\t} else {\n\t\t\t// go upwards, starting from `line - 1`\n\t\t\tlet validPrecedingLine = line - 1;\n\t\t\twhile (validPrecedingLine >= 1) {\n\t\t\t\tlet lineContent = model.getLineContent(validPrecedingLine);\n\t\t\t\tlet nonWhitespaceIdx = strings.lastNonWhitespaceIndex(lineContent);\n\n\t\t\t\tif (nonWhitespaceIdx >= 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tvalidPrecedingLine--;\n\t\t\t}\n\n\t\t\tif (validPrecedingLine < 1 || line > model.getLineCount()) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tlet maxColumn = model.getLineMaxColumn(validPrecedingLine);\n\t\t\tlet enter = LanguageConfigurationRegistry.getEnterAction(this._autoIndent, model, new Range(validPrecedingLine, maxColumn, validPrecedingLine, maxColumn));\n\t\t\treturn this.parseEnterResult(model, indentConverter, tabSize, line, enter);\n\t\t}\n\t}\n\n\tprivate matchEnterRule(model: ITextModel, indentConverter: IIndentConverter, tabSize: number, line: number, oneLineAbove: number, previousLineText?: string) {\n\t\tlet validPrecedingLine = oneLineAbove;\n\t\twhile (validPrecedingLine >= 1) {\n\t\t\t// ship empty lines as empty lines just inherit indentation\n\t\t\tlet lineContent;\n\t\t\tif (validPrecedingLine === oneLineAbove && previousLineText !== undefined) {\n\t\t\t\tlineContent = previousLineText;\n\t\t\t} else {\n\t\t\t\tlineContent = model.getLineContent(validPrecedingLine);\n\t\t\t}\n\n\t\t\tlet nonWhitespaceIdx = strings.lastNonWhitespaceIndex(lineContent);\n\t\t\tif (nonWhitespaceIdx >= 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tvalidPrecedingLine--;\n\t\t}\n\n\t\tif (validPrecedingLine < 1 || line > model.getLineCount()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlet maxColumn = model.getLineMaxColumn(validPrecedingLine);\n\t\tlet enter = LanguageConfigurationRegistry.getEnterAction(this._autoIndent, model, new Range(validPrecedingLine, maxColumn, validPrecedingLine, maxColumn));\n\t\treturn this.parseEnterResult(model, indentConverter, tabSize, line, enter);\n\t}\n\n\tprivate trimLeft(str: string) {\n\t\treturn str.replace(/^\\s+/, '');\n\t}\n\n\tprivate shouldAutoIndent(model: ITextModel, selection: Selection) {\n\t\tif (this._autoIndent < EditorAutoIndentStrategy.Full) {\n\t\t\treturn false;\n\t\t}\n\t\t// if it's not easy to tokenize, we stop auto indent.\n\t\tif (!model.isCheapToTokenize(selection.startLineNumber)) {\n\t\t\treturn false;\n\t\t}\n\t\tlet languageAtSelectionStart = model.getLanguageIdAtPosition(selection.startLineNumber, 1);\n\t\tlet languageAtSelectionEnd = model.getLanguageIdAtPosition(selection.endLineNumber, 1);\n\n\t\tif (languageAtSelectionStart !== languageAtSelectionEnd) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (LanguageConfigurationRegistry.getIndentRulesSupport(languageAtSelectionStart) === null) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate getIndentEditsOfMovingBlock(model: ITextModel, builder: IEditOperationBuilder, s: Selection, tabSize: number, insertSpaces: boolean, offset: number) {\n\t\tfor (let i = s.startLineNumber; i <= s.endLineNumber; i++) {\n\t\t\tlet lineContent = model.getLineContent(i);\n\t\t\tlet originalIndent = strings.getLeadingWhitespace(lineContent);\n\t\t\tlet originalSpacesCnt = indentUtils.getSpaceCnt(originalIndent, tabSize);\n\t\t\tlet newSpacesCnt = originalSpacesCnt + offset;\n\t\t\tlet newIndent = indentUtils.generateIndent(newSpacesCnt, tabSize, insertSpaces);\n\n\t\t\tif (newIndent !== originalIndent) {\n\t\t\t\tbuilder.addEditOperation(new Range(i, 1, i, originalIndent.length + 1), newIndent);\n\n\t\t\t\tif (i === s.endLineNumber && s.endColumn <= originalIndent.length + 1 && newIndent === '') {\n\t\t\t\t\t// as users select part of the original indent white spaces\n\t\t\t\t\t// when we adjust the indentation of endLine, we should adjust the cursor position as well.\n\t\t\t\t\tthis._moveEndLineSelectionShrink = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tpublic computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {\n\t\tlet result = helper.getTrackedSelection(this._selectionId!);\n\n\t\tif (this._moveEndPositionDown) {\n\t\t\tresult = result.setEndPosition(result.endLineNumber + 1, 1);\n\t\t}\n\n\t\tif (this._moveEndLineSelectionShrink && result.startLineNumber < result.endLineNumber) {\n\t\t\tresult = result.setEndPosition(result.endLineNumber, 2);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport { isChrome, isEdge, isFirefox, isLinux, isMacintosh, isSafari, isWeb, isWindows } from 'vs/base/common/platform';\nimport { isFalsyOrWhitespace } from 'vs/base/common/strings';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nconst CONSTANT_VALUES = new Map();\nCONSTANT_VALUES.set('false', false);\nCONSTANT_VALUES.set('true', true);\nCONSTANT_VALUES.set('isMac', isMacintosh);\nCONSTANT_VALUES.set('isLinux', isLinux);\nCONSTANT_VALUES.set('isWindows', isWindows);\nCONSTANT_VALUES.set('isWeb', isWeb);\nCONSTANT_VALUES.set('isMacNative', isMacintosh && !isWeb);\nCONSTANT_VALUES.set('isEdge', isEdge);\nCONSTANT_VALUES.set('isFirefox', isFirefox);\nCONSTANT_VALUES.set('isChrome', isChrome);\nCONSTANT_VALUES.set('isSafari', isSafari);\n\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\n\nexport const enum ContextKeyExprType {\n\tFalse = 0,\n\tTrue = 1,\n\tDefined = 2,\n\tNot = 3,\n\tEquals = 4,\n\tNotEquals = 5,\n\tAnd = 6,\n\tRegex = 7,\n\tNotRegex = 8,\n\tOr = 9,\n\tIn = 10,\n\tNotIn = 11,\n\tGreater = 12,\n\tGreaterEquals = 13,\n\tSmaller = 14,\n\tSmallerEquals = 15,\n}\n\nexport interface IContextKeyExpression {\n\n}\n\nexport type ContextKeyExpression = (\n\tContextKeyFalseExpr | ContextKeyTrueExpr | ContextKeyDefinedExpr | ContextKeyNotExpr\n\t| ContextKeyEqualsExpr | ContextKeyNotEqualsExpr | ContextKeyRegexExpr\n\t| ContextKeyNotRegexExpr | ContextKeyAndExpr | ContextKeyOrExpr | ContextKeyInExpr\n\t| ContextKeyNotInExpr | ContextKeyGreaterExpr | ContextKeyGreaterEqualsExpr\n\t| ContextKeySmallerExpr | ContextKeySmallerEqualsExpr\n);\n\nexport abstract class ContextKeyExpr {\n\tpublic static has(key: string): ContextKeyExpression {\n\t\treturn ContextKeyDefinedExpr.create(key);\n\t}\n\tpublic static equals(key: string, value: any): ContextKeyExpression {\n\t\treturn ContextKeyEqualsExpr.create(key, value);\n\t}\n\tpublic static regex(key: string, value: RegExp): ContextKeyExpression {\n\t\treturn ContextKeyRegexExpr.create(key, value);\n\t}\n\tpublic static not(key: string): ContextKeyExpression {\n\t\treturn ContextKeyNotExpr.create(key);\n\t}\n\tpublic static and(...expr: Array): ContextKeyExpression | undefined {\n\t\treturn ContextKeyAndExpr.create(expr, null);\n\t}\n\tpublic static or(...expr: Array): ContextKeyExpression | undefined {\n\t\treturn ContextKeyOrExpr.create(expr, null, true);\n\t}\n\n\tpublic static deserialize(serialized: string | null | undefined, strict: boolean = false): ContextKeyExpression | undefined {\n\t\tif (!serialized) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn this._deserializeOrExpression(serialized, strict);\n\t}\n\n\tprivate static _deserializeOrExpression(serialized: string, strict: boolean): ContextKeyExpression | undefined {\n\t\tlet pieces = serialized.split('||');\n\t\treturn ContextKeyOrExpr.create(pieces.map(p => this._deserializeAndExpression(p, strict)), null, true);\n\t}\n\n\tprivate static _deserializeAndExpression(serialized: string, strict: boolean): ContextKeyExpression | undefined {\n\t\tlet pieces = serialized.split('&&');\n\t\treturn ContextKeyAndExpr.create(pieces.map(p => this._deserializeOne(p, strict)), null);\n\t}\n\n\tprivate static _deserializeOne(serializedOne: string, strict: boolean): ContextKeyExpression {\n\t\tserializedOne = serializedOne.trim();\n\n\t\tif (serializedOne.indexOf('!=') >= 0) {\n\t\t\tlet pieces = serializedOne.split('!=');\n\t\t\treturn ContextKeyNotEqualsExpr.create(pieces[0].trim(), this._deserializeValue(pieces[1], strict));\n\t\t}\n\n\t\tif (serializedOne.indexOf('==') >= 0) {\n\t\t\tlet pieces = serializedOne.split('==');\n\t\t\treturn ContextKeyEqualsExpr.create(pieces[0].trim(), this._deserializeValue(pieces[1], strict));\n\t\t}\n\n\t\tif (serializedOne.indexOf('=~') >= 0) {\n\t\t\tlet pieces = serializedOne.split('=~');\n\t\t\treturn ContextKeyRegexExpr.create(pieces[0].trim(), this._deserializeRegexValue(pieces[1], strict));\n\t\t}\n\n\t\tif (serializedOne.indexOf(' in ') >= 0) {\n\t\t\tlet pieces = serializedOne.split(' in ');\n\t\t\treturn ContextKeyInExpr.create(pieces[0].trim(), pieces[1].trim());\n\t\t}\n\n\t\tif (/^[^<=>]+>=[^<=>]+$/.test(serializedOne)) {\n\t\t\tconst pieces = serializedOne.split('>=');\n\t\t\treturn ContextKeyGreaterEqualsExpr.create(pieces[0].trim(), pieces[1].trim());\n\t\t}\n\n\t\tif (/^[^<=>]+>[^<=>]+$/.test(serializedOne)) {\n\t\t\tconst pieces = serializedOne.split('>');\n\t\t\treturn ContextKeyGreaterExpr.create(pieces[0].trim(), pieces[1].trim());\n\t\t}\n\n\t\tif (/^[^<=>]+<=[^<=>]+$/.test(serializedOne)) {\n\t\t\tconst pieces = serializedOne.split('<=');\n\t\t\treturn ContextKeySmallerEqualsExpr.create(pieces[0].trim(), pieces[1].trim());\n\t\t}\n\n\t\tif (/^[^<=>]+<[^<=>]+$/.test(serializedOne)) {\n\t\t\tconst pieces = serializedOne.split('<');\n\t\t\treturn ContextKeySmallerExpr.create(pieces[0].trim(), pieces[1].trim());\n\t\t}\n\n\t\tif (/^\\!\\s*/.test(serializedOne)) {\n\t\t\treturn ContextKeyNotExpr.create(serializedOne.substr(1).trim());\n\t\t}\n\n\t\treturn ContextKeyDefinedExpr.create(serializedOne);\n\t}\n\n\tprivate static _deserializeValue(serializedValue: string, strict: boolean): any {\n\t\tserializedValue = serializedValue.trim();\n\n\t\tif (serializedValue === 'true') {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (serializedValue === 'false') {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet m = /^'([^']*)'$/.exec(serializedValue);\n\t\tif (m) {\n\t\t\treturn m[1].trim();\n\t\t}\n\n\t\treturn serializedValue;\n\t}\n\n\tprivate static _deserializeRegexValue(serializedValue: string, strict: boolean): RegExp | null {\n\n\t\tif (isFalsyOrWhitespace(serializedValue)) {\n\t\t\tif (strict) {\n\t\t\t\tthrow new Error('missing regexp-value for =~-expression');\n\t\t\t} else {\n\t\t\t\tconsole.warn('missing regexp-value for =~-expression');\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\tlet start = serializedValue.indexOf('/');\n\t\tlet end = serializedValue.lastIndexOf('/');\n\t\tif (start === end || start < 0 /* || to < 0 */) {\n\t\t\tif (strict) {\n\t\t\t\tthrow new Error(`bad regexp-value '${serializedValue}', missing /-enclosure`);\n\t\t\t} else {\n\t\t\t\tconsole.warn(`bad regexp-value '${serializedValue}', missing /-enclosure`);\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\tlet value = serializedValue.slice(start + 1, end);\n\t\tlet caseIgnoreFlag = serializedValue[end + 1] === 'i' ? 'i' : '';\n\t\ttry {\n\t\t\treturn new RegExp(value, caseIgnoreFlag);\n\t\t} catch (e) {\n\t\t\tif (strict) {\n\t\t\t\tthrow new Error(`bad regexp-value '${serializedValue}', parse error: ${e}`);\n\t\t\t} else {\n\t\t\t\tconsole.warn(`bad regexp-value '${serializedValue}', parse error: ${e}`);\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t}\n}\n\nexport function expressionsAreEqualWithConstantSubstitution(a: ContextKeyExpression | null | undefined, b: ContextKeyExpression | null | undefined): boolean {\n\tconst aExpr = a ? a.substituteConstants() : undefined;\n\tconst bExpr = b ? b.substituteConstants() : undefined;\n\tif (!aExpr && !bExpr) {\n\t\treturn true;\n\t}\n\tif (!aExpr || !bExpr) {\n\t\treturn false;\n\t}\n\treturn aExpr.equals(bExpr);\n}\n\nfunction cmp(a: ContextKeyExpression, b: ContextKeyExpression): number {\n\treturn a.cmp(b);\n}\n\nexport class ContextKeyFalseExpr implements IContextKeyExpression {\n\tpublic static INSTANCE = new ContextKeyFalseExpr();\n\n\tpublic readonly type = ContextKeyExprType.False;\n\n\tprotected constructor() {\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\treturn this.type - other.type;\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\treturn (other.type === this.type);\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\treturn false;\n\t}\n\n\tpublic serialize(): string {\n\t\treturn 'false';\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\treturn ContextKeyTrueExpr.INSTANCE;\n\t}\n}\n\nexport class ContextKeyTrueExpr implements IContextKeyExpression {\n\tpublic static INSTANCE = new ContextKeyTrueExpr();\n\n\tpublic readonly type = ContextKeyExprType.True;\n\n\tprotected constructor() {\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\treturn this.type - other.type;\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\treturn (other.type === this.type);\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\treturn true;\n\t}\n\n\tpublic serialize(): string {\n\t\treturn 'true';\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\treturn ContextKeyFalseExpr.INSTANCE;\n\t}\n}\n\nexport class ContextKeyDefinedExpr implements IContextKeyExpression {\n\tpublic static create(key: string, negated: ContextKeyExpression | null = null): ContextKeyExpression {\n\t\tconst constantValue = CONSTANT_VALUES.get(key);\n\t\tif (typeof constantValue === 'boolean') {\n\t\t\treturn constantValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE;\n\t\t}\n\t\treturn new ContextKeyDefinedExpr(key, negated);\n\t}\n\n\tpublic readonly type = ContextKeyExprType.Defined;\n\n\tprotected constructor(\n\t\treadonly key: string,\n\t\tprivate negated: ContextKeyExpression | null\n\t) {\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\treturn cmp1(this.key, other.key);\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\treturn (this.key === other.key);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\tconst constantValue = CONSTANT_VALUES.get(this.key);\n\t\tif (typeof constantValue === 'boolean') {\n\t\t\treturn constantValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE;\n\t\t}\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\treturn (!!context.getValue(this.key));\n\t}\n\n\tpublic serialize(): string {\n\t\treturn this.key;\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [this.key];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tthis.negated = ContextKeyNotExpr.create(this.key, this);\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nexport class ContextKeyEqualsExpr implements IContextKeyExpression {\n\n\tpublic static create(key: string, value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {\n\t\tif (typeof value === 'boolean') {\n\t\t\treturn (value ? ContextKeyDefinedExpr.create(key, negated) : ContextKeyNotExpr.create(key, negated));\n\t\t}\n\t\tconst constantValue = CONSTANT_VALUES.get(key);\n\t\tif (typeof constantValue === 'boolean') {\n\t\t\tconst trueValue = constantValue ? 'true' : 'false';\n\t\t\treturn (value === trueValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE);\n\t\t}\n\t\treturn new ContextKeyEqualsExpr(key, value, negated);\n\t}\n\n\tpublic readonly type = ContextKeyExprType.Equals;\n\n\tprivate constructor(\n\t\tprivate readonly key: string,\n\t\tprivate readonly value: any,\n\t\tprivate negated: ContextKeyExpression | null\n\t) {\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\treturn cmp2(this.key, this.value, other.key, other.value);\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\treturn (this.key === other.key && this.value === other.value);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\tconst constantValue = CONSTANT_VALUES.get(this.key);\n\t\tif (typeof constantValue === 'boolean') {\n\t\t\tconst trueValue = constantValue ? 'true' : 'false';\n\t\t\treturn (this.value === trueValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE);\n\t\t}\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\t// Intentional ==\n\t\t// eslint-disable-next-line eqeqeq\n\t\treturn (context.getValue(this.key) == this.value);\n\t}\n\n\tpublic serialize(): string {\n\t\treturn `${this.key} == '${this.value}'`;\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [this.key];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tthis.negated = ContextKeyNotEqualsExpr.create(this.key, this.value, this);\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nexport class ContextKeyInExpr implements IContextKeyExpression {\n\n\tpublic static create(key: string, valueKey: string): ContextKeyInExpr {\n\t\treturn new ContextKeyInExpr(key, valueKey);\n\t}\n\n\tpublic readonly type = ContextKeyExprType.In;\n\tprivate negated: ContextKeyExpression | null = null;\n\n\tprivate constructor(\n\t\tprivate readonly key: string,\n\t\tprivate readonly valueKey: string,\n\t) {\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\treturn cmp2(this.key, this.valueKey, other.key, other.valueKey);\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\treturn (this.key === other.key && this.valueKey === other.valueKey);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\tconst source = context.getValue(this.valueKey);\n\n\t\tconst item = context.getValue(this.key);\n\n\t\tif (Array.isArray(source)) {\n\t\t\treturn (source.indexOf(item) >= 0);\n\t\t}\n\n\t\tif (typeof item === 'string' && typeof source === 'object' && source !== null) {\n\t\t\treturn hasOwnProperty.call(source, item);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic serialize(): string {\n\t\treturn `${this.key} in '${this.valueKey}'`;\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [this.key, this.valueKey];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tthis.negated = ContextKeyNotInExpr.create(this);\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nexport class ContextKeyNotInExpr implements IContextKeyExpression {\n\n\tpublic static create(actual: ContextKeyInExpr): ContextKeyNotInExpr {\n\t\treturn new ContextKeyNotInExpr(actual);\n\t}\n\n\tpublic readonly type = ContextKeyExprType.NotIn;\n\n\tprivate constructor(private readonly _actual: ContextKeyInExpr) {\n\t\t//\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\treturn this._actual.cmp(other._actual);\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\treturn this._actual.equals(other._actual);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\treturn !this._actual.evaluate(context);\n\t}\n\n\tpublic serialize(): string {\n\t\tthrow new Error('Method not implemented.');\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn this._actual.keys();\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\treturn this._actual;\n\t}\n}\n\nexport class ContextKeyNotEqualsExpr implements IContextKeyExpression {\n\n\tpublic static create(key: string, value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {\n\t\tif (typeof value === 'boolean') {\n\t\t\tif (value) {\n\t\t\t\treturn ContextKeyNotExpr.create(key, negated);\n\t\t\t}\n\t\t\treturn ContextKeyDefinedExpr.create(key, negated);\n\t\t}\n\t\tconst constantValue = CONSTANT_VALUES.get(key);\n\t\tif (typeof constantValue === 'boolean') {\n\t\t\tconst falseValue = constantValue ? 'true' : 'false';\n\t\t\treturn (value === falseValue ? ContextKeyFalseExpr.INSTANCE : ContextKeyTrueExpr.INSTANCE);\n\t\t}\n\t\treturn new ContextKeyNotEqualsExpr(key, value, negated);\n\t}\n\n\tpublic readonly type = ContextKeyExprType.NotEquals;\n\n\tprivate constructor(\n\t\tprivate readonly key: string,\n\t\tprivate readonly value: any,\n\t\tprivate negated: ContextKeyExpression | null\n\t) {\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\treturn cmp2(this.key, this.value, other.key, other.value);\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\treturn (this.key === other.key && this.value === other.value);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\tconst constantValue = CONSTANT_VALUES.get(this.key);\n\t\tif (typeof constantValue === 'boolean') {\n\t\t\tconst falseValue = constantValue ? 'true' : 'false';\n\t\t\treturn (this.value === falseValue ? ContextKeyFalseExpr.INSTANCE : ContextKeyTrueExpr.INSTANCE);\n\t\t}\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\t// Intentional !=\n\t\t// eslint-disable-next-line eqeqeq\n\t\treturn (context.getValue(this.key) != this.value);\n\t}\n\n\tpublic serialize(): string {\n\t\treturn `${this.key} != '${this.value}'`;\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [this.key];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tthis.negated = ContextKeyEqualsExpr.create(this.key, this.value, this);\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nexport class ContextKeyNotExpr implements IContextKeyExpression {\n\n\tpublic static create(key: string, negated: ContextKeyExpression | null = null): ContextKeyExpression {\n\t\tconst constantValue = CONSTANT_VALUES.get(key);\n\t\tif (typeof constantValue === 'boolean') {\n\t\t\treturn (constantValue ? ContextKeyFalseExpr.INSTANCE : ContextKeyTrueExpr.INSTANCE);\n\t\t}\n\t\treturn new ContextKeyNotExpr(key, negated);\n\t}\n\n\tpublic readonly type = ContextKeyExprType.Not;\n\n\tprivate constructor(\n\t\tprivate readonly key: string,\n\t\tprivate negated: ContextKeyExpression | null\n\t) {\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\treturn cmp1(this.key, other.key);\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\treturn (this.key === other.key);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\tconst constantValue = CONSTANT_VALUES.get(this.key);\n\t\tif (typeof constantValue === 'boolean') {\n\t\t\treturn (constantValue ? ContextKeyFalseExpr.INSTANCE : ContextKeyTrueExpr.INSTANCE);\n\t\t}\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\treturn (!context.getValue(this.key));\n\t}\n\n\tpublic serialize(): string {\n\t\treturn `!${this.key}`;\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [this.key];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tthis.negated = ContextKeyDefinedExpr.create(this.key, this);\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nfunction withFloatOrStr(value: any, callback: (value: number | string) => T): T | ContextKeyFalseExpr {\n\tif (typeof value === 'string') {\n\t\tconst n = parseFloat(value);\n\t\tif (!isNaN(n)) {\n\t\t\tvalue = n;\n\t\t}\n\t}\n\tif (typeof value === 'string' || typeof value === 'number') {\n\t\treturn callback(value);\n\t}\n\treturn ContextKeyFalseExpr.INSTANCE;\n}\n\nexport class ContextKeyGreaterExpr implements IContextKeyExpression {\n\n\tpublic static create(key: string, _value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {\n\t\treturn withFloatOrStr(_value, (value) => new ContextKeyGreaterExpr(key, value, negated));\n\t}\n\n\tpublic readonly type = ContextKeyExprType.Greater;\n\n\tprivate constructor(\n\t\tprivate readonly key: string,\n\t\tprivate readonly value: number | string,\n\t\tprivate negated: ContextKeyExpression | null\n\t) { }\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\treturn cmp2(this.key, this.value, other.key, other.value);\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\treturn (this.key === other.key && this.value === other.value);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\tif (typeof this.value === 'string') {\n\t\t\treturn false;\n\t\t}\n\t\treturn (parseFloat(context.getValue(this.key)) > this.value);\n\t}\n\n\tpublic serialize(): string {\n\t\treturn `${this.key} > ${this.value}`;\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [this.key];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tthis.negated = ContextKeySmallerEqualsExpr.create(this.key, this.value, this);\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nexport class ContextKeyGreaterEqualsExpr implements IContextKeyExpression {\n\n\tpublic static create(key: string, _value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {\n\t\treturn withFloatOrStr(_value, (value) => new ContextKeyGreaterEqualsExpr(key, value, negated));\n\t}\n\n\tpublic readonly type = ContextKeyExprType.GreaterEquals;\n\n\tprivate constructor(\n\t\tprivate readonly key: string,\n\t\tprivate readonly value: number | string,\n\t\tprivate negated: ContextKeyExpression | null\n\t) { }\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\treturn cmp2(this.key, this.value, other.key, other.value);\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\treturn (this.key === other.key && this.value === other.value);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\tif (typeof this.value === 'string') {\n\t\t\treturn false;\n\t\t}\n\t\treturn (parseFloat(context.getValue(this.key)) >= this.value);\n\t}\n\n\tpublic serialize(): string {\n\t\treturn `${this.key} >= ${this.value}`;\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [this.key];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tthis.negated = ContextKeySmallerExpr.create(this.key, this.value, this);\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nexport class ContextKeySmallerExpr implements IContextKeyExpression {\n\n\tpublic static create(key: string, _value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {\n\t\treturn withFloatOrStr(_value, (value) => new ContextKeySmallerExpr(key, value, negated));\n\t}\n\n\tpublic readonly type = ContextKeyExprType.Smaller;\n\n\tprivate constructor(\n\t\tprivate readonly key: string,\n\t\tprivate readonly value: number | string,\n\t\tprivate negated: ContextKeyExpression | null\n\t) {\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\treturn cmp2(this.key, this.value, other.key, other.value);\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\treturn (this.key === other.key && this.value === other.value);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\tif (typeof this.value === 'string') {\n\t\t\treturn false;\n\t\t}\n\t\treturn (parseFloat(context.getValue(this.key)) < this.value);\n\t}\n\n\tpublic serialize(): string {\n\t\treturn `${this.key} < ${this.value}`;\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [this.key];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tthis.negated = ContextKeyGreaterEqualsExpr.create(this.key, this.value, this);\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nexport class ContextKeySmallerEqualsExpr implements IContextKeyExpression {\n\n\tpublic static create(key: string, _value: any, negated: ContextKeyExpression | null = null): ContextKeyExpression {\n\t\treturn withFloatOrStr(_value, (value) => new ContextKeySmallerEqualsExpr(key, value, negated));\n\t}\n\n\tpublic readonly type = ContextKeyExprType.SmallerEquals;\n\n\tprivate constructor(\n\t\tprivate readonly key: string,\n\t\tprivate readonly value: number | string,\n\t\tprivate negated: ContextKeyExpression | null\n\t) {\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\treturn cmp2(this.key, this.value, other.key, other.value);\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\treturn (this.key === other.key && this.value === other.value);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\tif (typeof this.value === 'string') {\n\t\t\treturn false;\n\t\t}\n\t\treturn (parseFloat(context.getValue(this.key)) <= this.value);\n\t}\n\n\tpublic serialize(): string {\n\t\treturn `${this.key} <= ${this.value}`;\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [this.key];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tthis.negated = ContextKeyGreaterExpr.create(this.key, this.value, this);\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nexport class ContextKeyRegexExpr implements IContextKeyExpression {\n\n\tpublic static create(key: string, regexp: RegExp | null): ContextKeyRegexExpr {\n\t\treturn new ContextKeyRegexExpr(key, regexp);\n\t}\n\n\tpublic readonly type = ContextKeyExprType.Regex;\n\tprivate negated: ContextKeyExpression | null = null;\n\n\tprivate constructor(\n\t\tprivate readonly key: string,\n\t\tprivate readonly regexp: RegExp | null\n\t) {\n\t\t//\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\tif (this.key < other.key) {\n\t\t\treturn -1;\n\t\t}\n\t\tif (this.key > other.key) {\n\t\t\treturn 1;\n\t\t}\n\t\tconst thisSource = this.regexp ? this.regexp.source : '';\n\t\tconst otherSource = other.regexp ? other.regexp.source : '';\n\t\tif (thisSource < otherSource) {\n\t\t\treturn -1;\n\t\t}\n\t\tif (thisSource > otherSource) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\tconst thisSource = this.regexp ? this.regexp.source : '';\n\t\t\tconst otherSource = other.regexp ? other.regexp.source : '';\n\t\t\treturn (this.key === other.key && thisSource === otherSource);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\tlet value = context.getValue(this.key);\n\t\treturn this.regexp ? this.regexp.test(value) : false;\n\t}\n\n\tpublic serialize(): string {\n\t\tconst value = this.regexp\n\t\t\t? `/${this.regexp.source}/${this.regexp.ignoreCase ? 'i' : ''}`\n\t\t\t: '/invalid/';\n\t\treturn `${this.key} =~ ${value}`;\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn [this.key];\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tthis.negated = ContextKeyNotRegexExpr.create(this);\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nexport class ContextKeyNotRegexExpr implements IContextKeyExpression {\n\n\tpublic static create(actual: ContextKeyRegexExpr): ContextKeyExpression {\n\t\treturn new ContextKeyNotRegexExpr(actual);\n\t}\n\n\tpublic readonly type = ContextKeyExprType.NotRegex;\n\n\tprivate constructor(private readonly _actual: ContextKeyRegexExpr) {\n\t\t//\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\treturn this._actual.cmp(other._actual);\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\treturn this._actual.equals(other._actual);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\treturn this;\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\treturn !this._actual.evaluate(context);\n\t}\n\n\tpublic serialize(): string {\n\t\tthrow new Error('Method not implemented.');\n\t}\n\n\tpublic keys(): string[] {\n\t\treturn this._actual.keys();\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\treturn this._actual;\n\t}\n}\n\n/**\n * @returns the same instance if nothing changed.\n */\nfunction eliminateConstantsInArray(arr: ContextKeyExpression[]): (ContextKeyExpression | undefined)[] {\n\t// Allocate array only if there is a difference\n\tlet newArr: (ContextKeyExpression | undefined)[] | null = null;\n\tfor (let i = 0, len = arr.length; i < len; i++) {\n\t\tconst newExpr = arr[i].substituteConstants();\n\n\t\tif (arr[i] !== newExpr) {\n\t\t\t// something has changed!\n\n\t\t\t// allocate array on first difference\n\t\t\tif (newArr === null) {\n\t\t\t\tnewArr = [];\n\t\t\t\tfor (let j = 0; j < i; j++) {\n\t\t\t\t\tnewArr[j] = arr[j];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (newArr !== null) {\n\t\t\tnewArr[i] = newExpr;\n\t\t}\n\t}\n\n\tif (newArr === null) {\n\t\treturn arr;\n\t}\n\treturn newArr;\n}\n\nclass ContextKeyAndExpr implements IContextKeyExpression {\n\n\tpublic static create(_expr: ReadonlyArray, negated: ContextKeyExpression | null): ContextKeyExpression | undefined {\n\t\treturn ContextKeyAndExpr._normalizeArr(_expr, negated);\n\t}\n\n\tpublic readonly type = ContextKeyExprType.And;\n\n\tprivate constructor(\n\t\tpublic readonly expr: ContextKeyExpression[],\n\t\tprivate negated: ContextKeyExpression | null\n\t) {\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\tif (this.expr.length < other.expr.length) {\n\t\t\treturn -1;\n\t\t}\n\t\tif (this.expr.length > other.expr.length) {\n\t\t\treturn 1;\n\t\t}\n\t\tfor (let i = 0, len = this.expr.length; i < len; i++) {\n\t\t\tconst r = cmp(this.expr[i], other.expr[i]);\n\t\t\tif (r !== 0) {\n\t\t\t\treturn r;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\tif (this.expr.length !== other.expr.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tfor (let i = 0, len = this.expr.length; i < len; i++) {\n\t\t\t\tif (!this.expr[i].equals(other.expr[i])) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\tconst exprArr = eliminateConstantsInArray(this.expr);\n\t\tif (exprArr === this.expr) {\n\t\t\t// no change\n\t\t\treturn this;\n\t\t}\n\t\treturn ContextKeyAndExpr.create(exprArr, this.negated);\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\tfor (let i = 0, len = this.expr.length; i < len; i++) {\n\t\t\tif (!this.expr[i].evaluate(context)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\tprivate static _normalizeArr(arr: ReadonlyArray, negated: ContextKeyExpression | null): ContextKeyExpression | undefined {\n\t\tconst expr: ContextKeyExpression[] = [];\n\t\tlet hasTrue = false;\n\n\t\tfor (const e of arr) {\n\t\t\tif (!e) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (e.type === ContextKeyExprType.True) {\n\t\t\t\t// anything && true ==> anything\n\t\t\t\thasTrue = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (e.type === ContextKeyExprType.False) {\n\t\t\t\t// anything && false ==> false\n\t\t\t\treturn ContextKeyFalseExpr.INSTANCE;\n\t\t\t}\n\n\t\t\tif (e.type === ContextKeyExprType.And) {\n\t\t\t\texpr.push(...e.expr);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\texpr.push(e);\n\t\t}\n\n\t\tif (expr.length === 0 && hasTrue) {\n\t\t\treturn ContextKeyTrueExpr.INSTANCE;\n\t\t}\n\n\t\tif (expr.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (expr.length === 1) {\n\t\t\treturn expr[0];\n\t\t}\n\n\t\texpr.sort(cmp);\n\n\t\t// eliminate duplicate terms\n\t\tfor (let i = 1; i < expr.length; i++) {\n\t\t\tif (expr[i - 1].equals(expr[i])) {\n\t\t\t\texpr.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\n\t\tif (expr.length === 1) {\n\t\t\treturn expr[0];\n\t\t}\n\n\t\t// We must distribute any OR expression because we don't support parens\n\t\t// OR extensions will be at the end (due to sorting rules)\n\t\twhile (expr.length > 1) {\n\t\t\tconst lastElement = expr[expr.length - 1];\n\t\t\tif (lastElement.type !== ContextKeyExprType.Or) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// pop the last element\n\t\t\texpr.pop();\n\n\t\t\t// pop the second to last element\n\t\t\tconst secondToLastElement = expr.pop()!;\n\n\t\t\tconst isFinished = (expr.length === 0);\n\n\t\t\t// distribute `lastElement` over `secondToLastElement`\n\t\t\tconst resultElement = ContextKeyOrExpr.create(\n\t\t\t\tlastElement.expr.map(el => ContextKeyAndExpr.create([el, secondToLastElement], null)),\n\t\t\t\tnull,\n\t\t\t\tisFinished\n\t\t\t);\n\n\t\t\tif (resultElement) {\n\t\t\t\texpr.push(resultElement);\n\t\t\t\texpr.sort(cmp);\n\t\t\t}\n\t\t}\n\n\t\tif (expr.length === 1) {\n\t\t\treturn expr[0];\n\t\t}\n\n\t\treturn new ContextKeyAndExpr(expr, negated);\n\t}\n\n\tpublic serialize(): string {\n\t\treturn this.expr.map(e => e.serialize()).join(' && ');\n\t}\n\n\tpublic keys(): string[] {\n\t\tconst result: string[] = [];\n\t\tfor (let expr of this.expr) {\n\t\t\tresult.push(...expr.keys());\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tconst result: ContextKeyExpression[] = [];\n\t\t\tfor (let expr of this.expr) {\n\t\t\t\tresult.push(expr.negate());\n\t\t\t}\n\t\t\tthis.negated = ContextKeyOrExpr.create(result, this, true)!;\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nclass ContextKeyOrExpr implements IContextKeyExpression {\n\n\tpublic static create(_expr: ReadonlyArray, negated: ContextKeyExpression | null, extraRedundantCheck: boolean): ContextKeyExpression | undefined {\n\t\treturn ContextKeyOrExpr._normalizeArr(_expr, negated, extraRedundantCheck);\n\t}\n\n\tpublic readonly type = ContextKeyExprType.Or;\n\n\tprivate constructor(\n\t\tpublic readonly expr: ContextKeyExpression[],\n\t\tprivate negated: ContextKeyExpression | null\n\t) {\n\t}\n\n\tpublic cmp(other: ContextKeyExpression): number {\n\t\tif (other.type !== this.type) {\n\t\t\treturn this.type - other.type;\n\t\t}\n\t\tif (this.expr.length < other.expr.length) {\n\t\t\treturn -1;\n\t\t}\n\t\tif (this.expr.length > other.expr.length) {\n\t\t\treturn 1;\n\t\t}\n\t\tfor (let i = 0, len = this.expr.length; i < len; i++) {\n\t\t\tconst r = cmp(this.expr[i], other.expr[i]);\n\t\t\tif (r !== 0) {\n\t\t\t\treturn r;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\n\tpublic equals(other: ContextKeyExpression): boolean {\n\t\tif (other.type === this.type) {\n\t\t\tif (this.expr.length !== other.expr.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tfor (let i = 0, len = this.expr.length; i < len; i++) {\n\t\t\t\tif (!this.expr[i].equals(other.expr[i])) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic substituteConstants(): ContextKeyExpression | undefined {\n\t\tconst exprArr = eliminateConstantsInArray(this.expr);\n\t\tif (exprArr === this.expr) {\n\t\t\t// no change\n\t\t\treturn this;\n\t\t}\n\t\treturn ContextKeyOrExpr.create(exprArr, this.negated, false);\n\t}\n\n\tpublic evaluate(context: IContext): boolean {\n\t\tfor (let i = 0, len = this.expr.length; i < len; i++) {\n\t\t\tif (this.expr[i].evaluate(context)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate static _normalizeArr(arr: ReadonlyArray, negated: ContextKeyExpression | null, extraRedundantCheck: boolean): ContextKeyExpression | undefined {\n\t\tlet expr: ContextKeyExpression[] = [];\n\t\tlet hasFalse = false;\n\n\t\tif (arr) {\n\t\t\tfor (let i = 0, len = arr.length; i < len; i++) {\n\t\t\t\tconst e = arr[i];\n\t\t\t\tif (!e) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (e.type === ContextKeyExprType.False) {\n\t\t\t\t\t// anything || false ==> anything\n\t\t\t\t\thasFalse = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (e.type === ContextKeyExprType.True) {\n\t\t\t\t\t// anything || true ==> true\n\t\t\t\t\treturn ContextKeyTrueExpr.INSTANCE;\n\t\t\t\t}\n\n\t\t\t\tif (e.type === ContextKeyExprType.Or) {\n\t\t\t\t\texpr = expr.concat(e.expr);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\texpr.push(e);\n\t\t\t}\n\n\t\t\tif (expr.length === 0 && hasFalse) {\n\t\t\t\treturn ContextKeyFalseExpr.INSTANCE;\n\t\t\t}\n\n\t\t\texpr.sort(cmp);\n\t\t}\n\n\t\tif (expr.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (expr.length === 1) {\n\t\t\treturn expr[0];\n\t\t}\n\n\t\t// eliminate duplicate terms\n\t\tfor (let i = 1; i < expr.length; i++) {\n\t\t\tif (expr[i - 1].equals(expr[i])) {\n\t\t\t\texpr.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\n\t\tif (expr.length === 1) {\n\t\t\treturn expr[0];\n\t\t}\n\n\t\t// eliminate redundant terms\n\t\tif (extraRedundantCheck) {\n\t\t\tfor (let i = 0; i < expr.length; i++) {\n\t\t\t\tfor (let j = i + 1; j < expr.length; j++) {\n\t\t\t\t\tif (implies(expr[i], expr[j])) {\n\t\t\t\t\t\texpr.splice(j, 1);\n\t\t\t\t\t\tj--;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (expr.length === 1) {\n\t\t\t\treturn expr[0];\n\t\t\t}\n\t\t}\n\n\t\treturn new ContextKeyOrExpr(expr, negated);\n\t}\n\n\tpublic serialize(): string {\n\t\treturn this.expr.map(e => e.serialize()).join(' || ');\n\t}\n\n\tpublic keys(): string[] {\n\t\tconst result: string[] = [];\n\t\tfor (let expr of this.expr) {\n\t\t\tresult.push(...expr.keys());\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic negate(): ContextKeyExpression {\n\t\tif (!this.negated) {\n\t\t\tlet result: ContextKeyExpression[] = [];\n\t\t\tfor (let expr of this.expr) {\n\t\t\t\tresult.push(expr.negate());\n\t\t\t}\n\n\t\t\t// We don't support parens, so here we distribute the AND over the OR terminals\n\t\t\t// We always take the first 2 AND pairs and distribute them\n\t\t\twhile (result.length > 1) {\n\t\t\t\tconst LEFT = result.shift()!;\n\t\t\t\tconst RIGHT = result.shift()!;\n\n\t\t\t\tconst all: ContextKeyExpression[] = [];\n\t\t\t\tfor (const left of getTerminals(LEFT)) {\n\t\t\t\t\tfor (const right of getTerminals(RIGHT)) {\n\t\t\t\t\t\tall.push(ContextKeyAndExpr.create([left, right], null)!);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst isFinished = (result.length === 0);\n\t\t\t\tresult.unshift(ContextKeyOrExpr.create(all, null, isFinished)!);\n\t\t\t}\n\n\t\t\tthis.negated = result[0];\n\t\t}\n\t\treturn this.negated;\n\t}\n}\n\nexport interface ContextKeyInfo {\n\treadonly key: string;\n\treadonly type?: string;\n\treadonly description?: string;\n}\n\nexport class RawContextKey extends ContextKeyDefinedExpr {\n\n\tprivate static _info: ContextKeyInfo[] = [];\n\n\tstatic all(): IterableIterator {\n\t\treturn RawContextKey._info.values();\n\t}\n\n\tprivate readonly _defaultValue: T | undefined;\n\n\tconstructor(key: string, defaultValue: T | undefined, metaOrHide?: string | true | { type: string, description: string }) {\n\t\tsuper(key, null);\n\t\tthis._defaultValue = defaultValue;\n\n\t\t// collect all context keys into a central place\n\t\tif (typeof metaOrHide === 'object') {\n\t\t\tRawContextKey._info.push({ ...metaOrHide, key });\n\t\t} else if (metaOrHide !== true) {\n\t\t\tRawContextKey._info.push({ key, description: metaOrHide, type: defaultValue !== null && defaultValue !== undefined ? typeof defaultValue : undefined });\n\t\t}\n\t}\n\n\tpublic bindTo(target: IContextKeyService): IContextKey {\n\t\treturn target.createKey(this.key, this._defaultValue);\n\t}\n\n\tpublic getValue(target: IContextKeyService): T | undefined {\n\t\treturn target.getContextKeyValue(this.key);\n\t}\n\n\tpublic toNegated(): ContextKeyExpression {\n\t\treturn this.negate();\n\t}\n\n\tpublic isEqualTo(value: any): ContextKeyExpression {\n\t\treturn ContextKeyEqualsExpr.create(this.key, value);\n\t}\n}\n\nexport interface IContext {\n\tgetValue(key: string): T | undefined;\n}\n\nexport interface IContextKey {\n\tset(value: T): void;\n\treset(): void;\n\tget(): T | undefined;\n}\n\nexport interface IContextKeyServiceTarget {\n\tparentElement: IContextKeyServiceTarget | null;\n\tsetAttribute(attr: string, value: string): void;\n\tremoveAttribute(attr: string): void;\n\thasAttribute(attr: string): boolean;\n\tgetAttribute(attr: string): string | null;\n}\n\nexport const IContextKeyService = createDecorator('contextKeyService');\n\nexport interface IReadableSet {\n\thas(value: T): boolean;\n}\n\nexport interface IContextKeyChangeEvent {\n\taffectsSome(keys: IReadableSet): boolean;\n}\n\nexport interface IContextKeyService {\n\treadonly _serviceBrand: undefined;\n\tdispose(): void;\n\n\tonDidChangeContext: Event;\n\tbufferChangeEvents(callback: Function): void;\n\n\tcreateKey(key: string, defaultValue: T | undefined): IContextKey;\n\tcontextMatchesRules(rules: ContextKeyExpression | undefined): boolean;\n\tgetContextKeyValue(key: string): T | undefined;\n\n\tcreateScoped(target: IContextKeyServiceTarget): IContextKeyService;\n\tgetContext(target: IContextKeyServiceTarget | null): IContext;\n}\n\nexport const SET_CONTEXT_COMMAND_ID = 'setContext';\n\nfunction cmp1(key1: string, key2: string): number {\n\tif (key1 < key2) {\n\t\treturn -1;\n\t}\n\tif (key1 > key2) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nfunction cmp2(key1: string, value1: any, key2: string, value2: any): number {\n\tif (key1 < key2) {\n\t\treturn -1;\n\t}\n\tif (key1 > key2) {\n\t\treturn 1;\n\t}\n\tif (value1 < value2) {\n\t\treturn -1;\n\t}\n\tif (value1 > value2) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\n/**\n * Returns true if it is provable `p` implies `q`.\n */\nexport function implies(p: ContextKeyExpression, q: ContextKeyExpression): boolean {\n\n\tif (q.type === ContextKeyExprType.And && (p.type !== ContextKeyExprType.Or && p.type !== ContextKeyExprType.And)) {\n\t\t// covers the case: A implies A && B\n\t\tfor (const qTerm of q.expr) {\n\t\t\tif (p.equals(qTerm)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst notP = p.negate();\n\tconst expr = getTerminals(notP).concat(getTerminals(q));\n\texpr.sort(cmp);\n\n\tfor (let i = 0; i < expr.length; i++) {\n\t\tconst a = expr[i];\n\t\tconst notA = a.negate();\n\t\tfor (let j = i + 1; j < expr.length; j++) {\n\t\t\tconst b = expr[j];\n\t\t\tif (notA.equals(b)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\nfunction getTerminals(node: ContextKeyExpression) {\n\tif (node.type === ContextKeyExprType.Or) {\n\t\treturn node.expr;\n\t}\n\treturn [node];\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as nls from 'vs/nls';\nimport { RawContextKey } from 'vs/platform/contextkey/common/contextkey';\n\nexport namespace EditorContextKeys {\n\n\texport const editorSimpleInput = new RawContextKey('editorSimpleInput', false, true);\n\t/**\n\t * A context key that is set when the editor's text has focus (cursor is blinking).\n\t * Is false when focus is in simple editor widgets (repl input, scm commit input).\n\t */\n\texport const editorTextFocus = new RawContextKey('editorTextFocus', false, nls.localize('editorTextFocus', \"Whether the editor text has focus (cursor is blinking)\"));\n\t/**\n\t * A context key that is set when the editor's text or an editor's widget has focus.\n\t */\n\texport const focus = new RawContextKey('editorFocus', false, nls.localize('editorFocus', \"Whether the editor or an editor widget has focus (e.g. focus is in the find widget)\"));\n\n\t/**\n\t * A context key that is set when any editor input has focus (regular editor, repl input...).\n\t */\n\texport const textInputFocus = new RawContextKey('textInputFocus', false, nls.localize('textInputFocus', \"Whether an editor or a rich text input has focus (cursor is blinking)\"));\n\n\texport const readOnly = new RawContextKey('editorReadonly', false, nls.localize('editorReadonly', \"Whether the editor is read only\"));\n\texport const inDiffEditor = new RawContextKey('inDiffEditor', false, nls.localize('inDiffEditor', \"Whether the context is a diff editor\"));\n\texport const columnSelection = new RawContextKey('editorColumnSelection', false, nls.localize('editorColumnSelection', \"Whether `editor.columnSelection` is enabled\"));\n\texport const writable = readOnly.toNegated();\n\texport const hasNonEmptySelection = new RawContextKey('editorHasSelection', false, nls.localize('editorHasSelection', \"Whether the editor has text selected\"));\n\texport const hasOnlyEmptySelection = hasNonEmptySelection.toNegated();\n\texport const hasMultipleSelections = new RawContextKey('editorHasMultipleSelections', false, nls.localize('editorHasMultipleSelections', \"Whether the editor has multiple selections\"));\n\texport const hasSingleSelection = hasMultipleSelections.toNegated();\n\texport const tabMovesFocus = new RawContextKey('editorTabMovesFocus', false, nls.localize('editorTabMovesFocus', \"Whether `Tab` will move focus out of the editor\"));\n\texport const tabDoesNotMoveFocus = tabMovesFocus.toNegated();\n\texport const isInWalkThroughSnippet = new RawContextKey('isInEmbeddedEditor', false, true);\n\texport const canUndo = new RawContextKey('canUndo', false, true);\n\texport const canRedo = new RawContextKey('canRedo', false, true);\n\n\texport const hoverVisible = new RawContextKey('editorHoverVisible', false, nls.localize('editorHoverVisible', \"Whether the editor hover is visible\"));\n\n\t/**\n\t * A context key that is set when an editor is part of a larger editor, like notebooks or\n\t * (future) a diff editor\n\t */\n\texport const inCompositeEditor = new RawContextKey('inCompositeEditor', undefined, nls.localize('inCompositeEditor', \"Whether the editor is part of a larger editor (e.g. notebooks)\"));\n\texport const notInCompositeEditor = inCompositeEditor.toNegated();\n\n\t// -- mode context keys\n\texport const languageId = new RawContextKey('editorLangId', '', nls.localize('editorLangId', \"The language identifier of the editor\"));\n\texport const hasCompletionItemProvider = new RawContextKey('editorHasCompletionItemProvider', false, nls.localize('editorHasCompletionItemProvider', \"Whether the editor has a completion item provider\"));\n\texport const hasCodeActionsProvider = new RawContextKey('editorHasCodeActionsProvider', false, nls.localize('editorHasCodeActionsProvider', \"Whether the editor has a code actions provider\"));\n\texport const hasCodeLensProvider = new RawContextKey('editorHasCodeLensProvider', false, nls.localize('editorHasCodeLensProvider', \"Whether the editor has a code lens provider\"));\n\texport const hasDefinitionProvider = new RawContextKey('editorHasDefinitionProvider', false, nls.localize('editorHasDefinitionProvider', \"Whether the editor has a definition provider\"));\n\texport const hasDeclarationProvider = new RawContextKey('editorHasDeclarationProvider', false, nls.localize('editorHasDeclarationProvider', \"Whether the editor has a declaration provider\"));\n\texport const hasImplementationProvider = new RawContextKey('editorHasImplementationProvider', false, nls.localize('editorHasImplementationProvider', \"Whether the editor has an implementation provider\"));\n\texport const hasTypeDefinitionProvider = new RawContextKey('editorHasTypeDefinitionProvider', false, nls.localize('editorHasTypeDefinitionProvider', \"Whether the editor has a type definition provider\"));\n\texport const hasHoverProvider = new RawContextKey('editorHasHoverProvider', false, nls.localize('editorHasHoverProvider', \"Whether the editor has a hover provider\"));\n\texport const hasDocumentHighlightProvider = new RawContextKey('editorHasDocumentHighlightProvider', false, nls.localize('editorHasDocumentHighlightProvider', \"Whether the editor has a document highlight provider\"));\n\texport const hasDocumentSymbolProvider = new RawContextKey('editorHasDocumentSymbolProvider', false, nls.localize('editorHasDocumentSymbolProvider', \"Whether the editor has a document symbol provider\"));\n\texport const hasReferenceProvider = new RawContextKey('editorHasReferenceProvider', false, nls.localize('editorHasReferenceProvider', \"Whether the editor has a reference provider\"));\n\texport const hasRenameProvider = new RawContextKey('editorHasRenameProvider', false, nls.localize('editorHasRenameProvider', \"Whether the editor has a rename provider\"));\n\texport const hasSignatureHelpProvider = new RawContextKey('editorHasSignatureHelpProvider', false, nls.localize('editorHasSignatureHelpProvider', \"Whether the editor has a signature help provider\"));\n\texport const hasInlayHintsProvider = new RawContextKey('editorHasInlayHintsProvider', false, nls.localize('editorHasInlayHintsProvider', \"Whether the editor has an inline hints provider\"));\n\n\t// -- mode context keys: formatting\n\texport const hasDocumentFormattingProvider = new RawContextKey('editorHasDocumentFormattingProvider', false, nls.localize('editorHasDocumentFormattingProvider', \"Whether the editor has a document formatting provider\"));\n\texport const hasDocumentSelectionFormattingProvider = new RawContextKey('editorHasDocumentSelectionFormattingProvider', false, nls.localize('editorHasDocumentSelectionFormattingProvider', \"Whether the editor has a document selection formatting provider\"));\n\texport const hasMultipleDocumentFormattingProvider = new RawContextKey('editorHasMultipleDocumentFormattingProvider', false, nls.localize('editorHasMultipleDocumentFormattingProvider', \"Whether the editor has multiple document formatting providers\"));\n\texport const hasMultipleDocumentSelectionFormattingProvider = new RawContextKey('editorHasMultipleDocumentSelectionFormattingProvider', false, nls.localize('editorHasMultipleDocumentSelectionFormattingProvider', \"Whether the editor has multiple document selection formatting providers\"));\n\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { onUnexpectedExternalError } from 'vs/base/common/errors';\nimport { assertType } from 'vs/base/common/types';\nimport { URI } from 'vs/base/common/uri';\nimport { IPosition, Position } from 'vs/editor/common/core/position';\nimport { ITextModel } from 'vs/editor/common/model';\nimport * as modes from 'vs/editor/common/languages';\nimport { ITextModelService } from 'vs/editor/common/services/resolverService';\nimport { CommandsRegistry } from 'vs/platform/commands/common/commands';\nimport { RawContextKey } from 'vs/platform/contextkey/common/contextkey';\n\nexport const Context = {\n\tVisible: new RawContextKey('parameterHintsVisible', false),\n\tMultipleSignatures: new RawContextKey('parameterHintsMultipleSignatures', false),\n};\n\nexport async function provideSignatureHelp(\n\tmodel: ITextModel,\n\tposition: Position,\n\tcontext: modes.SignatureHelpContext,\n\ttoken: CancellationToken\n): Promise {\n\n\tconst supports = modes.SignatureHelpProviderRegistry.ordered(model);\n\n\tfor (const support of supports) {\n\t\ttry {\n\t\t\tconst result = await support.provideSignatureHelp(model, position, token, context);\n\t\t\tif (result) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tonUnexpectedExternalError(err);\n\t\t}\n\t}\n\treturn undefined;\n}\n\nCommandsRegistry.registerCommand('_executeSignatureHelpProvider', async (accessor, ...args: [URI, IPosition, string?]) => {\n\tconst [uri, position, triggerCharacter] = args;\n\tassertType(URI.isUri(uri));\n\tassertType(Position.isIPosition(position));\n\tassertType(typeof triggerCharacter === 'string' || !triggerCharacter);\n\n\tconst ref = await accessor.get(ITextModelService).createModelReference(uri);\n\ttry {\n\n\t\tconst result = await provideSignatureHelp(ref.object.textEditorModel, Position.lift(position), {\n\t\t\ttriggerKind: modes.SignatureHelpTriggerKind.Invoke,\n\t\t\tisRetrigger: false,\n\t\t\ttriggerCharacter,\n\t\t}, CancellationToken.None);\n\n\t\tif (!result) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tsetTimeout(() => result.dispose(), 0);\n\t\treturn result.value;\n\n\t} finally {\n\t\tref.dispose();\n\t}\n});\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancelablePromise, createCancelablePromise, Delayer } from 'vs/base/common/async';\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport { Emitter } from 'vs/base/common/event';\nimport { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { ICursorSelectionChangedEvent } from 'vs/editor/common/cursor/cursorEvents';\nimport { CharacterSet } from 'vs/editor/common/core/characterClassifier';\nimport * as modes from 'vs/editor/common/languages';\nimport { provideSignatureHelp } from 'vs/editor/contrib/parameterHints/browser/provideSignatureHelp';\n\nexport interface TriggerContext {\n\treadonly triggerKind: modes.SignatureHelpTriggerKind;\n\treadonly triggerCharacter?: string;\n}\n\nnamespace ParameterHintState {\n\texport const enum Type {\n\t\tDefault,\n\t\tActive,\n\t\tPending,\n\t}\n\n\texport const Default = { type: Type.Default } as const;\n\n\texport class Pending {\n\t\treadonly type = Type.Pending;\n\t\tconstructor(\n\t\t\treadonly request: CancelablePromise,\n\t\t\treadonly previouslyActiveHints: modes.SignatureHelp | undefined,\n\t\t) { }\n\t}\n\n\texport class Active {\n\t\treadonly type = Type.Active;\n\t\tconstructor(\n\t\t\treadonly hints: modes.SignatureHelp\n\t\t) { }\n\t}\n\n\texport type State = typeof Default | Pending | Active;\n}\n\nexport class ParameterHintsModel extends Disposable {\n\n\tprivate static readonly DEFAULT_DELAY = 120; // ms\n\n\tprivate readonly _onChangedHints = this._register(new Emitter());\n\tpublic readonly onChangedHints = this._onChangedHints.event;\n\n\tprivate readonly editor: ICodeEditor;\n\tprivate triggerOnType = false;\n\tprivate _state: ParameterHintState.State = ParameterHintState.Default;\n\tprivate _pendingTriggers: TriggerContext[] = [];\n\tprivate readonly _lastSignatureHelpResult = this._register(new MutableDisposable());\n\tprivate triggerChars = new CharacterSet();\n\tprivate retriggerChars = new CharacterSet();\n\n\tprivate readonly throttledDelayer: Delayer;\n\tprivate triggerId = 0;\n\n\tconstructor(\n\t\teditor: ICodeEditor,\n\t\tdelay: number = ParameterHintsModel.DEFAULT_DELAY\n\t) {\n\t\tsuper();\n\n\t\tthis.editor = editor;\n\n\t\tthis.throttledDelayer = new Delayer(delay);\n\n\t\tthis._register(this.editor.onDidBlurEditorWidget(() => this.cancel()));\n\t\tthis._register(this.editor.onDidChangeConfiguration(() => this.onEditorConfigurationChange()));\n\t\tthis._register(this.editor.onDidChangeModel(e => this.onModelChanged()));\n\t\tthis._register(this.editor.onDidChangeModelLanguage(_ => this.onModelChanged()));\n\t\tthis._register(this.editor.onDidChangeCursorSelection(e => this.onCursorChange(e)));\n\t\tthis._register(this.editor.onDidChangeModelContent(e => this.onModelContentChange()));\n\t\tthis._register(modes.SignatureHelpProviderRegistry.onDidChange(this.onModelChanged, this));\n\t\tthis._register(this.editor.onDidType(text => this.onDidType(text)));\n\n\t\tthis.onEditorConfigurationChange();\n\t\tthis.onModelChanged();\n\t}\n\n\tprivate get state() { return this._state; }\n\tprivate set state(value: ParameterHintState.State) {\n\t\tif (this._state.type === ParameterHintState.Type.Pending) {\n\t\t\tthis._state.request.cancel();\n\t\t}\n\t\tthis._state = value;\n\t}\n\n\tcancel(silent: boolean = false): void {\n\t\tthis.state = ParameterHintState.Default;\n\n\t\tthis.throttledDelayer.cancel();\n\n\t\tif (!silent) {\n\t\t\tthis._onChangedHints.fire(undefined);\n\t\t}\n\t}\n\n\ttrigger(context: TriggerContext, delay?: number): void {\n\t\tconst model = this.editor.getModel();\n\t\tif (!model || !modes.SignatureHelpProviderRegistry.has(model)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst triggerId = ++this.triggerId;\n\n\t\tthis._pendingTriggers.push(context);\n\t\tthis.throttledDelayer.trigger(() => {\n\t\t\treturn this.doTrigger(triggerId);\n\t\t}, delay)\n\t\t\t.catch(onUnexpectedError);\n\t}\n\n\tpublic next(): void {\n\t\tif (this.state.type !== ParameterHintState.Type.Active) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst length = this.state.hints.signatures.length;\n\t\tconst activeSignature = this.state.hints.activeSignature;\n\t\tconst last = (activeSignature % length) === (length - 1);\n\t\tconst cycle = this.editor.getOption(EditorOption.parameterHints).cycle;\n\n\t\t// If there is only one signature, or we're on last signature of list\n\t\tif ((length < 2 || last) && !cycle) {\n\t\t\tthis.cancel();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.updateActiveSignature(last && cycle ? 0 : activeSignature + 1);\n\t}\n\n\tpublic previous(): void {\n\t\tif (this.state.type !== ParameterHintState.Type.Active) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst length = this.state.hints.signatures.length;\n\t\tconst activeSignature = this.state.hints.activeSignature;\n\t\tconst first = activeSignature === 0;\n\t\tconst cycle = this.editor.getOption(EditorOption.parameterHints).cycle;\n\n\t\t// If there is only one signature, or we're on first signature of list\n\t\tif ((length < 2 || first) && !cycle) {\n\t\t\tthis.cancel();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.updateActiveSignature(first && cycle ? length - 1 : activeSignature - 1);\n\t}\n\n\tprivate updateActiveSignature(activeSignature: number) {\n\t\tif (this.state.type !== ParameterHintState.Type.Active) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.state = new ParameterHintState.Active({ ...this.state.hints, activeSignature });\n\t\tthis._onChangedHints.fire(this.state.hints);\n\t}\n\n\tprivate async doTrigger(triggerId: number): Promise {\n\t\tconst isRetrigger = this.state.type === ParameterHintState.Type.Active || this.state.type === ParameterHintState.Type.Pending;\n\t\tconst activeSignatureHelp = this.getLastActiveHints();\n\t\tthis.cancel(true);\n\n\t\tif (this._pendingTriggers.length === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst context: TriggerContext = this._pendingTriggers.reduce(mergeTriggerContexts);\n\t\tthis._pendingTriggers = [];\n\n\t\tconst triggerContext = {\n\t\t\ttriggerKind: context.triggerKind,\n\t\t\ttriggerCharacter: context.triggerCharacter,\n\t\t\tisRetrigger: isRetrigger,\n\t\t\tactiveSignatureHelp: activeSignatureHelp\n\t\t};\n\n\t\tif (!this.editor.hasModel()) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst model = this.editor.getModel();\n\t\tconst position = this.editor.getPosition();\n\n\t\tthis.state = new ParameterHintState.Pending(\n\t\t\tcreateCancelablePromise(token => provideSignatureHelp(model, position, triggerContext, token)),\n\t\t\tactiveSignatureHelp);\n\n\t\ttry {\n\t\t\tconst result = await this.state.request;\n\n\t\t\t// Check that we are still resolving the correct signature help\n\t\t\tif (triggerId !== this.triggerId) {\n\t\t\t\tresult?.dispose();\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (!result || !result.value.signatures || result.value.signatures.length === 0) {\n\t\t\t\tresult?.dispose();\n\t\t\t\tthis._lastSignatureHelpResult.clear();\n\t\t\t\tthis.cancel();\n\t\t\t\treturn false;\n\t\t\t} else {\n\t\t\t\tthis.state = new ParameterHintState.Active(result.value);\n\t\t\t\tthis._lastSignatureHelpResult.value = result;\n\t\t\t\tthis._onChangedHints.fire(this.state.hints);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (triggerId === this.triggerId) {\n\t\t\t\tthis.state = ParameterHintState.Default;\n\t\t\t}\n\t\t\tonUnexpectedError(error);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate getLastActiveHints(): modes.SignatureHelp | undefined {\n\t\tswitch (this.state.type) {\n\t\t\tcase ParameterHintState.Type.Active: return this.state.hints;\n\t\t\tcase ParameterHintState.Type.Pending: return this.state.previouslyActiveHints;\n\t\t\tdefault: return undefined;\n\t\t}\n\t}\n\n\tprivate get isTriggered(): boolean {\n\t\treturn this.state.type === ParameterHintState.Type.Active\n\t\t\t|| this.state.type === ParameterHintState.Type.Pending\n\t\t\t|| this.throttledDelayer.isTriggered();\n\t}\n\n\tprivate onModelChanged(): void {\n\t\tthis.cancel();\n\n\t\t// Update trigger characters\n\t\tthis.triggerChars = new CharacterSet();\n\t\tthis.retriggerChars = new CharacterSet();\n\n\t\tconst model = this.editor.getModel();\n\t\tif (!model) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const support of modes.SignatureHelpProviderRegistry.ordered(model)) {\n\t\t\tfor (const ch of support.signatureHelpTriggerCharacters || []) {\n\t\t\t\tthis.triggerChars.add(ch.charCodeAt(0));\n\n\t\t\t\t// All trigger characters are also considered retrigger characters\n\t\t\t\tthis.retriggerChars.add(ch.charCodeAt(0));\n\t\t\t}\n\n\t\t\tfor (const ch of support.signatureHelpRetriggerCharacters || []) {\n\t\t\t\tthis.retriggerChars.add(ch.charCodeAt(0));\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onDidType(text: string) {\n\t\tif (!this.triggerOnType) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst lastCharIndex = text.length - 1;\n\t\tconst triggerCharCode = text.charCodeAt(lastCharIndex);\n\n\t\tif (this.triggerChars.has(triggerCharCode) || this.isTriggered && this.retriggerChars.has(triggerCharCode)) {\n\t\t\tthis.trigger({\n\t\t\t\ttriggerKind: modes.SignatureHelpTriggerKind.TriggerCharacter,\n\t\t\t\ttriggerCharacter: text.charAt(lastCharIndex),\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate onCursorChange(e: ICursorSelectionChangedEvent): void {\n\t\tif (e.source === 'mouse') {\n\t\t\tthis.cancel();\n\t\t} else if (this.isTriggered) {\n\t\t\tthis.trigger({ triggerKind: modes.SignatureHelpTriggerKind.ContentChange });\n\t\t}\n\t}\n\n\tprivate onModelContentChange(): void {\n\t\tif (this.isTriggered) {\n\t\t\tthis.trigger({ triggerKind: modes.SignatureHelpTriggerKind.ContentChange });\n\t\t}\n\t}\n\n\tprivate onEditorConfigurationChange(): void {\n\t\tthis.triggerOnType = this.editor.getOption(EditorOption.parameterHints).enabled;\n\n\t\tif (!this.triggerOnType) {\n\t\t\tthis.cancel();\n\t\t}\n\t}\n\n\toverride dispose(): void {\n\t\tthis.cancel(true);\n\t\tsuper.dispose();\n\t}\n}\n\nfunction mergeTriggerContexts(previous: TriggerContext, current: TriggerContext) {\n\tswitch (current.triggerKind) {\n\t\tcase modes.SignatureHelpTriggerKind.Invoke:\n\t\t\t// Invoke overrides previous triggers.\n\t\t\treturn current;\n\n\t\tcase modes.SignatureHelpTriggerKind.ContentChange:\n\t\t\t// Ignore content changes triggers\n\t\t\treturn previous;\n\n\t\tcase modes.SignatureHelpTriggerKind.TriggerCharacter:\n\t\tdefault:\n\t\t\treturn current;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';\nimport { CompletionModel } from './completionModel';\nimport { ISelectedSuggestion } from './suggestWidget';\n\nexport class SuggestAlternatives {\n\n\tstatic readonly OtherSuggestions = new RawContextKey('hasOtherSuggestions', false);\n\n\tprivate readonly _ckOtherSuggestions: IContextKey;\n\n\tprivate _index: number = 0;\n\tprivate _model: CompletionModel | undefined;\n\tprivate _acceptNext: ((selected: ISelectedSuggestion) => any) | undefined;\n\tprivate _listener: IDisposable | undefined;\n\tprivate _ignore: boolean | undefined;\n\n\tconstructor(\n\t\tprivate readonly _editor: ICodeEditor,\n\t\t@IContextKeyService contextKeyService: IContextKeyService\n\t) {\n\t\tthis._ckOtherSuggestions = SuggestAlternatives.OtherSuggestions.bindTo(contextKeyService);\n\t}\n\n\tdispose(): void {\n\t\tthis.reset();\n\t}\n\n\treset(): void {\n\t\tthis._ckOtherSuggestions.reset();\n\t\tthis._listener?.dispose();\n\t\tthis._model = undefined;\n\t\tthis._acceptNext = undefined;\n\t\tthis._ignore = false;\n\t}\n\n\tset({ model, index }: ISelectedSuggestion, acceptNext: (selected: ISelectedSuggestion) => any): void {\n\n\t\t// no suggestions -> nothing to do\n\t\tif (model.items.length === 0) {\n\t\t\tthis.reset();\n\t\t\treturn;\n\t\t}\n\n\t\t// no alternative suggestions -> nothing to do\n\t\tlet nextIndex = SuggestAlternatives._moveIndex(true, model, index);\n\t\tif (nextIndex === index) {\n\t\t\tthis.reset();\n\t\t\treturn;\n\t\t}\n\n\t\tthis._acceptNext = acceptNext;\n\t\tthis._model = model;\n\t\tthis._index = index;\n\t\tthis._listener = this._editor.onDidChangeCursorPosition(() => {\n\t\t\tif (!this._ignore) {\n\t\t\t\tthis.reset();\n\t\t\t}\n\t\t});\n\t\tthis._ckOtherSuggestions.set(true);\n\t}\n\n\tprivate static _moveIndex(fwd: boolean, model: CompletionModel, index: number): number {\n\t\tlet newIndex = index;\n\t\twhile (true) {\n\t\t\tnewIndex = (newIndex + model.items.length + (fwd ? +1 : -1)) % model.items.length;\n\t\t\tif (newIndex === index) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!model.items[newIndex].completion.additionalTextEdits) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn newIndex;\n\t}\n\n\tnext(): void {\n\t\tthis._move(true);\n\t}\n\n\tprev(): void {\n\t\tthis._move(false);\n\t}\n\n\tprivate _move(fwd: boolean): void {\n\t\tif (!this._model) {\n\t\t\t// nothing to reason about\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tthis._ignore = true;\n\t\t\tthis._index = SuggestAlternatives._moveIndex(fwd, this._model, this._index);\n\t\t\tthis._acceptNext!({ index: this._index, item: this._model.items[this._index], model: this._model });\n\t\t} finally {\n\t\t\tthis._ignore = false;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';\n\nexport class WordContextKey {\n\n\tstatic readonly AtEnd = new RawContextKey('atEndOfWord', false);\n\n\tprivate readonly _ckAtEnd: IContextKey;\n\tprivate readonly _configListener: IDisposable;\n\n\tprivate _enabled: boolean = false;\n\tprivate _selectionListener?: IDisposable;\n\n\tconstructor(\n\t\tprivate readonly _editor: ICodeEditor,\n\t\t@IContextKeyService contextKeyService: IContextKeyService,\n\t) {\n\n\t\tthis._ckAtEnd = WordContextKey.AtEnd.bindTo(contextKeyService);\n\t\tthis._configListener = this._editor.onDidChangeConfiguration(e => e.hasChanged(EditorOption.tabCompletion) && this._update());\n\t\tthis._update();\n\t}\n\n\tdispose(): void {\n\t\tthis._configListener.dispose();\n\t\tthis._selectionListener?.dispose();\n\t\tthis._ckAtEnd.reset();\n\t}\n\n\tprivate _update(): void {\n\t\t// only update this when tab completions are enabled\n\t\tconst enabled = this._editor.getOption(EditorOption.tabCompletion) === 'on';\n\t\tif (this._enabled === enabled) {\n\t\t\treturn;\n\t\t}\n\t\tthis._enabled = enabled;\n\n\t\tif (this._enabled) {\n\t\t\tconst checkForWordEnd = () => {\n\t\t\t\tif (!this._editor.hasModel()) {\n\t\t\t\t\tthis._ckAtEnd.set(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst model = this._editor.getModel();\n\t\t\t\tconst selection = this._editor.getSelection();\n\t\t\t\tconst word = model.getWordAtPosition(selection.getStartPosition());\n\t\t\t\tif (!word) {\n\t\t\t\t\tthis._ckAtEnd.set(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._ckAtEnd.set(word.endColumn === selection.getStartPosition().column);\n\t\t\t};\n\t\t\tthis._selectionListener = this._editor.onDidChangeCursorSelection(checkForWordEnd);\n\t\t\tcheckForWordEnd();\n\n\t\t} else if (this._selectionListener) {\n\t\t\tthis._ckAtEnd.reset();\n\t\t\tthis._selectionListener.dispose();\n\t\t\tthis._selectionListener = undefined;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport { RawContextKey } from 'vs/platform/contextkey/common/contextkey';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const IAccessibilityService = createDecorator('accessibilityService');\n\nexport interface IAccessibilityService {\n\treadonly _serviceBrand: undefined;\n\n\treadonly onDidChangeScreenReaderOptimized: Event;\n\tisScreenReaderOptimized(): boolean;\n\tgetAccessibilitySupport(): AccessibilitySupport;\n}\n\nexport const enum AccessibilitySupport {\n\t/**\n\t * This should be the browser case where it is not known if a screen reader is attached or no.\n\t */\n\tUnknown = 0,\n\n\tDisabled = 1,\n\n\tEnabled = 2\n}\n\nexport const CONTEXT_ACCESSIBILITY_MODE_ENABLED = new RawContextKey('accessibilityModeEnabled', false);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as browser from 'vs/base/browser/browser';\nimport * as arrays from 'vs/base/common/arrays';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport * as objects from 'vs/base/common/objects';\nimport * as platform from 'vs/base/common/platform';\nimport { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver';\nimport { FontMeasurements } from 'vs/editor/browser/config/fontMeasurements';\nimport { migrateOptions } from 'vs/editor/browser/config/migrateOptions';\nimport { TabFocus } from 'vs/editor/browser/config/tabFocus';\nimport { ComputeOptionsMemory, ConfigurationChangedEvent, EditorOption, editorOptionsRegistry, FindComputedEditorOptionValueById, IComputedEditorOptions, IEditorOptions, IEnvironmentalOptions } from 'vs/editor/common/config/editorOptions';\nimport { EditorZoom } from 'vs/editor/common/config/editorZoom';\nimport { BareFontInfo, FontInfo, IValidatedEditorOptions } from 'vs/editor/common/config/fontInfo';\nimport { IDimension } from 'vs/editor/common/core/dimension';\nimport { IEditorConfiguration } from 'vs/editor/common/config/editorConfiguration';\nimport { AccessibilitySupport, IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';\n\nexport interface IEditorConstructionOptions extends IEditorOptions {\n\t/**\n\t * The initial editor dimension (to avoid measuring the container).\n\t */\n\tdimension?: IDimension;\n\t/**\n\t * Place overflow widgets inside an external DOM node.\n\t * Defaults to an internal DOM node.\n\t */\n\toverflowWidgetsDomNode?: HTMLElement;\n}\n\nexport class EditorConfiguration extends Disposable implements IEditorConfiguration {\n\n\tprivate _onDidChange = this._register(new Emitter());\n\tpublic readonly onDidChange: Event = this._onDidChange.event;\n\n\tprivate _onDidChangeFast = this._register(new Emitter());\n\tpublic readonly onDidChangeFast: Event = this._onDidChangeFast.event;\n\n\tpublic readonly isSimpleWidget: boolean;\n\tprivate readonly _containerObserver: ElementSizeObserver;\n\n\tprivate _isDominatedByLongLines: boolean = false;\n\tprivate _viewLineCount: number = 1;\n\tprivate _lineNumbersDigitCount: number = 1;\n\tprivate _reservedHeight: number = 0;\n\n\tprivate readonly _computeOptionsMemory: ComputeOptionsMemory = new ComputeOptionsMemory();\n\t/**\n\t * Raw options as they were passed in and merged with all calls to `updateOptions`.\n\t */\n\tprivate readonly _rawOptions: IEditorOptions;\n\t/**\n\t * Validated version of `_rawOptions`.\n\t */\n\tprivate _validatedOptions: ValidatedEditorOptions;\n\t/**\n\t * Complete options which are a combination of passed in options and env values.\n\t */\n\tpublic options: ComputedEditorOptions;\n\n\tconstructor(\n\t\tisSimpleWidget: boolean,\n\t\toptions: Readonly,\n\t\tcontainer: HTMLElement | null,\n\t\t@IAccessibilityService private readonly _accessibilityService: IAccessibilityService\n\t) {\n\t\tsuper();\n\t\tthis.isSimpleWidget = isSimpleWidget;\n\t\tthis._containerObserver = this._register(new ElementSizeObserver(container, options.dimension));\n\n\t\tthis._rawOptions = deepCloneAndMigrateOptions(options);\n\t\tthis._validatedOptions = EditorOptionsUtil.validateOptions(this._rawOptions);\n\t\tthis.options = this._computeOptions();\n\n\t\tif (this.options.get(EditorOption.automaticLayout)) {\n\t\t\tthis._containerObserver.startObserving();\n\t\t}\n\n\t\tthis._register(EditorZoom.onDidChangeZoomLevel(() => this._recomputeOptions()));\n\t\tthis._register(TabFocus.onDidChangeTabFocus(() => this._recomputeOptions()));\n\t\tthis._register(this._containerObserver.onDidChange(() => this._recomputeOptions()));\n\t\tthis._register(FontMeasurements.onDidChange(() => this._recomputeOptions()));\n\t\tthis._register(browser.PixelRatio.onDidChange(() => this._recomputeOptions()));\n\t\tthis._register(this._accessibilityService.onDidChangeScreenReaderOptimized(() => this._recomputeOptions()));\n\t}\n\n\tprivate _recomputeOptions(): void {\n\t\tconst newOptions = this._computeOptions();\n\t\tconst changeEvent = EditorOptionsUtil.checkEquals(this.options, newOptions);\n\t\tif (changeEvent === null) {\n\t\t\t// nothing changed!\n\t\t\treturn;\n\t\t}\n\n\t\tthis.options = newOptions;\n\t\tthis._onDidChangeFast.fire(changeEvent);\n\t\tthis._onDidChange.fire(changeEvent);\n\t}\n\n\tprivate _computeOptions(): ComputedEditorOptions {\n\t\tconst partialEnv = this._readEnvConfiguration();\n\t\tconst bareFontInfo = BareFontInfo.createFromValidatedSettings(this._validatedOptions, partialEnv.pixelRatio, this.isSimpleWidget);\n\t\tconst fontInfo = this._readFontInfo(bareFontInfo);\n\t\tconst env: IEnvironmentalOptions = {\n\t\t\tmemory: this._computeOptionsMemory,\n\t\t\touterWidth: partialEnv.outerWidth,\n\t\t\touterHeight: partialEnv.outerHeight - this._reservedHeight,\n\t\t\tfontInfo: fontInfo,\n\t\t\textraEditorClassName: partialEnv.extraEditorClassName,\n\t\t\tisDominatedByLongLines: this._isDominatedByLongLines,\n\t\t\tviewLineCount: this._viewLineCount,\n\t\t\tlineNumbersDigitCount: this._lineNumbersDigitCount,\n\t\t\temptySelectionClipboard: partialEnv.emptySelectionClipboard,\n\t\t\tpixelRatio: partialEnv.pixelRatio,\n\t\t\ttabFocusMode: TabFocus.getTabFocusMode(),\n\t\t\taccessibilitySupport: partialEnv.accessibilitySupport\n\t\t};\n\t\treturn EditorOptionsUtil.computeOptions(this._validatedOptions, env);\n\t}\n\n\tprotected _readEnvConfiguration(): IEnvConfiguration {\n\t\treturn {\n\t\t\textraEditorClassName: getExtraEditorClassName(),\n\t\t\touterWidth: this._containerObserver.getWidth(),\n\t\t\touterHeight: this._containerObserver.getHeight(),\n\t\t\temptySelectionClipboard: browser.isWebKit || browser.isFirefox,\n\t\t\tpixelRatio: browser.PixelRatio.value,\n\t\t\taccessibilitySupport: (\n\t\t\t\tthis._accessibilityService.isScreenReaderOptimized()\n\t\t\t\t\t? AccessibilitySupport.Enabled\n\t\t\t\t\t: this._accessibilityService.getAccessibilitySupport()\n\t\t\t)\n\t\t};\n\t}\n\n\tprotected _readFontInfo(bareFontInfo: BareFontInfo): FontInfo {\n\t\treturn FontMeasurements.readFontInfo(bareFontInfo);\n\t}\n\n\tpublic getRawOptions(): IEditorOptions {\n\t\treturn this._rawOptions;\n\t}\n\n\tpublic updateOptions(_newOptions: Readonly): void {\n\t\tconst newOptions = deepCloneAndMigrateOptions(_newOptions);\n\n\t\tconst didChange = EditorOptionsUtil.applyUpdate(this._rawOptions, newOptions);\n\t\tif (!didChange) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._validatedOptions = EditorOptionsUtil.validateOptions(this._rawOptions);\n\t\tthis._recomputeOptions();\n\t}\n\n\tpublic observeContainer(dimension?: IDimension): void {\n\t\tthis._containerObserver.observe(dimension);\n\t}\n\n\tpublic setIsDominatedByLongLines(isDominatedByLongLines: boolean): void {\n\t\tif (this._isDominatedByLongLines === isDominatedByLongLines) {\n\t\t\treturn;\n\t\t}\n\t\tthis._isDominatedByLongLines = isDominatedByLongLines;\n\t\tthis._recomputeOptions();\n\t}\n\n\tpublic setModelLineCount(modelLineCount: number): void {\n\t\tconst lineNumbersDigitCount = digitCount(modelLineCount);\n\t\tif (this._lineNumbersDigitCount === lineNumbersDigitCount) {\n\t\t\treturn;\n\t\t}\n\t\tthis._lineNumbersDigitCount = lineNumbersDigitCount;\n\t\tthis._recomputeOptions();\n\t}\n\n\tpublic setViewLineCount(viewLineCount: number): void {\n\t\tif (this._viewLineCount === viewLineCount) {\n\t\t\treturn;\n\t\t}\n\t\tthis._viewLineCount = viewLineCount;\n\t\tthis._recomputeOptions();\n\t}\n\n\tpublic setReservedHeight(reservedHeight: number) {\n\t\tif (this._reservedHeight === reservedHeight) {\n\t\t\treturn;\n\t\t}\n\t\tthis._reservedHeight = reservedHeight;\n\t\tthis._recomputeOptions();\n\t}\n}\n\nfunction digitCount(n: number): number {\n\tlet r = 0;\n\twhile (n) {\n\t\tn = Math.floor(n / 10);\n\t\tr++;\n\t}\n\treturn r ? r : 1;\n}\n\nfunction getExtraEditorClassName(): string {\n\tlet extra = '';\n\tif (!browser.isSafari && !browser.isWebkitWebView) {\n\t\t// Use user-select: none in all browsers except Safari and native macOS WebView\n\t\textra += 'no-user-select ';\n\t}\n\tif (browser.isSafari) {\n\t\t// See https://github.com/microsoft/vscode/issues/108822\n\t\textra += 'no-minimap-shadow ';\n\t}\n\tif (platform.isMacintosh) {\n\t\textra += 'mac ';\n\t}\n\treturn extra;\n}\n\nexport interface IEnvConfiguration {\n\textraEditorClassName: string;\n\touterWidth: number;\n\touterHeight: number;\n\temptySelectionClipboard: boolean;\n\tpixelRatio: number;\n\taccessibilitySupport: AccessibilitySupport;\n}\n\nclass ValidatedEditorOptions implements IValidatedEditorOptions {\n\tprivate readonly _values: any[] = [];\n\tpublic _read(option: EditorOption): T {\n\t\treturn this._values[option];\n\t}\n\tpublic get(id: T): FindComputedEditorOptionValueById {\n\t\treturn this._values[id];\n\t}\n\tpublic _write(option: EditorOption, value: T): void {\n\t\tthis._values[option] = value;\n\t}\n}\n\nexport class ComputedEditorOptions implements IComputedEditorOptions {\n\tprivate readonly _values: any[] = [];\n\tpublic _read(id: EditorOption): T {\n\t\tif (id >= this._values.length) {\n\t\t\tthrow new Error('Cannot read uninitialized value');\n\t\t}\n\t\treturn this._values[id];\n\t}\n\tpublic get(id: T): FindComputedEditorOptionValueById {\n\t\treturn this._read(id);\n\t}\n\tpublic _write(id: EditorOption, value: T): void {\n\t\tthis._values[id] = value;\n\t}\n}\n\nclass EditorOptionsUtil {\n\n\tpublic static validateOptions(options: IEditorOptions): ValidatedEditorOptions {\n\t\tconst result = new ValidatedEditorOptions();\n\t\tfor (const editorOption of editorOptionsRegistry) {\n\t\t\tconst value = (editorOption.name === '_never_' ? undefined : (options as any)[editorOption.name]);\n\t\t\tresult._write(editorOption.id, editorOption.validate(value));\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic static computeOptions(options: ValidatedEditorOptions, env: IEnvironmentalOptions): ComputedEditorOptions {\n\t\tconst result = new ComputedEditorOptions();\n\t\tfor (const editorOption of editorOptionsRegistry) {\n\t\t\tresult._write(editorOption.id, editorOption.compute(env, result, options._read(editorOption.id)));\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate static _deepEquals(a: T, b: T): boolean {\n\t\tif (typeof a !== 'object' || typeof b !== 'object' || !a || !b) {\n\t\t\treturn a === b;\n\t\t}\n\t\tif (Array.isArray(a) || Array.isArray(b)) {\n\t\t\treturn (Array.isArray(a) && Array.isArray(b) ? arrays.equals(a, b) : false);\n\t\t}\n\t\tif (Object.keys(a).length !== Object.keys(b).length) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (const key in a) {\n\t\t\tif (!EditorOptionsUtil._deepEquals(a[key], b[key])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic static checkEquals(a: ComputedEditorOptions, b: ComputedEditorOptions): ConfigurationChangedEvent | null {\n\t\tconst result: boolean[] = [];\n\t\tlet somethingChanged = false;\n\t\tfor (const editorOption of editorOptionsRegistry) {\n\t\t\tconst changed = !EditorOptionsUtil._deepEquals(a._read(editorOption.id), b._read(editorOption.id));\n\t\t\tresult[editorOption.id] = changed;\n\t\t\tif (changed) {\n\t\t\t\tsomethingChanged = true;\n\t\t\t}\n\t\t}\n\t\treturn (somethingChanged ? new ConfigurationChangedEvent(result) : null);\n\t}\n\n\t/**\n\t * Returns true if something changed.\n\t * Modifies `options`.\n\t*/\n\tpublic static applyUpdate(options: IEditorOptions, update: Readonly): boolean {\n\t\tlet changed = false;\n\t\tfor (const editorOption of editorOptionsRegistry) {\n\t\t\tif (update.hasOwnProperty(editorOption.name)) {\n\t\t\t\tconst result = editorOption.applyUpdate((options as any)[editorOption.name], (update as any)[editorOption.name]);\n\t\t\t\t(options as any)[editorOption.name] = result.newValue;\n\t\t\t\tchanged = changed || result.didChange;\n\t\t\t}\n\t\t}\n\t\treturn changed;\n\t}\n}\n\nfunction deepCloneAndMigrateOptions(_options: Readonly): IEditorOptions {\n\tconst options = objects.deepClone(_options);\n\tmigrateOptions(options);\n\treturn options;\n}\n","\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { AccessibilitySupport, CONTEXT_ACCESSIBILITY_MODE_ENABLED, IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';\nimport { IConfigurationService } from 'vs/platform/configuration/common/configuration';\nimport { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';\n\nexport class AccessibilityService extends Disposable implements IAccessibilityService {\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate _accessibilityModeEnabledContext: IContextKey;\n\tprotected _accessibilitySupport = AccessibilitySupport.Unknown;\n\tprotected readonly _onDidChangeScreenReaderOptimized = new Emitter();\n\n\tconstructor(\n\t\t@IContextKeyService private readonly _contextKeyService: IContextKeyService,\n\t\t@IConfigurationService protected readonly _configurationService: IConfigurationService,\n\t) {\n\t\tsuper();\n\t\tthis._accessibilityModeEnabledContext = CONTEXT_ACCESSIBILITY_MODE_ENABLED.bindTo(this._contextKeyService);\n\t\tconst updateContextKey = () => this._accessibilityModeEnabledContext.set(this.isScreenReaderOptimized());\n\t\tthis._register(this._configurationService.onDidChangeConfiguration(e => {\n\t\t\tif (e.affectsConfiguration('editor.accessibilitySupport')) {\n\t\t\t\tupdateContextKey();\n\t\t\t\tthis._onDidChangeScreenReaderOptimized.fire();\n\t\t\t}\n\t\t}));\n\t\tupdateContextKey();\n\t\tthis.onDidChangeScreenReaderOptimized(() => updateContextKey());\n\t}\n\n\tget onDidChangeScreenReaderOptimized(): Event {\n\t\treturn this._onDidChangeScreenReaderOptimized.event;\n\t}\n\n\tisScreenReaderOptimized(): boolean {\n\t\tconst config = this._configurationService.getValue('editor.accessibilitySupport');\n\t\treturn config === 'on' || (config === 'auto' && this._accessibilitySupport === AccessibilitySupport.Enabled);\n\t}\n\n\tgetAccessibilitySupport(): AccessibilitySupport {\n\t\treturn this._accessibilitySupport;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, PauseableEmitter } from 'vs/base/common/event';\nimport { Iterable } from 'vs/base/common/iterator';\nimport { DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';\nimport { TernarySearchTree } from 'vs/base/common/map';\nimport { localize } from 'vs/nls';\nimport { CommandsRegistry } from 'vs/platform/commands/common/commands';\nimport { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';\nimport { ContextKeyExpression, ContextKeyInfo, IContext, IContextKey, IContextKeyChangeEvent, IContextKeyService, IContextKeyServiceTarget, IReadableSet, RawContextKey, SET_CONTEXT_COMMAND_ID } from 'vs/platform/contextkey/common/contextkey';\n\nconst KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context';\n\nexport class Context implements IContext {\n\n\tprotected _parent: Context | null;\n\tprotected _value: { [key: string]: any; };\n\tprotected _id: number;\n\n\tconstructor(id: number, parent: Context | null) {\n\t\tthis._id = id;\n\t\tthis._parent = parent;\n\t\tthis._value = Object.create(null);\n\t\tthis._value['_contextId'] = id;\n\t}\n\n\tpublic setValue(key: string, value: any): boolean {\n\t\t// console.log('SET ' + key + ' = ' + value + ' ON ' + this._id);\n\t\tif (this._value[key] !== value) {\n\t\t\tthis._value[key] = value;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic removeValue(key: string): boolean {\n\t\t// console.log('REMOVE ' + key + ' FROM ' + this._id);\n\t\tif (key in this._value) {\n\t\t\tdelete this._value[key];\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic getValue(key: string): T | undefined {\n\t\tconst ret = this._value[key];\n\t\tif (typeof ret === 'undefined' && this._parent) {\n\t\t\treturn this._parent.getValue(key);\n\t\t}\n\t\treturn ret;\n\t}\n}\n\nclass NullContext extends Context {\n\n\tstatic readonly INSTANCE = new NullContext();\n\n\tconstructor() {\n\t\tsuper(-1, null);\n\t}\n\n\tpublic override setValue(key: string, value: any): boolean {\n\t\treturn false;\n\t}\n\n\tpublic override removeValue(key: string): boolean {\n\t\treturn false;\n\t}\n\n\tpublic override getValue(key: string): T | undefined {\n\t\treturn undefined;\n\t}\n}\n\nclass ConfigAwareContextValuesContainer extends Context {\n\tprivate static readonly _keyPrefix = 'config.';\n\n\tprivate readonly _values = TernarySearchTree.forConfigKeys();\n\tprivate readonly _listener: IDisposable;\n\n\tconstructor(\n\t\tid: number,\n\t\tprivate readonly _configurationService: IConfigurationService,\n\t\temitter: Emitter\n\t) {\n\t\tsuper(id, null);\n\n\t\tthis._listener = this._configurationService.onDidChangeConfiguration(event => {\n\t\t\tif (event.source === ConfigurationTarget.DEFAULT) {\n\t\t\t\t// new setting, reset everything\n\t\t\t\tconst allKeys = Array.from(Iterable.map(this._values, ([k]) => k));\n\t\t\t\tthis._values.clear();\n\t\t\t\temitter.fire(new ArrayContextKeyChangeEvent(allKeys));\n\t\t\t} else {\n\t\t\t\tconst changedKeys: string[] = [];\n\t\t\t\tfor (const configKey of event.affectedKeys) {\n\t\t\t\t\tconst contextKey = `config.${configKey}`;\n\n\t\t\t\t\tconst cachedItems = this._values.findSuperstr(contextKey);\n\t\t\t\t\tif (cachedItems !== undefined) {\n\t\t\t\t\t\tchangedKeys.push(...Iterable.map(cachedItems, ([key]) => key));\n\t\t\t\t\t\tthis._values.deleteSuperstr(contextKey);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this._values.has(contextKey)) {\n\t\t\t\t\t\tchangedKeys.push(contextKey);\n\t\t\t\t\t\tthis._values.delete(contextKey);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\temitter.fire(new ArrayContextKeyChangeEvent(changedKeys));\n\t\t\t}\n\t\t});\n\t}\n\n\tdispose(): void {\n\t\tthis._listener.dispose();\n\t}\n\n\toverride getValue(key: string): any {\n\n\t\tif (key.indexOf(ConfigAwareContextValuesContainer._keyPrefix) !== 0) {\n\t\t\treturn super.getValue(key);\n\t\t}\n\n\t\tif (this._values.has(key)) {\n\t\t\treturn this._values.get(key);\n\t\t}\n\n\t\tconst configKey = key.substr(ConfigAwareContextValuesContainer._keyPrefix.length);\n\t\tconst configValue = this._configurationService.getValue(configKey);\n\t\tlet value: any = undefined;\n\t\tswitch (typeof configValue) {\n\t\t\tcase 'number':\n\t\t\tcase 'boolean':\n\t\t\tcase 'string':\n\t\t\t\tvalue = configValue;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (Array.isArray(configValue)) {\n\t\t\t\t\tvalue = JSON.stringify(configValue);\n\t\t\t\t} else {\n\t\t\t\t\tvalue = configValue;\n\t\t\t\t}\n\t\t}\n\n\t\tthis._values.set(key, value);\n\t\treturn value;\n\t}\n\n\toverride setValue(key: string, value: any): boolean {\n\t\treturn super.setValue(key, value);\n\t}\n\n\toverride removeValue(key: string): boolean {\n\t\treturn super.removeValue(key);\n\t}\n}\n\nclass ContextKey implements IContextKey {\n\n\tprivate _service: AbstractContextKeyService;\n\tprivate _key: string;\n\tprivate _defaultValue: T | undefined;\n\n\tconstructor(service: AbstractContextKeyService, key: string, defaultValue: T | undefined) {\n\t\tthis._service = service;\n\t\tthis._key = key;\n\t\tthis._defaultValue = defaultValue;\n\t\tthis.reset();\n\t}\n\n\tpublic set(value: T): void {\n\t\tthis._service.setContext(this._key, value);\n\t}\n\n\tpublic reset(): void {\n\t\tif (typeof this._defaultValue === 'undefined') {\n\t\t\tthis._service.removeContext(this._key);\n\t\t} else {\n\t\t\tthis._service.setContext(this._key, this._defaultValue);\n\t\t}\n\t}\n\n\tpublic get(): T | undefined {\n\t\treturn this._service.getContextKeyValue(this._key);\n\t}\n}\n\nclass SimpleContextKeyChangeEvent implements IContextKeyChangeEvent {\n\tconstructor(readonly key: string) { }\n\taffectsSome(keys: IReadableSet): boolean {\n\t\treturn keys.has(this.key);\n\t}\n}\n\nclass ArrayContextKeyChangeEvent implements IContextKeyChangeEvent {\n\tconstructor(readonly keys: string[]) { }\n\taffectsSome(keys: IReadableSet): boolean {\n\t\tfor (const key of this.keys) {\n\t\t\tif (keys.has(key)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n\nclass CompositeContextKeyChangeEvent implements IContextKeyChangeEvent {\n\tconstructor(readonly events: IContextKeyChangeEvent[]) { }\n\taffectsSome(keys: IReadableSet): boolean {\n\t\tfor (const e of this.events) {\n\t\t\tif (e.affectsSome(keys)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n\nexport abstract class AbstractContextKeyService implements IContextKeyService {\n\tdeclare _serviceBrand: undefined;\n\n\tprotected _isDisposed: boolean;\n\tprotected _myContextId: number;\n\n\tprotected _onDidChangeContext = new PauseableEmitter({ merge: input => new CompositeContextKeyChangeEvent(input) });\n\treadonly onDidChangeContext = this._onDidChangeContext.event;\n\n\tconstructor(myContextId: number) {\n\t\tthis._isDisposed = false;\n\t\tthis._myContextId = myContextId;\n\t}\n\n\tabstract dispose(): void;\n\n\tpublic createKey(key: string, defaultValue: T | undefined): IContextKey {\n\t\tif (this._isDisposed) {\n\t\t\tthrow new Error(`AbstractContextKeyService has been disposed`);\n\t\t}\n\t\treturn new ContextKey(this, key, defaultValue);\n\t}\n\n\n\tbufferChangeEvents(callback: Function): void {\n\t\tthis._onDidChangeContext.pause();\n\t\ttry {\n\t\t\tcallback();\n\t\t} finally {\n\t\t\tthis._onDidChangeContext.resume();\n\t\t}\n\t}\n\n\tpublic createScoped(domNode: IContextKeyServiceTarget): IContextKeyService {\n\t\tif (this._isDisposed) {\n\t\t\tthrow new Error(`AbstractContextKeyService has been disposed`);\n\t\t}\n\t\treturn new ScopedContextKeyService(this, domNode);\n\t}\n\n\tpublic contextMatchesRules(rules: ContextKeyExpression | undefined): boolean {\n\t\tif (this._isDisposed) {\n\t\t\tthrow new Error(`AbstractContextKeyService has been disposed`);\n\t\t}\n\t\tconst context = this.getContextValuesContainer(this._myContextId);\n\t\tconst result = (rules ? rules.evaluate(context) : true);\n\t\t// console.group(rules.serialize() + ' -> ' + result);\n\t\t// rules.keys().forEach(key => { console.log(key, ctx[key]); });\n\t\t// console.groupEnd();\n\t\treturn result;\n\t}\n\n\tpublic getContextKeyValue(key: string): T | undefined {\n\t\tif (this._isDisposed) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn this.getContextValuesContainer(this._myContextId).getValue(key);\n\t}\n\n\tpublic setContext(key: string, value: any): void {\n\t\tif (this._isDisposed) {\n\t\t\treturn;\n\t\t}\n\t\tconst myContext = this.getContextValuesContainer(this._myContextId);\n\t\tif (!myContext) {\n\t\t\treturn;\n\t\t}\n\t\tif (myContext.setValue(key, value)) {\n\t\t\tthis._onDidChangeContext.fire(new SimpleContextKeyChangeEvent(key));\n\t\t}\n\t}\n\n\tpublic removeContext(key: string): void {\n\t\tif (this._isDisposed) {\n\t\t\treturn;\n\t\t}\n\t\tif (this.getContextValuesContainer(this._myContextId).removeValue(key)) {\n\t\t\tthis._onDidChangeContext.fire(new SimpleContextKeyChangeEvent(key));\n\t\t}\n\t}\n\n\tpublic getContext(target: IContextKeyServiceTarget | null): IContext {\n\t\tif (this._isDisposed) {\n\t\t\treturn NullContext.INSTANCE;\n\t\t}\n\t\treturn this.getContextValuesContainer(findContextAttr(target));\n\t}\n\n\tpublic abstract getContextValuesContainer(contextId: number): Context;\n\tpublic abstract createChildContext(parentContextId?: number): number;\n\tpublic abstract disposeContext(contextId: number): void;\n}\n\nexport class ContextKeyService extends AbstractContextKeyService implements IContextKeyService {\n\n\tprivate _lastContextId: number;\n\tprivate readonly _contexts = new Map();\n\n\tprivate readonly _toDispose = new DisposableStore();\n\n\tconstructor(@IConfigurationService configurationService: IConfigurationService) {\n\t\tsuper(0);\n\t\tthis._lastContextId = 0;\n\n\n\t\tconst myContext = new ConfigAwareContextValuesContainer(this._myContextId, configurationService, this._onDidChangeContext);\n\t\tthis._contexts.set(this._myContextId, myContext);\n\t\tthis._toDispose.add(myContext);\n\n\t\t// Uncomment this to see the contexts continuously logged\n\t\t// let lastLoggedValue: string | null = null;\n\t\t// setInterval(() => {\n\t\t// \tlet values = Object.keys(this._contexts).map((key) => this._contexts[key]);\n\t\t// \tlet logValue = values.map(v => JSON.stringify(v._value, null, '\\t')).join('\\n');\n\t\t// \tif (lastLoggedValue !== logValue) {\n\t\t// \t\tlastLoggedValue = logValue;\n\t\t// \t\tconsole.log(lastLoggedValue);\n\t\t// \t}\n\t\t// }, 2000);\n\t}\n\n\tpublic dispose(): void {\n\t\tthis._onDidChangeContext.dispose();\n\t\tthis._isDisposed = true;\n\t\tthis._toDispose.dispose();\n\t}\n\n\tpublic getContextValuesContainer(contextId: number): Context {\n\t\tif (this._isDisposed) {\n\t\t\treturn NullContext.INSTANCE;\n\t\t}\n\t\treturn this._contexts.get(contextId) || NullContext.INSTANCE;\n\t}\n\n\tpublic createChildContext(parentContextId: number = this._myContextId): number {\n\t\tif (this._isDisposed) {\n\t\t\tthrow new Error(`ContextKeyService has been disposed`);\n\t\t}\n\t\tlet id = (++this._lastContextId);\n\t\tthis._contexts.set(id, new Context(id, this.getContextValuesContainer(parentContextId)));\n\t\treturn id;\n\t}\n\n\tpublic disposeContext(contextId: number): void {\n\t\tif (!this._isDisposed) {\n\t\t\tthis._contexts.delete(contextId);\n\t\t}\n\t}\n}\n\nclass ScopedContextKeyService extends AbstractContextKeyService {\n\n\tprivate _parent: AbstractContextKeyService;\n\tprivate _domNode: IContextKeyServiceTarget;\n\n\tprivate readonly _parentChangeListener = new MutableDisposable();\n\n\tconstructor(parent: AbstractContextKeyService, domNode: IContextKeyServiceTarget) {\n\t\tsuper(parent.createChildContext());\n\t\tthis._parent = parent;\n\t\tthis._updateParentChangeListener();\n\n\t\tthis._domNode = domNode;\n\t\tif (this._domNode.hasAttribute(KEYBINDING_CONTEXT_ATTR)) {\n\t\t\tlet extraInfo = '';\n\t\t\tif ((this._domNode as HTMLElement).classList) {\n\t\t\t\textraInfo = Array.from((this._domNode as HTMLElement).classList.values()).join(', ');\n\t\t\t}\n\n\t\t\tconsole.error(`Element already has context attribute${extraInfo ? ': ' + extraInfo : ''}`);\n\t\t}\n\t\tthis._domNode.setAttribute(KEYBINDING_CONTEXT_ATTR, String(this._myContextId));\n\t}\n\n\tprivate _updateParentChangeListener(): void {\n\t\t// Forward parent events to this listener. Parent will change.\n\t\tthis._parentChangeListener.value = this._parent.onDidChangeContext(this._onDidChangeContext.fire, this._onDidChangeContext);\n\t}\n\n\tpublic dispose(): void {\n\t\tif (this._isDisposed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._onDidChangeContext.dispose();\n\t\tthis._parent.disposeContext(this._myContextId);\n\t\tthis._parentChangeListener.dispose();\n\t\tthis._domNode.removeAttribute(KEYBINDING_CONTEXT_ATTR);\n\t\tthis._isDisposed = true;\n\t}\n\n\tpublic getContextValuesContainer(contextId: number): Context {\n\t\tif (this._isDisposed) {\n\t\t\treturn NullContext.INSTANCE;\n\t\t}\n\t\treturn this._parent.getContextValuesContainer(contextId);\n\t}\n\n\tpublic createChildContext(parentContextId: number = this._myContextId): number {\n\t\tif (this._isDisposed) {\n\t\t\tthrow new Error(`ScopedContextKeyService has been disposed`);\n\t\t}\n\t\treturn this._parent.createChildContext(parentContextId);\n\t}\n\n\tpublic disposeContext(contextId: number): void {\n\t\tif (this._isDisposed) {\n\t\t\treturn;\n\t\t}\n\t\tthis._parent.disposeContext(contextId);\n\t}\n}\n\nfunction findContextAttr(domNode: IContextKeyServiceTarget | null): number {\n\twhile (domNode) {\n\t\tif (domNode.hasAttribute(KEYBINDING_CONTEXT_ATTR)) {\n\t\t\tconst attr = domNode.getAttribute(KEYBINDING_CONTEXT_ATTR);\n\t\t\tif (attr) {\n\t\t\t\treturn parseInt(attr, 10);\n\t\t\t}\n\t\t\treturn NaN;\n\t\t}\n\t\tdomNode = domNode.parentElement;\n\t}\n\treturn 0;\n}\n\nCommandsRegistry.registerCommand(SET_CONTEXT_COMMAND_ID, function (accessor, contextKey: any, contextValue: any) {\n\taccessor.get(IContextKeyService).createKey(String(contextKey), contextValue);\n});\n\nCommandsRegistry.registerCommand({\n\tid: 'getContextKeyInfo',\n\thandler() {\n\t\treturn [...RawContextKey.all()].sort((a, b) => a.key.localeCompare(b.key));\n\t},\n\tdescription: {\n\t\tdescription: localize('getContextKeyInfo', \"A command that returns information about context keys\"),\n\t\targs: []\n\t}\n});\n\nCommandsRegistry.registerCommand('_generateContextKeyInfo', function () {\n\tconst result: ContextKeyInfo[] = [];\n\tconst seen = new Set();\n\tfor (let info of RawContextKey.all()) {\n\t\tif (!seen.has(info.key)) {\n\t\t\tseen.add(info.key);\n\t\t\tresult.push(info);\n\t\t}\n\t}\n\tresult.sort((a, b) => a.key.localeCompare(b.key));\n\tconsole.log(JSON.stringify(result, undefined, 2));\n});\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { isIOS, isLinux, isMacintosh, isWeb, isWindows } from 'vs/base/common/platform';\nimport { localize } from 'vs/nls';\nimport { RawContextKey } from 'vs/platform/contextkey/common/contextkey';\n\nexport const IsMacContext = new RawContextKey('isMac', isMacintosh, localize('isMac', \"Whether the operating system is macOS\"));\nexport const IsLinuxContext = new RawContextKey('isLinux', isLinux, localize('isLinux', \"Whether the operating system is Linux\"));\nexport const IsWindowsContext = new RawContextKey('isWindows', isWindows, localize('isWindows', \"Whether the operating system is Windows\"));\n\nexport const IsWebContext = new RawContextKey('isWeb', isWeb, localize('isWeb', \"Whether the platform is a web browser\"));\nexport const IsMacNativeContext = new RawContextKey('isMacNative', isMacintosh && !isWeb, localize('isMacNative', \"Whether the operating system is macOS on a non-browser platform\"));\nexport const IsIOSContext = new RawContextKey('isIOS', isIOS, localize('isIOS', \"Whether the operating system is IOS\"));\n\nexport const IsDevelopmentContext = new RawContextKey('isDevelopment', false, true);\n\nexport const InputFocusedContextKey = 'inputFocus';\nexport const InputFocusedContext = new RawContextKey(InputFocusedContextKey, false, localize('inputFocus', \"Whether keyboard focus is inside an input box\"));\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IContextMenuDelegate } from 'vs/base/browser/contextmenu';\nimport { AnchorAlignment, AnchorAxisAlignment, IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const IContextViewService = createDecorator('contextViewService');\n\nexport interface IContextViewService extends IContextViewProvider {\n\n\treadonly _serviceBrand: undefined;\n\n\tshowContextView(delegate: IContextViewDelegate, container?: HTMLElement, shadowRoot?: boolean): IDisposable;\n\thideContextView(data?: any): void;\n\tgetContextViewElement(): HTMLElement;\n}\n\nexport interface IContextViewDelegate {\n\n\tcanRelayout?: boolean; // Default: true\n\n\tgetAnchor(): HTMLElement | { x: number; y: number; width?: number; height?: number; };\n\trender(container: HTMLElement): IDisposable;\n\tonHide?(data?: any): void;\n\tfocus?(): void;\n\tanchorAlignment?: AnchorAlignment;\n\tanchorAxisAlignment?: AnchorAxisAlignment;\n}\n\nexport const IContextMenuService = createDecorator('contextMenuService');\n\nexport interface IContextMenuService {\n\n\treadonly _serviceBrand: undefined;\n\n\tshowContextMenu(delegate: IContextMenuDelegate): void;\n}\n","\nimport Severity from 'vs/base/common/severity';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport interface IConfirmation {\n\ttitle?: string;\n\tmessage: string;\n\tdetail?: string;\n\tprimaryButton?: string;\n\tsecondaryButton?: string;\n}\n\nexport interface IConfirmationResult {\n\n\t/**\n\t * Will be true if the dialog was confirmed with the primary button\n\t * pressed.\n\t */\n\tconfirmed: boolean;\n\n\t/**\n\t * This will only be defined if the confirmation was created\n\t * with the checkbox option defined.\n\t */\n\tcheckboxChecked?: boolean;\n}\n\nexport interface IShowResult {\n\n\t/**\n\t * Selected choice index. If the user refused to choose,\n\t * then a promise with index of `cancelId` option is returned. If there is no such\n\t * option then promise with index `0` is returned.\n\t */\n\tchoice: number;\n}\n\nexport const IDialogService = createDecorator('dialogService');\n\nexport interface IDialogOptions {\n\tcancelId?: number;\n}\n\n/**\n * A service to bring up modal dialogs.\n *\n * Note: use the `INotificationService.prompt()` method for a non-modal way to ask\n * the user for input.\n */\nexport interface IDialogService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Ask the user for confirmation with a modal dialog.\n\t */\n\tconfirm(confirmation: IConfirmation): Promise;\n\n\t/**\n\t * Present a modal dialog to the user.\n\t *\n\t * @returns A promise with the selected choice index. If the user refused to choose,\n\t * then a promise with index of `cancelId` option is returned. If there is no such\n\t * option then promise with index `0` is returned.\n\t */\n\tshow(severity: Severity, message: string, buttons?: string[], options?: IDialogOptions): Promise;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';\nimport { SyncDescriptor } from './descriptors';\n\nexport class ServiceCollection {\n\n\tprivate _entries = new Map, any>();\n\n\tconstructor(...entries: [ServiceIdentifier, any][]) {\n\t\tfor (let [id, service] of entries) {\n\t\t\tthis.set(id, service);\n\t\t}\n\t}\n\n\tset(id: ServiceIdentifier, instanceOrDescriptor: T | SyncDescriptor): T | SyncDescriptor {\n\t\tconst result = this._entries.get(id);\n\t\tthis._entries.set(id, instanceOrDescriptor);\n\t\treturn result;\n\t}\n\n\tget(id: ServiceIdentifier): T | SyncDescriptor {\n\t\treturn this._entries.get(id);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IdleValue } from 'vs/base/common/async';\nimport { illegalState } from 'vs/base/common/errors';\nimport { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';\nimport { Graph } from 'vs/platform/instantiation/common/graph';\nimport { IInstantiationService, ServiceIdentifier, ServicesAccessor, _util } from 'vs/platform/instantiation/common/instantiation';\nimport { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';\n\n// TRACING\nconst _enableTracing = false;\n\nclass CyclicDependencyError extends Error {\n\tconstructor(graph: Graph) {\n\t\tsuper('cyclic dependency between services');\n\t\tthis.message = graph.findCycleSlow() ?? `UNABLE to detect cycle, dumping graph: \\n${graph.toString()}`;\n\t}\n}\n\nexport class InstantiationService implements IInstantiationService {\n\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate readonly _services: ServiceCollection;\n\tprivate readonly _strict: boolean;\n\tprivate readonly _parent?: InstantiationService;\n\n\tconstructor(services: ServiceCollection = new ServiceCollection(), strict: boolean = false, parent?: InstantiationService) {\n\t\tthis._services = services;\n\t\tthis._strict = strict;\n\t\tthis._parent = parent;\n\n\t\tthis._services.set(IInstantiationService, this);\n\t}\n\n\tcreateChild(services: ServiceCollection): IInstantiationService {\n\t\treturn new InstantiationService(services, this._strict, this);\n\t}\n\n\tinvokeFunction(fn: (accessor: ServicesAccessor, ...args: TS) => R, ...args: TS): R {\n\t\tlet _trace = Trace.traceInvocation(fn);\n\t\tlet _done = false;\n\t\ttry {\n\t\t\tconst accessor: ServicesAccessor = {\n\t\t\t\tget: (id: ServiceIdentifier) => {\n\n\t\t\t\t\tif (_done) {\n\t\t\t\t\t\tthrow illegalState('service accessor is only valid during the invocation of its target method');\n\t\t\t\t\t}\n\n\t\t\t\t\tconst result = this._getOrCreateServiceInstance(id, _trace);\n\t\t\t\t\tif (!result) {\n\t\t\t\t\t\tthrow new Error(`[invokeFunction] unknown service '${id}'`);\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t};\n\t\t\treturn fn(accessor, ...args);\n\t\t} finally {\n\t\t\t_done = true;\n\t\t\t_trace.stop();\n\t\t}\n\t}\n\n\tcreateInstance(ctorOrDescriptor: any | SyncDescriptor, ...rest: any[]): any {\n\t\tlet _trace: Trace;\n\t\tlet result: any;\n\t\tif (ctorOrDescriptor instanceof SyncDescriptor) {\n\t\t\t_trace = Trace.traceCreation(ctorOrDescriptor.ctor);\n\t\t\tresult = this._createInstance(ctorOrDescriptor.ctor, ctorOrDescriptor.staticArguments.concat(rest), _trace);\n\t\t} else {\n\t\t\t_trace = Trace.traceCreation(ctorOrDescriptor);\n\t\t\tresult = this._createInstance(ctorOrDescriptor, rest, _trace);\n\t\t}\n\t\t_trace.stop();\n\t\treturn result;\n\t}\n\n\tprivate _createInstance(ctor: any, args: any[] = [], _trace: Trace): T {\n\n\t\t// arguments defined by service decorators\n\t\tlet serviceDependencies = _util.getServiceDependencies(ctor).sort((a, b) => a.index - b.index);\n\t\tlet serviceArgs: any[] = [];\n\t\tfor (const dependency of serviceDependencies) {\n\t\t\tlet service = this._getOrCreateServiceInstance(dependency.id, _trace);\n\t\t\tif (!service && this._strict && !dependency.optional) {\n\t\t\t\tthrow new Error(`[createInstance] ${ctor.name} depends on UNKNOWN service ${dependency.id}.`);\n\t\t\t}\n\t\t\tserviceArgs.push(service);\n\t\t}\n\n\t\tlet firstServiceArgPos = serviceDependencies.length > 0 ? serviceDependencies[0].index : args.length;\n\n\t\t// check for argument mismatches, adjust static args if needed\n\t\tif (args.length !== firstServiceArgPos) {\n\t\t\tconsole.warn(`[createInstance] First service dependency of ${ctor.name} at position ${firstServiceArgPos + 1} conflicts with ${args.length} static arguments`);\n\n\t\t\tlet delta = firstServiceArgPos - args.length;\n\t\t\tif (delta > 0) {\n\t\t\t\targs = args.concat(new Array(delta));\n\t\t\t} else {\n\t\t\t\targs = args.slice(0, firstServiceArgPos);\n\t\t\t}\n\t\t}\n\n\t\t// now create the instance\n\t\treturn new ctor(...[...args, ...serviceArgs]);\n\t}\n\n\tprivate _setServiceInstance(id: ServiceIdentifier, instance: T): void {\n\t\tif (this._services.get(id) instanceof SyncDescriptor) {\n\t\t\tthis._services.set(id, instance);\n\t\t} else if (this._parent) {\n\t\t\tthis._parent._setServiceInstance(id, instance);\n\t\t} else {\n\t\t\tthrow new Error('illegalState - setting UNKNOWN service instance');\n\t\t}\n\t}\n\n\tprivate _getServiceInstanceOrDescriptor(id: ServiceIdentifier): T | SyncDescriptor {\n\t\tlet instanceOrDesc = this._services.get(id);\n\t\tif (!instanceOrDesc && this._parent) {\n\t\t\treturn this._parent._getServiceInstanceOrDescriptor(id);\n\t\t} else {\n\t\t\treturn instanceOrDesc;\n\t\t}\n\t}\n\n\tprotected _getOrCreateServiceInstance(id: ServiceIdentifier, _trace: Trace): T {\n\t\tlet thing = this._getServiceInstanceOrDescriptor(id);\n\t\tif (thing instanceof SyncDescriptor) {\n\t\t\treturn this._safeCreateAndCacheServiceInstance(id, thing, _trace.branch(id, true));\n\t\t} else {\n\t\t\t_trace.branch(id, false);\n\t\t\treturn thing;\n\t\t}\n\t}\n\n\tprivate readonly _activeInstantiations = new Set>();\n\n\n\tprivate _safeCreateAndCacheServiceInstance(id: ServiceIdentifier, desc: SyncDescriptor, _trace: Trace): T {\n\t\tif (this._activeInstantiations.has(id)) {\n\t\t\tthrow new Error(`illegal state - RECURSIVELY instantiating service '${id}'`);\n\t\t}\n\t\tthis._activeInstantiations.add(id);\n\t\ttry {\n\t\t\treturn this._createAndCacheServiceInstance(id, desc, _trace);\n\t\t} finally {\n\t\t\tthis._activeInstantiations.delete(id);\n\t\t}\n\t}\n\n\tprivate _createAndCacheServiceInstance(id: ServiceIdentifier, desc: SyncDescriptor, _trace: Trace): T {\n\n\t\ttype Triple = { id: ServiceIdentifier, desc: SyncDescriptor, _trace: Trace; };\n\t\tconst graph = new Graph(data => data.id.toString());\n\n\t\tlet cycleCount = 0;\n\t\tconst stack = [{ id, desc, _trace }];\n\t\twhile (stack.length) {\n\t\t\tconst item = stack.pop()!;\n\t\t\tgraph.lookupOrInsertNode(item);\n\n\t\t\t// a weak but working heuristic for cycle checks\n\t\t\tif (cycleCount++ > 1000) {\n\t\t\t\tthrow new CyclicDependencyError(graph);\n\t\t\t}\n\n\t\t\t// check all dependencies for existence and if they need to be created first\n\t\t\tfor (let dependency of _util.getServiceDependencies(item.desc.ctor)) {\n\n\t\t\t\tlet instanceOrDesc = this._getServiceInstanceOrDescriptor(dependency.id);\n\t\t\t\tif (!instanceOrDesc && !dependency.optional) {\n\t\t\t\t\tconsole.warn(`[createInstance] ${id} depends on ${dependency.id} which is NOT registered.`);\n\t\t\t\t}\n\n\t\t\t\tif (instanceOrDesc instanceof SyncDescriptor) {\n\t\t\t\t\tconst d = { id: dependency.id, desc: instanceOrDesc, _trace: item._trace.branch(dependency.id, true) };\n\t\t\t\t\tgraph.insertEdge(item, d);\n\t\t\t\t\tstack.push(d);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\twhile (true) {\n\t\t\tconst roots = graph.roots();\n\n\t\t\t// if there is no more roots but still\n\t\t\t// nodes in the graph we have a cycle\n\t\t\tif (roots.length === 0) {\n\t\t\t\tif (!graph.isEmpty()) {\n\t\t\t\t\tthrow new CyclicDependencyError(graph);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tfor (const { data } of roots) {\n\t\t\t\t// Repeat the check for this still being a service sync descriptor. That's because\n\t\t\t\t// instantiating a dependency might have side-effect and recursively trigger instantiation\n\t\t\t\t// so that some dependencies are now fullfilled already.\n\t\t\t\tconst instanceOrDesc = this._getServiceInstanceOrDescriptor(data.id);\n\t\t\t\tif (instanceOrDesc instanceof SyncDescriptor) {\n\t\t\t\t\t// create instance and overwrite the service collections\n\t\t\t\t\tconst instance = this._createServiceInstanceWithOwner(data.id, data.desc.ctor, data.desc.staticArguments, data.desc.supportsDelayedInstantiation, data._trace);\n\t\t\t\t\tthis._setServiceInstance(data.id, instance);\n\t\t\t\t}\n\t\t\t\tgraph.removeNode(data);\n\t\t\t}\n\t\t}\n\t\treturn this._getServiceInstanceOrDescriptor(id);\n\t}\n\n\tprivate _createServiceInstanceWithOwner(id: ServiceIdentifier, ctor: any, args: any[] = [], supportsDelayedInstantiation: boolean, _trace: Trace): T {\n\t\tif (this._services.get(id) instanceof SyncDescriptor) {\n\t\t\treturn this._createServiceInstance(ctor, args, supportsDelayedInstantiation, _trace);\n\t\t} else if (this._parent) {\n\t\t\treturn this._parent._createServiceInstanceWithOwner(id, ctor, args, supportsDelayedInstantiation, _trace);\n\t\t} else {\n\t\t\tthrow new Error(`illegalState - creating UNKNOWN service instance ${ctor.name}`);\n\t\t}\n\t}\n\n\tprivate _createServiceInstance(ctor: any, args: any[] = [], _supportsDelayedInstantiation: boolean, _trace: Trace): T {\n\t\tif (!_supportsDelayedInstantiation) {\n\t\t\t// eager instantiation\n\t\t\treturn this._createInstance(ctor, args, _trace);\n\n\t\t} else {\n\t\t\t// Return a proxy object that's backed by an idle value. That\n\t\t\t// strategy is to instantiate services in our idle time or when actually\n\t\t\t// needed but not when injected into a consumer\n\t\t\tconst idle = new IdleValue(() => this._createInstance(ctor, args, _trace));\n\t\t\treturn new Proxy(Object.create(null), {\n\t\t\t\tget(target: any, key: PropertyKey): any {\n\t\t\t\t\tif (key in target) {\n\t\t\t\t\t\treturn target[key];\n\t\t\t\t\t}\n\t\t\t\t\tlet obj = idle.value;\n\t\t\t\t\tlet prop = obj[key];\n\t\t\t\t\tif (typeof prop !== 'function') {\n\t\t\t\t\t\treturn prop;\n\t\t\t\t\t}\n\t\t\t\t\tprop = prop.bind(obj);\n\t\t\t\t\ttarget[key] = prop;\n\t\t\t\t\treturn prop;\n\t\t\t\t},\n\t\t\t\tset(_target: T, p: PropertyKey, value: any): boolean {\n\t\t\t\t\tidle.value[p] = value;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n}\n\n//#region -- tracing ---\n\nconst enum TraceType {\n\tCreation, Invocation, Branch\n}\n\nexport class Trace {\n\n\tprivate static readonly _None = new class extends Trace {\n\t\tconstructor() { super(-1, null); }\n\t\toverride stop() { }\n\t\toverride branch() { return this; }\n\t};\n\n\tstatic traceInvocation(ctor: any): Trace {\n\t\treturn !_enableTracing ? Trace._None : new Trace(TraceType.Invocation, ctor.name || (ctor.toString() as string).substring(0, 42).replace(/\\n/g, ''));\n\t}\n\n\tstatic traceCreation(ctor: any): Trace {\n\t\treturn !_enableTracing ? Trace._None : new Trace(TraceType.Creation, ctor.name);\n\t}\n\n\tprivate static _totals: number = 0;\n\tprivate readonly _start: number = Date.now();\n\tprivate readonly _dep: [ServiceIdentifier, boolean, Trace?][] = [];\n\n\tprivate constructor(\n\t\treadonly type: TraceType,\n\t\treadonly name: string | null\n\t) { }\n\n\tbranch(id: ServiceIdentifier, first: boolean): Trace {\n\t\tlet child = new Trace(TraceType.Branch, id.toString());\n\t\tthis._dep.push([id, first, child]);\n\t\treturn child;\n\t}\n\n\tstop() {\n\t\tlet dur = Date.now() - this._start;\n\t\tTrace._totals += dur;\n\n\t\tlet causedCreation = false;\n\n\t\tfunction printChild(n: number, trace: Trace) {\n\t\t\tlet res: string[] = [];\n\t\t\tlet prefix = new Array(n + 1).join('\\t');\n\t\t\tfor (const [id, first, child] of trace._dep) {\n\t\t\t\tif (first && child) {\n\t\t\t\t\tcausedCreation = true;\n\t\t\t\t\tres.push(`${prefix}CREATES -> ${id}`);\n\t\t\t\t\tlet nested = printChild(n + 1, child);\n\t\t\t\t\tif (nested) {\n\t\t\t\t\t\tres.push(nested);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tres.push(`${prefix}uses -> ${id}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res.join('\\n');\n\t\t}\n\n\t\tlet lines = [\n\t\t\t`${this.type === TraceType.Creation ? 'CREATE' : 'CALL'} ${this.name}`,\n\t\t\t`${printChild(1, this)}`,\n\t\t\t`DONE, took ${dur.toFixed(2)}ms (grand total ${Trace._totals.toFixed(2)}ms)`\n\t\t];\n\n\t\tif (dur > 2 || causedCreation) {\n\t\t\tconsole.log(lines.join('\\n'));\n\t\t}\n\t}\n}\n\n//#endregion\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions';\nimport { IntervalTimer, TimeoutTimer } from 'vs/base/common/async';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { KeybindingModifier, ResolvedKeybinding, ResolvedKeybindingPart } from 'vs/base/common/keybindings';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport * as nls from 'vs/nls';\nimport { ICommandService } from 'vs/platform/commands/common/commands';\nimport { IContextKeyService, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';\nimport { IKeybindingEvent, IKeybindingService, IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';\nimport { IResolveResult, KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';\nimport { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';\nimport { ILogService } from 'vs/platform/log/common/log';\nimport { INotificationService } from 'vs/platform/notification/common/notification';\nimport { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';\n\ninterface CurrentChord {\n\tkeypress: string;\n\tlabel: string | null;\n}\n\nconst HIGH_FREQ_COMMANDS = /^(cursor|delete)/;\n\nexport abstract class AbstractKeybindingService extends Disposable implements IKeybindingService {\n\tpublic _serviceBrand: undefined;\n\n\tprotected readonly _onDidUpdateKeybindings: Emitter = this._register(new Emitter());\n\tget onDidUpdateKeybindings(): Event {\n\t\treturn this._onDidUpdateKeybindings ? this._onDidUpdateKeybindings.event : Event.None; // Sinon stubbing walks properties on prototype\n\t}\n\n\tprivate _currentChord: CurrentChord | null;\n\tprivate _currentChordChecker: IntervalTimer;\n\tprivate _currentChordStatusMessage: IDisposable | null;\n\tprivate _ignoreSingleModifiers: KeybindingModifierSet;\n\tprivate _currentSingleModifier: KeybindingModifier | null;\n\tprivate _currentSingleModifierClearTimeout: TimeoutTimer;\n\n\tprotected _logging: boolean;\n\n\tconstructor(\n\t\tprivate _contextKeyService: IContextKeyService,\n\t\tprotected _commandService: ICommandService,\n\t\tprotected _telemetryService: ITelemetryService,\n\t\tprivate _notificationService: INotificationService,\n\t\tprotected _logService: ILogService,\n\t) {\n\t\tsuper();\n\n\t\tthis._currentChord = null;\n\t\tthis._currentChordChecker = new IntervalTimer();\n\t\tthis._currentChordStatusMessage = null;\n\t\tthis._ignoreSingleModifiers = KeybindingModifierSet.EMPTY;\n\t\tthis._currentSingleModifier = null;\n\t\tthis._currentSingleModifierClearTimeout = new TimeoutTimer();\n\t\tthis._logging = false;\n\t}\n\n\tpublic override dispose(): void {\n\t\tsuper.dispose();\n\t}\n\n\tprotected abstract _getResolver(): KeybindingResolver;\n\tprotected abstract _documentHasFocus(): boolean;\n\tpublic abstract resolveKeyboardEvent(keyboardEvent: IKeyboardEvent): ResolvedKeybinding;\n\n\tprotected _log(str: string): void {\n\t\tif (this._logging) {\n\t\t\tthis._logService.info(`[KeybindingService]: ${str}`);\n\t\t}\n\t}\n\n\tpublic getKeybindings(): readonly ResolvedKeybindingItem[] {\n\t\treturn this._getResolver().getKeybindings();\n\t}\n\n\tpublic lookupKeybinding(commandId: string, context?: IContextKeyService): ResolvedKeybinding | undefined {\n\t\tconst result = this._getResolver().lookupPrimaryKeybinding(commandId, context || this._contextKeyService);\n\t\tif (!result) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn result.resolvedKeybinding;\n\t}\n\n\tpublic dispatchEvent(e: IKeyboardEvent, target: IContextKeyServiceTarget): boolean {\n\t\treturn this._dispatch(e, target);\n\t}\n\n\tpublic softDispatch(e: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult | null {\n\t\tconst keybinding = this.resolveKeyboardEvent(e);\n\t\tif (keybinding.isChord()) {\n\t\t\tconsole.warn('Unexpected keyboard event mapped to a chord');\n\t\t\treturn null;\n\t\t}\n\t\tconst [firstPart,] = keybinding.getDispatchParts();\n\t\tif (firstPart === null) {\n\t\t\t// cannot be dispatched, probably only modifier keys\n\t\t\treturn null;\n\t\t}\n\n\t\tconst contextValue = this._contextKeyService.getContext(target);\n\t\tconst currentChord = this._currentChord ? this._currentChord.keypress : null;\n\t\treturn this._getResolver().resolve(contextValue, currentChord, firstPart);\n\t}\n\n\tprivate _enterChordMode(firstPart: string, keypressLabel: string | null): void {\n\t\tthis._currentChord = {\n\t\t\tkeypress: firstPart,\n\t\t\tlabel: keypressLabel\n\t\t};\n\t\tthis._currentChordStatusMessage = this._notificationService.status(nls.localize('first.chord', \"({0}) was pressed. Waiting for second key of chord...\", keypressLabel));\n\t\tconst chordEnterTime = Date.now();\n\t\tthis._currentChordChecker.cancelAndSet(() => {\n\n\t\t\tif (!this._documentHasFocus()) {\n\t\t\t\t// Focus has been lost => leave chord mode\n\t\t\t\tthis._leaveChordMode();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (Date.now() - chordEnterTime > 5000) {\n\t\t\t\t// 5 seconds elapsed => leave chord mode\n\t\t\t\tthis._leaveChordMode();\n\t\t\t}\n\n\t\t}, 500);\n\t}\n\n\tprivate _leaveChordMode(): void {\n\t\tif (this._currentChordStatusMessage) {\n\t\t\tthis._currentChordStatusMessage.dispose();\n\t\t\tthis._currentChordStatusMessage = null;\n\t\t}\n\t\tthis._currentChordChecker.cancel();\n\t\tthis._currentChord = null;\n\t}\n\n\tprotected _dispatch(e: IKeyboardEvent, target: IContextKeyServiceTarget): boolean {\n\t\treturn this._doDispatch(this.resolveKeyboardEvent(e), target, /*isSingleModiferChord*/false);\n\t}\n\n\tprotected _singleModifierDispatch(e: IKeyboardEvent, target: IContextKeyServiceTarget): boolean {\n\t\tconst keybinding = this.resolveKeyboardEvent(e);\n\t\tconst [singleModifier,] = keybinding.getSingleModifierDispatchParts();\n\n\t\tif (singleModifier) {\n\n\t\t\tif (this._ignoreSingleModifiers.has(singleModifier)) {\n\t\t\t\tthis._log(`+ Ignoring single modifier ${singleModifier} due to it being pressed together with other keys.`);\n\t\t\t\tthis._ignoreSingleModifiers = KeybindingModifierSet.EMPTY;\n\t\t\t\tthis._currentSingleModifierClearTimeout.cancel();\n\t\t\t\tthis._currentSingleModifier = null;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tthis._ignoreSingleModifiers = KeybindingModifierSet.EMPTY;\n\n\t\t\tif (this._currentSingleModifier === null) {\n\t\t\t\t// we have a valid `singleModifier`, store it for the next keyup, but clear it in 300ms\n\t\t\t\tthis._log(`+ Storing single modifier for possible chord ${singleModifier}.`);\n\t\t\t\tthis._currentSingleModifier = singleModifier;\n\t\t\t\tthis._currentSingleModifierClearTimeout.cancelAndSet(() => {\n\t\t\t\t\tthis._log(`+ Clearing single modifier due to 300ms elapsed.`);\n\t\t\t\t\tthis._currentSingleModifier = null;\n\t\t\t\t}, 300);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (singleModifier === this._currentSingleModifier) {\n\t\t\t\t// bingo!\n\t\t\t\tthis._log(`/ Dispatching single modifier chord ${singleModifier} ${singleModifier}`);\n\t\t\t\tthis._currentSingleModifierClearTimeout.cancel();\n\t\t\t\tthis._currentSingleModifier = null;\n\t\t\t\treturn this._doDispatch(keybinding, target, /*isSingleModiferChord*/true);\n\t\t\t}\n\n\t\t\tthis._log(`+ Clearing single modifier due to modifier mismatch: ${this._currentSingleModifier} ${singleModifier}`);\n\t\t\tthis._currentSingleModifierClearTimeout.cancel();\n\t\t\tthis._currentSingleModifier = null;\n\t\t\treturn false;\n\t\t}\n\n\t\t// When pressing a modifier and holding it pressed with any other modifier or key combination,\n\t\t// the pressed modifiers should no longer be considered for single modifier dispatch.\n\t\tconst [firstPart,] = keybinding.getParts();\n\t\tthis._ignoreSingleModifiers = new KeybindingModifierSet(firstPart);\n\n\t\tif (this._currentSingleModifier !== null) {\n\t\t\tthis._log(`+ Clearing single modifier due to other key up.`);\n\t\t}\n\t\tthis._currentSingleModifierClearTimeout.cancel();\n\t\tthis._currentSingleModifier = null;\n\t\treturn false;\n\t}\n\n\tprivate _doDispatch(keybinding: ResolvedKeybinding, target: IContextKeyServiceTarget, isSingleModiferChord = false): boolean {\n\t\tlet shouldPreventDefault = false;\n\n\t\tif (keybinding.isChord()) {\n\t\t\tconsole.warn('Unexpected keyboard event mapped to a chord');\n\t\t\treturn false;\n\t\t}\n\n\t\tlet firstPart: string | null = null; // the first keybinding i.e. Ctrl+K\n\t\tlet currentChord: string | null = null;// the \"second\" keybinding i.e. Ctrl+K \"Ctrl+D\"\n\n\t\tif (isSingleModiferChord) {\n\t\t\tconst [dispatchKeyname,] = keybinding.getSingleModifierDispatchParts();\n\t\t\tfirstPart = dispatchKeyname;\n\t\t\tcurrentChord = dispatchKeyname;\n\t\t} else {\n\t\t\t[firstPart,] = keybinding.getDispatchParts();\n\t\t\tcurrentChord = this._currentChord ? this._currentChord.keypress : null;\n\t\t}\n\n\t\tif (firstPart === null) {\n\t\t\tthis._log(`\\\\ Keyboard event cannot be dispatched in keydown phase.`);\n\t\t\t// cannot be dispatched, probably only modifier keys\n\t\t\treturn shouldPreventDefault;\n\t\t}\n\n\t\tconst contextValue = this._contextKeyService.getContext(target);\n\t\tconst keypressLabel = keybinding.getLabel();\n\t\tconst resolveResult = this._getResolver().resolve(contextValue, currentChord, firstPart);\n\n\t\tthis._logService.trace('KeybindingService#dispatch', keypressLabel, resolveResult?.commandId);\n\n\t\tif (resolveResult && resolveResult.enterChord) {\n\t\t\tshouldPreventDefault = true;\n\t\t\tthis._enterChordMode(firstPart, keypressLabel);\n\t\t\treturn shouldPreventDefault;\n\t\t}\n\n\t\tif (this._currentChord) {\n\t\t\tif (!resolveResult || !resolveResult.commandId) {\n\t\t\t\tthis._notificationService.status(nls.localize('missing.chord', \"The key combination ({0}, {1}) is not a command.\", this._currentChord.label, keypressLabel), { hideAfter: 10 * 1000 /* 10s */ });\n\t\t\t\tshouldPreventDefault = true;\n\t\t\t}\n\t\t}\n\n\t\tthis._leaveChordMode();\n\n\t\tif (resolveResult && resolveResult.commandId) {\n\t\t\tif (!resolveResult.bubble) {\n\t\t\t\tshouldPreventDefault = true;\n\t\t\t}\n\t\t\tif (typeof resolveResult.commandArgs === 'undefined') {\n\t\t\t\tthis._commandService.executeCommand(resolveResult.commandId).then(undefined, err => this._notificationService.warn(err));\n\t\t\t} else {\n\t\t\t\tthis._commandService.executeCommand(resolveResult.commandId, resolveResult.commandArgs).then(undefined, err => this._notificationService.warn(err));\n\t\t\t}\n\t\t\tif (!HIGH_FREQ_COMMANDS.test(resolveResult.commandId)) {\n\t\t\t\tthis._telemetryService.publicLog2('workbenchActionExecuted', { id: resolveResult.commandId, from: 'keybinding' });\n\t\t\t}\n\t\t}\n\n\t\treturn shouldPreventDefault;\n\t}\n\n\tmightProducePrintableCharacter(event: IKeyboardEvent): boolean {\n\t\tif (event.ctrlKey || event.metaKey) {\n\t\t\t// ignore ctrl/cmd-combination but not shift/alt-combinatios\n\t\t\treturn false;\n\t\t}\n\t\t// weak check for certain ranges. this is properly implemented in a subclass\n\t\t// with access to the KeyboardMapperFactory.\n\t\tif ((event.keyCode >= KeyCode.KeyA && event.keyCode <= KeyCode.KeyZ)\n\t\t\t|| (event.keyCode >= KeyCode.Digit0 && event.keyCode <= KeyCode.Digit9)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n}\n\nclass KeybindingModifierSet {\n\n\tpublic static EMPTY = new KeybindingModifierSet(null);\n\n\tprivate readonly _ctrlKey: boolean;\n\tprivate readonly _shiftKey: boolean;\n\tprivate readonly _altKey: boolean;\n\tprivate readonly _metaKey: boolean;\n\n\tconstructor(source: ResolvedKeybindingPart | null) {\n\t\tthis._ctrlKey = source ? source.ctrlKey : false;\n\t\tthis._shiftKey = source ? source.shiftKey : false;\n\t\tthis._altKey = source ? source.altKey : false;\n\t\tthis._metaKey = source ? source.metaKey : false;\n\t}\n\n\thas(modifier: KeybindingModifier) {\n\t\tswitch (modifier) {\n\t\t\tcase 'ctrl': return this._ctrlKey;\n\t\t\tcase 'shift': return this._shiftKey;\n\t\t\tcase 'alt': return this._altKey;\n\t\t\tcase 'meta': return this._metaKey;\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { illegalArgument } from 'vs/base/common/errors';\nimport { AriaLabelProvider, ElectronAcceleratorLabelProvider, UILabelProvider } from 'vs/base/common/keybindingLabels';\nimport { IBaseKeybinding, KeybindingModifier, ResolvedKeybinding, ResolvedKeybindingPart } from 'vs/base/common/keybindings';\nimport { OperatingSystem } from 'vs/base/common/platform';\n\nexport abstract class BaseResolvedKeybinding extends ResolvedKeybinding {\n\n\tprotected readonly _os: OperatingSystem;\n\tprotected readonly _parts: T[];\n\n\tconstructor(os: OperatingSystem, parts: T[]) {\n\t\tsuper();\n\t\tif (parts.length === 0) {\n\t\t\tthrow illegalArgument(`parts`);\n\t\t}\n\t\tthis._os = os;\n\t\tthis._parts = parts;\n\t}\n\n\tpublic getLabel(): string | null {\n\t\treturn UILabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getLabel(keybinding));\n\t}\n\n\tpublic getAriaLabel(): string | null {\n\t\treturn AriaLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getAriaLabel(keybinding));\n\t}\n\n\tpublic getElectronAccelerator(): string | null {\n\t\tif (this._parts.length > 1) {\n\t\t\t// [Electron Accelerators] Electron cannot handle chords\n\t\t\treturn null;\n\t\t}\n\t\tif (this._parts[0].isDuplicateModifierCase()) {\n\t\t\t// [Electron Accelerators] Electron cannot handle modifier only keybindings\n\t\t\t// e.g. \"shift shift\"\n\t\t\treturn null;\n\t\t}\n\t\treturn ElectronAcceleratorLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getElectronAccelerator(keybinding));\n\t}\n\n\tpublic isChord(): boolean {\n\t\treturn (this._parts.length > 1);\n\t}\n\n\tpublic getParts(): ResolvedKeybindingPart[] {\n\t\treturn this._parts.map((keybinding) => this._getPart(keybinding));\n\t}\n\n\tprivate _getPart(keybinding: T): ResolvedKeybindingPart {\n\t\treturn new ResolvedKeybindingPart(\n\t\t\tkeybinding.ctrlKey,\n\t\t\tkeybinding.shiftKey,\n\t\t\tkeybinding.altKey,\n\t\t\tkeybinding.metaKey,\n\t\t\tthis._getLabel(keybinding),\n\t\t\tthis._getAriaLabel(keybinding)\n\t\t);\n\t}\n\n\tpublic getDispatchParts(): (string | null)[] {\n\t\treturn this._parts.map((keybinding) => this._getDispatchPart(keybinding));\n\t}\n\n\tpublic getSingleModifierDispatchParts(): (KeybindingModifier | null)[] {\n\t\treturn this._parts.map((keybinding) => this._getSingleModifierDispatchPart(keybinding));\n\t}\n\n\tprotected abstract _getLabel(keybinding: T): string | null;\n\tprotected abstract _getAriaLabel(keybinding: T): string | null;\n\tprotected abstract _getElectronAccelerator(keybinding: T): string | null;\n\tprotected abstract _getDispatchPart(keybinding: T): string | null;\n\tprotected abstract _getSingleModifierDispatchPart(keybinding: T): KeybindingModifier | null;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { ResolvedKeybinding } from 'vs/base/common/keybindings';\nimport { IContextKeyService, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { IResolveResult } from 'vs/platform/keybinding/common/keybindingResolver';\nimport { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';\n\nexport const enum KeybindingSource {\n\tDefault = 1,\n\tUser\n}\n\nexport interface IKeybindingEvent {\n\tsource: KeybindingSource;\n}\n\nexport interface IKeyboardEvent {\n\treadonly _standardKeyboardEventBrand: true;\n\n\treadonly ctrlKey: boolean;\n\treadonly shiftKey: boolean;\n\treadonly altKey: boolean;\n\treadonly metaKey: boolean;\n\treadonly keyCode: KeyCode;\n}\n\nexport const IKeybindingService = createDecorator('keybindingService');\n\nexport interface IKeybindingService {\n\treadonly _serviceBrand: undefined;\n\n\tonDidUpdateKeybindings: Event;\n\n\t/**\n\t * Resolve and dispatch `keyboardEvent` and invoke the command.\n\t */\n\tdispatchEvent(e: IKeyboardEvent, target: IContextKeyServiceTarget): boolean;\n\n\t/**\n\t * Resolve and dispatch `keyboardEvent`, but do not invoke the command or change inner state.\n\t */\n\tsoftDispatch(keyboardEvent: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult | null;\n\n\t/**\n\t * Look up the preferred (last defined) keybinding for a command.\n\t * @returns The preferred keybinding or null if the command is not bound.\n\t */\n\tlookupKeybinding(commandId: string, context?: IContextKeyService): ResolvedKeybinding | undefined;\n\n\tgetKeybindings(): readonly ResolvedKeybindingItem[];\n\n\t/**\n\t * Will the given key event produce a character that's rendered on screen, e.g. in a\n\t * text box. *Note* that the results of this function can be incorrect.\n\t */\n\tmightProducePrintableCharacter(event: IKeyboardEvent): boolean;\n}\n\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { implies, ContextKeyExpression, ContextKeyExprType, IContext, IContextKeyService, expressionsAreEqualWithConstantSubstitution } from 'vs/platform/contextkey/common/contextkey';\nimport { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';\n\nexport interface IResolveResult {\n\t/** Whether the resolved keybinding is entering a chord */\n\tenterChord: boolean;\n\t/** Whether the resolved keybinding is leaving (and executing) a chord */\n\tleaveChord: boolean;\n\tcommandId: string | null;\n\tcommandArgs: any;\n\tbubble: boolean;\n}\n\nexport class KeybindingResolver {\n\tprivate readonly _log: (str: string) => void;\n\tprivate readonly _defaultKeybindings: ResolvedKeybindingItem[];\n\tprivate readonly _keybindings: ResolvedKeybindingItem[];\n\tprivate readonly _defaultBoundCommands: Map;\n\tprivate readonly _map: Map;\n\tprivate readonly _lookupMap: Map;\n\n\tconstructor(\n\t\tdefaultKeybindings: ResolvedKeybindingItem[],\n\t\toverrides: ResolvedKeybindingItem[],\n\t\tlog: (str: string) => void\n\t) {\n\t\tthis._log = log;\n\t\tthis._defaultKeybindings = defaultKeybindings;\n\n\t\tthis._defaultBoundCommands = new Map();\n\t\tfor (const defaultKeybinding of defaultKeybindings) {\n\t\t\tconst command = defaultKeybinding.command;\n\t\t\tif (command && command.charAt(0) !== '-') {\n\t\t\t\tthis._defaultBoundCommands.set(command, true);\n\t\t\t}\n\t\t}\n\n\t\tthis._map = new Map();\n\t\tthis._lookupMap = new Map();\n\n\t\tthis._keybindings = KeybindingResolver.handleRemovals(([] as ResolvedKeybindingItem[]).concat(defaultKeybindings).concat(overrides));\n\t\tfor (let i = 0, len = this._keybindings.length; i < len; i++) {\n\t\t\tlet k = this._keybindings[i];\n\t\t\tif (k.keypressParts.length === 0) {\n\t\t\t\t// unbound\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (k.when && k.when.type === ContextKeyExprType.False) {\n\t\t\t\t// when condition is false\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// TODO@chords\n\t\t\tthis._addKeyPress(k.keypressParts[0], k);\n\t\t}\n\t}\n\n\tprivate static _isTargetedForRemoval(defaultKb: ResolvedKeybindingItem, keypressFirstPart: string | null, keypressChordPart: string | null, when: ContextKeyExpression | undefined): boolean {\n\t\t// TODO@chords\n\t\tif (keypressFirstPart && defaultKb.keypressParts[0] !== keypressFirstPart) {\n\t\t\treturn false;\n\t\t}\n\t\t// TODO@chords\n\t\tif (keypressChordPart && defaultKb.keypressParts[1] !== keypressChordPart) {\n\t\t\treturn false;\n\t\t}\n\t\tif (when) {\n\t\t\tif (!defaultKb.when) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!expressionsAreEqualWithConstantSubstitution(when, defaultKb.when)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\n\t}\n\n\t/**\n\t * Looks for rules containing \"-commandId\" and removes them.\n\t */\n\tpublic static handleRemovals(rules: ResolvedKeybindingItem[]): ResolvedKeybindingItem[] {\n\t\t// Do a first pass and construct a hash-map for removals\n\t\tconst removals = new Map();\n\t\tfor (let i = 0, len = rules.length; i < len; i++) {\n\t\t\tconst rule = rules[i];\n\t\t\tif (rule.command && rule.command.charAt(0) === '-') {\n\t\t\t\tconst command = rule.command.substring(1);\n\t\t\t\tif (!removals.has(command)) {\n\t\t\t\t\tremovals.set(command, [rule]);\n\t\t\t\t} else {\n\t\t\t\t\tremovals.get(command)!.push(rule);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (removals.size === 0) {\n\t\t\t// There are no removals\n\t\t\treturn rules;\n\t\t}\n\n\t\t// Do a second pass and keep only non-removed keybindings\n\t\tconst result: ResolvedKeybindingItem[] = [];\n\t\tfor (let i = 0, len = rules.length; i < len; i++) {\n\t\t\tconst rule = rules[i];\n\n\t\t\tif (!rule.command || rule.command.length === 0) {\n\t\t\t\tresult.push(rule);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (rule.command.charAt(0) === '-') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst commandRemovals = removals.get(rule.command);\n\t\t\tif (!commandRemovals || !rule.isDefault) {\n\t\t\t\tresult.push(rule);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlet isRemoved = false;\n\t\t\tfor (const commandRemoval of commandRemovals) {\n\t\t\t\t// TODO@chords\n\t\t\t\tconst keypressFirstPart = commandRemoval.keypressParts[0];\n\t\t\t\tconst keypressChordPart = commandRemoval.keypressParts[1];\n\t\t\t\tconst when = commandRemoval.when;\n\t\t\t\tif (this._isTargetedForRemoval(rule, keypressFirstPart, keypressChordPart, when)) {\n\t\t\t\t\tisRemoved = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!isRemoved) {\n\t\t\t\tresult.push(rule);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate _addKeyPress(keypress: string, item: ResolvedKeybindingItem): void {\n\n\t\tconst conflicts = this._map.get(keypress);\n\n\t\tif (typeof conflicts === 'undefined') {\n\t\t\t// There is no conflict so far\n\t\t\tthis._map.set(keypress, [item]);\n\t\t\tthis._addToLookupMap(item);\n\t\t\treturn;\n\t\t}\n\n\t\tfor (let i = conflicts.length - 1; i >= 0; i--) {\n\t\t\tlet conflict = conflicts[i];\n\n\t\t\tif (conflict.command === item.command) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst conflictIsChord = (conflict.keypressParts.length > 1);\n\t\t\tconst itemIsChord = (item.keypressParts.length > 1);\n\n\t\t\t// TODO@chords\n\t\t\tif (conflictIsChord && itemIsChord && conflict.keypressParts[1] !== item.keypressParts[1]) {\n\t\t\t\t// The conflict only shares the chord start with this command\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (KeybindingResolver.whenIsEntirelyIncluded(conflict.when, item.when)) {\n\t\t\t\t// `item` completely overwrites `conflict`\n\t\t\t\t// Remove conflict from the lookupMap\n\t\t\t\tthis._removeFromLookupMap(conflict);\n\t\t\t}\n\t\t}\n\n\t\tconflicts.push(item);\n\t\tthis._addToLookupMap(item);\n\t}\n\n\tprivate _addToLookupMap(item: ResolvedKeybindingItem): void {\n\t\tif (!item.command) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet arr = this._lookupMap.get(item.command);\n\t\tif (typeof arr === 'undefined') {\n\t\t\tarr = [item];\n\t\t\tthis._lookupMap.set(item.command, arr);\n\t\t} else {\n\t\t\tarr.push(item);\n\t\t}\n\t}\n\n\tprivate _removeFromLookupMap(item: ResolvedKeybindingItem): void {\n\t\tif (!item.command) {\n\t\t\treturn;\n\t\t}\n\t\tlet arr = this._lookupMap.get(item.command);\n\t\tif (typeof arr === 'undefined') {\n\t\t\treturn;\n\t\t}\n\t\tfor (let i = 0, len = arr.length; i < len; i++) {\n\t\t\tif (arr[i] === item) {\n\t\t\t\tarr.splice(i, 1);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns true if it is provable `a` implies `b`.\n\t */\n\tpublic static whenIsEntirelyIncluded(a: ContextKeyExpression | null | undefined, b: ContextKeyExpression | null | undefined): boolean {\n\t\tif (!b || b.type === ContextKeyExprType.True) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!a || a.type === ContextKeyExprType.True) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn implies(a, b);\n\t}\n\n\tpublic getKeybindings(): readonly ResolvedKeybindingItem[] {\n\t\treturn this._keybindings;\n\t}\n\n\tpublic lookupPrimaryKeybinding(commandId: string, context: IContextKeyService): ResolvedKeybindingItem | null {\n\t\tconst items = this._lookupMap.get(commandId);\n\t\tif (typeof items === 'undefined' || items.length === 0) {\n\t\t\treturn null;\n\t\t}\n\t\tif (items.length === 1) {\n\t\t\treturn items[0];\n\t\t}\n\n\t\tfor (let i = items.length - 1; i >= 0; i--) {\n\t\t\tconst item = items[i];\n\t\t\tif (context.contextMatchesRules(item.when)) {\n\t\t\t\treturn item;\n\t\t\t}\n\t\t}\n\n\t\treturn items[items.length - 1];\n\t}\n\n\tpublic resolve(context: IContext, currentChord: string | null, keypress: string): IResolveResult | null {\n\t\tthis._log(`| Resolving ${keypress}${currentChord ? ` chorded from ${currentChord}` : ``}`);\n\t\tlet lookupMap: ResolvedKeybindingItem[] | null = null;\n\n\t\tif (currentChord !== null) {\n\t\t\t// Fetch all chord bindings for `currentChord`\n\n\t\t\tconst candidates = this._map.get(currentChord);\n\t\t\tif (typeof candidates === 'undefined') {\n\t\t\t\t// No chords starting with `currentChord`\n\t\t\t\tthis._log(`\\\\ No keybinding entries.`);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tlookupMap = [];\n\t\t\tfor (let i = 0, len = candidates.length; i < len; i++) {\n\t\t\t\tlet candidate = candidates[i];\n\t\t\t\t// TODO@chords\n\t\t\t\tif (candidate.keypressParts[1] === keypress) {\n\t\t\t\t\tlookupMap.push(candidate);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst candidates = this._map.get(keypress);\n\t\t\tif (typeof candidates === 'undefined') {\n\t\t\t\t// No bindings with `keypress`\n\t\t\t\tthis._log(`\\\\ No keybinding entries.`);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tlookupMap = candidates;\n\t\t}\n\n\t\tlet result = this._findCommand(context, lookupMap);\n\t\tif (!result) {\n\t\t\tthis._log(`\\\\ From ${lookupMap.length} keybinding entries, no when clauses matched the context.`);\n\t\t\treturn null;\n\t\t}\n\n\t\t// TODO@chords\n\t\tif (currentChord === null && result.keypressParts.length > 1 && result.keypressParts[1] !== null) {\n\t\t\tthis._log(`\\\\ From ${lookupMap.length} keybinding entries, matched chord, when: ${printWhenExplanation(result.when)}, source: ${printSourceExplanation(result)}.`);\n\t\t\treturn {\n\t\t\t\tenterChord: true,\n\t\t\t\tleaveChord: false,\n\t\t\t\tcommandId: null,\n\t\t\t\tcommandArgs: null,\n\t\t\t\tbubble: false\n\t\t\t};\n\t\t}\n\n\t\tthis._log(`\\\\ From ${lookupMap.length} keybinding entries, matched ${result.command}, when: ${printWhenExplanation(result.when)}, source: ${printSourceExplanation(result)}.`);\n\t\treturn {\n\t\t\tenterChord: false,\n\t\t\tleaveChord: result.keypressParts.length > 1,\n\t\t\tcommandId: result.command,\n\t\t\tcommandArgs: result.commandArgs,\n\t\t\tbubble: result.bubble\n\t\t};\n\t}\n\n\tprivate _findCommand(context: IContext, matches: ResolvedKeybindingItem[]): ResolvedKeybindingItem | null {\n\t\tfor (let i = matches.length - 1; i >= 0; i--) {\n\t\t\tlet k = matches[i];\n\n\t\t\tif (!KeybindingResolver._contextMatchesRules(context, k.when)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\treturn k;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate static _contextMatchesRules(context: IContext, rules: ContextKeyExpression | null | undefined): boolean {\n\t\tif (!rules) {\n\t\t\treturn true;\n\t\t}\n\t\treturn rules.evaluate(context);\n\t}\n}\n\nfunction printWhenExplanation(when: ContextKeyExpression | undefined): string {\n\tif (!when) {\n\t\treturn `no when condition`;\n\t}\n\treturn `${when.serialize()}`;\n}\n\nfunction printSourceExplanation(kb: ResolvedKeybindingItem): string {\n\treturn (\n\t\tkb.extensionId\n\t\t\t? (kb.isBuiltinExtension ? `built-in extension ${kb.extensionId}` : `user extension ${kb.extensionId}`)\n\t\t\t: (kb.isDefault ? `built-in` : `user`)\n\t);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from 'vs/base/common/charCode';\nimport { ResolvedKeybinding } from 'vs/base/common/keybindings';\nimport { ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';\n\nexport class ResolvedKeybindingItem {\n\t_resolvedKeybindingItemBrand: void = undefined;\n\n\tpublic readonly resolvedKeybinding: ResolvedKeybinding | undefined;\n\tpublic readonly keypressParts: string[];\n\tpublic readonly bubble: boolean;\n\tpublic readonly command: string | null;\n\tpublic readonly commandArgs: any;\n\tpublic readonly when: ContextKeyExpression | undefined;\n\tpublic readonly isDefault: boolean;\n\tpublic readonly extensionId: string | null;\n\tpublic readonly isBuiltinExtension: boolean;\n\n\tconstructor(resolvedKeybinding: ResolvedKeybinding | undefined, command: string | null, commandArgs: any, when: ContextKeyExpression | undefined, isDefault: boolean, extensionId: string | null, isBuiltinExtension: boolean) {\n\t\tthis.resolvedKeybinding = resolvedKeybinding;\n\t\tthis.keypressParts = resolvedKeybinding ? removeElementsAfterNulls(resolvedKeybinding.getDispatchParts()) : [];\n\t\tif (resolvedKeybinding && this.keypressParts.length === 0) {\n\t\t\t// handle possible single modifier chord keybindings\n\t\t\tthis.keypressParts = removeElementsAfterNulls(resolvedKeybinding.getSingleModifierDispatchParts());\n\t\t}\n\t\tthis.bubble = (command ? command.charCodeAt(0) === CharCode.Caret : false);\n\t\tthis.command = this.bubble ? command!.substr(1) : command;\n\t\tthis.commandArgs = commandArgs;\n\t\tthis.when = when;\n\t\tthis.isDefault = isDefault;\n\t\tthis.extensionId = extensionId;\n\t\tthis.isBuiltinExtension = isBuiltinExtension;\n\t}\n}\n\nexport function removeElementsAfterNulls(arr: (T | null)[]): T[] {\n\tlet result: T[] = [];\n\tfor (let i = 0, len = arr.length; i < len; i++) {\n\t\tconst element = arr[i];\n\t\tif (!element) {\n\t\t\t// stop processing at first encountered null\n\t\t\treturn result;\n\t\t}\n\t\tresult.push(element);\n\t}\n\treturn result;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { KeyCode, KeyCodeUtils, IMMUTABLE_CODE_TO_KEY_CODE, ScanCode } from 'vs/base/common/keyCodes';\nimport { ChordKeybinding, Keybinding, KeybindingModifier, SimpleKeybinding, ScanCodeBinding } from 'vs/base/common/keybindings';\nimport { OperatingSystem } from 'vs/base/common/platform';\nimport { BaseResolvedKeybinding } from 'vs/platform/keybinding/common/baseResolvedKeybinding';\nimport { removeElementsAfterNulls } from 'vs/platform/keybinding/common/resolvedKeybindingItem';\n\n/**\n * Do not instantiate. Use KeybindingService to get a ResolvedKeybinding seeded with information about the current kb layout.\n */\nexport class USLayoutResolvedKeybinding extends BaseResolvedKeybinding {\n\n\tconstructor(actual: Keybinding, os: OperatingSystem) {\n\t\tsuper(os, actual.parts);\n\t}\n\n\tprivate _keyCodeToUILabel(keyCode: KeyCode): string {\n\t\tif (this._os === OperatingSystem.Macintosh) {\n\t\t\tswitch (keyCode) {\n\t\t\t\tcase KeyCode.LeftArrow:\n\t\t\t\t\treturn '←';\n\t\t\t\tcase KeyCode.UpArrow:\n\t\t\t\t\treturn '↑';\n\t\t\t\tcase KeyCode.RightArrow:\n\t\t\t\t\treturn '→';\n\t\t\t\tcase KeyCode.DownArrow:\n\t\t\t\t\treturn '↓';\n\t\t\t}\n\t\t}\n\t\treturn KeyCodeUtils.toString(keyCode);\n\t}\n\n\tprotected _getLabel(keybinding: SimpleKeybinding): string | null {\n\t\tif (keybinding.isDuplicateModifierCase()) {\n\t\t\treturn '';\n\t\t}\n\t\treturn this._keyCodeToUILabel(keybinding.keyCode);\n\t}\n\n\tprotected _getAriaLabel(keybinding: SimpleKeybinding): string | null {\n\t\tif (keybinding.isDuplicateModifierCase()) {\n\t\t\treturn '';\n\t\t}\n\t\treturn KeyCodeUtils.toString(keybinding.keyCode);\n\t}\n\n\tprotected _getElectronAccelerator(keybinding: SimpleKeybinding): string | null {\n\t\treturn KeyCodeUtils.toElectronAccelerator(keybinding.keyCode);\n\t}\n\n\tprotected _getDispatchPart(keybinding: SimpleKeybinding): string | null {\n\t\treturn USLayoutResolvedKeybinding.getDispatchStr(keybinding);\n\t}\n\n\tpublic static getDispatchStr(keybinding: SimpleKeybinding): string | null {\n\t\tif (keybinding.isModifierKey()) {\n\t\t\treturn null;\n\t\t}\n\t\tlet result = '';\n\n\t\tif (keybinding.ctrlKey) {\n\t\t\tresult += 'ctrl+';\n\t\t}\n\t\tif (keybinding.shiftKey) {\n\t\t\tresult += 'shift+';\n\t\t}\n\t\tif (keybinding.altKey) {\n\t\t\tresult += 'alt+';\n\t\t}\n\t\tif (keybinding.metaKey) {\n\t\t\tresult += 'meta+';\n\t\t}\n\t\tresult += KeyCodeUtils.toString(keybinding.keyCode);\n\n\t\treturn result;\n\t}\n\n\tprotected _getSingleModifierDispatchPart(keybinding: SimpleKeybinding): KeybindingModifier | null {\n\t\tif (keybinding.keyCode === KeyCode.Ctrl && !keybinding.shiftKey && !keybinding.altKey && !keybinding.metaKey) {\n\t\t\treturn 'ctrl';\n\t\t}\n\t\tif (keybinding.keyCode === KeyCode.Shift && !keybinding.ctrlKey && !keybinding.altKey && !keybinding.metaKey) {\n\t\t\treturn 'shift';\n\t\t}\n\t\tif (keybinding.keyCode === KeyCode.Alt && !keybinding.ctrlKey && !keybinding.shiftKey && !keybinding.metaKey) {\n\t\t\treturn 'alt';\n\t\t}\n\t\tif (keybinding.keyCode === KeyCode.Meta && !keybinding.ctrlKey && !keybinding.shiftKey && !keybinding.altKey) {\n\t\t\treturn 'meta';\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * *NOTE*: Check return value for `KeyCode.Unknown`.\n\t */\n\tprivate static _scanCodeToKeyCode(scanCode: ScanCode): KeyCode {\n\t\tconst immutableKeyCode = IMMUTABLE_CODE_TO_KEY_CODE[scanCode];\n\t\tif (immutableKeyCode !== KeyCode.DependsOnKbLayout) {\n\t\t\treturn immutableKeyCode;\n\t\t}\n\n\t\tswitch (scanCode) {\n\t\t\tcase ScanCode.KeyA: return KeyCode.KeyA;\n\t\t\tcase ScanCode.KeyB: return KeyCode.KeyB;\n\t\t\tcase ScanCode.KeyC: return KeyCode.KeyC;\n\t\t\tcase ScanCode.KeyD: return KeyCode.KeyD;\n\t\t\tcase ScanCode.KeyE: return KeyCode.KeyE;\n\t\t\tcase ScanCode.KeyF: return KeyCode.KeyF;\n\t\t\tcase ScanCode.KeyG: return KeyCode.KeyG;\n\t\t\tcase ScanCode.KeyH: return KeyCode.KeyH;\n\t\t\tcase ScanCode.KeyI: return KeyCode.KeyI;\n\t\t\tcase ScanCode.KeyJ: return KeyCode.KeyJ;\n\t\t\tcase ScanCode.KeyK: return KeyCode.KeyK;\n\t\t\tcase ScanCode.KeyL: return KeyCode.KeyL;\n\t\t\tcase ScanCode.KeyM: return KeyCode.KeyM;\n\t\t\tcase ScanCode.KeyN: return KeyCode.KeyN;\n\t\t\tcase ScanCode.KeyO: return KeyCode.KeyO;\n\t\t\tcase ScanCode.KeyP: return KeyCode.KeyP;\n\t\t\tcase ScanCode.KeyQ: return KeyCode.KeyQ;\n\t\t\tcase ScanCode.KeyR: return KeyCode.KeyR;\n\t\t\tcase ScanCode.KeyS: return KeyCode.KeyS;\n\t\t\tcase ScanCode.KeyT: return KeyCode.KeyT;\n\t\t\tcase ScanCode.KeyU: return KeyCode.KeyU;\n\t\t\tcase ScanCode.KeyV: return KeyCode.KeyV;\n\t\t\tcase ScanCode.KeyW: return KeyCode.KeyW;\n\t\t\tcase ScanCode.KeyX: return KeyCode.KeyX;\n\t\t\tcase ScanCode.KeyY: return KeyCode.KeyY;\n\t\t\tcase ScanCode.KeyZ: return KeyCode.KeyZ;\n\t\t\tcase ScanCode.Digit1: return KeyCode.Digit1;\n\t\t\tcase ScanCode.Digit2: return KeyCode.Digit2;\n\t\t\tcase ScanCode.Digit3: return KeyCode.Digit3;\n\t\t\tcase ScanCode.Digit4: return KeyCode.Digit4;\n\t\t\tcase ScanCode.Digit5: return KeyCode.Digit5;\n\t\t\tcase ScanCode.Digit6: return KeyCode.Digit6;\n\t\t\tcase ScanCode.Digit7: return KeyCode.Digit7;\n\t\t\tcase ScanCode.Digit8: return KeyCode.Digit8;\n\t\t\tcase ScanCode.Digit9: return KeyCode.Digit9;\n\t\t\tcase ScanCode.Digit0: return KeyCode.Digit0;\n\t\t\tcase ScanCode.Minus: return KeyCode.Minus;\n\t\t\tcase ScanCode.Equal: return KeyCode.Equal;\n\t\t\tcase ScanCode.BracketLeft: return KeyCode.BracketLeft;\n\t\t\tcase ScanCode.BracketRight: return KeyCode.BracketRight;\n\t\t\tcase ScanCode.Backslash: return KeyCode.Backslash;\n\t\t\tcase ScanCode.IntlHash: return KeyCode.Unknown; // missing\n\t\t\tcase ScanCode.Semicolon: return KeyCode.Semicolon;\n\t\t\tcase ScanCode.Quote: return KeyCode.Quote;\n\t\t\tcase ScanCode.Backquote: return KeyCode.Backquote;\n\t\t\tcase ScanCode.Comma: return KeyCode.Comma;\n\t\t\tcase ScanCode.Period: return KeyCode.Period;\n\t\t\tcase ScanCode.Slash: return KeyCode.Slash;\n\t\t\tcase ScanCode.IntlBackslash: return KeyCode.IntlBackslash;\n\t\t}\n\t\treturn KeyCode.Unknown;\n\t}\n\n\tprivate static _resolveSimpleUserBinding(binding: SimpleKeybinding | ScanCodeBinding | null): SimpleKeybinding | null {\n\t\tif (!binding) {\n\t\t\treturn null;\n\t\t}\n\t\tif (binding instanceof SimpleKeybinding) {\n\t\t\treturn binding;\n\t\t}\n\t\tconst keyCode = this._scanCodeToKeyCode(binding.scanCode);\n\t\tif (keyCode === KeyCode.Unknown) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new SimpleKeybinding(binding.ctrlKey, binding.shiftKey, binding.altKey, binding.metaKey, keyCode);\n\t}\n\n\tpublic static resolveUserBinding(input: (SimpleKeybinding | ScanCodeBinding)[], os: OperatingSystem): USLayoutResolvedKeybinding[] {\n\t\tconst parts: SimpleKeybinding[] = removeElementsAfterNulls(input.map(keybinding => this._resolveSimpleUserBinding(keybinding)));\n\t\tif (parts.length > 0) {\n\t\t\treturn [new USLayoutResolvedKeybinding(new ChordKeybinding(parts), os)];\n\t\t}\n\t\treturn [];\n\t}\n}\n","\nimport { URI } from 'vs/base/common/uri';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const ILabelService = createDecorator('labelService');\n\nexport interface ILabelService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Gets the human readable label for a uri.\n\t * If `relative` is passed returns a label relative to the workspace root that the uri belongs to.\n\t * If `noPrefix` is passed does not tildify the label and also does not prepand the root name for relative labels in a multi root scenario.\n\t * If `separator` is passed, will use that over the defined path separator of the formatter.\n\t */\n\tgetUriLabel(resource: URI, options?: { relative?: boolean, noPrefix?: boolean, endWithSeparator?: boolean, separator?: '/' | '\\\\' }): string;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDimension } from 'vs/base/browser/dom';\nimport { Event } from 'vs/base/common/event';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const ILayoutService = createDecorator('layoutService');\n\nexport interface ILayoutService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * The dimensions of the container.\n\t */\n\treadonly dimension: IDimension;\n\n\t/**\n\t * Does the application have a single container?\n\t */\n\treadonly hasContainer: boolean;\n\n\t/**\n\t * Container of the application.\n\t */\n\treadonly container: HTMLElement;\n\n\t/**\n\t * An offset to use for positioning elements inside the container.\n\t */\n\treadonly offset?: { top: number };\n\n\t/**\n\t * An event that is emitted when the container is layed out. The\n\t * event carries the dimensions of the container as part of it.\n\t */\n\treadonly onDidLayout: Event;\n\n\t/**\n\t * Focus the primary component of the container.\n\t */\n\tfocus(): void;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { Event } from 'vs/base/common/event';\nimport { ILayoutService } from 'vs/platform/layout/browser/layoutService';\nimport { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';\nimport { registerSingleton } from 'vs/platform/instantiation/common/extensions';\n\nclass StandaloneLayoutService implements ILayoutService {\n\tdeclare readonly _serviceBrand: undefined;\n\n\tpublic onDidLayout = Event.None;\n\n\tprivate _dimension?: dom.IDimension;\n\tget dimension(): dom.IDimension {\n\t\tif (!this._dimension) {\n\t\t\tthis._dimension = dom.getClientArea(window.document.body);\n\t\t}\n\n\t\treturn this._dimension;\n\t}\n\n\tget hasContainer(): boolean {\n\t\treturn false;\n\t}\n\n\tget container(): HTMLElement {\n\t\t// On a page, multiple editors can be created. Therefore, there are multiple containers, not\n\t\t// just a single one. Please use `ICodeEditorService` to get the current focused code editor\n\t\t// and use its container if necessary. You can also instantiate `EditorScopedLayoutService`\n\t\t// which implements `ILayoutService` but is not a part of the service collection because\n\t\t// it is code editor instance specific.\n\t\tthrow new Error(`ILayoutService.container is not available in the standalone editor!`);\n\t}\n\n\tfocus(): void {\n\t\tthis._codeEditorService.getFocusedCodeEditor()?.focus();\n\t}\n\n\tconstructor(\n\t\t@ICodeEditorService private _codeEditorService: ICodeEditorService\n\t) { }\n}\n\nexport class EditorScopedLayoutService extends StandaloneLayoutService {\n\toverride get hasContainer(): boolean {\n\t\treturn false;\n\t}\n\toverride get container(): HTMLElement {\n\t\treturn this._container;\n\t}\n\tconstructor(\n\t\tprivate _container: HTMLElement,\n\t\t@ICodeEditorService codeEditorService: ICodeEditorService,\n\t) {\n\t\tsuper(codeEditorService);\n\t}\n}\n\nregisterSingleton(ILayoutService, StandaloneLayoutService);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ContextView, ContextViewDOMPosition } from 'vs/base/browser/ui/contextview/contextview';\nimport { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { ILayoutService } from 'vs/platform/layout/browser/layoutService';\nimport { IContextViewDelegate, IContextViewService } from './contextView';\n\nexport class ContextViewService extends Disposable implements IContextViewService {\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate currentViewDisposable: IDisposable = Disposable.None;\n\tprivate contextView: ContextView;\n\tprivate container: HTMLElement | null;\n\n\tconstructor(\n\t\t@ILayoutService readonly layoutService: ILayoutService\n\t) {\n\t\tsuper();\n\n\t\tthis.container = layoutService.hasContainer ? layoutService.container : null;\n\t\tthis.contextView = this._register(new ContextView(this.container, ContextViewDOMPosition.ABSOLUTE));\n\t\tthis.layout();\n\n\t\tthis._register(layoutService.onDidLayout(() => this.layout()));\n\t}\n\n\t// ContextView\n\n\tprivate setContainer(container: HTMLElement, domPosition?: ContextViewDOMPosition): void {\n\t\tthis.contextView.setContainer(container, domPosition || ContextViewDOMPosition.ABSOLUTE);\n\t}\n\n\tshowContextView(delegate: IContextViewDelegate, container?: HTMLElement, shadowRoot?: boolean): IDisposable {\n\t\tif (container) {\n\t\t\tif (container !== this.container) {\n\t\t\t\tthis.container = container;\n\t\t\t\tthis.setContainer(container, shadowRoot ? ContextViewDOMPosition.FIXED_SHADOW : ContextViewDOMPosition.FIXED);\n\t\t\t}\n\t\t} else {\n\t\t\tif (this.layoutService.hasContainer && this.container !== this.layoutService.container) {\n\t\t\t\tthis.container = this.layoutService.container;\n\t\t\t\tthis.setContainer(this.container, ContextViewDOMPosition.ABSOLUTE);\n\t\t\t}\n\t\t}\n\n\t\tthis.contextView.show(delegate);\n\n\t\tconst disposable = toDisposable(() => {\n\t\t\tif (this.currentViewDisposable === disposable) {\n\t\t\t\tthis.hideContextView();\n\t\t\t}\n\t\t});\n\n\t\tthis.currentViewDisposable = disposable;\n\t\treturn disposable;\n\t}\n\n\tgetContextViewElement(): HTMLElement {\n\t\treturn this.contextView.getViewElement();\n\t}\n\n\tlayout(): void {\n\t\tthis.contextView.layout();\n\t}\n\n\thideContextView(data?: any): void {\n\t\tthis.contextView.hide(data);\n\t}\n}\n","\nimport { Emitter } from 'vs/base/common/event';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const ILogService = createDecorator('logService');\n\nexport enum LogLevel {\n\tTrace,\n\tDebug,\n\tInfo,\n\tWarning,\n\tError,\n\tCritical,\n\tOff\n}\n\nexport const DEFAULT_LOG_LEVEL: LogLevel = LogLevel.Info;\n\nexport interface ILogger extends IDisposable {\n\tgetLevel(): LogLevel;\n\n\ttrace(message: string, ...args: any[]): void;\n\tdebug(message: string, ...args: any[]): void;\n\tinfo(message: string, ...args: any[]): void;\n\terror(message: string | Error, ...args: any[]): void;\n}\n\nexport interface ILogService extends ILogger {\n\treadonly _serviceBrand: undefined;\n}\n\nexport abstract class AbstractLogger extends Disposable {\n\n\tprivate level: LogLevel = DEFAULT_LOG_LEVEL;\n\tprivate readonly _onDidChangeLogLevel: Emitter = this._register(new Emitter());\n\n\tsetLevel(level: LogLevel): void {\n\t\tif (this.level !== level) {\n\t\t\tthis.level = level;\n\t\t\tthis._onDidChangeLogLevel.fire(this.level);\n\t\t}\n\t}\n\n\tgetLevel(): LogLevel {\n\t\treturn this.level;\n\t}\n\n}\n\nexport class ConsoleLogger extends AbstractLogger implements ILogger {\n\n\tconstructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL) {\n\t\tsuper();\n\t\tthis.setLevel(logLevel);\n\t}\n\n\ttrace(message: string, ...args: any[]): void {\n\t\tif (this.getLevel() <= LogLevel.Trace) {\n\t\t\tconsole.log('%cTRACE', 'color: #888', message, ...args);\n\t\t}\n\t}\n\n\tdebug(message: string, ...args: any[]): void {\n\t\tif (this.getLevel() <= LogLevel.Debug) {\n\t\t\tconsole.log('%cDEBUG', 'background: #eee; color: #888', message, ...args);\n\t\t}\n\t}\n\n\tinfo(message: string, ...args: any[]): void {\n\t\tif (this.getLevel() <= LogLevel.Info) {\n\t\t\tconsole.log('%c INFO', 'color: #33f', message, ...args);\n\t\t}\n\t}\n\n\terror(message: string, ...args: any[]): void {\n\t\tif (this.getLevel() <= LogLevel.Error) {\n\t\t\tconsole.log('%c ERR', 'color: #f33', message, ...args);\n\t\t}\n\t}\n\n\toverride dispose(): void {\n\t\t// noop\n\t}\n}\n\nexport class LogService extends Disposable implements ILogService {\n\tdeclare readonly _serviceBrand: undefined;\n\n\tconstructor(private logger: ILogger) {\n\t\tsuper();\n\t\tthis._register(logger);\n\t}\n\n\tgetLevel(): LogLevel {\n\t\treturn this.logger.getLevel();\n\t}\n\n\ttrace(message: string, ...args: any[]): void {\n\t\tthis.logger.trace(message, ...args);\n\t}\n\n\tdebug(message: string, ...args: any[]): void {\n\t\tthis.logger.debug(message, ...args);\n\t}\n\n\tinfo(message: string, ...args: any[]): void {\n\t\tthis.logger.info(message, ...args);\n\t}\n\n\terror(message: string | Error, ...args: any[]): void {\n\t\tthis.logger.error(message, ...args);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IntervalTimer, timeout } from 'vs/base/common/async';\nimport { Disposable, IDisposable, dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';\nimport { URI } from 'vs/base/common/uri';\nimport { SimpleWorkerClient, logOnceWebWorkerWarning, IWorkerClient } from 'vs/base/common/worker/simpleWorker';\nimport { DefaultWorkerFactory } from 'vs/base/browser/defaultWorkerFactory';\nimport { Position } from 'vs/editor/common/core/position';\nimport { IRange, Range } from 'vs/editor/common/core/range';\nimport { IDiffComputationResult } from 'vs/editor/common/diff/diffComputer';\nimport { ITextModel } from 'vs/editor/common/model';\nimport * as modes from 'vs/editor/common/languages';\nimport { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';\nimport { EditorSimpleWorker } from 'vs/editor/common/services/editorSimpleWorker';\nimport { IEditorWorkerService, IUnicodeHighlightsResult } from 'vs/editor/common/services/editorWorker';\nimport { IModelService } from 'vs/editor/common/services/model';\nimport { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration';\nimport { regExpFlags } from 'vs/base/common/strings';\nimport { isNonEmptyArray } from 'vs/base/common/arrays';\nimport { ILogService } from 'vs/platform/log/common/log';\nimport { StopWatch } from 'vs/base/common/stopwatch';\nimport { canceled } from 'vs/base/common/errors';\nimport { UnicodeHighlighterOptions } from 'vs/editor/common/languages/unicodeTextModelHighlighter';\nimport { IEditorWorkerHost } from 'vs/editor/common/services/editorWorkerHost';\n\n/**\n * Stop syncing a model to the worker if it was not needed for 1 min.\n */\nconst STOP_SYNC_MODEL_DELTA_TIME_MS = 60 * 1000;\n\n/**\n * Stop the worker if it was not needed for 5 min.\n */\nconst STOP_WORKER_DELTA_TIME_MS = 5 * 60 * 1000;\n\nfunction canSyncModel(modelService: IModelService, resource: URI): boolean {\n\tconst model = modelService.getModel(resource);\n\tif (!model) {\n\t\treturn false;\n\t}\n\tif (model.isTooLargeForSyncing()) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport class EditorWorkerService extends Disposable implements IEditorWorkerService {\n\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate readonly _modelService: IModelService;\n\tprivate readonly _workerManager: WorkerManager;\n\tprivate readonly _logService: ILogService;\n\n\tconstructor(\n\t\t@IModelService modelService: IModelService,\n\t\t@ITextResourceConfigurationService configurationService: ITextResourceConfigurationService,\n\t\t@ILogService logService: ILogService,\n\t\t@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService\n\t) {\n\t\tsuper();\n\t\tthis._modelService = modelService;\n\t\tthis._workerManager = this._register(new WorkerManager(this._modelService, languageConfigurationService));\n\t\tthis._logService = logService;\n\n\t\t// register default link-provider and default completions-provider\n\t\tthis._register(modes.LinkProviderRegistry.register({ language: '*', hasAccessToAllModels: true }, {\n\t\t\tprovideLinks: (model, token) => {\n\t\t\t\tif (!canSyncModel(this._modelService, model.uri)) {\n\t\t\t\t\treturn Promise.resolve({ links: [] }); // File too large\n\t\t\t\t}\n\t\t\t\treturn this._workerManager.withWorker().then(client => client.computeLinks(model.uri)).then(links => {\n\t\t\t\t\treturn links && { links };\n\t\t\t\t});\n\t\t\t}\n\t\t}));\n\t\tthis._register(modes.CompletionProviderRegistry.register('*', new WordBasedCompletionItemProvider(this._workerManager, configurationService, this._modelService, languageConfigurationService)));\n\t}\n\n\tpublic override dispose(): void {\n\t\tsuper.dispose();\n\t}\n\n\tpublic canComputeUnicodeHighlights(uri: URI): boolean {\n\t\treturn canSyncModel(this._modelService, uri);\n\t}\n\n\tpublic computedUnicodeHighlights(uri: URI, options: UnicodeHighlighterOptions, range?: IRange): Promise {\n\t\treturn this._workerManager.withWorker().then(client => client.computedUnicodeHighlights(uri, options, range));\n\t}\n\n\tpublic computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean, maxComputationTime: number): Promise {\n\t\treturn this._workerManager.withWorker().then(client => client.computeDiff(original, modified, ignoreTrimWhitespace, maxComputationTime));\n\t}\n\n\tpublic computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[] | null | undefined): Promise {\n\t\tif (isNonEmptyArray(edits)) {\n\t\t\tif (!canSyncModel(this._modelService, resource)) {\n\t\t\t\treturn Promise.resolve(edits); // File too large\n\t\t\t}\n\t\t\tconst sw = StopWatch.create(true);\n\t\t\tconst result = this._workerManager.withWorker().then(client => client.computeMoreMinimalEdits(resource, edits));\n\t\t\tresult.finally(() => this._logService.trace('FORMAT#computeMoreMinimalEdits', resource.toString(true), sw.elapsed()));\n\t\t\treturn Promise.race([result, timeout(1000).then(() => edits)]);\n\n\t\t} else {\n\t\t\treturn Promise.resolve(undefined);\n\t\t}\n\t}\n\n\tpublic canNavigateValueSet(resource: URI): boolean {\n\t\treturn (canSyncModel(this._modelService, resource));\n\t}\n\n\tpublic navigateValueSet(resource: URI, range: IRange, up: boolean): Promise {\n\t\treturn this._workerManager.withWorker().then(client => client.navigateValueSet(resource, range, up));\n\t}\n\n\tcanComputeWordRanges(resource: URI): boolean {\n\t\treturn canSyncModel(this._modelService, resource);\n\t}\n\n\tcomputeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] } | null> {\n\t\treturn this._workerManager.withWorker().then(client => client.computeWordRanges(resource, range));\n\t}\n}\n\nclass WordBasedCompletionItemProvider implements modes.CompletionItemProvider {\n\n\tprivate readonly _workerManager: WorkerManager;\n\tprivate readonly _configurationService: ITextResourceConfigurationService;\n\tprivate readonly _modelService: IModelService;\n\n\treadonly _debugDisplayName = 'wordbasedCompletions';\n\n\tconstructor(\n\t\tworkerManager: WorkerManager,\n\t\tconfigurationService: ITextResourceConfigurationService,\n\t\tmodelService: IModelService,\n\t\tprivate readonly languageConfigurationService: ILanguageConfigurationService\n\t) {\n\t\tthis._workerManager = workerManager;\n\t\tthis._configurationService = configurationService;\n\t\tthis._modelService = modelService;\n\t}\n\n\tasync provideCompletionItems(model: ITextModel, position: Position): Promise {\n\t\ttype WordBasedSuggestionsConfig = {\n\t\t\twordBasedSuggestions?: boolean,\n\t\t\twordBasedSuggestionsMode?: 'currentDocument' | 'matchingDocuments' | 'allDocuments'\n\t\t};\n\t\tconst config = this._configurationService.getValue(model.uri, position, 'editor');\n\t\tif (!config.wordBasedSuggestions) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst models: URI[] = [];\n\t\tif (config.wordBasedSuggestionsMode === 'currentDocument') {\n\t\t\t// only current file and only if not too large\n\t\t\tif (canSyncModel(this._modelService, model.uri)) {\n\t\t\t\tmodels.push(model.uri);\n\t\t\t}\n\t\t} else {\n\t\t\t// either all files or files of same language\n\t\t\tfor (const candidate of this._modelService.getModels()) {\n\t\t\t\tif (!canSyncModel(this._modelService, candidate.uri)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (candidate === model) {\n\t\t\t\t\tmodels.unshift(candidate.uri);\n\n\t\t\t\t} else if (config.wordBasedSuggestionsMode === 'allDocuments' || candidate.getLanguageId() === model.getLanguageId()) {\n\t\t\t\t\tmodels.push(candidate.uri);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (models.length === 0) {\n\t\t\treturn undefined; // File too large, no other files\n\t\t}\n\n\t\tconst wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition();\n\t\tconst word = model.getWordAtPosition(position);\n\t\tconst replace = !word ? Range.fromPositions(position) : new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn);\n\t\tconst insert = replace.setEndPosition(position.lineNumber, position.column);\n\n\t\tconst client = await this._workerManager.withWorker();\n\t\tconst data = await client.textualSuggest(models, word?.word, wordDefRegExp);\n\t\tif (!data) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tduration: data.duration,\n\t\t\tsuggestions: data.words.map((word): modes.CompletionItem => {\n\t\t\t\treturn {\n\t\t\t\t\tkind: modes.CompletionItemKind.Text,\n\t\t\t\t\tlabel: word,\n\t\t\t\t\tinsertText: word,\n\t\t\t\t\trange: { insert, replace }\n\t\t\t\t};\n\t\t\t}),\n\t\t};\n\t}\n}\n\nclass WorkerManager extends Disposable {\n\n\tprivate readonly _modelService: IModelService;\n\tprivate _editorWorkerClient: EditorWorkerClient | null;\n\tprivate _lastWorkerUsedTime: number;\n\n\tconstructor(modelService: IModelService, private readonly languageConfigurationService: ILanguageConfigurationService) {\n\t\tsuper();\n\t\tthis._modelService = modelService;\n\t\tthis._editorWorkerClient = null;\n\t\tthis._lastWorkerUsedTime = (new Date()).getTime();\n\n\t\tconst stopWorkerInterval = this._register(new IntervalTimer());\n\t\tstopWorkerInterval.cancelAndSet(() => this._checkStopIdleWorker(), Math.round(STOP_WORKER_DELTA_TIME_MS / 2));\n\n\t\tthis._register(this._modelService.onModelRemoved(_ => this._checkStopEmptyWorker()));\n\t}\n\n\tpublic override dispose(): void {\n\t\tif (this._editorWorkerClient) {\n\t\t\tthis._editorWorkerClient.dispose();\n\t\t\tthis._editorWorkerClient = null;\n\t\t}\n\t\tsuper.dispose();\n\t}\n\n\t/**\n\t * Check if the model service has no more models and stop the worker if that is the case.\n\t */\n\tprivate _checkStopEmptyWorker(): void {\n\t\tif (!this._editorWorkerClient) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst models = this._modelService.getModels();\n\t\tif (models.length === 0) {\n\t\t\t// There are no more models => nothing possible for me to do\n\t\t\tthis._editorWorkerClient.dispose();\n\t\t\tthis._editorWorkerClient = null;\n\t\t}\n\t}\n\n\t/**\n\t * Check if the worker has been idle for a while and then stop it.\n\t */\n\tprivate _checkStopIdleWorker(): void {\n\t\tif (!this._editorWorkerClient) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst timeSinceLastWorkerUsedTime = (new Date()).getTime() - this._lastWorkerUsedTime;\n\t\tif (timeSinceLastWorkerUsedTime > STOP_WORKER_DELTA_TIME_MS) {\n\t\t\tthis._editorWorkerClient.dispose();\n\t\t\tthis._editorWorkerClient = null;\n\t\t}\n\t}\n\n\tpublic withWorker(): Promise {\n\t\tthis._lastWorkerUsedTime = (new Date()).getTime();\n\t\tif (!this._editorWorkerClient) {\n\t\t\tthis._editorWorkerClient = new EditorWorkerClient(this._modelService, false, 'editorWorkerService', this.languageConfigurationService);\n\t\t}\n\t\treturn Promise.resolve(this._editorWorkerClient);\n\t}\n}\n\nclass EditorModelManager extends Disposable {\n\n\tprivate readonly _proxy: EditorSimpleWorker;\n\tprivate readonly _modelService: IModelService;\n\tprivate _syncedModels: { [modelUrl: string]: IDisposable; } = Object.create(null);\n\tprivate _syncedModelsLastUsedTime: { [modelUrl: string]: number; } = Object.create(null);\n\n\tconstructor(proxy: EditorSimpleWorker, modelService: IModelService, keepIdleModels: boolean) {\n\t\tsuper();\n\t\tthis._proxy = proxy;\n\t\tthis._modelService = modelService;\n\n\t\tif (!keepIdleModels) {\n\t\t\tconst timer = new IntervalTimer();\n\t\t\ttimer.cancelAndSet(() => this._checkStopModelSync(), Math.round(STOP_SYNC_MODEL_DELTA_TIME_MS / 2));\n\t\t\tthis._register(timer);\n\t\t}\n\t}\n\n\tpublic override dispose(): void {\n\t\tfor (let modelUrl in this._syncedModels) {\n\t\t\tdispose(this._syncedModels[modelUrl]);\n\t\t}\n\t\tthis._syncedModels = Object.create(null);\n\t\tthis._syncedModelsLastUsedTime = Object.create(null);\n\t\tsuper.dispose();\n\t}\n\n\tpublic ensureSyncedResources(resources: URI[], forceLargeModels: boolean): void {\n\t\tfor (const resource of resources) {\n\t\t\tconst resourceStr = resource.toString();\n\n\t\t\tif (!this._syncedModels[resourceStr]) {\n\t\t\t\tthis._beginModelSync(resource, forceLargeModels);\n\t\t\t}\n\t\t\tif (this._syncedModels[resourceStr]) {\n\t\t\t\tthis._syncedModelsLastUsedTime[resourceStr] = (new Date()).getTime();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _checkStopModelSync(): void {\n\t\tconst currentTime = (new Date()).getTime();\n\n\t\tconst toRemove: string[] = [];\n\t\tfor (let modelUrl in this._syncedModelsLastUsedTime) {\n\t\t\tconst elapsedTime = currentTime - this._syncedModelsLastUsedTime[modelUrl];\n\t\t\tif (elapsedTime > STOP_SYNC_MODEL_DELTA_TIME_MS) {\n\t\t\t\ttoRemove.push(modelUrl);\n\t\t\t}\n\t\t}\n\n\t\tfor (const e of toRemove) {\n\t\t\tthis._stopModelSync(e);\n\t\t}\n\t}\n\n\tprivate _beginModelSync(resource: URI, forceLargeModels: boolean): void {\n\t\tconst model = this._modelService.getModel(resource);\n\t\tif (!model) {\n\t\t\treturn;\n\t\t}\n\t\tif (!forceLargeModels && model.isTooLargeForSyncing()) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelUrl = resource.toString();\n\n\t\tthis._proxy.acceptNewModel({\n\t\t\turl: model.uri.toString(),\n\t\t\tlines: model.getLinesContent(),\n\t\t\tEOL: model.getEOL(),\n\t\t\tversionId: model.getVersionId()\n\t\t});\n\n\t\tconst toDispose = new DisposableStore();\n\t\ttoDispose.add(model.onDidChangeContent((e) => {\n\t\t\tthis._proxy.acceptModelChanged(modelUrl.toString(), e);\n\t\t}));\n\t\ttoDispose.add(model.onWillDispose(() => {\n\t\t\tthis._stopModelSync(modelUrl);\n\t\t}));\n\t\ttoDispose.add(toDisposable(() => {\n\t\t\tthis._proxy.acceptRemovedModel(modelUrl);\n\t\t}));\n\n\t\tthis._syncedModels[modelUrl] = toDispose;\n\t}\n\n\tprivate _stopModelSync(modelUrl: string): void {\n\t\tconst toDispose = this._syncedModels[modelUrl];\n\t\tdelete this._syncedModels[modelUrl];\n\t\tdelete this._syncedModelsLastUsedTime[modelUrl];\n\t\tdispose(toDispose);\n\t}\n}\n\nclass SynchronousWorkerClient implements IWorkerClient {\n\tprivate readonly _instance: T;\n\tprivate readonly _proxyObj: Promise;\n\n\tconstructor(instance: T) {\n\t\tthis._instance = instance;\n\t\tthis._proxyObj = Promise.resolve(this._instance);\n\t}\n\n\tpublic dispose(): void {\n\t\tthis._instance.dispose();\n\t}\n\n\tpublic getProxyObject(): Promise {\n\t\treturn this._proxyObj;\n\t}\n}\n\nexport interface IEditorWorkerClient {\n\tfhr(method: string, args: any[]): Promise;\n}\n\nexport class EditorWorkerHost implements IEditorWorkerHost {\n\n\tprivate readonly _workerClient: IEditorWorkerClient;\n\n\tconstructor(workerClient: IEditorWorkerClient) {\n\t\tthis._workerClient = workerClient;\n\t}\n\n\t// foreign host request\n\tpublic fhr(method: string, args: any[]): Promise {\n\t\treturn this._workerClient.fhr(method, args);\n\t}\n}\n\nexport class EditorWorkerClient extends Disposable implements IEditorWorkerClient {\n\n\tprivate readonly _modelService: IModelService;\n\tprivate readonly _keepIdleModels: boolean;\n\tprotected _worker: IWorkerClient | null;\n\tprotected readonly _workerFactory: DefaultWorkerFactory;\n\tprivate _modelManager: EditorModelManager | null;\n\tprivate _disposed = false;\n\n\tconstructor(\n\t\tmodelService: IModelService,\n\t\tkeepIdleModels: boolean,\n\t\tlabel: string | undefined,\n\t\tprivate readonly languageConfigurationService: ILanguageConfigurationService\n\t) {\n\t\tsuper();\n\t\tthis._modelService = modelService;\n\t\tthis._keepIdleModels = keepIdleModels;\n\t\tthis._workerFactory = new DefaultWorkerFactory(label);\n\t\tthis._worker = null;\n\t\tthis._modelManager = null;\n\t}\n\n\t// foreign host request\n\tpublic fhr(method: string, args: any[]): Promise {\n\t\tthrow new Error(`Not implemented!`);\n\t}\n\n\tprivate _getOrCreateWorker(): IWorkerClient {\n\t\tif (!this._worker) {\n\t\t\ttry {\n\t\t\t\tthis._worker = this._register(new SimpleWorkerClient(\n\t\t\t\t\tthis._workerFactory,\n\t\t\t\t\t'vs/editor/common/services/editorSimpleWorker',\n\t\t\t\t\tnew EditorWorkerHost(this)\n\t\t\t\t));\n\t\t\t} catch (err) {\n\t\t\t\tlogOnceWebWorkerWarning(err);\n\t\t\t\tthis._worker = new SynchronousWorkerClient(new EditorSimpleWorker(new EditorWorkerHost(this), null));\n\t\t\t}\n\t\t}\n\t\treturn this._worker;\n\t}\n\n\tprotected _getProxy(): Promise {\n\t\treturn this._getOrCreateWorker().getProxyObject().then(undefined, (err) => {\n\t\t\tlogOnceWebWorkerWarning(err);\n\t\t\tthis._worker = new SynchronousWorkerClient(new EditorSimpleWorker(new EditorWorkerHost(this), null));\n\t\t\treturn this._getOrCreateWorker().getProxyObject();\n\t\t});\n\t}\n\n\tprivate _getOrCreateModelManager(proxy: EditorSimpleWorker): EditorModelManager {\n\t\tif (!this._modelManager) {\n\t\t\tthis._modelManager = this._register(new EditorModelManager(proxy, this._modelService, this._keepIdleModels));\n\t\t}\n\t\treturn this._modelManager;\n\t}\n\n\tprotected async _withSyncedResources(resources: URI[], forceLargeModels: boolean = false): Promise {\n\t\tif (this._disposed) {\n\t\t\treturn Promise.reject(canceled());\n\t\t}\n\t\treturn this._getProxy().then((proxy) => {\n\t\t\tthis._getOrCreateModelManager(proxy).ensureSyncedResources(resources, forceLargeModels);\n\t\t\treturn proxy;\n\t\t});\n\t}\n\n\tpublic computedUnicodeHighlights(uri: URI, options: UnicodeHighlighterOptions, range?: IRange): Promise {\n\t\treturn this._withSyncedResources([uri]).then(proxy => {\n\t\t\treturn proxy.computeUnicodeHighlights(uri.toString(), options, range);\n\t\t});\n\t}\n\n\tpublic computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean, maxComputationTime: number): Promise {\n\t\treturn this._withSyncedResources([original, modified], /* forceLargeModels */true).then(proxy => {\n\t\t\treturn proxy.computeDiff(original.toString(), modified.toString(), ignoreTrimWhitespace, maxComputationTime);\n\t\t});\n\t}\n\n\tpublic computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[]): Promise {\n\t\treturn this._withSyncedResources([resource]).then(proxy => {\n\t\t\treturn proxy.computeMoreMinimalEdits(resource.toString(), edits);\n\t\t});\n\t}\n\n\tpublic computeLinks(resource: URI): Promise {\n\t\treturn this._withSyncedResources([resource]).then(proxy => {\n\t\t\treturn proxy.computeLinks(resource.toString());\n\t\t});\n\t}\n\n\tpublic async textualSuggest(resources: URI[], leadingWord: string | undefined, wordDefRegExp: RegExp): Promise<{ words: string[], duration: number } | null> {\n\t\tconst proxy = await this._withSyncedResources(resources);\n\t\tconst wordDef = wordDefRegExp.source;\n\t\tconst wordDefFlags = regExpFlags(wordDefRegExp);\n\t\treturn proxy.textualSuggest(resources.map(r => r.toString()), leadingWord, wordDef, wordDefFlags);\n\t}\n\n\tcomputeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] } | null> {\n\t\treturn this._withSyncedResources([resource]).then(proxy => {\n\t\t\tconst model = this._modelService.getModel(resource);\n\t\t\tif (!model) {\n\t\t\t\treturn Promise.resolve(null);\n\t\t\t}\n\t\t\tconst wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition();\n\t\t\tconst wordDef = wordDefRegExp.source;\n\t\t\tconst wordDefFlags = regExpFlags(wordDefRegExp);\n\t\t\treturn proxy.computeWordRanges(resource.toString(), range, wordDef, wordDefFlags);\n\t\t});\n\t}\n\n\tpublic navigateValueSet(resource: URI, range: IRange, up: boolean): Promise {\n\t\treturn this._withSyncedResources([resource]).then(proxy => {\n\t\t\tconst model = this._modelService.getModel(resource);\n\t\t\tif (!model) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition();\n\t\t\tconst wordDef = wordDefRegExp.source;\n\t\t\tconst wordDefFlags = regExpFlags(wordDefRegExp);\n\t\t\treturn proxy.navigateValueSet(resource.toString(), range, up, wordDef, wordDefFlags);\n\t\t});\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tthis._disposed = true;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { URI } from 'vs/base/common/uri';\nimport { EditorWorkerClient } from 'vs/editor/browser/services/editorWorkerService';\nimport { IModelService } from 'vs/editor/common/services/model';\nimport * as types from 'vs/base/common/types';\nimport { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';\n\n/**\n * Create a new web worker that has model syncing capabilities built in.\n * Specify an AMD module to load that will `create` an object that will be proxied.\n */\nexport function createWebWorker(modelService: IModelService, languageConfigurationService: ILanguageConfigurationService, opts: IWebWorkerOptions): MonacoWebWorker {\n\treturn new MonacoWebWorkerImpl(modelService, languageConfigurationService, opts);\n}\n\n/**\n * A web worker that can provide a proxy to an arbitrary file.\n */\nexport interface MonacoWebWorker {\n\t/**\n\t * Terminate the web worker, thus invalidating the returned proxy.\n\t */\n\tdispose(): void;\n\t/**\n\t * Get a proxy to the arbitrary loaded code.\n\t */\n\tgetProxy(): Promise;\n\t/**\n\t * Synchronize (send) the models at `resources` to the web worker,\n\t * making them available in the monaco.worker.getMirrorModels().\n\t */\n\twithSyncedResources(resources: URI[]): Promise;\n}\n\nexport interface IWebWorkerOptions {\n\t/**\n\t * The AMD moduleId to load.\n\t * It should export a function `create` that should return the exported proxy.\n\t */\n\tmoduleId: string;\n\t/**\n\t * The data to send over when calling create on the module.\n\t */\n\tcreateData?: any;\n\t/**\n\t * A label to be used to identify the web worker for debugging purposes.\n\t */\n\tlabel?: string;\n\t/**\n\t * An object that can be used by the web worker to make calls back to the main thread.\n\t */\n\thost?: any;\n\t/**\n\t * Keep idle models.\n\t * Defaults to false, which means that idle models will stop syncing after a while.\n\t */\n\tkeepIdleModels?: boolean;\n}\n\nclass MonacoWebWorkerImpl extends EditorWorkerClient implements MonacoWebWorker {\n\n\tprivate readonly _foreignModuleId: string;\n\tprivate readonly _foreignModuleHost: { [method: string]: Function } | null;\n\tprivate _foreignModuleCreateData: any | null;\n\tprivate _foreignProxy: Promise | null;\n\n\tconstructor(modelService: IModelService, languageConfigurationService: ILanguageConfigurationService, opts: IWebWorkerOptions) {\n\t\tsuper(modelService, opts.keepIdleModels || false, opts.label, languageConfigurationService);\n\t\tthis._foreignModuleId = opts.moduleId;\n\t\tthis._foreignModuleCreateData = opts.createData || null;\n\t\tthis._foreignModuleHost = opts.host || null;\n\t\tthis._foreignProxy = null;\n\t}\n\n\t// foreign host request\n\tpublic override fhr(method: string, args: any[]): Promise {\n\t\tif (!this._foreignModuleHost || typeof this._foreignModuleHost[method] !== 'function') {\n\t\t\treturn Promise.reject(new Error('Missing method ' + method + ' or missing main thread foreign host.'));\n\t\t}\n\n\t\ttry {\n\t\t\treturn Promise.resolve(this._foreignModuleHost[method].apply(this._foreignModuleHost, args));\n\t\t} catch (e) {\n\t\t\treturn Promise.reject(e);\n\t\t}\n\t}\n\n\tprivate _getForeignProxy(): Promise {\n\t\tif (!this._foreignProxy) {\n\t\t\tthis._foreignProxy = this._getProxy().then((proxy) => {\n\t\t\t\tconst foreignHostMethods = this._foreignModuleHost ? types.getAllMethodNames(this._foreignModuleHost) : [];\n\t\t\t\treturn proxy.loadForeignModule(this._foreignModuleId, this._foreignModuleCreateData, foreignHostMethods).then((foreignMethods) => {\n\t\t\t\t\tthis._foreignModuleCreateData = null;\n\n\t\t\t\t\tconst proxyMethodRequest = (method: string, args: any[]): Promise => {\n\t\t\t\t\t\treturn proxy.fmr(method, args);\n\t\t\t\t\t};\n\n\t\t\t\t\tconst createProxyMethod = (method: string, proxyMethodRequest: (method: string, args: any[]) => Promise): () => Promise => {\n\t\t\t\t\t\treturn function () {\n\t\t\t\t\t\t\tconst args = Array.prototype.slice.call(arguments, 0);\n\t\t\t\t\t\t\treturn proxyMethodRequest(method, args);\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\n\t\t\t\t\tconst foreignProxy = {} as T;\n\t\t\t\t\tfor (const foreignMethod of foreignMethods) {\n\t\t\t\t\t\t(foreignProxy)[foreignMethod] = createProxyMethod(foreignMethod, proxyMethodRequest);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn foreignProxy;\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\treturn this._foreignProxy;\n\t}\n\n\tpublic getProxy(): Promise {\n\t\treturn this._getForeignProxy();\n\t}\n\n\tpublic withSyncedResources(resources: URI[]): Promise {\n\t\treturn this._withSyncedResources(resources).then(_ => this.getProxy());\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { doHash } from 'vs/base/common/hash';\nimport { LRUCache } from 'vs/base/common/map';\nimport { clamp, MovingAverage, SlidingWindowAverage } from 'vs/base/common/numbers';\nimport { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { registerSingleton } from 'vs/platform/instantiation/common/extensions';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { ILogService } from 'vs/platform/log/common/log';\n\n\nexport const ILanguageFeatureDebounceService = createDecorator('ILanguageFeatureDebounceService');\n\nexport interface ILanguageFeatureDebounceService {\n\n\treadonly _serviceBrand: undefined;\n\n\tfor(feature: LanguageFeatureRegistry, debugName: string, config?: { min?: number, max?: number, salt?: string }): IFeatureDebounceInformation;\n}\n\nexport interface IFeatureDebounceInformation {\n\tget(model: ITextModel): number;\n\tupdate(model: ITextModel, value: number): number;\n\tdefault(): number;\n}\n\nnamespace IdentityHash {\n\tconst _hashes = new WeakMap();\n\tlet pool = 0;\n\texport function of(obj: object): number {\n\t\tlet value = _hashes.get(obj);\n\t\tif (value === undefined) {\n\t\t\tvalue = ++pool;\n\t\t\t_hashes.set(obj, value);\n\t\t}\n\t\treturn value;\n\t}\n}\n\nclass FeatureDebounceInformation implements IFeatureDebounceInformation {\n\n\tprivate readonly _cache = new LRUCache(50, 0.7);\n\n\tconstructor(\n\t\tprivate readonly _logService: ILogService,\n\t\tprivate readonly _name: string,\n\t\tprivate readonly _registry: LanguageFeatureRegistry,\n\t\tprivate readonly _default: number,\n\t\tprivate readonly _min: number,\n\t\tprivate readonly _max: number,\n\t) { }\n\n\tprivate _key(model: ITextModel): string {\n\t\treturn model.id + this._registry.all(model).reduce((hashVal, obj) => doHash(IdentityHash.of(obj), hashVal), 0);\n\t}\n\n\tget(model: ITextModel): number {\n\t\tconst key = this._key(model);\n\t\tconst avg = this._cache.get(key);\n\t\treturn avg\n\t\t\t? clamp(avg.value, this._min, this._max)\n\t\t\t: this.default();\n\t}\n\n\tupdate(model: ITextModel, value: number): number {\n\t\tconst key = this._key(model);\n\t\tlet avg = this._cache.get(key);\n\t\tif (!avg) {\n\t\t\tavg = new SlidingWindowAverage(6);\n\t\t\tthis._cache.set(key, avg);\n\t\t}\n\t\tconst newValue = clamp(avg.update(value), this._min, this._max);\n\t\tthis._logService.trace(`[DEBOUNCE: ${this._name}] for ${model.uri.toString()} is ${newValue}ms`);\n\t\treturn newValue;\n\t}\n\n\tprivate _overall(): number {\n\t\tconst result = new MovingAverage();\n\t\tfor (const [, avg] of this._cache) {\n\t\t\tresult.update(avg.value);\n\t\t}\n\t\treturn result.value;\n\t}\n\n\tdefault() {\n\t\tconst value = (this._overall() | 0) || this._default;\n\t\treturn clamp(value, this._min, this._max);\n\t}\n}\n\n\nexport class LanguageFeatureDebounceService implements ILanguageFeatureDebounceService {\n\n\tdeclare _serviceBrand: undefined;\n\n\tprivate readonly _data = new Map();\n\n\tconstructor(@ILogService private readonly _logService: ILogService) {\n\n\t}\n\n\tfor(feature: LanguageFeatureRegistry, name: string, config?: { min?: number, max?: number, key?: string }): IFeatureDebounceInformation {\n\t\tconst min = config?.min ?? 50;\n\t\tconst max = config?.max ?? min ** 2;\n\t\tconst extra = config?.key ?? undefined;\n\t\tconst key = `${IdentityHash.of(feature)},${min}${extra ? ',' + extra : ''}`;\n\t\tlet info = this._data.get(key);\n\t\tif (!info) {\n\t\t\tinfo = new FeatureDebounceInformation(\n\t\t\t\tthis._logService,\n\t\t\t\tname,\n\t\t\t\tfeature,\n\t\t\t\t(this._overallAverage() | 0) || (min * 1.5), // default is overall default or derived from min-value\n\t\t\t\tmin,\n\t\t\t\tmax\n\t\t\t);\n\t\t\tthis._data.set(key, info);\n\t\t}\n\t\treturn info;\n\t}\n\n\tprivate _overallAverage(): number {\n\t\t// Average of all language features. Not a great value but an approximation\n\t\tlet result = new MovingAverage();\n\t\tfor (let info of this._data.values()) {\n\t\t\tresult.update(info.default());\n\t\t}\n\t\treturn result.value;\n\t}\n}\n\nregisterSingleton(ILanguageFeatureDebounceService, LanguageFeatureDebounceService, true);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { equals } from 'vs/base/common/arrays';\nimport { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';\nimport { onUnexpectedExternalError } from 'vs/base/common/errors';\nimport { Iterable } from 'vs/base/common/iterator';\nimport { LRUCache } from 'vs/base/common/map';\nimport { URI } from 'vs/base/common/uri';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { DocumentSymbol, DocumentSymbolProvider, DocumentSymbolProviderRegistry } from 'vs/editor/common/languages';\nimport { IFeatureDebounceInformation, ILanguageFeatureDebounceService } from 'vs/editor/common/services/languageFeatureDebounce';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { registerSingleton } from 'vs/platform/instantiation/common/extensions';\nimport { IModelService } from 'vs/editor/common/services/model';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\n\nexport abstract class TreeElement {\n\n\tabstract id: string;\n\tabstract children: Map;\n\tabstract parent: TreeElement | undefined;\n\n\tremove(): void {\n\t\tif (this.parent) {\n\t\t\tthis.parent.children.delete(this.id);\n\t\t}\n\t}\n\n\tstatic findId(candidate: DocumentSymbol | string, container: TreeElement): string {\n\t\t// complex id-computation which contains the origin/extension,\n\t\t// the parent path, and some dedupe logic when names collide\n\t\tlet candidateId: string;\n\t\tif (typeof candidate === 'string') {\n\t\t\tcandidateId = `${container.id}/${candidate}`;\n\t\t} else {\n\t\t\tcandidateId = `${container.id}/${candidate.name}`;\n\t\t\tif (container.children.get(candidateId) !== undefined) {\n\t\t\t\tcandidateId = `${container.id}/${candidate.name}_${candidate.range.startLineNumber}_${candidate.range.startColumn}`;\n\t\t\t}\n\t\t}\n\n\t\tlet id = candidateId;\n\t\tfor (let i = 0; container.children.get(id) !== undefined; i++) {\n\t\t\tid = `${candidateId}_${i}`;\n\t\t}\n\n\t\treturn id;\n\t}\n\n\tstatic empty(element: TreeElement): boolean {\n\t\treturn element.children.size === 0;\n\t}\n}\n\nexport class OutlineElement extends TreeElement {\n\n\tchildren = new Map();\n\n\tconstructor(\n\t\treadonly id: string,\n\t\tpublic parent: TreeElement | undefined,\n\t\treadonly symbol: DocumentSymbol\n\t) {\n\t\tsuper();\n\t}\n}\n\nexport class OutlineGroup extends TreeElement {\n\n\tchildren = new Map();\n\n\tconstructor(\n\t\treadonly id: string,\n\t\tpublic parent: TreeElement | undefined,\n\t\treadonly label: string,\n\t\treadonly order: number,\n\t) {\n\t\tsuper();\n\t}\n}\n\nexport class OutlineModel extends TreeElement {\n\n\tstatic create(textModel: ITextModel, token: CancellationToken): Promise {\n\n\t\tconst cts = new CancellationTokenSource(token);\n\t\tconst result = new OutlineModel(textModel.uri);\n\t\tconst provider = DocumentSymbolProviderRegistry.ordered(textModel);\n\t\tconst promises = provider.map((provider, index) => {\n\n\t\t\tlet id = TreeElement.findId(`provider_${index}`, result);\n\t\t\tlet group = new OutlineGroup(id, result, provider.displayName ?? 'Unknown Outline Provider', index);\n\n\t\t\treturn Promise.resolve(provider.provideDocumentSymbols(textModel, cts.token)).then(result => {\n\t\t\t\tfor (const info of result || []) {\n\t\t\t\t\tOutlineModel._makeOutlineElement(info, group);\n\t\t\t\t}\n\t\t\t\treturn group;\n\t\t\t}, err => {\n\t\t\t\tonUnexpectedExternalError(err);\n\t\t\t\treturn group;\n\t\t\t}).then(group => {\n\t\t\t\tif (!TreeElement.empty(group)) {\n\t\t\t\t\tresult._groups.set(id, group);\n\t\t\t\t} else {\n\t\t\t\t\tgroup.remove();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\tconst listener = DocumentSymbolProviderRegistry.onDidChange(() => {\n\t\t\tconst newProvider = DocumentSymbolProviderRegistry.ordered(textModel);\n\t\t\tif (!equals(newProvider, provider)) {\n\t\t\t\tcts.cancel();\n\t\t\t}\n\t\t});\n\n\t\treturn Promise.all(promises).then(() => {\n\t\t\tif (cts.token.isCancellationRequested && !token.isCancellationRequested) {\n\t\t\t\treturn OutlineModel.create(textModel, token);\n\t\t\t} else {\n\t\t\t\treturn result._compact();\n\t\t\t}\n\t\t}).finally(() => {\n\t\t\tlistener.dispose();\n\t\t});\n\t}\n\n\tprivate static _makeOutlineElement(info: DocumentSymbol, container: OutlineGroup | OutlineElement): void {\n\t\tlet id = TreeElement.findId(info, container);\n\t\tlet res = new OutlineElement(id, container, info);\n\t\tif (info.children) {\n\t\t\tfor (const childInfo of info.children) {\n\t\t\t\tOutlineModel._makeOutlineElement(childInfo, res);\n\t\t\t}\n\t\t}\n\t\tcontainer.children.set(res.id, res);\n\t}\n\n\treadonly id = 'root';\n\treadonly parent = undefined;\n\n\tprotected _groups = new Map();\n\tchildren = new Map();\n\n\tprotected constructor(readonly uri: URI) {\n\t\tsuper();\n\n\t\tthis.id = 'root';\n\t\tthis.parent = undefined;\n\t}\n\n\tprivate _compact(): this {\n\t\tlet count = 0;\n\t\tfor (const [key, group] of this._groups) {\n\t\t\tif (group.children.size === 0) { // empty\n\t\t\t\tthis._groups.delete(key);\n\t\t\t} else {\n\t\t\t\tcount += 1;\n\t\t\t}\n\t\t}\n\t\tif (count !== 1) {\n\t\t\t//\n\t\t\tthis.children = this._groups;\n\t\t} else {\n\t\t\t// adopt all elements of the first group\n\t\t\tlet group = Iterable.first(this._groups.values())!;\n\t\t\tfor (let [, child] of group.children) {\n\t\t\t\tchild.parent = this;\n\t\t\t\tthis.children.set(child.id, child);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\tgetTopLevelSymbols(): DocumentSymbol[] {\n\t\tconst roots: DocumentSymbol[] = [];\n\t\tfor (const child of this.children.values()) {\n\t\t\tif (child instanceof OutlineElement) {\n\t\t\t\troots.push(child.symbol);\n\t\t\t} else {\n\t\t\t\troots.push(...Iterable.map(child.children.values(), child => child.symbol));\n\t\t\t}\n\t\t}\n\t\treturn roots.sort((a, b) => Range.compareRangesUsingStarts(a.range, b.range));\n\t}\n\n\tasListOfDocumentSymbols(): DocumentSymbol[] {\n\t\tconst roots = this.getTopLevelSymbols();\n\t\tconst bucket: DocumentSymbol[] = [];\n\t\tOutlineModel._flattenDocumentSymbols(bucket, roots, '');\n\t\treturn bucket.sort((a, b) =>\n\t\t\tPosition.compare(Range.getStartPosition(a.range), Range.getStartPosition(b.range)) || Position.compare(Range.getEndPosition(b.range), Range.getEndPosition(a.range))\n\t\t);\n\t}\n\n\tprivate static _flattenDocumentSymbols(bucket: DocumentSymbol[], entries: DocumentSymbol[], overrideContainerLabel: string): void {\n\t\tfor (const entry of entries) {\n\t\t\tbucket.push({\n\t\t\t\tkind: entry.kind,\n\t\t\t\ttags: entry.tags,\n\t\t\t\tname: entry.name,\n\t\t\t\tdetail: entry.detail,\n\t\t\t\tcontainerName: entry.containerName || overrideContainerLabel,\n\t\t\t\trange: entry.range,\n\t\t\t\tselectionRange: entry.selectionRange,\n\t\t\t\tchildren: undefined, // we flatten it...\n\t\t\t});\n\n\t\t\t// Recurse over children\n\t\t\tif (entry.children) {\n\t\t\t\tOutlineModel._flattenDocumentSymbols(bucket, entry.children, entry.name);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nexport const IOutlineModelService = createDecorator('IOutlineModelService');\n\nexport interface IOutlineModelService {\n\t_serviceBrand: undefined;\n\tgetOrCreate(model: ITextModel, token: CancellationToken): Promise;\n}\n\ninterface CacheEntry {\n\tversionId: number;\n\tprovider: DocumentSymbolProvider[];\n\n\tpromiseCnt: number;\n\tsource: CancellationTokenSource;\n\tpromise: Promise;\n\tmodel: OutlineModel | undefined;\n}\n\nexport class OutlineModelService implements IOutlineModelService {\n\n\tdeclare _serviceBrand: undefined;\n\n\tprivate readonly _disposables = new DisposableStore();\n\tprivate readonly _debounceInformation: IFeatureDebounceInformation;\n\tprivate readonly _cache = new LRUCache(10, 0.7);\n\n\tconstructor(\n\t\t@ILanguageFeatureDebounceService debounces: ILanguageFeatureDebounceService,\n\t\t@IModelService modelService: IModelService\n\t) {\n\t\tthis._debounceInformation = debounces.for(DocumentSymbolProviderRegistry, 'DocumentSymbols', { min: 350 });\n\n\t\t// don't cache outline models longer than their text model\n\t\tthis._disposables.add(modelService.onModelRemoved(textModel => {\n\t\t\tthis._cache.delete(textModel.id);\n\t\t}));\n\t}\n\n\tdispose(): void {\n\t\tthis._disposables.dispose();\n\t}\n\n\tasync getOrCreate(textModel: ITextModel, token: CancellationToken): Promise {\n\n\t\tconst provider = DocumentSymbolProviderRegistry.ordered(textModel);\n\n\t\tlet data = this._cache.get(textModel.id);\n\t\tif (!data || data.versionId !== textModel.getVersionId() || !equals(data.provider, provider)) {\n\t\t\tlet source = new CancellationTokenSource();\n\t\t\tdata = {\n\t\t\t\tversionId: textModel.getVersionId(),\n\t\t\t\tprovider,\n\t\t\t\tpromiseCnt: 0,\n\t\t\t\tsource,\n\t\t\t\tpromise: OutlineModel.create(textModel, source.token),\n\t\t\t\tmodel: undefined,\n\t\t\t};\n\t\t\tthis._cache.set(textModel.id, data);\n\n\t\t\tconst now = Date.now();\n\t\t\tdata.promise.then(outlineModel => {\n\t\t\t\tdata!.model = outlineModel;\n\t\t\t\tthis._debounceInformation.update(textModel, Date.now() - now);\n\t\t\t}).catch(_err => {\n\t\t\t\tthis._cache.delete(textModel.id);\n\t\t\t});\n\t\t}\n\n\t\tif (data.model) {\n\t\t\t// resolved -> return data\n\t\t\treturn data.model;\n\t\t}\n\n\t\t// increase usage counter\n\t\tdata.promiseCnt += 1;\n\n\t\tconst listener = token.onCancellationRequested(() => {\n\t\t\t// last -> cancel provider request, remove cached promise\n\t\t\tif (--data!.promiseCnt === 0) {\n\t\t\t\tdata!.source.cancel();\n\t\t\t\tthis._cache.delete(textModel.id);\n\t\t\t}\n\t\t});\n\n\t\ttry {\n\t\t\treturn await data.promise;\n\t\t} finally {\n\t\t\tlistener.dispose();\n\t\t}\n\t}\n}\n\nregisterSingleton(IOutlineModelService, OutlineModelService, true);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { assertType } from 'vs/base/common/types';\nimport { URI } from 'vs/base/common/uri';\nimport { ITextModelService } from 'vs/editor/common/services/resolverService';\nimport { IOutlineModelService } from 'vs/editor/contrib/documentSymbols/browser/outlineModel';\nimport { CommandsRegistry } from 'vs/platform/commands/common/commands';\n\nCommandsRegistry.registerCommand('_executeDocumentSymbolProvider', async function (accessor, ...args) {\n\tconst [resource] = args;\n\tassertType(URI.isUri(resource));\n\n\tconst outlineService = accessor.get(IOutlineModelService);\n\tconst modelService = accessor.get(ITextModelService);\n\n\tconst reference = await modelService.createModelReference(resource);\n\ttry {\n\t\treturn (await outlineService.getOrCreate(reference.object.textEditorModel, CancellationToken.None)).getTopLevelSymbols();\n\t} finally {\n\t\treference.dispose();\n\t}\n});\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { isSafari, isWebkitWebView } from 'vs/base/browser/browser';\nimport { $, addDisposableListener } from 'vs/base/browser/dom';\nimport { DeferredPromise } from 'vs/base/common/async';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';\nimport { ILayoutService } from 'vs/platform/layout/browser/layoutService';\nimport { ILogService } from 'vs/platform/log/common/log';\n\nexport class BrowserClipboardService extends Disposable implements IClipboardService {\n\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate readonly mapTextToType = new Map(); // unsupported in web (only in-memory)\n\n\tconstructor(\n\t\t@ILayoutService private readonly layoutService: ILayoutService,\n\t\t@ILogService private readonly logService: ILogService) {\n\t\tsuper();\n\t\tif (isSafari || isWebkitWebView) {\n\t\t\tthis.installWebKitWriteTextWorkaround();\n\t\t}\n\t}\n\n\tprivate webKitPendingClipboardWritePromise: DeferredPromise | undefined;\n\n\t// In Safari, it has the following note:\n\t//\n\t// \"The request to write to the clipboard must be triggered during a user gesture.\n\t// A call to clipboard.write or clipboard.writeText outside the scope of a user\n\t// gesture(such as \"click\" or \"touch\" event handlers) will result in the immediate\n\t// rejection of the promise returned by the API call.\"\n\t// From: https://webkit.org/blog/10855/async-clipboard-api/\n\t//\n\t// Since extensions run in a web worker, and handle gestures in an asynchronous way,\n\t// they are not classified by Safari as \"in response to a user gesture\" and will reject.\n\t//\n\t// This function sets up some handlers to work around that behavior.\n\tprivate installWebKitWriteTextWorkaround(): void {\n\t\tconst handler = () => {\n\t\t\tconst currentWritePromise = new DeferredPromise();\n\n\t\t\t// Cancel the previous promise since we just created a new one in response to this new event\n\t\t\tif (this.webKitPendingClipboardWritePromise && !this.webKitPendingClipboardWritePromise.isSettled) {\n\t\t\t\tthis.webKitPendingClipboardWritePromise.cancel();\n\t\t\t}\n\t\t\tthis.webKitPendingClipboardWritePromise = currentWritePromise;\n\n\t\t\t// The ctor of ClipboardItem allows you to pass in a promise that will resolve to a string.\n\t\t\t// This allows us to pass in a Promise that will either be cancelled by another event or\n\t\t\t// resolved with the contents of the first call to this.writeText.\n\t\t\t// see https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem/ClipboardItem#parameters\n\t\t\tnavigator.clipboard.write([new ClipboardItem({\n\t\t\t\t'text/plain': currentWritePromise.p,\n\t\t\t})]).catch(async err => {\n\t\t\t\tif (!(err instanceof Error) || err.name !== 'NotAllowedError' || !currentWritePromise.isRejected) {\n\t\t\t\t\tthis.logService.error(err);\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\tif (this.layoutService.hasContainer) {\n\t\t\tthis._register(addDisposableListener(this.layoutService.container, 'click', handler));\n\t\t\tthis._register(addDisposableListener(this.layoutService.container, 'keydown', handler));\n\t\t}\n\t}\n\n\tasync writeText(text: string, type?: string): Promise {\n\n\t\t// With type: only in-memory is supported\n\t\tif (type) {\n\t\t\tthis.mapTextToType.set(type, text);\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.webKitPendingClipboardWritePromise) {\n\t\t\t// For Safari, we complete this Promise which allows the call to `navigator.clipboard.write()`\n\t\t\t// above to resolve and successfully copy to the clipboard. If we let this continue, Safari\n\t\t\t// would throw an error because this call stack doesn't appear to originate from a user gesture.\n\t\t\treturn this.webKitPendingClipboardWritePromise.complete(text);\n\t\t}\n\n\t\t// Guard access to navigator.clipboard with try/catch\n\t\t// as we have seen DOMExceptions in certain browsers\n\t\t// due to security policies.\n\t\ttry {\n\t\t\treturn await navigator.clipboard.writeText(text);\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t}\n\n\t\t// Fallback to textarea and execCommand solution\n\n\t\tconst activeElement = document.activeElement;\n\n\t\tconst textArea: HTMLTextAreaElement = document.body.appendChild($('textarea', { 'aria-hidden': true }));\n\t\ttextArea.style.height = '1px';\n\t\ttextArea.style.width = '1px';\n\t\ttextArea.style.position = 'absolute';\n\n\t\ttextArea.value = text;\n\t\ttextArea.focus();\n\t\ttextArea.select();\n\n\t\tdocument.execCommand('copy');\n\n\t\tif (activeElement instanceof HTMLElement) {\n\t\t\tactiveElement.focus();\n\t\t}\n\n\t\tdocument.body.removeChild(textArea);\n\n\t\treturn;\n\t}\n\n\tasync readText(type?: string): Promise {\n\n\t\t// With type: only in-memory is supported\n\t\tif (type) {\n\t\t\treturn this.mapTextToType.get(type) || '';\n\t\t}\n\n\t\t// Guard access to navigator.clipboard with try/catch\n\t\t// as we have seen DOMExceptions in certain browsers\n\t\t// due to security policies.\n\t\ttry {\n\t\t\treturn await navigator.clipboard.readText();\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\n\t\t\treturn '';\n\t\t}\n\t}\n\n\tprivate findText = ''; // unsupported in web (only in-memory)\n\n\tasync readFindText(): Promise {\n\t\treturn this.findText;\n\t}\n\n\tasync writeFindText(text: string): Promise {\n\t\tthis.findText = text;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from 'vs/base/common/event';\nimport Severity from 'vs/base/common/severity';\nimport { URI } from 'vs/base/common/uri';\nimport { localize } from 'vs/nls';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport interface IMarkerService {\n\treadonly _serviceBrand: undefined;\n\n\tchangeOne(owner: string, resource: URI, markers: IMarkerData[]): void;\n\n\tremove(owner: string, resources: URI[]): void;\n\n\tread(filter?: { owner?: string; resource?: URI; severities?: number, take?: number; }): IMarker[];\n\n\treadonly onMarkerChanged: Event;\n}\n\n/**\n *\n */\nexport interface IRelatedInformation {\n\tresource: URI;\n\tmessage: string;\n\tstartLineNumber: number;\n\tstartColumn: number;\n\tendLineNumber: number;\n\tendColumn: number;\n}\n\nexport const enum MarkerTag {\n\tUnnecessary = 1,\n\tDeprecated = 2\n}\n\nexport enum MarkerSeverity {\n\tHint = 1,\n\tInfo = 2,\n\tWarning = 4,\n\tError = 8,\n}\n\nexport namespace MarkerSeverity {\n\n\texport function compare(a: MarkerSeverity, b: MarkerSeverity): number {\n\t\treturn b - a;\n\t}\n\n\tconst _displayStrings: { [value: number]: string; } = Object.create(null);\n\t_displayStrings[MarkerSeverity.Error] = localize('sev.error', \"Error\");\n\t_displayStrings[MarkerSeverity.Warning] = localize('sev.warning', \"Warning\");\n\t_displayStrings[MarkerSeverity.Info] = localize('sev.info', \"Info\");\n\n\texport function toString(a: MarkerSeverity): string {\n\t\treturn _displayStrings[a] || '';\n\t}\n\n\texport function fromSeverity(severity: Severity): MarkerSeverity {\n\t\tswitch (severity) {\n\t\t\tcase Severity.Error: return MarkerSeverity.Error;\n\t\t\tcase Severity.Warning: return MarkerSeverity.Warning;\n\t\t\tcase Severity.Info: return MarkerSeverity.Info;\n\t\t\tcase Severity.Ignore: return MarkerSeverity.Hint;\n\t\t}\n\t}\n\n\texport function toSeverity(severity: MarkerSeverity): Severity {\n\t\tswitch (severity) {\n\t\t\tcase MarkerSeverity.Error: return Severity.Error;\n\t\t\tcase MarkerSeverity.Warning: return Severity.Warning;\n\t\t\tcase MarkerSeverity.Info: return Severity.Info;\n\t\t\tcase MarkerSeverity.Hint: return Severity.Ignore;\n\t\t}\n\t}\n}\n\n/**\n * A structure defining a problem/warning/etc.\n */\nexport interface IMarkerData {\n\tcode?: string | { value: string; target: URI };\n\tseverity: MarkerSeverity;\n\tmessage: string;\n\tsource?: string;\n\tstartLineNumber: number;\n\tstartColumn: number;\n\tendLineNumber: number;\n\tendColumn: number;\n\trelatedInformation?: IRelatedInformation[];\n\ttags?: MarkerTag[];\n}\n\nexport interface IMarker {\n\towner: string;\n\tresource: URI;\n\tseverity: MarkerSeverity;\n\tcode?: string | { value: string; target: URI };\n\tmessage: string;\n\tsource?: string;\n\tstartLineNumber: number;\n\tstartColumn: number;\n\tendLineNumber: number;\n\tendColumn: number;\n\trelatedInformation?: IRelatedInformation[];\n\ttags?: MarkerTag[];\n}\n\nexport interface MarkerStatistics {\n\terrors: number;\n\twarnings: number;\n\tinfos: number;\n\tunknowns: number;\n}\n\nexport namespace IMarkerData {\n\tconst emptyString = '';\n\texport function makeKey(markerData: IMarkerData): string {\n\t\treturn makeKeyOptionalMessage(markerData, true);\n\t}\n\n\texport function makeKeyOptionalMessage(markerData: IMarkerData, useMessage: boolean): string {\n\t\tlet result: string[] = [emptyString];\n\t\tif (markerData.source) {\n\t\t\tresult.push(markerData.source.replace('¦', '\\\\¦'));\n\t\t} else {\n\t\t\tresult.push(emptyString);\n\t\t}\n\t\tif (markerData.code) {\n\t\t\tif (typeof markerData.code === 'string') {\n\t\t\t\tresult.push(markerData.code.replace('¦', '\\\\¦'));\n\t\t\t} else {\n\t\t\t\tresult.push(markerData.code.value.replace('¦', '\\\\¦'));\n\t\t\t}\n\t\t} else {\n\t\t\tresult.push(emptyString);\n\t\t}\n\t\tif (markerData.severity !== undefined && markerData.severity !== null) {\n\t\t\tresult.push(MarkerSeverity.toString(markerData.severity));\n\t\t} else {\n\t\t\tresult.push(emptyString);\n\t\t}\n\n\t\t// Modifed to not include the message as part of the marker key to work around\n\t\t// https://github.com/microsoft/vscode/issues/77475\n\t\tif (markerData.message && useMessage) {\n\t\t\tresult.push(markerData.message.replace('¦', '\\\\¦'));\n\t\t} else {\n\t\t\tresult.push(emptyString);\n\t\t}\n\t\tif (markerData.startLineNumber !== undefined && markerData.startLineNumber !== null) {\n\t\t\tresult.push(markerData.startLineNumber.toString());\n\t\t} else {\n\t\t\tresult.push(emptyString);\n\t\t}\n\t\tif (markerData.startColumn !== undefined && markerData.startColumn !== null) {\n\t\t\tresult.push(markerData.startColumn.toString());\n\t\t} else {\n\t\t\tresult.push(emptyString);\n\t\t}\n\t\tif (markerData.endLineNumber !== undefined && markerData.endLineNumber !== null) {\n\t\t\tresult.push(markerData.endLineNumber.toString());\n\t\t} else {\n\t\t\tresult.push(emptyString);\n\t\t}\n\t\tif (markerData.endColumn !== undefined && markerData.endColumn !== null) {\n\t\t\tresult.push(markerData.endColumn.toString());\n\t\t} else {\n\t\t\tresult.push(emptyString);\n\t\t}\n\t\tresult.push(emptyString);\n\t\treturn result.join('¦');\n\t}\n}\n\nexport const IMarkerService = createDecorator('markerService');\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { binarySearch } from 'vs/base/common/arrays';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\nimport { LinkedList } from 'vs/base/common/linkedList';\nimport { compare } from 'vs/base/common/strings';\nimport { URI } from 'vs/base/common/uri';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range } from 'vs/editor/common/core/range';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { registerSingleton } from 'vs/platform/instantiation/common/extensions';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { IMarker, IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers';\nimport { IConfigurationService } from 'vs/platform/configuration/common/configuration';\n\nexport class MarkerCoordinate {\n\tconstructor(\n\t\treadonly marker: IMarker,\n\t\treadonly index: number,\n\t\treadonly total: number\n\t) { }\n}\n\nexport class MarkerList {\n\n\tprivate readonly _onDidChange = new Emitter();\n\treadonly onDidChange: Event = this._onDidChange.event;\n\n\tprivate readonly _resourceFilter?: (uri: URI) => boolean;\n\tprivate readonly _dispoables = new DisposableStore();\n\n\tprivate _markers: IMarker[] = [];\n\tprivate _nextIdx: number = -1;\n\n\tconstructor(\n\t\tresourceFilter: URI | ((uri: URI) => boolean) | undefined,\n\t\t@IMarkerService private readonly _markerService: IMarkerService,\n\t\t@IConfigurationService private readonly _configService: IConfigurationService,\n\t) {\n\t\tif (URI.isUri(resourceFilter)) {\n\t\t\tthis._resourceFilter = uri => uri.toString() === resourceFilter.toString();\n\t\t} else if (resourceFilter) {\n\t\t\tthis._resourceFilter = resourceFilter;\n\t\t}\n\n\t\tconst compareOrder = this._configService.getValue('problems.sortOrder');\n\t\tconst compareMarker = (a: IMarker, b: IMarker): number => {\n\t\t\tlet res = compare(a.resource.toString(), b.resource.toString());\n\t\t\tif (compareOrder === 'position') {\n\t\t\t\tres = Range.compareRangesUsingStarts(a, b) || MarkerSeverity.compare(a.severity, b.severity);\n\t\t\t} else {\n\t\t\t\tres = MarkerSeverity.compare(a.severity, b.severity) || Range.compareRangesUsingStarts(a, b);\n\t\t\t}\n\t\t\treturn res;\n\t\t};\n\n\t\tconst updateMarker = () => {\n\t\t\tthis._markers = this._markerService.read({\n\t\t\t\tresource: URI.isUri(resourceFilter) ? resourceFilter : undefined,\n\t\t\t\tseverities: MarkerSeverity.Error | MarkerSeverity.Warning | MarkerSeverity.Info\n\t\t\t});\n\t\t\tif (typeof resourceFilter === 'function') {\n\t\t\t\tthis._markers = this._markers.filter(m => this._resourceFilter!(m.resource));\n\t\t\t}\n\t\t\tthis._markers.sort(compareMarker);\n\t\t};\n\n\t\tupdateMarker();\n\n\t\tthis._dispoables.add(_markerService.onMarkerChanged(uris => {\n\t\t\tif (!this._resourceFilter || uris.some(uri => this._resourceFilter!(uri))) {\n\t\t\t\tupdateMarker();\n\t\t\t\tthis._nextIdx = -1;\n\t\t\t\tthis._onDidChange.fire();\n\t\t\t}\n\t\t}));\n\t}\n\n\tdispose(): void {\n\t\tthis._dispoables.dispose();\n\t\tthis._onDidChange.dispose();\n\t}\n\n\tmatches(uri: URI | undefined) {\n\t\tif (!this._resourceFilter && !uri) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!this._resourceFilter || !uri) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this._resourceFilter(uri);\n\t}\n\n\tget selected(): MarkerCoordinate | undefined {\n\t\tconst marker = this._markers[this._nextIdx];\n\t\treturn marker && new MarkerCoordinate(marker, this._nextIdx + 1, this._markers.length);\n\t}\n\n\tprivate _initIdx(model: ITextModel, position: Position, fwd: boolean): void {\n\t\tlet found = false;\n\n\t\tlet idx = this._markers.findIndex(marker => marker.resource.toString() === model.uri.toString());\n\t\tif (idx < 0) {\n\t\t\tidx = binarySearch(this._markers, { resource: model.uri }, (a, b) => compare(a.resource.toString(), b.resource.toString()));\n\t\t\tif (idx < 0) {\n\t\t\t\tidx = ~idx;\n\t\t\t}\n\t\t}\n\n\t\tfor (let i = idx; i < this._markers.length; i++) {\n\t\t\tlet range = Range.lift(this._markers[i]);\n\n\t\t\tif (range.isEmpty()) {\n\t\t\t\tconst word = model.getWordAtPosition(range.getStartPosition());\n\t\t\t\tif (word) {\n\t\t\t\t\trange = new Range(range.startLineNumber, word.startColumn, range.startLineNumber, word.endColumn);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (position && (range.containsPosition(position) || position.isBeforeOrEqual(range.getStartPosition()))) {\n\t\t\t\tthis._nextIdx = i;\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (this._markers[i].resource.toString() !== model.uri.toString()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!found) {\n\t\t\t// after the last change\n\t\t\tthis._nextIdx = fwd ? 0 : this._markers.length - 1;\n\t\t}\n\t\tif (this._nextIdx < 0) {\n\t\t\tthis._nextIdx = this._markers.length - 1;\n\t\t}\n\t}\n\n\tresetIndex() {\n\t\tthis._nextIdx = -1;\n\t}\n\n\tmove(fwd: boolean, model: ITextModel, position: Position): boolean {\n\t\tif (this._markers.length === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet oldIdx = this._nextIdx;\n\t\tif (this._nextIdx === -1) {\n\t\t\tthis._initIdx(model, position, fwd);\n\t\t} else if (fwd) {\n\t\t\tthis._nextIdx = (this._nextIdx + 1) % this._markers.length;\n\t\t} else if (!fwd) {\n\t\t\tthis._nextIdx = (this._nextIdx - 1 + this._markers.length) % this._markers.length;\n\t\t}\n\n\t\tif (oldIdx !== this._nextIdx) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tfind(uri: URI, position: Position): MarkerCoordinate | undefined {\n\t\tlet idx = this._markers.findIndex(marker => marker.resource.toString() === uri.toString());\n\t\tif (idx < 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tfor (; idx < this._markers.length; idx++) {\n\t\t\tif (Range.containsPosition(this._markers[idx], position)) {\n\t\t\t\treturn new MarkerCoordinate(this._markers[idx], idx + 1, this._markers.length);\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n}\n\nexport const IMarkerNavigationService = createDecorator('IMarkerNavigationService');\n\nexport interface IMarkerNavigationService {\n\treadonly _serviceBrand: undefined;\n\tgetMarkerList(resource: URI | undefined): MarkerList;\n}\n\nexport interface IMarkerListProvider {\n\tgetMarkerList(resource: URI | undefined): MarkerList | undefined;\n}\n\nclass MarkerNavigationService implements IMarkerNavigationService, IMarkerListProvider {\n\n\treadonly _serviceBrand: undefined;\n\n\tprivate readonly _provider = new LinkedList();\n\n\tconstructor(\n\t\t@IMarkerService private readonly _markerService: IMarkerService,\n\t\t@IConfigurationService private readonly _configService: IConfigurationService,\n\t) { }\n\n\tgetMarkerList(resource: URI | undefined): MarkerList {\n\t\tfor (let provider of this._provider) {\n\t\t\tconst result = provider.getMarkerList(resource);\n\t\t\tif (result) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\t// default\n\t\treturn new MarkerList(resource, this._markerService, this._configService);\n\t}\n}\n\nregisterSingleton(IMarkerNavigationService, MarkerNavigationService, true);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { isFalsyOrEmpty } from 'vs/base/common/arrays';\nimport { DebounceEmitter } from 'vs/base/common/event';\nimport { Iterable } from 'vs/base/common/iterator';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { ResourceMap } from 'vs/base/common/map';\nimport { Schemas } from 'vs/base/common/network';\nimport { URI } from 'vs/base/common/uri';\nimport { IMarker, IMarkerData, IMarkerService, MarkerSeverity, MarkerStatistics } from './markers';\n\nclass DoubleResourceMap{\n\n\tprivate _byResource = new ResourceMap>();\n\tprivate _byOwner = new Map>();\n\n\tset(resource: URI, owner: string, value: V) {\n\t\tlet ownerMap = this._byResource.get(resource);\n\t\tif (!ownerMap) {\n\t\t\townerMap = new Map();\n\t\t\tthis._byResource.set(resource, ownerMap);\n\t\t}\n\t\townerMap.set(owner, value);\n\n\t\tlet resourceMap = this._byOwner.get(owner);\n\t\tif (!resourceMap) {\n\t\t\tresourceMap = new ResourceMap();\n\t\t\tthis._byOwner.set(owner, resourceMap);\n\t\t}\n\t\tresourceMap.set(resource, value);\n\t}\n\n\tget(resource: URI, owner: string): V | undefined {\n\t\tlet ownerMap = this._byResource.get(resource);\n\t\treturn ownerMap?.get(owner);\n\t}\n\n\tdelete(resource: URI, owner: string): boolean {\n\t\tlet removedA = false;\n\t\tlet removedB = false;\n\t\tlet ownerMap = this._byResource.get(resource);\n\t\tif (ownerMap) {\n\t\t\tremovedA = ownerMap.delete(owner);\n\t\t}\n\t\tlet resourceMap = this._byOwner.get(owner);\n\t\tif (resourceMap) {\n\t\t\tremovedB = resourceMap.delete(resource);\n\t\t}\n\t\tif (removedA !== removedB) {\n\t\t\tthrow new Error('illegal state');\n\t\t}\n\t\treturn removedA && removedB;\n\t}\n\n\tvalues(key?: URI | string): Iterable {\n\t\tif (typeof key === 'string') {\n\t\t\treturn this._byOwner.get(key)?.values() ?? Iterable.empty();\n\t\t}\n\t\tif (URI.isUri(key)) {\n\t\t\treturn this._byResource.get(key)?.values() ?? Iterable.empty();\n\t\t}\n\n\t\treturn Iterable.map(Iterable.concat(...this._byOwner.values()), map => map[1]);\n\t}\n}\n\nclass MarkerStats implements MarkerStatistics {\n\n\terrors: number = 0;\n\tinfos: number = 0;\n\twarnings: number = 0;\n\tunknowns: number = 0;\n\n\tprivate readonly _data = new ResourceMap();\n\tprivate readonly _service: IMarkerService;\n\tprivate readonly _subscription: IDisposable;\n\n\tconstructor(service: IMarkerService) {\n\t\tthis._service = service;\n\t\tthis._subscription = service.onMarkerChanged(this._update, this);\n\t}\n\n\tdispose(): void {\n\t\tthis._subscription.dispose();\n\t}\n\n\tprivate _update(resources: readonly URI[]): void {\n\t\tfor (const resource of resources) {\n\t\t\tconst oldStats = this._data.get(resource);\n\t\t\tif (oldStats) {\n\t\t\t\tthis._substract(oldStats);\n\t\t\t}\n\t\t\tconst newStats = this._resourceStats(resource);\n\t\t\tthis._add(newStats);\n\t\t\tthis._data.set(resource, newStats);\n\t\t}\n\t}\n\n\tprivate _resourceStats(resource: URI): MarkerStatistics {\n\t\tconst result: MarkerStatistics = { errors: 0, warnings: 0, infos: 0, unknowns: 0 };\n\n\t\t// TODO this is a hack\n\t\tif (resource.scheme === Schemas.inMemory || resource.scheme === Schemas.walkThrough || resource.scheme === Schemas.walkThroughSnippet) {\n\t\t\treturn result;\n\t\t}\n\n\t\tfor (const { severity } of this._service.read({ resource })) {\n\t\t\tif (severity === MarkerSeverity.Error) {\n\t\t\t\tresult.errors += 1;\n\t\t\t} else if (severity === MarkerSeverity.Warning) {\n\t\t\t\tresult.warnings += 1;\n\t\t\t} else if (severity === MarkerSeverity.Info) {\n\t\t\t\tresult.infos += 1;\n\t\t\t} else {\n\t\t\t\tresult.unknowns += 1;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate _substract(op: MarkerStatistics) {\n\t\tthis.errors -= op.errors;\n\t\tthis.warnings -= op.warnings;\n\t\tthis.infos -= op.infos;\n\t\tthis.unknowns -= op.unknowns;\n\t}\n\n\tprivate _add(op: MarkerStatistics) {\n\t\tthis.errors += op.errors;\n\t\tthis.warnings += op.warnings;\n\t\tthis.infos += op.infos;\n\t\tthis.unknowns += op.unknowns;\n\t}\n}\n\nexport class MarkerService implements IMarkerService {\n\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate readonly _onMarkerChanged = new DebounceEmitter({\n\t\tdelay: 0,\n\t\tmerge: MarkerService._merge\n\t});\n\n\treadonly onMarkerChanged = this._onMarkerChanged.event;\n\n\tprivate readonly _data = new DoubleResourceMap();\n\tprivate readonly _stats = new MarkerStats(this);\n\n\tdispose(): void {\n\t\tthis._stats.dispose();\n\t\tthis._onMarkerChanged.dispose();\n\t}\n\n\tremove(owner: string, resources: URI[]): void {\n\t\tfor (const resource of resources || []) {\n\t\t\tthis.changeOne(owner, resource, []);\n\t\t}\n\t}\n\n\tchangeOne(owner: string, resource: URI, markerData: IMarkerData[]): void {\n\n\t\tif (isFalsyOrEmpty(markerData)) {\n\t\t\t// remove marker for this (owner,resource)-tuple\n\t\t\tconst removed = this._data.delete(resource, owner);\n\t\t\tif (removed) {\n\t\t\t\tthis._onMarkerChanged.fire([resource]);\n\t\t\t}\n\n\t\t} else {\n\t\t\t// insert marker for this (owner,resource)-tuple\n\t\t\tconst markers: IMarker[] = [];\n\t\t\tfor (const data of markerData) {\n\t\t\t\tconst marker = MarkerService._toMarker(owner, resource, data);\n\t\t\t\tif (marker) {\n\t\t\t\t\tmarkers.push(marker);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._data.set(resource, owner, markers);\n\t\t\tthis._onMarkerChanged.fire([resource]);\n\t\t}\n\t}\n\n\tprivate static _toMarker(owner: string, resource: URI, data: IMarkerData): IMarker | undefined {\n\t\tlet {\n\t\t\tcode, severity,\n\t\t\tmessage, source,\n\t\t\tstartLineNumber, startColumn, endLineNumber, endColumn,\n\t\t\trelatedInformation,\n\t\t\ttags,\n\t\t} = data;\n\n\t\tif (!message) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// santize data\n\t\tstartLineNumber = startLineNumber > 0 ? startLineNumber : 1;\n\t\tstartColumn = startColumn > 0 ? startColumn : 1;\n\t\tendLineNumber = endLineNumber >= startLineNumber ? endLineNumber : startLineNumber;\n\t\tendColumn = endColumn > 0 ? endColumn : startColumn;\n\n\t\treturn {\n\t\t\tresource,\n\t\t\towner,\n\t\t\tcode,\n\t\t\tseverity,\n\t\t\tmessage,\n\t\t\tsource,\n\t\t\tstartLineNumber,\n\t\t\tstartColumn,\n\t\t\tendLineNumber,\n\t\t\tendColumn,\n\t\t\trelatedInformation,\n\t\t\ttags,\n\t\t};\n\t}\n\n\tread(filter: { owner?: string; resource?: URI; severities?: number, take?: number; } = Object.create(null)): IMarker[] {\n\n\t\tlet { owner, resource, severities, take } = filter;\n\n\t\tif (!take || take < 0) {\n\t\t\ttake = -1;\n\t\t}\n\n\t\tif (owner && resource) {\n\t\t\t// exactly one owner AND resource\n\t\t\tconst data = this._data.get(resource, owner);\n\t\t\tif (!data) {\n\t\t\t\treturn [];\n\t\t\t} else {\n\t\t\t\tconst result: IMarker[] = [];\n\t\t\t\tfor (const marker of data) {\n\t\t\t\t\tif (MarkerService._accept(marker, severities)) {\n\t\t\t\t\t\tconst newLen = result.push(marker);\n\t\t\t\t\t\tif (take > 0 && newLen === take) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t} else if (!owner && !resource) {\n\t\t\t// all\n\t\t\tconst result: IMarker[] = [];\n\t\t\tfor (let markers of this._data.values()) {\n\t\t\t\tfor (let data of markers) {\n\t\t\t\t\tif (MarkerService._accept(data, severities)) {\n\t\t\t\t\t\tconst newLen = result.push(data);\n\t\t\t\t\t\tif (take > 0 && newLen === take) {\n\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\n\t\t} else {\n\t\t\t// of one resource OR owner\n\t\t\tconst iterable = this._data.values(resource ?? owner!);\n\t\t\tconst result: IMarker[] = [];\n\t\t\tfor (const markers of iterable) {\n\t\t\t\tfor (const data of markers) {\n\t\t\t\t\tif (MarkerService._accept(data, severities)) {\n\t\t\t\t\t\tconst newLen = result.push(data);\n\t\t\t\t\t\tif (take > 0 && newLen === take) {\n\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tprivate static _accept(marker: IMarker, severities?: number): boolean {\n\t\treturn severities === undefined || (severities & marker.severity) === marker.severity;\n\t}\n\n\t// --- event debounce logic\n\n\tprivate static _merge(all: (readonly URI[])[]): URI[] {\n\t\tconst set = new ResourceMap();\n\t\tfor (let array of all) {\n\t\t\tfor (let item of array) {\n\t\t\t\tset.set(item, true);\n\t\t\t}\n\t\t}\n\t\treturn Array.from(set.keys());\n\t}\n}\n","\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport BaseSeverity from 'vs/base/common/severity';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport import Severity = BaseSeverity;\n\nexport const INotificationService = createDecorator('notificationService');\n\nexport type NotificationMessage = string | Error;\n\nexport interface INotificationProperties {\n\n\t/**\n\t * Sticky notifications are not automatically removed after a certain timeout. By\n\t * default, notifications with primary actions and severity error are always sticky.\n\t */\n\treadonly sticky?: boolean;\n}\n\nexport interface INotification extends INotificationProperties {\n\n\t/**\n\t * The severity of the notification. Either `Info`, `Warning` or `Error`.\n\t */\n\treadonly severity: Severity;\n\n\t/**\n\t * The message of the notification. This can either be a `string` or `Error`. Messages\n\t * can optionally include links in the format: `[text](link)`\n\t */\n\treadonly message: NotificationMessage;\n\n\t/**\n\t * The source of the notification appears as additional information.\n\t */\n\treadonly source?: string | { label: string; id: string; };\n}\n\nexport interface INotificationHandle {\n}\n\nexport interface IStatusMessageOptions {\n\n\t/**\n\t * An optional timeout after which the status message is to be hidden. By default\n\t * the status message will not hide until another status message is displayed.\n\t */\n\treadonly hideAfter?: number;\n}\n\n/**\n * A service to bring up notifications and non-modal prompts.\n *\n * Note: use the `IDialogService` for a modal way to ask the user for input.\n */\nexport interface INotificationService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Show the provided notification to the user. The returned `INotificationHandle`\n\t * can be used to control the notification afterwards.\n\t *\n\t * **Note:** If your intent is to show a message with actions to the user, consider\n\t * the `INotificationService.prompt()` method instead which are optimized for\n\t * this usecase and much easier to use!\n\t *\n\t * @returns a handle on the notification to e.g. hide it or update message, buttons, etc.\n\t */\n\tnotify(notification: INotification): INotificationHandle;\n\n\t/**\n\t * A convenient way of reporting infos. Use the `INotificationService.notify`\n\t * method if you need more control over the notification.\n\t */\n\tinfo(message: NotificationMessage | NotificationMessage[]): void;\n\n\t/**\n\t * A convenient way of reporting warnings. Use the `INotificationService.notify`\n\t * method if you need more control over the notification.\n\t */\n\twarn(message: NotificationMessage | NotificationMessage[]): void;\n\n\t/**\n\t * A convenient way of reporting errors. Use the `INotificationService.notify`\n\t * method if you need more control over the notification.\n\t */\n\terror(message: NotificationMessage | NotificationMessage[]): void;\n\n\t/**\n\t * Shows a status message in the status area with the provided text.\n\t *\n\t * @param message the message to show as status\n\t * @param options provides some optional configuration options\n\t *\n\t * @returns a disposable to hide the status message\n\t */\n\tstatus(message: NotificationMessage, options?: IStatusMessageOptions): IDisposable;\n}\n\nexport class NoOpNotification implements INotificationHandle {\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport { equalsIgnoreCase, startsWithIgnoreCase } from 'vs/base/common/strings';\nimport { URI } from 'vs/base/common/uri';\nimport { IEditorOptions } from 'vs/platform/editor/common/editor';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport const IOpenerService = createDecorator('openerService');\n\nexport type OpenInternalOptions = {\n\n\t/**\n\t * Signals that the intent is to open an editor to the side\n\t * of the currently active editor.\n\t */\n\treadonly openToSide?: boolean;\n\n\t/**\n\t * Extra editor options to apply in case an editor is used to open.\n\t */\n\treadonly editorOptions?: IEditorOptions;\n\n\t/**\n\t * Signals that the editor to open was triggered through a user\n\t * action, such as keyboard or mouse usage.\n\t */\n\treadonly fromUserGesture?: boolean;\n\n\t/**\n\t * Allow command links to be handled.\n\t */\n\treadonly allowCommands?: boolean;\n};\n\nexport type OpenExternalOptions = {\n\treadonly openExternal?: boolean;\n\treadonly allowTunneling?: boolean;\n\treadonly allowContributedOpeners?: boolean | string;\n};\n\nexport type OpenOptions = OpenInternalOptions & OpenExternalOptions;\n\nexport type ResolveExternalUriOptions = { readonly allowTunneling?: boolean };\n\nexport interface IResolvedExternalUri extends IDisposable {\n\tresolved: URI;\n}\n\nexport interface IOpener {\n\topen(resource: URI | string, options?: OpenInternalOptions | OpenExternalOptions): Promise;\n}\n\nexport interface IExternalOpener {\n\topenExternal(href: string, ctx: { sourceUri: URI, preferredOpenerId?: string }, token: CancellationToken): Promise;\n\tdispose?(): void;\n}\n\nexport interface IValidator {\n\tshouldOpen(resource: URI | string): Promise;\n}\n\nexport interface IExternalUriResolver {\n\tresolveExternalUri(resource: URI, options?: OpenOptions): Promise<{ resolved: URI, dispose(): void } | undefined>;\n}\n\nexport interface IOpenerService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Register a participant that can handle the open() call.\n\t */\n\tregisterOpener(opener: IOpener): IDisposable;\n\n\t/**\n\t * Register a participant that can validate if the URI resource be opened.\n\t * Validators are run before openers.\n\t */\n\tregisterValidator(validator: IValidator): IDisposable;\n\n\t/**\n\t * Register a participant that can resolve an external URI resource to be opened.\n\t */\n\tregisterExternalUriResolver(resolver: IExternalUriResolver): IDisposable;\n\n\t/**\n\t * Sets the handler for opening externally. If not provided,\n\t * a default handler will be used.\n\t */\n\tsetDefaultExternalOpener(opener: IExternalOpener): void;\n\n\t/**\n\t * Registers a new opener external resources openers.\n\t */\n\tregisterExternalOpener(opener: IExternalOpener): IDisposable;\n\n\t/**\n\t * Opens a resource, like a webaddress, a document uri, or executes command.\n\t *\n\t * @param resource A resource\n\t * @return A promise that resolves when the opening is done.\n\t */\n\topen(resource: URI | string, options?: OpenInternalOptions | OpenExternalOptions): Promise;\n\n\t/**\n\t * Resolve a resource to its external form.\n\t * @throws whenever resolvers couldn't resolve this resource externally.\n\t */\n\tresolveExternalUri(resource: URI, options?: ResolveExternalUriOptions): Promise;\n}\n\nexport const NullOpenerService = Object.freeze({\n\t_serviceBrand: undefined,\n\tregisterOpener() { return Disposable.None; },\n\tregisterValidator() { return Disposable.None; },\n\tregisterExternalUriResolver() { return Disposable.None; },\n\tsetDefaultExternalOpener() { },\n\tregisterExternalOpener() { return Disposable.None; },\n\tasync open() { return false; },\n\tasync resolveExternalUri(uri: URI) { return { resolved: uri, dispose() { } }; },\n} as IOpenerService);\n\nexport function matchesScheme(target: URI | string, scheme: string): boolean {\n\tif (URI.isUri(target)) {\n\t\treturn equalsIgnoreCase(target.scheme, scheme);\n\t} else {\n\t\treturn startsWithIgnoreCase(target, scheme + ':');\n\t}\n}\n\nexport function matchesSomeScheme(target: URI | string, ...schemes: string[]): boolean {\n\treturn schemes.some(scheme => matchesScheme(target, scheme));\n}\n\nexport function selectionFragment(target: URI): { startLineNumber: number; startColumn: number; } | undefined {\n\tlet selection: { startLineNumber: number; startColumn: number; } | undefined = undefined;\n\tconst match = /^L?(\\d+)(?:,(\\d+))?/.exec(target.fragment);\n\tif (match) {\n\t\t// support file:///some/file.js#73,84\n\t\t// support file:///some/file.js#L73\n\t\tselection = {\n\t\t\tstartLineNumber: parseInt(match[1]),\n\t\t\tstartColumn: match[2] ? parseInt(match[2]) : 1\n\t\t};\n\t}\n\treturn selection;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { LinkedList } from 'vs/base/common/linkedList';\nimport { ResourceMap } from 'vs/base/common/map';\nimport { parse } from 'vs/base/common/marshalling';\nimport { Schemas } from 'vs/base/common/network';\nimport { normalizePath } from 'vs/base/common/resources';\nimport { URI } from 'vs/base/common/uri';\nimport { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';\nimport { ICommandService } from 'vs/platform/commands/common/commands';\nimport { EditorOpenContext } from 'vs/platform/editor/common/editor';\nimport { IExternalOpener, IExternalUriResolver, IOpener, IOpenerService, IResolvedExternalUri, IValidator, matchesScheme, matchesSomeScheme, OpenOptions, ResolveExternalUriOptions, selectionFragment } from 'vs/platform/opener/common/opener';\n\nclass CommandOpener implements IOpener {\n\n\tconstructor(@ICommandService private readonly _commandService: ICommandService) { }\n\n\tasync open(target: URI | string, options?: OpenOptions): Promise {\n\t\tif (!matchesScheme(target, Schemas.command)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!options?.allowCommands) {\n\t\t\t// silently ignore commands when command-links are disabled, also\n\t\t\t// surpress other openers by returning TRUE\n\t\t\treturn true;\n\t\t}\n\t\t// run command or bail out if command isn't known\n\t\tif (typeof target === 'string') {\n\t\t\ttarget = URI.parse(target);\n\t\t}\n\t\t// execute as command\n\t\tlet args: any = [];\n\t\ttry {\n\t\t\targs = parse(decodeURIComponent(target.query));\n\t\t} catch {\n\t\t\t// ignore and retry\n\t\t\ttry {\n\t\t\t\targs = parse(target.query);\n\t\t\t} catch {\n\t\t\t\t// ignore error\n\t\t\t}\n\t\t}\n\t\tif (!Array.isArray(args)) {\n\t\t\targs = [args];\n\t\t}\n\t\tawait this._commandService.executeCommand(target.path, ...args);\n\t\treturn true;\n\t}\n}\n\nclass EditorOpener implements IOpener {\n\n\tconstructor(@ICodeEditorService private readonly _editorService: ICodeEditorService) { }\n\n\tasync open(target: URI | string, options: OpenOptions) {\n\t\tif (typeof target === 'string') {\n\t\t\ttarget = URI.parse(target);\n\t\t}\n\t\tconst selection: { startLineNumber: number; startColumn: number; } | undefined = selectionFragment(target);\n\t\tif (selection) {\n\t\t\ttarget = target.with({ fragment: '' });\n\t\t}\n\n\t\tif (target.scheme === Schemas.file) {\n\t\t\ttarget = normalizePath(target); // workaround for non-normalized paths (https://github.com/microsoft/vscode/issues/12954)\n\t\t}\n\n\t\tawait this._editorService.openCodeEditor(\n\t\t\t{\n\t\t\t\tresource: target,\n\t\t\t\toptions: {\n\t\t\t\t\tselection,\n\t\t\t\t\tcontext: options?.fromUserGesture ? EditorOpenContext.USER : EditorOpenContext.API,\n\t\t\t\t\t...options?.editorOptions\n\t\t\t\t}\n\t\t\t},\n\t\t\tthis._editorService.getFocusedCodeEditor(),\n\t\t\toptions?.openToSide\n\t\t);\n\n\t\treturn true;\n\t}\n}\n\nexport class OpenerService implements IOpenerService {\n\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate readonly _openers = new LinkedList();\n\tprivate readonly _validators = new LinkedList();\n\tprivate readonly _resolvers = new LinkedList();\n\tprivate readonly _resolvedUriTargets = new ResourceMap(uri => uri.with({ path: null, fragment: null, query: null }).toString());\n\n\tprivate _defaultExternalOpener: IExternalOpener;\n\tprivate readonly _externalOpeners = new LinkedList();\n\n\tconstructor(\n\t\t@ICodeEditorService editorService: ICodeEditorService,\n\t\t@ICommandService commandService: ICommandService\n\t) {\n\t\t// Default external opener is going through window.open()\n\t\tthis._defaultExternalOpener = {\n\t\t\topenExternal: async href => {\n\t\t\t\t// ensure to open HTTP/HTTPS links into new windows\n\t\t\t\t// to not trigger a navigation. Any other link is\n\t\t\t\t// safe to be set as HREF to prevent a blank window\n\t\t\t\t// from opening.\n\t\t\t\tif (matchesSomeScheme(href, Schemas.http, Schemas.https)) {\n\t\t\t\t\tdom.windowOpenNoOpener(href);\n\t\t\t\t} else {\n\t\t\t\t\twindow.location.href = href;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t};\n\n\t\t// Default opener: any external, maito, http(s), command, and catch-all-editors\n\t\tthis._openers.push({\n\t\t\topen: async (target: URI | string, options?: OpenOptions) => {\n\t\t\t\tif (options?.openExternal || matchesSomeScheme(target, Schemas.mailto, Schemas.http, Schemas.https, Schemas.vsls)) {\n\t\t\t\t\t// open externally\n\t\t\t\t\tawait this._doOpenExternal(target, options);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tthis._openers.push(new CommandOpener(commandService));\n\t\tthis._openers.push(new EditorOpener(editorService));\n\t}\n\n\tregisterOpener(opener: IOpener): IDisposable {\n\t\tconst remove = this._openers.unshift(opener);\n\t\treturn { dispose: remove };\n\t}\n\n\tregisterValidator(validator: IValidator): IDisposable {\n\t\tconst remove = this._validators.push(validator);\n\t\treturn { dispose: remove };\n\t}\n\n\tregisterExternalUriResolver(resolver: IExternalUriResolver): IDisposable {\n\t\tconst remove = this._resolvers.push(resolver);\n\t\treturn { dispose: remove };\n\t}\n\n\tsetDefaultExternalOpener(externalOpener: IExternalOpener): void {\n\t\tthis._defaultExternalOpener = externalOpener;\n\t}\n\n\tregisterExternalOpener(opener: IExternalOpener): IDisposable {\n\t\tconst remove = this._externalOpeners.push(opener);\n\t\treturn { dispose: remove };\n\t}\n\n\tasync open(target: URI | string, options?: OpenOptions): Promise {\n\t\t// check with contributed validators\n\t\tconst targetURI = typeof target === 'string' ? URI.parse(target) : target;\n\t\t// validate against the original URI that this URI resolves to, if one exists\n\t\tconst validationTarget = this._resolvedUriTargets.get(targetURI) ?? target;\n\t\tfor (const validator of this._validators) {\n\t\t\tif (!(await validator.shouldOpen(validationTarget))) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// check with contributed openers\n\t\tfor (const opener of this._openers) {\n\t\t\tconst handled = await opener.open(target, options);\n\t\t\tif (handled) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tasync resolveExternalUri(resource: URI, options?: ResolveExternalUriOptions): Promise {\n\t\tfor (const resolver of this._resolvers) {\n\t\t\ttry {\n\t\t\t\tconst result = await resolver.resolveExternalUri(resource, options);\n\t\t\t\tif (result) {\n\t\t\t\t\tif (!this._resolvedUriTargets.has(result.resolved)) {\n\t\t\t\t\t\tthis._resolvedUriTargets.set(result.resolved, resource);\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// noop\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error('Could not resolve external URI: ' + resource.toString());\n\t}\n\n\tprivate async _doOpenExternal(resource: URI | string, options: OpenOptions | undefined): Promise {\n\n\t\t//todo@jrieken IExternalUriResolver should support `uri: URI | string`\n\t\tconst uri = typeof resource === 'string' ? URI.parse(resource) : resource;\n\t\tlet externalUri: URI;\n\n\t\ttry {\n\t\t\texternalUri = (await this.resolveExternalUri(uri, options)).resolved;\n\t\t} catch {\n\t\t\texternalUri = uri;\n\t\t}\n\n\t\tlet href: string;\n\t\tif (typeof resource === 'string' && uri.toString() === externalUri.toString()) {\n\t\t\t// open the url-string AS IS\n\t\t\thref = resource;\n\t\t} else {\n\t\t\t// open URI using the toString(noEncode)+encodeURI-trick\n\t\t\thref = encodeURI(externalUri.toString(true));\n\t\t}\n\n\t\tif (options?.allowContributedOpeners) {\n\t\t\tconst preferredOpenerId = typeof options?.allowContributedOpeners === 'string' ? options?.allowContributedOpeners : undefined;\n\t\t\tfor (const opener of this._externalOpeners) {\n\t\t\t\tconst didOpen = await opener.openExternal(href, {\n\t\t\t\t\tsourceUri: uri,\n\t\t\t\t\tpreferredOpenerId,\n\t\t\t\t}, CancellationToken.None);\n\t\t\t\tif (didOpen) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this._defaultExternalOpener.openExternal(href, { sourceUri: uri }, CancellationToken.None);\n\t}\n\n\tdispose() {\n\t\tthis._validators.clear();\n\t}\n}\n","\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\n\nexport interface IProgressIndicator {\n\n\t/**\n\t * Show progress customized with the provided flags.\n\t */\n\tshow(infinite: true, delay?: number): IProgressRunner;\n\tshow(total: number, delay?: number): IProgressRunner;\n\n\t/**\n\t * Indicate progress for the duration of the provided promise. Progress will stop in\n\t * any case of promise completion, error or cancellation.\n\t */\n\tshowWhile(promise: Promise, delay?: number): Promise;\n}\n\nexport interface IProgressRunner {\n\ttotal(value: number): void;\n\tworked(value: number): void;\n\tdone(): void;\n}\n\nexport const emptyProgressRunner: IProgressRunner = Object.freeze({\n\ttotal() { },\n\tworked() { },\n\tdone() { }\n});\n\nexport interface IProgress {\n\treport(item: T): void;\n}\n\nexport class Progress implements IProgress {\n\n\tstatic readonly None: IProgress = Object.freeze({ report() { } });\n\n\tprivate _value?: T;\n\n\tconstructor(private callback: (data: T) => void) { }\n\n\treport(item: T) {\n\t\tthis._value = item;\n\t\tthis.callback(this._value);\n\t}\n}\n\nexport const IEditorProgressService = createDecorator('editorProgressService');\n\n/**\n * A progress service that will report progress local to the editor triggered from.\n */\nexport interface IEditorProgressService extends IProgressIndicator {\n\n\treadonly _serviceBrand: undefined;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { timeout } from 'vs/base/common/async';\nimport { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';\nimport { Disposable, DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';\nimport { IKeyMods, IQuickPickDidAcceptEvent, IQuickPickSeparator } from 'vs/base/parts/quickinput/common/quickInput';\nimport { IQuickAccessProvider } from 'vs/platform/quickinput/common/quickAccess';\nimport { IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';\n\nexport enum TriggerAction {\n\n\t/**\n\t * Do nothing after the button was clicked.\n\t */\n\tNO_ACTION,\n\n\t/**\n\t * Close the picker.\n\t */\n\tCLOSE_PICKER,\n\n\t/**\n\t * Update the results of the picker.\n\t */\n\tREFRESH_PICKER,\n\n\t/**\n\t * Remove the item from the picker.\n\t */\n\tREMOVE_ITEM\n}\n\nexport interface IPickerQuickAccessItem extends IQuickPickItem {\n\n\t/**\n\t* A method that will be executed when the pick item is accepted from\n\t* the picker. The picker will close automatically before running this.\n\t*\n\t* @param keyMods the state of modifier keys when the item was accepted.\n\t* @param event the underlying event that caused the accept to trigger.\n\t*/\n\taccept?(keyMods: IKeyMods, event: IQuickPickDidAcceptEvent): void;\n\n\t/**\n\t * A method that will be executed when a button of the pick item was\n\t * clicked on.\n\t *\n\t * @param buttonIndex index of the button of the item that\n\t * was clicked.\n\t *\n\t * @param the state of modifier keys when the button was triggered.\n\t *\n\t * @returns a value that indicates what should happen after the trigger\n\t * which can be a `Promise` for long running operations.\n\t */\n\ttrigger?(buttonIndex: number, keyMods: IKeyMods): TriggerAction | Promise;\n}\n\nexport interface IPickerQuickAccessProviderOptions {\n\n\t/**\n\t * Enables support for opening picks in the background via gesture.\n\t */\n\tcanAcceptInBackground?: boolean;\n\n\t/**\n\t * Enables to show a pick entry when no results are returned from a search.\n\t */\n\tnoResultsPick?: T;\n}\n\nexport type Pick = T | IQuickPickSeparator;\nexport type PicksWithActive = { items: readonly Pick[], active?: T };\nexport type Picks = readonly Pick[] | PicksWithActive;\nexport type FastAndSlowPicks = { picks: Picks, additionalPicks: Promise> };\n\nfunction isPicksWithActive(obj: unknown): obj is PicksWithActive {\n\tconst candidate = obj as PicksWithActive;\n\n\treturn Array.isArray(candidate.items);\n}\n\nfunction isFastAndSlowPicks(obj: unknown): obj is FastAndSlowPicks {\n\tconst candidate = obj as FastAndSlowPicks;\n\n\treturn !!candidate.picks && candidate.additionalPicks instanceof Promise;\n}\n\nexport abstract class PickerQuickAccessProvider extends Disposable implements IQuickAccessProvider {\n\n\tprivate static FAST_PICKS_RACE_DELAY = 200; // timeout before we accept fast results before slow results are present\n\n\tconstructor(private prefix: string, protected options?: IPickerQuickAccessProviderOptions) {\n\t\tsuper();\n\t}\n\n\tprovide(picker: IQuickPick, token: CancellationToken): IDisposable {\n\t\tconst disposables = new DisposableStore();\n\n\t\t// Apply options if any\n\t\tpicker.canAcceptInBackground = !!this.options?.canAcceptInBackground;\n\n\t\t// Disable filtering & sorting, we control the results\n\t\tpicker.matchOnLabel = picker.matchOnDescription = picker.matchOnDetail = picker.sortByLabel = false;\n\n\t\t// Set initial picks and update on type\n\t\tlet picksCts: CancellationTokenSource | undefined = undefined;\n\t\tconst picksDisposable = disposables.add(new MutableDisposable());\n\t\tconst updatePickerItems = async () => {\n\t\t\tconst picksDisposables = picksDisposable.value = new DisposableStore();\n\n\t\t\t// Cancel any previous ask for picks and busy\n\t\t\tpicksCts?.dispose(true);\n\t\t\tpicker.busy = false;\n\n\t\t\t// Create new cancellation source for this run\n\t\t\tpicksCts = new CancellationTokenSource(token);\n\n\t\t\t// Collect picks and support both long running and short or combined\n\t\t\tconst picksToken = picksCts.token;\n\t\t\tconst picksFilter = picker.value.substr(this.prefix.length).trim();\n\t\t\tconst providedPicks = this._getPicks(picksFilter, picksDisposables, picksToken);\n\n\t\t\tconst applyPicks = (picks: Picks, skipEmpty?: boolean): boolean => {\n\t\t\t\tlet items: readonly Pick[];\n\t\t\t\tlet activeItem: T | undefined = undefined;\n\n\t\t\t\tif (isPicksWithActive(picks)) {\n\t\t\t\t\titems = picks.items;\n\t\t\t\t\tactiveItem = picks.active;\n\t\t\t\t} else {\n\t\t\t\t\titems = picks;\n\t\t\t\t}\n\n\t\t\t\tif (items.length === 0) {\n\t\t\t\t\tif (skipEmpty) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (picksFilter.length > 0 && this.options?.noResultsPick) {\n\t\t\t\t\t\titems = [this.options.noResultsPick];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpicker.items = items;\n\t\t\t\tif (activeItem) {\n\t\t\t\t\tpicker.activeItems = [activeItem];\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t};\n\n\t\t\t// No Picks\n\t\t\tif (providedPicks === null) {\n\t\t\t\t// Ignore\n\t\t\t}\n\n\t\t\t// Fast and Slow Picks\n\t\t\telse if (isFastAndSlowPicks(providedPicks)) {\n\t\t\t\tlet fastPicksApplied = false;\n\t\t\t\tlet slowPicksApplied = false;\n\n\t\t\t\tawait Promise.all([\n\n\t\t\t\t\t// Fast Picks: to reduce amount of flicker, we race against\n\t\t\t\t\t// the slow picks over 500ms and then set the fast picks.\n\t\t\t\t\t// If the slow picks are faster, we reduce the flicker by\n\t\t\t\t\t// only setting the items once.\n\t\t\t\t\t(async () => {\n\t\t\t\t\t\tawait timeout(PickerQuickAccessProvider.FAST_PICKS_RACE_DELAY);\n\t\t\t\t\t\tif (picksToken.isCancellationRequested) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!slowPicksApplied) {\n\t\t\t\t\t\t\tfastPicksApplied = applyPicks(providedPicks.picks, true /* skip over empty to reduce flicker */);\n\t\t\t\t\t\t}\n\t\t\t\t\t})(),\n\n\t\t\t\t\t// Slow Picks: we await the slow picks and then set them at\n\t\t\t\t\t// once together with the fast picks, but only if we actually\n\t\t\t\t\t// have additional results.\n\t\t\t\t\t(async () => {\n\t\t\t\t\t\tpicker.busy = true;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst awaitedAdditionalPicks = await providedPicks.additionalPicks;\n\t\t\t\t\t\t\tif (picksToken.isCancellationRequested) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlet picks: readonly Pick[];\n\t\t\t\t\t\t\tlet activePick: Pick | undefined = undefined;\n\t\t\t\t\t\t\tif (isPicksWithActive(providedPicks.picks)) {\n\t\t\t\t\t\t\t\tpicks = providedPicks.picks.items;\n\t\t\t\t\t\t\t\tactivePick = providedPicks.picks.active;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tpicks = providedPicks.picks;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlet additionalPicks: readonly Pick[];\n\t\t\t\t\t\t\tlet additionalActivePick: Pick | undefined = undefined;\n\t\t\t\t\t\t\tif (isPicksWithActive(awaitedAdditionalPicks)) {\n\t\t\t\t\t\t\t\tadditionalPicks = awaitedAdditionalPicks.items;\n\t\t\t\t\t\t\t\tadditionalActivePick = awaitedAdditionalPicks.active;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tadditionalPicks = awaitedAdditionalPicks;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (additionalPicks.length > 0 || !fastPicksApplied) {\n\t\t\t\t\t\t\t\t// If we do not have any activePick or additionalActivePick\n\t\t\t\t\t\t\t\t// we try to preserve the currently active pick from the\n\t\t\t\t\t\t\t\t// fast results. This fixes an issue where the user might\n\t\t\t\t\t\t\t\t// have made a pick active before the additional results\n\t\t\t\t\t\t\t\t// kick in.\n\t\t\t\t\t\t\t\t// See https://github.com/microsoft/vscode/issues/102480\n\t\t\t\t\t\t\t\tlet fallbackActivePick: Pick | undefined = undefined;\n\t\t\t\t\t\t\t\tif (!activePick && !additionalActivePick) {\n\t\t\t\t\t\t\t\t\tconst fallbackActivePickCandidate = picker.activeItems[0];\n\t\t\t\t\t\t\t\t\tif (fallbackActivePickCandidate && picks.indexOf(fallbackActivePickCandidate) !== -1) {\n\t\t\t\t\t\t\t\t\t\tfallbackActivePick = fallbackActivePickCandidate;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tapplyPicks({\n\t\t\t\t\t\t\t\t\titems: [...picks, ...additionalPicks],\n\t\t\t\t\t\t\t\t\tactive: activePick || additionalActivePick || fallbackActivePick\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tif (!picksToken.isCancellationRequested) {\n\t\t\t\t\t\t\t\tpicker.busy = false;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tslowPicksApplied = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t})()\n\t\t\t\t]);\n\t\t\t}\n\n\t\t\t// Fast Picks\n\t\t\telse if (!(providedPicks instanceof Promise)) {\n\t\t\t\tapplyPicks(providedPicks);\n\t\t\t}\n\n\t\t\t// Slow Picks\n\t\t\telse {\n\t\t\t\tpicker.busy = true;\n\t\t\t\ttry {\n\t\t\t\t\tconst awaitedPicks = await providedPicks;\n\t\t\t\t\tif (picksToken.isCancellationRequested) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tapplyPicks(awaitedPicks);\n\t\t\t\t} finally {\n\t\t\t\t\tif (!picksToken.isCancellationRequested) {\n\t\t\t\t\t\tpicker.busy = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tdisposables.add(picker.onDidChangeValue(() => updatePickerItems()));\n\t\tupdatePickerItems();\n\n\t\t// Accept the pick on accept and hide picker\n\t\tdisposables.add(picker.onDidAccept(event => {\n\t\t\tconst [item] = picker.selectedItems;\n\t\t\tif (typeof item?.accept === 'function') {\n\t\t\t\tif (!event.inBackground) {\n\t\t\t\t\tpicker.hide(); // hide picker unless we accept in background\n\t\t\t\t}\n\n\t\t\t\titem.accept(picker.keyMods, event);\n\t\t\t}\n\t\t}));\n\n\t\t// Trigger the pick with button index if button triggered\n\t\tdisposables.add(picker.onDidTriggerItemButton(async ({ button, item }) => {\n\t\t\tif (typeof item.trigger === 'function') {\n\t\t\t\tconst buttonIndex = item.buttons?.indexOf(button) ?? -1;\n\t\t\t\tif (buttonIndex >= 0) {\n\t\t\t\t\tconst result = item.trigger(buttonIndex, picker.keyMods);\n\t\t\t\t\tconst action = (typeof result === 'number') ? result : await result;\n\n\t\t\t\t\tif (token.isCancellationRequested) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tswitch (action) {\n\t\t\t\t\t\tcase TriggerAction.NO_ACTION:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TriggerAction.CLOSE_PICKER:\n\t\t\t\t\t\t\tpicker.hide();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TriggerAction.REFRESH_PICKER:\n\t\t\t\t\t\t\tupdatePickerItems();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TriggerAction.REMOVE_ITEM: {\n\t\t\t\t\t\t\tconst index = picker.items.indexOf(item);\n\t\t\t\t\t\t\tif (index !== -1) {\n\t\t\t\t\t\t\t\tconst items = picker.items.slice();\n\t\t\t\t\t\t\t\tconst removed = items.splice(index, 1);\n\t\t\t\t\t\t\t\tconst activeItems = picker.activeItems.filter(activeItem => activeItem !== removed[0]);\n\t\t\t\t\t\t\t\tconst keepScrollPositionBefore = picker.keepScrollPosition;\n\t\t\t\t\t\t\t\tpicker.keepScrollPosition = true;\n\t\t\t\t\t\t\t\tpicker.items = items;\n\t\t\t\t\t\t\t\tif (activeItems) {\n\t\t\t\t\t\t\t\t\tpicker.activeItems = activeItems;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tpicker.keepScrollPosition = keepScrollPositionBefore;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}));\n\n\t\treturn disposables;\n\t}\n\n\t/**\n\t * Returns an array of picks and separators as needed. If the picks are resolved\n\t * long running, the provided cancellation token should be used to cancel the\n\t * operation when the token signals this.\n\t *\n\t * The implementor is responsible for filtering and sorting the picks given the\n\t * provided `filter`.\n\t *\n\t * @param filter a filter to apply to the picks.\n\t * @param disposables can be used to register disposables that should be cleaned\n\t * up when the picker closes.\n\t * @param token for long running tasks, implementors need to check on cancellation\n\t * through this token.\n\t * @returns the picks either directly, as promise or combined fast and slow results.\n\t * Pickers can return `null` to signal that no change in picks is needed.\n\t */\n\tprotected abstract _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Picks | Promise> | FastAndSlowPicks | null;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { IPickOptions, IQuickPick, IQuickPickItem, QuickPickInput } from 'vs/base/parts/quickinput/common/quickInput';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { IQuickAccessController } from 'vs/platform/quickinput/common/quickAccess';\n\nexport * from 'vs/base/parts/quickinput/common/quickInput';\n\nexport const IQuickInputService = createDecorator('quickInputService');\n\nexport type Omit = Pick>;\n\nexport interface IQuickInputService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Provides access to the quick access providers.\n\t */\n\treadonly quickAccess: IQuickAccessController;\n\n\t/**\n\t * Opens the quick input box for selecting items and returns a promise\n\t * with the user selected item(s) if any.\n\t */\n\tpick(picks: Promise[]> | QuickPickInput[], options?: IPickOptions & { canPickMany: true }, token?: CancellationToken): Promise;\n\tpick(picks: Promise[]> | QuickPickInput[], options?: IPickOptions & { canPickMany: false }, token?: CancellationToken): Promise;\n\tpick(picks: Promise[]> | QuickPickInput[], options?: Omit, 'canPickMany'>, token?: CancellationToken): Promise;\n\n\t/**\n\t * Provides raw access to the quick pick controller.\n\t */\n\tcreateQuickPick(): IQuickPick;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as Assert from 'vs/base/common/assert';\nimport * as Types from 'vs/base/common/types';\n\nexport interface IRegistry {\n\n\t/**\n\t * Adds the extension functions and properties defined by data to the\n\t * platform. The provided id must be unique.\n\t * @param id a unique identifier\n\t * @param data a contribution\n\t */\n\tadd(id: string, data: any): void;\n\n\t/**\n\t * Returns the extension functions and properties defined by the specified key or null.\n\t * @param id an extension identifier\n\t */\n\tas(id: string): T;\n}\n\nclass RegistryImpl implements IRegistry {\n\n\tprivate readonly data = new Map();\n\n\tpublic add(id: string, data: any): void {\n\t\tAssert.ok(Types.isString(id));\n\t\tAssert.ok(Types.isObject(data));\n\t\tAssert.ok(!this.data.has(id), 'There is already an extension with this id');\n\n\t\tthis.data.set(id, data);\n\t}\n\n\tpublic as(id: string): any {\n\t\treturn this.data.get(id) || null;\n\t}\n}\n\nexport const Registry: IRegistry = new RegistryImpl();\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter } from 'vs/base/common/event';\nimport { IJSONSchema } from 'vs/base/common/jsonSchema';\nimport * as platform from 'vs/platform/registry/common/platform';\n\nexport const Extensions = {\n\tJSONContribution: 'base.contributions.json'\n};\n\nexport interface IJSONContributionRegistry {\n\n\t/**\n\t * Register a schema to the registry.\n\t */\n\tregisterSchema(uri: string, unresolvedSchemaContent: IJSONSchema): void;\n\n\n\t/**\n\t * Notifies all listeners that the content of the given schema has changed.\n\t * @param uri The id of the schema\n\t */\n\tnotifySchemaChanged(uri: string): void;\n}\n\n\n\nfunction normalizeId(id: string) {\n\tif (id.length > 0 && id.charAt(id.length - 1) === '#') {\n\t\treturn id.substring(0, id.length - 1);\n\t}\n\treturn id;\n}\n\n\n\nclass JSONContributionRegistry implements IJSONContributionRegistry {\n\n\tprivate schemasById: { [id: string]: IJSONSchema };\n\n\tprivate readonly _onDidChangeSchema = new Emitter();\n\n\tconstructor() {\n\t\tthis.schemasById = {};\n\t}\n\n\tpublic registerSchema(uri: string, unresolvedSchemaContent: IJSONSchema): void {\n\t\tthis.schemasById[normalizeId(uri)] = unresolvedSchemaContent;\n\t\tthis._onDidChangeSchema.fire(uri);\n\t}\n\n\tpublic notifySchemaChanged(uri: string): void {\n\t\tthis._onDidChangeSchema.fire(uri);\n\t}\n\n}\n\nconst jsonContributionRegistry = new JSONContributionRegistry();\nplatform.Registry.add(Extensions.JSONContribution, jsonContributionRegistry);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { distinct } from 'vs/base/common/arrays';\nimport { IStringDictionary } from 'vs/base/common/collections';\nimport { Emitter } from 'vs/base/common/event';\nimport { IJSONSchema } from 'vs/base/common/jsonSchema';\nimport * as types from 'vs/base/common/types';\nimport * as nls from 'vs/nls';\nimport { Extensions as JSONExtensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';\nimport { Registry } from 'vs/platform/registry/common/platform';\n\nexport const Extensions = {\n\tConfiguration: 'base.contributions.configuration'\n};\n\nexport interface IConfigurationRegistry {\n\n\t/**\n\t * Register a configuration to the registry.\n\t */\n\tregisterConfiguration(configuration: IConfigurationNode): void;\n\n\t/**\n\t * Register multiple default configurations to the registry.\n\t */\n\tregisterDefaultConfigurations(defaultConfigurations: IConfigurationDefaults[]): void;\n\n\t/**\n\t * Returns all configurations settings of all configuration nodes contributed to this registry.\n\t */\n\tgetConfigurationProperties(): IStringDictionary;\n\n\t/**\n\t * Register the identifiers for editor configurations\n\t */\n\tregisterOverrideIdentifiers(identifiers: string[]): void;\n}\n\nexport const enum ConfigurationScope {\n\t/**\n\t * Application specific configuration, which can be configured only in local user settings.\n\t */\n\tAPPLICATION = 1,\n\t/**\n\t * Machine specific configuration, which can be configured only in local and remote user settings.\n\t */\n\tMACHINE,\n\t/**\n\t * Window specific configuration, which can be configured in the user or workspace settings.\n\t */\n\tWINDOW,\n\t/**\n\t * Resource specific configuration, which can be configured in the user, workspace or folder settings.\n\t */\n\tRESOURCE,\n\t/**\n\t * Resource specific configuration that can be configured in language specific settings\n\t */\n\tLANGUAGE_OVERRIDABLE,\n\t/**\n\t * Machine specific configuration that can also be configured in workspace or folder settings.\n\t */\n\tMACHINE_OVERRIDABLE,\n}\n\nexport interface IConfigurationPropertySchema extends IJSONSchema {\n\n\tscope?: ConfigurationScope;\n\n\t/**\n\t * When restricted, value of this configuration will be read only from trusted sources.\n\t * For eg., If the workspace is not trusted, then the value of this configuration is not read from workspace settings file.\n\t */\n\trestricted?: boolean;\n\n\t/**\n\t * When `false` this property is excluded from the registry. Default is to include.\n\t */\n\tincluded?: boolean;\n}\n\nexport interface IExtensionInfo {\n}\n\nexport interface IConfigurationNode {\n\tid?: string;\n\torder?: number;\n\ttype?: string | string[];\n\ttitle?: string;\n\tproperties?: IStringDictionary;\n\tallOf?: IConfigurationNode[];\n\tscope?: ConfigurationScope;\n\textensionInfo?: IExtensionInfo;\n\trestrictedProperties?: string[];\n}\n\nexport interface IConfigurationDefaults {\n\toverrides: IStringDictionary;\n\tsource?: IExtensionInfo | string;\n}\n\nexport type IRegisteredConfigurationPropertySchema = IConfigurationPropertySchema & {\n\tdefaultDefaultValue?: any,\n\tsource?: IExtensionInfo,\n\tdefaultValueSource?: IExtensionInfo | string;\n};\n\nexport type IConfigurationDefaultOverride = { value: any, source?: IExtensionInfo | string };\n\nexport const allSettings: { properties: IStringDictionary, patternProperties: IStringDictionary } = { properties: {}, patternProperties: {} };\nexport const applicationSettings: { properties: IStringDictionary, patternProperties: IStringDictionary } = { properties: {}, patternProperties: {} };\nexport const machineSettings: { properties: IStringDictionary, patternProperties: IStringDictionary } = { properties: {}, patternProperties: {} };\nexport const machineOverridableSettings: { properties: IStringDictionary, patternProperties: IStringDictionary } = { properties: {}, patternProperties: {} };\nexport const windowSettings: { properties: IStringDictionary, patternProperties: IStringDictionary } = { properties: {}, patternProperties: {} };\nexport const resourceSettings: { properties: IStringDictionary, patternProperties: IStringDictionary } = { properties: {}, patternProperties: {} };\n\nexport const resourceLanguageSettingsSchemaId = 'vscode://schemas/settings/resourceLanguage';\n\nconst contributionRegistry = Registry.as(JSONExtensions.JSONContribution);\n\nclass ConfigurationRegistry implements IConfigurationRegistry {\n\n\tprivate readonly configurationDefaultsOverrides: Map;\n\tprivate readonly defaultLanguageConfigurationOverridesNode: IConfigurationNode;\n\tprivate readonly configurationContributors: IConfigurationNode[];\n\tprivate readonly configurationProperties: IStringDictionary;\n\tprivate readonly excludedConfigurationProperties: IStringDictionary;\n\tprivate readonly resourceLanguageSettingsSchema: IJSONSchema;\n\tprivate readonly overrideIdentifiers = new Set();\n\n\tprivate readonly _onDidSchemaChange = new Emitter();\n\n\tprivate readonly _onDidUpdateConfiguration = new Emitter<{ properties: string[], defaultsOverrides?: boolean }>();\n\n\tconstructor() {\n\t\tthis.configurationDefaultsOverrides = new Map();\n\t\tthis.defaultLanguageConfigurationOverridesNode = {\n\t\t\tid: 'defaultOverrides',\n\t\t\ttitle: nls.localize('defaultLanguageConfigurationOverrides.title', \"Default Language Configuration Overrides\"),\n\t\t\tproperties: {}\n\t\t};\n\t\tthis.configurationContributors = [this.defaultLanguageConfigurationOverridesNode];\n\t\tthis.resourceLanguageSettingsSchema = { properties: {}, patternProperties: {}, additionalProperties: false, errorMessage: 'Unknown editor configuration setting', allowTrailingCommas: true, allowComments: true };\n\t\tthis.configurationProperties = {};\n\t\tthis.excludedConfigurationProperties = {};\n\n\t\tcontributionRegistry.registerSchema(resourceLanguageSettingsSchemaId, this.resourceLanguageSettingsSchema);\n\t\tthis.registerOverridePropertyPatternKey();\n\t}\n\n\tpublic registerConfiguration(configuration: IConfigurationNode, validate: boolean = true): void {\n\t\tthis.registerConfigurations([configuration], validate);\n\t}\n\n\tpublic registerConfigurations(configurations: IConfigurationNode[], validate: boolean = true): void {\n\t\tconst properties = this.doRegisterConfigurations(configurations, validate);\n\n\t\tcontributionRegistry.registerSchema(resourceLanguageSettingsSchemaId, this.resourceLanguageSettingsSchema);\n\t\tthis._onDidSchemaChange.fire();\n\t\tthis._onDidUpdateConfiguration.fire({ properties });\n\t}\n\n\tpublic registerDefaultConfigurations(configurationDefaults: IConfigurationDefaults[]): void {\n\t\tconst properties: string[] = [];\n\t\tconst overrideIdentifiers: string[] = [];\n\n\t\tfor (const { overrides, source } of configurationDefaults) {\n\t\t\tfor (const key in overrides) {\n\t\t\t\tproperties.push(key);\n\n\t\t\t\tif (OVERRIDE_PROPERTY_REGEX.test(key)) {\n\t\t\t\t\tconst defaultValue = { ...(this.configurationDefaultsOverrides.get(key)?.value || {}), ...overrides[key] };\n\t\t\t\t\tthis.configurationDefaultsOverrides.set(key, { source, value: defaultValue });\n\t\t\t\t\tconst property: IRegisteredConfigurationPropertySchema = {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tdefault: defaultValue,\n\t\t\t\t\t\tdescription: nls.localize('defaultLanguageConfiguration.description', \"Configure settings to be overridden for {0} language.\", key),\n\t\t\t\t\t\t$ref: resourceLanguageSettingsSchemaId,\n\t\t\t\t\t\tdefaultDefaultValue: defaultValue,\n\t\t\t\t\t\tsource: types.isString(source) ? undefined : source,\n\t\t\t\t\t};\n\t\t\t\t\toverrideIdentifiers.push(...overrideIdentifiersFromKey(key));\n\t\t\t\t\tthis.configurationProperties[key] = property;\n\t\t\t\t\tthis.defaultLanguageConfigurationOverridesNode.properties![key] = property;\n\t\t\t\t} else {\n\t\t\t\t\tthis.configurationDefaultsOverrides.set(key, { value: overrides[key], source });\n\t\t\t\t\tconst property = this.configurationProperties[key];\n\t\t\t\t\tif (property) {\n\t\t\t\t\t\tthis.updatePropertyDefaultValue(key, property);\n\t\t\t\t\t\tthis.updateSchema(key, property);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.registerOverrideIdentifiers(overrideIdentifiers);\n\t\tthis._onDidSchemaChange.fire();\n\t\tthis._onDidUpdateConfiguration.fire({ properties, defaultsOverrides: true });\n\t}\n\n\tpublic registerOverrideIdentifiers(overrideIdentifiers: string[]): void {\n\t\tfor (const overrideIdentifier of overrideIdentifiers) {\n\t\t\tthis.overrideIdentifiers.add(overrideIdentifier);\n\t\t}\n\t\tthis.updateOverridePropertyPatternKey();\n\t}\n\n\tprivate doRegisterConfigurations(configurations: IConfigurationNode[], validate: boolean): string[] {\n\t\tconst properties: string[] = [];\n\t\tconfigurations.forEach(configuration => {\n\t\t\tproperties.push(...this.validateAndRegisterProperties(configuration, validate, configuration.extensionInfo, configuration.restrictedProperties)); // fills in defaults\n\t\t\tthis.configurationContributors.push(configuration);\n\t\t\tthis.registerJSONConfiguration(configuration);\n\t\t});\n\t\treturn properties;\n\t}\n\n\tprivate validateAndRegisterProperties(configuration: IConfigurationNode, validate: boolean = true, extensionInfo: IExtensionInfo | undefined, restrictedProperties: string[] | undefined, scope: ConfigurationScope = ConfigurationScope.WINDOW): string[] {\n\t\tscope = types.isUndefinedOrNull(configuration.scope) ? scope : configuration.scope;\n\t\tlet propertyKeys: string[] = [];\n\t\tlet properties = configuration.properties;\n\t\tif (properties) {\n\t\t\tfor (let key in properties) {\n\t\t\t\tif (validate && validateProperty(key)) {\n\t\t\t\t\tdelete properties[key];\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst property: IRegisteredConfigurationPropertySchema = properties[key];\n\t\t\t\tproperty.source = extensionInfo;\n\n\t\t\t\t// update default value\n\t\t\t\tproperty.defaultDefaultValue = properties[key].default;\n\t\t\t\tthis.updatePropertyDefaultValue(key, property);\n\n\t\t\t\t// update scope\n\t\t\t\tif (OVERRIDE_PROPERTY_REGEX.test(key)) {\n\t\t\t\t\tproperty.scope = undefined; // No scope for overridable properties `[${identifier}]`\n\t\t\t\t} else {\n\t\t\t\t\tproperty.scope = types.isUndefinedOrNull(property.scope) ? scope : property.scope;\n\t\t\t\t\tproperty.restricted = types.isUndefinedOrNull(property.restricted) ? !!restrictedProperties?.includes(key) : property.restricted;\n\t\t\t\t}\n\n\t\t\t\t// Add to properties maps\n\t\t\t\t// Property is included by default if 'included' is unspecified\n\t\t\t\tif (properties[key].hasOwnProperty('included') && !properties[key].included) {\n\t\t\t\t\tthis.excludedConfigurationProperties[key] = properties[key];\n\t\t\t\t\tdelete properties[key];\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\tthis.configurationProperties[key] = properties[key];\n\t\t\t\t}\n\n\t\t\t\tif (!properties[key].deprecationMessage && properties[key].markdownDeprecationMessage) {\n\t\t\t\t\t// If not set, default deprecationMessage to the markdown source\n\t\t\t\t\tproperties[key].deprecationMessage = properties[key].markdownDeprecationMessage;\n\t\t\t\t}\n\n\t\t\t\tpropertyKeys.push(key);\n\t\t\t}\n\t\t}\n\t\tlet subNodes = configuration.allOf;\n\t\tif (subNodes) {\n\t\t\tfor (let node of subNodes) {\n\t\t\t\tpropertyKeys.push(...this.validateAndRegisterProperties(node, validate, extensionInfo, restrictedProperties, scope));\n\t\t\t}\n\t\t}\n\t\treturn propertyKeys;\n\t}\n\n\tgetConfigurationProperties(): IStringDictionary {\n\t\treturn this.configurationProperties;\n\t}\n\n\tprivate registerJSONConfiguration(configuration: IConfigurationNode) {\n\t\tconst register = (configuration: IConfigurationNode) => {\n\t\t\tlet properties = configuration.properties;\n\t\t\tif (properties) {\n\t\t\t\tfor (const key in properties) {\n\t\t\t\t\tthis.updateSchema(key, properties[key]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet subNodes = configuration.allOf;\n\t\t\tif (subNodes) {\n\t\t\t\tsubNodes.forEach(register);\n\t\t\t}\n\t\t};\n\t\tregister(configuration);\n\t}\n\n\tprivate updateSchema(key: string, property: IConfigurationPropertySchema): void {\n\t\tallSettings.properties[key] = property;\n\t\tswitch (property.scope) {\n\t\t\tcase ConfigurationScope.APPLICATION:\n\t\t\t\tapplicationSettings.properties[key] = property;\n\t\t\t\tbreak;\n\t\t\tcase ConfigurationScope.MACHINE:\n\t\t\t\tmachineSettings.properties[key] = property;\n\t\t\t\tbreak;\n\t\t\tcase ConfigurationScope.MACHINE_OVERRIDABLE:\n\t\t\t\tmachineOverridableSettings.properties[key] = property;\n\t\t\t\tbreak;\n\t\t\tcase ConfigurationScope.WINDOW:\n\t\t\t\twindowSettings.properties[key] = property;\n\t\t\t\tbreak;\n\t\t\tcase ConfigurationScope.RESOURCE:\n\t\t\t\tresourceSettings.properties[key] = property;\n\t\t\t\tbreak;\n\t\t\tcase ConfigurationScope.LANGUAGE_OVERRIDABLE:\n\t\t\t\tresourceSettings.properties[key] = property;\n\t\t\t\tthis.resourceLanguageSettingsSchema.properties![key] = property;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate updateOverridePropertyPatternKey(): void {\n\t\tfor (const overrideIdentifier of this.overrideIdentifiers.values()) {\n\t\t\tconst overrideIdentifierProperty = `[${overrideIdentifier}]`;\n\t\t\tconst resourceLanguagePropertiesSchema: IJSONSchema = {\n\t\t\t\ttype: 'object',\n\t\t\t\tdescription: nls.localize('overrideSettings.defaultDescription', \"Configure editor settings to be overridden for a language.\"),\n\t\t\t\terrorMessage: nls.localize('overrideSettings.errorMessage', \"This setting does not support per-language configuration.\"),\n\t\t\t\t$ref: resourceLanguageSettingsSchemaId,\n\t\t\t};\n\t\t\tthis.updatePropertyDefaultValue(overrideIdentifierProperty, resourceLanguagePropertiesSchema);\n\t\t\tallSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n\t\t\tapplicationSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n\t\t\tmachineSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n\t\t\tmachineOverridableSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n\t\t\twindowSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n\t\t\tresourceSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n\t\t}\n\t\tthis._onDidSchemaChange.fire();\n\t}\n\n\tprivate registerOverridePropertyPatternKey(): void {\n\t\tconst resourceLanguagePropertiesSchema: IJSONSchema = {\n\t\t\ttype: 'object',\n\t\t\tdescription: nls.localize('overrideSettings.defaultDescription', \"Configure editor settings to be overridden for a language.\"),\n\t\t\terrorMessage: nls.localize('overrideSettings.errorMessage', \"This setting does not support per-language configuration.\"),\n\t\t\t$ref: resourceLanguageSettingsSchemaId,\n\t\t};\n\t\tallSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n\t\tapplicationSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n\t\tmachineSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n\t\tmachineOverridableSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n\t\twindowSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n\t\tresourceSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n\t\tthis._onDidSchemaChange.fire();\n\t}\n\n\tprivate updatePropertyDefaultValue(key: string, property: IRegisteredConfigurationPropertySchema): void {\n\t\tconst configurationdefaultOverride = this.configurationDefaultsOverrides.get(key);\n\t\tlet defaultValue = configurationdefaultOverride?.value;\n\t\tlet defaultSource = configurationdefaultOverride?.source;\n\t\tif (types.isUndefined(defaultValue)) {\n\t\t\tdefaultValue = property.defaultDefaultValue;\n\t\t\tdefaultSource = undefined;\n\t\t}\n\t\tif (types.isUndefined(defaultValue)) {\n\t\t\tdefaultValue = getDefaultValue(property.type);\n\t\t}\n\t\tproperty.default = defaultValue;\n\t\tproperty.defaultValueSource = defaultSource;\n\t}\n}\n\nconst OVERRIDE_IDENTIFIER_PATTERN = `\\\\[([^\\\\]]+)\\\\]`;\nconst OVERRIDE_IDENTIFIER_REGEX = new RegExp(OVERRIDE_IDENTIFIER_PATTERN, 'g');\nexport const OVERRIDE_PROPERTY_PATTERN = `^(${OVERRIDE_IDENTIFIER_PATTERN})+$`;\nexport const OVERRIDE_PROPERTY_REGEX = new RegExp(OVERRIDE_PROPERTY_PATTERN);\n\nexport function overrideIdentifiersFromKey(key: string): string[] {\n\tconst identifiers: string[] = [];\n\tif (OVERRIDE_PROPERTY_REGEX.test(key)) {\n\t\tlet matches = OVERRIDE_IDENTIFIER_REGEX.exec(key);\n\t\twhile (matches?.length) {\n\t\t\tconst identifier = matches[1].trim();\n\t\t\tif (identifier) {\n\t\t\t\tidentifiers.push(identifier);\n\t\t\t}\n\t\t\tmatches = OVERRIDE_IDENTIFIER_REGEX.exec(key);\n\t\t}\n\t}\n\treturn distinct(identifiers);\n}\n\nexport function getDefaultValue(type: string | string[] | undefined): any {\n\tconst t = Array.isArray(type) ? (type)[0] : type;\n\tswitch (t) {\n\t\tcase 'boolean':\n\t\t\treturn false;\n\t\tcase 'integer':\n\t\tcase 'number':\n\t\t\treturn 0;\n\t\tcase 'string':\n\t\t\treturn '';\n\t\tcase 'array':\n\t\t\treturn [];\n\t\tcase 'object':\n\t\t\treturn {};\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\nconst configurationRegistry = new ConfigurationRegistry();\nRegistry.add(Extensions.Configuration, configurationRegistry);\n\nexport function validateProperty(property: string): string | null {\n\tif (!property.trim()) {\n\t\treturn nls.localize('config.property.empty', \"Cannot register an empty property\");\n\t}\n\tif (OVERRIDE_PROPERTY_REGEX.test(property)) {\n\t\treturn nls.localize('config.property.languageDefault', \"Cannot register '{0}'. This matches property pattern '\\\\\\\\[.*\\\\\\\\]$' for describing language specific editor settings. Use 'configurationDefaults' contribution.\", property);\n\t}\n\tif (configurationRegistry.getConfigurationProperties()[property] !== undefined) {\n\t\treturn nls.localize('config.property.duplicate', \"Cannot register '{0}'. This property is already registered.\", property);\n\t}\n\treturn null;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { editorOptionsRegistry } from 'vs/editor/common/config/editorOptions';\nimport { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/core/textModelDefaults';\nimport * as nls from 'vs/nls';\nimport { ConfigurationScope, Extensions, IConfigurationNode, IConfigurationPropertySchema, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';\nimport { Registry } from 'vs/platform/registry/common/platform';\n\nexport const editorConfigurationBaseNode = Object.freeze({\n\tid: 'editor',\n\torder: 5,\n\ttype: 'object',\n\ttitle: nls.localize('editorConfigurationTitle', \"Editor\"),\n\tscope: ConfigurationScope.LANGUAGE_OVERRIDABLE,\n});\n\nconst editorConfiguration: IConfigurationNode = {\n\t...editorConfigurationBaseNode,\n\tproperties: {\n\t\t'editor.tabSize': {\n\t\t\ttype: 'number',\n\t\t\tdefault: EDITOR_MODEL_DEFAULTS.tabSize,\n\t\t\tminimum: 1,\n\t\t\tmarkdownDescription: nls.localize('tabSize', \"The number of spaces a tab is equal to. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.\")\n\t\t},\n\t\t// 'editor.indentSize': {\n\t\t// \t'anyOf': [\n\t\t// \t\t{\n\t\t// \t\t\ttype: 'string',\n\t\t// \t\t\tenum: ['tabSize']\n\t\t// \t\t},\n\t\t// \t\t{\n\t\t// \t\t\ttype: 'number',\n\t\t// \t\t\tminimum: 1\n\t\t// \t\t}\n\t\t// \t],\n\t\t// \tdefault: 'tabSize',\n\t\t// \tmarkdownDescription: nls.localize('indentSize', \"The number of spaces used for indentation or 'tabSize' to use the value from `#editor.tabSize#`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.\")\n\t\t// },\n\t\t'editor.insertSpaces': {\n\t\t\ttype: 'boolean',\n\t\t\tdefault: EDITOR_MODEL_DEFAULTS.insertSpaces,\n\t\t\tmarkdownDescription: nls.localize('insertSpaces', \"Insert spaces when pressing `Tab`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.\")\n\t\t},\n\t\t'editor.detectIndentation': {\n\t\t\ttype: 'boolean',\n\t\t\tdefault: EDITOR_MODEL_DEFAULTS.detectIndentation,\n\t\t\tmarkdownDescription: nls.localize('detectIndentation', \"Controls whether `#editor.tabSize#` and `#editor.insertSpaces#` will be automatically detected when a file is opened based on the file contents.\")\n\t\t},\n\t\t'editor.trimAutoWhitespace': {\n\t\t\ttype: 'boolean',\n\t\t\tdefault: EDITOR_MODEL_DEFAULTS.trimAutoWhitespace,\n\t\t\tdescription: nls.localize('trimAutoWhitespace', \"Remove trailing auto inserted whitespace.\")\n\t\t},\n\t\t'editor.largeFileOptimizations': {\n\t\t\ttype: 'boolean',\n\t\t\tdefault: EDITOR_MODEL_DEFAULTS.largeFileOptimizations,\n\t\t\tdescription: nls.localize('largeFileOptimizations', \"Special handling for large files to disable certain memory intensive features.\")\n\t\t},\n\t\t'editor.wordBasedSuggestions': {\n\t\t\ttype: 'boolean',\n\t\t\tdefault: true,\n\t\t\tdescription: nls.localize('wordBasedSuggestions', \"Controls whether completions should be computed based on words in the document.\")\n\t\t},\n\t\t'editor.wordBasedSuggestionsMode': {\n\t\t\tenum: ['currentDocument', 'matchingDocuments', 'allDocuments'],\n\t\t\tdefault: 'matchingDocuments',\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('wordBasedSuggestionsMode.currentDocument', 'Only suggest words from the active document.'),\n\t\t\t\tnls.localize('wordBasedSuggestionsMode.matchingDocuments', 'Suggest words from all open documents of the same language.'),\n\t\t\t\tnls.localize('wordBasedSuggestionsMode.allDocuments', 'Suggest words from all open documents.')\n\t\t\t],\n\t\t\tdescription: nls.localize('wordBasedSuggestionsMode', \"Controls from which documents word based completions are computed.\")\n\t\t},\n\t\t'editor.semanticHighlighting.enabled': {\n\t\t\tenum: [true, false, 'configuredByTheme'],\n\t\t\tenumDescriptions: [\n\t\t\t\tnls.localize('semanticHighlighting.true', 'Semantic highlighting enabled for all color themes.'),\n\t\t\t\tnls.localize('semanticHighlighting.false', 'Semantic highlighting disabled for all color themes.'),\n\t\t\t\tnls.localize('semanticHighlighting.configuredByTheme', 'Semantic highlighting is configured by the current color theme\\'s `semanticHighlighting` setting.')\n\t\t\t],\n\t\t\tdefault: 'configuredByTheme',\n\t\t\tdescription: nls.localize('semanticHighlighting.enabled', \"Controls whether the semanticHighlighting is shown for the languages that support it.\")\n\t\t},\n\t\t'editor.stablePeek': {\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t\tmarkdownDescription: nls.localize('stablePeek', \"Keep peek editors open even when double clicking their content or when hitting `Escape`.\")\n\t\t},\n\t\t'editor.maxTokenizationLineLength': {\n\t\t\ttype: 'integer',\n\t\t\tdefault: 20_000,\n\t\t\tdescription: nls.localize('maxTokenizationLineLength', \"Lines above this length will not be tokenized for performance reasons\")\n\t\t},\n\t\t'editor.language.brackets': {\n\t\t\ttype: 'array',\n\t\t\tdefault: false, // We want to distinguish the empty array from not configured.\n\t\t\tdescription: nls.localize('schema.brackets', 'Defines the bracket symbols that increase or decrease the indentation.'),\n\t\t\titems: {\n\t\t\t\ttype: 'array',\n\t\t\t\titems: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: nls.localize('schema.openBracket', 'The opening bracket character or string sequence.')\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: nls.localize('schema.closeBracket', 'The closing bracket character or string sequence.')\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t},\n\t\t'editor.language.colorizedBracketPairs': {\n\t\t\ttype: 'array',\n\t\t\tdefault: false, // We want to distinguish the empty array from not configured.\n\t\t\tdescription: nls.localize('schema.colorizedBracketPairs', 'Defines the bracket pairs that are colorized by their nesting level if bracket pair colorization is enabled.'),\n\t\t\titems: {\n\t\t\t\ttype: 'array',\n\t\t\t\titems: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: nls.localize('schema.openBracket', 'The opening bracket character or string sequence.')\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: nls.localize('schema.closeBracket', 'The closing bracket character or string sequence.')\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t},\n\t\t'diffEditor.maxComputationTime': {\n\t\t\ttype: 'number',\n\t\t\tdefault: 5000,\n\t\t\tdescription: nls.localize('maxComputationTime', \"Timeout in milliseconds after which diff computation is cancelled. Use 0 for no timeout.\")\n\t\t},\n\t\t'diffEditor.maxFileSize': {\n\t\t\ttype: 'number',\n\t\t\tdefault: 50,\n\t\t\tdescription: nls.localize('maxFileSize', \"Maximum file size in MB for which to compute diffs. Use 0 for no limit.\")\n\t\t},\n\t\t'diffEditor.renderSideBySide': {\n\t\t\ttype: 'boolean',\n\t\t\tdefault: true,\n\t\t\tdescription: nls.localize('sideBySide', \"Controls whether the diff editor shows the diff side by side or inline.\")\n\t\t},\n\t\t'diffEditor.ignoreTrimWhitespace': {\n\t\t\ttype: 'boolean',\n\t\t\tdefault: true,\n\t\t\tdescription: nls.localize('ignoreTrimWhitespace', \"When enabled, the diff editor ignores changes in leading or trailing whitespace.\")\n\t\t},\n\t\t'diffEditor.renderIndicators': {\n\t\t\ttype: 'boolean',\n\t\t\tdefault: true,\n\t\t\tdescription: nls.localize('renderIndicators', \"Controls whether the diff editor shows +/- indicators for added/removed changes.\")\n\t\t},\n\t\t'diffEditor.codeLens': {\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t\tdescription: nls.localize('codeLens', \"Controls whether the editor shows CodeLens.\")\n\t\t},\n\t\t'diffEditor.wordWrap': {\n\t\t\ttype: 'string',\n\t\t\tenum: ['off', 'on', 'inherit'],\n\t\t\tdefault: 'inherit',\n\t\t\tmarkdownEnumDescriptions: [\n\t\t\t\tnls.localize('wordWrap.off', \"Lines will never wrap.\"),\n\t\t\t\tnls.localize('wordWrap.on', \"Lines will wrap at the viewport width.\"),\n\t\t\t\tnls.localize('wordWrap.inherit', \"Lines will wrap according to the `#editor.wordWrap#` setting.\"),\n\t\t\t]\n\t\t}\n\t}\n};\n\nfunction isConfigurationPropertySchema(x: IConfigurationPropertySchema | { [path: string]: IConfigurationPropertySchema; }): x is IConfigurationPropertySchema {\n\treturn (typeof x.type !== 'undefined' || typeof x.anyOf !== 'undefined');\n}\n\n// Add properties from the Editor Option Registry\nfor (const editorOption of editorOptionsRegistry) {\n\tconst schema = editorOption.schema;\n\tif (typeof schema !== 'undefined') {\n\t\tif (isConfigurationPropertySchema(schema)) {\n\t\t\t// This is a single schema contribution\n\t\t\teditorConfiguration.properties![`editor.${editorOption.name}`] = schema;\n\t\t} else {\n\t\t\tfor (const key in schema) {\n\t\t\t\tif (Object.hasOwnProperty.call(schema, key)) {\n\t\t\t\t\teditorConfiguration.properties![key] = schema[key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nlet cachedEditorConfigurationKeys: { [key: string]: boolean; } | null = null;\nfunction getEditorConfigurationKeys(): { [key: string]: boolean; } {\n\tif (cachedEditorConfigurationKeys === null) {\n\t\tcachedEditorConfigurationKeys = <{ [key: string]: boolean; }>Object.create(null);\n\t\tObject.keys(editorConfiguration.properties!).forEach((prop) => {\n\t\t\tcachedEditorConfigurationKeys![prop] = true;\n\t\t});\n\t}\n\treturn cachedEditorConfigurationKeys;\n}\n\nexport function isEditorConfigurationKey(key: string): boolean {\n\tconst editorConfigurationKeys = getEditorConfigurationKeys();\n\treturn (editorConfigurationKeys[`editor.${key}`] || false);\n}\n\nexport function isDiffEditorConfigurationKey(key: string): boolean {\n\tconst editorConfigurationKeys = getEditorConfigurationKeys();\n\treturn (editorConfigurationKeys[`diffEditor.${key}`] || false);\n}\n\nconst configurationRegistry = Registry.as(Extensions.Configuration);\nconfigurationRegistry.registerConfiguration(editorConfiguration);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as nls from 'vs/nls';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { LanguageConfigurationRegistry } from 'vs/editor/common/languages/languageConfigurationRegistry';\nimport { ILanguageExtensionPoint } from 'vs/editor/common/services/language';\nimport { Registry } from 'vs/platform/registry/common/platform';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { Mimes } from 'vs/base/common/mime';\nimport { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';\n\n// Define extension point ids\nexport const Extensions = {\n\tModesRegistry: 'editor.modesRegistry'\n};\n\nexport class EditorModesRegistry {\n\n\tprivate readonly _languages: ILanguageExtensionPoint[];\n\n\tprivate readonly _onDidChangeLanguages = new Emitter();\n\tpublic readonly onDidChangeLanguages: Event = this._onDidChangeLanguages.event;\n\n\tconstructor() {\n\t\tthis._languages = [];\n\t}\n\n\tpublic registerLanguage(def: ILanguageExtensionPoint): IDisposable {\n\t\tthis._languages.push(def);\n\t\tthis._onDidChangeLanguages.fire(undefined);\n\t\treturn {\n\t\t\tdispose: () => {\n\t\t\t\tfor (let i = 0, len = this._languages.length; i < len; i++) {\n\t\t\t\t\tif (this._languages[i] === def) {\n\t\t\t\t\t\tthis._languages.splice(i, 1);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic getLanguages(): ReadonlyArray {\n\t\treturn this._languages;\n\t}\n}\n\nexport const ModesRegistry = new EditorModesRegistry();\nRegistry.add(Extensions.ModesRegistry, ModesRegistry);\n\nexport const PLAINTEXT_LANGUAGE_ID = 'plaintext';\nexport const PLAINTEXT_EXTENSION = '.txt';\n\nModesRegistry.registerLanguage({\n\tid: PLAINTEXT_LANGUAGE_ID,\n\textensions: [PLAINTEXT_EXTENSION],\n\taliases: [nls.localize('plainText.alias', \"Plain Text\"), 'text'],\n\tmimetypes: [Mimes.text]\n});\n\nLanguageConfigurationRegistry.register(PLAINTEXT_LANGUAGE_ID, {\n\tbrackets: [\n\t\t['(', ')'],\n\t\t['[', ']'],\n\t\t['{', '}'],\n\t],\n\tsurroundingPairs: [\n\t\t{ open: '{', close: '}' },\n\t\t{ open: '[', close: ']' },\n\t\t{ open: '(', close: ')' },\n\t\t{ open: '<', close: '>' },\n\t\t{ open: '\\\"', close: '\\\"' },\n\t\t{ open: '\\'', close: '\\'' },\n\t\t{ open: '`', close: '`' },\n\t],\n\tcolorizedBracketPairs: [],\n\tfolding: {\n\t\toffSide: true\n\t}\n}, 0);\n\nRegistry.as(ConfigurationExtensions.Configuration)\n\t.registerDefaultConfigurations([{\n\t\toverrides: {\n\t\t\t'[plaintext]': {\n\t\t\t\t'editor.unicodeHighlight.ambiguousCharacters': false,\n\t\t\t\t'editor.unicodeHighlight.invisibleCharacters': false\n\t\t\t}\n\t\t}\n\t}]);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Schemas } from 'vs/base/common/network';\nimport { DataUri, basenameOrAuthority } from 'vs/base/common/resources';\nimport { URI as uri } from 'vs/base/common/uri';\nimport { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';\nimport { ILanguageService } from 'vs/editor/common/services/language';\nimport { IModelService } from 'vs/editor/common/services/model';\nimport { FileKind } from 'vs/platform/files/common/files';\n\nexport function getIconClasses(modelService: IModelService, languageService: ILanguageService, resource: uri | undefined, fileKind?: FileKind): string[] {\n\n\t// we always set these base classes even if we do not have a path\n\tconst classes = fileKind === FileKind.ROOT_FOLDER ? ['rootfolder-icon'] : fileKind === FileKind.FOLDER ? ['folder-icon'] : ['file-icon'];\n\tif (resource) {\n\n\t\t// Get the path and name of the resource. For data-URIs, we need to parse specially\n\t\tlet name: string | undefined;\n\t\tif (resource.scheme === Schemas.data) {\n\t\t\tconst metadata = DataUri.parseMetaData(resource);\n\t\t\tname = metadata.get(DataUri.META_DATA_LABEL);\n\t\t} else {\n\t\t\tname = cssEscape(basenameOrAuthority(resource).toLowerCase());\n\t\t}\n\n\t\t// Folders\n\t\tif (fileKind === FileKind.FOLDER) {\n\t\t\tclasses.push(`${name}-name-folder-icon`);\n\t\t}\n\n\t\t// Files\n\t\telse {\n\n\t\t\t// Name & Extension(s)\n\t\t\tif (name) {\n\t\t\t\tclasses.push(`${name}-name-file-icon`);\n\t\t\t\t// Avoid doing an explosive combination of extensions for very long filenames\n\t\t\t\t// (most file systems do not allow files > 255 length) with lots of `.` characters\n\t\t\t\t// https://github.com/microsoft/vscode/issues/116199\n\t\t\t\tif (name.length <= 255) {\n\t\t\t\t\tconst dotSegments = name.split('.');\n\t\t\t\t\tfor (let i = 1; i < dotSegments.length; i++) {\n\t\t\t\t\t\tclasses.push(`${dotSegments.slice(i).join('.')}-ext-file-icon`); // add each combination of all found extensions if more than one\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tclasses.push(`ext-file-icon`); // extra segment to increase file-ext score\n\t\t\t}\n\n\t\t\t// Detected Mode\n\t\t\tconst detectedLanguageId = detectLanguageId(modelService, languageService, resource);\n\t\t\tif (detectedLanguageId) {\n\t\t\t\tclasses.push(`${cssEscape(detectedLanguageId)}-lang-file-icon`);\n\t\t\t}\n\t\t}\n\t}\n\treturn classes;\n}\n\nfunction detectLanguageId(modelService: IModelService, languageService: ILanguageService, resource: uri): string | null {\n\tif (!resource) {\n\t\treturn null; // we need a resource at least\n\t}\n\n\tlet languageId: string | null = null;\n\n\t// Data URI: check for encoded metadata\n\tif (resource.scheme === Schemas.data) {\n\t\tconst metadata = DataUri.parseMetaData(resource);\n\t\tconst mime = metadata.get(DataUri.META_DATA_MIME);\n\n\t\tif (mime) {\n\t\t\tlanguageId = languageService.getLanguageIdByMimeType(mime);\n\t\t}\n\t}\n\n\t// Any other URI: check for model if existing\n\telse {\n\t\tconst model = modelService.getModel(resource);\n\t\tif (model) {\n\t\t\tlanguageId = model.getLanguageId();\n\t\t}\n\t}\n\n\t// only take if the language id is specific (aka no just plain text)\n\tif (languageId && languageId !== PLAINTEXT_LANGUAGE_ID) {\n\t\treturn languageId;\n\t}\n\n\t// otherwise fallback to path based detection\n\treturn languageService.guessLanguageIdByFilepathOrFirstLine(resource);\n}\n\nexport function cssEscape(str: string): string {\n\treturn str.replace(/[\\11\\12\\14\\15\\40]/g, '/'); // HTML class names can not contain certain whitespace characters, use / instead, which doesn't exist in file names.\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { coalesce } from 'vs/base/common/arrays';\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';\nimport { clearLanguageAssociations, getMimeTypes, registerLanguageAssociation } from 'vs/editor/common/services/languagesAssociations';\nimport { URI } from 'vs/base/common/uri';\nimport { ILanguageIdCodec, LanguageId } from 'vs/editor/common/languages';\nimport { ModesRegistry, PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';\nimport { ILanguageExtensionPoint, ILanguageIcon } from 'vs/editor/common/services/language';\nimport { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';\nimport { Registry } from 'vs/platform/registry/common/platform';\n\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst NULL_LANGUAGE_ID = 'vs.editor.nullLanguage';\n\nexport interface IResolvedLanguage {\n\tidentifier: string;\n\tname: string | null;\n\tmimetypes: string[];\n\taliases: string[];\n\textensions: string[];\n\tfilenames: string[];\n\tconfigurationFiles: URI[];\n\ticons: ILanguageIcon[];\n}\n\nexport class LanguageIdCodec implements ILanguageIdCodec {\n\n\tprivate _nextLanguageId: number;\n\tprivate readonly _languageIdToLanguage: string[] = [];\n\tprivate readonly _languageToLanguageId = new Map();\n\n\tconstructor() {\n\t\tthis._register(NULL_LANGUAGE_ID, LanguageId.Null);\n\t\tthis._register(PLAINTEXT_LANGUAGE_ID, LanguageId.PlainText);\n\t\tthis._nextLanguageId = 2;\n\t}\n\n\tprivate _register(language: string, languageId: LanguageId): void {\n\t\tthis._languageIdToLanguage[languageId] = language;\n\t\tthis._languageToLanguageId.set(language, languageId);\n\t}\n\n\tpublic register(language: string): void {\n\t\tif (this._languageToLanguageId.has(language)) {\n\t\t\treturn;\n\t\t}\n\t\tconst languageId = this._nextLanguageId++;\n\t\tthis._register(language, languageId);\n\t}\n\n\tpublic encodeLanguageId(languageId: string): LanguageId {\n\t\treturn this._languageToLanguageId.get(languageId) || LanguageId.Null;\n\t}\n\n\tpublic decodeLanguageId(languageId: LanguageId): string {\n\t\treturn this._languageIdToLanguage[languageId] || NULL_LANGUAGE_ID;\n\t}\n}\n\nexport class LanguagesRegistry extends Disposable {\n\n\tstatic instanceCount = 0;\n\n\tprivate readonly _onDidChange: Emitter = this._register(new Emitter());\n\tpublic readonly onDidChange: Event = this._onDidChange.event;\n\n\tprivate readonly _warnOnOverwrite: boolean;\n\tpublic readonly languageIdCodec: LanguageIdCodec;\n\tprivate _dynamicLanguages: ILanguageExtensionPoint[];\n\tprivate _languages: { [id: string]: IResolvedLanguage; };\n\tprivate _mimeTypesMap: { [mimeType: string]: string; };\n\tprivate _nameMap: { [name: string]: string; };\n\tprivate _lowercaseNameMap: { [name: string]: string; };\n\n\tconstructor(useModesRegistry = true, warnOnOverwrite = false) {\n\t\tsuper();\n\t\tLanguagesRegistry.instanceCount++;\n\n\t\tthis._warnOnOverwrite = warnOnOverwrite;\n\t\tthis.languageIdCodec = new LanguageIdCodec();\n\t\tthis._dynamicLanguages = [];\n\t\tthis._languages = {};\n\t\tthis._mimeTypesMap = {};\n\t\tthis._nameMap = {};\n\t\tthis._lowercaseNameMap = {};\n\n\t\tif (useModesRegistry) {\n\t\t\tthis._initializeFromRegistry();\n\t\t\tthis._register(ModesRegistry.onDidChangeLanguages((m) => {\n\t\t\t\tthis._initializeFromRegistry();\n\t\t\t}));\n\t\t}\n\t}\n\n\toverride dispose() {\n\t\tLanguagesRegistry.instanceCount--;\n\t\tsuper.dispose();\n\t}\n\n\tprivate _initializeFromRegistry(): void {\n\t\tthis._languages = {};\n\t\tthis._mimeTypesMap = {};\n\t\tthis._nameMap = {};\n\t\tthis._lowercaseNameMap = {};\n\n\t\tclearLanguageAssociations();\n\t\tconst desc = ([]).concat(ModesRegistry.getLanguages()).concat(this._dynamicLanguages);\n\t\tthis._registerLanguages(desc);\n\t}\n\n\t_registerLanguages(desc: ILanguageExtensionPoint[]): void {\n\n\t\tfor (const d of desc) {\n\t\t\tthis._registerLanguage(d);\n\t\t}\n\n\t\t// Rebuild fast path maps\n\t\tthis._mimeTypesMap = {};\n\t\tthis._nameMap = {};\n\t\tthis._lowercaseNameMap = {};\n\t\tObject.keys(this._languages).forEach((langId) => {\n\t\t\tconst language = this._languages[langId];\n\t\t\tif (language.name) {\n\t\t\t\tthis._nameMap[language.name] = language.identifier;\n\t\t\t}\n\t\t\tlanguage.aliases.forEach((alias) => {\n\t\t\t\tthis._lowercaseNameMap[alias.toLowerCase()] = language.identifier;\n\t\t\t});\n\t\t\tlanguage.mimetypes.forEach((mimetype) => {\n\t\t\t\tthis._mimeTypesMap[mimetype] = language.identifier;\n\t\t\t});\n\t\t});\n\n\t\tRegistry.as(Extensions.Configuration).registerOverrideIdentifiers(this.getRegisteredLanguageIds());\n\n\t\tthis._onDidChange.fire();\n\t}\n\n\tprivate _registerLanguage(lang: ILanguageExtensionPoint): void {\n\t\tconst langId = lang.id;\n\n\t\tlet resolvedLanguage: IResolvedLanguage;\n\t\tif (hasOwnProperty.call(this._languages, langId)) {\n\t\t\tresolvedLanguage = this._languages[langId];\n\t\t} else {\n\t\t\tthis.languageIdCodec.register(langId);\n\t\t\tresolvedLanguage = {\n\t\t\t\tidentifier: langId,\n\t\t\t\tname: null,\n\t\t\t\tmimetypes: [],\n\t\t\t\taliases: [],\n\t\t\t\textensions: [],\n\t\t\t\tfilenames: [],\n\t\t\t\tconfigurationFiles: [],\n\t\t\t\ticons: []\n\t\t\t};\n\t\t\tthis._languages[langId] = resolvedLanguage;\n\t\t}\n\n\t\tthis._mergeLanguage(resolvedLanguage, lang);\n\t}\n\n\tprivate _mergeLanguage(resolvedLanguage: IResolvedLanguage, lang: ILanguageExtensionPoint): void {\n\t\tconst langId = lang.id;\n\n\t\tlet primaryMime: string | null = null;\n\n\t\tif (Array.isArray(lang.mimetypes) && lang.mimetypes.length > 0) {\n\t\t\tresolvedLanguage.mimetypes.push(...lang.mimetypes);\n\t\t\tprimaryMime = lang.mimetypes[0];\n\t\t}\n\n\t\tif (!primaryMime) {\n\t\t\tprimaryMime = `text/x-${langId}`;\n\t\t\tresolvedLanguage.mimetypes.push(primaryMime);\n\t\t}\n\n\t\tif (Array.isArray(lang.extensions)) {\n\t\t\tif (lang.configuration) {\n\t\t\t\t// insert first as this appears to be the 'primary' language definition\n\t\t\t\tresolvedLanguage.extensions = lang.extensions.concat(resolvedLanguage.extensions);\n\t\t\t} else {\n\t\t\t\tresolvedLanguage.extensions = resolvedLanguage.extensions.concat(lang.extensions);\n\t\t\t}\n\t\t\tfor (let extension of lang.extensions) {\n\t\t\t\tregisterLanguageAssociation({ id: langId, mime: primaryMime, extension: extension }, this._warnOnOverwrite);\n\t\t\t}\n\t\t}\n\n\t\tif (Array.isArray(lang.filenames)) {\n\t\t\tfor (let filename of lang.filenames) {\n\t\t\t\tregisterLanguageAssociation({ id: langId, mime: primaryMime, filename: filename }, this._warnOnOverwrite);\n\t\t\t\tresolvedLanguage.filenames.push(filename);\n\t\t\t}\n\t\t}\n\n\t\tif (Array.isArray(lang.filenamePatterns)) {\n\t\t\tfor (let filenamePattern of lang.filenamePatterns) {\n\t\t\t\tregisterLanguageAssociation({ id: langId, mime: primaryMime, filepattern: filenamePattern }, this._warnOnOverwrite);\n\t\t\t}\n\t\t}\n\n\t\tif (typeof lang.firstLine === 'string' && lang.firstLine.length > 0) {\n\t\t\tlet firstLineRegexStr = lang.firstLine;\n\t\t\tif (firstLineRegexStr.charAt(0) !== '^') {\n\t\t\t\tfirstLineRegexStr = '^' + firstLineRegexStr;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst firstLineRegex = new RegExp(firstLineRegexStr);\n\t\t\t\tif (!regExpLeadsToEndlessLoop(firstLineRegex)) {\n\t\t\t\t\tregisterLanguageAssociation({ id: langId, mime: primaryMime, firstline: firstLineRegex }, this._warnOnOverwrite);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// Most likely, the regex was bad\n\t\t\t\tonUnexpectedError(err);\n\t\t\t}\n\t\t}\n\n\t\tresolvedLanguage.aliases.push(langId);\n\n\t\tlet langAliases: Array | null = null;\n\t\tif (typeof lang.aliases !== 'undefined' && Array.isArray(lang.aliases)) {\n\t\t\tif (lang.aliases.length === 0) {\n\t\t\t\t// signal that this language should not get a name\n\t\t\t\tlangAliases = [null];\n\t\t\t} else {\n\t\t\t\tlangAliases = lang.aliases;\n\t\t\t}\n\t\t}\n\n\t\tif (langAliases !== null) {\n\t\t\tfor (const langAlias of langAliases) {\n\t\t\t\tif (!langAlias || langAlias.length === 0) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tresolvedLanguage.aliases.push(langAlias);\n\t\t\t}\n\t\t}\n\n\t\tconst containsAliases = (langAliases !== null && langAliases.length > 0);\n\t\tif (containsAliases && langAliases![0] === null) {\n\t\t\t// signal that this language should not get a name\n\t\t} else {\n\t\t\tconst bestName = (containsAliases ? langAliases![0] : null) || langId;\n\t\t\tif (containsAliases || !resolvedLanguage.name) {\n\t\t\t\tresolvedLanguage.name = bestName;\n\t\t\t}\n\t\t}\n\n\t\tif (lang.configuration) {\n\t\t\tresolvedLanguage.configurationFiles.push(lang.configuration);\n\t\t}\n\n\t\tif (lang.icon) {\n\t\t\tresolvedLanguage.icons.push(lang.icon);\n\t\t}\n\t}\n\n\tpublic isRegisteredLanguageId(languageId: string | null | undefined): boolean {\n\t\tif (!languageId) {\n\t\t\treturn false;\n\t\t}\n\t\treturn hasOwnProperty.call(this._languages, languageId);\n\t}\n\n\tpublic getRegisteredLanguageIds(): string[] {\n\t\treturn Object.keys(this._languages);\n\t}\n\n\tpublic getLanguageIdByLanguageName(languageName: string): string | null {\n\t\tconst languageNameLower = languageName.toLowerCase();\n\t\tif (!hasOwnProperty.call(this._lowercaseNameMap, languageNameLower)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn this._lowercaseNameMap[languageNameLower];\n\t}\n\n\tpublic getLanguageIdByMimeType(mimeType: string | null | undefined): string | null {\n\t\tif (!mimeType) {\n\t\t\treturn null;\n\t\t}\n\t\tif (hasOwnProperty.call(this._mimeTypesMap, mimeType)) {\n\t\t\treturn this._mimeTypesMap[mimeType];\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic guessLanguageIdByFilepathOrFirstLine(resource: URI | null, firstLine?: string): string[] {\n\t\tif (!resource && !firstLine) {\n\t\t\treturn [];\n\t\t}\n\t\tconst mimeTypes = getMimeTypes(resource, firstLine);\n\t\treturn coalesce(mimeTypes.map(mimeType => this.getLanguageIdByMimeType(mimeType)));\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport { URI } from 'vs/base/common/uri';\nimport { LanguagesRegistry } from 'vs/editor/common/services/languagesRegistry';\nimport { ILanguageSelection, ILanguageService } from 'vs/editor/common/services/language';\nimport { firstOrDefault } from 'vs/base/common/arrays';\nimport { ILanguageIdCodec, TokenizationRegistry } from 'vs/editor/common/languages';\nimport { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';\n\nexport class LanguageService extends Disposable implements ILanguageService {\n\tpublic _serviceBrand: undefined;\n\n\tstatic instanceCount = 0;\n\n\tprivate readonly _encounteredLanguages: Set;\n\tprotected readonly _registry: LanguagesRegistry;\n\tpublic readonly languageIdCodec: ILanguageIdCodec;\n\n\tprivate readonly _onDidEncounterLanguage = this._register(new Emitter());\n\tpublic readonly onDidEncounterLanguage: Event = this._onDidEncounterLanguage.event;\n\n\tprotected readonly _onDidChange = this._register(new Emitter({ leakWarningThreshold: 200 /* https://github.com/microsoft/vscode/issues/119968 */ }));\n\tpublic readonly onDidChange: Event = this._onDidChange.event;\n\n\tconstructor(warnOnOverwrite = false) {\n\t\tsuper();\n\t\tLanguageService.instanceCount++;\n\t\tthis._encounteredLanguages = new Set();\n\t\tthis._registry = this._register(new LanguagesRegistry(true, warnOnOverwrite));\n\t\tthis.languageIdCodec = this._registry.languageIdCodec;\n\t\tthis._register(this._registry.onDidChange(() => this._onDidChange.fire()));\n\t}\n\n\tpublic override dispose(): void {\n\t\tLanguageService.instanceCount--;\n\t\tsuper.dispose();\n\t}\n\n\tpublic isRegisteredLanguageId(languageId: string | null | undefined): boolean {\n\t\treturn this._registry.isRegisteredLanguageId(languageId);\n\t}\n\n\tpublic getLanguageIdByLanguageName(languageName: string): string | null {\n\t\treturn this._registry.getLanguageIdByLanguageName(languageName);\n\t}\n\n\tpublic getLanguageIdByMimeType(mimeType: string | null | undefined): string | null {\n\t\treturn this._registry.getLanguageIdByMimeType(mimeType);\n\t}\n\n\tpublic guessLanguageIdByFilepathOrFirstLine(resource: URI | null, firstLine?: string): string | null {\n\t\tconst languageIds = this._registry.guessLanguageIdByFilepathOrFirstLine(resource, firstLine);\n\t\treturn firstOrDefault(languageIds, null);\n\t}\n\n\tpublic createById(languageId: string | null | undefined): ILanguageSelection {\n\t\treturn new LanguageSelection(this.onDidChange, () => {\n\t\t\treturn this._createAndGetLanguageIdentifier(languageId);\n\t\t});\n\t}\n\n\tpublic createByFilepathOrFirstLine(resource: URI | null, firstLine?: string): ILanguageSelection {\n\t\treturn new LanguageSelection(this.onDidChange, () => {\n\t\t\tconst languageId = this.guessLanguageIdByFilepathOrFirstLine(resource, firstLine);\n\t\t\treturn this._createAndGetLanguageIdentifier(languageId);\n\t\t});\n\t}\n\n\tprivate _createAndGetLanguageIdentifier(languageId: string | null | undefined): string {\n\t\tif (!languageId || !this.isRegisteredLanguageId(languageId)) {\n\t\t\t// Fall back to plain text if language is unknown\n\t\t\tlanguageId = PLAINTEXT_LANGUAGE_ID;\n\t\t}\n\n\t\tif (!this._encounteredLanguages.has(languageId)) {\n\t\t\tthis._encounteredLanguages.add(languageId);\n\n\t\t\t// Ensure tokenizers are created\n\t\t\tTokenizationRegistry.getOrCreate(languageId);\n\n\t\t\t// Fire event\n\t\t\tthis._onDidEncounterLanguage.fire(languageId);\n\t\t}\n\n\t\treturn languageId;\n\t}\n}\n\nclass LanguageSelection implements ILanguageSelection {\n\n\tpublic languageId: string;\n\n\tprivate _listener: IDisposable | null = null;\n\tprivate _emitter: Emitter | null = null;\n\n\tconstructor(\n\t\tprivate readonly _onDidChangeLanguages: Event,\n\t\tprivate readonly _selector: () => string\n\t) {\n\t\tthis.languageId = this._selector();\n\t}\n\n\tprivate _dispose(): void {\n\t\tif (this._listener) {\n\t\t\tthis._listener.dispose();\n\t\t\tthis._listener = null;\n\t\t}\n\t\tif (this._emitter) {\n\t\t\tthis._emitter.dispose();\n\t\t\tthis._emitter = null;\n\t\t}\n\t}\n\n\tpublic get onDidChange(): Event {\n\t\tif (!this._listener) {\n\t\t\tthis._listener = this._onDidChangeLanguages(() => this._evaluate());\n\t\t}\n\t\tif (!this._emitter) {\n\t\t\tthis._emitter = new Emitter({\n\t\t\t\tonLastListenerRemove: () => {\n\t\t\t\t\tthis._dispose();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\treturn this._emitter.event;\n\t}\n\n\tprivate _evaluate(): void {\n\t\tconst languageId = this._selector();\n\t\tif (languageId === this.languageId) {\n\t\t\t// no change\n\t\t\treturn;\n\t\t}\n\t\tthis.languageId = languageId;\n\t\tif (this._emitter) {\n\t\t\tthis._emitter.fire(this.languageId);\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IMarkdownString } from 'vs/base/common/htmlContent';\nimport { renderMarkdown, MarkdownRenderOptions, MarkedOptions } from 'vs/base/browser/markdownRenderer';\nimport { IOpenerService } from 'vs/platform/opener/common/opener';\nimport { ILanguageService } from 'vs/editor/common/services/language';\nimport { onUnexpectedError } from 'vs/base/common/errors';\nimport { tokenizeToString } from 'vs/editor/common/languages/textToHtmlTokenizer';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { Emitter } from 'vs/base/common/event';\nimport { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { URI } from 'vs/base/common/uri';\nimport { applyFontInfo } from 'vs/editor/browser/config/domFontInfo';\nimport { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';\n\nexport interface IMarkdownRenderResult extends IDisposable {\n\telement: HTMLElement;\n}\n\nexport interface IMarkdownRendererOptions {\n\teditor?: ICodeEditor;\n\tbaseUrl?: URI;\n\tcodeBlockFontFamily?: string;\n}\n\n/**\n * Markdown renderer that can render codeblocks with the editor mechanics. This\n * renderer should always be preferred.\n */\nexport class MarkdownRenderer {\n\n\tprivate static _ttpTokenizer = window.trustedTypes?.createPolicy('tokenizeToString', {\n\t\tcreateHTML(html: string) {\n\t\t\treturn html;\n\t\t}\n\t});\n\n\tprivate readonly _onDidRenderAsync = new Emitter();\n\treadonly onDidRenderAsync = this._onDidRenderAsync.event;\n\n\tconstructor(\n\t\tprivate readonly _options: IMarkdownRendererOptions,\n\t\t@ILanguageService private readonly _languageService: ILanguageService,\n\t\t@IOpenerService private readonly _openerService: IOpenerService,\n\t) { }\n\n\tdispose(): void {\n\t\tthis._onDidRenderAsync.dispose();\n\t}\n\n\trender(markdown: IMarkdownString | undefined, options?: MarkdownRenderOptions, markedOptions?: MarkedOptions): IMarkdownRenderResult {\n\t\tif (!markdown) {\n\t\t\tconst element = document.createElement('span');\n\t\t\treturn { element, dispose: () => { } };\n\t\t}\n\n\t\tconst disposables = new DisposableStore();\n\t\tconst rendered = disposables.add(renderMarkdown(markdown, { ...this._getRenderOptions(markdown, disposables), ...options }, markedOptions));\n\t\treturn {\n\t\t\telement: rendered.element,\n\t\t\tdispose: () => disposables.dispose()\n\t\t};\n\t}\n\n\tprotected _getRenderOptions(markdown: IMarkdownString, disposeables: DisposableStore): MarkdownRenderOptions {\n\t\treturn {\n\t\t\tbaseUrl: this._options.baseUrl,\n\t\t\tcodeBlockRenderer: async (languageAlias, value) => {\n\t\t\t\t// In markdown,\n\t\t\t\t// it is possible that we stumble upon language aliases (e.g.js instead of javascript)\n\t\t\t\t// it is possible no alias is given in which case we fall back to the current editor lang\n\t\t\t\tlet languageId: string | undefined | null;\n\t\t\t\tif (languageAlias) {\n\t\t\t\t\tlanguageId = this._languageService.getLanguageIdByLanguageName(languageAlias);\n\t\t\t\t} else if (this._options.editor) {\n\t\t\t\t\tlanguageId = this._options.editor.getModel()?.getLanguageId();\n\t\t\t\t}\n\t\t\t\tif (!languageId) {\n\t\t\t\t\tlanguageId = PLAINTEXT_LANGUAGE_ID;\n\t\t\t\t}\n\t\t\t\tconst html = await tokenizeToString(this._languageService, value, languageId);\n\n\t\t\t\tconst element = document.createElement('span');\n\n\t\t\t\telement.innerHTML = (MarkdownRenderer._ttpTokenizer?.createHTML(html) ?? html) as string;\n\n\t\t\t\t// use \"good\" font\n\t\t\t\tif (this._options.editor) {\n\t\t\t\t\tconst fontInfo = this._options.editor.getOption(EditorOption.fontInfo);\n\t\t\t\t\tapplyFontInfo(element, fontInfo);\n\t\t\t\t} else if (this._options.codeBlockFontFamily) {\n\t\t\t\t\telement.style.fontFamily = this._options.codeBlockFontFamily;\n\t\t\t\t}\n\n\t\t\t\treturn element;\n\t\t\t},\n\t\t\tasyncRenderCallback: () => this._onDidRenderAsync.fire(),\n\t\t\tactionHandler: {\n\t\t\t\tcallback: (content) => this._openerService.open(content, { fromUserGesture: true, allowContributedOpeners: true, allowCommands: markdown.isTrusted }).catch(onUnexpectedError),\n\t\t\t\tdisposables: disposeables\n\t\t\t}\n\t\t};\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { asArray } from 'vs/base/common/arrays';\nimport { IMarkdownString, isEmptyMarkdownString } from 'vs/base/common/htmlContent';\nimport { Disposable, DisposableStore } from 'vs/base/common/lifecycle';\nimport { MarkdownRenderer } from 'vs/editor/contrib/markdownRenderer/browser/markdownRenderer';\nimport { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition } from 'vs/editor/browser/editorBrowser';\nimport { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { ILanguageService } from 'vs/editor/common/services/language';\nimport { HoverOperation, HoverStartMode, IHoverComputer } from 'vs/editor/contrib/hover/browser/hoverOperation';\nimport { IOpenerService, NullOpenerService } from 'vs/platform/opener/common/opener';\nimport { HoverWidget } from 'vs/base/browser/ui/hover/hoverWidget';\n\nconst $ = dom.$;\n\nexport interface IHoverMessage {\n\tvalue: IMarkdownString;\n}\n\nexport class MarginHoverWidget extends Disposable implements IOverlayWidget {\n\n\tpublic static readonly ID = 'editor.contrib.modesGlyphHoverWidget';\n\n\tprivate readonly _editor: ICodeEditor;\n\tprivate readonly _hover: HoverWidget;\n\n\tprivate _isVisible: boolean;\n\tprivate _messages: IHoverMessage[];\n\n\tprivate readonly _markdownRenderer: MarkdownRenderer;\n\tprivate readonly _computer: MarginHoverComputer;\n\tprivate readonly _hoverOperation: HoverOperation;\n\tprivate readonly _renderDisposeables = this._register(new DisposableStore());\n\n\tconstructor(\n\t\teditor: ICodeEditor,\n\t\tlanguageService: ILanguageService,\n\t\topenerService: IOpenerService = NullOpenerService,\n\t) {\n\t\tsuper();\n\t\tthis._editor = editor;\n\n\t\tthis._isVisible = false;\n\t\tthis._messages = [];\n\n\t\tthis._hover = this._register(new HoverWidget());\n\t\tthis._hover.containerDomNode.classList.toggle('hidden', !this._isVisible);\n\n\t\tthis._markdownRenderer = this._register(new MarkdownRenderer({ editor: this._editor }, languageService, openerService));\n\t\tthis._computer = new MarginHoverComputer(this._editor);\n\t\tthis._hoverOperation = this._register(new HoverOperation(this._editor, this._computer));\n\t\tthis._register(this._hoverOperation.onResult((result) => {\n\t\t\tthis._withResult(result.value);\n\t\t}));\n\n\t\tthis._register(this._editor.onDidChangeModelDecorations(() => this._onModelDecorationsChanged()));\n\t\tthis._register(this._editor.onDidChangeConfiguration((e: ConfigurationChangedEvent) => {\n\t\t\tif (e.hasChanged(EditorOption.fontInfo)) {\n\t\t\t\tthis._updateFont();\n\t\t\t}\n\t\t}));\n\n\t\tthis._editor.addOverlayWidget(this);\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._editor.removeOverlayWidget(this);\n\t\tsuper.dispose();\n\t}\n\n\tpublic getId(): string {\n\t\treturn MarginHoverWidget.ID;\n\t}\n\n\tpublic getDomNode(): HTMLElement {\n\t\treturn this._hover.containerDomNode;\n\t}\n\n\tpublic getPosition(): IOverlayWidgetPosition | null {\n\t\treturn null;\n\t}\n\n\tprivate _updateFont(): void {\n\t\tconst codeClasses: HTMLElement[] = Array.prototype.slice.call(this._hover.contentsDomNode.getElementsByClassName('code'));\n\t\tcodeClasses.forEach(node => this._editor.applyFontInfo(node));\n\t}\n\n\tprivate _onModelDecorationsChanged(): void {\n\t\tif (this._isVisible) {\n\t\t\t// The decorations have changed and the hover is visible,\n\t\t\t// we need to recompute the displayed text\n\t\t\tthis._hoverOperation.cancel();\n\t\t\tthis._hoverOperation.start(HoverStartMode.Delayed);\n\t\t}\n\t}\n\n\tpublic startShowingAt(lineNumber: number): void {\n\t\tif (this._computer.lineNumber === lineNumber) {\n\t\t\t// We have to show the widget at the exact same line number as before, so no work is needed\n\t\t\treturn;\n\t\t}\n\n\t\tthis._hoverOperation.cancel();\n\n\t\tthis.hide();\n\n\t\tthis._computer.lineNumber = lineNumber;\n\t\tthis._hoverOperation.start(HoverStartMode.Delayed);\n\t}\n\n\tpublic hide(): void {\n\t\tthis._computer.lineNumber = -1;\n\t\tthis._hoverOperation.cancel();\n\t\tif (!this._isVisible) {\n\t\t\treturn;\n\t\t}\n\t\tthis._isVisible = false;\n\t\tthis._hover.containerDomNode.classList.toggle('hidden', !this._isVisible);\n\t}\n\n\tprivate _withResult(result: IHoverMessage[]): void {\n\t\tthis._messages = result;\n\n\t\tif (this._messages.length > 0) {\n\t\t\tthis._renderMessages(this._computer.lineNumber, this._messages);\n\t\t} else {\n\t\t\tthis.hide();\n\t\t}\n\t}\n\n\tprivate _renderMessages(lineNumber: number, messages: IHoverMessage[]): void {\n\t\tthis._renderDisposeables.clear();\n\n\t\tconst fragment = document.createDocumentFragment();\n\n\t\tfor (const msg of messages) {\n\t\t\tconst markdownHoverElement = $('div.hover-row.markdown-hover');\n\t\t\tconst hoverContentsElement = dom.append(markdownHoverElement, $('div.hover-contents'));\n\t\t\tconst renderedContents = this._renderDisposeables.add(this._markdownRenderer.render(msg.value));\n\t\t\thoverContentsElement.appendChild(renderedContents.element);\n\t\t\tfragment.appendChild(markdownHoverElement);\n\t\t}\n\n\t\tthis._updateContents(fragment);\n\t\tthis._showAt(lineNumber);\n\t}\n\n\tprivate _updateContents(node: Node): void {\n\t\tthis._hover.contentsDomNode.textContent = '';\n\t\tthis._hover.contentsDomNode.appendChild(node);\n\t\tthis._updateFont();\n\t}\n\n\tprivate _showAt(lineNumber: number): void {\n\t\tif (!this._isVisible) {\n\t\t\tthis._isVisible = true;\n\t\t\tthis._hover.containerDomNode.classList.toggle('hidden', !this._isVisible);\n\t\t}\n\n\t\tconst editorLayout = this._editor.getLayoutInfo();\n\t\tconst topForLineNumber = this._editor.getTopForLineNumber(lineNumber);\n\t\tconst editorScrollTop = this._editor.getScrollTop();\n\t\tconst lineHeight = this._editor.getOption(EditorOption.lineHeight);\n\t\tconst nodeHeight = this._hover.containerDomNode.clientHeight;\n\t\tconst top = topForLineNumber - editorScrollTop - ((nodeHeight - lineHeight) / 2);\n\n\t\tthis._hover.containerDomNode.style.left = `${editorLayout.glyphMarginLeft + editorLayout.glyphMarginWidth}px`;\n\t\tthis._hover.containerDomNode.style.top = `${Math.max(Math.round(top), 0)}px`;\n\t}\n}\n\nclass MarginHoverComputer implements IHoverComputer {\n\n\tprivate _lineNumber: number = -1;\n\n\tpublic get lineNumber(): number {\n\t\treturn this._lineNumber;\n\t}\n\n\tpublic set lineNumber(value: number) {\n\t\tthis._lineNumber = value;\n\t}\n\n\tconstructor(\n\t\tprivate readonly _editor: ICodeEditor\n\t) {\n\t}\n\n\tpublic computeSync(): IHoverMessage[] {\n\n\t\tconst toHoverMessage = (contents: IMarkdownString): IHoverMessage => {\n\t\t\treturn {\n\t\t\t\tvalue: contents\n\t\t\t};\n\t\t};\n\n\t\tconst lineDecorations = this._editor.getLineDecorations(this._lineNumber);\n\n\t\tconst result: IHoverMessage[] = [];\n\t\tif (!lineDecorations) {\n\t\t\treturn result;\n\t\t}\n\n\t\tfor (const d of lineDecorations) {\n\t\t\tif (!d.options.glyphMarginClassName) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst hoverMessage = d.options.glyphMarginHoverMessage;\n\t\t\tif (!hoverMessage || isEmptyMarkdownString(hoverMessage)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tresult.push(...asArray(hoverMessage).map(toHoverMessage));\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { isSafari } from 'vs/base/browser/browser';\nimport * as dom from 'vs/base/browser/dom';\nimport { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';\nimport { Codicon } from 'vs/base/common/codicons';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { MarkdownString } from 'vs/base/common/htmlContent';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\nimport { MarkdownRenderer } from 'vs/editor/contrib/markdownRenderer/browser/markdownRenderer';\nimport { ICodeEditor, IOverlayWidget } from 'vs/editor/browser/editorBrowser';\nimport { EditorOption, EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions';\nimport { ResizableHTMLElement } from 'vs/editor/contrib/suggest/browser/resizable';\nimport * as nls from 'vs/nls';\nimport { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';\nimport { CompletionItem } from './suggest';\n\nexport function canExpandCompletionItem(item: CompletionItem | undefined): boolean {\n\treturn !!item && Boolean(item.completion.documentation || item.completion.detail && item.completion.detail !== item.completion.label);\n}\n\nexport class SuggestDetailsWidget {\n\n\treadonly domNode: HTMLDivElement;\n\n\tprivate readonly _onDidClose = new Emitter();\n\treadonly onDidClose: Event = this._onDidClose.event;\n\n\tprivate readonly _onDidChangeContents = new Emitter();\n\treadonly onDidChangeContents: Event = this._onDidChangeContents.event;\n\n\tprivate readonly _close: HTMLElement;\n\tprivate readonly _scrollbar: DomScrollableElement;\n\tprivate readonly _body: HTMLElement;\n\tprivate readonly _header: HTMLElement;\n\tprivate readonly _type: HTMLElement;\n\tprivate readonly _docs: HTMLElement;\n\tprivate readonly _disposables = new DisposableStore();\n\n\tprivate readonly _markdownRenderer: MarkdownRenderer;\n\tprivate readonly _renderDisposeable = new DisposableStore();\n\tprivate _borderWidth: number = 1;\n\tprivate _size = new dom.Dimension(330, 0);\n\n\tconstructor(\n\t\tprivate readonly _editor: ICodeEditor,\n\t\t@IInstantiationService instaService: IInstantiationService,\n\t) {\n\t\tthis.domNode = dom.$('.suggest-details');\n\t\tthis.domNode.classList.add('no-docs');\n\n\t\tthis._markdownRenderer = instaService.createInstance(MarkdownRenderer, { editor: _editor });\n\n\t\tthis._body = dom.$('.body');\n\n\t\tthis._scrollbar = new DomScrollableElement(this._body, {});\n\t\tdom.append(this.domNode, this._scrollbar.getDomNode());\n\t\tthis._disposables.add(this._scrollbar);\n\n\t\tthis._header = dom.append(this._body, dom.$('.header'));\n\t\tthis._close = dom.append(this._header, dom.$('span' + Codicon.close.cssSelector));\n\t\tthis._close.title = nls.localize('details.close', \"Close\");\n\t\tthis._type = dom.append(this._header, dom.$('p.type'));\n\n\t\tthis._docs = dom.append(this._body, dom.$('p.docs'));\n\n\t\tthis._configureFont();\n\n\t\tthis._disposables.add(this._editor.onDidChangeConfiguration(e => {\n\t\t\tif (e.hasChanged(EditorOption.fontInfo)) {\n\t\t\t\tthis._configureFont();\n\t\t\t}\n\t\t}));\n\t}\n\n\tdispose(): void {\n\t\tthis._disposables.dispose();\n\t\tthis._renderDisposeable.dispose();\n\t}\n\n\tprivate _configureFont(): void {\n\t\tconst options = this._editor.getOptions();\n\t\tconst fontInfo = options.get(EditorOption.fontInfo);\n\t\tconst fontFamily = fontInfo.getMassagedFontFamily(isSafari ? EDITOR_FONT_DEFAULTS.fontFamily : null);\n\t\tconst fontSize = options.get(EditorOption.suggestFontSize) || fontInfo.fontSize;\n\t\tconst lineHeight = options.get(EditorOption.suggestLineHeight) || fontInfo.lineHeight;\n\t\tconst fontWeight = fontInfo.fontWeight;\n\t\tconst fontSizePx = `${fontSize}px`;\n\t\tconst lineHeightPx = `${lineHeight}px`;\n\n\t\tthis.domNode.style.fontSize = fontSizePx;\n\t\tthis.domNode.style.lineHeight = `${lineHeight / fontSize}`;\n\t\tthis.domNode.style.fontWeight = fontWeight;\n\t\tthis.domNode.style.fontFeatureSettings = fontInfo.fontFeatureSettings;\n\t\tthis._type.style.fontFamily = fontFamily;\n\t\tthis._close.style.height = lineHeightPx;\n\t\tthis._close.style.width = lineHeightPx;\n\t}\n\n\tgetLayoutInfo() {\n\t\tconst lineHeight = this._editor.getOption(EditorOption.suggestLineHeight) || this._editor.getOption(EditorOption.fontInfo).lineHeight;\n\t\tconst borderWidth = this._borderWidth;\n\t\tconst borderHeight = borderWidth * 2;\n\t\treturn {\n\t\t\tlineHeight,\n\t\t\tborderWidth,\n\t\t\tborderHeight,\n\t\t\tverticalPadding: 22,\n\t\t\thorizontalPadding: 14\n\t\t};\n\t}\n\n\n\trenderLoading(): void {\n\t\tthis._type.textContent = nls.localize('loading', \"Loading...\");\n\t\tthis._docs.textContent = '';\n\t\tthis.domNode.classList.remove('no-docs', 'no-type');\n\t\tthis.layout(this.size.width, this.getLayoutInfo().lineHeight * 2);\n\t\tthis._onDidChangeContents.fire(this);\n\t}\n\n\trenderItem(item: CompletionItem, explainMode: boolean): void {\n\t\tthis._renderDisposeable.clear();\n\n\t\tlet { detail, documentation } = item.completion;\n\n\t\tif (explainMode) {\n\t\t\tlet md = '';\n\t\t\tmd += `score: ${item.score[0]}\\n`;\n\t\t\tmd += `prefix: ${item.word ?? '(no prefix)'}\\n`;\n\t\t\tmd += `word: ${item.completion.filterText ? item.completion.filterText + ' (filterText)' : item.textLabel}\\n`;\n\t\t\tmd += `distance: ${item.distance} (localityBonus-setting)\\n`;\n\t\t\tmd += `index: ${item.idx}, based on ${item.completion.sortText && `sortText: \"${item.completion.sortText}\"` || 'label'}\\n`;\n\t\t\tmd += `commit_chars: ${item.completion.commitCharacters?.join('')}\\n`;\n\t\t\tdocumentation = new MarkdownString().appendCodeblock('empty', md);\n\t\t\tdetail = `Provider: ${item.provider._debugDisplayName}`;\n\t\t}\n\n\t\tif (!explainMode && !canExpandCompletionItem(item)) {\n\t\t\tthis.clearContents();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.domNode.classList.remove('no-docs', 'no-type');\n\n\t\t// --- details\n\n\t\tif (detail) {\n\t\t\tconst cappedDetail = detail.length > 100000 ? `${detail.substr(0, 100000)}…` : detail;\n\t\t\tthis._type.textContent = cappedDetail;\n\t\t\tthis._type.title = cappedDetail;\n\t\t\tdom.show(this._type);\n\t\t\tthis._type.classList.toggle('auto-wrap', !/\\r?\\n^\\s+/gmi.test(cappedDetail));\n\t\t} else {\n\t\t\tdom.clearNode(this._type);\n\t\t\tthis._type.title = '';\n\t\t\tdom.hide(this._type);\n\t\t\tthis.domNode.classList.add('no-type');\n\t\t}\n\n\t\t// --- documentation\n\t\tdom.clearNode(this._docs);\n\t\tif (typeof documentation === 'string') {\n\t\t\tthis._docs.classList.remove('markdown-docs');\n\t\t\tthis._docs.textContent = documentation;\n\n\t\t} else if (documentation) {\n\t\t\tthis._docs.classList.add('markdown-docs');\n\t\t\tdom.clearNode(this._docs);\n\t\t\tconst renderedContents = this._markdownRenderer.render(documentation);\n\t\t\tthis._docs.appendChild(renderedContents.element);\n\t\t\tthis._renderDisposeable.add(renderedContents);\n\t\t\tthis._renderDisposeable.add(this._markdownRenderer.onDidRenderAsync(() => {\n\t\t\t\tthis.layout(this._size.width, this._type.clientHeight + this._docs.clientHeight);\n\t\t\t\tthis._onDidChangeContents.fire(this);\n\t\t\t}));\n\t\t}\n\n\t\tthis.domNode.style.userSelect = 'text';\n\t\tthis.domNode.tabIndex = -1;\n\n\t\tthis._close.onmousedown = e => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t};\n\t\tthis._close.onclick = e => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tthis._onDidClose.fire();\n\t\t};\n\n\t\tthis._body.scrollTop = 0;\n\n\t\tthis.layout(this._size.width, this._type.clientHeight + this._docs.clientHeight);\n\t\tthis._onDidChangeContents.fire(this);\n\t}\n\n\tclearContents() {\n\t\tthis.domNode.classList.add('no-docs');\n\t\tthis._type.textContent = '';\n\t\tthis._docs.textContent = '';\n\t}\n\n\tget size() {\n\t\treturn this._size;\n\t}\n\n\tlayout(width: number, height: number): void {\n\t\tconst newSize = new dom.Dimension(width, height);\n\t\tif (!dom.Dimension.equals(newSize, this._size)) {\n\t\t\tthis._size = newSize;\n\t\t\tdom.size(this.domNode, width, height);\n\t\t}\n\t\tthis._scrollbar.scanDomNode();\n\t}\n\n\tscrollDown(much = 8): void {\n\t\tthis._body.scrollTop += much;\n\t}\n\n\tscrollUp(much = 8): void {\n\t\tthis._body.scrollTop -= much;\n\t}\n\n\tscrollTop(): void {\n\t\tthis._body.scrollTop = 0;\n\t}\n\n\tscrollBottom(): void {\n\t\tthis._body.scrollTop = this._body.scrollHeight;\n\t}\n\n\tpageDown(): void {\n\t\tthis.scrollDown(80);\n\t}\n\n\tpageUp(): void {\n\t\tthis.scrollUp(80);\n\t}\n\n\tset borderWidth(width: number) {\n\t\tthis._borderWidth = width;\n\t}\n\n\tget borderWidth() {\n\t\treturn this._borderWidth;\n\t}\n}\n\ninterface TopLeftPosition {\n\ttop: number;\n\tleft: number;\n}\n\nexport class SuggestDetailsOverlay implements IOverlayWidget {\n\n\tprivate readonly _disposables = new DisposableStore();\n\tprivate readonly _resizable: ResizableHTMLElement;\n\n\tprivate _added: boolean = false;\n\tprivate _anchorBox?: dom.IDomNodePagePosition;\n\tprivate _preferAlignAtTop: boolean = true;\n\tprivate _userSize?: dom.Dimension;\n\tprivate _topLeft?: TopLeftPosition;\n\n\tconstructor(\n\t\treadonly widget: SuggestDetailsWidget,\n\t\tprivate readonly _editor: ICodeEditor\n\t) {\n\n\t\tthis._resizable = new ResizableHTMLElement();\n\t\tthis._resizable.domNode.classList.add('suggest-details-container');\n\t\tthis._resizable.domNode.appendChild(widget.domNode);\n\t\tthis._resizable.enableSashes(false, true, true, false);\n\n\t\tlet topLeftNow: TopLeftPosition | undefined;\n\t\tlet sizeNow: dom.Dimension | undefined;\n\t\tlet deltaTop: number = 0;\n\t\tlet deltaLeft: number = 0;\n\t\tthis._disposables.add(this._resizable.onDidWillResize(() => {\n\t\t\ttopLeftNow = this._topLeft;\n\t\t\tsizeNow = this._resizable.size;\n\t\t}));\n\n\t\tthis._disposables.add(this._resizable.onDidResize(e => {\n\t\t\tif (topLeftNow && sizeNow) {\n\t\t\t\tthis.widget.layout(e.dimension.width, e.dimension.height);\n\n\t\t\t\tlet updateTopLeft = false;\n\t\t\t\tif (e.west) {\n\t\t\t\t\tdeltaLeft = sizeNow.width - e.dimension.width;\n\t\t\t\t\tupdateTopLeft = true;\n\t\t\t\t}\n\t\t\t\tif (e.north) {\n\t\t\t\t\tdeltaTop = sizeNow.height - e.dimension.height;\n\t\t\t\t\tupdateTopLeft = true;\n\t\t\t\t}\n\t\t\t\tif (updateTopLeft) {\n\t\t\t\t\tthis._applyTopLeft({\n\t\t\t\t\t\ttop: topLeftNow.top + deltaTop,\n\t\t\t\t\t\tleft: topLeftNow.left + deltaLeft,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (e.done) {\n\t\t\t\ttopLeftNow = undefined;\n\t\t\t\tsizeNow = undefined;\n\t\t\t\tdeltaTop = 0;\n\t\t\t\tdeltaLeft = 0;\n\t\t\t\tthis._userSize = e.dimension;\n\t\t\t}\n\t\t}));\n\n\t\tthis._disposables.add(this.widget.onDidChangeContents(() => {\n\t\t\tif (this._anchorBox) {\n\t\t\t\tthis._placeAtAnchor(this._anchorBox, this._userSize ?? this.widget.size, this._preferAlignAtTop);\n\t\t\t}\n\t\t}));\n\t}\n\n\tdispose(): void {\n\t\tthis._resizable.dispose();\n\t\tthis._disposables.dispose();\n\t\tthis.hide();\n\t}\n\n\tgetId(): string {\n\t\treturn 'suggest.details';\n\t}\n\n\tgetDomNode(): HTMLElement {\n\t\treturn this._resizable.domNode;\n\t}\n\n\tgetPosition(): null {\n\t\treturn null;\n\t}\n\n\tshow(): void {\n\t\tif (!this._added) {\n\t\t\tthis._editor.addOverlayWidget(this);\n\t\t\tthis.getDomNode().style.position = 'fixed';\n\t\t\tthis._added = true;\n\t\t}\n\t}\n\n\thide(sessionEnded: boolean = false): void {\n\t\tthis._resizable.clearSashHoverState();\n\n\t\tif (this._added) {\n\t\t\tthis._editor.removeOverlayWidget(this);\n\t\t\tthis._added = false;\n\t\t\tthis._anchorBox = undefined;\n\t\t\tthis._topLeft = undefined;\n\t\t}\n\t\tif (sessionEnded) {\n\t\t\tthis._userSize = undefined;\n\t\t\tthis.widget.clearContents();\n\t\t}\n\t}\n\n\tplaceAtAnchor(anchor: HTMLElement, preferAlignAtTop: boolean) {\n\t\tconst anchorBox = anchor.getBoundingClientRect();\n\t\tthis._anchorBox = anchorBox;\n\t\tthis._preferAlignAtTop = preferAlignAtTop;\n\t\tthis._placeAtAnchor(this._anchorBox, this._userSize ?? this.widget.size, preferAlignAtTop);\n\t}\n\n\t_placeAtAnchor(anchorBox: dom.IDomNodePagePosition, size: dom.Dimension, preferAlignAtTop: boolean) {\n\t\tconst bodyBox = dom.getClientArea(document.body);\n\n\t\tconst info = this.widget.getLayoutInfo();\n\n\t\tconst defaultMinSize = new dom.Dimension(220, 2 * info.lineHeight);\n\t\tconst defaultTop = anchorBox.top;\n\n\t\ttype Placement = { top: number, left: number, fit: number, maxSizeTop: dom.Dimension, maxSizeBottom: dom.Dimension, minSize: dom.Dimension };\n\n\t\t// EAST\n\t\tconst eastPlacement: Placement = (function () {\n\t\t\tconst width = bodyBox.width - (anchorBox.left + anchorBox.width + info.borderWidth + info.horizontalPadding);\n\t\t\tconst left = -info.borderWidth + anchorBox.left + anchorBox.width;\n\t\t\tconst maxSizeTop = new dom.Dimension(width, bodyBox.height - anchorBox.top - info.borderHeight - info.verticalPadding);\n\t\t\tconst maxSizeBottom = maxSizeTop.with(undefined, anchorBox.top + anchorBox.height - info.borderHeight - info.verticalPadding);\n\t\t\treturn { top: defaultTop, left, fit: width - size.width, maxSizeTop, maxSizeBottom, minSize: defaultMinSize.with(Math.min(width, defaultMinSize.width)) };\n\t\t})();\n\n\t\t// WEST\n\t\tconst westPlacement: Placement = (function () {\n\t\t\tconst width = anchorBox.left - info.borderWidth - info.horizontalPadding;\n\t\t\tconst left = Math.max(info.horizontalPadding, anchorBox.left - size.width - info.borderWidth);\n\t\t\tconst maxSizeTop = new dom.Dimension(width, bodyBox.height - anchorBox.top - info.borderHeight - info.verticalPadding);\n\t\t\tconst maxSizeBottom = maxSizeTop.with(undefined, anchorBox.top + anchorBox.height - info.borderHeight - info.verticalPadding);\n\t\t\treturn { top: defaultTop, left, fit: width - size.width, maxSizeTop, maxSizeBottom, minSize: defaultMinSize.with(Math.min(width, defaultMinSize.width)) };\n\t\t})();\n\n\t\t// SOUTH\n\t\tconst southPacement: Placement = (function () {\n\t\t\tconst left = anchorBox.left;\n\t\t\tconst top = -info.borderWidth + anchorBox.top + anchorBox.height;\n\t\t\tconst maxSizeBottom = new dom.Dimension(anchorBox.width - info.borderHeight, bodyBox.height - anchorBox.top - anchorBox.height - info.verticalPadding);\n\t\t\treturn { top, left, fit: maxSizeBottom.height - size.height, maxSizeBottom, maxSizeTop: maxSizeBottom, minSize: defaultMinSize.with(maxSizeBottom.width) };\n\t\t})();\n\n\t\t// take first placement that fits or the first with \"least bad\" fit\n\t\tconst placements = [eastPlacement, westPlacement, southPacement];\n\t\tconst placement = placements.find(p => p.fit >= 0) ?? placements.sort((a, b) => b.fit - a.fit)[0];\n\n\t\t// top/bottom placement\n\t\tconst bottom = anchorBox.top + anchorBox.height - info.borderHeight;\n\t\tlet alignAtTop: boolean;\n\t\tlet height = size.height;\n\t\tconst maxHeight = Math.max(placement.maxSizeTop.height, placement.maxSizeBottom.height);\n\t\tif (height > maxHeight) {\n\t\t\theight = maxHeight;\n\t\t}\n\t\tlet maxSize: dom.Dimension;\n\t\tif (preferAlignAtTop) {\n\t\t\tif (height <= placement.maxSizeTop.height) {\n\t\t\t\talignAtTop = true;\n\t\t\t\tmaxSize = placement.maxSizeTop;\n\t\t\t} else {\n\t\t\t\talignAtTop = false;\n\t\t\t\tmaxSize = placement.maxSizeBottom;\n\t\t\t}\n\t\t} else {\n\t\t\tif (height <= placement.maxSizeBottom.height) {\n\t\t\t\talignAtTop = false;\n\t\t\t\tmaxSize = placement.maxSizeBottom;\n\t\t\t} else {\n\t\t\t\talignAtTop = true;\n\t\t\t\tmaxSize = placement.maxSizeTop;\n\t\t\t}\n\t\t}\n\n\t\tthis._applyTopLeft({ left: placement.left, top: alignAtTop ? placement.top : bottom - height });\n\t\tthis.getDomNode().style.position = 'fixed';\n\n\t\tthis._resizable.enableSashes(!alignAtTop, placement === eastPlacement, alignAtTop, placement !== eastPlacement);\n\n\t\tthis._resizable.minSize = placement.minSize;\n\t\tthis._resizable.maxSize = maxSize;\n\t\tthis._resizable.layout(height, Math.min(maxSize.width, size.width));\n\t\tthis.widget.layout(this._resizable.size.width, this._resizable.size.height);\n\t}\n\n\tprivate _applyTopLeft(topLeft: TopLeftPosition): void {\n\t\tthis._topLeft = topLeft;\n\t\tthis.getDomNode().style.left = `${this._topLeft.left}px`;\n\t\tthis.getDomNode().style.top = `${this._topLeft.top}px`;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as arrays from 'vs/base/common/arrays';\nimport { IStringDictionary } from 'vs/base/common/collections';\nimport { ResourceMap } from 'vs/base/common/map';\nimport * as objects from 'vs/base/common/objects';\nimport * as types from 'vs/base/common/types';\nimport { URI, UriComponents } from 'vs/base/common/uri';\nimport { addToValueTree, ConfigurationTarget, getConfigurationValue, IConfigurationChange, IConfigurationChangeEvent, IConfigurationData, IConfigurationModel, IConfigurationOverrides, IConfigurationUpdateOverrides, IConfigurationValue, IOverrides, removeFromValueTree, toValuesTree } from 'vs/platform/configuration/common/configuration';\nimport { Extensions, IConfigurationRegistry, overrideIdentifiersFromKey, OVERRIDE_PROPERTY_REGEX } from 'vs/platform/configuration/common/configurationRegistry';\nimport { Registry } from 'vs/platform/registry/common/platform';\nimport { Workspace } from 'vs/platform/workspace/common/workspace';\n\nexport class ConfigurationModel implements IConfigurationModel {\n\n\tprivate isFrozen: boolean = false;\n\tprivate readonly overrideConfigurations = new Map();\n\n\tconstructor(\n\t\tprivate readonly _contents: any = {},\n\t\tprivate readonly _keys: string[] = [],\n\t\tprivate readonly _overrides: IOverrides[] = []\n\t) {\n\t}\n\n\tget contents(): any {\n\t\treturn this.checkAndFreeze(this._contents);\n\t}\n\n\tget overrides(): IOverrides[] {\n\t\treturn this.checkAndFreeze(this._overrides);\n\t}\n\n\tget keys(): string[] {\n\t\treturn this.checkAndFreeze(this._keys);\n\t}\n\n\tisEmpty(): boolean {\n\t\treturn this._keys.length === 0 && Object.keys(this._contents).length === 0 && this._overrides.length === 0;\n\t}\n\n\tgetValue(section: string | undefined): V {\n\t\treturn section ? getConfigurationValue(this.contents, section) : this.contents;\n\t}\n\n\tgetOverrideValue(section: string | undefined, overrideIdentifier: string): V | undefined {\n\t\tconst overrideContents = this.getContentsForOverrideIdentifer(overrideIdentifier);\n\t\treturn overrideContents\n\t\t\t? section ? getConfigurationValue(overrideContents, section) : overrideContents\n\t\t\t: undefined;\n\t}\n\n\toverride(identifier: string): ConfigurationModel {\n\t\tlet overrideConfigurationModel = this.overrideConfigurations.get(identifier);\n\t\tif (!overrideConfigurationModel) {\n\t\t\toverrideConfigurationModel = this.createOverrideConfigurationModel(identifier);\n\t\t\tthis.overrideConfigurations.set(identifier, overrideConfigurationModel);\n\t\t}\n\t\treturn overrideConfigurationModel;\n\t}\n\n\tmerge(...others: ConfigurationModel[]): ConfigurationModel {\n\t\tconst contents = objects.deepClone(this.contents);\n\t\tconst overrides = objects.deepClone(this.overrides);\n\t\tconst keys = [...this.keys];\n\n\t\tfor (const other of others) {\n\t\t\tthis.mergeContents(contents, other.contents);\n\n\t\t\tfor (const otherOverride of other.overrides) {\n\t\t\t\tconst [override] = overrides.filter(o => arrays.equals(o.identifiers, otherOverride.identifiers));\n\t\t\t\tif (override) {\n\t\t\t\t\tthis.mergeContents(override.contents, otherOverride.contents);\n\t\t\t\t\toverride.keys.push(...otherOverride.keys);\n\t\t\t\t\toverride.keys = arrays.distinct(override.keys);\n\t\t\t\t} else {\n\t\t\t\t\toverrides.push(objects.deepClone(otherOverride));\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const key of other.keys) {\n\t\t\t\tif (keys.indexOf(key) === -1) {\n\t\t\t\t\tkeys.push(key);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn new ConfigurationModel(contents, keys, overrides);\n\t}\n\n\tfreeze(): ConfigurationModel {\n\t\tthis.isFrozen = true;\n\t\treturn this;\n\t}\n\n\tprivate createOverrideConfigurationModel(identifier: string): ConfigurationModel {\n\t\tconst overrideContents = this.getContentsForOverrideIdentifer(identifier);\n\n\t\tif (!overrideContents || typeof overrideContents !== 'object' || !Object.keys(overrideContents).length) {\n\t\t\t// If there are no valid overrides, return self\n\t\t\treturn this;\n\t\t}\n\n\t\tlet contents: any = {};\n\t\tfor (const key of arrays.distinct([...Object.keys(this.contents), ...Object.keys(overrideContents)])) {\n\n\t\t\tlet contentsForKey = this.contents[key];\n\t\t\tlet overrideContentsForKey = overrideContents[key];\n\n\t\t\t// If there are override contents for the key, clone and merge otherwise use base contents\n\t\t\tif (overrideContentsForKey) {\n\t\t\t\t// Clone and merge only if base contents and override contents are of type object otherwise just override\n\t\t\t\tif (typeof contentsForKey === 'object' && typeof overrideContentsForKey === 'object') {\n\t\t\t\t\tcontentsForKey = objects.deepClone(contentsForKey);\n\t\t\t\t\tthis.mergeContents(contentsForKey, overrideContentsForKey);\n\t\t\t\t} else {\n\t\t\t\t\tcontentsForKey = overrideContentsForKey;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcontents[key] = contentsForKey;\n\t\t}\n\n\t\treturn new ConfigurationModel(contents, this.keys, this.overrides);\n\t}\n\n\tprivate mergeContents(source: any, target: any): void {\n\t\tfor (const key of Object.keys(target)) {\n\t\t\tif (key in source) {\n\t\t\t\tif (types.isObject(source[key]) && types.isObject(target[key])) {\n\t\t\t\t\tthis.mergeContents(source[key], target[key]);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tsource[key] = objects.deepClone(target[key]);\n\t\t}\n\t}\n\n\tprivate checkAndFreeze(data: T): T {\n\t\tif (this.isFrozen && !Object.isFrozen(data)) {\n\t\t\treturn objects.deepFreeze(data);\n\t\t}\n\t\treturn data;\n\t}\n\n\tprivate getContentsForOverrideIdentifer(identifier: string): any {\n\t\tlet contentsForIdentifierOnly: IStringDictionary | null = null;\n\t\tlet contents: IStringDictionary | null = null;\n\t\tconst mergeContents = (contentsToMerge: any) => {\n\t\t\tif (contentsToMerge) {\n\t\t\t\tif (contents) {\n\t\t\t\t\tthis.mergeContents(contents, contentsToMerge);\n\t\t\t\t} else {\n\t\t\t\t\tcontents = objects.deepClone(contentsToMerge);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tfor (const override of this.overrides) {\n\t\t\tif (arrays.equals(override.identifiers, [identifier])) {\n\t\t\t\tcontentsForIdentifierOnly = override.contents;\n\t\t\t} else if (override.identifiers.includes(identifier)) {\n\t\t\t\tmergeContents(override.contents);\n\t\t\t}\n\t\t}\n\t\t// Merge contents of the identifier only at the end to take precedence.\n\t\tmergeContents(contentsForIdentifierOnly);\n\t\treturn contents;\n\t}\n\n\ttoJSON(): IConfigurationModel {\n\t\treturn {\n\t\t\tcontents: this.contents,\n\t\t\toverrides: this.overrides,\n\t\t\tkeys: this.keys\n\t\t};\n\t}\n\n\t// Update methods\n\n\tpublic setValue(key: string, value: any) {\n\t\tthis.addKey(key);\n\t\taddToValueTree(this.contents, key, value, e => { throw new Error(e); });\n\t}\n\n\tpublic removeValue(key: string): void {\n\t\tif (this.removeKey(key)) {\n\t\t\tremoveFromValueTree(this.contents, key);\n\t\t}\n\t}\n\n\tprivate addKey(key: string): void {\n\t\tlet index = this.keys.length;\n\t\tfor (let i = 0; i < index; i++) {\n\t\t\tif (key.indexOf(this.keys[i]) === 0) {\n\t\t\t\tindex = i;\n\t\t\t}\n\t\t}\n\t\tthis.keys.splice(index, 1, key);\n\t}\n\n\tprivate removeKey(key: string): boolean {\n\t\tlet index = this.keys.indexOf(key);\n\t\tif (index !== -1) {\n\t\t\tthis.keys.splice(index, 1);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n}\n\nexport class DefaultConfigurationModel extends ConfigurationModel {\n\n\tconstructor(configurationDefaultsOverrides: IStringDictionary = {}) {\n\t\tconst properties = Registry.as(Extensions.Configuration).getConfigurationProperties();\n\t\tconst keys = Object.keys(properties);\n\t\tconst contents: any = Object.create(null);\n\t\tconst overrides: IOverrides[] = [];\n\n\t\tfor (const key in properties) {\n\t\t\tconst defaultOverrideValue = configurationDefaultsOverrides[key];\n\t\t\tconst value = defaultOverrideValue !== undefined ? defaultOverrideValue : properties[key].default;\n\t\t\taddToValueTree(contents, key, value, message => console.error(`Conflict in default settings: ${message}`));\n\t\t}\n\t\tfor (const key of Object.keys(contents)) {\n\t\t\tif (OVERRIDE_PROPERTY_REGEX.test(key)) {\n\t\t\t\toverrides.push({\n\t\t\t\t\tidentifiers: overrideIdentifiersFromKey(key),\n\t\t\t\t\tkeys: Object.keys(contents[key]),\n\t\t\t\t\tcontents: toValuesTree(contents[key], message => console.error(`Conflict in default settings file: ${message}`)),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tsuper(contents, keys, overrides);\n\t}\n}\n\n\nexport class Configuration {\n\n\tprivate _workspaceConsolidatedConfiguration: ConfigurationModel | null = null;\n\tprivate _foldersConsolidatedConfigurations: ResourceMap = new ResourceMap();\n\n\tconstructor(\n\t\tprivate _defaultConfiguration: ConfigurationModel,\n\t\tprivate _localUserConfiguration: ConfigurationModel,\n\t\tprivate _remoteUserConfiguration: ConfigurationModel = new ConfigurationModel(),\n\t\tprivate _workspaceConfiguration: ConfigurationModel = new ConfigurationModel(),\n\t\tprivate _folderConfigurations: ResourceMap = new ResourceMap(),\n\t\tprivate _memoryConfiguration: ConfigurationModel = new ConfigurationModel(),\n\t\tprivate _memoryConfigurationByResource: ResourceMap = new ResourceMap(),\n\t\tprivate _freeze: boolean = true) {\n\t}\n\n\tgetValue(section: string | undefined, overrides: IConfigurationOverrides, workspace: Workspace | undefined): any {\n\t\tconst consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides, workspace);\n\t\treturn consolidateConfigurationModel.getValue(section);\n\t}\n\n\tupdateValue(key: string, value: any, overrides: IConfigurationUpdateOverrides = {}): void {\n\t\tlet memoryConfiguration: ConfigurationModel | undefined;\n\t\tif (overrides.resource) {\n\t\t\tmemoryConfiguration = this._memoryConfigurationByResource.get(overrides.resource);\n\t\t\tif (!memoryConfiguration) {\n\t\t\t\tmemoryConfiguration = new ConfigurationModel();\n\t\t\t\tthis._memoryConfigurationByResource.set(overrides.resource, memoryConfiguration);\n\t\t\t}\n\t\t} else {\n\t\t\tmemoryConfiguration = this._memoryConfiguration;\n\t\t}\n\n\t\tif (value === undefined) {\n\t\t\tmemoryConfiguration.removeValue(key);\n\t\t} else {\n\t\t\tmemoryConfiguration.setValue(key, value);\n\t\t}\n\n\t\tif (!overrides.resource) {\n\t\t\tthis._workspaceConsolidatedConfiguration = null;\n\t\t}\n\t}\n\n\tinspect(key: string, overrides: IConfigurationOverrides, workspace: Workspace | undefined): IConfigurationValue {\n\t\tconst consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides, workspace);\n\t\tconst folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource, workspace);\n\t\tconst memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration;\n\n\t\tconst defaultValue = overrides.overrideIdentifier ? this._defaultConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this._defaultConfiguration.freeze().getValue(key);\n\t\tconst userValue = overrides.overrideIdentifier ? this.userConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.userConfiguration.freeze().getValue(key);\n\t\tconst userLocalValue = overrides.overrideIdentifier ? this.localUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.localUserConfiguration.freeze().getValue(key);\n\t\tconst userRemoteValue = overrides.overrideIdentifier ? this.remoteUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.remoteUserConfiguration.freeze().getValue(key);\n\t\tconst workspaceValue = workspace ? overrides.overrideIdentifier ? this._workspaceConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this._workspaceConfiguration.freeze().getValue(key) : undefined; //Check on workspace exists or not because _workspaceConfiguration is never null\n\t\tconst workspaceFolderValue = folderConfigurationModel ? overrides.overrideIdentifier ? folderConfigurationModel.freeze().override(overrides.overrideIdentifier).getValue(key) : folderConfigurationModel.freeze().getValue(key) : undefined;\n\t\tconst memoryValue = overrides.overrideIdentifier ? memoryConfigurationModel.override(overrides.overrideIdentifier).getValue(key) : memoryConfigurationModel.getValue(key);\n\t\tconst value = consolidateConfigurationModel.getValue(key);\n\t\tconst overrideIdentifiers: string[] = arrays.distinct(arrays.flatten(consolidateConfigurationModel.overrides.map(override => override.identifiers))).filter(overrideIdentifier => consolidateConfigurationModel.getOverrideValue(key, overrideIdentifier) !== undefined);\n\n\t\treturn {\n\t\t\tdefaultValue: defaultValue,\n\t\t\tuserValue: userValue,\n\t\t\tuserLocalValue: userLocalValue,\n\t\t\tuserRemoteValue: userRemoteValue,\n\t\t\tworkspaceValue: workspaceValue,\n\t\t\tworkspaceFolderValue: workspaceFolderValue,\n\t\t\tmemoryValue: memoryValue,\n\t\t\tvalue,\n\n\t\t\tdefault: defaultValue !== undefined ? { value: this._defaultConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this._defaultConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n\t\t\tuser: userValue !== undefined ? { value: this.userConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.userConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n\t\t\tuserLocal: userLocalValue !== undefined ? { value: this.localUserConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.localUserConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n\t\t\tuserRemote: userRemoteValue !== undefined ? { value: this.remoteUserConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.remoteUserConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n\t\t\tworkspace: workspaceValue !== undefined ? { value: this._workspaceConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this._workspaceConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n\t\t\tworkspaceFolder: workspaceFolderValue !== undefined ? { value: folderConfigurationModel?.freeze().getValue(key), override: overrides.overrideIdentifier ? folderConfigurationModel?.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n\t\t\tmemory: memoryValue !== undefined ? { value: memoryConfigurationModel.getValue(key), override: overrides.overrideIdentifier ? memoryConfigurationModel.getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n\n\t\t\toverrideIdentifiers: overrideIdentifiers.length ? overrideIdentifiers : undefined\n\t\t};\n\t}\n\n\tprivate _userConfiguration: ConfigurationModel | null = null;\n\tget userConfiguration(): ConfigurationModel {\n\t\tif (!this._userConfiguration) {\n\t\t\tthis._userConfiguration = this._remoteUserConfiguration.isEmpty() ? this._localUserConfiguration : this._localUserConfiguration.merge(this._remoteUserConfiguration);\n\t\t\tif (this._freeze) {\n\t\t\t\tthis._userConfiguration.freeze();\n\t\t\t}\n\t\t}\n\t\treturn this._userConfiguration;\n\t}\n\n\tget localUserConfiguration(): ConfigurationModel {\n\t\treturn this._localUserConfiguration;\n\t}\n\n\tget remoteUserConfiguration(): ConfigurationModel {\n\t\treturn this._remoteUserConfiguration;\n\t}\n\n\tprivate getConsolidateConfigurationModel(overrides: IConfigurationOverrides, workspace: Workspace | undefined): ConfigurationModel {\n\t\tlet configurationModel = this.getConsolidatedConfigurationModelForResource(overrides, workspace);\n\t\treturn overrides.overrideIdentifier ? configurationModel.override(overrides.overrideIdentifier) : configurationModel;\n\t}\n\n\tprivate getConsolidatedConfigurationModelForResource({ resource }: IConfigurationOverrides, workspace: Workspace | undefined): ConfigurationModel {\n\t\tlet consolidateConfiguration = this.getWorkspaceConsolidatedConfiguration();\n\n\t\tif (workspace && resource) {\n\t\t\tconst root = workspace.getFolder(resource);\n\t\t\tif (root) {\n\t\t\t\tconsolidateConfiguration = this.getFolderConsolidatedConfiguration(root.uri) || consolidateConfiguration;\n\t\t\t}\n\t\t\tconst memoryConfigurationForResource = this._memoryConfigurationByResource.get(resource);\n\t\t\tif (memoryConfigurationForResource) {\n\t\t\t\tconsolidateConfiguration = consolidateConfiguration.merge(memoryConfigurationForResource);\n\t\t\t}\n\t\t}\n\n\t\treturn consolidateConfiguration;\n\t}\n\n\tprivate getWorkspaceConsolidatedConfiguration(): ConfigurationModel {\n\t\tif (!this._workspaceConsolidatedConfiguration) {\n\t\t\tthis._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this.userConfiguration, this._workspaceConfiguration, this._memoryConfiguration);\n\t\t\tif (this._freeze) {\n\t\t\t\tthis._workspaceConfiguration = this._workspaceConfiguration.freeze();\n\t\t\t}\n\t\t}\n\t\treturn this._workspaceConsolidatedConfiguration;\n\t}\n\n\tprivate getFolderConsolidatedConfiguration(folder: URI): ConfigurationModel {\n\t\tlet folderConsolidatedConfiguration = this._foldersConsolidatedConfigurations.get(folder);\n\t\tif (!folderConsolidatedConfiguration) {\n\t\t\tconst workspaceConsolidateConfiguration = this.getWorkspaceConsolidatedConfiguration();\n\t\t\tconst folderConfiguration = this._folderConfigurations.get(folder);\n\t\t\tif (folderConfiguration) {\n\t\t\t\tfolderConsolidatedConfiguration = workspaceConsolidateConfiguration.merge(folderConfiguration);\n\t\t\t\tif (this._freeze) {\n\t\t\t\t\tfolderConsolidatedConfiguration = folderConsolidatedConfiguration.freeze();\n\t\t\t\t}\n\t\t\t\tthis._foldersConsolidatedConfigurations.set(folder, folderConsolidatedConfiguration);\n\t\t\t} else {\n\t\t\t\tfolderConsolidatedConfiguration = workspaceConsolidateConfiguration;\n\t\t\t}\n\t\t}\n\t\treturn folderConsolidatedConfiguration;\n\t}\n\n\tprivate getFolderConfigurationModelForResource(resource: URI | null | undefined, workspace: Workspace | undefined): ConfigurationModel | undefined {\n\t\tif (workspace && resource) {\n\t\t\tconst root = workspace.getFolder(resource);\n\t\t\tif (root) {\n\t\t\t\treturn this._folderConfigurations.get(root.uri);\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\ttoData(): IConfigurationData {\n\t\treturn {\n\t\t\tdefaults: {\n\t\t\t\tcontents: this._defaultConfiguration.contents,\n\t\t\t\toverrides: this._defaultConfiguration.overrides,\n\t\t\t\tkeys: this._defaultConfiguration.keys\n\t\t\t},\n\t\t\tuser: {\n\t\t\t\tcontents: this.userConfiguration.contents,\n\t\t\t\toverrides: this.userConfiguration.overrides,\n\t\t\t\tkeys: this.userConfiguration.keys\n\t\t\t},\n\t\t\tworkspace: {\n\t\t\t\tcontents: this._workspaceConfiguration.contents,\n\t\t\t\toverrides: this._workspaceConfiguration.overrides,\n\t\t\t\tkeys: this._workspaceConfiguration.keys\n\t\t\t},\n\t\t\tfolders: [...this._folderConfigurations.keys()].reduce<[UriComponents, IConfigurationModel][]>((result, folder) => {\n\t\t\t\tconst { contents, overrides, keys } = this._folderConfigurations.get(folder)!;\n\t\t\t\tresult.push([folder, { contents, overrides, keys }]);\n\t\t\t\treturn result;\n\t\t\t}, [])\n\t\t};\n\t}\n\n\tstatic parse(data: IConfigurationData): Configuration {\n\t\tconst defaultConfiguration = this.parseConfigurationModel(data.defaults);\n\t\tconst userConfiguration = this.parseConfigurationModel(data.user);\n\t\tconst workspaceConfiguration = this.parseConfigurationModel(data.workspace);\n\t\tconst folders: ResourceMap = data.folders.reduce((result, value) => {\n\t\t\tresult.set(URI.revive(value[0]), this.parseConfigurationModel(value[1]));\n\t\t\treturn result;\n\t\t}, new ResourceMap());\n\t\treturn new Configuration(defaultConfiguration, userConfiguration, new ConfigurationModel(), workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap(), false);\n\t}\n\n\tprivate static parseConfigurationModel(model: IConfigurationModel): ConfigurationModel {\n\t\treturn new ConfigurationModel(model.contents, model.keys, model.overrides).freeze();\n\t}\n\n}\n\nexport class ConfigurationChangeEvent implements IConfigurationChangeEvent {\n\n\tprivate readonly affectedKeysTree: any;\n\treadonly affectedKeys: string[];\n\tsource!: ConfigurationTarget;\n\tsourceConfig: any;\n\n\tconstructor(readonly change: IConfigurationChange, private readonly previous: { workspace?: Workspace, data: IConfigurationData } | undefined, private readonly currentConfiguraiton: Configuration, private readonly currentWorkspace?: Workspace) {\n\t\tconst keysSet = new Set();\n\t\tchange.keys.forEach(key => keysSet.add(key));\n\t\tchange.overrides.forEach(([, keys]) => keys.forEach(key => keysSet.add(key)));\n\t\tthis.affectedKeys = [...keysSet.values()];\n\n\t\tconst configurationModel = new ConfigurationModel();\n\t\tthis.affectedKeys.forEach(key => configurationModel.setValue(key, {}));\n\t\tthis.affectedKeysTree = configurationModel.contents;\n\t}\n\n\tprivate _previousConfiguration: Configuration | undefined = undefined;\n\tget previousConfiguration(): Configuration | undefined {\n\t\tif (!this._previousConfiguration && this.previous) {\n\t\t\tthis._previousConfiguration = Configuration.parse(this.previous.data);\n\t\t}\n\t\treturn this._previousConfiguration;\n\t}\n\n\taffectsConfiguration(section: string, overrides?: IConfigurationOverrides): boolean {\n\t\tif (this.doesAffectedKeysTreeContains(this.affectedKeysTree, section)) {\n\t\t\tif (overrides) {\n\t\t\t\tconst value1 = this.previousConfiguration ? this.previousConfiguration.getValue(section, overrides, this.previous?.workspace) : undefined;\n\t\t\t\tconst value2 = this.currentConfiguraiton.getValue(section, overrides, this.currentWorkspace);\n\t\t\t\treturn !objects.equals(value1, value2);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate doesAffectedKeysTreeContains(affectedKeysTree: any, section: string): boolean {\n\t\tlet requestedTree = toValuesTree({ [section]: true }, () => { });\n\n\t\tlet key;\n\t\twhile (typeof requestedTree === 'object' && (key = Object.keys(requestedTree)[0])) { // Only one key should present, since we added only one property\n\t\t\taffectedKeysTree = affectedKeysTree[key];\n\t\t\tif (!affectedKeysTree) {\n\t\t\t\treturn false; // Requested tree is not found\n\t\t\t}\n\t\t\trequestedTree = requestedTree[key];\n\t\t}\n\t\treturn true;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { createKeybinding, Keybinding, SimpleKeybinding, ScanCodeBinding } from 'vs/base/common/keybindings';\nimport { OperatingSystem, OS } from 'vs/base/common/platform';\nimport { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands';\nimport { ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';\nimport { Registry } from 'vs/platform/registry/common/platform';\n\nexport interface IKeybindingItem {\n\tkeybinding: (SimpleKeybinding | ScanCodeBinding)[];\n\tcommand: string;\n\tcommandArgs?: any;\n\twhen: ContextKeyExpression | null | undefined;\n\tweight1: number;\n\tweight2: number;\n\textensionId: string | null;\n\tisBuiltinExtension: boolean;\n}\n\nexport interface IKeybindings {\n\tprimary?: number;\n\tsecondary?: number[];\n\twin?: {\n\t\tprimary: number;\n\t\tsecondary?: number[];\n\t};\n\tlinux?: {\n\t\tprimary: number;\n\t\tsecondary?: number[];\n\t};\n\tmac?: {\n\t\tprimary: number;\n\t\tsecondary?: number[];\n\t};\n}\n\nexport interface IKeybindingRule extends IKeybindings {\n\tid: string;\n\tweight: number;\n\targs?: any;\n\twhen?: ContextKeyExpression | null | undefined;\n}\n\nexport const enum KeybindingWeight {\n\tEditorCore = 0,\n\tEditorContrib = 100,\n\tWorkbenchContrib = 200,\n\tBuiltinExtension = 300,\n\tExternalExtension = 400\n}\n\nexport interface ICommandAndKeybindingRule extends IKeybindingRule {\n\thandler: ICommandHandler;\n}\n\nexport interface IKeybindingsRegistry {\n\tregisterKeybindingRule(rule: IKeybindingRule): void;\n\tregisterCommandAndKeybindingRule(desc: ICommandAndKeybindingRule): void;\n\tgetDefaultKeybindings(): IKeybindingItem[];\n}\n\nclass KeybindingsRegistryImpl implements IKeybindingsRegistry {\n\n\tprivate _coreKeybindings: IKeybindingItem[];\n\tprivate _extensionKeybindings: IKeybindingItem[];\n\tprivate _cachedMergedKeybindings: IKeybindingItem[] | null;\n\n\tconstructor() {\n\t\tthis._coreKeybindings = [];\n\t\tthis._extensionKeybindings = [];\n\t\tthis._cachedMergedKeybindings = null;\n\t}\n\n\t/**\n\t * Take current platform into account and reduce to primary & secondary.\n\t */\n\tprivate static bindToCurrentPlatform(kb: IKeybindings): { primary?: number; secondary?: number[]; } {\n\t\tif (OS === OperatingSystem.Windows) {\n\t\t\tif (kb && kb.win) {\n\t\t\t\treturn kb.win;\n\t\t\t}\n\t\t} else if (OS === OperatingSystem.Macintosh) {\n\t\t\tif (kb && kb.mac) {\n\t\t\t\treturn kb.mac;\n\t\t\t}\n\t\t} else {\n\t\t\tif (kb && kb.linux) {\n\t\t\t\treturn kb.linux;\n\t\t\t}\n\t\t}\n\n\t\treturn kb;\n\t}\n\n\tpublic registerKeybindingRule(rule: IKeybindingRule): void {\n\t\tconst actualKb = KeybindingsRegistryImpl.bindToCurrentPlatform(rule);\n\n\t\tif (actualKb && actualKb.primary) {\n\t\t\tconst kk = createKeybinding(actualKb.primary, OS);\n\t\t\tif (kk) {\n\t\t\t\tthis._registerDefaultKeybinding(kk, rule.id, rule.args, rule.weight, 0, rule.when);\n\t\t\t}\n\t\t}\n\n\t\tif (actualKb && Array.isArray(actualKb.secondary)) {\n\t\t\tfor (let i = 0, len = actualKb.secondary.length; i < len; i++) {\n\t\t\t\tconst k = actualKb.secondary[i];\n\t\t\t\tconst kk = createKeybinding(k, OS);\n\t\t\t\tif (kk) {\n\t\t\t\t\tthis._registerDefaultKeybinding(kk, rule.id, rule.args, rule.weight, -i - 1, rule.when);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic registerCommandAndKeybindingRule(desc: ICommandAndKeybindingRule): void {\n\t\tthis.registerKeybindingRule(desc);\n\t\tCommandsRegistry.registerCommand(desc);\n\t}\n\n\tprivate static _mightProduceChar(keyCode: KeyCode): boolean {\n\t\tif (keyCode >= KeyCode.Digit0 && keyCode <= KeyCode.Digit9) {\n\t\t\treturn true;\n\t\t}\n\t\tif (keyCode >= KeyCode.KeyA && keyCode <= KeyCode.KeyZ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn (\n\t\t\tkeyCode === KeyCode.Semicolon\n\t\t\t|| keyCode === KeyCode.Equal\n\t\t\t|| keyCode === KeyCode.Comma\n\t\t\t|| keyCode === KeyCode.Minus\n\t\t\t|| keyCode === KeyCode.Period\n\t\t\t|| keyCode === KeyCode.Slash\n\t\t\t|| keyCode === KeyCode.Backquote\n\t\t\t|| keyCode === KeyCode.ABNT_C1\n\t\t\t|| keyCode === KeyCode.ABNT_C2\n\t\t\t|| keyCode === KeyCode.BracketLeft\n\t\t\t|| keyCode === KeyCode.Backslash\n\t\t\t|| keyCode === KeyCode.BracketRight\n\t\t\t|| keyCode === KeyCode.Quote\n\t\t\t|| keyCode === KeyCode.OEM_8\n\t\t\t|| keyCode === KeyCode.IntlBackslash\n\t\t);\n\t}\n\n\tprivate _assertNoCtrlAlt(keybinding: SimpleKeybinding, commandId: string): void {\n\t\tif (keybinding.ctrlKey && keybinding.altKey && !keybinding.metaKey) {\n\t\t\tif (KeybindingsRegistryImpl._mightProduceChar(keybinding.keyCode)) {\n\t\t\t\tconsole.warn('Ctrl+Alt+ keybindings should not be used by default under Windows. Offender: ', keybinding, ' for ', commandId);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _registerDefaultKeybinding(keybinding: Keybinding, commandId: string, commandArgs: any, weight1: number, weight2: number, when: ContextKeyExpression | null | undefined): void {\n\t\tif (OS === OperatingSystem.Windows) {\n\t\t\tthis._assertNoCtrlAlt(keybinding.parts[0], commandId);\n\t\t}\n\t\tthis._coreKeybindings.push({\n\t\t\tkeybinding: keybinding.parts,\n\t\t\tcommand: commandId,\n\t\t\tcommandArgs: commandArgs,\n\t\t\twhen: when,\n\t\t\tweight1: weight1,\n\t\t\tweight2: weight2,\n\t\t\textensionId: null,\n\t\t\tisBuiltinExtension: false\n\t\t});\n\t\tthis._cachedMergedKeybindings = null;\n\t}\n\n\tpublic getDefaultKeybindings(): IKeybindingItem[] {\n\t\tif (!this._cachedMergedKeybindings) {\n\t\t\tthis._cachedMergedKeybindings = ([]).concat(this._coreKeybindings).concat(this._extensionKeybindings);\n\t\t\tthis._cachedMergedKeybindings.sort(sorter);\n\t\t}\n\t\treturn this._cachedMergedKeybindings.slice(0);\n\t}\n}\nexport const KeybindingsRegistry: IKeybindingsRegistry = new KeybindingsRegistryImpl();\n\n// Define extension point ids\nexport const Extensions = {\n\tEditorModes: 'platform.keybindingsRegistry'\n};\nRegistry.add(Extensions.EditorModes, KeybindingsRegistry);\n\nfunction sorter(a: IKeybindingItem, b: IKeybindingItem): number {\n\tif (a.weight1 !== b.weight1) {\n\t\treturn a.weight1 - b.weight1;\n\t}\n\tif (a.command < b.command) {\n\t\treturn -1;\n\t}\n\tif (a.command > b.command) {\n\t\treturn 1;\n\t}\n\treturn a.weight2 - b.weight2;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IHistoryNavigationWidget } from 'vs/base/browser/history';\nimport { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';\nimport { FindInput, IFindInputOptions } from 'vs/base/browser/ui/findinput/findInput';\nimport { IReplaceInputOptions, ReplaceInput } from 'vs/base/browser/ui/findinput/replaceInput';\nimport { KeyCode, KeyMod } from 'vs/base/common/keyCodes';\nimport { ContextKeyExpr, IContextKey, IContextKeyService, IContextKeyServiceTarget, RawContextKey } from 'vs/platform/contextkey/common/contextkey';\nimport { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';\n\n// TODO@Connor: this constant is duplicated here to avoid a layer breaker import\nconst suggestWidgetVisibleContext = 'suggestWidgetVisible';\n\nexport const HistoryNavigationWidgetContext = 'historyNavigationWidget';\nconst HistoryNavigationForwardsEnablementContext = 'historyNavigationForwardsEnabled';\nconst HistoryNavigationBackwardsEnablementContext = 'historyNavigationBackwardsEnabled';\n\nfunction bindContextScopedWidget(contextKeyService: IContextKeyService, widget: IContextScopedWidget, contextKey: string): void {\n\tnew RawContextKey(contextKey, widget).bindTo(contextKeyService);\n}\n\nfunction createWidgetScopedContextKeyService(contextKeyService: IContextKeyService, widget: IContextScopedWidget): IContextKeyService {\n\treturn contextKeyService.createScoped(widget.target);\n}\n\nfunction getContextScopedWidget(contextKeyService: IContextKeyService, contextKey: string): T | undefined {\n\treturn contextKeyService.getContext(document.activeElement).getValue(contextKey);\n}\n\ninterface IContextScopedWidget {\n\treadonly target: IContextKeyServiceTarget;\n}\n\nexport interface IContextScopedHistoryNavigationWidget extends IContextScopedWidget {\n\thistoryNavigator: IHistoryNavigationWidget;\n}\n\nexport interface IHistoryNavigationContext {\n\tscopedContextKeyService: IContextKeyService,\n\thistoryNavigationForwardsEnablement: IContextKey,\n\thistoryNavigationBackwardsEnablement: IContextKey,\n}\n\nexport function createAndBindHistoryNavigationWidgetScopedContextKeyService(contextKeyService: IContextKeyService, widget: IContextScopedHistoryNavigationWidget): IHistoryNavigationContext {\n\tconst scopedContextKeyService = createWidgetScopedContextKeyService(contextKeyService, widget);\n\tbindContextScopedWidget(scopedContextKeyService, widget, HistoryNavigationWidgetContext);\n\tconst historyNavigationForwardsEnablement = new RawContextKey(HistoryNavigationForwardsEnablementContext, true).bindTo(scopedContextKeyService);\n\tconst historyNavigationBackwardsEnablement = new RawContextKey(HistoryNavigationBackwardsEnablementContext, true).bindTo(scopedContextKeyService);\n\treturn {\n\t\tscopedContextKeyService,\n\t\thistoryNavigationForwardsEnablement,\n\t\thistoryNavigationBackwardsEnablement,\n\t};\n}\n\nexport class ContextScopedFindInput extends FindInput {\n\n\tconstructor(container: HTMLElement | null, contextViewProvider: IContextViewProvider, options: IFindInputOptions,\n\t\t@IContextKeyService contextKeyService: IContextKeyService, showFindOptions: boolean = false\n\t) {\n\t\tsuper(container, contextViewProvider, showFindOptions, options);\n\t\tthis._register(createAndBindHistoryNavigationWidgetScopedContextKeyService(contextKeyService, { target: this.inputBox.element, historyNavigator: this.inputBox }).scopedContextKeyService);\n\t}\n}\n\nexport class ContextScopedReplaceInput extends ReplaceInput {\n\n\tconstructor(container: HTMLElement | null, contextViewProvider: IContextViewProvider | undefined, options: IReplaceInputOptions,\n\t\t@IContextKeyService contextKeyService: IContextKeyService, showReplaceOptions: boolean = false\n\t) {\n\t\tsuper(container, contextViewProvider, showReplaceOptions, options);\n\t\tthis._register(createAndBindHistoryNavigationWidgetScopedContextKeyService(contextKeyService, { target: this.inputBox.element, historyNavigator: this.inputBox }).scopedContextKeyService);\n\t}\n\n}\n\nKeybindingsRegistry.registerCommandAndKeybindingRule({\n\tid: 'history.showPrevious',\n\tweight: KeybindingWeight.WorkbenchContrib,\n\twhen: ContextKeyExpr.and(\n\t\tContextKeyExpr.has(HistoryNavigationWidgetContext),\n\t\tContextKeyExpr.equals(HistoryNavigationBackwardsEnablementContext, true),\n\t\tContextKeyExpr.equals(suggestWidgetVisibleContext, false),\n\t),\n\tprimary: KeyCode.UpArrow,\n\tsecondary: [KeyMod.Alt | KeyCode.UpArrow],\n\thandler: (accessor) => {\n\t\tconst widget = getContextScopedWidget(accessor.get(IContextKeyService), HistoryNavigationWidgetContext);\n\t\tif (widget) {\n\t\t\tconst historyInputBox: IHistoryNavigationWidget = widget.historyNavigator;\n\t\t\thistoryInputBox.showPreviousValue();\n\t\t}\n\t}\n});\n\nKeybindingsRegistry.registerCommandAndKeybindingRule({\n\tid: 'history.showNext',\n\tweight: KeybindingWeight.WorkbenchContrib,\n\twhen: ContextKeyExpr.and(\n\t\tContextKeyExpr.has(HistoryNavigationWidgetContext),\n\t\tContextKeyExpr.equals(HistoryNavigationForwardsEnablementContext, true),\n\t\tContextKeyExpr.equals(suggestWidgetVisibleContext, false),\n\t),\n\tprimary: KeyCode.DownArrow,\n\tsecondary: [KeyMod.Alt | KeyCode.DownArrow],\n\thandler: (accessor) => {\n\t\tconst widget = getContextScopedWidget(accessor.get(IContextKeyService), HistoryNavigationWidgetContext);\n\t\tif (widget) {\n\t\t\tconst historyInputBox: IHistoryNavigationWidget = widget.historyNavigator;\n\t\t\thistoryInputBox.showNextValue();\n\t\t}\n\t}\n});\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { coalesce } from 'vs/base/common/arrays';\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { ItemActivation } from 'vs/base/parts/quickinput/common/quickInput';\nimport { IQuickNavigateConfiguration, IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';\nimport { Registry } from 'vs/platform/registry/common/platform';\n\nexport interface IQuickAccessOptions {\n\n\t/**\n\t * Allows to enable quick navigate support in quick input.\n\t */\n\tquickNavigateConfiguration?: IQuickNavigateConfiguration;\n\n\t/**\n\t * Allows to configure a different item activation strategy.\n\t * By default the first item in the list will get activated.\n\t */\n\titemActivation?: ItemActivation;\n\n\t/**\n\t * Whether to take the input value as is and not restore it\n\t * from any existing value if quick access is visible.\n\t */\n\tpreserveValue?: boolean;\n}\n\nexport interface IQuickAccessController {\n\n\t/**\n\t * Open the quick access picker with the optional value prefilled.\n\t */\n\tshow(value?: string, options?: IQuickAccessOptions): void;\n}\n\nexport enum DefaultQuickAccessFilterValue {\n\n\t/**\n\t * Keep the value as it is given to quick access.\n\t */\n\tPRESERVE = 0,\n\n\t/**\n\t * Use the value that was used last time something was accepted from the picker.\n\t */\n\tLAST = 1\n}\n\nexport interface IQuickAccessProvider {\n\n\t/**\n\t * Allows to set a default filter value when the provider opens. This can be:\n\t * - `undefined` to not specify any default value\n\t * - `DefaultFilterValues.PRESERVE` to use the value that was last typed\n\t * - `string` for the actual value to use\n\t *\n\t * Note: the default filter will only be used if quick access was opened with\n\t * the exact prefix of the provider. Otherwise the filter value is preserved.\n\t */\n\treadonly defaultFilterValue?: string | DefaultQuickAccessFilterValue;\n\n\t/**\n\t * Called whenever a prefix was typed into quick pick that matches the provider.\n\t *\n\t * @param picker the picker to use for showing provider results. The picker is\n\t * automatically shown after the method returns, no need to call `show()`.\n\t * @param token providers have to check the cancellation token everytime after\n\t * a long running operation or from event handlers because it could be that the\n\t * picker has been closed or changed meanwhile. The token can be used to find out\n\t * that the picker was closed without picking an entry (e.g. was canceled by the user).\n\t * @return a disposable that will automatically be disposed when the picker\n\t * closes or is replaced by another picker.\n\t */\n\tprovide(picker: IQuickPick, token: CancellationToken): IDisposable;\n}\n\nexport interface IQuickAccessProviderHelp {\n\n\t/**\n\t * The prefix to show for the help entry. If not provided,\n\t * the prefix used for registration will be taken.\n\t */\n\tprefix?: string;\n\n\t/**\n\t * A description text to help understand the intent of the provider.\n\t */\n\tdescription: string;\n\n\t/**\n\t * Separation between provider for editors and global ones.\n\t */\n\tneedsEditor: boolean;\n}\n\nexport interface IQuickAccessProviderDescriptor {\n\n\t/**\n\t * The actual provider that will be instantiated as needed.\n\t */\n\treadonly ctor: { new(...services: any /* TS BrandedService but no clue how to type this properly */[]): IQuickAccessProvider };\n\n\t/**\n\t * The prefix for quick access picker to use the provider for.\n\t */\n\treadonly prefix: string;\n\n\t/**\n\t * A placeholder to use for the input field when the provider is active.\n\t * This will also be read out by screen readers and thus helps for\n\t * accessibility.\n\t */\n\treadonly placeholder?: string;\n\n\t/**\n\t * Documentation for the provider in the quick access help.\n\t */\n\treadonly helpEntries: IQuickAccessProviderHelp[];\n\n\t/**\n\t * A context key that will be set automatically when the\n\t * picker for the provider is showing.\n\t */\n\treadonly contextKey?: string;\n}\n\nexport const Extensions = {\n\tQuickaccess: 'workbench.contributions.quickaccess'\n};\n\nexport interface IQuickAccessRegistry {\n\n\t/**\n\t * Registers a quick access provider to the platform.\n\t */\n\tregisterQuickAccessProvider(provider: IQuickAccessProviderDescriptor): IDisposable;\n\n\t/**\n\t * Get all registered quick access providers.\n\t */\n\tgetQuickAccessProviders(): IQuickAccessProviderDescriptor[];\n\n\t/**\n\t * Get a specific quick access provider for a given prefix.\n\t */\n\tgetQuickAccessProvider(prefix: string): IQuickAccessProviderDescriptor | undefined;\n}\n\nexport class QuickAccessRegistry implements IQuickAccessRegistry {\n\tprivate providers: IQuickAccessProviderDescriptor[] = [];\n\tprivate defaultProvider: IQuickAccessProviderDescriptor | undefined = undefined;\n\n\tregisterQuickAccessProvider(provider: IQuickAccessProviderDescriptor): IDisposable {\n\n\t\t// Extract the default provider when no prefix is present\n\t\tif (provider.prefix.length === 0) {\n\t\t\tthis.defaultProvider = provider;\n\t\t} else {\n\t\t\tthis.providers.push(provider);\n\t\t}\n\n\t\t// sort the providers by decreasing prefix length, such that longer\n\t\t// prefixes take priority: 'ext' vs 'ext install' - the latter should win\n\t\tthis.providers.sort((providerA, providerB) => providerB.prefix.length - providerA.prefix.length);\n\n\t\treturn toDisposable(() => {\n\t\t\tthis.providers.splice(this.providers.indexOf(provider), 1);\n\n\t\t\tif (this.defaultProvider === provider) {\n\t\t\t\tthis.defaultProvider = undefined;\n\t\t\t}\n\t\t});\n\t}\n\n\tgetQuickAccessProviders(): IQuickAccessProviderDescriptor[] {\n\t\treturn coalesce([this.defaultProvider, ...this.providers]);\n\t}\n\n\tgetQuickAccessProvider(prefix: string): IQuickAccessProviderDescriptor | undefined {\n\t\tconst result = prefix ? (this.providers.find(provider => prefix.startsWith(provider.prefix)) || undefined) : undefined;\n\n\t\treturn result || this.defaultProvider;\n\t}\n}\n\nRegistry.add(Extensions.Quickaccess, new QuickAccessRegistry());\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';\nimport { localize } from 'vs/nls';\nimport { Extensions, IQuickAccessProvider, IQuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess';\nimport { IQuickInputService, IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';\nimport { Registry } from 'vs/platform/registry/common/platform';\n\ninterface IHelpQuickAccessPickItem extends IQuickPickItem {\n\tprefix: string;\n}\n\nexport class HelpQuickAccessProvider implements IQuickAccessProvider {\n\n\tstatic PREFIX = '?';\n\n\tprivate readonly registry = Registry.as(Extensions.Quickaccess);\n\n\tconstructor(@IQuickInputService private readonly quickInputService: IQuickInputService) { }\n\n\tprovide(picker: IQuickPick): IDisposable {\n\t\tconst disposables = new DisposableStore();\n\n\t\t// Open a picker with the selected value if picked\n\t\tdisposables.add(picker.onDidAccept(() => {\n\t\t\tconst [item] = picker.selectedItems;\n\t\t\tif (item) {\n\t\t\t\tthis.quickInputService.quickAccess.show(item.prefix, { preserveValue: true });\n\t\t\t}\n\t\t}));\n\n\t\t// Also open a picker when we detect the user typed the exact\n\t\t// name of a provider (e.g. `?term` for terminals)\n\t\tdisposables.add(picker.onDidChangeValue(value => {\n\t\t\tconst providerDescriptor = this.registry.getQuickAccessProvider(value.substr(HelpQuickAccessProvider.PREFIX.length));\n\t\t\tif (providerDescriptor && providerDescriptor.prefix && providerDescriptor.prefix !== HelpQuickAccessProvider.PREFIX) {\n\t\t\t\tthis.quickInputService.quickAccess.show(providerDescriptor.prefix, { preserveValue: true });\n\t\t\t}\n\t\t}));\n\n\t\t// Fill in all providers separated by editor/global scope\n\t\tconst { editorProviders, globalProviders } = this.getQuickAccessProviders();\n\t\tpicker.items = editorProviders.length === 0 || globalProviders.length === 0 ?\n\n\t\t\t// Without groups\n\t\t\t[\n\t\t\t\t...(editorProviders.length === 0 ? globalProviders : editorProviders)\n\t\t\t] :\n\n\t\t\t// With groups\n\t\t\t[\n\t\t\t\t{ label: localize('globalCommands', \"global commands\"), type: 'separator' },\n\t\t\t\t...globalProviders,\n\t\t\t\t{ label: localize('editorCommands', \"editor commands\"), type: 'separator' },\n\t\t\t\t...editorProviders\n\t\t\t];\n\n\t\treturn disposables;\n\t}\n\n\tprivate getQuickAccessProviders(): { editorProviders: IHelpQuickAccessPickItem[], globalProviders: IHelpQuickAccessPickItem[] } {\n\t\tconst globalProviders: IHelpQuickAccessPickItem[] = [];\n\t\tconst editorProviders: IHelpQuickAccessPickItem[] = [];\n\n\t\tfor (const provider of this.registry.getQuickAccessProviders().sort((providerA, providerB) => providerA.prefix.localeCompare(providerB.prefix))) {\n\t\t\tif (provider.prefix === HelpQuickAccessProvider.PREFIX) {\n\t\t\t\tcontinue; // exclude help which is already active\n\t\t\t}\n\n\t\t\tfor (const helpEntry of provider.helpEntries) {\n\t\t\t\tconst prefix = helpEntry.prefix || provider.prefix;\n\t\t\t\tconst label = prefix || '\\u2026' /* ... */;\n\n\t\t\t\t(helpEntry.needsEditor ? editorProviders : globalProviders).push({\n\t\t\t\t\tprefix,\n\t\t\t\t\tlabel,\n\t\t\t\t\tariaLabel: localize('helpPickAriaLabel', \"{0}, {1}\", label, helpEntry.description),\n\t\t\t\t\tdescription: helpEntry.description\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn { editorProviders, globalProviders };\n\t}\n}\n\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Registry } from 'vs/platform/registry/common/platform';\nimport { IQuickAccessRegistry, Extensions } from 'vs/platform/quickinput/common/quickAccess';\nimport { QuickHelpNLS } from 'vs/editor/common/standaloneStrings';\nimport { HelpQuickAccessProvider } from 'vs/platform/quickinput/browser/helpQuickAccess';\n\nRegistry.as(Extensions.Quickaccess).registerQuickAccessProvider({\n\tctor: HelpQuickAccessProvider,\n\tprefix: '',\n\thelpEntries: [{ description: QuickHelpNLS.helpQuickAccessActionLabel, needsEditor: true }]\n});\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { DeferredPromise } from 'vs/base/common/async';\nimport { CancellationTokenSource } from 'vs/base/common/cancellation';\nimport { once } from 'vs/base/common/functional';\nimport { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';\nimport { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';\nimport { DefaultQuickAccessFilterValue, Extensions, IQuickAccessController, IQuickAccessOptions, IQuickAccessProvider, IQuickAccessProviderDescriptor, IQuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess';\nimport { IQuickInputService, IQuickPick, IQuickPickItem, ItemActivation } from 'vs/platform/quickinput/common/quickInput';\nimport { Registry } from 'vs/platform/registry/common/platform';\n\nexport class QuickAccessController extends Disposable implements IQuickAccessController {\n\n\tprivate readonly registry = Registry.as(Extensions.Quickaccess);\n\tprivate readonly mapProviderToDescriptor = new Map();\n\n\tprivate readonly lastAcceptedPickerValues = new Map();\n\n\tprivate visibleQuickAccess: {\n\t\tpicker: IQuickPick,\n\t\tdescriptor: IQuickAccessProviderDescriptor | undefined,\n\t\tvalue: string\n\t} | undefined = undefined;\n\n\tconstructor(\n\t\t@IQuickInputService private readonly quickInputService: IQuickInputService,\n\t\t@IInstantiationService private readonly instantiationService: IInstantiationService\n\t) {\n\t\tsuper();\n\t}\n\n\tshow(value = '', options?: IQuickAccessOptions): void {\n\t\tthis.doShowOrPick(value, false, options);\n\t}\n\n\tprivate doShowOrPick(value: string, pick: true, options?: IQuickAccessOptions): Promise;\n\tprivate doShowOrPick(value: string, pick: false, options?: IQuickAccessOptions): void;\n\tprivate doShowOrPick(value: string, pick: boolean, options?: IQuickAccessOptions): Promise | void {\n\n\t\t// Find provider for the value to show\n\t\tconst [provider, descriptor] = this.getOrInstantiateProvider(value);\n\n\t\t// Return early if quick access is already showing on that same prefix\n\t\tconst visibleQuickAccess = this.visibleQuickAccess;\n\t\tconst visibleDescriptor = visibleQuickAccess?.descriptor;\n\t\tif (visibleQuickAccess && descriptor && visibleDescriptor === descriptor) {\n\n\t\t\t// Apply value only if it is more specific than the prefix\n\t\t\t// from the provider and we are not instructed to preserve\n\t\t\tif (value !== descriptor.prefix && !options?.preserveValue) {\n\t\t\t\tvisibleQuickAccess.picker.value = value;\n\t\t\t}\n\n\t\t\t// Always adjust selection\n\t\t\tthis.adjustValueSelection(visibleQuickAccess.picker, descriptor, options);\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Rewrite the filter value based on certain rules unless disabled\n\t\tif (descriptor && !options?.preserveValue) {\n\t\t\tlet newValue: string | undefined = undefined;\n\n\t\t\t// If we have a visible provider with a value, take it's filter value but\n\t\t\t// rewrite to new provider prefix in case they differ\n\t\t\tif (visibleQuickAccess && visibleDescriptor && visibleDescriptor !== descriptor) {\n\t\t\t\tconst newValueCandidateWithoutPrefix = visibleQuickAccess.value.substr(visibleDescriptor.prefix.length);\n\t\t\t\tif (newValueCandidateWithoutPrefix) {\n\t\t\t\t\tnewValue = `${descriptor.prefix}${newValueCandidateWithoutPrefix}`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Otherwise, take a default value as instructed\n\t\t\tif (!newValue) {\n\t\t\t\tconst defaultFilterValue = provider?.defaultFilterValue;\n\t\t\t\tif (defaultFilterValue === DefaultQuickAccessFilterValue.LAST) {\n\t\t\t\t\tnewValue = this.lastAcceptedPickerValues.get(descriptor);\n\t\t\t\t} else if (typeof defaultFilterValue === 'string') {\n\t\t\t\t\tnewValue = `${descriptor.prefix}${defaultFilterValue}`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (typeof newValue === 'string') {\n\t\t\t\tvalue = newValue;\n\t\t\t}\n\t\t}\n\n\t\t// Create a picker for the provider to use with the initial value\n\t\t// and adjust the filtering to exclude the prefix from filtering\n\t\tconst disposables = new DisposableStore();\n\t\tconst picker = disposables.add(this.quickInputService.createQuickPick());\n\t\tpicker.value = value;\n\t\tthis.adjustValueSelection(picker, descriptor, options);\n\t\tpicker.placeholder = descriptor?.placeholder;\n\t\tpicker.quickNavigate = options?.quickNavigateConfiguration;\n\t\tpicker.hideInput = !!picker.quickNavigate && !visibleQuickAccess; // only hide input if there was no picker opened already\n\t\tif (typeof options?.itemActivation === 'number' || options?.quickNavigateConfiguration) {\n\t\t\tpicker.itemActivation = options?.itemActivation ?? ItemActivation.SECOND /* quick nav is always second */;\n\t\t}\n\t\tpicker.contextKey = descriptor?.contextKey;\n\t\tpicker.filterValue = (value: string) => value.substring(descriptor ? descriptor.prefix.length : 0);\n\t\tif (descriptor?.placeholder) {\n\t\t\tpicker.ariaLabel = descriptor?.placeholder;\n\t\t}\n\n\t\t// Pick mode: setup a promise that can be resolved\n\t\t// with the selected items and prevent execution\n\t\tlet pickPromise: DeferredPromise | undefined = undefined;\n\t\tif (pick) {\n\t\t\tpickPromise = new DeferredPromise();\n\t\t\tdisposables.add(once(picker.onWillAccept)(e => {\n\t\t\t\te.veto();\n\t\t\t\tpicker.hide();\n\t\t\t}));\n\t\t}\n\n\t\t// Register listeners\n\t\tdisposables.add(this.registerPickerListeners(picker, provider, descriptor, value));\n\n\t\t// Ask provider to fill the picker as needed if we have one\n\t\t// and pass over a cancellation token that will indicate when\n\t\t// the picker is hiding without a pick being made.\n\t\tconst cts = disposables.add(new CancellationTokenSource());\n\t\tif (provider) {\n\t\t\tdisposables.add(provider.provide(picker, cts.token));\n\t\t}\n\n\t\t// Finally, trigger disposal and cancellation when the picker\n\t\t// hides depending on items selected or not.\n\t\tonce(picker.onDidHide)(() => {\n\t\t\tif (picker.selectedItems.length === 0) {\n\t\t\t\tcts.cancel();\n\t\t\t}\n\n\t\t\t// Start to dispose once picker hides\n\t\t\tdisposables.dispose();\n\n\t\t\t// Resolve pick promise with selected items\n\t\t\tpickPromise?.complete(picker.selectedItems.slice(0));\n\t\t});\n\n\t\t// Finally, show the picker. This is important because a provider\n\t\t// may not call this and then our disposables would leak that rely\n\t\t// on the onDidHide event.\n\t\tpicker.show();\n\n\t\t// Pick mode: return with promise\n\t\tif (pick) {\n\t\t\treturn pickPromise?.p;\n\t\t}\n\t}\n\n\tprivate adjustValueSelection(picker: IQuickPick, descriptor?: IQuickAccessProviderDescriptor, options?: IQuickAccessOptions): void {\n\t\tlet valueSelection: [number, number];\n\n\t\t// Preserve: just always put the cursor at the end\n\t\tif (options?.preserveValue) {\n\t\t\tvalueSelection = [picker.value.length, picker.value.length];\n\t\t}\n\n\t\t// Otherwise: select the value up until the prefix\n\t\telse {\n\t\t\tvalueSelection = [descriptor?.prefix.length ?? 0, picker.value.length];\n\t\t}\n\n\t\tpicker.valueSelection = valueSelection;\n\t}\n\n\tprivate registerPickerListeners(picker: IQuickPick, provider: IQuickAccessProvider | undefined, descriptor: IQuickAccessProviderDescriptor | undefined, value: string): IDisposable {\n\t\tconst disposables = new DisposableStore();\n\n\t\t// Remember as last visible picker and clean up once picker get's disposed\n\t\tconst visibleQuickAccess = this.visibleQuickAccess = { picker, descriptor, value };\n\t\tdisposables.add(toDisposable(() => {\n\t\t\tif (visibleQuickAccess === this.visibleQuickAccess) {\n\t\t\t\tthis.visibleQuickAccess = undefined;\n\t\t\t}\n\t\t}));\n\n\t\t// Whenever the value changes, check if the provider has\n\t\t// changed and if so - re-create the picker from the beginning\n\t\tdisposables.add(picker.onDidChangeValue(value => {\n\t\t\tconst [providerForValue] = this.getOrInstantiateProvider(value);\n\t\t\tif (providerForValue !== provider) {\n\t\t\t\tthis.show(value, { preserveValue: true } /* do not rewrite value from user typing! */);\n\t\t\t} else {\n\t\t\t\tvisibleQuickAccess.value = value; // remember the value in our visible one\n\t\t\t}\n\t\t}));\n\n\t\t// Remember picker input for future use when accepting\n\t\tif (descriptor) {\n\t\t\tdisposables.add(picker.onDidAccept(() => {\n\t\t\t\tthis.lastAcceptedPickerValues.set(descriptor, picker.value);\n\t\t\t}));\n\t\t}\n\n\t\treturn disposables;\n\t}\n\n\tprivate getOrInstantiateProvider(value: string): [IQuickAccessProvider | undefined, IQuickAccessProviderDescriptor | undefined] {\n\t\tconst providerDescriptor = this.registry.getQuickAccessProvider(value);\n\t\tif (!providerDescriptor) {\n\t\t\treturn [undefined, undefined];\n\t\t}\n\n\t\tlet provider = this.mapProviderToDescriptor.get(providerDescriptor);\n\t\tif (!provider) {\n\t\t\tprovider = this.instantiationService.createInstance(providerDescriptor.ctor);\n\t\t\tthis.mapProviderToDescriptor.set(providerDescriptor, provider);\n\t\t}\n\n\t\treturn [provider, providerDescriptor];\n\t}\n}\n","\nimport { Emitter, Event, PauseableEmitter } from 'vs/base/common/event';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { isUndefinedOrNull } from 'vs/base/common/types';\nimport { InMemoryStorageDatabase, IStorage, Storage } from 'vs/base/parts/storage/common/storage';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nconst TARGET_KEY = '__$__targetStorageMarker';\n\nexport const IStorageService = createDecorator('storageService');\n\nexport enum WillSaveStateReason {\n\n\t/**\n\t * No specific reason to save state.\n\t */\n\tNONE,\n\n\t/**\n\t * A hint that the workbench is about to shutdown.\n\t */\n\tSHUTDOWN\n}\n\nexport interface IWillSaveStateEvent {\n\treason: WillSaveStateReason;\n}\n\nexport interface IStorageService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Emitted when the storage is about to persist. This is the right time\n\t * to persist data to ensure it is stored before the application shuts\n\t * down.\n\t *\n\t * The will save state event allows to optionally ask for the reason of\n\t * saving the state, e.g. to find out if the state is saved due to a\n\t * shutdown.\n\t *\n\t * Note: this event may be fired many times, not only on shutdown to prevent\n\t * loss of state in situations where the shutdown is not sufficient to\n\t * persist the data properly.\n\t */\n\treadonly onWillSaveState: Event;\n\n\t/**\n\t * Retrieve an element stored with the given key from storage. Use\n\t * the provided `defaultValue` if the element is `null` or `undefined`.\n\t *\n\t * @param scope allows to define the scope of the storage operation\n\t * to either the current workspace only or all workspaces.\n\t */\n\tget(key: string, scope: StorageScope, fallbackValue: string): string;\n\tget(key: string, scope: StorageScope, fallbackValue?: string): string | undefined;\n\n\t/**\n\t * Retrieve an element stored with the given key from storage. Use\n\t * the provided `defaultValue` if the element is `null` or `undefined`.\n\t * The element will be converted to a `boolean`.\n\t *\n\t * @param scope allows to define the scope of the storage operation\n\t * to either the current workspace only or all workspaces.\n\t */\n\tgetBoolean(key: string, scope: StorageScope, fallbackValue: boolean): boolean;\n\tgetBoolean(key: string, scope: StorageScope, fallbackValue?: boolean): boolean | undefined;\n\n\t/**\n\t * Retrieve an element stored with the given key from storage. Use\n\t * the provided `defaultValue` if the element is `null` or `undefined`.\n\t * The element will be converted to a `number` using `parseInt` with a\n\t * base of `10`.\n\t *\n\t * @param scope allows to define the scope of the storage operation\n\t * to either the current workspace only or all workspaces.\n\t */\n\tgetNumber(key: string, scope: StorageScope, fallbackValue: number): number;\n\tgetNumber(key: string, scope: StorageScope, fallbackValue?: number): number | undefined;\n\n\t/**\n\t * Store a value under the given key to storage. The value will be\n\t * converted to a `string`. Storing either `undefined` or `null` will\n\t * remove the entry under the key.\n\t *\n\t * @param scope allows to define the scope of the storage operation\n\t * to either the current workspace only or all workspaces.\n\t *\n\t * @param target allows to define the target of the storage operation\n\t * to either the current machine or user.\n\t */\n\tstore(key: string, value: string | boolean | number | undefined | null, scope: StorageScope, target: StorageTarget): void;\n\n\t/**\n\t * Delete an element stored under the provided key from storage.\n\t *\n\t * The scope argument allows to define the scope of the storage\n\t * operation to either the current workspace only or all workspaces.\n\t */\n\tremove(key: string, scope: StorageScope): void;\n}\n\nexport const enum StorageScope {\n\n\t/**\n\t * The stored data will be scoped to all workspaces.\n\t */\n\tGLOBAL,\n\n\t/**\n\t * The stored data will be scoped to the current workspace.\n\t */\n\tWORKSPACE\n}\n\nexport const enum StorageTarget {\n\n\t/**\n\t * The stored data is user specific and applies across machines.\n\t */\n\tUSER,\n\n\t/**\n\t * The stored data is machine specific.\n\t */\n\tMACHINE\n}\n\nexport interface IStorageValueChangeEvent {\n\n\t/**\n\t * The scope for the storage entry that changed\n\t * or was removed.\n\t */\n\treadonly scope: StorageScope;\n\n\t/**\n\t * The `key` of the storage entry that was changed\n\t * or was removed.\n\t */\n\treadonly key: string;\n\n\t/**\n\t * The `target` can be `undefined` if a key is being\n\t * removed.\n\t */\n\treadonly target: StorageTarget | undefined;\n}\n\nexport interface IStorageTargetChangeEvent {\n\n\t/**\n\t * The scope for the target that changed. Listeners\n\t * should use `keys(scope, target)` to get an updated\n\t * list of keys for the given `scope` and `target`.\n\t */\n\treadonly scope: StorageScope;\n}\n\ninterface IKeyTargets {\n\t[key: string]: StorageTarget\n}\n\nexport interface IStorageServiceOptions {\n\tflushInterval: number;\n}\n\nexport abstract class AbstractStorageService extends Disposable implements IStorageService {\n\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate static DEFAULT_FLUSH_INTERVAL = 60 * 1000; // every minute\n\n\tprivate readonly _onDidChangeValue = this._register(new PauseableEmitter());\n\n\tprivate readonly _onDidChangeTarget = this._register(new PauseableEmitter());\n\n\tprivate readonly _onWillSaveState = this._register(new Emitter());\n\treadonly onWillSaveState = this._onWillSaveState.event;\n\n\tconstructor(private readonly options: IStorageServiceOptions = { flushInterval: AbstractStorageService.DEFAULT_FLUSH_INTERVAL }) {\n\t\tsuper();\n\t}\n\n\tprotected emitDidChangeValue(scope: StorageScope, key: string): void {\n\n\t\t// Specially handle `TARGET_KEY`\n\t\tif (key === TARGET_KEY) {\n\n\t\t\t// Clear our cached version which is now out of date\n\t\t\tif (scope === StorageScope.GLOBAL) {\n\t\t\t\tthis._globalKeyTargets = undefined;\n\t\t\t} else if (scope === StorageScope.WORKSPACE) {\n\t\t\t\tthis._workspaceKeyTargets = undefined;\n\t\t\t}\n\n\t\t\t// Emit as `didChangeTarget` event\n\t\t\tthis._onDidChangeTarget.fire({ scope });\n\t\t}\n\n\t\t// Emit any other key to outside\n\t\telse {\n\t\t\tthis._onDidChangeValue.fire({ scope, key, target: this.getKeyTargets(scope)[key] });\n\t\t}\n\t}\n\n\tget(key: string, scope: StorageScope, fallbackValue: string): string;\n\tget(key: string, scope: StorageScope): string | undefined;\n\tget(key: string, scope: StorageScope, fallbackValue?: string): string | undefined {\n\t\treturn this.getStorage(scope)?.get(key, fallbackValue);\n\t}\n\n\tgetBoolean(key: string, scope: StorageScope, fallbackValue: boolean): boolean;\n\tgetBoolean(key: string, scope: StorageScope): boolean | undefined;\n\tgetBoolean(key: string, scope: StorageScope, fallbackValue?: boolean): boolean | undefined {\n\t\treturn this.getStorage(scope)?.getBoolean(key, fallbackValue);\n\t}\n\n\tgetNumber(key: string, scope: StorageScope, fallbackValue: number): number;\n\tgetNumber(key: string, scope: StorageScope): number | undefined;\n\tgetNumber(key: string, scope: StorageScope, fallbackValue?: number): number | undefined {\n\t\treturn this.getStorage(scope)?.getNumber(key, fallbackValue);\n\t}\n\n\tstore(key: string, value: string | boolean | number | undefined | null, scope: StorageScope, target: StorageTarget): void {\n\n\t\t// We remove the key for undefined/null values\n\t\tif (isUndefinedOrNull(value)) {\n\t\t\tthis.remove(key, scope);\n\t\t\treturn;\n\t\t}\n\n\t\t// Update our datastructures but send events only after\n\t\tthis.withPausedEmitters(() => {\n\n\t\t\t// Update key-target map\n\t\t\tthis.updateKeyTarget(key, scope, target);\n\n\t\t\t// Store actual value\n\t\t\tthis.getStorage(scope)?.set(key, value);\n\t\t});\n\t}\n\n\tremove(key: string, scope: StorageScope): void {\n\n\t\t// Update our datastructures but send events only after\n\t\tthis.withPausedEmitters(() => {\n\n\t\t\t// Update key-target map\n\t\t\tthis.updateKeyTarget(key, scope, undefined);\n\n\t\t\t// Remove actual key\n\t\t\tthis.getStorage(scope)?.delete(key);\n\t\t});\n\t}\n\n\tprivate withPausedEmitters(fn: Function): void {\n\n\t\t// Pause emitters\n\t\tthis._onDidChangeValue.pause();\n\t\tthis._onDidChangeTarget.pause();\n\n\t\ttry {\n\t\t\tfn();\n\t\t} finally {\n\n\t\t\t// Resume emitters\n\t\t\tthis._onDidChangeValue.resume();\n\t\t\tthis._onDidChangeTarget.resume();\n\t\t}\n\t}\n\n\tprivate updateKeyTarget(key: string, scope: StorageScope, target: StorageTarget | undefined): void {\n\n\t\t// Add\n\t\tconst keyTargets = this.getKeyTargets(scope);\n\t\tif (typeof target === 'number') {\n\t\t\tif (keyTargets[key] !== target) {\n\t\t\t\tkeyTargets[key] = target;\n\t\t\t\tthis.getStorage(scope)?.set(TARGET_KEY, JSON.stringify(keyTargets));\n\t\t\t}\n\t\t}\n\n\t\t// Remove\n\t\telse {\n\t\t\tif (typeof keyTargets[key] === 'number') {\n\t\t\t\tdelete keyTargets[key];\n\t\t\t\tthis.getStorage(scope)?.set(TARGET_KEY, JSON.stringify(keyTargets));\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _workspaceKeyTargets: IKeyTargets | undefined = undefined;\n\tprivate get workspaceKeyTargets(): IKeyTargets {\n\t\tif (!this._workspaceKeyTargets) {\n\t\t\tthis._workspaceKeyTargets = this.loadKeyTargets(StorageScope.WORKSPACE);\n\t\t}\n\n\t\treturn this._workspaceKeyTargets;\n\t}\n\n\tprivate _globalKeyTargets: IKeyTargets | undefined = undefined;\n\tprivate get globalKeyTargets(): IKeyTargets {\n\t\tif (!this._globalKeyTargets) {\n\t\t\tthis._globalKeyTargets = this.loadKeyTargets(StorageScope.GLOBAL);\n\t\t}\n\n\t\treturn this._globalKeyTargets;\n\t}\n\n\tprivate getKeyTargets(scope: StorageScope): IKeyTargets {\n\t\treturn scope === StorageScope.GLOBAL ? this.globalKeyTargets : this.workspaceKeyTargets;\n\t}\n\n\tprivate loadKeyTargets(scope: StorageScope): { [key: string]: StorageTarget } {\n\t\tconst keysRaw = this.get(TARGET_KEY, scope);\n\t\tif (keysRaw) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(keysRaw);\n\t\t\t} catch (error) {\n\t\t\t\t// Fail gracefully\n\t\t\t}\n\t\t}\n\n\t\treturn Object.create(null);\n\t}\n\n\tprotected abstract getStorage(scope: StorageScope): IStorage | undefined;\n}\n\nexport class InMemoryStorageService extends AbstractStorageService {\n\n\tprivate readonly globalStorage = this._register(new Storage(new InMemoryStorageDatabase()));\n\tprivate readonly workspaceStorage = this._register(new Storage(new InMemoryStorageDatabase()));\n\n\tconstructor() {\n\t\tsuper();\n\n\t\tthis._register(this.workspaceStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.WORKSPACE, key)));\n\t\tthis._register(this.globalStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.GLOBAL, key)));\n\t}\n\n\tprotected getStorage(scope: StorageScope): IStorage {\n\t\treturn scope === StorageScope.GLOBAL ? this.globalStorage : this.workspaceStorage;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { runWhenIdle } from 'vs/base/common/async';\nimport { once } from 'vs/base/common/functional';\nimport { LRUCache } from 'vs/base/common/map';\nimport { Range } from 'vs/editor/common/core/range';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { CodeLens, CodeLensList, CodeLensProvider } from 'vs/editor/common/languages';\nimport { CodeLensModel } from 'vs/editor/contrib/codelens/browser/codelens';\nimport { registerSingleton } from 'vs/platform/instantiation/common/extensions';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { IStorageService, StorageScope, StorageTarget, WillSaveStateReason } from 'vs/platform/storage/common/storage';\n\nexport const ICodeLensCache = createDecorator('ICodeLensCache');\n\nexport interface ICodeLensCache {\n\treadonly _serviceBrand: undefined;\n\tput(model: ITextModel, data: CodeLensModel): void;\n\tget(model: ITextModel): CodeLensModel | undefined;\n\tdelete(model: ITextModel): void;\n}\n\ninterface ISerializedCacheData {\n\tlineCount: number;\n\tlines: number[];\n}\n\nclass CacheItem {\n\n\tconstructor(\n\t\treadonly lineCount: number,\n\t\treadonly data: CodeLensModel\n\t) { }\n}\n\nexport class CodeLensCache implements ICodeLensCache {\n\n\tdeclare readonly _serviceBrand: undefined;\n\n\tprivate readonly _fakeProvider = new class implements CodeLensProvider {\n\t\tprovideCodeLenses(): CodeLensList {\n\t\t\tthrow new Error('not supported');\n\t\t}\n\t};\n\n\tprivate readonly _cache = new LRUCache(20, 0.75);\n\n\tconstructor(@IStorageService storageService: IStorageService) {\n\n\t\t// remove old data\n\t\tconst oldkey = 'codelens/cache';\n\t\trunWhenIdle(() => storageService.remove(oldkey, StorageScope.WORKSPACE));\n\n\t\t// restore lens data on start\n\t\tconst key = 'codelens/cache2';\n\t\tconst raw = storageService.get(key, StorageScope.WORKSPACE, '{}');\n\t\tthis._deserialize(raw);\n\n\t\t// store lens data on shutdown\n\t\tonce(storageService.onWillSaveState)(e => {\n\t\t\tif (e.reason === WillSaveStateReason.SHUTDOWN) {\n\t\t\t\tstorageService.store(key, this._serialize(), StorageScope.WORKSPACE, StorageTarget.MACHINE);\n\t\t\t}\n\t\t});\n\t}\n\n\tput(model: ITextModel, data: CodeLensModel): void {\n\t\t// create a copy of the model that is without command-ids\n\t\t// but with comand-labels\n\t\tconst copyItems = data.lenses.map(item => {\n\t\t\treturn {\n\t\t\t\trange: item.symbol.range,\n\t\t\t\tcommand: item.symbol.command && { id: '', title: item.symbol.command?.title },\n\t\t\t};\n\t\t});\n\t\tconst copyModel = new CodeLensModel();\n\t\tcopyModel.add({ lenses: copyItems, dispose: () => { } }, this._fakeProvider);\n\n\t\tconst item = new CacheItem(model.getLineCount(), copyModel);\n\t\tthis._cache.set(model.uri.toString(), item);\n\t}\n\n\tget(model: ITextModel) {\n\t\tconst item = this._cache.get(model.uri.toString());\n\t\treturn item && item.lineCount === model.getLineCount() ? item.data : undefined;\n\t}\n\n\tdelete(model: ITextModel): void {\n\t\tthis._cache.delete(model.uri.toString());\n\t}\n\n\t// --- persistence\n\n\tprivate _serialize(): string {\n\t\tconst data: Record = Object.create(null);\n\t\tfor (const [key, value] of this._cache) {\n\t\t\tconst lines = new Set();\n\t\t\tfor (const d of value.data.lenses) {\n\t\t\t\tlines.add(d.symbol.range.startLineNumber);\n\t\t\t}\n\t\t\tdata[key] = {\n\t\t\t\tlineCount: value.lineCount,\n\t\t\t\tlines: [...lines.values()]\n\t\t\t};\n\t\t}\n\t\treturn JSON.stringify(data);\n\t}\n\n\tprivate _deserialize(raw: string): void {\n\t\ttry {\n\t\t\tconst data: Record = JSON.parse(raw);\n\t\t\tfor (const key in data) {\n\t\t\t\tconst element = data[key];\n\t\t\t\tconst lenses: CodeLens[] = [];\n\t\t\t\tfor (const line of element.lines) {\n\t\t\t\t\tlenses.push({ range: new Range(line, 1, line, 11) });\n\t\t\t\t}\n\n\t\t\t\tconst model = new CodeLensModel();\n\t\t\t\tmodel.add({ lenses, dispose() { } }, this._fakeProvider);\n\t\t\t\tthis._cache.set(key, new CacheItem(element.lineCount, model));\n\t\t\t}\n\t\t} catch {\n\t\t\t// ignore...\n\t\t}\n\t}\n}\n\nregisterSingleton(ICodeLensCache, CodeLensCache);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n\nimport { RunOnceScheduler } from 'vs/base/common/async';\nimport { DisposableStore } from 'vs/base/common/lifecycle';\nimport { LRUCache, TernarySearchTree } from 'vs/base/common/map';\nimport { IPosition } from 'vs/editor/common/core/position';\nimport { ITextModel } from 'vs/editor/common/model';\nimport { CompletionItemKind, CompletionItemKinds } from 'vs/editor/common/languages';\nimport { CompletionItem } from 'vs/editor/contrib/suggest/browser/suggest';\nimport { IConfigurationService } from 'vs/platform/configuration/common/configuration';\nimport { registerSingleton } from 'vs/platform/instantiation/common/extensions';\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { IStorageService, StorageScope, StorageTarget, WillSaveStateReason } from 'vs/platform/storage/common/storage';\n\nexport abstract class Memory {\n\n\tconstructor(readonly name: MemMode) { }\n\n\tselect(model: ITextModel, pos: IPosition, items: CompletionItem[]): number {\n\t\tif (items.length === 0) {\n\t\t\treturn 0;\n\t\t}\n\t\tlet topScore = items[0].score[0];\n\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\tconst { score, completion: suggestion } = items[i];\n\t\t\tif (score[0] !== topScore) {\n\t\t\t\t// stop when leaving the group of top matches\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (suggestion.preselect) {\n\t\t\t\t// stop when seeing an auto-select-item\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\n\tabstract memorize(model: ITextModel, pos: IPosition, item: CompletionItem): void;\n\n\tabstract toJSON(): object | undefined;\n\n\tabstract fromJSON(data: object): void;\n}\n\nexport class NoMemory extends Memory {\n\n\tconstructor() {\n\t\tsuper('first');\n\t}\n\n\tmemorize(model: ITextModel, pos: IPosition, item: CompletionItem): void {\n\t\t// no-op\n\t}\n\n\ttoJSON() {\n\t\treturn undefined;\n\t}\n\n\tfromJSON() {\n\t\t//\n\t}\n}\n\nexport interface MemItem {\n\ttype: string | CompletionItemKind;\n\tinsertText: string;\n\ttouch: number;\n}\n\nexport class LRUMemory extends Memory {\n\n\tconstructor() {\n\t\tsuper('recentlyUsed');\n\t}\n\n\tprivate _cache = new LRUCache(300, 0.66);\n\tprivate _seq = 0;\n\n\tmemorize(model: ITextModel, pos: IPosition, item: CompletionItem): void {\n\t\tconst key = `${model.getLanguageId()}/${item.textLabel}`;\n\t\tthis._cache.set(key, {\n\t\t\ttouch: this._seq++,\n\t\t\ttype: item.completion.kind,\n\t\t\tinsertText: item.completion.insertText\n\t\t});\n\t}\n\n\toverride select(model: ITextModel, pos: IPosition, items: CompletionItem[]): number {\n\n\t\tif (items.length === 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst lineSuffix = model.getLineContent(pos.lineNumber).substr(pos.column - 10, pos.column - 1);\n\t\tif (/\\s$/.test(lineSuffix)) {\n\t\t\treturn super.select(model, pos, items);\n\t\t}\n\n\t\tlet topScore = items[0].score[0];\n\t\tlet indexPreselect = -1;\n\t\tlet indexRecency = -1;\n\t\tlet seq = -1;\n\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\tif (items[i].score[0] !== topScore) {\n\t\t\t\t// consider only top items\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst key = `${model.getLanguageId()}/${items[i].textLabel}`;\n\t\t\tconst item = this._cache.peek(key);\n\t\t\tif (item && item.touch > seq && item.type === items[i].completion.kind && item.insertText === items[i].completion.insertText) {\n\t\t\t\tseq = item.touch;\n\t\t\t\tindexRecency = i;\n\t\t\t}\n\t\t\tif (items[i].completion.preselect && indexPreselect === -1) {\n\t\t\t\t// stop when seeing an auto-select-item\n\t\t\t\treturn indexPreselect = i;\n\t\t\t}\n\t\t}\n\t\tif (indexRecency !== -1) {\n\t\t\treturn indexRecency;\n\t\t} else if (indexPreselect !== -1) {\n\t\t\treturn indexPreselect;\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\ttoJSON(): object {\n\t\treturn this._cache.toJSON();\n\t}\n\n\tfromJSON(data: [string, MemItem][]): void {\n\t\tthis._cache.clear();\n\t\tlet seq = 0;\n\t\tfor (const [key, value] of data) {\n\t\t\tvalue.touch = seq;\n\t\t\tvalue.type = typeof value.type === 'number' ? value.type : CompletionItemKinds.fromString(value.type);\n\t\t\tthis._cache.set(key, value);\n\t\t}\n\t\tthis._seq = this._cache.size;\n\t}\n}\n\n\nexport class PrefixMemory extends Memory {\n\n\tconstructor() {\n\t\tsuper('recentlyUsedByPrefix');\n\t}\n\n\tprivate _trie = TernarySearchTree.forStrings();\n\tprivate _seq = 0;\n\n\tmemorize(model: ITextModel, pos: IPosition, item: CompletionItem): void {\n\t\tconst { word } = model.getWordUntilPosition(pos);\n\t\tconst key = `${model.getLanguageId()}/${word}`;\n\t\tthis._trie.set(key, {\n\t\t\ttype: item.completion.kind,\n\t\t\tinsertText: item.completion.insertText,\n\t\t\ttouch: this._seq++\n\t\t});\n\t}\n\n\toverride select(model: ITextModel, pos: IPosition, items: CompletionItem[]): number {\n\t\tlet { word } = model.getWordUntilPosition(pos);\n\t\tif (!word) {\n\t\t\treturn super.select(model, pos, items);\n\t\t}\n\t\tlet key = `${model.getLanguageId()}/${word}`;\n\t\tlet item = this._trie.get(key);\n\t\tif (!item) {\n\t\t\titem = this._trie.findSubstr(key);\n\t\t}\n\t\tif (item) {\n\t\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\t\tlet { kind, insertText } = items[i].completion;\n\t\t\t\tif (kind === item.type && insertText === item.insertText) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn super.select(model, pos, items);\n\t}\n\n\ttoJSON(): object {\n\n\t\tlet entries: [string, MemItem][] = [];\n\t\tthis._trie.forEach((value, key) => entries.push([key, value]));\n\n\t\t// sort by last recently used (touch), then\n\t\t// take the top 200 item and normalize their\n\t\t// touch\n\t\tentries\n\t\t\t.sort((a, b) => -(a[1].touch - b[1].touch))\n\t\t\t.forEach((value, i) => value[1].touch = i);\n\n\t\treturn entries.slice(0, 200);\n\t}\n\n\tfromJSON(data: [string, MemItem][]): void {\n\t\tthis._trie.clear();\n\t\tif (data.length > 0) {\n\t\t\tthis._seq = data[0][1].touch + 1;\n\t\t\tfor (const [key, value] of data) {\n\t\t\t\tvalue.type = typeof value.type === 'number' ? value.type : CompletionItemKinds.fromString(value.type);\n\t\t\t\tthis._trie.set(key, value);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport type MemMode = 'first' | 'recentlyUsed' | 'recentlyUsedByPrefix';\n\nexport class SuggestMemoryService implements ISuggestMemoryService {\n\n\tprivate static readonly _strategyCtors = new Map([\n\t\t['recentlyUsedByPrefix', PrefixMemory],\n\t\t['recentlyUsed', LRUMemory],\n\t\t['first', NoMemory]\n\t]);\n\n\tprivate static readonly _storagePrefix = 'suggest/memories';\n\n\treadonly _serviceBrand: undefined;\n\n\n\tprivate readonly _persistSoon: RunOnceScheduler;\n\tprivate readonly _disposables = new DisposableStore();\n\n\tprivate _strategy?: Memory;\n\n\tconstructor(\n\t\t@IStorageService private readonly _storageService: IStorageService,\n\t\t@IConfigurationService private readonly _configService: IConfigurationService,\n\t) {\n\t\tthis._persistSoon = new RunOnceScheduler(() => this._saveState(), 500);\n\t\tthis._disposables.add(_storageService.onWillSaveState(e => {\n\t\t\tif (e.reason === WillSaveStateReason.SHUTDOWN) {\n\t\t\t\tthis._saveState();\n\t\t\t}\n\t\t}));\n\t}\n\n\tdispose(): void {\n\t\tthis._disposables.dispose();\n\t\tthis._persistSoon.dispose();\n\t}\n\n\tmemorize(model: ITextModel, pos: IPosition, item: CompletionItem): void {\n\t\tthis._withStrategy(model, pos).memorize(model, pos, item);\n\t\tthis._persistSoon.schedule();\n\t}\n\n\tselect(model: ITextModel, pos: IPosition, items: CompletionItem[]): number {\n\t\treturn this._withStrategy(model, pos).select(model, pos, items);\n\t}\n\n\tprivate _withStrategy(model: ITextModel, pos: IPosition): Memory {\n\n\t\tconst mode = this._configService.getValue('editor.suggestSelection', {\n\t\t\toverrideIdentifier: model.getLanguageIdAtPosition(pos.lineNumber, pos.column),\n\t\t\tresource: model.uri\n\t\t});\n\n\t\tif (this._strategy?.name !== mode) {\n\n\t\t\tthis._saveState();\n\t\t\tconst ctor = SuggestMemoryService._strategyCtors.get(mode) || NoMemory;\n\t\t\tthis._strategy = new ctor();\n\n\t\t\ttry {\n\t\t\t\tconst share = this._configService.getValue('editor.suggest.shareSuggestSelections');\n\t\t\t\tconst scope = share ? StorageScope.GLOBAL : StorageScope.WORKSPACE;\n\t\t\t\tconst raw = this._storageService.get(`${SuggestMemoryService._storagePrefix}/${mode}`, scope);\n\t\t\t\tif (raw) {\n\t\t\t\t\tthis._strategy.fromJSON(JSON.parse(raw));\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\t// things can go wrong with JSON...\n\t\t\t}\n\t\t}\n\n\t\treturn this._strategy;\n\t}\n\n\tprivate _saveState() {\n\t\tif (this._strategy) {\n\t\t\tconst share = this._configService.getValue('editor.suggest.shareSuggestSelections');\n\t\t\tconst scope = share ? StorageScope.GLOBAL : StorageScope.WORKSPACE;\n\t\t\tconst raw = JSON.stringify(this._strategy);\n\t\t\tthis._storageService.store(`${SuggestMemoryService._storagePrefix}/${this._strategy.name}`, raw, scope, StorageTarget.MACHINE);\n\t\t}\n\t}\n}\n\n\nexport const ISuggestMemoryService = createDecorator('ISuggestMemories');\n\nexport interface ISuggestMemoryService {\n\treadonly _serviceBrand: undefined;\n\tmemorize(model: ITextModel, pos: IPosition, item: CompletionItem): void;\n\tselect(model: ITextModel, pos: IPosition, items: CompletionItem[]): number;\n}\n\nregisterSingleton(ISuggestMemoryService, SuggestMemoryService, true);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { createDecorator } from 'vs/platform/instantiation/common/instantiation';\nimport { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings';\n\nexport const ITelemetryService = createDecorator('telemetryService');\n\nexport interface ITelemetryService {\n\n\treadonly _serviceBrand: undefined;\n\n\tpublicLog2 = never, T extends GDPRClassification = never>(eventName: string, data?: StrictPropertyCheck, anonymizeFilePaths?: boolean): Promise;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions';\nimport { CancellationToken } from 'vs/base/common/cancellation';\nimport { toErrorMessage } from 'vs/base/common/errorMessage';\nimport { isCancellationError } from 'vs/base/common/errors';\nimport { matchesContiguousSubString, matchesPrefix, matchesWords, or } from 'vs/base/common/filters';\nimport { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';\nimport { LRUCache } from 'vs/base/common/map';\nimport Severity from 'vs/base/common/severity';\nimport { withNullAsUndefined } from 'vs/base/common/types';\nimport { localize } from 'vs/nls';\nimport { ICommandService } from 'vs/platform/commands/common/commands';\nimport { IConfigurationService } from 'vs/platform/configuration/common/configuration';\nimport { IDialogService } from 'vs/platform/dialogs/common/dialogs';\nimport { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';\nimport { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';\nimport { IPickerQuickAccessItem, IPickerQuickAccessProviderOptions, PickerQuickAccessProvider } from 'vs/platform/quickinput/browser/pickerQuickAccess';\nimport { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';\nimport { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';\nimport { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';\n\nexport interface ICommandQuickPick extends IPickerQuickAccessItem {\n\tcommandId: string;\n\tcommandAlias?: string;\n}\n\nexport interface ICommandsQuickAccessOptions extends IPickerQuickAccessProviderOptions {\n\tshowAlias: boolean;\n}\n\nexport abstract class AbstractCommandsQuickAccessProvider extends PickerQuickAccessProvider implements IDisposable {\n\n\tstatic PREFIX = '>';\n\n\tprivate static WORD_FILTER = or(matchesPrefix, matchesWords, matchesContiguousSubString);\n\n\tprivate readonly commandsHistory = this._register(this.instantiationService.createInstance(CommandsHistory));\n\n\tprotected override readonly options: ICommandsQuickAccessOptions;\n\n\tconstructor(\n\t\toptions: ICommandsQuickAccessOptions,\n\t\t@IInstantiationService private readonly instantiationService: IInstantiationService,\n\t\t@IKeybindingService private readonly keybindingService: IKeybindingService,\n\t\t@ICommandService private readonly commandService: ICommandService,\n\t\t@ITelemetryService private readonly telemetryService: ITelemetryService,\n\t\t@IDialogService private readonly dialogService: IDialogService\n\t) {\n\t\tsuper(AbstractCommandsQuickAccessProvider.PREFIX, options);\n\n\t\tthis.options = options;\n\t}\n\n\tprotected async _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise> {\n\n\t\t// Ask subclass for all command picks\n\t\tconst allCommandPicks = await this.getCommandPicks(disposables, token);\n\n\t\tif (token.isCancellationRequested) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Filter\n\t\tconst filteredCommandPicks: ICommandQuickPick[] = [];\n\t\tfor (const commandPick of allCommandPicks) {\n\t\t\tconst labelHighlights = withNullAsUndefined(AbstractCommandsQuickAccessProvider.WORD_FILTER(filter, commandPick.label));\n\t\t\tconst aliasHighlights = commandPick.commandAlias ? withNullAsUndefined(AbstractCommandsQuickAccessProvider.WORD_FILTER(filter, commandPick.commandAlias)) : undefined;\n\n\t\t\t// Add if matching in label or alias\n\t\t\tif (labelHighlights || aliasHighlights) {\n\t\t\t\tcommandPick.highlights = {\n\t\t\t\t\tlabel: labelHighlights,\n\t\t\t\t\tdetail: this.options.showAlias ? aliasHighlights : undefined\n\t\t\t\t};\n\n\t\t\t\tfilteredCommandPicks.push(commandPick);\n\t\t\t}\n\n\t\t\t// Also add if we have a 100% command ID match\n\t\t\telse if (filter === commandPick.commandId) {\n\t\t\t\tfilteredCommandPicks.push(commandPick);\n\t\t\t}\n\t\t}\n\n\t\t// Add description to commands that have duplicate labels\n\t\tconst mapLabelToCommand = new Map();\n\t\tfor (const commandPick of filteredCommandPicks) {\n\t\t\tconst existingCommandForLabel = mapLabelToCommand.get(commandPick.label);\n\t\t\tif (existingCommandForLabel) {\n\t\t\t\tcommandPick.description = commandPick.commandId;\n\t\t\t\texistingCommandForLabel.description = existingCommandForLabel.commandId;\n\t\t\t} else {\n\t\t\t\tmapLabelToCommand.set(commandPick.label, commandPick);\n\t\t\t}\n\t\t}\n\n\t\t// Sort by MRU order and fallback to name otherwise\n\t\tfilteredCommandPicks.sort((commandPickA, commandPickB) => {\n\t\t\tconst commandACounter = this.commandsHistory.peek(commandPickA.commandId);\n\t\t\tconst commandBCounter = this.commandsHistory.peek(commandPickB.commandId);\n\n\t\t\tif (commandACounter && commandBCounter) {\n\t\t\t\treturn commandACounter > commandBCounter ? -1 : 1; // use more recently used command before older\n\t\t\t}\n\n\t\t\tif (commandACounter) {\n\t\t\t\treturn -1; // first command was used, so it wins over the non used one\n\t\t\t}\n\n\t\t\tif (commandBCounter) {\n\t\t\t\treturn 1; // other command was used so it wins over the command\n\t\t\t}\n\n\t\t\t// both commands were never used, so we sort by name\n\t\t\treturn commandPickA.label.localeCompare(commandPickB.label);\n\t\t});\n\n\t\tconst commandPicks: Array = [];\n\n\t\tlet addSeparator = false;\n\t\tfor (let i = 0; i < filteredCommandPicks.length; i++) {\n\t\t\tconst commandPick = filteredCommandPicks[i];\n\t\t\tconst keybinding = this.keybindingService.lookupKeybinding(commandPick.commandId);\n\t\t\tconst ariaLabel = keybinding ?\n\t\t\t\tlocalize('commandPickAriaLabelWithKeybinding', \"{0}, {1}\", commandPick.label, keybinding.getAriaLabel()) :\n\t\t\t\tcommandPick.label;\n\n\t\t\t// Separator: recently used\n\t\t\tif (i === 0 && this.commandsHistory.peek(commandPick.commandId)) {\n\t\t\t\tcommandPicks.push({ type: 'separator', label: localize('recentlyUsed', \"recently used\") });\n\t\t\t\taddSeparator = true;\n\t\t\t}\n\n\t\t\t// Separator: other commands\n\t\t\tif (i !== 0 && addSeparator && !this.commandsHistory.peek(commandPick.commandId)) {\n\t\t\t\tcommandPicks.push({ type: 'separator', label: localize('morecCommands', \"other commands\") });\n\t\t\t\taddSeparator = false; // only once\n\t\t\t}\n\n\t\t\t// Command\n\t\t\tcommandPicks.push({\n\t\t\t\t...commandPick,\n\t\t\t\tariaLabel,\n\t\t\t\tdetail: this.options.showAlias && commandPick.commandAlias !== commandPick.label ? commandPick.commandAlias : undefined,\n\t\t\t\tkeybinding,\n\t\t\t\taccept: async () => {\n\n\t\t\t\t\t// Add to history\n\t\t\t\t\tthis.commandsHistory.push(commandPick.commandId);\n\n\t\t\t\t\t// Telementry\n\t\t\t\t\tthis.telemetryService.publicLog2('workbenchActionExecuted', {\n\t\t\t\t\t\tid: commandPick.commandId,\n\t\t\t\t\t\tfrom: 'quick open'\n\t\t\t\t\t});\n\n\t\t\t\t\t// Run\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.commandService.executeCommand(commandPick.commandId);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (!isCancellationError(error)) {\n\t\t\t\t\t\t\tthis.dialogService.show(Severity.Error, localize('canNotRun', \"Command '{0}' resulted in an error ({1})\", commandPick.label, toErrorMessage(error)));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn commandPicks;\n\t}\n\n\t/**\n\t * Subclasses to provide the actual command entries.\n\t */\n\tprotected abstract getCommandPicks(disposables: DisposableStore, token: CancellationToken): Promise>;\n}\n\ninterface ISerializedCommandHistory {\n\tusesLRU?: boolean;\n\tentries: { key: string; value: number; }[];\n}\n\ninterface ICommandsQuickAccessConfiguration {\n\tworkbench: {\n\t\tcommandPalette: {\n\t\t\thistory: number;\n\t\t\tpreserveInput: boolean;\n\t\t};\n\t};\n}\n\nexport class CommandsHistory extends Disposable {\n\n\tstatic readonly DEFAULT_COMMANDS_HISTORY_LENGTH = 50;\n\n\tprivate static readonly PREF_KEY_CACHE = 'commandPalette.mru.cache';\n\tprivate static readonly PREF_KEY_COUNTER = 'commandPalette.mru.counter';\n\n\tprivate static cache: LRUCache | undefined;\n\tprivate static counter = 1;\n\n\tprivate configuredCommandsHistoryLength = 0;\n\n\tconstructor(\n\t\t@IStorageService private readonly storageService: IStorageService,\n\t\t@IConfigurationService private readonly configurationService: IConfigurationService,\n\t) {\n\t\tsuper();\n\n\t\tthis.updateConfiguration();\n\t\tthis.load();\n\n\t\tthis.registerListeners();\n\t}\n\n\tprivate registerListeners(): void {\n\t\tthis._register(this.configurationService.onDidChangeConfiguration(() => this.updateConfiguration()));\n\t}\n\n\tprivate updateConfiguration(): void {\n\t\tthis.configuredCommandsHistoryLength = CommandsHistory.getConfiguredCommandHistoryLength(this.configurationService);\n\n\t\tif (CommandsHistory.cache && CommandsHistory.cache.limit !== this.configuredCommandsHistoryLength) {\n\t\t\tCommandsHistory.cache.limit = this.configuredCommandsHistoryLength;\n\n\t\t\tCommandsHistory.saveState(this.storageService);\n\t\t}\n\t}\n\n\tprivate load(): void {\n\t\tconst raw = this.storageService.get(CommandsHistory.PREF_KEY_CACHE, StorageScope.GLOBAL);\n\t\tlet serializedCache: ISerializedCommandHistory | undefined;\n\t\tif (raw) {\n\t\t\ttry {\n\t\t\t\tserializedCache = JSON.parse(raw);\n\t\t\t} catch (error) {\n\t\t\t\t// invalid data\n\t\t\t}\n\t\t}\n\n\t\tconst cache = CommandsHistory.cache = new LRUCache(this.configuredCommandsHistoryLength, 1);\n\t\tif (serializedCache) {\n\t\t\tlet entries: { key: string; value: number; }[];\n\t\t\tif (serializedCache.usesLRU) {\n\t\t\t\tentries = serializedCache.entries;\n\t\t\t} else {\n\t\t\t\tentries = serializedCache.entries.sort((a, b) => a.value - b.value);\n\t\t\t}\n\t\t\tentries.forEach(entry => cache.set(entry.key, entry.value));\n\t\t}\n\n\t\tCommandsHistory.counter = this.storageService.getNumber(CommandsHistory.PREF_KEY_COUNTER, StorageScope.GLOBAL, CommandsHistory.counter);\n\t}\n\n\tpush(commandId: string): void {\n\t\tif (!CommandsHistory.cache) {\n\t\t\treturn;\n\t\t}\n\n\t\tCommandsHistory.cache.set(commandId, CommandsHistory.counter++); // set counter to command\n\n\t\tCommandsHistory.saveState(this.storageService);\n\t}\n\n\tpeek(commandId: string): number | undefined {\n\t\treturn CommandsHistory.cache?.peek(commandId);\n\t}\n\n\tstatic saveState(storageService: IStorageService): void {\n\t\tif (!CommandsHistory.cache) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst serializedCache: ISerializedCommandHistory = { usesLRU: true, entries: [] };\n\t\tCommandsHistory.cache.forEach((value, key) => serializedCache.entries.push({ key, value }));\n\n\t\tstorageService.store(CommandsHistory.PREF_KEY_CACHE, JSON.stringify(serializedCache), StorageScope.GLOBAL, StorageTarget.USER);\n\t\tstorageService.store(CommandsHistory.PREF_KEY_COUNTER, CommandsHistory.counter, StorageScope.GLOBAL, StorageTarget.USER);\n\t}\n\n\tstatic getConfiguredCommandHistoryLength(configurationService: IConfigurationService): number {\n\t\tconst config = configurationService.getValue();\n\n\t\tconst configuredCommandHistoryLength = config.workbench?.commandPalette?.history;\n\t\tif (typeof configuredCommandHistoryLength === 'number') {\n\t\t\treturn configuredCommandHistoryLength;\n\t\t}\n\n\t\treturn CommandsHistory.DEFAULT_COMMANDS_HISTORY_LENGTH;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { stripIcons } from 'vs/base/common/iconLabels';\nimport { IEditor } from 'vs/editor/common/editorCommon';\nimport { ICommandService } from 'vs/platform/commands/common/commands';\nimport { IDialogService } from 'vs/platform/dialogs/common/dialogs';\nimport { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';\nimport { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';\nimport { AbstractCommandsQuickAccessProvider, ICommandQuickPick, ICommandsQuickAccessOptions } from 'vs/platform/quickinput/browser/commandsQuickAccess';\nimport { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';\n\nexport abstract class AbstractEditorCommandsQuickAccessProvider extends AbstractCommandsQuickAccessProvider {\n\n\tconstructor(\n\t\toptions: ICommandsQuickAccessOptions,\n\t\tinstantiationService: IInstantiationService,\n\t\tkeybindingService: IKeybindingService,\n\t\tcommandService: ICommandService,\n\t\ttelemetryService: ITelemetryService,\n\t\tdialogService: IDialogService\n\t) {\n\t\tsuper(options, instantiationService, keybindingService, commandService, telemetryService, dialogService);\n\t}\n\n\t/**\n\t * Subclasses to provide the current active editor control.\n\t */\n\tprotected abstract activeTextEditorControl: IEditor | undefined;\n\n\tprotected getCodeEditorCommandPicks(): ICommandQuickPick[] {\n\t\tconst activeTextEditorControl = this.activeTextEditorControl;\n\t\tif (!activeTextEditorControl) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst editorCommandPicks: ICommandQuickPick[] = [];\n\t\tfor (const editorAction of activeTextEditorControl.getSupportedActions()) {\n\t\t\teditorCommandPicks.push({\n\t\t\t\tcommandId: editorAction.id,\n\t\t\t\tcommandAlias: editorAction.alias,\n\t\t\t\tlabel: stripIcons(editorAction.label) || editorAction.id,\n\t\t\t});\n\t\t}\n\n\t\treturn editorCommandPicks;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { RunOnceScheduler } from 'vs/base/common/async';\nimport { Color, RGBA } from 'vs/base/common/color';\nimport { Emitter, Event } from 'vs/base/common/event';\nimport { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';\nimport { assertNever } from 'vs/base/common/types';\nimport * as nls from 'vs/nls';\nimport { Extensions as JSONExtensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';\nimport * as platform from 'vs/platform/registry/common/platform';\nimport { IColorTheme } from 'vs/platform/theme/common/themeService';\n\n// ------ API types\n\nexport type ColorIdentifier = string;\n\nexport interface ColorContribution {\n\treadonly id: ColorIdentifier;\n\treadonly description: string;\n\treadonly defaults: ColorDefaults | null;\n\treadonly needsTransparency: boolean;\n\treadonly deprecationMessage: string | undefined;\n}\n\n/**\n * Returns the css variable name for the given color identifier. Dots (`.`) are replaced with hyphens (`-`) and\n * everything is prefixed with `--vscode-`.\n *\n * @sample `editorSuggestWidget.background` is `--vscode-editorSuggestWidget-background`.\n */\nexport function asCssVariableName(colorIdent: ColorIdentifier): string {\n\treturn `--vscode-${colorIdent.replace('.', '-')}`;\n}\n\nexport const enum ColorTransformType {\n\tDarken,\n\tLighten,\n\tTransparent,\n\tOneOf,\n\tLessProminent,\n\tIfDefinedThenElse\n}\n\nexport type ColorTransform =\n\t| { op: ColorTransformType.Darken; value: ColorValue; factor: number }\n\t| { op: ColorTransformType.Lighten; value: ColorValue; factor: number }\n\t| { op: ColorTransformType.Transparent; value: ColorValue; factor: number }\n\t| { op: ColorTransformType.OneOf; values: readonly ColorValue[] }\n\t| { op: ColorTransformType.LessProminent; value: ColorValue; background: ColorValue; factor: number; transparency: number }\n\t| { op: ColorTransformType.IfDefinedThenElse; if: ColorIdentifier; then: ColorValue, else: ColorValue };\n\nexport interface ColorDefaults {\n\tlight: ColorValue | null;\n\tdark: ColorValue | null;\n\thc: ColorValue | null;\n}\n\n/**\n * A Color Value is either a color literal, a reference to an other color or a derived color\n */\nexport type ColorValue = Color | string | ColorIdentifier | ColorTransform;\n\n// color registry\nexport const Extensions = {\n\tColorContribution: 'base.contributions.colors'\n};\n\nexport interface IColorRegistry {\n\n\t/**\n\t * Get all color contributions\n\t */\n\tgetColors(): ColorContribution[];\n\n\t/**\n\t * Gets the default color of the given id\n\t */\n\tresolveDefaultColor(id: ColorIdentifier, theme: IColorTheme): Color | undefined;\n\n}\n\nclass ColorRegistry implements IColorRegistry {\n\n\tprivate readonly _onDidChangeSchema = new Emitter();\n\treadonly onDidChangeSchema: Event = this._onDidChangeSchema.event;\n\n\tprivate colorsById: { [key: string]: ColorContribution };\n\tprivate colorSchema: IJSONSchema & { properties: IJSONSchemaMap } = { type: 'object', properties: {} };\n\tprivate colorReferenceSchema: IJSONSchema & { enum: string[], enumDescriptions: string[] } = { type: 'string', enum: [], enumDescriptions: [] };\n\n\tconstructor() {\n\t\tthis.colorsById = {};\n\t}\n\n\tpublic registerColor(id: string, defaults: ColorDefaults | null, description: string, needsTransparency = false, deprecationMessage?: string): ColorIdentifier {\n\t\tlet colorContribution: ColorContribution = { id, description, defaults, needsTransparency, deprecationMessage };\n\t\tthis.colorsById[id] = colorContribution;\n\t\tlet propertySchema: IJSONSchema = { type: 'string', description, format: 'color-hex', defaultSnippets: [{ body: '${1:#ff0000}' }] };\n\t\tif (deprecationMessage) {\n\t\t\tpropertySchema.deprecationMessage = deprecationMessage;\n\t\t}\n\t\tthis.colorSchema.properties[id] = propertySchema;\n\t\tthis.colorReferenceSchema.enum.push(id);\n\t\tthis.colorReferenceSchema.enumDescriptions.push(description);\n\n\t\tthis._onDidChangeSchema.fire();\n\t\treturn id;\n\t}\n\n\tpublic getColors(): ColorContribution[] {\n\t\treturn Object.keys(this.colorsById).map(id => this.colorsById[id]);\n\t}\n\n\tpublic resolveDefaultColor(id: ColorIdentifier, theme: IColorTheme): Color | undefined {\n\t\tconst colorDesc = this.colorsById[id];\n\t\tif (colorDesc && colorDesc.defaults) {\n\t\t\tconst colorValue = colorDesc.defaults[theme.type];\n\t\t\treturn resolveColorValue(colorValue, theme);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tpublic getColorSchema(): IJSONSchema {\n\t\treturn this.colorSchema;\n\t}\n\n\tpublic toString() {\n\t\tlet sorter = (a: string, b: string) => {\n\t\t\tlet cat1 = a.indexOf('.') === -1 ? 0 : 1;\n\t\t\tlet cat2 = b.indexOf('.') === -1 ? 0 : 1;\n\t\t\tif (cat1 !== cat2) {\n\t\t\t\treturn cat1 - cat2;\n\t\t\t}\n\t\t\treturn a.localeCompare(b);\n\t\t};\n\n\t\treturn Object.keys(this.colorsById).sort(sorter).map(k => `- \\`${k}\\`: ${this.colorsById[k].description}`).join('\\n');\n\t}\n\n}\n\nconst colorRegistry = new ColorRegistry();\nplatform.Registry.add(Extensions.ColorContribution, colorRegistry);\n\nexport function registerColor(id: string, defaults: ColorDefaults | null, description: string, needsTransparency?: boolean, deprecationMessage?: string): ColorIdentifier {\n\treturn colorRegistry.registerColor(id, defaults, description, needsTransparency, deprecationMessage);\n}\n\n// ----- base colors\n\nexport const foreground = registerColor('foreground', { dark: '#CCCCCC', light: '#616161', hc: '#FFFFFF' }, nls.localize('foreground', \"Overall foreground color. This color is only used if not overridden by a component.\"));\nexport const errorForeground = registerColor('errorForeground', { dark: '#F48771', light: '#A1260D', hc: '#F48771' }, nls.localize('errorForeground', \"Overall foreground color for error messages. This color is only used if not overridden by a component.\"));\nexport const descriptionForeground = registerColor('descriptionForeground', { light: '#717171', dark: transparent(foreground, 0.7), hc: transparent(foreground, 0.7) }, nls.localize('descriptionForeground', \"Foreground color for description text providing additional information, for example for a label.\"));\nexport const iconForeground = registerColor('icon.foreground', { dark: '#C5C5C5', light: '#424242', hc: '#FFFFFF' }, nls.localize('iconForeground', \"The default color for icons in the workbench.\"));\n\nexport const focusBorder = registerColor('focusBorder', { dark: '#007FD4', light: '#0090F1', hc: '#F38518' }, nls.localize('focusBorder', \"Overall border color for focused elements. This color is only used if not overridden by a component.\"));\n\nexport const contrastBorder = registerColor('contrastBorder', { light: null, dark: null, hc: '#6FC3DF' }, nls.localize('contrastBorder', \"An extra border around elements to separate them from others for greater contrast.\"));\nexport const activeContrastBorder = registerColor('contrastActiveBorder', { light: null, dark: null, hc: focusBorder }, nls.localize('activeContrastBorder', \"An extra border around active elements to separate them from others for greater contrast.\"));\n\nexport const selectionBackground = registerColor('selection.background', { light: null, dark: null, hc: null }, nls.localize('selectionBackground', \"The background color of text selections in the workbench (e.g. for input fields or text areas). Note that this does not apply to selections within the editor.\"));\n\n// ------ text colors\n\nexport const textSeparatorForeground = registerColor('textSeparator.foreground', { light: '#0000002e', dark: '#ffffff2e', hc: Color.black }, nls.localize('textSeparatorForeground', \"Color for text separators.\"));\nexport const textLinkForeground = registerColor('textLink.foreground', { light: '#006AB1', dark: '#3794FF', hc: '#3794FF' }, nls.localize('textLinkForeground', \"Foreground color for links in text.\"));\nexport const textLinkActiveForeground = registerColor('textLink.activeForeground', { light: '#006AB1', dark: '#3794FF', hc: '#3794FF' }, nls.localize('textLinkActiveForeground', \"Foreground color for links in text when clicked on and on mouse hover.\"));\nexport const textPreformatForeground = registerColor('textPreformat.foreground', { light: '#A31515', dark: '#D7BA7D', hc: '#D7BA7D' }, nls.localize('textPreformatForeground', \"Foreground color for preformatted text segments.\"));\nexport const textBlockQuoteBackground = registerColor('textBlockQuote.background', { light: '#7f7f7f1a', dark: '#7f7f7f1a', hc: null }, nls.localize('textBlockQuoteBackground', \"Background color for block quotes in text.\"));\nexport const textBlockQuoteBorder = registerColor('textBlockQuote.border', { light: '#007acc80', dark: '#007acc80', hc: Color.white }, nls.localize('textBlockQuoteBorder', \"Border color for block quotes in text.\"));\nexport const textCodeBlockBackground = registerColor('textCodeBlock.background', { light: '#dcdcdc66', dark: '#0a0a0a66', hc: Color.black }, nls.localize('textCodeBlockBackground', \"Background color for code blocks in text.\"));\n\n// ----- widgets\nexport const widgetShadow = registerColor('widget.shadow', { dark: transparent(Color.black, .36), light: transparent(Color.black, .16), hc: null }, nls.localize('widgetShadow', 'Shadow color of widgets such as find/replace inside the editor.'));\n\nexport const inputBackground = registerColor('input.background', { dark: '#3C3C3C', light: Color.white, hc: Color.black }, nls.localize('inputBoxBackground', \"Input box background.\"));\nexport const inputForeground = registerColor('input.foreground', { dark: foreground, light: foreground, hc: foreground }, nls.localize('inputBoxForeground', \"Input box foreground.\"));\nexport const inputBorder = registerColor('input.border', { dark: null, light: null, hc: contrastBorder }, nls.localize('inputBoxBorder', \"Input box border.\"));\nexport const inputActiveOptionBorder = registerColor('inputOption.activeBorder', { dark: '#007ACC00', light: '#007ACC00', hc: contrastBorder }, nls.localize('inputBoxActiveOptionBorder', \"Border color of activated options in input fields.\"));\nexport const inputActiveOptionHoverBackground = registerColor('inputOption.hoverBackground', { dark: '#5a5d5e80', light: '#b8b8b850', hc: null }, nls.localize('inputOption.hoverBackground', \"Background color of activated options in input fields.\"));\nexport const inputActiveOptionBackground = registerColor('inputOption.activeBackground', { dark: transparent(focusBorder, 0.4), light: transparent(focusBorder, 0.2), hc: Color.transparent }, nls.localize('inputOption.activeBackground', \"Background hover color of options in input fields.\"));\nexport const inputActiveOptionForeground = registerColor('inputOption.activeForeground', { dark: Color.white, light: Color.black, hc: null }, nls.localize('inputOption.activeForeground', \"Foreground color of activated options in input fields.\"));\nexport const inputPlaceholderForeground = registerColor('input.placeholderForeground', { light: transparent(foreground, 0.5), dark: transparent(foreground, 0.5), hc: transparent(foreground, 0.7) }, nls.localize('inputPlaceholderForeground', \"Input box foreground color for placeholder text.\"));\n\nexport const inputValidationInfoBackground = registerColor('inputValidation.infoBackground', { dark: '#063B49', light: '#D6ECF2', hc: Color.black }, nls.localize('inputValidationInfoBackground', \"Input validation background color for information severity.\"));\nexport const inputValidationInfoForeground = registerColor('inputValidation.infoForeground', { dark: null, light: null, hc: null }, nls.localize('inputValidationInfoForeground', \"Input validation foreground color for information severity.\"));\nexport const inputValidationInfoBorder = registerColor('inputValidation.infoBorder', { dark: '#007acc', light: '#007acc', hc: contrastBorder }, nls.localize('inputValidationInfoBorder', \"Input validation border color for information severity.\"));\nexport const inputValidationWarningBackground = registerColor('inputValidation.warningBackground', { dark: '#352A05', light: '#F6F5D2', hc: Color.black }, nls.localize('inputValidationWarningBackground', \"Input validation background color for warning severity.\"));\nexport const inputValidationWarningForeground = registerColor('inputValidation.warningForeground', { dark: null, light: null, hc: null }, nls.localize('inputValidationWarningForeground', \"Input validation foreground color for warning severity.\"));\nexport const inputValidationWarningBorder = registerColor('inputValidation.warningBorder', { dark: '#B89500', light: '#B89500', hc: contrastBorder }, nls.localize('inputValidationWarningBorder', \"Input validation border color for warning severity.\"));\nexport const inputValidationErrorBackground = registerColor('inputValidation.errorBackground', { dark: '#5A1D1D', light: '#F2DEDE', hc: Color.black }, nls.localize('inputValidationErrorBackground', \"Input validation background color for error severity.\"));\nexport const inputValidationErrorForeground = registerColor('inputValidation.errorForeground', { dark: null, light: null, hc: null }, nls.localize('inputValidationErrorForeground', \"Input validation foreground color for error severity.\"));\nexport const inputValidationErrorBorder = registerColor('inputValidation.errorBorder', { dark: '#BE1100', light: '#BE1100', hc: contrastBorder }, nls.localize('inputValidationErrorBorder', \"Input validation border color for error severity.\"));\n\nexport const selectBackground = registerColor('dropdown.background', { dark: '#3C3C3C', light: Color.white, hc: Color.black }, nls.localize('dropdownBackground', \"Dropdown background.\"));\nexport const selectListBackground = registerColor('dropdown.listBackground', { dark: null, light: null, hc: Color.black }, nls.localize('dropdownListBackground', \"Dropdown list background.\"));\nexport const selectForeground = registerColor('dropdown.foreground', { dark: '#F0F0F0', light: null, hc: Color.white }, nls.localize('dropdownForeground', \"Dropdown foreground.\"));\nexport const selectBorder = registerColor('dropdown.border', { dark: selectBackground, light: '#CECECE', hc: contrastBorder }, nls.localize('dropdownBorder', \"Dropdown border.\"));\n\nexport const simpleCheckboxBackground = registerColor('checkbox.background', { dark: selectBackground, light: selectBackground, hc: selectBackground }, nls.localize('checkbox.background', \"Background color of checkbox widget.\"));\nexport const simpleCheckboxForeground = registerColor('checkbox.foreground', { dark: selectForeground, light: selectForeground, hc: selectForeground }, nls.localize('checkbox.foreground', \"Foreground color of checkbox widget.\"));\nexport const simpleCheckboxBorder = registerColor('checkbox.border', { dark: selectBorder, light: selectBorder, hc: selectBorder }, nls.localize('checkbox.border', \"Border color of checkbox widget.\"));\n\nexport const buttonForeground = registerColor('button.foreground', { dark: Color.white, light: Color.white, hc: Color.white }, nls.localize('buttonForeground', \"Button foreground color.\"));\nexport const buttonBackground = registerColor('button.background', { dark: '#0E639C', light: '#007ACC', hc: null }, nls.localize('buttonBackground', \"Button background color.\"));\nexport const buttonHoverBackground = registerColor('button.hoverBackground', { dark: lighten(buttonBackground, 0.2), light: darken(buttonBackground, 0.2), hc: null }, nls.localize('buttonHoverBackground', \"Button background color when hovering.\"));\nexport const buttonBorder = registerColor('button.border', { dark: contrastBorder, light: contrastBorder, hc: contrastBorder }, nls.localize('buttonBorder', \"Button border color.\"));\n\nexport const buttonSecondaryForeground = registerColor('button.secondaryForeground', { dark: Color.white, light: Color.white, hc: Color.white }, nls.localize('buttonSecondaryForeground', \"Secondary button foreground color.\"));\nexport const buttonSecondaryBackground = registerColor('button.secondaryBackground', { dark: '#3A3D41', light: '#5F6A79', hc: null }, nls.localize('buttonSecondaryBackground', \"Secondary button background color.\"));\nexport const buttonSecondaryHoverBackground = registerColor('button.secondaryHoverBackground', { dark: lighten(buttonSecondaryBackground, 0.2), light: darken(buttonSecondaryBackground, 0.2), hc: null }, nls.localize('buttonSecondaryHoverBackground', \"Secondary button background color when hovering.\"));\n\nexport const badgeBackground = registerColor('badge.background', { dark: '#4D4D4D', light: '#C4C4C4', hc: Color.black }, nls.localize('badgeBackground', \"Badge background color. Badges are small information labels, e.g. for search results count.\"));\nexport const badgeForeground = registerColor('badge.foreground', { dark: Color.white, light: '#333', hc: Color.white }, nls.localize('badgeForeground', \"Badge foreground color. Badges are small information labels, e.g. for search results count.\"));\n\nexport const scrollbarShadow = registerColor('scrollbar.shadow', { dark: '#000000', light: '#DDDDDD', hc: null }, nls.localize('scrollbarShadow', \"Scrollbar shadow to indicate that the view is scrolled.\"));\nexport const scrollbarSliderBackground = registerColor('scrollbarSlider.background', { dark: Color.fromHex('#797979').transparent(0.4), light: Color.fromHex('#646464').transparent(0.4), hc: transparent(contrastBorder, 0.6) }, nls.localize('scrollbarSliderBackground', \"Scrollbar slider background color.\"));\nexport const scrollbarSliderHoverBackground = registerColor('scrollbarSlider.hoverBackground', { dark: Color.fromHex('#646464').transparent(0.7), light: Color.fromHex('#646464').transparent(0.7), hc: transparent(contrastBorder, 0.8) }, nls.localize('scrollbarSliderHoverBackground', \"Scrollbar slider background color when hovering.\"));\nexport const scrollbarSliderActiveBackground = registerColor('scrollbarSlider.activeBackground', { dark: Color.fromHex('#BFBFBF').transparent(0.4), light: Color.fromHex('#000000').transparent(0.6), hc: contrastBorder }, nls.localize('scrollbarSliderActiveBackground', \"Scrollbar slider background color when clicked on.\"));\n\nexport const progressBarBackground = registerColor('progressBar.background', { dark: Color.fromHex('#0E70C0'), light: Color.fromHex('#0E70C0'), hc: contrastBorder }, nls.localize('progressBarBackground', \"Background color of the progress bar that can show for long running operations.\"));\n\nexport const editorErrorBackground = registerColor('editorError.background', { dark: null, light: null, hc: null }, nls.localize('editorError.background', 'Background color of error text in the editor. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const editorErrorForeground = registerColor('editorError.foreground', { dark: '#F14C4C', light: '#E51400', hc: null }, nls.localize('editorError.foreground', 'Foreground color of error squigglies in the editor.'));\nexport const editorErrorBorder = registerColor('editorError.border', { dark: null, light: null, hc: Color.fromHex('#E47777').transparent(0.8) }, nls.localize('errorBorder', 'Border color of error boxes in the editor.'));\n\nexport const editorWarningBackground = registerColor('editorWarning.background', { dark: null, light: null, hc: null }, nls.localize('editorWarning.background', 'Background color of warning text in the editor. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const editorWarningForeground = registerColor('editorWarning.foreground', { dark: '#CCA700', light: '#BF8803', hc: null }, nls.localize('editorWarning.foreground', 'Foreground color of warning squigglies in the editor.'));\nexport const editorWarningBorder = registerColor('editorWarning.border', { dark: null, light: null, hc: Color.fromHex('#FFCC00').transparent(0.8) }, nls.localize('warningBorder', 'Border color of warning boxes in the editor.'));\n\nexport const editorInfoBackground = registerColor('editorInfo.background', { dark: null, light: null, hc: null }, nls.localize('editorInfo.background', 'Background color of info text in the editor. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const editorInfoForeground = registerColor('editorInfo.foreground', { dark: '#3794FF', light: '#1a85ff', hc: '#3794FF' }, nls.localize('editorInfo.foreground', 'Foreground color of info squigglies in the editor.'));\nexport const editorInfoBorder = registerColor('editorInfo.border', { dark: null, light: null, hc: Color.fromHex('#3794FF').transparent(0.8) }, nls.localize('infoBorder', 'Border color of info boxes in the editor.'));\n\nexport const editorHintForeground = registerColor('editorHint.foreground', { dark: Color.fromHex('#eeeeee').transparent(0.7), light: '#6c6c6c', hc: null }, nls.localize('editorHint.foreground', 'Foreground color of hint squigglies in the editor.'));\nexport const editorHintBorder = registerColor('editorHint.border', { dark: null, light: null, hc: Color.fromHex('#eeeeee').transparent(0.8) }, nls.localize('hintBorder', 'Border color of hint boxes in the editor.'));\n\nexport const sashHoverBorder = registerColor('sash.hoverBorder', { dark: focusBorder, light: focusBorder, hc: focusBorder }, nls.localize('sashActiveBorder', \"Border color of active sashes.\"));\n\n/**\n * Editor background color.\n * Because of bug https://monacotools.visualstudio.com/DefaultCollection/Monaco/_workitems/edit/13254\n * we are *not* using the color white (or #ffffff, rgba(255,255,255)) but something very close to white.\n */\nexport const editorBackground = registerColor('editor.background', { light: '#fffffe', dark: '#1E1E1E', hc: Color.black }, nls.localize('editorBackground', \"Editor background color.\"));\n\n/**\n * Editor foreground color.\n */\nexport const editorForeground = registerColor('editor.foreground', { light: '#333333', dark: '#BBBBBB', hc: Color.white }, nls.localize('editorForeground', \"Editor default foreground color.\"));\n\n/**\n * Editor widgets\n */\nexport const editorWidgetBackground = registerColor('editorWidget.background', { dark: '#252526', light: '#F3F3F3', hc: '#0C141F' }, nls.localize('editorWidgetBackground', 'Background color of editor widgets, such as find/replace.'));\nexport const editorWidgetForeground = registerColor('editorWidget.foreground', { dark: foreground, light: foreground, hc: foreground }, nls.localize('editorWidgetForeground', 'Foreground color of editor widgets, such as find/replace.'));\n\nexport const editorWidgetBorder = registerColor('editorWidget.border', { dark: '#454545', light: '#C8C8C8', hc: contrastBorder }, nls.localize('editorWidgetBorder', 'Border color of editor widgets. The color is only used if the widget chooses to have a border and if the color is not overridden by a widget.'));\n\nexport const editorWidgetResizeBorder = registerColor('editorWidget.resizeBorder', { light: null, dark: null, hc: null }, nls.localize('editorWidgetResizeBorder', \"Border color of the resize bar of editor widgets. The color is only used if the widget chooses to have a resize border and if the color is not overridden by a widget.\"));\n\n/**\n * Quick pick widget\n */\nexport const quickInputBackground = registerColor('quickInput.background', { dark: editorWidgetBackground, light: editorWidgetBackground, hc: editorWidgetBackground }, nls.localize('pickerBackground', \"Quick picker background color. The quick picker widget is the container for pickers like the command palette.\"));\nexport const quickInputForeground = registerColor('quickInput.foreground', { dark: editorWidgetForeground, light: editorWidgetForeground, hc: editorWidgetForeground }, nls.localize('pickerForeground', \"Quick picker foreground color. The quick picker widget is the container for pickers like the command palette.\"));\nexport const quickInputTitleBackground = registerColor('quickInputTitle.background', { dark: new Color(new RGBA(255, 255, 255, 0.105)), light: new Color(new RGBA(0, 0, 0, 0.06)), hc: '#000000' }, nls.localize('pickerTitleBackground', \"Quick picker title background color. The quick picker widget is the container for pickers like the command palette.\"));\nexport const pickerGroupForeground = registerColor('pickerGroup.foreground', { dark: '#3794FF', light: '#0066BF', hc: Color.white }, nls.localize('pickerGroupForeground', \"Quick picker color for grouping labels.\"));\nexport const pickerGroupBorder = registerColor('pickerGroup.border', { dark: '#3F3F46', light: '#CCCEDB', hc: Color.white }, nls.localize('pickerGroupBorder', \"Quick picker color for grouping borders.\"));\n\n/**\n * Keybinding label\n */\nexport const keybindingLabelBackground = registerColor('keybindingLabel.background', { dark: new Color(new RGBA(128, 128, 128, 0.17)), light: new Color(new RGBA(221, 221, 221, 0.4)), hc: Color.transparent }, nls.localize('keybindingLabelBackground', \"Keybinding label background color. The keybinding label is used to represent a keyboard shortcut.\"));\nexport const keybindingLabelForeground = registerColor('keybindingLabel.foreground', { dark: Color.fromHex('#CCCCCC'), light: Color.fromHex('#555555'), hc: Color.white }, nls.localize('keybindingLabelForeground', \"Keybinding label foreground color. The keybinding label is used to represent a keyboard shortcut.\"));\nexport const keybindingLabelBorder = registerColor('keybindingLabel.border', { dark: new Color(new RGBA(51, 51, 51, 0.6)), light: new Color(new RGBA(204, 204, 204, 0.4)), hc: new Color(new RGBA(111, 195, 223)) }, nls.localize('keybindingLabelBorder', \"Keybinding label border color. The keybinding label is used to represent a keyboard shortcut.\"));\nexport const keybindingLabelBottomBorder = registerColor('keybindingLabel.bottomBorder', { dark: new Color(new RGBA(68, 68, 68, 0.6)), light: new Color(new RGBA(187, 187, 187, 0.4)), hc: new Color(new RGBA(111, 195, 223)) }, nls.localize('keybindingLabelBottomBorder', \"Keybinding label border bottom color. The keybinding label is used to represent a keyboard shortcut.\"));\n\n/**\n * Editor selection colors.\n */\nexport const editorSelectionBackground = registerColor('editor.selectionBackground', { light: '#ADD6FF', dark: '#264F78', hc: '#f3f518' }, nls.localize('editorSelectionBackground', \"Color of the editor selection.\"));\nexport const editorSelectionForeground = registerColor('editor.selectionForeground', { light: null, dark: null, hc: '#000000' }, nls.localize('editorSelectionForeground', \"Color of the selected text for high contrast.\"));\nexport const editorInactiveSelection = registerColor('editor.inactiveSelectionBackground', { light: transparent(editorSelectionBackground, 0.5), dark: transparent(editorSelectionBackground, 0.5), hc: transparent(editorSelectionBackground, 0.5) }, nls.localize('editorInactiveSelection', \"Color of the selection in an inactive editor. The color must not be opaque so as not to hide underlying decorations.\"), true);\nexport const editorSelectionHighlight = registerColor('editor.selectionHighlightBackground', { light: lessProminent(editorSelectionBackground, editorBackground, 0.3, 0.6), dark: lessProminent(editorSelectionBackground, editorBackground, 0.3, 0.6), hc: null }, nls.localize('editorSelectionHighlight', 'Color for regions with the same content as the selection. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const editorSelectionHighlightBorder = registerColor('editor.selectionHighlightBorder', { light: null, dark: null, hc: activeContrastBorder }, nls.localize('editorSelectionHighlightBorder', \"Border color for regions with the same content as the selection.\"));\n\n\n/**\n * Editor find match colors.\n */\nexport const editorFindMatch = registerColor('editor.findMatchBackground', { light: '#A8AC94', dark: '#515C6A', hc: null }, nls.localize('editorFindMatch', \"Color of the current search match.\"));\nexport const editorFindMatchHighlight = registerColor('editor.findMatchHighlightBackground', { light: '#EA5C0055', dark: '#EA5C0055', hc: null }, nls.localize('findMatchHighlight', \"Color of the other search matches. The color must not be opaque so as not to hide underlying decorations.\"), true);\nexport const editorFindRangeHighlight = registerColor('editor.findRangeHighlightBackground', { dark: '#3a3d4166', light: '#b4b4b44d', hc: null }, nls.localize('findRangeHighlight', \"Color of the range limiting the search. The color must not be opaque so as not to hide underlying decorations.\"), true);\nexport const editorFindMatchBorder = registerColor('editor.findMatchBorder', { light: null, dark: null, hc: activeContrastBorder }, nls.localize('editorFindMatchBorder', \"Border color of the current search match.\"));\nexport const editorFindMatchHighlightBorder = registerColor('editor.findMatchHighlightBorder', { light: null, dark: null, hc: activeContrastBorder }, nls.localize('findMatchHighlightBorder', \"Border color of the other search matches.\"));\nexport const editorFindRangeHighlightBorder = registerColor('editor.findRangeHighlightBorder', { dark: null, light: null, hc: transparent(activeContrastBorder, 0.4) }, nls.localize('findRangeHighlightBorder', \"Border color of the range limiting the search. The color must not be opaque so as not to hide underlying decorations.\"), true);\n\n/**\n * Search Editor query match colors.\n *\n * Distinct from normal editor find match to allow for better differentiation\n */\nexport const searchEditorFindMatch = registerColor('searchEditor.findMatchBackground', { light: transparent(editorFindMatchHighlight, 0.66), dark: transparent(editorFindMatchHighlight, 0.66), hc: editorFindMatchHighlight }, nls.localize('searchEditor.queryMatch', \"Color of the Search Editor query matches.\"));\nexport const searchEditorFindMatchBorder = registerColor('searchEditor.findMatchBorder', { light: transparent(editorFindMatchHighlightBorder, 0.66), dark: transparent(editorFindMatchHighlightBorder, 0.66), hc: editorFindMatchHighlightBorder }, nls.localize('searchEditor.editorFindMatchBorder', \"Border color of the Search Editor query matches.\"));\n\n/**\n * Editor hover\n */\nexport const editorHoverHighlight = registerColor('editor.hoverHighlightBackground', { light: '#ADD6FF26', dark: '#264f7840', hc: '#ADD6FF26' }, nls.localize('hoverHighlight', 'Highlight below the word for which a hover is shown. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const editorHoverBackground = registerColor('editorHoverWidget.background', { light: editorWidgetBackground, dark: editorWidgetBackground, hc: editorWidgetBackground }, nls.localize('hoverBackground', 'Background color of the editor hover.'));\nexport const editorHoverForeground = registerColor('editorHoverWidget.foreground', { light: editorWidgetForeground, dark: editorWidgetForeground, hc: editorWidgetForeground }, nls.localize('hoverForeground', 'Foreground color of the editor hover.'));\nexport const editorHoverBorder = registerColor('editorHoverWidget.border', { light: editorWidgetBorder, dark: editorWidgetBorder, hc: editorWidgetBorder }, nls.localize('hoverBorder', 'Border color of the editor hover.'));\nexport const editorHoverStatusBarBackground = registerColor('editorHoverWidget.statusBarBackground', { dark: lighten(editorHoverBackground, 0.2), light: darken(editorHoverBackground, 0.05), hc: editorWidgetBackground }, nls.localize('statusBarBackground', \"Background color of the editor hover status bar.\"));\n/**\n * Editor link colors\n */\nexport const editorActiveLinkForeground = registerColor('editorLink.activeForeground', { dark: '#4E94CE', light: Color.blue, hc: Color.cyan }, nls.localize('activeLinkForeground', 'Color of active links.'));\n\n/**\n * Inline hints\n */\nexport const editorInlayHintForeground = registerColor('editorInlayHint.foreground', { dark: transparent(badgeForeground, .8), light: transparent(badgeForeground, .8), hc: badgeForeground }, nls.localize('editorInlayHintForeground', 'Foreground color of inline hints'));\nexport const editorInlayHintBackground = registerColor('editorInlayHint.background', { dark: transparent(badgeBackground, .6), light: transparent(badgeBackground, .3), hc: badgeBackground }, nls.localize('editorInlayHintBackground', 'Background color of inline hints'));\nexport const editorInlayHintTypeForeground = registerColor('editorInlayHint.typeForeground', { dark: editorInlayHintForeground, light: editorInlayHintForeground, hc: editorInlayHintForeground }, nls.localize('editorInlayHintForegroundTypes', 'Foreground color of inline hints for types'));\nexport const editorInlayHintTypeBackground = registerColor('editorInlayHint.typeBackground', { dark: editorInlayHintBackground, light: editorInlayHintBackground, hc: editorInlayHintBackground }, nls.localize('editorInlayHintBackgroundTypes', 'Background color of inline hints for types'));\nexport const editorInlayHintParameterForeground = registerColor('editorInlayHint.parameterForeground', { dark: editorInlayHintForeground, light: editorInlayHintForeground, hc: editorInlayHintForeground }, nls.localize('editorInlayHintForegroundParameter', 'Foreground color of inline hints for parameters'));\nexport const editorInlayHintParameterBackground = registerColor('editorInlayHint.parameterBackground', { dark: editorInlayHintBackground, light: editorInlayHintBackground, hc: editorInlayHintBackground }, nls.localize('editorInlayHintBackgroundParameter', 'Background color of inline hints for parameters'));\n\n/**\n * Editor lighbulb icon colors\n */\nexport const editorLightBulbForeground = registerColor('editorLightBulb.foreground', { dark: '#FFCC00', light: '#DDB100', hc: '#FFCC00' }, nls.localize('editorLightBulbForeground', \"The color used for the lightbulb actions icon.\"));\nexport const editorLightBulbAutoFixForeground = registerColor('editorLightBulbAutoFix.foreground', { dark: '#75BEFF', light: '#007ACC', hc: '#75BEFF' }, nls.localize('editorLightBulbAutoFixForeground', \"The color used for the lightbulb auto fix actions icon.\"));\n\n/**\n * Diff Editor Colors\n */\nexport const defaultInsertColor = new Color(new RGBA(155, 185, 85, 0.2));\nexport const defaultRemoveColor = new Color(new RGBA(255, 0, 0, 0.2));\n\nexport const diffInserted = registerColor('diffEditor.insertedTextBackground', { dark: defaultInsertColor, light: defaultInsertColor, hc: null }, nls.localize('diffEditorInserted', 'Background color for text that got inserted. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const diffRemoved = registerColor('diffEditor.removedTextBackground', { dark: defaultRemoveColor, light: defaultRemoveColor, hc: null }, nls.localize('diffEditorRemoved', 'Background color for text that got removed. The color must not be opaque so as not to hide underlying decorations.'), true);\n\nexport const diffInsertedOutline = registerColor('diffEditor.insertedTextBorder', { dark: null, light: null, hc: '#33ff2eff' }, nls.localize('diffEditorInsertedOutline', 'Outline color for the text that got inserted.'));\nexport const diffRemovedOutline = registerColor('diffEditor.removedTextBorder', { dark: null, light: null, hc: '#FF008F' }, nls.localize('diffEditorRemovedOutline', 'Outline color for text that got removed.'));\n\nexport const diffBorder = registerColor('diffEditor.border', { dark: null, light: null, hc: contrastBorder }, nls.localize('diffEditorBorder', 'Border color between the two text editors.'));\nexport const diffDiagonalFill = registerColor('diffEditor.diagonalFill', { dark: '#cccccc33', light: '#22222233', hc: null }, nls.localize('diffDiagonalFill', \"Color of the diff editor's diagonal fill. The diagonal fill is used in side-by-side diff views.\"));\n\n/**\n * List and tree colors\n */\nexport const listFocusBackground = registerColor('list.focusBackground', { dark: null, light: null, hc: null }, nls.localize('listFocusBackground', \"List/Tree background color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listFocusForeground = registerColor('list.focusForeground', { dark: null, light: null, hc: null }, nls.localize('listFocusForeground', \"List/Tree foreground color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listFocusOutline = registerColor('list.focusOutline', { dark: focusBorder, light: focusBorder, hc: activeContrastBorder }, nls.localize('listFocusOutline', \"List/Tree outline color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listActiveSelectionBackground = registerColor('list.activeSelectionBackground', { dark: '#094771', light: '#0060C0', hc: null }, nls.localize('listActiveSelectionBackground', \"List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listActiveSelectionForeground = registerColor('list.activeSelectionForeground', { dark: Color.white, light: Color.white, hc: null }, nls.localize('listActiveSelectionForeground', \"List/Tree foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listActiveSelectionIconForeground = registerColor('list.activeSelectionIconForeground', { dark: null, light: null, hc: null }, nls.localize('listActiveSelectionIconForeground', \"List/Tree icon foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listInactiveSelectionBackground = registerColor('list.inactiveSelectionBackground', { dark: '#37373D', light: '#E4E6F1', hc: null }, nls.localize('listInactiveSelectionBackground', \"List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listInactiveSelectionForeground = registerColor('list.inactiveSelectionForeground', { dark: null, light: null, hc: null }, nls.localize('listInactiveSelectionForeground', \"List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listInactiveSelectionIconForeground = registerColor('list.inactiveSelectionIconForeground', { dark: null, light: null, hc: null }, nls.localize('listInactiveSelectionIconForeground', \"List/Tree icon foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listInactiveFocusBackground = registerColor('list.inactiveFocusBackground', { dark: null, light: null, hc: null }, nls.localize('listInactiveFocusBackground', \"List/Tree background color for the focused item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listInactiveFocusOutline = registerColor('list.inactiveFocusOutline', { dark: null, light: null, hc: null }, nls.localize('listInactiveFocusOutline', \"List/Tree outline color for the focused item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listHoverBackground = registerColor('list.hoverBackground', { dark: '#2A2D2E', light: '#F0F0F0', hc: null }, nls.localize('listHoverBackground', \"List/Tree background when hovering over items using the mouse.\"));\nexport const listHoverForeground = registerColor('list.hoverForeground', { dark: null, light: null, hc: null }, nls.localize('listHoverForeground', \"List/Tree foreground when hovering over items using the mouse.\"));\nexport const listDropBackground = registerColor('list.dropBackground', { dark: '#062F4A', light: '#D6EBFF', hc: null }, nls.localize('listDropBackground', \"List/Tree drag and drop background when moving items around using the mouse.\"));\nexport const listHighlightForeground = registerColor('list.highlightForeground', { dark: '#18A3FF', light: '#0066BF', hc: focusBorder }, nls.localize('highlight', 'List/Tree foreground color of the match highlights when searching inside the list/tree.'));\nexport const listFocusHighlightForeground = registerColor('list.focusHighlightForeground', { dark: listHighlightForeground, light: ifDefinedThenElse(listActiveSelectionBackground, listHighlightForeground, '#9DDDFF'), hc: listHighlightForeground }, nls.localize('listFocusHighlightForeground', 'List/Tree foreground color of the match highlights on actively focused items when searching inside the list/tree.'));\nexport const listInvalidItemForeground = registerColor('list.invalidItemForeground', { dark: '#B89500', light: '#B89500', hc: '#B89500' }, nls.localize('invalidItemForeground', 'List/Tree foreground color for invalid items, for example an unresolved root in explorer.'));\nexport const listErrorForeground = registerColor('list.errorForeground', { dark: '#F88070', light: '#B01011', hc: null }, nls.localize('listErrorForeground', 'Foreground color of list items containing errors.'));\nexport const listWarningForeground = registerColor('list.warningForeground', { dark: '#CCA700', light: '#855F00', hc: null }, nls.localize('listWarningForeground', 'Foreground color of list items containing warnings.'));\nexport const listFilterWidgetBackground = registerColor('listFilterWidget.background', { light: '#efc1ad', dark: '#653723', hc: Color.black }, nls.localize('listFilterWidgetBackground', 'Background color of the type filter widget in lists and trees.'));\nexport const listFilterWidgetOutline = registerColor('listFilterWidget.outline', { dark: Color.transparent, light: Color.transparent, hc: '#f38518' }, nls.localize('listFilterWidgetOutline', 'Outline color of the type filter widget in lists and trees.'));\nexport const listFilterWidgetNoMatchesOutline = registerColor('listFilterWidget.noMatchesOutline', { dark: '#BE1100', light: '#BE1100', hc: contrastBorder }, nls.localize('listFilterWidgetNoMatchesOutline', 'Outline color of the type filter widget in lists and trees, when there are no matches.'));\nexport const listFilterMatchHighlight = registerColor('list.filterMatchBackground', { dark: editorFindMatchHighlight, light: editorFindMatchHighlight, hc: null }, nls.localize('listFilterMatchHighlight', 'Background color of the filtered match.'));\nexport const listFilterMatchHighlightBorder = registerColor('list.filterMatchBorder', { dark: editorFindMatchHighlightBorder, light: editorFindMatchHighlightBorder, hc: contrastBorder }, nls.localize('listFilterMatchHighlightBorder', 'Border color of the filtered match.'));\nexport const treeIndentGuidesStroke = registerColor('tree.indentGuidesStroke', { dark: '#585858', light: '#a9a9a9', hc: '#a9a9a9' }, nls.localize('treeIndentGuidesStroke', \"Tree stroke color for the indentation guides.\"));\nexport const tableColumnsBorder = registerColor('tree.tableColumnsBorder', { dark: '#CCCCCC20', light: '#61616120', hc: null }, nls.localize('tableColumnsBorder', \"Table border color between columns.\"));\nexport const tableOddRowsBackgroundColor = registerColor('tree.tableOddRowsBackground', { dark: transparent(foreground, 0.04), light: transparent(foreground, 0.04), hc: null }, nls.localize('tableOddRowsBackgroundColor', \"Background color for odd table rows.\"));\nexport const listDeemphasizedForeground = registerColor('list.deemphasizedForeground', { dark: '#8C8C8C', light: '#8E8E90', hc: '#A7A8A9' }, nls.localize('listDeemphasizedForeground', \"List/Tree foreground color for items that are deemphasized. \"));\n\n/**\n * Quick pick widget (dependent on List and tree colors)\n */\nexport const _deprecatedQuickInputListFocusBackground = registerColor('quickInput.list.focusBackground', { dark: null, light: null, hc: null }, '', undefined, nls.localize('quickInput.list.focusBackground deprecation', \"Please use quickInputList.focusBackground instead\"));\nexport const quickInputListFocusForeground = registerColor('quickInputList.focusForeground', { dark: listActiveSelectionForeground, light: listActiveSelectionForeground, hc: listActiveSelectionForeground }, nls.localize('quickInput.listFocusForeground', \"Quick picker foreground color for the focused item.\"));\nexport const quickInputListFocusIconForeground = registerColor('quickInputList.focusIconForeground', { dark: listActiveSelectionIconForeground, light: listActiveSelectionIconForeground, hc: listActiveSelectionIconForeground }, nls.localize('quickInput.listFocusIconForeground', \"Quick picker icon foreground color for the focused item.\"));\nexport const quickInputListFocusBackground = registerColor('quickInputList.focusBackground', { dark: oneOf(_deprecatedQuickInputListFocusBackground, listActiveSelectionBackground), light: oneOf(_deprecatedQuickInputListFocusBackground, listActiveSelectionBackground), hc: null }, nls.localize('quickInput.listFocusBackground', \"Quick picker background color for the focused item.\"));\n\n/**\n * Menu colors\n */\nexport const menuBorder = registerColor('menu.border', { dark: null, light: null, hc: contrastBorder }, nls.localize('menuBorder', \"Border color of menus.\"));\nexport const menuForeground = registerColor('menu.foreground', { dark: selectForeground, light: foreground, hc: selectForeground }, nls.localize('menuForeground', \"Foreground color of menu items.\"));\nexport const menuBackground = registerColor('menu.background', { dark: selectBackground, light: selectBackground, hc: selectBackground }, nls.localize('menuBackground', \"Background color of menu items.\"));\nexport const menuSelectionForeground = registerColor('menu.selectionForeground', { dark: listActiveSelectionForeground, light: listActiveSelectionForeground, hc: listActiveSelectionForeground }, nls.localize('menuSelectionForeground', \"Foreground color of the selected menu item in menus.\"));\nexport const menuSelectionBackground = registerColor('menu.selectionBackground', { dark: listActiveSelectionBackground, light: listActiveSelectionBackground, hc: listActiveSelectionBackground }, nls.localize('menuSelectionBackground', \"Background color of the selected menu item in menus.\"));\nexport const menuSelectionBorder = registerColor('menu.selectionBorder', { dark: null, light: null, hc: activeContrastBorder }, nls.localize('menuSelectionBorder', \"Border color of the selected menu item in menus.\"));\nexport const menuSeparatorBackground = registerColor('menu.separatorBackground', { dark: '#BBBBBB', light: '#888888', hc: contrastBorder }, nls.localize('menuSeparatorBackground', \"Color of a separator menu item in menus.\"));\n\n/**\n * Toolbar colors\n */\nexport const toolbarHoverBackground = registerColor('toolbar.hoverBackground', { dark: '#5a5d5e50', light: '#b8b8b850', hc: null }, nls.localize('toolbarHoverBackground', \"Toolbar background when hovering over actions using the mouse\"));\nexport const toolbarHoverOutline = registerColor('toolbar.hoverOutline', { dark: null, light: null, hc: activeContrastBorder }, nls.localize('toolbarHoverOutline', \"Toolbar outline when hovering over actions using the mouse\"));\nexport const toolbarActiveBackground = registerColor('toolbar.activeBackground', { dark: lighten(toolbarHoverBackground, 0.1), light: darken(toolbarHoverBackground, 0.1), hc: null }, nls.localize('toolbarActiveBackground', \"Toolbar background when holding the mouse over actions\"));\n\n/**\n * Snippet placeholder colors\n */\nexport const snippetTabstopHighlightBackground = registerColor('editor.snippetTabstopHighlightBackground', { dark: new Color(new RGBA(124, 124, 124, 0.3)), light: new Color(new RGBA(10, 50, 100, 0.2)), hc: new Color(new RGBA(124, 124, 124, 0.3)) }, nls.localize('snippetTabstopHighlightBackground', \"Highlight background color of a snippet tabstop.\"));\nexport const snippetTabstopHighlightBorder = registerColor('editor.snippetTabstopHighlightBorder', { dark: null, light: null, hc: null }, nls.localize('snippetTabstopHighlightBorder', \"Highlight border color of a snippet tabstop.\"));\nexport const snippetFinalTabstopHighlightBackground = registerColor('editor.snippetFinalTabstopHighlightBackground', { dark: null, light: null, hc: null }, nls.localize('snippetFinalTabstopHighlightBackground', \"Highlight background color of the final tabstop of a snippet.\"));\nexport const snippetFinalTabstopHighlightBorder = registerColor('editor.snippetFinalTabstopHighlightBorder', { dark: '#525252', light: new Color(new RGBA(10, 50, 100, 0.5)), hc: '#525252' }, nls.localize('snippetFinalTabstopHighlightBorder', \"Highlight border color of the final tabstop of a snippet.\"));\n\n/**\n * Breadcrumb colors\n */\nexport const breadcrumbsForeground = registerColor('breadcrumb.foreground', { light: transparent(foreground, 0.8), dark: transparent(foreground, 0.8), hc: transparent(foreground, 0.8) }, nls.localize('breadcrumbsFocusForeground', \"Color of focused breadcrumb items.\"));\nexport const breadcrumbsBackground = registerColor('breadcrumb.background', { light: editorBackground, dark: editorBackground, hc: editorBackground }, nls.localize('breadcrumbsBackground', \"Background color of breadcrumb items.\"));\nexport const breadcrumbsFocusForeground = registerColor('breadcrumb.focusForeground', { light: darken(foreground, 0.2), dark: lighten(foreground, 0.1), hc: lighten(foreground, 0.1) }, nls.localize('breadcrumbsFocusForeground', \"Color of focused breadcrumb items.\"));\nexport const breadcrumbsActiveSelectionForeground = registerColor('breadcrumb.activeSelectionForeground', { light: darken(foreground, 0.2), dark: lighten(foreground, 0.1), hc: lighten(foreground, 0.1) }, nls.localize('breadcrumbsSelectedForegound', \"Color of selected breadcrumb items.\"));\nexport const breadcrumbsPickerBackground = registerColor('breadcrumbPicker.background', { light: editorWidgetBackground, dark: editorWidgetBackground, hc: editorWidgetBackground }, nls.localize('breadcrumbsSelectedBackground', \"Background color of breadcrumb item picker.\"));\n\n/**\n * Merge-conflict colors\n */\n\nconst headerTransparency = 0.5;\nconst currentBaseColor = Color.fromHex('#40C8AE').transparent(headerTransparency);\nconst incomingBaseColor = Color.fromHex('#40A6FF').transparent(headerTransparency);\nconst commonBaseColor = Color.fromHex('#606060').transparent(0.4);\nconst contentTransparency = 0.4;\nconst rulerTransparency = 1;\n\nexport const mergeCurrentHeaderBackground = registerColor('merge.currentHeaderBackground', { dark: currentBaseColor, light: currentBaseColor, hc: null }, nls.localize('mergeCurrentHeaderBackground', 'Current header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const mergeCurrentContentBackground = registerColor('merge.currentContentBackground', { dark: transparent(mergeCurrentHeaderBackground, contentTransparency), light: transparent(mergeCurrentHeaderBackground, contentTransparency), hc: transparent(mergeCurrentHeaderBackground, contentTransparency) }, nls.localize('mergeCurrentContentBackground', 'Current content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const mergeIncomingHeaderBackground = registerColor('merge.incomingHeaderBackground', { dark: incomingBaseColor, light: incomingBaseColor, hc: null }, nls.localize('mergeIncomingHeaderBackground', 'Incoming header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const mergeIncomingContentBackground = registerColor('merge.incomingContentBackground', { dark: transparent(mergeIncomingHeaderBackground, contentTransparency), light: transparent(mergeIncomingHeaderBackground, contentTransparency), hc: transparent(mergeIncomingHeaderBackground, contentTransparency) }, nls.localize('mergeIncomingContentBackground', 'Incoming content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const mergeCommonHeaderBackground = registerColor('merge.commonHeaderBackground', { dark: commonBaseColor, light: commonBaseColor, hc: null }, nls.localize('mergeCommonHeaderBackground', 'Common ancestor header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const mergeCommonContentBackground = registerColor('merge.commonContentBackground', { dark: transparent(mergeCommonHeaderBackground, contentTransparency), light: transparent(mergeCommonHeaderBackground, contentTransparency), hc: transparent(mergeCommonHeaderBackground, contentTransparency) }, nls.localize('mergeCommonContentBackground', 'Common ancestor content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.'), true);\n\nexport const mergeBorder = registerColor('merge.border', { dark: null, light: null, hc: '#C3DF6F' }, nls.localize('mergeBorder', 'Border color on headers and the splitter in inline merge-conflicts.'));\n\nexport const overviewRulerCurrentContentForeground = registerColor('editorOverviewRuler.currentContentForeground', { dark: transparent(mergeCurrentHeaderBackground, rulerTransparency), light: transparent(mergeCurrentHeaderBackground, rulerTransparency), hc: mergeBorder }, nls.localize('overviewRulerCurrentContentForeground', 'Current overview ruler foreground for inline merge-conflicts.'));\nexport const overviewRulerIncomingContentForeground = registerColor('editorOverviewRuler.incomingContentForeground', { dark: transparent(mergeIncomingHeaderBackground, rulerTransparency), light: transparent(mergeIncomingHeaderBackground, rulerTransparency), hc: mergeBorder }, nls.localize('overviewRulerIncomingContentForeground', 'Incoming overview ruler foreground for inline merge-conflicts.'));\nexport const overviewRulerCommonContentForeground = registerColor('editorOverviewRuler.commonContentForeground', { dark: transparent(mergeCommonHeaderBackground, rulerTransparency), light: transparent(mergeCommonHeaderBackground, rulerTransparency), hc: mergeBorder }, nls.localize('overviewRulerCommonContentForeground', 'Common ancestor overview ruler foreground for inline merge-conflicts.'));\n\nexport const overviewRulerFindMatchForeground = registerColor('editorOverviewRuler.findMatchForeground', { dark: '#d186167e', light: '#d186167e', hc: '#AB5A00' }, nls.localize('overviewRulerFindMatchForeground', 'Overview ruler marker color for find matches. The color must not be opaque so as not to hide underlying decorations.'), true);\n\nexport const overviewRulerSelectionHighlightForeground = registerColor('editorOverviewRuler.selectionHighlightForeground', { dark: '#A0A0A0CC', light: '#A0A0A0CC', hc: '#A0A0A0CC' }, nls.localize('overviewRulerSelectionHighlightForeground', 'Overview ruler marker color for selection highlights. The color must not be opaque so as not to hide underlying decorations.'), true);\n\n\nexport const minimapFindMatch = registerColor('minimap.findMatchHighlight', { light: '#d18616', dark: '#d18616', hc: '#AB5A00' }, nls.localize('minimapFindMatchHighlight', 'Minimap marker color for find matches.'), true);\nexport const minimapSelectionOccurrenceHighlight = registerColor('minimap.selectionOccurrenceHighlight', { light: '#c9c9c9', dark: '#676767', hc: '#ffffff' }, nls.localize('minimapSelectionOccurrenceHighlight', 'Minimap marker color for repeating editor selections.'), true);\nexport const minimapSelection = registerColor('minimap.selectionHighlight', { light: '#ADD6FF', dark: '#264F78', hc: '#ffffff' }, nls.localize('minimapSelectionHighlight', 'Minimap marker color for the editor selection.'), true);\nexport const minimapError = registerColor('minimap.errorHighlight', { dark: new Color(new RGBA(255, 18, 18, 0.7)), light: new Color(new RGBA(255, 18, 18, 0.7)), hc: new Color(new RGBA(255, 50, 50, 1)) }, nls.localize('minimapError', 'Minimap marker color for errors.'));\nexport const minimapWarning = registerColor('minimap.warningHighlight', { dark: editorWarningForeground, light: editorWarningForeground, hc: editorWarningBorder }, nls.localize('overviewRuleWarning', 'Minimap marker color for warnings.'));\nexport const minimapBackground = registerColor('minimap.background', { dark: null, light: null, hc: null }, nls.localize('minimapBackground', \"Minimap background color.\"));\nexport const minimapForegroundOpacity = registerColor('minimap.foregroundOpacity', { dark: Color.fromHex('#000f'), light: Color.fromHex('#000f'), hc: Color.fromHex('#000f') }, nls.localize('minimapForegroundOpacity', 'Opacity of foreground elements rendered in the minimap. For example, \"#000000c0\" will render the elements with 75% opacity.'));\n\nexport const minimapSliderBackground = registerColor('minimapSlider.background', { light: transparent(scrollbarSliderBackground, 0.5), dark: transparent(scrollbarSliderBackground, 0.5), hc: transparent(scrollbarSliderBackground, 0.5) }, nls.localize('minimapSliderBackground', \"Minimap slider background color.\"));\nexport const minimapSliderHoverBackground = registerColor('minimapSlider.hoverBackground', { light: transparent(scrollbarSliderHoverBackground, 0.5), dark: transparent(scrollbarSliderHoverBackground, 0.5), hc: transparent(scrollbarSliderHoverBackground, 0.5) }, nls.localize('minimapSliderHoverBackground', \"Minimap slider background color when hovering.\"));\nexport const minimapSliderActiveBackground = registerColor('minimapSlider.activeBackground', { light: transparent(scrollbarSliderActiveBackground, 0.5), dark: transparent(scrollbarSliderActiveBackground, 0.5), hc: transparent(scrollbarSliderActiveBackground, 0.5) }, nls.localize('minimapSliderActiveBackground', \"Minimap slider background color when clicked on.\"));\n\nexport const problemsErrorIconForeground = registerColor('problemsErrorIcon.foreground', { dark: editorErrorForeground, light: editorErrorForeground, hc: editorErrorForeground }, nls.localize('problemsErrorIconForeground', \"The color used for the problems error icon.\"));\nexport const problemsWarningIconForeground = registerColor('problemsWarningIcon.foreground', { dark: editorWarningForeground, light: editorWarningForeground, hc: editorWarningForeground }, nls.localize('problemsWarningIconForeground', \"The color used for the problems warning icon.\"));\nexport const problemsInfoIconForeground = registerColor('problemsInfoIcon.foreground', { dark: editorInfoForeground, light: editorInfoForeground, hc: editorInfoForeground }, nls.localize('problemsInfoIconForeground', \"The color used for the problems info icon.\"));\n\n/**\n * Chart colors\n */\nexport const chartsForeground = registerColor('charts.foreground', { dark: foreground, light: foreground, hc: foreground }, nls.localize('chartsForeground', \"The foreground color used in charts.\"));\nexport const chartsLines = registerColor('charts.lines', { dark: transparent(foreground, .5), light: transparent(foreground, .5), hc: transparent(foreground, .5) }, nls.localize('chartsLines', \"The color used for horizontal lines in charts.\"));\nexport const chartsRed = registerColor('charts.red', { dark: editorErrorForeground, light: editorErrorForeground, hc: editorErrorForeground }, nls.localize('chartsRed', \"The red color used in chart visualizations.\"));\nexport const chartsBlue = registerColor('charts.blue', { dark: editorInfoForeground, light: editorInfoForeground, hc: editorInfoForeground }, nls.localize('chartsBlue', \"The blue color used in chart visualizations.\"));\nexport const chartsYellow = registerColor('charts.yellow', { dark: editorWarningForeground, light: editorWarningForeground, hc: editorWarningForeground }, nls.localize('chartsYellow', \"The yellow color used in chart visualizations.\"));\nexport const chartsOrange = registerColor('charts.orange', { dark: minimapFindMatch, light: minimapFindMatch, hc: minimapFindMatch }, nls.localize('chartsOrange', \"The orange color used in chart visualizations.\"));\nexport const chartsGreen = registerColor('charts.green', { dark: '#89D185', light: '#388A34', hc: '#89D185' }, nls.localize('chartsGreen', \"The green color used in chart visualizations.\"));\nexport const chartsPurple = registerColor('charts.purple', { dark: '#B180D7', light: '#652D90', hc: '#B180D7' }, nls.localize('chartsPurple', \"The purple color used in chart visualizations.\"));\n\n// ----- color functions\n\nexport function executeTransform(transform: ColorTransform, theme: IColorTheme) {\n\tswitch (transform.op) {\n\t\tcase ColorTransformType.Darken:\n\t\t\treturn resolveColorValue(transform.value, theme)?.darken(transform.factor);\n\n\t\tcase ColorTransformType.Lighten:\n\t\t\treturn resolveColorValue(transform.value, theme)?.lighten(transform.factor);\n\n\t\tcase ColorTransformType.Transparent:\n\t\t\treturn resolveColorValue(transform.value, theme)?.transparent(transform.factor);\n\n\t\tcase ColorTransformType.OneOf:\n\t\t\tfor (const candidate of transform.values) {\n\t\t\t\tconst color = resolveColorValue(candidate, theme);\n\t\t\t\tif (color) {\n\t\t\t\t\treturn color;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\n\t\tcase ColorTransformType.IfDefinedThenElse:\n\t\t\treturn resolveColorValue(theme.defines(transform.if) ? transform.then : transform.else, theme);\n\n\t\tcase ColorTransformType.LessProminent: {\n\t\t\tconst from = resolveColorValue(transform.value, theme);\n\t\t\tif (!from) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst backgroundColor = resolveColorValue(transform.background, theme);\n\t\t\tif (!backgroundColor) {\n\t\t\t\treturn from.transparent(transform.factor * transform.transparency);\n\t\t\t}\n\n\t\t\treturn from.isDarkerThan(backgroundColor)\n\t\t\t\t? Color.getLighterColor(from, backgroundColor, transform.factor).transparent(transform.transparency)\n\t\t\t\t: Color.getDarkerColor(from, backgroundColor, transform.factor).transparent(transform.transparency);\n\t\t}\n\t\tdefault:\n\t\t\tthrow assertNever(transform);\n\t}\n}\n\nexport function darken(colorValue: ColorValue, factor: number): ColorTransform {\n\treturn { op: ColorTransformType.Darken, value: colorValue, factor };\n}\n\nexport function lighten(colorValue: ColorValue, factor: number): ColorTransform {\n\treturn { op: ColorTransformType.Lighten, value: colorValue, factor };\n}\n\nexport function transparent(colorValue: ColorValue, factor: number): ColorTransform {\n\treturn { op: ColorTransformType.Transparent, value: colorValue, factor };\n}\n\nexport function oneOf(...colorValues: ColorValue[]): ColorTransform {\n\treturn { op: ColorTransformType.OneOf, values: colorValues };\n}\n\nexport function ifDefinedThenElse(ifArg: ColorIdentifier, thenArg: ColorValue, elseArg: ColorValue): ColorTransform {\n\treturn { op: ColorTransformType.IfDefinedThenElse, if: ifArg, then: thenArg, else: elseArg };\n}\n\nfunction lessProminent(colorValue: ColorValue, backgroundColorValue: ColorValue, factor: number, transparency: number): ColorTransform {\n\treturn { op: ColorTransformType.LessProminent, value: colorValue, background: backgroundColorValue, factor, transparency };\n}\n\n// ----- implementation\n\n/**\n * @param colorValue Resolve a color value in the context of a theme\n */\nexport function resolveColorValue(colorValue: ColorValue | null, theme: IColorTheme): Color | undefined {\n\tif (colorValue === null) {\n\t\treturn undefined;\n\t} else if (typeof colorValue === 'string') {\n\t\tif (colorValue[0] === '#') {\n\t\t\treturn Color.fromHex(colorValue);\n\t\t}\n\t\treturn theme.getColor(colorValue);\n\t} else if (colorValue instanceof Color) {\n\t\treturn colorValue;\n\t} else if (typeof colorValue === 'object') {\n\t\treturn executeTransform(colorValue, theme);\n\t}\n\treturn undefined;\n}\n\nexport const workbenchColorsSchemaId = 'vscode://schemas/workbench-colors';\n\nlet schemaRegistry = platform.Registry.as(JSONExtensions.JSONContribution);\nschemaRegistry.registerSchema(workbenchColorsSchemaId, colorRegistry.getColorSchema());\n\nconst delayer = new RunOnceScheduler(() => schemaRegistry.notifySchemaChanged(workbenchColorsSchemaId), 200);\ncolorRegistry.onDidChangeSchema(() => {\n\tif (!delayer.isScheduled()) {\n\t\tdelayer.schedule();\n\t}\n});\n\n// setTimeout(_ => console.log(colorRegistry.toString()), 5000);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { GlobalMouseMoveMonitor } from 'vs/base/browser/globalMouseMoveMonitor';\nimport { StandardMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { RunOnceScheduler } from 'vs/base/common/async';\nimport { Disposable, IDisposable } from 'vs/base/common/lifecycle';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { asCssVariableName } from 'vs/platform/theme/common/colorRegistry';\nimport { ThemeColor } from 'vs/platform/theme/common/themeService';\n\n/**\n * Coordinates relative to the whole document (e.g. mouse event's pageX and pageY)\n */\nexport class PageCoordinates {\n\t_pageCoordinatesBrand: void = undefined;\n\n\tconstructor(\n\t\tpublic readonly x: number,\n\t\tpublic readonly y: number\n\t) { }\n\n\tpublic toClientCoordinates(): ClientCoordinates {\n\t\treturn new ClientCoordinates(this.x - dom.StandardWindow.scrollX, this.y - dom.StandardWindow.scrollY);\n\t}\n}\n\n/**\n * Coordinates within the application's client area (i.e. origin is document's scroll position).\n *\n * For example, clicking in the top-left corner of the client area will\n * always result in a mouse event with a client.x value of 0, regardless\n * of whether the page is scrolled horizontally.\n */\nexport class ClientCoordinates {\n\t_clientCoordinatesBrand: void = undefined;\n\n\tconstructor(\n\t\tpublic readonly clientX: number,\n\t\tpublic readonly clientY: number\n\t) { }\n\n\tpublic toPageCoordinates(): PageCoordinates {\n\t\treturn new PageCoordinates(this.clientX + dom.StandardWindow.scrollX, this.clientY + dom.StandardWindow.scrollY);\n\t}\n}\n\n/**\n * The position of the editor in the page.\n */\nexport class EditorPagePosition {\n\t_editorPagePositionBrand: void = undefined;\n\n\tconstructor(\n\t\tpublic readonly x: number,\n\t\tpublic readonly y: number,\n\t\tpublic readonly width: number,\n\t\tpublic readonly height: number\n\t) { }\n}\n\n/**\n * Coordinates relative to the the (top;left) of the editor that can be used safely with other internal editor metrics.\n * **NOTE**: This position is obtained by taking page coordinates and transforming them relative to the\n * editor's (top;left) position in a way in which scale transformations are taken into account.\n * **NOTE**: These coordinates could be negative if the mouse position is outside the editor.\n */\nexport class CoordinatesRelativeToEditor {\n\t_positionRelativeToEditorBrand: void = undefined;\n\n\tconstructor(\n\t\tpublic readonly x: number,\n\t\tpublic readonly y: number\n\t) { }\n}\n\nexport function createEditorPagePosition(editorViewDomNode: HTMLElement): EditorPagePosition {\n\tconst editorPos = dom.getDomNodePagePosition(editorViewDomNode);\n\treturn new EditorPagePosition(editorPos.left, editorPos.top, editorPos.width, editorPos.height);\n}\n\nexport function createCoordinatesRelativeToEditor(editorViewDomNode: HTMLElement, editorPagePosition: EditorPagePosition, pos: PageCoordinates) {\n\t// The editor's page position is read from the DOM using getBoundingClientRect().\n\t//\n\t// getBoundingClientRect() returns the actual dimensions, while offsetWidth and offsetHeight\n\t// reflect the unscaled size. We can use this difference to detect a transform:scale()\n\t// and we will apply the transformation in inverse to get mouse coordinates that make sense inside the editor.\n\t//\n\t// This could be expanded to cover rotation as well maybe by walking the DOM up from `editorViewDomNode`\n\t// and computing the effective transformation matrix using getComputedStyle(element).transform.\n\t//\n\tconst scaleX = editorPagePosition.width / editorViewDomNode.offsetWidth;\n\tconst scaleY = editorPagePosition.height / editorViewDomNode.offsetHeight;\n\n\t// Adjust mouse offsets if editor appears to be scaled via transforms\n\tconst relativeX = (pos.x - editorPagePosition.x) / scaleX;\n\tconst relativeY = (pos.y - editorPagePosition.y) / scaleY;\n\treturn new CoordinatesRelativeToEditor(relativeX, relativeY);\n}\n\nexport class EditorMouseEvent extends StandardMouseEvent {\n\t_editorMouseEventBrand: void = undefined;\n\n\t/**\n\t * Coordinates relative to the whole document.\n\t */\n\tpublic readonly pos: PageCoordinates;\n\n\t/**\n\t * Editor's coordinates relative to the whole document.\n\t */\n\tpublic readonly editorPos: EditorPagePosition;\n\n\t/**\n\t * Coordinates relative to the (top;left) of the editor.\n\t * *NOTE*: These coordinates are preferred because they take into account transformations applied to the editor.\n\t * *NOTE*: These coordinates could be negative if the mouse position is outside the editor.\n\t */\n\tpublic readonly relativePos: CoordinatesRelativeToEditor;\n\n\tconstructor(e: MouseEvent, editorViewDomNode: HTMLElement) {\n\t\tsuper(e);\n\t\tthis.pos = new PageCoordinates(this.posx, this.posy);\n\t\tthis.editorPos = createEditorPagePosition(editorViewDomNode);\n\t\tthis.relativePos = createCoordinatesRelativeToEditor(editorViewDomNode, this.editorPos, this.pos);\n\t}\n}\n\nexport interface EditorMouseEventMerger {\n\t(lastEvent: EditorMouseEvent | null, currentEvent: EditorMouseEvent): EditorMouseEvent;\n}\n\nexport class EditorMouseEventFactory {\n\n\tprivate readonly _editorViewDomNode: HTMLElement;\n\n\tconstructor(editorViewDomNode: HTMLElement) {\n\t\tthis._editorViewDomNode = editorViewDomNode;\n\t}\n\n\tprivate _create(e: MouseEvent): EditorMouseEvent {\n\t\treturn new EditorMouseEvent(e, this._editorViewDomNode);\n\t}\n\n\tpublic onContextMenu(target: HTMLElement, callback: (e: EditorMouseEvent) => void): IDisposable {\n\t\treturn dom.addDisposableListener(target, 'contextmenu', (e: MouseEvent) => {\n\t\t\tcallback(this._create(e));\n\t\t});\n\t}\n\n\tpublic onMouseUp(target: HTMLElement, callback: (e: EditorMouseEvent) => void): IDisposable {\n\t\treturn dom.addDisposableListener(target, 'mouseup', (e: MouseEvent) => {\n\t\t\tcallback(this._create(e));\n\t\t});\n\t}\n\n\tpublic onMouseDown(target: HTMLElement, callback: (e: EditorMouseEvent) => void): IDisposable {\n\t\treturn dom.addDisposableListener(target, 'mousedown', (e: MouseEvent) => {\n\t\t\tcallback(this._create(e));\n\t\t});\n\t}\n\n\tpublic onMouseLeave(target: HTMLElement, callback: (e: EditorMouseEvent) => void): IDisposable {\n\t\treturn dom.addDisposableNonBubblingMouseOutListener(target, (e: MouseEvent) => {\n\t\t\tcallback(this._create(e));\n\t\t});\n\t}\n\n\tpublic onMouseMoveThrottled(target: HTMLElement, callback: (e: EditorMouseEvent) => void, merger: EditorMouseEventMerger, minimumTimeMs: number): IDisposable {\n\t\tconst myMerger: dom.IEventMerger = (lastEvent: EditorMouseEvent | null, currentEvent: MouseEvent): EditorMouseEvent => {\n\t\t\treturn merger(lastEvent, this._create(currentEvent));\n\t\t};\n\t\treturn dom.addDisposableThrottledListener(target, 'mousemove', callback, myMerger, minimumTimeMs);\n\t}\n}\n\nexport class EditorPointerEventFactory {\n\n\tprivate readonly _editorViewDomNode: HTMLElement;\n\n\tconstructor(editorViewDomNode: HTMLElement) {\n\t\tthis._editorViewDomNode = editorViewDomNode;\n\t}\n\n\tprivate _create(e: MouseEvent): EditorMouseEvent {\n\t\treturn new EditorMouseEvent(e, this._editorViewDomNode);\n\t}\n\n\tpublic onPointerUp(target: HTMLElement, callback: (e: EditorMouseEvent) => void): IDisposable {\n\t\treturn dom.addDisposableListener(target, 'pointerup', (e: MouseEvent) => {\n\t\t\tcallback(this._create(e));\n\t\t});\n\t}\n\n\tpublic onPointerDown(target: HTMLElement, callback: (e: EditorMouseEvent) => void): IDisposable {\n\t\treturn dom.addDisposableListener(target, 'pointerdown', (e: MouseEvent) => {\n\t\t\tcallback(this._create(e));\n\t\t});\n\t}\n\n\tpublic onPointerLeave(target: HTMLElement, callback: (e: EditorMouseEvent) => void): IDisposable {\n\t\treturn dom.addDisposableNonBubblingPointerOutListener(target, (e: MouseEvent) => {\n\t\t\tcallback(this._create(e));\n\t\t});\n\t}\n\n\tpublic onPointerMoveThrottled(target: HTMLElement, callback: (e: EditorMouseEvent) => void, merger: EditorMouseEventMerger, minimumTimeMs: number): IDisposable {\n\t\tconst myMerger: dom.IEventMerger = (lastEvent: EditorMouseEvent | null, currentEvent: MouseEvent): EditorMouseEvent => {\n\t\t\treturn merger(lastEvent, this._create(currentEvent));\n\t\t};\n\t\treturn dom.addDisposableThrottledListener(target, 'pointermove', callback, myMerger, minimumTimeMs);\n\t}\n}\n\nexport class GlobalEditorMouseMoveMonitor extends Disposable {\n\n\tprivate readonly _editorViewDomNode: HTMLElement;\n\tprivate readonly _globalMouseMoveMonitor: GlobalMouseMoveMonitor;\n\tprivate _keydownListener: IDisposable | null;\n\n\tconstructor(editorViewDomNode: HTMLElement) {\n\t\tsuper();\n\t\tthis._editorViewDomNode = editorViewDomNode;\n\t\tthis._globalMouseMoveMonitor = this._register(new GlobalMouseMoveMonitor());\n\t\tthis._keydownListener = null;\n\t}\n\n\tpublic startMonitoring(\n\t\tinitialElement: HTMLElement,\n\t\tinitialButtons: number,\n\t\tmerger: EditorMouseEventMerger,\n\t\tmouseMoveCallback: (e: EditorMouseEvent) => void,\n\t\tonStopCallback: (browserEvent?: MouseEvent | KeyboardEvent) => void\n\t): void {\n\n\t\t// Add a <> keydown event listener that will cancel the monitoring\n\t\t// if something other than a modifier key is pressed\n\t\tthis._keydownListener = dom.addStandardDisposableListener(document, 'keydown', (e) => {\n\t\t\tconst kb = e.toKeybinding();\n\t\t\tif (kb.isModifierKey()) {\n\t\t\t\t// Allow modifier keys\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._globalMouseMoveMonitor.stopMonitoring(true, e.browserEvent);\n\t\t}, true);\n\n\t\tconst myMerger: dom.IEventMerger = (lastEvent: EditorMouseEvent | null, currentEvent: MouseEvent): EditorMouseEvent => {\n\t\t\treturn merger(lastEvent, new EditorMouseEvent(currentEvent, this._editorViewDomNode));\n\t\t};\n\n\t\tthis._globalMouseMoveMonitor.startMonitoring(initialElement, initialButtons, myMerger, mouseMoveCallback, (e) => {\n\t\t\tthis._keydownListener!.dispose();\n\t\t\tonStopCallback(e);\n\t\t});\n\t}\n\n\tpublic stopMonitoring(): void {\n\t\tthis._globalMouseMoveMonitor.stopMonitoring(true);\n\t}\n}\n\n\n/**\n * A helper to create dynamic css rules, bound to a class name.\n * Rules are reused.\n * Reference counting and delayed garbage collection ensure that no rules leak.\n*/\nexport class DynamicCssRules {\n\tprivate static _idPool = 0;\n\tprivate readonly _instanceId = ++DynamicCssRules._idPool;\n\tprivate _counter = 0;\n\tprivate readonly _rules = new Map();\n\n\t// We delay garbage collection so that hanging rules can be reused.\n\tprivate readonly _garbageCollectionScheduler = new RunOnceScheduler(() => this.garbageCollect(), 1000);\n\n\tconstructor(private readonly _editor: ICodeEditor) {\n\t}\n\n\tpublic createClassNameRef(options: CssProperties): ClassNameReference {\n\t\tconst rule = this.getOrCreateRule(options);\n\t\trule.increaseRefCount();\n\n\t\treturn {\n\t\t\tclassName: rule.className,\n\t\t\tdispose: () => {\n\t\t\t\trule.decreaseRefCount();\n\t\t\t\tthis._garbageCollectionScheduler.schedule();\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate getOrCreateRule(properties: CssProperties): RefCountedCssRule {\n\t\tconst key = this.computeUniqueKey(properties);\n\t\tlet existingRule = this._rules.get(key);\n\t\tif (!existingRule) {\n\t\t\tconst counter = this._counter++;\n\t\t\texistingRule = new RefCountedCssRule(key, `dyn-rule-${this._instanceId}-${counter}`,\n\t\t\t\tdom.isInShadowDOM(this._editor.getContainerDomNode())\n\t\t\t\t\t? this._editor.getContainerDomNode()\n\t\t\t\t\t: undefined,\n\t\t\t\tproperties\n\t\t\t);\n\t\t\tthis._rules.set(key, existingRule);\n\t\t}\n\t\treturn existingRule;\n\t}\n\n\tprivate computeUniqueKey(properties: CssProperties): string {\n\t\treturn JSON.stringify(properties);\n\t}\n\n\tprivate garbageCollect() {\n\t\tfor (const rule of this._rules.values()) {\n\t\t\tif (!rule.hasReferences()) {\n\t\t\t\tthis._rules.delete(rule.key);\n\t\t\t\trule.dispose();\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport interface ClassNameReference extends IDisposable {\n\tclassName: string;\n}\n\nexport interface CssProperties {\n\tborderRadius?: string;\n\tfontSize?: string;\n\tfontFamily?: string;\n\ttextDecoration?: string;\n\tcolor?: string | ThemeColor;\n\tbackgroundColor?: string | ThemeColor;\n\tverticalAlign?: string;\n\tcursor?: string;\n\tpadding?: string;\n\twidth?: string;\n\tdisplay?: string;\n}\n\nclass RefCountedCssRule {\n\tprivate _referenceCount: number = 0;\n\tprivate _styleElement: HTMLStyleElement;\n\n\tconstructor(\n\t\tpublic readonly key: string,\n\t\tpublic readonly className: string,\n\t\t_containerElement: HTMLElement | undefined,\n\t\tpublic readonly properties: CssProperties,\n\t) {\n\t\tthis._styleElement = dom.createStyleSheet(\n\t\t\t_containerElement\n\t\t);\n\n\t\tthis._styleElement.textContent = this.getCssText(this.className, this.properties);\n\t}\n\n\tprivate getCssText(className: string, properties: CssProperties): string {\n\t\tlet str = `.${className} {`;\n\t\tfor (const prop in properties) {\n\t\t\tconst value = (properties as any)[prop] as string | ThemeColor;\n\t\t\tlet cssValue;\n\t\t\tif (typeof value === 'object') {\n\t\t\t\tcssValue = `var(${asCssVariableName(value.id)})`;\n\t\t\t} else {\n\t\t\t\tcssValue = value;\n\t\t\t}\n\n\t\t\tconst cssPropName = camelToDashes(prop);\n\t\t\tstr += `\\n\\t${cssPropName}: ${cssValue};`;\n\t\t}\n\t\tstr += `\\n}`;\n\t\treturn str;\n\t}\n\n\tpublic dispose(): void {\n\t\tthis._styleElement.remove();\n\t}\n\n\tpublic increaseRefCount(): void {\n\t\tthis._referenceCount++;\n\t}\n\n\tpublic decreaseRefCount(): void {\n\t\tthis._referenceCount--;\n\t}\n\n\tpublic hasReferences(): boolean {\n\t\treturn this._referenceCount > 0;\n\t}\n}\n\nfunction camelToDashes(str: string): string {\n\treturn str.replace(/(^[A-Z])/, ([first]) => first.toLowerCase())\n\t\t.replace(/([A-Z])/g, ([letter]) => `-${letter.toLowerCase()}`);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Color } from 'vs/base/common/color';\nimport { IDisposable } from 'vs/base/common/lifecycle';\nimport { IThemable, styleFn } from 'vs/base/common/styler';\nimport { activeContrastBorder, badgeBackground, badgeForeground, ColorIdentifier, ColorValue, contrastBorder, listActiveSelectionBackground, listActiveSelectionForeground, listActiveSelectionIconForeground, listDropBackground, listFilterWidgetBackground, listFilterWidgetNoMatchesOutline, listFilterWidgetOutline, listFocusBackground, listFocusForeground, listFocusOutline, listHoverBackground, listHoverForeground, listInactiveFocusBackground, listInactiveFocusOutline, listInactiveSelectionBackground, listInactiveSelectionForeground, listInactiveSelectionIconForeground, menuBackground, menuBorder, menuForeground, menuSelectionBackground, menuSelectionBorder, menuSelectionForeground, menuSeparatorBackground, resolveColorValue, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, tableColumnsBorder, tableOddRowsBackgroundColor, treeIndentGuidesStroke, widgetShadow } from 'vs/platform/theme/common/colorRegistry';\nimport { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';\n\nexport interface IStyleOverrides {\n\t[color: string]: ColorIdentifier | undefined;\n}\n\nexport interface IColorMapping {\n\t[optionsKey: string]: ColorValue | undefined;\n}\n\nexport interface IComputedStyles {\n\t[color: string]: Color | undefined;\n}\n\nexport function computeStyles(theme: IColorTheme, styleMap: IColorMapping): IComputedStyles {\n\tconst styles = Object.create(null) as IComputedStyles;\n\tfor (let key in styleMap) {\n\t\tconst value = styleMap[key];\n\t\tif (value) {\n\t\t\tstyles[key] = resolveColorValue(value, theme);\n\t\t}\n\t}\n\n\treturn styles;\n}\n\nexport function attachStyler(themeService: IThemeService, styleMap: T, widgetOrCallback: IThemable | styleFn): IDisposable {\n\tfunction applyStyles(): void {\n\t\tconst styles = computeStyles(themeService.getColorTheme(), styleMap);\n\n\t\tif (typeof widgetOrCallback === 'function') {\n\t\t\twidgetOrCallback(styles);\n\t\t} else {\n\t\t\twidgetOrCallback.style(styles);\n\t\t}\n\t}\n\n\tapplyStyles();\n\n\treturn themeService.onDidColorThemeChange(applyStyles);\n}\n\nexport interface IBadgeStyleOverrides extends IStyleOverrides {\n\tbadgeBackground?: ColorIdentifier;\n\tbadgeForeground?: ColorIdentifier;\n}\n\nexport function attachBadgeStyler(widget: IThemable, themeService: IThemeService, style?: IBadgeStyleOverrides): IDisposable {\n\treturn attachStyler(themeService, {\n\t\tbadgeBackground: style?.badgeBackground || badgeBackground,\n\t\tbadgeForeground: style?.badgeForeground || badgeForeground,\n\t\tbadgeBorder: contrastBorder\n\t} as IBadgeStyleOverrides, widget);\n}\n\nexport function attachListStyler(widget: IThemable, themeService: IThemeService, overrides?: IColorMapping): IDisposable {\n\treturn attachStyler(themeService, { ...defaultListStyles, ...(overrides || {}) }, widget);\n}\n\nexport const defaultListStyles: IColorMapping = {\n\tlistFocusBackground,\n\tlistFocusForeground,\n\tlistFocusOutline,\n\tlistActiveSelectionBackground,\n\tlistActiveSelectionForeground,\n\tlistActiveSelectionIconForeground,\n\tlistFocusAndSelectionBackground: listActiveSelectionBackground,\n\tlistFocusAndSelectionForeground: listActiveSelectionForeground,\n\tlistInactiveSelectionBackground,\n\tlistInactiveSelectionIconForeground,\n\tlistInactiveSelectionForeground,\n\tlistInactiveFocusBackground,\n\tlistInactiveFocusOutline,\n\tlistHoverBackground,\n\tlistHoverForeground,\n\tlistDropBackground,\n\tlistSelectionOutline: activeContrastBorder,\n\tlistHoverOutline: activeContrastBorder,\n\tlistFilterWidgetBackground,\n\tlistFilterWidgetOutline,\n\tlistFilterWidgetNoMatchesOutline,\n\tlistMatchesShadow: widgetShadow,\n\ttreeIndentGuidesStroke,\n\ttableColumnsBorder,\n\ttableOddRowsBackgroundColor\n};\n\nexport interface IMenuStyleOverrides extends IColorMapping {\n\tshadowColor?: ColorIdentifier;\n\tborderColor?: ColorIdentifier;\n\tforegroundColor?: ColorIdentifier;\n\tbackgroundColor?: ColorIdentifier;\n\tselectionForegroundColor?: ColorIdentifier;\n\tselectionBackgroundColor?: ColorIdentifier;\n\tselectionBorderColor?: ColorIdentifier;\n\tseparatorColor?: ColorIdentifier;\n}\n\nexport const defaultMenuStyles = {\n\tshadowColor: widgetShadow,\n\tborderColor: menuBorder,\n\tforegroundColor: menuForeground,\n\tbackgroundColor: menuBackground,\n\tselectionForegroundColor: menuSelectionForeground,\n\tselectionBackgroundColor: menuSelectionBackground,\n\tselectionBorderColor: menuSelectionBorder,\n\tseparatorColor: menuSeparatorBackground,\n\tscrollbarShadow: scrollbarShadow,\n\tscrollbarSliderBackground: scrollbarSliderBackground,\n\tscrollbarSliderHoverBackground: scrollbarSliderHoverBackground,\n\tscrollbarSliderActiveBackground: scrollbarSliderActiveBackground\n};\n\nexport function attachMenuStyler(widget: IThemable, themeService: IThemeService, style?: IMenuStyleOverrides): IDisposable {\n\treturn attachStyler(themeService, { ...defaultMenuStyles, ...style }, widget);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IContextMenuDelegate } from 'vs/base/browser/contextmenu';\nimport { $, addDisposableListener, EventType, isHTMLElement } from 'vs/base/browser/dom';\nimport { StandardMouseEvent } from 'vs/base/browser/mouseEvent';\nimport { Menu } from 'vs/base/browser/ui/menu/menu';\nimport { ActionRunner, IRunEvent, WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions';\nimport { isCancellationError } from 'vs/base/common/errors';\nimport { combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle';\nimport 'vs/css!./contextMenuHandler';\nimport { IContextViewService } from 'vs/platform/contextview/browser/contextView';\nimport { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';\nimport { INotificationService } from 'vs/platform/notification/common/notification';\nimport { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';\nimport { attachMenuStyler } from 'vs/platform/theme/common/styler';\nimport { IThemeService } from 'vs/platform/theme/common/themeService';\n\n\nexport interface IContextMenuHandlerOptions {\n\tblockMouse: boolean;\n}\n\nexport class ContextMenuHandler {\n\tprivate focusToReturn: HTMLElement | null = null;\n\tprivate block: HTMLElement | null = null;\n\tprivate options: IContextMenuHandlerOptions = { blockMouse: true };\n\n\tconstructor(\n\t\tprivate contextViewService: IContextViewService,\n\t\tprivate telemetryService: ITelemetryService,\n\t\tprivate notificationService: INotificationService,\n\t\tprivate keybindingService: IKeybindingService,\n\t\tprivate themeService: IThemeService\n\t) { }\n\n\tconfigure(options: IContextMenuHandlerOptions): void {\n\t\tthis.options = options;\n\t}\n\n\tshowContextMenu(delegate: IContextMenuDelegate): void {\n\t\tconst actions = delegate.getActions();\n\t\tif (!actions.length) {\n\t\t\treturn; // Don't render an empty context menu\n\t\t}\n\n\t\tthis.focusToReturn = document.activeElement as HTMLElement;\n\n\t\tlet menu: Menu | undefined;\n\n\t\tlet shadowRootElement = isHTMLElement(delegate.domForShadowRoot) ? delegate.domForShadowRoot : undefined;\n\t\tthis.contextViewService.showContextView({\n\t\t\tgetAnchor: () => delegate.getAnchor(),\n\t\t\tcanRelayout: false,\n\t\t\tanchorAlignment: delegate.anchorAlignment,\n\t\t\tanchorAxisAlignment: delegate.anchorAxisAlignment,\n\n\t\t\trender: (container) => {\n\t\t\t\tlet className = delegate.getMenuClassName ? delegate.getMenuClassName() : '';\n\n\t\t\t\tif (className) {\n\t\t\t\t\tcontainer.className += ' ' + className;\n\t\t\t\t}\n\n\t\t\t\t// Render invisible div to block mouse interaction in the rest of the UI\n\t\t\t\tif (this.options.blockMouse) {\n\t\t\t\t\tthis.block = container.appendChild($('.context-view-block'));\n\t\t\t\t\tthis.block.style.position = 'fixed';\n\t\t\t\t\tthis.block.style.cursor = 'initial';\n\t\t\t\t\tthis.block.style.left = '0';\n\t\t\t\t\tthis.block.style.top = '0';\n\t\t\t\t\tthis.block.style.width = '100%';\n\t\t\t\t\tthis.block.style.height = '100%';\n\t\t\t\t\tthis.block.style.zIndex = '-1';\n\n\t\t\t\t\t// TODO@Steven: this is never getting disposed\n\t\t\t\t\taddDisposableListener(this.block, EventType.MOUSE_DOWN, e => e.stopPropagation());\n\t\t\t\t}\n\n\t\t\t\tconst menuDisposables = new DisposableStore();\n\n\t\t\t\tconst actionRunner = delegate.actionRunner || new ActionRunner();\n\t\t\t\tactionRunner.onBeforeRun(this.onActionRun, this, menuDisposables);\n\t\t\t\tactionRunner.onDidRun(this.onDidActionRun, this, menuDisposables);\n\t\t\t\tmenu = new Menu(container, actions, {\n\t\t\t\t\tactionViewItemProvider: delegate.getActionViewItem,\n\t\t\t\t\tcontext: delegate.getActionsContext ? delegate.getActionsContext() : null,\n\t\t\t\t\tactionRunner,\n\t\t\t\t\tgetKeyBinding: delegate.getKeyBinding ? delegate.getKeyBinding : action => this.keybindingService.lookupKeybinding(action.id)\n\t\t\t\t});\n\n\t\t\t\tmenuDisposables.add(attachMenuStyler(menu, this.themeService));\n\n\t\t\t\tmenu.onDidCancel(() => this.contextViewService.hideContextView(true), null, menuDisposables);\n\t\t\t\tmenu.onDidBlur(() => this.contextViewService.hideContextView(true), null, menuDisposables);\n\t\t\t\tmenuDisposables.add(addDisposableListener(window, EventType.BLUR, () => this.contextViewService.hideContextView(true)));\n\t\t\t\tmenuDisposables.add(addDisposableListener(window, EventType.MOUSE_DOWN, (e: MouseEvent) => {\n\t\t\t\t\tif (e.defaultPrevented) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet event = new StandardMouseEvent(e);\n\t\t\t\t\tlet element: HTMLElement | null = event.target;\n\n\t\t\t\t\t// Don't do anything as we are likely creating a context menu\n\t\t\t\t\tif (event.rightButton) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\twhile (element) {\n\t\t\t\t\t\tif (element === container) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\telement = element.parentElement;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.contextViewService.hideContextView(true);\n\t\t\t\t}));\n\n\t\t\t\treturn combinedDisposable(menuDisposables, menu);\n\t\t\t},\n\n\t\t\tfocus: () => {\n\t\t\t\tif (menu) {\n\t\t\t\t\tmenu.focus(!!delegate.autoSelectFirstItem);\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tonHide: (didCancel?: boolean) => {\n\t\t\t\tif (delegate.onHide) {\n\t\t\t\t\tdelegate.onHide(!!didCancel);\n\t\t\t\t}\n\n\t\t\t\tif (this.block) {\n\t\t\t\t\tthis.block.remove();\n\t\t\t\t\tthis.block = null;\n\t\t\t\t}\n\n\t\t\t\tif (this.focusToReturn) {\n\t\t\t\t\tthis.focusToReturn.focus();\n\t\t\t\t}\n\t\t\t}\n\t\t}, shadowRootElement, !!shadowRootElement);\n\t}\n\n\tprivate onActionRun(e: IRunEvent): void {\n\t\tthis.telemetryService.publicLog2('workbenchActionExecuted', { id: e.action.id, from: 'contextMenu' });\n\n\t\tthis.contextViewService.hideContextView(false);\n\n\t\t// Restore focus here\n\t\tif (this.focusToReturn) {\n\t\t\tthis.focusToReturn.focus();\n\t\t}\n\t}\n\n\tprivate onDidActionRun(e: IRunEvent): void {\n\t\tif (e.error && !isCancellationError(e.error)) {\n\t\t\tthis.notificationService.error(e.error);\n\t\t}\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n/**\n * Color scheme used by the OS and by color themes.\n */\nexport enum ColorScheme {\n\tDARK = 'dark',\n\tLIGHT = 'light',\n\tHIGH_CONTRAST = 'hc'\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as browser from 'vs/base/browser/browser';\nimport { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';\nimport * as platform from 'vs/base/common/platform';\nimport { IVisibleLine } from 'vs/editor/browser/view/viewLayer';\nimport { RangeUtil } from 'vs/editor/browser/viewParts/lines/rangeUtil';\nimport { IStringBuilder } from 'vs/editor/common/core/stringBuilder';\nimport { IEditorConfiguration } from 'vs/editor/common/config/editorConfiguration';\nimport { FloatHorizontalRange, VisibleRanges } from 'vs/editor/browser/view/renderingContext';\nimport { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';\nimport { CharacterMapping, ForeignElementType, RenderLineInput, renderViewLine, LineRange, DomPosition } from 'vs/editor/common/viewLayout/viewLineRenderer';\nimport { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';\nimport { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel';\nimport { ColorScheme } from 'vs/platform/theme/common/theme';\nimport { EditorOption, EditorFontLigatures } from 'vs/editor/common/config/editorOptions';\n\nconst canUseFastRenderedViewLine = (function () {\n\tif (platform.isNative) {\n\t\t// In VSCode we know very well when the zoom level changes\n\t\treturn true;\n\t}\n\n\tif (platform.isLinux || browser.isFirefox || browser.isSafari) {\n\t\t// On Linux, it appears that zooming affects char widths (in pixels), which is unexpected.\n\t\t// --\n\t\t// Even though we read character widths correctly, having read them at a specific zoom level\n\t\t// does not mean they are the same at the current zoom level.\n\t\t// --\n\t\t// This could be improved if we ever figure out how to get an event when browsers zoom,\n\t\t// but until then we have to stick with reading client rects.\n\t\t// --\n\t\t// The same has been observed with Firefox on Windows7\n\t\t// --\n\t\t// The same has been oversved with Safari\n\t\treturn false;\n\t}\n\n\treturn true;\n})();\n\nlet monospaceAssumptionsAreValid = true;\n\nexport class DomReadingContext {\n\n\tprivate readonly _domNode: HTMLElement;\n\tprivate _clientRectDeltaLeft: number;\n\tprivate _clientRectScale: number;\n\tprivate _clientRectRead: boolean;\n\n\tprivate readClientRect(): void {\n\t\tif (!this._clientRectRead) {\n\t\t\tthis._clientRectRead = true;\n\t\t\tconst rect = this._domNode.getBoundingClientRect();\n\t\t\tthis._clientRectDeltaLeft = rect.left;\n\t\t\tthis._clientRectScale = rect.width / this._domNode.offsetWidth;\n\t\t}\n\t}\n\n\tpublic get clientRectDeltaLeft(): number {\n\t\tif (!this._clientRectRead) {\n\t\t\tthis.readClientRect();\n\t\t}\n\t\treturn this._clientRectDeltaLeft;\n\t}\n\n\tpublic get clientRectScale(): number {\n\t\tif (!this._clientRectRead) {\n\t\t\tthis.readClientRect();\n\t\t}\n\t\treturn this._clientRectScale;\n\t}\n\n\tpublic readonly endNode: HTMLElement;\n\n\tconstructor(domNode: HTMLElement, endNode: HTMLElement) {\n\t\tthis._domNode = domNode;\n\t\tthis._clientRectDeltaLeft = 0;\n\t\tthis._clientRectScale = 1;\n\t\tthis._clientRectRead = false;\n\t\tthis.endNode = endNode;\n\t}\n\n}\n\nexport class ViewLineOptions {\n\tpublic readonly themeType: ColorScheme;\n\tpublic readonly renderWhitespace: 'none' | 'boundary' | 'selection' | 'trailing' | 'all';\n\tpublic readonly renderControlCharacters: boolean;\n\tpublic readonly spaceWidth: number;\n\tpublic readonly middotWidth: number;\n\tpublic readonly wsmiddotWidth: number;\n\tpublic readonly useMonospaceOptimizations: boolean;\n\tpublic readonly canUseHalfwidthRightwardsArrow: boolean;\n\tpublic readonly lineHeight: number;\n\tpublic readonly stopRenderingLineAfter: number;\n\tpublic readonly fontLigatures: string;\n\n\tconstructor(config: IEditorConfiguration, themeType: ColorScheme) {\n\t\tthis.themeType = themeType;\n\t\tconst options = config.options;\n\t\tconst fontInfo = options.get(EditorOption.fontInfo);\n\t\tthis.renderWhitespace = options.get(EditorOption.renderWhitespace);\n\t\tthis.renderControlCharacters = options.get(EditorOption.renderControlCharacters);\n\t\tthis.spaceWidth = fontInfo.spaceWidth;\n\t\tthis.middotWidth = fontInfo.middotWidth;\n\t\tthis.wsmiddotWidth = fontInfo.wsmiddotWidth;\n\t\tthis.useMonospaceOptimizations = (\n\t\t\tfontInfo.isMonospace\n\t\t\t&& !options.get(EditorOption.disableMonospaceOptimizations)\n\t\t);\n\t\tthis.canUseHalfwidthRightwardsArrow = fontInfo.canUseHalfwidthRightwardsArrow;\n\t\tthis.lineHeight = options.get(EditorOption.lineHeight);\n\t\tthis.stopRenderingLineAfter = options.get(EditorOption.stopRenderingLineAfter);\n\t\tthis.fontLigatures = options.get(EditorOption.fontLigatures);\n\t}\n\n\tpublic equals(other: ViewLineOptions): boolean {\n\t\treturn (\n\t\t\tthis.themeType === other.themeType\n\t\t\t&& this.renderWhitespace === other.renderWhitespace\n\t\t\t&& this.renderControlCharacters === other.renderControlCharacters\n\t\t\t&& this.spaceWidth === other.spaceWidth\n\t\t\t&& this.middotWidth === other.middotWidth\n\t\t\t&& this.wsmiddotWidth === other.wsmiddotWidth\n\t\t\t&& this.useMonospaceOptimizations === other.useMonospaceOptimizations\n\t\t\t&& this.canUseHalfwidthRightwardsArrow === other.canUseHalfwidthRightwardsArrow\n\t\t\t&& this.lineHeight === other.lineHeight\n\t\t\t&& this.stopRenderingLineAfter === other.stopRenderingLineAfter\n\t\t\t&& this.fontLigatures === other.fontLigatures\n\t\t);\n\t}\n}\n\nexport class ViewLine implements IVisibleLine {\n\n\tpublic static readonly CLASS_NAME = 'view-line';\n\n\tprivate _options: ViewLineOptions;\n\tprivate _isMaybeInvalid: boolean;\n\tprivate _renderedViewLine: IRenderedViewLine | null;\n\n\tconstructor(options: ViewLineOptions) {\n\t\tthis._options = options;\n\t\tthis._isMaybeInvalid = true;\n\t\tthis._renderedViewLine = null;\n\t}\n\n\t// --- begin IVisibleLineData\n\n\tpublic getDomNode(): HTMLElement | null {\n\t\tif (this._renderedViewLine && this._renderedViewLine.domNode) {\n\t\t\treturn this._renderedViewLine.domNode.domNode;\n\t\t}\n\t\treturn null;\n\t}\n\tpublic setDomNode(domNode: HTMLElement): void {\n\t\tif (this._renderedViewLine) {\n\t\t\tthis._renderedViewLine.domNode = createFastDomNode(domNode);\n\t\t} else {\n\t\t\tthrow new Error('I have no rendered view line to set the dom node to...');\n\t\t}\n\t}\n\n\tpublic onContentChanged(): void {\n\t\tthis._isMaybeInvalid = true;\n\t}\n\tpublic onTokensChanged(): void {\n\t\tthis._isMaybeInvalid = true;\n\t}\n\tpublic onDecorationsChanged(): void {\n\t\tthis._isMaybeInvalid = true;\n\t}\n\tpublic onOptionsChanged(newOptions: ViewLineOptions): void {\n\t\tthis._isMaybeInvalid = true;\n\t\tthis._options = newOptions;\n\t}\n\tpublic onSelectionChanged(): boolean {\n\t\tif (this._options.themeType === ColorScheme.HIGH_CONTRAST || this._options.renderWhitespace === 'selection') {\n\t\t\tthis._isMaybeInvalid = true;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic renderLine(lineNumber: number, deltaTop: number, viewportData: ViewportData, sb: IStringBuilder): boolean {\n\t\tif (this._isMaybeInvalid === false) {\n\t\t\t// it appears that nothing relevant has changed\n\t\t\treturn false;\n\t\t}\n\n\t\tthis._isMaybeInvalid = false;\n\n\t\tconst lineData = viewportData.getViewLineRenderingData(lineNumber);\n\t\tconst options = this._options;\n\t\tconst actualInlineDecorations = LineDecoration.filter(lineData.inlineDecorations, lineNumber, lineData.minColumn, lineData.maxColumn);\n\n\t\t// Only send selection information when needed for rendering whitespace\n\t\tlet selectionsOnLine: LineRange[] | null = null;\n\t\tif (options.themeType === ColorScheme.HIGH_CONTRAST || this._options.renderWhitespace === 'selection') {\n\t\t\tconst selections = viewportData.selections;\n\t\t\tfor (const selection of selections) {\n\n\t\t\t\tif (selection.endLineNumber < lineNumber || selection.startLineNumber > lineNumber) {\n\t\t\t\t\t// Selection does not intersect line\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst startColumn = (selection.startLineNumber === lineNumber ? selection.startColumn : lineData.minColumn);\n\t\t\t\tconst endColumn = (selection.endLineNumber === lineNumber ? selection.endColumn : lineData.maxColumn);\n\n\t\t\t\tif (startColumn < endColumn) {\n\t\t\t\t\tif (options.themeType === ColorScheme.HIGH_CONTRAST || this._options.renderWhitespace !== 'selection') {\n\t\t\t\t\t\tactualInlineDecorations.push(new LineDecoration(startColumn, endColumn, 'inline-selected-text', InlineDecorationType.Regular));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!selectionsOnLine) {\n\t\t\t\t\t\t\tselectionsOnLine = [];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tselectionsOnLine.push(new LineRange(startColumn - 1, endColumn - 1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst renderLineInput = new RenderLineInput(\n\t\t\toptions.useMonospaceOptimizations,\n\t\t\toptions.canUseHalfwidthRightwardsArrow,\n\t\t\tlineData.content,\n\t\t\tlineData.continuesWithWrappedLine,\n\t\t\tlineData.isBasicASCII,\n\t\t\tlineData.containsRTL,\n\t\t\tlineData.minColumn - 1,\n\t\t\tlineData.tokens,\n\t\t\tactualInlineDecorations,\n\t\t\tlineData.tabSize,\n\t\t\tlineData.startVisibleColumn,\n\t\t\toptions.spaceWidth,\n\t\t\toptions.middotWidth,\n\t\t\toptions.wsmiddotWidth,\n\t\t\toptions.stopRenderingLineAfter,\n\t\t\toptions.renderWhitespace,\n\t\t\toptions.renderControlCharacters,\n\t\t\toptions.fontLigatures !== EditorFontLigatures.OFF,\n\t\t\tselectionsOnLine\n\t\t);\n\n\t\tif (this._renderedViewLine && this._renderedViewLine.input.equals(renderLineInput)) {\n\t\t\t// no need to do anything, we have the same render input\n\t\t\treturn false;\n\t\t}\n\n\t\tsb.appendASCIIString('
    ');\n\n\t\tconst output = renderViewLine(renderLineInput, sb);\n\n\t\tsb.appendASCIIString('
    ');\n\n\t\tlet renderedViewLine: IRenderedViewLine | null = null;\n\t\tif (monospaceAssumptionsAreValid && canUseFastRenderedViewLine && lineData.isBasicASCII && options.useMonospaceOptimizations && output.containsForeignElements === ForeignElementType.None) {\n\t\t\tif (lineData.content.length < 300 && renderLineInput.lineTokens.getCount() < 100) {\n\t\t\t\t// Browser rounding errors have been observed in Chrome and IE, so using the fast\n\t\t\t\t// view line only for short lines. Please test before removing the length check...\n\t\t\t\t// ---\n\t\t\t\t// Another rounding error has been observed on Linux in VSCode, where width\n\t\t\t\t// rounding errors add up to an observable large number...\n\t\t\t\t// ---\n\t\t\t\t// Also see another example of rounding errors on Windows in\n\t\t\t\t// https://github.com/microsoft/vscode/issues/33178\n\t\t\t\trenderedViewLine = new FastRenderedViewLine(\n\t\t\t\t\tthis._renderedViewLine ? this._renderedViewLine.domNode : null,\n\t\t\t\t\trenderLineInput,\n\t\t\t\t\toutput.characterMapping\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (!renderedViewLine) {\n\t\t\trenderedViewLine = createRenderedLine(\n\t\t\t\tthis._renderedViewLine ? this._renderedViewLine.domNode : null,\n\t\t\t\trenderLineInput,\n\t\t\t\toutput.characterMapping,\n\t\t\t\toutput.containsRTL,\n\t\t\t\toutput.containsForeignElements\n\t\t\t);\n\t\t}\n\n\t\tthis._renderedViewLine = renderedViewLine;\n\n\t\treturn true;\n\t}\n\n\tpublic layoutLine(lineNumber: number, deltaTop: number): void {\n\t\tif (this._renderedViewLine && this._renderedViewLine.domNode) {\n\t\t\tthis._renderedViewLine.domNode.setTop(deltaTop);\n\t\t\tthis._renderedViewLine.domNode.setHeight(this._options.lineHeight);\n\t\t}\n\t}\n\n\t// --- end IVisibleLineData\n\n\tpublic getWidth(): number {\n\t\tif (!this._renderedViewLine) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn this._renderedViewLine.getWidth();\n\t}\n\n\tpublic getWidthIsFast(): boolean {\n\t\tif (!this._renderedViewLine) {\n\t\t\treturn true;\n\t\t}\n\t\treturn this._renderedViewLine.getWidthIsFast();\n\t}\n\n\tpublic needsMonospaceFontCheck(): boolean {\n\t\tif (!this._renderedViewLine) {\n\t\t\treturn false;\n\t\t}\n\t\treturn (this._renderedViewLine instanceof FastRenderedViewLine);\n\t}\n\n\tpublic monospaceAssumptionsAreValid(): boolean {\n\t\tif (!this._renderedViewLine) {\n\t\t\treturn monospaceAssumptionsAreValid;\n\t\t}\n\t\tif (this._renderedViewLine instanceof FastRenderedViewLine) {\n\t\t\treturn this._renderedViewLine.monospaceAssumptionsAreValid();\n\t\t}\n\t\treturn monospaceAssumptionsAreValid;\n\t}\n\n\tpublic onMonospaceAssumptionsInvalidated(): void {\n\t\tif (this._renderedViewLine && this._renderedViewLine instanceof FastRenderedViewLine) {\n\t\t\tthis._renderedViewLine = this._renderedViewLine.toSlowRenderedLine();\n\t\t}\n\t}\n\n\tpublic getVisibleRangesForRange(lineNumber: number, startColumn: number, endColumn: number, context: DomReadingContext): VisibleRanges | null {\n\t\tif (!this._renderedViewLine) {\n\t\t\treturn null;\n\t\t}\n\n\t\tstartColumn = Math.min(this._renderedViewLine.input.lineContent.length + 1, Math.max(1, startColumn));\n\t\tendColumn = Math.min(this._renderedViewLine.input.lineContent.length + 1, Math.max(1, endColumn));\n\n\t\tconst stopRenderingLineAfter = this._renderedViewLine.input.stopRenderingLineAfter;\n\t\tlet outsideRenderedLine = false;\n\n\t\tif (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter + 1 && endColumn > stopRenderingLineAfter + 1) {\n\t\t\t// This range is obviously not visible\n\t\t\toutsideRenderedLine = true;\n\t\t}\n\n\t\tif (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter + 1) {\n\t\t\tstartColumn = stopRenderingLineAfter + 1;\n\t\t}\n\n\t\tif (stopRenderingLineAfter !== -1 && endColumn > stopRenderingLineAfter + 1) {\n\t\t\tendColumn = stopRenderingLineAfter + 1;\n\t\t}\n\n\t\tconst horizontalRanges = this._renderedViewLine.getVisibleRangesForRange(lineNumber, startColumn, endColumn, context);\n\t\tif (horizontalRanges && horizontalRanges.length > 0) {\n\t\t\treturn new VisibleRanges(outsideRenderedLine, horizontalRanges);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic getColumnOfNodeOffset(lineNumber: number, spanNode: HTMLElement, offset: number): number {\n\t\tif (!this._renderedViewLine) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn this._renderedViewLine.getColumnOfNodeOffset(lineNumber, spanNode, offset);\n\t}\n}\n\ninterface IRenderedViewLine {\n\tdomNode: FastDomNode | null;\n\treadonly input: RenderLineInput;\n\tgetWidth(): number;\n\tgetWidthIsFast(): boolean;\n\tgetVisibleRangesForRange(lineNumber: number, startColumn: number, endColumn: number, context: DomReadingContext): FloatHorizontalRange[] | null;\n\tgetColumnOfNodeOffset(lineNumber: number, spanNode: HTMLElement, offset: number): number;\n}\n\n/**\n * A rendered line which is guaranteed to contain only regular ASCII and is rendered with a monospace font.\n */\nclass FastRenderedViewLine implements IRenderedViewLine {\n\n\tpublic domNode: FastDomNode | null;\n\tpublic readonly input: RenderLineInput;\n\n\tprivate readonly _characterMapping: CharacterMapping;\n\tprivate readonly _charWidth: number;\n\n\tconstructor(domNode: FastDomNode | null, renderLineInput: RenderLineInput, characterMapping: CharacterMapping) {\n\t\tthis.domNode = domNode;\n\t\tthis.input = renderLineInput;\n\n\t\tthis._characterMapping = characterMapping;\n\t\tthis._charWidth = renderLineInput.spaceWidth;\n\t}\n\n\tpublic getWidth(): number {\n\t\treturn Math.round(this._getCharPosition(this._characterMapping.length));\n\t}\n\n\tpublic getWidthIsFast(): boolean {\n\t\treturn true;\n\t}\n\n\tpublic monospaceAssumptionsAreValid(): boolean {\n\t\tif (!this.domNode) {\n\t\t\treturn monospaceAssumptionsAreValid;\n\t\t}\n\t\tconst expectedWidth = this.getWidth();\n\t\tconst actualWidth = (this.domNode.domNode.firstChild).offsetWidth;\n\t\tif (Math.abs(expectedWidth - actualWidth) >= 2) {\n\t\t\t// more than 2px off\n\t\t\tconsole.warn(`monospace assumptions have been violated, therefore disabling monospace optimizations!`);\n\t\t\tmonospaceAssumptionsAreValid = false;\n\t\t}\n\t\treturn monospaceAssumptionsAreValid;\n\t}\n\n\tpublic toSlowRenderedLine(): RenderedViewLine {\n\t\treturn createRenderedLine(this.domNode, this.input, this._characterMapping, false, ForeignElementType.None);\n\t}\n\n\tpublic getVisibleRangesForRange(lineNumber: number, startColumn: number, endColumn: number, context: DomReadingContext): FloatHorizontalRange[] | null {\n\t\tconst startPosition = this._getCharPosition(startColumn);\n\t\tconst endPosition = this._getCharPosition(endColumn);\n\t\treturn [new FloatHorizontalRange(startPosition, endPosition - startPosition)];\n\t}\n\n\tprivate _getCharPosition(column: number): number {\n\t\tconst charOffset = this._characterMapping.getAbsoluteOffset(column);\n\t\treturn this._charWidth * charOffset;\n\t}\n\n\tpublic getColumnOfNodeOffset(lineNumber: number, spanNode: HTMLElement, offset: number): number {\n\t\tconst spanNodeTextContentLength = spanNode.textContent!.length;\n\n\t\tlet spanIndex = -1;\n\t\twhile (spanNode) {\n\t\t\tspanNode = spanNode.previousSibling;\n\t\t\tspanIndex++;\n\t\t}\n\n\t\treturn this._characterMapping.getColumn(new DomPosition(spanIndex, offset), spanNodeTextContentLength);\n\t}\n}\n\n/**\n * Every time we render a line, we save what we have rendered in an instance of this class.\n */\nclass RenderedViewLine implements IRenderedViewLine {\n\n\tpublic domNode: FastDomNode | null;\n\tpublic readonly input: RenderLineInput;\n\n\tprotected readonly _characterMapping: CharacterMapping;\n\tprivate readonly _isWhitespaceOnly: boolean;\n\tprivate readonly _containsForeignElements: ForeignElementType;\n\tprivate _cachedWidth: number;\n\n\t/**\n\t * This is a map that is used only when the line is guaranteed to have no RTL text.\n\t */\n\tprivate readonly _pixelOffsetCache: Float32Array | null;\n\n\tconstructor(domNode: FastDomNode | null, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) {\n\t\tthis.domNode = domNode;\n\t\tthis.input = renderLineInput;\n\t\tthis._characterMapping = characterMapping;\n\t\tthis._isWhitespaceOnly = /^\\s*$/.test(renderLineInput.lineContent);\n\t\tthis._containsForeignElements = containsForeignElements;\n\t\tthis._cachedWidth = -1;\n\n\t\tthis._pixelOffsetCache = null;\n\t\tif (!containsRTL || this._characterMapping.length === 0 /* the line is empty */) {\n\t\t\tthis._pixelOffsetCache = new Float32Array(Math.max(2, this._characterMapping.length + 1));\n\t\t\tfor (let column = 0, len = this._characterMapping.length; column <= len; column++) {\n\t\t\t\tthis._pixelOffsetCache[column] = -1;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --- Reading from the DOM methods\n\n\tprotected _getReadingTarget(myDomNode: FastDomNode): HTMLElement {\n\t\treturn myDomNode.domNode.firstChild;\n\t}\n\n\t/**\n\t * Width of the line in pixels\n\t */\n\tpublic getWidth(): number {\n\t\tif (!this.domNode) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (this._cachedWidth === -1) {\n\t\t\tthis._cachedWidth = this._getReadingTarget(this.domNode).offsetWidth;\n\t\t}\n\t\treturn this._cachedWidth;\n\t}\n\n\tpublic getWidthIsFast(): boolean {\n\t\tif (this._cachedWidth === -1) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Visible ranges for a model range\n\t */\n\tpublic getVisibleRangesForRange(lineNumber: number, startColumn: number, endColumn: number, context: DomReadingContext): FloatHorizontalRange[] | null {\n\t\tif (!this.domNode) {\n\t\t\treturn null;\n\t\t}\n\t\tif (this._pixelOffsetCache !== null) {\n\t\t\t// the text is LTR\n\t\t\tconst startOffset = this._readPixelOffset(this.domNode, lineNumber, startColumn, context);\n\t\t\tif (startOffset === -1) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst endOffset = this._readPixelOffset(this.domNode, lineNumber, endColumn, context);\n\t\t\tif (endOffset === -1) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn [new FloatHorizontalRange(startOffset, endOffset - startOffset)];\n\t\t}\n\n\t\treturn this._readVisibleRangesForRange(this.domNode, lineNumber, startColumn, endColumn, context);\n\t}\n\n\tprotected _readVisibleRangesForRange(domNode: FastDomNode, lineNumber: number, startColumn: number, endColumn: number, context: DomReadingContext): FloatHorizontalRange[] | null {\n\t\tif (startColumn === endColumn) {\n\t\t\tconst pixelOffset = this._readPixelOffset(domNode, lineNumber, startColumn, context);\n\t\t\tif (pixelOffset === -1) {\n\t\t\t\treturn null;\n\t\t\t} else {\n\t\t\t\treturn [new FloatHorizontalRange(pixelOffset, 0)];\n\t\t\t}\n\t\t} else {\n\t\t\treturn this._readRawVisibleRangesForRange(domNode, startColumn, endColumn, context);\n\t\t}\n\t}\n\n\tprotected _readPixelOffset(domNode: FastDomNode, lineNumber: number, column: number, context: DomReadingContext): number {\n\t\tif (this._characterMapping.length === 0) {\n\t\t\t// This line has no content\n\t\t\tif (this._containsForeignElements === ForeignElementType.None) {\n\t\t\t\t// We can assume the line is really empty\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (this._containsForeignElements === ForeignElementType.After) {\n\t\t\t\t// We have foreign elements after the (empty) line\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (this._containsForeignElements === ForeignElementType.Before) {\n\t\t\t\t// We have foreign elements before the (empty) line\n\t\t\t\treturn this.getWidth();\n\t\t\t}\n\t\t\t// We have foreign elements before & after the (empty) line\n\t\t\tconst readingTarget = this._getReadingTarget(domNode);\n\t\t\tif (readingTarget.firstChild) {\n\t\t\t\treturn (readingTarget.firstChild).offsetWidth;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\n\t\tif (this._pixelOffsetCache !== null) {\n\t\t\t// the text is LTR\n\n\t\t\tconst cachedPixelOffset = this._pixelOffsetCache[column];\n\t\t\tif (cachedPixelOffset !== -1) {\n\t\t\t\treturn cachedPixelOffset;\n\t\t\t}\n\n\t\t\tconst result = this._actualReadPixelOffset(domNode, lineNumber, column, context);\n\t\t\tthis._pixelOffsetCache[column] = result;\n\t\t\treturn result;\n\t\t}\n\n\t\treturn this._actualReadPixelOffset(domNode, lineNumber, column, context);\n\t}\n\n\tprivate _actualReadPixelOffset(domNode: FastDomNode, lineNumber: number, column: number, context: DomReadingContext): number {\n\t\tif (this._characterMapping.length === 0) {\n\t\t\t// This line has no content\n\t\t\tconst r = RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), 0, 0, 0, 0, context.clientRectDeltaLeft, context.clientRectScale, context.endNode);\n\t\t\tif (!r || r.length === 0) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\treturn r[0].left;\n\t\t}\n\n\t\tif (column === this._characterMapping.length && this._isWhitespaceOnly && this._containsForeignElements === ForeignElementType.None) {\n\t\t\t// This branch helps in the case of whitespace only lines which have a width set\n\t\t\treturn this.getWidth();\n\t\t}\n\n\t\tconst domPosition = this._characterMapping.getDomPosition(column);\n\n\t\tconst r = RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), domPosition.partIndex, domPosition.charIndex, domPosition.partIndex, domPosition.charIndex, context.clientRectDeltaLeft, context.clientRectScale, context.endNode);\n\t\tif (!r || r.length === 0) {\n\t\t\treturn -1;\n\t\t}\n\t\tconst result = r[0].left;\n\t\tif (this.input.isBasicASCII) {\n\t\t\tconst charOffset = this._characterMapping.getAbsoluteOffset(column);\n\t\t\tconst expectedResult = Math.round(this.input.spaceWidth * charOffset);\n\t\t\tif (Math.abs(expectedResult - result) <= 1) {\n\t\t\t\treturn expectedResult;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate _readRawVisibleRangesForRange(domNode: FastDomNode, startColumn: number, endColumn: number, context: DomReadingContext): FloatHorizontalRange[] | null {\n\n\t\tif (startColumn === 1 && endColumn === this._characterMapping.length) {\n\t\t\t// This branch helps IE with bidi text & gives a performance boost to other browsers when reading visible ranges for an entire line\n\n\t\t\treturn [new FloatHorizontalRange(0, this.getWidth())];\n\t\t}\n\n\t\tconst startDomPosition = this._characterMapping.getDomPosition(startColumn);\n\t\tconst endDomPosition = this._characterMapping.getDomPosition(endColumn);\n\n\t\treturn RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), startDomPosition.partIndex, startDomPosition.charIndex, endDomPosition.partIndex, endDomPosition.charIndex, context.clientRectDeltaLeft, context.clientRectScale, context.endNode);\n\t}\n\n\t/**\n\t * Returns the column for the text found at a specific offset inside a rendered dom node\n\t */\n\tpublic getColumnOfNodeOffset(lineNumber: number, spanNode: HTMLElement, offset: number): number {\n\t\tconst spanNodeTextContentLength = spanNode.textContent!.length;\n\n\t\tlet spanIndex = -1;\n\t\twhile (spanNode) {\n\t\t\tspanNode = spanNode.previousSibling;\n\t\t\tspanIndex++;\n\t\t}\n\n\t\treturn this._characterMapping.getColumn(new DomPosition(spanIndex, offset), spanNodeTextContentLength);\n\t}\n}\n\nclass WebKitRenderedViewLine extends RenderedViewLine {\n\tprotected override _readVisibleRangesForRange(domNode: FastDomNode, lineNumber: number, startColumn: number, endColumn: number, context: DomReadingContext): FloatHorizontalRange[] | null {\n\t\tconst output = super._readVisibleRangesForRange(domNode, lineNumber, startColumn, endColumn, context);\n\n\t\tif (!output || output.length === 0 || startColumn === endColumn || (startColumn === 1 && endColumn === this._characterMapping.length)) {\n\t\t\treturn output;\n\t\t}\n\n\t\t// WebKit is buggy and returns an expanded range (to contain words in some cases)\n\t\t// The last client rect is enlarged (I think)\n\t\tif (!this.input.containsRTL) {\n\t\t\t// This is an attempt to patch things up\n\t\t\t// Find position of last column\n\t\t\tconst endPixelOffset = this._readPixelOffset(domNode, lineNumber, endColumn, context);\n\t\t\tif (endPixelOffset !== -1) {\n\t\t\t\tconst lastRange = output[output.length - 1];\n\t\t\t\tif (lastRange.left < endPixelOffset) {\n\t\t\t\t\t// Trim down the width of the last visible range to not go after the last column's position\n\t\t\t\t\tlastRange.width = endPixelOffset - lastRange.left;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn output;\n\t}\n}\n\nconst createRenderedLine: (domNode: FastDomNode | null, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) => RenderedViewLine = (function () {\n\tif (browser.isWebKit) {\n\t\treturn createWebKitRenderedLine;\n\t}\n\treturn createNormalRenderedLine;\n})();\n\nfunction createWebKitRenderedLine(domNode: FastDomNode | null, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType): RenderedViewLine {\n\treturn new WebKitRenderedViewLine(domNode, renderLineInput, characterMapping, containsRTL, containsForeignElements);\n}\n\nfunction createNormalRenderedLine(domNode: FastDomNode | null, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType): RenderedViewLine {\n\treturn new RenderedViewLine(domNode, renderLineInput, characterMapping, containsRTL, containsForeignElements);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IPointerHandlerHelper } from 'vs/editor/browser/controller/mouseHandler';\nimport { IMouseTargetContentEmptyData, IMouseTargetMarginData, IMouseTarget, IMouseTargetContentEmpty, IMouseTargetContentText, IMouseTargetContentWidget, IMouseTargetMargin, IMouseTargetOutsideEditor, IMouseTargetOverlayWidget, IMouseTargetScrollbar, IMouseTargetTextarea, IMouseTargetUnknown, IMouseTargetViewZone, IMouseTargetContentTextData, IMouseTargetViewZoneData, MouseTargetType } from 'vs/editor/browser/editorBrowser';\nimport { ClientCoordinates, EditorMouseEvent, EditorPagePosition, PageCoordinates, CoordinatesRelativeToEditor } from 'vs/editor/browser/editorDom';\nimport { PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart';\nimport { ViewLine } from 'vs/editor/browser/viewParts/lines/viewLine';\nimport { IViewCursorRenderData } from 'vs/editor/browser/viewParts/viewCursors/viewCursor';\nimport { EditorLayoutInfo, EditorOption } from 'vs/editor/common/config/editorOptions';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Range as EditorRange } from 'vs/editor/common/core/range';\nimport { HorizontalPosition } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport { IViewModel } from 'vs/editor/common/viewModel/viewModel';\nimport { CursorColumns } from 'vs/editor/common/core/cursorColumns';\nimport * as dom from 'vs/base/browser/dom';\nimport { AtomicTabMoveOperations, Direction } from 'vs/editor/common/cursor/cursorAtomicMoveOperations';\nimport { PositionAffinity } from 'vs/editor/common/model';\nimport { InjectedText } from 'vs/editor/common/viewModel/modelLineProjectionData';\n\nconst enum HitTestResultType {\n\tUnknown,\n\tContent,\n}\n\nclass UnknownHitTestResult {\n\treadonly type = HitTestResultType.Unknown;\n\tconstructor(\n\t\treadonly hitTarget: Element | null = null\n\t) { }\n}\n\nclass ContentHitTestResult {\n\treadonly type = HitTestResultType.Content;\n\tconstructor(\n\t\treadonly position: Position,\n\t\treadonly spanNode: HTMLElement,\n\t\treadonly injectedText: InjectedText | null,\n\t) { }\n}\n\ntype HitTestResult = UnknownHitTestResult | ContentHitTestResult;\n\nnamespace HitTestResult {\n\texport function createFromDOMInfo(ctx: HitTestContext, spanNode: HTMLElement, offset: number): HitTestResult {\n\t\tconst position = ctx.getPositionFromDOMInfo(spanNode, offset);\n\t\tif (position) {\n\t\t\treturn new ContentHitTestResult(position, spanNode, null);\n\t\t}\n\t\treturn new UnknownHitTestResult(spanNode);\n\t}\n}\n\nexport class PointerHandlerLastRenderData {\n\tconstructor(\n\t\tpublic readonly lastViewCursorsRenderData: IViewCursorRenderData[],\n\t\tpublic readonly lastTextareaPosition: Position | null\n\t) { }\n}\n\nexport class MouseTarget {\n\n\tprivate static _deduceRage(position: Position): EditorRange;\n\tprivate static _deduceRage(position: Position, range: EditorRange | null): EditorRange;\n\tprivate static _deduceRage(position: Position | null): EditorRange | null;\n\tprivate static _deduceRage(position: Position | null, range: EditorRange | null = null): EditorRange | null {\n\t\tif (!range && position) {\n\t\t\treturn new EditorRange(position.lineNumber, position.column, position.lineNumber, position.column);\n\t\t}\n\t\treturn range ?? null;\n\t}\n\tpublic static createUnknown(element: Element | null, mouseColumn: number, position: Position | null): IMouseTargetUnknown {\n\t\treturn { type: MouseTargetType.UNKNOWN, element, mouseColumn, position, range: this._deduceRage(position) };\n\t}\n\tpublic static createTextarea(element: Element | null, mouseColumn: number): IMouseTargetTextarea {\n\t\treturn { type: MouseTargetType.TEXTAREA, element, mouseColumn, position: null, range: null };\n\t}\n\tpublic static createMargin(type: MouseTargetType.GUTTER_GLYPH_MARGIN | MouseTargetType.GUTTER_LINE_NUMBERS | MouseTargetType.GUTTER_LINE_DECORATIONS, element: Element | null, mouseColumn: number, position: Position, range: EditorRange, detail: IMouseTargetMarginData): IMouseTargetMargin {\n\t\treturn { type, element, mouseColumn, position, range, detail };\n\t}\n\tpublic static createViewZone(type: MouseTargetType.GUTTER_VIEW_ZONE | MouseTargetType.CONTENT_VIEW_ZONE, element: Element | null, mouseColumn: number, position: Position, detail: IMouseTargetViewZoneData): IMouseTargetViewZone {\n\t\treturn { type, element, mouseColumn, position, range: this._deduceRage(position), detail };\n\t}\n\tpublic static createContentText(element: Element | null, mouseColumn: number, position: Position, range: EditorRange | null, detail: IMouseTargetContentTextData): IMouseTargetContentText {\n\t\treturn { type: MouseTargetType.CONTENT_TEXT, element, mouseColumn, position, range: this._deduceRage(position, range), detail };\n\t}\n\tpublic static createContentEmpty(element: Element | null, mouseColumn: number, position: Position, detail: IMouseTargetContentEmptyData): IMouseTargetContentEmpty {\n\t\treturn { type: MouseTargetType.CONTENT_EMPTY, element, mouseColumn, position, range: this._deduceRage(position), detail };\n\t}\n\tpublic static createContentWidget(element: Element | null, mouseColumn: number, detail: string): IMouseTargetContentWidget {\n\t\treturn { type: MouseTargetType.CONTENT_WIDGET, element, mouseColumn, position: null, range: null, detail };\n\t}\n\tpublic static createScrollbar(element: Element | null, mouseColumn: number, position: Position): IMouseTargetScrollbar {\n\t\treturn { type: MouseTargetType.SCROLLBAR, element, mouseColumn, position, range: this._deduceRage(position) };\n\t}\n\tpublic static createOverlayWidget(element: Element | null, mouseColumn: number, detail: string): IMouseTargetOverlayWidget {\n\t\treturn { type: MouseTargetType.OVERLAY_WIDGET, element, mouseColumn, position: null, range: null, detail };\n\t}\n\tpublic static createOutsideEditor(mouseColumn: number, position: Position): IMouseTargetOutsideEditor {\n\t\treturn { type: MouseTargetType.OUTSIDE_EDITOR, element: null, mouseColumn, position, range: this._deduceRage(position) };\n\t}\n\n\tprivate static _typeToString(type: MouseTargetType): string {\n\t\tif (type === MouseTargetType.TEXTAREA) {\n\t\t\treturn 'TEXTAREA';\n\t\t}\n\t\tif (type === MouseTargetType.GUTTER_GLYPH_MARGIN) {\n\t\t\treturn 'GUTTER_GLYPH_MARGIN';\n\t\t}\n\t\tif (type === MouseTargetType.GUTTER_LINE_NUMBERS) {\n\t\t\treturn 'GUTTER_LINE_NUMBERS';\n\t\t}\n\t\tif (type === MouseTargetType.GUTTER_LINE_DECORATIONS) {\n\t\t\treturn 'GUTTER_LINE_DECORATIONS';\n\t\t}\n\t\tif (type === MouseTargetType.GUTTER_VIEW_ZONE) {\n\t\t\treturn 'GUTTER_VIEW_ZONE';\n\t\t}\n\t\tif (type === MouseTargetType.CONTENT_TEXT) {\n\t\t\treturn 'CONTENT_TEXT';\n\t\t}\n\t\tif (type === MouseTargetType.CONTENT_EMPTY) {\n\t\t\treturn 'CONTENT_EMPTY';\n\t\t}\n\t\tif (type === MouseTargetType.CONTENT_VIEW_ZONE) {\n\t\t\treturn 'CONTENT_VIEW_ZONE';\n\t\t}\n\t\tif (type === MouseTargetType.CONTENT_WIDGET) {\n\t\t\treturn 'CONTENT_WIDGET';\n\t\t}\n\t\tif (type === MouseTargetType.OVERVIEW_RULER) {\n\t\t\treturn 'OVERVIEW_RULER';\n\t\t}\n\t\tif (type === MouseTargetType.SCROLLBAR) {\n\t\t\treturn 'SCROLLBAR';\n\t\t}\n\t\tif (type === MouseTargetType.OVERLAY_WIDGET) {\n\t\t\treturn 'OVERLAY_WIDGET';\n\t\t}\n\t\treturn 'UNKNOWN';\n\t}\n\n\tpublic static toString(target: IMouseTarget): string {\n\t\treturn this._typeToString(target.type) + ': ' + target.position + ' - ' + target.range + ' - ' + JSON.stringify((target).detail);\n\t}\n}\n\nclass ElementPath {\n\n\tpublic static isTextArea(path: Uint8Array): boolean {\n\t\treturn (\n\t\t\tpath.length === 2\n\t\t\t&& path[0] === PartFingerprint.OverflowGuard\n\t\t\t&& path[1] === PartFingerprint.TextArea\n\t\t);\n\t}\n\n\tpublic static isChildOfViewLines(path: Uint8Array): boolean {\n\t\treturn (\n\t\t\tpath.length >= 4\n\t\t\t&& path[0] === PartFingerprint.OverflowGuard\n\t\t\t&& path[3] === PartFingerprint.ViewLines\n\t\t);\n\t}\n\n\tpublic static isStrictChildOfViewLines(path: Uint8Array): boolean {\n\t\treturn (\n\t\t\tpath.length > 4\n\t\t\t&& path[0] === PartFingerprint.OverflowGuard\n\t\t\t&& path[3] === PartFingerprint.ViewLines\n\t\t);\n\t}\n\n\tpublic static isChildOfScrollableElement(path: Uint8Array): boolean {\n\t\treturn (\n\t\t\tpath.length >= 2\n\t\t\t&& path[0] === PartFingerprint.OverflowGuard\n\t\t\t&& path[1] === PartFingerprint.ScrollableElement\n\t\t);\n\t}\n\n\tpublic static isChildOfMinimap(path: Uint8Array): boolean {\n\t\treturn (\n\t\t\tpath.length >= 2\n\t\t\t&& path[0] === PartFingerprint.OverflowGuard\n\t\t\t&& path[1] === PartFingerprint.Minimap\n\t\t);\n\t}\n\n\tpublic static isChildOfContentWidgets(path: Uint8Array): boolean {\n\t\treturn (\n\t\t\tpath.length >= 4\n\t\t\t&& path[0] === PartFingerprint.OverflowGuard\n\t\t\t&& path[3] === PartFingerprint.ContentWidgets\n\t\t);\n\t}\n\n\tpublic static isChildOfOverflowingContentWidgets(path: Uint8Array): boolean {\n\t\treturn (\n\t\t\tpath.length >= 1\n\t\t\t&& path[0] === PartFingerprint.OverflowingContentWidgets\n\t\t);\n\t}\n\n\tpublic static isChildOfOverlayWidgets(path: Uint8Array): boolean {\n\t\treturn (\n\t\t\tpath.length >= 2\n\t\t\t&& path[0] === PartFingerprint.OverflowGuard\n\t\t\t&& path[1] === PartFingerprint.OverlayWidgets\n\t\t);\n\t}\n}\n\nexport class HitTestContext {\n\n\tpublic readonly model: IViewModel;\n\tpublic readonly layoutInfo: EditorLayoutInfo;\n\tpublic readonly viewDomNode: HTMLElement;\n\tpublic readonly lineHeight: number;\n\tpublic readonly stickyTabStops: boolean;\n\tpublic readonly typicalHalfwidthCharacterWidth: number;\n\tpublic readonly lastRenderData: PointerHandlerLastRenderData;\n\n\tprivate readonly _context: ViewContext;\n\tprivate readonly _viewHelper: IPointerHandlerHelper;\n\n\tconstructor(context: ViewContext, viewHelper: IPointerHandlerHelper, lastRenderData: PointerHandlerLastRenderData) {\n\t\tthis.model = context.model;\n\t\tconst options = context.configuration.options;\n\t\tthis.layoutInfo = options.get(EditorOption.layoutInfo);\n\t\tthis.viewDomNode = viewHelper.viewDomNode;\n\t\tthis.lineHeight = options.get(EditorOption.lineHeight);\n\t\tthis.stickyTabStops = options.get(EditorOption.stickyTabStops);\n\t\tthis.typicalHalfwidthCharacterWidth = options.get(EditorOption.fontInfo).typicalHalfwidthCharacterWidth;\n\t\tthis.lastRenderData = lastRenderData;\n\t\tthis._context = context;\n\t\tthis._viewHelper = viewHelper;\n\t}\n\n\tpublic getZoneAtCoord(mouseVerticalOffset: number): IMouseTargetViewZoneData | null {\n\t\treturn HitTestContext.getZoneAtCoord(this._context, mouseVerticalOffset);\n\t}\n\n\tpublic static getZoneAtCoord(context: ViewContext, mouseVerticalOffset: number): IMouseTargetViewZoneData | null {\n\t\t// The target is either a view zone or the empty space after the last view-line\n\t\tconst viewZoneWhitespace = context.viewLayout.getWhitespaceAtVerticalOffset(mouseVerticalOffset);\n\n\t\tif (viewZoneWhitespace) {\n\t\t\tconst viewZoneMiddle = viewZoneWhitespace.verticalOffset + viewZoneWhitespace.height / 2;\n\t\t\tconst lineCount = context.model.getLineCount();\n\t\t\tlet positionBefore: Position | null = null;\n\t\t\tlet position: Position | null;\n\t\t\tlet positionAfter: Position | null = null;\n\n\t\t\tif (viewZoneWhitespace.afterLineNumber !== lineCount) {\n\t\t\t\t// There are more lines after this view zone\n\t\t\t\tpositionAfter = new Position(viewZoneWhitespace.afterLineNumber + 1, 1);\n\t\t\t}\n\t\t\tif (viewZoneWhitespace.afterLineNumber > 0) {\n\t\t\t\t// There are more lines above this view zone\n\t\t\t\tpositionBefore = new Position(viewZoneWhitespace.afterLineNumber, context.model.getLineMaxColumn(viewZoneWhitespace.afterLineNumber));\n\t\t\t}\n\n\t\t\tif (positionAfter === null) {\n\t\t\t\tposition = positionBefore;\n\t\t\t} else if (positionBefore === null) {\n\t\t\t\tposition = positionAfter;\n\t\t\t} else if (mouseVerticalOffset < viewZoneMiddle) {\n\t\t\t\tposition = positionBefore;\n\t\t\t} else {\n\t\t\t\tposition = positionAfter;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tviewZoneId: viewZoneWhitespace.id,\n\t\t\t\tafterLineNumber: viewZoneWhitespace.afterLineNumber,\n\t\t\t\tpositionBefore: positionBefore,\n\t\t\t\tpositionAfter: positionAfter,\n\t\t\t\tposition: position!\n\t\t\t};\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic getFullLineRangeAtCoord(mouseVerticalOffset: number): { range: EditorRange; isAfterLines: boolean; } {\n\t\tif (this._context.viewLayout.isAfterLines(mouseVerticalOffset)) {\n\t\t\t// Below the last line\n\t\t\tconst lineNumber = this._context.model.getLineCount();\n\t\t\tconst maxLineColumn = this._context.model.getLineMaxColumn(lineNumber);\n\t\t\treturn {\n\t\t\t\trange: new EditorRange(lineNumber, maxLineColumn, lineNumber, maxLineColumn),\n\t\t\t\tisAfterLines: true\n\t\t\t};\n\t\t}\n\n\t\tconst lineNumber = this._context.viewLayout.getLineNumberAtVerticalOffset(mouseVerticalOffset);\n\t\tconst maxLineColumn = this._context.model.getLineMaxColumn(lineNumber);\n\t\treturn {\n\t\t\trange: new EditorRange(lineNumber, 1, lineNumber, maxLineColumn),\n\t\t\tisAfterLines: false\n\t\t};\n\t}\n\n\tpublic getLineNumberAtVerticalOffset(mouseVerticalOffset: number): number {\n\t\treturn this._context.viewLayout.getLineNumberAtVerticalOffset(mouseVerticalOffset);\n\t}\n\n\tpublic isAfterLines(mouseVerticalOffset: number): boolean {\n\t\treturn this._context.viewLayout.isAfterLines(mouseVerticalOffset);\n\t}\n\n\tpublic isInTopPadding(mouseVerticalOffset: number): boolean {\n\t\treturn this._context.viewLayout.isInTopPadding(mouseVerticalOffset);\n\t}\n\n\tpublic isInBottomPadding(mouseVerticalOffset: number): boolean {\n\t\treturn this._context.viewLayout.isInBottomPadding(mouseVerticalOffset);\n\t}\n\n\tpublic getVerticalOffsetForLineNumber(lineNumber: number): number {\n\t\treturn this._context.viewLayout.getVerticalOffsetForLineNumber(lineNumber);\n\t}\n\n\tpublic findAttribute(element: Element, attr: string): string | null {\n\t\treturn HitTestContext._findAttribute(element, attr, this._viewHelper.viewDomNode);\n\t}\n\n\tprivate static _findAttribute(element: Element, attr: string, stopAt: Element): string | null {\n\t\twhile (element && element !== document.body) {\n\t\t\tif (element.hasAttribute && element.hasAttribute(attr)) {\n\t\t\t\treturn element.getAttribute(attr);\n\t\t\t}\n\t\t\tif (element === stopAt) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\telement = element.parentNode;\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic getLineWidth(lineNumber: number): number {\n\t\treturn this._viewHelper.getLineWidth(lineNumber);\n\t}\n\n\tpublic visibleRangeForPosition(lineNumber: number, column: number): HorizontalPosition | null {\n\t\treturn this._viewHelper.visibleRangeForPosition(lineNumber, column);\n\t}\n\n\tpublic getPositionFromDOMInfo(spanNode: HTMLElement, offset: number): Position | null {\n\t\treturn this._viewHelper.getPositionFromDOMInfo(spanNode, offset);\n\t}\n\n\tpublic getCurrentScrollTop(): number {\n\t\treturn this._context.viewLayout.getCurrentScrollTop();\n\t}\n\n\tpublic getCurrentScrollLeft(): number {\n\t\treturn this._context.viewLayout.getCurrentScrollLeft();\n\t}\n}\n\nabstract class BareHitTestRequest {\n\n\tpublic readonly editorPos: EditorPagePosition;\n\tpublic readonly pos: PageCoordinates;\n\tpublic readonly relativePos: CoordinatesRelativeToEditor;\n\tpublic readonly mouseVerticalOffset: number;\n\tpublic readonly isInMarginArea: boolean;\n\tpublic readonly isInContentArea: boolean;\n\tpublic readonly mouseContentHorizontalOffset: number;\n\n\tprotected readonly mouseColumn: number;\n\n\tconstructor(ctx: HitTestContext, editorPos: EditorPagePosition, pos: PageCoordinates, relativePos: CoordinatesRelativeToEditor) {\n\t\tthis.editorPos = editorPos;\n\t\tthis.pos = pos;\n\t\tthis.relativePos = relativePos;\n\n\t\tthis.mouseVerticalOffset = Math.max(0, ctx.getCurrentScrollTop() + this.relativePos.y);\n\t\tthis.mouseContentHorizontalOffset = ctx.getCurrentScrollLeft() + this.relativePos.x - ctx.layoutInfo.contentLeft;\n\t\tthis.isInMarginArea = (this.relativePos.x < ctx.layoutInfo.contentLeft && this.relativePos.x >= ctx.layoutInfo.glyphMarginLeft);\n\t\tthis.isInContentArea = !this.isInMarginArea;\n\t\tthis.mouseColumn = Math.max(0, MouseTargetFactory._getMouseColumn(this.mouseContentHorizontalOffset, ctx.typicalHalfwidthCharacterWidth));\n\t}\n}\n\nclass HitTestRequest extends BareHitTestRequest {\n\tprivate readonly _ctx: HitTestContext;\n\tpublic readonly target: Element | null;\n\tpublic readonly targetPath: Uint8Array;\n\n\tconstructor(ctx: HitTestContext, editorPos: EditorPagePosition, pos: PageCoordinates, relativePos: CoordinatesRelativeToEditor, target: Element | null) {\n\t\tsuper(ctx, editorPos, pos, relativePos);\n\t\tthis._ctx = ctx;\n\n\t\tif (target) {\n\t\t\tthis.target = target;\n\t\t\tthis.targetPath = PartFingerprints.collect(target, ctx.viewDomNode);\n\t\t} else {\n\t\t\tthis.target = null;\n\t\t\tthis.targetPath = new Uint8Array(0);\n\t\t}\n\t}\n\n\tpublic override toString(): string {\n\t\treturn `pos(${this.pos.x},${this.pos.y}), editorPos(${this.editorPos.x},${this.editorPos.y}), relativePos(${this.relativePos.x},${this.relativePos.y}), mouseVerticalOffset: ${this.mouseVerticalOffset}, mouseContentHorizontalOffset: ${this.mouseContentHorizontalOffset}\\n\\ttarget: ${this.target ? (this.target).outerHTML : null}`;\n\t}\n\n\tprivate _getMouseColumn(position: Position | null = null): number {\n\t\tif (position && position.column < this._ctx.model.getLineMaxColumn(position.lineNumber)) {\n\t\t\t// Most likely, the line contains foreign decorations...\n\t\t\treturn CursorColumns.visibleColumnFromColumn(this._ctx.model.getLineContent(position.lineNumber), position.column, this._ctx.model.getTextModelOptions().tabSize) + 1;\n\t\t}\n\t\treturn this.mouseColumn;\n\t}\n\n\tpublic fulfillUnknown(position: Position | null = null): IMouseTargetUnknown {\n\t\treturn MouseTarget.createUnknown(this.target, this._getMouseColumn(position), position);\n\t}\n\tpublic fulfillTextarea(): IMouseTargetTextarea {\n\t\treturn MouseTarget.createTextarea(this.target, this._getMouseColumn());\n\t}\n\tpublic fulfillMargin(type: MouseTargetType.GUTTER_GLYPH_MARGIN | MouseTargetType.GUTTER_LINE_NUMBERS | MouseTargetType.GUTTER_LINE_DECORATIONS, position: Position, range: EditorRange, detail: IMouseTargetMarginData): IMouseTargetMargin {\n\t\treturn MouseTarget.createMargin(type, this.target, this._getMouseColumn(position), position, range, detail);\n\t}\n\tpublic fulfillViewZone(type: MouseTargetType.GUTTER_VIEW_ZONE | MouseTargetType.CONTENT_VIEW_ZONE, position: Position, detail: IMouseTargetViewZoneData): IMouseTargetViewZone {\n\t\treturn MouseTarget.createViewZone(type, this.target, this._getMouseColumn(position), position, detail);\n\t}\n\tpublic fulfillContentText(position: Position, range: EditorRange | null, detail: IMouseTargetContentTextData): IMouseTargetContentText {\n\t\treturn MouseTarget.createContentText(this.target, this._getMouseColumn(position), position, range, detail);\n\t}\n\tpublic fulfillContentEmpty(position: Position, detail: IMouseTargetContentEmptyData): IMouseTargetContentEmpty {\n\t\treturn MouseTarget.createContentEmpty(this.target, this._getMouseColumn(position), position, detail);\n\t}\n\tpublic fulfillContentWidget(detail: string): IMouseTargetContentWidget {\n\t\treturn MouseTarget.createContentWidget(this.target, this._getMouseColumn(), detail);\n\t}\n\tpublic fulfillScrollbar(position: Position): IMouseTargetScrollbar {\n\t\treturn MouseTarget.createScrollbar(this.target, this._getMouseColumn(position), position);\n\t}\n\tpublic fulfillOverlayWidget(detail: string): IMouseTargetOverlayWidget {\n\t\treturn MouseTarget.createOverlayWidget(this.target, this._getMouseColumn(), detail);\n\t}\n\n\tpublic withTarget(target: Element | null): HitTestRequest {\n\t\treturn new HitTestRequest(this._ctx, this.editorPos, this.pos, this.relativePos, target);\n\t}\n}\n\ninterface ResolvedHitTestRequest extends HitTestRequest {\n\treadonly target: Element;\n}\n\nconst EMPTY_CONTENT_AFTER_LINES: IMouseTargetContentEmptyData = { isAfterLines: true };\n\nfunction createEmptyContentDataInLines(horizontalDistanceToText: number): IMouseTargetContentEmptyData {\n\treturn {\n\t\tisAfterLines: false,\n\t\thorizontalDistanceToText: horizontalDistanceToText\n\t};\n}\n\nexport class MouseTargetFactory {\n\n\tprivate readonly _context: ViewContext;\n\tprivate readonly _viewHelper: IPointerHandlerHelper;\n\n\tconstructor(context: ViewContext, viewHelper: IPointerHandlerHelper) {\n\t\tthis._context = context;\n\t\tthis._viewHelper = viewHelper;\n\t}\n\n\tpublic mouseTargetIsWidget(e: EditorMouseEvent): boolean {\n\t\tconst t = e.target;\n\t\tconst path = PartFingerprints.collect(t, this._viewHelper.viewDomNode);\n\n\t\t// Is it a content widget?\n\t\tif (ElementPath.isChildOfContentWidgets(path) || ElementPath.isChildOfOverflowingContentWidgets(path)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Is it an overlay widget?\n\t\tif (ElementPath.isChildOfOverlayWidgets(path)) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic createMouseTarget(lastRenderData: PointerHandlerLastRenderData, editorPos: EditorPagePosition, pos: PageCoordinates, relativePos: CoordinatesRelativeToEditor, target: HTMLElement | null): IMouseTarget {\n\t\tconst ctx = new HitTestContext(this._context, this._viewHelper, lastRenderData);\n\t\tconst request = new HitTestRequest(ctx, editorPos, pos, relativePos, target);\n\t\ttry {\n\t\t\tconst r = MouseTargetFactory._createMouseTarget(ctx, request, false);\n\t\t\t// console.log(MouseTarget.toString(r));\n\t\t\treturn r;\n\t\t} catch (err) {\n\t\t\t// console.log(err);\n\t\t\treturn request.fulfillUnknown();\n\t\t}\n\t}\n\n\tprivate static _createMouseTarget(ctx: HitTestContext, request: HitTestRequest, domHitTestExecuted: boolean): IMouseTarget {\n\n\t\t// console.log(`${domHitTestExecuted ? '=>' : ''}CAME IN REQUEST: ${request}`);\n\n\t\t// First ensure the request has a target\n\t\tif (request.target === null) {\n\t\t\tif (domHitTestExecuted) {\n\t\t\t\t// Still no target... and we have already executed hit test...\n\t\t\t\treturn request.fulfillUnknown();\n\t\t\t}\n\n\t\t\tconst hitTestResult = MouseTargetFactory._doHitTest(ctx, request);\n\n\t\t\tif (hitTestResult.type === HitTestResultType.Content) {\n\t\t\t\treturn MouseTargetFactory.createMouseTargetFromHitTestPosition(ctx, request, hitTestResult.spanNode, hitTestResult.position, hitTestResult.injectedText);\n\t\t\t}\n\n\t\t\treturn this._createMouseTarget(ctx, request.withTarget(hitTestResult.hitTarget), true);\n\t\t}\n\n\t\t// we know for a fact that request.target is not null\n\t\tconst resolvedRequest = request;\n\n\t\tlet result: IMouseTarget | null = null;\n\n\t\tresult = result || MouseTargetFactory._hitTestContentWidget(ctx, resolvedRequest);\n\t\tresult = result || MouseTargetFactory._hitTestOverlayWidget(ctx, resolvedRequest);\n\t\tresult = result || MouseTargetFactory._hitTestMinimap(ctx, resolvedRequest);\n\t\tresult = result || MouseTargetFactory._hitTestScrollbarSlider(ctx, resolvedRequest);\n\t\tresult = result || MouseTargetFactory._hitTestViewZone(ctx, resolvedRequest);\n\t\tresult = result || MouseTargetFactory._hitTestMargin(ctx, resolvedRequest);\n\t\tresult = result || MouseTargetFactory._hitTestViewCursor(ctx, resolvedRequest);\n\t\tresult = result || MouseTargetFactory._hitTestTextArea(ctx, resolvedRequest);\n\t\tresult = result || MouseTargetFactory._hitTestViewLines(ctx, resolvedRequest, domHitTestExecuted);\n\t\tresult = result || MouseTargetFactory._hitTestScrollbar(ctx, resolvedRequest);\n\n\t\treturn (result || request.fulfillUnknown());\n\t}\n\n\tprivate static _hitTestContentWidget(ctx: HitTestContext, request: ResolvedHitTestRequest): IMouseTarget | null {\n\t\t// Is it a content widget?\n\t\tif (ElementPath.isChildOfContentWidgets(request.targetPath) || ElementPath.isChildOfOverflowingContentWidgets(request.targetPath)) {\n\t\t\tconst widgetId = ctx.findAttribute(request.target, 'widgetId');\n\t\t\tif (widgetId) {\n\t\t\t\treturn request.fulfillContentWidget(widgetId);\n\t\t\t} else {\n\t\t\t\treturn request.fulfillUnknown();\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate static _hitTestOverlayWidget(ctx: HitTestContext, request: ResolvedHitTestRequest): IMouseTarget | null {\n\t\t// Is it an overlay widget?\n\t\tif (ElementPath.isChildOfOverlayWidgets(request.targetPath)) {\n\t\t\tconst widgetId = ctx.findAttribute(request.target, 'widgetId');\n\t\t\tif (widgetId) {\n\t\t\t\treturn request.fulfillOverlayWidget(widgetId);\n\t\t\t} else {\n\t\t\t\treturn request.fulfillUnknown();\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate static _hitTestViewCursor(ctx: HitTestContext, request: ResolvedHitTestRequest): IMouseTarget | null {\n\n\t\tif (request.target) {\n\t\t\t// Check if we've hit a painted cursor\n\t\t\tconst lastViewCursorsRenderData = ctx.lastRenderData.lastViewCursorsRenderData;\n\n\t\t\tfor (const d of lastViewCursorsRenderData) {\n\n\t\t\t\tif (request.target === d.domNode) {\n\t\t\t\t\treturn request.fulfillContentText(d.position, null, { mightBeForeignElement: false, injectedText: null });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (request.isInContentArea) {\n\t\t\t// Edge has a bug when hit-testing the exact position of a cursor,\n\t\t\t// instead of returning the correct dom node, it returns the\n\t\t\t// first or last rendered view line dom node, therefore help it out\n\t\t\t// and first check if we are on top of a cursor\n\n\t\t\tconst lastViewCursorsRenderData = ctx.lastRenderData.lastViewCursorsRenderData;\n\t\t\tconst mouseContentHorizontalOffset = request.mouseContentHorizontalOffset;\n\t\t\tconst mouseVerticalOffset = request.mouseVerticalOffset;\n\n\t\t\tfor (const d of lastViewCursorsRenderData) {\n\n\t\t\t\tif (mouseContentHorizontalOffset < d.contentLeft) {\n\t\t\t\t\t// mouse position is to the left of the cursor\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (mouseContentHorizontalOffset > d.contentLeft + d.width) {\n\t\t\t\t\t// mouse position is to the right of the cursor\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst cursorVerticalOffset = ctx.getVerticalOffsetForLineNumber(d.position.lineNumber);\n\n\t\t\t\tif (\n\t\t\t\t\tcursorVerticalOffset <= mouseVerticalOffset\n\t\t\t\t\t&& mouseVerticalOffset <= cursorVerticalOffset + d.height\n\t\t\t\t) {\n\t\t\t\t\treturn request.fulfillContentText(d.position, null, { mightBeForeignElement: false, injectedText: null });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate static _hitTestViewZone(ctx: HitTestContext, request: ResolvedHitTestRequest): IMouseTarget | null {\n\t\tconst viewZoneData = ctx.getZoneAtCoord(request.mouseVerticalOffset);\n\t\tif (viewZoneData) {\n\t\t\tconst mouseTargetType = (request.isInContentArea ? MouseTargetType.CONTENT_VIEW_ZONE : MouseTargetType.GUTTER_VIEW_ZONE);\n\t\t\treturn request.fulfillViewZone(mouseTargetType, viewZoneData.position, viewZoneData);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate static _hitTestTextArea(ctx: HitTestContext, request: ResolvedHitTestRequest): IMouseTarget | null {\n\t\t// Is it the textarea?\n\t\tif (ElementPath.isTextArea(request.targetPath)) {\n\t\t\tif (ctx.lastRenderData.lastTextareaPosition) {\n\t\t\t\treturn request.fulfillContentText(ctx.lastRenderData.lastTextareaPosition, null, { mightBeForeignElement: false, injectedText: null });\n\t\t\t}\n\t\t\treturn request.fulfillTextarea();\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate static _hitTestMargin(ctx: HitTestContext, request: ResolvedHitTestRequest): IMouseTarget | null {\n\t\tif (request.isInMarginArea) {\n\t\t\tconst res = ctx.getFullLineRangeAtCoord(request.mouseVerticalOffset);\n\t\t\tconst pos = res.range.getStartPosition();\n\t\t\tlet offset = Math.abs(request.relativePos.x);\n\t\t\tconst detail: IMouseTargetMarginData = {\n\t\t\t\tisAfterLines: res.isAfterLines,\n\t\t\t\tglyphMarginLeft: ctx.layoutInfo.glyphMarginLeft,\n\t\t\t\tglyphMarginWidth: ctx.layoutInfo.glyphMarginWidth,\n\t\t\t\tlineNumbersWidth: ctx.layoutInfo.lineNumbersWidth,\n\t\t\t\toffsetX: offset\n\t\t\t};\n\n\t\t\toffset -= ctx.layoutInfo.glyphMarginLeft;\n\n\t\t\tif (offset <= ctx.layoutInfo.glyphMarginWidth) {\n\t\t\t\t// On the glyph margin\n\t\t\t\treturn request.fulfillMargin(MouseTargetType.GUTTER_GLYPH_MARGIN, pos, res.range, detail);\n\t\t\t}\n\t\t\toffset -= ctx.layoutInfo.glyphMarginWidth;\n\n\t\t\tif (offset <= ctx.layoutInfo.lineNumbersWidth) {\n\t\t\t\t// On the line numbers\n\t\t\t\treturn request.fulfillMargin(MouseTargetType.GUTTER_LINE_NUMBERS, pos, res.range, detail);\n\t\t\t}\n\t\t\toffset -= ctx.layoutInfo.lineNumbersWidth;\n\n\t\t\t// On the line decorations\n\t\t\treturn request.fulfillMargin(MouseTargetType.GUTTER_LINE_DECORATIONS, pos, res.range, detail);\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate static _hitTestViewLines(ctx: HitTestContext, request: ResolvedHitTestRequest, domHitTestExecuted: boolean): IMouseTarget | null {\n\t\tif (!ElementPath.isChildOfViewLines(request.targetPath)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (ctx.isInTopPadding(request.mouseVerticalOffset)) {\n\t\t\treturn request.fulfillContentEmpty(new Position(1, 1), EMPTY_CONTENT_AFTER_LINES);\n\t\t}\n\n\t\t// Check if it is below any lines and any view zones\n\t\tif (ctx.isAfterLines(request.mouseVerticalOffset) || ctx.isInBottomPadding(request.mouseVerticalOffset)) {\n\t\t\t// This most likely indicates it happened after the last view-line\n\t\t\tconst lineCount = ctx.model.getLineCount();\n\t\t\tconst maxLineColumn = ctx.model.getLineMaxColumn(lineCount);\n\t\t\treturn request.fulfillContentEmpty(new Position(lineCount, maxLineColumn), EMPTY_CONTENT_AFTER_LINES);\n\t\t}\n\n\t\tif (domHitTestExecuted) {\n\t\t\t// Check if we are hitting a view-line (can happen in the case of inline decorations on empty lines)\n\t\t\t// See https://github.com/microsoft/vscode/issues/46942\n\t\t\tif (ElementPath.isStrictChildOfViewLines(request.targetPath)) {\n\t\t\t\tconst lineNumber = ctx.getLineNumberAtVerticalOffset(request.mouseVerticalOffset);\n\t\t\t\tif (ctx.model.getLineLength(lineNumber) === 0) {\n\t\t\t\t\tconst lineWidth = ctx.getLineWidth(lineNumber);\n\t\t\t\t\tconst detail = createEmptyContentDataInLines(request.mouseContentHorizontalOffset - lineWidth);\n\t\t\t\t\treturn request.fulfillContentEmpty(new Position(lineNumber, 1), detail);\n\t\t\t\t}\n\n\t\t\t\tconst lineWidth = ctx.getLineWidth(lineNumber);\n\t\t\t\tif (request.mouseContentHorizontalOffset >= lineWidth) {\n\t\t\t\t\tconst detail = createEmptyContentDataInLines(request.mouseContentHorizontalOffset - lineWidth);\n\t\t\t\t\tconst pos = new Position(lineNumber, ctx.model.getLineMaxColumn(lineNumber));\n\t\t\t\t\treturn request.fulfillContentEmpty(pos, detail);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// We have already executed hit test...\n\t\t\treturn request.fulfillUnknown();\n\t\t}\n\n\t\tconst hitTestResult = MouseTargetFactory._doHitTest(ctx, request);\n\n\t\tif (hitTestResult.type === HitTestResultType.Content) {\n\t\t\treturn MouseTargetFactory.createMouseTargetFromHitTestPosition(ctx, request, hitTestResult.spanNode, hitTestResult.position, hitTestResult.injectedText);\n\t\t}\n\n\t\treturn this._createMouseTarget(ctx, request.withTarget(hitTestResult.hitTarget), true);\n\t}\n\n\tprivate static _hitTestMinimap(ctx: HitTestContext, request: ResolvedHitTestRequest): IMouseTarget | null {\n\t\tif (ElementPath.isChildOfMinimap(request.targetPath)) {\n\t\t\tconst possibleLineNumber = ctx.getLineNumberAtVerticalOffset(request.mouseVerticalOffset);\n\t\t\tconst maxColumn = ctx.model.getLineMaxColumn(possibleLineNumber);\n\t\t\treturn request.fulfillScrollbar(new Position(possibleLineNumber, maxColumn));\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate static _hitTestScrollbarSlider(ctx: HitTestContext, request: ResolvedHitTestRequest): IMouseTarget | null {\n\t\tif (ElementPath.isChildOfScrollableElement(request.targetPath)) {\n\t\t\tif (request.target && request.target.nodeType === 1) {\n\t\t\t\tconst className = request.target.className;\n\t\t\t\tif (className && /\\b(slider|scrollbar)\\b/.test(className)) {\n\t\t\t\t\tconst possibleLineNumber = ctx.getLineNumberAtVerticalOffset(request.mouseVerticalOffset);\n\t\t\t\t\tconst maxColumn = ctx.model.getLineMaxColumn(possibleLineNumber);\n\t\t\t\t\treturn request.fulfillScrollbar(new Position(possibleLineNumber, maxColumn));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate static _hitTestScrollbar(ctx: HitTestContext, request: ResolvedHitTestRequest): IMouseTarget | null {\n\t\t// Is it the overview ruler?\n\t\t// Is it a child of the scrollable element?\n\t\tif (ElementPath.isChildOfScrollableElement(request.targetPath)) {\n\t\t\tconst possibleLineNumber = ctx.getLineNumberAtVerticalOffset(request.mouseVerticalOffset);\n\t\t\tconst maxColumn = ctx.model.getLineMaxColumn(possibleLineNumber);\n\t\t\treturn request.fulfillScrollbar(new Position(possibleLineNumber, maxColumn));\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic getMouseColumn(relativePos: CoordinatesRelativeToEditor): number {\n\t\tconst options = this._context.configuration.options;\n\t\tconst layoutInfo = options.get(EditorOption.layoutInfo);\n\t\tconst mouseContentHorizontalOffset = this._context.viewLayout.getCurrentScrollLeft() + relativePos.x - layoutInfo.contentLeft;\n\t\treturn MouseTargetFactory._getMouseColumn(mouseContentHorizontalOffset, options.get(EditorOption.fontInfo).typicalHalfwidthCharacterWidth);\n\t}\n\n\tpublic static _getMouseColumn(mouseContentHorizontalOffset: number, typicalHalfwidthCharacterWidth: number): number {\n\t\tif (mouseContentHorizontalOffset < 0) {\n\t\t\treturn 1;\n\t\t}\n\t\tconst chars = Math.round(mouseContentHorizontalOffset / typicalHalfwidthCharacterWidth);\n\t\treturn (chars + 1);\n\t}\n\n\tprivate static createMouseTargetFromHitTestPosition(ctx: HitTestContext, request: HitTestRequest, spanNode: HTMLElement, pos: Position, injectedText: InjectedText | null): IMouseTarget {\n\t\tconst lineNumber = pos.lineNumber;\n\t\tconst column = pos.column;\n\n\t\tconst lineWidth = ctx.getLineWidth(lineNumber);\n\n\t\tif (request.mouseContentHorizontalOffset > lineWidth) {\n\t\t\tconst detail = createEmptyContentDataInLines(request.mouseContentHorizontalOffset - lineWidth);\n\t\t\treturn request.fulfillContentEmpty(pos, detail);\n\t\t}\n\n\t\tconst visibleRange = ctx.visibleRangeForPosition(lineNumber, column);\n\n\t\tif (!visibleRange) {\n\t\t\treturn request.fulfillUnknown(pos);\n\t\t}\n\n\t\tconst columnHorizontalOffset = visibleRange.left;\n\n\t\tif (request.mouseContentHorizontalOffset === columnHorizontalOffset) {\n\t\t\treturn request.fulfillContentText(pos, null, { mightBeForeignElement: !!injectedText, injectedText });\n\t\t}\n\n\t\t// Let's define a, b, c and check if the offset is in between them...\n\t\tinterface OffsetColumn { offset: number; column: number; }\n\n\t\tconst points: OffsetColumn[] = [];\n\t\tpoints.push({ offset: visibleRange.left, column: column });\n\t\tif (column > 1) {\n\t\t\tconst visibleRange = ctx.visibleRangeForPosition(lineNumber, column - 1);\n\t\t\tif (visibleRange) {\n\t\t\t\tpoints.push({ offset: visibleRange.left, column: column - 1 });\n\t\t\t}\n\t\t}\n\t\tconst lineMaxColumn = ctx.model.getLineMaxColumn(lineNumber);\n\t\tif (column < lineMaxColumn) {\n\t\t\tconst visibleRange = ctx.visibleRangeForPosition(lineNumber, column + 1);\n\t\t\tif (visibleRange) {\n\t\t\t\tpoints.push({ offset: visibleRange.left, column: column + 1 });\n\t\t\t}\n\t\t}\n\n\t\tpoints.sort((a, b) => a.offset - b.offset);\n\n\t\tconst mouseCoordinates = request.pos.toClientCoordinates();\n\t\tconst spanNodeClientRect = spanNode.getBoundingClientRect();\n\t\tconst mouseIsOverSpanNode = (spanNodeClientRect.left <= mouseCoordinates.clientX && mouseCoordinates.clientX <= spanNodeClientRect.right);\n\n\t\tfor (let i = 1; i < points.length; i++) {\n\t\t\tconst prev = points[i - 1];\n\t\t\tconst curr = points[i];\n\t\t\tif (prev.offset <= request.mouseContentHorizontalOffset && request.mouseContentHorizontalOffset <= curr.offset) {\n\t\t\t\tconst rng = new EditorRange(lineNumber, prev.column, lineNumber, curr.column);\n\t\t\t\treturn request.fulfillContentText(pos, rng, { mightBeForeignElement: !mouseIsOverSpanNode || !!injectedText, injectedText });\n\t\t\t}\n\t\t}\n\t\treturn request.fulfillContentText(pos, null, { mightBeForeignElement: !mouseIsOverSpanNode || !!injectedText, injectedText });\n\t}\n\n\t/**\n\t * Most probably WebKit browsers and Edge\n\t */\n\tprivate static _doHitTestWithCaretRangeFromPoint(ctx: HitTestContext, request: BareHitTestRequest): HitTestResult {\n\n\t\t// In Chrome, especially on Linux it is possible to click between lines,\n\t\t// so try to adjust the `hity` below so that it lands in the center of a line\n\t\tconst lineNumber = ctx.getLineNumberAtVerticalOffset(request.mouseVerticalOffset);\n\t\tconst lineVerticalOffset = ctx.getVerticalOffsetForLineNumber(lineNumber);\n\t\tconst lineCenteredVerticalOffset = lineVerticalOffset + Math.floor(ctx.lineHeight / 2);\n\t\tlet adjustedPageY = request.pos.y + (lineCenteredVerticalOffset - request.mouseVerticalOffset);\n\n\t\tif (adjustedPageY <= request.editorPos.y) {\n\t\t\tadjustedPageY = request.editorPos.y + 1;\n\t\t}\n\t\tif (adjustedPageY >= request.editorPos.y + request.editorPos.height) {\n\t\t\tadjustedPageY = request.editorPos.y + request.editorPos.height - 1;\n\t\t}\n\n\t\tconst adjustedPage = new PageCoordinates(request.pos.x, adjustedPageY);\n\n\t\tconst r = this._actualDoHitTestWithCaretRangeFromPoint(ctx, adjustedPage.toClientCoordinates());\n\t\tif (r.type === HitTestResultType.Content) {\n\t\t\treturn r;\n\t\t}\n\n\t\t// Also try to hit test without the adjustment (for the edge cases that we are near the top or bottom)\n\t\treturn this._actualDoHitTestWithCaretRangeFromPoint(ctx, request.pos.toClientCoordinates());\n\t}\n\n\tprivate static _actualDoHitTestWithCaretRangeFromPoint(ctx: HitTestContext, coords: ClientCoordinates): HitTestResult {\n\t\tconst shadowRoot = dom.getShadowRoot(ctx.viewDomNode);\n\t\tlet range: Range;\n\t\tif (shadowRoot) {\n\t\t\tif (typeof (shadowRoot).caretRangeFromPoint === 'undefined') {\n\t\t\t\trange = shadowCaretRangeFromPoint(shadowRoot, coords.clientX, coords.clientY);\n\t\t\t} else {\n\t\t\t\trange = (shadowRoot).caretRangeFromPoint(coords.clientX, coords.clientY);\n\t\t\t}\n\t\t} else {\n\t\t\trange = (document).caretRangeFromPoint(coords.clientX, coords.clientY);\n\t\t}\n\n\t\tif (!range || !range.startContainer) {\n\t\t\treturn new UnknownHitTestResult();\n\t\t}\n\n\t\t// Chrome always hits a TEXT_NODE, while Edge sometimes hits a token span\n\t\tconst startContainer = range.startContainer;\n\n\t\tif (startContainer.nodeType === startContainer.TEXT_NODE) {\n\t\t\t// startContainer is expected to be the token text\n\t\t\tconst parent1 = startContainer.parentNode; // expected to be the token span\n\t\t\tconst parent2 = parent1 ? parent1.parentNode : null; // expected to be the view line container span\n\t\t\tconst parent3 = parent2 ? parent2.parentNode : null; // expected to be the view line div\n\t\t\tconst parent3ClassName = parent3 && parent3.nodeType === parent3.ELEMENT_NODE ? (parent3).className : null;\n\n\t\t\tif (parent3ClassName === ViewLine.CLASS_NAME) {\n\t\t\t\treturn HitTestResult.createFromDOMInfo(ctx, parent1, range.startOffset);\n\t\t\t} else {\n\t\t\t\treturn new UnknownHitTestResult(startContainer.parentNode);\n\t\t\t}\n\t\t} else if (startContainer.nodeType === startContainer.ELEMENT_NODE) {\n\t\t\t// startContainer is expected to be the token span\n\t\t\tconst parent1 = startContainer.parentNode; // expected to be the view line container span\n\t\t\tconst parent2 = parent1 ? parent1.parentNode : null; // expected to be the view line div\n\t\t\tconst parent2ClassName = parent2 && parent2.nodeType === parent2.ELEMENT_NODE ? (parent2).className : null;\n\n\t\t\tif (parent2ClassName === ViewLine.CLASS_NAME) {\n\t\t\t\treturn HitTestResult.createFromDOMInfo(ctx, startContainer, (startContainer).textContent!.length);\n\t\t\t} else {\n\t\t\t\treturn new UnknownHitTestResult(startContainer);\n\t\t\t}\n\t\t}\n\n\t\treturn new UnknownHitTestResult();\n\t}\n\n\t/**\n\t * Most probably Gecko\n\t */\n\tprivate static _doHitTestWithCaretPositionFromPoint(ctx: HitTestContext, coords: ClientCoordinates): HitTestResult {\n\t\tconst hitResult: { offsetNode: Node; offset: number; } = (document).caretPositionFromPoint(coords.clientX, coords.clientY);\n\n\t\tif (hitResult.offsetNode.nodeType === hitResult.offsetNode.TEXT_NODE) {\n\t\t\t// offsetNode is expected to be the token text\n\t\t\tconst parent1 = hitResult.offsetNode.parentNode; // expected to be the token span\n\t\t\tconst parent2 = parent1 ? parent1.parentNode : null; // expected to be the view line container span\n\t\t\tconst parent3 = parent2 ? parent2.parentNode : null; // expected to be the view line div\n\t\t\tconst parent3ClassName = parent3 && parent3.nodeType === parent3.ELEMENT_NODE ? (parent3).className : null;\n\n\t\t\tif (parent3ClassName === ViewLine.CLASS_NAME) {\n\t\t\t\treturn HitTestResult.createFromDOMInfo(ctx, hitResult.offsetNode.parentNode, hitResult.offset);\n\t\t\t} else {\n\t\t\t\treturn new UnknownHitTestResult(hitResult.offsetNode.parentNode);\n\t\t\t}\n\t\t}\n\n\t\t// For inline decorations, Gecko sometimes returns the `` of the line and the offset is the `` with the inline decoration\n\t\t// Some other times, it returns the `` with the inline decoration\n\t\tif (hitResult.offsetNode.nodeType === hitResult.offsetNode.ELEMENT_NODE) {\n\t\t\tconst parent1 = hitResult.offsetNode.parentNode;\n\t\t\tconst parent1ClassName = parent1 && parent1.nodeType === parent1.ELEMENT_NODE ? (parent1).className : null;\n\t\t\tconst parent2 = parent1 ? parent1.parentNode : null;\n\t\t\tconst parent2ClassName = parent2 && parent2.nodeType === parent2.ELEMENT_NODE ? (parent2).className : null;\n\n\t\t\tif (parent1ClassName === ViewLine.CLASS_NAME) {\n\t\t\t\t// it returned the `` of the line and the offset is the `` with the inline decoration\n\t\t\t\tconst tokenSpan = hitResult.offsetNode.childNodes[Math.min(hitResult.offset, hitResult.offsetNode.childNodes.length - 1)];\n\t\t\t\tif (tokenSpan) {\n\t\t\t\t\treturn HitTestResult.createFromDOMInfo(ctx, tokenSpan, 0);\n\t\t\t\t}\n\t\t\t} else if (parent2ClassName === ViewLine.CLASS_NAME) {\n\t\t\t\t// it returned the `` with the inline decoration\n\t\t\t\treturn HitTestResult.createFromDOMInfo(ctx, hitResult.offsetNode, 0);\n\t\t\t}\n\t\t}\n\n\t\treturn new UnknownHitTestResult(hitResult.offsetNode);\n\t}\n\n\tprivate static _snapToSoftTabBoundary(position: Position, viewModel: IViewModel): Position {\n\t\tconst lineContent = viewModel.getLineContent(position.lineNumber);\n\t\tconst { tabSize } = viewModel.getTextModelOptions();\n\t\tconst newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - 1, tabSize, Direction.Nearest);\n\t\tif (newPosition !== -1) {\n\t\t\treturn new Position(position.lineNumber, newPosition + 1);\n\t\t}\n\t\treturn position;\n\t}\n\n\tprivate static _doHitTest(ctx: HitTestContext, request: BareHitTestRequest): HitTestResult {\n\n\t\tlet result: HitTestResult = new UnknownHitTestResult();\n\t\tif (typeof (document).caretRangeFromPoint === 'function') {\n\t\t\tresult = this._doHitTestWithCaretRangeFromPoint(ctx, request);\n\t\t} else if ((document).caretPositionFromPoint) {\n\t\t\tresult = this._doHitTestWithCaretPositionFromPoint(ctx, request.pos.toClientCoordinates());\n\t\t}\n\t\tif (result.type === HitTestResultType.Content) {\n\t\t\tconst injectedText = ctx.model.getInjectedTextAt(result.position);\n\n\t\t\tconst normalizedPosition = ctx.model.normalizePosition(result.position, PositionAffinity.None);\n\t\t\tif (injectedText || !normalizedPosition.equals(result.position)) {\n\t\t\t\tresult = new ContentHitTestResult(normalizedPosition, result.spanNode, injectedText);\n\t\t\t}\n\t\t}\n\t\t// Snap to the nearest soft tab boundary if atomic soft tabs are enabled.\n\t\tif (result.type === HitTestResultType.Content && ctx.stickyTabStops) {\n\t\t\tresult = new ContentHitTestResult(this._snapToSoftTabBoundary(result.position, ctx.model), result.spanNode, result.injectedText);\n\t\t}\n\t\treturn result;\n\t}\n}\n\nexport function shadowCaretRangeFromPoint(shadowRoot: ShadowRoot, x: number, y: number): Range {\n\tconst range = document.createRange();\n\n\t// Get the element under the point\n\tlet el: Element | null = (shadowRoot).elementFromPoint(x, y);\n\n\tif (el !== null) {\n\t\t// Get the last child of the element until its firstChild is a text node\n\t\t// This assumes that the pointer is on the right of the line, out of the tokens\n\t\t// and that we want to get the offset of the last token of the line\n\t\twhile (el && el.firstChild && el.firstChild.nodeType !== el.firstChild.TEXT_NODE && el.lastChild && el.lastChild.firstChild) {\n\t\t\tel = el.lastChild;\n\t\t}\n\n\t\t// Grab its rect\n\t\tconst rect = el.getBoundingClientRect();\n\n\t\t// And its font\n\t\tconst font = window.getComputedStyle(el, null).getPropertyValue('font');\n\n\t\t// And also its txt content\n\t\tconst text = (el as any).innerText;\n\n\t\t// Position the pixel cursor at the left of the element\n\t\tlet pixelCursor = rect.left;\n\t\tlet offset = 0;\n\t\tlet step: number;\n\n\t\t// If the point is on the right of the box put the cursor after the last character\n\t\tif (x > rect.left + rect.width) {\n\t\t\toffset = text.length;\n\t\t} else {\n\t\t\tconst charWidthReader = CharWidthReader.getInstance();\n\t\t\t// Goes through all the characters of the innerText, and checks if the x of the point\n\t\t\t// belongs to the character.\n\t\t\tfor (let i = 0; i < text.length + 1; i++) {\n\t\t\t\t// The step is half the width of the character\n\t\t\t\tstep = charWidthReader.getCharWidth(text.charAt(i), font) / 2;\n\t\t\t\t// Move to the center of the character\n\t\t\t\tpixelCursor += step;\n\t\t\t\t// If the x of the point is smaller that the position of the cursor, the point is over that character\n\t\t\t\tif (x < pixelCursor) {\n\t\t\t\t\toffset = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// Move between the current character and the next\n\t\t\t\tpixelCursor += step;\n\t\t\t}\n\t\t}\n\n\t\t// Creates a range with the text node of the element and set the offset found\n\t\trange.setStart(el.firstChild!, offset);\n\t\trange.setEnd(el.firstChild!, offset);\n\t}\n\n\treturn range;\n}\n\nclass CharWidthReader {\n\tprivate static _INSTANCE: CharWidthReader | null = null;\n\n\tpublic static getInstance(): CharWidthReader {\n\t\tif (!CharWidthReader._INSTANCE) {\n\t\t\tCharWidthReader._INSTANCE = new CharWidthReader();\n\t\t}\n\t\treturn CharWidthReader._INSTANCE;\n\t}\n\n\tprivate readonly _cache: { [cacheKey: string]: number; };\n\tprivate readonly _canvas: HTMLCanvasElement;\n\n\tprivate constructor() {\n\t\tthis._cache = {};\n\t\tthis._canvas = document.createElement('canvas');\n\t}\n\n\tpublic getCharWidth(char: string, font: string): number {\n\t\tconst cacheKey = char + font;\n\t\tif (this._cache[cacheKey]) {\n\t\t\treturn this._cache[cacheKey];\n\t\t}\n\n\t\tconst context = this._canvas.getContext('2d')!;\n\t\tcontext.font = font;\n\t\tconst metrics = context.measureText(char);\n\t\tconst width = metrics.width;\n\t\tthis._cache[cacheKey] = width;\n\t\treturn width;\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport { StandardWheelEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent';\nimport { TimeoutTimer } from 'vs/base/common/async';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport * as platform from 'vs/base/common/platform';\nimport { HitTestContext, MouseTarget, MouseTargetFactory, PointerHandlerLastRenderData } from 'vs/editor/browser/controller/mouseTarget';\nimport { IMouseTarget, IMouseTargetViewZoneData, MouseTargetType } from 'vs/editor/browser/editorBrowser';\nimport { ClientCoordinates, EditorMouseEvent, EditorMouseEventFactory, GlobalEditorMouseMoveMonitor, createEditorPagePosition, createCoordinatesRelativeToEditor } from 'vs/editor/browser/editorDom';\nimport { ViewController } from 'vs/editor/browser/view/viewController';\nimport { EditorZoom } from 'vs/editor/common/config/editorZoom';\nimport { Position } from 'vs/editor/common/core/position';\nimport { Selection } from 'vs/editor/common/core/selection';\nimport { HorizontalPosition } from 'vs/editor/browser/view/renderingContext';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport * as viewEvents from 'vs/editor/common/viewModel/viewEvents';\nimport { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';\nimport { EditorOption } from 'vs/editor/common/config/editorOptions';\n\n/**\n * Merges mouse events when mouse move events are throttled\n */\nexport function createMouseMoveEventMerger(mouseTargetFactory: MouseTargetFactory | null) {\n\treturn function (lastEvent: EditorMouseEvent | null, currentEvent: EditorMouseEvent): EditorMouseEvent {\n\t\tlet targetIsWidget = false;\n\t\tif (mouseTargetFactory) {\n\t\t\ttargetIsWidget = mouseTargetFactory.mouseTargetIsWidget(currentEvent);\n\t\t}\n\t\tif (!targetIsWidget) {\n\t\t\tcurrentEvent.preventDefault();\n\t\t}\n\t\treturn currentEvent;\n\t};\n}\n\nexport interface IPointerHandlerHelper {\n\tviewDomNode: HTMLElement;\n\tlinesContentDomNode: HTMLElement;\n\n\tfocusTextArea(): void;\n\tdispatchTextAreaEvent(event: CustomEvent): void;\n\n\t/**\n\t * Get the last rendered information for cursors & textarea.\n\t */\n\tgetLastRenderData(): PointerHandlerLastRenderData;\n\n\tshouldSuppressMouseDownOnViewZone(viewZoneId: string): boolean;\n\tshouldSuppressMouseDownOnWidget(widgetId: string): boolean;\n\n\t/**\n\t * Decode a position from a rendered dom node\n\t */\n\tgetPositionFromDOMInfo(spanNode: HTMLElement, offset: number): Position | null;\n\n\tvisibleRangeForPosition(lineNumber: number, column: number): HorizontalPosition | null;\n\tgetLineWidth(lineNumber: number): number;\n}\n\nexport class MouseHandler extends ViewEventHandler {\n\n\tstatic readonly MOUSE_MOVE_MINIMUM_TIME = 100; // ms\n\n\tprotected _context: ViewContext;\n\tprotected viewController: ViewController;\n\tprotected viewHelper: IPointerHandlerHelper;\n\tprotected mouseTargetFactory: MouseTargetFactory;\n\tprotected readonly _mouseDownOperation: MouseDownOperation;\n\tprivate lastMouseLeaveTime: number;\n\tprivate _height: number;\n\n\tconstructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {\n\t\tsuper();\n\n\t\tthis._context = context;\n\t\tthis.viewController = viewController;\n\t\tthis.viewHelper = viewHelper;\n\t\tthis.mouseTargetFactory = new MouseTargetFactory(this._context, viewHelper);\n\n\t\tthis._mouseDownOperation = this._register(new MouseDownOperation(\n\t\t\tthis._context,\n\t\t\tthis.viewController,\n\t\t\tthis.viewHelper,\n\t\t\t(e, testEventTarget) => this._createMouseTarget(e, testEventTarget),\n\t\t\t(e) => this._getMouseColumn(e)\n\t\t));\n\n\t\tthis.lastMouseLeaveTime = -1;\n\t\tthis._height = this._context.configuration.options.get(EditorOption.layoutInfo).height;\n\n\t\tconst mouseEvents = new EditorMouseEventFactory(this.viewHelper.viewDomNode);\n\n\t\tthis._register(mouseEvents.onContextMenu(this.viewHelper.viewDomNode, (e) => this._onContextMenu(e, true)));\n\n\t\tthis._register(mouseEvents.onMouseMoveThrottled(this.viewHelper.viewDomNode,\n\t\t\t(e) => this._onMouseMove(e),\n\t\t\tcreateMouseMoveEventMerger(this.mouseTargetFactory), MouseHandler.MOUSE_MOVE_MINIMUM_TIME));\n\n\t\tthis._register(mouseEvents.onMouseUp(this.viewHelper.viewDomNode, (e) => this._onMouseUp(e)));\n\n\t\tthis._register(mouseEvents.onMouseLeave(this.viewHelper.viewDomNode, (e) => this._onMouseLeave(e)));\n\n\t\tthis._register(mouseEvents.onMouseDown(this.viewHelper.viewDomNode, (e) => this._onMouseDown(e)));\n\n\t\tconst onMouseWheel = (browserEvent: IMouseWheelEvent) => {\n\t\t\tthis.viewController.emitMouseWheel(browserEvent);\n\n\t\t\tif (!this._context.configuration.options.get(EditorOption.mouseWheelZoom)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst e = new StandardWheelEvent(browserEvent);\n\t\t\tconst doMouseWheelZoom = (\n\t\t\t\tplatform.isMacintosh\n\t\t\t\t\t// on macOS we support cmd + two fingers scroll (`metaKey` set)\n\t\t\t\t\t// and also the two fingers pinch gesture (`ctrKey` set)\n\t\t\t\t\t? ((browserEvent.metaKey || browserEvent.ctrlKey) && !browserEvent.shiftKey && !browserEvent.altKey)\n\t\t\t\t\t: (browserEvent.ctrlKey && !browserEvent.metaKey && !browserEvent.shiftKey && !browserEvent.altKey)\n\t\t\t);\n\t\t\tif (doMouseWheelZoom) {\n\t\t\t\tconst zoomLevel: number = EditorZoom.getZoomLevel();\n\t\t\t\tconst delta = e.deltaY > 0 ? 1 : -1;\n\t\t\t\tEditorZoom.setZoomLevel(zoomLevel + delta);\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t}\n\t\t};\n\t\tthis._register(dom.addDisposableListener(this.viewHelper.viewDomNode, dom.EventType.MOUSE_WHEEL, onMouseWheel, { capture: true, passive: false }));\n\n\t\tthis._context.addEventHandler(this);\n\t}\n\n\tpublic override dispose(): void {\n\t\tthis._context.removeEventHandler(this);\n\t\tsuper.dispose();\n\t}\n\n\t// --- begin event handlers\n\tpublic override onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {\n\t\tif (e.hasChanged(EditorOption.layoutInfo)) {\n\t\t\t// layout change\n\t\t\tconst height = this._context.configuration.options.get(EditorOption.layoutInfo).height;\n\t\t\tif (this._height !== height) {\n\t\t\t\tthis._height = height;\n\t\t\t\tthis._mouseDownOperation.onHeightChanged();\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\tpublic override onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean {\n\t\tthis._mouseDownOperation.onCursorStateChanged(e);\n\t\treturn false;\n\t}\n\tpublic override onFocusChanged(e: viewEvents.ViewFocusChangedEvent): boolean {\n\t\treturn false;\n\t}\n\tpublic override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {\n\t\tthis._mouseDownOperation.onScrollChanged();\n\t\treturn false;\n\t}\n\t// --- end event handlers\n\n\tpublic getTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget | null {\n\t\tconst clientPos = new ClientCoordinates(clientX, clientY);\n\t\tconst pos = clientPos.toPageCoordinates();\n\t\tconst editorPos = createEditorPagePosition(this.viewHelper.viewDomNode);\n\n\t\tif (pos.y < editorPos.y || pos.y > editorPos.y + editorPos.height || pos.x < editorPos.x || pos.x > editorPos.x + editorPos.width) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst relativePos = createCoordinatesRelativeToEditor(this.viewHelper.viewDomNode, editorPos, pos);\n\t\treturn this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), editorPos, pos, relativePos, null);\n\t}\n\n\tprotected _createMouseTarget(e: EditorMouseEvent, testEventTarget: boolean): IMouseTarget {\n\t\tlet target = e.target;\n\t\tif (!this.viewHelper.viewDomNode.contains(target)) {\n\t\t\tconst shadowRoot = dom.getShadowRoot(this.viewHelper.viewDomNode);\n\t\t\tif (shadowRoot) {\n\t\t\t\ttarget = (shadowRoot).elementsFromPoint(e.posx, e.posy).find(\n\t\t\t\t\t(el: Element) => this.viewHelper.viewDomNode.contains(el)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), e.editorPos, e.pos, e.relativePos, testEventTarget ? target : null);\n\t}\n\n\tprivate _getMouseColumn(e: EditorMouseEvent): number {\n\t\treturn this.mouseTargetFactory.getMouseColumn(e.relativePos);\n\t}\n\n\tprotected _onContextMenu(e: EditorMouseEvent, testEventTarget: boolean): void {\n\t\tthis.viewController.emitContextMenu({\n\t\t\tevent: e,\n\t\t\ttarget: this._createMouseTarget(e, testEventTarget)\n\t\t});\n\t}\n\n\tpublic _onMouseMove(e: EditorMouseEvent): void {\n\t\tif (this._mouseDownOperation.isActive()) {\n\t\t\t// In selection/drag operation\n\t\t\treturn;\n\t\t}\n\t\tconst actualMouseMoveTime = e.timestamp;\n\t\tif (actualMouseMoveTime < this.lastMouseLeaveTime) {\n\t\t\t// Due to throttling, this event occurred before the mouse left the editor, therefore ignore it.\n\t\t\treturn;\n\t\t}\n\n\t\tthis.viewController.emitMouseMove({\n\t\t\tevent: e,\n\t\t\ttarget: this._createMouseTarget(e, true)\n\t\t});\n\t}\n\n\tpublic _onMouseLeave(e: EditorMouseEvent): void {\n\t\tthis.lastMouseLeaveTime = (new Date()).getTime();\n\t\tthis.viewController.emitMouseLeave({\n\t\t\tevent: e,\n\t\t\ttarget: null\n\t\t});\n\t}\n\n\tpublic _onMouseUp(e: EditorMouseEvent): void {\n\t\tthis.viewController.emitMouseUp({\n\t\t\tevent: e,\n\t\t\ttarget: this._createMouseTarget(e, true)\n\t\t});\n\t}\n\n\tpublic _onMouseDown(e: EditorMouseEvent): void {\n\t\tconst t = this._createMouseTarget(e, true);\n\n\t\tconst targetIsContent = (t.type === MouseTargetType.CONTENT_TEXT || t.type === MouseTargetType.CONTENT_EMPTY);\n\t\tconst targetIsGutter = (t.type === MouseTargetType.GUTTER_GLYPH_MARGIN || t.type === MouseTargetType.GUTTER_LINE_NUMBERS || t.type === MouseTargetType.GUTTER_LINE_DECORATIONS);\n\t\tconst targetIsLineNumbers = (t.type === MouseTargetType.GUTTER_LINE_NUMBERS);\n\t\tconst selectOnLineNumbers = this._context.configuration.options.get(EditorOption.selectOnLineNumbers);\n\t\tconst targetIsViewZone = (t.type === MouseTargetType.CONTENT_VIEW_ZONE || t.type === MouseTargetType.GUTTER_VIEW_ZONE);\n\t\tconst targetIsWidget = (t.type === MouseTargetType.CONTENT_WIDGET);\n\n\t\tlet shouldHandle = e.leftButton || e.middleButton;\n\t\tif (platform.isMacintosh && e.leftButton && e.ctrlKey) {\n\t\t\tshouldHandle = false;\n\t\t}\n\n\t\tconst focus = () => {\n\t\t\te.preventDefault();\n\t\t\tthis.viewHelper.focusTextArea();\n\t\t};\n\n\t\tif (shouldHandle && (targetIsContent || (targetIsLineNumbers && selectOnLineNumbers))) {\n\t\t\tfocus();\n\t\t\tthis._mouseDownOperation.start(t.type, e);\n\n\t\t} else if (targetIsGutter) {\n\t\t\t// Do not steal focus\n\t\t\te.preventDefault();\n\t\t} else if (targetIsViewZone) {\n\t\t\tconst viewZoneData = t.detail;\n\t\t\tif (this.viewHelper.shouldSuppressMouseDownOnViewZone(viewZoneData.viewZoneId)) {\n\t\t\t\tfocus();\n\t\t\t\tthis._mouseDownOperation.start(t.type, e);\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t} else if (targetIsWidget && this.viewHelper.shouldSuppressMouseDownOnWidget(t.detail)) {\n\t\t\tfocus();\n\t\t\te.preventDefault();\n\t\t}\n\n\t\tthis.viewController.emitMouseDown({\n\t\t\tevent: e,\n\t\t\ttarget: t\n\t\t});\n\t}\n}\n\nclass MouseDownOperation extends Disposable {\n\n\tprivate readonly _context: ViewContext;\n\tprivate readonly _viewController: ViewController;\n\tprivate readonly _viewHelper: IPointerHandlerHelper;\n\tprivate readonly _createMouseTarget: (e: EditorMouseEvent, testEventTarget: boolean) => IMouseTarget;\n\tprivate readonly _getMouseColumn: (e: EditorMouseEvent) => number;\n\n\tprivate readonly _mouseMoveMonitor: GlobalEditorMouseMoveMonitor;\n\tprivate readonly _onScrollTimeout: TimeoutTimer;\n\tprivate readonly _mouseState: MouseDownState;\n\n\tprivate _currentSelection: Selection;\n\tprivate _isActive: boolean;\n\tprivate _lastMouseEvent: EditorMouseEvent | null;\n\n\tconstructor(\n\t\tcontext: ViewContext,\n\t\tviewController: ViewController,\n\t\tviewHelper: IPointerHandlerHelper,\n\t\tcreateMouseTarget: (e: EditorMouseEvent, testEventTarget: boolean) => IMouseTarget,\n\t\tgetMouseColumn: (e: EditorMouseEvent) => number\n\t) {\n\t\tsuper();\n\t\tthis._context = context;\n\t\tthis._viewController = viewController;\n\t\tthis._viewHelper = viewHelper;\n\t\tthis._createMouseTarget = createMouseTarget;\n\t\tthis._getMouseColumn = getMouseColumn;\n\n\t\tthis._mouseMoveMonitor = this._register(new GlobalEditorMouseMoveMonitor(this._viewHelper.viewDomNode));\n\t\tthis._onScrollTimeout = this._register(new TimeoutTimer());\n\t\tthis._mouseState = new MouseDownState();\n\n\t\tthis._currentSelection = new Selection(1, 1, 1, 1);\n\t\tthis._isActive = false;\n\t\tthis._lastMouseEvent = null;\n\t}\n\n\tpublic override dispose(): void {\n\t\tsuper.dispose();\n\t}\n\n\tpublic isActive(): boolean {\n\t\treturn this._isActive;\n\t}\n\n\tprivate _onMouseDownThenMove(e: EditorMouseEvent): void {\n\t\tthis._lastMouseEvent = e;\n\t\tthis._mouseState.setModifiers(e);\n\n\t\tconst position = this._findMousePosition(e, true);\n\t\tif (!position) {\n\t\t\t// Ignoring because position is unknown\n\t\t\treturn;\n\t\t}\n\n\t\tif (this._mouseState.isDragAndDrop) {\n\t\t\tthis._viewController.emitMouseDrag({\n\t\t\t\tevent: e,\n\t\t\t\ttarget: position\n\t\t\t});\n\t\t} else {\n\t\t\tthis._dispatchMouse(position, true);\n\t\t}\n\t}\n\n\tpublic start(targetType: MouseTargetType, e: EditorMouseEvent): void {\n\t\tthis._lastMouseEvent = e;\n\n\t\tthis._mouseState.setStartedOnLineNumbers(targetType === MouseTargetType.GUTTER_LINE_NUMBERS);\n\t\tthis._mouseState.setStartButtons(e);\n\t\tthis._mouseState.setModifiers(e);\n\t\tconst position = this._findMousePosition(e, true);\n\t\tif (!position || !position.position) {\n\t\t\t// Ignoring because position is unknown\n\t\t\treturn;\n\t\t}\n\n\t\tthis._mouseState.trySetCount(e.detail, position.position);\n\n\t\t// Overwrite the detail of the MouseEvent, as it will be sent out in an event and contributions might rely on it.\n\t\te.detail = this._mouseState.count;\n\n\t\tconst options = this._context.configuration.options;\n\n\t\tif (!options.get(EditorOption.readOnly)\n\t\t\t&& options.get(EditorOption.dragAndDrop)\n\t\t\t&& !options.get(EditorOption.columnSelection)\n\t\t\t&& !this._mouseState.altKey // we don't support multiple mouse\n\t\t\t&& e.detail < 2 // only single click on a selection can work\n\t\t\t&& !this._isActive // the mouse is not down yet\n\t\t\t&& !this._currentSelection.isEmpty() // we don't drag single cursor\n\t\t\t&& (position.type === MouseTargetType.CONTENT_TEXT) // single click on text\n\t\t\t&& position.position && this._currentSelection.containsPosition(position.position) // single click on a selection\n\t\t) {\n\t\t\tthis._mouseState.isDragAndDrop = true;\n\t\t\tthis._isActive = true;\n\n\t\t\tthis._mouseMoveMonitor.startMonitoring(\n\t\t\t\te.target,\n\t\t\t\te.buttons,\n\t\t\t\tcreateMouseMoveEventMerger(null),\n\t\t\t\t(e) => this._onMouseDownThenMove(e),\n\t\t\t\t(browserEvent?: MouseEvent | KeyboardEvent) => {\n\t\t\t\t\tconst position = this._findMousePosition(this._lastMouseEvent!, true);\n\n\t\t\t\t\tif (browserEvent && browserEvent instanceof KeyboardEvent) {\n\t\t\t\t\t\t// cancel\n\t\t\t\t\t\tthis._viewController.emitMouseDropCanceled();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._viewController.emitMouseDrop({\n\t\t\t\t\t\t\tevent: this._lastMouseEvent!,\n\t\t\t\t\t\t\ttarget: (position ? this._createMouseTarget(this._lastMouseEvent!, true) : null) // Ignoring because position is unknown, e.g., Content View Zone\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._stop();\n\t\t\t\t}\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\tthis._mouseState.isDragAndDrop = false;\n\t\tthis._dispatchMouse(position, e.shiftKey);\n\n\t\tif (!this._isActive) {\n\t\t\tthis._isActive = true;\n\t\t\tthis._mouseMoveMonitor.startMonitoring(\n\t\t\t\te.target,\n\t\t\t\te.buttons,\n\t\t\t\tcreateMouseMoveEventMerger(null),\n\t\t\t\t(e) => this._onMouseDownThenMove(e),\n\t\t\t\t() => this._stop()\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate _stop(): void {\n\t\tthis._isActive = false;\n\t\tthis._onScrollTimeout.cancel();\n\t}\n\n\tpublic onHeightChanged(): void {\n\t\tthis._mouseMoveMonitor.stopMonitoring();\n\t}\n\n\tpublic onScrollChanged(): void {\n\t\tif (!this._isActive) {\n\t\t\treturn;\n\t\t}\n\t\tthis._onScrollTimeout.setIfNotSet(() => {\n\t\t\tif (!this._lastMouseEvent) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst position = this._findMousePosition(this._lastMouseEvent, false);\n\t\t\tif (!position) {\n\t\t\t\t// Ignoring because position is unknown\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this._mouseState.isDragAndDrop) {\n\t\t\t\t// Ignoring because users are dragging the text\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._dispatchMouse(position, true);\n\t\t}, 10);\n\t}\n\n\tpublic onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): void {\n\t\tthis._currentSelection = e.selections[0];\n\t}\n\n\tprivate _getPositionOutsideEditor(e: EditorMouseEvent): IMouseTarget | null {\n\t\tconst editorContent = e.editorPos;\n\t\tconst model = this._context.model;\n\t\tconst viewLayout = this._context.viewLayout;\n\n\t\tconst mouseColumn = this._getMouseColumn(e);\n\n\t\tif (e.posy < editorContent.y) {\n\t\t\tconst verticalOffset = Math.max(viewLayout.getCurrentScrollTop() - (editorContent.y - e.posy), 0);\n\t\t\tconst viewZoneData = HitTestContext.getZoneAtCoord(this._context, verticalOffset);\n\t\t\tif (viewZoneData) {\n\t\t\t\tconst newPosition = this._helpPositionJumpOverViewZone(viewZoneData);\n\t\t\t\tif (newPosition) {\n\t\t\t\t\treturn MouseTarget.createOutsideEditor(mouseColumn, newPosition);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst aboveLineNumber = viewLayout.getLineNumberAtVerticalOffset(verticalOffset);\n\t\t\treturn MouseTarget.createOutsideEditor(mouseColumn, new Position(aboveLineNumber, 1));\n\t\t}\n\n\t\tif (e.posy > editorContent.y + editorContent.height) {\n\t\t\tconst verticalOffset = viewLayout.getCurrentScrollTop() + e.relativePos.y;\n\t\t\tconst viewZoneData = HitTestContext.getZoneAtCoord(this._context, verticalOffset);\n\t\t\tif (viewZoneData) {\n\t\t\t\tconst newPosition = this._helpPositionJumpOverViewZone(viewZoneData);\n\t\t\t\tif (newPosition) {\n\t\t\t\t\treturn MouseTarget.createOutsideEditor(mouseColumn, newPosition);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst belowLineNumber = viewLayout.getLineNumberAtVerticalOffset(verticalOffset);\n\t\t\treturn MouseTarget.createOutsideEditor(mouseColumn, new Position(belowLineNumber, model.getLineMaxColumn(belowLineNumber)));\n\t\t}\n\n\t\tconst possibleLineNumber = viewLayout.getLineNumberAtVerticalOffset(viewLayout.getCurrentScrollTop() + e.relativePos.y);\n\n\t\tif (e.posx < editorContent.x) {\n\t\t\treturn MouseTarget.createOutsideEditor(mouseColumn, new Position(possibleLineNumber, 1));\n\t\t}\n\n\t\tif (e.posx > editorContent.x + editorContent.width) {\n\t\t\treturn MouseTarget.createOutsideEditor(mouseColumn, new Position(possibleLineNumber, model.getLineMaxColumn(possibleLineNumber)));\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate _findMousePosition(e: EditorMouseEvent, testEventTarget: boolean): IMouseTarget | null {\n\t\tconst positionOutsideEditor = this._getPositionOutsideEditor(e);\n\t\tif (positionOutsideEditor) {\n\t\t\treturn positionOutsideEditor;\n\t\t}\n\n\t\tconst t = this._createMouseTarget(e, testEventTarget);\n\t\tconst hintedPosition = t.position;\n\t\tif (!hintedPosition) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (t.type === MouseTargetType.CONTENT_VIEW_ZONE || t.type === MouseTargetType.GUTTER_VIEW_ZONE) {\n\t\t\tconst newPosition = this._helpPositionJumpOverViewZone(t.detail);\n\t\t\tif (newPosition) {\n\t\t\t\treturn MouseTarget.createViewZone(t.type, t.element, t.mouseColumn, newPosition, t.detail);\n\t\t\t}\n\t\t}\n\n\t\treturn t;\n\t}\n\n\tprivate _helpPositionJumpOverViewZone(viewZoneData: IMouseTargetViewZoneData): Position | null {\n\t\t// Force position on view zones to go above or below depending on where selection started from\n\t\tconst selectionStart = new Position(this._currentSelection.selectionStartLineNumber, this._currentSelection.selectionStartColumn);\n\t\tconst positionBefore = viewZoneData.positionBefore;\n\t\tconst positionAfter = viewZoneData.positionAfter;\n\n\t\tif (positionBefore && positionAfter) {\n\t\t\tif (positionBefore.isBefore(selectionStart)) {\n\t\t\t\treturn positionBefore;\n\t\t\t} else {\n\t\t\t\treturn positionAfter;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate _dispatchMouse(position: IMouseTarget, inSelectionMode: boolean): void {\n\t\tif (!position.position) {\n\t\t\treturn;\n\t\t}\n\t\tthis._viewController.dispatchMouse({\n\t\t\tposition: position.position,\n\t\t\tmouseColumn: position.mouseColumn,\n\t\t\tstartedOnLineNumbers: this._mouseState.startedOnLineNumbers,\n\n\t\t\tinSelectionMode: inSelectionMode,\n\t\t\tmouseDownCount: this._mouseState.count,\n\t\t\taltKey: this._mouseState.altKey,\n\t\t\tctrlKey: this._mouseState.ctrlKey,\n\t\t\tmetaKey: this._mouseState.metaKey,\n\t\t\tshiftKey: this._mouseState.shiftKey,\n\n\t\t\tleftButton: this._mouseState.leftButton,\n\t\t\tmiddleButton: this._mouseState.middleButton,\n\t\t});\n\t}\n}\n\nclass MouseDownState {\n\n\tprivate static readonly CLEAR_MOUSE_DOWN_COUNT_TIME = 400; // ms\n\n\tprivate _altKey: boolean;\n\tpublic get altKey(): boolean { return this._altKey; }\n\n\tprivate _ctrlKey: boolean;\n\tpublic get ctrlKey(): boolean { return this._ctrlKey; }\n\n\tprivate _metaKey: boolean;\n\tpublic get metaKey(): boolean { return this._metaKey; }\n\n\tprivate _shiftKey: boolean;\n\tpublic get shiftKey(): boolean { return this._shiftKey; }\n\n\tprivate _leftButton: boolean;\n\tpublic get leftButton(): boolean { return this._leftButton; }\n\n\tprivate _middleButton: boolean;\n\tpublic get middleButton(): boolean { return this._middleButton; }\n\n\tprivate _startedOnLineNumbers: boolean;\n\tpublic get startedOnLineNumbers(): boolean { return this._startedOnLineNumbers; }\n\n\tprivate _lastMouseDownPosition: Position | null;\n\tprivate _lastMouseDownPositionEqualCount: number;\n\tprivate _lastMouseDownCount: number;\n\tprivate _lastSetMouseDownCountTime: number;\n\tpublic isDragAndDrop: boolean;\n\n\tconstructor() {\n\t\tthis._altKey = false;\n\t\tthis._ctrlKey = false;\n\t\tthis._metaKey = false;\n\t\tthis._shiftKey = false;\n\t\tthis._leftButton = false;\n\t\tthis._middleButton = false;\n\t\tthis._startedOnLineNumbers = false;\n\t\tthis._lastMouseDownPosition = null;\n\t\tthis._lastMouseDownPositionEqualCount = 0;\n\t\tthis._lastMouseDownCount = 0;\n\t\tthis._lastSetMouseDownCountTime = 0;\n\t\tthis.isDragAndDrop = false;\n\t}\n\n\tpublic get count(): number {\n\t\treturn this._lastMouseDownCount;\n\t}\n\n\tpublic setModifiers(source: EditorMouseEvent) {\n\t\tthis._altKey = source.altKey;\n\t\tthis._ctrlKey = source.ctrlKey;\n\t\tthis._metaKey = source.metaKey;\n\t\tthis._shiftKey = source.shiftKey;\n\t}\n\n\tpublic setStartButtons(source: EditorMouseEvent) {\n\t\tthis._leftButton = source.leftButton;\n\t\tthis._middleButton = source.middleButton;\n\t}\n\n\tpublic setStartedOnLineNumbers(startedOnLineNumbers: boolean): void {\n\t\tthis._startedOnLineNumbers = startedOnLineNumbers;\n\t}\n\n\tpublic trySetCount(setMouseDownCount: number, newMouseDownPosition: Position): void {\n\t\t// a. Invalidate multiple clicking if too much time has passed (will be hit by IE because the detail field of mouse events contains garbage in IE10)\n\t\tconst currentTime = (new Date()).getTime();\n\t\tif (currentTime - this._lastSetMouseDownCountTime > MouseDownState.CLEAR_MOUSE_DOWN_COUNT_TIME) {\n\t\t\tsetMouseDownCount = 1;\n\t\t}\n\t\tthis._lastSetMouseDownCountTime = currentTime;\n\n\t\t// b. Ensure that we don't jump from single click to triple click in one go (will be hit by IE because the detail field of mouse events contains garbage in IE10)\n\t\tif (setMouseDownCount > this._lastMouseDownCount + 1) {\n\t\t\tsetMouseDownCount = this._lastMouseDownCount + 1;\n\t\t}\n\n\t\t// c. Invalidate multiple clicking if the logical position is different\n\t\tif (this._lastMouseDownPosition && this._lastMouseDownPosition.equals(newMouseDownPosition)) {\n\t\t\tthis._lastMouseDownPositionEqualCount++;\n\t\t} else {\n\t\t\tthis._lastMouseDownPositionEqualCount = 1;\n\t\t}\n\t\tthis._lastMouseDownPosition = newMouseDownPosition;\n\n\t\t// Finally set the lastMouseDownCount\n\t\tthis._lastMouseDownCount = Math.min(setMouseDownCount, this._lastMouseDownPositionEqualCount);\n\t}\n\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport * as dom from 'vs/base/browser/dom';\nimport * as platform from 'vs/base/common/platform';\nimport { EventType, Gesture, GestureEvent } from 'vs/base/browser/touch';\nimport { Disposable } from 'vs/base/common/lifecycle';\nimport { IPointerHandlerHelper, MouseHandler, createMouseMoveEventMerger } from 'vs/editor/browser/controller/mouseHandler';\nimport { IMouseTarget } from 'vs/editor/browser/editorBrowser';\nimport { EditorMouseEvent, EditorPointerEventFactory } from 'vs/editor/browser/editorDom';\nimport { ViewController } from 'vs/editor/browser/view/viewController';\nimport { ViewContext } from 'vs/editor/common/viewModel/viewContext';\nimport { BrowserFeatures } from 'vs/base/browser/canIUse';\nimport { TextAreaSyntethicEvents } from 'vs/editor/browser/controller/textAreaInput';\n\n/**\n * Currently only tested on iOS 13/ iPadOS.\n */\nexport class PointerEventHandler extends MouseHandler {\n\tprivate _lastPointerType: string;\n\tconstructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {\n\t\tsuper(context, viewController, viewHelper);\n\n\t\tthis._register(Gesture.addTarget(this.viewHelper.linesContentDomNode));\n\t\tthis._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Tap, (e) => this.onTap(e)));\n\t\tthis._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Change, (e) => this.onChange(e)));\n\t\tthis._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Contextmenu, (e: MouseEvent) => this._onContextMenu(new EditorMouseEvent(e, this.viewHelper.viewDomNode), false)));\n\n\t\tthis._lastPointerType = 'mouse';\n\n\t\tthis._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, 'pointerdown', (e: any) => {\n\t\t\tconst pointerType = e.pointerType;\n\t\t\tif (pointerType === 'mouse') {\n\t\t\t\tthis._lastPointerType = 'mouse';\n\t\t\t\treturn;\n\t\t\t} else if (pointerType === 'touch') {\n\t\t\t\tthis._lastPointerType = 'touch';\n\t\t\t} else {\n\t\t\t\tthis._lastPointerType = 'pen';\n\t\t\t}\n\t\t}));\n\n\t\t// PonterEvents\n\t\tconst pointerEvents = new EditorPointerEventFactory(this.viewHelper.viewDomNode);\n\n\t\tthis._register(pointerEvents.onPointerMoveThrottled(this.viewHelper.viewDomNode,\n\t\t\t(e) => this._onMouseMove(e),\n\t\t\tcreateMouseMoveEventMerger(this.mouseTargetFactory), MouseHandler.MOUSE_MOVE_MINIMUM_TIME));\n\t\tthis._register(pointerEvents.onPointerUp(this.viewHelper.viewDomNode, (e) => this._onMouseUp(e)));\n\t\tthis._register(pointerEvents.onPointerLeave(this.viewHelper.viewDomNode, (e) => this._onMouseLeave(e)));\n\t\tthis._register(pointerEvents.onPointerDown(this.viewHelper.viewDomNode, (e) => this._onMouseDown(e)));\n\t}\n\n\tprivate onTap(event: GestureEvent): void {\n\t\tif (!event.initialTarget || !this.viewHelper.linesContentDomNode.contains(event.initialTarget)) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\t\tthis.viewHelper.focusTextArea();\n\t\tconst target = this._createMouseTarget(new EditorMouseEvent(event, this.viewHelper.viewDomNode), false);\n\n\t\tif (target.position) {\n\t\t\t// this.viewController.moveTo(target.position);\n\t\t\tthis.viewController.dispatchMouse({\n\t\t\t\tposition: target.position,\n\t\t\t\tmouseColumn: target.position.column,\n\t\t\t\tstartedOnLineNumbers: false,\n\t\t\t\tmouseDownCount: event.tapCount,\n\t\t\t\tinSelectionMode: false,\n\t\t\t\taltKey: false,\n\t\t\t\tctrlKey: false,\n\t\t\t\tmetaKey: false,\n\t\t\t\tshiftKey: false,\n\n\t\t\t\tleftButton: false,\n\t\t\t\tmiddleButton: false,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate onChange(e: GestureEvent): void {\n\t\tif (this._lastPointerType === 'touch') {\n\t\t\tthis._context.model.deltaScrollNow(-e.translationX, -e.translationY);\n\t\t}\n\t}\n\n\tpublic override _onMouseDown(e: EditorMouseEvent): void {\n\t\tif ((e.browserEvent as any).pointerType === 'touch') {\n\t\t\treturn;\n\t\t}\n\n\t\tsuper._onMouseDown(e);\n\t}\n}\n\nclass TouchHandler extends MouseHandler {\n\n\tconstructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {\n\t\tsuper(context, viewController, viewHelper);\n\n\t\tthis._register(Gesture.addTarget(this.viewHelper.linesContentDomNode));\n\n\t\tthis._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Tap, (e) => this.onTap(e)));\n\t\tthis._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Change, (e) => this.onChange(e)));\n\t\tthis._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Contextmenu, (e: MouseEvent) => this._onContextMenu(new EditorMouseEvent(e, this.viewHelper.viewDomNode), false)));\n\t}\n\n\tprivate onTap(event: GestureEvent): void {\n\t\tevent.preventDefault();\n\n\t\tthis.viewHelper.focusTextArea();\n\n\t\tconst target = this._createMouseTarget(new EditorMouseEvent(event, this.viewHelper.viewDomNode), false);\n\n\t\tif (target.position) {\n\t\t\t// Send the tap event also to the