View File Name : 5807.f05d997ece5811bbc849.js.map
';\n const output = [];\n for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {\n const lineIndex = lineNumber - visibleStartLineNumber;\n const classNames = toRender[lineIndex];\n if (classNames.length === 0) {\n output[lineIndex] = '';\n }\n else {\n output[lineIndex] = ('
= this._renderResult.length) {\n return '';\n }\n return this._renderResult[lineIndex];\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 *--------------------------------------------------------------------------------------------*/\nimport './indentGuides.css';\nimport { DynamicViewOverlay } from '../../view/dynamicViewOverlay.js';\nimport { editorActiveIndentGuides, editorBracketHighlightingForeground1, editorBracketHighlightingForeground2, editorBracketHighlightingForeground3, editorBracketHighlightingForeground4, editorBracketHighlightingForeground5, editorBracketHighlightingForeground6, editorBracketPairGuideActiveBackground1, editorBracketPairGuideActiveBackground2, editorBracketPairGuideActiveBackground3, editorBracketPairGuideActiveBackground4, editorBracketPairGuideActiveBackground5, editorBracketPairGuideActiveBackground6, editorBracketPairGuideBackground1, editorBracketPairGuideBackground2, editorBracketPairGuideBackground3, editorBracketPairGuideBackground4, editorBracketPairGuideBackground5, editorBracketPairGuideBackground6, editorIndentGuides } from '../../../common/core/editorColorRegistry.js';\nimport { registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';\nimport { Position } from '../../../common/core/position.js';\nimport { ArrayQueue } from '../../../../base/common/arrays.js';\nimport { isDefined } from '../../../../base/common/types.js';\nimport { BracketPairGuidesClassNames } from '../../../common/model/guidesTextModelPart.js';\nimport { IndentGuide, HorizontalGuidesState } from '../../../common/textModelGuides.js';\nexport class IndentGuidesOverlay extends DynamicViewOverlay {\n constructor(context) {\n super();\n this._context = context;\n this._primaryPosition = null;\n const options = this._context.configuration.options;\n const wrappingInfo = options.get(134 /* EditorOption.wrappingInfo */);\n const fontInfo = options.get(46 /* EditorOption.fontInfo */);\n this._lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this._spaceWidth = fontInfo.spaceWidth;\n this._maxIndentLeft = wrappingInfo.wrappingColumn === -1 ? -1 : (wrappingInfo.wrappingColumn * fontInfo.typicalHalfwidthCharacterWidth);\n this._bracketPairGuideOptions = options.get(13 /* EditorOption.guides */);\n this._renderResult = null;\n this._context.addEventHandler(this);\n }\n dispose() {\n this._context.removeEventHandler(this);\n this._renderResult = null;\n super.dispose();\n }\n // --- begin event handlers\n onConfigurationChanged(e) {\n const options = this._context.configuration.options;\n const wrappingInfo = options.get(134 /* EditorOption.wrappingInfo */);\n const fontInfo = options.get(46 /* EditorOption.fontInfo */);\n this._lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this._spaceWidth = fontInfo.spaceWidth;\n this._maxIndentLeft = wrappingInfo.wrappingColumn === -1 ? -1 : (wrappingInfo.wrappingColumn * fontInfo.typicalHalfwidthCharacterWidth);\n this._bracketPairGuideOptions = options.get(13 /* EditorOption.guides */);\n return true;\n }\n onCursorStateChanged(e) {\n var _a;\n const selection = e.selections[0];\n const newPosition = selection.getPosition();\n if (!((_a = this._primaryPosition) === null || _a === void 0 ? void 0 : _a.equals(newPosition))) {\n this._primaryPosition = newPosition;\n return true;\n }\n return false;\n }\n onDecorationsChanged(e) {\n // true for inline decorations\n return true;\n }\n onFlushed(e) {\n return true;\n }\n onLinesChanged(e) {\n return true;\n }\n onLinesDeleted(e) {\n return true;\n }\n onLinesInserted(e) {\n return true;\n }\n onScrollChanged(e) {\n return e.scrollTopChanged; // || e.scrollWidthChanged;\n }\n onZonesChanged(e) {\n return true;\n }\n onLanguageConfigurationChanged(e) {\n return true;\n }\n // --- end event handlers\n prepareRender(ctx) {\n var _a, _b, _c, _d;\n if (!this._bracketPairGuideOptions.indentation && this._bracketPairGuideOptions.bracketPairs === false) {\n this._renderResult = null;\n return;\n }\n const visibleStartLineNumber = ctx.visibleRange.startLineNumber;\n const visibleEndLineNumber = ctx.visibleRange.endLineNumber;\n const scrollWidth = ctx.scrollWidth;\n const lineHeight = this._lineHeight;\n const activeCursorPosition = this._primaryPosition;\n const indents = this.getGuidesByLine(visibleStartLineNumber, visibleEndLineNumber, activeCursorPosition);\n const output = [];\n for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {\n const lineIndex = lineNumber - visibleStartLineNumber;\n const indent = indents[lineIndex];\n let result = '';\n const leftOffset = (_b = (_a = ctx.visibleRangeForPosition(new Position(lineNumber, 1))) === null || _a === void 0 ? void 0 : _a.left) !== null && _b !== void 0 ? _b : 0;\n for (const guide of indent) {\n const left = guide.column === -1\n ? leftOffset + (guide.visibleColumn - 1) * this._spaceWidth\n : ctx.visibleRangeForPosition(new Position(lineNumber, guide.column)).left;\n if (left > scrollWidth || (this._maxIndentLeft > 0 && left > this._maxIndentLeft)) {\n break;\n }\n const className = guide.horizontalLine ? (guide.horizontalLine.top ? 'horizontal-top' : 'horizontal-bottom') : 'vertical';\n const width = guide.horizontalLine\n ? ((_d = (_c = ctx.visibleRangeForPosition(new Position(lineNumber, guide.horizontalLine.endColumn))) === null || _c === void 0 ? void 0 : _c.left) !== null && _d !== void 0 ? _d : (left + this._spaceWidth)) - left\n : this._spaceWidth;\n result += `
`;\n }\n output[lineIndex] = result;\n }\n this._renderResult = output;\n }\n getGuidesByLine(visibleStartLineNumber, visibleEndLineNumber, activeCursorPosition) {\n const bracketGuides = this._bracketPairGuideOptions.bracketPairs !== false\n ? this._context.viewModel.getBracketGuidesInRangeByLine(visibleStartLineNumber, visibleEndLineNumber, activeCursorPosition, {\n highlightActive: this._bracketPairGuideOptions.highlightActiveBracketPair,\n horizontalGuides: this._bracketPairGuideOptions.bracketPairsHorizontal === true\n ? HorizontalGuidesState.Enabled\n : this._bracketPairGuideOptions.bracketPairsHorizontal === 'active'\n ? HorizontalGuidesState.EnabledForActive\n : HorizontalGuidesState.Disabled,\n includeInactive: this._bracketPairGuideOptions.bracketPairs === true,\n })\n : null;\n const indentGuides = this._bracketPairGuideOptions.indentation\n ? this._context.viewModel.getLinesIndentGuides(visibleStartLineNumber, visibleEndLineNumber)\n : null;\n let activeIndentStartLineNumber = 0;\n let activeIndentEndLineNumber = 0;\n let activeIndentLevel = 0;\n if (this._bracketPairGuideOptions.highlightActiveIndentation !== false && activeCursorPosition) {\n const activeIndentInfo = this._context.viewModel.getActiveIndentGuide(activeCursorPosition.lineNumber, visibleStartLineNumber, visibleEndLineNumber);\n activeIndentStartLineNumber = activeIndentInfo.startLineNumber;\n activeIndentEndLineNumber = activeIndentInfo.endLineNumber;\n activeIndentLevel = activeIndentInfo.indent;\n }\n const { indentSize } = this._context.viewModel.model.getOptions();\n const result = [];\n for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {\n const lineGuides = new Array();\n result.push(lineGuides);\n const bracketGuidesInLine = bracketGuides ? bracketGuides[lineNumber - visibleStartLineNumber] : [];\n const bracketGuidesInLineQueue = new ArrayQueue(bracketGuidesInLine);\n const indentGuidesInLine = indentGuides ? indentGuides[lineNumber - visibleStartLineNumber] : [];\n for (let indentLvl = 1; indentLvl <= indentGuidesInLine; indentLvl++) {\n const indentGuide = (indentLvl - 1) * indentSize + 1;\n const isActive = \n // Disable active indent guide if there are bracket guides.\n (this._bracketPairGuideOptions.highlightActiveIndentation === 'always' || bracketGuidesInLine.length === 0) &&\n activeIndentStartLineNumber <= lineNumber &&\n lineNumber <= activeIndentEndLineNumber &&\n indentLvl === activeIndentLevel;\n lineGuides.push(...bracketGuidesInLineQueue.takeWhile(g => g.visibleColumn < indentGuide) || []);\n const peeked = bracketGuidesInLineQueue.peek();\n if (!peeked || peeked.visibleColumn !== indentGuide || peeked.horizontalLine) {\n lineGuides.push(new IndentGuide(indentGuide, -1, isActive ? 'core-guide-indent-active' : 'core-guide-indent', null, -1, -1));\n }\n }\n lineGuides.push(...bracketGuidesInLineQueue.takeWhile(g => true) || []);\n }\n return result;\n }\n render(startLineNumber, lineNumber) {\n if (!this._renderResult) {\n return '';\n }\n const lineIndex = lineNumber - startLineNumber;\n if (lineIndex < 0 || lineIndex >= this._renderResult.length) {\n return '';\n }\n return this._renderResult[lineIndex];\n }\n}\nfunction transparentToUndefined(color) {\n if (color && color.isTransparent()) {\n return undefined;\n }\n return color;\n}\nregisterThemingParticipant((theme, collector) => {\n const editorIndentGuidesColor = theme.getColor(editorIndentGuides);\n if (editorIndentGuidesColor) {\n collector.addRule(`.monaco-editor .lines-content .core-guide-indent { box-shadow: 1px 0 0 0 ${editorIndentGuidesColor} inset; }`);\n }\n const editorActiveIndentGuidesColor = theme.getColor(editorActiveIndentGuides) || editorIndentGuidesColor;\n if (editorActiveIndentGuidesColor) {\n collector.addRule(`.monaco-editor .lines-content .core-guide-indent-active { box-shadow: 1px 0 0 0 ${editorActiveIndentGuidesColor} inset; }`);\n }\n const colors = [\n { bracketColor: editorBracketHighlightingForeground1, guideColor: editorBracketPairGuideBackground1, guideColorActive: editorBracketPairGuideActiveBackground1 },\n { bracketColor: editorBracketHighlightingForeground2, guideColor: editorBracketPairGuideBackground2, guideColorActive: editorBracketPairGuideActiveBackground2 },\n { bracketColor: editorBracketHighlightingForeground3, guideColor: editorBracketPairGuideBackground3, guideColorActive: editorBracketPairGuideActiveBackground3 },\n { bracketColor: editorBracketHighlightingForeground4, guideColor: editorBracketPairGuideBackground4, guideColorActive: editorBracketPairGuideActiveBackground4 },\n { bracketColor: editorBracketHighlightingForeground5, guideColor: editorBracketPairGuideBackground5, guideColorActive: editorBracketPairGuideActiveBackground5 },\n { bracketColor: editorBracketHighlightingForeground6, guideColor: editorBracketPairGuideBackground6, guideColorActive: editorBracketPairGuideActiveBackground6 }\n ];\n const colorProvider = new BracketPairGuidesClassNames();\n const colorValues = colors\n .map(c => {\n var _a, _b;\n const bracketColor = theme.getColor(c.bracketColor);\n const guideColor = theme.getColor(c.guideColor);\n const guideColorActive = theme.getColor(c.guideColorActive);\n const effectiveGuideColor = transparentToUndefined((_a = transparentToUndefined(guideColor)) !== null && _a !== void 0 ? _a : bracketColor === null || bracketColor === void 0 ? void 0 : bracketColor.transparent(0.3));\n const effectiveGuideColorActive = transparentToUndefined((_b = transparentToUndefined(guideColorActive)) !== null && _b !== void 0 ? _b : bracketColor);\n if (!effectiveGuideColor || !effectiveGuideColorActive) {\n return undefined;\n }\n return {\n guideColor: effectiveGuideColor,\n guideColorActive: effectiveGuideColorActive,\n };\n })\n .filter(isDefined);\n if (colorValues.length > 0) {\n for (let level = 0; level < 30; level++) {\n const colors = colorValues[level % colorValues.length];\n collector.addRule(`.monaco-editor .${colorProvider.getInlineClassNameOfLevel(level).replace(/ /g, '.')} { --guide-color: ${colors.guideColor}; --guide-color-active: ${colors.guideColorActive}; }`);\n }\n collector.addRule(`.monaco-editor .vertical { box-shadow: 1px 0 0 0 var(--guide-color) inset; }`);\n collector.addRule(`.monaco-editor .horizontal-top { border-top: 1px solid var(--guide-color); }`);\n collector.addRule(`.monaco-editor .horizontal-bottom { border-bottom: 1px solid var(--guide-color); }`);\n collector.addRule(`.monaco-editor .vertical.${colorProvider.activeClassName} { box-shadow: 1px 0 0 0 var(--guide-color-active) inset; }`);\n collector.addRule(`.monaco-editor .horizontal-top.${colorProvider.activeClassName} { border-top: 1px solid var(--guide-color-active); }`);\n collector.addRule(`.monaco-editor .horizontal-bottom.${colorProvider.activeClassName} { border-bottom: 1px solid var(--guide-color-active); }`);\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 *--------------------------------------------------------------------------------------------*/\nimport './viewLines.css';\nimport * as platform from '../../../../base/common/platform.js';\nimport { RunOnceScheduler } from '../../../../base/common/async.js';\nimport { applyFontInfo } from '../../config/domFontInfo.js';\nimport { VisibleLinesCollection } from '../../view/viewLayer.js';\nimport { PartFingerprints, ViewPart } from '../../view/viewPart.js';\nimport { DomReadingContext, ViewLine, ViewLineOptions } from './viewLine.js';\nimport { Position } from '../../../common/core/position.js';\nimport { Range } from '../../../common/core/range.js';\nimport { LineVisibleRanges, HorizontalPosition, HorizontalRange } from '../../view/renderingContext.js';\nimport { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from '../../../../base/browser/ui/mouseCursor/mouseCursor.js';\nclass LastRenderedData {\n constructor() {\n this._currentVisibleRange = new Range(1, 1, 1, 1);\n }\n getCurrentVisibleRange() {\n return this._currentVisibleRange;\n }\n setCurrentVisibleRange(currentVisibleRange) {\n this._currentVisibleRange = currentVisibleRange;\n }\n}\nclass HorizontalRevealRangeRequest {\n constructor(minimalReveal, lineNumber, startColumn, endColumn, startScrollTop, stopScrollTop, scrollType) {\n this.minimalReveal = minimalReveal;\n this.lineNumber = lineNumber;\n this.startColumn = startColumn;\n this.endColumn = endColumn;\n this.startScrollTop = startScrollTop;\n this.stopScrollTop = stopScrollTop;\n this.scrollType = scrollType;\n this.type = 'range';\n this.minLineNumber = lineNumber;\n this.maxLineNumber = lineNumber;\n }\n}\nclass HorizontalRevealSelectionsRequest {\n constructor(minimalReveal, selections, startScrollTop, stopScrollTop, scrollType) {\n this.minimalReveal = minimalReveal;\n this.selections = selections;\n this.startScrollTop = startScrollTop;\n this.stopScrollTop = stopScrollTop;\n this.scrollType = scrollType;\n this.type = 'selections';\n let minLineNumber = selections[0].startLineNumber;\n let maxLineNumber = selections[0].endLineNumber;\n for (let i = 1, len = selections.length; i < len; i++) {\n const selection = selections[i];\n minLineNumber = Math.min(minLineNumber, selection.startLineNumber);\n maxLineNumber = Math.max(maxLineNumber, selection.endLineNumber);\n }\n this.minLineNumber = minLineNumber;\n this.maxLineNumber = maxLineNumber;\n }\n}\nexport class ViewLines extends ViewPart {\n constructor(context, linesContent) {\n super(context);\n this._linesContent = linesContent;\n this._textRangeRestingSpot = document.createElement('div');\n this._visibleLines = new VisibleLinesCollection(this);\n this.domNode = this._visibleLines.domNode;\n const conf = this._context.configuration;\n const options = this._context.configuration.options;\n const fontInfo = options.get(46 /* EditorOption.fontInfo */);\n const wrappingInfo = options.get(134 /* EditorOption.wrappingInfo */);\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n this._lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this._typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;\n this._isViewportWrapping = wrappingInfo.isViewportWrapping;\n this._revealHorizontalRightPadding = options.get(91 /* EditorOption.revealHorizontalRightPadding */);\n this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight;\n this._cursorSurroundingLines = options.get(25 /* EditorOption.cursorSurroundingLines */);\n this._cursorSurroundingLinesStyle = options.get(26 /* EditorOption.cursorSurroundingLinesStyle */);\n this._canUseLayerHinting = !options.get(28 /* EditorOption.disableLayerHinting */);\n this._viewLineOptions = new ViewLineOptions(conf, this._context.theme.type);\n PartFingerprints.write(this.domNode, 7 /* PartFingerprint.ViewLines */);\n this.domNode.setClassName(`view-lines ${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`);\n applyFontInfo(this.domNode, fontInfo);\n // --- width & height\n this._maxLineWidth = 0;\n this._asyncUpdateLineWidths = new RunOnceScheduler(() => {\n this._updateLineWidthsSlow();\n }, 200);\n this._asyncCheckMonospaceFontAssumptions = new RunOnceScheduler(() => {\n this._checkMonospaceFontAssumptions();\n }, 2000);\n this._lastRenderedData = new LastRenderedData();\n this._horizontalRevealRequest = null;\n }\n dispose() {\n this._asyncUpdateLineWidths.dispose();\n this._asyncCheckMonospaceFontAssumptions.dispose();\n super.dispose();\n }\n getDomNode() {\n return this.domNode;\n }\n // ---- begin IVisibleLinesHost\n createVisibleLine() {\n return new ViewLine(this._viewLineOptions);\n }\n // ---- end IVisibleLinesHost\n // ---- begin view event handlers\n onConfigurationChanged(e) {\n this._visibleLines.onConfigurationChanged(e);\n if (e.hasChanged(134 /* EditorOption.wrappingInfo */)) {\n this._maxLineWidth = 0;\n }\n const options = this._context.configuration.options;\n const fontInfo = options.get(46 /* EditorOption.fontInfo */);\n const wrappingInfo = options.get(134 /* EditorOption.wrappingInfo */);\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n this._lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this._typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;\n this._isViewportWrapping = wrappingInfo.isViewportWrapping;\n this._revealHorizontalRightPadding = options.get(91 /* EditorOption.revealHorizontalRightPadding */);\n this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight;\n this._cursorSurroundingLines = options.get(25 /* EditorOption.cursorSurroundingLines */);\n this._cursorSurroundingLinesStyle = options.get(26 /* EditorOption.cursorSurroundingLinesStyle */);\n this._canUseLayerHinting = !options.get(28 /* EditorOption.disableLayerHinting */);\n applyFontInfo(this.domNode, fontInfo);\n this._onOptionsMaybeChanged();\n if (e.hasChanged(133 /* EditorOption.layoutInfo */)) {\n this._maxLineWidth = 0;\n }\n return true;\n }\n _onOptionsMaybeChanged() {\n const conf = this._context.configuration;\n const newViewLineOptions = new ViewLineOptions(conf, this._context.theme.type);\n if (!this._viewLineOptions.equals(newViewLineOptions)) {\n this._viewLineOptions = newViewLineOptions;\n const startLineNumber = this._visibleLines.getStartLineNumber();\n const endLineNumber = this._visibleLines.getEndLineNumber();\n for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n const line = this._visibleLines.getVisibleLine(lineNumber);\n line.onOptionsChanged(this._viewLineOptions);\n }\n return true;\n }\n return false;\n }\n onCursorStateChanged(e) {\n const rendStartLineNumber = this._visibleLines.getStartLineNumber();\n const rendEndLineNumber = this._visibleLines.getEndLineNumber();\n let r = false;\n for (let lineNumber = rendStartLineNumber; lineNumber <= rendEndLineNumber; lineNumber++) {\n r = this._visibleLines.getVisibleLine(lineNumber).onSelectionChanged() || r;\n }\n return r;\n }\n onDecorationsChanged(e) {\n if (true /*e.inlineDecorationsChanged*/) {\n const rendStartLineNumber = this._visibleLines.getStartLineNumber();\n const rendEndLineNumber = this._visibleLines.getEndLineNumber();\n for (let lineNumber = rendStartLineNumber; lineNumber <= rendEndLineNumber; lineNumber++) {\n this._visibleLines.getVisibleLine(lineNumber).onDecorationsChanged();\n }\n }\n return true;\n }\n onFlushed(e) {\n const shouldRender = this._visibleLines.onFlushed(e);\n this._maxLineWidth = 0;\n return shouldRender;\n }\n onLinesChanged(e) {\n return this._visibleLines.onLinesChanged(e);\n }\n onLinesDeleted(e) {\n return this._visibleLines.onLinesDeleted(e);\n }\n onLinesInserted(e) {\n return this._visibleLines.onLinesInserted(e);\n }\n onRevealRangeRequest(e) {\n // Using the future viewport here in order to handle multiple\n // incoming reveal range requests that might all desire to be animated\n const desiredScrollTop = this._computeScrollTopToRevealRange(this._context.viewLayout.getFutureViewport(), e.source, e.minimalReveal, e.range, e.selections, e.verticalType);\n if (desiredScrollTop === -1) {\n // marker to abort the reveal range request\n return false;\n }\n // validate the new desired scroll top\n let newScrollPosition = this._context.viewLayout.validateScrollPosition({ scrollTop: desiredScrollTop });\n if (e.revealHorizontal) {\n if (e.range && e.range.startLineNumber !== e.range.endLineNumber) {\n // Two or more lines? => scroll to base (That's how you see most of the two lines)\n newScrollPosition = {\n scrollTop: newScrollPosition.scrollTop,\n scrollLeft: 0\n };\n }\n else if (e.range) {\n // We don't necessarily know the horizontal offset of this range since the line might not be in the view...\n this._horizontalRevealRequest = new HorizontalRevealRangeRequest(e.minimalReveal, e.range.startLineNumber, e.range.startColumn, e.range.endColumn, this._context.viewLayout.getCurrentScrollTop(), newScrollPosition.scrollTop, e.scrollType);\n }\n else if (e.selections && e.selections.length > 0) {\n this._horizontalRevealRequest = new HorizontalRevealSelectionsRequest(e.minimalReveal, e.selections, this._context.viewLayout.getCurrentScrollTop(), newScrollPosition.scrollTop, e.scrollType);\n }\n }\n else {\n this._horizontalRevealRequest = null;\n }\n const scrollTopDelta = Math.abs(this._context.viewLayout.getCurrentScrollTop() - newScrollPosition.scrollTop);\n const scrollType = (scrollTopDelta <= this._lineHeight ? 1 /* ScrollType.Immediate */ : e.scrollType);\n this._context.viewModel.viewLayout.setScrollPosition(newScrollPosition, scrollType);\n return true;\n }\n onScrollChanged(e) {\n if (this._horizontalRevealRequest && e.scrollLeftChanged) {\n // cancel any outstanding horizontal reveal request if someone else scrolls horizontally.\n this._horizontalRevealRequest = null;\n }\n if (this._horizontalRevealRequest && e.scrollTopChanged) {\n const min = Math.min(this._horizontalRevealRequest.startScrollTop, this._horizontalRevealRequest.stopScrollTop);\n const max = Math.max(this._horizontalRevealRequest.startScrollTop, this._horizontalRevealRequest.stopScrollTop);\n if (e.scrollTop < min || e.scrollTop > max) {\n // cancel any outstanding horizontal reveal request if someone else scrolls vertically.\n this._horizontalRevealRequest = null;\n }\n }\n this.domNode.setWidth(e.scrollWidth);\n return this._visibleLines.onScrollChanged(e) || true;\n }\n onTokensChanged(e) {\n return this._visibleLines.onTokensChanged(e);\n }\n onZonesChanged(e) {\n this._context.viewModel.viewLayout.setMaxLineWidth(this._maxLineWidth);\n return this._visibleLines.onZonesChanged(e);\n }\n onThemeChanged(e) {\n return this._onOptionsMaybeChanged();\n }\n // ---- end view event handlers\n // ----------- HELPERS FOR OTHERS\n getPositionFromDOMInfo(spanNode, offset) {\n const viewLineDomNode = this._getViewLineDomNode(spanNode);\n if (viewLineDomNode === null) {\n // Couldn't find view line node\n return null;\n }\n const lineNumber = this._getLineNumberFor(viewLineDomNode);\n if (lineNumber === -1) {\n // Couldn't find view line node\n return null;\n }\n if (lineNumber < 1 || lineNumber > this._context.viewModel.getLineCount()) {\n // lineNumber is outside range\n return null;\n }\n if (this._context.viewModel.getLineMaxColumn(lineNumber) === 1) {\n // Line is empty\n return new Position(lineNumber, 1);\n }\n const rendStartLineNumber = this._visibleLines.getStartLineNumber();\n const rendEndLineNumber = this._visibleLines.getEndLineNumber();\n if (lineNumber < rendStartLineNumber || lineNumber > rendEndLineNumber) {\n // Couldn't find line\n return null;\n }\n let column = this._visibleLines.getVisibleLine(lineNumber).getColumnOfNodeOffset(lineNumber, spanNode, offset);\n const minColumn = this._context.viewModel.getLineMinColumn(lineNumber);\n if (column < minColumn) {\n column = minColumn;\n }\n return new Position(lineNumber, column);\n }\n _getViewLineDomNode(node) {\n while (node && node.nodeType === 1) {\n if (node.className === ViewLine.CLASS_NAME) {\n return node;\n }\n node = node.parentElement;\n }\n return null;\n }\n /**\n * @returns the line number of this view line dom node.\n */\n _getLineNumberFor(domNode) {\n const startLineNumber = this._visibleLines.getStartLineNumber();\n const endLineNumber = this._visibleLines.getEndLineNumber();\n for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n const line = this._visibleLines.getVisibleLine(lineNumber);\n if (domNode === line.getDomNode()) {\n return lineNumber;\n }\n }\n return -1;\n }\n getLineWidth(lineNumber) {\n const rendStartLineNumber = this._visibleLines.getStartLineNumber();\n const rendEndLineNumber = this._visibleLines.getEndLineNumber();\n if (lineNumber < rendStartLineNumber || lineNumber > rendEndLineNumber) {\n // Couldn't find line\n return -1;\n }\n return this._visibleLines.getVisibleLine(lineNumber).getWidth();\n }\n linesVisibleRangesForRange(_range, includeNewLines) {\n if (this.shouldRender()) {\n // Cannot read from the DOM because it is dirty\n // i.e. the model & the dom are out of sync, so I'd be reading something stale\n return null;\n }\n const originalEndLineNumber = _range.endLineNumber;\n const range = Range.intersectRanges(_range, this._lastRenderedData.getCurrentVisibleRange());\n if (!range) {\n return null;\n }\n const visibleRanges = [];\n let visibleRangesLen = 0;\n const domReadingContext = new DomReadingContext(this.domNode.domNode, this._textRangeRestingSpot);\n let nextLineModelLineNumber = 0;\n if (includeNewLines) {\n nextLineModelLineNumber = this._context.viewModel.coordinatesConverter.convertViewPositionToModelPosition(new Position(range.startLineNumber, 1)).lineNumber;\n }\n const rendStartLineNumber = this._visibleLines.getStartLineNumber();\n const rendEndLineNumber = this._visibleLines.getEndLineNumber();\n for (let lineNumber = range.startLineNumber; lineNumber <= range.endLineNumber; lineNumber++) {\n if (lineNumber < rendStartLineNumber || lineNumber > rendEndLineNumber) {\n continue;\n }\n const startColumn = lineNumber === range.startLineNumber ? range.startColumn : 1;\n const endColumn = lineNumber === range.endLineNumber ? range.endColumn : this._context.viewModel.getLineMaxColumn(lineNumber);\n const visibleRangesForLine = this._visibleLines.getVisibleLine(lineNumber).getVisibleRangesForRange(lineNumber, startColumn, endColumn, domReadingContext);\n if (!visibleRangesForLine) {\n continue;\n }\n if (includeNewLines && lineNumber < originalEndLineNumber) {\n const currentLineModelLineNumber = nextLineModelLineNumber;\n nextLineModelLineNumber = this._context.viewModel.coordinatesConverter.convertViewPositionToModelPosition(new Position(lineNumber + 1, 1)).lineNumber;\n if (currentLineModelLineNumber !== nextLineModelLineNumber) {\n visibleRangesForLine.ranges[visibleRangesForLine.ranges.length - 1].width += this._typicalHalfwidthCharacterWidth;\n }\n }\n visibleRanges[visibleRangesLen++] = new LineVisibleRanges(visibleRangesForLine.outsideRenderedLine, lineNumber, HorizontalRange.from(visibleRangesForLine.ranges));\n }\n if (visibleRangesLen === 0) {\n return null;\n }\n return visibleRanges;\n }\n _visibleRangesForLineRange(lineNumber, startColumn, endColumn) {\n if (this.shouldRender()) {\n // Cannot read from the DOM because it is dirty\n // i.e. the model & the dom are out of sync, so I'd be reading something stale\n return null;\n }\n if (lineNumber < this._visibleLines.getStartLineNumber() || lineNumber > this._visibleLines.getEndLineNumber()) {\n return null;\n }\n return this._visibleLines.getVisibleLine(lineNumber).getVisibleRangesForRange(lineNumber, startColumn, endColumn, new DomReadingContext(this.domNode.domNode, this._textRangeRestingSpot));\n }\n visibleRangeForPosition(position) {\n const visibleRanges = this._visibleRangesForLineRange(position.lineNumber, position.column, position.column);\n if (!visibleRanges) {\n return null;\n }\n return new HorizontalPosition(visibleRanges.outsideRenderedLine, visibleRanges.ranges[0].left);\n }\n // --- implementation\n updateLineWidths() {\n this._updateLineWidths(false);\n }\n /**\n * Updates the max line width if it is fast to compute.\n * Returns true if all lines were taken into account.\n * Returns false if some lines need to be reevaluated (in a slow fashion).\n */\n _updateLineWidthsFast() {\n return this._updateLineWidths(true);\n }\n _updateLineWidthsSlow() {\n this._updateLineWidths(false);\n }\n _updateLineWidths(fast) {\n const rendStartLineNumber = this._visibleLines.getStartLineNumber();\n const rendEndLineNumber = this._visibleLines.getEndLineNumber();\n let localMaxLineWidth = 1;\n let allWidthsComputed = true;\n for (let lineNumber = rendStartLineNumber; lineNumber <= rendEndLineNumber; lineNumber++) {\n const visibleLine = this._visibleLines.getVisibleLine(lineNumber);\n if (fast && !visibleLine.getWidthIsFast()) {\n // Cannot compute width in a fast way for this line\n allWidthsComputed = false;\n continue;\n }\n localMaxLineWidth = Math.max(localMaxLineWidth, visibleLine.getWidth());\n }\n if (allWidthsComputed && rendStartLineNumber === 1 && rendEndLineNumber === this._context.viewModel.getLineCount()) {\n // we know the max line width for all the lines\n this._maxLineWidth = 0;\n }\n this._ensureMaxLineWidth(localMaxLineWidth);\n return allWidthsComputed;\n }\n _checkMonospaceFontAssumptions() {\n // Problems with monospace assumptions are more apparent for longer lines,\n // as small rounding errors start to sum up, so we will select the longest\n // line for a closer inspection\n let longestLineNumber = -1;\n let longestWidth = -1;\n const rendStartLineNumber = this._visibleLines.getStartLineNumber();\n const rendEndLineNumber = this._visibleLines.getEndLineNumber();\n for (let lineNumber = rendStartLineNumber; lineNumber <= rendEndLineNumber; lineNumber++) {\n const visibleLine = this._visibleLines.getVisibleLine(lineNumber);\n if (visibleLine.needsMonospaceFontCheck()) {\n const lineWidth = visibleLine.getWidth();\n if (lineWidth > longestWidth) {\n longestWidth = lineWidth;\n longestLineNumber = lineNumber;\n }\n }\n }\n if (longestLineNumber === -1) {\n return;\n }\n if (!this._visibleLines.getVisibleLine(longestLineNumber).monospaceAssumptionsAreValid()) {\n for (let lineNumber = rendStartLineNumber; lineNumber <= rendEndLineNumber; lineNumber++) {\n const visibleLine = this._visibleLines.getVisibleLine(lineNumber);\n visibleLine.onMonospaceAssumptionsInvalidated();\n }\n }\n }\n prepareRender() {\n throw new Error('Not supported');\n }\n render() {\n throw new Error('Not supported');\n }\n renderText(viewportData) {\n // (1) render lines - ensures lines are in the DOM\n this._visibleLines.renderLines(viewportData);\n this._lastRenderedData.setCurrentVisibleRange(viewportData.visibleRange);\n this.domNode.setWidth(this._context.viewLayout.getScrollWidth());\n this.domNode.setHeight(Math.min(this._context.viewLayout.getScrollHeight(), 1000000));\n // (2) compute horizontal scroll position:\n // - this must happen after the lines are in the DOM since it might need a line that rendered just now\n // - it might change `scrollWidth` and `scrollLeft`\n if (this._horizontalRevealRequest) {\n const horizontalRevealRequest = this._horizontalRevealRequest;\n // Check that we have the line that contains the horizontal range in the viewport\n if (viewportData.startLineNumber <= horizontalRevealRequest.minLineNumber && horizontalRevealRequest.maxLineNumber <= viewportData.endLineNumber) {\n this._horizontalRevealRequest = null;\n // allow `visibleRangesForRange2` to work\n this.onDidRender();\n // compute new scroll position\n const newScrollLeft = this._computeScrollLeftToReveal(horizontalRevealRequest);\n if (newScrollLeft) {\n if (!this._isViewportWrapping) {\n // ensure `scrollWidth` is large enough\n this._ensureMaxLineWidth(newScrollLeft.maxHorizontalOffset);\n }\n // set `scrollLeft`\n this._context.viewModel.viewLayout.setScrollPosition({\n scrollLeft: newScrollLeft.scrollLeft\n }, horizontalRevealRequest.scrollType);\n }\n }\n }\n // Update max line width (not so important, it is just so the horizontal scrollbar doesn't get too small)\n if (!this._updateLineWidthsFast()) {\n // Computing the width of some lines would be slow => delay it\n this._asyncUpdateLineWidths.schedule();\n }\n if (platform.isLinux && !this._asyncCheckMonospaceFontAssumptions.isScheduled()) {\n const rendStartLineNumber = this._visibleLines.getStartLineNumber();\n const rendEndLineNumber = this._visibleLines.getEndLineNumber();\n for (let lineNumber = rendStartLineNumber; lineNumber <= rendEndLineNumber; lineNumber++) {\n const visibleLine = this._visibleLines.getVisibleLine(lineNumber);\n if (visibleLine.needsMonospaceFontCheck()) {\n this._asyncCheckMonospaceFontAssumptions.schedule();\n break;\n }\n }\n }\n // (3) handle scrolling\n this._linesContent.setLayerHinting(this._canUseLayerHinting);\n this._linesContent.setContain('strict');\n const adjustedScrollTop = this._context.viewLayout.getCurrentScrollTop() - viewportData.bigNumbersDelta;\n this._linesContent.setTop(-adjustedScrollTop);\n this._linesContent.setLeft(-this._context.viewLayout.getCurrentScrollLeft());\n }\n // --- width\n _ensureMaxLineWidth(lineWidth) {\n const iLineWidth = Math.ceil(lineWidth);\n if (this._maxLineWidth < iLineWidth) {\n this._maxLineWidth = iLineWidth;\n this._context.viewModel.viewLayout.setMaxLineWidth(this._maxLineWidth);\n }\n }\n _computeScrollTopToRevealRange(viewport, source, minimalReveal, range, selections, verticalType) {\n const viewportStartY = viewport.top;\n const viewportHeight = viewport.height;\n const viewportEndY = viewportStartY + viewportHeight;\n let boxIsSingleRange;\n let boxStartY;\n let boxEndY;\n if (selections && selections.length > 0) {\n let minLineNumber = selections[0].startLineNumber;\n let maxLineNumber = selections[0].endLineNumber;\n for (let i = 1, len = selections.length; i < len; i++) {\n const selection = selections[i];\n minLineNumber = Math.min(minLineNumber, selection.startLineNumber);\n maxLineNumber = Math.max(maxLineNumber, selection.endLineNumber);\n }\n boxIsSingleRange = false;\n boxStartY = this._context.viewLayout.getVerticalOffsetForLineNumber(minLineNumber);\n boxEndY = this._context.viewLayout.getVerticalOffsetForLineNumber(maxLineNumber) + this._lineHeight;\n }\n else if (range) {\n boxIsSingleRange = true;\n boxStartY = this._context.viewLayout.getVerticalOffsetForLineNumber(range.startLineNumber);\n boxEndY = this._context.viewLayout.getVerticalOffsetForLineNumber(range.endLineNumber) + this._lineHeight;\n }\n else {\n return -1;\n }\n const shouldIgnoreScrollOff = (source === 'mouse' || minimalReveal) && this._cursorSurroundingLinesStyle === 'default';\n if (!shouldIgnoreScrollOff) {\n const context = Math.min((viewportHeight / this._lineHeight) / 2, this._cursorSurroundingLines);\n boxStartY -= context * this._lineHeight;\n boxEndY += Math.max(0, (context - 1)) * this._lineHeight;\n }\n else {\n if (!minimalReveal) {\n // Reveal one more line above (this case is hit when dragging)\n boxStartY -= this._lineHeight;\n }\n }\n if (verticalType === 0 /* viewEvents.VerticalRevealType.Simple */ || verticalType === 4 /* viewEvents.VerticalRevealType.Bottom */) {\n // Reveal one line more when the last line would be covered by the scrollbar - arrow down case or revealing a line explicitly at bottom\n boxEndY += (minimalReveal ? this._horizontalScrollbarHeight : this._lineHeight);\n }\n let newScrollTop;\n if (boxEndY - boxStartY > viewportHeight) {\n // the box is larger than the viewport ... scroll to its top\n if (!boxIsSingleRange) {\n // do not reveal multiple cursors if there are more than fit the viewport\n return -1;\n }\n newScrollTop = boxStartY;\n }\n else if (verticalType === 5 /* viewEvents.VerticalRevealType.NearTop */ || verticalType === 6 /* viewEvents.VerticalRevealType.NearTopIfOutsideViewport */) {\n if (verticalType === 6 /* viewEvents.VerticalRevealType.NearTopIfOutsideViewport */ && viewportStartY <= boxStartY && boxEndY <= viewportEndY) {\n // Box is already in the viewport... do nothing\n newScrollTop = viewportStartY;\n }\n else {\n // We want a gap that is 20% of the viewport, but with a minimum of 5 lines\n const desiredGapAbove = Math.max(5 * this._lineHeight, viewportHeight * 0.2);\n // Try to scroll just above the box with the desired gap\n const desiredScrollTop = boxStartY - desiredGapAbove;\n // But ensure that the box is not pushed out of viewport\n const minScrollTop = boxEndY - viewportHeight;\n newScrollTop = Math.max(minScrollTop, desiredScrollTop);\n }\n }\n else if (verticalType === 1 /* viewEvents.VerticalRevealType.Center */ || verticalType === 2 /* viewEvents.VerticalRevealType.CenterIfOutsideViewport */) {\n if (verticalType === 2 /* viewEvents.VerticalRevealType.CenterIfOutsideViewport */ && viewportStartY <= boxStartY && boxEndY <= viewportEndY) {\n // Box is already in the viewport... do nothing\n newScrollTop = viewportStartY;\n }\n else {\n // Box is outside the viewport... center it\n const boxMiddleY = (boxStartY + boxEndY) / 2;\n newScrollTop = Math.max(0, boxMiddleY - viewportHeight / 2);\n }\n }\n else {\n newScrollTop = this._computeMinimumScrolling(viewportStartY, viewportEndY, boxStartY, boxEndY, verticalType === 3 /* viewEvents.VerticalRevealType.Top */, verticalType === 4 /* viewEvents.VerticalRevealType.Bottom */);\n }\n return newScrollTop;\n }\n _computeScrollLeftToReveal(horizontalRevealRequest) {\n const viewport = this._context.viewLayout.getCurrentViewport();\n const viewportStartX = viewport.left;\n const viewportEndX = viewportStartX + viewport.width;\n let boxStartX = 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */;\n let boxEndX = 0;\n if (horizontalRevealRequest.type === 'range') {\n const visibleRanges = this._visibleRangesForLineRange(horizontalRevealRequest.lineNumber, horizontalRevealRequest.startColumn, horizontalRevealRequest.endColumn);\n if (!visibleRanges) {\n return null;\n }\n for (const visibleRange of visibleRanges.ranges) {\n boxStartX = Math.min(boxStartX, Math.round(visibleRange.left));\n boxEndX = Math.max(boxEndX, Math.round(visibleRange.left + visibleRange.width));\n }\n }\n else {\n for (const selection of horizontalRevealRequest.selections) {\n if (selection.startLineNumber !== selection.endLineNumber) {\n return null;\n }\n const visibleRanges = this._visibleRangesForLineRange(selection.startLineNumber, selection.startColumn, selection.endColumn);\n if (!visibleRanges) {\n return null;\n }\n for (const visibleRange of visibleRanges.ranges) {\n boxStartX = Math.min(boxStartX, Math.round(visibleRange.left));\n boxEndX = Math.max(boxEndX, Math.round(visibleRange.left + visibleRange.width));\n }\n }\n }\n if (!horizontalRevealRequest.minimalReveal) {\n boxStartX = Math.max(0, boxStartX - ViewLines.HORIZONTAL_EXTRA_PX);\n boxEndX += this._revealHorizontalRightPadding;\n }\n if (horizontalRevealRequest.type === 'selections' && boxEndX - boxStartX > viewport.width) {\n return null;\n }\n const newScrollLeft = this._computeMinimumScrolling(viewportStartX, viewportEndX, boxStartX, boxEndX);\n return {\n scrollLeft: newScrollLeft,\n maxHorizontalOffset: boxEndX\n };\n }\n _computeMinimumScrolling(viewportStart, viewportEnd, boxStart, boxEnd, revealAtStart, revealAtEnd) {\n viewportStart = viewportStart | 0;\n viewportEnd = viewportEnd | 0;\n boxStart = boxStart | 0;\n boxEnd = boxEnd | 0;\n revealAtStart = !!revealAtStart;\n revealAtEnd = !!revealAtEnd;\n const viewportLength = viewportEnd - viewportStart;\n const boxLength = boxEnd - boxStart;\n if (boxLength < viewportLength) {\n // The box would fit in the viewport\n if (revealAtStart) {\n return boxStart;\n }\n if (revealAtEnd) {\n return Math.max(0, boxEnd - viewportLength);\n }\n if (boxStart < viewportStart) {\n // The box is above the viewport\n return boxStart;\n }\n else if (boxEnd > viewportEnd) {\n // The box is below the viewport\n return Math.max(0, boxEnd - viewportLength);\n }\n }\n else {\n // The box would not fit in the viewport\n // Reveal the beginning of the box\n return boxStart;\n }\n return viewportStart;\n }\n}\n/**\n * Adds this amount of pixels to the right of lines (no-one wants to type near the edge of the viewport)\n */\nViewLines.HORIZONTAL_EXTRA_PX = 30;\n","/*---------------------------------------------------------------------------------------------\n * 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 './linesDecorations.css';\nimport { DecorationToRender, DedupOverlay } from '../glyphMargin/glyphMargin.js';\nexport class LinesDecorationsOverlay extends DedupOverlay {\n constructor(context) {\n super();\n this._context = context;\n const options = this._context.configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n this._decorationsLeft = layoutInfo.decorationsLeft;\n this._decorationsWidth = layoutInfo.decorationsWidth;\n this._renderResult = null;\n this._context.addEventHandler(this);\n }\n dispose() {\n this._context.removeEventHandler(this);\n this._renderResult = null;\n super.dispose();\n }\n // --- begin event handlers\n onConfigurationChanged(e) {\n const options = this._context.configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n this._decorationsLeft = layoutInfo.decorationsLeft;\n this._decorationsWidth = layoutInfo.decorationsWidth;\n return true;\n }\n onDecorationsChanged(e) {\n return true;\n }\n onFlushed(e) {\n return true;\n }\n onLinesChanged(e) {\n return true;\n }\n onLinesDeleted(e) {\n return true;\n }\n onLinesInserted(e) {\n return true;\n }\n onScrollChanged(e) {\n return e.scrollTopChanged;\n }\n onZonesChanged(e) {\n return true;\n }\n // --- end event handlers\n _getDecorations(ctx) {\n const decorations = ctx.getDecorationsInViewport();\n const r = [];\n let rLen = 0;\n for (let i = 0, len = decorations.length; i < len; i++) {\n const d = decorations[i];\n const linesDecorationsClassName = d.options.linesDecorationsClassName;\n if (linesDecorationsClassName) {\n r[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, linesDecorationsClassName);\n }\n const firstLineDecorationClassName = d.options.firstLineDecorationClassName;\n if (firstLineDecorationClassName) {\n r[rLen++] = new DecorationToRender(d.range.startLineNumber, d.range.startLineNumber, firstLineDecorationClassName);\n }\n }\n return r;\n }\n prepareRender(ctx) {\n const visibleStartLineNumber = ctx.visibleRange.startLineNumber;\n const visibleEndLineNumber = ctx.visibleRange.endLineNumber;\n const toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx));\n const left = this._decorationsLeft.toString();\n const width = this._decorationsWidth.toString();\n const common = '\" style=\"left:' + left + 'px;width:' + width + 'px;\">
';\n const output = [];\n for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {\n const lineIndex = lineNumber - visibleStartLineNumber;\n const classNames = toRender[lineIndex];\n let lineOutput = '';\n for (let i = 0, len = classNames.length; i < len; i++) {\n lineOutput += '
';\n }\n output[lineIndex] = lineOutput;\n }\n this._renderResult = output;\n }\n render(startLineNumber, lineNumber) {\n if (!this._renderResult) {\n return '';\n }\n return this._renderResult[lineNumber - startLineNumber];\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/**\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 constructor(r, g, b, a) {\n this._rgba8Brand = undefined;\n this.r = RGBA8._clamp(r);\n this.g = RGBA8._clamp(g);\n this.b = RGBA8._clamp(b);\n this.a = RGBA8._clamp(a);\n }\n equals(other) {\n return (this.r === other.r\n && this.g === other.g\n && this.b === other.b\n && this.a === other.a);\n }\n static _clamp(c) {\n if (c < 0) {\n return 0;\n }\n if (c > 255) {\n return 255;\n }\n return c | 0;\n }\n}\nRGBA8.Empty = new RGBA8(0, 0, 0, 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 *--------------------------------------------------------------------------------------------*/\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable, markAsSingleton } from '../../../base/common/lifecycle.js';\nimport { RGBA8 } from '../core/rgba.js';\nimport { TokenizationRegistry } from '../languages.js';\nexport class MinimapTokensColorTracker extends Disposable {\n constructor() {\n super();\n this._onDidChange = new Emitter();\n this.onDidChange = this._onDidChange.event;\n this._updateColorMap();\n this._register(TokenizationRegistry.onDidChange(e => {\n if (e.changedColorMap) {\n this._updateColorMap();\n }\n }));\n }\n static getInstance() {\n if (!this._INSTANCE) {\n this._INSTANCE = markAsSingleton(new MinimapTokensColorTracker());\n }\n return this._INSTANCE;\n }\n _updateColorMap() {\n const colorMap = TokenizationRegistry.getColorMap();\n if (!colorMap) {\n this._colors = [RGBA8.Empty];\n this._backgroundIsLight = true;\n return;\n }\n this._colors = [RGBA8.Empty];\n for (let colorId = 1; colorId < colorMap.length; colorId++) {\n const source = colorMap[colorId].rgba;\n // Use a VM friendly data-type\n this._colors[colorId] = new RGBA8(source.r, source.g, source.b, Math.round(source.a * 255));\n }\n const backgroundLuminosity = colorMap[2 /* ColorId.DefaultBackground */].getRelativeLuminance();\n this._backgroundIsLight = backgroundLuminosity >= 0.5;\n this._onDidChange.fire(undefined);\n }\n getColor(colorId) {\n if (colorId < 1 || colorId >= this._colors.length) {\n // background color (basically invisible)\n colorId = 2 /* ColorId.DefaultBackground */;\n }\n return this._colors[colorId];\n }\n backgroundIsLight() {\n return this._backgroundIsLight;\n }\n}\nMinimapTokensColorTracker._INSTANCE = null;\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nexport const allCharCodes = (() => {\n const v = [];\n for (let i = 32 /* Constants.START_CH_CODE */; i <= 126 /* Constants.END_CH_CODE */; i++) {\n v.push(i);\n }\n v.push(65533 /* Constants.UNKNOWN_CODE */);\n return v;\n})();\nexport const getCharIndex = (chCode, fontScale) => {\n chCode -= 32 /* Constants.START_CH_CODE */;\n if (chCode < 0 || chCode > 96 /* Constants.CHAR_COUNT */) {\n if (fontScale <= 2) {\n // for smaller scales, we can get away with using any ASCII character...\n return (chCode + 96 /* Constants.CHAR_COUNT */) % 96 /* Constants.CHAR_COUNT */;\n }\n return 96 /* Constants.CHAR_COUNT */ - 1; // unknown symbol\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { getCharIndex } from './minimapCharSheet.js';\nimport { toUint8 } from '../../../../base/common/uint.js';\nexport class MinimapCharRenderer {\n constructor(charData, scale) {\n this.scale = scale;\n this._minimapCharRendererBrand = undefined;\n this.charDataNormal = MinimapCharRenderer.soften(charData, 12 / 15);\n this.charDataLight = MinimapCharRenderer.soften(charData, 50 / 60);\n }\n static soften(input, ratio) {\n const result = new Uint8ClampedArray(input.length);\n for (let i = 0, len = input.length; i < len; i++) {\n result[i] = toUint8(input[i] * ratio);\n }\n return result;\n }\n renderChar(target, dx, dy, chCode, color, foregroundAlpha, backgroundColor, backgroundAlpha, fontScale, useLighterFont, force1pxHeight) {\n const charWidth = 1 /* Constants.BASE_CHAR_WIDTH */ * this.scale;\n const charHeight = 2 /* Constants.BASE_CHAR_HEIGHT */ * this.scale;\n const renderHeight = (force1pxHeight ? 1 : charHeight);\n if (dx + charWidth > target.width || dy + renderHeight > target.height) {\n console.warn('bad render request outside image data');\n return;\n }\n const charData = useLighterFont ? this.charDataLight : this.charDataNormal;\n const charIndex = getCharIndex(chCode, fontScale);\n const destWidth = target.width * 4 /* Constants.RGBA_CHANNELS_CNT */;\n const backgroundR = backgroundColor.r;\n const backgroundG = backgroundColor.g;\n const backgroundB = backgroundColor.b;\n const deltaR = color.r - backgroundR;\n const deltaG = color.g - backgroundG;\n const deltaB = color.b - backgroundB;\n const destAlpha = Math.max(foregroundAlpha, backgroundAlpha);\n const dest = target.data;\n let sourceOffset = charIndex * charWidth * charHeight;\n let row = dy * destWidth + dx * 4 /* Constants.RGBA_CHANNELS_CNT */;\n for (let y = 0; y < renderHeight; y++) {\n let column = row;\n for (let x = 0; x < charWidth; x++) {\n const c = (charData[sourceOffset++] / 255) * (foregroundAlpha / 255);\n dest[column++] = backgroundR + deltaR * c;\n dest[column++] = backgroundG + deltaG * c;\n dest[column++] = backgroundB + deltaB * c;\n dest[column++] = destAlpha;\n }\n row += destWidth;\n }\n }\n blockRenderChar(target, dx, dy, color, foregroundAlpha, backgroundColor, backgroundAlpha, force1pxHeight) {\n const charWidth = 1 /* Constants.BASE_CHAR_WIDTH */ * this.scale;\n const charHeight = 2 /* Constants.BASE_CHAR_HEIGHT */ * this.scale;\n const renderHeight = (force1pxHeight ? 1 : charHeight);\n if (dx + charWidth > target.width || dy + renderHeight > target.height) {\n console.warn('bad render request outside image data');\n return;\n }\n const destWidth = target.width * 4 /* Constants.RGBA_CHANNELS_CNT */;\n const c = 0.5 * (foregroundAlpha / 255);\n const backgroundR = backgroundColor.r;\n const backgroundG = backgroundColor.g;\n const backgroundB = backgroundColor.b;\n const deltaR = color.r - backgroundR;\n const deltaG = color.g - backgroundG;\n const deltaB = color.b - backgroundB;\n const colorR = backgroundR + deltaR * c;\n const colorG = backgroundG + deltaG * c;\n const colorB = backgroundB + deltaB * c;\n const destAlpha = Math.max(foregroundAlpha, backgroundAlpha);\n const dest = target.data;\n let row = dy * destWidth + dx * 4 /* Constants.RGBA_CHANNELS_CNT */;\n for (let y = 0; y < renderHeight; y++) {\n let column = row;\n for (let x = 0; x < charWidth; x++) {\n dest[column++] = colorR;\n dest[column++] = colorG;\n dest[column++] = colorB;\n dest[column++] = destAlpha;\n }\n row += destWidth;\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 *--------------------------------------------------------------------------------------------*/\nimport { once } from '../../../../base/common/functional.js';\nconst charTable = {\n '0': 0,\n '1': 1,\n '2': 2,\n '3': 3,\n '4': 4,\n '5': 5,\n '6': 6,\n '7': 7,\n '8': 8,\n '9': 9,\n A: 10,\n B: 11,\n C: 12,\n D: 13,\n E: 14,\n F: 15\n};\nconst decodeData = (str) => {\n const output = new Uint8ClampedArray(str.length / 2);\n for (let i = 0; i < str.length; i += 2) {\n output[i >> 1] = (charTable[str[i]] << 4) | (charTable[str[i + 1]] & 0xF);\n }\n return output;\n};\n/*\nconst encodeData = (data: Uint8ClampedArray, length: string) => {\n const chars = '0123456789ABCDEF';\n let output = '';\n for (let i = 0; i < data.length; i++) {\n output += chars[data[i] >> 4] + chars[data[i] & 0xf];\n }\n return output;\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 = {\n 1: once(() => decodeData('0000511D6300CF609C709645A78432005642574171487021003C451900274D35D762755E8B629C5BA856AF57BA649530C167D1512A272A3F6038604460398526BCA2A968DB6F8957C768BE5FBE2FB467CF5D8D5B795DC7625B5DFF50DE64C466DB2FC47CD860A65E9A2EB96CB54CE06DA763AB2EA26860524D3763536601005116008177A8705E53AB738E6A982F88BAA35B5F5B626D9C636B449B737E5B7B678598869A662F6B5B8542706C704C80736A607578685B70594A49715A4522E792')),\n 2: once(() => decodeData('000000000000000055394F383D2800008B8B1F210002000081B1CBCBCC820000847AAF6B9AAF2119BE08B8881AD60000A44FD07DCCF107015338130C00000000385972265F390B406E2437634B4B48031B12B8A0847000001E15B29A402F0000000000004B33460B00007A752C2A0000000000004D3900000084394B82013400ABA5CFC7AD9C0302A45A3E5A98AB000089A43382D97900008BA54AA087A70A0248A6A7AE6DBE0000BF6F94987EA40A01A06DCFA7A7A9030496C32F77891D0000A99FB1A0AFA80603B29AB9CA75930D010C0948354D3900000C0948354F37460D0028BE673D8400000000AF9D7B6E00002B007AA8933400007AA642675C2700007984CFB9C3985B768772A8A6B7B20000CAAECAAFC4B700009F94A6009F840009D09F9BA4CA9C0000CC8FC76DC87F0000C991C472A2000000A894A48CA7B501079BA2C9C69BA20000B19A5D3FA89000005CA6009DA2960901B0A7F0669FB200009D009E00B7890000DAD0F5D092820000D294D4C48BD10000B5A7A4A3B1A50402CAB6CBA6A2000000B5A7A4A3B1A8044FCDADD19D9CB00000B7778F7B8AAE0803C9AB5D3F5D3F00009EA09EA0BAB006039EA0989A8C7900009B9EF4D6B7C00000A9A7816CACA80000ABAC84705D3F000096DA635CDC8C00006F486F266F263D4784006124097B00374F6D2D6D2D6D4A3A95872322000000030000000000008D8939130000000000002E22A5C9CBC70600AB25C0B5C9B400061A2DB04CA67001082AA6BEBEBFC606002321DACBC19E03087AA08B6768380000282FBAC0B8CA7A88AD25BBA5A29900004C396C5894A6000040485A6E356E9442A32CD17EADA70000B4237923628600003E2DE9C1D7B500002F25BBA5A2990000231DB6AFB4A804023025C0B5CAB588062B2CBDBEC0C706882435A75CA20000002326BD6A82A908048B4B9A5A668000002423A09CB4BB060025259C9D8A7900001C1FCAB2C7C700002A2A9387ABA200002626A4A47D6E9D14333163A0C87500004B6F9C2D643A257049364936493647358A34438355497F1A0000A24C1D590000D38DFFBDD4CD3126'))\n};\n","/*---------------------------------------------------------------------------------------------\n * 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 { MinimapCharRenderer } from './minimapCharRenderer.js';\nimport { allCharCodes } from './minimapCharSheet.js';\nimport { prebakedMiniMaps } from './minimapPreBaked.js';\nimport { toUint8 } from '../../../../base/common/uint.js';\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 /**\n * Creates a new character renderer factory with the given scale.\n */\n static create(scale, fontFamily) {\n // renderers are immutable. By default we'll 'create' a new minimap\n // character renderer whenever we switch editors, no need to do extra work.\n if (this.lastCreated && scale === this.lastCreated.scale && fontFamily === this.lastFontFamily) {\n return this.lastCreated;\n }\n let factory;\n if (prebakedMiniMaps[scale]) {\n factory = new MinimapCharRenderer(prebakedMiniMaps[scale](), scale);\n }\n else {\n factory = MinimapCharRendererFactory.createFromSampleData(MinimapCharRendererFactory.createSampleData(fontFamily).data, scale);\n }\n this.lastFontFamily = fontFamily;\n this.lastCreated = factory;\n return factory;\n }\n /**\n * Creates the font sample data, writing to a canvas.\n */\n static createSampleData(fontFamily) {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n canvas.style.height = `${16 /* Constants.SAMPLED_CHAR_HEIGHT */}px`;\n canvas.height = 16 /* Constants.SAMPLED_CHAR_HEIGHT */;\n canvas.width = 96 /* Constants.CHAR_COUNT */ * 10 /* Constants.SAMPLED_CHAR_WIDTH */;\n canvas.style.width = 96 /* Constants.CHAR_COUNT */ * 10 /* Constants.SAMPLED_CHAR_WIDTH */ + 'px';\n ctx.fillStyle = '#ffffff';\n ctx.font = `bold ${16 /* Constants.SAMPLED_CHAR_HEIGHT */}px ${fontFamily}`;\n ctx.textBaseline = 'middle';\n let x = 0;\n for (const code of allCharCodes) {\n ctx.fillText(String.fromCharCode(code), x, 16 /* Constants.SAMPLED_CHAR_HEIGHT */ / 2);\n x += 10 /* Constants.SAMPLED_CHAR_WIDTH */;\n }\n return ctx.getImageData(0, 0, 96 /* Constants.CHAR_COUNT */ * 10 /* Constants.SAMPLED_CHAR_WIDTH */, 16 /* Constants.SAMPLED_CHAR_HEIGHT */);\n }\n /**\n * Creates a character renderer from the canvas sample data.\n */\n static createFromSampleData(source, scale) {\n const expectedLength = 16 /* Constants.SAMPLED_CHAR_HEIGHT */ * 10 /* Constants.SAMPLED_CHAR_WIDTH */ * 4 /* Constants.RGBA_CHANNELS_CNT */ * 96 /* Constants.CHAR_COUNT */;\n if (source.length !== expectedLength) {\n throw new Error('Unexpected source in MinimapCharRenderer');\n }\n const charData = MinimapCharRendererFactory._downsample(source, scale);\n return new MinimapCharRenderer(charData, scale);\n }\n static _downsampleChar(source, sourceOffset, dest, destOffset, scale) {\n const width = 1 /* Constants.BASE_CHAR_WIDTH */ * scale;\n const height = 2 /* Constants.BASE_CHAR_HEIGHT */ * scale;\n let targetIndex = destOffset;\n let brightest = 0;\n // This is essentially an ad-hoc rescaling algorithm. Standard approaches\n // like bicubic interpolation are awesome for scaling between image sizes,\n // but don't work so well when scaling to very small pixel values, we end\n // up with blurry, indistinct forms.\n //\n // The approach taken here is simply mapping each source pixel to the target\n // pixels, and taking the weighted values for all pixels in each, and then\n // averaging them out. Finally we apply an intensity boost in _downsample,\n // since when scaling to the smallest pixel sizes there's more black space\n // which causes characters to be much less distinct.\n for (let y = 0; y < height; y++) {\n // 1. For this destination pixel, get the source pixels we're sampling\n // from (x1, y1) to the next pixel (x2, y2)\n const sourceY1 = (y / height) * 16 /* Constants.SAMPLED_CHAR_HEIGHT */;\n const sourceY2 = ((y + 1) / height) * 16 /* Constants.SAMPLED_CHAR_HEIGHT */;\n for (let x = 0; x < width; x++) {\n const sourceX1 = (x / width) * 10 /* Constants.SAMPLED_CHAR_WIDTH */;\n const sourceX2 = ((x + 1) / width) * 10 /* Constants.SAMPLED_CHAR_WIDTH */;\n // 2. Sample all of them, summing them up and weighting them. Similar\n // to bilinear interpolation.\n let value = 0;\n let samples = 0;\n for (let sy = sourceY1; sy < sourceY2; sy++) {\n const sourceRow = sourceOffset + Math.floor(sy) * 3840 /* Constants.RGBA_SAMPLED_ROW_WIDTH */;\n const yBalance = 1 - (sy - Math.floor(sy));\n for (let sx = sourceX1; sx < sourceX2; sx++) {\n const xBalance = 1 - (sx - Math.floor(sx));\n const sourceIndex = sourceRow + Math.floor(sx) * 4 /* Constants.RGBA_CHANNELS_CNT */;\n const weight = xBalance * yBalance;\n samples += weight;\n value += ((source[sourceIndex] * source[sourceIndex + 3]) / 255) * weight;\n }\n }\n const final = value / samples;\n brightest = Math.max(brightest, final);\n dest[targetIndex++] = toUint8(final);\n }\n }\n return brightest;\n }\n static _downsample(data, scale) {\n const pixelsPerCharacter = 2 /* Constants.BASE_CHAR_HEIGHT */ * scale * 1 /* Constants.BASE_CHAR_WIDTH */ * scale;\n const resultLen = pixelsPerCharacter * 96 /* Constants.CHAR_COUNT */;\n const result = new Uint8ClampedArray(resultLen);\n let resultOffset = 0;\n let sourceOffset = 0;\n let brightest = 0;\n for (let charIndex = 0; charIndex < 96 /* Constants.CHAR_COUNT */; charIndex++) {\n brightest = Math.max(brightest, this._downsampleChar(data, sourceOffset, result, resultOffset, scale));\n resultOffset += pixelsPerCharacter;\n sourceOffset += 10 /* Constants.SAMPLED_CHAR_WIDTH */ * 4 /* Constants.RGBA_CHANNELS_CNT */;\n }\n if (brightest > 0) {\n const adjust = 255 / brightest;\n for (let i = 0; i < resultLen; i++) {\n result[i] *= adjust;\n }\n }\n return result;\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 *--------------------------------------------------------------------------------------------*/\nimport './minimap.css';\nimport * as dom from '../../../../base/browser/dom.js';\nimport { createFastDomNode } from '../../../../base/browser/fastDomNode.js';\nimport { GlobalPointerMoveMonitor } from '../../../../base/browser/globalPointerMoveMonitor.js';\nimport { Disposable } from '../../../../base/common/lifecycle.js';\nimport * as platform from '../../../../base/common/platform.js';\nimport * as strings from '../../../../base/common/strings.js';\nimport { RenderedLinesCollection } from '../../view/viewLayer.js';\nimport { PartFingerprints, ViewPart } from '../../view/viewPart.js';\nimport { MINIMAP_GUTTER_WIDTH, EditorLayoutInfoComputer } from '../../../common/config/editorOptions.js';\nimport { Range } from '../../../common/core/range.js';\nimport { RGBA8 } from '../../../common/core/rgba.js';\nimport { MinimapTokensColorTracker } from '../../../common/viewModel/minimapTokensColorTracker.js';\nimport { ViewModelDecoration } from '../../../common/viewModel.js';\nimport { minimapSelection, scrollbarShadow, minimapBackground, minimapSliderBackground, minimapSliderHoverBackground, minimapSliderActiveBackground, minimapForegroundOpacity } from '../../../../platform/theme/common/colorRegistry.js';\nimport { registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';\nimport { Selection } from '../../../common/core/selection.js';\nimport { EventType, Gesture } from '../../../../base/browser/touch.js';\nimport { MinimapCharRendererFactory } from './minimapCharRendererFactory.js';\nimport { MinimapPosition } from '../../../common/model.js';\nimport { once } from '../../../../base/common/functional.js';\n/**\n * The orthogonal distance to the slider at which dragging \"resets\". This implements \"snapping\"\n */\nconst POINTER_DRAG_RESET_DISTANCE = 140;\nconst GUTTER_DECORATION_WIDTH = 2;\nclass MinimapOptions {\n constructor(configuration, theme, tokensColorTracker) {\n const options = configuration.options;\n const pixelRatio = options.get(131 /* EditorOption.pixelRatio */);\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n const minimapLayout = layoutInfo.minimap;\n const fontInfo = options.get(46 /* EditorOption.fontInfo */);\n const minimapOpts = options.get(67 /* EditorOption.minimap */);\n this.renderMinimap = minimapLayout.renderMinimap;\n this.size = minimapOpts.size;\n this.minimapHeightIsEditorHeight = minimapLayout.minimapHeightIsEditorHeight;\n this.scrollBeyondLastLine = options.get(96 /* EditorOption.scrollBeyondLastLine */);\n this.showSlider = minimapOpts.showSlider;\n this.autohide = minimapOpts.autohide;\n this.pixelRatio = pixelRatio;\n this.typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;\n this.lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this.minimapLeft = minimapLayout.minimapLeft;\n this.minimapWidth = minimapLayout.minimapWidth;\n this.minimapHeight = layoutInfo.height;\n this.canvasInnerWidth = minimapLayout.minimapCanvasInnerWidth;\n this.canvasInnerHeight = minimapLayout.minimapCanvasInnerHeight;\n this.canvasOuterWidth = minimapLayout.minimapCanvasOuterWidth;\n this.canvasOuterHeight = minimapLayout.minimapCanvasOuterHeight;\n this.isSampling = minimapLayout.minimapIsSampling;\n this.editorHeight = layoutInfo.height;\n this.fontScale = minimapLayout.minimapScale;\n this.minimapLineHeight = minimapLayout.minimapLineHeight;\n this.minimapCharWidth = 1 /* Constants.BASE_CHAR_WIDTH */ * this.fontScale;\n this.charRenderer = once(() => MinimapCharRendererFactory.create(this.fontScale, fontInfo.fontFamily));\n this.defaultBackgroundColor = tokensColorTracker.getColor(2 /* ColorId.DefaultBackground */);\n this.backgroundColor = MinimapOptions._getMinimapBackground(theme, this.defaultBackgroundColor);\n this.foregroundAlpha = MinimapOptions._getMinimapForegroundOpacity(theme);\n }\n static _getMinimapBackground(theme, defaultBackgroundColor) {\n const themeColor = theme.getColor(minimapBackground);\n if (themeColor) {\n return new RGBA8(themeColor.rgba.r, themeColor.rgba.g, themeColor.rgba.b, Math.round(255 * themeColor.rgba.a));\n }\n return defaultBackgroundColor;\n }\n static _getMinimapForegroundOpacity(theme) {\n const themeColor = theme.getColor(minimapForegroundOpacity);\n if (themeColor) {\n return RGBA8._clamp(Math.round(255 * themeColor.rgba.a));\n }\n return 255;\n }\n equals(other) {\n return (this.renderMinimap === other.renderMinimap\n && this.size === other.size\n && this.minimapHeightIsEditorHeight === other.minimapHeightIsEditorHeight\n && this.scrollBeyondLastLine === other.scrollBeyondLastLine\n && this.showSlider === other.showSlider\n && this.autohide === other.autohide\n && this.pixelRatio === other.pixelRatio\n && this.typicalHalfwidthCharacterWidth === other.typicalHalfwidthCharacterWidth\n && this.lineHeight === other.lineHeight\n && this.minimapLeft === other.minimapLeft\n && this.minimapWidth === other.minimapWidth\n && this.minimapHeight === other.minimapHeight\n && this.canvasInnerWidth === other.canvasInnerWidth\n && this.canvasInnerHeight === other.canvasInnerHeight\n && this.canvasOuterWidth === other.canvasOuterWidth\n && this.canvasOuterHeight === other.canvasOuterHeight\n && this.isSampling === other.isSampling\n && this.editorHeight === other.editorHeight\n && this.fontScale === other.fontScale\n && this.minimapLineHeight === other.minimapLineHeight\n && this.minimapCharWidth === other.minimapCharWidth\n && this.defaultBackgroundColor && this.defaultBackgroundColor.equals(other.defaultBackgroundColor)\n && this.backgroundColor && this.backgroundColor.equals(other.backgroundColor)\n && this.foregroundAlpha === other.foregroundAlpha);\n }\n}\nclass MinimapLayout {\n constructor(scrollTop, scrollHeight, sliderNeeded, computedSliderRatio, sliderTop, sliderHeight, startLineNumber, endLineNumber) {\n this.scrollTop = scrollTop;\n this.scrollHeight = scrollHeight;\n this.sliderNeeded = sliderNeeded;\n this._computedSliderRatio = computedSliderRatio;\n this.sliderTop = sliderTop;\n this.sliderHeight = sliderHeight;\n this.startLineNumber = startLineNumber;\n this.endLineNumber = endLineNumber;\n }\n /**\n * Compute a desired `scrollPosition` such that the slider moves by `delta`.\n */\n getDesiredScrollTopFromDelta(delta) {\n return Math.round(this.scrollTop + delta / this._computedSliderRatio);\n }\n getDesiredScrollTopFromTouchLocation(pageY) {\n return Math.round((pageY - this.sliderHeight / 2) / this._computedSliderRatio);\n }\n static create(options, viewportStartLineNumber, viewportEndLineNumber, viewportStartLineNumberVerticalOffset, viewportHeight, viewportContainsWhitespaceGaps, lineCount, realLineCount, scrollTop, scrollHeight, previousLayout) {\n const pixelRatio = options.pixelRatio;\n const minimapLineHeight = options.minimapLineHeight;\n const minimapLinesFitting = Math.floor(options.canvasInnerHeight / minimapLineHeight);\n const lineHeight = options.lineHeight;\n if (options.minimapHeightIsEditorHeight) {\n const logicalScrollHeight = (realLineCount * options.lineHeight\n + (options.scrollBeyondLastLine ? viewportHeight - options.lineHeight : 0));\n const sliderHeight = Math.max(1, Math.floor(viewportHeight * viewportHeight / logicalScrollHeight));\n const maxMinimapSliderTop = Math.max(0, options.minimapHeight - sliderHeight);\n // The slider can move from 0 to `maxMinimapSliderTop`\n // in the same way `scrollTop` can move from 0 to `scrollHeight` - `viewportHeight`.\n const computedSliderRatio = (maxMinimapSliderTop) / (scrollHeight - viewportHeight);\n const sliderTop = (scrollTop * computedSliderRatio);\n const sliderNeeded = (maxMinimapSliderTop > 0);\n const maxLinesFitting = Math.floor(options.canvasInnerHeight / options.minimapLineHeight);\n return new MinimapLayout(scrollTop, scrollHeight, sliderNeeded, computedSliderRatio, sliderTop, sliderHeight, 1, Math.min(lineCount, maxLinesFitting));\n }\n // The visible line count in a viewport can change due to a number of reasons:\n // a) with the same viewport width, different scroll positions can result in partial lines being visible:\n // e.g. for a line height of 20, and a viewport height of 600\n // * scrollTop = 0 => visible lines are [1, 30]\n // * scrollTop = 10 => visible lines are [1, 31] (with lines 1 and 31 partially visible)\n // * scrollTop = 20 => visible lines are [2, 31]\n // b) whitespace gaps might make their way in the viewport (which results in a decrease in the visible line count)\n // c) we could be in the scroll beyond last line case (which also results in a decrease in the visible line count, down to possibly only one line being visible)\n // We must first establish a desirable slider height.\n let sliderHeight;\n if (viewportContainsWhitespaceGaps && viewportEndLineNumber !== lineCount) {\n // case b) from above: there are whitespace gaps in the viewport.\n // In this case, the height of the slider directly reflects the visible line count.\n const viewportLineCount = viewportEndLineNumber - viewportStartLineNumber + 1;\n sliderHeight = Math.floor(viewportLineCount * minimapLineHeight / pixelRatio);\n }\n else {\n // The slider has a stable height\n const expectedViewportLineCount = viewportHeight / lineHeight;\n sliderHeight = Math.floor(expectedViewportLineCount * minimapLineHeight / pixelRatio);\n }\n let maxMinimapSliderTop;\n if (options.scrollBeyondLastLine) {\n // The minimap slider, when dragged all the way down, will contain the last line at its top\n maxMinimapSliderTop = (lineCount - 1) * minimapLineHeight / pixelRatio;\n }\n else {\n // The minimap slider, when dragged all the way down, will contain the last line at its bottom\n maxMinimapSliderTop = Math.max(0, lineCount * minimapLineHeight / pixelRatio - sliderHeight);\n }\n maxMinimapSliderTop = Math.min(options.minimapHeight - sliderHeight, maxMinimapSliderTop);\n // The slider can move from 0 to `maxMinimapSliderTop`\n // in the same way `scrollTop` can move from 0 to `scrollHeight` - `viewportHeight`.\n const computedSliderRatio = (maxMinimapSliderTop) / (scrollHeight - viewportHeight);\n const sliderTop = (scrollTop * computedSliderRatio);\n let extraLinesAtTheBottom = 0;\n if (options.scrollBeyondLastLine) {\n const expectedViewportLineCount = viewportHeight / lineHeight;\n extraLinesAtTheBottom = expectedViewportLineCount - 1;\n }\n if (minimapLinesFitting >= lineCount + extraLinesAtTheBottom) {\n // All lines fit in the minimap\n const startLineNumber = 1;\n const endLineNumber = lineCount;\n const sliderNeeded = (maxMinimapSliderTop > 0);\n return new MinimapLayout(scrollTop, scrollHeight, sliderNeeded, computedSliderRatio, sliderTop, sliderHeight, startLineNumber, endLineNumber);\n }\n else {\n let startLineNumber = Math.max(1, Math.floor(viewportStartLineNumber - sliderTop * pixelRatio / minimapLineHeight));\n // Avoid flickering caused by a partial viewport start line\n // by being consistent w.r.t. the previous layout decision\n if (previousLayout && previousLayout.scrollHeight === scrollHeight) {\n if (previousLayout.scrollTop > scrollTop) {\n // Scrolling up => never increase `startLineNumber`\n startLineNumber = Math.min(startLineNumber, previousLayout.startLineNumber);\n }\n if (previousLayout.scrollTop < scrollTop) {\n // Scrolling down => never decrease `startLineNumber`\n startLineNumber = Math.max(startLineNumber, previousLayout.startLineNumber);\n }\n }\n const endLineNumber = Math.min(lineCount, startLineNumber + minimapLinesFitting - 1);\n const partialLine = (scrollTop - viewportStartLineNumberVerticalOffset) / lineHeight;\n const sliderTopAligned = (viewportStartLineNumber - startLineNumber + partialLine) * minimapLineHeight / pixelRatio;\n return new MinimapLayout(scrollTop, scrollHeight, true, computedSliderRatio, sliderTopAligned, sliderHeight, startLineNumber, endLineNumber);\n }\n }\n}\nclass MinimapLine {\n constructor(dy) {\n this.dy = dy;\n }\n onContentChanged() {\n this.dy = -1;\n }\n onTokensChanged() {\n this.dy = -1;\n }\n}\nMinimapLine.INVALID = new MinimapLine(-1);\nclass RenderData {\n constructor(renderedLayout, imageData, lines) {\n this.renderedLayout = renderedLayout;\n this._imageData = imageData;\n this._renderedLines = new RenderedLinesCollection(() => MinimapLine.INVALID);\n this._renderedLines._set(renderedLayout.startLineNumber, lines);\n }\n /**\n * Check if the current RenderData matches accurately the new desired layout and no painting is needed.\n */\n linesEquals(layout) {\n if (!this.scrollEquals(layout)) {\n return false;\n }\n const tmp = this._renderedLines._get();\n const lines = tmp.lines;\n for (let i = 0, len = lines.length; i < len; i++) {\n if (lines[i].dy === -1) {\n // This line is invalid\n return false;\n }\n }\n return true;\n }\n /**\n * Check if the current RenderData matches the new layout's scroll position\n */\n scrollEquals(layout) {\n return this.renderedLayout.startLineNumber === layout.startLineNumber\n && this.renderedLayout.endLineNumber === layout.endLineNumber;\n }\n _get() {\n const tmp = this._renderedLines._get();\n return {\n imageData: this._imageData,\n rendLineNumberStart: tmp.rendLineNumberStart,\n lines: tmp.lines\n };\n }\n onLinesChanged(changeFromLineNumber, changeCount) {\n return this._renderedLines.onLinesChanged(changeFromLineNumber, changeCount);\n }\n onLinesDeleted(deleteFromLineNumber, deleteToLineNumber) {\n this._renderedLines.onLinesDeleted(deleteFromLineNumber, deleteToLineNumber);\n }\n onLinesInserted(insertFromLineNumber, insertToLineNumber) {\n this._renderedLines.onLinesInserted(insertFromLineNumber, insertToLineNumber);\n }\n onTokensChanged(ranges) {\n return this._renderedLines.onTokensChanged(ranges);\n }\n}\n/**\n * Some sort of double buffering.\n *\n * Keeps two buffers around that will be rotated for painting.\n * Always gives a buffer that is filled with the background color.\n */\nclass MinimapBuffers {\n constructor(ctx, WIDTH, HEIGHT, background) {\n this._backgroundFillData = MinimapBuffers._createBackgroundFillData(WIDTH, HEIGHT, background);\n this._buffers = [\n ctx.createImageData(WIDTH, HEIGHT),\n ctx.createImageData(WIDTH, HEIGHT)\n ];\n this._lastUsedBuffer = 0;\n }\n getBuffer() {\n // rotate buffers\n this._lastUsedBuffer = 1 - this._lastUsedBuffer;\n const result = this._buffers[this._lastUsedBuffer];\n // fill with background color\n result.data.set(this._backgroundFillData);\n return result;\n }\n static _createBackgroundFillData(WIDTH, HEIGHT, background) {\n const backgroundR = background.r;\n const backgroundG = background.g;\n const backgroundB = background.b;\n const backgroundA = background.a;\n const result = new Uint8ClampedArray(WIDTH * HEIGHT * 4);\n let offset = 0;\n for (let i = 0; i < HEIGHT; i++) {\n for (let j = 0; j < WIDTH; j++) {\n result[offset] = backgroundR;\n result[offset + 1] = backgroundG;\n result[offset + 2] = backgroundB;\n result[offset + 3] = backgroundA;\n offset += 4;\n }\n }\n return result;\n }\n}\nclass MinimapSamplingState {\n constructor(samplingRatio, minimapLines) {\n this.samplingRatio = samplingRatio;\n this.minimapLines = minimapLines;\n }\n static compute(options, viewLineCount, oldSamplingState) {\n if (options.renderMinimap === 0 /* RenderMinimap.None */ || !options.isSampling) {\n return [null, []];\n }\n // ratio is intentionally not part of the layout to avoid the layout changing all the time\n // so we need to recompute it again...\n const pixelRatio = options.pixelRatio;\n const lineHeight = options.lineHeight;\n const scrollBeyondLastLine = options.scrollBeyondLastLine;\n const { minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({\n viewLineCount: viewLineCount,\n scrollBeyondLastLine: scrollBeyondLastLine,\n height: options.editorHeight,\n lineHeight: lineHeight,\n pixelRatio: pixelRatio\n });\n const ratio = viewLineCount / minimapLineCount;\n const halfRatio = ratio / 2;\n if (!oldSamplingState || oldSamplingState.minimapLines.length === 0) {\n const result = [];\n result[0] = 1;\n if (minimapLineCount > 1) {\n for (let i = 0, lastIndex = minimapLineCount - 1; i < lastIndex; i++) {\n result[i] = Math.round(i * ratio + halfRatio);\n }\n result[minimapLineCount - 1] = viewLineCount;\n }\n return [new MinimapSamplingState(ratio, result), []];\n }\n const oldMinimapLines = oldSamplingState.minimapLines;\n const oldLength = oldMinimapLines.length;\n const result = [];\n let oldIndex = 0;\n let oldDeltaLineCount = 0;\n let minViewLineNumber = 1;\n const MAX_EVENT_COUNT = 10; // generate at most 10 events, if there are more than 10 changes, just flush all previous data\n let events = [];\n let lastEvent = null;\n for (let i = 0; i < minimapLineCount; i++) {\n const fromViewLineNumber = Math.max(minViewLineNumber, Math.round(i * ratio));\n const toViewLineNumber = Math.max(fromViewLineNumber, Math.round((i + 1) * ratio));\n while (oldIndex < oldLength && oldMinimapLines[oldIndex] < fromViewLineNumber) {\n if (events.length < MAX_EVENT_COUNT) {\n const oldMinimapLineNumber = oldIndex + 1 + oldDeltaLineCount;\n if (lastEvent && lastEvent.type === 'deleted' && lastEvent._oldIndex === oldIndex - 1) {\n lastEvent.deleteToLineNumber++;\n }\n else {\n lastEvent = { type: 'deleted', _oldIndex: oldIndex, deleteFromLineNumber: oldMinimapLineNumber, deleteToLineNumber: oldMinimapLineNumber };\n events.push(lastEvent);\n }\n oldDeltaLineCount--;\n }\n oldIndex++;\n }\n let selectedViewLineNumber;\n if (oldIndex < oldLength && oldMinimapLines[oldIndex] <= toViewLineNumber) {\n // reuse the old sampled line\n selectedViewLineNumber = oldMinimapLines[oldIndex];\n oldIndex++;\n }\n else {\n if (i === 0) {\n selectedViewLineNumber = 1;\n }\n else if (i + 1 === minimapLineCount) {\n selectedViewLineNumber = viewLineCount;\n }\n else {\n selectedViewLineNumber = Math.round(i * ratio + halfRatio);\n }\n if (events.length < MAX_EVENT_COUNT) {\n const oldMinimapLineNumber = oldIndex + 1 + oldDeltaLineCount;\n if (lastEvent && lastEvent.type === 'inserted' && lastEvent._i === i - 1) {\n lastEvent.insertToLineNumber++;\n }\n else {\n lastEvent = { type: 'inserted', _i: i, insertFromLineNumber: oldMinimapLineNumber, insertToLineNumber: oldMinimapLineNumber };\n events.push(lastEvent);\n }\n oldDeltaLineCount++;\n }\n }\n result[i] = selectedViewLineNumber;\n minViewLineNumber = selectedViewLineNumber;\n }\n if (events.length < MAX_EVENT_COUNT) {\n while (oldIndex < oldLength) {\n const oldMinimapLineNumber = oldIndex + 1 + oldDeltaLineCount;\n if (lastEvent && lastEvent.type === 'deleted' && lastEvent._oldIndex === oldIndex - 1) {\n lastEvent.deleteToLineNumber++;\n }\n else {\n lastEvent = { type: 'deleted', _oldIndex: oldIndex, deleteFromLineNumber: oldMinimapLineNumber, deleteToLineNumber: oldMinimapLineNumber };\n events.push(lastEvent);\n }\n oldDeltaLineCount--;\n oldIndex++;\n }\n }\n else {\n // too many events, just give up\n events = [{ type: 'flush' }];\n }\n return [new MinimapSamplingState(ratio, result), events];\n }\n modelLineToMinimapLine(lineNumber) {\n return Math.min(this.minimapLines.length, Math.max(1, Math.round(lineNumber / this.samplingRatio)));\n }\n /**\n * Will return null if the model line ranges are not intersecting with a sampled model line.\n */\n modelLineRangeToMinimapLineRange(fromLineNumber, toLineNumber) {\n let fromLineIndex = this.modelLineToMinimapLine(fromLineNumber) - 1;\n while (fromLineIndex > 0 && this.minimapLines[fromLineIndex - 1] >= fromLineNumber) {\n fromLineIndex--;\n }\n let toLineIndex = this.modelLineToMinimapLine(toLineNumber) - 1;\n while (toLineIndex + 1 < this.minimapLines.length && this.minimapLines[toLineIndex + 1] <= toLineNumber) {\n toLineIndex++;\n }\n if (fromLineIndex === toLineIndex) {\n const sampledLineNumber = this.minimapLines[fromLineIndex];\n if (sampledLineNumber < fromLineNumber || sampledLineNumber > toLineNumber) {\n // This line is not part of the sampled lines ==> nothing to do\n return null;\n }\n }\n return [fromLineIndex + 1, toLineIndex + 1];\n }\n /**\n * Will always return a range, even if it is not intersecting with a sampled model line.\n */\n decorationLineRangeToMinimapLineRange(startLineNumber, endLineNumber) {\n let minimapLineStart = this.modelLineToMinimapLine(startLineNumber);\n let minimapLineEnd = this.modelLineToMinimapLine(endLineNumber);\n if (startLineNumber !== endLineNumber && minimapLineEnd === minimapLineStart) {\n if (minimapLineEnd === this.minimapLines.length) {\n if (minimapLineStart > 1) {\n minimapLineStart--;\n }\n }\n else {\n minimapLineEnd++;\n }\n }\n return [minimapLineStart, minimapLineEnd];\n }\n onLinesDeleted(e) {\n // have the mapping be sticky\n const deletedLineCount = e.toLineNumber - e.fromLineNumber + 1;\n let changeStartIndex = this.minimapLines.length;\n let changeEndIndex = 0;\n for (let i = this.minimapLines.length - 1; i >= 0; i--) {\n if (this.minimapLines[i] < e.fromLineNumber) {\n break;\n }\n if (this.minimapLines[i] <= e.toLineNumber) {\n // this line got deleted => move to previous available\n this.minimapLines[i] = Math.max(1, e.fromLineNumber - 1);\n changeStartIndex = Math.min(changeStartIndex, i);\n changeEndIndex = Math.max(changeEndIndex, i);\n }\n else {\n this.minimapLines[i] -= deletedLineCount;\n }\n }\n return [changeStartIndex, changeEndIndex];\n }\n onLinesInserted(e) {\n // have the mapping be sticky\n const insertedLineCount = e.toLineNumber - e.fromLineNumber + 1;\n for (let i = this.minimapLines.length - 1; i >= 0; i--) {\n if (this.minimapLines[i] < e.fromLineNumber) {\n break;\n }\n this.minimapLines[i] += insertedLineCount;\n }\n }\n}\nexport class Minimap extends ViewPart {\n constructor(context) {\n super(context);\n this.tokensColorTracker = MinimapTokensColorTracker.getInstance();\n this._selections = [];\n this._minimapSelections = null;\n this.options = new MinimapOptions(this._context.configuration, this._context.theme, this.tokensColorTracker);\n const [samplingState,] = MinimapSamplingState.compute(this.options, this._context.viewModel.getLineCount(), null);\n this._samplingState = samplingState;\n this._shouldCheckSampling = false;\n this._actual = new InnerMinimap(context.theme, this);\n }\n dispose() {\n this._actual.dispose();\n super.dispose();\n }\n getDomNode() {\n return this._actual.getDomNode();\n }\n _onOptionsMaybeChanged() {\n const opts = new MinimapOptions(this._context.configuration, this._context.theme, this.tokensColorTracker);\n if (this.options.equals(opts)) {\n return false;\n }\n this.options = opts;\n this._recreateLineSampling();\n this._actual.onDidChangeOptions();\n return true;\n }\n // ---- begin view event handlers\n onConfigurationChanged(e) {\n return this._onOptionsMaybeChanged();\n }\n onCursorStateChanged(e) {\n this._selections = e.selections;\n this._minimapSelections = null;\n return this._actual.onSelectionChanged();\n }\n onDecorationsChanged(e) {\n if (e.affectsMinimap) {\n return this._actual.onDecorationsChanged();\n }\n return false;\n }\n onFlushed(e) {\n if (this._samplingState) {\n this._shouldCheckSampling = true;\n }\n return this._actual.onFlushed();\n }\n onLinesChanged(e) {\n if (this._samplingState) {\n const minimapLineRange = this._samplingState.modelLineRangeToMinimapLineRange(e.fromLineNumber, e.fromLineNumber + e.count - 1);\n if (minimapLineRange) {\n return this._actual.onLinesChanged(minimapLineRange[0], minimapLineRange[1] - minimapLineRange[0] + 1);\n }\n else {\n return false;\n }\n }\n else {\n return this._actual.onLinesChanged(e.fromLineNumber, e.count);\n }\n }\n onLinesDeleted(e) {\n if (this._samplingState) {\n const [changeStartIndex, changeEndIndex] = this._samplingState.onLinesDeleted(e);\n if (changeStartIndex <= changeEndIndex) {\n this._actual.onLinesChanged(changeStartIndex + 1, changeEndIndex - changeStartIndex + 1);\n }\n this._shouldCheckSampling = true;\n return true;\n }\n else {\n return this._actual.onLinesDeleted(e.fromLineNumber, e.toLineNumber);\n }\n }\n onLinesInserted(e) {\n if (this._samplingState) {\n this._samplingState.onLinesInserted(e);\n this._shouldCheckSampling = true;\n return true;\n }\n else {\n return this._actual.onLinesInserted(e.fromLineNumber, e.toLineNumber);\n }\n }\n onScrollChanged(e) {\n return this._actual.onScrollChanged();\n }\n onThemeChanged(e) {\n this._actual.onThemeChanged();\n this._onOptionsMaybeChanged();\n return true;\n }\n onTokensChanged(e) {\n if (this._samplingState) {\n const ranges = [];\n for (const range of e.ranges) {\n const minimapLineRange = this._samplingState.modelLineRangeToMinimapLineRange(range.fromLineNumber, range.toLineNumber);\n if (minimapLineRange) {\n ranges.push({ fromLineNumber: minimapLineRange[0], toLineNumber: minimapLineRange[1] });\n }\n }\n if (ranges.length) {\n return this._actual.onTokensChanged(ranges);\n }\n else {\n return false;\n }\n }\n else {\n return this._actual.onTokensChanged(e.ranges);\n }\n }\n onTokensColorsChanged(e) {\n this._onOptionsMaybeChanged();\n return this._actual.onTokensColorsChanged();\n }\n onZonesChanged(e) {\n return this._actual.onZonesChanged();\n }\n // --- end event handlers\n prepareRender(ctx) {\n if (this._shouldCheckSampling) {\n this._shouldCheckSampling = false;\n this._recreateLineSampling();\n }\n }\n render(ctx) {\n let viewportStartLineNumber = ctx.visibleRange.startLineNumber;\n let viewportEndLineNumber = ctx.visibleRange.endLineNumber;\n if (this._samplingState) {\n viewportStartLineNumber = this._samplingState.modelLineToMinimapLine(viewportStartLineNumber);\n viewportEndLineNumber = this._samplingState.modelLineToMinimapLine(viewportEndLineNumber);\n }\n const minimapCtx = {\n viewportContainsWhitespaceGaps: (ctx.viewportData.whitespaceViewportData.length > 0),\n scrollWidth: ctx.scrollWidth,\n scrollHeight: ctx.scrollHeight,\n viewportStartLineNumber: viewportStartLineNumber,\n viewportEndLineNumber: viewportEndLineNumber,\n viewportStartLineNumberVerticalOffset: ctx.getVerticalOffsetForLineNumber(viewportStartLineNumber),\n scrollTop: ctx.scrollTop,\n scrollLeft: ctx.scrollLeft,\n viewportWidth: ctx.viewportWidth,\n viewportHeight: ctx.viewportHeight,\n };\n this._actual.render(minimapCtx);\n }\n //#region IMinimapModel\n _recreateLineSampling() {\n this._minimapSelections = null;\n const wasSampling = Boolean(this._samplingState);\n const [samplingState, events] = MinimapSamplingState.compute(this.options, this._context.viewModel.getLineCount(), this._samplingState);\n this._samplingState = samplingState;\n if (wasSampling && this._samplingState) {\n // was sampling, is sampling\n for (const event of events) {\n switch (event.type) {\n case 'deleted':\n this._actual.onLinesDeleted(event.deleteFromLineNumber, event.deleteToLineNumber);\n break;\n case 'inserted':\n this._actual.onLinesInserted(event.insertFromLineNumber, event.insertToLineNumber);\n break;\n case 'flush':\n this._actual.onFlushed();\n break;\n }\n }\n }\n }\n getLineCount() {\n if (this._samplingState) {\n return this._samplingState.minimapLines.length;\n }\n return this._context.viewModel.getLineCount();\n }\n getRealLineCount() {\n return this._context.viewModel.getLineCount();\n }\n getLineContent(lineNumber) {\n if (this._samplingState) {\n return this._context.viewModel.getLineContent(this._samplingState.minimapLines[lineNumber - 1]);\n }\n return this._context.viewModel.getLineContent(lineNumber);\n }\n getLineMaxColumn(lineNumber) {\n if (this._samplingState) {\n return this._context.viewModel.getLineMaxColumn(this._samplingState.minimapLines[lineNumber - 1]);\n }\n return this._context.viewModel.getLineMaxColumn(lineNumber);\n }\n getMinimapLinesRenderingData(startLineNumber, endLineNumber, needed) {\n if (this._samplingState) {\n const result = [];\n for (let lineIndex = 0, lineCount = endLineNumber - startLineNumber + 1; lineIndex < lineCount; lineIndex++) {\n if (needed[lineIndex]) {\n result[lineIndex] = this._context.viewModel.getViewLineData(this._samplingState.minimapLines[startLineNumber + lineIndex - 1]);\n }\n else {\n result[lineIndex] = null;\n }\n }\n return result;\n }\n return this._context.viewModel.getMinimapLinesRenderingData(startLineNumber, endLineNumber, needed).data;\n }\n getSelections() {\n if (this._minimapSelections === null) {\n if (this._samplingState) {\n this._minimapSelections = [];\n for (const selection of this._selections) {\n const [minimapLineStart, minimapLineEnd] = this._samplingState.decorationLineRangeToMinimapLineRange(selection.startLineNumber, selection.endLineNumber);\n this._minimapSelections.push(new Selection(minimapLineStart, selection.startColumn, minimapLineEnd, selection.endColumn));\n }\n }\n else {\n this._minimapSelections = this._selections;\n }\n }\n return this._minimapSelections;\n }\n getMinimapDecorationsInViewport(startLineNumber, endLineNumber) {\n let visibleRange;\n if (this._samplingState) {\n const modelStartLineNumber = this._samplingState.minimapLines[startLineNumber - 1];\n const modelEndLineNumber = this._samplingState.minimapLines[endLineNumber - 1];\n visibleRange = new Range(modelStartLineNumber, 1, modelEndLineNumber, this._context.viewModel.getLineMaxColumn(modelEndLineNumber));\n }\n else {\n visibleRange = new Range(startLineNumber, 1, endLineNumber, this._context.viewModel.getLineMaxColumn(endLineNumber));\n }\n const decorations = this._context.viewModel.getDecorationsInViewport(visibleRange);\n if (this._samplingState) {\n const result = [];\n for (const decoration of decorations) {\n if (!decoration.options.minimap) {\n continue;\n }\n const range = decoration.range;\n const minimapStartLineNumber = this._samplingState.modelLineToMinimapLine(range.startLineNumber);\n const minimapEndLineNumber = this._samplingState.modelLineToMinimapLine(range.endLineNumber);\n result.push(new ViewModelDecoration(new Range(minimapStartLineNumber, range.startColumn, minimapEndLineNumber, range.endColumn), decoration.options));\n }\n return result;\n }\n return decorations;\n }\n getOptions() {\n return this._context.viewModel.model.getOptions();\n }\n revealLineNumber(lineNumber) {\n if (this._samplingState) {\n lineNumber = this._samplingState.minimapLines[lineNumber - 1];\n }\n this._context.viewModel.revealRange('mouse', false, new Range(lineNumber, 1, lineNumber, 1), 1 /* viewEvents.VerticalRevealType.Center */, 0 /* ScrollType.Smooth */);\n }\n setScrollTop(scrollTop) {\n this._context.viewModel.viewLayout.setScrollPosition({\n scrollTop: scrollTop\n }, 1 /* ScrollType.Immediate */);\n }\n}\nclass InnerMinimap extends Disposable {\n constructor(theme, model) {\n super();\n this._renderDecorations = false;\n this._gestureInProgress = false;\n this._theme = theme;\n this._model = model;\n this._lastRenderData = null;\n this._buffers = null;\n this._selectionColor = this._theme.getColor(minimapSelection);\n this._domNode = createFastDomNode(document.createElement('div'));\n PartFingerprints.write(this._domNode, 8 /* PartFingerprint.Minimap */);\n this._domNode.setClassName(this._getMinimapDomNodeClassName());\n this._domNode.setPosition('absolute');\n this._domNode.setAttribute('role', 'presentation');\n this._domNode.setAttribute('aria-hidden', 'true');\n this._shadow = createFastDomNode(document.createElement('div'));\n this._shadow.setClassName('minimap-shadow-hidden');\n this._domNode.appendChild(this._shadow);\n this._canvas = createFastDomNode(document.createElement('canvas'));\n this._canvas.setPosition('absolute');\n this._canvas.setLeft(0);\n this._domNode.appendChild(this._canvas);\n this._decorationsCanvas = createFastDomNode(document.createElement('canvas'));\n this._decorationsCanvas.setPosition('absolute');\n this._decorationsCanvas.setClassName('minimap-decorations-layer');\n this._decorationsCanvas.setLeft(0);\n this._domNode.appendChild(this._decorationsCanvas);\n this._slider = createFastDomNode(document.createElement('div'));\n this._slider.setPosition('absolute');\n this._slider.setClassName('minimap-slider');\n this._slider.setLayerHinting(true);\n this._slider.setContain('strict');\n this._domNode.appendChild(this._slider);\n this._sliderHorizontal = createFastDomNode(document.createElement('div'));\n this._sliderHorizontal.setPosition('absolute');\n this._sliderHorizontal.setClassName('minimap-slider-horizontal');\n this._slider.appendChild(this._sliderHorizontal);\n this._applyLayout();\n this._pointerDownListener = dom.addStandardDisposableListener(this._domNode.domNode, dom.EventType.POINTER_DOWN, (e) => {\n e.preventDefault();\n const renderMinimap = this._model.options.renderMinimap;\n if (renderMinimap === 0 /* RenderMinimap.None */) {\n return;\n }\n if (!this._lastRenderData) {\n return;\n }\n if (this._model.options.size !== 'proportional') {\n if (e.button === 0 && this._lastRenderData) {\n // pretend the click occurred in the center of the slider\n const position = dom.getDomNodePagePosition(this._slider.domNode);\n const initialPosY = position.top + position.height / 2;\n this._startSliderDragging(e, initialPosY, this._lastRenderData.renderedLayout);\n }\n return;\n }\n const minimapLineHeight = this._model.options.minimapLineHeight;\n const internalOffsetY = (this._model.options.canvasInnerHeight / this._model.options.canvasOuterHeight) * e.offsetY;\n const lineIndex = Math.floor(internalOffsetY / minimapLineHeight);\n let lineNumber = lineIndex + this._lastRenderData.renderedLayout.startLineNumber;\n lineNumber = Math.min(lineNumber, this._model.getLineCount());\n this._model.revealLineNumber(lineNumber);\n });\n this._sliderPointerMoveMonitor = new GlobalPointerMoveMonitor();\n this._sliderPointerDownListener = dom.addStandardDisposableListener(this._slider.domNode, dom.EventType.POINTER_DOWN, (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (e.button === 0 && this._lastRenderData) {\n this._startSliderDragging(e, e.pageY, this._lastRenderData.renderedLayout);\n }\n });\n this._gestureDisposable = Gesture.addTarget(this._domNode.domNode);\n this._sliderTouchStartListener = dom.addDisposableListener(this._domNode.domNode, EventType.Start, (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (this._lastRenderData) {\n this._slider.toggleClassName('active', true);\n this._gestureInProgress = true;\n this.scrollDueToTouchEvent(e);\n }\n }, { passive: false });\n this._sliderTouchMoveListener = dom.addDisposableListener(this._domNode.domNode, EventType.Change, (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (this._lastRenderData && this._gestureInProgress) {\n this.scrollDueToTouchEvent(e);\n }\n }, { passive: false });\n this._sliderTouchEndListener = dom.addStandardDisposableListener(this._domNode.domNode, EventType.End, (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._gestureInProgress = false;\n this._slider.toggleClassName('active', false);\n });\n }\n _startSliderDragging(e, initialPosY, initialSliderState) {\n if (!e.target || !(e.target instanceof Element)) {\n return;\n }\n const initialPosX = e.pageX;\n this._slider.toggleClassName('active', true);\n const handlePointerMove = (posy, posx) => {\n const pointerOrthogonalDelta = Math.abs(posx - initialPosX);\n if (platform.isWindows && pointerOrthogonalDelta > POINTER_DRAG_RESET_DISTANCE) {\n // The pointer has wondered away from the scrollbar => reset dragging\n this._model.setScrollTop(initialSliderState.scrollTop);\n return;\n }\n const pointerDelta = posy - initialPosY;\n this._model.setScrollTop(initialSliderState.getDesiredScrollTopFromDelta(pointerDelta));\n };\n if (e.pageY !== initialPosY) {\n handlePointerMove(e.pageY, initialPosX);\n }\n this._sliderPointerMoveMonitor.startMonitoring(e.target, e.pointerId, e.buttons, pointerMoveData => handlePointerMove(pointerMoveData.pageY, pointerMoveData.pageX), () => {\n this._slider.toggleClassName('active', false);\n });\n }\n scrollDueToTouchEvent(touch) {\n const startY = this._domNode.domNode.getBoundingClientRect().top;\n const scrollTop = this._lastRenderData.renderedLayout.getDesiredScrollTopFromTouchLocation(touch.pageY - startY);\n this._model.setScrollTop(scrollTop);\n }\n dispose() {\n this._pointerDownListener.dispose();\n this._sliderPointerMoveMonitor.dispose();\n this._sliderPointerDownListener.dispose();\n this._gestureDisposable.dispose();\n this._sliderTouchStartListener.dispose();\n this._sliderTouchMoveListener.dispose();\n this._sliderTouchEndListener.dispose();\n super.dispose();\n }\n _getMinimapDomNodeClassName() {\n const class_ = ['minimap'];\n if (this._model.options.showSlider === 'always') {\n class_.push('slider-always');\n }\n else {\n class_.push('slider-mouseover');\n }\n if (this._model.options.autohide) {\n class_.push('autohide');\n }\n return class_.join(' ');\n }\n getDomNode() {\n return this._domNode;\n }\n _applyLayout() {\n this._domNode.setLeft(this._model.options.minimapLeft);\n this._domNode.setWidth(this._model.options.minimapWidth);\n this._domNode.setHeight(this._model.options.minimapHeight);\n this._shadow.setHeight(this._model.options.minimapHeight);\n this._canvas.setWidth(this._model.options.canvasOuterWidth);\n this._canvas.setHeight(this._model.options.canvasOuterHeight);\n this._canvas.domNode.width = this._model.options.canvasInnerWidth;\n this._canvas.domNode.height = this._model.options.canvasInnerHeight;\n this._decorationsCanvas.setWidth(this._model.options.canvasOuterWidth);\n this._decorationsCanvas.setHeight(this._model.options.canvasOuterHeight);\n this._decorationsCanvas.domNode.width = this._model.options.canvasInnerWidth;\n this._decorationsCanvas.domNode.height = this._model.options.canvasInnerHeight;\n this._slider.setWidth(this._model.options.minimapWidth);\n }\n _getBuffer() {\n if (!this._buffers) {\n if (this._model.options.canvasInnerWidth > 0 && this._model.options.canvasInnerHeight > 0) {\n this._buffers = new MinimapBuffers(this._canvas.domNode.getContext('2d'), this._model.options.canvasInnerWidth, this._model.options.canvasInnerHeight, this._model.options.backgroundColor);\n }\n }\n return this._buffers ? this._buffers.getBuffer() : null;\n }\n // ---- begin view event handlers\n onDidChangeOptions() {\n this._lastRenderData = null;\n this._buffers = null;\n this._applyLayout();\n this._domNode.setClassName(this._getMinimapDomNodeClassName());\n }\n onSelectionChanged() {\n this._renderDecorations = true;\n return true;\n }\n onDecorationsChanged() {\n this._renderDecorations = true;\n return true;\n }\n onFlushed() {\n this._lastRenderData = null;\n return true;\n }\n onLinesChanged(changeFromLineNumber, changeCount) {\n if (this._lastRenderData) {\n return this._lastRenderData.onLinesChanged(changeFromLineNumber, changeCount);\n }\n return false;\n }\n onLinesDeleted(deleteFromLineNumber, deleteToLineNumber) {\n var _a;\n (_a = this._lastRenderData) === null || _a === void 0 ? void 0 : _a.onLinesDeleted(deleteFromLineNumber, deleteToLineNumber);\n return true;\n }\n onLinesInserted(insertFromLineNumber, insertToLineNumber) {\n var _a;\n (_a = this._lastRenderData) === null || _a === void 0 ? void 0 : _a.onLinesInserted(insertFromLineNumber, insertToLineNumber);\n return true;\n }\n onScrollChanged() {\n this._renderDecorations = true;\n return true;\n }\n onThemeChanged() {\n this._selectionColor = this._theme.getColor(minimapSelection);\n this._renderDecorations = true;\n return true;\n }\n onTokensChanged(ranges) {\n if (this._lastRenderData) {\n return this._lastRenderData.onTokensChanged(ranges);\n }\n return false;\n }\n onTokensColorsChanged() {\n this._lastRenderData = null;\n this._buffers = null;\n return true;\n }\n onZonesChanged() {\n this._lastRenderData = null;\n return true;\n }\n // --- end event handlers\n render(renderingCtx) {\n const renderMinimap = this._model.options.renderMinimap;\n if (renderMinimap === 0 /* RenderMinimap.None */) {\n this._shadow.setClassName('minimap-shadow-hidden');\n this._sliderHorizontal.setWidth(0);\n this._sliderHorizontal.setHeight(0);\n return;\n }\n if (renderingCtx.scrollLeft + renderingCtx.viewportWidth >= renderingCtx.scrollWidth) {\n this._shadow.setClassName('minimap-shadow-hidden');\n }\n else {\n this._shadow.setClassName('minimap-shadow-visible');\n }\n const layout = MinimapLayout.create(this._model.options, renderingCtx.viewportStartLineNumber, renderingCtx.viewportEndLineNumber, renderingCtx.viewportStartLineNumberVerticalOffset, renderingCtx.viewportHeight, renderingCtx.viewportContainsWhitespaceGaps, this._model.getLineCount(), this._model.getRealLineCount(), renderingCtx.scrollTop, renderingCtx.scrollHeight, this._lastRenderData ? this._lastRenderData.renderedLayout : null);\n this._slider.setDisplay(layout.sliderNeeded ? 'block' : 'none');\n this._slider.setTop(layout.sliderTop);\n this._slider.setHeight(layout.sliderHeight);\n // Compute horizontal slider coordinates\n this._sliderHorizontal.setLeft(0);\n this._sliderHorizontal.setWidth(this._model.options.minimapWidth);\n this._sliderHorizontal.setTop(0);\n this._sliderHorizontal.setHeight(layout.sliderHeight);\n this.renderDecorations(layout);\n this._lastRenderData = this.renderLines(layout);\n }\n renderDecorations(layout) {\n if (this._renderDecorations) {\n this._renderDecorations = false;\n const selections = this._model.getSelections();\n selections.sort(Range.compareRangesUsingStarts);\n const decorations = this._model.getMinimapDecorationsInViewport(layout.startLineNumber, layout.endLineNumber);\n decorations.sort((a, b) => (a.options.zIndex || 0) - (b.options.zIndex || 0));\n const { canvasInnerWidth, canvasInnerHeight } = this._model.options;\n const lineHeight = this._model.options.minimapLineHeight;\n const characterWidth = this._model.options.minimapCharWidth;\n const tabSize = this._model.getOptions().tabSize;\n const canvasContext = this._decorationsCanvas.domNode.getContext('2d');\n canvasContext.clearRect(0, 0, canvasInnerWidth, canvasInnerHeight);\n // We first need to render line highlights and then render decorations on top of those.\n // But we need to pick a single color for each line, and use that as a line highlight.\n // This needs to be the color of the decoration with the highest `zIndex`, but priority\n // is given to the selection.\n const highlightedLines = new ContiguousLineMap(layout.startLineNumber, layout.endLineNumber, false);\n this._renderSelectionLineHighlights(canvasContext, selections, highlightedLines, layout, lineHeight);\n this._renderDecorationsLineHighlights(canvasContext, decorations, highlightedLines, layout, lineHeight);\n const lineOffsetMap = new ContiguousLineMap(layout.startLineNumber, layout.endLineNumber, null);\n this._renderSelectionsHighlights(canvasContext, selections, lineOffsetMap, layout, lineHeight, tabSize, characterWidth, canvasInnerWidth);\n this._renderDecorationsHighlights(canvasContext, decorations, lineOffsetMap, layout, lineHeight, tabSize, characterWidth, canvasInnerWidth);\n }\n }\n _renderSelectionLineHighlights(canvasContext, selections, highlightedLines, layout, lineHeight) {\n if (!this._selectionColor || this._selectionColor.isTransparent()) {\n return;\n }\n canvasContext.fillStyle = this._selectionColor.transparent(0.5).toString();\n let y1 = 0;\n let y2 = 0;\n for (const selection of selections) {\n const startLineNumber = Math.max(layout.startLineNumber, selection.startLineNumber);\n const endLineNumber = Math.min(layout.endLineNumber, selection.endLineNumber);\n if (startLineNumber > endLineNumber) {\n // entirely outside minimap's viewport\n continue;\n }\n for (let line = startLineNumber; line <= endLineNumber; line++) {\n highlightedLines.set(line, true);\n }\n const yy1 = (startLineNumber - layout.startLineNumber) * lineHeight;\n const yy2 = (endLineNumber - layout.startLineNumber) * lineHeight + lineHeight;\n if (y2 >= yy1) {\n // merge into previous\n y2 = yy2;\n }\n else {\n if (y2 > y1) {\n // flush\n canvasContext.fillRect(MINIMAP_GUTTER_WIDTH, y1, canvasContext.canvas.width, y2 - y1);\n }\n y1 = yy1;\n y2 = yy2;\n }\n }\n if (y2 > y1) {\n // flush\n canvasContext.fillRect(MINIMAP_GUTTER_WIDTH, y1, canvasContext.canvas.width, y2 - y1);\n }\n }\n _renderDecorationsLineHighlights(canvasContext, decorations, highlightedLines, layout, lineHeight) {\n const highlightColors = new Map();\n // Loop backwards to hit first decorations with higher `zIndex`\n for (let i = decorations.length - 1; i >= 0; i--) {\n const decoration = decorations[i];\n const minimapOptions = decoration.options.minimap;\n if (!minimapOptions || minimapOptions.position !== MinimapPosition.Inline) {\n continue;\n }\n const startLineNumber = Math.max(layout.startLineNumber, decoration.range.startLineNumber);\n const endLineNumber = Math.min(layout.endLineNumber, decoration.range.endLineNumber);\n if (startLineNumber > endLineNumber) {\n // entirely outside minimap's viewport\n continue;\n }\n const decorationColor = minimapOptions.getColor(this._theme.value);\n if (!decorationColor || decorationColor.isTransparent()) {\n continue;\n }\n let highlightColor = highlightColors.get(decorationColor.toString());\n if (!highlightColor) {\n highlightColor = decorationColor.transparent(0.5).toString();\n highlightColors.set(decorationColor.toString(), highlightColor);\n }\n canvasContext.fillStyle = highlightColor;\n for (let line = startLineNumber; line <= endLineNumber; line++) {\n if (highlightedLines.has(line)) {\n continue;\n }\n highlightedLines.set(line, true);\n const y = (startLineNumber - layout.startLineNumber) * lineHeight;\n canvasContext.fillRect(MINIMAP_GUTTER_WIDTH, y, canvasContext.canvas.width, lineHeight);\n }\n }\n }\n _renderSelectionsHighlights(canvasContext, selections, lineOffsetMap, layout, lineHeight, tabSize, characterWidth, canvasInnerWidth) {\n if (!this._selectionColor || this._selectionColor.isTransparent()) {\n return;\n }\n for (const selection of selections) {\n const startLineNumber = Math.max(layout.startLineNumber, selection.startLineNumber);\n const endLineNumber = Math.min(layout.endLineNumber, selection.endLineNumber);\n if (startLineNumber > endLineNumber) {\n // entirely outside minimap's viewport\n continue;\n }\n for (let line = startLineNumber; line <= endLineNumber; line++) {\n this.renderDecorationOnLine(canvasContext, lineOffsetMap, selection, this._selectionColor, layout, line, lineHeight, lineHeight, tabSize, characterWidth, canvasInnerWidth);\n }\n }\n }\n _renderDecorationsHighlights(canvasContext, decorations, lineOffsetMap, layout, lineHeight, tabSize, characterWidth, canvasInnerWidth) {\n // Loop forwards to hit first decorations with lower `zIndex`\n for (const decoration of decorations) {\n const minimapOptions = decoration.options.minimap;\n if (!minimapOptions) {\n continue;\n }\n const startLineNumber = Math.max(layout.startLineNumber, decoration.range.startLineNumber);\n const endLineNumber = Math.min(layout.endLineNumber, decoration.range.endLineNumber);\n if (startLineNumber > endLineNumber) {\n // entirely outside minimap's viewport\n continue;\n }\n const decorationColor = minimapOptions.getColor(this._theme.value);\n if (!decorationColor || decorationColor.isTransparent()) {\n continue;\n }\n for (let line = startLineNumber; line <= endLineNumber; line++) {\n switch (minimapOptions.position) {\n case MinimapPosition.Inline:\n this.renderDecorationOnLine(canvasContext, lineOffsetMap, decoration.range, decorationColor, layout, line, lineHeight, lineHeight, tabSize, characterWidth, canvasInnerWidth);\n continue;\n case MinimapPosition.Gutter: {\n const y = (line - layout.startLineNumber) * lineHeight;\n const x = 2;\n this.renderDecoration(canvasContext, decorationColor, x, y, GUTTER_DECORATION_WIDTH, lineHeight);\n continue;\n }\n }\n }\n }\n }\n renderDecorationOnLine(canvasContext, lineOffsetMap, decorationRange, decorationColor, layout, lineNumber, height, lineHeight, tabSize, charWidth, canvasInnerWidth) {\n const y = (lineNumber - layout.startLineNumber) * lineHeight;\n // Skip rendering the line if it's vertically outside our viewport\n if (y + height < 0 || y > this._model.options.canvasInnerHeight) {\n return;\n }\n const { startLineNumber, endLineNumber } = decorationRange;\n const startColumn = (startLineNumber === lineNumber ? decorationRange.startColumn : 1);\n const endColumn = (endLineNumber === lineNumber ? decorationRange.endColumn : this._model.getLineMaxColumn(lineNumber));\n const x1 = this.getXOffsetForPosition(lineOffsetMap, lineNumber, startColumn, tabSize, charWidth, canvasInnerWidth);\n const x2 = this.getXOffsetForPosition(lineOffsetMap, lineNumber, endColumn, tabSize, charWidth, canvasInnerWidth);\n this.renderDecoration(canvasContext, decorationColor, x1, y, x2 - x1, height);\n }\n getXOffsetForPosition(lineOffsetMap, lineNumber, column, tabSize, charWidth, canvasInnerWidth) {\n if (column === 1) {\n return MINIMAP_GUTTER_WIDTH;\n }\n const minimumXOffset = (column - 1) * charWidth;\n if (minimumXOffset >= canvasInnerWidth) {\n // there is no need to look at actual characters,\n // as this column is certainly after the minimap width\n return canvasInnerWidth;\n }\n // Cache line offset data so that it is only read once per line\n let lineIndexToXOffset = lineOffsetMap.get(lineNumber);\n if (!lineIndexToXOffset) {\n const lineData = this._model.getLineContent(lineNumber);\n lineIndexToXOffset = [MINIMAP_GUTTER_WIDTH];\n let prevx = MINIMAP_GUTTER_WIDTH;\n for (let i = 1; i < lineData.length + 1; i++) {\n const charCode = lineData.charCodeAt(i - 1);\n const dx = charCode === 9 /* CharCode.Tab */\n ? tabSize * charWidth\n : strings.isFullWidthCharacter(charCode)\n ? 2 * charWidth\n : charWidth;\n const x = prevx + dx;\n if (x >= canvasInnerWidth) {\n // no need to keep on going, as we've hit the canvas width\n lineIndexToXOffset[i] = canvasInnerWidth;\n break;\n }\n lineIndexToXOffset[i] = x;\n prevx = x;\n }\n lineOffsetMap.set(lineNumber, lineIndexToXOffset);\n }\n if (column - 1 < lineIndexToXOffset.length) {\n return lineIndexToXOffset[column - 1];\n }\n // goes over the canvas width\n return canvasInnerWidth;\n }\n renderDecoration(canvasContext, decorationColor, x, y, width, height) {\n canvasContext.fillStyle = decorationColor && decorationColor.toString() || '';\n canvasContext.fillRect(x, y, width, height);\n }\n renderLines(layout) {\n const startLineNumber = layout.startLineNumber;\n const endLineNumber = layout.endLineNumber;\n const minimapLineHeight = this._model.options.minimapLineHeight;\n // Check if nothing changed w.r.t. lines from last frame\n if (this._lastRenderData && this._lastRenderData.linesEquals(layout)) {\n const _lastData = this._lastRenderData._get();\n // Nice!! Nothing changed from last frame\n return new RenderData(layout, _lastData.imageData, _lastData.lines);\n }\n // Oh well!! We need to repaint some lines...\n const imageData = this._getBuffer();\n if (!imageData) {\n // 0 width or 0 height canvas, nothing to do\n return null;\n }\n // Render untouched lines by using last rendered data.\n const [_dirtyY1, _dirtyY2, needed] = InnerMinimap._renderUntouchedLines(imageData, startLineNumber, endLineNumber, minimapLineHeight, this._lastRenderData);\n // Fetch rendering info from view model for rest of lines that need rendering.\n const lineInfo = this._model.getMinimapLinesRenderingData(startLineNumber, endLineNumber, needed);\n const tabSize = this._model.getOptions().tabSize;\n const defaultBackground = this._model.options.defaultBackgroundColor;\n const background = this._model.options.backgroundColor;\n const foregroundAlpha = this._model.options.foregroundAlpha;\n const tokensColorTracker = this._model.tokensColorTracker;\n const useLighterFont = tokensColorTracker.backgroundIsLight();\n const renderMinimap = this._model.options.renderMinimap;\n const charRenderer = this._model.options.charRenderer();\n const fontScale = this._model.options.fontScale;\n const minimapCharWidth = this._model.options.minimapCharWidth;\n const baseCharHeight = (renderMinimap === 1 /* RenderMinimap.Text */ ? 2 /* Constants.BASE_CHAR_HEIGHT */ : 2 /* Constants.BASE_CHAR_HEIGHT */ + 1);\n const renderMinimapLineHeight = baseCharHeight * fontScale;\n const innerLinePadding = (minimapLineHeight > renderMinimapLineHeight ? Math.floor((minimapLineHeight - renderMinimapLineHeight) / 2) : 0);\n // Render the rest of lines\n const backgroundA = background.a / 255;\n const renderBackground = new RGBA8(Math.round((background.r - defaultBackground.r) * backgroundA + defaultBackground.r), Math.round((background.g - defaultBackground.g) * backgroundA + defaultBackground.g), Math.round((background.b - defaultBackground.b) * backgroundA + defaultBackground.b), 255);\n let dy = 0;\n const renderedLines = [];\n for (let lineIndex = 0, lineCount = endLineNumber - startLineNumber + 1; lineIndex < lineCount; lineIndex++) {\n if (needed[lineIndex]) {\n InnerMinimap._renderLine(imageData, renderBackground, background.a, useLighterFont, renderMinimap, minimapCharWidth, tokensColorTracker, foregroundAlpha, charRenderer, dy, innerLinePadding, tabSize, lineInfo[lineIndex], fontScale, minimapLineHeight);\n }\n renderedLines[lineIndex] = new MinimapLine(dy);\n dy += minimapLineHeight;\n }\n const dirtyY1 = (_dirtyY1 === -1 ? 0 : _dirtyY1);\n const dirtyY2 = (_dirtyY2 === -1 ? imageData.height : _dirtyY2);\n const dirtyHeight = dirtyY2 - dirtyY1;\n // Finally, paint to the canvas\n const ctx = this._canvas.domNode.getContext('2d');\n ctx.putImageData(imageData, 0, 0, 0, dirtyY1, imageData.width, dirtyHeight);\n // Save rendered data for reuse on next frame if possible\n return new RenderData(layout, imageData, renderedLines);\n }\n static _renderUntouchedLines(target, startLineNumber, endLineNumber, minimapLineHeight, lastRenderData) {\n const needed = [];\n if (!lastRenderData) {\n for (let i = 0, len = endLineNumber - startLineNumber + 1; i < len; i++) {\n needed[i] = true;\n }\n return [-1, -1, needed];\n }\n const _lastData = lastRenderData._get();\n const lastTargetData = _lastData.imageData.data;\n const lastStartLineNumber = _lastData.rendLineNumberStart;\n const lastLines = _lastData.lines;\n const lastLinesLength = lastLines.length;\n const WIDTH = target.width;\n const targetData = target.data;\n const maxDestPixel = (endLineNumber - startLineNumber + 1) * minimapLineHeight * WIDTH * 4;\n let dirtyPixel1 = -1; // the pixel offset up to which all the data is equal to the prev frame\n let dirtyPixel2 = -1; // the pixel offset after which all the data is equal to the prev frame\n let copySourceStart = -1;\n let copySourceEnd = -1;\n let copyDestStart = -1;\n let copyDestEnd = -1;\n let dest_dy = 0;\n for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n const lineIndex = lineNumber - startLineNumber;\n const lastLineIndex = lineNumber - lastStartLineNumber;\n const source_dy = (lastLineIndex >= 0 && lastLineIndex < lastLinesLength ? lastLines[lastLineIndex].dy : -1);\n if (source_dy === -1) {\n needed[lineIndex] = true;\n dest_dy += minimapLineHeight;\n continue;\n }\n const sourceStart = source_dy * WIDTH * 4;\n const sourceEnd = (source_dy + minimapLineHeight) * WIDTH * 4;\n const destStart = dest_dy * WIDTH * 4;\n const destEnd = (dest_dy + minimapLineHeight) * WIDTH * 4;\n if (copySourceEnd === sourceStart && copyDestEnd === destStart) {\n // contiguous zone => extend copy request\n copySourceEnd = sourceEnd;\n copyDestEnd = destEnd;\n }\n else {\n if (copySourceStart !== -1) {\n // flush existing copy request\n targetData.set(lastTargetData.subarray(copySourceStart, copySourceEnd), copyDestStart);\n if (dirtyPixel1 === -1 && copySourceStart === 0 && copySourceStart === copyDestStart) {\n dirtyPixel1 = copySourceEnd;\n }\n if (dirtyPixel2 === -1 && copySourceEnd === maxDestPixel && copySourceStart === copyDestStart) {\n dirtyPixel2 = copySourceStart;\n }\n }\n copySourceStart = sourceStart;\n copySourceEnd = sourceEnd;\n copyDestStart = destStart;\n copyDestEnd = destEnd;\n }\n needed[lineIndex] = false;\n dest_dy += minimapLineHeight;\n }\n if (copySourceStart !== -1) {\n // flush existing copy request\n targetData.set(lastTargetData.subarray(copySourceStart, copySourceEnd), copyDestStart);\n if (dirtyPixel1 === -1 && copySourceStart === 0 && copySourceStart === copyDestStart) {\n dirtyPixel1 = copySourceEnd;\n }\n if (dirtyPixel2 === -1 && copySourceEnd === maxDestPixel && copySourceStart === copyDestStart) {\n dirtyPixel2 = copySourceStart;\n }\n }\n const dirtyY1 = (dirtyPixel1 === -1 ? -1 : dirtyPixel1 / (WIDTH * 4));\n const dirtyY2 = (dirtyPixel2 === -1 ? -1 : dirtyPixel2 / (WIDTH * 4));\n return [dirtyY1, dirtyY2, needed];\n }\n static _renderLine(target, backgroundColor, backgroundAlpha, useLighterFont, renderMinimap, charWidth, colorTracker, foregroundAlpha, minimapCharRenderer, dy, innerLinePadding, tabSize, lineData, fontScale, minimapLineHeight) {\n const content = lineData.content;\n const tokens = lineData.tokens;\n const maxDx = target.width - charWidth;\n const force1pxHeight = (minimapLineHeight === 1);\n let dx = MINIMAP_GUTTER_WIDTH;\n let charIndex = 0;\n let tabsCharDelta = 0;\n for (let tokenIndex = 0, tokensLen = tokens.getCount(); tokenIndex < tokensLen; tokenIndex++) {\n const tokenEndIndex = tokens.getEndOffset(tokenIndex);\n const tokenColorId = tokens.getForeground(tokenIndex);\n const tokenColor = colorTracker.getColor(tokenColorId);\n for (; charIndex < tokenEndIndex; charIndex++) {\n if (dx > maxDx) {\n // hit edge of minimap\n return;\n }\n const charCode = content.charCodeAt(charIndex);\n if (charCode === 9 /* CharCode.Tab */) {\n const insertSpacesCount = tabSize - (charIndex + tabsCharDelta) % tabSize;\n tabsCharDelta += insertSpacesCount - 1;\n // No need to render anything since tab is invisible\n dx += insertSpacesCount * charWidth;\n }\n else if (charCode === 32 /* CharCode.Space */) {\n // No need to render anything since space is invisible\n dx += charWidth;\n }\n else {\n // Render twice for a full width character\n const count = strings.isFullWidthCharacter(charCode) ? 2 : 1;\n for (let i = 0; i < count; i++) {\n if (renderMinimap === 2 /* RenderMinimap.Blocks */) {\n minimapCharRenderer.blockRenderChar(target, dx, dy + innerLinePadding, tokenColor, foregroundAlpha, backgroundColor, backgroundAlpha, force1pxHeight);\n }\n else { // RenderMinimap.Text\n minimapCharRenderer.renderChar(target, dx, dy + innerLinePadding, charCode, tokenColor, foregroundAlpha, backgroundColor, backgroundAlpha, fontScale, useLighterFont, force1pxHeight);\n }\n dx += charWidth;\n if (dx > maxDx) {\n // hit edge of minimap\n return;\n }\n }\n }\n }\n }\n }\n}\nclass ContiguousLineMap {\n constructor(startLineNumber, endLineNumber, defaultValue) {\n this._startLineNumber = startLineNumber;\n this._endLineNumber = endLineNumber;\n this._defaultValue = defaultValue;\n this._values = [];\n for (let i = 0, count = this._endLineNumber - this._startLineNumber + 1; i < count; i++) {\n this._values[i] = defaultValue;\n }\n }\n has(lineNumber) {\n return (this.get(lineNumber) !== this._defaultValue);\n }\n set(lineNumber, value) {\n if (lineNumber < this._startLineNumber || lineNumber > this._endLineNumber) {\n return;\n }\n this._values[lineNumber - this._startLineNumber] = value;\n }\n get(lineNumber) {\n if (lineNumber < this._startLineNumber || lineNumber > this._endLineNumber) {\n return this._defaultValue;\n }\n return this._values[lineNumber - this._startLineNumber];\n }\n}\nregisterThemingParticipant((theme, collector) => {\n const sliderBackground = theme.getColor(minimapSliderBackground);\n if (sliderBackground) {\n collector.addRule(`.monaco-editor .minimap-slider .minimap-slider-horizontal { background: ${sliderBackground}; }`);\n }\n const sliderHoverBackground = theme.getColor(minimapSliderHoverBackground);\n if (sliderHoverBackground) {\n collector.addRule(`.monaco-editor .minimap-slider:hover .minimap-slider-horizontal { background: ${sliderHoverBackground}; }`);\n }\n const sliderActiveBackground = theme.getColor(minimapSliderActiveBackground);\n if (sliderActiveBackground) {\n collector.addRule(`.monaco-editor .minimap-slider.active .minimap-slider-horizontal { background: ${sliderActiveBackground}; }`);\n }\n const shadow = theme.getColor(scrollbarShadow);\n if (shadow) {\n collector.addRule(`.monaco-editor .minimap-shadow-visible { box-shadow: ${shadow} -6px 0 6px -6px inset; }`);\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 *--------------------------------------------------------------------------------------------*/\nimport './overlayWidgets.css';\nimport { createFastDomNode } from '../../../../base/browser/fastDomNode.js';\nimport { PartFingerprints, ViewPart } from '../../view/viewPart.js';\nexport class ViewOverlayWidgets extends ViewPart {\n constructor(context) {\n super(context);\n const options = this._context.configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n this._widgets = {};\n this._verticalScrollbarWidth = layoutInfo.verticalScrollbarWidth;\n this._minimapWidth = layoutInfo.minimap.minimapWidth;\n this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight;\n this._editorHeight = layoutInfo.height;\n this._editorWidth = layoutInfo.width;\n this._domNode = createFastDomNode(document.createElement('div'));\n PartFingerprints.write(this._domNode, 4 /* PartFingerprint.OverlayWidgets */);\n this._domNode.setClassName('overlayWidgets');\n }\n dispose() {\n super.dispose();\n this._widgets = {};\n }\n getDomNode() {\n return this._domNode;\n }\n // ---- begin view event handlers\n onConfigurationChanged(e) {\n const options = this._context.configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n this._verticalScrollbarWidth = layoutInfo.verticalScrollbarWidth;\n this._minimapWidth = layoutInfo.minimap.minimapWidth;\n this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight;\n this._editorHeight = layoutInfo.height;\n this._editorWidth = layoutInfo.width;\n return true;\n }\n // ---- end view event handlers\n addWidget(widget) {\n const domNode = createFastDomNode(widget.getDomNode());\n this._widgets[widget.getId()] = {\n widget: widget,\n preference: null,\n domNode: domNode\n };\n // This is sync because a widget wants to be in the dom\n domNode.setPosition('absolute');\n domNode.setAttribute('widgetId', widget.getId());\n this._domNode.appendChild(domNode);\n this.setShouldRender();\n }\n setWidgetPosition(widget, preference) {\n const widgetData = this._widgets[widget.getId()];\n if (widgetData.preference === preference) {\n return false;\n }\n widgetData.preference = preference;\n this.setShouldRender();\n return true;\n }\n removeWidget(widget) {\n const widgetId = widget.getId();\n if (this._widgets.hasOwnProperty(widgetId)) {\n const widgetData = this._widgets[widgetId];\n const domNode = widgetData.domNode.domNode;\n delete this._widgets[widgetId];\n domNode.parentNode.removeChild(domNode);\n this.setShouldRender();\n }\n }\n _renderWidget(widgetData) {\n const domNode = widgetData.domNode;\n if (widgetData.preference === null) {\n domNode.setTop('');\n return;\n }\n if (widgetData.preference === 0 /* OverlayWidgetPositionPreference.TOP_RIGHT_CORNER */) {\n domNode.setTop(0);\n domNode.setRight((2 * this._verticalScrollbarWidth) + this._minimapWidth);\n }\n else if (widgetData.preference === 1 /* OverlayWidgetPositionPreference.BOTTOM_RIGHT_CORNER */) {\n const widgetHeight = domNode.domNode.clientHeight;\n domNode.setTop((this._editorHeight - widgetHeight - 2 * this._horizontalScrollbarHeight));\n domNode.setRight((2 * this._verticalScrollbarWidth) + this._minimapWidth);\n }\n else if (widgetData.preference === 2 /* OverlayWidgetPositionPreference.TOP_CENTER */) {\n domNode.setTop(0);\n domNode.domNode.style.right = '50%';\n }\n }\n prepareRender(ctx) {\n // Nothing to read\n }\n render(ctx) {\n this._domNode.setWidth(this._editorWidth);\n const keys = Object.keys(this._widgets);\n for (let i = 0, len = keys.length; i < len; i++) {\n const widgetId = keys[i];\n this._renderWidget(this._widgets[widgetId]);\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 *--------------------------------------------------------------------------------------------*/\nimport { createFastDomNode } from '../../../../base/browser/fastDomNode.js';\nimport { Color } from '../../../../base/common/color.js';\nimport { ViewPart } from '../../view/viewPart.js';\nimport { Position } from '../../../common/core/position.js';\nimport { TokenizationRegistry } from '../../../common/languages.js';\nimport { editorCursorForeground, editorOverviewRulerBorder, editorOverviewRulerBackground } from '../../../common/core/editorColorRegistry.js';\nimport { OverviewRulerDecorationsGroup } from '../../../common/viewModel.js';\nclass Settings {\n constructor(config, theme) {\n const options = config.options;\n this.lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this.pixelRatio = options.get(131 /* EditorOption.pixelRatio */);\n this.overviewRulerLanes = options.get(76 /* EditorOption.overviewRulerLanes */);\n this.renderBorder = options.get(75 /* EditorOption.overviewRulerBorder */);\n const borderColor = theme.getColor(editorOverviewRulerBorder);\n this.borderColor = borderColor ? borderColor.toString() : null;\n this.hideCursor = options.get(54 /* EditorOption.hideCursorInOverviewRuler */);\n const cursorColor = theme.getColor(editorCursorForeground);\n this.cursorColor = cursorColor ? cursorColor.transparent(0.7).toString() : null;\n this.themeType = theme.type;\n const minimapOpts = options.get(67 /* EditorOption.minimap */);\n const minimapEnabled = minimapOpts.enabled;\n const minimapSide = minimapOpts.side;\n const themeColor = theme.getColor(editorOverviewRulerBackground);\n const defaultBackground = TokenizationRegistry.getDefaultBackground();\n let backgroundColor = null;\n if (themeColor !== undefined) {\n backgroundColor = themeColor;\n }\n else if (minimapEnabled) {\n backgroundColor = defaultBackground;\n }\n if (backgroundColor === null || minimapSide === 'left') {\n this.backgroundColor = null;\n }\n else {\n this.backgroundColor = Color.Format.CSS.formatHex(backgroundColor);\n }\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n const position = layoutInfo.overviewRuler;\n this.top = position.top;\n this.right = position.right;\n this.domWidth = position.width;\n this.domHeight = position.height;\n if (this.overviewRulerLanes === 0) {\n // overview ruler is off\n this.canvasWidth = 0;\n this.canvasHeight = 0;\n }\n else {\n this.canvasWidth = (this.domWidth * this.pixelRatio) | 0;\n this.canvasHeight = (this.domHeight * this.pixelRatio) | 0;\n }\n const [x, w] = this._initLanes(1, this.canvasWidth, this.overviewRulerLanes);\n this.x = x;\n this.w = w;\n }\n _initLanes(canvasLeftOffset, canvasWidth, laneCount) {\n const remainingWidth = canvasWidth - canvasLeftOffset;\n if (laneCount >= 3) {\n const leftWidth = Math.floor(remainingWidth / 3);\n const rightWidth = Math.floor(remainingWidth / 3);\n const centerWidth = remainingWidth - leftWidth - rightWidth;\n const leftOffset = canvasLeftOffset;\n const centerOffset = leftOffset + leftWidth;\n const rightOffset = leftOffset + leftWidth + centerWidth;\n return [\n [\n 0,\n leftOffset,\n centerOffset,\n leftOffset,\n rightOffset,\n leftOffset,\n centerOffset,\n leftOffset, // Left | Center | Right\n ], [\n 0,\n leftWidth,\n centerWidth,\n leftWidth + centerWidth,\n rightWidth,\n leftWidth + centerWidth + rightWidth,\n centerWidth + rightWidth,\n leftWidth + centerWidth + rightWidth, // Left | Center | Right\n ]\n ];\n }\n else if (laneCount === 2) {\n const leftWidth = Math.floor(remainingWidth / 2);\n const rightWidth = remainingWidth - leftWidth;\n const leftOffset = canvasLeftOffset;\n const rightOffset = leftOffset + leftWidth;\n return [\n [\n 0,\n leftOffset,\n leftOffset,\n leftOffset,\n rightOffset,\n leftOffset,\n leftOffset,\n leftOffset, // Left | Center | Right\n ], [\n 0,\n leftWidth,\n leftWidth,\n leftWidth,\n rightWidth,\n leftWidth + rightWidth,\n leftWidth + rightWidth,\n leftWidth + rightWidth, // Left | Center | Right\n ]\n ];\n }\n else {\n const offset = canvasLeftOffset;\n const width = remainingWidth;\n return [\n [\n 0,\n offset,\n offset,\n offset,\n offset,\n offset,\n offset,\n offset, // Left | Center | Right\n ], [\n 0,\n width,\n width,\n width,\n width,\n width,\n width,\n width, // Left | Center | Right\n ]\n ];\n }\n }\n equals(other) {\n return (this.lineHeight === other.lineHeight\n && this.pixelRatio === other.pixelRatio\n && this.overviewRulerLanes === other.overviewRulerLanes\n && this.renderBorder === other.renderBorder\n && this.borderColor === other.borderColor\n && this.hideCursor === other.hideCursor\n && this.cursorColor === other.cursorColor\n && this.themeType === other.themeType\n && this.backgroundColor === other.backgroundColor\n && this.top === other.top\n && this.right === other.right\n && this.domWidth === other.domWidth\n && this.domHeight === other.domHeight\n && this.canvasWidth === other.canvasWidth\n && this.canvasHeight === other.canvasHeight);\n }\n}\nexport class DecorationsOverviewRuler extends ViewPart {\n constructor(context) {\n super(context);\n this._domNode = createFastDomNode(document.createElement('canvas'));\n this._domNode.setClassName('decorationsOverviewRuler');\n this._domNode.setPosition('absolute');\n this._domNode.setLayerHinting(true);\n this._domNode.setContain('strict');\n this._domNode.setAttribute('aria-hidden', 'true');\n this._updateSettings(false);\n this._tokensColorTrackerListener = TokenizationRegistry.onDidChange((e) => {\n if (e.changedColorMap) {\n this._updateSettings(true);\n }\n });\n this._cursorPositions = [];\n }\n dispose() {\n super.dispose();\n this._tokensColorTrackerListener.dispose();\n }\n _updateSettings(renderNow) {\n const newSettings = new Settings(this._context.configuration, this._context.theme);\n if (this._settings && this._settings.equals(newSettings)) {\n // nothing to do\n return false;\n }\n this._settings = newSettings;\n this._domNode.setTop(this._settings.top);\n this._domNode.setRight(this._settings.right);\n this._domNode.setWidth(this._settings.domWidth);\n this._domNode.setHeight(this._settings.domHeight);\n this._domNode.domNode.width = this._settings.canvasWidth;\n this._domNode.domNode.height = this._settings.canvasHeight;\n if (renderNow) {\n this._render();\n }\n return true;\n }\n // ---- begin view event handlers\n onConfigurationChanged(e) {\n return this._updateSettings(false);\n }\n onCursorStateChanged(e) {\n this._cursorPositions = [];\n for (let i = 0, len = e.selections.length; i < len; i++) {\n this._cursorPositions[i] = e.selections[i].getPosition();\n }\n this._cursorPositions.sort(Position.compare);\n return true;\n }\n onDecorationsChanged(e) {\n if (e.affectsOverviewRuler) {\n return true;\n }\n return false;\n }\n onFlushed(e) {\n return true;\n }\n onScrollChanged(e) {\n return e.scrollHeightChanged;\n }\n onZonesChanged(e) {\n return true;\n }\n onThemeChanged(e) {\n return this._updateSettings(false);\n }\n // ---- end view event handlers\n getDomNode() {\n return this._domNode.domNode;\n }\n prepareRender(ctx) {\n // Nothing to read\n }\n render(editorCtx) {\n this._render();\n }\n _render() {\n if (this._settings.overviewRulerLanes === 0) {\n // overview ruler is off\n this._domNode.setBackgroundColor(this._settings.backgroundColor ? this._settings.backgroundColor : '');\n this._domNode.setDisplay('none');\n return;\n }\n this._domNode.setDisplay('block');\n const canvasWidth = this._settings.canvasWidth;\n const canvasHeight = this._settings.canvasHeight;\n const lineHeight = this._settings.lineHeight;\n const viewLayout = this._context.viewLayout;\n const outerHeight = this._context.viewLayout.getScrollHeight();\n const heightRatio = canvasHeight / outerHeight;\n const decorations = this._context.viewModel.getAllOverviewRulerDecorations(this._context.theme);\n const minDecorationHeight = (6 /* Constants.MIN_DECORATION_HEIGHT */ * this._settings.pixelRatio) | 0;\n const halfMinDecorationHeight = (minDecorationHeight / 2) | 0;\n const canvasCtx = this._domNode.domNode.getContext('2d');\n if (this._settings.backgroundColor === null) {\n canvasCtx.clearRect(0, 0, canvasWidth, canvasHeight);\n }\n else {\n canvasCtx.fillStyle = this._settings.backgroundColor;\n canvasCtx.fillRect(0, 0, canvasWidth, canvasHeight);\n }\n const x = this._settings.x;\n const w = this._settings.w;\n decorations.sort(OverviewRulerDecorationsGroup.cmp);\n for (const decorationGroup of decorations) {\n const color = decorationGroup.color;\n const decorationGroupData = decorationGroup.data;\n canvasCtx.fillStyle = color;\n let prevLane = 0;\n let prevY1 = 0;\n let prevY2 = 0;\n for (let i = 0, len = decorationGroupData.length / 3; i < len; i++) {\n const lane = decorationGroupData[3 * i];\n const startLineNumber = decorationGroupData[3 * i + 1];\n const endLineNumber = decorationGroupData[3 * i + 2];\n let y1 = (viewLayout.getVerticalOffsetForLineNumber(startLineNumber) * heightRatio) | 0;\n let y2 = ((viewLayout.getVerticalOffsetForLineNumber(endLineNumber) + lineHeight) * heightRatio) | 0;\n const height = y2 - y1;\n if (height < minDecorationHeight) {\n let yCenter = ((y1 + y2) / 2) | 0;\n if (yCenter < halfMinDecorationHeight) {\n yCenter = halfMinDecorationHeight;\n }\n else if (yCenter + halfMinDecorationHeight > canvasHeight) {\n yCenter = canvasHeight - halfMinDecorationHeight;\n }\n y1 = yCenter - halfMinDecorationHeight;\n y2 = yCenter + halfMinDecorationHeight;\n }\n if (y1 > prevY2 + 1 || lane !== prevLane) {\n // flush prev\n if (i !== 0) {\n canvasCtx.fillRect(x[prevLane], prevY1, w[prevLane], prevY2 - prevY1);\n }\n prevLane = lane;\n prevY1 = y1;\n prevY2 = y2;\n }\n else {\n // merge into prev\n if (y2 > prevY2) {\n prevY2 = y2;\n }\n }\n }\n canvasCtx.fillRect(x[prevLane], prevY1, w[prevLane], prevY2 - prevY1);\n }\n // Draw cursors\n if (!this._settings.hideCursor && this._settings.cursorColor) {\n const cursorHeight = (2 * this._settings.pixelRatio) | 0;\n const halfCursorHeight = (cursorHeight / 2) | 0;\n const cursorX = this._settings.x[7 /* OverviewRulerLane.Full */];\n const cursorW = this._settings.w[7 /* OverviewRulerLane.Full */];\n canvasCtx.fillStyle = this._settings.cursorColor;\n let prevY1 = -100;\n let prevY2 = -100;\n for (let i = 0, len = this._cursorPositions.length; i < len; i++) {\n const cursor = this._cursorPositions[i];\n let yCenter = (viewLayout.getVerticalOffsetForLineNumber(cursor.lineNumber) * heightRatio) | 0;\n if (yCenter < halfCursorHeight) {\n yCenter = halfCursorHeight;\n }\n else if (yCenter + halfCursorHeight > canvasHeight) {\n yCenter = canvasHeight - halfCursorHeight;\n }\n const y1 = yCenter - halfCursorHeight;\n const y2 = y1 + cursorHeight;\n if (y1 > prevY2 + 1) {\n // flush prev\n if (i !== 0) {\n canvasCtx.fillRect(cursorX, prevY1, cursorW, prevY2 - prevY1);\n }\n prevY1 = y1;\n prevY2 = y2;\n }\n else {\n // merge into prev\n if (y2 > prevY2) {\n prevY2 = y2;\n }\n }\n }\n canvasCtx.fillRect(cursorX, prevY1, cursorW, prevY2 - prevY1);\n }\n if (this._settings.renderBorder && this._settings.borderColor && this._settings.overviewRulerLanes > 0) {\n canvasCtx.beginPath();\n canvasCtx.lineWidth = 1;\n canvasCtx.strokeStyle = this._settings.borderColor;\n canvasCtx.moveTo(0, 0);\n canvasCtx.lineTo(0, canvasHeight);\n canvasCtx.stroke();\n canvasCtx.moveTo(0, 0);\n canvasCtx.lineTo(canvasWidth, 0);\n canvasCtx.stroke();\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 *--------------------------------------------------------------------------------------------*/\nimport { createFastDomNode } from '../../../../base/browser/fastDomNode.js';\nimport { OverviewZoneManager } from '../../../common/viewModel/overviewZoneManager.js';\nimport { ViewEventHandler } from '../../../common/viewEventHandler.js';\nexport class OverviewRuler extends ViewEventHandler {\n constructor(context, cssClassName) {\n super();\n this._context = context;\n const options = this._context.configuration.options;\n this._domNode = createFastDomNode(document.createElement('canvas'));\n this._domNode.setClassName(cssClassName);\n this._domNode.setPosition('absolute');\n this._domNode.setLayerHinting(true);\n this._domNode.setContain('strict');\n this._zoneManager = new OverviewZoneManager((lineNumber) => this._context.viewLayout.getVerticalOffsetForLineNumber(lineNumber));\n this._zoneManager.setDOMWidth(0);\n this._zoneManager.setDOMHeight(0);\n this._zoneManager.setOuterHeight(this._context.viewLayout.getScrollHeight());\n this._zoneManager.setLineHeight(options.get(61 /* EditorOption.lineHeight */));\n this._zoneManager.setPixelRatio(options.get(131 /* EditorOption.pixelRatio */));\n this._context.addEventHandler(this);\n }\n dispose() {\n this._context.removeEventHandler(this);\n super.dispose();\n }\n // ---- begin view event handlers\n onConfigurationChanged(e) {\n const options = this._context.configuration.options;\n if (e.hasChanged(61 /* EditorOption.lineHeight */)) {\n this._zoneManager.setLineHeight(options.get(61 /* EditorOption.lineHeight */));\n this._render();\n }\n if (e.hasChanged(131 /* EditorOption.pixelRatio */)) {\n this._zoneManager.setPixelRatio(options.get(131 /* EditorOption.pixelRatio */));\n this._domNode.setWidth(this._zoneManager.getDOMWidth());\n this._domNode.setHeight(this._zoneManager.getDOMHeight());\n this._domNode.domNode.width = this._zoneManager.getCanvasWidth();\n this._domNode.domNode.height = this._zoneManager.getCanvasHeight();\n this._render();\n }\n return true;\n }\n onFlushed(e) {\n this._render();\n return true;\n }\n onScrollChanged(e) {\n if (e.scrollHeightChanged) {\n this._zoneManager.setOuterHeight(e.scrollHeight);\n this._render();\n }\n return true;\n }\n onZonesChanged(e) {\n this._render();\n return true;\n }\n // ---- end view event handlers\n getDomNode() {\n return this._domNode.domNode;\n }\n setLayout(position) {\n this._domNode.setTop(position.top);\n this._domNode.setRight(position.right);\n let hasChanged = false;\n hasChanged = this._zoneManager.setDOMWidth(position.width) || hasChanged;\n hasChanged = this._zoneManager.setDOMHeight(position.height) || hasChanged;\n if (hasChanged) {\n this._domNode.setWidth(this._zoneManager.getDOMWidth());\n this._domNode.setHeight(this._zoneManager.getDOMHeight());\n this._domNode.domNode.width = this._zoneManager.getCanvasWidth();\n this._domNode.domNode.height = this._zoneManager.getCanvasHeight();\n this._render();\n }\n }\n setZones(zones) {\n this._zoneManager.setZones(zones);\n this._render();\n }\n _render() {\n if (this._zoneManager.getOuterHeight() === 0) {\n return false;\n }\n const width = this._zoneManager.getCanvasWidth();\n const height = this._zoneManager.getCanvasHeight();\n const colorZones = this._zoneManager.resolveColorZones();\n const id2Color = this._zoneManager.getId2Color();\n const ctx = this._domNode.domNode.getContext('2d');\n ctx.clearRect(0, 0, width, height);\n if (colorZones.length > 0) {\n this._renderOneLane(ctx, colorZones, id2Color, width);\n }\n return true;\n }\n _renderOneLane(ctx, colorZones, id2Color, width) {\n let currentColorId = 0;\n let currentFrom = 0;\n let currentTo = 0;\n for (const zone of colorZones) {\n const zoneColorId = zone.colorId;\n const zoneFrom = zone.from;\n const zoneTo = zone.to;\n if (zoneColorId !== currentColorId) {\n ctx.fillRect(0, currentFrom, width, currentTo - currentFrom);\n currentColorId = zoneColorId;\n ctx.fillStyle = id2Color[currentColorId];\n currentFrom = zoneFrom;\n currentTo = zoneTo;\n }\n else {\n if (currentTo >= zoneFrom) {\n currentTo = Math.max(currentTo, zoneTo);\n }\n else {\n ctx.fillRect(0, currentFrom, width, currentTo - currentFrom);\n currentFrom = zoneFrom;\n currentTo = zoneTo;\n }\n }\n }\n ctx.fillRect(0, currentFrom, width, currentTo - currentFrom);\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 *--------------------------------------------------------------------------------------------*/\nimport './rulers.css';\nimport { createFastDomNode } from '../../../../base/browser/fastDomNode.js';\nimport { ViewPart } from '../../view/viewPart.js';\nimport { editorRuler } from '../../../common/core/editorColorRegistry.js';\nimport { registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';\nexport class Rulers extends ViewPart {\n constructor(context) {\n super(context);\n this.domNode = createFastDomNode(document.createElement('div'));\n this.domNode.setAttribute('role', 'presentation');\n this.domNode.setAttribute('aria-hidden', 'true');\n this.domNode.setClassName('view-rulers');\n this._renderedRulers = [];\n const options = this._context.configuration.options;\n this._rulers = options.get(93 /* EditorOption.rulers */);\n this._typicalHalfwidthCharacterWidth = options.get(46 /* EditorOption.fontInfo */).typicalHalfwidthCharacterWidth;\n }\n dispose() {\n super.dispose();\n }\n // --- begin event handlers\n onConfigurationChanged(e) {\n const options = this._context.configuration.options;\n this._rulers = options.get(93 /* EditorOption.rulers */);\n this._typicalHalfwidthCharacterWidth = options.get(46 /* EditorOption.fontInfo */).typicalHalfwidthCharacterWidth;\n return true;\n }\n onScrollChanged(e) {\n return e.scrollHeightChanged;\n }\n // --- end event handlers\n prepareRender(ctx) {\n // Nothing to read\n }\n _ensureRulersCount() {\n const currentCount = this._renderedRulers.length;\n const desiredCount = this._rulers.length;\n if (currentCount === desiredCount) {\n // Nothing to do\n return;\n }\n if (currentCount < desiredCount) {\n const { tabSize } = this._context.viewModel.model.getOptions();\n const rulerWidth = tabSize;\n let addCount = desiredCount - currentCount;\n while (addCount > 0) {\n const node = createFastDomNode(document.createElement('div'));\n node.setClassName('view-ruler');\n node.setWidth(rulerWidth);\n this.domNode.appendChild(node);\n this._renderedRulers.push(node);\n addCount--;\n }\n return;\n }\n let removeCount = currentCount - desiredCount;\n while (removeCount > 0) {\n const node = this._renderedRulers.pop();\n this.domNode.removeChild(node);\n removeCount--;\n }\n }\n render(ctx) {\n this._ensureRulersCount();\n for (let i = 0, len = this._rulers.length; i < len; i++) {\n const node = this._renderedRulers[i];\n const ruler = this._rulers[i];\n node.setBoxShadow(ruler.color ? `1px 0 0 0 ${ruler.color} inset` : ``);\n node.setHeight(Math.min(ctx.scrollHeight, 1000000));\n node.setLeft(ruler.column * this._typicalHalfwidthCharacterWidth);\n }\n }\n}\nregisterThemingParticipant((theme, collector) => {\n const rulerColor = theme.getColor(editorRuler);\n if (rulerColor) {\n collector.addRule(`.monaco-editor .view-ruler { box-shadow: 1px 0 0 0 ${rulerColor} inset; }`);\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 *--------------------------------------------------------------------------------------------*/\nimport './scrollDecoration.css';\nimport { createFastDomNode } from '../../../../base/browser/fastDomNode.js';\nimport { ViewPart } from '../../view/viewPart.js';\nimport { scrollbarShadow } from '../../../../platform/theme/common/colorRegistry.js';\nimport { registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';\nexport class ScrollDecorationViewPart extends ViewPart {\n constructor(context) {\n super(context);\n this._scrollTop = 0;\n this._width = 0;\n this._updateWidth();\n this._shouldShow = false;\n const options = this._context.configuration.options;\n const scrollbar = options.get(94 /* EditorOption.scrollbar */);\n this._useShadows = scrollbar.useShadows;\n this._domNode = createFastDomNode(document.createElement('div'));\n this._domNode.setAttribute('role', 'presentation');\n this._domNode.setAttribute('aria-hidden', 'true');\n }\n dispose() {\n super.dispose();\n }\n _updateShouldShow() {\n const newShouldShow = (this._useShadows && this._scrollTop > 0);\n if (this._shouldShow !== newShouldShow) {\n this._shouldShow = newShouldShow;\n return true;\n }\n return false;\n }\n getDomNode() {\n return this._domNode;\n }\n _updateWidth() {\n const options = this._context.configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n if (layoutInfo.minimap.renderMinimap === 0 || (layoutInfo.minimap.minimapWidth > 0 && layoutInfo.minimap.minimapLeft === 0)) {\n this._width = layoutInfo.width;\n }\n else {\n this._width = layoutInfo.width - layoutInfo.verticalScrollbarWidth;\n }\n }\n // --- begin event handlers\n onConfigurationChanged(e) {\n const options = this._context.configuration.options;\n const scrollbar = options.get(94 /* EditorOption.scrollbar */);\n this._useShadows = scrollbar.useShadows;\n this._updateWidth();\n this._updateShouldShow();\n return true;\n }\n onScrollChanged(e) {\n this._scrollTop = e.scrollTop;\n return this._updateShouldShow();\n }\n // --- end event handlers\n prepareRender(ctx) {\n // Nothing to read\n }\n render(ctx) {\n this._domNode.setWidth(this._width);\n this._domNode.setClassName(this._shouldShow ? 'scroll-decoration' : '');\n }\n}\nregisterThemingParticipant((theme, collector) => {\n const shadow = theme.getColor(scrollbarShadow);\n if (shadow) {\n collector.addRule(`.monaco-editor .scroll-decoration { box-shadow: ${shadow} 0 6px 6px -6px inset; }`);\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 *--------------------------------------------------------------------------------------------*/\nimport './selections.css';\nimport { DynamicViewOverlay } from '../../view/dynamicViewOverlay.js';\nimport { editorInactiveSelection, editorSelectionBackground, editorSelectionForeground } from '../../../../platform/theme/common/colorRegistry.js';\nimport { registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';\nclass HorizontalRangeWithStyle {\n constructor(other) {\n this.left = other.left;\n this.width = other.width;\n this.startStyle = null;\n this.endStyle = null;\n }\n}\nclass LineVisibleRangesWithStyle {\n constructor(lineNumber, ranges) {\n this.lineNumber = lineNumber;\n this.ranges = ranges;\n }\n}\nfunction toStyledRange(item) {\n return new HorizontalRangeWithStyle(item);\n}\nfunction toStyled(item) {\n return new LineVisibleRangesWithStyle(item.lineNumber, item.ranges.map(toStyledRange));\n}\nexport class SelectionsOverlay extends DynamicViewOverlay {\n constructor(context) {\n super();\n this._previousFrameVisibleRangesWithStyle = [];\n this._context = context;\n const options = this._context.configuration.options;\n this._lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this._roundedSelection = options.get(92 /* EditorOption.roundedSelection */);\n this._typicalHalfwidthCharacterWidth = options.get(46 /* EditorOption.fontInfo */).typicalHalfwidthCharacterWidth;\n this._selections = [];\n this._renderResult = null;\n this._context.addEventHandler(this);\n }\n dispose() {\n this._context.removeEventHandler(this);\n this._renderResult = null;\n super.dispose();\n }\n // --- begin event handlers\n onConfigurationChanged(e) {\n const options = this._context.configuration.options;\n this._lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this._roundedSelection = options.get(92 /* EditorOption.roundedSelection */);\n this._typicalHalfwidthCharacterWidth = options.get(46 /* EditorOption.fontInfo */).typicalHalfwidthCharacterWidth;\n return true;\n }\n onCursorStateChanged(e) {\n this._selections = e.selections.slice(0);\n return true;\n }\n onDecorationsChanged(e) {\n // true for inline decorations that can end up relayouting text\n return true; //e.inlineDecorationsChanged;\n }\n onFlushed(e) {\n return true;\n }\n onLinesChanged(e) {\n return true;\n }\n onLinesDeleted(e) {\n return true;\n }\n onLinesInserted(e) {\n return true;\n }\n onScrollChanged(e) {\n return e.scrollTopChanged;\n }\n onZonesChanged(e) {\n return true;\n }\n // --- end event handlers\n _visibleRangesHaveGaps(linesVisibleRanges) {\n for (let i = 0, len = linesVisibleRanges.length; i < len; i++) {\n const lineVisibleRanges = linesVisibleRanges[i];\n if (lineVisibleRanges.ranges.length > 1) {\n // There are two ranges on the same line\n return true;\n }\n }\n return false;\n }\n _enrichVisibleRangesWithStyle(viewport, linesVisibleRanges, previousFrame) {\n const epsilon = this._typicalHalfwidthCharacterWidth / 4;\n let previousFrameTop = null;\n let previousFrameBottom = null;\n if (previousFrame && previousFrame.length > 0 && linesVisibleRanges.length > 0) {\n const topLineNumber = linesVisibleRanges[0].lineNumber;\n if (topLineNumber === viewport.startLineNumber) {\n for (let i = 0; !previousFrameTop && i < previousFrame.length; i++) {\n if (previousFrame[i].lineNumber === topLineNumber) {\n previousFrameTop = previousFrame[i].ranges[0];\n }\n }\n }\n const bottomLineNumber = linesVisibleRanges[linesVisibleRanges.length - 1].lineNumber;\n if (bottomLineNumber === viewport.endLineNumber) {\n for (let i = previousFrame.length - 1; !previousFrameBottom && i >= 0; i--) {\n if (previousFrame[i].lineNumber === bottomLineNumber) {\n previousFrameBottom = previousFrame[i].ranges[0];\n }\n }\n }\n if (previousFrameTop && !previousFrameTop.startStyle) {\n previousFrameTop = null;\n }\n if (previousFrameBottom && !previousFrameBottom.startStyle) {\n previousFrameBottom = null;\n }\n }\n for (let i = 0, len = linesVisibleRanges.length; i < len; i++) {\n // We know for a fact that there is precisely one range on each line\n const curLineRange = linesVisibleRanges[i].ranges[0];\n const curLeft = curLineRange.left;\n const curRight = curLineRange.left + curLineRange.width;\n const startStyle = {\n top: 0 /* CornerStyle.EXTERN */,\n bottom: 0 /* CornerStyle.EXTERN */\n };\n const endStyle = {\n top: 0 /* CornerStyle.EXTERN */,\n bottom: 0 /* CornerStyle.EXTERN */\n };\n if (i > 0) {\n // Look above\n const prevLeft = linesVisibleRanges[i - 1].ranges[0].left;\n const prevRight = linesVisibleRanges[i - 1].ranges[0].left + linesVisibleRanges[i - 1].ranges[0].width;\n if (abs(curLeft - prevLeft) < epsilon) {\n startStyle.top = 2 /* CornerStyle.FLAT */;\n }\n else if (curLeft > prevLeft) {\n startStyle.top = 1 /* CornerStyle.INTERN */;\n }\n if (abs(curRight - prevRight) < epsilon) {\n endStyle.top = 2 /* CornerStyle.FLAT */;\n }\n else if (prevLeft < curRight && curRight < prevRight) {\n endStyle.top = 1 /* CornerStyle.INTERN */;\n }\n }\n else if (previousFrameTop) {\n // Accept some hiccups near the viewport edges to save on repaints\n startStyle.top = previousFrameTop.startStyle.top;\n endStyle.top = previousFrameTop.endStyle.top;\n }\n if (i + 1 < len) {\n // Look below\n const nextLeft = linesVisibleRanges[i + 1].ranges[0].left;\n const nextRight = linesVisibleRanges[i + 1].ranges[0].left + linesVisibleRanges[i + 1].ranges[0].width;\n if (abs(curLeft - nextLeft) < epsilon) {\n startStyle.bottom = 2 /* CornerStyle.FLAT */;\n }\n else if (nextLeft < curLeft && curLeft < nextRight) {\n startStyle.bottom = 1 /* CornerStyle.INTERN */;\n }\n if (abs(curRight - nextRight) < epsilon) {\n endStyle.bottom = 2 /* CornerStyle.FLAT */;\n }\n else if (curRight < nextRight) {\n endStyle.bottom = 1 /* CornerStyle.INTERN */;\n }\n }\n else if (previousFrameBottom) {\n // Accept some hiccups near the viewport edges to save on repaints\n startStyle.bottom = previousFrameBottom.startStyle.bottom;\n endStyle.bottom = previousFrameBottom.endStyle.bottom;\n }\n curLineRange.startStyle = startStyle;\n curLineRange.endStyle = endStyle;\n }\n }\n _getVisibleRangesWithStyle(selection, ctx, previousFrame) {\n const _linesVisibleRanges = ctx.linesVisibleRangesForRange(selection, true) || [];\n const linesVisibleRanges = _linesVisibleRanges.map(toStyled);\n const visibleRangesHaveGaps = this._visibleRangesHaveGaps(linesVisibleRanges);\n if (!visibleRangesHaveGaps && this._roundedSelection) {\n this._enrichVisibleRangesWithStyle(ctx.visibleRange, linesVisibleRanges, previousFrame);\n }\n // The visible ranges are sorted TOP-BOTTOM and LEFT-RIGHT\n return linesVisibleRanges;\n }\n _createSelectionPiece(top, height, className, left, width) {\n return ('
');\n }\n _actualRenderOneSelection(output2, visibleStartLineNumber, hasMultipleSelections, visibleRanges) {\n if (visibleRanges.length === 0) {\n return;\n }\n const visibleRangesHaveStyle = !!visibleRanges[0].ranges[0].startStyle;\n const fullLineHeight = (this._lineHeight).toString();\n const reducedLineHeight = (this._lineHeight - 1).toString();\n const firstLineNumber = visibleRanges[0].lineNumber;\n const lastLineNumber = visibleRanges[visibleRanges.length - 1].lineNumber;\n for (let i = 0, len = visibleRanges.length; i < len; i++) {\n const lineVisibleRanges = visibleRanges[i];\n const lineNumber = lineVisibleRanges.lineNumber;\n const lineIndex = lineNumber - visibleStartLineNumber;\n const lineHeight = hasMultipleSelections ? (lineNumber === lastLineNumber || lineNumber === firstLineNumber ? reducedLineHeight : fullLineHeight) : fullLineHeight;\n const top = hasMultipleSelections ? (lineNumber === firstLineNumber ? 1 : 0) : 0;\n let innerCornerOutput = '';\n let restOfSelectionOutput = '';\n for (let j = 0, lenJ = lineVisibleRanges.ranges.length; j < lenJ; j++) {\n const visibleRange = lineVisibleRanges.ranges[j];\n if (visibleRangesHaveStyle) {\n const startStyle = visibleRange.startStyle;\n const endStyle = visibleRange.endStyle;\n if (startStyle.top === 1 /* CornerStyle.INTERN */ || startStyle.bottom === 1 /* CornerStyle.INTERN */) {\n // Reverse rounded corner to the left\n // First comes the selection (blue layer)\n innerCornerOutput += this._createSelectionPiece(top, lineHeight, SelectionsOverlay.SELECTION_CLASS_NAME, visibleRange.left - SelectionsOverlay.ROUNDED_PIECE_WIDTH, SelectionsOverlay.ROUNDED_PIECE_WIDTH);\n // Second comes the background (white layer) with inverse border radius\n let className = SelectionsOverlay.EDITOR_BACKGROUND_CLASS_NAME;\n if (startStyle.top === 1 /* CornerStyle.INTERN */) {\n className += ' ' + SelectionsOverlay.SELECTION_TOP_RIGHT;\n }\n if (startStyle.bottom === 1 /* CornerStyle.INTERN */) {\n className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_RIGHT;\n }\n innerCornerOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left - SelectionsOverlay.ROUNDED_PIECE_WIDTH, SelectionsOverlay.ROUNDED_PIECE_WIDTH);\n }\n if (endStyle.top === 1 /* CornerStyle.INTERN */ || endStyle.bottom === 1 /* CornerStyle.INTERN */) {\n // Reverse rounded corner to the right\n // First comes the selection (blue layer)\n innerCornerOutput += this._createSelectionPiece(top, lineHeight, SelectionsOverlay.SELECTION_CLASS_NAME, visibleRange.left + visibleRange.width, SelectionsOverlay.ROUNDED_PIECE_WIDTH);\n // Second comes the background (white layer) with inverse border radius\n let className = SelectionsOverlay.EDITOR_BACKGROUND_CLASS_NAME;\n if (endStyle.top === 1 /* CornerStyle.INTERN */) {\n className += ' ' + SelectionsOverlay.SELECTION_TOP_LEFT;\n }\n if (endStyle.bottom === 1 /* CornerStyle.INTERN */) {\n className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_LEFT;\n }\n innerCornerOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left + visibleRange.width, SelectionsOverlay.ROUNDED_PIECE_WIDTH);\n }\n }\n let className = SelectionsOverlay.SELECTION_CLASS_NAME;\n if (visibleRangesHaveStyle) {\n const startStyle = visibleRange.startStyle;\n const endStyle = visibleRange.endStyle;\n if (startStyle.top === 0 /* CornerStyle.EXTERN */) {\n className += ' ' + SelectionsOverlay.SELECTION_TOP_LEFT;\n }\n if (startStyle.bottom === 0 /* CornerStyle.EXTERN */) {\n className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_LEFT;\n }\n if (endStyle.top === 0 /* CornerStyle.EXTERN */) {\n className += ' ' + SelectionsOverlay.SELECTION_TOP_RIGHT;\n }\n if (endStyle.bottom === 0 /* CornerStyle.EXTERN */) {\n className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_RIGHT;\n }\n }\n restOfSelectionOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left, visibleRange.width);\n }\n output2[lineIndex][0] += innerCornerOutput;\n output2[lineIndex][1] += restOfSelectionOutput;\n }\n }\n prepareRender(ctx) {\n // Build HTML for inner corners separate from HTML for the rest of selections,\n // as the inner corner HTML can interfere with that of other selections.\n // In final render, make sure to place the inner corner HTML before the rest of selection HTML. See issue #77777.\n const output = [];\n const visibleStartLineNumber = ctx.visibleRange.startLineNumber;\n const visibleEndLineNumber = ctx.visibleRange.endLineNumber;\n for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {\n const lineIndex = lineNumber - visibleStartLineNumber;\n output[lineIndex] = ['', ''];\n }\n const thisFrameVisibleRangesWithStyle = [];\n for (let i = 0, len = this._selections.length; i < len; i++) {\n const selection = this._selections[i];\n if (selection.isEmpty()) {\n thisFrameVisibleRangesWithStyle[i] = null;\n continue;\n }\n const visibleRangesWithStyle = this._getVisibleRangesWithStyle(selection, ctx, this._previousFrameVisibleRangesWithStyle[i]);\n thisFrameVisibleRangesWithStyle[i] = visibleRangesWithStyle;\n this._actualRenderOneSelection(output, visibleStartLineNumber, this._selections.length > 1, visibleRangesWithStyle);\n }\n this._previousFrameVisibleRangesWithStyle = thisFrameVisibleRangesWithStyle;\n this._renderResult = output.map(([internalCorners, restOfSelection]) => internalCorners + restOfSelection);\n }\n render(startLineNumber, lineNumber) {\n if (!this._renderResult) {\n return '';\n }\n const lineIndex = lineNumber - startLineNumber;\n if (lineIndex < 0 || lineIndex >= this._renderResult.length) {\n return '';\n }\n return this._renderResult[lineIndex];\n }\n}\nSelectionsOverlay.SELECTION_CLASS_NAME = 'selected-text';\nSelectionsOverlay.SELECTION_TOP_LEFT = 'top-left-radius';\nSelectionsOverlay.SELECTION_BOTTOM_LEFT = 'bottom-left-radius';\nSelectionsOverlay.SELECTION_TOP_RIGHT = 'top-right-radius';\nSelectionsOverlay.SELECTION_BOTTOM_RIGHT = 'bottom-right-radius';\nSelectionsOverlay.EDITOR_BACKGROUND_CLASS_NAME = 'monaco-editor-background';\nSelectionsOverlay.ROUNDED_PIECE_WIDTH = 10;\nregisterThemingParticipant((theme, collector) => {\n const editorSelectionColor = theme.getColor(editorSelectionBackground);\n if (editorSelectionColor) {\n collector.addRule(`.monaco-editor .focused .selected-text { background-color: ${editorSelectionColor}; }`);\n }\n const editorInactiveSelectionColor = theme.getColor(editorInactiveSelection);\n if (editorInactiveSelectionColor) {\n collector.addRule(`.monaco-editor .selected-text { background-color: ${editorInactiveSelectionColor}; }`);\n }\n const editorSelectionForegroundColor = theme.getColor(editorSelectionForeground);\n if (editorSelectionForegroundColor && !editorSelectionForegroundColor.isTransparent()) {\n collector.addRule(`.monaco-editor .view-line span.inline-selected-text { color: ${editorSelectionForegroundColor}; }`);\n }\n});\nfunction abs(n) {\n return n < 0 ? -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 *--------------------------------------------------------------------------------------------*/\nimport * as dom from '../../../../base/browser/dom.js';\nimport { createFastDomNode } from '../../../../base/browser/fastDomNode.js';\nimport * as strings from '../../../../base/common/strings.js';\nimport { applyFontInfo } from '../../config/domFontInfo.js';\nimport { TextEditorCursorStyle } from '../../../common/config/editorOptions.js';\nimport { Position } from '../../../common/core/position.js';\nimport { Range } from '../../../common/core/range.js';\nimport { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from '../../../../base/browser/ui/mouseCursor/mouseCursor.js';\nclass ViewCursorRenderData {\n constructor(top, left, width, height, textContent, textContentClassName) {\n this.top = top;\n this.left = left;\n this.width = width;\n this.height = height;\n this.textContent = textContent;\n this.textContentClassName = textContentClassName;\n }\n}\nexport class ViewCursor {\n constructor(context) {\n this._context = context;\n const options = this._context.configuration.options;\n const fontInfo = options.get(46 /* EditorOption.fontInfo */);\n this._cursorStyle = options.get(24 /* EditorOption.cursorStyle */);\n this._lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this._typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;\n this._lineCursorWidth = Math.min(options.get(27 /* EditorOption.cursorWidth */), this._typicalHalfwidthCharacterWidth);\n this._isVisible = true;\n // Create the dom node\n this._domNode = createFastDomNode(document.createElement('div'));\n this._domNode.setClassName(`cursor ${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`);\n this._domNode.setHeight(this._lineHeight);\n this._domNode.setTop(0);\n this._domNode.setLeft(0);\n applyFontInfo(this._domNode, fontInfo);\n this._domNode.setDisplay('none');\n this._position = new Position(1, 1);\n this._lastRenderedContent = '';\n this._renderData = null;\n }\n getDomNode() {\n return this._domNode;\n }\n getPosition() {\n return this._position;\n }\n show() {\n if (!this._isVisible) {\n this._domNode.setVisibility('inherit');\n this._isVisible = true;\n }\n }\n hide() {\n if (this._isVisible) {\n this._domNode.setVisibility('hidden');\n this._isVisible = false;\n }\n }\n onConfigurationChanged(e) {\n const options = this._context.configuration.options;\n const fontInfo = options.get(46 /* EditorOption.fontInfo */);\n this._cursorStyle = options.get(24 /* EditorOption.cursorStyle */);\n this._lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this._typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;\n this._lineCursorWidth = Math.min(options.get(27 /* EditorOption.cursorWidth */), this._typicalHalfwidthCharacterWidth);\n applyFontInfo(this._domNode, fontInfo);\n return true;\n }\n onCursorPositionChanged(position) {\n this._position = position;\n return true;\n }\n /**\n * If `this._position` is inside a grapheme, returns the position where the grapheme starts.\n * Also returns the next grapheme.\n */\n _getGraphemeAwarePosition() {\n const { lineNumber, column } = this._position;\n const lineContent = this._context.viewModel.getLineContent(lineNumber);\n const [startOffset, endOffset] = strings.getCharContainingOffset(lineContent, column - 1);\n return [new Position(lineNumber, startOffset + 1), lineContent.substring(startOffset, endOffset)];\n }\n _prepareRender(ctx) {\n let textContent = '';\n const [position, nextGrapheme] = this._getGraphemeAwarePosition();\n if (this._cursorStyle === TextEditorCursorStyle.Line || this._cursorStyle === TextEditorCursorStyle.LineThin) {\n const visibleRange = ctx.visibleRangeForPosition(position);\n if (!visibleRange || visibleRange.outsideRenderedLine) {\n // Outside viewport\n return null;\n }\n let width;\n if (this._cursorStyle === TextEditorCursorStyle.Line) {\n width = dom.computeScreenAwareSize(this._lineCursorWidth > 0 ? this._lineCursorWidth : 2);\n if (width > 2) {\n textContent = nextGrapheme;\n }\n }\n else {\n width = dom.computeScreenAwareSize(1);\n }\n let left = visibleRange.left;\n if (width >= 2 && left >= 1) {\n // try to center cursor\n left -= 1;\n }\n const top = ctx.getVerticalOffsetForLineNumber(position.lineNumber) - ctx.bigNumbersDelta;\n return new ViewCursorRenderData(top, left, width, this._lineHeight, textContent, '');\n }\n const visibleRangeForCharacter = ctx.linesVisibleRangesForRange(new Range(position.lineNumber, position.column, position.lineNumber, position.column + nextGrapheme.length), false);\n if (!visibleRangeForCharacter || visibleRangeForCharacter.length === 0) {\n // Outside viewport\n return null;\n }\n const firstVisibleRangeForCharacter = visibleRangeForCharacter[0];\n if (firstVisibleRangeForCharacter.outsideRenderedLine || firstVisibleRangeForCharacter.ranges.length === 0) {\n // Outside viewport\n return null;\n }\n const range = firstVisibleRangeForCharacter.ranges[0];\n const width = (nextGrapheme === '\\t'\n ? this._typicalHalfwidthCharacterWidth\n : (range.width < 1\n ? this._typicalHalfwidthCharacterWidth\n : range.width));\n let textContentClassName = '';\n if (this._cursorStyle === TextEditorCursorStyle.Block) {\n const lineData = this._context.viewModel.getViewLineData(position.lineNumber);\n textContent = nextGrapheme;\n const tokenIndex = lineData.tokens.findTokenIndexAtOffset(position.column - 1);\n textContentClassName = lineData.tokens.getClassName(tokenIndex);\n }\n let top = ctx.getVerticalOffsetForLineNumber(position.lineNumber) - ctx.bigNumbersDelta;\n let height = this._lineHeight;\n // Underline might interfere with clicking\n if (this._cursorStyle === TextEditorCursorStyle.Underline || this._cursorStyle === TextEditorCursorStyle.UnderlineThin) {\n top += this._lineHeight - 2;\n height = 2;\n }\n return new ViewCursorRenderData(top, range.left, width, height, textContent, textContentClassName);\n }\n prepareRender(ctx) {\n this._renderData = this._prepareRender(ctx);\n }\n render(ctx) {\n if (!this._renderData) {\n this._domNode.setDisplay('none');\n return null;\n }\n if (this._lastRenderedContent !== this._renderData.textContent) {\n this._lastRenderedContent = this._renderData.textContent;\n this._domNode.domNode.textContent = this._lastRenderedContent;\n }\n this._domNode.setClassName(`cursor ${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME} ${this._renderData.textContentClassName}`);\n this._domNode.setDisplay('block');\n this._domNode.setTop(this._renderData.top);\n this._domNode.setLeft(this._renderData.left);\n this._domNode.setWidth(this._renderData.width);\n this._domNode.setLineHeight(this._renderData.height);\n this._domNode.setHeight(this._renderData.height);\n return {\n domNode: this._domNode.domNode,\n position: this._position,\n contentLeft: this._renderData.left,\n height: this._renderData.height,\n width: 2\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 *--------------------------------------------------------------------------------------------*/\nimport './viewCursors.css';\nimport { createFastDomNode } from '../../../../base/browser/fastDomNode.js';\nimport { IntervalTimer, TimeoutTimer } from '../../../../base/common/async.js';\nimport { ViewPart } from '../../view/viewPart.js';\nimport { ViewCursor } from './viewCursor.js';\nimport { TextEditorCursorStyle } from '../../../common/config/editorOptions.js';\nimport { editorCursorBackground, editorCursorForeground } from '../../../common/core/editorColorRegistry.js';\nimport { registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';\nimport { isHighContrast } from '../../../../platform/theme/common/theme.js';\nexport class ViewCursors extends ViewPart {\n constructor(context) {\n super(context);\n const options = this._context.configuration.options;\n this._readOnly = options.get(83 /* EditorOption.readOnly */);\n this._cursorBlinking = options.get(22 /* EditorOption.cursorBlinking */);\n this._cursorStyle = options.get(24 /* EditorOption.cursorStyle */);\n this._cursorSmoothCaretAnimation = options.get(23 /* EditorOption.cursorSmoothCaretAnimation */);\n this._selectionIsEmpty = true;\n this._isComposingInput = false;\n this._isVisible = false;\n this._primaryCursor = new ViewCursor(this._context);\n this._secondaryCursors = [];\n this._renderData = [];\n this._domNode = createFastDomNode(document.createElement('div'));\n this._domNode.setAttribute('role', 'presentation');\n this._domNode.setAttribute('aria-hidden', 'true');\n this._updateDomClassName();\n this._domNode.appendChild(this._primaryCursor.getDomNode());\n this._startCursorBlinkAnimation = new TimeoutTimer();\n this._cursorFlatBlinkInterval = new IntervalTimer();\n this._blinkingEnabled = false;\n this._editorHasFocus = false;\n this._updateBlinking();\n }\n dispose() {\n super.dispose();\n this._startCursorBlinkAnimation.dispose();\n this._cursorFlatBlinkInterval.dispose();\n }\n getDomNode() {\n return this._domNode;\n }\n // --- begin event handlers\n onCompositionStart(e) {\n this._isComposingInput = true;\n this._updateBlinking();\n return true;\n }\n onCompositionEnd(e) {\n this._isComposingInput = false;\n this._updateBlinking();\n return true;\n }\n onConfigurationChanged(e) {\n const options = this._context.configuration.options;\n this._readOnly = options.get(83 /* EditorOption.readOnly */);\n this._cursorBlinking = options.get(22 /* EditorOption.cursorBlinking */);\n this._cursorStyle = options.get(24 /* EditorOption.cursorStyle */);\n this._cursorSmoothCaretAnimation = options.get(23 /* EditorOption.cursorSmoothCaretAnimation */);\n this._updateBlinking();\n this._updateDomClassName();\n this._primaryCursor.onConfigurationChanged(e);\n for (let i = 0, len = this._secondaryCursors.length; i < len; i++) {\n this._secondaryCursors[i].onConfigurationChanged(e);\n }\n return true;\n }\n _onCursorPositionChanged(position, secondaryPositions) {\n this._primaryCursor.onCursorPositionChanged(position);\n this._updateBlinking();\n if (this._secondaryCursors.length < secondaryPositions.length) {\n // Create new cursors\n const addCnt = secondaryPositions.length - this._secondaryCursors.length;\n for (let i = 0; i < addCnt; i++) {\n const newCursor = new ViewCursor(this._context);\n this._domNode.domNode.insertBefore(newCursor.getDomNode().domNode, this._primaryCursor.getDomNode().domNode.nextSibling);\n this._secondaryCursors.push(newCursor);\n }\n }\n else if (this._secondaryCursors.length > secondaryPositions.length) {\n // Remove some cursors\n const removeCnt = this._secondaryCursors.length - secondaryPositions.length;\n for (let i = 0; i < removeCnt; i++) {\n this._domNode.removeChild(this._secondaryCursors[0].getDomNode());\n this._secondaryCursors.splice(0, 1);\n }\n }\n for (let i = 0; i < secondaryPositions.length; i++) {\n this._secondaryCursors[i].onCursorPositionChanged(secondaryPositions[i]);\n }\n }\n onCursorStateChanged(e) {\n const positions = [];\n for (let i = 0, len = e.selections.length; i < len; i++) {\n positions[i] = e.selections[i].getPosition();\n }\n this._onCursorPositionChanged(positions[0], positions.slice(1));\n const selectionIsEmpty = e.selections[0].isEmpty();\n if (this._selectionIsEmpty !== selectionIsEmpty) {\n this._selectionIsEmpty = selectionIsEmpty;\n this._updateDomClassName();\n }\n return true;\n }\n onDecorationsChanged(e) {\n // true for inline decorations that can end up relayouting text\n return true;\n }\n onFlushed(e) {\n return true;\n }\n onFocusChanged(e) {\n this._editorHasFocus = e.isFocused;\n this._updateBlinking();\n return false;\n }\n onLinesChanged(e) {\n return true;\n }\n onLinesDeleted(e) {\n return true;\n }\n onLinesInserted(e) {\n return true;\n }\n onScrollChanged(e) {\n return true;\n }\n onTokensChanged(e) {\n const shouldRender = (position) => {\n for (let i = 0, len = e.ranges.length; i < len; i++) {\n if (e.ranges[i].fromLineNumber <= position.lineNumber && position.lineNumber <= e.ranges[i].toLineNumber) {\n return true;\n }\n }\n return false;\n };\n if (shouldRender(this._primaryCursor.getPosition())) {\n return true;\n }\n for (const secondaryCursor of this._secondaryCursors) {\n if (shouldRender(secondaryCursor.getPosition())) {\n return true;\n }\n }\n return false;\n }\n onZonesChanged(e) {\n return true;\n }\n // --- end event handlers\n // ---- blinking logic\n _getCursorBlinking() {\n if (this._isComposingInput) {\n // avoid double cursors\n return 0 /* TextEditorCursorBlinkingStyle.Hidden */;\n }\n if (!this._editorHasFocus) {\n return 0 /* TextEditorCursorBlinkingStyle.Hidden */;\n }\n if (this._readOnly) {\n return 5 /* TextEditorCursorBlinkingStyle.Solid */;\n }\n return this._cursorBlinking;\n }\n _updateBlinking() {\n this._startCursorBlinkAnimation.cancel();\n this._cursorFlatBlinkInterval.cancel();\n const blinkingStyle = this._getCursorBlinking();\n // hidden and solid are special as they involve no animations\n const isHidden = (blinkingStyle === 0 /* TextEditorCursorBlinkingStyle.Hidden */);\n const isSolid = (blinkingStyle === 5 /* TextEditorCursorBlinkingStyle.Solid */);\n if (isHidden) {\n this._hide();\n }\n else {\n this._show();\n }\n this._blinkingEnabled = false;\n this._updateDomClassName();\n if (!isHidden && !isSolid) {\n if (blinkingStyle === 1 /* TextEditorCursorBlinkingStyle.Blink */) {\n // flat blinking is handled by JavaScript to save battery life due to Chromium step timing issue https://bugs.chromium.org/p/chromium/issues/detail?id=361587\n this._cursorFlatBlinkInterval.cancelAndSet(() => {\n if (this._isVisible) {\n this._hide();\n }\n else {\n this._show();\n }\n }, ViewCursors.BLINK_INTERVAL);\n }\n else {\n this._startCursorBlinkAnimation.setIfNotSet(() => {\n this._blinkingEnabled = true;\n this._updateDomClassName();\n }, ViewCursors.BLINK_INTERVAL);\n }\n }\n }\n // --- end blinking logic\n _updateDomClassName() {\n this._domNode.setClassName(this._getClassName());\n }\n _getClassName() {\n let result = 'cursors-layer';\n if (!this._selectionIsEmpty) {\n result += ' has-selection';\n }\n switch (this._cursorStyle) {\n case TextEditorCursorStyle.Line:\n result += ' cursor-line-style';\n break;\n case TextEditorCursorStyle.Block:\n result += ' cursor-block-style';\n break;\n case TextEditorCursorStyle.Underline:\n result += ' cursor-underline-style';\n break;\n case TextEditorCursorStyle.LineThin:\n result += ' cursor-line-thin-style';\n break;\n case TextEditorCursorStyle.BlockOutline:\n result += ' cursor-block-outline-style';\n break;\n case TextEditorCursorStyle.UnderlineThin:\n result += ' cursor-underline-thin-style';\n break;\n default:\n result += ' cursor-line-style';\n }\n if (this._blinkingEnabled) {\n switch (this._getCursorBlinking()) {\n case 1 /* TextEditorCursorBlinkingStyle.Blink */:\n result += ' cursor-blink';\n break;\n case 2 /* TextEditorCursorBlinkingStyle.Smooth */:\n result += ' cursor-smooth';\n break;\n case 3 /* TextEditorCursorBlinkingStyle.Phase */:\n result += ' cursor-phase';\n break;\n case 4 /* TextEditorCursorBlinkingStyle.Expand */:\n result += ' cursor-expand';\n break;\n case 5 /* TextEditorCursorBlinkingStyle.Solid */:\n result += ' cursor-solid';\n break;\n default:\n result += ' cursor-solid';\n }\n }\n else {\n result += ' cursor-solid';\n }\n if (this._cursorSmoothCaretAnimation) {\n result += ' cursor-smooth-caret-animation';\n }\n return result;\n }\n _show() {\n this._primaryCursor.show();\n for (let i = 0, len = this._secondaryCursors.length; i < len; i++) {\n this._secondaryCursors[i].show();\n }\n this._isVisible = true;\n }\n _hide() {\n this._primaryCursor.hide();\n for (let i = 0, len = this._secondaryCursors.length; i < len; i++) {\n this._secondaryCursors[i].hide();\n }\n this._isVisible = false;\n }\n // ---- IViewPart implementation\n prepareRender(ctx) {\n this._primaryCursor.prepareRender(ctx);\n for (let i = 0, len = this._secondaryCursors.length; i < len; i++) {\n this._secondaryCursors[i].prepareRender(ctx);\n }\n }\n render(ctx) {\n const renderData = [];\n let renderDataLen = 0;\n const primaryRenderData = this._primaryCursor.render(ctx);\n if (primaryRenderData) {\n renderData[renderDataLen++] = primaryRenderData;\n }\n for (let i = 0, len = this._secondaryCursors.length; i < len; i++) {\n const secondaryRenderData = this._secondaryCursors[i].render(ctx);\n if (secondaryRenderData) {\n renderData[renderDataLen++] = secondaryRenderData;\n }\n }\n this._renderData = renderData;\n }\n getLastRenderData() {\n return this._renderData;\n }\n}\nViewCursors.BLINK_INTERVAL = 500;\nregisterThemingParticipant((theme, collector) => {\n const caret = theme.getColor(editorCursorForeground);\n if (caret) {\n let caretBackground = theme.getColor(editorCursorBackground);\n if (!caretBackground) {\n caretBackground = caret.opposite();\n }\n collector.addRule(`.monaco-editor .inputarea.ime-input { caret-color: ${caret}; }`);\n collector.addRule(`.monaco-editor .cursors-layer .cursor { background-color: ${caret}; border-color: ${caret}; color: ${caretBackground}; }`);\n if (isHighContrast(theme.type)) {\n collector.addRule(`.monaco-editor .cursors-layer.has-selection .cursor { border-left: 1px solid ${caretBackground}; border-right: 1px solid ${caretBackground}; }`);\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 *--------------------------------------------------------------------------------------------*/\nimport { createFastDomNode } from '../../../../base/browser/fastDomNode.js';\nimport { onUnexpectedError } from '../../../../base/common/errors.js';\nimport { ViewPart } from '../../view/viewPart.js';\nimport { Position } from '../../../common/core/position.js';\nconst invalidFunc = () => { throw new Error(`Invalid change accessor`); };\nexport class ViewZones extends ViewPart {\n constructor(context) {\n super(context);\n const options = this._context.configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n this._lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this._contentWidth = layoutInfo.contentWidth;\n this._contentLeft = layoutInfo.contentLeft;\n this.domNode = createFastDomNode(document.createElement('div'));\n this.domNode.setClassName('view-zones');\n this.domNode.setPosition('absolute');\n this.domNode.setAttribute('role', 'presentation');\n this.domNode.setAttribute('aria-hidden', 'true');\n this.marginDomNode = createFastDomNode(document.createElement('div'));\n this.marginDomNode.setClassName('margin-view-zones');\n this.marginDomNode.setPosition('absolute');\n this.marginDomNode.setAttribute('role', 'presentation');\n this.marginDomNode.setAttribute('aria-hidden', 'true');\n this._zones = {};\n }\n dispose() {\n super.dispose();\n this._zones = {};\n }\n // ---- begin view event handlers\n _recomputeWhitespacesProps() {\n const whitespaces = this._context.viewLayout.getWhitespaces();\n const oldWhitespaces = new Map();\n for (const whitespace of whitespaces) {\n oldWhitespaces.set(whitespace.id, whitespace);\n }\n let hadAChange = false;\n this._context.viewModel.changeWhitespace((whitespaceAccessor) => {\n const keys = Object.keys(this._zones);\n for (let i = 0, len = keys.length; i < len; i++) {\n const id = keys[i];\n const zone = this._zones[id];\n const props = this._computeWhitespaceProps(zone.delegate);\n zone.isInHiddenArea = props.isInHiddenArea;\n const oldWhitespace = oldWhitespaces.get(id);\n if (oldWhitespace && (oldWhitespace.afterLineNumber !== props.afterViewLineNumber || oldWhitespace.height !== props.heightInPx)) {\n whitespaceAccessor.changeOneWhitespace(id, props.afterViewLineNumber, props.heightInPx);\n this._safeCallOnComputedHeight(zone.delegate, props.heightInPx);\n hadAChange = true;\n }\n }\n });\n return hadAChange;\n }\n onConfigurationChanged(e) {\n const options = this._context.configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n this._lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this._contentWidth = layoutInfo.contentWidth;\n this._contentLeft = layoutInfo.contentLeft;\n if (e.hasChanged(61 /* EditorOption.lineHeight */)) {\n this._recomputeWhitespacesProps();\n }\n return true;\n }\n onLineMappingChanged(e) {\n return this._recomputeWhitespacesProps();\n }\n onLinesDeleted(e) {\n return true;\n }\n onScrollChanged(e) {\n return e.scrollTopChanged || e.scrollWidthChanged;\n }\n onZonesChanged(e) {\n return true;\n }\n onLinesInserted(e) {\n return true;\n }\n // ---- end view event handlers\n _getZoneOrdinal(zone) {\n if (typeof zone.afterColumn !== 'undefined') {\n return zone.afterColumn;\n }\n return 10000;\n }\n _computeWhitespaceProps(zone) {\n if (zone.afterLineNumber === 0) {\n return {\n isInHiddenArea: false,\n afterViewLineNumber: 0,\n heightInPx: this._heightInPixels(zone),\n minWidthInPx: this._minWidthInPixels(zone)\n };\n }\n let zoneAfterModelPosition;\n if (typeof zone.afterColumn !== 'undefined') {\n zoneAfterModelPosition = this._context.viewModel.model.validatePosition({\n lineNumber: zone.afterLineNumber,\n column: zone.afterColumn\n });\n }\n else {\n const validAfterLineNumber = this._context.viewModel.model.validatePosition({\n lineNumber: zone.afterLineNumber,\n column: 1\n }).lineNumber;\n zoneAfterModelPosition = new Position(validAfterLineNumber, this._context.viewModel.model.getLineMaxColumn(validAfterLineNumber));\n }\n let zoneBeforeModelPosition;\n if (zoneAfterModelPosition.column === this._context.viewModel.model.getLineMaxColumn(zoneAfterModelPosition.lineNumber)) {\n zoneBeforeModelPosition = this._context.viewModel.model.validatePosition({\n lineNumber: zoneAfterModelPosition.lineNumber + 1,\n column: 1\n });\n }\n else {\n zoneBeforeModelPosition = this._context.viewModel.model.validatePosition({\n lineNumber: zoneAfterModelPosition.lineNumber,\n column: zoneAfterModelPosition.column + 1\n });\n }\n const viewPosition = this._context.viewModel.coordinatesConverter.convertModelPositionToViewPosition(zoneAfterModelPosition, zone.afterColumnAffinity);\n const isVisible = this._context.viewModel.coordinatesConverter.modelPositionIsVisible(zoneBeforeModelPosition);\n return {\n isInHiddenArea: !isVisible,\n afterViewLineNumber: viewPosition.lineNumber,\n heightInPx: (isVisible ? this._heightInPixels(zone) : 0),\n minWidthInPx: this._minWidthInPixels(zone)\n };\n }\n changeViewZones(callback) {\n let zonesHaveChanged = false;\n this._context.viewModel.changeWhitespace((whitespaceAccessor) => {\n const changeAccessor = {\n addZone: (zone) => {\n zonesHaveChanged = true;\n return this._addZone(whitespaceAccessor, zone);\n },\n removeZone: (id) => {\n if (!id) {\n return;\n }\n zonesHaveChanged = this._removeZone(whitespaceAccessor, id) || zonesHaveChanged;\n },\n layoutZone: (id) => {\n if (!id) {\n return;\n }\n zonesHaveChanged = this._layoutZone(whitespaceAccessor, id) || zonesHaveChanged;\n }\n };\n safeInvoke1Arg(callback, changeAccessor);\n // Invalidate changeAccessor\n changeAccessor.addZone = invalidFunc;\n changeAccessor.removeZone = invalidFunc;\n changeAccessor.layoutZone = invalidFunc;\n });\n return zonesHaveChanged;\n }\n _addZone(whitespaceAccessor, zone) {\n const props = this._computeWhitespaceProps(zone);\n const whitespaceId = whitespaceAccessor.insertWhitespace(props.afterViewLineNumber, this._getZoneOrdinal(zone), props.heightInPx, props.minWidthInPx);\n const myZone = {\n whitespaceId: whitespaceId,\n delegate: zone,\n isInHiddenArea: props.isInHiddenArea,\n isVisible: false,\n domNode: createFastDomNode(zone.domNode),\n marginDomNode: zone.marginDomNode ? createFastDomNode(zone.marginDomNode) : null\n };\n this._safeCallOnComputedHeight(myZone.delegate, props.heightInPx);\n myZone.domNode.setPosition('absolute');\n myZone.domNode.domNode.style.width = '100%';\n myZone.domNode.setDisplay('none');\n myZone.domNode.setAttribute('monaco-view-zone', myZone.whitespaceId);\n this.domNode.appendChild(myZone.domNode);\n if (myZone.marginDomNode) {\n myZone.marginDomNode.setPosition('absolute');\n myZone.marginDomNode.domNode.style.width = '100%';\n myZone.marginDomNode.setDisplay('none');\n myZone.marginDomNode.setAttribute('monaco-view-zone', myZone.whitespaceId);\n this.marginDomNode.appendChild(myZone.marginDomNode);\n }\n this._zones[myZone.whitespaceId] = myZone;\n this.setShouldRender();\n return myZone.whitespaceId;\n }\n _removeZone(whitespaceAccessor, id) {\n if (this._zones.hasOwnProperty(id)) {\n const zone = this._zones[id];\n delete this._zones[id];\n whitespaceAccessor.removeWhitespace(zone.whitespaceId);\n zone.domNode.removeAttribute('monaco-visible-view-zone');\n zone.domNode.removeAttribute('monaco-view-zone');\n zone.domNode.domNode.parentNode.removeChild(zone.domNode.domNode);\n if (zone.marginDomNode) {\n zone.marginDomNode.removeAttribute('monaco-visible-view-zone');\n zone.marginDomNode.removeAttribute('monaco-view-zone');\n zone.marginDomNode.domNode.parentNode.removeChild(zone.marginDomNode.domNode);\n }\n this.setShouldRender();\n return true;\n }\n return false;\n }\n _layoutZone(whitespaceAccessor, id) {\n if (this._zones.hasOwnProperty(id)) {\n const zone = this._zones[id];\n const props = this._computeWhitespaceProps(zone.delegate);\n zone.isInHiddenArea = props.isInHiddenArea;\n // const newOrdinal = this._getZoneOrdinal(zone.delegate);\n whitespaceAccessor.changeOneWhitespace(zone.whitespaceId, props.afterViewLineNumber, props.heightInPx);\n // TODO@Alex: change `newOrdinal` too\n this._safeCallOnComputedHeight(zone.delegate, props.heightInPx);\n this.setShouldRender();\n return true;\n }\n return false;\n }\n shouldSuppressMouseDownOnViewZone(id) {\n if (this._zones.hasOwnProperty(id)) {\n const zone = this._zones[id];\n return Boolean(zone.delegate.suppressMouseDown);\n }\n return false;\n }\n _heightInPixels(zone) {\n if (typeof zone.heightInPx === 'number') {\n return zone.heightInPx;\n }\n if (typeof zone.heightInLines === 'number') {\n return this._lineHeight * zone.heightInLines;\n }\n return this._lineHeight;\n }\n _minWidthInPixels(zone) {\n if (typeof zone.minWidthInPx === 'number') {\n return zone.minWidthInPx;\n }\n return 0;\n }\n _safeCallOnComputedHeight(zone, height) {\n if (typeof zone.onComputedHeight === 'function') {\n try {\n zone.onComputedHeight(height);\n }\n catch (e) {\n onUnexpectedError(e);\n }\n }\n }\n _safeCallOnDomNodeTop(zone, top) {\n if (typeof zone.onDomNodeTop === 'function') {\n try {\n zone.onDomNodeTop(top);\n }\n catch (e) {\n onUnexpectedError(e);\n }\n }\n }\n prepareRender(ctx) {\n // Nothing to read\n }\n render(ctx) {\n const visibleWhitespaces = ctx.viewportData.whitespaceViewportData;\n const visibleZones = {};\n let hasVisibleZone = false;\n for (const visibleWhitespace of visibleWhitespaces) {\n if (this._zones[visibleWhitespace.id].isInHiddenArea) {\n continue;\n }\n visibleZones[visibleWhitespace.id] = visibleWhitespace;\n hasVisibleZone = true;\n }\n const keys = Object.keys(this._zones);\n for (let i = 0, len = keys.length; i < len; i++) {\n const id = keys[i];\n const zone = this._zones[id];\n let newTop = 0;\n let newHeight = 0;\n let newDisplay = 'none';\n if (visibleZones.hasOwnProperty(id)) {\n newTop = visibleZones[id].verticalOffset - ctx.bigNumbersDelta;\n newHeight = visibleZones[id].height;\n newDisplay = 'block';\n // zone is visible\n if (!zone.isVisible) {\n zone.domNode.setAttribute('monaco-visible-view-zone', 'true');\n zone.isVisible = true;\n }\n this._safeCallOnDomNodeTop(zone.delegate, ctx.getScrolledTopFromAbsoluteTop(visibleZones[id].verticalOffset));\n }\n else {\n if (zone.isVisible) {\n zone.domNode.removeAttribute('monaco-visible-view-zone');\n zone.isVisible = false;\n }\n this._safeCallOnDomNodeTop(zone.delegate, ctx.getScrolledTopFromAbsoluteTop(-1000000));\n }\n zone.domNode.setTop(newTop);\n zone.domNode.setHeight(newHeight);\n zone.domNode.setDisplay(newDisplay);\n if (zone.marginDomNode) {\n zone.marginDomNode.setTop(newTop);\n zone.marginDomNode.setHeight(newHeight);\n zone.marginDomNode.setDisplay(newDisplay);\n }\n }\n if (hasVisibleZone) {\n this.domNode.setWidth(Math.max(ctx.scrollWidth, this._contentWidth));\n this.marginDomNode.setWidth(this._contentLeft);\n }\n }\n}\nfunction safeInvoke1Arg(func, arg1) {\n try {\n return func(arg1);\n }\n catch (e) {\n onUnexpectedError(e);\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 *--------------------------------------------------------------------------------------------*/\nexport class EditorTheme {\n constructor(theme) {\n this._theme = theme;\n }\n get type() {\n return this._theme.type;\n }\n get value() {\n return this._theme;\n }\n update(theme) {\n this._theme = theme;\n }\n getColor(color) {\n return this._theme.getColor(color);\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 *--------------------------------------------------------------------------------------------*/\nimport { EditorTheme } from '../editorTheme.js';\nexport class ViewContext {\n constructor(configuration, theme, model) {\n this.configuration = configuration;\n this.theme = new EditorTheme(theme);\n this.viewModel = model;\n this.viewLayout = model.viewLayout;\n }\n addEventHandler(eventHandler) {\n this.viewModel.addViewEventHandler(eventHandler);\n }\n removeEventHandler(eventHandler) {\n this.viewModel.removeViewEventHandler(eventHandler);\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 *--------------------------------------------------------------------------------------------*/\nimport { Range } from '../core/range.js';\n/**\n * Contains all data needed to render at a specific viewport.\n */\nexport class ViewportData {\n constructor(selections, partialData, whitespaceViewportData, model) {\n this.selections = selections;\n this.startLineNumber = partialData.startLineNumber | 0;\n this.endLineNumber = partialData.endLineNumber | 0;\n this.relativeVerticalOffset = partialData.relativeVerticalOffset;\n this.bigNumbersDelta = partialData.bigNumbersDelta | 0;\n this.whitespaceViewportData = whitespaceViewportData;\n this._model = model;\n this.visibleRange = new Range(partialData.startLineNumber, this._model.getLineMinColumn(partialData.startLineNumber), partialData.endLineNumber, this._model.getLineMaxColumn(partialData.endLineNumber));\n }\n getViewLineRenderingData(lineNumber) {\n return this._model.getViewportViewLineRenderingData(this.visibleRange, lineNumber);\n }\n getDecorationsInViewport() {\n return this._model.getDecorationsInViewport(this.visibleRange);\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 *--------------------------------------------------------------------------------------------*/\nimport { createFastDomNode } from '../../../../base/browser/fastDomNode.js';\nimport './blockDecorations.css';\nimport { ViewPart } from '../../view/viewPart.js';\nexport class BlockDecorations extends ViewPart {\n constructor(context) {\n super(context);\n this.blocks = [];\n this.contentWidth = -1;\n this.domNode = createFastDomNode(document.createElement('div'));\n this.domNode.setAttribute('role', 'presentation');\n this.domNode.setAttribute('aria-hidden', 'true');\n this.domNode.setClassName('blockDecorations-container');\n this.update();\n }\n update() {\n let didChange = false;\n const options = this._context.configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n const newContentWidth = layoutInfo.contentWidth - layoutInfo.verticalScrollbarWidth;\n if (this.contentWidth !== newContentWidth) {\n this.contentWidth = newContentWidth;\n didChange = true;\n }\n return didChange;\n }\n dispose() {\n super.dispose();\n }\n // --- begin event handlers\n onConfigurationChanged(e) {\n return this.update();\n }\n onScrollChanged(e) {\n return e.scrollTopChanged || e.scrollLeftChanged;\n }\n onDecorationsChanged(e) {\n return true;\n }\n onZonesChanged(e) {\n return true;\n }\n // --- end event handlers\n prepareRender(ctx) {\n // Nothing to read\n }\n render(ctx) {\n let count = 0;\n const decorations = ctx.getDecorationsInViewport();\n for (const decoration of decorations) {\n if (!decoration.options.blockClassName) {\n continue;\n }\n let block = this.blocks[count];\n if (!block) {\n block = this.blocks[count] = createFastDomNode(document.createElement('div'));\n this.domNode.appendChild(block);\n }\n const top = ctx.getVerticalOffsetForLineNumber(decoration.range.startLineNumber);\n // See https://github.com/microsoft/vscode/pull/152740#discussion_r902661546\n const bottom = ctx.getVerticalOffsetForLineNumber(decoration.range.endLineNumber + 1);\n block.setClassName('blockDecorations-block ' + decoration.options.blockClassName);\n block.setLeft(ctx.scrollLeft);\n block.setWidth(this.contentWidth);\n block.setTop(top);\n block.setHeight(bottom - top);\n count++;\n }\n for (let i = count; i < this.blocks.length; i++) {\n this.blocks[i].domNode.remove();\n }\n this.blocks.length = count;\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 *--------------------------------------------------------------------------------------------*/\nimport * as dom from '../../base/browser/dom.js';\nimport { Selection } from '../common/core/selection.js';\nimport { createFastDomNode } from '../../base/browser/fastDomNode.js';\nimport { onUnexpectedError } from '../../base/common/errors.js';\nimport { PointerHandler } from './controller/pointerHandler.js';\nimport { TextAreaHandler } from './controller/textAreaHandler.js';\nimport { ViewController } from './view/viewController.js';\nimport { ViewUserInputEvents } from './view/viewUserInputEvents.js';\nimport { ContentViewOverlays, MarginViewOverlays } from './view/viewOverlays.js';\nimport { PartFingerprints } from './view/viewPart.js';\nimport { ViewContentWidgets } from './viewParts/contentWidgets/contentWidgets.js';\nimport { CurrentLineHighlightOverlay, CurrentLineMarginHighlightOverlay } from './viewParts/currentLineHighlight/currentLineHighlight.js';\nimport { DecorationsOverlay } from './viewParts/decorations/decorations.js';\nimport { EditorScrollbar } from './viewParts/editorScrollbar/editorScrollbar.js';\nimport { GlyphMarginOverlay } from './viewParts/glyphMargin/glyphMargin.js';\nimport { IndentGuidesOverlay } from './viewParts/indentGuides/indentGuides.js';\nimport { LineNumbersOverlay } from './viewParts/lineNumbers/lineNumbers.js';\nimport { ViewLines } from './viewParts/lines/viewLines.js';\nimport { LinesDecorationsOverlay } from './viewParts/linesDecorations/linesDecorations.js';\nimport { Margin } from './viewParts/margin/margin.js';\nimport { MarginViewLineDecorationsOverlay } from './viewParts/marginDecorations/marginDecorations.js';\nimport { Minimap } from './viewParts/minimap/minimap.js';\nimport { ViewOverlayWidgets } from './viewParts/overlayWidgets/overlayWidgets.js';\nimport { DecorationsOverviewRuler } from './viewParts/overviewRuler/decorationsOverviewRuler.js';\nimport { OverviewRuler } from './viewParts/overviewRuler/overviewRuler.js';\nimport { Rulers } from './viewParts/rulers/rulers.js';\nimport { ScrollDecorationViewPart } from './viewParts/scrollDecoration/scrollDecoration.js';\nimport { SelectionsOverlay } from './viewParts/selections/selections.js';\nimport { ViewCursors } from './viewParts/viewCursors/viewCursors.js';\nimport { ViewZones } from './viewParts/viewZones/viewZones.js';\nimport { Position } from '../common/core/position.js';\nimport { Range } from '../common/core/range.js';\nimport { RenderingContext } from './view/renderingContext.js';\nimport { ViewContext } from '../common/viewModel/viewContext.js';\nimport { ViewportData } from '../common/viewLayout/viewLinesViewportData.js';\nimport { ViewEventHandler } from '../common/viewEventHandler.js';\nimport { getThemeTypeSelector } from '../../platform/theme/common/themeService.js';\nimport { PointerHandlerLastRenderData } from './controller/mouseTarget.js';\nimport { BlockDecorations } from './viewParts/blockDecorations/blockDecorations.js';\nexport class View extends ViewEventHandler {\n constructor(commandDelegate, configuration, colorTheme, model, userInputEvents, overflowWidgetsDomNode) {\n super();\n this._selections = [new Selection(1, 1, 1, 1)];\n this._renderAnimationFrame = null;\n const viewController = new ViewController(configuration, model, userInputEvents, commandDelegate);\n // The view context is passed on to most classes (basically to reduce param. counts in ctors)\n this._context = new ViewContext(configuration, colorTheme, model);\n // Ensure the view is the first event handler in order to update the layout\n this._context.addEventHandler(this);\n this._viewParts = [];\n // Keyboard handler\n this._textAreaHandler = new TextAreaHandler(this._context, viewController, this._createTextAreaHandlerHelper());\n this._viewParts.push(this._textAreaHandler);\n // These two dom nodes must be constructed up front, since references are needed in the layout provider (scrolling & co.)\n this._linesContent = createFastDomNode(document.createElement('div'));\n this._linesContent.setClassName('lines-content' + ' monaco-editor-background');\n this._linesContent.setPosition('absolute');\n this.domNode = createFastDomNode(document.createElement('div'));\n this.domNode.setClassName(this._getEditorClassName());\n // Set role 'code' for better screen reader support https://github.com/microsoft/vscode/issues/93438\n this.domNode.setAttribute('role', 'code');\n this._overflowGuardContainer = createFastDomNode(document.createElement('div'));\n PartFingerprints.write(this._overflowGuardContainer, 3 /* PartFingerprint.OverflowGuard */);\n this._overflowGuardContainer.setClassName('overflow-guard');\n this._scrollbar = new EditorScrollbar(this._context, this._linesContent, this.domNode, this._overflowGuardContainer);\n this._viewParts.push(this._scrollbar);\n // View Lines\n this._viewLines = new ViewLines(this._context, this._linesContent);\n // View Zones\n this._viewZones = new ViewZones(this._context);\n this._viewParts.push(this._viewZones);\n // Decorations overview ruler\n const decorationsOverviewRuler = new DecorationsOverviewRuler(this._context);\n this._viewParts.push(decorationsOverviewRuler);\n const scrollDecoration = new ScrollDecorationViewPart(this._context);\n this._viewParts.push(scrollDecoration);\n const contentViewOverlays = new ContentViewOverlays(this._context);\n this._viewParts.push(contentViewOverlays);\n contentViewOverlays.addDynamicOverlay(new CurrentLineHighlightOverlay(this._context));\n contentViewOverlays.addDynamicOverlay(new SelectionsOverlay(this._context));\n contentViewOverlays.addDynamicOverlay(new IndentGuidesOverlay(this._context));\n contentViewOverlays.addDynamicOverlay(new DecorationsOverlay(this._context));\n const marginViewOverlays = new MarginViewOverlays(this._context);\n this._viewParts.push(marginViewOverlays);\n marginViewOverlays.addDynamicOverlay(new CurrentLineMarginHighlightOverlay(this._context));\n marginViewOverlays.addDynamicOverlay(new GlyphMarginOverlay(this._context));\n marginViewOverlays.addDynamicOverlay(new MarginViewLineDecorationsOverlay(this._context));\n marginViewOverlays.addDynamicOverlay(new LinesDecorationsOverlay(this._context));\n marginViewOverlays.addDynamicOverlay(new LineNumbersOverlay(this._context));\n const margin = new Margin(this._context);\n margin.getDomNode().appendChild(this._viewZones.marginDomNode);\n margin.getDomNode().appendChild(marginViewOverlays.getDomNode());\n this._viewParts.push(margin);\n // Content widgets\n this._contentWidgets = new ViewContentWidgets(this._context, this.domNode);\n this._viewParts.push(this._contentWidgets);\n this._viewCursors = new ViewCursors(this._context);\n this._viewParts.push(this._viewCursors);\n // Overlay widgets\n this._overlayWidgets = new ViewOverlayWidgets(this._context);\n this._viewParts.push(this._overlayWidgets);\n const rulers = new Rulers(this._context);\n this._viewParts.push(rulers);\n const blockOutline = new BlockDecorations(this._context);\n this._viewParts.push(blockOutline);\n const minimap = new Minimap(this._context);\n this._viewParts.push(minimap);\n // -------------- Wire dom nodes up\n if (decorationsOverviewRuler) {\n const overviewRulerData = this._scrollbar.getOverviewRulerLayoutInfo();\n overviewRulerData.parent.insertBefore(decorationsOverviewRuler.getDomNode(), overviewRulerData.insertBefore);\n }\n this._linesContent.appendChild(contentViewOverlays.getDomNode());\n this._linesContent.appendChild(rulers.domNode);\n this._linesContent.appendChild(blockOutline.domNode);\n this._linesContent.appendChild(this._viewZones.domNode);\n this._linesContent.appendChild(this._viewLines.getDomNode());\n this._linesContent.appendChild(this._contentWidgets.domNode);\n this._linesContent.appendChild(this._viewCursors.getDomNode());\n this._overflowGuardContainer.appendChild(margin.getDomNode());\n this._overflowGuardContainer.appendChild(this._scrollbar.getDomNode());\n this._overflowGuardContainer.appendChild(scrollDecoration.getDomNode());\n this._overflowGuardContainer.appendChild(this._textAreaHandler.textArea);\n this._overflowGuardContainer.appendChild(this._textAreaHandler.textAreaCover);\n this._overflowGuardContainer.appendChild(this._overlayWidgets.getDomNode());\n this._overflowGuardContainer.appendChild(minimap.getDomNode());\n this.domNode.appendChild(this._overflowGuardContainer);\n if (overflowWidgetsDomNode) {\n overflowWidgetsDomNode.appendChild(this._contentWidgets.overflowingContentWidgetsDomNode.domNode);\n }\n else {\n this.domNode.appendChild(this._contentWidgets.overflowingContentWidgetsDomNode);\n }\n this._applyLayout();\n // Pointer handler\n this._pointerHandler = this._register(new PointerHandler(this._context, viewController, this._createPointerHandlerHelper()));\n }\n _flushAccumulatedAndRenderNow() {\n this._renderNow();\n }\n _createPointerHandlerHelper() {\n return {\n viewDomNode: this.domNode.domNode,\n linesContentDomNode: this._linesContent.domNode,\n viewLinesDomNode: this._viewLines.getDomNode().domNode,\n focusTextArea: () => {\n this.focus();\n },\n dispatchTextAreaEvent: (event) => {\n this._textAreaHandler.textArea.domNode.dispatchEvent(event);\n },\n getLastRenderData: () => {\n const lastViewCursorsRenderData = this._viewCursors.getLastRenderData() || [];\n const lastTextareaPosition = this._textAreaHandler.getLastRenderData();\n return new PointerHandlerLastRenderData(lastViewCursorsRenderData, lastTextareaPosition);\n },\n shouldSuppressMouseDownOnViewZone: (viewZoneId) => {\n return this._viewZones.shouldSuppressMouseDownOnViewZone(viewZoneId);\n },\n shouldSuppressMouseDownOnWidget: (widgetId) => {\n return this._contentWidgets.shouldSuppressMouseDownOnWidget(widgetId);\n },\n getPositionFromDOMInfo: (spanNode, offset) => {\n this._flushAccumulatedAndRenderNow();\n return this._viewLines.getPositionFromDOMInfo(spanNode, offset);\n },\n visibleRangeForPosition: (lineNumber, column) => {\n this._flushAccumulatedAndRenderNow();\n return this._viewLines.visibleRangeForPosition(new Position(lineNumber, column));\n },\n getLineWidth: (lineNumber) => {\n this._flushAccumulatedAndRenderNow();\n return this._viewLines.getLineWidth(lineNumber);\n }\n };\n }\n _createTextAreaHandlerHelper() {\n return {\n visibleRangeForPosition: (position) => {\n this._flushAccumulatedAndRenderNow();\n return this._viewLines.visibleRangeForPosition(position);\n }\n };\n }\n _applyLayout() {\n const options = this._context.configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n this.domNode.setWidth(layoutInfo.width);\n this.domNode.setHeight(layoutInfo.height);\n this._overflowGuardContainer.setWidth(layoutInfo.width);\n this._overflowGuardContainer.setHeight(layoutInfo.height);\n this._linesContent.setWidth(1000000);\n this._linesContent.setHeight(1000000);\n }\n _getEditorClassName() {\n const focused = this._textAreaHandler.isFocused() ? ' focused' : '';\n return this._context.configuration.options.get(130 /* EditorOption.editorClassName */) + ' ' + getThemeTypeSelector(this._context.theme.type) + focused;\n }\n // --- begin event handlers\n handleEvents(events) {\n super.handleEvents(events);\n this._scheduleRender();\n }\n onConfigurationChanged(e) {\n this.domNode.setClassName(this._getEditorClassName());\n this._applyLayout();\n return false;\n }\n onCursorStateChanged(e) {\n this._selections = e.selections;\n return false;\n }\n onFocusChanged(e) {\n this.domNode.setClassName(this._getEditorClassName());\n return false;\n }\n onThemeChanged(e) {\n this._context.theme.update(e.theme);\n this.domNode.setClassName(this._getEditorClassName());\n return false;\n }\n // --- end event handlers\n dispose() {\n if (this._renderAnimationFrame !== null) {\n this._renderAnimationFrame.dispose();\n this._renderAnimationFrame = null;\n }\n this._contentWidgets.overflowingContentWidgetsDomNode.domNode.remove();\n this._context.removeEventHandler(this);\n this._viewLines.dispose();\n // Destroy view parts\n for (const viewPart of this._viewParts) {\n viewPart.dispose();\n }\n super.dispose();\n }\n _scheduleRender() {\n if (this._renderAnimationFrame === null) {\n this._renderAnimationFrame = dom.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), 100);\n }\n }\n _onRenderScheduled() {\n this._renderAnimationFrame = null;\n this._flushAccumulatedAndRenderNow();\n }\n _renderNow() {\n safeInvokeNoArg(() => this._actualRender());\n }\n _getViewPartsToRender() {\n const result = [];\n let resultLen = 0;\n for (const viewPart of this._viewParts) {\n if (viewPart.shouldRender()) {\n result[resultLen++] = viewPart;\n }\n }\n return result;\n }\n _actualRender() {\n if (!dom.isInDOM(this.domNode.domNode)) {\n return;\n }\n let viewPartsToRender = this._getViewPartsToRender();\n if (!this._viewLines.shouldRender() && viewPartsToRender.length === 0) {\n // Nothing to render\n return;\n }\n const partialViewportData = this._context.viewLayout.getLinesViewportData();\n this._context.viewModel.setViewport(partialViewportData.startLineNumber, partialViewportData.endLineNumber, partialViewportData.centeredLineNumber);\n const viewportData = new ViewportData(this._selections, partialViewportData, this._context.viewLayout.getWhitespaceViewportData(), this._context.viewModel);\n if (this._contentWidgets.shouldRender()) {\n // Give the content widgets a chance to set their max width before a possible synchronous layout\n this._contentWidgets.onBeforeRender(viewportData);\n }\n if (this._viewLines.shouldRender()) {\n this._viewLines.renderText(viewportData);\n this._viewLines.onDidRender();\n // Rendering of viewLines might cause scroll events to occur, so collect view parts to render again\n viewPartsToRender = this._getViewPartsToRender();\n }\n const renderingContext = new RenderingContext(this._context.viewLayout, viewportData, this._viewLines);\n // Render the rest of the parts\n for (const viewPart of viewPartsToRender) {\n viewPart.prepareRender(renderingContext);\n }\n for (const viewPart of viewPartsToRender) {\n viewPart.render(renderingContext);\n viewPart.onDidRender();\n }\n }\n // --- BEGIN CodeEditor helpers\n delegateVerticalScrollbarPointerDown(browserEvent) {\n this._scrollbar.delegateVerticalScrollbarPointerDown(browserEvent);\n }\n restoreState(scrollPosition) {\n this._context.viewModel.viewLayout.setScrollPosition({ scrollTop: scrollPosition.scrollTop }, 1 /* ScrollType.Immediate */);\n this._context.viewModel.tokenizeViewport();\n this._renderNow();\n this._viewLines.updateLineWidths();\n this._context.viewModel.viewLayout.setScrollPosition({ scrollLeft: scrollPosition.scrollLeft }, 1 /* ScrollType.Immediate */);\n }\n getOffsetForColumn(modelLineNumber, modelColumn) {\n const modelPosition = this._context.viewModel.model.validatePosition({\n lineNumber: modelLineNumber,\n column: modelColumn\n });\n const viewPosition = this._context.viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);\n this._flushAccumulatedAndRenderNow();\n const visibleRange = this._viewLines.visibleRangeForPosition(new Position(viewPosition.lineNumber, viewPosition.column));\n if (!visibleRange) {\n return -1;\n }\n return visibleRange.left;\n }\n getTargetAtClientPoint(clientX, clientY) {\n const mouseTarget = this._pointerHandler.getTargetAtClientPoint(clientX, clientY);\n if (!mouseTarget) {\n return null;\n }\n return ViewUserInputEvents.convertViewToModelMouseTarget(mouseTarget, this._context.viewModel.coordinatesConverter);\n }\n createOverviewRuler(cssClassName) {\n return new OverviewRuler(this._context, cssClassName);\n }\n change(callback) {\n this._viewZones.changeViewZones(callback);\n this._scheduleRender();\n }\n render(now, everything) {\n if (everything) {\n // Force everything to render...\n this._viewLines.forceShouldRender();\n for (const viewPart of this._viewParts) {\n viewPart.forceShouldRender();\n }\n }\n if (now) {\n this._flushAccumulatedAndRenderNow();\n }\n else {\n this._scheduleRender();\n }\n }\n focus() {\n this._textAreaHandler.focusTextArea();\n }\n isFocused() {\n return this._textAreaHandler.isFocused();\n }\n setAriaOptions(options) {\n this._textAreaHandler.setAriaOptions(options);\n }\n addContentWidget(widgetData) {\n this._contentWidgets.addWidget(widgetData.widget);\n this.layoutContentWidget(widgetData);\n this._scheduleRender();\n }\n layoutContentWidget(widgetData) {\n var _a, _b;\n let newRange = widgetData.position ? widgetData.position.range || null : null;\n if (newRange === null) {\n const newPosition = widgetData.position ? widgetData.position.position : null;\n if (newPosition !== null) {\n newRange = new Range(newPosition.lineNumber, newPosition.column, newPosition.lineNumber, newPosition.column);\n }\n }\n const newPreference = widgetData.position ? widgetData.position.preference : null;\n this._contentWidgets.setWidgetPosition(widgetData.widget, newRange, newPreference, (_b = (_a = widgetData.position) === null || _a === void 0 ? void 0 : _a.positionAffinity) !== null && _b !== void 0 ? _b : null);\n this._scheduleRender();\n }\n removeContentWidget(widgetData) {\n this._contentWidgets.removeWidget(widgetData.widget);\n this._scheduleRender();\n }\n addOverlayWidget(widgetData) {\n this._overlayWidgets.addWidget(widgetData.widget);\n this.layoutOverlayWidget(widgetData);\n this._scheduleRender();\n }\n layoutOverlayWidget(widgetData) {\n const newPreference = widgetData.position ? widgetData.position.preference : null;\n const shouldRender = this._overlayWidgets.setWidgetPosition(widgetData.widget, newPreference);\n if (shouldRender) {\n this._scheduleRender();\n }\n }\n removeOverlayWidget(widgetData) {\n this._overlayWidgets.removeWidget(widgetData.widget);\n this._scheduleRender();\n }\n}\nfunction safeInvokeNoArg(func) {\n try {\n return func();\n }\n catch (e) {\n onUnexpectedError(e);\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 *--------------------------------------------------------------------------------------------*/\nimport { CursorState, SingleCursorState } from '../cursorCommon.js';\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nimport { Selection } from '../core/selection.js';\n/**\n * Represents a single cursor.\n*/\nexport class Cursor {\n constructor(context) {\n this._selTrackedRange = null;\n this._trackSelection = true;\n this._setState(context, new SingleCursorState(new Range(1, 1, 1, 1), 0, new Position(1, 1), 0), new SingleCursorState(new Range(1, 1, 1, 1), 0, new Position(1, 1), 0));\n }\n dispose(context) {\n this._removeTrackedRange(context);\n }\n startTrackingSelection(context) {\n this._trackSelection = true;\n this._updateTrackedRange(context);\n }\n stopTrackingSelection(context) {\n this._trackSelection = false;\n this._removeTrackedRange(context);\n }\n _updateTrackedRange(context) {\n if (!this._trackSelection) {\n // don't track the selection\n return;\n }\n this._selTrackedRange = context.model._setTrackedRange(this._selTrackedRange, this.modelState.selection, 0 /* TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges */);\n }\n _removeTrackedRange(context) {\n this._selTrackedRange = context.model._setTrackedRange(this._selTrackedRange, null, 0 /* TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges */);\n }\n asCursorState() {\n return new CursorState(this.modelState, this.viewState);\n }\n readSelectionFromMarkers(context) {\n const range = context.model._getTrackedRange(this._selTrackedRange);\n return Selection.fromRange(range, this.modelState.selection.getDirection());\n }\n ensureValidState(context) {\n this._setState(context, this.modelState, this.viewState);\n }\n setState(context, modelState, viewState) {\n this._setState(context, modelState, viewState);\n }\n static _validatePositionWithCache(viewModel, position, cacheInput, cacheOutput) {\n if (position.equals(cacheInput)) {\n return cacheOutput;\n }\n return viewModel.normalizePosition(position, 2 /* PositionAffinity.None */);\n }\n static _validateViewState(viewModel, viewState) {\n const position = viewState.position;\n const sStartPosition = viewState.selectionStart.getStartPosition();\n const sEndPosition = viewState.selectionStart.getEndPosition();\n const validPosition = viewModel.normalizePosition(position, 2 /* PositionAffinity.None */);\n const validSStartPosition = this._validatePositionWithCache(viewModel, sStartPosition, position, validPosition);\n const validSEndPosition = this._validatePositionWithCache(viewModel, sEndPosition, sStartPosition, validSStartPosition);\n if (position.equals(validPosition) && sStartPosition.equals(validSStartPosition) && sEndPosition.equals(validSEndPosition)) {\n // fast path: the state is valid\n return viewState;\n }\n return new SingleCursorState(Range.fromPositions(validSStartPosition, validSEndPosition), viewState.selectionStartLeftoverVisibleColumns + sStartPosition.column - validSStartPosition.column, validPosition, viewState.leftoverVisibleColumns + position.column - validPosition.column);\n }\n _setState(context, modelState, viewState) {\n if (viewState) {\n viewState = Cursor._validateViewState(context.viewModel, viewState);\n }\n if (!modelState) {\n if (!viewState) {\n return;\n }\n // We only have the view state => compute the model state\n const selectionStart = context.model.validateRange(context.coordinatesConverter.convertViewRangeToModelRange(viewState.selectionStart));\n const position = context.model.validatePosition(context.coordinatesConverter.convertViewPositionToModelPosition(viewState.position));\n modelState = new SingleCursorState(selectionStart, viewState.selectionStartLeftoverVisibleColumns, position, viewState.leftoverVisibleColumns);\n }\n else {\n // Validate new model state\n const selectionStart = context.model.validateRange(modelState.selectionStart);\n const selectionStartLeftoverVisibleColumns = modelState.selectionStart.equalsRange(selectionStart) ? modelState.selectionStartLeftoverVisibleColumns : 0;\n const position = context.model.validatePosition(modelState.position);\n const leftoverVisibleColumns = modelState.position.equals(position) ? modelState.leftoverVisibleColumns : 0;\n modelState = new SingleCursorState(selectionStart, selectionStartLeftoverVisibleColumns, position, leftoverVisibleColumns);\n }\n if (!viewState) {\n // We only have the model state => compute the view state\n const viewSelectionStart1 = context.coordinatesConverter.convertModelPositionToViewPosition(new Position(modelState.selectionStart.startLineNumber, modelState.selectionStart.startColumn));\n const viewSelectionStart2 = context.coordinatesConverter.convertModelPositionToViewPosition(new Position(modelState.selectionStart.endLineNumber, modelState.selectionStart.endColumn));\n const viewSelectionStart = new Range(viewSelectionStart1.lineNumber, viewSelectionStart1.column, viewSelectionStart2.lineNumber, viewSelectionStart2.column);\n const viewPosition = context.coordinatesConverter.convertModelPositionToViewPosition(modelState.position);\n viewState = new SingleCursorState(viewSelectionStart, modelState.selectionStartLeftoverVisibleColumns, viewPosition, modelState.leftoverVisibleColumns);\n }\n else {\n // Validate new view state\n const viewSelectionStart = context.coordinatesConverter.validateViewRange(viewState.selectionStart, modelState.selectionStart);\n const viewPosition = context.coordinatesConverter.validateViewPosition(viewState.position, modelState.position);\n viewState = new SingleCursorState(viewSelectionStart, modelState.selectionStartLeftoverVisibleColumns, viewPosition, modelState.leftoverVisibleColumns);\n }\n this.modelState = modelState;\n this.viewState = viewState;\n this._updateTrackedRange(context);\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 *--------------------------------------------------------------------------------------------*/\nimport { compareBy, findLastMaxBy, findMinBy } from '../../../base/common/arrays.js';\nimport { CursorState } from '../cursorCommon.js';\nimport { Cursor } from './oneCursor.js';\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nimport { Selection } from '../core/selection.js';\nexport class CursorCollection {\n constructor(context) {\n this.context = context;\n this.cursors = [new Cursor(context)];\n this.lastAddedCursorIndex = 0;\n }\n dispose() {\n for (const cursor of this.cursors) {\n cursor.dispose(this.context);\n }\n }\n startTrackingSelections() {\n for (const cursor of this.cursors) {\n cursor.startTrackingSelection(this.context);\n }\n }\n stopTrackingSelections() {\n for (const cursor of this.cursors) {\n cursor.stopTrackingSelection(this.context);\n }\n }\n updateContext(context) {\n this.context = context;\n }\n ensureValidState() {\n for (const cursor of this.cursors) {\n cursor.ensureValidState(this.context);\n }\n }\n readSelectionFromMarkers() {\n return this.cursors.map(c => c.readSelectionFromMarkers(this.context));\n }\n getAll() {\n return this.cursors.map(c => c.asCursorState());\n }\n getViewPositions() {\n return this.cursors.map(c => c.viewState.position);\n }\n getTopMostViewPosition() {\n return findMinBy(this.cursors, compareBy(c => c.viewState.position, Position.compare)).viewState.position;\n }\n getBottomMostViewPosition() {\n return findLastMaxBy(this.cursors, compareBy(c => c.viewState.position, Position.compare)).viewState.position;\n }\n getSelections() {\n return this.cursors.map(c => c.modelState.selection);\n }\n getViewSelections() {\n return this.cursors.map(c => c.viewState.selection);\n }\n setSelections(selections) {\n this.setStates(CursorState.fromModelSelections(selections));\n }\n getPrimaryCursor() {\n return this.cursors[0].asCursorState();\n }\n setStates(states) {\n if (states === null) {\n return;\n }\n this.cursors[0].setState(this.context, states[0].modelState, states[0].viewState);\n this._setSecondaryStates(states.slice(1));\n }\n /**\n * Creates or disposes secondary cursors as necessary to match the number of `secondarySelections`.\n */\n _setSecondaryStates(secondaryStates) {\n const secondaryCursorsLength = this.cursors.length - 1;\n const secondaryStatesLength = secondaryStates.length;\n if (secondaryCursorsLength < secondaryStatesLength) {\n const createCnt = secondaryStatesLength - secondaryCursorsLength;\n for (let i = 0; i < createCnt; i++) {\n this._addSecondaryCursor();\n }\n }\n else if (secondaryCursorsLength > secondaryStatesLength) {\n const removeCnt = secondaryCursorsLength - secondaryStatesLength;\n for (let i = 0; i < removeCnt; i++) {\n this._removeSecondaryCursor(this.cursors.length - 2);\n }\n }\n for (let i = 0; i < secondaryStatesLength; i++) {\n this.cursors[i + 1].setState(this.context, secondaryStates[i].modelState, secondaryStates[i].viewState);\n }\n }\n killSecondaryCursors() {\n this._setSecondaryStates([]);\n }\n _addSecondaryCursor() {\n this.cursors.push(new Cursor(this.context));\n this.lastAddedCursorIndex = this.cursors.length - 1;\n }\n getLastAddedCursorIndex() {\n if (this.cursors.length === 1 || this.lastAddedCursorIndex === 0) {\n return 0;\n }\n return this.lastAddedCursorIndex;\n }\n _removeSecondaryCursor(removeIndex) {\n if (this.lastAddedCursorIndex >= removeIndex + 1) {\n this.lastAddedCursorIndex--;\n }\n this.cursors[removeIndex + 1].dispose(this.context);\n this.cursors.splice(removeIndex + 1, 1);\n }\n normalize() {\n if (this.cursors.length === 1) {\n return;\n }\n const cursors = this.cursors.slice(0);\n const sortedCursors = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n sortedCursors.push({\n index: i,\n selection: cursors[i].modelState.selection,\n });\n }\n sortedCursors.sort(compareBy(s => s.selection, Range.compareRangesUsingStarts));\n for (let sortedCursorIndex = 0; sortedCursorIndex < sortedCursors.length - 1; sortedCursorIndex++) {\n const current = sortedCursors[sortedCursorIndex];\n const next = sortedCursors[sortedCursorIndex + 1];\n const currentSelection = current.selection;\n const nextSelection = next.selection;\n if (!this.context.cursorConfig.multiCursorMergeOverlapping) {\n continue;\n }\n let shouldMergeCursors;\n if (nextSelection.isEmpty() || currentSelection.isEmpty()) {\n // Merge touching cursors if one of them is collapsed\n shouldMergeCursors = nextSelection.getStartPosition().isBeforeOrEqual(currentSelection.getEndPosition());\n }\n else {\n // Merge only overlapping cursors (i.e. allow touching ranges)\n shouldMergeCursors = nextSelection.getStartPosition().isBefore(currentSelection.getEndPosition());\n }\n if (shouldMergeCursors) {\n const winnerSortedCursorIndex = current.index < next.index ? sortedCursorIndex : sortedCursorIndex + 1;\n const looserSortedCursorIndex = current.index < next.index ? sortedCursorIndex + 1 : sortedCursorIndex;\n const looserIndex = sortedCursors[looserSortedCursorIndex].index;\n const winnerIndex = sortedCursors[winnerSortedCursorIndex].index;\n const looserSelection = sortedCursors[looserSortedCursorIndex].selection;\n const winnerSelection = sortedCursors[winnerSortedCursorIndex].selection;\n if (!looserSelection.equalsSelection(winnerSelection)) {\n const resultingRange = looserSelection.plusRange(winnerSelection);\n const looserSelectionIsLTR = (looserSelection.selectionStartLineNumber === looserSelection.startLineNumber && looserSelection.selectionStartColumn === looserSelection.startColumn);\n const winnerSelectionIsLTR = (winnerSelection.selectionStartLineNumber === winnerSelection.startLineNumber && winnerSelection.selectionStartColumn === winnerSelection.startColumn);\n // Give more importance to the last added cursor (think Ctrl-dragging + hitting another cursor)\n let resultingSelectionIsLTR;\n if (looserIndex === this.lastAddedCursorIndex) {\n resultingSelectionIsLTR = looserSelectionIsLTR;\n this.lastAddedCursorIndex = winnerIndex;\n }\n else {\n // Winner takes it all\n resultingSelectionIsLTR = winnerSelectionIsLTR;\n }\n let resultingSelection;\n if (resultingSelectionIsLTR) {\n resultingSelection = new Selection(resultingRange.startLineNumber, resultingRange.startColumn, resultingRange.endLineNumber, resultingRange.endColumn);\n }\n else {\n resultingSelection = new Selection(resultingRange.endLineNumber, resultingRange.endColumn, resultingRange.startLineNumber, resultingRange.startColumn);\n }\n sortedCursors[winnerSortedCursorIndex].selection = resultingSelection;\n const resultingState = CursorState.fromModelSelection(resultingSelection);\n cursors[winnerIndex].setState(this.context, resultingState.modelState, resultingState.viewState);\n }\n for (const sortedCursor of sortedCursors) {\n if (sortedCursor.index > looserIndex) {\n sortedCursor.index--;\n }\n }\n cursors.splice(looserIndex, 1);\n sortedCursors.splice(looserSortedCursorIndex, 1);\n this._removeSecondaryCursor(looserIndex - 1);\n sortedCursorIndex--;\n }\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 *--------------------------------------------------------------------------------------------*/\nexport class CursorContext {\n constructor(model, viewModel, coordinatesConverter, cursorConfig) {\n this._cursorContextBrand = undefined;\n this.model = model;\n this.viewModel = viewModel;\n this.coordinatesConverter = coordinatesConverter;\n this.cursorConfig = cursorConfig;\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 *--------------------------------------------------------------------------------------------*/\nexport class ViewCompositionStartEvent {\n constructor() {\n this.type = 0 /* ViewEventType.ViewCompositionStart */;\n }\n}\nexport class ViewCompositionEndEvent {\n constructor() {\n this.type = 1 /* ViewEventType.ViewCompositionEnd */;\n }\n}\nexport class ViewConfigurationChangedEvent {\n constructor(source) {\n this.type = 2 /* ViewEventType.ViewConfigurationChanged */;\n this._source = source;\n }\n hasChanged(id) {\n return this._source.hasChanged(id);\n }\n}\nexport class ViewCursorStateChangedEvent {\n constructor(selections, modelSelections) {\n this.type = 3 /* ViewEventType.ViewCursorStateChanged */;\n this.selections = selections;\n this.modelSelections = modelSelections;\n }\n}\nexport class ViewDecorationsChangedEvent {\n constructor(source) {\n this.type = 4 /* ViewEventType.ViewDecorationsChanged */;\n if (source) {\n this.affectsMinimap = source.affectsMinimap;\n this.affectsOverviewRuler = source.affectsOverviewRuler;\n }\n else {\n this.affectsMinimap = true;\n this.affectsOverviewRuler = true;\n }\n }\n}\nexport class ViewFlushedEvent {\n constructor() {\n this.type = 5 /* ViewEventType.ViewFlushed */;\n // Nothing to do\n }\n}\nexport class ViewFocusChangedEvent {\n constructor(isFocused) {\n this.type = 6 /* ViewEventType.ViewFocusChanged */;\n this.isFocused = isFocused;\n }\n}\nexport class ViewLanguageConfigurationEvent {\n constructor() {\n this.type = 7 /* ViewEventType.ViewLanguageConfigurationChanged */;\n }\n}\nexport class ViewLineMappingChangedEvent {\n constructor() {\n this.type = 8 /* ViewEventType.ViewLineMappingChanged */;\n // Nothing to do\n }\n}\nexport class ViewLinesChangedEvent {\n constructor(\n /**\n * The first line that has changed.\n */\n fromLineNumber, \n /**\n * The number of lines that have changed.\n */\n count) {\n this.fromLineNumber = fromLineNumber;\n this.count = count;\n this.type = 9 /* ViewEventType.ViewLinesChanged */;\n }\n}\nexport class ViewLinesDeletedEvent {\n constructor(fromLineNumber, toLineNumber) {\n this.type = 10 /* ViewEventType.ViewLinesDeleted */;\n this.fromLineNumber = fromLineNumber;\n this.toLineNumber = toLineNumber;\n }\n}\nexport class ViewLinesInsertedEvent {\n constructor(fromLineNumber, toLineNumber) {\n this.type = 11 /* ViewEventType.ViewLinesInserted */;\n this.fromLineNumber = fromLineNumber;\n this.toLineNumber = toLineNumber;\n }\n}\nexport class ViewRevealRangeRequestEvent {\n constructor(\n /**\n * Source of the call that caused the event.\n */\n source, \n /**\n * Reduce the revealing to a minimum (e.g. avoid scrolling if the bounding box is visible and near the viewport edge).\n */\n minimalReveal, \n /**\n * Range to be reavealed.\n */\n range, \n /**\n * Selections to be revealed.\n */\n selections, \n /**\n * The vertical reveal strategy.\n */\n verticalType, \n /**\n * If true: there should be a horizontal & vertical revealing.\n * If false: there should be just a vertical revealing.\n */\n revealHorizontal, \n /**\n * The scroll type.\n */\n scrollType) {\n this.source = source;\n this.minimalReveal = minimalReveal;\n this.range = range;\n this.selections = selections;\n this.verticalType = verticalType;\n this.revealHorizontal = revealHorizontal;\n this.scrollType = scrollType;\n this.type = 12 /* ViewEventType.ViewRevealRangeRequest */;\n }\n}\nexport class ViewScrollChangedEvent {\n constructor(source) {\n this.type = 13 /* ViewEventType.ViewScrollChanged */;\n this.scrollWidth = source.scrollWidth;\n this.scrollLeft = source.scrollLeft;\n this.scrollHeight = source.scrollHeight;\n this.scrollTop = source.scrollTop;\n this.scrollWidthChanged = source.scrollWidthChanged;\n this.scrollLeftChanged = source.scrollLeftChanged;\n this.scrollHeightChanged = source.scrollHeightChanged;\n this.scrollTopChanged = source.scrollTopChanged;\n }\n}\nexport class ViewThemeChangedEvent {\n constructor(theme) {\n this.theme = theme;\n this.type = 14 /* ViewEventType.ViewThemeChanged */;\n }\n}\nexport class ViewTokensChangedEvent {\n constructor(ranges) {\n this.type = 15 /* ViewEventType.ViewTokensChanged */;\n this.ranges = ranges;\n }\n}\nexport class ViewTokensColorsChangedEvent {\n constructor() {\n this.type = 16 /* ViewEventType.ViewTokensColorsChanged */;\n // Nothing to do\n }\n}\nexport class ViewZonesChangedEvent {\n constructor() {\n this.type = 17 /* ViewEventType.ViewZonesChanged */;\n // Nothing to do\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 *--------------------------------------------------------------------------------------------*/\nimport { Emitter } from '../../base/common/event.js';\nimport { Disposable } from '../../base/common/lifecycle.js';\nexport class ViewModelEventDispatcher extends Disposable {\n constructor() {\n super();\n this._onEvent = this._register(new Emitter());\n this.onEvent = this._onEvent.event;\n this._eventHandlers = [];\n this._viewEventQueue = null;\n this._isConsumingViewEventQueue = false;\n this._collector = null;\n this._collectorCnt = 0;\n this._outgoingEvents = [];\n }\n emitOutgoingEvent(e) {\n this._addOutgoingEvent(e);\n this._emitOutgoingEvents();\n }\n _addOutgoingEvent(e) {\n for (let i = 0, len = this._outgoingEvents.length; i < len; i++) {\n const mergeResult = (this._outgoingEvents[i].kind === e.kind ? this._outgoingEvents[i].attemptToMerge(e) : null);\n if (mergeResult) {\n this._outgoingEvents[i] = mergeResult;\n return;\n }\n }\n // not merged\n this._outgoingEvents.push(e);\n }\n _emitOutgoingEvents() {\n while (this._outgoingEvents.length > 0) {\n if (this._collector || this._isConsumingViewEventQueue) {\n // right now collecting or emitting view events, so let's postpone emitting\n return;\n }\n const event = this._outgoingEvents.shift();\n if (event.isNoOp()) {\n continue;\n }\n this._onEvent.fire(event);\n }\n }\n addViewEventHandler(eventHandler) {\n for (let i = 0, len = this._eventHandlers.length; i < len; i++) {\n if (this._eventHandlers[i] === eventHandler) {\n console.warn('Detected duplicate listener in ViewEventDispatcher', eventHandler);\n }\n }\n this._eventHandlers.push(eventHandler);\n }\n removeViewEventHandler(eventHandler) {\n for (let i = 0; i < this._eventHandlers.length; i++) {\n if (this._eventHandlers[i] === eventHandler) {\n this._eventHandlers.splice(i, 1);\n break;\n }\n }\n }\n beginEmitViewEvents() {\n this._collectorCnt++;\n if (this._collectorCnt === 1) {\n this._collector = new ViewModelEventsCollector();\n }\n return this._collector;\n }\n endEmitViewEvents() {\n this._collectorCnt--;\n if (this._collectorCnt === 0) {\n const outgoingEvents = this._collector.outgoingEvents;\n const viewEvents = this._collector.viewEvents;\n this._collector = null;\n for (const outgoingEvent of outgoingEvents) {\n this._addOutgoingEvent(outgoingEvent);\n }\n if (viewEvents.length > 0) {\n this._emitMany(viewEvents);\n }\n }\n this._emitOutgoingEvents();\n }\n emitSingleViewEvent(event) {\n try {\n const eventsCollector = this.beginEmitViewEvents();\n eventsCollector.emitViewEvent(event);\n }\n finally {\n this.endEmitViewEvents();\n }\n }\n _emitMany(events) {\n if (this._viewEventQueue) {\n this._viewEventQueue = this._viewEventQueue.concat(events);\n }\n else {\n this._viewEventQueue = events;\n }\n if (!this._isConsumingViewEventQueue) {\n this._consumeViewEventQueue();\n }\n }\n _consumeViewEventQueue() {\n try {\n this._isConsumingViewEventQueue = true;\n this._doConsumeQueue();\n }\n finally {\n this._isConsumingViewEventQueue = false;\n }\n }\n _doConsumeQueue() {\n while (this._viewEventQueue) {\n // Empty event queue, as events might come in while sending these off\n const events = this._viewEventQueue;\n this._viewEventQueue = null;\n // Use a clone of the event handlers list, as they might remove themselves\n const eventHandlers = this._eventHandlers.slice(0);\n for (const eventHandler of eventHandlers) {\n eventHandler.handleEvents(events);\n }\n }\n }\n}\nexport class ViewModelEventsCollector {\n constructor() {\n this.viewEvents = [];\n this.outgoingEvents = [];\n }\n emitViewEvent(event) {\n this.viewEvents.push(event);\n }\n emitOutgoingEvent(e) {\n this.outgoingEvents.push(e);\n }\n}\nexport class ContentSizeChangedEvent {\n constructor(oldContentWidth, oldContentHeight, contentWidth, contentHeight) {\n this.kind = 0 /* OutgoingViewModelEventKind.ContentSizeChanged */;\n this._oldContentWidth = oldContentWidth;\n this._oldContentHeight = oldContentHeight;\n this.contentWidth = contentWidth;\n this.contentHeight = contentHeight;\n this.contentWidthChanged = (this._oldContentWidth !== this.contentWidth);\n this.contentHeightChanged = (this._oldContentHeight !== this.contentHeight);\n }\n isNoOp() {\n return (!this.contentWidthChanged && !this.contentHeightChanged);\n }\n attemptToMerge(other) {\n if (other.kind !== this.kind) {\n return null;\n }\n return new ContentSizeChangedEvent(this._oldContentWidth, this._oldContentHeight, other.contentWidth, other.contentHeight);\n }\n}\nexport class FocusChangedEvent {\n constructor(oldHasFocus, hasFocus) {\n this.kind = 1 /* OutgoingViewModelEventKind.FocusChanged */;\n this.oldHasFocus = oldHasFocus;\n this.hasFocus = hasFocus;\n }\n isNoOp() {\n return (this.oldHasFocus === this.hasFocus);\n }\n attemptToMerge(other) {\n if (other.kind !== this.kind) {\n return null;\n }\n return new FocusChangedEvent(this.oldHasFocus, other.hasFocus);\n }\n}\nexport class ScrollChangedEvent {\n constructor(oldScrollWidth, oldScrollLeft, oldScrollHeight, oldScrollTop, scrollWidth, scrollLeft, scrollHeight, scrollTop) {\n this.kind = 2 /* OutgoingViewModelEventKind.ScrollChanged */;\n this._oldScrollWidth = oldScrollWidth;\n this._oldScrollLeft = oldScrollLeft;\n this._oldScrollHeight = oldScrollHeight;\n this._oldScrollTop = oldScrollTop;\n this.scrollWidth = scrollWidth;\n this.scrollLeft = scrollLeft;\n this.scrollHeight = scrollHeight;\n this.scrollTop = scrollTop;\n this.scrollWidthChanged = (this._oldScrollWidth !== this.scrollWidth);\n this.scrollLeftChanged = (this._oldScrollLeft !== this.scrollLeft);\n this.scrollHeightChanged = (this._oldScrollHeight !== this.scrollHeight);\n this.scrollTopChanged = (this._oldScrollTop !== this.scrollTop);\n }\n isNoOp() {\n return (!this.scrollWidthChanged && !this.scrollLeftChanged && !this.scrollHeightChanged && !this.scrollTopChanged);\n }\n attemptToMerge(other) {\n if (other.kind !== this.kind) {\n return null;\n }\n return new ScrollChangedEvent(this._oldScrollWidth, this._oldScrollLeft, this._oldScrollHeight, this._oldScrollTop, other.scrollWidth, other.scrollLeft, other.scrollHeight, other.scrollTop);\n }\n}\nexport class ViewZonesChangedEvent {\n constructor() {\n this.kind = 3 /* OutgoingViewModelEventKind.ViewZonesChanged */;\n }\n isNoOp() {\n return false;\n }\n attemptToMerge(other) {\n if (other.kind !== this.kind) {\n return null;\n }\n return this;\n }\n}\nexport class HiddenAreasChangedEvent {\n constructor() {\n this.kind = 4 /* OutgoingViewModelEventKind.HiddenAreasChanged */;\n }\n isNoOp() {\n return false;\n }\n attemptToMerge(other) {\n if (other.kind !== this.kind) {\n return null;\n }\n return this;\n }\n}\nexport class CursorStateChangedEvent {\n constructor(oldSelections, selections, oldModelVersionId, modelVersionId, source, reason, reachedMaxCursorCount) {\n this.kind = 6 /* OutgoingViewModelEventKind.CursorStateChanged */;\n this.oldSelections = oldSelections;\n this.selections = selections;\n this.oldModelVersionId = oldModelVersionId;\n this.modelVersionId = modelVersionId;\n this.source = source;\n this.reason = reason;\n this.reachedMaxCursorCount = reachedMaxCursorCount;\n }\n static _selectionsAreEqual(a, b) {\n if (!a && !b) {\n return true;\n }\n if (!a || !b) {\n return false;\n }\n const aLen = a.length;\n const bLen = b.length;\n if (aLen !== bLen) {\n return false;\n }\n for (let i = 0; i < aLen; i++) {\n if (!a[i].equalsSelection(b[i])) {\n return false;\n }\n }\n return true;\n }\n isNoOp() {\n return (CursorStateChangedEvent._selectionsAreEqual(this.oldSelections, this.selections)\n && this.oldModelVersionId === this.modelVersionId);\n }\n attemptToMerge(other) {\n if (other.kind !== this.kind) {\n return null;\n }\n return new CursorStateChangedEvent(this.oldSelections, other.selections, this.oldModelVersionId, other.modelVersionId, other.source, other.reason, this.reachedMaxCursorCount || other.reachedMaxCursorCount);\n }\n}\nexport class ReadOnlyEditAttemptEvent {\n constructor() {\n this.kind = 5 /* OutgoingViewModelEventKind.ReadOnlyEditAttempt */;\n }\n isNoOp() {\n return false;\n }\n attemptToMerge(other) {\n if (other.kind !== this.kind) {\n return null;\n }\n return this;\n }\n}\nexport class ModelDecorationsChangedEvent {\n constructor(event) {\n this.event = event;\n this.kind = 7 /* OutgoingViewModelEventKind.ModelDecorationsChanged */;\n }\n isNoOp() {\n return false;\n }\n attemptToMerge(other) {\n return null;\n }\n}\nexport class ModelLanguageChangedEvent {\n constructor(event) {\n this.event = event;\n this.kind = 8 /* OutgoingViewModelEventKind.ModelLanguageChanged */;\n }\n isNoOp() {\n return false;\n }\n attemptToMerge(other) {\n return null;\n }\n}\nexport class ModelLanguageConfigurationChangedEvent {\n constructor(event) {\n this.event = event;\n this.kind = 9 /* OutgoingViewModelEventKind.ModelLanguageConfigurationChanged */;\n }\n isNoOp() {\n return false;\n }\n attemptToMerge(other) {\n return null;\n }\n}\nexport class ModelContentChangedEvent {\n constructor(event) {\n this.event = event;\n this.kind = 10 /* OutgoingViewModelEventKind.ModelContentChanged */;\n }\n isNoOp() {\n return false;\n }\n attemptToMerge(other) {\n return null;\n }\n}\nexport class ModelOptionsChangedEvent {\n constructor(event) {\n this.event = event;\n this.kind = 11 /* OutgoingViewModelEventKind.ModelOptionsChanged */;\n }\n isNoOp() {\n return false;\n }\n attemptToMerge(other) {\n return null;\n }\n}\nexport class ModelTokensChangedEvent {\n constructor(event) {\n this.event = event;\n this.kind = 12 /* OutgoingViewModelEventKind.ModelTokensChanged */;\n }\n isNoOp() {\n return false;\n }\n attemptToMerge(other) {\n return null;\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 *--------------------------------------------------------------------------------------------*/\nimport { onUnexpectedError } from '../../../base/common/errors.js';\nimport * as strings from '../../../base/common/strings.js';\nimport { CursorCollection } from './cursorCollection.js';\nimport { CursorState, EditOperationResult } from '../cursorCommon.js';\nimport { CursorContext } from './cursorContext.js';\nimport { DeleteOperations } from './cursorDeleteOperations.js';\nimport { CompositionOutcome, TypeOperations, TypeWithAutoClosingCommand } from './cursorTypeOperations.js';\nimport { Range } from '../core/range.js';\nimport { Selection } from '../core/selection.js';\nimport { ModelInjectedTextChangedEvent } from '../textModelEvents.js';\nimport { ViewCursorStateChangedEvent, ViewRevealRangeRequestEvent } from '../viewEvents.js';\nimport { dispose, Disposable } from '../../../base/common/lifecycle.js';\nimport { CursorStateChangedEvent } from '../viewModelEventDispatcher.js';\nexport class CursorsController extends Disposable {\n constructor(model, viewModel, coordinatesConverter, cursorConfig) {\n super();\n this._model = model;\n this._knownModelVersionId = this._model.getVersionId();\n this._viewModel = viewModel;\n this._coordinatesConverter = coordinatesConverter;\n this.context = new CursorContext(this._model, this._viewModel, this._coordinatesConverter, cursorConfig);\n this._cursors = new CursorCollection(this.context);\n this._hasFocus = false;\n this._isHandling = false;\n this._compositionState = null;\n this._columnSelectData = null;\n this._autoClosedActions = [];\n this._prevEditOperationType = 0 /* EditOperationType.Other */;\n }\n dispose() {\n this._cursors.dispose();\n this._autoClosedActions = dispose(this._autoClosedActions);\n super.dispose();\n }\n updateConfiguration(cursorConfig) {\n this.context = new CursorContext(this._model, this._viewModel, this._coordinatesConverter, cursorConfig);\n this._cursors.updateContext(this.context);\n }\n onLineMappingChanged(eventsCollector) {\n if (this._knownModelVersionId !== this._model.getVersionId()) {\n // There are model change events that I didn't yet receive.\n //\n // This can happen when editing the model, and the view model receives the change events first,\n // and the view model emits line mapping changed events, all before the cursor gets a chance to\n // recover from markers.\n //\n // The model change listener above will be called soon and we'll ensure a valid cursor state there.\n return;\n }\n // Ensure valid state\n this.setStates(eventsCollector, 'viewModel', 0 /* CursorChangeReason.NotSet */, this.getCursorStates());\n }\n setHasFocus(hasFocus) {\n this._hasFocus = hasFocus;\n }\n _validateAutoClosedActions() {\n if (this._autoClosedActions.length > 0) {\n const selections = this._cursors.getSelections();\n for (let i = 0; i < this._autoClosedActions.length; i++) {\n const autoClosedAction = this._autoClosedActions[i];\n if (!autoClosedAction.isValid(selections)) {\n autoClosedAction.dispose();\n this._autoClosedActions.splice(i, 1);\n i--;\n }\n }\n }\n }\n // ------ some getters/setters\n getPrimaryCursorState() {\n return this._cursors.getPrimaryCursor();\n }\n getLastAddedCursorIndex() {\n return this._cursors.getLastAddedCursorIndex();\n }\n getCursorStates() {\n return this._cursors.getAll();\n }\n setStates(eventsCollector, source, reason, states) {\n let reachedMaxCursorCount = false;\n if (states !== null && states.length > CursorsController.MAX_CURSOR_COUNT) {\n states = states.slice(0, CursorsController.MAX_CURSOR_COUNT);\n reachedMaxCursorCount = true;\n }\n const oldState = CursorModelState.from(this._model, this);\n this._cursors.setStates(states);\n this._cursors.normalize();\n this._columnSelectData = null;\n this._validateAutoClosedActions();\n return this._emitStateChangedIfNecessary(eventsCollector, source, reason, oldState, reachedMaxCursorCount);\n }\n setCursorColumnSelectData(columnSelectData) {\n this._columnSelectData = columnSelectData;\n }\n revealPrimary(eventsCollector, source, minimalReveal, verticalType, revealHorizontal, scrollType) {\n const viewPositions = this._cursors.getViewPositions();\n let revealViewRange = null;\n let revealViewSelections = null;\n if (viewPositions.length > 1) {\n revealViewSelections = this._cursors.getViewSelections();\n }\n else {\n revealViewRange = Range.fromPositions(viewPositions[0], viewPositions[0]);\n }\n eventsCollector.emitViewEvent(new ViewRevealRangeRequestEvent(source, minimalReveal, revealViewRange, revealViewSelections, verticalType, revealHorizontal, scrollType));\n }\n saveState() {\n const result = [];\n const selections = this._cursors.getSelections();\n for (let i = 0, len = selections.length; i < len; i++) {\n const selection = selections[i];\n result.push({\n inSelectionMode: !selection.isEmpty(),\n selectionStart: {\n lineNumber: selection.selectionStartLineNumber,\n column: selection.selectionStartColumn,\n },\n position: {\n lineNumber: selection.positionLineNumber,\n column: selection.positionColumn,\n }\n });\n }\n return result;\n }\n restoreState(eventsCollector, states) {\n const desiredSelections = [];\n for (let i = 0, len = states.length; i < len; i++) {\n const state = states[i];\n let positionLineNumber = 1;\n let positionColumn = 1;\n // Avoid missing properties on the literal\n if (state.position && state.position.lineNumber) {\n positionLineNumber = state.position.lineNumber;\n }\n if (state.position && state.position.column) {\n positionColumn = state.position.column;\n }\n let selectionStartLineNumber = positionLineNumber;\n let selectionStartColumn = positionColumn;\n // Avoid missing properties on the literal\n if (state.selectionStart && state.selectionStart.lineNumber) {\n selectionStartLineNumber = state.selectionStart.lineNumber;\n }\n if (state.selectionStart && state.selectionStart.column) {\n selectionStartColumn = state.selectionStart.column;\n }\n desiredSelections.push({\n selectionStartLineNumber: selectionStartLineNumber,\n selectionStartColumn: selectionStartColumn,\n positionLineNumber: positionLineNumber,\n positionColumn: positionColumn\n });\n }\n this.setStates(eventsCollector, 'restoreState', 0 /* CursorChangeReason.NotSet */, CursorState.fromModelSelections(desiredSelections));\n this.revealPrimary(eventsCollector, 'restoreState', false, 0 /* VerticalRevealType.Simple */, true, 1 /* editorCommon.ScrollType.Immediate */);\n }\n onModelContentChanged(eventsCollector, event) {\n if (event instanceof ModelInjectedTextChangedEvent) {\n // If injected texts change, the view positions of all cursors need to be updated.\n if (this._isHandling) {\n // The view positions will be updated when handling finishes\n return;\n }\n // setStates might remove markers, which could trigger a decoration change.\n // If there are injected text decorations for that line, `onModelContentChanged` is emitted again\n // and an endless recursion happens.\n // _isHandling prevents that.\n this._isHandling = true;\n try {\n this.setStates(eventsCollector, 'modelChange', 0 /* CursorChangeReason.NotSet */, this.getCursorStates());\n }\n finally {\n this._isHandling = false;\n }\n }\n else {\n const e = event.rawContentChangedEvent;\n this._knownModelVersionId = e.versionId;\n if (this._isHandling) {\n return;\n }\n const hadFlushEvent = e.containsEvent(1 /* RawContentChangedType.Flush */);\n this._prevEditOperationType = 0 /* EditOperationType.Other */;\n if (hadFlushEvent) {\n // a model.setValue() was called\n this._cursors.dispose();\n this._cursors = new CursorCollection(this.context);\n this._validateAutoClosedActions();\n this._emitStateChangedIfNecessary(eventsCollector, 'model', 1 /* CursorChangeReason.ContentFlush */, null, false);\n }\n else {\n if (this._hasFocus && e.resultingSelection && e.resultingSelection.length > 0) {\n const cursorState = CursorState.fromModelSelections(e.resultingSelection);\n if (this.setStates(eventsCollector, 'modelChange', e.isUndoing ? 5 /* CursorChangeReason.Undo */ : e.isRedoing ? 6 /* CursorChangeReason.Redo */ : 2 /* CursorChangeReason.RecoverFromMarkers */, cursorState)) {\n this.revealPrimary(eventsCollector, 'modelChange', false, 0 /* VerticalRevealType.Simple */, true, 0 /* editorCommon.ScrollType.Smooth */);\n }\n }\n else {\n const selectionsFromMarkers = this._cursors.readSelectionFromMarkers();\n this.setStates(eventsCollector, 'modelChange', 2 /* CursorChangeReason.RecoverFromMarkers */, CursorState.fromModelSelections(selectionsFromMarkers));\n }\n }\n }\n }\n getSelection() {\n return this._cursors.getPrimaryCursor().modelState.selection;\n }\n getTopMostViewPosition() {\n return this._cursors.getTopMostViewPosition();\n }\n getBottomMostViewPosition() {\n return this._cursors.getBottomMostViewPosition();\n }\n getCursorColumnSelectData() {\n if (this._columnSelectData) {\n return this._columnSelectData;\n }\n const primaryCursor = this._cursors.getPrimaryCursor();\n const viewSelectionStart = primaryCursor.viewState.selectionStart.getStartPosition();\n const viewPosition = primaryCursor.viewState.position;\n return {\n isReal: false,\n fromViewLineNumber: viewSelectionStart.lineNumber,\n fromViewVisualColumn: this.context.cursorConfig.visibleColumnFromColumn(this._viewModel, viewSelectionStart),\n toViewLineNumber: viewPosition.lineNumber,\n toViewVisualColumn: this.context.cursorConfig.visibleColumnFromColumn(this._viewModel, viewPosition),\n };\n }\n getSelections() {\n return this._cursors.getSelections();\n }\n setSelections(eventsCollector, source, selections, reason) {\n this.setStates(eventsCollector, source, reason, CursorState.fromModelSelections(selections));\n }\n getPrevEditOperationType() {\n return this._prevEditOperationType;\n }\n setPrevEditOperationType(type) {\n this._prevEditOperationType = type;\n }\n // ------ auxiliary handling logic\n _pushAutoClosedAction(autoClosedCharactersRanges, autoClosedEnclosingRanges) {\n const autoClosedCharactersDeltaDecorations = [];\n const autoClosedEnclosingDeltaDecorations = [];\n for (let i = 0, len = autoClosedCharactersRanges.length; i < len; i++) {\n autoClosedCharactersDeltaDecorations.push({\n range: autoClosedCharactersRanges[i],\n options: {\n description: 'auto-closed-character',\n inlineClassName: 'auto-closed-character',\n stickiness: 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */\n }\n });\n autoClosedEnclosingDeltaDecorations.push({\n range: autoClosedEnclosingRanges[i],\n options: {\n description: 'auto-closed-enclosing',\n stickiness: 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */\n }\n });\n }\n const autoClosedCharactersDecorations = this._model.deltaDecorations([], autoClosedCharactersDeltaDecorations);\n const autoClosedEnclosingDecorations = this._model.deltaDecorations([], autoClosedEnclosingDeltaDecorations);\n this._autoClosedActions.push(new AutoClosedAction(this._model, autoClosedCharactersDecorations, autoClosedEnclosingDecorations));\n }\n _executeEditOperation(opResult) {\n if (!opResult) {\n // Nothing to execute\n return;\n }\n if (opResult.shouldPushStackElementBefore) {\n this._model.pushStackElement();\n }\n const result = CommandExecutor.executeCommands(this._model, this._cursors.getSelections(), opResult.commands);\n if (result) {\n // The commands were applied correctly\n this._interpretCommandResult(result);\n // Check for auto-closing closed characters\n const autoClosedCharactersRanges = [];\n const autoClosedEnclosingRanges = [];\n for (let i = 0; i < opResult.commands.length; i++) {\n const command = opResult.commands[i];\n if (command instanceof TypeWithAutoClosingCommand && command.enclosingRange && command.closeCharacterRange) {\n autoClosedCharactersRanges.push(command.closeCharacterRange);\n autoClosedEnclosingRanges.push(command.enclosingRange);\n }\n }\n if (autoClosedCharactersRanges.length > 0) {\n this._pushAutoClosedAction(autoClosedCharactersRanges, autoClosedEnclosingRanges);\n }\n this._prevEditOperationType = opResult.type;\n }\n if (opResult.shouldPushStackElementAfter) {\n this._model.pushStackElement();\n }\n }\n _interpretCommandResult(cursorState) {\n if (!cursorState || cursorState.length === 0) {\n cursorState = this._cursors.readSelectionFromMarkers();\n }\n this._columnSelectData = null;\n this._cursors.setSelections(cursorState);\n this._cursors.normalize();\n }\n // -----------------------------------------------------------------------------------------------------------\n // ----- emitting events\n _emitStateChangedIfNecessary(eventsCollector, source, reason, oldState, reachedMaxCursorCount) {\n const newState = CursorModelState.from(this._model, this);\n if (newState.equals(oldState)) {\n return false;\n }\n const selections = this._cursors.getSelections();\n const viewSelections = this._cursors.getViewSelections();\n // Let the view get the event first.\n eventsCollector.emitViewEvent(new ViewCursorStateChangedEvent(viewSelections, selections));\n // Only after the view has been notified, let the rest of the world know...\n if (!oldState\n || oldState.cursorState.length !== newState.cursorState.length\n || newState.cursorState.some((newCursorState, i) => !newCursorState.modelState.equals(oldState.cursorState[i].modelState))) {\n const oldSelections = oldState ? oldState.cursorState.map(s => s.modelState.selection) : null;\n const oldModelVersionId = oldState ? oldState.modelVersionId : 0;\n eventsCollector.emitOutgoingEvent(new CursorStateChangedEvent(oldSelections, selections, oldModelVersionId, newState.modelVersionId, source || 'keyboard', reason, reachedMaxCursorCount));\n }\n return true;\n }\n // -----------------------------------------------------------------------------------------------------------\n // ----- handlers beyond this point\n _findAutoClosingPairs(edits) {\n if (!edits.length) {\n return null;\n }\n const indices = [];\n for (let i = 0, len = edits.length; i < len; i++) {\n const edit = edits[i];\n if (!edit.text || edit.text.indexOf('\\n') >= 0) {\n return null;\n }\n const m = edit.text.match(/([)\\]}>'\"`])([^)\\]}>'\"`]*)$/);\n if (!m) {\n return null;\n }\n const closeChar = m[1];\n const autoClosingPairsCandidates = this.context.cursorConfig.autoClosingPairs.autoClosingPairsCloseSingleChar.get(closeChar);\n if (!autoClosingPairsCandidates || autoClosingPairsCandidates.length !== 1) {\n return null;\n }\n const openChar = autoClosingPairsCandidates[0].open;\n const closeCharIndex = edit.text.length - m[2].length - 1;\n const openCharIndex = edit.text.lastIndexOf(openChar, closeCharIndex - 1);\n if (openCharIndex === -1) {\n return null;\n }\n indices.push([openCharIndex, closeCharIndex]);\n }\n return indices;\n }\n executeEdits(eventsCollector, source, edits, cursorStateComputer) {\n let autoClosingIndices = null;\n if (source === 'snippet') {\n autoClosingIndices = this._findAutoClosingPairs(edits);\n }\n if (autoClosingIndices) {\n edits[0]._isTracked = true;\n }\n const autoClosedCharactersRanges = [];\n const autoClosedEnclosingRanges = [];\n const selections = this._model.pushEditOperations(this.getSelections(), edits, (undoEdits) => {\n if (autoClosingIndices) {\n for (let i = 0, len = autoClosingIndices.length; i < len; i++) {\n const [openCharInnerIndex, closeCharInnerIndex] = autoClosingIndices[i];\n const undoEdit = undoEdits[i];\n const lineNumber = undoEdit.range.startLineNumber;\n const openCharIndex = undoEdit.range.startColumn - 1 + openCharInnerIndex;\n const closeCharIndex = undoEdit.range.startColumn - 1 + closeCharInnerIndex;\n autoClosedCharactersRanges.push(new Range(lineNumber, closeCharIndex + 1, lineNumber, closeCharIndex + 2));\n autoClosedEnclosingRanges.push(new Range(lineNumber, openCharIndex + 1, lineNumber, closeCharIndex + 2));\n }\n }\n const selections = cursorStateComputer(undoEdits);\n if (selections) {\n // Don't recover the selection from markers because\n // we know what it should be.\n this._isHandling = true;\n }\n return selections;\n });\n if (selections) {\n this._isHandling = false;\n this.setSelections(eventsCollector, source, selections, 0 /* CursorChangeReason.NotSet */);\n }\n if (autoClosedCharactersRanges.length > 0) {\n this._pushAutoClosedAction(autoClosedCharactersRanges, autoClosedEnclosingRanges);\n }\n }\n _executeEdit(callback, eventsCollector, source, cursorChangeReason = 0 /* CursorChangeReason.NotSet */) {\n if (this.context.cursorConfig.readOnly) {\n // we cannot edit when read only...\n return;\n }\n const oldState = CursorModelState.from(this._model, this);\n this._cursors.stopTrackingSelections();\n this._isHandling = true;\n try {\n this._cursors.ensureValidState();\n callback();\n }\n catch (err) {\n onUnexpectedError(err);\n }\n this._isHandling = false;\n this._cursors.startTrackingSelections();\n this._validateAutoClosedActions();\n if (this._emitStateChangedIfNecessary(eventsCollector, source, cursorChangeReason, oldState, false)) {\n this.revealPrimary(eventsCollector, source, false, 0 /* VerticalRevealType.Simple */, true, 0 /* editorCommon.ScrollType.Smooth */);\n }\n }\n getAutoClosedCharacters() {\n return AutoClosedAction.getAllAutoClosedCharacters(this._autoClosedActions);\n }\n startComposition(eventsCollector) {\n this._compositionState = new CompositionState(this._model, this.getSelections());\n }\n endComposition(eventsCollector, source) {\n const compositionOutcome = this._compositionState ? this._compositionState.deduceOutcome(this._model, this.getSelections()) : null;\n this._compositionState = null;\n this._executeEdit(() => {\n if (source === 'keyboard') {\n // composition finishes, let's check if we need to auto complete if necessary.\n this._executeEditOperation(TypeOperations.compositionEndWithInterceptors(this._prevEditOperationType, this.context.cursorConfig, this._model, compositionOutcome, this.getSelections(), this.getAutoClosedCharacters()));\n }\n }, eventsCollector, source);\n }\n type(eventsCollector, text, source) {\n this._executeEdit(() => {\n if (source === 'keyboard') {\n // If this event is coming straight from the keyboard, look for electric characters and enter\n const len = text.length;\n let offset = 0;\n while (offset < len) {\n const charLength = strings.nextCharLength(text, offset);\n const chr = text.substr(offset, charLength);\n // Here we must interpret each typed character individually\n this._executeEditOperation(TypeOperations.typeWithInterceptors(!!this._compositionState, this._prevEditOperationType, this.context.cursorConfig, this._model, this.getSelections(), this.getAutoClosedCharacters(), chr));\n offset += charLength;\n }\n }\n else {\n this._executeEditOperation(TypeOperations.typeWithoutInterceptors(this._prevEditOperationType, this.context.cursorConfig, this._model, this.getSelections(), text));\n }\n }, eventsCollector, source);\n }\n compositionType(eventsCollector, text, replacePrevCharCnt, replaceNextCharCnt, positionDelta, source) {\n if (text.length === 0 && replacePrevCharCnt === 0 && replaceNextCharCnt === 0) {\n // this edit is a no-op\n if (positionDelta !== 0) {\n // but it still wants to move the cursor\n const newSelections = this.getSelections().map(selection => {\n const position = selection.getPosition();\n return new Selection(position.lineNumber, position.column + positionDelta, position.lineNumber, position.column + positionDelta);\n });\n this.setSelections(eventsCollector, source, newSelections, 0 /* CursorChangeReason.NotSet */);\n }\n return;\n }\n this._executeEdit(() => {\n this._executeEditOperation(TypeOperations.compositionType(this._prevEditOperationType, this.context.cursorConfig, this._model, this.getSelections(), text, replacePrevCharCnt, replaceNextCharCnt, positionDelta));\n }, eventsCollector, source);\n }\n paste(eventsCollector, text, pasteOnNewLine, multicursorText, source) {\n this._executeEdit(() => {\n this._executeEditOperation(TypeOperations.paste(this.context.cursorConfig, this._model, this.getSelections(), text, pasteOnNewLine, multicursorText || []));\n }, eventsCollector, source, 4 /* CursorChangeReason.Paste */);\n }\n cut(eventsCollector, source) {\n this._executeEdit(() => {\n this._executeEditOperation(DeleteOperations.cut(this.context.cursorConfig, this._model, this.getSelections()));\n }, eventsCollector, source);\n }\n executeCommand(eventsCollector, command, source) {\n this._executeEdit(() => {\n this._cursors.killSecondaryCursors();\n this._executeEditOperation(new EditOperationResult(0 /* EditOperationType.Other */, [command], {\n shouldPushStackElementBefore: false,\n shouldPushStackElementAfter: false\n }));\n }, eventsCollector, source);\n }\n executeCommands(eventsCollector, commands, source) {\n this._executeEdit(() => {\n this._executeEditOperation(new EditOperationResult(0 /* EditOperationType.Other */, commands, {\n shouldPushStackElementBefore: false,\n shouldPushStackElementAfter: false\n }));\n }, eventsCollector, source);\n }\n}\nCursorsController.MAX_CURSOR_COUNT = 10000;\n/**\n * A snapshot of the cursor and the model state\n */\nclass CursorModelState {\n constructor(modelVersionId, cursorState) {\n this.modelVersionId = modelVersionId;\n this.cursorState = cursorState;\n }\n static from(model, cursor) {\n return new CursorModelState(model.getVersionId(), cursor.getCursorStates());\n }\n equals(other) {\n if (!other) {\n return false;\n }\n if (this.modelVersionId !== other.modelVersionId) {\n return false;\n }\n if (this.cursorState.length !== other.cursorState.length) {\n return false;\n }\n for (let i = 0, len = this.cursorState.length; i < len; i++) {\n if (!this.cursorState[i].equals(other.cursorState[i])) {\n return false;\n }\n }\n return true;\n }\n}\nclass AutoClosedAction {\n constructor(model, autoClosedCharactersDecorations, autoClosedEnclosingDecorations) {\n this._model = model;\n this._autoClosedCharactersDecorations = autoClosedCharactersDecorations;\n this._autoClosedEnclosingDecorations = autoClosedEnclosingDecorations;\n }\n static getAllAutoClosedCharacters(autoClosedActions) {\n let autoClosedCharacters = [];\n for (const autoClosedAction of autoClosedActions) {\n autoClosedCharacters = autoClosedCharacters.concat(autoClosedAction.getAutoClosedCharactersRanges());\n }\n return autoClosedCharacters;\n }\n dispose() {\n this._autoClosedCharactersDecorations = this._model.deltaDecorations(this._autoClosedCharactersDecorations, []);\n this._autoClosedEnclosingDecorations = this._model.deltaDecorations(this._autoClosedEnclosingDecorations, []);\n }\n getAutoClosedCharactersRanges() {\n const result = [];\n for (let i = 0; i < this._autoClosedCharactersDecorations.length; i++) {\n const decorationRange = this._model.getDecorationRange(this._autoClosedCharactersDecorations[i]);\n if (decorationRange) {\n result.push(decorationRange);\n }\n }\n return result;\n }\n isValid(selections) {\n const enclosingRanges = [];\n for (let i = 0; i < this._autoClosedEnclosingDecorations.length; i++) {\n const decorationRange = this._model.getDecorationRange(this._autoClosedEnclosingDecorations[i]);\n if (decorationRange) {\n enclosingRanges.push(decorationRange);\n if (decorationRange.startLineNumber !== decorationRange.endLineNumber) {\n // Stop tracking if the range becomes multiline...\n return false;\n }\n }\n }\n enclosingRanges.sort(Range.compareRangesUsingStarts);\n selections.sort(Range.compareRangesUsingStarts);\n for (let i = 0; i < selections.length; i++) {\n if (i >= enclosingRanges.length) {\n return false;\n }\n if (!enclosingRanges[i].strictContainsRange(selections[i])) {\n return false;\n }\n }\n return true;\n }\n}\nclass CommandExecutor {\n static executeCommands(model, selectionsBefore, commands) {\n const ctx = {\n model: model,\n selectionsBefore: selectionsBefore,\n trackedRanges: [],\n trackedRangesDirection: []\n };\n const result = this._innerExecuteCommands(ctx, commands);\n for (let i = 0, len = ctx.trackedRanges.length; i < len; i++) {\n ctx.model._setTrackedRange(ctx.trackedRanges[i], null, 0 /* TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges */);\n }\n return result;\n }\n static _innerExecuteCommands(ctx, commands) {\n if (this._arrayIsEmpty(commands)) {\n return null;\n }\n const commandsData = this._getEditOperations(ctx, commands);\n if (commandsData.operations.length === 0) {\n return null;\n }\n const rawOperations = commandsData.operations;\n const loserCursorsMap = this._getLoserCursorMap(rawOperations);\n if (loserCursorsMap.hasOwnProperty('0')) {\n // These commands are very messed up\n console.warn('Ignoring commands');\n return null;\n }\n // Remove operations belonging to losing cursors\n const filteredOperations = [];\n for (let i = 0, len = rawOperations.length; i < len; i++) {\n if (!loserCursorsMap.hasOwnProperty(rawOperations[i].identifier.major.toString())) {\n filteredOperations.push(rawOperations[i]);\n }\n }\n // TODO@Alex: find a better way to do this.\n // give the hint that edit operations are tracked to the model\n if (commandsData.hadTrackedEditOperation && filteredOperations.length > 0) {\n filteredOperations[0]._isTracked = true;\n }\n let selectionsAfter = ctx.model.pushEditOperations(ctx.selectionsBefore, filteredOperations, (inverseEditOperations) => {\n const groupedInverseEditOperations = [];\n for (let i = 0; i < ctx.selectionsBefore.length; i++) {\n groupedInverseEditOperations[i] = [];\n }\n for (const op of inverseEditOperations) {\n if (!op.identifier) {\n // perhaps auto whitespace trim edits\n continue;\n }\n groupedInverseEditOperations[op.identifier.major].push(op);\n }\n const minorBasedSorter = (a, b) => {\n return a.identifier.minor - b.identifier.minor;\n };\n const cursorSelections = [];\n for (let i = 0; i < ctx.selectionsBefore.length; i++) {\n if (groupedInverseEditOperations[i].length > 0) {\n groupedInverseEditOperations[i].sort(minorBasedSorter);\n cursorSelections[i] = commands[i].computeCursorState(ctx.model, {\n getInverseEditOperations: () => {\n return groupedInverseEditOperations[i];\n },\n getTrackedSelection: (id) => {\n const idx = parseInt(id, 10);\n const range = ctx.model._getTrackedRange(ctx.trackedRanges[idx]);\n if (ctx.trackedRangesDirection[idx] === 0 /* SelectionDirection.LTR */) {\n return new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);\n }\n return new Selection(range.endLineNumber, range.endColumn, range.startLineNumber, range.startColumn);\n }\n });\n }\n else {\n cursorSelections[i] = ctx.selectionsBefore[i];\n }\n }\n return cursorSelections;\n });\n if (!selectionsAfter) {\n selectionsAfter = ctx.selectionsBefore;\n }\n // Extract losing cursors\n const losingCursors = [];\n for (const losingCursorIndex in loserCursorsMap) {\n if (loserCursorsMap.hasOwnProperty(losingCursorIndex)) {\n losingCursors.push(parseInt(losingCursorIndex, 10));\n }\n }\n // Sort losing cursors descending\n losingCursors.sort((a, b) => {\n return b - a;\n });\n // Remove losing cursors\n for (const losingCursor of losingCursors) {\n selectionsAfter.splice(losingCursor, 1);\n }\n return selectionsAfter;\n }\n static _arrayIsEmpty(commands) {\n for (let i = 0, len = commands.length; i < len; i++) {\n if (commands[i]) {\n return false;\n }\n }\n return true;\n }\n static _getEditOperations(ctx, commands) {\n let operations = [];\n let hadTrackedEditOperation = false;\n for (let i = 0, len = commands.length; i < len; i++) {\n const command = commands[i];\n if (command) {\n const r = this._getEditOperationsFromCommand(ctx, i, command);\n operations = operations.concat(r.operations);\n hadTrackedEditOperation = hadTrackedEditOperation || r.hadTrackedEditOperation;\n }\n }\n return {\n operations: operations,\n hadTrackedEditOperation: hadTrackedEditOperation\n };\n }\n static _getEditOperationsFromCommand(ctx, majorIdentifier, command) {\n // This method acts as a transaction, if the command fails\n // everything it has done is ignored\n const operations = [];\n let operationMinor = 0;\n const addEditOperation = (range, text, forceMoveMarkers = false) => {\n if (Range.isEmpty(range) && text === '') {\n // This command wants to add a no-op => no thank you\n return;\n }\n operations.push({\n identifier: {\n major: majorIdentifier,\n minor: operationMinor++\n },\n range: range,\n text: text,\n forceMoveMarkers: forceMoveMarkers,\n isAutoWhitespaceEdit: command.insertsAutoWhitespace\n });\n };\n let hadTrackedEditOperation = false;\n const addTrackedEditOperation = (selection, text, forceMoveMarkers) => {\n hadTrackedEditOperation = true;\n addEditOperation(selection, text, forceMoveMarkers);\n };\n const trackSelection = (_selection, trackPreviousOnEmpty) => {\n const selection = Selection.liftSelection(_selection);\n let stickiness;\n if (selection.isEmpty()) {\n if (typeof trackPreviousOnEmpty === 'boolean') {\n if (trackPreviousOnEmpty) {\n stickiness = 2 /* TrackedRangeStickiness.GrowsOnlyWhenTypingBefore */;\n }\n else {\n stickiness = 3 /* TrackedRangeStickiness.GrowsOnlyWhenTypingAfter */;\n }\n }\n else {\n // Try to lock it with surrounding text\n const maxLineColumn = ctx.model.getLineMaxColumn(selection.startLineNumber);\n if (selection.startColumn === maxLineColumn) {\n stickiness = 2 /* TrackedRangeStickiness.GrowsOnlyWhenTypingBefore */;\n }\n else {\n stickiness = 3 /* TrackedRangeStickiness.GrowsOnlyWhenTypingAfter */;\n }\n }\n }\n else {\n stickiness = 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */;\n }\n const l = ctx.trackedRanges.length;\n const id = ctx.model._setTrackedRange(null, selection, stickiness);\n ctx.trackedRanges[l] = id;\n ctx.trackedRangesDirection[l] = selection.getDirection();\n return l.toString();\n };\n const editOperationBuilder = {\n addEditOperation: addEditOperation,\n addTrackedEditOperation: addTrackedEditOperation,\n trackSelection: trackSelection\n };\n try {\n command.getEditOperations(ctx.model, editOperationBuilder);\n }\n catch (e) {\n // TODO@Alex use notification service if this should be user facing\n // e.friendlyMessage = nls.localize('corrupt.commands', \"Unexpected exception while executing command.\");\n onUnexpectedError(e);\n return {\n operations: [],\n hadTrackedEditOperation: false\n };\n }\n return {\n operations: operations,\n hadTrackedEditOperation: hadTrackedEditOperation\n };\n }\n static _getLoserCursorMap(operations) {\n // This is destructive on the array\n operations = operations.slice(0);\n // Sort operations with last one first\n operations.sort((a, b) => {\n // Note the minus!\n return -(Range.compareRangesUsingEnds(a.range, b.range));\n });\n // Operations can not overlap!\n const loserCursorsMap = {};\n for (let i = 1; i < operations.length; i++) {\n const previousOp = operations[i - 1];\n const currentOp = operations[i];\n if (Range.getStartPosition(previousOp.range).isBefore(Range.getEndPosition(currentOp.range))) {\n let loserMajor;\n if (previousOp.identifier.major > currentOp.identifier.major) {\n // previousOp loses the battle\n loserMajor = previousOp.identifier.major;\n }\n else {\n loserMajor = currentOp.identifier.major;\n }\n loserCursorsMap[loserMajor.toString()] = true;\n for (let j = 0; j < operations.length; j++) {\n if (operations[j].identifier.major === loserMajor) {\n operations.splice(j, 1);\n if (j < i) {\n i--;\n }\n j--;\n }\n }\n if (i > 0) {\n i--;\n }\n }\n }\n return loserCursorsMap;\n }\n}\nclass CompositionLineState {\n constructor(text, startSelection, endSelection) {\n this.text = text;\n this.startSelection = startSelection;\n this.endSelection = endSelection;\n }\n}\nclass CompositionState {\n constructor(textModel, selections) {\n this._original = CompositionState._capture(textModel, selections);\n }\n static _capture(textModel, selections) {\n const result = [];\n for (const selection of selections) {\n if (selection.startLineNumber !== selection.endLineNumber) {\n return null;\n }\n result.push(new CompositionLineState(textModel.getLineContent(selection.startLineNumber), selection.startColumn - 1, selection.endColumn - 1));\n }\n return result;\n }\n /**\n * Returns the inserted text during this composition.\n * If the composition resulted in existing text being changed (i.e. not a pure insertion) it returns null.\n */\n deduceOutcome(textModel, selections) {\n if (!this._original) {\n return null;\n }\n const current = CompositionState._capture(textModel, selections);\n if (!current) {\n return null;\n }\n if (this._original.length !== current.length) {\n return null;\n }\n const result = [];\n for (let i = 0, len = this._original.length; i < len; i++) {\n result.push(CompositionState._deduceOutcome(this._original[i], current[i]));\n }\n return result;\n }\n static _deduceOutcome(original, current) {\n const commonPrefix = Math.min(original.startSelection, current.startSelection, strings.commonPrefixLength(original.text, current.text));\n const commonSuffix = Math.min(original.text.length - original.endSelection, current.text.length - current.endSelection, strings.commonSuffixLength(original.text, current.text));\n const deletedText = original.text.substring(commonPrefix, original.text.length - commonSuffix);\n const insertedText = current.text.substring(commonPrefix, current.text.length - commonSuffix);\n return new CompositionOutcome(deletedText, original.startSelection - commonPrefix, original.endSelection - commonPrefix, insertedText, current.startSelection - commonPrefix, current.endSelection - commonPrefix);\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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../base/common/strings.js';\nclass PendingChanges {\n constructor() {\n this._hasPending = false;\n this._inserts = [];\n this._changes = [];\n this._removes = [];\n }\n insert(x) {\n this._hasPending = true;\n this._inserts.push(x);\n }\n change(x) {\n this._hasPending = true;\n this._changes.push(x);\n }\n remove(x) {\n this._hasPending = true;\n this._removes.push(x);\n }\n mustCommit() {\n return this._hasPending;\n }\n commit(linesLayout) {\n if (!this._hasPending) {\n return;\n }\n const inserts = this._inserts;\n const changes = this._changes;\n const removes = this._removes;\n this._hasPending = false;\n this._inserts = [];\n this._changes = [];\n this._removes = [];\n linesLayout._commitPendingChanges(inserts, changes, removes);\n }\n}\nexport class EditorWhitespace {\n constructor(id, afterLineNumber, ordinal, height, minWidth) {\n this.id = id;\n this.afterLineNumber = afterLineNumber;\n this.ordinal = ordinal;\n this.height = height;\n this.minWidth = minWidth;\n this.prefixSum = 0;\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 constructor(lineCount, lineHeight, paddingTop, paddingBottom) {\n this._instanceId = strings.singleLetterHash(++LinesLayout.INSTANCE_COUNT);\n this._pendingChanges = new PendingChanges();\n this._lastWhitespaceId = 0;\n this._arr = [];\n this._prefixSumValidIndex = -1;\n this._minWidth = -1; /* marker for not being computed */\n this._lineCount = lineCount;\n this._lineHeight = lineHeight;\n this._paddingTop = paddingTop;\n this._paddingBottom = paddingBottom;\n }\n /**\n * Find the insertion index for a new value inside a sorted array of values.\n * If the value is already present in the sorted array, the insertion index will be after the already existing value.\n */\n static findInsertionIndex(arr, afterLineNumber, ordinal) {\n let low = 0;\n let high = arr.length;\n while (low < high) {\n const mid = ((low + high) >>> 1);\n if (afterLineNumber === arr[mid].afterLineNumber) {\n if (ordinal < arr[mid].ordinal) {\n high = mid;\n }\n else {\n low = mid + 1;\n }\n }\n else if (afterLineNumber < arr[mid].afterLineNumber) {\n high = mid;\n }\n else {\n low = mid + 1;\n }\n }\n return low;\n }\n /**\n * Change the height of a line in pixels.\n */\n setLineHeight(lineHeight) {\n this._checkPendingChanges();\n this._lineHeight = lineHeight;\n }\n /**\n * Changes the padding used to calculate vertical offsets.\n */\n setPadding(paddingTop, paddingBottom) {\n this._paddingTop = paddingTop;\n this._paddingBottom = paddingBottom;\n }\n /**\n * Set the number of lines.\n *\n * @param lineCount New number of lines.\n */\n onFlushed(lineCount) {\n this._checkPendingChanges();\n this._lineCount = lineCount;\n }\n changeWhitespace(callback) {\n let hadAChange = false;\n try {\n const accessor = {\n insertWhitespace: (afterLineNumber, ordinal, heightInPx, minWidth) => {\n hadAChange = true;\n afterLineNumber = afterLineNumber | 0;\n ordinal = ordinal | 0;\n heightInPx = heightInPx | 0;\n minWidth = minWidth | 0;\n const id = this._instanceId + (++this._lastWhitespaceId);\n this._pendingChanges.insert(new EditorWhitespace(id, afterLineNumber, ordinal, heightInPx, minWidth));\n return id;\n },\n changeOneWhitespace: (id, newAfterLineNumber, newHeight) => {\n hadAChange = true;\n newAfterLineNumber = newAfterLineNumber | 0;\n newHeight = newHeight | 0;\n this._pendingChanges.change({ id, newAfterLineNumber, newHeight });\n },\n removeWhitespace: (id) => {\n hadAChange = true;\n this._pendingChanges.remove({ id });\n }\n };\n callback(accessor);\n }\n finally {\n this._pendingChanges.commit(this);\n }\n return hadAChange;\n }\n _commitPendingChanges(inserts, changes, removes) {\n if (inserts.length > 0 || removes.length > 0) {\n this._minWidth = -1; /* marker for not being computed */\n }\n if (inserts.length + changes.length + removes.length <= 1) {\n // when only one thing happened, handle it \"delicately\"\n for (const insert of inserts) {\n this._insertWhitespace(insert);\n }\n for (const change of changes) {\n this._changeOneWhitespace(change.id, change.newAfterLineNumber, change.newHeight);\n }\n for (const remove of removes) {\n const index = this._findWhitespaceIndex(remove.id);\n if (index === -1) {\n continue;\n }\n this._removeWhitespace(index);\n }\n return;\n }\n // simply rebuild the entire datastructure\n const toRemove = new Set();\n for (const remove of removes) {\n toRemove.add(remove.id);\n }\n const toChange = new Map();\n for (const change of changes) {\n toChange.set(change.id, change);\n }\n const applyRemoveAndChange = (whitespaces) => {\n const result = [];\n for (const whitespace of whitespaces) {\n if (toRemove.has(whitespace.id)) {\n continue;\n }\n if (toChange.has(whitespace.id)) {\n const change = toChange.get(whitespace.id);\n whitespace.afterLineNumber = change.newAfterLineNumber;\n whitespace.height = change.newHeight;\n }\n result.push(whitespace);\n }\n return result;\n };\n const result = applyRemoveAndChange(this._arr).concat(applyRemoveAndChange(inserts));\n result.sort((a, b) => {\n if (a.afterLineNumber === b.afterLineNumber) {\n return a.ordinal - b.ordinal;\n }\n return a.afterLineNumber - b.afterLineNumber;\n });\n this._arr = result;\n this._prefixSumValidIndex = -1;\n }\n _checkPendingChanges() {\n if (this._pendingChanges.mustCommit()) {\n this._pendingChanges.commit(this);\n }\n }\n _insertWhitespace(whitespace) {\n const insertIndex = LinesLayout.findInsertionIndex(this._arr, whitespace.afterLineNumber, whitespace.ordinal);\n this._arr.splice(insertIndex, 0, whitespace);\n this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, insertIndex - 1);\n }\n _findWhitespaceIndex(id) {\n const arr = this._arr;\n for (let i = 0, len = arr.length; i < len; i++) {\n if (arr[i].id === id) {\n return i;\n }\n }\n return -1;\n }\n _changeOneWhitespace(id, newAfterLineNumber, newHeight) {\n const index = this._findWhitespaceIndex(id);\n if (index === -1) {\n return;\n }\n if (this._arr[index].height !== newHeight) {\n this._arr[index].height = newHeight;\n this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, index - 1);\n }\n if (this._arr[index].afterLineNumber !== newAfterLineNumber) {\n // `afterLineNumber` changed for this whitespace\n // Record old whitespace\n const whitespace = this._arr[index];\n // Since changing `afterLineNumber` can trigger a reordering, we're gonna remove this whitespace\n this._removeWhitespace(index);\n whitespace.afterLineNumber = newAfterLineNumber;\n // And add it again\n this._insertWhitespace(whitespace);\n }\n }\n _removeWhitespace(removeIndex) {\n this._arr.splice(removeIndex, 1);\n this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, removeIndex - 1);\n }\n /**\n * Notify the layouter that lines have been deleted (a continuous zone of lines).\n *\n * @param fromLineNumber The line number at which the deletion started, inclusive\n * @param toLineNumber The line number at which the deletion ended, inclusive\n */\n onLinesDeleted(fromLineNumber, toLineNumber) {\n this._checkPendingChanges();\n fromLineNumber = fromLineNumber | 0;\n toLineNumber = toLineNumber | 0;\n this._lineCount -= (toLineNumber - fromLineNumber + 1);\n for (let i = 0, len = this._arr.length; i < len; i++) {\n const afterLineNumber = this._arr[i].afterLineNumber;\n if (fromLineNumber <= afterLineNumber && afterLineNumber <= toLineNumber) {\n // The line this whitespace was after has been deleted\n // => move whitespace to before first deleted line\n this._arr[i].afterLineNumber = fromLineNumber - 1;\n }\n else if (afterLineNumber > toLineNumber) {\n // The line this whitespace was after has been moved up\n // => move whitespace up\n this._arr[i].afterLineNumber -= (toLineNumber - fromLineNumber + 1);\n }\n }\n }\n /**\n * Notify the layouter that lines have been inserted (a continuous zone of lines).\n *\n * @param fromLineNumber The line number at which the insertion started, inclusive\n * @param toLineNumber The line number at which the insertion ended, inclusive.\n */\n onLinesInserted(fromLineNumber, toLineNumber) {\n this._checkPendingChanges();\n fromLineNumber = fromLineNumber | 0;\n toLineNumber = toLineNumber | 0;\n this._lineCount += (toLineNumber - fromLineNumber + 1);\n for (let i = 0, len = this._arr.length; i < len; i++) {\n const afterLineNumber = this._arr[i].afterLineNumber;\n if (fromLineNumber <= afterLineNumber) {\n this._arr[i].afterLineNumber += (toLineNumber - fromLineNumber + 1);\n }\n }\n }\n /**\n * Get the sum of all the whitespaces.\n */\n getWhitespacesTotalHeight() {\n this._checkPendingChanges();\n if (this._arr.length === 0) {\n return 0;\n }\n return this.getWhitespacesAccumulatedHeight(this._arr.length - 1);\n }\n /**\n * Return the sum of the heights of the whitespaces at [0..index].\n * This includes the whitespace at `index`.\n *\n * @param index The index of the whitespace.\n * @return The sum of the heights of all whitespaces before the one at `index`, including the one at `index`.\n */\n getWhitespacesAccumulatedHeight(index) {\n this._checkPendingChanges();\n index = index | 0;\n let startIndex = Math.max(0, this._prefixSumValidIndex + 1);\n if (startIndex === 0) {\n this._arr[0].prefixSum = this._arr[0].height;\n startIndex++;\n }\n for (let i = startIndex; i <= index; i++) {\n this._arr[i].prefixSum = this._arr[i - 1].prefixSum + this._arr[i].height;\n }\n this._prefixSumValidIndex = Math.max(this._prefixSumValidIndex, index);\n return this._arr[index].prefixSum;\n }\n /**\n * Get the sum of heights for all objects.\n *\n * @return The sum of heights for all objects.\n */\n getLinesTotalHeight() {\n this._checkPendingChanges();\n const linesHeight = this._lineHeight * this._lineCount;\n const whitespacesHeight = this.getWhitespacesTotalHeight();\n return linesHeight + whitespacesHeight + this._paddingTop + this._paddingBottom;\n }\n /**\n * Returns the accumulated height of whitespaces before the given line number.\n *\n * @param lineNumber The line number\n */\n getWhitespaceAccumulatedHeightBeforeLineNumber(lineNumber) {\n this._checkPendingChanges();\n lineNumber = lineNumber | 0;\n const lastWhitespaceBeforeLineNumber = this._findLastWhitespaceBeforeLineNumber(lineNumber);\n if (lastWhitespaceBeforeLineNumber === -1) {\n return 0;\n }\n return this.getWhitespacesAccumulatedHeight(lastWhitespaceBeforeLineNumber);\n }\n _findLastWhitespaceBeforeLineNumber(lineNumber) {\n lineNumber = lineNumber | 0;\n // Find the whitespace before line number\n const arr = this._arr;\n let low = 0;\n let high = arr.length - 1;\n while (low <= high) {\n const delta = (high - low) | 0;\n const halfDelta = (delta / 2) | 0;\n const mid = (low + halfDelta) | 0;\n if (arr[mid].afterLineNumber < lineNumber) {\n if (mid + 1 >= arr.length || arr[mid + 1].afterLineNumber >= lineNumber) {\n return mid;\n }\n else {\n low = (mid + 1) | 0;\n }\n }\n else {\n high = (mid - 1) | 0;\n }\n }\n return -1;\n }\n _findFirstWhitespaceAfterLineNumber(lineNumber) {\n lineNumber = lineNumber | 0;\n const lastWhitespaceBeforeLineNumber = this._findLastWhitespaceBeforeLineNumber(lineNumber);\n const firstWhitespaceAfterLineNumber = lastWhitespaceBeforeLineNumber + 1;\n if (firstWhitespaceAfterLineNumber < this._arr.length) {\n return firstWhitespaceAfterLineNumber;\n }\n return -1;\n }\n /**\n * Find the index of the first whitespace which has `afterLineNumber` >= `lineNumber`.\n * @return The index of the first whitespace with `afterLineNumber` >= `lineNumber` or -1 if no whitespace is found.\n */\n getFirstWhitespaceIndexAfterLineNumber(lineNumber) {\n this._checkPendingChanges();\n lineNumber = lineNumber | 0;\n return this._findFirstWhitespaceAfterLineNumber(lineNumber);\n }\n /**\n * Get the vertical offset (the sum of heights for all objects above) a certain line number.\n *\n * @param lineNumber The line number\n * @return The sum of heights for all objects above `lineNumber`.\n */\n getVerticalOffsetForLineNumber(lineNumber, includeViewZones = false) {\n this._checkPendingChanges();\n lineNumber = lineNumber | 0;\n let previousLinesHeight;\n if (lineNumber > 1) {\n previousLinesHeight = this._lineHeight * (lineNumber - 1);\n }\n else {\n previousLinesHeight = 0;\n }\n const previousWhitespacesHeight = this.getWhitespaceAccumulatedHeightBeforeLineNumber(lineNumber - (includeViewZones ? 1 : 0));\n return previousLinesHeight + previousWhitespacesHeight + this._paddingTop;\n }\n /**\n * Get the vertical offset (the sum of heights for all objects above) a certain line number.\n *\n * @param lineNumber The line number\n * @return The sum of heights for all objects above `lineNumber`.\n */\n getVerticalOffsetAfterLineNumber(lineNumber, includeViewZones = false) {\n this._checkPendingChanges();\n lineNumber = lineNumber | 0;\n const previousLinesHeight = this._lineHeight * lineNumber;\n const previousWhitespacesHeight = this.getWhitespaceAccumulatedHeightBeforeLineNumber(lineNumber + (includeViewZones ? 1 : 0));\n return previousLinesHeight + previousWhitespacesHeight + this._paddingTop;\n }\n /**\n * The maximum min width for all whitespaces.\n */\n getWhitespaceMinWidth() {\n this._checkPendingChanges();\n if (this._minWidth === -1) {\n let minWidth = 0;\n for (let i = 0, len = this._arr.length; i < len; i++) {\n minWidth = Math.max(minWidth, this._arr[i].minWidth);\n }\n this._minWidth = minWidth;\n }\n return this._minWidth;\n }\n /**\n * Check if `verticalOffset` is below all lines.\n */\n isAfterLines(verticalOffset) {\n this._checkPendingChanges();\n const totalHeight = this.getLinesTotalHeight();\n return verticalOffset > totalHeight;\n }\n isInTopPadding(verticalOffset) {\n if (this._paddingTop === 0) {\n return false;\n }\n this._checkPendingChanges();\n return (verticalOffset < this._paddingTop);\n }\n isInBottomPadding(verticalOffset) {\n if (this._paddingBottom === 0) {\n return false;\n }\n this._checkPendingChanges();\n const totalHeight = this.getLinesTotalHeight();\n return (verticalOffset >= totalHeight - this._paddingBottom);\n }\n /**\n * Find the first line number that is at or after vertical offset `verticalOffset`.\n * i.e. if getVerticalOffsetForLine(line) is x and getVerticalOffsetForLine(line + 1) is y, then\n * getLineNumberAtOrAfterVerticalOffset(i) = line, x <= i < y.\n *\n * @param verticalOffset The vertical offset to search at.\n * @return The line number at or after vertical offset `verticalOffset`.\n */\n getLineNumberAtOrAfterVerticalOffset(verticalOffset) {\n this._checkPendingChanges();\n verticalOffset = verticalOffset | 0;\n if (verticalOffset < 0) {\n return 1;\n }\n const linesCount = this._lineCount | 0;\n const lineHeight = this._lineHeight;\n let minLineNumber = 1;\n let maxLineNumber = linesCount;\n while (minLineNumber < maxLineNumber) {\n const midLineNumber = ((minLineNumber + maxLineNumber) / 2) | 0;\n const midLineNumberVerticalOffset = this.getVerticalOffsetForLineNumber(midLineNumber) | 0;\n if (verticalOffset >= midLineNumberVerticalOffset + lineHeight) {\n // vertical offset is after mid line number\n minLineNumber = midLineNumber + 1;\n }\n else if (verticalOffset >= midLineNumberVerticalOffset) {\n // Hit\n return midLineNumber;\n }\n else {\n // vertical offset is before mid line number, but mid line number could still be what we're searching for\n maxLineNumber = midLineNumber;\n }\n }\n if (minLineNumber > linesCount) {\n return linesCount;\n }\n return minLineNumber;\n }\n /**\n * Get all the lines and their relative vertical offsets that are positioned between `verticalOffset1` and `verticalOffset2`.\n *\n * @param verticalOffset1 The beginning of the viewport.\n * @param verticalOffset2 The end of the viewport.\n * @return A structure describing the lines positioned between `verticalOffset1` and `verticalOffset2`.\n */\n getLinesViewportData(verticalOffset1, verticalOffset2) {\n this._checkPendingChanges();\n verticalOffset1 = verticalOffset1 | 0;\n verticalOffset2 = verticalOffset2 | 0;\n const lineHeight = this._lineHeight;\n // Find first line number\n // We don't live in a perfect world, so the line number might start before or after verticalOffset1\n const startLineNumber = this.getLineNumberAtOrAfterVerticalOffset(verticalOffset1) | 0;\n const startLineNumberVerticalOffset = this.getVerticalOffsetForLineNumber(startLineNumber) | 0;\n let endLineNumber = this._lineCount | 0;\n // Also keep track of what whitespace we've got\n let whitespaceIndex = this.getFirstWhitespaceIndexAfterLineNumber(startLineNumber) | 0;\n const whitespaceCount = this.getWhitespacesCount() | 0;\n let currentWhitespaceHeight;\n let currentWhitespaceAfterLineNumber;\n if (whitespaceIndex === -1) {\n whitespaceIndex = whitespaceCount;\n currentWhitespaceAfterLineNumber = endLineNumber + 1;\n currentWhitespaceHeight = 0;\n }\n else {\n currentWhitespaceAfterLineNumber = this.getAfterLineNumberForWhitespaceIndex(whitespaceIndex) | 0;\n currentWhitespaceHeight = this.getHeightForWhitespaceIndex(whitespaceIndex) | 0;\n }\n let currentVerticalOffset = startLineNumberVerticalOffset;\n let currentLineRelativeOffset = currentVerticalOffset;\n // IE (all versions) cannot handle units above about 1,533,908 px, so every 500k pixels bring numbers down\n const STEP_SIZE = 500000;\n let bigNumbersDelta = 0;\n if (startLineNumberVerticalOffset >= STEP_SIZE) {\n // Compute a delta that guarantees that lines are positioned at `lineHeight` increments\n bigNumbersDelta = Math.floor(startLineNumberVerticalOffset / STEP_SIZE) * STEP_SIZE;\n bigNumbersDelta = Math.floor(bigNumbersDelta / lineHeight) * lineHeight;\n currentLineRelativeOffset -= bigNumbersDelta;\n }\n const linesOffsets = [];\n const verticalCenter = verticalOffset1 + (verticalOffset2 - verticalOffset1) / 2;\n let centeredLineNumber = -1;\n // Figure out how far the lines go\n for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n if (centeredLineNumber === -1) {\n const currentLineTop = currentVerticalOffset;\n const currentLineBottom = currentVerticalOffset + lineHeight;\n if ((currentLineTop <= verticalCenter && verticalCenter < currentLineBottom) || currentLineTop > verticalCenter) {\n centeredLineNumber = lineNumber;\n }\n }\n // Count current line height in the vertical offsets\n currentVerticalOffset += lineHeight;\n linesOffsets[lineNumber - startLineNumber] = currentLineRelativeOffset;\n // Next line starts immediately after this one\n currentLineRelativeOffset += lineHeight;\n while (currentWhitespaceAfterLineNumber === lineNumber) {\n // Push down next line with the height of the current whitespace\n currentLineRelativeOffset += currentWhitespaceHeight;\n // Count current whitespace in the vertical offsets\n currentVerticalOffset += currentWhitespaceHeight;\n whitespaceIndex++;\n if (whitespaceIndex >= whitespaceCount) {\n currentWhitespaceAfterLineNumber = endLineNumber + 1;\n }\n else {\n currentWhitespaceAfterLineNumber = this.getAfterLineNumberForWhitespaceIndex(whitespaceIndex) | 0;\n currentWhitespaceHeight = this.getHeightForWhitespaceIndex(whitespaceIndex) | 0;\n }\n }\n if (currentVerticalOffset >= verticalOffset2) {\n // We have covered the entire viewport area, time to stop\n endLineNumber = lineNumber;\n break;\n }\n }\n if (centeredLineNumber === -1) {\n centeredLineNumber = endLineNumber;\n }\n const endLineNumberVerticalOffset = this.getVerticalOffsetForLineNumber(endLineNumber) | 0;\n let completelyVisibleStartLineNumber = startLineNumber;\n let completelyVisibleEndLineNumber = endLineNumber;\n if (completelyVisibleStartLineNumber < completelyVisibleEndLineNumber) {\n if (startLineNumberVerticalOffset < verticalOffset1) {\n completelyVisibleStartLineNumber++;\n }\n }\n if (completelyVisibleStartLineNumber < completelyVisibleEndLineNumber) {\n if (endLineNumberVerticalOffset + lineHeight > verticalOffset2) {\n completelyVisibleEndLineNumber--;\n }\n }\n return {\n bigNumbersDelta: bigNumbersDelta,\n startLineNumber: startLineNumber,\n endLineNumber: endLineNumber,\n relativeVerticalOffset: linesOffsets,\n centeredLineNumber: centeredLineNumber,\n completelyVisibleStartLineNumber: completelyVisibleStartLineNumber,\n completelyVisibleEndLineNumber: completelyVisibleEndLineNumber\n };\n }\n getVerticalOffsetForWhitespaceIndex(whitespaceIndex) {\n this._checkPendingChanges();\n whitespaceIndex = whitespaceIndex | 0;\n const afterLineNumber = this.getAfterLineNumberForWhitespaceIndex(whitespaceIndex);\n let previousLinesHeight;\n if (afterLineNumber >= 1) {\n previousLinesHeight = this._lineHeight * afterLineNumber;\n }\n else {\n previousLinesHeight = 0;\n }\n let previousWhitespacesHeight;\n if (whitespaceIndex > 0) {\n previousWhitespacesHeight = this.getWhitespacesAccumulatedHeight(whitespaceIndex - 1);\n }\n else {\n previousWhitespacesHeight = 0;\n }\n return previousLinesHeight + previousWhitespacesHeight + this._paddingTop;\n }\n getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset) {\n this._checkPendingChanges();\n verticalOffset = verticalOffset | 0;\n let minWhitespaceIndex = 0;\n let maxWhitespaceIndex = this.getWhitespacesCount() - 1;\n if (maxWhitespaceIndex < 0) {\n return -1;\n }\n // Special case: nothing to be found\n const maxWhitespaceVerticalOffset = this.getVerticalOffsetForWhitespaceIndex(maxWhitespaceIndex);\n const maxWhitespaceHeight = this.getHeightForWhitespaceIndex(maxWhitespaceIndex);\n if (verticalOffset >= maxWhitespaceVerticalOffset + maxWhitespaceHeight) {\n return -1;\n }\n while (minWhitespaceIndex < maxWhitespaceIndex) {\n const midWhitespaceIndex = Math.floor((minWhitespaceIndex + maxWhitespaceIndex) / 2);\n const midWhitespaceVerticalOffset = this.getVerticalOffsetForWhitespaceIndex(midWhitespaceIndex);\n const midWhitespaceHeight = this.getHeightForWhitespaceIndex(midWhitespaceIndex);\n if (verticalOffset >= midWhitespaceVerticalOffset + midWhitespaceHeight) {\n // vertical offset is after whitespace\n minWhitespaceIndex = midWhitespaceIndex + 1;\n }\n else if (verticalOffset >= midWhitespaceVerticalOffset) {\n // Hit\n return midWhitespaceIndex;\n }\n else {\n // vertical offset is before whitespace, but midWhitespaceIndex might still be what we're searching for\n maxWhitespaceIndex = midWhitespaceIndex;\n }\n }\n return minWhitespaceIndex;\n }\n /**\n * Get exactly the whitespace that is layouted at `verticalOffset`.\n *\n * @param verticalOffset The vertical offset.\n * @return Precisely the whitespace that is layouted at `verticaloffset` or null.\n */\n getWhitespaceAtVerticalOffset(verticalOffset) {\n this._checkPendingChanges();\n verticalOffset = verticalOffset | 0;\n const candidateIndex = this.getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset);\n if (candidateIndex < 0) {\n return null;\n }\n if (candidateIndex >= this.getWhitespacesCount()) {\n return null;\n }\n const candidateTop = this.getVerticalOffsetForWhitespaceIndex(candidateIndex);\n if (candidateTop > verticalOffset) {\n return null;\n }\n const candidateHeight = this.getHeightForWhitespaceIndex(candidateIndex);\n const candidateId = this.getIdForWhitespaceIndex(candidateIndex);\n const candidateAfterLineNumber = this.getAfterLineNumberForWhitespaceIndex(candidateIndex);\n return {\n id: candidateId,\n afterLineNumber: candidateAfterLineNumber,\n verticalOffset: candidateTop,\n height: candidateHeight\n };\n }\n /**\n * Get a list of whitespaces that are positioned between `verticalOffset1` and `verticalOffset2`.\n *\n * @param verticalOffset1 The beginning of the viewport.\n * @param verticalOffset2 The end of the viewport.\n * @return An array with all the whitespaces in the viewport. If no whitespace is in viewport, the array is empty.\n */\n getWhitespaceViewportData(verticalOffset1, verticalOffset2) {\n this._checkPendingChanges();\n verticalOffset1 = verticalOffset1 | 0;\n verticalOffset2 = verticalOffset2 | 0;\n const startIndex = this.getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset1);\n const endIndex = this.getWhitespacesCount() - 1;\n if (startIndex < 0) {\n return [];\n }\n const result = [];\n for (let i = startIndex; i <= endIndex; i++) {\n const top = this.getVerticalOffsetForWhitespaceIndex(i);\n const height = this.getHeightForWhitespaceIndex(i);\n if (top >= verticalOffset2) {\n break;\n }\n result.push({\n id: this.getIdForWhitespaceIndex(i),\n afterLineNumber: this.getAfterLineNumberForWhitespaceIndex(i),\n verticalOffset: top,\n height: height\n });\n }\n return result;\n }\n /**\n * Get all whitespaces.\n */\n getWhitespaces() {\n this._checkPendingChanges();\n return this._arr.slice(0);\n }\n /**\n * The number of whitespaces.\n */\n getWhitespacesCount() {\n this._checkPendingChanges();\n return this._arr.length;\n }\n /**\n * Get the `id` for whitespace at index `index`.\n *\n * @param index The index of the whitespace.\n * @return `id` of whitespace at `index`.\n */\n getIdForWhitespaceIndex(index) {\n this._checkPendingChanges();\n index = index | 0;\n return this._arr[index].id;\n }\n /**\n * Get the `afterLineNumber` for whitespace at index `index`.\n *\n * @param index The index of the whitespace.\n * @return `afterLineNumber` of whitespace at `index`.\n */\n getAfterLineNumberForWhitespaceIndex(index) {\n this._checkPendingChanges();\n index = index | 0;\n return this._arr[index].afterLineNumber;\n }\n /**\n * Get the `height` for whitespace at index `index`.\n *\n * @param index The index of the whitespace.\n * @return `height` of whitespace at `index`.\n */\n getHeightForWhitespaceIndex(index) {\n this._checkPendingChanges();\n index = index | 0;\n return this._arr[index].height;\n }\n}\nLinesLayout.INSTANCE_COUNT = 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 *--------------------------------------------------------------------------------------------*/\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { Scrollable } from '../../../base/common/scrollable.js';\nimport { LinesLayout } from './linesLayout.js';\nimport { Viewport } from '../viewModel.js';\nimport { ContentSizeChangedEvent } from '../viewModelEventDispatcher.js';\nconst SMOOTH_SCROLLING_TIME = 125;\nclass EditorScrollDimensions {\n constructor(width, contentWidth, height, contentHeight) {\n width = width | 0;\n contentWidth = contentWidth | 0;\n height = height | 0;\n contentHeight = contentHeight | 0;\n if (width < 0) {\n width = 0;\n }\n if (contentWidth < 0) {\n contentWidth = 0;\n }\n if (height < 0) {\n height = 0;\n }\n if (contentHeight < 0) {\n contentHeight = 0;\n }\n this.width = width;\n this.contentWidth = contentWidth;\n this.scrollWidth = Math.max(width, contentWidth);\n this.height = height;\n this.contentHeight = contentHeight;\n this.scrollHeight = Math.max(height, contentHeight);\n }\n equals(other) {\n return (this.width === other.width\n && this.contentWidth === other.contentWidth\n && this.height === other.height\n && this.contentHeight === other.contentHeight);\n }\n}\nclass EditorScrollable extends Disposable {\n constructor(smoothScrollDuration, scheduleAtNextAnimationFrame) {\n super();\n this._onDidContentSizeChange = this._register(new Emitter());\n this.onDidContentSizeChange = this._onDidContentSizeChange.event;\n this._dimensions = new EditorScrollDimensions(0, 0, 0, 0);\n this._scrollable = this._register(new Scrollable({\n forceIntegerValues: true,\n smoothScrollDuration,\n scheduleAtNextAnimationFrame\n }));\n this.onDidScroll = this._scrollable.onScroll;\n }\n getScrollable() {\n return this._scrollable;\n }\n setSmoothScrollDuration(smoothScrollDuration) {\n this._scrollable.setSmoothScrollDuration(smoothScrollDuration);\n }\n validateScrollPosition(scrollPosition) {\n return this._scrollable.validateScrollPosition(scrollPosition);\n }\n getScrollDimensions() {\n return this._dimensions;\n }\n setScrollDimensions(dimensions) {\n if (this._dimensions.equals(dimensions)) {\n return;\n }\n const oldDimensions = this._dimensions;\n this._dimensions = dimensions;\n this._scrollable.setScrollDimensions({\n width: dimensions.width,\n scrollWidth: dimensions.scrollWidth,\n height: dimensions.height,\n scrollHeight: dimensions.scrollHeight\n }, true);\n const contentWidthChanged = (oldDimensions.contentWidth !== dimensions.contentWidth);\n const contentHeightChanged = (oldDimensions.contentHeight !== dimensions.contentHeight);\n if (contentWidthChanged || contentHeightChanged) {\n this._onDidContentSizeChange.fire(new ContentSizeChangedEvent(oldDimensions.contentWidth, oldDimensions.contentHeight, dimensions.contentWidth, dimensions.contentHeight));\n }\n }\n getFutureScrollPosition() {\n return this._scrollable.getFutureScrollPosition();\n }\n getCurrentScrollPosition() {\n return this._scrollable.getCurrentScrollPosition();\n }\n setScrollPositionNow(update) {\n this._scrollable.setScrollPositionNow(update);\n }\n setScrollPositionSmooth(update) {\n this._scrollable.setScrollPositionSmooth(update);\n }\n}\nexport class ViewLayout extends Disposable {\n constructor(configuration, lineCount, scheduleAtNextAnimationFrame) {\n super();\n this._configuration = configuration;\n const options = this._configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n const padding = options.get(77 /* EditorOption.padding */);\n this._linesLayout = new LinesLayout(lineCount, options.get(61 /* EditorOption.lineHeight */), padding.top, padding.bottom);\n this._scrollable = this._register(new EditorScrollable(0, scheduleAtNextAnimationFrame));\n this._configureSmoothScrollDuration();\n this._scrollable.setScrollDimensions(new EditorScrollDimensions(layoutInfo.contentWidth, 0, layoutInfo.height, 0));\n this.onDidScroll = this._scrollable.onDidScroll;\n this.onDidContentSizeChange = this._scrollable.onDidContentSizeChange;\n this._updateHeight();\n }\n dispose() {\n super.dispose();\n }\n getScrollable() {\n return this._scrollable.getScrollable();\n }\n onHeightMaybeChanged() {\n this._updateHeight();\n }\n _configureSmoothScrollDuration() {\n this._scrollable.setSmoothScrollDuration(this._configuration.options.get(105 /* EditorOption.smoothScrolling */) ? SMOOTH_SCROLLING_TIME : 0);\n }\n // ---- begin view event handlers\n onConfigurationChanged(e) {\n const options = this._configuration.options;\n if (e.hasChanged(61 /* EditorOption.lineHeight */)) {\n this._linesLayout.setLineHeight(options.get(61 /* EditorOption.lineHeight */));\n }\n if (e.hasChanged(77 /* EditorOption.padding */)) {\n const padding = options.get(77 /* EditorOption.padding */);\n this._linesLayout.setPadding(padding.top, padding.bottom);\n }\n if (e.hasChanged(133 /* EditorOption.layoutInfo */)) {\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n const width = layoutInfo.contentWidth;\n const height = layoutInfo.height;\n const scrollDimensions = this._scrollable.getScrollDimensions();\n const contentWidth = scrollDimensions.contentWidth;\n this._scrollable.setScrollDimensions(new EditorScrollDimensions(width, scrollDimensions.contentWidth, height, this._getContentHeight(width, height, contentWidth)));\n }\n else {\n this._updateHeight();\n }\n if (e.hasChanged(105 /* EditorOption.smoothScrolling */)) {\n this._configureSmoothScrollDuration();\n }\n }\n onFlushed(lineCount) {\n this._linesLayout.onFlushed(lineCount);\n }\n onLinesDeleted(fromLineNumber, toLineNumber) {\n this._linesLayout.onLinesDeleted(fromLineNumber, toLineNumber);\n }\n onLinesInserted(fromLineNumber, toLineNumber) {\n this._linesLayout.onLinesInserted(fromLineNumber, toLineNumber);\n }\n // ---- end view event handlers\n _getHorizontalScrollbarHeight(width, scrollWidth) {\n const options = this._configuration.options;\n const scrollbar = options.get(94 /* EditorOption.scrollbar */);\n if (scrollbar.horizontal === 2 /* ScrollbarVisibility.Hidden */) {\n // horizontal scrollbar not visible\n return 0;\n }\n if (width >= scrollWidth) {\n // horizontal scrollbar not visible\n return 0;\n }\n return scrollbar.horizontalScrollbarSize;\n }\n _getContentHeight(width, height, contentWidth) {\n const options = this._configuration.options;\n let result = this._linesLayout.getLinesTotalHeight();\n if (options.get(96 /* EditorOption.scrollBeyondLastLine */)) {\n result += Math.max(0, height - options.get(61 /* EditorOption.lineHeight */) - options.get(77 /* EditorOption.padding */).bottom);\n }\n else {\n result += this._getHorizontalScrollbarHeight(width, contentWidth);\n }\n return result;\n }\n _updateHeight() {\n const scrollDimensions = this._scrollable.getScrollDimensions();\n const width = scrollDimensions.width;\n const height = scrollDimensions.height;\n const contentWidth = scrollDimensions.contentWidth;\n this._scrollable.setScrollDimensions(new EditorScrollDimensions(width, scrollDimensions.contentWidth, height, this._getContentHeight(width, height, contentWidth)));\n }\n // ---- Layouting logic\n getCurrentViewport() {\n const scrollDimensions = this._scrollable.getScrollDimensions();\n const currentScrollPosition = this._scrollable.getCurrentScrollPosition();\n return new Viewport(currentScrollPosition.scrollTop, currentScrollPosition.scrollLeft, scrollDimensions.width, scrollDimensions.height);\n }\n getFutureViewport() {\n const scrollDimensions = this._scrollable.getScrollDimensions();\n const currentScrollPosition = this._scrollable.getFutureScrollPosition();\n return new Viewport(currentScrollPosition.scrollTop, currentScrollPosition.scrollLeft, scrollDimensions.width, scrollDimensions.height);\n }\n _computeContentWidth(maxLineWidth) {\n const options = this._configuration.options;\n const wrappingInfo = options.get(134 /* EditorOption.wrappingInfo */);\n const fontInfo = options.get(46 /* EditorOption.fontInfo */);\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n if (wrappingInfo.isViewportWrapping) {\n const minimap = options.get(67 /* EditorOption.minimap */);\n if (maxLineWidth > layoutInfo.contentWidth + fontInfo.typicalHalfwidthCharacterWidth) {\n // This is a case where viewport wrapping is on, but the line extends above the viewport\n if (minimap.enabled && minimap.side === 'right') {\n // We need to accomodate the scrollbar width\n return maxLineWidth + layoutInfo.verticalScrollbarWidth;\n }\n }\n return maxLineWidth;\n }\n else {\n const extraHorizontalSpace = options.get(95 /* EditorOption.scrollBeyondLastColumn */) * fontInfo.typicalHalfwidthCharacterWidth;\n const whitespaceMinWidth = this._linesLayout.getWhitespaceMinWidth();\n return Math.max(maxLineWidth + extraHorizontalSpace + layoutInfo.verticalScrollbarWidth, whitespaceMinWidth);\n }\n }\n setMaxLineWidth(maxLineWidth) {\n const scrollDimensions = this._scrollable.getScrollDimensions();\n // const newScrollWidth = ;\n this._scrollable.setScrollDimensions(new EditorScrollDimensions(scrollDimensions.width, this._computeContentWidth(maxLineWidth), scrollDimensions.height, scrollDimensions.contentHeight));\n // The height might depend on the fact that there is a horizontal scrollbar or not\n this._updateHeight();\n }\n // ---- view state\n saveState() {\n const currentScrollPosition = this._scrollable.getFutureScrollPosition();\n const scrollTop = currentScrollPosition.scrollTop;\n const firstLineNumberInViewport = this._linesLayout.getLineNumberAtOrAfterVerticalOffset(scrollTop);\n const whitespaceAboveFirstLine = this._linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(firstLineNumberInViewport);\n return {\n scrollTop: scrollTop,\n scrollTopWithoutViewZones: scrollTop - whitespaceAboveFirstLine,\n scrollLeft: currentScrollPosition.scrollLeft\n };\n }\n // ----\n changeWhitespace(callback) {\n const hadAChange = this._linesLayout.changeWhitespace(callback);\n if (hadAChange) {\n this.onHeightMaybeChanged();\n }\n return hadAChange;\n }\n getVerticalOffsetForLineNumber(lineNumber, includeViewZones = false) {\n return this._linesLayout.getVerticalOffsetForLineNumber(lineNumber, includeViewZones);\n }\n getVerticalOffsetAfterLineNumber(lineNumber, includeViewZones = false) {\n return this._linesLayout.getVerticalOffsetAfterLineNumber(lineNumber, includeViewZones);\n }\n isAfterLines(verticalOffset) {\n return this._linesLayout.isAfterLines(verticalOffset);\n }\n isInTopPadding(verticalOffset) {\n return this._linesLayout.isInTopPadding(verticalOffset);\n }\n isInBottomPadding(verticalOffset) {\n return this._linesLayout.isInBottomPadding(verticalOffset);\n }\n getLineNumberAtVerticalOffset(verticalOffset) {\n return this._linesLayout.getLineNumberAtOrAfterVerticalOffset(verticalOffset);\n }\n getWhitespaceAtVerticalOffset(verticalOffset) {\n return this._linesLayout.getWhitespaceAtVerticalOffset(verticalOffset);\n }\n getLinesViewportData() {\n const visibleBox = this.getCurrentViewport();\n return this._linesLayout.getLinesViewportData(visibleBox.top, visibleBox.top + visibleBox.height);\n }\n getLinesViewportDataAtScrollTop(scrollTop) {\n // do some minimal validations on scrollTop\n const scrollDimensions = this._scrollable.getScrollDimensions();\n if (scrollTop + scrollDimensions.height > scrollDimensions.scrollHeight) {\n scrollTop = scrollDimensions.scrollHeight - scrollDimensions.height;\n }\n if (scrollTop < 0) {\n scrollTop = 0;\n }\n return this._linesLayout.getLinesViewportData(scrollTop, scrollTop + scrollDimensions.height);\n }\n getWhitespaceViewportData() {\n const visibleBox = this.getCurrentViewport();\n return this._linesLayout.getWhitespaceViewportData(visibleBox.top, visibleBox.top + visibleBox.height);\n }\n getWhitespaces() {\n return this._linesLayout.getWhitespaces();\n }\n // ----\n getContentWidth() {\n const scrollDimensions = this._scrollable.getScrollDimensions();\n return scrollDimensions.contentWidth;\n }\n getScrollWidth() {\n const scrollDimensions = this._scrollable.getScrollDimensions();\n return scrollDimensions.scrollWidth;\n }\n getContentHeight() {\n const scrollDimensions = this._scrollable.getScrollDimensions();\n return scrollDimensions.contentHeight;\n }\n getScrollHeight() {\n const scrollDimensions = this._scrollable.getScrollDimensions();\n return scrollDimensions.scrollHeight;\n }\n getCurrentScrollLeft() {\n const currentScrollPosition = this._scrollable.getCurrentScrollPosition();\n return currentScrollPosition.scrollLeft;\n }\n getCurrentScrollTop() {\n const currentScrollPosition = this._scrollable.getCurrentScrollPosition();\n return currentScrollPosition.scrollTop;\n }\n validateScrollPosition(scrollPosition) {\n return this._scrollable.validateScrollPosition(scrollPosition);\n }\n setScrollPosition(position, type) {\n if (type === 1 /* ScrollType.Immediate */) {\n this._scrollable.setScrollPositionNow(position);\n }\n else {\n this._scrollable.setScrollPositionSmooth(position);\n }\n }\n deltaScrollNow(deltaScrollLeft, deltaScrollTop) {\n const currentScrollPosition = this._scrollable.getCurrentScrollPosition();\n this._scrollable.setScrollPositionNow({\n scrollLeft: currentScrollPosition.scrollLeft + deltaScrollLeft,\n scrollTop: currentScrollPosition.scrollTop + deltaScrollTop\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 *--------------------------------------------------------------------------------------------*/\nimport { LineTokens } from '../tokens/lineTokens.js';\nimport { Position } from '../core/position.js';\nimport { LineInjectedText } from '../textModelEvents.js';\nimport { SingleLineInlineDecoration, ViewLineData } from '../viewModel.js';\nexport function createModelLineProjection(lineBreakData, isVisible) {\n if (lineBreakData === null) {\n // No mapping needed\n if (isVisible) {\n return IdentityModelLineProjection.INSTANCE;\n }\n return HiddenModelLineProjection.INSTANCE;\n }\n else {\n return new ModelLineProjection(lineBreakData, isVisible);\n }\n}\n/**\n * This projection is used to\n * * wrap model lines\n * * inject text\n */\nclass ModelLineProjection {\n constructor(lineBreakData, isVisible) {\n this._projectionData = lineBreakData;\n this._isVisible = isVisible;\n }\n isVisible() {\n return this._isVisible;\n }\n setVisible(isVisible) {\n this._isVisible = isVisible;\n return this;\n }\n getProjectionData() {\n return this._projectionData;\n }\n getViewLineCount() {\n if (!this._isVisible) {\n return 0;\n }\n return this._projectionData.getOutputLineCount();\n }\n getViewLineContent(model, modelLineNumber, outputLineIndex) {\n this._assertVisible();\n const startOffsetInInputWithInjections = outputLineIndex > 0 ? this._projectionData.breakOffsets[outputLineIndex - 1] : 0;\n const endOffsetInInputWithInjections = this._projectionData.breakOffsets[outputLineIndex];\n let r;\n if (this._projectionData.injectionOffsets !== null) {\n const injectedTexts = this._projectionData.injectionOffsets.map((offset, idx) => new LineInjectedText(0, 0, offset + 1, this._projectionData.injectionOptions[idx], 0));\n const lineWithInjections = LineInjectedText.applyInjectedText(model.getLineContent(modelLineNumber), injectedTexts);\n r = lineWithInjections.substring(startOffsetInInputWithInjections, endOffsetInInputWithInjections);\n }\n else {\n r = model.getValueInRange({\n startLineNumber: modelLineNumber,\n startColumn: startOffsetInInputWithInjections + 1,\n endLineNumber: modelLineNumber,\n endColumn: endOffsetInInputWithInjections + 1\n });\n }\n if (outputLineIndex > 0) {\n r = spaces(this._projectionData.wrappedTextIndentLength) + r;\n }\n return r;\n }\n getViewLineLength(model, modelLineNumber, outputLineIndex) {\n this._assertVisible();\n return this._projectionData.getLineLength(outputLineIndex);\n }\n getViewLineMinColumn(_model, _modelLineNumber, outputLineIndex) {\n this._assertVisible();\n return this._projectionData.getMinOutputOffset(outputLineIndex) + 1;\n }\n getViewLineMaxColumn(model, modelLineNumber, outputLineIndex) {\n this._assertVisible();\n return this._projectionData.getMaxOutputOffset(outputLineIndex) + 1;\n }\n /**\n * Try using {@link getViewLinesData} instead.\n */\n getViewLineData(model, modelLineNumber, outputLineIndex) {\n const arr = new Array();\n this.getViewLinesData(model, modelLineNumber, outputLineIndex, 1, 0, [true], arr);\n return arr[0];\n }\n getViewLinesData(model, modelLineNumber, outputLineIdx, lineCount, globalStartIndex, needed, result) {\n this._assertVisible();\n const lineBreakData = this._projectionData;\n const injectionOffsets = lineBreakData.injectionOffsets;\n const injectionOptions = lineBreakData.injectionOptions;\n let inlineDecorationsPerOutputLine = null;\n if (injectionOffsets) {\n inlineDecorationsPerOutputLine = [];\n let totalInjectedTextLengthBefore = 0;\n let currentInjectedOffset = 0;\n for (let outputLineIndex = 0; outputLineIndex < lineBreakData.getOutputLineCount(); outputLineIndex++) {\n const inlineDecorations = new Array();\n inlineDecorationsPerOutputLine[outputLineIndex] = inlineDecorations;\n const lineStartOffsetInInputWithInjections = outputLineIndex > 0 ? lineBreakData.breakOffsets[outputLineIndex - 1] : 0;\n const lineEndOffsetInInputWithInjections = lineBreakData.breakOffsets[outputLineIndex];\n while (currentInjectedOffset < injectionOffsets.length) {\n const length = injectionOptions[currentInjectedOffset].content.length;\n const injectedTextStartOffsetInInputWithInjections = injectionOffsets[currentInjectedOffset] + totalInjectedTextLengthBefore;\n const injectedTextEndOffsetInInputWithInjections = injectedTextStartOffsetInInputWithInjections + length;\n if (injectedTextStartOffsetInInputWithInjections > lineEndOffsetInInputWithInjections) {\n // Injected text only starts in later wrapped lines.\n break;\n }\n if (lineStartOffsetInInputWithInjections < injectedTextEndOffsetInInputWithInjections) {\n // Injected text ends after or in this line (but also starts in or before this line).\n const options = injectionOptions[currentInjectedOffset];\n if (options.inlineClassName) {\n const offset = (outputLineIndex > 0 ? lineBreakData.wrappedTextIndentLength : 0);\n const start = offset + Math.max(injectedTextStartOffsetInInputWithInjections - lineStartOffsetInInputWithInjections, 0);\n const end = offset + Math.min(injectedTextEndOffsetInInputWithInjections - lineStartOffsetInInputWithInjections, lineEndOffsetInInputWithInjections);\n if (start !== end) {\n inlineDecorations.push(new SingleLineInlineDecoration(start, end, options.inlineClassName, options.inlineClassNameAffectsLetterSpacing));\n }\n }\n }\n if (injectedTextEndOffsetInInputWithInjections <= lineEndOffsetInInputWithInjections) {\n totalInjectedTextLengthBefore += length;\n currentInjectedOffset++;\n }\n else {\n // injected text breaks into next line, process it again\n break;\n }\n }\n }\n }\n let lineWithInjections;\n if (injectionOffsets) {\n lineWithInjections = model.tokenization.getLineTokens(modelLineNumber).withInserted(injectionOffsets.map((offset, idx) => ({\n offset,\n text: injectionOptions[idx].content,\n tokenMetadata: LineTokens.defaultTokenMetadata\n })));\n }\n else {\n lineWithInjections = model.tokenization.getLineTokens(modelLineNumber);\n }\n for (let outputLineIndex = outputLineIdx; outputLineIndex < outputLineIdx + lineCount; outputLineIndex++) {\n const globalIndex = globalStartIndex + outputLineIndex - outputLineIdx;\n if (!needed[globalIndex]) {\n result[globalIndex] = null;\n continue;\n }\n result[globalIndex] = this._getViewLineData(lineWithInjections, inlineDecorationsPerOutputLine ? inlineDecorationsPerOutputLine[outputLineIndex] : null, outputLineIndex);\n }\n }\n _getViewLineData(lineWithInjections, inlineDecorations, outputLineIndex) {\n this._assertVisible();\n const lineBreakData = this._projectionData;\n const deltaStartIndex = (outputLineIndex > 0 ? lineBreakData.wrappedTextIndentLength : 0);\n const lineStartOffsetInInputWithInjections = outputLineIndex > 0 ? lineBreakData.breakOffsets[outputLineIndex - 1] : 0;\n const lineEndOffsetInInputWithInjections = lineBreakData.breakOffsets[outputLineIndex];\n const tokens = lineWithInjections.sliceAndInflate(lineStartOffsetInInputWithInjections, lineEndOffsetInInputWithInjections, deltaStartIndex);\n let lineContent = tokens.getLineContent();\n if (outputLineIndex > 0) {\n lineContent = spaces(lineBreakData.wrappedTextIndentLength) + lineContent;\n }\n const minColumn = this._projectionData.getMinOutputOffset(outputLineIndex) + 1;\n const maxColumn = lineContent.length + 1;\n const continuesWithWrappedLine = (outputLineIndex + 1 < this.getViewLineCount());\n const startVisibleColumn = (outputLineIndex === 0 ? 0 : lineBreakData.breakOffsetsVisibleColumn[outputLineIndex - 1]);\n return new ViewLineData(lineContent, continuesWithWrappedLine, minColumn, maxColumn, startVisibleColumn, tokens, inlineDecorations);\n }\n getModelColumnOfViewPosition(outputLineIndex, outputColumn) {\n this._assertVisible();\n return this._projectionData.translateToInputOffset(outputLineIndex, outputColumn - 1) + 1;\n }\n getViewPositionOfModelPosition(deltaLineNumber, inputColumn, affinity = 2 /* PositionAffinity.None */) {\n this._assertVisible();\n const r = this._projectionData.translateToOutputPosition(inputColumn - 1, affinity);\n return r.toPosition(deltaLineNumber);\n }\n getViewLineNumberOfModelPosition(deltaLineNumber, inputColumn) {\n this._assertVisible();\n const r = this._projectionData.translateToOutputPosition(inputColumn - 1);\n return deltaLineNumber + r.outputLineIndex;\n }\n normalizePosition(outputLineIndex, outputPosition, affinity) {\n const baseViewLineNumber = outputPosition.lineNumber - outputLineIndex;\n const normalizedOutputPosition = this._projectionData.normalizeOutputPosition(outputLineIndex, outputPosition.column - 1, affinity);\n const result = normalizedOutputPosition.toPosition(baseViewLineNumber);\n return result;\n }\n getInjectedTextAt(outputLineIndex, outputColumn) {\n return this._projectionData.getInjectedText(outputLineIndex, outputColumn - 1);\n }\n _assertVisible() {\n if (!this._isVisible) {\n throw new Error('Not supported');\n }\n }\n}\n/**\n * This projection does not change the model line.\n*/\nclass IdentityModelLineProjection {\n constructor() { }\n isVisible() {\n return true;\n }\n setVisible(isVisible) {\n if (isVisible) {\n return this;\n }\n return HiddenModelLineProjection.INSTANCE;\n }\n getProjectionData() {\n return null;\n }\n getViewLineCount() {\n return 1;\n }\n getViewLineContent(model, modelLineNumber, _outputLineIndex) {\n return model.getLineContent(modelLineNumber);\n }\n getViewLineLength(model, modelLineNumber, _outputLineIndex) {\n return model.getLineLength(modelLineNumber);\n }\n getViewLineMinColumn(model, modelLineNumber, _outputLineIndex) {\n return model.getLineMinColumn(modelLineNumber);\n }\n getViewLineMaxColumn(model, modelLineNumber, _outputLineIndex) {\n return model.getLineMaxColumn(modelLineNumber);\n }\n getViewLineData(model, modelLineNumber, _outputLineIndex) {\n const lineTokens = model.tokenization.getLineTokens(modelLineNumber);\n const lineContent = lineTokens.getLineContent();\n return new ViewLineData(lineContent, false, 1, lineContent.length + 1, 0, lineTokens.inflate(), null);\n }\n getViewLinesData(model, modelLineNumber, _fromOuputLineIndex, _toOutputLineIndex, globalStartIndex, needed, result) {\n if (!needed[globalStartIndex]) {\n result[globalStartIndex] = null;\n return;\n }\n result[globalStartIndex] = this.getViewLineData(model, modelLineNumber, 0);\n }\n getModelColumnOfViewPosition(_outputLineIndex, outputColumn) {\n return outputColumn;\n }\n getViewPositionOfModelPosition(deltaLineNumber, inputColumn) {\n return new Position(deltaLineNumber, inputColumn);\n }\n getViewLineNumberOfModelPosition(deltaLineNumber, _inputColumn) {\n return deltaLineNumber;\n }\n normalizePosition(outputLineIndex, outputPosition, affinity) {\n return outputPosition;\n }\n getInjectedTextAt(_outputLineIndex, _outputColumn) {\n return null;\n }\n}\nIdentityModelLineProjection.INSTANCE = new IdentityModelLineProjection();\n/**\n * This projection hides the model line.\n */\nclass HiddenModelLineProjection {\n constructor() { }\n isVisible() {\n return false;\n }\n setVisible(isVisible) {\n if (!isVisible) {\n return this;\n }\n return IdentityModelLineProjection.INSTANCE;\n }\n getProjectionData() {\n return null;\n }\n getViewLineCount() {\n return 0;\n }\n getViewLineContent(_model, _modelLineNumber, _outputLineIndex) {\n throw new Error('Not supported');\n }\n getViewLineLength(_model, _modelLineNumber, _outputLineIndex) {\n throw new Error('Not supported');\n }\n getViewLineMinColumn(_model, _modelLineNumber, _outputLineIndex) {\n throw new Error('Not supported');\n }\n getViewLineMaxColumn(_model, _modelLineNumber, _outputLineIndex) {\n throw new Error('Not supported');\n }\n getViewLineData(_model, _modelLineNumber, _outputLineIndex) {\n throw new Error('Not supported');\n }\n getViewLinesData(_model, _modelLineNumber, _fromOuputLineIndex, _toOutputLineIndex, _globalStartIndex, _needed, _result) {\n throw new Error('Not supported');\n }\n getModelColumnOfViewPosition(_outputLineIndex, _outputColumn) {\n throw new Error('Not supported');\n }\n getViewPositionOfModelPosition(_deltaLineNumber, _inputColumn) {\n throw new Error('Not supported');\n }\n getViewLineNumberOfModelPosition(_deltaLineNumber, _inputColumn) {\n throw new Error('Not supported');\n }\n normalizePosition(outputLineIndex, outputPosition, affinity) {\n throw new Error('Not supported');\n }\n getInjectedTextAt(_outputLineIndex, _outputColumn) {\n throw new Error('Not supported');\n }\n}\nHiddenModelLineProjection.INSTANCE = new HiddenModelLineProjection();\nconst _spaces = [''];\nfunction spaces(count) {\n if (count >= _spaces.length) {\n for (let i = 1; i <= count; i++) {\n _spaces[i] = _makeSpaces(i);\n }\n }\n return _spaces[count];\n}\nfunction _makeSpaces(count) {\n return 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 *--------------------------------------------------------------------------------------------*/\nimport * as arrays from '../../../base/common/arrays.js';\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nimport { IndentGuide, IndentGuideHorizontalLine } from '../textModelGuides.js';\nimport { ModelDecorationOptions } from '../model/textModel.js';\nimport { LineInjectedText } from '../textModelEvents.js';\nimport * as viewEvents from '../viewEvents.js';\nimport { createModelLineProjection } from './modelLineProjection.js';\nimport { ConstantTimePrefixSumComputer } from '../model/prefixSumComputer.js';\nimport { ViewLineData } from '../viewModel.js';\nexport class ViewModelLinesFromProjectedModel {\n constructor(editorId, model, domLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, fontInfo, tabSize, wrappingStrategy, wrappingColumn, wrappingIndent) {\n this._editorId = editorId;\n this.model = model;\n this._validModelVersionId = -1;\n this._domLineBreaksComputerFactory = domLineBreaksComputerFactory;\n this._monospaceLineBreaksComputerFactory = monospaceLineBreaksComputerFactory;\n this.fontInfo = fontInfo;\n this.tabSize = tabSize;\n this.wrappingStrategy = wrappingStrategy;\n this.wrappingColumn = wrappingColumn;\n this.wrappingIndent = wrappingIndent;\n this._constructLines(/*resetHiddenAreas*/ true, null);\n }\n dispose() {\n this.hiddenAreasDecorationIds = this.model.deltaDecorations(this.hiddenAreasDecorationIds, []);\n }\n createCoordinatesConverter() {\n return new CoordinatesConverter(this);\n }\n _constructLines(resetHiddenAreas, previousLineBreaks) {\n this.modelLineProjections = [];\n if (resetHiddenAreas) {\n this.hiddenAreasDecorationIds = this.model.deltaDecorations(this.hiddenAreasDecorationIds, []);\n }\n const linesContent = this.model.getLinesContent();\n const injectedTextDecorations = this.model.getInjectedTextDecorations(this._editorId);\n const lineCount = linesContent.length;\n const lineBreaksComputer = this.createLineBreaksComputer();\n const injectedTextQueue = new arrays.ArrayQueue(LineInjectedText.fromDecorations(injectedTextDecorations));\n for (let i = 0; i < lineCount; i++) {\n const lineInjectedText = injectedTextQueue.takeWhile(t => t.lineNumber === i + 1);\n lineBreaksComputer.addRequest(linesContent[i], lineInjectedText, previousLineBreaks ? previousLineBreaks[i] : null);\n }\n const linesBreaks = lineBreaksComputer.finalize();\n const values = [];\n const hiddenAreas = this.hiddenAreasDecorationIds.map((areaId) => this.model.getDecorationRange(areaId)).sort(Range.compareRangesUsingStarts);\n let hiddenAreaStart = 1, hiddenAreaEnd = 0;\n let hiddenAreaIdx = -1;\n let nextLineNumberToUpdateHiddenArea = (hiddenAreaIdx + 1 < hiddenAreas.length) ? hiddenAreaEnd + 1 : lineCount + 2;\n for (let i = 0; i < lineCount; i++) {\n const lineNumber = i + 1;\n if (lineNumber === nextLineNumberToUpdateHiddenArea) {\n hiddenAreaIdx++;\n hiddenAreaStart = hiddenAreas[hiddenAreaIdx].startLineNumber;\n hiddenAreaEnd = hiddenAreas[hiddenAreaIdx].endLineNumber;\n nextLineNumberToUpdateHiddenArea = (hiddenAreaIdx + 1 < hiddenAreas.length) ? hiddenAreaEnd + 1 : lineCount + 2;\n }\n const isInHiddenArea = (lineNumber >= hiddenAreaStart && lineNumber <= hiddenAreaEnd);\n const line = createModelLineProjection(linesBreaks[i], !isInHiddenArea);\n values[i] = line.getViewLineCount();\n this.modelLineProjections[i] = line;\n }\n this._validModelVersionId = this.model.getVersionId();\n this.projectedModelLineLineCounts = new ConstantTimePrefixSumComputer(values);\n }\n getHiddenAreas() {\n return this.hiddenAreasDecorationIds.map((decId) => this.model.getDecorationRange(decId));\n }\n setHiddenAreas(_ranges) {\n const validatedRanges = _ranges.map(r => this.model.validateRange(r));\n const newRanges = normalizeLineRanges(validatedRanges);\n // TODO@Martin: Please stop calling this method on each model change!\n // This checks if there really was a change\n const oldRanges = this.hiddenAreasDecorationIds.map((areaId) => this.model.getDecorationRange(areaId)).sort(Range.compareRangesUsingStarts);\n if (newRanges.length === oldRanges.length) {\n let hasDifference = false;\n for (let i = 0; i < newRanges.length; i++) {\n if (!newRanges[i].equalsRange(oldRanges[i])) {\n hasDifference = true;\n break;\n }\n }\n if (!hasDifference) {\n return false;\n }\n }\n const newDecorations = newRanges.map((r) => ({\n range: r,\n options: ModelDecorationOptions.EMPTY,\n }));\n this.hiddenAreasDecorationIds = this.model.deltaDecorations(this.hiddenAreasDecorationIds, newDecorations);\n const hiddenAreas = newRanges;\n let hiddenAreaStart = 1, hiddenAreaEnd = 0;\n let hiddenAreaIdx = -1;\n let nextLineNumberToUpdateHiddenArea = (hiddenAreaIdx + 1 < hiddenAreas.length) ? hiddenAreaEnd + 1 : this.modelLineProjections.length + 2;\n let hasVisibleLine = false;\n for (let i = 0; i < this.modelLineProjections.length; i++) {\n const lineNumber = i + 1;\n if (lineNumber === nextLineNumberToUpdateHiddenArea) {\n hiddenAreaIdx++;\n hiddenAreaStart = hiddenAreas[hiddenAreaIdx].startLineNumber;\n hiddenAreaEnd = hiddenAreas[hiddenAreaIdx].endLineNumber;\n nextLineNumberToUpdateHiddenArea = (hiddenAreaIdx + 1 < hiddenAreas.length) ? hiddenAreaEnd + 1 : this.modelLineProjections.length + 2;\n }\n let lineChanged = false;\n if (lineNumber >= hiddenAreaStart && lineNumber <= hiddenAreaEnd) {\n // Line should be hidden\n if (this.modelLineProjections[i].isVisible()) {\n this.modelLineProjections[i] = this.modelLineProjections[i].setVisible(false);\n lineChanged = true;\n }\n }\n else {\n hasVisibleLine = true;\n // Line should be visible\n if (!this.modelLineProjections[i].isVisible()) {\n this.modelLineProjections[i] = this.modelLineProjections[i].setVisible(true);\n lineChanged = true;\n }\n }\n if (lineChanged) {\n const newOutputLineCount = this.modelLineProjections[i].getViewLineCount();\n this.projectedModelLineLineCounts.setValue(i, newOutputLineCount);\n }\n }\n if (!hasVisibleLine) {\n // Cannot have everything be hidden => reveal everything!\n this.setHiddenAreas([]);\n }\n return true;\n }\n modelPositionIsVisible(modelLineNumber, _modelColumn) {\n if (modelLineNumber < 1 || modelLineNumber > this.modelLineProjections.length) {\n // invalid arguments\n return false;\n }\n return this.modelLineProjections[modelLineNumber - 1].isVisible();\n }\n getModelLineViewLineCount(modelLineNumber) {\n if (modelLineNumber < 1 || modelLineNumber > this.modelLineProjections.length) {\n // invalid arguments\n return 1;\n }\n return this.modelLineProjections[modelLineNumber - 1].getViewLineCount();\n }\n setTabSize(newTabSize) {\n if (this.tabSize === newTabSize) {\n return false;\n }\n this.tabSize = newTabSize;\n this._constructLines(/*resetHiddenAreas*/ false, null);\n return true;\n }\n setWrappingSettings(fontInfo, wrappingStrategy, wrappingColumn, wrappingIndent) {\n const equalFontInfo = this.fontInfo.equals(fontInfo);\n const equalWrappingStrategy = (this.wrappingStrategy === wrappingStrategy);\n const equalWrappingColumn = (this.wrappingColumn === wrappingColumn);\n const equalWrappingIndent = (this.wrappingIndent === wrappingIndent);\n if (equalFontInfo && equalWrappingStrategy && equalWrappingColumn && equalWrappingIndent) {\n return false;\n }\n const onlyWrappingColumnChanged = (equalFontInfo && equalWrappingStrategy && !equalWrappingColumn && equalWrappingIndent);\n this.fontInfo = fontInfo;\n this.wrappingStrategy = wrappingStrategy;\n this.wrappingColumn = wrappingColumn;\n this.wrappingIndent = wrappingIndent;\n let previousLineBreaks = null;\n if (onlyWrappingColumnChanged) {\n previousLineBreaks = [];\n for (let i = 0, len = this.modelLineProjections.length; i < len; i++) {\n previousLineBreaks[i] = this.modelLineProjections[i].getProjectionData();\n }\n }\n this._constructLines(/*resetHiddenAreas*/ false, previousLineBreaks);\n return true;\n }\n createLineBreaksComputer() {\n const lineBreaksComputerFactory = (this.wrappingStrategy === 'advanced'\n ? this._domLineBreaksComputerFactory\n : this._monospaceLineBreaksComputerFactory);\n return lineBreaksComputerFactory.createLineBreaksComputer(this.fontInfo, this.tabSize, this.wrappingColumn, this.wrappingIndent);\n }\n onModelFlushed() {\n this._constructLines(/*resetHiddenAreas*/ true, null);\n }\n onModelLinesDeleted(versionId, fromLineNumber, toLineNumber) {\n if (!versionId || versionId <= this._validModelVersionId) {\n // Here we check for versionId in case the lines were reconstructed in the meantime.\n // We don't want to apply stale change events on top of a newer read model state.\n return null;\n }\n const outputFromLineNumber = (fromLineNumber === 1 ? 1 : this.projectedModelLineLineCounts.getPrefixSum(fromLineNumber - 1) + 1);\n const outputToLineNumber = this.projectedModelLineLineCounts.getPrefixSum(toLineNumber);\n this.modelLineProjections.splice(fromLineNumber - 1, toLineNumber - fromLineNumber + 1);\n this.projectedModelLineLineCounts.removeValues(fromLineNumber - 1, toLineNumber - fromLineNumber + 1);\n return new viewEvents.ViewLinesDeletedEvent(outputFromLineNumber, outputToLineNumber);\n }\n onModelLinesInserted(versionId, fromLineNumber, _toLineNumber, lineBreaks) {\n if (!versionId || versionId <= this._validModelVersionId) {\n // Here we check for versionId in case the lines were reconstructed in the meantime.\n // We don't want to apply stale change events on top of a newer read model state.\n return null;\n }\n // cannot use this.getHiddenAreas() because those decorations have already seen the effect of this model change\n const isInHiddenArea = (fromLineNumber > 2 && !this.modelLineProjections[fromLineNumber - 2].isVisible());\n const outputFromLineNumber = (fromLineNumber === 1 ? 1 : this.projectedModelLineLineCounts.getPrefixSum(fromLineNumber - 1) + 1);\n let totalOutputLineCount = 0;\n const insertLines = [];\n const insertPrefixSumValues = [];\n for (let i = 0, len = lineBreaks.length; i < len; i++) {\n const line = createModelLineProjection(lineBreaks[i], !isInHiddenArea);\n insertLines.push(line);\n const outputLineCount = line.getViewLineCount();\n totalOutputLineCount += outputLineCount;\n insertPrefixSumValues[i] = outputLineCount;\n }\n // TODO@Alex: use arrays.arrayInsert\n this.modelLineProjections =\n this.modelLineProjections.slice(0, fromLineNumber - 1)\n .concat(insertLines)\n .concat(this.modelLineProjections.slice(fromLineNumber - 1));\n this.projectedModelLineLineCounts.insertValues(fromLineNumber - 1, insertPrefixSumValues);\n return new viewEvents.ViewLinesInsertedEvent(outputFromLineNumber, outputFromLineNumber + totalOutputLineCount - 1);\n }\n onModelLineChanged(versionId, lineNumber, lineBreakData) {\n if (versionId !== null && versionId <= this._validModelVersionId) {\n // Here we check for versionId in case the lines were reconstructed in the meantime.\n // We don't want to apply stale change events on top of a newer read model state.\n return [false, null, null, null];\n }\n const lineIndex = lineNumber - 1;\n const oldOutputLineCount = this.modelLineProjections[lineIndex].getViewLineCount();\n const isVisible = this.modelLineProjections[lineIndex].isVisible();\n const line = createModelLineProjection(lineBreakData, isVisible);\n this.modelLineProjections[lineIndex] = line;\n const newOutputLineCount = this.modelLineProjections[lineIndex].getViewLineCount();\n let lineMappingChanged = false;\n let changeFrom = 0;\n let changeTo = -1;\n let insertFrom = 0;\n let insertTo = -1;\n let deleteFrom = 0;\n let deleteTo = -1;\n if (oldOutputLineCount > newOutputLineCount) {\n changeFrom = this.projectedModelLineLineCounts.getPrefixSum(lineNumber - 1) + 1;\n changeTo = changeFrom + newOutputLineCount - 1;\n deleteFrom = changeTo + 1;\n deleteTo = deleteFrom + (oldOutputLineCount - newOutputLineCount) - 1;\n lineMappingChanged = true;\n }\n else if (oldOutputLineCount < newOutputLineCount) {\n changeFrom = this.projectedModelLineLineCounts.getPrefixSum(lineNumber - 1) + 1;\n changeTo = changeFrom + oldOutputLineCount - 1;\n insertFrom = changeTo + 1;\n insertTo = insertFrom + (newOutputLineCount - oldOutputLineCount) - 1;\n lineMappingChanged = true;\n }\n else {\n changeFrom = this.projectedModelLineLineCounts.getPrefixSum(lineNumber - 1) + 1;\n changeTo = changeFrom + newOutputLineCount - 1;\n }\n this.projectedModelLineLineCounts.setValue(lineIndex, newOutputLineCount);\n const viewLinesChangedEvent = (changeFrom <= changeTo ? new viewEvents.ViewLinesChangedEvent(changeFrom, changeTo - changeFrom + 1) : null);\n const viewLinesInsertedEvent = (insertFrom <= insertTo ? new viewEvents.ViewLinesInsertedEvent(insertFrom, insertTo) : null);\n const viewLinesDeletedEvent = (deleteFrom <= deleteTo ? new viewEvents.ViewLinesDeletedEvent(deleteFrom, deleteTo) : null);\n return [lineMappingChanged, viewLinesChangedEvent, viewLinesInsertedEvent, viewLinesDeletedEvent];\n }\n acceptVersionId(versionId) {\n this._validModelVersionId = versionId;\n if (this.modelLineProjections.length === 1 && !this.modelLineProjections[0].isVisible()) {\n // At least one line must be visible => reset hidden areas\n this.setHiddenAreas([]);\n }\n }\n getViewLineCount() {\n return this.projectedModelLineLineCounts.getTotalSum();\n }\n _toValidViewLineNumber(viewLineNumber) {\n if (viewLineNumber < 1) {\n return 1;\n }\n const viewLineCount = this.getViewLineCount();\n if (viewLineNumber > viewLineCount) {\n return viewLineCount;\n }\n return viewLineNumber | 0;\n }\n getActiveIndentGuide(viewLineNumber, minLineNumber, maxLineNumber) {\n viewLineNumber = this._toValidViewLineNumber(viewLineNumber);\n minLineNumber = this._toValidViewLineNumber(minLineNumber);\n maxLineNumber = this._toValidViewLineNumber(maxLineNumber);\n const modelPosition = this.convertViewPositionToModelPosition(viewLineNumber, this.getViewLineMinColumn(viewLineNumber));\n const modelMinPosition = this.convertViewPositionToModelPosition(minLineNumber, this.getViewLineMinColumn(minLineNumber));\n const modelMaxPosition = this.convertViewPositionToModelPosition(maxLineNumber, this.getViewLineMinColumn(maxLineNumber));\n const result = this.model.guides.getActiveIndentGuide(modelPosition.lineNumber, modelMinPosition.lineNumber, modelMaxPosition.lineNumber);\n const viewStartPosition = this.convertModelPositionToViewPosition(result.startLineNumber, 1);\n const viewEndPosition = this.convertModelPositionToViewPosition(result.endLineNumber, this.model.getLineMaxColumn(result.endLineNumber));\n return {\n startLineNumber: viewStartPosition.lineNumber,\n endLineNumber: viewEndPosition.lineNumber,\n indent: result.indent\n };\n }\n // #region ViewLineInfo\n getViewLineInfo(viewLineNumber) {\n viewLineNumber = this._toValidViewLineNumber(viewLineNumber);\n const r = this.projectedModelLineLineCounts.getIndexOf(viewLineNumber - 1);\n const lineIndex = r.index;\n const remainder = r.remainder;\n return new ViewLineInfo(lineIndex + 1, remainder);\n }\n getMinColumnOfViewLine(viewLineInfo) {\n return this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewLineMinColumn(this.model, viewLineInfo.modelLineNumber, viewLineInfo.modelLineWrappedLineIdx);\n }\n getMaxColumnOfViewLine(viewLineInfo) {\n return this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewLineMaxColumn(this.model, viewLineInfo.modelLineNumber, viewLineInfo.modelLineWrappedLineIdx);\n }\n getModelStartPositionOfViewLine(viewLineInfo) {\n const line = this.modelLineProjections[viewLineInfo.modelLineNumber - 1];\n const minViewColumn = line.getViewLineMinColumn(this.model, viewLineInfo.modelLineNumber, viewLineInfo.modelLineWrappedLineIdx);\n const column = line.getModelColumnOfViewPosition(viewLineInfo.modelLineWrappedLineIdx, minViewColumn);\n return new Position(viewLineInfo.modelLineNumber, column);\n }\n getModelEndPositionOfViewLine(viewLineInfo) {\n const line = this.modelLineProjections[viewLineInfo.modelLineNumber - 1];\n const maxViewColumn = line.getViewLineMaxColumn(this.model, viewLineInfo.modelLineNumber, viewLineInfo.modelLineWrappedLineIdx);\n const column = line.getModelColumnOfViewPosition(viewLineInfo.modelLineWrappedLineIdx, maxViewColumn);\n return new Position(viewLineInfo.modelLineNumber, column);\n }\n getViewLineInfosGroupedByModelRanges(viewStartLineNumber, viewEndLineNumber) {\n const startViewLine = this.getViewLineInfo(viewStartLineNumber);\n const endViewLine = this.getViewLineInfo(viewEndLineNumber);\n const result = new Array();\n let lastVisibleModelPos = this.getModelStartPositionOfViewLine(startViewLine);\n let viewLines = new Array();\n for (let curModelLine = startViewLine.modelLineNumber; curModelLine <= endViewLine.modelLineNumber; curModelLine++) {\n const line = this.modelLineProjections[curModelLine - 1];\n if (line.isVisible()) {\n const startOffset = curModelLine === startViewLine.modelLineNumber\n ? startViewLine.modelLineWrappedLineIdx\n : 0;\n const endOffset = curModelLine === endViewLine.modelLineNumber\n ? endViewLine.modelLineWrappedLineIdx + 1\n : line.getViewLineCount();\n for (let i = startOffset; i < endOffset; i++) {\n viewLines.push(new ViewLineInfo(curModelLine, i));\n }\n }\n if (!line.isVisible() && lastVisibleModelPos) {\n const lastVisibleModelPos2 = new Position(curModelLine - 1, this.model.getLineMaxColumn(curModelLine - 1) + 1);\n const modelRange = Range.fromPositions(lastVisibleModelPos, lastVisibleModelPos2);\n result.push(new ViewLineInfoGroupedByModelRange(modelRange, viewLines));\n viewLines = [];\n lastVisibleModelPos = null;\n }\n else if (line.isVisible() && !lastVisibleModelPos) {\n lastVisibleModelPos = new Position(curModelLine, 1);\n }\n }\n if (lastVisibleModelPos) {\n const modelRange = Range.fromPositions(lastVisibleModelPos, this.getModelEndPositionOfViewLine(endViewLine));\n result.push(new ViewLineInfoGroupedByModelRange(modelRange, viewLines));\n }\n return result;\n }\n // #endregion\n getViewLinesBracketGuides(viewStartLineNumber, viewEndLineNumber, activeViewPosition, options) {\n const modelActivePosition = activeViewPosition ? this.convertViewPositionToModelPosition(activeViewPosition.lineNumber, activeViewPosition.column) : null;\n const resultPerViewLine = [];\n for (const group of this.getViewLineInfosGroupedByModelRanges(viewStartLineNumber, viewEndLineNumber)) {\n const modelRangeStartLineNumber = group.modelRange.startLineNumber;\n const bracketGuidesPerModelLine = this.model.guides.getLinesBracketGuides(modelRangeStartLineNumber, group.modelRange.endLineNumber, modelActivePosition, options);\n for (const viewLineInfo of group.viewLines) {\n const bracketGuides = bracketGuidesPerModelLine[viewLineInfo.modelLineNumber - modelRangeStartLineNumber];\n // visibleColumns stay as they are (this is a bug and needs to be fixed, but it is not a regression)\n // model-columns must be converted to view-model columns.\n const result = bracketGuides.map(g => {\n if (g.forWrappedLinesAfterColumn !== -1) {\n const p = this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewPositionOfModelPosition(0, g.forWrappedLinesAfterColumn);\n if (p.lineNumber >= viewLineInfo.modelLineWrappedLineIdx) {\n return undefined;\n }\n }\n if (g.forWrappedLinesBeforeOrAtColumn !== -1) {\n const p = this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewPositionOfModelPosition(0, g.forWrappedLinesBeforeOrAtColumn);\n if (p.lineNumber < viewLineInfo.modelLineWrappedLineIdx) {\n return undefined;\n }\n }\n if (!g.horizontalLine) {\n return g;\n }\n let column = -1;\n if (g.column !== -1) {\n const p = this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewPositionOfModelPosition(0, g.column);\n if (p.lineNumber === viewLineInfo.modelLineWrappedLineIdx) {\n column = p.column;\n }\n else if (p.lineNumber < viewLineInfo.modelLineWrappedLineIdx) {\n column = this.getMinColumnOfViewLine(viewLineInfo);\n }\n else if (p.lineNumber > viewLineInfo.modelLineWrappedLineIdx) {\n return undefined;\n }\n }\n const viewPosition = this.convertModelPositionToViewPosition(viewLineInfo.modelLineNumber, g.horizontalLine.endColumn);\n const p = this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewPositionOfModelPosition(0, g.horizontalLine.endColumn);\n if (p.lineNumber === viewLineInfo.modelLineWrappedLineIdx) {\n return new IndentGuide(g.visibleColumn, column, g.className, new IndentGuideHorizontalLine(g.horizontalLine.top, viewPosition.column), -1, -1);\n }\n else if (p.lineNumber < viewLineInfo.modelLineWrappedLineIdx) {\n return undefined;\n }\n else {\n if (g.visibleColumn !== -1) {\n // Don't repeat horizontal lines that use visibleColumn for unrelated lines.\n return undefined;\n }\n return new IndentGuide(g.visibleColumn, column, g.className, new IndentGuideHorizontalLine(g.horizontalLine.top, this.getMaxColumnOfViewLine(viewLineInfo)), -1, -1);\n }\n });\n resultPerViewLine.push(result.filter((r) => !!r));\n }\n }\n return resultPerViewLine;\n }\n getViewLinesIndentGuides(viewStartLineNumber, viewEndLineNumber) {\n // TODO: Use the same code as in `getViewLinesBracketGuides`.\n // Future TODO: Merge with `getViewLinesBracketGuides`.\n // However, this requires more refactoring of indent guides.\n viewStartLineNumber = this._toValidViewLineNumber(viewStartLineNumber);\n viewEndLineNumber = this._toValidViewLineNumber(viewEndLineNumber);\n const modelStart = this.convertViewPositionToModelPosition(viewStartLineNumber, this.getViewLineMinColumn(viewStartLineNumber));\n const modelEnd = this.convertViewPositionToModelPosition(viewEndLineNumber, this.getViewLineMaxColumn(viewEndLineNumber));\n let result = [];\n const resultRepeatCount = [];\n const resultRepeatOption = [];\n const modelStartLineIndex = modelStart.lineNumber - 1;\n const modelEndLineIndex = modelEnd.lineNumber - 1;\n let reqStart = null;\n for (let modelLineIndex = modelStartLineIndex; modelLineIndex <= modelEndLineIndex; modelLineIndex++) {\n const line = this.modelLineProjections[modelLineIndex];\n if (line.isVisible()) {\n const viewLineStartIndex = line.getViewLineNumberOfModelPosition(0, modelLineIndex === modelStartLineIndex ? modelStart.column : 1);\n const viewLineEndIndex = line.getViewLineNumberOfModelPosition(0, this.model.getLineMaxColumn(modelLineIndex + 1));\n const count = viewLineEndIndex - viewLineStartIndex + 1;\n let option = 0 /* IndentGuideRepeatOption.BlockNone */;\n if (count > 1 && line.getViewLineMinColumn(this.model, modelLineIndex + 1, viewLineEndIndex) === 1) {\n // wrapped lines should block indent guides\n option = (viewLineStartIndex === 0 ? 1 /* IndentGuideRepeatOption.BlockSubsequent */ : 2 /* IndentGuideRepeatOption.BlockAll */);\n }\n resultRepeatCount.push(count);\n resultRepeatOption.push(option);\n // merge into previous request\n if (reqStart === null) {\n reqStart = new Position(modelLineIndex + 1, 0);\n }\n }\n else {\n // hit invisible line => flush request\n if (reqStart !== null) {\n result = result.concat(this.model.guides.getLinesIndentGuides(reqStart.lineNumber, modelLineIndex));\n reqStart = null;\n }\n }\n }\n if (reqStart !== null) {\n result = result.concat(this.model.guides.getLinesIndentGuides(reqStart.lineNumber, modelEnd.lineNumber));\n reqStart = null;\n }\n const viewLineCount = viewEndLineNumber - viewStartLineNumber + 1;\n const viewIndents = new Array(viewLineCount);\n let currIndex = 0;\n for (let i = 0, len = result.length; i < len; i++) {\n let value = result[i];\n const count = Math.min(viewLineCount - currIndex, resultRepeatCount[i]);\n const option = resultRepeatOption[i];\n let blockAtIndex;\n if (option === 2 /* IndentGuideRepeatOption.BlockAll */) {\n blockAtIndex = 0;\n }\n else if (option === 1 /* IndentGuideRepeatOption.BlockSubsequent */) {\n blockAtIndex = 1;\n }\n else {\n blockAtIndex = count;\n }\n for (let j = 0; j < count; j++) {\n if (j === blockAtIndex) {\n value = 0;\n }\n viewIndents[currIndex++] = value;\n }\n }\n return viewIndents;\n }\n getViewLineContent(viewLineNumber) {\n const info = this.getViewLineInfo(viewLineNumber);\n return this.modelLineProjections[info.modelLineNumber - 1].getViewLineContent(this.model, info.modelLineNumber, info.modelLineWrappedLineIdx);\n }\n getViewLineLength(viewLineNumber) {\n const info = this.getViewLineInfo(viewLineNumber);\n return this.modelLineProjections[info.modelLineNumber - 1].getViewLineLength(this.model, info.modelLineNumber, info.modelLineWrappedLineIdx);\n }\n getViewLineMinColumn(viewLineNumber) {\n const info = this.getViewLineInfo(viewLineNumber);\n return this.modelLineProjections[info.modelLineNumber - 1].getViewLineMinColumn(this.model, info.modelLineNumber, info.modelLineWrappedLineIdx);\n }\n getViewLineMaxColumn(viewLineNumber) {\n const info = this.getViewLineInfo(viewLineNumber);\n return this.modelLineProjections[info.modelLineNumber - 1].getViewLineMaxColumn(this.model, info.modelLineNumber, info.modelLineWrappedLineIdx);\n }\n getViewLineData(viewLineNumber) {\n const info = this.getViewLineInfo(viewLineNumber);\n return this.modelLineProjections[info.modelLineNumber - 1].getViewLineData(this.model, info.modelLineNumber, info.modelLineWrappedLineIdx);\n }\n getViewLinesData(viewStartLineNumber, viewEndLineNumber, needed) {\n viewStartLineNumber = this._toValidViewLineNumber(viewStartLineNumber);\n viewEndLineNumber = this._toValidViewLineNumber(viewEndLineNumber);\n const start = this.projectedModelLineLineCounts.getIndexOf(viewStartLineNumber - 1);\n let viewLineNumber = viewStartLineNumber;\n const startModelLineIndex = start.index;\n const startRemainder = start.remainder;\n const result = [];\n for (let modelLineIndex = startModelLineIndex, len = this.model.getLineCount(); modelLineIndex < len; modelLineIndex++) {\n const line = this.modelLineProjections[modelLineIndex];\n if (!line.isVisible()) {\n continue;\n }\n const fromViewLineIndex = (modelLineIndex === startModelLineIndex ? startRemainder : 0);\n let remainingViewLineCount = line.getViewLineCount() - fromViewLineIndex;\n let lastLine = false;\n if (viewLineNumber + remainingViewLineCount > viewEndLineNumber) {\n lastLine = true;\n remainingViewLineCount = viewEndLineNumber - viewLineNumber + 1;\n }\n line.getViewLinesData(this.model, modelLineIndex + 1, fromViewLineIndex, remainingViewLineCount, viewLineNumber - viewStartLineNumber, needed, result);\n viewLineNumber += remainingViewLineCount;\n if (lastLine) {\n break;\n }\n }\n return result;\n }\n validateViewPosition(viewLineNumber, viewColumn, expectedModelPosition) {\n viewLineNumber = this._toValidViewLineNumber(viewLineNumber);\n const r = this.projectedModelLineLineCounts.getIndexOf(viewLineNumber - 1);\n const lineIndex = r.index;\n const remainder = r.remainder;\n const line = this.modelLineProjections[lineIndex];\n const minColumn = line.getViewLineMinColumn(this.model, lineIndex + 1, remainder);\n const maxColumn = line.getViewLineMaxColumn(this.model, lineIndex + 1, remainder);\n if (viewColumn < minColumn) {\n viewColumn = minColumn;\n }\n if (viewColumn > maxColumn) {\n viewColumn = maxColumn;\n }\n const computedModelColumn = line.getModelColumnOfViewPosition(remainder, viewColumn);\n const computedModelPosition = this.model.validatePosition(new Position(lineIndex + 1, computedModelColumn));\n if (computedModelPosition.equals(expectedModelPosition)) {\n return new Position(viewLineNumber, viewColumn);\n }\n return this.convertModelPositionToViewPosition(expectedModelPosition.lineNumber, expectedModelPosition.column);\n }\n validateViewRange(viewRange, expectedModelRange) {\n const validViewStart = this.validateViewPosition(viewRange.startLineNumber, viewRange.startColumn, expectedModelRange.getStartPosition());\n const validViewEnd = this.validateViewPosition(viewRange.endLineNumber, viewRange.endColumn, expectedModelRange.getEndPosition());\n return new Range(validViewStart.lineNumber, validViewStart.column, validViewEnd.lineNumber, validViewEnd.column);\n }\n convertViewPositionToModelPosition(viewLineNumber, viewColumn) {\n const info = this.getViewLineInfo(viewLineNumber);\n const inputColumn = this.modelLineProjections[info.modelLineNumber - 1].getModelColumnOfViewPosition(info.modelLineWrappedLineIdx, viewColumn);\n // console.log('out -> in ' + viewLineNumber + ',' + viewColumn + ' ===> ' + (lineIndex+1) + ',' + inputColumn);\n return this.model.validatePosition(new Position(info.modelLineNumber, inputColumn));\n }\n convertViewRangeToModelRange(viewRange) {\n const start = this.convertViewPositionToModelPosition(viewRange.startLineNumber, viewRange.startColumn);\n const end = this.convertViewPositionToModelPosition(viewRange.endLineNumber, viewRange.endColumn);\n return new Range(start.lineNumber, start.column, end.lineNumber, end.column);\n }\n convertModelPositionToViewPosition(_modelLineNumber, _modelColumn, affinity = 2 /* PositionAffinity.None */) {\n const validPosition = this.model.validatePosition(new Position(_modelLineNumber, _modelColumn));\n const inputLineNumber = validPosition.lineNumber;\n const inputColumn = validPosition.column;\n let lineIndex = inputLineNumber - 1, lineIndexChanged = false;\n while (lineIndex > 0 && !this.modelLineProjections[lineIndex].isVisible()) {\n lineIndex--;\n lineIndexChanged = true;\n }\n if (lineIndex === 0 && !this.modelLineProjections[lineIndex].isVisible()) {\n // Could not reach a real line\n // console.log('in -> out ' + inputLineNumber + ',' + inputColumn + ' ===> ' + 1 + ',' + 1);\n return new Position(1, 1);\n }\n const deltaLineNumber = 1 + this.projectedModelLineLineCounts.getPrefixSum(lineIndex);\n let r;\n if (lineIndexChanged) {\n r = this.modelLineProjections[lineIndex].getViewPositionOfModelPosition(deltaLineNumber, this.model.getLineMaxColumn(lineIndex + 1), affinity);\n }\n else {\n r = this.modelLineProjections[inputLineNumber - 1].getViewPositionOfModelPosition(deltaLineNumber, inputColumn, affinity);\n }\n // console.log('in -> out ' + inputLineNumber + ',' + inputColumn + ' ===> ' + r.lineNumber + ',' + r);\n return r;\n }\n /**\n * @param affinity The affinity in case of an empty range. Has no effect for non-empty ranges.\n */\n convertModelRangeToViewRange(modelRange, affinity = 0 /* PositionAffinity.Left */) {\n if (modelRange.isEmpty()) {\n const start = this.convertModelPositionToViewPosition(modelRange.startLineNumber, modelRange.startColumn, affinity);\n return Range.fromPositions(start);\n }\n else {\n const start = this.convertModelPositionToViewPosition(modelRange.startLineNumber, modelRange.startColumn, 1 /* PositionAffinity.Right */);\n const end = this.convertModelPositionToViewPosition(modelRange.endLineNumber, modelRange.endColumn, 0 /* PositionAffinity.Left */);\n return new Range(start.lineNumber, start.column, end.lineNumber, end.column);\n }\n }\n getViewLineNumberOfModelPosition(modelLineNumber, modelColumn) {\n let lineIndex = modelLineNumber - 1;\n if (this.modelLineProjections[lineIndex].isVisible()) {\n // this model line is visible\n const deltaLineNumber = 1 + this.projectedModelLineLineCounts.getPrefixSum(lineIndex);\n return this.modelLineProjections[lineIndex].getViewLineNumberOfModelPosition(deltaLineNumber, modelColumn);\n }\n // this model line is not visible\n while (lineIndex > 0 && !this.modelLineProjections[lineIndex].isVisible()) {\n lineIndex--;\n }\n if (lineIndex === 0 && !this.modelLineProjections[lineIndex].isVisible()) {\n // Could not reach a real line\n return 1;\n }\n const deltaLineNumber = 1 + this.projectedModelLineLineCounts.getPrefixSum(lineIndex);\n return this.modelLineProjections[lineIndex].getViewLineNumberOfModelPosition(deltaLineNumber, this.model.getLineMaxColumn(lineIndex + 1));\n }\n getDecorationsInRange(range, ownerId, filterOutValidation) {\n const modelStart = this.convertViewPositionToModelPosition(range.startLineNumber, range.startColumn);\n const modelEnd = this.convertViewPositionToModelPosition(range.endLineNumber, range.endColumn);\n if (modelEnd.lineNumber - modelStart.lineNumber <= range.endLineNumber - range.startLineNumber) {\n // most likely there are no hidden lines => fast path\n // fetch decorations from column 1 to cover the case of wrapped lines that have whole line decorations at column 1\n return this.model.getDecorationsInRange(new Range(modelStart.lineNumber, 1, modelEnd.lineNumber, modelEnd.column), ownerId, filterOutValidation);\n }\n let result = [];\n const modelStartLineIndex = modelStart.lineNumber - 1;\n const modelEndLineIndex = modelEnd.lineNumber - 1;\n let reqStart = null;\n for (let modelLineIndex = modelStartLineIndex; modelLineIndex <= modelEndLineIndex; modelLineIndex++) {\n const line = this.modelLineProjections[modelLineIndex];\n if (line.isVisible()) {\n // merge into previous request\n if (reqStart === null) {\n reqStart = new Position(modelLineIndex + 1, modelLineIndex === modelStartLineIndex ? modelStart.column : 1);\n }\n }\n else {\n // hit invisible line => flush request\n if (reqStart !== null) {\n const maxLineColumn = this.model.getLineMaxColumn(modelLineIndex);\n result = result.concat(this.model.getDecorationsInRange(new Range(reqStart.lineNumber, reqStart.column, modelLineIndex, maxLineColumn), ownerId, filterOutValidation));\n reqStart = null;\n }\n }\n }\n if (reqStart !== null) {\n result = result.concat(this.model.getDecorationsInRange(new Range(reqStart.lineNumber, reqStart.column, modelEnd.lineNumber, modelEnd.column), ownerId, filterOutValidation));\n reqStart = null;\n }\n result.sort((a, b) => {\n const res = Range.compareRangesUsingStarts(a.range, b.range);\n if (res === 0) {\n if (a.id < b.id) {\n return -1;\n }\n if (a.id > b.id) {\n return 1;\n }\n return 0;\n }\n return res;\n });\n // Eliminate duplicate decorations that might have intersected our visible ranges multiple times\n const finalResult = [];\n let finalResultLen = 0;\n let prevDecId = null;\n for (const dec of result) {\n const decId = dec.id;\n if (prevDecId === decId) {\n // skip\n continue;\n }\n prevDecId = decId;\n finalResult[finalResultLen++] = dec;\n }\n return finalResult;\n }\n getInjectedTextAt(position) {\n const info = this.getViewLineInfo(position.lineNumber);\n return this.modelLineProjections[info.modelLineNumber - 1].getInjectedTextAt(info.modelLineWrappedLineIdx, position.column);\n }\n normalizePosition(position, affinity) {\n const info = this.getViewLineInfo(position.lineNumber);\n return this.modelLineProjections[info.modelLineNumber - 1].normalizePosition(info.modelLineWrappedLineIdx, position, affinity);\n }\n getLineIndentColumn(lineNumber) {\n const info = this.getViewLineInfo(lineNumber);\n if (info.modelLineWrappedLineIdx === 0) {\n return this.model.getLineIndentColumn(info.modelLineNumber);\n }\n // wrapped lines have no indentation.\n // We deliberately don't handle the case that indentation is wrapped\n // to avoid two view lines reporting indentation for the very same model line.\n return 0;\n }\n}\n/**\n * Overlapping unsorted ranges:\n * [ ) [ ) [ )\n * [ ) [ )\n * ->\n * Non overlapping sorted ranges:\n * [ ) [ ) [ )\n *\n * Note: This function only considers line information! Columns are ignored.\n*/\nfunction normalizeLineRanges(ranges) {\n if (ranges.length === 0) {\n return [];\n }\n const sortedRanges = ranges.slice();\n sortedRanges.sort(Range.compareRangesUsingStarts);\n const result = [];\n let currentRangeStart = sortedRanges[0].startLineNumber;\n let currentRangeEnd = sortedRanges[0].endLineNumber;\n for (let i = 1, len = sortedRanges.length; i < len; i++) {\n const range = sortedRanges[i];\n if (range.startLineNumber > currentRangeEnd + 1) {\n result.push(new Range(currentRangeStart, 1, currentRangeEnd, 1));\n currentRangeStart = range.startLineNumber;\n currentRangeEnd = range.endLineNumber;\n }\n else if (range.endLineNumber > currentRangeEnd) {\n currentRangeEnd = range.endLineNumber;\n }\n }\n result.push(new Range(currentRangeStart, 1, currentRangeEnd, 1));\n return result;\n}\n/**\n * Represents a view line. Can be used to efficiently query more information about it.\n */\nclass ViewLineInfo {\n constructor(modelLineNumber, modelLineWrappedLineIdx) {\n this.modelLineNumber = modelLineNumber;\n this.modelLineWrappedLineIdx = modelLineWrappedLineIdx;\n }\n}\n/**\n * A list of view lines that have a contiguous span in the model.\n*/\nclass ViewLineInfoGroupedByModelRange {\n constructor(modelRange, viewLines) {\n this.modelRange = modelRange;\n this.viewLines = viewLines;\n }\n}\nclass CoordinatesConverter {\n constructor(lines) {\n this._lines = lines;\n }\n // View -> Model conversion and related methods\n convertViewPositionToModelPosition(viewPosition) {\n return this._lines.convertViewPositionToModelPosition(viewPosition.lineNumber, viewPosition.column);\n }\n convertViewRangeToModelRange(viewRange) {\n return this._lines.convertViewRangeToModelRange(viewRange);\n }\n validateViewPosition(viewPosition, expectedModelPosition) {\n return this._lines.validateViewPosition(viewPosition.lineNumber, viewPosition.column, expectedModelPosition);\n }\n validateViewRange(viewRange, expectedModelRange) {\n return this._lines.validateViewRange(viewRange, expectedModelRange);\n }\n // Model -> View conversion and related methods\n convertModelPositionToViewPosition(modelPosition, affinity) {\n return this._lines.convertModelPositionToViewPosition(modelPosition.lineNumber, modelPosition.column, affinity);\n }\n convertModelRangeToViewRange(modelRange, affinity) {\n return this._lines.convertModelRangeToViewRange(modelRange, affinity);\n }\n modelPositionIsVisible(modelPosition) {\n return this._lines.modelPositionIsVisible(modelPosition.lineNumber, modelPosition.column);\n }\n getModelLineViewLineCount(modelLineNumber) {\n return this._lines.getModelLineViewLineCount(modelLineNumber);\n }\n getViewLineNumberOfModelPosition(modelLineNumber, modelColumn) {\n return this._lines.getViewLineNumberOfModelPosition(modelLineNumber, modelColumn);\n }\n}\nexport class ViewModelLinesFromModelAsIs {\n constructor(model) {\n this.model = model;\n }\n dispose() {\n }\n createCoordinatesConverter() {\n return new IdentityCoordinatesConverter(this);\n }\n getHiddenAreas() {\n return [];\n }\n setHiddenAreas(_ranges) {\n return false;\n }\n setTabSize(_newTabSize) {\n return false;\n }\n setWrappingSettings(_fontInfo, _wrappingStrategy, _wrappingColumn, _wrappingIndent) {\n return false;\n }\n createLineBreaksComputer() {\n const result = [];\n return {\n addRequest: (lineText, injectedText, previousLineBreakData) => {\n result.push(null);\n },\n finalize: () => {\n return result;\n }\n };\n }\n onModelFlushed() {\n }\n onModelLinesDeleted(_versionId, fromLineNumber, toLineNumber) {\n return new viewEvents.ViewLinesDeletedEvent(fromLineNumber, toLineNumber);\n }\n onModelLinesInserted(_versionId, fromLineNumber, toLineNumber, lineBreaks) {\n return new viewEvents.ViewLinesInsertedEvent(fromLineNumber, toLineNumber);\n }\n onModelLineChanged(_versionId, lineNumber, lineBreakData) {\n return [false, new viewEvents.ViewLinesChangedEvent(lineNumber, 1), null, null];\n }\n acceptVersionId(_versionId) {\n }\n getViewLineCount() {\n return this.model.getLineCount();\n }\n getActiveIndentGuide(viewLineNumber, _minLineNumber, _maxLineNumber) {\n return {\n startLineNumber: viewLineNumber,\n endLineNumber: viewLineNumber,\n indent: 0\n };\n }\n getViewLinesBracketGuides(startLineNumber, endLineNumber, activePosition) {\n return new Array(endLineNumber - startLineNumber + 1).fill([]);\n }\n getViewLinesIndentGuides(viewStartLineNumber, viewEndLineNumber) {\n const viewLineCount = viewEndLineNumber - viewStartLineNumber + 1;\n const result = new Array(viewLineCount);\n for (let i = 0; i < viewLineCount; i++) {\n result[i] = 0;\n }\n return result;\n }\n getViewLineContent(viewLineNumber) {\n return this.model.getLineContent(viewLineNumber);\n }\n getViewLineLength(viewLineNumber) {\n return this.model.getLineLength(viewLineNumber);\n }\n getViewLineMinColumn(viewLineNumber) {\n return this.model.getLineMinColumn(viewLineNumber);\n }\n getViewLineMaxColumn(viewLineNumber) {\n return this.model.getLineMaxColumn(viewLineNumber);\n }\n getViewLineData(viewLineNumber) {\n const lineTokens = this.model.tokenization.getLineTokens(viewLineNumber);\n const lineContent = lineTokens.getLineContent();\n return new ViewLineData(lineContent, false, 1, lineContent.length + 1, 0, lineTokens.inflate(), null);\n }\n getViewLinesData(viewStartLineNumber, viewEndLineNumber, needed) {\n const lineCount = this.model.getLineCount();\n viewStartLineNumber = Math.min(Math.max(1, viewStartLineNumber), lineCount);\n viewEndLineNumber = Math.min(Math.max(1, viewEndLineNumber), lineCount);\n const result = [];\n for (let lineNumber = viewStartLineNumber; lineNumber <= viewEndLineNumber; lineNumber++) {\n const idx = lineNumber - viewStartLineNumber;\n result[idx] = needed[idx] ? this.getViewLineData(lineNumber) : null;\n }\n return result;\n }\n getDecorationsInRange(range, ownerId, filterOutValidation) {\n return this.model.getDecorationsInRange(range, ownerId, filterOutValidation);\n }\n normalizePosition(position, affinity) {\n return this.model.normalizePosition(position, affinity);\n }\n getLineIndentColumn(lineNumber) {\n return this.model.getLineIndentColumn(lineNumber);\n }\n getInjectedTextAt(position) {\n // Identity lines collection does not support injected text.\n return null;\n }\n}\nclass IdentityCoordinatesConverter {\n constructor(lines) {\n this._lines = lines;\n }\n _validPosition(pos) {\n return this._lines.model.validatePosition(pos);\n }\n _validRange(range) {\n return this._lines.model.validateRange(range);\n }\n // View -> Model conversion and related methods\n convertViewPositionToModelPosition(viewPosition) {\n return this._validPosition(viewPosition);\n }\n convertViewRangeToModelRange(viewRange) {\n return this._validRange(viewRange);\n }\n validateViewPosition(_viewPosition, expectedModelPosition) {\n return this._validPosition(expectedModelPosition);\n }\n validateViewRange(_viewRange, expectedModelRange) {\n return this._validRange(expectedModelRange);\n }\n // Model -> View conversion and related methods\n convertModelPositionToViewPosition(modelPosition) {\n return this._validPosition(modelPosition);\n }\n convertModelRangeToViewRange(modelRange) {\n return this._validRange(modelRange);\n }\n modelPositionIsVisible(modelPosition) {\n const lineCount = this._lines.model.getLineCount();\n if (modelPosition.lineNumber < 1 || modelPosition.lineNumber > lineCount) {\n // invalid arguments\n return false;\n }\n return true;\n }\n getModelLineViewLineCount(modelLineNumber) {\n return 1;\n }\n getViewLineNumberOfModelPosition(modelLineNumber, modelColumn) {\n return modelLineNumber;\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 *--------------------------------------------------------------------------------------------*/\nimport { ArrayQueue } from '../../../base/common/arrays.js';\nimport { RunOnceScheduler } from '../../../base/common/async.js';\nimport { Color } from '../../../base/common/color.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport * as platform from '../../../base/common/platform.js';\nimport * as strings from '../../../base/common/strings.js';\nimport { EDITOR_FONT_DEFAULTS, filterValidationDecorations } from '../config/editorOptions.js';\nimport { CursorsController } from '../cursor/cursor.js';\nimport { CursorConfiguration } from '../cursorCommon.js';\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nimport * as textModelEvents from '../textModelEvents.js';\nimport { TokenizationRegistry } from '../languages.js';\nimport { PLAINTEXT_LANGUAGE_ID } from '../languages/modesRegistry.js';\nimport { tokenizeLineToHTML } from '../languages/textToHtmlTokenizer.js';\nimport * as viewEvents from '../viewEvents.js';\nimport { ViewLayout } from '../viewLayout/viewLayout.js';\nimport { MinimapTokensColorTracker } from './minimapTokensColorTracker.js';\nimport { MinimapLinesRenderingData, OverviewRulerDecorationsGroup, ViewLineRenderingData } from '../viewModel.js';\nimport { ViewModelDecorations } from './viewModelDecorations.js';\nimport { FocusChangedEvent, HiddenAreasChangedEvent, ModelContentChangedEvent, ModelDecorationsChangedEvent, ModelLanguageChangedEvent, ModelLanguageConfigurationChangedEvent, ModelOptionsChangedEvent, ModelTokensChangedEvent, ReadOnlyEditAttemptEvent, ScrollChangedEvent, ViewModelEventDispatcher, ViewZonesChangedEvent } from '../viewModelEventDispatcher.js';\nimport { ViewModelLinesFromModelAsIs, ViewModelLinesFromProjectedModel } from './viewModelLines.js';\nconst USE_IDENTITY_LINES_COLLECTION = true;\nexport class ViewModel extends Disposable {\n constructor(editorId, configuration, model, domLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, scheduleAtNextAnimationFrame, languageConfigurationService, _themeService) {\n super();\n this.languageConfigurationService = languageConfigurationService;\n this._themeService = _themeService;\n this._editorId = editorId;\n this._configuration = configuration;\n this.model = model;\n this._eventDispatcher = new ViewModelEventDispatcher();\n this.onEvent = this._eventDispatcher.onEvent;\n this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService);\n this._tokenizeViewportSoon = this._register(new RunOnceScheduler(() => this.tokenizeViewport(), 50));\n this._updateConfigurationViewLineCount = this._register(new RunOnceScheduler(() => this._updateConfigurationViewLineCountNow(), 0));\n this._hasFocus = false;\n this._viewportStart = ViewportStart.create(this.model);\n if (USE_IDENTITY_LINES_COLLECTION && this.model.isTooLargeForTokenization()) {\n this._lines = new ViewModelLinesFromModelAsIs(this.model);\n }\n else {\n const options = this._configuration.options;\n const fontInfo = options.get(46 /* EditorOption.fontInfo */);\n const wrappingStrategy = options.get(127 /* EditorOption.wrappingStrategy */);\n const wrappingInfo = options.get(134 /* EditorOption.wrappingInfo */);\n const wrappingIndent = options.get(126 /* EditorOption.wrappingIndent */);\n this._lines = new ViewModelLinesFromProjectedModel(this._editorId, this.model, domLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, fontInfo, this.model.getOptions().tabSize, wrappingStrategy, wrappingInfo.wrappingColumn, wrappingIndent);\n }\n this.coordinatesConverter = this._lines.createCoordinatesConverter();\n this._cursor = this._register(new CursorsController(model, this, this.coordinatesConverter, this.cursorConfig));\n this.viewLayout = this._register(new ViewLayout(this._configuration, this.getLineCount(), scheduleAtNextAnimationFrame));\n this._register(this.viewLayout.onDidScroll((e) => {\n if (e.scrollTopChanged) {\n this._tokenizeViewportSoon.schedule();\n }\n if (e.scrollTopChanged) {\n this._viewportStart.invalidate();\n }\n this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewScrollChangedEvent(e));\n this._eventDispatcher.emitOutgoingEvent(new ScrollChangedEvent(e.oldScrollWidth, e.oldScrollLeft, e.oldScrollHeight, e.oldScrollTop, e.scrollWidth, e.scrollLeft, e.scrollHeight, e.scrollTop));\n }));\n this._register(this.viewLayout.onDidContentSizeChange((e) => {\n this._eventDispatcher.emitOutgoingEvent(e);\n }));\n this._decorations = new ViewModelDecorations(this._editorId, this.model, this._configuration, this._lines, this.coordinatesConverter);\n this._registerModelEvents();\n this._register(this._configuration.onDidChangeFast((e) => {\n try {\n const eventsCollector = this._eventDispatcher.beginEmitViewEvents();\n this._onConfigurationChanged(eventsCollector, e);\n }\n finally {\n this._eventDispatcher.endEmitViewEvents();\n }\n }));\n this._register(MinimapTokensColorTracker.getInstance().onDidChange(() => {\n this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewTokensColorsChangedEvent());\n }));\n this._register(this._themeService.onDidColorThemeChange((theme) => {\n this._invalidateDecorationsColorCache();\n this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewThemeChangedEvent(theme));\n }));\n this._updateConfigurationViewLineCountNow();\n }\n dispose() {\n // First remove listeners, as disposing the lines might end up sending\n // model decoration changed events ... and we no longer care about them ...\n super.dispose();\n this._decorations.dispose();\n this._lines.dispose();\n this._viewportStart.dispose();\n this._eventDispatcher.dispose();\n }\n createLineBreaksComputer() {\n return this._lines.createLineBreaksComputer();\n }\n addViewEventHandler(eventHandler) {\n this._eventDispatcher.addViewEventHandler(eventHandler);\n }\n removeViewEventHandler(eventHandler) {\n this._eventDispatcher.removeViewEventHandler(eventHandler);\n }\n _updateConfigurationViewLineCountNow() {\n this._configuration.setViewLineCount(this._lines.getViewLineCount());\n }\n tokenizeViewport() {\n const linesViewportData = this.viewLayout.getLinesViewportData();\n const viewVisibleRange = new Range(linesViewportData.startLineNumber, this.getLineMinColumn(linesViewportData.startLineNumber), linesViewportData.endLineNumber, this.getLineMaxColumn(linesViewportData.endLineNumber));\n const modelVisibleRanges = this._toModelVisibleRanges(viewVisibleRange);\n for (const modelVisibleRange of modelVisibleRanges) {\n this.model.tokenization.tokenizeViewport(modelVisibleRange.startLineNumber, modelVisibleRange.endLineNumber);\n }\n }\n setHasFocus(hasFocus) {\n this._hasFocus = hasFocus;\n this._cursor.setHasFocus(hasFocus);\n this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewFocusChangedEvent(hasFocus));\n this._eventDispatcher.emitOutgoingEvent(new FocusChangedEvent(!hasFocus, hasFocus));\n }\n onCompositionStart() {\n this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewCompositionStartEvent());\n }\n onCompositionEnd() {\n this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewCompositionEndEvent());\n }\n _onConfigurationChanged(eventsCollector, e) {\n // We might need to restore the current centered view range, so save it (if available)\n let previousViewportStartModelPosition = null;\n if (this._viewportStart.isValid) {\n const previousViewportStartViewPosition = new Position(this._viewportStart.viewLineNumber, this.getLineMinColumn(this._viewportStart.viewLineNumber));\n previousViewportStartModelPosition = this.coordinatesConverter.convertViewPositionToModelPosition(previousViewportStartViewPosition);\n }\n let restorePreviousViewportStart = false;\n const options = this._configuration.options;\n const fontInfo = options.get(46 /* EditorOption.fontInfo */);\n const wrappingStrategy = options.get(127 /* EditorOption.wrappingStrategy */);\n const wrappingInfo = options.get(134 /* EditorOption.wrappingInfo */);\n const wrappingIndent = options.get(126 /* EditorOption.wrappingIndent */);\n if (this._lines.setWrappingSettings(fontInfo, wrappingStrategy, wrappingInfo.wrappingColumn, wrappingIndent)) {\n eventsCollector.emitViewEvent(new viewEvents.ViewFlushedEvent());\n eventsCollector.emitViewEvent(new viewEvents.ViewLineMappingChangedEvent());\n eventsCollector.emitViewEvent(new viewEvents.ViewDecorationsChangedEvent(null));\n this._cursor.onLineMappingChanged(eventsCollector);\n this._decorations.onLineMappingChanged();\n this.viewLayout.onFlushed(this.getLineCount());\n if (this.viewLayout.getCurrentScrollTop() !== 0) {\n // Never change the scroll position from 0 to something else...\n restorePreviousViewportStart = true;\n }\n this._updateConfigurationViewLineCount.schedule();\n }\n if (e.hasChanged(83 /* EditorOption.readOnly */)) {\n // Must read again all decorations due to readOnly filtering\n this._decorations.reset();\n eventsCollector.emitViewEvent(new viewEvents.ViewDecorationsChangedEvent(null));\n }\n eventsCollector.emitViewEvent(new viewEvents.ViewConfigurationChangedEvent(e));\n this.viewLayout.onConfigurationChanged(e);\n if (restorePreviousViewportStart && previousViewportStartModelPosition) {\n const viewPosition = this.coordinatesConverter.convertModelPositionToViewPosition(previousViewportStartModelPosition);\n const viewPositionTop = this.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber);\n this.viewLayout.setScrollPosition({ scrollTop: viewPositionTop + this._viewportStart.startLineDelta }, 1 /* ScrollType.Immediate */);\n }\n if (CursorConfiguration.shouldRecreate(e)) {\n this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService);\n this._cursor.updateConfiguration(this.cursorConfig);\n }\n }\n _registerModelEvents() {\n this._register(this.model.onDidChangeContentOrInjectedText((e) => {\n try {\n const eventsCollector = this._eventDispatcher.beginEmitViewEvents();\n let hadOtherModelChange = false;\n let hadModelLineChangeThatChangedLineMapping = false;\n const changes = (e instanceof textModelEvents.InternalModelContentChangeEvent ? e.rawContentChangedEvent.changes : e.changes);\n const versionId = (e instanceof textModelEvents.InternalModelContentChangeEvent ? e.rawContentChangedEvent.versionId : null);\n // Do a first pass to compute line mappings, and a second pass to actually interpret them\n const lineBreaksComputer = this._lines.createLineBreaksComputer();\n for (const change of changes) {\n switch (change.changeType) {\n case 4 /* textModelEvents.RawContentChangedType.LinesInserted */: {\n for (let lineIdx = 0; lineIdx < change.detail.length; lineIdx++) {\n const line = change.detail[lineIdx];\n let injectedText = change.injectedTexts[lineIdx];\n if (injectedText) {\n injectedText = injectedText.filter(element => (!element.ownerId || element.ownerId === this._editorId));\n }\n lineBreaksComputer.addRequest(line, injectedText, null);\n }\n break;\n }\n case 2 /* textModelEvents.RawContentChangedType.LineChanged */: {\n let injectedText = null;\n if (change.injectedText) {\n injectedText = change.injectedText.filter(element => (!element.ownerId || element.ownerId === this._editorId));\n }\n lineBreaksComputer.addRequest(change.detail, injectedText, null);\n break;\n }\n }\n }\n const lineBreaks = lineBreaksComputer.finalize();\n const lineBreakQueue = new ArrayQueue(lineBreaks);\n for (const change of changes) {\n switch (change.changeType) {\n case 1 /* textModelEvents.RawContentChangedType.Flush */: {\n this._lines.onModelFlushed();\n eventsCollector.emitViewEvent(new viewEvents.ViewFlushedEvent());\n this._decorations.reset();\n this.viewLayout.onFlushed(this.getLineCount());\n hadOtherModelChange = true;\n break;\n }\n case 3 /* textModelEvents.RawContentChangedType.LinesDeleted */: {\n const linesDeletedEvent = this._lines.onModelLinesDeleted(versionId, change.fromLineNumber, change.toLineNumber);\n if (linesDeletedEvent !== null) {\n eventsCollector.emitViewEvent(linesDeletedEvent);\n this.viewLayout.onLinesDeleted(linesDeletedEvent.fromLineNumber, linesDeletedEvent.toLineNumber);\n }\n hadOtherModelChange = true;\n break;\n }\n case 4 /* textModelEvents.RawContentChangedType.LinesInserted */: {\n const insertedLineBreaks = lineBreakQueue.takeCount(change.detail.length);\n const linesInsertedEvent = this._lines.onModelLinesInserted(versionId, change.fromLineNumber, change.toLineNumber, insertedLineBreaks);\n if (linesInsertedEvent !== null) {\n eventsCollector.emitViewEvent(linesInsertedEvent);\n this.viewLayout.onLinesInserted(linesInsertedEvent.fromLineNumber, linesInsertedEvent.toLineNumber);\n }\n hadOtherModelChange = true;\n break;\n }\n case 2 /* textModelEvents.RawContentChangedType.LineChanged */: {\n const changedLineBreakData = lineBreakQueue.dequeue();\n const [lineMappingChanged, linesChangedEvent, linesInsertedEvent, linesDeletedEvent] = this._lines.onModelLineChanged(versionId, change.lineNumber, changedLineBreakData);\n hadModelLineChangeThatChangedLineMapping = lineMappingChanged;\n if (linesChangedEvent) {\n eventsCollector.emitViewEvent(linesChangedEvent);\n }\n if (linesInsertedEvent) {\n eventsCollector.emitViewEvent(linesInsertedEvent);\n this.viewLayout.onLinesInserted(linesInsertedEvent.fromLineNumber, linesInsertedEvent.toLineNumber);\n }\n if (linesDeletedEvent) {\n eventsCollector.emitViewEvent(linesDeletedEvent);\n this.viewLayout.onLinesDeleted(linesDeletedEvent.fromLineNumber, linesDeletedEvent.toLineNumber);\n }\n break;\n }\n case 5 /* textModelEvents.RawContentChangedType.EOLChanged */: {\n // Nothing to do. The new version will be accepted below\n break;\n }\n }\n }\n if (versionId !== null) {\n this._lines.acceptVersionId(versionId);\n }\n this.viewLayout.onHeightMaybeChanged();\n if (!hadOtherModelChange && hadModelLineChangeThatChangedLineMapping) {\n eventsCollector.emitViewEvent(new viewEvents.ViewLineMappingChangedEvent());\n eventsCollector.emitViewEvent(new viewEvents.ViewDecorationsChangedEvent(null));\n this._cursor.onLineMappingChanged(eventsCollector);\n this._decorations.onLineMappingChanged();\n }\n }\n finally {\n this._eventDispatcher.endEmitViewEvents();\n }\n // Update the configuration and reset the centered view line\n const viewportStartWasValid = this._viewportStart.isValid;\n this._viewportStart.invalidate();\n this._configuration.setModelLineCount(this.model.getLineCount());\n this._updateConfigurationViewLineCountNow();\n // Recover viewport\n if (!this._hasFocus && this.model.getAttachedEditorCount() >= 2 && viewportStartWasValid) {\n const modelRange = this.model._getTrackedRange(this._viewportStart.modelTrackedRange);\n if (modelRange) {\n const viewPosition = this.coordinatesConverter.convertModelPositionToViewPosition(modelRange.getStartPosition());\n const viewPositionTop = this.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber);\n this.viewLayout.setScrollPosition({ scrollTop: viewPositionTop + this._viewportStart.startLineDelta }, 1 /* ScrollType.Immediate */);\n }\n }\n try {\n const eventsCollector = this._eventDispatcher.beginEmitViewEvents();\n if (e instanceof textModelEvents.InternalModelContentChangeEvent) {\n eventsCollector.emitOutgoingEvent(new ModelContentChangedEvent(e.contentChangedEvent));\n }\n this._cursor.onModelContentChanged(eventsCollector, e);\n }\n finally {\n this._eventDispatcher.endEmitViewEvents();\n }\n this._tokenizeViewportSoon.schedule();\n }));\n this._register(this.model.onDidChangeTokens((e) => {\n const viewRanges = [];\n for (let j = 0, lenJ = e.ranges.length; j < lenJ; j++) {\n const modelRange = e.ranges[j];\n const viewStartLineNumber = this.coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.fromLineNumber, 1)).lineNumber;\n const viewEndLineNumber = this.coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.toLineNumber, this.model.getLineMaxColumn(modelRange.toLineNumber))).lineNumber;\n viewRanges[j] = {\n fromLineNumber: viewStartLineNumber,\n toLineNumber: viewEndLineNumber\n };\n }\n this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewTokensChangedEvent(viewRanges));\n if (e.tokenizationSupportChanged) {\n this._tokenizeViewportSoon.schedule();\n }\n this._eventDispatcher.emitOutgoingEvent(new ModelTokensChangedEvent(e));\n }));\n this._register(this.model.onDidChangeLanguageConfiguration((e) => {\n this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewLanguageConfigurationEvent());\n this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService);\n this._cursor.updateConfiguration(this.cursorConfig);\n this._eventDispatcher.emitOutgoingEvent(new ModelLanguageConfigurationChangedEvent(e));\n }));\n this._register(this.model.onDidChangeLanguage((e) => {\n this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService);\n this._cursor.updateConfiguration(this.cursorConfig);\n this._eventDispatcher.emitOutgoingEvent(new ModelLanguageChangedEvent(e));\n }));\n this._register(this.model.onDidChangeOptions((e) => {\n // A tab size change causes a line mapping changed event => all view parts will repaint OK, no further event needed here\n if (this._lines.setTabSize(this.model.getOptions().tabSize)) {\n try {\n const eventsCollector = this._eventDispatcher.beginEmitViewEvents();\n eventsCollector.emitViewEvent(new viewEvents.ViewFlushedEvent());\n eventsCollector.emitViewEvent(new viewEvents.ViewLineMappingChangedEvent());\n eventsCollector.emitViewEvent(new viewEvents.ViewDecorationsChangedEvent(null));\n this._cursor.onLineMappingChanged(eventsCollector);\n this._decorations.onLineMappingChanged();\n this.viewLayout.onFlushed(this.getLineCount());\n }\n finally {\n this._eventDispatcher.endEmitViewEvents();\n }\n this._updateConfigurationViewLineCount.schedule();\n }\n this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService);\n this._cursor.updateConfiguration(this.cursorConfig);\n this._eventDispatcher.emitOutgoingEvent(new ModelOptionsChangedEvent(e));\n }));\n this._register(this.model.onDidChangeDecorations((e) => {\n this._decorations.onModelDecorationsChanged();\n this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewDecorationsChangedEvent(e));\n this._eventDispatcher.emitOutgoingEvent(new ModelDecorationsChangedEvent(e));\n }));\n }\n setHiddenAreas(ranges) {\n let lineMappingChanged = false;\n try {\n const eventsCollector = this._eventDispatcher.beginEmitViewEvents();\n lineMappingChanged = this._lines.setHiddenAreas(ranges);\n if (lineMappingChanged) {\n eventsCollector.emitViewEvent(new viewEvents.ViewFlushedEvent());\n eventsCollector.emitViewEvent(new viewEvents.ViewLineMappingChangedEvent());\n eventsCollector.emitViewEvent(new viewEvents.ViewDecorationsChangedEvent(null));\n this._cursor.onLineMappingChanged(eventsCollector);\n this._decorations.onLineMappingChanged();\n this.viewLayout.onFlushed(this.getLineCount());\n this.viewLayout.onHeightMaybeChanged();\n }\n }\n finally {\n this._eventDispatcher.endEmitViewEvents();\n }\n this._updateConfigurationViewLineCount.schedule();\n if (lineMappingChanged) {\n this._eventDispatcher.emitOutgoingEvent(new HiddenAreasChangedEvent());\n }\n }\n getVisibleRangesPlusViewportAboveBelow() {\n const layoutInfo = this._configuration.options.get(133 /* EditorOption.layoutInfo */);\n const lineHeight = this._configuration.options.get(61 /* EditorOption.lineHeight */);\n const linesAround = Math.max(20, Math.round(layoutInfo.height / lineHeight));\n const partialData = this.viewLayout.getLinesViewportData();\n const startViewLineNumber = Math.max(1, partialData.completelyVisibleStartLineNumber - linesAround);\n const endViewLineNumber = Math.min(this.getLineCount(), partialData.completelyVisibleEndLineNumber + linesAround);\n return this._toModelVisibleRanges(new Range(startViewLineNumber, this.getLineMinColumn(startViewLineNumber), endViewLineNumber, this.getLineMaxColumn(endViewLineNumber)));\n }\n getVisibleRanges() {\n const visibleViewRange = this.getCompletelyVisibleViewRange();\n return this._toModelVisibleRanges(visibleViewRange);\n }\n getHiddenAreas() {\n return this._lines.getHiddenAreas();\n }\n _toModelVisibleRanges(visibleViewRange) {\n const visibleRange = this.coordinatesConverter.convertViewRangeToModelRange(visibleViewRange);\n const hiddenAreas = this._lines.getHiddenAreas();\n if (hiddenAreas.length === 0) {\n return [visibleRange];\n }\n const result = [];\n let resultLen = 0;\n let startLineNumber = visibleRange.startLineNumber;\n let startColumn = visibleRange.startColumn;\n const endLineNumber = visibleRange.endLineNumber;\n const endColumn = visibleRange.endColumn;\n for (let i = 0, len = hiddenAreas.length; i < len; i++) {\n const hiddenStartLineNumber = hiddenAreas[i].startLineNumber;\n const hiddenEndLineNumber = hiddenAreas[i].endLineNumber;\n if (hiddenEndLineNumber < startLineNumber) {\n continue;\n }\n if (hiddenStartLineNumber > endLineNumber) {\n continue;\n }\n if (startLineNumber < hiddenStartLineNumber) {\n result[resultLen++] = new Range(startLineNumber, startColumn, hiddenStartLineNumber - 1, this.model.getLineMaxColumn(hiddenStartLineNumber - 1));\n }\n startLineNumber = hiddenEndLineNumber + 1;\n startColumn = 1;\n }\n if (startLineNumber < endLineNumber || (startLineNumber === endLineNumber && startColumn < endColumn)) {\n result[resultLen++] = new Range(startLineNumber, startColumn, endLineNumber, endColumn);\n }\n return result;\n }\n getCompletelyVisibleViewRange() {\n const partialData = this.viewLayout.getLinesViewportData();\n const startViewLineNumber = partialData.completelyVisibleStartLineNumber;\n const endViewLineNumber = partialData.completelyVisibleEndLineNumber;\n return new Range(startViewLineNumber, this.getLineMinColumn(startViewLineNumber), endViewLineNumber, this.getLineMaxColumn(endViewLineNumber));\n }\n getCompletelyVisibleViewRangeAtScrollTop(scrollTop) {\n const partialData = this.viewLayout.getLinesViewportDataAtScrollTop(scrollTop);\n const startViewLineNumber = partialData.completelyVisibleStartLineNumber;\n const endViewLineNumber = partialData.completelyVisibleEndLineNumber;\n return new Range(startViewLineNumber, this.getLineMinColumn(startViewLineNumber), endViewLineNumber, this.getLineMaxColumn(endViewLineNumber));\n }\n saveState() {\n const compatViewState = this.viewLayout.saveState();\n const scrollTop = compatViewState.scrollTop;\n const firstViewLineNumber = this.viewLayout.getLineNumberAtVerticalOffset(scrollTop);\n const firstPosition = this.coordinatesConverter.convertViewPositionToModelPosition(new Position(firstViewLineNumber, this.getLineMinColumn(firstViewLineNumber)));\n const firstPositionDeltaTop = this.viewLayout.getVerticalOffsetForLineNumber(firstViewLineNumber) - scrollTop;\n return {\n scrollLeft: compatViewState.scrollLeft,\n firstPosition: firstPosition,\n firstPositionDeltaTop: firstPositionDeltaTop\n };\n }\n reduceRestoreState(state) {\n if (typeof state.firstPosition === 'undefined') {\n // This is a view state serialized by an older version\n return this._reduceRestoreStateCompatibility(state);\n }\n const modelPosition = this.model.validatePosition(state.firstPosition);\n const viewPosition = this.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);\n const scrollTop = this.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber) - state.firstPositionDeltaTop;\n return {\n scrollLeft: state.scrollLeft,\n scrollTop: scrollTop\n };\n }\n _reduceRestoreStateCompatibility(state) {\n return {\n scrollLeft: state.scrollLeft,\n scrollTop: state.scrollTopWithoutViewZones\n };\n }\n getTabSize() {\n return this.model.getOptions().tabSize;\n }\n getLineCount() {\n return this._lines.getViewLineCount();\n }\n /**\n * Gives a hint that a lot of requests are about to come in for these line numbers.\n */\n setViewport(startLineNumber, endLineNumber, centeredLineNumber) {\n this._viewportStart.update(this, startLineNumber);\n }\n getActiveIndentGuide(lineNumber, minLineNumber, maxLineNumber) {\n return this._lines.getActiveIndentGuide(lineNumber, minLineNumber, maxLineNumber);\n }\n getLinesIndentGuides(startLineNumber, endLineNumber) {\n return this._lines.getViewLinesIndentGuides(startLineNumber, endLineNumber);\n }\n getBracketGuidesInRangeByLine(startLineNumber, endLineNumber, activePosition, options) {\n return this._lines.getViewLinesBracketGuides(startLineNumber, endLineNumber, activePosition, options);\n }\n getLineContent(lineNumber) {\n return this._lines.getViewLineContent(lineNumber);\n }\n getLineLength(lineNumber) {\n return this._lines.getViewLineLength(lineNumber);\n }\n getLineMinColumn(lineNumber) {\n return this._lines.getViewLineMinColumn(lineNumber);\n }\n getLineMaxColumn(lineNumber) {\n return this._lines.getViewLineMaxColumn(lineNumber);\n }\n getLineFirstNonWhitespaceColumn(lineNumber) {\n const result = strings.firstNonWhitespaceIndex(this.getLineContent(lineNumber));\n if (result === -1) {\n return 0;\n }\n return result + 1;\n }\n getLineLastNonWhitespaceColumn(lineNumber) {\n const result = strings.lastNonWhitespaceIndex(this.getLineContent(lineNumber));\n if (result === -1) {\n return 0;\n }\n return result + 2;\n }\n getDecorationsInViewport(visibleRange) {\n return this._decorations.getDecorationsViewportData(visibleRange).decorations;\n }\n getInjectedTextAt(viewPosition) {\n return this._lines.getInjectedTextAt(viewPosition);\n }\n getViewportViewLineRenderingData(visibleRange, lineNumber) {\n const allInlineDecorations = this._decorations.getDecorationsViewportData(visibleRange).inlineDecorations;\n const inlineDecorations = allInlineDecorations[lineNumber - visibleRange.startLineNumber];\n return this._getViewLineRenderingData(lineNumber, inlineDecorations);\n }\n getViewLineRenderingData(lineNumber) {\n const inlineDecorations = this._decorations.getInlineDecorationsOnLine(lineNumber);\n return this._getViewLineRenderingData(lineNumber, inlineDecorations);\n }\n _getViewLineRenderingData(lineNumber, inlineDecorations) {\n const mightContainRTL = this.model.mightContainRTL();\n const mightContainNonBasicASCII = this.model.mightContainNonBasicASCII();\n const tabSize = this.getTabSize();\n const lineData = this._lines.getViewLineData(lineNumber);\n if (lineData.inlineDecorations) {\n inlineDecorations = [\n ...inlineDecorations,\n ...lineData.inlineDecorations.map(d => d.toInlineDecoration(lineNumber))\n ];\n }\n return new ViewLineRenderingData(lineData.minColumn, lineData.maxColumn, lineData.content, lineData.continuesWithWrappedLine, mightContainRTL, mightContainNonBasicASCII, lineData.tokens, inlineDecorations, tabSize, lineData.startVisibleColumn);\n }\n getViewLineData(lineNumber) {\n return this._lines.getViewLineData(lineNumber);\n }\n getMinimapLinesRenderingData(startLineNumber, endLineNumber, needed) {\n const result = this._lines.getViewLinesData(startLineNumber, endLineNumber, needed);\n return new MinimapLinesRenderingData(this.getTabSize(), result);\n }\n getAllOverviewRulerDecorations(theme) {\n const decorations = this.model.getOverviewRulerDecorations(this._editorId, filterValidationDecorations(this._configuration.options));\n const result = new OverviewRulerDecorations();\n for (const decoration of decorations) {\n const decorationOptions = decoration.options;\n const opts = decorationOptions.overviewRuler;\n if (!opts) {\n continue;\n }\n const lane = opts.position;\n if (lane === 0) {\n continue;\n }\n const color = opts.getColor(theme.value);\n const viewStartLineNumber = this.coordinatesConverter.getViewLineNumberOfModelPosition(decoration.range.startLineNumber, decoration.range.startColumn);\n const viewEndLineNumber = this.coordinatesConverter.getViewLineNumberOfModelPosition(decoration.range.endLineNumber, decoration.range.endColumn);\n result.accept(color, decorationOptions.zIndex, viewStartLineNumber, viewEndLineNumber, lane);\n }\n return result.asArray;\n }\n _invalidateDecorationsColorCache() {\n const decorations = this.model.getOverviewRulerDecorations();\n for (const decoration of decorations) {\n const opts1 = decoration.options.overviewRuler;\n if (opts1) {\n opts1.invalidateCachedColor();\n }\n const opts2 = decoration.options.minimap;\n if (opts2) {\n opts2.invalidateCachedColor();\n }\n }\n }\n getValueInRange(range, eol) {\n const modelRange = this.coordinatesConverter.convertViewRangeToModelRange(range);\n return this.model.getValueInRange(modelRange, eol);\n }\n deduceModelPositionRelativeToViewPosition(viewAnchorPosition, deltaOffset, lineFeedCnt) {\n const modelAnchor = this.coordinatesConverter.convertViewPositionToModelPosition(viewAnchorPosition);\n if (this.model.getEOL().length === 2) {\n // This model uses CRLF, so the delta must take that into account\n if (deltaOffset < 0) {\n deltaOffset -= lineFeedCnt;\n }\n else {\n deltaOffset += lineFeedCnt;\n }\n }\n const modelAnchorOffset = this.model.getOffsetAt(modelAnchor);\n const resultOffset = modelAnchorOffset + deltaOffset;\n return this.model.getPositionAt(resultOffset);\n }\n getPlainTextToCopy(modelRanges, emptySelectionClipboard, forceCRLF) {\n const newLineCharacter = forceCRLF ? '\\r\\n' : this.model.getEOL();\n modelRanges = modelRanges.slice(0);\n modelRanges.sort(Range.compareRangesUsingStarts);\n let hasEmptyRange = false;\n let hasNonEmptyRange = false;\n for (const range of modelRanges) {\n if (range.isEmpty()) {\n hasEmptyRange = true;\n }\n else {\n hasNonEmptyRange = true;\n }\n }\n if (!hasNonEmptyRange) {\n // all ranges are empty\n if (!emptySelectionClipboard) {\n return '';\n }\n const modelLineNumbers = modelRanges.map((r) => r.startLineNumber);\n let result = '';\n for (let i = 0; i < modelLineNumbers.length; i++) {\n if (i > 0 && modelLineNumbers[i - 1] === modelLineNumbers[i]) {\n continue;\n }\n result += this.model.getLineContent(modelLineNumbers[i]) + newLineCharacter;\n }\n return result;\n }\n if (hasEmptyRange && emptySelectionClipboard) {\n // mixed empty selections and non-empty selections\n const result = [];\n let prevModelLineNumber = 0;\n for (const modelRange of modelRanges) {\n const modelLineNumber = modelRange.startLineNumber;\n if (modelRange.isEmpty()) {\n if (modelLineNumber !== prevModelLineNumber) {\n result.push(this.model.getLineContent(modelLineNumber));\n }\n }\n else {\n result.push(this.model.getValueInRange(modelRange, forceCRLF ? 2 /* EndOfLinePreference.CRLF */ : 0 /* EndOfLinePreference.TextDefined */));\n }\n prevModelLineNumber = modelLineNumber;\n }\n return result.length === 1 ? result[0] : result;\n }\n const result = [];\n for (const modelRange of modelRanges) {\n if (!modelRange.isEmpty()) {\n result.push(this.model.getValueInRange(modelRange, forceCRLF ? 2 /* EndOfLinePreference.CRLF */ : 0 /* EndOfLinePreference.TextDefined */));\n }\n }\n return result.length === 1 ? result[0] : result;\n }\n getRichTextToCopy(modelRanges, emptySelectionClipboard) {\n const languageId = this.model.getLanguageId();\n if (languageId === PLAINTEXT_LANGUAGE_ID) {\n return null;\n }\n if (modelRanges.length !== 1) {\n // no multiple selection support at this time\n return null;\n }\n let range = modelRanges[0];\n if (range.isEmpty()) {\n if (!emptySelectionClipboard) {\n // nothing to copy\n return null;\n }\n const lineNumber = range.startLineNumber;\n range = new Range(lineNumber, this.model.getLineMinColumn(lineNumber), lineNumber, this.model.getLineMaxColumn(lineNumber));\n }\n const fontInfo = this._configuration.options.get(46 /* EditorOption.fontInfo */);\n const colorMap = this._getColorMap();\n const hasBadChars = (/[:;\\\\\\/<>]/.test(fontInfo.fontFamily));\n const useDefaultFontFamily = (hasBadChars || fontInfo.fontFamily === EDITOR_FONT_DEFAULTS.fontFamily);\n let fontFamily;\n if (useDefaultFontFamily) {\n fontFamily = EDITOR_FONT_DEFAULTS.fontFamily;\n }\n else {\n fontFamily = fontInfo.fontFamily;\n fontFamily = fontFamily.replace(/\"/g, '\\'');\n const hasQuotesOrIsList = /[,']/.test(fontFamily);\n if (!hasQuotesOrIsList) {\n const needsQuotes = /[+ ]/.test(fontFamily);\n if (needsQuotes) {\n fontFamily = `'${fontFamily}'`;\n }\n }\n fontFamily = `${fontFamily}, ${EDITOR_FONT_DEFAULTS.fontFamily}`;\n }\n return {\n mode: languageId,\n html: (`
`\n + this._getHTMLToCopy(range, colorMap)\n + '
')\n };\n }\n _getHTMLToCopy(modelRange, colorMap) {\n const startLineNumber = modelRange.startLineNumber;\n const startColumn = modelRange.startColumn;\n const endLineNumber = modelRange.endLineNumber;\n const endColumn = modelRange.endColumn;\n const tabSize = this.getTabSize();\n let result = '';\n for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n const lineTokens = this.model.tokenization.getLineTokens(lineNumber);\n const lineContent = lineTokens.getLineContent();\n const startOffset = (lineNumber === startLineNumber ? startColumn - 1 : 0);\n const endOffset = (lineNumber === endLineNumber ? endColumn - 1 : lineContent.length);\n if (lineContent === '') {\n result += '
';\n }\n else {\n result += tokenizeLineToHTML(lineContent, lineTokens.inflate(), colorMap, startOffset, endOffset, tabSize, platform.isWindows);\n }\n }\n return result;\n }\n _getColorMap() {\n const colorMap = TokenizationRegistry.getColorMap();\n const result = ['#000000'];\n if (colorMap) {\n for (let i = 1, len = colorMap.length; i < len; i++) {\n result[i] = Color.Format.CSS.formatHex(colorMap[i]);\n }\n }\n return result;\n }\n //#region cursor operations\n getPrimaryCursorState() {\n return this._cursor.getPrimaryCursorState();\n }\n getLastAddedCursorIndex() {\n return this._cursor.getLastAddedCursorIndex();\n }\n getCursorStates() {\n return this._cursor.getCursorStates();\n }\n setCursorStates(source, reason, states) {\n return this._withViewEventsCollector(eventsCollector => this._cursor.setStates(eventsCollector, source, reason, states));\n }\n getCursorColumnSelectData() {\n return this._cursor.getCursorColumnSelectData();\n }\n getCursorAutoClosedCharacters() {\n return this._cursor.getAutoClosedCharacters();\n }\n setCursorColumnSelectData(columnSelectData) {\n this._cursor.setCursorColumnSelectData(columnSelectData);\n }\n getPrevEditOperationType() {\n return this._cursor.getPrevEditOperationType();\n }\n setPrevEditOperationType(type) {\n this._cursor.setPrevEditOperationType(type);\n }\n getSelection() {\n return this._cursor.getSelection();\n }\n getSelections() {\n return this._cursor.getSelections();\n }\n getPosition() {\n return this._cursor.getPrimaryCursorState().modelState.position;\n }\n setSelections(source, selections, reason = 0 /* CursorChangeReason.NotSet */) {\n this._withViewEventsCollector(eventsCollector => this._cursor.setSelections(eventsCollector, source, selections, reason));\n }\n saveCursorState() {\n return this._cursor.saveState();\n }\n restoreCursorState(states) {\n this._withViewEventsCollector(eventsCollector => this._cursor.restoreState(eventsCollector, states));\n }\n _executeCursorEdit(callback) {\n if (this._cursor.context.cursorConfig.readOnly) {\n // we cannot edit when read only...\n this._eventDispatcher.emitOutgoingEvent(new ReadOnlyEditAttemptEvent());\n return;\n }\n this._withViewEventsCollector(callback);\n }\n executeEdits(source, edits, cursorStateComputer) {\n this._executeCursorEdit(eventsCollector => this._cursor.executeEdits(eventsCollector, source, edits, cursorStateComputer));\n }\n startComposition() {\n this._executeCursorEdit(eventsCollector => this._cursor.startComposition(eventsCollector));\n }\n endComposition(source) {\n this._executeCursorEdit(eventsCollector => this._cursor.endComposition(eventsCollector, source));\n }\n type(text, source) {\n this._executeCursorEdit(eventsCollector => this._cursor.type(eventsCollector, text, source));\n }\n compositionType(text, replacePrevCharCnt, replaceNextCharCnt, positionDelta, source) {\n this._executeCursorEdit(eventsCollector => this._cursor.compositionType(eventsCollector, text, replacePrevCharCnt, replaceNextCharCnt, positionDelta, source));\n }\n paste(text, pasteOnNewLine, multicursorText, source) {\n this._executeCursorEdit(eventsCollector => this._cursor.paste(eventsCollector, text, pasteOnNewLine, multicursorText, source));\n }\n cut(source) {\n this._executeCursorEdit(eventsCollector => this._cursor.cut(eventsCollector, source));\n }\n executeCommand(command, source) {\n this._executeCursorEdit(eventsCollector => this._cursor.executeCommand(eventsCollector, command, source));\n }\n executeCommands(commands, source) {\n this._executeCursorEdit(eventsCollector => this._cursor.executeCommands(eventsCollector, commands, source));\n }\n revealPrimaryCursor(source, revealHorizontal, minimalReveal = false) {\n this._withViewEventsCollector(eventsCollector => this._cursor.revealPrimary(eventsCollector, source, minimalReveal, 0 /* viewEvents.VerticalRevealType.Simple */, revealHorizontal, 0 /* ScrollType.Smooth */));\n }\n revealTopMostCursor(source) {\n const viewPosition = this._cursor.getTopMostViewPosition();\n const viewRange = new Range(viewPosition.lineNumber, viewPosition.column, viewPosition.lineNumber, viewPosition.column);\n this._withViewEventsCollector(eventsCollector => eventsCollector.emitViewEvent(new viewEvents.ViewRevealRangeRequestEvent(source, false, viewRange, null, 0 /* viewEvents.VerticalRevealType.Simple */, true, 0 /* ScrollType.Smooth */)));\n }\n revealBottomMostCursor(source) {\n const viewPosition = this._cursor.getBottomMostViewPosition();\n const viewRange = new Range(viewPosition.lineNumber, viewPosition.column, viewPosition.lineNumber, viewPosition.column);\n this._withViewEventsCollector(eventsCollector => eventsCollector.emitViewEvent(new viewEvents.ViewRevealRangeRequestEvent(source, false, viewRange, null, 0 /* viewEvents.VerticalRevealType.Simple */, true, 0 /* ScrollType.Smooth */)));\n }\n revealRange(source, revealHorizontal, viewRange, verticalType, scrollType) {\n this._withViewEventsCollector(eventsCollector => eventsCollector.emitViewEvent(new viewEvents.ViewRevealRangeRequestEvent(source, false, viewRange, null, verticalType, revealHorizontal, scrollType)));\n }\n //#endregion\n //#region viewLayout\n changeWhitespace(callback) {\n const hadAChange = this.viewLayout.changeWhitespace(callback);\n if (hadAChange) {\n this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewZonesChangedEvent());\n this._eventDispatcher.emitOutgoingEvent(new ViewZonesChangedEvent());\n }\n }\n //#endregion\n _withViewEventsCollector(callback) {\n try {\n const eventsCollector = this._eventDispatcher.beginEmitViewEvents();\n return callback(eventsCollector);\n }\n finally {\n this._eventDispatcher.endEmitViewEvents();\n }\n }\n normalizePosition(position, affinity) {\n return this._lines.normalizePosition(position, affinity);\n }\n /**\n * Gets the column at which indentation stops at a given line.\n * @internal\n */\n getLineIndentColumn(lineNumber) {\n return this._lines.getLineIndentColumn(lineNumber);\n }\n}\nclass ViewportStart {\n constructor(_model, _viewLineNumber, _isValid, _modelTrackedRange, _startLineDelta) {\n this._model = _model;\n this._viewLineNumber = _viewLineNumber;\n this._isValid = _isValid;\n this._modelTrackedRange = _modelTrackedRange;\n this._startLineDelta = _startLineDelta;\n }\n static create(model) {\n const viewportStartLineTrackedRange = model._setTrackedRange(null, new Range(1, 1, 1, 1), 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */);\n return new ViewportStart(model, 1, false, viewportStartLineTrackedRange, 0);\n }\n get viewLineNumber() {\n return this._viewLineNumber;\n }\n get isValid() {\n return this._isValid;\n }\n get modelTrackedRange() {\n return this._modelTrackedRange;\n }\n get startLineDelta() {\n return this._startLineDelta;\n }\n dispose() {\n this._model._setTrackedRange(this._modelTrackedRange, null, 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */);\n }\n update(viewModel, startLineNumber) {\n const position = viewModel.coordinatesConverter.convertViewPositionToModelPosition(new Position(startLineNumber, viewModel.getLineMinColumn(startLineNumber)));\n const viewportStartLineTrackedRange = viewModel.model._setTrackedRange(this._modelTrackedRange, new Range(position.lineNumber, position.column, position.lineNumber, position.column), 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */);\n const viewportStartLineTop = viewModel.viewLayout.getVerticalOffsetForLineNumber(startLineNumber);\n const scrollTop = viewModel.viewLayout.getCurrentScrollTop();\n this._viewLineNumber = startLineNumber;\n this._isValid = true;\n this._modelTrackedRange = viewportStartLineTrackedRange;\n this._startLineDelta = scrollTop - viewportStartLineTop;\n }\n invalidate() {\n this._isValid = false;\n }\n}\nclass OverviewRulerDecorations {\n constructor() {\n this._asMap = Object.create(null);\n this.asArray = [];\n }\n accept(color, zIndex, startLineNumber, endLineNumber, lane) {\n const prevGroup = this._asMap[color];\n if (prevGroup) {\n const prevData = prevGroup.data;\n const prevLane = prevData[prevData.length - 3];\n const prevEndLineNumber = prevData[prevData.length - 1];\n if (prevLane === lane && prevEndLineNumber + 1 >= startLineNumber) {\n // merge into prev\n if (endLineNumber > prevEndLineNumber) {\n prevData[prevData.length - 1] = endLineNumber;\n }\n return;\n }\n // push\n prevData.push(lane, startLineNumber, endLineNumber);\n }\n else {\n const group = new OverviewRulerDecorationsGroup(color, zIndex, [lane, startLineNumber, endLineNumber]);\n this._asMap[color] = group;\n this.asArray.push(group);\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 *--------------------------------------------------------------------------------------------*/\nimport { assertNever } from '../../base/common/types.js';\nimport { Position } from './core/position.js';\nimport { InjectedTextCursorStops } from './model.js';\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 constructor(injectionOffsets, \n /**\n * `injectionOptions.length` must equal `injectionOffsets.length`\n */\n injectionOptions, \n /**\n * Refers to offsets after applying injections to the source.\n * The last break offset indicates the length of the source after applying injections.\n */\n breakOffsets, \n /**\n * Refers to offsets after applying injections\n */\n breakOffsetsVisibleColumn, wrappedTextIndentLength) {\n this.injectionOffsets = injectionOffsets;\n this.injectionOptions = injectionOptions;\n this.breakOffsets = breakOffsets;\n this.breakOffsetsVisibleColumn = breakOffsetsVisibleColumn;\n this.wrappedTextIndentLength = wrappedTextIndentLength;\n }\n getOutputLineCount() {\n return this.breakOffsets.length;\n }\n getMinOutputOffset(outputLineIndex) {\n if (outputLineIndex > 0) {\n return this.wrappedTextIndentLength;\n }\n return 0;\n }\n getLineLength(outputLineIndex) {\n // These offsets refer to model text with injected text.\n const startOffset = outputLineIndex > 0 ? this.breakOffsets[outputLineIndex - 1] : 0;\n const endOffset = this.breakOffsets[outputLineIndex];\n let lineLength = endOffset - startOffset;\n if (outputLineIndex > 0) {\n lineLength += this.wrappedTextIndentLength;\n }\n return lineLength;\n }\n getMaxOutputOffset(outputLineIndex) {\n return this.getLineLength(outputLineIndex);\n }\n translateToInputOffset(outputLineIndex, outputOffset) {\n if (outputLineIndex > 0) {\n outputOffset = Math.max(0, outputOffset - this.wrappedTextIndentLength);\n }\n const offsetInInputWithInjection = outputLineIndex === 0 ? outputOffset : this.breakOffsets[outputLineIndex - 1] + outputOffset;\n let offsetInInput = offsetInInputWithInjection;\n if (this.injectionOffsets !== null) {\n for (let i = 0; i < this.injectionOffsets.length; i++) {\n if (offsetInInput > this.injectionOffsets[i]) {\n if (offsetInInput < this.injectionOffsets[i] + this.injectionOptions[i].content.length) {\n // `inputOffset` is within injected text\n offsetInInput = this.injectionOffsets[i];\n }\n else {\n offsetInInput -= this.injectionOptions[i].content.length;\n }\n }\n else {\n break;\n }\n }\n }\n return offsetInInput;\n }\n translateToOutputPosition(inputOffset, affinity = 2 /* PositionAffinity.None */) {\n let inputOffsetInInputWithInjection = inputOffset;\n if (this.injectionOffsets !== null) {\n for (let i = 0; i < this.injectionOffsets.length; i++) {\n if (inputOffset < this.injectionOffsets[i]) {\n break;\n }\n if (affinity !== 1 /* PositionAffinity.Right */ && inputOffset === this.injectionOffsets[i]) {\n break;\n }\n inputOffsetInInputWithInjection += this.injectionOptions[i].content.length;\n }\n }\n return this.offsetInInputWithInjectionsToOutputPosition(inputOffsetInInputWithInjection, affinity);\n }\n offsetInInputWithInjectionsToOutputPosition(offsetInInputWithInjections, affinity = 2 /* PositionAffinity.None */) {\n let low = 0;\n let high = this.breakOffsets.length - 1;\n let mid = 0;\n let midStart = 0;\n while (low <= high) {\n mid = low + ((high - low) / 2) | 0;\n const midStop = this.breakOffsets[mid];\n midStart = mid > 0 ? this.breakOffsets[mid - 1] : 0;\n if (affinity === 0 /* PositionAffinity.Left */) {\n if (offsetInInputWithInjections <= midStart) {\n high = mid - 1;\n }\n else if (offsetInInputWithInjections > midStop) {\n low = mid + 1;\n }\n else {\n break;\n }\n }\n else {\n if (offsetInInputWithInjections < midStart) {\n high = mid - 1;\n }\n else if (offsetInInputWithInjections >= midStop) {\n low = mid + 1;\n }\n else {\n break;\n }\n }\n }\n let outputOffset = offsetInInputWithInjections - midStart;\n if (mid > 0) {\n outputOffset += this.wrappedTextIndentLength;\n }\n return new OutputPosition(mid, outputOffset);\n }\n normalizeOutputPosition(outputLineIndex, outputOffset, affinity) {\n if (this.injectionOffsets !== null) {\n const offsetInInputWithInjections = this.outputPositionToOffsetInInputWithInjections(outputLineIndex, outputOffset);\n const normalizedOffsetInUnwrappedLine = this.normalizeOffsetInInputWithInjectionsAroundInjections(offsetInInputWithInjections, affinity);\n if (normalizedOffsetInUnwrappedLine !== offsetInInputWithInjections) {\n // injected text caused a change\n return this.offsetInInputWithInjectionsToOutputPosition(normalizedOffsetInUnwrappedLine, affinity);\n }\n }\n if (affinity === 0 /* PositionAffinity.Left */) {\n if (outputLineIndex > 0 && outputOffset === this.getMinOutputOffset(outputLineIndex)) {\n return new OutputPosition(outputLineIndex - 1, this.getMaxOutputOffset(outputLineIndex - 1));\n }\n }\n else if (affinity === 1 /* PositionAffinity.Right */) {\n const maxOutputLineIndex = this.getOutputLineCount() - 1;\n if (outputLineIndex < maxOutputLineIndex && outputOffset === this.getMaxOutputOffset(outputLineIndex)) {\n return new OutputPosition(outputLineIndex + 1, this.getMinOutputOffset(outputLineIndex + 1));\n }\n }\n return new OutputPosition(outputLineIndex, outputOffset);\n }\n outputPositionToOffsetInInputWithInjections(outputLineIndex, outputOffset) {\n if (outputLineIndex > 0) {\n outputOffset = Math.max(0, outputOffset - this.wrappedTextIndentLength);\n }\n const result = (outputLineIndex > 0 ? this.breakOffsets[outputLineIndex - 1] : 0) + outputOffset;\n return result;\n }\n normalizeOffsetInInputWithInjectionsAroundInjections(offsetInInputWithInjections, affinity) {\n const injectedText = this.getInjectedTextAtOffset(offsetInInputWithInjections);\n if (!injectedText) {\n return offsetInInputWithInjections;\n }\n if (affinity === 2 /* PositionAffinity.None */) {\n if (offsetInInputWithInjections === injectedText.offsetInInputWithInjections + injectedText.length\n && hasRightCursorStop(this.injectionOptions[injectedText.injectedTextIndex].cursorStops)) {\n return injectedText.offsetInInputWithInjections + injectedText.length;\n }\n else {\n let result = injectedText.offsetInInputWithInjections;\n if (hasLeftCursorStop(this.injectionOptions[injectedText.injectedTextIndex].cursorStops)) {\n return result;\n }\n let index = injectedText.injectedTextIndex - 1;\n while (index >= 0 && this.injectionOffsets[index] === this.injectionOffsets[injectedText.injectedTextIndex]) {\n if (hasRightCursorStop(this.injectionOptions[index].cursorStops)) {\n break;\n }\n result -= this.injectionOptions[index].content.length;\n if (hasLeftCursorStop(this.injectionOptions[index].cursorStops)) {\n break;\n }\n index--;\n }\n return result;\n }\n }\n else if (affinity === 1 /* PositionAffinity.Right */ || affinity === 4 /* PositionAffinity.RightOfInjectedText */) {\n let result = injectedText.offsetInInputWithInjections + injectedText.length;\n let index = injectedText.injectedTextIndex;\n // traverse all injected text that touch each other\n while (index + 1 < this.injectionOffsets.length && this.injectionOffsets[index + 1] === this.injectionOffsets[index]) {\n result += this.injectionOptions[index + 1].content.length;\n index++;\n }\n return result;\n }\n else if (affinity === 0 /* PositionAffinity.Left */ || affinity === 3 /* PositionAffinity.LeftOfInjectedText */) {\n // affinity is left\n let result = injectedText.offsetInInputWithInjections;\n let index = injectedText.injectedTextIndex;\n // traverse all injected text that touch each other\n while (index - 1 >= 0 && this.injectionOffsets[index - 1] === this.injectionOffsets[index]) {\n result -= this.injectionOptions[index - 1].content.length;\n index--;\n }\n return result;\n }\n assertNever(affinity);\n }\n getInjectedText(outputLineIndex, outputOffset) {\n const offset = this.outputPositionToOffsetInInputWithInjections(outputLineIndex, outputOffset);\n const injectedText = this.getInjectedTextAtOffset(offset);\n if (!injectedText) {\n return null;\n }\n return {\n options: this.injectionOptions[injectedText.injectedTextIndex]\n };\n }\n getInjectedTextAtOffset(offsetInInputWithInjections) {\n const injectionOffsets = this.injectionOffsets;\n const injectionOptions = this.injectionOptions;\n if (injectionOffsets !== null) {\n let totalInjectedTextLengthBefore = 0;\n for (let i = 0; i < injectionOffsets.length; i++) {\n const length = injectionOptions[i].content.length;\n const injectedTextStartOffsetInInputWithInjections = injectionOffsets[i] + totalInjectedTextLengthBefore;\n const injectedTextEndOffsetInInputWithInjections = injectionOffsets[i] + totalInjectedTextLengthBefore + length;\n if (injectedTextStartOffsetInInputWithInjections > offsetInInputWithInjections) {\n // Injected text starts later.\n break; // All later injected texts have an even larger offset.\n }\n if (offsetInInputWithInjections <= injectedTextEndOffsetInInputWithInjections) {\n // Injected text ends after or with the given position (but also starts with or before it).\n return {\n injectedTextIndex: i,\n offsetInInputWithInjections: injectedTextStartOffsetInInputWithInjections,\n length\n };\n }\n totalInjectedTextLengthBefore += length;\n }\n }\n return undefined;\n }\n}\nfunction hasRightCursorStop(cursorStop) {\n if (cursorStop === null || cursorStop === undefined) {\n return true;\n }\n return cursorStop === InjectedTextCursorStops.Right || cursorStop === InjectedTextCursorStops.Both;\n}\nfunction hasLeftCursorStop(cursorStop) {\n if (cursorStop === null || cursorStop === undefined) {\n return true;\n }\n return cursorStop === InjectedTextCursorStops.Left || cursorStop === InjectedTextCursorStops.Both;\n}\nexport class InjectedText {\n constructor(options) {\n this.options = options;\n }\n}\nexport class OutputPosition {\n constructor(outputLineIndex, outputOffset) {\n this.outputLineIndex = outputLineIndex;\n this.outputOffset = outputOffset;\n }\n toString() {\n return `${this.outputLineIndex}:${this.outputOffset}`;\n }\n toPosition(baseLineNumber) {\n return new Position(baseLineNumber + this.outputLineIndex, this.outputOffset + 1);\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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../base/common/strings.js';\nimport { CharacterClassifier } from '../core/characterClassifier.js';\nimport { LineInjectedText } from '../textModelEvents.js';\nimport { ModelLineProjectionData } from '../modelLineProjectionData.js';\nexport class MonospaceLineBreaksComputerFactory {\n constructor(breakBeforeChars, breakAfterChars) {\n this.classifier = new WrappingCharacterClassifier(breakBeforeChars, breakAfterChars);\n }\n static create(options) {\n return new MonospaceLineBreaksComputerFactory(options.get(122 /* EditorOption.wordWrapBreakBeforeCharacters */), options.get(121 /* EditorOption.wordWrapBreakAfterCharacters */));\n }\n createLineBreaksComputer(fontInfo, tabSize, wrappingColumn, wrappingIndent) {\n const requests = [];\n const injectedTexts = [];\n const previousBreakingData = [];\n return {\n addRequest: (lineText, injectedText, previousLineBreakData) => {\n requests.push(lineText);\n injectedTexts.push(injectedText);\n previousBreakingData.push(previousLineBreakData);\n },\n finalize: () => {\n const columnsForFullWidthChar = fontInfo.typicalFullwidthCharacterWidth / fontInfo.typicalHalfwidthCharacterWidth;\n const result = [];\n for (let i = 0, len = requests.length; i < len; i++) {\n const injectedText = injectedTexts[i];\n const previousLineBreakData = previousBreakingData[i];\n if (previousLineBreakData && !previousLineBreakData.injectionOptions && !injectedText) {\n result[i] = createLineBreaksFromPreviousLineBreaks(this.classifier, previousLineBreakData, requests[i], tabSize, wrappingColumn, columnsForFullWidthChar, wrappingIndent);\n }\n else {\n result[i] = createLineBreaks(this.classifier, requests[i], injectedText, tabSize, wrappingColumn, columnsForFullWidthChar, wrappingIndent);\n }\n }\n arrPool1.length = 0;\n arrPool2.length = 0;\n return result;\n }\n };\n }\n}\nclass WrappingCharacterClassifier extends CharacterClassifier {\n constructor(BREAK_BEFORE, BREAK_AFTER) {\n super(0 /* CharacterClass.NONE */);\n for (let i = 0; i < BREAK_BEFORE.length; i++) {\n this.set(BREAK_BEFORE.charCodeAt(i), 1 /* CharacterClass.BREAK_BEFORE */);\n }\n for (let i = 0; i < BREAK_AFTER.length; i++) {\n this.set(BREAK_AFTER.charCodeAt(i), 2 /* CharacterClass.BREAK_AFTER */);\n }\n }\n get(charCode) {\n if (charCode >= 0 && charCode < 256) {\n return this._asciiMap[charCode];\n }\n else {\n // Initialize CharacterClass.BREAK_IDEOGRAPHIC for these Unicode ranges:\n // 1. CJK Unified Ideographs (0x4E00 -- 0x9FFF)\n // 2. CJK Unified Ideographs Extension A (0x3400 -- 0x4DBF)\n // 3. Hiragana and Katakana (0x3040 -- 0x30FF)\n if ((charCode >= 0x3040 && charCode <= 0x30FF)\n || (charCode >= 0x3400 && charCode <= 0x4DBF)\n || (charCode >= 0x4E00 && charCode <= 0x9FFF)) {\n return 3 /* CharacterClass.BREAK_IDEOGRAPHIC */;\n }\n return (this._map.get(charCode) || this._defaultValue);\n }\n }\n}\nlet arrPool1 = [];\nlet arrPool2 = [];\nfunction createLineBreaksFromPreviousLineBreaks(classifier, previousBreakingData, lineText, tabSize, firstLineBreakColumn, columnsForFullWidthChar, wrappingIndent) {\n if (firstLineBreakColumn === -1) {\n return null;\n }\n const len = lineText.length;\n if (len <= 1) {\n return null;\n }\n const prevBreakingOffsets = previousBreakingData.breakOffsets;\n const prevBreakingOffsetsVisibleColumn = previousBreakingData.breakOffsetsVisibleColumn;\n const wrappedTextIndentLength = computeWrappedTextIndentLength(lineText, tabSize, firstLineBreakColumn, columnsForFullWidthChar, wrappingIndent);\n const wrappedLineBreakColumn = firstLineBreakColumn - wrappedTextIndentLength;\n const breakingOffsets = arrPool1;\n const breakingOffsetsVisibleColumn = arrPool2;\n let breakingOffsetsCount = 0;\n let lastBreakingOffset = 0;\n let lastBreakingOffsetVisibleColumn = 0;\n let breakingColumn = firstLineBreakColumn;\n const prevLen = prevBreakingOffsets.length;\n let prevIndex = 0;\n if (prevIndex >= 0) {\n let bestDistance = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex] - breakingColumn);\n while (prevIndex + 1 < prevLen) {\n const distance = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex + 1] - breakingColumn);\n if (distance >= bestDistance) {\n break;\n }\n bestDistance = distance;\n prevIndex++;\n }\n }\n while (prevIndex < prevLen) {\n // Allow for prevIndex to be -1 (for the case where we hit a tab when walking backwards from the first break)\n let prevBreakOffset = prevIndex < 0 ? 0 : prevBreakingOffsets[prevIndex];\n let prevBreakOffsetVisibleColumn = prevIndex < 0 ? 0 : prevBreakingOffsetsVisibleColumn[prevIndex];\n if (lastBreakingOffset > prevBreakOffset) {\n prevBreakOffset = lastBreakingOffset;\n prevBreakOffsetVisibleColumn = lastBreakingOffsetVisibleColumn;\n }\n let breakOffset = 0;\n let breakOffsetVisibleColumn = 0;\n let forcedBreakOffset = 0;\n let forcedBreakOffsetVisibleColumn = 0;\n // initially, we search as much as possible to the right (if it fits)\n if (prevBreakOffsetVisibleColumn <= breakingColumn) {\n let visibleColumn = prevBreakOffsetVisibleColumn;\n let prevCharCode = prevBreakOffset === 0 ? 0 /* CharCode.Null */ : lineText.charCodeAt(prevBreakOffset - 1);\n let prevCharCodeClass = prevBreakOffset === 0 ? 0 /* CharacterClass.NONE */ : classifier.get(prevCharCode);\n let entireLineFits = true;\n for (let i = prevBreakOffset; i < len; i++) {\n const charStartOffset = i;\n const charCode = lineText.charCodeAt(i);\n let charCodeClass;\n let charWidth;\n if (strings.isHighSurrogate(charCode)) {\n // A surrogate pair must always be considered as a single unit, so it is never to be broken\n i++;\n charCodeClass = 0 /* CharacterClass.NONE */;\n charWidth = 2;\n }\n else {\n charCodeClass = classifier.get(charCode);\n charWidth = computeCharWidth(charCode, visibleColumn, tabSize, columnsForFullWidthChar);\n }\n if (charStartOffset > lastBreakingOffset && canBreak(prevCharCode, prevCharCodeClass, charCode, charCodeClass)) {\n breakOffset = charStartOffset;\n breakOffsetVisibleColumn = visibleColumn;\n }\n visibleColumn += charWidth;\n // check if adding character at `i` will go over the breaking column\n if (visibleColumn > breakingColumn) {\n // We need to break at least before character at `i`:\n if (charStartOffset > lastBreakingOffset) {\n forcedBreakOffset = charStartOffset;\n forcedBreakOffsetVisibleColumn = visibleColumn - charWidth;\n }\n else {\n // we need to advance at least by one character\n forcedBreakOffset = i + 1;\n forcedBreakOffsetVisibleColumn = visibleColumn;\n }\n if (visibleColumn - breakOffsetVisibleColumn > wrappedLineBreakColumn) {\n // Cannot break at `breakOffset` => reset it if it was set\n breakOffset = 0;\n }\n entireLineFits = false;\n break;\n }\n prevCharCode = charCode;\n prevCharCodeClass = charCodeClass;\n }\n if (entireLineFits) {\n // there is no more need to break => stop the outer loop!\n if (breakingOffsetsCount > 0) {\n // Add last segment, no need to assign to `lastBreakingOffset` and `lastBreakingOffsetVisibleColumn`\n breakingOffsets[breakingOffsetsCount] = prevBreakingOffsets[prevBreakingOffsets.length - 1];\n breakingOffsetsVisibleColumn[breakingOffsetsCount] = prevBreakingOffsetsVisibleColumn[prevBreakingOffsets.length - 1];\n breakingOffsetsCount++;\n }\n break;\n }\n }\n if (breakOffset === 0) {\n // must search left\n let visibleColumn = prevBreakOffsetVisibleColumn;\n let charCode = lineText.charCodeAt(prevBreakOffset);\n let charCodeClass = classifier.get(charCode);\n let hitATabCharacter = false;\n for (let i = prevBreakOffset - 1; i >= lastBreakingOffset; i--) {\n const charStartOffset = i + 1;\n const prevCharCode = lineText.charCodeAt(i);\n if (prevCharCode === 9 /* CharCode.Tab */) {\n // cannot determine the width of a tab when going backwards, so we must go forwards\n hitATabCharacter = true;\n break;\n }\n let prevCharCodeClass;\n let prevCharWidth;\n if (strings.isLowSurrogate(prevCharCode)) {\n // A surrogate pair must always be considered as a single unit, so it is never to be broken\n i--;\n prevCharCodeClass = 0 /* CharacterClass.NONE */;\n prevCharWidth = 2;\n }\n else {\n prevCharCodeClass = classifier.get(prevCharCode);\n prevCharWidth = (strings.isFullWidthCharacter(prevCharCode) ? columnsForFullWidthChar : 1);\n }\n if (visibleColumn <= breakingColumn) {\n if (forcedBreakOffset === 0) {\n forcedBreakOffset = charStartOffset;\n forcedBreakOffsetVisibleColumn = visibleColumn;\n }\n if (visibleColumn <= breakingColumn - wrappedLineBreakColumn) {\n // went too far!\n break;\n }\n if (canBreak(prevCharCode, prevCharCodeClass, charCode, charCodeClass)) {\n breakOffset = charStartOffset;\n breakOffsetVisibleColumn = visibleColumn;\n break;\n }\n }\n visibleColumn -= prevCharWidth;\n charCode = prevCharCode;\n charCodeClass = prevCharCodeClass;\n }\n if (breakOffset !== 0) {\n const remainingWidthOfNextLine = wrappedLineBreakColumn - (forcedBreakOffsetVisibleColumn - breakOffsetVisibleColumn);\n if (remainingWidthOfNextLine <= tabSize) {\n const charCodeAtForcedBreakOffset = lineText.charCodeAt(forcedBreakOffset);\n let charWidth;\n if (strings.isHighSurrogate(charCodeAtForcedBreakOffset)) {\n // A surrogate pair must always be considered as a single unit, so it is never to be broken\n charWidth = 2;\n }\n else {\n charWidth = computeCharWidth(charCodeAtForcedBreakOffset, forcedBreakOffsetVisibleColumn, tabSize, columnsForFullWidthChar);\n }\n if (remainingWidthOfNextLine - charWidth < 0) {\n // it is not worth it to break at breakOffset, it just introduces an extra needless line!\n breakOffset = 0;\n }\n }\n }\n if (hitATabCharacter) {\n // cannot determine the width of a tab when going backwards, so we must go forwards from the previous break\n prevIndex--;\n continue;\n }\n }\n if (breakOffset === 0) {\n // Could not find a good breaking point\n breakOffset = forcedBreakOffset;\n breakOffsetVisibleColumn = forcedBreakOffsetVisibleColumn;\n }\n if (breakOffset <= lastBreakingOffset) {\n // Make sure that we are advancing (at least one character)\n const charCode = lineText.charCodeAt(lastBreakingOffset);\n if (strings.isHighSurrogate(charCode)) {\n // A surrogate pair must always be considered as a single unit, so it is never to be broken\n breakOffset = lastBreakingOffset + 2;\n breakOffsetVisibleColumn = lastBreakingOffsetVisibleColumn + 2;\n }\n else {\n breakOffset = lastBreakingOffset + 1;\n breakOffsetVisibleColumn = lastBreakingOffsetVisibleColumn + computeCharWidth(charCode, lastBreakingOffsetVisibleColumn, tabSize, columnsForFullWidthChar);\n }\n }\n lastBreakingOffset = breakOffset;\n breakingOffsets[breakingOffsetsCount] = breakOffset;\n lastBreakingOffsetVisibleColumn = breakOffsetVisibleColumn;\n breakingOffsetsVisibleColumn[breakingOffsetsCount] = breakOffsetVisibleColumn;\n breakingOffsetsCount++;\n breakingColumn = breakOffsetVisibleColumn + wrappedLineBreakColumn;\n while (prevIndex < 0 || (prevIndex < prevLen && prevBreakingOffsetsVisibleColumn[prevIndex] < breakOffsetVisibleColumn)) {\n prevIndex++;\n }\n let bestDistance = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex] - breakingColumn);\n while (prevIndex + 1 < prevLen) {\n const distance = Math.abs(prevBreakingOffsetsVisibleColumn[prevIndex + 1] - breakingColumn);\n if (distance >= bestDistance) {\n break;\n }\n bestDistance = distance;\n prevIndex++;\n }\n }\n if (breakingOffsetsCount === 0) {\n return null;\n }\n // Doing here some object reuse which ends up helping a huge deal with GC pauses!\n breakingOffsets.length = breakingOffsetsCount;\n breakingOffsetsVisibleColumn.length = breakingOffsetsCount;\n arrPool1 = previousBreakingData.breakOffsets;\n arrPool2 = previousBreakingData.breakOffsetsVisibleColumn;\n previousBreakingData.breakOffsets = breakingOffsets;\n previousBreakingData.breakOffsetsVisibleColumn = breakingOffsetsVisibleColumn;\n previousBreakingData.wrappedTextIndentLength = wrappedTextIndentLength;\n return previousBreakingData;\n}\nfunction createLineBreaks(classifier, _lineText, injectedTexts, tabSize, firstLineBreakColumn, columnsForFullWidthChar, wrappingIndent) {\n const lineText = LineInjectedText.applyInjectedText(_lineText, injectedTexts);\n let injectionOptions;\n let injectionOffsets;\n if (injectedTexts && injectedTexts.length > 0) {\n injectionOptions = injectedTexts.map(t => t.options);\n injectionOffsets = injectedTexts.map(text => text.column - 1);\n }\n else {\n injectionOptions = null;\n injectionOffsets = null;\n }\n if (firstLineBreakColumn === -1) {\n if (!injectionOptions) {\n return null;\n }\n // creating a `LineBreakData` with an invalid `breakOffsetsVisibleColumn` is OK\n // because `breakOffsetsVisibleColumn` will never be used because it contains injected text\n return new ModelLineProjectionData(injectionOffsets, injectionOptions, [lineText.length], [], 0);\n }\n const len = lineText.length;\n if (len <= 1) {\n if (!injectionOptions) {\n return null;\n }\n // creating a `LineBreakData` with an invalid `breakOffsetsVisibleColumn` is OK\n // because `breakOffsetsVisibleColumn` will never be used because it contains injected text\n return new ModelLineProjectionData(injectionOffsets, injectionOptions, [lineText.length], [], 0);\n }\n const wrappedTextIndentLength = computeWrappedTextIndentLength(lineText, tabSize, firstLineBreakColumn, columnsForFullWidthChar, wrappingIndent);\n const wrappedLineBreakColumn = firstLineBreakColumn - wrappedTextIndentLength;\n const breakingOffsets = [];\n const breakingOffsetsVisibleColumn = [];\n let breakingOffsetsCount = 0;\n let breakOffset = 0;\n let breakOffsetVisibleColumn = 0;\n let breakingColumn = firstLineBreakColumn;\n let prevCharCode = lineText.charCodeAt(0);\n let prevCharCodeClass = classifier.get(prevCharCode);\n let visibleColumn = computeCharWidth(prevCharCode, 0, tabSize, columnsForFullWidthChar);\n let startOffset = 1;\n if (strings.isHighSurrogate(prevCharCode)) {\n // A surrogate pair must always be considered as a single unit, so it is never to be broken\n visibleColumn += 1;\n prevCharCode = lineText.charCodeAt(1);\n prevCharCodeClass = classifier.get(prevCharCode);\n startOffset++;\n }\n for (let i = startOffset; i < len; i++) {\n const charStartOffset = i;\n const charCode = lineText.charCodeAt(i);\n let charCodeClass;\n let charWidth;\n if (strings.isHighSurrogate(charCode)) {\n // A surrogate pair must always be considered as a single unit, so it is never to be broken\n i++;\n charCodeClass = 0 /* CharacterClass.NONE */;\n charWidth = 2;\n }\n else {\n charCodeClass = classifier.get(charCode);\n charWidth = computeCharWidth(charCode, visibleColumn, tabSize, columnsForFullWidthChar);\n }\n if (canBreak(prevCharCode, prevCharCodeClass, charCode, charCodeClass)) {\n breakOffset = charStartOffset;\n breakOffsetVisibleColumn = visibleColumn;\n }\n visibleColumn += charWidth;\n // check if adding character at `i` will go over the breaking column\n if (visibleColumn > breakingColumn) {\n // We need to break at least before character at `i`:\n if (breakOffset === 0 || visibleColumn - breakOffsetVisibleColumn > wrappedLineBreakColumn) {\n // Cannot break at `breakOffset`, must break at `i`\n breakOffset = charStartOffset;\n breakOffsetVisibleColumn = visibleColumn - charWidth;\n }\n breakingOffsets[breakingOffsetsCount] = breakOffset;\n breakingOffsetsVisibleColumn[breakingOffsetsCount] = breakOffsetVisibleColumn;\n breakingOffsetsCount++;\n breakingColumn = breakOffsetVisibleColumn + wrappedLineBreakColumn;\n breakOffset = 0;\n }\n prevCharCode = charCode;\n prevCharCodeClass = charCodeClass;\n }\n if (breakingOffsetsCount === 0 && (!injectedTexts || injectedTexts.length === 0)) {\n return null;\n }\n // Add last segment\n breakingOffsets[breakingOffsetsCount] = len;\n breakingOffsetsVisibleColumn[breakingOffsetsCount] = visibleColumn;\n return new ModelLineProjectionData(injectionOffsets, injectionOptions, breakingOffsets, breakingOffsetsVisibleColumn, wrappedTextIndentLength);\n}\nfunction computeCharWidth(charCode, visibleColumn, tabSize, columnsForFullWidthChar) {\n if (charCode === 9 /* CharCode.Tab */) {\n return (tabSize - (visibleColumn % tabSize));\n }\n if (strings.isFullWidthCharacter(charCode)) {\n return columnsForFullWidthChar;\n }\n if (charCode < 32) {\n // when using `editor.renderControlCharacters`, the substitutions are often wide\n return columnsForFullWidthChar;\n }\n return 1;\n}\nfunction tabCharacterWidth(visibleColumn, tabSize) {\n return (tabSize - (visibleColumn % tabSize));\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, prevCharCodeClass, charCode, charCodeClass) {\n return (charCode !== 32 /* CharCode.Space */\n && ((prevCharCodeClass === 2 /* CharacterClass.BREAK_AFTER */ && charCodeClass !== 2 /* CharacterClass.BREAK_AFTER */) // break at the end of multiple BREAK_AFTER\n || (prevCharCodeClass !== 1 /* CharacterClass.BREAK_BEFORE */ && charCodeClass === 1 /* CharacterClass.BREAK_BEFORE */) // break at the start of multiple BREAK_BEFORE\n || (prevCharCodeClass === 3 /* CharacterClass.BREAK_IDEOGRAPHIC */ && charCodeClass !== 2 /* CharacterClass.BREAK_AFTER */)\n || (charCodeClass === 3 /* CharacterClass.BREAK_IDEOGRAPHIC */ && prevCharCodeClass !== 1 /* CharacterClass.BREAK_BEFORE */)));\n}\nfunction computeWrappedTextIndentLength(lineText, tabSize, firstLineBreakColumn, columnsForFullWidthChar, wrappingIndent) {\n let wrappedTextIndentLength = 0;\n if (wrappingIndent !== 0 /* WrappingIndent.None */) {\n const firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineText);\n if (firstNonWhitespaceIndex !== -1) {\n // Track existing indent\n for (let i = 0; i < firstNonWhitespaceIndex; i++) {\n const charWidth = (lineText.charCodeAt(i) === 9 /* CharCode.Tab */ ? tabCharacterWidth(wrappedTextIndentLength, tabSize) : 1);\n wrappedTextIndentLength += charWidth;\n }\n // Increase indent of continuation lines, if desired\n const numberOfAdditionalTabs = (wrappingIndent === 3 /* WrappingIndent.DeepIndent */ ? 2 : wrappingIndent === 2 /* WrappingIndent.Indent */ ? 1 : 0);\n for (let i = 0; i < numberOfAdditionalTabs; i++) {\n const charWidth = tabCharacterWidth(wrappedTextIndentLength, tabSize);\n wrappedTextIndentLength += charWidth;\n }\n // Force sticking to beginning of line if no character would fit except for the indentation\n if (wrappedTextIndentLength + columnsForFullWidthChar > firstLineBreakColumn) {\n wrappedTextIndentLength = 0;\n }\n }\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nvar _a;\nimport { createStringBuilder } from '../../common/core/stringBuilder.js';\nimport * as strings from '../../../base/common/strings.js';\nimport { applyFontInfo } from '../config/domFontInfo.js';\nimport { LineInjectedText } from '../../common/textModelEvents.js';\nimport { ModelLineProjectionData } from '../../common/modelLineProjectionData.js';\nconst ttPolicy = (_a = window.trustedTypes) === null || _a === void 0 ? void 0 : _a.createPolicy('domLineBreaksComputer', { createHTML: value => value });\nexport class DOMLineBreaksComputerFactory {\n static create() {\n return new DOMLineBreaksComputerFactory();\n }\n constructor() {\n }\n createLineBreaksComputer(fontInfo, tabSize, wrappingColumn, wrappingIndent) {\n const requests = [];\n const injectedTexts = [];\n return {\n addRequest: (lineText, injectedText, previousLineBreakData) => {\n requests.push(lineText);\n injectedTexts.push(injectedText);\n },\n finalize: () => {\n return createLineBreaks(requests, fontInfo, tabSize, wrappingColumn, wrappingIndent, injectedTexts);\n }\n };\n }\n}\nfunction createLineBreaks(requests, fontInfo, tabSize, firstLineBreakColumn, wrappingIndent, injectedTextsPerLine) {\n var _a;\n function createEmptyLineBreakWithPossiblyInjectedText(requestIdx) {\n const injectedTexts = injectedTextsPerLine[requestIdx];\n if (injectedTexts) {\n const lineText = LineInjectedText.applyInjectedText(requests[requestIdx], injectedTexts);\n const injectionOptions = injectedTexts.map(t => t.options);\n const injectionOffsets = injectedTexts.map(text => text.column - 1);\n // creating a `LineBreakData` with an invalid `breakOffsetsVisibleColumn` is OK\n // because `breakOffsetsVisibleColumn` will never be used because it contains injected text\n return new ModelLineProjectionData(injectionOffsets, injectionOptions, [lineText.length], [], 0);\n }\n else {\n return null;\n }\n }\n if (firstLineBreakColumn === -1) {\n const result = [];\n for (let i = 0, len = requests.length; i < len; i++) {\n result[i] = createEmptyLineBreakWithPossiblyInjectedText(i);\n }\n return result;\n }\n const overallWidth = Math.round(firstLineBreakColumn * fontInfo.typicalHalfwidthCharacterWidth);\n const additionalIndent = (wrappingIndent === 3 /* WrappingIndent.DeepIndent */ ? 2 : wrappingIndent === 2 /* WrappingIndent.Indent */ ? 1 : 0);\n const additionalIndentSize = Math.round(tabSize * additionalIndent);\n const additionalIndentLength = Math.ceil(fontInfo.spaceWidth * additionalIndentSize);\n const containerDomNode = document.createElement('div');\n applyFontInfo(containerDomNode, fontInfo);\n const sb = createStringBuilder(10000);\n const firstNonWhitespaceIndices = [];\n const wrappedTextIndentLengths = [];\n const renderLineContents = [];\n const allCharOffsets = [];\n const allVisibleColumns = [];\n for (let i = 0; i < requests.length; i++) {\n const lineContent = LineInjectedText.applyInjectedText(requests[i], injectedTextsPerLine[i]);\n let firstNonWhitespaceIndex = 0;\n let wrappedTextIndentLength = 0;\n let width = overallWidth;\n if (wrappingIndent !== 0 /* WrappingIndent.None */) {\n firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineContent);\n if (firstNonWhitespaceIndex === -1) {\n // all whitespace line\n firstNonWhitespaceIndex = 0;\n }\n else {\n // Track existing indent\n for (let i = 0; i < firstNonWhitespaceIndex; i++) {\n const charWidth = (lineContent.charCodeAt(i) === 9 /* CharCode.Tab */\n ? (tabSize - (wrappedTextIndentLength % tabSize))\n : 1);\n wrappedTextIndentLength += charWidth;\n }\n const indentWidth = Math.ceil(fontInfo.spaceWidth * wrappedTextIndentLength);\n // Force sticking to beginning of line if no character would fit except for the indentation\n if (indentWidth + fontInfo.typicalFullwidthCharacterWidth > overallWidth) {\n firstNonWhitespaceIndex = 0;\n wrappedTextIndentLength = 0;\n }\n else {\n width = overallWidth - indentWidth;\n }\n }\n }\n const renderLineContent = lineContent.substr(firstNonWhitespaceIndex);\n const tmp = renderLine(renderLineContent, wrappedTextIndentLength, tabSize, width, sb, additionalIndentLength);\n firstNonWhitespaceIndices[i] = firstNonWhitespaceIndex;\n wrappedTextIndentLengths[i] = wrappedTextIndentLength;\n renderLineContents[i] = renderLineContent;\n allCharOffsets[i] = tmp[0];\n allVisibleColumns[i] = tmp[1];\n }\n const html = sb.build();\n const trustedhtml = (_a = ttPolicy === null || ttPolicy === void 0 ? void 0 : ttPolicy.createHTML(html)) !== null && _a !== void 0 ? _a : html;\n containerDomNode.innerHTML = trustedhtml;\n containerDomNode.style.position = 'absolute';\n containerDomNode.style.top = '10000';\n containerDomNode.style.wordWrap = 'break-word';\n document.body.appendChild(containerDomNode);\n const range = document.createRange();\n const lineDomNodes = Array.prototype.slice.call(containerDomNode.children, 0);\n const result = [];\n for (let i = 0; i < requests.length; i++) {\n const lineDomNode = lineDomNodes[i];\n const breakOffsets = readLineBreaks(range, lineDomNode, renderLineContents[i], allCharOffsets[i]);\n if (breakOffsets === null) {\n result[i] = createEmptyLineBreakWithPossiblyInjectedText(i);\n continue;\n }\n const firstNonWhitespaceIndex = firstNonWhitespaceIndices[i];\n const wrappedTextIndentLength = wrappedTextIndentLengths[i] + additionalIndentSize;\n const visibleColumns = allVisibleColumns[i];\n const breakOffsetsVisibleColumn = [];\n for (let j = 0, len = breakOffsets.length; j < len; j++) {\n breakOffsetsVisibleColumn[j] = visibleColumns[breakOffsets[j]];\n }\n if (firstNonWhitespaceIndex !== 0) {\n // All break offsets are relative to the renderLineContent, make them absolute again\n for (let j = 0, len = breakOffsets.length; j < len; j++) {\n breakOffsets[j] += firstNonWhitespaceIndex;\n }\n }\n let injectionOptions;\n let injectionOffsets;\n const curInjectedTexts = injectedTextsPerLine[i];\n if (curInjectedTexts) {\n injectionOptions = curInjectedTexts.map(t => t.options);\n injectionOffsets = curInjectedTexts.map(text => text.column - 1);\n }\n else {\n injectionOptions = null;\n injectionOffsets = null;\n }\n result[i] = new ModelLineProjectionData(injectionOffsets, injectionOptions, breakOffsets, breakOffsetsVisibleColumn, wrappedTextIndentLength);\n }\n document.body.removeChild(containerDomNode);\n return result;\n}\nfunction renderLine(lineContent, initialVisibleColumn, tabSize, width, sb, wrappingIndentLength) {\n if (wrappingIndentLength !== 0) {\n const hangingOffset = String(wrappingIndentLength);\n sb.appendASCIIString('
');\n // if (containsRTL) {\n // \tsb.appendASCIIString('\" dir=\"ltr');\n // }\n const len = lineContent.length;\n let visibleColumn = initialVisibleColumn;\n let charOffset = 0;\n const charOffsets = [];\n const visibleColumns = [];\n let nextCharCode = (0 < len ? lineContent.charCodeAt(0) : 0 /* CharCode.Null */);\n sb.appendASCIIString('');\n for (let charIndex = 0; charIndex < len; charIndex++) {\n if (charIndex !== 0 && charIndex % 16384 /* Constants.SPAN_MODULO_LIMIT */ === 0) {\n sb.appendASCIIString('');\n }\n charOffsets[charIndex] = charOffset;\n visibleColumns[charIndex] = visibleColumn;\n const charCode = nextCharCode;\n nextCharCode = (charIndex + 1 < len ? lineContent.charCodeAt(charIndex + 1) : 0 /* CharCode.Null */);\n let producedCharacters = 1;\n let charWidth = 1;\n switch (charCode) {\n case 9 /* CharCode.Tab */:\n producedCharacters = (tabSize - (visibleColumn % tabSize));\n charWidth = producedCharacters;\n for (let space = 1; space <= producedCharacters; space++) {\n if (space < producedCharacters) {\n sb.write1(0xA0); // \n }\n else {\n sb.appendASCII(32 /* CharCode.Space */);\n }\n }\n break;\n case 32 /* CharCode.Space */:\n if (nextCharCode === 32 /* CharCode.Space */) {\n sb.write1(0xA0); // \n }\n else {\n sb.appendASCII(32 /* CharCode.Space */);\n }\n break;\n case 60 /* CharCode.LessThan */:\n sb.appendASCIIString('<');\n break;\n case 62 /* CharCode.GreaterThan */:\n sb.appendASCIIString('>');\n break;\n case 38 /* CharCode.Ampersand */:\n sb.appendASCIIString('&');\n break;\n case 0 /* CharCode.Null */:\n sb.appendASCIIString('');\n break;\n case 65279 /* CharCode.UTF8_BOM */:\n case 8232 /* CharCode.LINE_SEPARATOR */:\n case 8233 /* CharCode.PARAGRAPH_SEPARATOR */:\n case 133 /* CharCode.NEXT_LINE */:\n sb.write1(0xFFFD);\n break;\n default:\n if (strings.isFullWidthCharacter(charCode)) {\n charWidth++;\n }\n if (charCode < 32) {\n sb.write1(9216 + charCode);\n }\n else {\n sb.write1(charCode);\n }\n }\n charOffset += producedCharacters;\n visibleColumn += charWidth;\n }\n sb.appendASCIIString('');\n charOffsets[lineContent.length] = charOffset;\n visibleColumns[lineContent.length] = visibleColumn;\n sb.appendASCIIString('
');\n return [charOffsets, visibleColumns];\n}\nfunction readLineBreaks(range, lineDomNode, lineContent, charOffsets) {\n if (lineContent.length <= 1) {\n return null;\n }\n const spans = Array.prototype.slice.call(lineDomNode.children, 0);\n const breakOffsets = [];\n try {\n discoverBreaks(range, spans, charOffsets, 0, null, lineContent.length - 1, null, breakOffsets);\n }\n catch (err) {\n console.log(err);\n return null;\n }\n if (breakOffsets.length === 0) {\n return null;\n }\n breakOffsets.push(lineContent.length);\n return breakOffsets;\n}\nfunction discoverBreaks(range, spans, charOffsets, low, lowRects, high, highRects, result) {\n if (low === high) {\n return;\n }\n lowRects = lowRects || readClientRect(range, spans, charOffsets[low], charOffsets[low + 1]);\n highRects = highRects || readClientRect(range, spans, charOffsets[high], charOffsets[high + 1]);\n if (Math.abs(lowRects[0].top - highRects[0].top) <= 0.1) {\n // same line\n return;\n }\n // there is at least one line break between these two offsets\n if (low + 1 === high) {\n // the two characters are adjacent, so the line break must be exactly between them\n result.push(high);\n return;\n }\n const mid = low + ((high - low) / 2) | 0;\n const midRects = readClientRect(range, spans, charOffsets[mid], charOffsets[mid + 1]);\n discoverBreaks(range, spans, charOffsets, low, lowRects, mid, midRects, result);\n discoverBreaks(range, spans, charOffsets, mid, midRects, high, highRects, result);\n}\nfunction readClientRect(range, spans, startOffset, endOffset) {\n range.setStart(spans[(startOffset / 16384 /* Constants.SPAN_MODULO_LIMIT */) | 0].firstChild, startOffset % 16384 /* Constants.SPAN_MODULO_LIMIT */);\n range.setEnd(spans[(endOffset / 16384 /* Constants.SPAN_MODULO_LIMIT */) | 0].firstChild, endOffset % 16384 /* Constants.SPAN_MODULO_LIMIT */);\n return 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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport '../services/markerDecorations.js';\nimport './media/editor.css';\nimport * as nls from '../../../nls.js';\nimport * as dom from '../../../base/browser/dom.js';\nimport { onUnexpectedError } from '../../../base/common/errors.js';\nimport { Emitter, EventDeliveryQueue } from '../../../base/common/event.js';\nimport { Disposable, dispose } from '../../../base/common/lifecycle.js';\nimport { Schemas } from '../../../base/common/network.js';\nimport { EditorConfiguration } from '../config/editorConfiguration.js';\nimport { EditorExtensionsRegistry } from '../editorExtensions.js';\nimport { ICodeEditorService } from '../services/codeEditorService.js';\nimport { View } from '../view.js';\nimport { ViewUserInputEvents } from '../view/viewUserInputEvents.js';\nimport { filterValidationDecorations } from '../../common/config/editorOptions.js';\nimport { CursorsController } from '../../common/cursor/cursor.js';\nimport { CursorColumns } from '../../common/core/cursorColumns.js';\nimport { Position } from '../../common/core/position.js';\nimport { Range } from '../../common/core/range.js';\nimport { Selection } from '../../common/core/selection.js';\nimport { InternalEditorAction } from '../../common/editorAction.js';\nimport * as editorCommon from '../../common/editorCommon.js';\nimport { EditorContextKeys } from '../../common/editorContextKeys.js';\nimport { ModelDecorationOptions } from '../../common/model/textModel.js';\nimport { editorUnnecessaryCodeBorder, editorUnnecessaryCodeOpacity } from '../../common/core/editorColorRegistry.js';\nimport { editorErrorBorder, editorErrorForeground, editorHintBorder, editorHintForeground, editorInfoBorder, editorInfoForeground, editorWarningBorder, editorWarningForeground, editorForeground, editorErrorBackground, editorInfoBackground, editorWarningBackground } from '../../../platform/theme/common/colorRegistry.js';\nimport { ViewModel } from '../../common/viewModel/viewModelImpl.js';\nimport { ICommandService } from '../../../platform/commands/common/commands.js';\nimport { IContextKeyService } from '../../../platform/contextkey/common/contextkey.js';\nimport { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';\nimport { ServiceCollection } from '../../../platform/instantiation/common/serviceCollection.js';\nimport { INotificationService } from '../../../platform/notification/common/notification.js';\nimport { IThemeService, registerThemingParticipant } from '../../../platform/theme/common/themeService.js';\nimport { IAccessibilityService } from '../../../platform/accessibility/common/accessibility.js';\nimport { withNullAsUndefined } from '../../../base/common/types.js';\nimport { MonospaceLineBreaksComputerFactory } from '../../common/viewModel/monospaceLineBreaksComputer.js';\nimport { DOMLineBreaksComputerFactory } from '../view/domLineBreaksComputer.js';\nimport { WordOperations } from '../../common/cursor/cursorWordOperations.js';\nimport { ILanguageConfigurationService } from '../../common/languages/languageConfigurationRegistry.js';\nimport { applyFontInfo } from '../config/domFontInfo.js';\nimport { ILanguageFeaturesService } from '../../common/services/languageFeatures.js';\nlet EDITOR_ID = 0;\nclass ModelData {\n constructor(model, viewModel, view, hasRealView, listenersToRemove) {\n this.model = model;\n this.viewModel = viewModel;\n this.view = view;\n this.hasRealView = hasRealView;\n this.listenersToRemove = listenersToRemove;\n }\n dispose() {\n dispose(this.listenersToRemove);\n this.model.onBeforeDetached();\n if (this.hasRealView) {\n this.view.dispose();\n }\n this.viewModel.dispose();\n }\n}\nlet CodeEditorWidget = class CodeEditorWidget extends Disposable {\n constructor(domElement, _options, codeEditorWidgetOptions, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService, languageFeaturesService) {\n super();\n this.languageConfigurationService = languageConfigurationService;\n //#region Eventing\n this._deliveryQueue = new EventDeliveryQueue();\n this._onDidDispose = this._register(new Emitter());\n this.onDidDispose = this._onDidDispose.event;\n this._onDidChangeModelContent = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeModelContent = this._onDidChangeModelContent.event;\n this._onDidChangeModelLanguage = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeModelLanguage = this._onDidChangeModelLanguage.event;\n this._onDidChangeModelLanguageConfiguration = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeModelLanguageConfiguration = this._onDidChangeModelLanguageConfiguration.event;\n this._onDidChangeModelOptions = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeModelOptions = this._onDidChangeModelOptions.event;\n this._onDidChangeModelDecorations = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeModelDecorations = this._onDidChangeModelDecorations.event;\n this._onDidChangeModelTokens = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeModelTokens = this._onDidChangeModelTokens.event;\n this._onDidChangeConfiguration = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeConfiguration = this._onDidChangeConfiguration.event;\n this._onDidChangeModel = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeModel = this._onDidChangeModel.event;\n this._onDidChangeCursorPosition = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeCursorPosition = this._onDidChangeCursorPosition.event;\n this._onDidChangeCursorSelection = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeCursorSelection = this._onDidChangeCursorSelection.event;\n this._onDidAttemptReadOnlyEdit = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidAttemptReadOnlyEdit = this._onDidAttemptReadOnlyEdit.event;\n this._onDidLayoutChange = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidLayoutChange = this._onDidLayoutChange.event;\n this._editorTextFocus = this._register(new BooleanEventEmitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidFocusEditorText = this._editorTextFocus.onDidChangeToTrue;\n this.onDidBlurEditorText = this._editorTextFocus.onDidChangeToFalse;\n this._editorWidgetFocus = this._register(new BooleanEventEmitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidFocusEditorWidget = this._editorWidgetFocus.onDidChangeToTrue;\n this.onDidBlurEditorWidget = this._editorWidgetFocus.onDidChangeToFalse;\n this._onWillType = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onWillType = this._onWillType.event;\n this._onDidType = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidType = this._onDidType.event;\n this._onDidCompositionStart = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidCompositionStart = this._onDidCompositionStart.event;\n this._onDidCompositionEnd = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidCompositionEnd = this._onDidCompositionEnd.event;\n this._onDidPaste = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidPaste = this._onDidPaste.event;\n this._onMouseUp = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onMouseUp = this._onMouseUp.event;\n this._onMouseDown = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onMouseDown = this._onMouseDown.event;\n this._onMouseDrag = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onMouseDrag = this._onMouseDrag.event;\n this._onMouseDrop = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onMouseDrop = this._onMouseDrop.event;\n this._onMouseDropCanceled = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onMouseDropCanceled = this._onMouseDropCanceled.event;\n this._onDropIntoEditor = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDropIntoEditor = this._onDropIntoEditor.event;\n this._onContextMenu = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onContextMenu = this._onContextMenu.event;\n this._onMouseMove = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onMouseMove = this._onMouseMove.event;\n this._onMouseLeave = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onMouseLeave = this._onMouseLeave.event;\n this._onMouseWheel = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onMouseWheel = this._onMouseWheel.event;\n this._onKeyUp = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onKeyUp = this._onKeyUp.event;\n this._onKeyDown = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onKeyDown = this._onKeyDown.event;\n this._onDidContentSizeChange = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidContentSizeChange = this._onDidContentSizeChange.event;\n this._onDidScrollChange = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidScrollChange = this._onDidScrollChange.event;\n this._onDidChangeViewZones = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeViewZones = this._onDidChangeViewZones.event;\n this._onDidChangeHiddenAreas = this._register(new Emitter({ deliveryQueue: this._deliveryQueue }));\n this.onDidChangeHiddenAreas = this._onDidChangeHiddenAreas.event;\n this._bannerDomNode = null;\n this._dropIntoEditorDecorations = this.createDecorationsCollection();\n const options = Object.assign({}, _options);\n this._domElement = domElement;\n this._overflowWidgetsDomNode = options.overflowWidgetsDomNode;\n delete options.overflowWidgetsDomNode;\n this._id = (++EDITOR_ID);\n this._decorationTypeKeysToIds = {};\n this._decorationTypeSubtypes = {};\n this._telemetryData = codeEditorWidgetOptions.telemetryData;\n this._configuration = this._register(this._createConfiguration(codeEditorWidgetOptions.isSimpleWidget || false, options, accessibilityService));\n this._register(this._configuration.onDidChange((e) => {\n this._onDidChangeConfiguration.fire(e);\n const options = this._configuration.options;\n if (e.hasChanged(133 /* EditorOption.layoutInfo */)) {\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n this._onDidLayoutChange.fire(layoutInfo);\n }\n }));\n this._contextKeyService = this._register(contextKeyService.createScoped(this._domElement));\n this._notificationService = notificationService;\n this._codeEditorService = codeEditorService;\n this._commandService = commandService;\n this._themeService = themeService;\n this._register(new EditorContextKeysManager(this, this._contextKeyService));\n this._register(new EditorModeContext(this, this._contextKeyService, languageFeaturesService));\n this._instantiationService = instantiationService.createChild(new ServiceCollection([IContextKeyService, this._contextKeyService]));\n this._modelData = null;\n this._contributions = {};\n this._actions = {};\n this._focusTracker = new CodeEditorWidgetFocusTracker(domElement);\n this._register(this._focusTracker.onChange(() => {\n this._editorWidgetFocus.setValue(this._focusTracker.hasFocus());\n }));\n this._contentWidgets = {};\n this._overlayWidgets = {};\n let contributions;\n if (Array.isArray(codeEditorWidgetOptions.contributions)) {\n contributions = codeEditorWidgetOptions.contributions;\n }\n else {\n contributions = EditorExtensionsRegistry.getEditorContributions();\n }\n for (const desc of contributions) {\n if (this._contributions[desc.id]) {\n onUnexpectedError(new Error(`Cannot have two contributions with the same id ${desc.id}`));\n continue;\n }\n try {\n const contribution = this._instantiationService.createInstance(desc.ctor, this);\n this._contributions[desc.id] = contribution;\n }\n catch (err) {\n onUnexpectedError(err);\n }\n }\n EditorExtensionsRegistry.getEditorActions().forEach((action) => {\n if (this._actions[action.id]) {\n onUnexpectedError(new Error(`Cannot have two actions with the same id ${action.id}`));\n return;\n }\n const internalAction = new InternalEditorAction(action.id, action.label, action.alias, withNullAsUndefined(action.precondition), () => {\n return this._instantiationService.invokeFunction((accessor) => {\n return Promise.resolve(action.runEditorCommand(accessor, this, null));\n });\n }, this._contextKeyService);\n this._actions[internalAction.id] = internalAction;\n });\n const isDropIntoEnabled = () => {\n return !this._configuration.options.get(83 /* EditorOption.readOnly */)\n && this._configuration.options.get(32 /* EditorOption.dropIntoEditor */).enabled;\n };\n this._register(new dom.DragAndDropObserver(this._domElement, {\n onDragEnter: () => undefined,\n onDragOver: e => {\n if (!isDropIntoEnabled()) {\n return;\n }\n const target = this.getTargetAtClientPoint(e.clientX, e.clientY);\n if (target === null || target === void 0 ? void 0 : target.position) {\n this.showDropIndicatorAt(target.position);\n }\n },\n onDrop: (e) => __awaiter(this, void 0, void 0, function* () {\n if (!isDropIntoEnabled()) {\n return;\n }\n this.removeDropIndicator();\n if (!e.dataTransfer) {\n return;\n }\n const target = this.getTargetAtClientPoint(e.clientX, e.clientY);\n if (target === null || target === void 0 ? void 0 : target.position) {\n this._onDropIntoEditor.fire({ position: target.position, event: e });\n }\n }),\n onDragLeave: () => {\n this.removeDropIndicator();\n },\n onDragEnd: () => {\n this.removeDropIndicator();\n },\n }));\n this._codeEditorService.addCodeEditor(this);\n }\n //#endregion\n get isSimpleWidget() {\n return this._configuration.isSimpleWidget;\n }\n _createConfiguration(isSimpleWidget, options, accessibilityService) {\n return new EditorConfiguration(isSimpleWidget, options, this._domElement, accessibilityService);\n }\n getId() {\n return this.getEditorType() + ':' + this._id;\n }\n getEditorType() {\n return editorCommon.EditorType.ICodeEditor;\n }\n dispose() {\n this._codeEditorService.removeCodeEditor(this);\n this._focusTracker.dispose();\n const keys = Object.keys(this._contributions);\n for (let i = 0, len = keys.length; i < len; i++) {\n const contributionId = keys[i];\n this._contributions[contributionId].dispose();\n }\n this._contributions = {};\n this._actions = {};\n this._contentWidgets = {};\n this._overlayWidgets = {};\n this._removeDecorationTypes();\n this._postDetachModelCleanup(this._detachModel());\n this._onDidDispose.fire();\n super.dispose();\n }\n invokeWithinContext(fn) {\n return this._instantiationService.invokeFunction(fn);\n }\n updateOptions(newOptions) {\n this._configuration.updateOptions(newOptions || {});\n }\n getOptions() {\n return this._configuration.options;\n }\n getOption(id) {\n return this._configuration.options.get(id);\n }\n getRawOptions() {\n return this._configuration.getRawOptions();\n }\n getOverflowWidgetsDomNode() {\n return this._overflowWidgetsDomNode;\n }\n getConfiguredWordAtPosition(position) {\n if (!this._modelData) {\n return null;\n }\n return WordOperations.getWordAtPosition(this._modelData.model, this._configuration.options.get(119 /* EditorOption.wordSeparators */), position);\n }\n getValue(options = null) {\n if (!this._modelData) {\n return '';\n }\n const preserveBOM = (options && options.preserveBOM) ? true : false;\n let eolPreference = 0 /* EndOfLinePreference.TextDefined */;\n if (options && options.lineEnding && options.lineEnding === '\\n') {\n eolPreference = 1 /* EndOfLinePreference.LF */;\n }\n else if (options && options.lineEnding && options.lineEnding === '\\r\\n') {\n eolPreference = 2 /* EndOfLinePreference.CRLF */;\n }\n return this._modelData.model.getValue(eolPreference, preserveBOM);\n }\n setValue(newValue) {\n if (!this._modelData) {\n return;\n }\n this._modelData.model.setValue(newValue);\n }\n getModel() {\n if (!this._modelData) {\n return null;\n }\n return this._modelData.model;\n }\n setModel(_model = null) {\n const model = _model;\n if (this._modelData === null && model === null) {\n // Current model is the new model\n return;\n }\n if (this._modelData && this._modelData.model === model) {\n // Current model is the new model\n return;\n }\n const hasTextFocus = this.hasTextFocus();\n const detachedModel = this._detachModel();\n this._attachModel(model);\n if (hasTextFocus && this.hasModel()) {\n this.focus();\n }\n const e = {\n oldModelUrl: detachedModel ? detachedModel.uri : null,\n newModelUrl: model ? model.uri : null\n };\n this._removeDecorationTypes();\n this._onDidChangeModel.fire(e);\n this._postDetachModelCleanup(detachedModel);\n }\n _removeDecorationTypes() {\n this._decorationTypeKeysToIds = {};\n if (this._decorationTypeSubtypes) {\n for (const decorationType in this._decorationTypeSubtypes) {\n const subTypes = this._decorationTypeSubtypes[decorationType];\n for (const subType in subTypes) {\n this._removeDecorationType(decorationType + '-' + subType);\n }\n }\n this._decorationTypeSubtypes = {};\n }\n }\n getVisibleRanges() {\n if (!this._modelData) {\n return [];\n }\n return this._modelData.viewModel.getVisibleRanges();\n }\n getVisibleRangesPlusViewportAboveBelow() {\n if (!this._modelData) {\n return [];\n }\n return this._modelData.viewModel.getVisibleRangesPlusViewportAboveBelow();\n }\n getWhitespaces() {\n if (!this._modelData) {\n return [];\n }\n return this._modelData.viewModel.viewLayout.getWhitespaces();\n }\n static _getVerticalOffsetAfterPosition(modelData, modelLineNumber, modelColumn, includeViewZones) {\n const modelPosition = modelData.model.validatePosition({\n lineNumber: modelLineNumber,\n column: modelColumn\n });\n const viewPosition = modelData.viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);\n return modelData.viewModel.viewLayout.getVerticalOffsetAfterLineNumber(viewPosition.lineNumber, includeViewZones);\n }\n getTopForLineNumber(lineNumber, includeViewZones = false) {\n if (!this._modelData) {\n return -1;\n }\n return CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, lineNumber, 1, includeViewZones);\n }\n getTopForPosition(lineNumber, column) {\n if (!this._modelData) {\n return -1;\n }\n return CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, lineNumber, column, false);\n }\n static _getVerticalOffsetForPosition(modelData, modelLineNumber, modelColumn, includeViewZones = false) {\n const modelPosition = modelData.model.validatePosition({\n lineNumber: modelLineNumber,\n column: modelColumn\n });\n const viewPosition = modelData.viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);\n return modelData.viewModel.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber, includeViewZones);\n }\n getBottomForLineNumber(lineNumber, includeViewZones = false) {\n if (!this._modelData) {\n return -1;\n }\n return CodeEditorWidget._getVerticalOffsetAfterPosition(this._modelData, lineNumber, 1, includeViewZones);\n }\n setHiddenAreas(ranges) {\n var _a;\n (_a = this._modelData) === null || _a === void 0 ? void 0 : _a.viewModel.setHiddenAreas(ranges.map(r => Range.lift(r)));\n }\n getVisibleColumnFromPosition(rawPosition) {\n if (!this._modelData) {\n return rawPosition.column;\n }\n const position = this._modelData.model.validatePosition(rawPosition);\n const tabSize = this._modelData.model.getOptions().tabSize;\n return CursorColumns.visibleColumnFromColumn(this._modelData.model.getLineContent(position.lineNumber), position.column, tabSize) + 1;\n }\n getPosition() {\n if (!this._modelData) {\n return null;\n }\n return this._modelData.viewModel.getPosition();\n }\n setPosition(position, source = 'api') {\n if (!this._modelData) {\n return;\n }\n if (!Position.isIPosition(position)) {\n throw new Error('Invalid arguments');\n }\n this._modelData.viewModel.setSelections(source, [{\n selectionStartLineNumber: position.lineNumber,\n selectionStartColumn: position.column,\n positionLineNumber: position.lineNumber,\n positionColumn: position.column\n }]);\n }\n _sendRevealRange(modelRange, verticalType, revealHorizontal, scrollType) {\n if (!this._modelData) {\n return;\n }\n if (!Range.isIRange(modelRange)) {\n throw new Error('Invalid arguments');\n }\n const validatedModelRange = this._modelData.model.validateRange(modelRange);\n const viewRange = this._modelData.viewModel.coordinatesConverter.convertModelRangeToViewRange(validatedModelRange);\n this._modelData.viewModel.revealRange('api', revealHorizontal, viewRange, verticalType, scrollType);\n }\n revealLine(lineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealLine(lineNumber, 0 /* VerticalRevealType.Simple */, scrollType);\n }\n revealLineInCenter(lineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealLine(lineNumber, 1 /* VerticalRevealType.Center */, scrollType);\n }\n revealLineInCenterIfOutsideViewport(lineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealLine(lineNumber, 2 /* VerticalRevealType.CenterIfOutsideViewport */, scrollType);\n }\n revealLineNearTop(lineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealLine(lineNumber, 5 /* VerticalRevealType.NearTop */, scrollType);\n }\n _revealLine(lineNumber, revealType, scrollType) {\n if (typeof lineNumber !== 'number') {\n throw new Error('Invalid arguments');\n }\n this._sendRevealRange(new Range(lineNumber, 1, lineNumber, 1), revealType, false, scrollType);\n }\n revealPosition(position, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealPosition(position, 0 /* VerticalRevealType.Simple */, true, scrollType);\n }\n revealPositionInCenter(position, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealPosition(position, 1 /* VerticalRevealType.Center */, true, scrollType);\n }\n revealPositionInCenterIfOutsideViewport(position, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealPosition(position, 2 /* VerticalRevealType.CenterIfOutsideViewport */, true, scrollType);\n }\n revealPositionNearTop(position, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealPosition(position, 5 /* VerticalRevealType.NearTop */, true, scrollType);\n }\n _revealPosition(position, verticalType, revealHorizontal, scrollType) {\n if (!Position.isIPosition(position)) {\n throw new Error('Invalid arguments');\n }\n this._sendRevealRange(new Range(position.lineNumber, position.column, position.lineNumber, position.column), verticalType, revealHorizontal, scrollType);\n }\n getSelection() {\n if (!this._modelData) {\n return null;\n }\n return this._modelData.viewModel.getSelection();\n }\n getSelections() {\n if (!this._modelData) {\n return null;\n }\n return this._modelData.viewModel.getSelections();\n }\n setSelection(something, source = 'api') {\n const isSelection = Selection.isISelection(something);\n const isRange = Range.isIRange(something);\n if (!isSelection && !isRange) {\n throw new Error('Invalid arguments');\n }\n if (isSelection) {\n this._setSelectionImpl(something, source);\n }\n else if (isRange) {\n // act as if it was an IRange\n const selection = {\n selectionStartLineNumber: something.startLineNumber,\n selectionStartColumn: something.startColumn,\n positionLineNumber: something.endLineNumber,\n positionColumn: something.endColumn\n };\n this._setSelectionImpl(selection, source);\n }\n }\n _setSelectionImpl(sel, source) {\n if (!this._modelData) {\n return;\n }\n const selection = new Selection(sel.selectionStartLineNumber, sel.selectionStartColumn, sel.positionLineNumber, sel.positionColumn);\n this._modelData.viewModel.setSelections(source, [selection]);\n }\n revealLines(startLineNumber, endLineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealLines(startLineNumber, endLineNumber, 0 /* VerticalRevealType.Simple */, scrollType);\n }\n revealLinesInCenter(startLineNumber, endLineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealLines(startLineNumber, endLineNumber, 1 /* VerticalRevealType.Center */, scrollType);\n }\n revealLinesInCenterIfOutsideViewport(startLineNumber, endLineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealLines(startLineNumber, endLineNumber, 2 /* VerticalRevealType.CenterIfOutsideViewport */, scrollType);\n }\n revealLinesNearTop(startLineNumber, endLineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealLines(startLineNumber, endLineNumber, 5 /* VerticalRevealType.NearTop */, scrollType);\n }\n _revealLines(startLineNumber, endLineNumber, verticalType, scrollType) {\n if (typeof startLineNumber !== 'number' || typeof endLineNumber !== 'number') {\n throw new Error('Invalid arguments');\n }\n this._sendRevealRange(new Range(startLineNumber, 1, endLineNumber, 1), verticalType, false, scrollType);\n }\n revealRange(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */, revealVerticalInCenter = false, revealHorizontal = true) {\n this._revealRange(range, revealVerticalInCenter ? 1 /* VerticalRevealType.Center */ : 0 /* VerticalRevealType.Simple */, revealHorizontal, scrollType);\n }\n revealRangeInCenter(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealRange(range, 1 /* VerticalRevealType.Center */, true, scrollType);\n }\n revealRangeInCenterIfOutsideViewport(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealRange(range, 2 /* VerticalRevealType.CenterIfOutsideViewport */, true, scrollType);\n }\n revealRangeNearTop(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealRange(range, 5 /* VerticalRevealType.NearTop */, true, scrollType);\n }\n revealRangeNearTopIfOutsideViewport(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealRange(range, 6 /* VerticalRevealType.NearTopIfOutsideViewport */, true, scrollType);\n }\n revealRangeAtTop(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._revealRange(range, 3 /* VerticalRevealType.Top */, true, scrollType);\n }\n _revealRange(range, verticalType, revealHorizontal, scrollType) {\n if (!Range.isIRange(range)) {\n throw new Error('Invalid arguments');\n }\n this._sendRevealRange(Range.lift(range), verticalType, revealHorizontal, scrollType);\n }\n setSelections(ranges, source = 'api', reason = 0 /* CursorChangeReason.NotSet */) {\n if (!this._modelData) {\n return;\n }\n if (!ranges || ranges.length === 0) {\n throw new Error('Invalid arguments');\n }\n for (let i = 0, len = ranges.length; i < len; i++) {\n if (!Selection.isISelection(ranges[i])) {\n throw new Error('Invalid arguments');\n }\n }\n this._modelData.viewModel.setSelections(source, ranges, reason);\n }\n getContentWidth() {\n if (!this._modelData) {\n return -1;\n }\n return this._modelData.viewModel.viewLayout.getContentWidth();\n }\n getScrollWidth() {\n if (!this._modelData) {\n return -1;\n }\n return this._modelData.viewModel.viewLayout.getScrollWidth();\n }\n getScrollLeft() {\n if (!this._modelData) {\n return -1;\n }\n return this._modelData.viewModel.viewLayout.getCurrentScrollLeft();\n }\n getContentHeight() {\n if (!this._modelData) {\n return -1;\n }\n return this._modelData.viewModel.viewLayout.getContentHeight();\n }\n getScrollHeight() {\n if (!this._modelData) {\n return -1;\n }\n return this._modelData.viewModel.viewLayout.getScrollHeight();\n }\n getScrollTop() {\n if (!this._modelData) {\n return -1;\n }\n return this._modelData.viewModel.viewLayout.getCurrentScrollTop();\n }\n setScrollLeft(newScrollLeft, scrollType = 1 /* editorCommon.ScrollType.Immediate */) {\n if (!this._modelData) {\n return;\n }\n if (typeof newScrollLeft !== 'number') {\n throw new Error('Invalid arguments');\n }\n this._modelData.viewModel.viewLayout.setScrollPosition({\n scrollLeft: newScrollLeft\n }, scrollType);\n }\n setScrollTop(newScrollTop, scrollType = 1 /* editorCommon.ScrollType.Immediate */) {\n if (!this._modelData) {\n return;\n }\n if (typeof newScrollTop !== 'number') {\n throw new Error('Invalid arguments');\n }\n this._modelData.viewModel.viewLayout.setScrollPosition({\n scrollTop: newScrollTop\n }, scrollType);\n }\n setScrollPosition(position, scrollType = 1 /* editorCommon.ScrollType.Immediate */) {\n if (!this._modelData) {\n return;\n }\n this._modelData.viewModel.viewLayout.setScrollPosition(position, scrollType);\n }\n saveViewState() {\n if (!this._modelData) {\n return null;\n }\n const contributionsState = {};\n const keys = Object.keys(this._contributions);\n for (const id of keys) {\n const contribution = this._contributions[id];\n if (typeof contribution.saveViewState === 'function') {\n contributionsState[id] = contribution.saveViewState();\n }\n }\n const cursorState = this._modelData.viewModel.saveCursorState();\n const viewState = this._modelData.viewModel.saveState();\n return {\n cursorState: cursorState,\n viewState: viewState,\n contributionsState: contributionsState\n };\n }\n restoreViewState(s) {\n if (!this._modelData || !this._modelData.hasRealView) {\n return;\n }\n const codeEditorState = s;\n if (codeEditorState && codeEditorState.cursorState && codeEditorState.viewState) {\n const cursorState = codeEditorState.cursorState;\n if (Array.isArray(cursorState)) {\n if (cursorState.length > 0) {\n this._modelData.viewModel.restoreCursorState(cursorState);\n }\n }\n else {\n // Backwards compatibility\n this._modelData.viewModel.restoreCursorState([cursorState]);\n }\n const contributionsState = codeEditorState.contributionsState || {};\n const keys = Object.keys(this._contributions);\n for (let i = 0, len = keys.length; i < len; i++) {\n const id = keys[i];\n const contribution = this._contributions[id];\n if (typeof contribution.restoreViewState === 'function') {\n contribution.restoreViewState(contributionsState[id]);\n }\n }\n const reducedState = this._modelData.viewModel.reduceRestoreState(codeEditorState.viewState);\n this._modelData.view.restoreState(reducedState);\n }\n }\n getContribution(id) {\n return (this._contributions[id] || null);\n }\n getActions() {\n const result = [];\n const keys = Object.keys(this._actions);\n for (let i = 0, len = keys.length; i < len; i++) {\n const id = keys[i];\n result.push(this._actions[id]);\n }\n return result;\n }\n getSupportedActions() {\n let result = this.getActions();\n result = result.filter(action => action.isSupported());\n return result;\n }\n getAction(id) {\n return this._actions[id] || null;\n }\n trigger(source, handlerId, payload) {\n payload = payload || {};\n switch (handlerId) {\n case \"compositionStart\" /* editorCommon.Handler.CompositionStart */:\n this._startComposition();\n return;\n case \"compositionEnd\" /* editorCommon.Handler.CompositionEnd */:\n this._endComposition(source);\n return;\n case \"type\" /* editorCommon.Handler.Type */: {\n const args = payload;\n this._type(source, args.text || '');\n return;\n }\n case \"replacePreviousChar\" /* editorCommon.Handler.ReplacePreviousChar */: {\n const args = payload;\n this._compositionType(source, args.text || '', args.replaceCharCnt || 0, 0, 0);\n return;\n }\n case \"compositionType\" /* editorCommon.Handler.CompositionType */: {\n const args = payload;\n this._compositionType(source, args.text || '', args.replacePrevCharCnt || 0, args.replaceNextCharCnt || 0, args.positionDelta || 0);\n return;\n }\n case \"paste\" /* editorCommon.Handler.Paste */: {\n const args = payload;\n this._paste(source, args.text || '', args.pasteOnNewLine || false, args.multicursorText || null, args.mode || null);\n return;\n }\n case \"cut\" /* editorCommon.Handler.Cut */:\n this._cut(source);\n return;\n }\n const action = this.getAction(handlerId);\n if (action) {\n Promise.resolve(action.run()).then(undefined, onUnexpectedError);\n return;\n }\n if (!this._modelData) {\n return;\n }\n if (this._triggerEditorCommand(source, handlerId, payload)) {\n return;\n }\n this._triggerCommand(handlerId, payload);\n }\n _triggerCommand(handlerId, payload) {\n this._commandService.executeCommand(handlerId, payload);\n }\n _startComposition() {\n if (!this._modelData) {\n return;\n }\n this._modelData.viewModel.startComposition();\n this._onDidCompositionStart.fire();\n }\n _endComposition(source) {\n if (!this._modelData) {\n return;\n }\n this._modelData.viewModel.endComposition(source);\n this._onDidCompositionEnd.fire();\n }\n _type(source, text) {\n if (!this._modelData || text.length === 0) {\n return;\n }\n if (source === 'keyboard') {\n this._onWillType.fire(text);\n }\n this._modelData.viewModel.type(text, source);\n if (source === 'keyboard') {\n this._onDidType.fire(text);\n }\n }\n _compositionType(source, text, replacePrevCharCnt, replaceNextCharCnt, positionDelta) {\n if (!this._modelData) {\n return;\n }\n this._modelData.viewModel.compositionType(text, replacePrevCharCnt, replaceNextCharCnt, positionDelta, source);\n }\n _paste(source, text, pasteOnNewLine, multicursorText, mode) {\n if (!this._modelData || text.length === 0) {\n return;\n }\n const viewModel = this._modelData.viewModel;\n const startPosition = viewModel.getSelection().getStartPosition();\n viewModel.paste(text, pasteOnNewLine, multicursorText, source);\n const endPosition = viewModel.getSelection().getStartPosition();\n if (source === 'keyboard') {\n this._onDidPaste.fire({\n range: new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column),\n languageId: mode\n });\n }\n }\n _cut(source) {\n if (!this._modelData) {\n return;\n }\n this._modelData.viewModel.cut(source);\n }\n _triggerEditorCommand(source, handlerId, payload) {\n const command = EditorExtensionsRegistry.getEditorCommand(handlerId);\n if (command) {\n payload = payload || {};\n payload.source = source;\n this._instantiationService.invokeFunction((accessor) => {\n Promise.resolve(command.runEditorCommand(accessor, this, payload)).then(undefined, onUnexpectedError);\n });\n return true;\n }\n return false;\n }\n _getViewModel() {\n if (!this._modelData) {\n return null;\n }\n return this._modelData.viewModel;\n }\n pushUndoStop() {\n if (!this._modelData) {\n return false;\n }\n if (this._configuration.options.get(83 /* EditorOption.readOnly */)) {\n // read only editor => sorry!\n return false;\n }\n this._modelData.model.pushStackElement();\n return true;\n }\n popUndoStop() {\n if (!this._modelData) {\n return false;\n }\n if (this._configuration.options.get(83 /* EditorOption.readOnly */)) {\n // read only editor => sorry!\n return false;\n }\n this._modelData.model.popStackElement();\n return true;\n }\n executeEdits(source, edits, endCursorState) {\n if (!this._modelData) {\n return false;\n }\n if (this._configuration.options.get(83 /* EditorOption.readOnly */)) {\n // read only editor => sorry!\n return false;\n }\n let cursorStateComputer;\n if (!endCursorState) {\n cursorStateComputer = () => null;\n }\n else if (Array.isArray(endCursorState)) {\n cursorStateComputer = () => endCursorState;\n }\n else {\n cursorStateComputer = endCursorState;\n }\n this._modelData.viewModel.executeEdits(source, edits, cursorStateComputer);\n return true;\n }\n executeCommand(source, command) {\n if (!this._modelData) {\n return;\n }\n this._modelData.viewModel.executeCommand(command, source);\n }\n executeCommands(source, commands) {\n if (!this._modelData) {\n return;\n }\n this._modelData.viewModel.executeCommands(commands, source);\n }\n createDecorationsCollection(decorations) {\n return new EditorDecorationsCollection(this, decorations);\n }\n changeDecorations(callback) {\n if (!this._modelData) {\n // callback will not be called\n return null;\n }\n return this._modelData.model.changeDecorations(callback, this._id);\n }\n getLineDecorations(lineNumber) {\n if (!this._modelData) {\n return null;\n }\n return this._modelData.model.getLineDecorations(lineNumber, this._id, filterValidationDecorations(this._configuration.options));\n }\n getDecorationsInRange(range) {\n if (!this._modelData) {\n return null;\n }\n return this._modelData.model.getDecorationsInRange(range, this._id, filterValidationDecorations(this._configuration.options));\n }\n /**\n * @deprecated\n */\n deltaDecorations(oldDecorations, newDecorations) {\n if (!this._modelData) {\n return [];\n }\n if (oldDecorations.length === 0 && newDecorations.length === 0) {\n return oldDecorations;\n }\n return this._modelData.model.deltaDecorations(oldDecorations, newDecorations, this._id);\n }\n removeDecorations(decorationIds) {\n if (!this._modelData || decorationIds.length === 0) {\n return;\n }\n this._modelData.model.changeDecorations((changeAccessor) => {\n changeAccessor.deltaDecorations(decorationIds, []);\n });\n }\n removeDecorationsByType(decorationTypeKey) {\n // remove decorations for type and sub type\n const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey];\n if (oldDecorationsIds) {\n this.deltaDecorations(oldDecorationsIds, []);\n }\n if (this._decorationTypeKeysToIds.hasOwnProperty(decorationTypeKey)) {\n delete this._decorationTypeKeysToIds[decorationTypeKey];\n }\n if (this._decorationTypeSubtypes.hasOwnProperty(decorationTypeKey)) {\n delete this._decorationTypeSubtypes[decorationTypeKey];\n }\n }\n getLayoutInfo() {\n const options = this._configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n return layoutInfo;\n }\n createOverviewRuler(cssClassName) {\n if (!this._modelData || !this._modelData.hasRealView) {\n return null;\n }\n return this._modelData.view.createOverviewRuler(cssClassName);\n }\n getContainerDomNode() {\n return this._domElement;\n }\n getDomNode() {\n if (!this._modelData || !this._modelData.hasRealView) {\n return null;\n }\n return this._modelData.view.domNode.domNode;\n }\n delegateVerticalScrollbarPointerDown(browserEvent) {\n if (!this._modelData || !this._modelData.hasRealView) {\n return;\n }\n this._modelData.view.delegateVerticalScrollbarPointerDown(browserEvent);\n }\n layout(dimension) {\n this._configuration.observeContainer(dimension);\n this.render();\n }\n focus() {\n if (!this._modelData || !this._modelData.hasRealView) {\n return;\n }\n this._modelData.view.focus();\n }\n hasTextFocus() {\n if (!this._modelData || !this._modelData.hasRealView) {\n return false;\n }\n return this._modelData.view.isFocused();\n }\n hasWidgetFocus() {\n return this._focusTracker && this._focusTracker.hasFocus();\n }\n addContentWidget(widget) {\n const widgetData = {\n widget: widget,\n position: widget.getPosition()\n };\n if (this._contentWidgets.hasOwnProperty(widget.getId())) {\n console.warn('Overwriting a content widget with the same id.');\n }\n this._contentWidgets[widget.getId()] = widgetData;\n if (this._modelData && this._modelData.hasRealView) {\n this._modelData.view.addContentWidget(widgetData);\n }\n }\n layoutContentWidget(widget) {\n const widgetId = widget.getId();\n if (this._contentWidgets.hasOwnProperty(widgetId)) {\n const widgetData = this._contentWidgets[widgetId];\n widgetData.position = widget.getPosition();\n if (this._modelData && this._modelData.hasRealView) {\n this._modelData.view.layoutContentWidget(widgetData);\n }\n }\n }\n removeContentWidget(widget) {\n const widgetId = widget.getId();\n if (this._contentWidgets.hasOwnProperty(widgetId)) {\n const widgetData = this._contentWidgets[widgetId];\n delete this._contentWidgets[widgetId];\n if (this._modelData && this._modelData.hasRealView) {\n this._modelData.view.removeContentWidget(widgetData);\n }\n }\n }\n addOverlayWidget(widget) {\n const widgetData = {\n widget: widget,\n position: widget.getPosition()\n };\n if (this._overlayWidgets.hasOwnProperty(widget.getId())) {\n console.warn('Overwriting an overlay widget with the same id.');\n }\n this._overlayWidgets[widget.getId()] = widgetData;\n if (this._modelData && this._modelData.hasRealView) {\n this._modelData.view.addOverlayWidget(widgetData);\n }\n }\n layoutOverlayWidget(widget) {\n const widgetId = widget.getId();\n if (this._overlayWidgets.hasOwnProperty(widgetId)) {\n const widgetData = this._overlayWidgets[widgetId];\n widgetData.position = widget.getPosition();\n if (this._modelData && this._modelData.hasRealView) {\n this._modelData.view.layoutOverlayWidget(widgetData);\n }\n }\n }\n removeOverlayWidget(widget) {\n const widgetId = widget.getId();\n if (this._overlayWidgets.hasOwnProperty(widgetId)) {\n const widgetData = this._overlayWidgets[widgetId];\n delete this._overlayWidgets[widgetId];\n if (this._modelData && this._modelData.hasRealView) {\n this._modelData.view.removeOverlayWidget(widgetData);\n }\n }\n }\n changeViewZones(callback) {\n if (!this._modelData || !this._modelData.hasRealView) {\n return;\n }\n this._modelData.view.change(callback);\n }\n getTargetAtClientPoint(clientX, clientY) {\n if (!this._modelData || !this._modelData.hasRealView) {\n return null;\n }\n return this._modelData.view.getTargetAtClientPoint(clientX, clientY);\n }\n getScrolledVisiblePosition(rawPosition) {\n if (!this._modelData || !this._modelData.hasRealView) {\n return null;\n }\n const position = this._modelData.model.validatePosition(rawPosition);\n const options = this._configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n const top = CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, position.lineNumber, position.column) - this.getScrollTop();\n const left = this._modelData.view.getOffsetForColumn(position.lineNumber, position.column) + layoutInfo.glyphMarginWidth + layoutInfo.lineNumbersWidth + layoutInfo.decorationsWidth - this.getScrollLeft();\n return {\n top: top,\n left: left,\n height: options.get(61 /* EditorOption.lineHeight */)\n };\n }\n getOffsetForColumn(lineNumber, column) {\n if (!this._modelData || !this._modelData.hasRealView) {\n return -1;\n }\n return this._modelData.view.getOffsetForColumn(lineNumber, column);\n }\n render(forceRedraw = false) {\n if (!this._modelData || !this._modelData.hasRealView) {\n return;\n }\n this._modelData.view.render(true, forceRedraw);\n }\n setAriaOptions(options) {\n if (!this._modelData || !this._modelData.hasRealView) {\n return;\n }\n this._modelData.view.setAriaOptions(options);\n }\n applyFontInfo(target) {\n applyFontInfo(target, this._configuration.options.get(46 /* EditorOption.fontInfo */));\n }\n setBanner(domNode, domNodeHeight) {\n if (this._bannerDomNode && this._domElement.contains(this._bannerDomNode)) {\n this._domElement.removeChild(this._bannerDomNode);\n }\n this._bannerDomNode = domNode;\n this._configuration.setReservedHeight(domNode ? domNodeHeight : 0);\n if (this._bannerDomNode) {\n this._domElement.prepend(this._bannerDomNode);\n }\n }\n _attachModel(model) {\n if (!model) {\n this._modelData = null;\n return;\n }\n const listenersToRemove = [];\n this._domElement.setAttribute('data-mode-id', model.getLanguageId());\n this._configuration.setIsDominatedByLongLines(model.isDominatedByLongLines());\n this._configuration.setModelLineCount(model.getLineCount());\n model.onBeforeAttached();\n const viewModel = new ViewModel(this._id, this._configuration, model, DOMLineBreaksComputerFactory.create(), MonospaceLineBreaksComputerFactory.create(this._configuration.options), (callback) => dom.scheduleAtNextAnimationFrame(callback), this.languageConfigurationService, this._themeService);\n // Someone might destroy the model from under the editor, so prevent any exceptions by setting a null model\n listenersToRemove.push(model.onWillDispose(() => this.setModel(null)));\n listenersToRemove.push(viewModel.onEvent((e) => {\n switch (e.kind) {\n case 0 /* OutgoingViewModelEventKind.ContentSizeChanged */:\n this._onDidContentSizeChange.fire(e);\n break;\n case 1 /* OutgoingViewModelEventKind.FocusChanged */:\n this._editorTextFocus.setValue(e.hasFocus);\n break;\n case 2 /* OutgoingViewModelEventKind.ScrollChanged */:\n this._onDidScrollChange.fire(e);\n break;\n case 3 /* OutgoingViewModelEventKind.ViewZonesChanged */:\n this._onDidChangeViewZones.fire();\n break;\n case 4 /* OutgoingViewModelEventKind.HiddenAreasChanged */:\n this._onDidChangeHiddenAreas.fire();\n break;\n case 5 /* OutgoingViewModelEventKind.ReadOnlyEditAttempt */:\n this._onDidAttemptReadOnlyEdit.fire();\n break;\n case 6 /* OutgoingViewModelEventKind.CursorStateChanged */: {\n if (e.reachedMaxCursorCount) {\n this._notificationService.warn(nls.localize('cursors.maximum', \"The number of cursors has been limited to {0}.\", CursorsController.MAX_CURSOR_COUNT));\n }\n const positions = [];\n for (let i = 0, len = e.selections.length; i < len; i++) {\n positions[i] = e.selections[i].getPosition();\n }\n const e1 = {\n position: positions[0],\n secondaryPositions: positions.slice(1),\n reason: e.reason,\n source: e.source\n };\n this._onDidChangeCursorPosition.fire(e1);\n const e2 = {\n selection: e.selections[0],\n secondarySelections: e.selections.slice(1),\n modelVersionId: e.modelVersionId,\n oldSelections: e.oldSelections,\n oldModelVersionId: e.oldModelVersionId,\n source: e.source,\n reason: e.reason\n };\n this._onDidChangeCursorSelection.fire(e2);\n break;\n }\n case 7 /* OutgoingViewModelEventKind.ModelDecorationsChanged */:\n this._onDidChangeModelDecorations.fire(e.event);\n break;\n case 8 /* OutgoingViewModelEventKind.ModelLanguageChanged */:\n this._domElement.setAttribute('data-mode-id', model.getLanguageId());\n this._onDidChangeModelLanguage.fire(e.event);\n break;\n case 9 /* OutgoingViewModelEventKind.ModelLanguageConfigurationChanged */:\n this._onDidChangeModelLanguageConfiguration.fire(e.event);\n break;\n case 10 /* OutgoingViewModelEventKind.ModelContentChanged */:\n this._onDidChangeModelContent.fire(e.event);\n break;\n case 11 /* OutgoingViewModelEventKind.ModelOptionsChanged */:\n this._onDidChangeModelOptions.fire(e.event);\n break;\n case 12 /* OutgoingViewModelEventKind.ModelTokensChanged */:\n this._onDidChangeModelTokens.fire(e.event);\n break;\n }\n }));\n const [view, hasRealView] = this._createView(viewModel);\n if (hasRealView) {\n this._domElement.appendChild(view.domNode.domNode);\n let keys = Object.keys(this._contentWidgets);\n for (let i = 0, len = keys.length; i < len; i++) {\n const widgetId = keys[i];\n view.addContentWidget(this._contentWidgets[widgetId]);\n }\n keys = Object.keys(this._overlayWidgets);\n for (let i = 0, len = keys.length; i < len; i++) {\n const widgetId = keys[i];\n view.addOverlayWidget(this._overlayWidgets[widgetId]);\n }\n view.render(false, true);\n view.domNode.domNode.setAttribute('data-uri', model.uri.toString());\n }\n this._modelData = new ModelData(model, viewModel, view, hasRealView, listenersToRemove);\n }\n _createView(viewModel) {\n let commandDelegate;\n if (this.isSimpleWidget) {\n commandDelegate = {\n paste: (text, pasteOnNewLine, multicursorText, mode) => {\n this._paste('keyboard', text, pasteOnNewLine, multicursorText, mode);\n },\n type: (text) => {\n this._type('keyboard', text);\n },\n compositionType: (text, replacePrevCharCnt, replaceNextCharCnt, positionDelta) => {\n this._compositionType('keyboard', text, replacePrevCharCnt, replaceNextCharCnt, positionDelta);\n },\n startComposition: () => {\n this._startComposition();\n },\n endComposition: () => {\n this._endComposition('keyboard');\n },\n cut: () => {\n this._cut('keyboard');\n }\n };\n }\n else {\n commandDelegate = {\n paste: (text, pasteOnNewLine, multicursorText, mode) => {\n const payload = { text, pasteOnNewLine, multicursorText, mode };\n this._commandService.executeCommand(\"paste\" /* editorCommon.Handler.Paste */, payload);\n },\n type: (text) => {\n const payload = { text };\n this._commandService.executeCommand(\"type\" /* editorCommon.Handler.Type */, payload);\n },\n compositionType: (text, replacePrevCharCnt, replaceNextCharCnt, positionDelta) => {\n // Try if possible to go through the existing `replacePreviousChar` command\n if (replaceNextCharCnt || positionDelta) {\n // must be handled through the new command\n const payload = { text, replacePrevCharCnt, replaceNextCharCnt, positionDelta };\n this._commandService.executeCommand(\"compositionType\" /* editorCommon.Handler.CompositionType */, payload);\n }\n else {\n const payload = { text, replaceCharCnt: replacePrevCharCnt };\n this._commandService.executeCommand(\"replacePreviousChar\" /* editorCommon.Handler.ReplacePreviousChar */, payload);\n }\n },\n startComposition: () => {\n this._commandService.executeCommand(\"compositionStart\" /* editorCommon.Handler.CompositionStart */, {});\n },\n endComposition: () => {\n this._commandService.executeCommand(\"compositionEnd\" /* editorCommon.Handler.CompositionEnd */, {});\n },\n cut: () => {\n this._commandService.executeCommand(\"cut\" /* editorCommon.Handler.Cut */, {});\n }\n };\n }\n const viewUserInputEvents = new ViewUserInputEvents(viewModel.coordinatesConverter);\n viewUserInputEvents.onKeyDown = (e) => this._onKeyDown.fire(e);\n viewUserInputEvents.onKeyUp = (e) => this._onKeyUp.fire(e);\n viewUserInputEvents.onContextMenu = (e) => this._onContextMenu.fire(e);\n viewUserInputEvents.onMouseMove = (e) => this._onMouseMove.fire(e);\n viewUserInputEvents.onMouseLeave = (e) => this._onMouseLeave.fire(e);\n viewUserInputEvents.onMouseDown = (e) => this._onMouseDown.fire(e);\n viewUserInputEvents.onMouseUp = (e) => this._onMouseUp.fire(e);\n viewUserInputEvents.onMouseDrag = (e) => this._onMouseDrag.fire(e);\n viewUserInputEvents.onMouseDrop = (e) => this._onMouseDrop.fire(e);\n viewUserInputEvents.onMouseDropCanceled = (e) => this._onMouseDropCanceled.fire(e);\n viewUserInputEvents.onMouseWheel = (e) => this._onMouseWheel.fire(e);\n const view = new View(commandDelegate, this._configuration, this._themeService.getColorTheme(), viewModel, viewUserInputEvents, this._overflowWidgetsDomNode);\n return [view, true];\n }\n _postDetachModelCleanup(detachedModel) {\n detachedModel === null || detachedModel === void 0 ? void 0 : detachedModel.removeAllDecorationsWithOwnerId(this._id);\n }\n _detachModel() {\n if (!this._modelData) {\n return null;\n }\n const model = this._modelData.model;\n const removeDomNode = this._modelData.hasRealView ? this._modelData.view.domNode.domNode : null;\n this._modelData.dispose();\n this._modelData = null;\n this._domElement.removeAttribute('data-mode-id');\n if (removeDomNode && this._domElement.contains(removeDomNode)) {\n this._domElement.removeChild(removeDomNode);\n }\n if (this._bannerDomNode && this._domElement.contains(this._bannerDomNode)) {\n this._domElement.removeChild(this._bannerDomNode);\n }\n return model;\n }\n _removeDecorationType(key) {\n this._codeEditorService.removeDecorationType(key);\n }\n hasModel() {\n return (this._modelData !== null);\n }\n showDropIndicatorAt(position) {\n const newDecorations = [{\n range: new Range(position.lineNumber, position.column, position.lineNumber, position.column),\n options: CodeEditorWidget.dropIntoEditorDecorationOptions\n }];\n this._dropIntoEditorDecorations.set(newDecorations);\n this.revealPosition(position, 1 /* editorCommon.ScrollType.Immediate */);\n }\n removeDropIndicator() {\n this._dropIntoEditorDecorations.clear();\n }\n};\nCodeEditorWidget.dropIntoEditorDecorationOptions = ModelDecorationOptions.register({\n description: 'workbench-dnd-target',\n className: 'dnd-target'\n});\nCodeEditorWidget = __decorate([\n __param(3, IInstantiationService),\n __param(4, ICodeEditorService),\n __param(5, ICommandService),\n __param(6, IContextKeyService),\n __param(7, IThemeService),\n __param(8, INotificationService),\n __param(9, IAccessibilityService),\n __param(10, ILanguageConfigurationService),\n __param(11, ILanguageFeaturesService)\n], CodeEditorWidget);\nexport { CodeEditorWidget };\nexport class BooleanEventEmitter extends Disposable {\n constructor(_emitterOptions) {\n super();\n this._emitterOptions = _emitterOptions;\n this._onDidChangeToTrue = this._register(new Emitter(this._emitterOptions));\n this.onDidChangeToTrue = this._onDidChangeToTrue.event;\n this._onDidChangeToFalse = this._register(new Emitter(this._emitterOptions));\n this.onDidChangeToFalse = this._onDidChangeToFalse.event;\n this._value = 0 /* BooleanEventValue.NotSet */;\n }\n setValue(_value) {\n const value = (_value ? 2 /* BooleanEventValue.True */ : 1 /* BooleanEventValue.False */);\n if (this._value === value) {\n return;\n }\n this._value = value;\n if (this._value === 2 /* BooleanEventValue.True */) {\n this._onDidChangeToTrue.fire();\n }\n else if (this._value === 1 /* BooleanEventValue.False */) {\n this._onDidChangeToFalse.fire();\n }\n }\n}\nclass EditorContextKeysManager extends Disposable {\n constructor(editor, contextKeyService) {\n super();\n this._editor = editor;\n contextKeyService.createKey('editorId', editor.getId());\n this._editorSimpleInput = EditorContextKeys.editorSimpleInput.bindTo(contextKeyService);\n this._editorFocus = EditorContextKeys.focus.bindTo(contextKeyService);\n this._textInputFocus = EditorContextKeys.textInputFocus.bindTo(contextKeyService);\n this._editorTextFocus = EditorContextKeys.editorTextFocus.bindTo(contextKeyService);\n this._editorTabMovesFocus = EditorContextKeys.tabMovesFocus.bindTo(contextKeyService);\n this._editorReadonly = EditorContextKeys.readOnly.bindTo(contextKeyService);\n this._inDiffEditor = EditorContextKeys.inDiffEditor.bindTo(contextKeyService);\n this._editorColumnSelection = EditorContextKeys.columnSelection.bindTo(contextKeyService);\n this._hasMultipleSelections = EditorContextKeys.hasMultipleSelections.bindTo(contextKeyService);\n this._hasNonEmptySelection = EditorContextKeys.hasNonEmptySelection.bindTo(contextKeyService);\n this._canUndo = EditorContextKeys.canUndo.bindTo(contextKeyService);\n this._canRedo = EditorContextKeys.canRedo.bindTo(contextKeyService);\n this._register(this._editor.onDidChangeConfiguration(() => this._updateFromConfig()));\n this._register(this._editor.onDidChangeCursorSelection(() => this._updateFromSelection()));\n this._register(this._editor.onDidFocusEditorWidget(() => this._updateFromFocus()));\n this._register(this._editor.onDidBlurEditorWidget(() => this._updateFromFocus()));\n this._register(this._editor.onDidFocusEditorText(() => this._updateFromFocus()));\n this._register(this._editor.onDidBlurEditorText(() => this._updateFromFocus()));\n this._register(this._editor.onDidChangeModel(() => this._updateFromModel()));\n this._register(this._editor.onDidChangeConfiguration(() => this._updateFromModel()));\n this._updateFromConfig();\n this._updateFromSelection();\n this._updateFromFocus();\n this._updateFromModel();\n this._editorSimpleInput.set(this._editor.isSimpleWidget);\n }\n _updateFromConfig() {\n const options = this._editor.getOptions();\n this._editorTabMovesFocus.set(options.get(132 /* EditorOption.tabFocusMode */));\n this._editorReadonly.set(options.get(83 /* EditorOption.readOnly */));\n this._inDiffEditor.set(options.get(56 /* EditorOption.inDiffEditor */));\n this._editorColumnSelection.set(options.get(18 /* EditorOption.columnSelection */));\n }\n _updateFromSelection() {\n const selections = this._editor.getSelections();\n if (!selections) {\n this._hasMultipleSelections.reset();\n this._hasNonEmptySelection.reset();\n }\n else {\n this._hasMultipleSelections.set(selections.length > 1);\n this._hasNonEmptySelection.set(selections.some(s => !s.isEmpty()));\n }\n }\n _updateFromFocus() {\n this._editorFocus.set(this._editor.hasWidgetFocus() && !this._editor.isSimpleWidget);\n this._editorTextFocus.set(this._editor.hasTextFocus() && !this._editor.isSimpleWidget);\n this._textInputFocus.set(this._editor.hasTextFocus());\n }\n _updateFromModel() {\n const model = this._editor.getModel();\n this._canUndo.set(Boolean(model && model.canUndo()));\n this._canRedo.set(Boolean(model && model.canRedo()));\n }\n}\nexport class EditorModeContext extends Disposable {\n constructor(_editor, _contextKeyService, _languageFeaturesService) {\n super();\n this._editor = _editor;\n this._contextKeyService = _contextKeyService;\n this._languageFeaturesService = _languageFeaturesService;\n this._langId = EditorContextKeys.languageId.bindTo(_contextKeyService);\n this._hasCompletionItemProvider = EditorContextKeys.hasCompletionItemProvider.bindTo(_contextKeyService);\n this._hasCodeActionsProvider = EditorContextKeys.hasCodeActionsProvider.bindTo(_contextKeyService);\n this._hasCodeLensProvider = EditorContextKeys.hasCodeLensProvider.bindTo(_contextKeyService);\n this._hasDefinitionProvider = EditorContextKeys.hasDefinitionProvider.bindTo(_contextKeyService);\n this._hasDeclarationProvider = EditorContextKeys.hasDeclarationProvider.bindTo(_contextKeyService);\n this._hasImplementationProvider = EditorContextKeys.hasImplementationProvider.bindTo(_contextKeyService);\n this._hasTypeDefinitionProvider = EditorContextKeys.hasTypeDefinitionProvider.bindTo(_contextKeyService);\n this._hasHoverProvider = EditorContextKeys.hasHoverProvider.bindTo(_contextKeyService);\n this._hasDocumentHighlightProvider = EditorContextKeys.hasDocumentHighlightProvider.bindTo(_contextKeyService);\n this._hasDocumentSymbolProvider = EditorContextKeys.hasDocumentSymbolProvider.bindTo(_contextKeyService);\n this._hasReferenceProvider = EditorContextKeys.hasReferenceProvider.bindTo(_contextKeyService);\n this._hasRenameProvider = EditorContextKeys.hasRenameProvider.bindTo(_contextKeyService);\n this._hasSignatureHelpProvider = EditorContextKeys.hasSignatureHelpProvider.bindTo(_contextKeyService);\n this._hasInlayHintsProvider = EditorContextKeys.hasInlayHintsProvider.bindTo(_contextKeyService);\n this._hasDocumentFormattingProvider = EditorContextKeys.hasDocumentFormattingProvider.bindTo(_contextKeyService);\n this._hasDocumentSelectionFormattingProvider = EditorContextKeys.hasDocumentSelectionFormattingProvider.bindTo(_contextKeyService);\n this._hasMultipleDocumentFormattingProvider = EditorContextKeys.hasMultipleDocumentFormattingProvider.bindTo(_contextKeyService);\n this._hasMultipleDocumentSelectionFormattingProvider = EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider.bindTo(_contextKeyService);\n this._isInWalkThrough = EditorContextKeys.isInWalkThroughSnippet.bindTo(_contextKeyService);\n const update = () => this._update();\n // update when model/mode changes\n this._register(_editor.onDidChangeModel(update));\n this._register(_editor.onDidChangeModelLanguage(update));\n // update when registries change\n this._register(_languageFeaturesService.completionProvider.onDidChange(update));\n this._register(_languageFeaturesService.codeActionProvider.onDidChange(update));\n this._register(_languageFeaturesService.codeLensProvider.onDidChange(update));\n this._register(_languageFeaturesService.definitionProvider.onDidChange(update));\n this._register(_languageFeaturesService.declarationProvider.onDidChange(update));\n this._register(_languageFeaturesService.implementationProvider.onDidChange(update));\n this._register(_languageFeaturesService.typeDefinitionProvider.onDidChange(update));\n this._register(_languageFeaturesService.hoverProvider.onDidChange(update));\n this._register(_languageFeaturesService.documentHighlightProvider.onDidChange(update));\n this._register(_languageFeaturesService.documentSymbolProvider.onDidChange(update));\n this._register(_languageFeaturesService.referenceProvider.onDidChange(update));\n this._register(_languageFeaturesService.renameProvider.onDidChange(update));\n this._register(_languageFeaturesService.documentFormattingEditProvider.onDidChange(update));\n this._register(_languageFeaturesService.documentRangeFormattingEditProvider.onDidChange(update));\n this._register(_languageFeaturesService.signatureHelpProvider.onDidChange(update));\n this._register(_languageFeaturesService.inlayHintsProvider.onDidChange(update));\n update();\n }\n dispose() {\n super.dispose();\n }\n reset() {\n this._contextKeyService.bufferChangeEvents(() => {\n this._langId.reset();\n this._hasCompletionItemProvider.reset();\n this._hasCodeActionsProvider.reset();\n this._hasCodeLensProvider.reset();\n this._hasDefinitionProvider.reset();\n this._hasDeclarationProvider.reset();\n this._hasImplementationProvider.reset();\n this._hasTypeDefinitionProvider.reset();\n this._hasHoverProvider.reset();\n this._hasDocumentHighlightProvider.reset();\n this._hasDocumentSymbolProvider.reset();\n this._hasReferenceProvider.reset();\n this._hasRenameProvider.reset();\n this._hasDocumentFormattingProvider.reset();\n this._hasDocumentSelectionFormattingProvider.reset();\n this._hasSignatureHelpProvider.reset();\n this._isInWalkThrough.reset();\n });\n }\n _update() {\n const model = this._editor.getModel();\n if (!model) {\n this.reset();\n return;\n }\n this._contextKeyService.bufferChangeEvents(() => {\n this._langId.set(model.getLanguageId());\n this._hasCompletionItemProvider.set(this._languageFeaturesService.completionProvider.has(model));\n this._hasCodeActionsProvider.set(this._languageFeaturesService.codeActionProvider.has(model));\n this._hasCodeLensProvider.set(this._languageFeaturesService.codeLensProvider.has(model));\n this._hasDefinitionProvider.set(this._languageFeaturesService.definitionProvider.has(model));\n this._hasDeclarationProvider.set(this._languageFeaturesService.declarationProvider.has(model));\n this._hasImplementationProvider.set(this._languageFeaturesService.implementationProvider.has(model));\n this._hasTypeDefinitionProvider.set(this._languageFeaturesService.typeDefinitionProvider.has(model));\n this._hasHoverProvider.set(this._languageFeaturesService.hoverProvider.has(model));\n this._hasDocumentHighlightProvider.set(this._languageFeaturesService.documentHighlightProvider.has(model));\n this._hasDocumentSymbolProvider.set(this._languageFeaturesService.documentSymbolProvider.has(model));\n this._hasReferenceProvider.set(this._languageFeaturesService.referenceProvider.has(model));\n this._hasRenameProvider.set(this._languageFeaturesService.renameProvider.has(model));\n this._hasSignatureHelpProvider.set(this._languageFeaturesService.signatureHelpProvider.has(model));\n this._hasInlayHintsProvider.set(this._languageFeaturesService.inlayHintsProvider.has(model));\n this._hasDocumentFormattingProvider.set(this._languageFeaturesService.documentFormattingEditProvider.has(model) || this._languageFeaturesService.documentRangeFormattingEditProvider.has(model));\n this._hasDocumentSelectionFormattingProvider.set(this._languageFeaturesService.documentRangeFormattingEditProvider.has(model));\n this._hasMultipleDocumentFormattingProvider.set(this._languageFeaturesService.documentFormattingEditProvider.all(model).length + this._languageFeaturesService.documentRangeFormattingEditProvider.all(model).length > 1);\n this._hasMultipleDocumentSelectionFormattingProvider.set(this._languageFeaturesService.documentRangeFormattingEditProvider.all(model).length > 1);\n this._isInWalkThrough.set(model.uri.scheme === Schemas.walkThroughSnippet);\n });\n }\n}\nclass CodeEditorWidgetFocusTracker extends Disposable {\n constructor(domElement) {\n super();\n this._onChange = this._register(new Emitter());\n this.onChange = this._onChange.event;\n this._hasFocus = false;\n this._domFocusTracker = this._register(dom.trackFocus(domElement));\n this._register(this._domFocusTracker.onDidFocus(() => {\n this._hasFocus = true;\n this._onChange.fire(undefined);\n }));\n this._register(this._domFocusTracker.onDidBlur(() => {\n this._hasFocus = false;\n this._onChange.fire(undefined);\n }));\n }\n hasFocus() {\n return this._hasFocus;\n }\n}\nclass EditorDecorationsCollection {\n constructor(_editor, decorations) {\n this._editor = _editor;\n this._decorationIds = [];\n this._isChangingDecorations = false;\n if (Array.isArray(decorations) && decorations.length > 0) {\n this.set(decorations);\n }\n }\n get length() {\n return this._decorationIds.length;\n }\n onDidChange(listener, thisArgs, disposables) {\n return this._editor.onDidChangeModelDecorations((e) => {\n if (this._isChangingDecorations) {\n return;\n }\n listener.call(thisArgs, e);\n }, disposables);\n }\n getRange(index) {\n if (!this._editor.hasModel()) {\n return null;\n }\n if (index >= this._decorationIds.length) {\n return null;\n }\n return this._editor.getModel().getDecorationRange(this._decorationIds[index]);\n }\n getRanges() {\n if (!this._editor.hasModel()) {\n return [];\n }\n const model = this._editor.getModel();\n const result = [];\n for (const decorationId of this._decorationIds) {\n const range = model.getDecorationRange(decorationId);\n if (range) {\n result.push(range);\n }\n }\n return result;\n }\n has(decoration) {\n return this._decorationIds.includes(decoration.id);\n }\n clear() {\n if (this._decorationIds.length === 0) {\n // nothing to do\n return;\n }\n this.set([]);\n }\n set(newDecorations) {\n try {\n this._isChangingDecorations = true;\n this._editor.changeDecorations((accessor) => {\n this._decorationIds = accessor.deltaDecorations(this._decorationIds, newDecorations);\n });\n }\n finally {\n this._isChangingDecorations = false;\n }\n }\n}\nconst squigglyStart = encodeURIComponent(`
`);\nfunction getSquigglySVGData(color) {\n return squigglyStart + encodeURIComponent(color.toString()) + squigglyEnd;\n}\nconst dotdotdotStart = encodeURIComponent(`
`);\nfunction getDotDotDotSVGData(color) {\n return dotdotdotStart + encodeURIComponent(color.toString()) + dotdotdotEnd;\n}\nregisterThemingParticipant((theme, collector) => {\n const errorBorderColor = theme.getColor(editorErrorBorder);\n if (errorBorderColor) {\n collector.addRule(`.monaco-editor .${\"squiggly-error\" /* ClassName.EditorErrorDecoration */} { border-bottom: 4px double ${errorBorderColor}; }`);\n }\n const errorForeground = theme.getColor(editorErrorForeground);\n if (errorForeground) {\n collector.addRule(`.monaco-editor .${\"squiggly-error\" /* ClassName.EditorErrorDecoration */} { background: url(\"data:image/svg+xml,${getSquigglySVGData(errorForeground)}\") repeat-x bottom left; }`);\n }\n const errorBackground = theme.getColor(editorErrorBackground);\n if (errorBackground) {\n collector.addRule(`.monaco-editor .${\"squiggly-error\" /* ClassName.EditorErrorDecoration */}::before { display: block; content: ''; width: 100%; height: 100%; background: ${errorBackground}; }`);\n }\n const warningBorderColor = theme.getColor(editorWarningBorder);\n if (warningBorderColor) {\n collector.addRule(`.monaco-editor .${\"squiggly-warning\" /* ClassName.EditorWarningDecoration */} { border-bottom: 4px double ${warningBorderColor}; }`);\n }\n const warningForeground = theme.getColor(editorWarningForeground);\n if (warningForeground) {\n collector.addRule(`.monaco-editor .${\"squiggly-warning\" /* ClassName.EditorWarningDecoration */} { background: url(\"data:image/svg+xml,${getSquigglySVGData(warningForeground)}\") repeat-x bottom left; }`);\n }\n const warningBackground = theme.getColor(editorWarningBackground);\n if (warningBackground) {\n collector.addRule(`.monaco-editor .${\"squiggly-warning\" /* ClassName.EditorWarningDecoration */}::before { display: block; content: ''; width: 100%; height: 100%; background: ${warningBackground}; }`);\n }\n const infoBorderColor = theme.getColor(editorInfoBorder);\n if (infoBorderColor) {\n collector.addRule(`.monaco-editor .${\"squiggly-info\" /* ClassName.EditorInfoDecoration */} { border-bottom: 4px double ${infoBorderColor}; }`);\n }\n const infoForeground = theme.getColor(editorInfoForeground);\n if (infoForeground) {\n collector.addRule(`.monaco-editor .${\"squiggly-info\" /* ClassName.EditorInfoDecoration */} { background: url(\"data:image/svg+xml,${getSquigglySVGData(infoForeground)}\") repeat-x bottom left; }`);\n }\n const infoBackground = theme.getColor(editorInfoBackground);\n if (infoBackground) {\n collector.addRule(`.monaco-editor .${\"squiggly-info\" /* ClassName.EditorInfoDecoration */}::before { display: block; content: ''; width: 100%; height: 100%; background: ${infoBackground}; }`);\n }\n const hintBorderColor = theme.getColor(editorHintBorder);\n if (hintBorderColor) {\n collector.addRule(`.monaco-editor .${\"squiggly-hint\" /* ClassName.EditorHintDecoration */} { border-bottom: 2px dotted ${hintBorderColor}; }`);\n }\n const hintForeground = theme.getColor(editorHintForeground);\n if (hintForeground) {\n collector.addRule(`.monaco-editor .${\"squiggly-hint\" /* ClassName.EditorHintDecoration */} { background: url(\"data:image/svg+xml,${getDotDotDotSVGData(hintForeground)}\") no-repeat bottom left; }`);\n }\n const unnecessaryForeground = theme.getColor(editorUnnecessaryCodeOpacity);\n if (unnecessaryForeground) {\n collector.addRule(`.monaco-editor.showUnused .${\"squiggly-inline-unnecessary\" /* ClassName.EditorUnnecessaryInlineDecoration */} { opacity: ${unnecessaryForeground.rgba.a}; }`);\n }\n const unnecessaryBorder = theme.getColor(editorUnnecessaryCodeBorder);\n if (unnecessaryBorder) {\n collector.addRule(`.monaco-editor.showUnused .${\"squiggly-unnecessary\" /* ClassName.EditorUnnecessaryDecoration */} { border-bottom: 2px dashed ${unnecessaryBorder}; }`);\n }\n const deprecatedForeground = theme.getColor(editorForeground) || 'inherit';\n collector.addRule(`.monaco-editor.showDeprecated .${\"squiggly-inline-deprecated\" /* ClassName.EditorDeprecatedInlineDecoration */} { text-decoration: line-through; text-decoration-color: ${deprecatedForeground}}`);\n});\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar _a;\nimport './media/diffReview.css';\nimport * as nls from '../../../nls.js';\nimport * as dom from '../../../base/browser/dom.js';\nimport { createFastDomNode } from '../../../base/browser/fastDomNode.js';\nimport { ActionBar } from '../../../base/browser/ui/actionbar/actionbar.js';\nimport { DomScrollableElement } from '../../../base/browser/ui/scrollbar/scrollableElement.js';\nimport { Action } from '../../../base/common/actions.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { applyFontInfo } from '../config/domFontInfo.js';\nimport { EditorAction, registerEditorAction } from '../editorExtensions.js';\nimport { ICodeEditorService } from '../services/codeEditorService.js';\nimport { EditorFontLigatures } from '../../common/config/editorOptions.js';\nimport { LineTokens } from '../../common/tokens/lineTokens.js';\nimport { Position } from '../../common/core/position.js';\nimport { editorLineNumbers } from '../../common/core/editorColorRegistry.js';\nimport { RenderLineInput, renderViewLine2 as renderViewLine } from '../../common/viewLayout/viewLineRenderer.js';\nimport { ViewLineRenderingData } from '../../common/viewModel.js';\nimport { ContextKeyExpr } from '../../../platform/contextkey/common/contextkey.js';\nimport { scrollbarShadow } from '../../../platform/theme/common/colorRegistry.js';\nimport { registerThemingParticipant, ThemeIcon } from '../../../platform/theme/common/themeService.js';\nimport { Codicon } from '../../../base/common/codicons.js';\nimport { registerIcon } from '../../../platform/theme/common/iconRegistry.js';\nimport { ILanguageService } from '../../common/languages/language.js';\nconst DIFF_LINES_PADDING = 3;\nclass DiffEntry {\n constructor(originalLineStart, originalLineEnd, modifiedLineStart, modifiedLineEnd) {\n this.originalLineStart = originalLineStart;\n this.originalLineEnd = originalLineEnd;\n this.modifiedLineStart = modifiedLineStart;\n this.modifiedLineEnd = modifiedLineEnd;\n }\n getType() {\n if (this.originalLineStart === 0) {\n return 1 /* DiffEntryType.Insert */;\n }\n if (this.modifiedLineStart === 0) {\n return 2 /* DiffEntryType.Delete */;\n }\n return 0 /* DiffEntryType.Equal */;\n }\n}\nclass Diff {\n constructor(entries) {\n this.entries = entries;\n }\n}\nconst diffReviewInsertIcon = registerIcon('diff-review-insert', Codicon.add, nls.localize('diffReviewInsertIcon', 'Icon for \\'Insert\\' in diff review.'));\nconst diffReviewRemoveIcon = registerIcon('diff-review-remove', Codicon.remove, nls.localize('diffReviewRemoveIcon', 'Icon for \\'Remove\\' in diff review.'));\nconst diffReviewCloseIcon = registerIcon('diff-review-close', Codicon.close, nls.localize('diffReviewCloseIcon', 'Icon for \\'Close\\' in diff review.'));\nlet DiffReview = class DiffReview extends Disposable {\n constructor(diffEditor, _languageService) {\n super();\n this._languageService = _languageService;\n this._width = 0;\n this._diffEditor = diffEditor;\n this._isVisible = false;\n this.shadow = createFastDomNode(document.createElement('div'));\n this.shadow.setClassName('diff-review-shadow');\n this.actionBarContainer = createFastDomNode(document.createElement('div'));\n this.actionBarContainer.setClassName('diff-review-actions');\n this._actionBar = this._register(new ActionBar(this.actionBarContainer.domNode));\n this._actionBar.push(new Action('diffreview.close', nls.localize('label.close', \"Close\"), 'close-diff-review ' + ThemeIcon.asClassName(diffReviewCloseIcon), true, () => __awaiter(this, void 0, void 0, function* () { return this.hide(); })), { label: false, icon: true });\n this.domNode = createFastDomNode(document.createElement('div'));\n this.domNode.setClassName('diff-review monaco-editor-background');\n this._content = createFastDomNode(document.createElement('div'));\n this._content.setClassName('diff-review-content');\n this._content.setAttribute('role', 'code');\n this.scrollbar = this._register(new DomScrollableElement(this._content.domNode, {}));\n this.domNode.domNode.appendChild(this.scrollbar.getDomNode());\n this._register(diffEditor.onDidUpdateDiff(() => {\n if (!this._isVisible) {\n return;\n }\n this._diffs = this._compute();\n this._render();\n }));\n this._register(diffEditor.getModifiedEditor().onDidChangeCursorPosition(() => {\n if (!this._isVisible) {\n return;\n }\n this._render();\n }));\n this._register(dom.addStandardDisposableListener(this.domNode.domNode, 'click', (e) => {\n e.preventDefault();\n const row = dom.findParentWithClass(e.target, 'diff-review-row');\n if (row) {\n this._goToRow(row);\n }\n }));\n this._register(dom.addStandardDisposableListener(this.domNode.domNode, 'keydown', (e) => {\n if (e.equals(18 /* KeyCode.DownArrow */)\n || e.equals(2048 /* KeyMod.CtrlCmd */ | 18 /* KeyCode.DownArrow */)\n || e.equals(512 /* KeyMod.Alt */ | 18 /* KeyCode.DownArrow */)) {\n e.preventDefault();\n this._goToRow(this._getNextRow());\n }\n if (e.equals(16 /* KeyCode.UpArrow */)\n || e.equals(2048 /* KeyMod.CtrlCmd */ | 16 /* KeyCode.UpArrow */)\n || e.equals(512 /* KeyMod.Alt */ | 16 /* KeyCode.UpArrow */)) {\n e.preventDefault();\n this._goToRow(this._getPrevRow());\n }\n if (e.equals(9 /* KeyCode.Escape */)\n || e.equals(2048 /* KeyMod.CtrlCmd */ | 9 /* KeyCode.Escape */)\n || e.equals(512 /* KeyMod.Alt */ | 9 /* KeyCode.Escape */)\n || e.equals(1024 /* KeyMod.Shift */ | 9 /* KeyCode.Escape */)) {\n e.preventDefault();\n this.hide();\n }\n if (e.equals(10 /* KeyCode.Space */)\n || e.equals(3 /* KeyCode.Enter */)) {\n e.preventDefault();\n this.accept();\n }\n }));\n this._diffs = [];\n this._currentDiff = null;\n }\n prev() {\n let index = 0;\n if (!this._isVisible) {\n this._diffs = this._compute();\n }\n if (this._isVisible) {\n let currentIndex = -1;\n for (let i = 0, len = this._diffs.length; i < len; i++) {\n if (this._diffs[i] === this._currentDiff) {\n currentIndex = i;\n break;\n }\n }\n index = (this._diffs.length + currentIndex - 1);\n }\n else {\n index = this._findDiffIndex(this._diffEditor.getPosition());\n }\n if (this._diffs.length === 0) {\n // Nothing to do\n return;\n }\n index = index % this._diffs.length;\n const entries = this._diffs[index].entries;\n this._diffEditor.setPosition(new Position(entries[0].modifiedLineStart, 1));\n this._diffEditor.setSelection({ startColumn: 1, startLineNumber: entries[0].modifiedLineStart, endColumn: 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, endLineNumber: entries[entries.length - 1].modifiedLineEnd });\n this._isVisible = true;\n this._diffEditor.doLayout();\n this._render();\n this._goToRow(this._getNextRow());\n }\n next() {\n let index = 0;\n if (!this._isVisible) {\n this._diffs = this._compute();\n }\n if (this._isVisible) {\n let currentIndex = -1;\n for (let i = 0, len = this._diffs.length; i < len; i++) {\n if (this._diffs[i] === this._currentDiff) {\n currentIndex = i;\n break;\n }\n }\n index = (currentIndex + 1);\n }\n else {\n index = this._findDiffIndex(this._diffEditor.getPosition());\n }\n if (this._diffs.length === 0) {\n // Nothing to do\n return;\n }\n index = index % this._diffs.length;\n const entries = this._diffs[index].entries;\n this._diffEditor.setPosition(new Position(entries[0].modifiedLineStart, 1));\n this._diffEditor.setSelection({ startColumn: 1, startLineNumber: entries[0].modifiedLineStart, endColumn: 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, endLineNumber: entries[entries.length - 1].modifiedLineEnd });\n this._isVisible = true;\n this._diffEditor.doLayout();\n this._render();\n this._goToRow(this._getNextRow());\n }\n accept() {\n let jumpToLineNumber = -1;\n const current = this._getCurrentFocusedRow();\n if (current) {\n const lineNumber = parseInt(current.getAttribute('data-line'), 10);\n if (!isNaN(lineNumber)) {\n jumpToLineNumber = lineNumber;\n }\n }\n this.hide();\n if (jumpToLineNumber !== -1) {\n this._diffEditor.setPosition(new Position(jumpToLineNumber, 1));\n this._diffEditor.revealPosition(new Position(jumpToLineNumber, 1), 1 /* ScrollType.Immediate */);\n }\n }\n hide() {\n this._isVisible = false;\n this._diffEditor.updateOptions({ readOnly: false });\n this._diffEditor.focus();\n this._diffEditor.doLayout();\n this._render();\n }\n _getPrevRow() {\n const current = this._getCurrentFocusedRow();\n if (!current) {\n return this._getFirstRow();\n }\n if (current.previousElementSibling) {\n return current.previousElementSibling;\n }\n return current;\n }\n _getNextRow() {\n const current = this._getCurrentFocusedRow();\n if (!current) {\n return this._getFirstRow();\n }\n if (current.nextElementSibling) {\n return current.nextElementSibling;\n }\n return current;\n }\n _getFirstRow() {\n return this.domNode.domNode.querySelector('.diff-review-row');\n }\n _getCurrentFocusedRow() {\n const result = document.activeElement;\n if (result && /diff-review-row/.test(result.className)) {\n return result;\n }\n return null;\n }\n _goToRow(row) {\n const prev = this._getCurrentFocusedRow();\n row.tabIndex = 0;\n row.focus();\n if (prev && prev !== row) {\n prev.tabIndex = -1;\n }\n this.scrollbar.scanDomNode();\n }\n isVisible() {\n return this._isVisible;\n }\n layout(top, width, height) {\n this._width = width;\n this.shadow.setTop(top - 6);\n this.shadow.setWidth(width);\n this.shadow.setHeight(this._isVisible ? 6 : 0);\n this.domNode.setTop(top);\n this.domNode.setWidth(width);\n this.domNode.setHeight(height);\n this._content.setHeight(height);\n this._content.setWidth(width);\n if (this._isVisible) {\n this.actionBarContainer.setAttribute('aria-hidden', 'false');\n this.actionBarContainer.setDisplay('block');\n }\n else {\n this.actionBarContainer.setAttribute('aria-hidden', 'true');\n this.actionBarContainer.setDisplay('none');\n }\n }\n _compute() {\n const lineChanges = this._diffEditor.getLineChanges();\n if (!lineChanges || lineChanges.length === 0) {\n return [];\n }\n const originalModel = this._diffEditor.getOriginalEditor().getModel();\n const modifiedModel = this._diffEditor.getModifiedEditor().getModel();\n if (!originalModel || !modifiedModel) {\n return [];\n }\n return DiffReview._mergeAdjacent(lineChanges, originalModel.getLineCount(), modifiedModel.getLineCount());\n }\n static _mergeAdjacent(lineChanges, originalLineCount, modifiedLineCount) {\n if (!lineChanges || lineChanges.length === 0) {\n return [];\n }\n const diffs = [];\n let diffsLength = 0;\n for (let i = 0, len = lineChanges.length; i < len; i++) {\n const lineChange = lineChanges[i];\n const originalStart = lineChange.originalStartLineNumber;\n const originalEnd = lineChange.originalEndLineNumber;\n const modifiedStart = lineChange.modifiedStartLineNumber;\n const modifiedEnd = lineChange.modifiedEndLineNumber;\n const r = [];\n let rLength = 0;\n // Emit before anchors\n {\n const originalEqualAbove = (originalEnd === 0 ? originalStart : originalStart - 1);\n const modifiedEqualAbove = (modifiedEnd === 0 ? modifiedStart : modifiedStart - 1);\n // Make sure we don't step into the previous diff\n let minOriginal = 1;\n let minModified = 1;\n if (i > 0) {\n const prevLineChange = lineChanges[i - 1];\n if (prevLineChange.originalEndLineNumber === 0) {\n minOriginal = prevLineChange.originalStartLineNumber + 1;\n }\n else {\n minOriginal = prevLineChange.originalEndLineNumber + 1;\n }\n if (prevLineChange.modifiedEndLineNumber === 0) {\n minModified = prevLineChange.modifiedStartLineNumber + 1;\n }\n else {\n minModified = prevLineChange.modifiedEndLineNumber + 1;\n }\n }\n let fromOriginal = originalEqualAbove - DIFF_LINES_PADDING + 1;\n let fromModified = modifiedEqualAbove - DIFF_LINES_PADDING + 1;\n if (fromOriginal < minOriginal) {\n const delta = minOriginal - fromOriginal;\n fromOriginal = fromOriginal + delta;\n fromModified = fromModified + delta;\n }\n if (fromModified < minModified) {\n const delta = minModified - fromModified;\n fromOriginal = fromOriginal + delta;\n fromModified = fromModified + delta;\n }\n r[rLength++] = new DiffEntry(fromOriginal, originalEqualAbove, fromModified, modifiedEqualAbove);\n }\n // Emit deleted lines\n {\n if (originalEnd !== 0) {\n r[rLength++] = new DiffEntry(originalStart, originalEnd, 0, 0);\n }\n }\n // Emit inserted lines\n {\n if (modifiedEnd !== 0) {\n r[rLength++] = new DiffEntry(0, 0, modifiedStart, modifiedEnd);\n }\n }\n // Emit after anchors\n {\n const originalEqualBelow = (originalEnd === 0 ? originalStart + 1 : originalEnd + 1);\n const modifiedEqualBelow = (modifiedEnd === 0 ? modifiedStart + 1 : modifiedEnd + 1);\n // Make sure we don't step into the next diff\n let maxOriginal = originalLineCount;\n let maxModified = modifiedLineCount;\n if (i + 1 < len) {\n const nextLineChange = lineChanges[i + 1];\n if (nextLineChange.originalEndLineNumber === 0) {\n maxOriginal = nextLineChange.originalStartLineNumber;\n }\n else {\n maxOriginal = nextLineChange.originalStartLineNumber - 1;\n }\n if (nextLineChange.modifiedEndLineNumber === 0) {\n maxModified = nextLineChange.modifiedStartLineNumber;\n }\n else {\n maxModified = nextLineChange.modifiedStartLineNumber - 1;\n }\n }\n let toOriginal = originalEqualBelow + DIFF_LINES_PADDING - 1;\n let toModified = modifiedEqualBelow + DIFF_LINES_PADDING - 1;\n if (toOriginal > maxOriginal) {\n const delta = maxOriginal - toOriginal;\n toOriginal = toOriginal + delta;\n toModified = toModified + delta;\n }\n if (toModified > maxModified) {\n const delta = maxModified - toModified;\n toOriginal = toOriginal + delta;\n toModified = toModified + delta;\n }\n r[rLength++] = new DiffEntry(originalEqualBelow, toOriginal, modifiedEqualBelow, toModified);\n }\n diffs[diffsLength++] = new Diff(r);\n }\n // Merge adjacent diffs\n let curr = diffs[0].entries;\n const r = [];\n let rLength = 0;\n for (let i = 1, len = diffs.length; i < len; i++) {\n const thisDiff = diffs[i].entries;\n const currLast = curr[curr.length - 1];\n const thisFirst = thisDiff[0];\n if (currLast.getType() === 0 /* DiffEntryType.Equal */\n && thisFirst.getType() === 0 /* DiffEntryType.Equal */\n && thisFirst.originalLineStart <= currLast.originalLineEnd) {\n // We are dealing with equal lines that overlap\n curr[curr.length - 1] = new DiffEntry(currLast.originalLineStart, thisFirst.originalLineEnd, currLast.modifiedLineStart, thisFirst.modifiedLineEnd);\n curr = curr.concat(thisDiff.slice(1));\n continue;\n }\n r[rLength++] = new Diff(curr);\n curr = thisDiff;\n }\n r[rLength++] = new Diff(curr);\n return r;\n }\n _findDiffIndex(pos) {\n const lineNumber = pos.lineNumber;\n for (let i = 0, len = this._diffs.length; i < len; i++) {\n const diff = this._diffs[i].entries;\n const lastModifiedLine = diff[diff.length - 1].modifiedLineEnd;\n if (lineNumber <= lastModifiedLine) {\n return i;\n }\n }\n return 0;\n }\n _render() {\n const originalOptions = this._diffEditor.getOriginalEditor().getOptions();\n const modifiedOptions = this._diffEditor.getModifiedEditor().getOptions();\n const originalModel = this._diffEditor.getOriginalEditor().getModel();\n const modifiedModel = this._diffEditor.getModifiedEditor().getModel();\n const originalModelOpts = originalModel.getOptions();\n const modifiedModelOpts = modifiedModel.getOptions();\n if (!this._isVisible || !originalModel || !modifiedModel) {\n dom.clearNode(this._content.domNode);\n this._currentDiff = null;\n this.scrollbar.scanDomNode();\n return;\n }\n this._diffEditor.updateOptions({ readOnly: true });\n const diffIndex = this._findDiffIndex(this._diffEditor.getPosition());\n if (this._diffs[diffIndex] === this._currentDiff) {\n return;\n }\n this._currentDiff = this._diffs[diffIndex];\n const diffs = this._diffs[diffIndex].entries;\n const container = document.createElement('div');\n container.className = 'diff-review-table';\n container.setAttribute('role', 'list');\n container.setAttribute('aria-label', 'Difference review. Use \"Stage | Unstage | Revert Selected Ranges\" commands');\n applyFontInfo(container, modifiedOptions.get(46 /* EditorOption.fontInfo */));\n let minOriginalLine = 0;\n let maxOriginalLine = 0;\n let minModifiedLine = 0;\n let maxModifiedLine = 0;\n for (let i = 0, len = diffs.length; i < len; i++) {\n const diffEntry = diffs[i];\n const originalLineStart = diffEntry.originalLineStart;\n const originalLineEnd = diffEntry.originalLineEnd;\n const modifiedLineStart = diffEntry.modifiedLineStart;\n const modifiedLineEnd = diffEntry.modifiedLineEnd;\n if (originalLineStart !== 0 && ((minOriginalLine === 0 || originalLineStart < minOriginalLine))) {\n minOriginalLine = originalLineStart;\n }\n if (originalLineEnd !== 0 && ((maxOriginalLine === 0 || originalLineEnd > maxOriginalLine))) {\n maxOriginalLine = originalLineEnd;\n }\n if (modifiedLineStart !== 0 && ((minModifiedLine === 0 || modifiedLineStart < minModifiedLine))) {\n minModifiedLine = modifiedLineStart;\n }\n if (modifiedLineEnd !== 0 && ((maxModifiedLine === 0 || modifiedLineEnd > maxModifiedLine))) {\n maxModifiedLine = modifiedLineEnd;\n }\n }\n const header = document.createElement('div');\n header.className = 'diff-review-row';\n const cell = document.createElement('div');\n cell.className = 'diff-review-cell diff-review-summary';\n const originalChangedLinesCnt = maxOriginalLine - minOriginalLine + 1;\n const modifiedChangedLinesCnt = maxModifiedLine - minModifiedLine + 1;\n cell.appendChild(document.createTextNode(`${diffIndex + 1}/${this._diffs.length}: @@ -${minOriginalLine},${originalChangedLinesCnt} +${minModifiedLine},${modifiedChangedLinesCnt} @@`));\n header.setAttribute('data-line', String(minModifiedLine));\n const getAriaLines = (lines) => {\n if (lines === 0) {\n return nls.localize('no_lines_changed', \"no lines changed\");\n }\n else if (lines === 1) {\n return nls.localize('one_line_changed', \"1 line changed\");\n }\n else {\n return nls.localize('more_lines_changed', \"{0} lines changed\", lines);\n }\n };\n const originalChangedLinesCntAria = getAriaLines(originalChangedLinesCnt);\n const modifiedChangedLinesCntAria = getAriaLines(modifiedChangedLinesCnt);\n header.setAttribute('aria-label', nls.localize({\n key: 'header',\n comment: [\n 'This is the ARIA label for a git diff header.',\n 'A git diff header looks like this: @@ -154,12 +159,39 @@.',\n 'That encodes that at original line 154 (which is now line 159), 12 lines were removed/changed with 39 lines.',\n 'Variables 0 and 1 refer to the diff index out of total number of diffs.',\n 'Variables 2 and 4 will be numbers (a line number).',\n 'Variables 3 and 5 will be \"no lines changed\", \"1 line changed\" or \"X lines changed\", localized separately.'\n ]\n }, \"Difference {0} of {1}: original line {2}, {3}, modified line {4}, {5}\", (diffIndex + 1), this._diffs.length, minOriginalLine, originalChangedLinesCntAria, minModifiedLine, modifiedChangedLinesCntAria));\n header.appendChild(cell);\n // @@ -504,7 +517,7 @@\n header.setAttribute('role', 'listitem');\n container.appendChild(header);\n const lineHeight = modifiedOptions.get(61 /* EditorOption.lineHeight */);\n let modLine = minModifiedLine;\n for (let i = 0, len = diffs.length; i < len; i++) {\n const diffEntry = diffs[i];\n DiffReview._renderSection(container, diffEntry, modLine, lineHeight, this._width, originalOptions, originalModel, originalModelOpts, modifiedOptions, modifiedModel, modifiedModelOpts, this._languageService.languageIdCodec);\n if (diffEntry.modifiedLineStart !== 0) {\n modLine = diffEntry.modifiedLineEnd;\n }\n }\n dom.clearNode(this._content.domNode);\n this._content.domNode.appendChild(container);\n this.scrollbar.scanDomNode();\n }\n static _renderSection(dest, diffEntry, modLine, lineHeight, width, originalOptions, originalModel, originalModelOpts, modifiedOptions, modifiedModel, modifiedModelOpts, languageIdCodec) {\n const type = diffEntry.getType();\n let rowClassName = 'diff-review-row';\n let lineNumbersExtraClassName = '';\n const spacerClassName = 'diff-review-spacer';\n let spacerIcon = null;\n switch (type) {\n case 1 /* DiffEntryType.Insert */:\n rowClassName = 'diff-review-row line-insert';\n lineNumbersExtraClassName = ' char-insert';\n spacerIcon = diffReviewInsertIcon;\n break;\n case 2 /* DiffEntryType.Delete */:\n rowClassName = 'diff-review-row line-delete';\n lineNumbersExtraClassName = ' char-delete';\n spacerIcon = diffReviewRemoveIcon;\n break;\n }\n const originalLineStart = diffEntry.originalLineStart;\n const originalLineEnd = diffEntry.originalLineEnd;\n const modifiedLineStart = diffEntry.modifiedLineStart;\n const modifiedLineEnd = diffEntry.modifiedLineEnd;\n const cnt = Math.max(modifiedLineEnd - modifiedLineStart, originalLineEnd - originalLineStart);\n const originalLayoutInfo = originalOptions.get(133 /* EditorOption.layoutInfo */);\n const originalLineNumbersWidth = originalLayoutInfo.glyphMarginWidth + originalLayoutInfo.lineNumbersWidth;\n const modifiedLayoutInfo = modifiedOptions.get(133 /* EditorOption.layoutInfo */);\n const modifiedLineNumbersWidth = 10 + modifiedLayoutInfo.glyphMarginWidth + modifiedLayoutInfo.lineNumbersWidth;\n for (let i = 0; i <= cnt; i++) {\n const originalLine = (originalLineStart === 0 ? 0 : originalLineStart + i);\n const modifiedLine = (modifiedLineStart === 0 ? 0 : modifiedLineStart + i);\n const row = document.createElement('div');\n row.style.minWidth = width + 'px';\n row.className = rowClassName;\n row.setAttribute('role', 'listitem');\n if (modifiedLine !== 0) {\n modLine = modifiedLine;\n }\n row.setAttribute('data-line', String(modLine));\n const cell = document.createElement('div');\n cell.className = 'diff-review-cell';\n cell.style.height = `${lineHeight}px`;\n row.appendChild(cell);\n const originalLineNumber = document.createElement('span');\n originalLineNumber.style.width = (originalLineNumbersWidth + 'px');\n originalLineNumber.style.minWidth = (originalLineNumbersWidth + 'px');\n originalLineNumber.className = 'diff-review-line-number' + lineNumbersExtraClassName;\n if (originalLine !== 0) {\n originalLineNumber.appendChild(document.createTextNode(String(originalLine)));\n }\n else {\n originalLineNumber.innerText = '\\u00a0';\n }\n cell.appendChild(originalLineNumber);\n const modifiedLineNumber = document.createElement('span');\n modifiedLineNumber.style.width = (modifiedLineNumbersWidth + 'px');\n modifiedLineNumber.style.minWidth = (modifiedLineNumbersWidth + 'px');\n modifiedLineNumber.style.paddingRight = '10px';\n modifiedLineNumber.className = 'diff-review-line-number' + lineNumbersExtraClassName;\n if (modifiedLine !== 0) {\n modifiedLineNumber.appendChild(document.createTextNode(String(modifiedLine)));\n }\n else {\n modifiedLineNumber.innerText = '\\u00a0';\n }\n cell.appendChild(modifiedLineNumber);\n const spacer = document.createElement('span');\n spacer.className = spacerClassName;\n if (spacerIcon) {\n const spacerCodicon = document.createElement('span');\n spacerCodicon.className = ThemeIcon.asClassName(spacerIcon);\n spacerCodicon.innerText = '\\u00a0\\u00a0';\n spacer.appendChild(spacerCodicon);\n }\n else {\n spacer.innerText = '\\u00a0\\u00a0';\n }\n cell.appendChild(spacer);\n let lineContent;\n if (modifiedLine !== 0) {\n let html = this._renderLine(modifiedModel, modifiedOptions, modifiedModelOpts.tabSize, modifiedLine, languageIdCodec);\n if (DiffReview._ttPolicy) {\n html = DiffReview._ttPolicy.createHTML(html);\n }\n cell.insertAdjacentHTML('beforeend', html);\n lineContent = modifiedModel.getLineContent(modifiedLine);\n }\n else {\n let html = this._renderLine(originalModel, originalOptions, originalModelOpts.tabSize, originalLine, languageIdCodec);\n if (DiffReview._ttPolicy) {\n html = DiffReview._ttPolicy.createHTML(html);\n }\n cell.insertAdjacentHTML('beforeend', html);\n lineContent = originalModel.getLineContent(originalLine);\n }\n if (lineContent.length === 0) {\n lineContent = nls.localize('blankLine', \"blank\");\n }\n let ariaLabel = '';\n switch (type) {\n case 0 /* DiffEntryType.Equal */:\n if (originalLine === modifiedLine) {\n ariaLabel = nls.localize({ key: 'unchangedLine', comment: ['The placeholders are contents of the line and should not be translated.'] }, \"{0} unchanged line {1}\", lineContent, originalLine);\n }\n else {\n ariaLabel = nls.localize('equalLine', \"{0} original line {1} modified line {2}\", lineContent, originalLine, modifiedLine);\n }\n break;\n case 1 /* DiffEntryType.Insert */:\n ariaLabel = nls.localize('insertLine', \"+ {0} modified line {1}\", lineContent, modifiedLine);\n break;\n case 2 /* DiffEntryType.Delete */:\n ariaLabel = nls.localize('deleteLine', \"- {0} original line {1}\", lineContent, originalLine);\n break;\n }\n row.setAttribute('aria-label', ariaLabel);\n dest.appendChild(row);\n }\n }\n static _renderLine(model, options, tabSize, lineNumber, languageIdCodec) {\n const lineContent = model.getLineContent(lineNumber);\n const fontInfo = options.get(46 /* EditorOption.fontInfo */);\n const lineTokens = LineTokens.createEmpty(lineContent, languageIdCodec);\n const isBasicASCII = ViewLineRenderingData.isBasicASCII(lineContent, model.mightContainNonBasicASCII());\n const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, model.mightContainRTL());\n const r = renderViewLine(new RenderLineInput((fontInfo.isMonospace && !options.get(29 /* EditorOption.disableMonospaceOptimizations */)), fontInfo.canUseHalfwidthRightwardsArrow, lineContent, false, isBasicASCII, containsRTL, 0, lineTokens, [], tabSize, 0, fontInfo.spaceWidth, fontInfo.middotWidth, fontInfo.wsmiddotWidth, options.get(107 /* EditorOption.stopRenderingLineAfter */), options.get(90 /* EditorOption.renderWhitespace */), options.get(85 /* EditorOption.renderControlCharacters */), options.get(47 /* EditorOption.fontLigatures */) !== EditorFontLigatures.OFF, null));\n return r.html;\n }\n};\nDiffReview._ttPolicy = (_a = window.trustedTypes) === null || _a === void 0 ? void 0 : _a.createPolicy('diffReview', { createHTML: value => value });\nDiffReview = __decorate([\n __param(1, ILanguageService)\n], DiffReview);\nexport { DiffReview };\n// theming\nregisterThemingParticipant((theme, collector) => {\n const lineNumbers = theme.getColor(editorLineNumbers);\n if (lineNumbers) {\n collector.addRule(`.monaco-diff-editor .diff-review-line-number { color: ${lineNumbers}; }`);\n }\n const shadow = theme.getColor(scrollbarShadow);\n if (shadow) {\n collector.addRule(`.monaco-diff-editor .diff-review-shadow { box-shadow: ${shadow} 0 -6px 6px -6px inset; }`);\n }\n});\nclass DiffReviewNext extends EditorAction {\n constructor() {\n super({\n id: 'editor.action.diffReview.next',\n label: nls.localize('editor.action.diffReview.next', \"Go to Next Difference\"),\n alias: 'Go to Next Difference',\n precondition: ContextKeyExpr.has('isInDiffEditor'),\n kbOpts: {\n kbExpr: null,\n primary: 65 /* KeyCode.F7 */,\n weight: 100 /* KeybindingWeight.EditorContrib */\n }\n });\n }\n run(accessor, editor) {\n const diffEditor = findFocusedDiffEditor(accessor);\n if (diffEditor) {\n diffEditor.diffReviewNext();\n }\n }\n}\nclass DiffReviewPrev extends EditorAction {\n constructor() {\n super({\n id: 'editor.action.diffReview.prev',\n label: nls.localize('editor.action.diffReview.prev', \"Go to Previous Difference\"),\n alias: 'Go to Previous Difference',\n precondition: ContextKeyExpr.has('isInDiffEditor'),\n kbOpts: {\n kbExpr: null,\n primary: 1024 /* KeyMod.Shift */ | 65 /* KeyCode.F7 */,\n weight: 100 /* KeybindingWeight.EditorContrib */\n }\n });\n }\n run(accessor, editor) {\n const diffEditor = findFocusedDiffEditor(accessor);\n if (diffEditor) {\n diffEditor.diffReviewPrev();\n }\n }\n}\nfunction findFocusedDiffEditor(accessor) {\n const codeEditorService = accessor.get(ICodeEditorService);\n const diffEditors = codeEditorService.listDiffEditors();\n const activeCodeEditor = codeEditorService.getActiveCodeEditor();\n if (!activeCodeEditor) {\n return null;\n }\n for (let i = 0, len = diffEditors.length; i < len; i++) {\n const diffEditor = diffEditors[i];\n if (diffEditor.getModifiedEditor().getId() === activeCodeEditor.getId() || diffEditor.getOriginalEditor().getId() === activeCodeEditor.getId()) {\n return diffEditor;\n }\n }\n return null;\n}\nregisterEditorAction(DiffReviewNext);\nregisterEditorAction(DiffReviewPrev);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport * as nls from '../../../nls.js';\nimport * as dom from '../../../base/browser/dom.js';\nimport { Action } from '../../../base/common/actions.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { Range } from '../../common/core/range.js';\nimport { Codicon } from '../../../base/common/codicons.js';\nexport class InlineDiffMargin extends Disposable {\n constructor(_viewZoneId, _marginDomNode, editor, diff, _contextMenuService, _clipboardService) {\n super();\n this._viewZoneId = _viewZoneId;\n this._marginDomNode = _marginDomNode;\n this.editor = editor;\n this.diff = diff;\n this._contextMenuService = _contextMenuService;\n this._clipboardService = _clipboardService;\n this._visibility = false;\n // make sure the diff margin shows above overlay.\n this._marginDomNode.style.zIndex = '10';\n this._diffActions = document.createElement('div');\n this._diffActions.className = Codicon.lightBulb.classNames + ' lightbulb-glyph';\n this._diffActions.style.position = 'absolute';\n const lineHeight = editor.getOption(61 /* EditorOption.lineHeight */);\n const lineFeed = editor.getModel().getEOL();\n this._diffActions.style.right = '0px';\n this._diffActions.style.visibility = 'hidden';\n this._diffActions.style.height = `${lineHeight}px`;\n this._diffActions.style.lineHeight = `${lineHeight}px`;\n this._marginDomNode.appendChild(this._diffActions);\n const actions = [];\n const isDeletion = diff.modifiedEndLineNumber === 0;\n // default action\n actions.push(new Action('diff.clipboard.copyDeletedContent', isDeletion\n ? (diff.originalEndLineNumber > diff.modifiedStartLineNumber\n ? nls.localize('diff.clipboard.copyDeletedLinesContent.label', \"Copy deleted lines\")\n : nls.localize('diff.clipboard.copyDeletedLinesContent.single.label', \"Copy deleted line\"))\n : (diff.originalEndLineNumber > diff.modifiedStartLineNumber\n ? nls.localize('diff.clipboard.copyChangedLinesContent.label', \"Copy changed lines\")\n : nls.localize('diff.clipboard.copyChangedLinesContent.single.label', \"Copy changed line\")), undefined, true, () => __awaiter(this, void 0, void 0, function* () {\n const range = new Range(diff.originalStartLineNumber, 1, diff.originalEndLineNumber + 1, 1);\n const deletedText = diff.originalModel.getValueInRange(range);\n yield this._clipboardService.writeText(deletedText);\n })));\n let currentLineNumberOffset = 0;\n let copyLineAction = undefined;\n if (diff.originalEndLineNumber > diff.modifiedStartLineNumber) {\n copyLineAction = new Action('diff.clipboard.copyDeletedLineContent', isDeletion\n ? nls.localize('diff.clipboard.copyDeletedLineContent.label', \"Copy deleted line ({0})\", diff.originalStartLineNumber)\n : nls.localize('diff.clipboard.copyChangedLineContent.label', \"Copy changed line ({0})\", diff.originalStartLineNumber), undefined, true, () => __awaiter(this, void 0, void 0, function* () {\n const lineContent = diff.originalModel.getLineContent(diff.originalStartLineNumber + currentLineNumberOffset);\n if (lineContent === '') {\n // empty line\n const eof = diff.originalModel.getEndOfLineSequence();\n yield this._clipboardService.writeText(eof === 0 /* EndOfLineSequence.LF */ ? '\\n' : '\\r\\n');\n }\n else {\n yield this._clipboardService.writeText(lineContent);\n }\n }));\n actions.push(copyLineAction);\n }\n const readOnly = editor.getOption(83 /* EditorOption.readOnly */);\n if (!readOnly) {\n actions.push(new Action('diff.inline.revertChange', nls.localize('diff.inline.revertChange.label', \"Revert this change\"), undefined, true, () => __awaiter(this, void 0, void 0, function* () {\n const range = new Range(diff.originalStartLineNumber, 1, diff.originalEndLineNumber, diff.originalModel.getLineMaxColumn(diff.originalEndLineNumber));\n const deletedText = diff.originalModel.getValueInRange(range);\n if (diff.modifiedEndLineNumber === 0) {\n // deletion only\n const column = editor.getModel().getLineMaxColumn(diff.modifiedStartLineNumber);\n editor.executeEdits('diffEditor', [\n {\n range: new Range(diff.modifiedStartLineNumber, column, diff.modifiedStartLineNumber, column),\n text: lineFeed + deletedText\n }\n ]);\n }\n else {\n const column = editor.getModel().getLineMaxColumn(diff.modifiedEndLineNumber);\n editor.executeEdits('diffEditor', [\n {\n range: new Range(diff.modifiedStartLineNumber, 1, diff.modifiedEndLineNumber, column),\n text: deletedText\n }\n ]);\n }\n })));\n }\n const showContextMenu = (x, y) => {\n this._contextMenuService.showContextMenu({\n getAnchor: () => {\n return {\n x,\n y\n };\n },\n getActions: () => {\n if (copyLineAction) {\n copyLineAction.label =\n isDeletion\n ? nls.localize('diff.clipboard.copyDeletedLineContent.label', \"Copy deleted line ({0})\", diff.originalStartLineNumber + currentLineNumberOffset)\n : nls.localize('diff.clipboard.copyChangedLineContent.label', \"Copy changed line ({0})\", diff.originalStartLineNumber + currentLineNumberOffset);\n }\n return actions;\n },\n autoSelectFirstItem: true\n });\n };\n this._register(dom.addStandardDisposableListener(this._diffActions, 'mousedown', e => {\n const { top, height } = dom.getDomNodePagePosition(this._diffActions);\n const pad = Math.floor(lineHeight / 3);\n e.preventDefault();\n showContextMenu(e.posx, top + height + pad);\n }));\n this._register(editor.onMouseMove((e) => {\n if (e.target.type === 8 /* MouseTargetType.CONTENT_VIEW_ZONE */ || e.target.type === 5 /* MouseTargetType.GUTTER_VIEW_ZONE */) {\n const viewZoneId = e.target.detail.viewZoneId;\n if (viewZoneId === this._viewZoneId) {\n this.visibility = true;\n currentLineNumberOffset = this._updateLightBulbPosition(this._marginDomNode, e.event.browserEvent.y, lineHeight);\n }\n else {\n this.visibility = false;\n }\n }\n else {\n this.visibility = false;\n }\n }));\n this._register(editor.onMouseDown((e) => {\n if (!e.event.rightButton) {\n return;\n }\n if (e.target.type === 8 /* MouseTargetType.CONTENT_VIEW_ZONE */ || e.target.type === 5 /* MouseTargetType.GUTTER_VIEW_ZONE */) {\n const viewZoneId = e.target.detail.viewZoneId;\n if (viewZoneId === this._viewZoneId) {\n e.event.preventDefault();\n currentLineNumberOffset = this._updateLightBulbPosition(this._marginDomNode, e.event.browserEvent.y, lineHeight);\n showContextMenu(e.event.posx, e.event.posy + lineHeight);\n }\n }\n }));\n }\n get visibility() {\n return this._visibility;\n }\n set visibility(_visibility) {\n if (this._visibility !== _visibility) {\n this._visibility = _visibility;\n if (_visibility) {\n this._diffActions.style.visibility = 'visible';\n }\n else {\n this._diffActions.style.visibility = 'hidden';\n }\n }\n }\n _updateLightBulbPosition(marginDomNode, y, lineHeight) {\n const { top } = dom.getDomNodePagePosition(marginDomNode);\n const offset = y - top;\n const lineNumberOffset = Math.floor(offset / lineHeight);\n const newTop = lineNumberOffset * lineHeight;\n this._diffActions.style.top = `${newTop}px`;\n if (this.diff.viewLineCounts) {\n let acc = 0;\n for (let i = 0; i < this.diff.viewLineCounts.length; i++) {\n acc += this.diff.viewLineCounts[i];\n if (lineNumberOffset < acc) {\n return i;\n }\n }\n }\n return lineNumberOffset;\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar _a;\nimport './media/diffEditor.css';\nimport * as nls from '../../../nls.js';\nimport * as dom from '../../../base/browser/dom.js';\nimport * as assert from '../../../base/common/assert.js';\nimport { createFastDomNode } from '../../../base/browser/fastDomNode.js';\nimport { Sash } from '../../../base/browser/ui/sash/sash.js';\nimport { RunOnceScheduler } from '../../../base/common/async.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { applyFontInfo } from '../config/domFontInfo.js';\nimport { StableEditorScrollState } from '../stableEditorScroll.js';\nimport { ICodeEditorService } from '../services/codeEditorService.js';\nimport { CodeEditorWidget } from './codeEditorWidget.js';\nimport { DiffReview } from './diffReview.js';\nimport { EditorOptions, EditorFontLigatures, stringSet as validateStringSetOption, boolean as validateBooleanOption, clampedInt } from '../../common/config/editorOptions.js';\nimport { Position } from '../../common/core/position.js';\nimport { Range } from '../../common/core/range.js';\nimport { createStringBuilder } from '../../common/core/stringBuilder.js';\nimport * as editorCommon from '../../common/editorCommon.js';\nimport { ModelDecorationOptions } from '../../common/model/textModel.js';\nimport { IEditorWorkerService } from '../../common/services/editorWorker.js';\nimport { OverviewRulerZone } from '../../common/viewModel/overviewZoneManager.js';\nimport { LineDecoration } from '../../common/viewLayout/lineDecorations.js';\nimport { RenderLineInput, renderViewLine } from '../../common/viewLayout/viewLineRenderer.js';\nimport { InlineDecoration, ViewLineRenderingData } from '../../common/viewModel.js';\nimport { IContextKeyService } from '../../../platform/contextkey/common/contextkey.js';\nimport { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';\nimport { ServiceCollection } from '../../../platform/instantiation/common/serviceCollection.js';\nimport { INotificationService } from '../../../platform/notification/common/notification.js';\nimport { defaultInsertColor, defaultRemoveColor, diffBorder, diffInserted, diffInsertedOutline, diffRemoved, diffRemovedOutline, scrollbarShadow, scrollbarSliderBackground, scrollbarSliderHoverBackground, scrollbarSliderActiveBackground, diffDiagonalFill, diffInsertedLineGutter, diffRemovedLineGutter, diffInsertedLine, diffRemovedLine, diffOverviewRulerInserted, diffOverviewRulerRemoved } from '../../../platform/theme/common/colorRegistry.js';\nimport { IThemeService, getThemeTypeSelector, registerThemingParticipant, ThemeIcon } from '../../../platform/theme/common/themeService.js';\nimport { IContextMenuService } from '../../../platform/contextview/browser/contextView.js';\nimport { InlineDiffMargin } from './inlineDiffMargin.js';\nimport { IClipboardService } from '../../../platform/clipboard/common/clipboardService.js';\nimport { EditorExtensionsRegistry } from '../editorExtensions.js';\nimport { onUnexpectedError } from '../../../base/common/errors.js';\nimport { IEditorProgressService } from '../../../platform/progress/common/progress.js';\nimport { ElementSizeObserver } from '../config/elementSizeObserver.js';\nimport { Codicon } from '../../../base/common/codicons.js';\nimport { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from '../../../base/browser/ui/mouseCursor/mouseCursor.js';\nimport { registerIcon } from '../../../platform/theme/common/iconRegistry.js';\nimport { isHighContrast } from '../../../platform/theme/common/theme.js';\nclass VisualEditorState {\n constructor(_contextMenuService, _clipboardService) {\n this._contextMenuService = _contextMenuService;\n this._clipboardService = _clipboardService;\n this._zones = [];\n this._inlineDiffMargins = [];\n this._zonesMap = {};\n this._decorations = [];\n }\n getForeignViewZones(allViewZones) {\n return allViewZones.filter((z) => !this._zonesMap[String(z.id)]);\n }\n clean(editor) {\n // (1) View zones\n if (this._zones.length > 0) {\n editor.changeViewZones((viewChangeAccessor) => {\n for (const zoneId of this._zones) {\n viewChangeAccessor.removeZone(zoneId);\n }\n });\n }\n this._zones = [];\n this._zonesMap = {};\n // (2) Model decorations\n editor.changeDecorations((changeAccessor) => {\n this._decorations = changeAccessor.deltaDecorations(this._decorations, []);\n });\n }\n apply(editor, overviewRuler, newDecorations, restoreScrollState) {\n const scrollState = restoreScrollState ? StableEditorScrollState.capture(editor) : null;\n // view zones\n editor.changeViewZones((viewChangeAccessor) => {\n var _a;\n for (const zoneId of this._zones) {\n viewChangeAccessor.removeZone(zoneId);\n }\n for (const inlineDiffMargin of this._inlineDiffMargins) {\n inlineDiffMargin.dispose();\n }\n this._zones = [];\n this._zonesMap = {};\n this._inlineDiffMargins = [];\n for (let i = 0, length = newDecorations.zones.length; i < length; i++) {\n const viewZone = newDecorations.zones[i];\n viewZone.suppressMouseDown = true;\n const zoneId = viewChangeAccessor.addZone(viewZone);\n this._zones.push(zoneId);\n this._zonesMap[String(zoneId)] = true;\n if (newDecorations.zones[i].diff && viewZone.marginDomNode) {\n viewZone.suppressMouseDown = false;\n if (((_a = newDecorations.zones[i].diff) === null || _a === void 0 ? void 0 : _a.originalModel.getValueLength()) !== 0) {\n // do not contribute diff margin actions for newly created files\n this._inlineDiffMargins.push(new InlineDiffMargin(zoneId, viewZone.marginDomNode, editor, newDecorations.zones[i].diff, this._contextMenuService, this._clipboardService));\n }\n }\n }\n });\n scrollState === null || scrollState === void 0 ? void 0 : scrollState.restore(editor);\n // decorations\n editor.changeDecorations((changeAccessor) => {\n this._decorations = changeAccessor.deltaDecorations(this._decorations, newDecorations.decorations);\n });\n // overview ruler\n overviewRuler === null || overviewRuler === void 0 ? void 0 : overviewRuler.setZones(newDecorations.overviewZones);\n }\n}\nlet DIFF_EDITOR_ID = 0;\nconst diffInsertIcon = registerIcon('diff-insert', Codicon.add, nls.localize('diffInsertIcon', 'Line decoration for inserts in the diff editor.'));\nconst diffRemoveIcon = registerIcon('diff-remove', Codicon.remove, nls.localize('diffRemoveIcon', 'Line decoration for removals in the diff editor.'));\nconst ttPolicy = (_a = window.trustedTypes) === null || _a === void 0 ? void 0 : _a.createPolicy('diffEditorWidget', { createHTML: value => value });\nlet DiffEditorWidget = class DiffEditorWidget extends Disposable {\n constructor(domElement, options, codeEditorWidgetOptions, clipboardService, editorWorkerService, contextKeyService, instantiationService, codeEditorService, themeService, notificationService, contextMenuService, _editorProgressService) {\n super();\n this._editorProgressService = _editorProgressService;\n this._onDidDispose = this._register(new Emitter());\n this.onDidDispose = this._onDidDispose.event;\n this._onDidUpdateDiff = this._register(new Emitter());\n this.onDidUpdateDiff = this._onDidUpdateDiff.event;\n this._onDidContentSizeChange = this._register(new Emitter());\n this._lastOriginalWarning = null;\n this._lastModifiedWarning = null;\n this._editorWorkerService = editorWorkerService;\n this._codeEditorService = codeEditorService;\n this._contextKeyService = this._register(contextKeyService.createScoped(domElement));\n this._instantiationService = instantiationService.createChild(new ServiceCollection([IContextKeyService, this._contextKeyService]));\n this._contextKeyService.createKey('isInDiffEditor', true);\n this._themeService = themeService;\n this._notificationService = notificationService;\n this._id = (++DIFF_EDITOR_ID);\n this._state = 0 /* editorBrowser.DiffEditorState.Idle */;\n this._updatingDiffProgress = null;\n this._domElement = domElement;\n options = options || {};\n this._options = validateDiffEditorOptions(options, {\n enableSplitViewResizing: true,\n renderSideBySide: true,\n renderMarginRevertIcon: true,\n maxComputationTime: 5000,\n maxFileSize: 50,\n ignoreTrimWhitespace: true,\n renderIndicators: true,\n originalEditable: false,\n diffCodeLens: false,\n renderOverviewRuler: true,\n diffWordWrap: 'inherit'\n });\n if (typeof options.isInEmbeddedEditor !== 'undefined') {\n this._contextKeyService.createKey('isInEmbeddedDiffEditor', options.isInEmbeddedEditor);\n }\n else {\n this._contextKeyService.createKey('isInEmbeddedDiffEditor', false);\n }\n this._updateDecorationsRunner = this._register(new RunOnceScheduler(() => this._updateDecorations(), 0));\n this._containerDomElement = document.createElement('div');\n this._containerDomElement.className = DiffEditorWidget._getClassName(this._themeService.getColorTheme(), this._options.renderSideBySide);\n this._containerDomElement.style.position = 'relative';\n this._containerDomElement.style.height = '100%';\n this._domElement.appendChild(this._containerDomElement);\n this._overviewViewportDomElement = createFastDomNode(document.createElement('div'));\n this._overviewViewportDomElement.setClassName('diffViewport');\n this._overviewViewportDomElement.setPosition('absolute');\n this._overviewDomElement = document.createElement('div');\n this._overviewDomElement.className = 'diffOverview';\n this._overviewDomElement.style.position = 'absolute';\n this._overviewDomElement.appendChild(this._overviewViewportDomElement.domNode);\n this._register(dom.addStandardDisposableListener(this._overviewDomElement, dom.EventType.POINTER_DOWN, (e) => {\n this._modifiedEditor.delegateVerticalScrollbarPointerDown(e);\n }));\n if (this._options.renderOverviewRuler) {\n this._containerDomElement.appendChild(this._overviewDomElement);\n }\n // Create left side\n this._originalDomNode = document.createElement('div');\n this._originalDomNode.className = 'editor original';\n this._originalDomNode.style.position = 'absolute';\n this._originalDomNode.style.height = '100%';\n this._containerDomElement.appendChild(this._originalDomNode);\n // Create right side\n this._modifiedDomNode = document.createElement('div');\n this._modifiedDomNode.className = 'editor modified';\n this._modifiedDomNode.style.position = 'absolute';\n this._modifiedDomNode.style.height = '100%';\n this._containerDomElement.appendChild(this._modifiedDomNode);\n this._beginUpdateDecorationsTimeout = -1;\n this._currentlyChangingViewZones = false;\n this._diffComputationToken = 0;\n this._originalEditorState = new VisualEditorState(contextMenuService, clipboardService);\n this._modifiedEditorState = new VisualEditorState(contextMenuService, clipboardService);\n this._isVisible = true;\n this._isHandlingScrollEvent = false;\n this._elementSizeObserver = this._register(new ElementSizeObserver(this._containerDomElement, options.dimension));\n this._register(this._elementSizeObserver.onDidChange(() => this._onDidContainerSizeChanged()));\n if (options.automaticLayout) {\n this._elementSizeObserver.startObserving();\n }\n this._diffComputationResult = null;\n this._originalEditor = this._createLeftHandSideEditor(options, codeEditorWidgetOptions.originalEditor || {});\n this._modifiedEditor = this._createRightHandSideEditor(options, codeEditorWidgetOptions.modifiedEditor || {});\n this._originalOverviewRuler = null;\n this._modifiedOverviewRuler = null;\n this._reviewPane = instantiationService.createInstance(DiffReview, this);\n this._containerDomElement.appendChild(this._reviewPane.domNode.domNode);\n this._containerDomElement.appendChild(this._reviewPane.shadow.domNode);\n this._containerDomElement.appendChild(this._reviewPane.actionBarContainer.domNode);\n if (this._options.renderSideBySide) {\n this._setStrategy(new DiffEditorWidgetSideBySide(this._createDataSource(), this._options.enableSplitViewResizing));\n }\n else {\n this._setStrategy(new DiffEditorWidgetInline(this._createDataSource(), this._options.enableSplitViewResizing));\n }\n this._register(themeService.onDidColorThemeChange(t => {\n if (this._strategy && this._strategy.applyColors(t)) {\n this._updateDecorationsRunner.schedule();\n }\n this._containerDomElement.className = DiffEditorWidget._getClassName(this._themeService.getColorTheme(), this._options.renderSideBySide);\n }));\n const contributions = EditorExtensionsRegistry.getDiffEditorContributions();\n for (const desc of contributions) {\n try {\n this._register(instantiationService.createInstance(desc.ctor, this));\n }\n catch (err) {\n onUnexpectedError(err);\n }\n }\n this._codeEditorService.addDiffEditor(this);\n }\n _setState(newState) {\n if (this._state === newState) {\n return;\n }\n this._state = newState;\n if (this._updatingDiffProgress) {\n this._updatingDiffProgress.done();\n this._updatingDiffProgress = null;\n }\n if (this._state === 1 /* editorBrowser.DiffEditorState.ComputingDiff */) {\n this._updatingDiffProgress = this._editorProgressService.show(true, 1000);\n }\n }\n diffReviewNext() {\n this._reviewPane.next();\n }\n diffReviewPrev() {\n this._reviewPane.prev();\n }\n static _getClassName(theme, renderSideBySide) {\n let result = 'monaco-diff-editor monaco-editor-background ';\n if (renderSideBySide) {\n result += 'side-by-side ';\n }\n result += getThemeTypeSelector(theme.type);\n return result;\n }\n _disposeOverviewRulers() {\n if (this._originalOverviewRuler) {\n this._overviewDomElement.removeChild(this._originalOverviewRuler.getDomNode());\n this._originalOverviewRuler.dispose();\n this._originalOverviewRuler = null;\n }\n if (this._modifiedOverviewRuler) {\n this._overviewDomElement.removeChild(this._modifiedOverviewRuler.getDomNode());\n this._modifiedOverviewRuler.dispose();\n this._modifiedOverviewRuler = null;\n }\n }\n _createOverviewRulers() {\n if (!this._options.renderOverviewRuler) {\n return;\n }\n assert.ok(!this._originalOverviewRuler && !this._modifiedOverviewRuler);\n if (this._originalEditor.hasModel()) {\n this._originalOverviewRuler = this._originalEditor.createOverviewRuler('original diffOverviewRuler');\n this._overviewDomElement.appendChild(this._originalOverviewRuler.getDomNode());\n }\n if (this._modifiedEditor.hasModel()) {\n this._modifiedOverviewRuler = this._modifiedEditor.createOverviewRuler('modified diffOverviewRuler');\n this._overviewDomElement.appendChild(this._modifiedOverviewRuler.getDomNode());\n }\n this._layoutOverviewRulers();\n }\n _createLeftHandSideEditor(options, codeEditorWidgetOptions) {\n const editor = this._createInnerEditor(this._instantiationService, this._originalDomNode, this._adjustOptionsForLeftHandSide(options), codeEditorWidgetOptions);\n this._register(editor.onDidScrollChange((e) => {\n if (this._isHandlingScrollEvent) {\n return;\n }\n if (!e.scrollTopChanged && !e.scrollLeftChanged && !e.scrollHeightChanged) {\n return;\n }\n this._isHandlingScrollEvent = true;\n this._modifiedEditor.setScrollPosition({\n scrollLeft: e.scrollLeft,\n scrollTop: e.scrollTop\n });\n this._isHandlingScrollEvent = false;\n this._layoutOverviewViewport();\n }));\n this._register(editor.onDidChangeViewZones(() => {\n this._onViewZonesChanged();\n }));\n this._register(editor.onDidChangeConfiguration((e) => {\n if (!editor.getModel()) {\n return;\n }\n if (e.hasChanged(46 /* EditorOption.fontInfo */)) {\n this._updateDecorationsRunner.schedule();\n }\n if (e.hasChanged(134 /* EditorOption.wrappingInfo */)) {\n this._updateDecorationsRunner.cancel();\n this._updateDecorations();\n }\n }));\n this._register(editor.onDidChangeHiddenAreas(() => {\n this._updateDecorationsRunner.cancel();\n this._updateDecorations();\n }));\n this._register(editor.onDidChangeModelContent(() => {\n if (this._isVisible) {\n this._beginUpdateDecorationsSoon();\n }\n }));\n const isInDiffLeftEditorKey = this._contextKeyService.createKey('isInDiffLeftEditor', editor.hasWidgetFocus());\n this._register(editor.onDidFocusEditorWidget(() => isInDiffLeftEditorKey.set(true)));\n this._register(editor.onDidBlurEditorWidget(() => isInDiffLeftEditorKey.set(false)));\n this._register(editor.onDidContentSizeChange(e => {\n const width = this._originalEditor.getContentWidth() + this._modifiedEditor.getContentWidth() + DiffEditorWidget.ONE_OVERVIEW_WIDTH;\n const height = Math.max(this._modifiedEditor.getContentHeight(), this._originalEditor.getContentHeight());\n this._onDidContentSizeChange.fire({\n contentHeight: height,\n contentWidth: width,\n contentHeightChanged: e.contentHeightChanged,\n contentWidthChanged: e.contentWidthChanged\n });\n }));\n return editor;\n }\n _createRightHandSideEditor(options, codeEditorWidgetOptions) {\n const editor = this._createInnerEditor(this._instantiationService, this._modifiedDomNode, this._adjustOptionsForRightHandSide(options), codeEditorWidgetOptions);\n this._register(editor.onDidScrollChange((e) => {\n if (this._isHandlingScrollEvent) {\n return;\n }\n if (!e.scrollTopChanged && !e.scrollLeftChanged && !e.scrollHeightChanged) {\n return;\n }\n this._isHandlingScrollEvent = true;\n this._originalEditor.setScrollPosition({\n scrollLeft: e.scrollLeft,\n scrollTop: e.scrollTop\n });\n this._isHandlingScrollEvent = false;\n this._layoutOverviewViewport();\n }));\n this._register(editor.onDidChangeViewZones(() => {\n this._onViewZonesChanged();\n }));\n this._register(editor.onDidChangeConfiguration((e) => {\n if (!editor.getModel()) {\n return;\n }\n if (e.hasChanged(46 /* EditorOption.fontInfo */)) {\n this._updateDecorationsRunner.schedule();\n }\n if (e.hasChanged(134 /* EditorOption.wrappingInfo */)) {\n this._updateDecorationsRunner.cancel();\n this._updateDecorations();\n }\n }));\n this._register(editor.onDidChangeHiddenAreas(() => {\n this._updateDecorationsRunner.cancel();\n this._updateDecorations();\n }));\n this._register(editor.onDidChangeModelContent(() => {\n if (this._isVisible) {\n this._beginUpdateDecorationsSoon();\n }\n }));\n this._register(editor.onDidChangeModelOptions((e) => {\n if (e.tabSize) {\n this._updateDecorationsRunner.schedule();\n }\n }));\n const isInDiffRightEditorKey = this._contextKeyService.createKey('isInDiffRightEditor', editor.hasWidgetFocus());\n this._register(editor.onDidFocusEditorWidget(() => isInDiffRightEditorKey.set(true)));\n this._register(editor.onDidBlurEditorWidget(() => isInDiffRightEditorKey.set(false)));\n this._register(editor.onDidContentSizeChange(e => {\n const width = this._originalEditor.getContentWidth() + this._modifiedEditor.getContentWidth() + DiffEditorWidget.ONE_OVERVIEW_WIDTH;\n const height = Math.max(this._modifiedEditor.getContentHeight(), this._originalEditor.getContentHeight());\n this._onDidContentSizeChange.fire({\n contentHeight: height,\n contentWidth: width,\n contentHeightChanged: e.contentHeightChanged,\n contentWidthChanged: e.contentWidthChanged\n });\n }));\n // Revert change when an arrow is clicked.\n this._register(editor.onMouseDown(event => {\n var _a, _b;\n if (!event.event.rightButton && event.target.position && ((_a = event.target.element) === null || _a === void 0 ? void 0 : _a.className.includes('arrow-revert-change'))) {\n const lineNumber = event.target.position.lineNumber;\n const change = (_b = this._diffComputationResult) === null || _b === void 0 ? void 0 : _b.changes.find(c => c.modifiedStartLineNumber === lineNumber - 1 || c.modifiedStartLineNumber === lineNumber);\n if (change) {\n this.revertChange(change);\n }\n event.event.stopPropagation();\n this._updateDecorations();\n return;\n }\n }));\n return editor;\n }\n /**\n * Reverts a change in the modified editor.\n */\n revertChange(change) {\n const editor = this._modifiedEditor;\n const original = this._originalEditor.getModel();\n const modified = this._modifiedEditor.getModel();\n if (!original || !modified || !editor) {\n return;\n }\n const originalRange = change.originalEndLineNumber > 0 ? new Range(change.originalStartLineNumber, 1, change.originalEndLineNumber, original.getLineMaxColumn(change.originalEndLineNumber)) : null;\n const originalContent = originalRange ? original.getValueInRange(originalRange) : null;\n const newRange = change.modifiedEndLineNumber > 0 ? new Range(change.modifiedStartLineNumber, 1, change.modifiedEndLineNumber, modified.getLineMaxColumn(change.modifiedEndLineNumber)) : null;\n const eol = modified.getEOL();\n if (change.originalEndLineNumber === 0 && newRange) {\n // Insert change.\n // To revert: delete the new content and a linebreak (if possible)\n let range = newRange;\n if (change.modifiedStartLineNumber > 1) {\n // Try to include a linebreak from before.\n range = newRange.setStartPosition(change.modifiedStartLineNumber - 1, modified.getLineMaxColumn(change.modifiedStartLineNumber - 1));\n }\n else if (change.modifiedEndLineNumber < modified.getLineCount()) {\n // Try to include the linebreak from after.\n range = newRange.setEndPosition(change.modifiedEndLineNumber + 1, 1);\n }\n editor.executeEdits('diffEditor', [{\n range,\n text: '',\n }]);\n }\n else if (change.modifiedEndLineNumber === 0 && originalContent !== null) {\n // Delete change.\n // To revert: insert the old content and a linebreak.\n const insertAt = change.modifiedStartLineNumber < modified.getLineCount() ? new Position(change.modifiedStartLineNumber + 1, 1) : new Position(change.modifiedStartLineNumber, modified.getLineMaxColumn(change.modifiedStartLineNumber));\n editor.executeEdits('diffEditor', [{\n range: Range.fromPositions(insertAt, insertAt),\n text: change.modifiedStartLineNumber < modified.getLineCount() ? originalContent + eol : eol + originalContent,\n }]);\n }\n else if (newRange && originalContent !== null) {\n // Modified change.\n editor.executeEdits('diffEditor', [{\n range: newRange,\n text: originalContent,\n }]);\n }\n }\n _createInnerEditor(instantiationService, container, options, editorWidgetOptions) {\n return instantiationService.createInstance(CodeEditorWidget, container, options, editorWidgetOptions);\n }\n dispose() {\n this._codeEditorService.removeDiffEditor(this);\n if (this._beginUpdateDecorationsTimeout !== -1) {\n window.clearTimeout(this._beginUpdateDecorationsTimeout);\n this._beginUpdateDecorationsTimeout = -1;\n }\n this._cleanViewZonesAndDecorations();\n if (this._originalOverviewRuler) {\n this._overviewDomElement.removeChild(this._originalOverviewRuler.getDomNode());\n this._originalOverviewRuler.dispose();\n }\n if (this._modifiedOverviewRuler) {\n this._overviewDomElement.removeChild(this._modifiedOverviewRuler.getDomNode());\n this._modifiedOverviewRuler.dispose();\n }\n this._overviewDomElement.removeChild(this._overviewViewportDomElement.domNode);\n if (this._options.renderOverviewRuler) {\n this._containerDomElement.removeChild(this._overviewDomElement);\n }\n this._containerDomElement.removeChild(this._originalDomNode);\n this._originalEditor.dispose();\n this._containerDomElement.removeChild(this._modifiedDomNode);\n this._modifiedEditor.dispose();\n this._strategy.dispose();\n this._containerDomElement.removeChild(this._reviewPane.domNode.domNode);\n this._containerDomElement.removeChild(this._reviewPane.shadow.domNode);\n this._containerDomElement.removeChild(this._reviewPane.actionBarContainer.domNode);\n this._reviewPane.dispose();\n this._domElement.removeChild(this._containerDomElement);\n this._onDidDispose.fire();\n super.dispose();\n }\n //------------ begin IDiffEditor methods\n getId() {\n return this.getEditorType() + ':' + this._id;\n }\n getEditorType() {\n return editorCommon.EditorType.IDiffEditor;\n }\n getLineChanges() {\n if (!this._diffComputationResult) {\n return null;\n }\n return this._diffComputationResult.changes;\n }\n getOriginalEditor() {\n return this._originalEditor;\n }\n getModifiedEditor() {\n return this._modifiedEditor;\n }\n updateOptions(_newOptions) {\n const newOptions = validateDiffEditorOptions(_newOptions, this._options);\n const changed = changedDiffEditorOptions(this._options, newOptions);\n this._options = newOptions;\n const beginUpdateDecorations = (changed.ignoreTrimWhitespace || changed.renderIndicators || changed.renderMarginRevertIcon);\n const beginUpdateDecorationsSoon = (this._isVisible && (changed.maxComputationTime || changed.maxFileSize));\n if (beginUpdateDecorations) {\n this._beginUpdateDecorations();\n }\n else if (beginUpdateDecorationsSoon) {\n this._beginUpdateDecorationsSoon();\n }\n this._modifiedEditor.updateOptions(this._adjustOptionsForRightHandSide(_newOptions));\n this._originalEditor.updateOptions(this._adjustOptionsForLeftHandSide(_newOptions));\n // enableSplitViewResizing\n this._strategy.setEnableSplitViewResizing(this._options.enableSplitViewResizing);\n // renderSideBySide\n if (changed.renderSideBySide) {\n if (this._options.renderSideBySide) {\n this._setStrategy(new DiffEditorWidgetSideBySide(this._createDataSource(), this._options.enableSplitViewResizing));\n }\n else {\n this._setStrategy(new DiffEditorWidgetInline(this._createDataSource(), this._options.enableSplitViewResizing));\n }\n // Update class name\n this._containerDomElement.className = DiffEditorWidget._getClassName(this._themeService.getColorTheme(), this._options.renderSideBySide);\n }\n // renderOverviewRuler\n if (changed.renderOverviewRuler) {\n if (this._options.renderOverviewRuler) {\n this._containerDomElement.appendChild(this._overviewDomElement);\n }\n else {\n this._containerDomElement.removeChild(this._overviewDomElement);\n }\n }\n }\n getModel() {\n return {\n original: this._originalEditor.getModel(),\n modified: this._modifiedEditor.getModel()\n };\n }\n setModel(model) {\n // Guard us against partial null model\n if (model && (!model.original || !model.modified)) {\n throw new Error(!model.original ? 'DiffEditorWidget.setModel: Original model is null' : 'DiffEditorWidget.setModel: Modified model is null');\n }\n // Remove all view zones & decorations\n this._cleanViewZonesAndDecorations();\n this._disposeOverviewRulers();\n // Update code editor models\n this._originalEditor.setModel(model ? model.original : null);\n this._modifiedEditor.setModel(model ? model.modified : null);\n this._updateDecorationsRunner.cancel();\n // this.originalEditor.onDidChangeModelOptions\n if (model) {\n this._originalEditor.setScrollTop(0);\n this._modifiedEditor.setScrollTop(0);\n }\n // Disable any diff computations that will come in\n this._diffComputationResult = null;\n this._diffComputationToken++;\n this._setState(0 /* editorBrowser.DiffEditorState.Idle */);\n if (model) {\n this._createOverviewRulers();\n // Begin comparing\n this._beginUpdateDecorations();\n }\n this._layoutOverviewViewport();\n }\n getContainerDomNode() {\n return this._domElement;\n }\n getVisibleColumnFromPosition(position) {\n return this._modifiedEditor.getVisibleColumnFromPosition(position);\n }\n getPosition() {\n return this._modifiedEditor.getPosition();\n }\n setPosition(position, source = 'api') {\n this._modifiedEditor.setPosition(position, source);\n }\n revealLine(lineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealLine(lineNumber, scrollType);\n }\n revealLineInCenter(lineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealLineInCenter(lineNumber, scrollType);\n }\n revealLineInCenterIfOutsideViewport(lineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealLineInCenterIfOutsideViewport(lineNumber, scrollType);\n }\n revealLineNearTop(lineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealLineNearTop(lineNumber, scrollType);\n }\n revealPosition(position, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealPosition(position, scrollType);\n }\n revealPositionInCenter(position, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealPositionInCenter(position, scrollType);\n }\n revealPositionInCenterIfOutsideViewport(position, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealPositionInCenterIfOutsideViewport(position, scrollType);\n }\n revealPositionNearTop(position, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealPositionNearTop(position, scrollType);\n }\n getSelection() {\n return this._modifiedEditor.getSelection();\n }\n getSelections() {\n return this._modifiedEditor.getSelections();\n }\n setSelection(something, source = 'api') {\n this._modifiedEditor.setSelection(something, source);\n }\n setSelections(ranges, source = 'api') {\n this._modifiedEditor.setSelections(ranges, source);\n }\n revealLines(startLineNumber, endLineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealLines(startLineNumber, endLineNumber, scrollType);\n }\n revealLinesInCenter(startLineNumber, endLineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealLinesInCenter(startLineNumber, endLineNumber, scrollType);\n }\n revealLinesInCenterIfOutsideViewport(startLineNumber, endLineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealLinesInCenterIfOutsideViewport(startLineNumber, endLineNumber, scrollType);\n }\n revealLinesNearTop(startLineNumber, endLineNumber, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealLinesNearTop(startLineNumber, endLineNumber, scrollType);\n }\n revealRange(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */, revealVerticalInCenter = false, revealHorizontal = true) {\n this._modifiedEditor.revealRange(range, scrollType, revealVerticalInCenter, revealHorizontal);\n }\n revealRangeInCenter(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealRangeInCenter(range, scrollType);\n }\n revealRangeInCenterIfOutsideViewport(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealRangeInCenterIfOutsideViewport(range, scrollType);\n }\n revealRangeNearTop(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealRangeNearTop(range, scrollType);\n }\n revealRangeNearTopIfOutsideViewport(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealRangeNearTopIfOutsideViewport(range, scrollType);\n }\n revealRangeAtTop(range, scrollType = 0 /* editorCommon.ScrollType.Smooth */) {\n this._modifiedEditor.revealRangeAtTop(range, scrollType);\n }\n getSupportedActions() {\n return this._modifiedEditor.getSupportedActions();\n }\n saveViewState() {\n const originalViewState = this._originalEditor.saveViewState();\n const modifiedViewState = this._modifiedEditor.saveViewState();\n return {\n original: originalViewState,\n modified: modifiedViewState\n };\n }\n restoreViewState(s) {\n if (s && s.original && s.modified) {\n const diffEditorState = s;\n this._originalEditor.restoreViewState(diffEditorState.original);\n this._modifiedEditor.restoreViewState(diffEditorState.modified);\n }\n }\n layout(dimension) {\n this._elementSizeObserver.observe(dimension);\n }\n focus() {\n this._modifiedEditor.focus();\n }\n hasTextFocus() {\n return this._originalEditor.hasTextFocus() || this._modifiedEditor.hasTextFocus();\n }\n trigger(source, handlerId, payload) {\n this._modifiedEditor.trigger(source, handlerId, payload);\n }\n createDecorationsCollection(decorations) {\n return this._modifiedEditor.createDecorationsCollection(decorations);\n }\n changeDecorations(callback) {\n return this._modifiedEditor.changeDecorations(callback);\n }\n //------------ end IDiffEditor methods\n //------------ begin layouting methods\n _onDidContainerSizeChanged() {\n this._doLayout();\n }\n _getReviewHeight() {\n return this._reviewPane.isVisible() ? this._elementSizeObserver.getHeight() : 0;\n }\n _layoutOverviewRulers() {\n if (!this._options.renderOverviewRuler) {\n return;\n }\n if (!this._originalOverviewRuler || !this._modifiedOverviewRuler) {\n return;\n }\n const height = this._elementSizeObserver.getHeight();\n const reviewHeight = this._getReviewHeight();\n const freeSpace = DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH - 2 * DiffEditorWidget.ONE_OVERVIEW_WIDTH;\n const layoutInfo = this._modifiedEditor.getLayoutInfo();\n if (layoutInfo) {\n this._originalOverviewRuler.setLayout({\n top: 0,\n width: DiffEditorWidget.ONE_OVERVIEW_WIDTH,\n right: freeSpace + DiffEditorWidget.ONE_OVERVIEW_WIDTH,\n height: (height - reviewHeight)\n });\n this._modifiedOverviewRuler.setLayout({\n top: 0,\n right: 0,\n width: DiffEditorWidget.ONE_OVERVIEW_WIDTH,\n height: (height - reviewHeight)\n });\n }\n }\n //------------ end layouting methods\n _onViewZonesChanged() {\n if (this._currentlyChangingViewZones) {\n return;\n }\n this._updateDecorationsRunner.schedule();\n }\n _beginUpdateDecorationsSoon() {\n // Clear previous timeout if necessary\n if (this._beginUpdateDecorationsTimeout !== -1) {\n window.clearTimeout(this._beginUpdateDecorationsTimeout);\n this._beginUpdateDecorationsTimeout = -1;\n }\n this._beginUpdateDecorationsTimeout = window.setTimeout(() => this._beginUpdateDecorations(), DiffEditorWidget.UPDATE_DIFF_DECORATIONS_DELAY);\n }\n static _equals(a, b) {\n if (!a && !b) {\n return true;\n }\n if (!a || !b) {\n return false;\n }\n return (a.toString() === b.toString());\n }\n _beginUpdateDecorations() {\n this._beginUpdateDecorationsTimeout = -1;\n const currentOriginalModel = this._originalEditor.getModel();\n const currentModifiedModel = this._modifiedEditor.getModel();\n if (!currentOriginalModel || !currentModifiedModel) {\n return;\n }\n // Prevent old diff requests to come if a new request has been initiated\n // The best method would be to call cancel on the Promise, but this is not\n // yet supported, so using tokens for now.\n this._diffComputationToken++;\n const currentToken = this._diffComputationToken;\n const diffLimit = this._options.maxFileSize * 1024 * 1024; // MB\n const canSyncModelForDiff = (model) => {\n const bufferTextLength = model.getValueLength();\n return (diffLimit === 0 || bufferTextLength <= diffLimit);\n };\n if (!canSyncModelForDiff(currentOriginalModel) || !canSyncModelForDiff(currentModifiedModel)) {\n if (!DiffEditorWidget._equals(currentOriginalModel.uri, this._lastOriginalWarning)\n || !DiffEditorWidget._equals(currentModifiedModel.uri, this._lastModifiedWarning)) {\n this._lastOriginalWarning = currentOriginalModel.uri;\n this._lastModifiedWarning = currentModifiedModel.uri;\n this._notificationService.warn(nls.localize(\"diff.tooLarge\", \"Cannot compare files because one file is too large.\"));\n }\n return;\n }\n this._setState(1 /* editorBrowser.DiffEditorState.ComputingDiff */);\n this._editorWorkerService.computeDiff(currentOriginalModel.uri, currentModifiedModel.uri, this._options.ignoreTrimWhitespace, this._options.maxComputationTime).then((result) => {\n if (currentToken === this._diffComputationToken\n && currentOriginalModel === this._originalEditor.getModel()\n && currentModifiedModel === this._modifiedEditor.getModel()) {\n this._setState(2 /* editorBrowser.DiffEditorState.DiffComputed */);\n this._diffComputationResult = result;\n this._updateDecorationsRunner.schedule();\n this._onDidUpdateDiff.fire();\n }\n }, (error) => {\n if (currentToken === this._diffComputationToken\n && currentOriginalModel === this._originalEditor.getModel()\n && currentModifiedModel === this._modifiedEditor.getModel()) {\n this._setState(2 /* editorBrowser.DiffEditorState.DiffComputed */);\n this._diffComputationResult = null;\n this._updateDecorationsRunner.schedule();\n }\n });\n }\n _cleanViewZonesAndDecorations() {\n this._originalEditorState.clean(this._originalEditor);\n this._modifiedEditorState.clean(this._modifiedEditor);\n }\n _updateDecorations() {\n if (!this._originalEditor.getModel() || !this._modifiedEditor.getModel()) {\n return;\n }\n const lineChanges = (this._diffComputationResult ? this._diffComputationResult.changes : []);\n const foreignOriginal = this._originalEditorState.getForeignViewZones(this._originalEditor.getWhitespaces());\n const foreignModified = this._modifiedEditorState.getForeignViewZones(this._modifiedEditor.getWhitespaces());\n const diffDecorations = this._strategy.getEditorsDiffDecorations(lineChanges, this._options.ignoreTrimWhitespace, this._options.renderIndicators, this._options.renderMarginRevertIcon, foreignOriginal, foreignModified);\n try {\n this._currentlyChangingViewZones = true;\n this._originalEditorState.apply(this._originalEditor, this._originalOverviewRuler, diffDecorations.original, false);\n this._modifiedEditorState.apply(this._modifiedEditor, this._modifiedOverviewRuler, diffDecorations.modified, true);\n }\n finally {\n this._currentlyChangingViewZones = false;\n }\n }\n _adjustOptionsForSubEditor(options) {\n const clonedOptions = Object.assign({}, options);\n clonedOptions.inDiffEditor = true;\n clonedOptions.automaticLayout = false;\n // Clone scrollbar options before changing them\n clonedOptions.scrollbar = Object.assign({}, (clonedOptions.scrollbar || {}));\n clonedOptions.scrollbar.vertical = 'visible';\n clonedOptions.folding = false;\n clonedOptions.codeLens = this._options.diffCodeLens;\n clonedOptions.fixedOverflowWidgets = true;\n // clonedOptions.lineDecorationsWidth = '2ch';\n // Clone minimap options before changing them\n clonedOptions.minimap = Object.assign({}, (clonedOptions.minimap || {}));\n clonedOptions.minimap.enabled = false;\n return clonedOptions;\n }\n _adjustOptionsForLeftHandSide(options) {\n const result = this._adjustOptionsForSubEditor(options);\n if (!this._options.renderSideBySide) {\n // never wrap hidden editor\n result.wordWrapOverride1 = 'off';\n result.wordWrapOverride2 = 'off';\n }\n else {\n result.wordWrapOverride1 = this._options.diffWordWrap;\n }\n if (options.originalAriaLabel) {\n result.ariaLabel = options.originalAriaLabel;\n }\n result.readOnly = !this._options.originalEditable;\n result.dropIntoEditor = { enabled: !result.readOnly };\n result.extraEditorClassName = 'original-in-monaco-diff-editor';\n return Object.assign(Object.assign({}, result), { dimension: {\n height: 0,\n width: 0\n } });\n }\n _adjustOptionsForRightHandSide(options) {\n const result = this._adjustOptionsForSubEditor(options);\n if (options.modifiedAriaLabel) {\n result.ariaLabel = options.modifiedAriaLabel;\n }\n result.wordWrapOverride1 = this._options.diffWordWrap;\n result.revealHorizontalRightPadding = EditorOptions.revealHorizontalRightPadding.defaultValue + DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH;\n result.scrollbar.verticalHasArrows = false;\n result.extraEditorClassName = 'modified-in-monaco-diff-editor';\n return Object.assign(Object.assign({}, result), { dimension: {\n height: 0,\n width: 0\n } });\n }\n doLayout() {\n this._elementSizeObserver.observe();\n this._doLayout();\n }\n _doLayout() {\n const width = this._elementSizeObserver.getWidth();\n const height = this._elementSizeObserver.getHeight();\n const reviewHeight = this._getReviewHeight();\n const splitPoint = this._strategy.layout();\n this._originalDomNode.style.width = splitPoint + 'px';\n this._originalDomNode.style.left = '0px';\n this._modifiedDomNode.style.width = (width - splitPoint) + 'px';\n this._modifiedDomNode.style.left = splitPoint + 'px';\n this._overviewDomElement.style.top = '0px';\n this._overviewDomElement.style.height = (height - reviewHeight) + 'px';\n this._overviewDomElement.style.width = DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH + 'px';\n this._overviewDomElement.style.left = (width - DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH) + 'px';\n this._overviewViewportDomElement.setWidth(DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH);\n this._overviewViewportDomElement.setHeight(30);\n this._originalEditor.layout({ width: splitPoint, height: (height - reviewHeight) });\n this._modifiedEditor.layout({ width: width - splitPoint - (this._options.renderOverviewRuler ? DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH : 0), height: (height - reviewHeight) });\n if (this._originalOverviewRuler || this._modifiedOverviewRuler) {\n this._layoutOverviewRulers();\n }\n this._reviewPane.layout(height - reviewHeight, width, reviewHeight);\n this._layoutOverviewViewport();\n }\n _layoutOverviewViewport() {\n const layout = this._computeOverviewViewport();\n if (!layout) {\n this._overviewViewportDomElement.setTop(0);\n this._overviewViewportDomElement.setHeight(0);\n }\n else {\n this._overviewViewportDomElement.setTop(layout.top);\n this._overviewViewportDomElement.setHeight(layout.height);\n }\n }\n _computeOverviewViewport() {\n const layoutInfo = this._modifiedEditor.getLayoutInfo();\n if (!layoutInfo) {\n return null;\n }\n const scrollTop = this._modifiedEditor.getScrollTop();\n const scrollHeight = this._modifiedEditor.getScrollHeight();\n const computedAvailableSize = Math.max(0, layoutInfo.height);\n const computedRepresentableSize = Math.max(0, computedAvailableSize - 2 * 0);\n const computedRatio = scrollHeight > 0 ? (computedRepresentableSize / scrollHeight) : 0;\n const computedSliderSize = Math.max(0, Math.floor(layoutInfo.height * computedRatio));\n const computedSliderPosition = Math.floor(scrollTop * computedRatio);\n return {\n height: computedSliderSize,\n top: computedSliderPosition\n };\n }\n _createDataSource() {\n return {\n getWidth: () => {\n return this._elementSizeObserver.getWidth();\n },\n getHeight: () => {\n return (this._elementSizeObserver.getHeight() - this._getReviewHeight());\n },\n getOptions: () => {\n return {\n renderOverviewRuler: this._options.renderOverviewRuler\n };\n },\n getContainerDomNode: () => {\n return this._containerDomElement;\n },\n relayoutEditors: () => {\n this._doLayout();\n },\n getOriginalEditor: () => {\n return this._originalEditor;\n },\n getModifiedEditor: () => {\n return this._modifiedEditor;\n }\n };\n }\n _setStrategy(newStrategy) {\n if (this._strategy) {\n this._strategy.dispose();\n }\n this._strategy = newStrategy;\n newStrategy.applyColors(this._themeService.getColorTheme());\n if (this._diffComputationResult) {\n this._updateDecorations();\n }\n // Just do a layout, the strategy might need it\n this._doLayout();\n }\n _getLineChangeAtOrBeforeLineNumber(lineNumber, startLineNumberExtractor) {\n const lineChanges = (this._diffComputationResult ? this._diffComputationResult.changes : []);\n if (lineChanges.length === 0 || lineNumber < startLineNumberExtractor(lineChanges[0])) {\n // There are no changes or `lineNumber` is before the first change\n return null;\n }\n let min = 0;\n let max = lineChanges.length - 1;\n while (min < max) {\n const mid = Math.floor((min + max) / 2);\n const midStart = startLineNumberExtractor(lineChanges[mid]);\n const midEnd = (mid + 1 <= max ? startLineNumberExtractor(lineChanges[mid + 1]) : 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */);\n if (lineNumber < midStart) {\n max = mid - 1;\n }\n else if (lineNumber >= midEnd) {\n min = mid + 1;\n }\n else {\n // HIT!\n min = mid;\n max = mid;\n }\n }\n return lineChanges[min];\n }\n _getEquivalentLineForOriginalLineNumber(lineNumber) {\n const lineChange = this._getLineChangeAtOrBeforeLineNumber(lineNumber, (lineChange) => lineChange.originalStartLineNumber);\n if (!lineChange) {\n return lineNumber;\n }\n const originalEquivalentLineNumber = lineChange.originalStartLineNumber + (lineChange.originalEndLineNumber > 0 ? -1 : 0);\n const modifiedEquivalentLineNumber = lineChange.modifiedStartLineNumber + (lineChange.modifiedEndLineNumber > 0 ? -1 : 0);\n const lineChangeOriginalLength = (lineChange.originalEndLineNumber > 0 ? (lineChange.originalEndLineNumber - lineChange.originalStartLineNumber + 1) : 0);\n const lineChangeModifiedLength = (lineChange.modifiedEndLineNumber > 0 ? (lineChange.modifiedEndLineNumber - lineChange.modifiedStartLineNumber + 1) : 0);\n const delta = lineNumber - originalEquivalentLineNumber;\n if (delta <= lineChangeOriginalLength) {\n return modifiedEquivalentLineNumber + Math.min(delta, lineChangeModifiedLength);\n }\n return modifiedEquivalentLineNumber + lineChangeModifiedLength - lineChangeOriginalLength + delta;\n }\n _getEquivalentLineForModifiedLineNumber(lineNumber) {\n const lineChange = this._getLineChangeAtOrBeforeLineNumber(lineNumber, (lineChange) => lineChange.modifiedStartLineNumber);\n if (!lineChange) {\n return lineNumber;\n }\n const originalEquivalentLineNumber = lineChange.originalStartLineNumber + (lineChange.originalEndLineNumber > 0 ? -1 : 0);\n const modifiedEquivalentLineNumber = lineChange.modifiedStartLineNumber + (lineChange.modifiedEndLineNumber > 0 ? -1 : 0);\n const lineChangeOriginalLength = (lineChange.originalEndLineNumber > 0 ? (lineChange.originalEndLineNumber - lineChange.originalStartLineNumber + 1) : 0);\n const lineChangeModifiedLength = (lineChange.modifiedEndLineNumber > 0 ? (lineChange.modifiedEndLineNumber - lineChange.modifiedStartLineNumber + 1) : 0);\n const delta = lineNumber - modifiedEquivalentLineNumber;\n if (delta <= lineChangeModifiedLength) {\n return originalEquivalentLineNumber + Math.min(delta, lineChangeOriginalLength);\n }\n return originalEquivalentLineNumber + lineChangeOriginalLength - lineChangeModifiedLength + delta;\n }\n getDiffLineInformationForOriginal(lineNumber) {\n if (!this._diffComputationResult) {\n // Cannot answer that which I don't know\n return null;\n }\n return {\n equivalentLineNumber: this._getEquivalentLineForOriginalLineNumber(lineNumber)\n };\n }\n getDiffLineInformationForModified(lineNumber) {\n if (!this._diffComputationResult) {\n // Cannot answer that which I don't know\n return null;\n }\n return {\n equivalentLineNumber: this._getEquivalentLineForModifiedLineNumber(lineNumber)\n };\n }\n};\nDiffEditorWidget.ONE_OVERVIEW_WIDTH = 15;\nDiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH = 30;\nDiffEditorWidget.UPDATE_DIFF_DECORATIONS_DELAY = 200; // ms\nDiffEditorWidget = __decorate([\n __param(3, IClipboardService),\n __param(4, IEditorWorkerService),\n __param(5, IContextKeyService),\n __param(6, IInstantiationService),\n __param(7, ICodeEditorService),\n __param(8, IThemeService),\n __param(9, INotificationService),\n __param(10, IContextMenuService),\n __param(11, IEditorProgressService)\n], DiffEditorWidget);\nexport { DiffEditorWidget };\nclass DiffEditorWidgetStyle extends Disposable {\n constructor(dataSource) {\n super();\n this._dataSource = dataSource;\n this._insertColor = null;\n this._removeColor = null;\n }\n applyColors(theme) {\n const newInsertColor = theme.getColor(diffOverviewRulerInserted) || (theme.getColor(diffInserted) || defaultInsertColor).transparent(2);\n const newRemoveColor = theme.getColor(diffOverviewRulerRemoved) || (theme.getColor(diffRemoved) || defaultRemoveColor).transparent(2);\n const hasChanges = !newInsertColor.equals(this._insertColor) || !newRemoveColor.equals(this._removeColor);\n this._insertColor = newInsertColor;\n this._removeColor = newRemoveColor;\n return hasChanges;\n }\n getEditorsDiffDecorations(lineChanges, ignoreTrimWhitespace, renderIndicators, renderMarginRevertIcon, originalWhitespaces, modifiedWhitespaces) {\n // Get view zones\n modifiedWhitespaces = modifiedWhitespaces.sort((a, b) => {\n return a.afterLineNumber - b.afterLineNumber;\n });\n originalWhitespaces = originalWhitespaces.sort((a, b) => {\n return a.afterLineNumber - b.afterLineNumber;\n });\n const zones = this._getViewZones(lineChanges, originalWhitespaces, modifiedWhitespaces, renderIndicators);\n // Get decorations & overview ruler zones\n const originalDecorations = this._getOriginalEditorDecorations(zones, lineChanges, ignoreTrimWhitespace, renderIndicators);\n const modifiedDecorations = this._getModifiedEditorDecorations(zones, lineChanges, ignoreTrimWhitespace, renderIndicators, renderMarginRevertIcon);\n return {\n original: {\n decorations: originalDecorations.decorations,\n overviewZones: originalDecorations.overviewZones,\n zones: zones.original\n },\n modified: {\n decorations: modifiedDecorations.decorations,\n overviewZones: modifiedDecorations.overviewZones,\n zones: zones.modified\n }\n };\n }\n}\nclass ForeignViewZonesIterator {\n constructor(source) {\n this._source = source;\n this._index = -1;\n this.current = null;\n this.advance();\n }\n advance() {\n this._index++;\n if (this._index < this._source.length) {\n this.current = this._source[this._index];\n }\n else {\n this.current = null;\n }\n }\n}\nclass ViewZonesComputer {\n constructor(_lineChanges, _originalForeignVZ, _modifiedForeignVZ, _originalEditor, _modifiedEditor) {\n this._lineChanges = _lineChanges;\n this._originalForeignVZ = _originalForeignVZ;\n this._modifiedForeignVZ = _modifiedForeignVZ;\n this._originalEditor = _originalEditor;\n this._modifiedEditor = _modifiedEditor;\n }\n static _getViewLineCount(editor, startLineNumber, endLineNumber) {\n const model = editor.getModel();\n const viewModel = editor._getViewModel();\n if (model && viewModel) {\n const viewRange = getViewRange(model, viewModel, startLineNumber, endLineNumber);\n return (viewRange.endLineNumber - viewRange.startLineNumber + 1);\n }\n return (endLineNumber - startLineNumber + 1);\n }\n getViewZones() {\n const originalLineHeight = this._originalEditor.getOption(61 /* EditorOption.lineHeight */);\n const modifiedLineHeight = this._modifiedEditor.getOption(61 /* EditorOption.lineHeight */);\n const originalHasWrapping = (this._originalEditor.getOption(134 /* EditorOption.wrappingInfo */).wrappingColumn !== -1);\n const modifiedHasWrapping = (this._modifiedEditor.getOption(134 /* EditorOption.wrappingInfo */).wrappingColumn !== -1);\n const hasWrapping = (originalHasWrapping || modifiedHasWrapping);\n const originalModel = this._originalEditor.getModel();\n const originalCoordinatesConverter = this._originalEditor._getViewModel().coordinatesConverter;\n const modifiedCoordinatesConverter = this._modifiedEditor._getViewModel().coordinatesConverter;\n const result = {\n original: [],\n modified: []\n };\n let lineChangeModifiedLength = 0;\n let lineChangeOriginalLength = 0;\n let originalEquivalentLineNumber = 0;\n let modifiedEquivalentLineNumber = 0;\n let originalEndEquivalentLineNumber = 0;\n let modifiedEndEquivalentLineNumber = 0;\n const sortMyViewZones = (a, b) => {\n return a.afterLineNumber - b.afterLineNumber;\n };\n const addAndCombineIfPossible = (destination, item) => {\n if (item.domNode === null && destination.length > 0) {\n const lastItem = destination[destination.length - 1];\n if (lastItem.afterLineNumber === item.afterLineNumber && lastItem.domNode === null) {\n lastItem.heightInLines += item.heightInLines;\n return;\n }\n }\n destination.push(item);\n };\n const modifiedForeignVZ = new ForeignViewZonesIterator(this._modifiedForeignVZ);\n const originalForeignVZ = new ForeignViewZonesIterator(this._originalForeignVZ);\n let lastOriginalLineNumber = 1;\n let lastModifiedLineNumber = 1;\n // In order to include foreign view zones after the last line change, the for loop will iterate once more after the end of the `lineChanges` array\n for (let i = 0, length = this._lineChanges.length; i <= length; i++) {\n const lineChange = (i < length ? this._lineChanges[i] : null);\n if (lineChange !== null) {\n originalEquivalentLineNumber = lineChange.originalStartLineNumber + (lineChange.originalEndLineNumber > 0 ? -1 : 0);\n modifiedEquivalentLineNumber = lineChange.modifiedStartLineNumber + (lineChange.modifiedEndLineNumber > 0 ? -1 : 0);\n lineChangeOriginalLength = (lineChange.originalEndLineNumber > 0 ? ViewZonesComputer._getViewLineCount(this._originalEditor, lineChange.originalStartLineNumber, lineChange.originalEndLineNumber) : 0);\n lineChangeModifiedLength = (lineChange.modifiedEndLineNumber > 0 ? ViewZonesComputer._getViewLineCount(this._modifiedEditor, lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber) : 0);\n originalEndEquivalentLineNumber = Math.max(lineChange.originalStartLineNumber, lineChange.originalEndLineNumber);\n modifiedEndEquivalentLineNumber = Math.max(lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber);\n }\n else {\n // Increase to very large value to get the producing tests of foreign view zones running\n originalEquivalentLineNumber += 10000000 + lineChangeOriginalLength;\n modifiedEquivalentLineNumber += 10000000 + lineChangeModifiedLength;\n originalEndEquivalentLineNumber = originalEquivalentLineNumber;\n modifiedEndEquivalentLineNumber = modifiedEquivalentLineNumber;\n }\n // Each step produces view zones, and after producing them, we try to cancel them out, to avoid empty-empty view zone cases\n let stepOriginal = [];\n let stepModified = [];\n // ---------------------------- PRODUCE VIEW ZONES\n // [PRODUCE] View zones due to line mapping differences (equal lines but wrapped differently)\n if (hasWrapping) {\n let count;\n if (lineChange) {\n if (lineChange.originalEndLineNumber > 0) {\n count = lineChange.originalStartLineNumber - lastOriginalLineNumber;\n }\n else {\n count = lineChange.modifiedStartLineNumber - lastModifiedLineNumber;\n }\n }\n else {\n // `lastOriginalLineNumber` has not been looked at yet\n count = originalModel.getLineCount() - lastOriginalLineNumber + 1;\n }\n for (let i = 0; i < count; i++) {\n const originalLineNumber = lastOriginalLineNumber + i;\n const modifiedLineNumber = lastModifiedLineNumber + i;\n const originalViewLineCount = originalCoordinatesConverter.getModelLineViewLineCount(originalLineNumber);\n const modifiedViewLineCount = modifiedCoordinatesConverter.getModelLineViewLineCount(modifiedLineNumber);\n if (originalViewLineCount < modifiedViewLineCount) {\n stepOriginal.push({\n afterLineNumber: originalLineNumber,\n heightInLines: modifiedViewLineCount - originalViewLineCount,\n domNode: null,\n marginDomNode: null\n });\n }\n else if (originalViewLineCount > modifiedViewLineCount) {\n stepModified.push({\n afterLineNumber: modifiedLineNumber,\n heightInLines: originalViewLineCount - modifiedViewLineCount,\n domNode: null,\n marginDomNode: null\n });\n }\n }\n if (lineChange) {\n lastOriginalLineNumber = (lineChange.originalEndLineNumber > 0 ? lineChange.originalEndLineNumber : lineChange.originalStartLineNumber) + 1;\n lastModifiedLineNumber = (lineChange.modifiedEndLineNumber > 0 ? lineChange.modifiedEndLineNumber : lineChange.modifiedStartLineNumber) + 1;\n }\n }\n // [PRODUCE] View zone(s) in original-side due to foreign view zone(s) in modified-side\n while (modifiedForeignVZ.current && modifiedForeignVZ.current.afterLineNumber <= modifiedEndEquivalentLineNumber) {\n let viewZoneLineNumber;\n if (modifiedForeignVZ.current.afterLineNumber <= modifiedEquivalentLineNumber) {\n viewZoneLineNumber = originalEquivalentLineNumber - modifiedEquivalentLineNumber + modifiedForeignVZ.current.afterLineNumber;\n }\n else {\n viewZoneLineNumber = originalEndEquivalentLineNumber;\n }\n let marginDomNode = null;\n if (lineChange && lineChange.modifiedStartLineNumber <= modifiedForeignVZ.current.afterLineNumber && modifiedForeignVZ.current.afterLineNumber <= lineChange.modifiedEndLineNumber) {\n marginDomNode = this._createOriginalMarginDomNodeForModifiedForeignViewZoneInAddedRegion();\n }\n stepOriginal.push({\n afterLineNumber: viewZoneLineNumber,\n heightInLines: modifiedForeignVZ.current.height / modifiedLineHeight,\n domNode: null,\n marginDomNode: marginDomNode\n });\n modifiedForeignVZ.advance();\n }\n // [PRODUCE] View zone(s) in modified-side due to foreign view zone(s) in original-side\n while (originalForeignVZ.current && originalForeignVZ.current.afterLineNumber <= originalEndEquivalentLineNumber) {\n let viewZoneLineNumber;\n if (originalForeignVZ.current.afterLineNumber <= originalEquivalentLineNumber) {\n viewZoneLineNumber = modifiedEquivalentLineNumber - originalEquivalentLineNumber + originalForeignVZ.current.afterLineNumber;\n }\n else {\n viewZoneLineNumber = modifiedEndEquivalentLineNumber;\n }\n stepModified.push({\n afterLineNumber: viewZoneLineNumber,\n heightInLines: originalForeignVZ.current.height / originalLineHeight,\n domNode: null\n });\n originalForeignVZ.advance();\n }\n if (lineChange !== null && isChangeOrInsert(lineChange)) {\n const r = this._produceOriginalFromDiff(lineChange, lineChangeOriginalLength, lineChangeModifiedLength);\n if (r) {\n stepOriginal.push(r);\n }\n }\n if (lineChange !== null && isChangeOrDelete(lineChange)) {\n const r = this._produceModifiedFromDiff(lineChange, lineChangeOriginalLength, lineChangeModifiedLength);\n if (r) {\n stepModified.push(r);\n }\n }\n // ---------------------------- END PRODUCE VIEW ZONES\n // ---------------------------- EMIT MINIMAL VIEW ZONES\n // [CANCEL & EMIT] Try to cancel view zones out\n let stepOriginalIndex = 0;\n let stepModifiedIndex = 0;\n stepOriginal = stepOriginal.sort(sortMyViewZones);\n stepModified = stepModified.sort(sortMyViewZones);\n while (stepOriginalIndex < stepOriginal.length && stepModifiedIndex < stepModified.length) {\n const original = stepOriginal[stepOriginalIndex];\n const modified = stepModified[stepModifiedIndex];\n const originalDelta = original.afterLineNumber - originalEquivalentLineNumber;\n const modifiedDelta = modified.afterLineNumber - modifiedEquivalentLineNumber;\n if (originalDelta < modifiedDelta) {\n addAndCombineIfPossible(result.original, original);\n stepOriginalIndex++;\n }\n else if (modifiedDelta < originalDelta) {\n addAndCombineIfPossible(result.modified, modified);\n stepModifiedIndex++;\n }\n else if (original.shouldNotShrink) {\n addAndCombineIfPossible(result.original, original);\n stepOriginalIndex++;\n }\n else if (modified.shouldNotShrink) {\n addAndCombineIfPossible(result.modified, modified);\n stepModifiedIndex++;\n }\n else {\n if (original.heightInLines >= modified.heightInLines) {\n // modified view zone gets removed\n original.heightInLines -= modified.heightInLines;\n stepModifiedIndex++;\n }\n else {\n // original view zone gets removed\n modified.heightInLines -= original.heightInLines;\n stepOriginalIndex++;\n }\n }\n }\n // [EMIT] Remaining original view zones\n while (stepOriginalIndex < stepOriginal.length) {\n addAndCombineIfPossible(result.original, stepOriginal[stepOriginalIndex]);\n stepOriginalIndex++;\n }\n // [EMIT] Remaining modified view zones\n while (stepModifiedIndex < stepModified.length) {\n addAndCombineIfPossible(result.modified, stepModified[stepModifiedIndex]);\n stepModifiedIndex++;\n }\n // ---------------------------- END EMIT MINIMAL VIEW ZONES\n }\n return {\n original: ViewZonesComputer._ensureDomNodes(result.original),\n modified: ViewZonesComputer._ensureDomNodes(result.modified),\n };\n }\n static _ensureDomNodes(zones) {\n return zones.map((z) => {\n if (!z.domNode) {\n z.domNode = createFakeLinesDiv();\n }\n return z;\n });\n }\n}\nfunction createDecoration(startLineNumber, startColumn, endLineNumber, endColumn, options) {\n return {\n range: new Range(startLineNumber, startColumn, endLineNumber, endColumn),\n options: options\n };\n}\nconst DECORATIONS = {\n arrowRevertChange: ModelDecorationOptions.register({\n description: 'diff-editor-arrow-revert-change',\n glyphMarginClassName: 'arrow-revert-change ' + ThemeIcon.asClassName(Codicon.arrowRight),\n }),\n charDelete: ModelDecorationOptions.register({\n description: 'diff-editor-char-delete',\n className: 'char-delete'\n }),\n charDeleteWholeLine: ModelDecorationOptions.register({\n description: 'diff-editor-char-delete-whole-line',\n className: 'char-delete',\n isWholeLine: true\n }),\n charInsert: ModelDecorationOptions.register({\n description: 'diff-editor-char-insert',\n className: 'char-insert'\n }),\n charInsertWholeLine: ModelDecorationOptions.register({\n description: 'diff-editor-char-insert-whole-line',\n className: 'char-insert',\n isWholeLine: true\n }),\n lineInsert: ModelDecorationOptions.register({\n description: 'diff-editor-line-insert',\n className: 'line-insert',\n marginClassName: 'gutter-insert',\n isWholeLine: true\n }),\n lineInsertWithSign: ModelDecorationOptions.register({\n description: 'diff-editor-line-insert-with-sign',\n className: 'line-insert',\n linesDecorationsClassName: 'insert-sign ' + ThemeIcon.asClassName(diffInsertIcon),\n marginClassName: 'gutter-insert',\n isWholeLine: true\n }),\n lineDelete: ModelDecorationOptions.register({\n description: 'diff-editor-line-delete',\n className: 'line-delete',\n marginClassName: 'gutter-delete',\n isWholeLine: true\n }),\n lineDeleteWithSign: ModelDecorationOptions.register({\n description: 'diff-editor-line-delete-with-sign',\n className: 'line-delete',\n linesDecorationsClassName: 'delete-sign ' + ThemeIcon.asClassName(diffRemoveIcon),\n marginClassName: 'gutter-delete',\n isWholeLine: true\n }),\n lineDeleteMargin: ModelDecorationOptions.register({\n description: 'diff-editor-line-delete-margin',\n marginClassName: 'gutter-delete',\n })\n};\nclass DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle {\n constructor(dataSource, enableSplitViewResizing) {\n super(dataSource);\n this._disableSash = (enableSplitViewResizing === false);\n this._sashRatio = null;\n this._sashPosition = null;\n this._startSashPosition = null;\n this._sash = this._register(new Sash(this._dataSource.getContainerDomNode(), this, { orientation: 0 /* Orientation.VERTICAL */ }));\n if (this._disableSash) {\n this._sash.state = 0 /* SashState.Disabled */;\n }\n this._sash.onDidStart(() => this._onSashDragStart());\n this._sash.onDidChange((e) => this._onSashDrag(e));\n this._sash.onDidEnd(() => this._onSashDragEnd());\n this._sash.onDidReset(() => this._onSashReset());\n }\n setEnableSplitViewResizing(enableSplitViewResizing) {\n const newDisableSash = (enableSplitViewResizing === false);\n if (this._disableSash !== newDisableSash) {\n this._disableSash = newDisableSash;\n this._sash.state = this._disableSash ? 0 /* SashState.Disabled */ : 3 /* SashState.Enabled */;\n }\n }\n layout(sashRatio = this._sashRatio) {\n const w = this._dataSource.getWidth();\n const contentWidth = w - (this._dataSource.getOptions().renderOverviewRuler ? DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH : 0);\n let sashPosition = Math.floor((sashRatio || 0.5) * contentWidth);\n const midPoint = Math.floor(0.5 * contentWidth);\n sashPosition = this._disableSash ? midPoint : sashPosition || midPoint;\n if (contentWidth > DiffEditorWidgetSideBySide.MINIMUM_EDITOR_WIDTH * 2) {\n if (sashPosition < DiffEditorWidgetSideBySide.MINIMUM_EDITOR_WIDTH) {\n sashPosition = DiffEditorWidgetSideBySide.MINIMUM_EDITOR_WIDTH;\n }\n if (sashPosition > contentWidth - DiffEditorWidgetSideBySide.MINIMUM_EDITOR_WIDTH) {\n sashPosition = contentWidth - DiffEditorWidgetSideBySide.MINIMUM_EDITOR_WIDTH;\n }\n }\n else {\n sashPosition = midPoint;\n }\n if (this._sashPosition !== sashPosition) {\n this._sashPosition = sashPosition;\n }\n this._sash.layout();\n return this._sashPosition;\n }\n _onSashDragStart() {\n this._startSashPosition = this._sashPosition;\n }\n _onSashDrag(e) {\n const w = this._dataSource.getWidth();\n const contentWidth = w - (this._dataSource.getOptions().renderOverviewRuler ? DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH : 0);\n const sashPosition = this.layout((this._startSashPosition + (e.currentX - e.startX)) / contentWidth);\n this._sashRatio = sashPosition / contentWidth;\n this._dataSource.relayoutEditors();\n }\n _onSashDragEnd() {\n this._sash.layout();\n }\n _onSashReset() {\n this._sashRatio = 0.5;\n this._dataSource.relayoutEditors();\n this._sash.layout();\n }\n getVerticalSashTop(sash) {\n return 0;\n }\n getVerticalSashLeft(sash) {\n return this._sashPosition;\n }\n getVerticalSashHeight(sash) {\n return this._dataSource.getHeight();\n }\n _getViewZones(lineChanges, originalForeignVZ, modifiedForeignVZ) {\n const originalEditor = this._dataSource.getOriginalEditor();\n const modifiedEditor = this._dataSource.getModifiedEditor();\n const c = new SideBySideViewZonesComputer(lineChanges, originalForeignVZ, modifiedForeignVZ, originalEditor, modifiedEditor);\n return c.getViewZones();\n }\n _getOriginalEditorDecorations(zones, lineChanges, ignoreTrimWhitespace, renderIndicators) {\n const originalEditor = this._dataSource.getOriginalEditor();\n const overviewZoneColor = String(this._removeColor);\n const result = {\n decorations: [],\n overviewZones: []\n };\n const originalModel = originalEditor.getModel();\n const originalViewModel = originalEditor._getViewModel();\n for (const lineChange of lineChanges) {\n if (isChangeOrDelete(lineChange)) {\n result.decorations.push({\n range: new Range(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */),\n options: (renderIndicators ? DECORATIONS.lineDeleteWithSign : DECORATIONS.lineDelete)\n });\n if (!isChangeOrInsert(lineChange) || !lineChange.charChanges) {\n result.decorations.push(createDecoration(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, DECORATIONS.charDeleteWholeLine));\n }\n const viewRange = getViewRange(originalModel, originalViewModel, lineChange.originalStartLineNumber, lineChange.originalEndLineNumber);\n result.overviewZones.push(new OverviewRulerZone(viewRange.startLineNumber, viewRange.endLineNumber, /*use endLineNumber*/ 0, overviewZoneColor));\n if (lineChange.charChanges) {\n for (const charChange of lineChange.charChanges) {\n if (isCharChangeOrDelete(charChange)) {\n if (ignoreTrimWhitespace) {\n for (let lineNumber = charChange.originalStartLineNumber; lineNumber <= charChange.originalEndLineNumber; lineNumber++) {\n let startColumn;\n let endColumn;\n if (lineNumber === charChange.originalStartLineNumber) {\n startColumn = charChange.originalStartColumn;\n }\n else {\n startColumn = originalModel.getLineFirstNonWhitespaceColumn(lineNumber);\n }\n if (lineNumber === charChange.originalEndLineNumber) {\n endColumn = charChange.originalEndColumn;\n }\n else {\n endColumn = originalModel.getLineLastNonWhitespaceColumn(lineNumber);\n }\n result.decorations.push(createDecoration(lineNumber, startColumn, lineNumber, endColumn, DECORATIONS.charDelete));\n }\n }\n else {\n result.decorations.push(createDecoration(charChange.originalStartLineNumber, charChange.originalStartColumn, charChange.originalEndLineNumber, charChange.originalEndColumn, DECORATIONS.charDelete));\n }\n }\n }\n }\n }\n }\n return result;\n }\n _getModifiedEditorDecorations(zones, lineChanges, ignoreTrimWhitespace, renderIndicators, renderMarginRevertIcon) {\n const modifiedEditor = this._dataSource.getModifiedEditor();\n const overviewZoneColor = String(this._insertColor);\n const result = {\n decorations: [],\n overviewZones: []\n };\n const modifiedModel = modifiedEditor.getModel();\n const modifiedViewModel = modifiedEditor._getViewModel();\n for (const lineChange of lineChanges) {\n // Arrows for reverting changes.\n if (renderMarginRevertIcon) {\n if (lineChange.modifiedEndLineNumber > 0) {\n result.decorations.push({\n range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedStartLineNumber, 1),\n options: DECORATIONS.arrowRevertChange\n });\n }\n else {\n const viewZone = zones.modified.find(z => z.afterLineNumber === lineChange.modifiedStartLineNumber);\n if (viewZone) {\n viewZone.marginDomNode = createViewZoneMarginArrow();\n }\n }\n }\n if (isChangeOrInsert(lineChange)) {\n result.decorations.push({\n range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */),\n options: (renderIndicators ? DECORATIONS.lineInsertWithSign : DECORATIONS.lineInsert)\n });\n if (!isChangeOrDelete(lineChange) || !lineChange.charChanges) {\n result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, DECORATIONS.charInsertWholeLine));\n }\n const viewRange = getViewRange(modifiedModel, modifiedViewModel, lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber);\n result.overviewZones.push(new OverviewRulerZone(viewRange.startLineNumber, viewRange.endLineNumber, /*use endLineNumber*/ 0, overviewZoneColor));\n if (lineChange.charChanges) {\n for (const charChange of lineChange.charChanges) {\n if (isCharChangeOrInsert(charChange)) {\n if (ignoreTrimWhitespace) {\n for (let lineNumber = charChange.modifiedStartLineNumber; lineNumber <= charChange.modifiedEndLineNumber; lineNumber++) {\n let startColumn;\n let endColumn;\n if (lineNumber === charChange.modifiedStartLineNumber) {\n startColumn = charChange.modifiedStartColumn;\n }\n else {\n startColumn = modifiedModel.getLineFirstNonWhitespaceColumn(lineNumber);\n }\n if (lineNumber === charChange.modifiedEndLineNumber) {\n endColumn = charChange.modifiedEndColumn;\n }\n else {\n endColumn = modifiedModel.getLineLastNonWhitespaceColumn(lineNumber);\n }\n result.decorations.push(createDecoration(lineNumber, startColumn, lineNumber, endColumn, DECORATIONS.charInsert));\n }\n }\n else {\n result.decorations.push(createDecoration(charChange.modifiedStartLineNumber, charChange.modifiedStartColumn, charChange.modifiedEndLineNumber, charChange.modifiedEndColumn, DECORATIONS.charInsert));\n }\n }\n }\n }\n }\n }\n return result;\n }\n}\nDiffEditorWidgetSideBySide.MINIMUM_EDITOR_WIDTH = 100;\nclass SideBySideViewZonesComputer extends ViewZonesComputer {\n constructor(lineChanges, originalForeignVZ, modifiedForeignVZ, originalEditor, modifiedEditor) {\n super(lineChanges, originalForeignVZ, modifiedForeignVZ, originalEditor, modifiedEditor);\n }\n _createOriginalMarginDomNodeForModifiedForeignViewZoneInAddedRegion() {\n return null;\n }\n _produceOriginalFromDiff(lineChange, lineChangeOriginalLength, lineChangeModifiedLength) {\n if (lineChangeModifiedLength > lineChangeOriginalLength) {\n return {\n afterLineNumber: Math.max(lineChange.originalStartLineNumber, lineChange.originalEndLineNumber),\n heightInLines: (lineChangeModifiedLength - lineChangeOriginalLength),\n domNode: null\n };\n }\n return null;\n }\n _produceModifiedFromDiff(lineChange, lineChangeOriginalLength, lineChangeModifiedLength) {\n if (lineChangeOriginalLength > lineChangeModifiedLength) {\n return {\n afterLineNumber: Math.max(lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber),\n heightInLines: (lineChangeOriginalLength - lineChangeModifiedLength),\n domNode: null\n };\n }\n return null;\n }\n}\nclass DiffEditorWidgetInline extends DiffEditorWidgetStyle {\n constructor(dataSource, enableSplitViewResizing) {\n super(dataSource);\n this._decorationsLeft = dataSource.getOriginalEditor().getLayoutInfo().decorationsLeft;\n this._register(dataSource.getOriginalEditor().onDidLayoutChange((layoutInfo) => {\n if (this._decorationsLeft !== layoutInfo.decorationsLeft) {\n this._decorationsLeft = layoutInfo.decorationsLeft;\n dataSource.relayoutEditors();\n }\n }));\n }\n setEnableSplitViewResizing(enableSplitViewResizing) {\n // Nothing to do..\n }\n _getViewZones(lineChanges, originalForeignVZ, modifiedForeignVZ, renderIndicators) {\n const originalEditor = this._dataSource.getOriginalEditor();\n const modifiedEditor = this._dataSource.getModifiedEditor();\n const computer = new InlineViewZonesComputer(lineChanges, originalForeignVZ, modifiedForeignVZ, originalEditor, modifiedEditor, renderIndicators);\n return computer.getViewZones();\n }\n _getOriginalEditorDecorations(zones, lineChanges, ignoreTrimWhitespace, renderIndicators) {\n const overviewZoneColor = String(this._removeColor);\n const result = {\n decorations: [],\n overviewZones: []\n };\n const originalEditor = this._dataSource.getOriginalEditor();\n const originalModel = originalEditor.getModel();\n const originalViewModel = originalEditor._getViewModel();\n let zoneIndex = 0;\n for (const lineChange of lineChanges) {\n // Add overview zones in the overview ruler\n if (isChangeOrDelete(lineChange)) {\n result.decorations.push({\n range: new Range(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */),\n options: DECORATIONS.lineDeleteMargin\n });\n while (zoneIndex < zones.modified.length) {\n const zone = zones.modified[zoneIndex];\n if (zone.diff && zone.diff.originalStartLineNumber >= lineChange.originalStartLineNumber) {\n break;\n }\n zoneIndex++;\n }\n let zoneHeightInLines = 0;\n if (zoneIndex < zones.modified.length) {\n const zone = zones.modified[zoneIndex];\n if (zone.diff\n && zone.diff.originalStartLineNumber === lineChange.originalStartLineNumber\n && zone.diff.originalEndLineNumber === lineChange.originalEndLineNumber\n && zone.diff.modifiedStartLineNumber === lineChange.modifiedStartLineNumber\n && zone.diff.modifiedEndLineNumber === lineChange.modifiedEndLineNumber) {\n zoneHeightInLines = zone.heightInLines;\n }\n }\n const viewRange = getViewRange(originalModel, originalViewModel, lineChange.originalStartLineNumber, lineChange.originalEndLineNumber);\n result.overviewZones.push(new OverviewRulerZone(viewRange.startLineNumber, viewRange.endLineNumber, zoneHeightInLines, overviewZoneColor));\n }\n }\n return result;\n }\n _getModifiedEditorDecorations(zones, lineChanges, ignoreTrimWhitespace, renderIndicators, renderMarginRevertIcon) {\n const modifiedEditor = this._dataSource.getModifiedEditor();\n const overviewZoneColor = String(this._insertColor);\n const result = {\n decorations: [],\n overviewZones: []\n };\n const modifiedModel = modifiedEditor.getModel();\n const modifiedViewModel = modifiedEditor._getViewModel();\n for (const lineChange of lineChanges) {\n // Add decorations & overview zones\n if (isChangeOrInsert(lineChange)) {\n result.decorations.push({\n range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */),\n options: (renderIndicators ? DECORATIONS.lineInsertWithSign : DECORATIONS.lineInsert)\n });\n const viewRange = getViewRange(modifiedModel, modifiedViewModel, lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber);\n result.overviewZones.push(new OverviewRulerZone(viewRange.startLineNumber, viewRange.endLineNumber, /*use endLineNumber*/ 0, overviewZoneColor));\n if (lineChange.charChanges) {\n for (const charChange of lineChange.charChanges) {\n if (isCharChangeOrInsert(charChange)) {\n if (ignoreTrimWhitespace) {\n for (let lineNumber = charChange.modifiedStartLineNumber; lineNumber <= charChange.modifiedEndLineNumber; lineNumber++) {\n let startColumn;\n let endColumn;\n if (lineNumber === charChange.modifiedStartLineNumber) {\n startColumn = charChange.modifiedStartColumn;\n }\n else {\n startColumn = modifiedModel.getLineFirstNonWhitespaceColumn(lineNumber);\n }\n if (lineNumber === charChange.modifiedEndLineNumber) {\n endColumn = charChange.modifiedEndColumn;\n }\n else {\n endColumn = modifiedModel.getLineLastNonWhitespaceColumn(lineNumber);\n }\n result.decorations.push(createDecoration(lineNumber, startColumn, lineNumber, endColumn, DECORATIONS.charInsert));\n }\n }\n else {\n result.decorations.push(createDecoration(charChange.modifiedStartLineNumber, charChange.modifiedStartColumn, charChange.modifiedEndLineNumber, charChange.modifiedEndColumn, DECORATIONS.charInsert));\n }\n }\n }\n }\n else {\n result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, DECORATIONS.charInsertWholeLine));\n }\n }\n }\n return result;\n }\n layout() {\n // An editor should not be smaller than 5px\n return Math.max(5, this._decorationsLeft);\n }\n}\nclass InlineViewZonesComputer extends ViewZonesComputer {\n constructor(lineChanges, originalForeignVZ, modifiedForeignVZ, originalEditor, modifiedEditor, renderIndicators) {\n super(lineChanges, originalForeignVZ, modifiedForeignVZ, originalEditor, modifiedEditor);\n this._originalModel = originalEditor.getModel();\n this._renderIndicators = renderIndicators;\n this._pendingLineChange = [];\n this._pendingViewZones = [];\n this._lineBreaksComputer = this._modifiedEditor._getViewModel().createLineBreaksComputer();\n }\n getViewZones() {\n const result = super.getViewZones();\n this._finalize(result);\n return result;\n }\n _createOriginalMarginDomNodeForModifiedForeignViewZoneInAddedRegion() {\n const result = document.createElement('div');\n result.className = 'inline-added-margin-view-zone';\n return result;\n }\n _produceOriginalFromDiff(lineChange, lineChangeOriginalLength, lineChangeModifiedLength) {\n const marginDomNode = document.createElement('div');\n marginDomNode.className = 'inline-added-margin-view-zone';\n return {\n afterLineNumber: Math.max(lineChange.originalStartLineNumber, lineChange.originalEndLineNumber),\n heightInLines: lineChangeModifiedLength,\n domNode: document.createElement('div'),\n marginDomNode: marginDomNode\n };\n }\n _produceModifiedFromDiff(lineChange, lineChangeOriginalLength, lineChangeModifiedLength) {\n const domNode = document.createElement('div');\n domNode.className = `view-lines line-delete ${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`;\n const marginDomNode = document.createElement('div');\n marginDomNode.className = 'inline-deleted-margin-view-zone';\n const viewZone = {\n shouldNotShrink: true,\n afterLineNumber: (lineChange.modifiedEndLineNumber === 0 ? lineChange.modifiedStartLineNumber : lineChange.modifiedStartLineNumber - 1),\n heightInLines: lineChangeOriginalLength,\n minWidthInPx: 0,\n domNode: domNode,\n marginDomNode: marginDomNode,\n diff: {\n originalStartLineNumber: lineChange.originalStartLineNumber,\n originalEndLineNumber: lineChange.originalEndLineNumber,\n modifiedStartLineNumber: lineChange.modifiedStartLineNumber,\n modifiedEndLineNumber: lineChange.modifiedEndLineNumber,\n originalModel: this._originalModel,\n viewLineCounts: null,\n }\n };\n for (let lineNumber = lineChange.originalStartLineNumber; lineNumber <= lineChange.originalEndLineNumber; lineNumber++) {\n this._lineBreaksComputer.addRequest(this._originalModel.getLineContent(lineNumber), null, null);\n }\n this._pendingLineChange.push(lineChange);\n this._pendingViewZones.push(viewZone);\n return viewZone;\n }\n _finalize(result) {\n const modifiedEditorOptions = this._modifiedEditor.getOptions();\n const tabSize = this._modifiedEditor.getModel().getOptions().tabSize;\n const fontInfo = modifiedEditorOptions.get(46 /* EditorOption.fontInfo */);\n const disableMonospaceOptimizations = modifiedEditorOptions.get(29 /* EditorOption.disableMonospaceOptimizations */);\n const typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;\n const scrollBeyondLastColumn = modifiedEditorOptions.get(95 /* EditorOption.scrollBeyondLastColumn */);\n const mightContainNonBasicASCII = this._originalModel.mightContainNonBasicASCII();\n const mightContainRTL = this._originalModel.mightContainRTL();\n const lineHeight = modifiedEditorOptions.get(61 /* EditorOption.lineHeight */);\n const layoutInfo = modifiedEditorOptions.get(133 /* EditorOption.layoutInfo */);\n const lineDecorationsWidth = layoutInfo.decorationsWidth;\n const stopRenderingLineAfter = modifiedEditorOptions.get(107 /* EditorOption.stopRenderingLineAfter */);\n const renderWhitespace = modifiedEditorOptions.get(90 /* EditorOption.renderWhitespace */);\n const renderControlCharacters = modifiedEditorOptions.get(85 /* EditorOption.renderControlCharacters */);\n const fontLigatures = modifiedEditorOptions.get(47 /* EditorOption.fontLigatures */);\n const lineBreaks = this._lineBreaksComputer.finalize();\n let lineBreakIndex = 0;\n for (let i = 0; i < this._pendingLineChange.length; i++) {\n const lineChange = this._pendingLineChange[i];\n const viewZone = this._pendingViewZones[i];\n const domNode = viewZone.domNode;\n applyFontInfo(domNode, fontInfo);\n const marginDomNode = viewZone.marginDomNode;\n applyFontInfo(marginDomNode, fontInfo);\n const decorations = [];\n if (lineChange.charChanges) {\n for (const charChange of lineChange.charChanges) {\n if (isCharChangeOrDelete(charChange)) {\n decorations.push(new InlineDecoration(new Range(charChange.originalStartLineNumber, charChange.originalStartColumn, charChange.originalEndLineNumber, charChange.originalEndColumn), 'char-delete', 0 /* InlineDecorationType.Regular */));\n }\n }\n }\n const hasCharChanges = (decorations.length > 0);\n const sb = createStringBuilder(10000);\n let maxCharsPerLine = 0;\n let renderedLineCount = 0;\n let viewLineCounts = null;\n for (let lineNumber = lineChange.originalStartLineNumber; lineNumber <= lineChange.originalEndLineNumber; lineNumber++) {\n const lineIndex = lineNumber - lineChange.originalStartLineNumber;\n const lineTokens = this._originalModel.tokenization.getLineTokens(lineNumber);\n const lineContent = lineTokens.getLineContent();\n const lineBreakData = lineBreaks[lineBreakIndex++];\n const actualDecorations = LineDecoration.filter(decorations, lineNumber, 1, lineContent.length + 1);\n if (lineBreakData) {\n let lastBreakOffset = 0;\n for (const breakOffset of lineBreakData.breakOffsets) {\n const viewLineTokens = lineTokens.sliceAndInflate(lastBreakOffset, breakOffset, 0);\n const viewLineContent = lineContent.substring(lastBreakOffset, breakOffset);\n maxCharsPerLine = Math.max(maxCharsPerLine, this._renderOriginalLine(renderedLineCount++, viewLineContent, viewLineTokens, LineDecoration.extractWrapped(actualDecorations, lastBreakOffset, breakOffset), hasCharChanges, mightContainNonBasicASCII, mightContainRTL, fontInfo, disableMonospaceOptimizations, lineHeight, lineDecorationsWidth, stopRenderingLineAfter, renderWhitespace, renderControlCharacters, fontLigatures, tabSize, sb, marginDomNode));\n lastBreakOffset = breakOffset;\n }\n if (!viewLineCounts) {\n viewLineCounts = [];\n }\n // make sure all lines before this one have an entry in `viewLineCounts`\n while (viewLineCounts.length < lineIndex) {\n viewLineCounts[viewLineCounts.length] = 1;\n }\n viewLineCounts[lineIndex] = lineBreakData.breakOffsets.length;\n viewZone.heightInLines += (lineBreakData.breakOffsets.length - 1);\n const marginDomNode2 = document.createElement('div');\n marginDomNode2.className = 'gutter-delete';\n result.original.push({\n afterLineNumber: lineNumber,\n afterColumn: 0,\n heightInLines: lineBreakData.breakOffsets.length - 1,\n domNode: createFakeLinesDiv(),\n marginDomNode: marginDomNode2\n });\n }\n else {\n maxCharsPerLine = Math.max(maxCharsPerLine, this._renderOriginalLine(renderedLineCount++, lineContent, lineTokens, actualDecorations, hasCharChanges, mightContainNonBasicASCII, mightContainRTL, fontInfo, disableMonospaceOptimizations, lineHeight, lineDecorationsWidth, stopRenderingLineAfter, renderWhitespace, renderControlCharacters, fontLigatures, tabSize, sb, marginDomNode));\n }\n }\n maxCharsPerLine += scrollBeyondLastColumn;\n const html = sb.build();\n const trustedhtml = ttPolicy ? ttPolicy.createHTML(html) : html;\n domNode.innerHTML = trustedhtml;\n viewZone.minWidthInPx = (maxCharsPerLine * typicalHalfwidthCharacterWidth);\n if (viewLineCounts) {\n // make sure all lines have an entry in `viewLineCounts`\n const cnt = lineChange.originalEndLineNumber - lineChange.originalStartLineNumber;\n while (viewLineCounts.length <= cnt) {\n viewLineCounts[viewLineCounts.length] = 1;\n }\n }\n viewZone.diff.viewLineCounts = viewLineCounts;\n }\n result.original.sort((a, b) => {\n return a.afterLineNumber - b.afterLineNumber;\n });\n }\n _renderOriginalLine(renderedLineCount, lineContent, lineTokens, decorations, hasCharChanges, mightContainNonBasicASCII, mightContainRTL, fontInfo, disableMonospaceOptimizations, lineHeight, lineDecorationsWidth, stopRenderingLineAfter, renderWhitespace, renderControlCharacters, fontLigatures, tabSize, sb, marginDomNode) {\n sb.appendASCIIString('
');\n const isBasicASCII = ViewLineRenderingData.isBasicASCII(lineContent, mightContainNonBasicASCII);\n const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, mightContainRTL);\n const output = renderViewLine(new RenderLineInput((fontInfo.isMonospace && !disableMonospaceOptimizations), fontInfo.canUseHalfwidthRightwardsArrow, lineContent, false, isBasicASCII, containsRTL, 0, lineTokens, decorations, tabSize, 0, fontInfo.spaceWidth, fontInfo.middotWidth, fontInfo.wsmiddotWidth, stopRenderingLineAfter, renderWhitespace, renderControlCharacters, fontLigatures !== EditorFontLigatures.OFF, null // Send no selections, original line cannot be selected\n ), sb);\n sb.appendASCIIString('
');\n if (this._renderIndicators) {\n const marginElement = document.createElement('div');\n marginElement.className = `delete-sign ${ThemeIcon.asClassName(diffRemoveIcon)}`;\n marginElement.setAttribute('style', `position:absolute;top:${renderedLineCount * lineHeight}px;width:${lineDecorationsWidth}px;height:${lineHeight}px;right:0;`);\n marginDomNode.appendChild(marginElement);\n }\n return output.characterMapping.getHorizontalOffset(output.characterMapping.length);\n }\n}\nfunction validateDiffWordWrap(value, defaultValue) {\n return validateStringSetOption(value, defaultValue, ['off', 'on', 'inherit']);\n}\nfunction isChangeOrInsert(lineChange) {\n return lineChange.modifiedEndLineNumber > 0;\n}\nfunction isChangeOrDelete(lineChange) {\n return lineChange.originalEndLineNumber > 0;\n}\nfunction isCharChangeOrInsert(charChange) {\n if (charChange.modifiedStartLineNumber === charChange.modifiedEndLineNumber) {\n return charChange.modifiedEndColumn - charChange.modifiedStartColumn > 0;\n }\n return charChange.modifiedEndLineNumber - charChange.modifiedStartLineNumber > 0;\n}\nfunction isCharChangeOrDelete(charChange) {\n if (charChange.originalStartLineNumber === charChange.originalEndLineNumber) {\n return charChange.originalEndColumn - charChange.originalStartColumn > 0;\n }\n return charChange.originalEndLineNumber - charChange.originalStartLineNumber > 0;\n}\nfunction createFakeLinesDiv() {\n const r = document.createElement('div');\n r.className = 'diagonal-fill';\n return r;\n}\nfunction createViewZoneMarginArrow() {\n const arrow = document.createElement('div');\n arrow.className = 'arrow-revert-change ' + ThemeIcon.asClassName(Codicon.arrowRight);\n return dom.$('div', {}, arrow);\n}\nfunction getViewRange(model, viewModel, startLineNumber, endLineNumber) {\n const lineCount = model.getLineCount();\n startLineNumber = Math.min(lineCount, Math.max(1, startLineNumber));\n endLineNumber = Math.min(lineCount, Math.max(1, endLineNumber));\n return viewModel.coordinatesConverter.convertModelRangeToViewRange(new Range(startLineNumber, model.getLineMinColumn(startLineNumber), endLineNumber, model.getLineMaxColumn(endLineNumber)));\n}\nfunction validateDiffEditorOptions(options, defaults) {\n return {\n enableSplitViewResizing: validateBooleanOption(options.enableSplitViewResizing, defaults.enableSplitViewResizing),\n renderSideBySide: validateBooleanOption(options.renderSideBySide, defaults.renderSideBySide),\n renderMarginRevertIcon: validateBooleanOption(options.renderMarginRevertIcon, defaults.renderMarginRevertIcon),\n maxComputationTime: clampedInt(options.maxComputationTime, defaults.maxComputationTime, 0, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */),\n maxFileSize: clampedInt(options.maxFileSize, defaults.maxFileSize, 0, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */),\n ignoreTrimWhitespace: validateBooleanOption(options.ignoreTrimWhitespace, defaults.ignoreTrimWhitespace),\n renderIndicators: validateBooleanOption(options.renderIndicators, defaults.renderIndicators),\n originalEditable: validateBooleanOption(options.originalEditable, defaults.originalEditable),\n diffCodeLens: validateBooleanOption(options.diffCodeLens, defaults.diffCodeLens),\n renderOverviewRuler: validateBooleanOption(options.renderOverviewRuler, defaults.renderOverviewRuler),\n diffWordWrap: validateDiffWordWrap(options.diffWordWrap, defaults.diffWordWrap),\n };\n}\nfunction changedDiffEditorOptions(a, b) {\n return {\n enableSplitViewResizing: (a.enableSplitViewResizing !== b.enableSplitViewResizing),\n renderSideBySide: (a.renderSideBySide !== b.renderSideBySide),\n renderMarginRevertIcon: (a.renderMarginRevertIcon !== b.renderMarginRevertIcon),\n maxComputationTime: (a.maxComputationTime !== b.maxComputationTime),\n maxFileSize: (a.maxFileSize !== b.maxFileSize),\n ignoreTrimWhitespace: (a.ignoreTrimWhitespace !== b.ignoreTrimWhitespace),\n renderIndicators: (a.renderIndicators !== b.renderIndicators),\n originalEditable: (a.originalEditable !== b.originalEditable),\n diffCodeLens: (a.diffCodeLens !== b.diffCodeLens),\n renderOverviewRuler: (a.renderOverviewRuler !== b.renderOverviewRuler),\n diffWordWrap: (a.diffWordWrap !== b.diffWordWrap),\n };\n}\nregisterThemingParticipant((theme, collector) => {\n const added = theme.getColor(diffInserted);\n if (added) {\n collector.addRule(`.monaco-editor .char-insert, .monaco-diff-editor .char-insert { background-color: ${added}; }`);\n }\n const lineAdded = theme.getColor(diffInsertedLine) || added;\n if (lineAdded) {\n collector.addRule(`.monaco-editor .line-insert, .monaco-diff-editor .line-insert { background-color: ${lineAdded}; }`);\n }\n const gutterAdded = theme.getColor(diffInsertedLineGutter) || lineAdded;\n if (gutterAdded) {\n collector.addRule(`.monaco-editor .inline-added-margin-view-zone { background-color: ${gutterAdded}; }`);\n collector.addRule(`.monaco-editor .gutter-insert, .monaco-diff-editor .gutter-insert { background-color: ${gutterAdded}; }`);\n }\n const removed = theme.getColor(diffRemoved);\n if (removed) {\n collector.addRule(`.monaco-editor .char-delete, .monaco-diff-editor .char-delete { background-color: ${removed}; }`);\n }\n const lineRemoved = theme.getColor(diffRemovedLine) || removed;\n if (lineRemoved) {\n collector.addRule(`.monaco-editor .line-delete, .monaco-diff-editor .line-delete { background-color: ${lineRemoved}; }`);\n }\n const gutterRemoved = theme.getColor(diffRemovedLineGutter) || lineRemoved;\n if (gutterRemoved) {\n collector.addRule(`.monaco-editor .inline-deleted-margin-view-zone { background-color: ${gutterRemoved}; }`);\n collector.addRule(`.monaco-editor .gutter-delete, .monaco-diff-editor .gutter-delete { background-color: ${gutterRemoved}; }`);\n }\n const addedOutline = theme.getColor(diffInsertedOutline);\n if (addedOutline) {\n collector.addRule(`.monaco-editor .line-insert, .monaco-editor .char-insert { border: 1px ${isHighContrast(theme.type) ? 'dashed' : 'solid'} ${addedOutline}; }`);\n }\n const removedOutline = theme.getColor(diffRemovedOutline);\n if (removedOutline) {\n collector.addRule(`.monaco-editor .line-delete, .monaco-editor .char-delete { border: 1px ${isHighContrast(theme.type) ? 'dashed' : 'solid'} ${removedOutline}; }`);\n }\n const shadow = theme.getColor(scrollbarShadow);\n if (shadow) {\n collector.addRule(`.monaco-diff-editor.side-by-side .editor.modified { box-shadow: -6px 0 5px -5px ${shadow}; }`);\n }\n const border = theme.getColor(diffBorder);\n if (border) {\n collector.addRule(`.monaco-diff-editor.side-by-side .editor.modified { border-left: 1px solid ${border}; }`);\n }\n const scrollbarSliderBackgroundColor = theme.getColor(scrollbarSliderBackground);\n if (scrollbarSliderBackgroundColor) {\n collector.addRule(`\n\t\t\t.monaco-diff-editor .diffViewport {\n\t\t\t\tbackground: ${scrollbarSliderBackgroundColor};\n\t\t\t}\n\t\t`);\n }\n const scrollbarSliderHoverBackgroundColor = theme.getColor(scrollbarSliderHoverBackground);\n if (scrollbarSliderHoverBackgroundColor) {\n collector.addRule(`\n\t\t\t.monaco-diff-editor .diffViewport:hover {\n\t\t\t\tbackground: ${scrollbarSliderHoverBackgroundColor};\n\t\t\t}\n\t\t`);\n }\n const scrollbarSliderActiveBackgroundColor = theme.getColor(scrollbarSliderActiveBackground);\n if (scrollbarSliderActiveBackgroundColor) {\n collector.addRule(`\n\t\t\t.monaco-diff-editor .diffViewport:active {\n\t\t\t\tbackground: ${scrollbarSliderActiveBackgroundColor};\n\t\t\t}\n\t\t`);\n }\n const diffDiagonalFillColor = theme.getColor(diffDiagonalFill);\n collector.addRule(`\n\t.monaco-editor .diagonal-fill {\n\t\tbackground-image: linear-gradient(\n\t\t\t-45deg,\n\t\t\t${diffDiagonalFillColor} 12.5%,\n\t\t\t#0000 12.5%, #0000 50%,\n\t\t\t${diffDiagonalFillColor} 50%, ${diffDiagonalFillColor} 62.5%,\n\t\t\t#0000 62.5%, #0000 100%\n\t\t);\n\t\tbackground-size: 8px 8px;\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 *--------------------------------------------------------------------------------------------*/\nimport * as assert from '../../../base/common/assert.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport * as objects from '../../../base/common/objects.js';\nimport { Range } from '../../common/core/range.js';\nconst defaultOptions = {\n followsCaret: true,\n ignoreCharChanges: true,\n alwaysRevealFirst: true\n};\n/**\n * Create a new diff navigator for the provided diff editor.\n */\nexport class DiffNavigator extends Disposable {\n constructor(editor, options = {}) {\n super();\n this._onDidUpdate = this._register(new Emitter());\n this._editor = editor;\n this._options = objects.mixin(options, defaultOptions, false);\n this.disposed = false;\n this.nextIdx = -1;\n this.ranges = [];\n this.ignoreSelectionChange = false;\n this.revealFirst = Boolean(this._options.alwaysRevealFirst);\n // hook up to diff editor for diff, disposal, and caret move\n this._register(this._editor.onDidDispose(() => this.dispose()));\n this._register(this._editor.onDidUpdateDiff(() => this._onDiffUpdated()));\n if (this._options.followsCaret) {\n this._register(this._editor.getModifiedEditor().onDidChangeCursorPosition((e) => {\n if (this.ignoreSelectionChange) {\n return;\n }\n this.nextIdx = -1;\n }));\n }\n if (this._options.alwaysRevealFirst) {\n this._register(this._editor.getModifiedEditor().onDidChangeModel((e) => {\n this.revealFirst = true;\n }));\n }\n // init things\n this._init();\n }\n _init() {\n const changes = this._editor.getLineChanges();\n if (!changes) {\n return;\n }\n }\n _onDiffUpdated() {\n this._init();\n this._compute(this._editor.getLineChanges());\n if (this.revealFirst) {\n // Only reveal first on first non-null changes\n if (this._editor.getLineChanges() !== null) {\n this.revealFirst = false;\n this.nextIdx = -1;\n this.next(1 /* ScrollType.Immediate */);\n }\n }\n }\n _compute(lineChanges) {\n // new ranges\n this.ranges = [];\n if (lineChanges) {\n // create ranges from changes\n lineChanges.forEach((lineChange) => {\n if (!this._options.ignoreCharChanges && lineChange.charChanges) {\n lineChange.charChanges.forEach((charChange) => {\n this.ranges.push({\n rhs: true,\n range: new Range(charChange.modifiedStartLineNumber, charChange.modifiedStartColumn, charChange.modifiedEndLineNumber, charChange.modifiedEndColumn)\n });\n });\n }\n else {\n if (lineChange.modifiedEndLineNumber === 0) {\n // a deletion\n this.ranges.push({\n rhs: true,\n range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedStartLineNumber + 1, 1)\n });\n }\n else {\n // an insertion or modification\n this.ranges.push({\n rhs: true,\n range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber + 1, 1)\n });\n }\n }\n });\n }\n // sort\n this.ranges.sort((left, right) => Range.compareRangesUsingStarts(left.range, right.range));\n this._onDidUpdate.fire(this);\n }\n _initIdx(fwd) {\n let found = false;\n const position = this._editor.getPosition();\n if (!position) {\n this.nextIdx = 0;\n return;\n }\n for (let i = 0, len = this.ranges.length; i < len && !found; i++) {\n const range = this.ranges[i].range;\n if (position.isBeforeOrEqual(range.getStartPosition())) {\n this.nextIdx = i + (fwd ? 0 : -1);\n found = true;\n }\n }\n if (!found) {\n // after the last change\n this.nextIdx = fwd ? 0 : this.ranges.length - 1;\n }\n if (this.nextIdx < 0) {\n this.nextIdx = this.ranges.length - 1;\n }\n }\n _move(fwd, scrollType) {\n assert.ok(!this.disposed, 'Illegal State - diff navigator has been disposed');\n if (!this.canNavigate()) {\n return;\n }\n if (this.nextIdx === -1) {\n this._initIdx(fwd);\n }\n else if (fwd) {\n this.nextIdx += 1;\n if (this.nextIdx >= this.ranges.length) {\n this.nextIdx = 0;\n }\n }\n else {\n this.nextIdx -= 1;\n if (this.nextIdx < 0) {\n this.nextIdx = this.ranges.length - 1;\n }\n }\n const info = this.ranges[this.nextIdx];\n this.ignoreSelectionChange = true;\n try {\n const pos = info.range.getStartPosition();\n this._editor.setPosition(pos);\n this._editor.revealRangeInCenter(info.range, scrollType);\n }\n finally {\n this.ignoreSelectionChange = false;\n }\n }\n canNavigate() {\n return this.ranges && this.ranges.length > 0;\n }\n next(scrollType = 0 /* ScrollType.Smooth */) {\n this._move(true, scrollType);\n }\n previous(scrollType = 0 /* ScrollType.Smooth */) {\n this._move(false, scrollType);\n }\n dispose() {\n super.dispose();\n this.ranges = [];\n this.disposed = true;\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 *--------------------------------------------------------------------------------------------*/\nimport { Selection } from '../core/selection.js';\nexport class ReplaceCommand {\n constructor(range, text, insertsAutoWhitespace = false) {\n this._range = range;\n this._text = text;\n this.insertsAutoWhitespace = insertsAutoWhitespace;\n }\n getEditOperations(model, builder) {\n builder.addTrackedEditOperation(this._range, this._text);\n }\n computeCursorState(model, helper) {\n const inverseEditOperations = helper.getInverseEditOperations();\n const srcRange = inverseEditOperations[0].range;\n return Selection.fromPositions(srcRange.getEndPosition());\n }\n}\nexport class ReplaceCommandThatSelectsText {\n constructor(range, text) {\n this._range = range;\n this._text = text;\n }\n getEditOperations(model, builder) {\n builder.addTrackedEditOperation(this._range, this._text);\n }\n computeCursorState(model, helper) {\n const inverseEditOperations = helper.getInverseEditOperations();\n const srcRange = inverseEditOperations[0].range;\n return Selection.fromRange(srcRange, 0 /* SelectionDirection.LTR */);\n }\n}\nexport class ReplaceCommandWithoutChangingPosition {\n constructor(range, text, insertsAutoWhitespace = false) {\n this._range = range;\n this._text = text;\n this.insertsAutoWhitespace = insertsAutoWhitespace;\n }\n getEditOperations(model, builder) {\n builder.addTrackedEditOperation(this._range, this._text);\n }\n computeCursorState(model, helper) {\n const inverseEditOperations = helper.getInverseEditOperations();\n const srcRange = inverseEditOperations[0].range;\n return Selection.fromPositions(srcRange.getStartPosition());\n }\n}\nexport class ReplaceCommandWithOffsetCursorState {\n constructor(range, text, lineNumberDeltaOffset, columnDeltaOffset, insertsAutoWhitespace = false) {\n this._range = range;\n this._text = text;\n this._columnDeltaOffset = columnDeltaOffset;\n this._lineNumberDeltaOffset = lineNumberDeltaOffset;\n this.insertsAutoWhitespace = insertsAutoWhitespace;\n }\n getEditOperations(model, builder) {\n builder.addTrackedEditOperation(this._range, this._text);\n }\n computeCursorState(model, helper) {\n const inverseEditOperations = helper.getInverseEditOperations();\n const srcRange = inverseEditOperations[0].range;\n return Selection.fromPositions(srcRange.getEndPosition().delta(this._lineNumberDeltaOffset, this._columnDeltaOffset));\n }\n}\nexport class ReplaceCommandThatPreservesSelection {\n constructor(editRange, text, initialSelection, forceMoveMarkers = false) {\n this._range = editRange;\n this._text = text;\n this._initialSelection = initialSelection;\n this._forceMoveMarkers = forceMoveMarkers;\n this._selectionId = null;\n }\n getEditOperations(model, builder) {\n builder.addTrackedEditOperation(this._range, this._text, this._forceMoveMarkers);\n this._selectionId = builder.trackSelection(this._initialSelection);\n }\n computeCursorState(model, helper) {\n return helper.getTrackedSelection(this._selectionId);\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport * as strings from '../../../base/common/strings.js';\nimport { CursorColumns } from '../core/cursorColumns.js';\nimport { Range } from '../core/range.js';\nimport { Selection } from '../core/selection.js';\nimport { getEnterAction } from '../languages/enterAction.js';\nimport { ILanguageConfigurationService } from '../languages/languageConfigurationRegistry.js';\nconst repeatCache = Object.create(null);\nexport function cachedStringRepeat(str, count) {\n if (count <= 0) {\n return '';\n }\n if (!repeatCache[str]) {\n repeatCache[str] = ['', str];\n }\n const cache = repeatCache[str];\n for (let i = cache.length; i <= count; i++) {\n cache[i] = cache[i - 1] + str;\n }\n return cache[count];\n}\nlet ShiftCommand = class ShiftCommand {\n constructor(range, opts, _languageConfigurationService) {\n this._languageConfigurationService = _languageConfigurationService;\n this._opts = opts;\n this._selection = range;\n this._selectionId = null;\n this._useLastEditRangeForCursorEndPosition = false;\n this._selectionStartColumnStaysPut = false;\n }\n static unshiftIndent(line, column, tabSize, indentSize, insertSpaces) {\n // Determine the visible column where the content starts\n const contentStartVisibleColumn = CursorColumns.visibleColumnFromColumn(line, column, tabSize);\n if (insertSpaces) {\n const indent = cachedStringRepeat(' ', indentSize);\n const desiredTabStop = CursorColumns.prevIndentTabStop(contentStartVisibleColumn, indentSize);\n const indentCount = desiredTabStop / indentSize; // will be an integer\n return cachedStringRepeat(indent, indentCount);\n }\n else {\n const indent = '\\t';\n const desiredTabStop = CursorColumns.prevRenderTabStop(contentStartVisibleColumn, tabSize);\n const indentCount = desiredTabStop / tabSize; // will be an integer\n return cachedStringRepeat(indent, indentCount);\n }\n }\n static shiftIndent(line, column, tabSize, indentSize, insertSpaces) {\n // Determine the visible column where the content starts\n const contentStartVisibleColumn = CursorColumns.visibleColumnFromColumn(line, column, tabSize);\n if (insertSpaces) {\n const indent = cachedStringRepeat(' ', indentSize);\n const desiredTabStop = CursorColumns.nextIndentTabStop(contentStartVisibleColumn, indentSize);\n const indentCount = desiredTabStop / indentSize; // will be an integer\n return cachedStringRepeat(indent, indentCount);\n }\n else {\n const indent = '\\t';\n const desiredTabStop = CursorColumns.nextRenderTabStop(contentStartVisibleColumn, tabSize);\n const indentCount = desiredTabStop / tabSize; // will be an integer\n return cachedStringRepeat(indent, indentCount);\n }\n }\n _addEditOperation(builder, range, text) {\n if (this._useLastEditRangeForCursorEndPosition) {\n builder.addTrackedEditOperation(range, text);\n }\n else {\n builder.addEditOperation(range, text);\n }\n }\n getEditOperations(model, builder) {\n const startLine = this._selection.startLineNumber;\n let endLine = this._selection.endLineNumber;\n if (this._selection.endColumn === 1 && startLine !== endLine) {\n endLine = endLine - 1;\n }\n const { tabSize, indentSize, insertSpaces } = this._opts;\n const shouldIndentEmptyLines = (startLine === endLine);\n if (this._opts.useTabStops) {\n // if indenting or outdenting on a whitespace only line\n if (this._selection.isEmpty()) {\n if (/^\\s*$/.test(model.getLineContent(startLine))) {\n this._useLastEditRangeForCursorEndPosition = true;\n }\n }\n // keep track of previous line's \"miss-alignment\"\n let previousLineExtraSpaces = 0, extraSpaces = 0;\n for (let lineNumber = startLine; lineNumber <= endLine; lineNumber++, previousLineExtraSpaces = extraSpaces) {\n extraSpaces = 0;\n const lineText = model.getLineContent(lineNumber);\n let indentationEndIndex = strings.firstNonWhitespaceIndex(lineText);\n if (this._opts.isUnshift && (lineText.length === 0 || indentationEndIndex === 0)) {\n // empty line or line with no leading whitespace => nothing to do\n continue;\n }\n if (!shouldIndentEmptyLines && !this._opts.isUnshift && lineText.length === 0) {\n // do not indent empty lines => nothing to do\n continue;\n }\n if (indentationEndIndex === -1) {\n // the entire line is whitespace\n indentationEndIndex = lineText.length;\n }\n if (lineNumber > 1) {\n const contentStartVisibleColumn = CursorColumns.visibleColumnFromColumn(lineText, indentationEndIndex + 1, tabSize);\n if (contentStartVisibleColumn % indentSize !== 0) {\n // The current line is \"miss-aligned\", so let's see if this is expected...\n // This can only happen when it has trailing commas in the indent\n if (model.tokenization.isCheapToTokenize(lineNumber - 1)) {\n const enterAction = getEnterAction(this._opts.autoIndent, model, new Range(lineNumber - 1, model.getLineMaxColumn(lineNumber - 1), lineNumber - 1, model.getLineMaxColumn(lineNumber - 1)), this._languageConfigurationService);\n if (enterAction) {\n extraSpaces = previousLineExtraSpaces;\n if (enterAction.appendText) {\n for (let j = 0, lenJ = enterAction.appendText.length; j < lenJ && extraSpaces < indentSize; j++) {\n if (enterAction.appendText.charCodeAt(j) === 32 /* CharCode.Space */) {\n extraSpaces++;\n }\n else {\n break;\n }\n }\n }\n if (enterAction.removeText) {\n extraSpaces = Math.max(0, extraSpaces - enterAction.removeText);\n }\n // Act as if `prefixSpaces` is not part of the indentation\n for (let j = 0; j < extraSpaces; j++) {\n if (indentationEndIndex === 0 || lineText.charCodeAt(indentationEndIndex - 1) !== 32 /* CharCode.Space */) {\n break;\n }\n indentationEndIndex--;\n }\n }\n }\n }\n }\n if (this._opts.isUnshift && indentationEndIndex === 0) {\n // line with no leading whitespace => nothing to do\n continue;\n }\n let desiredIndent;\n if (this._opts.isUnshift) {\n desiredIndent = ShiftCommand.unshiftIndent(lineText, indentationEndIndex + 1, tabSize, indentSize, insertSpaces);\n }\n else {\n desiredIndent = ShiftCommand.shiftIndent(lineText, indentationEndIndex + 1, tabSize, indentSize, insertSpaces);\n }\n this._addEditOperation(builder, new Range(lineNumber, 1, lineNumber, indentationEndIndex + 1), desiredIndent);\n if (lineNumber === startLine && !this._selection.isEmpty()) {\n // Force the startColumn to stay put because we're inserting after it\n this._selectionStartColumnStaysPut = (this._selection.startColumn <= indentationEndIndex + 1);\n }\n }\n }\n else {\n // if indenting or outdenting on a whitespace only line\n if (!this._opts.isUnshift && this._selection.isEmpty() && model.getLineLength(startLine) === 0) {\n this._useLastEditRangeForCursorEndPosition = true;\n }\n const oneIndent = (insertSpaces ? cachedStringRepeat(' ', indentSize) : '\\t');\n for (let lineNumber = startLine; lineNumber <= endLine; lineNumber++) {\n const lineText = model.getLineContent(lineNumber);\n let indentationEndIndex = strings.firstNonWhitespaceIndex(lineText);\n if (this._opts.isUnshift && (lineText.length === 0 || indentationEndIndex === 0)) {\n // empty line or line with no leading whitespace => nothing to do\n continue;\n }\n if (!shouldIndentEmptyLines && !this._opts.isUnshift && lineText.length === 0) {\n // do not indent empty lines => nothing to do\n continue;\n }\n if (indentationEndIndex === -1) {\n // the entire line is whitespace\n indentationEndIndex = lineText.length;\n }\n if (this._opts.isUnshift && indentationEndIndex === 0) {\n // line with no leading whitespace => nothing to do\n continue;\n }\n if (this._opts.isUnshift) {\n indentationEndIndex = Math.min(indentationEndIndex, indentSize);\n for (let i = 0; i < indentationEndIndex; i++) {\n const chr = lineText.charCodeAt(i);\n if (chr === 9 /* CharCode.Tab */) {\n indentationEndIndex = i + 1;\n break;\n }\n }\n this._addEditOperation(builder, new Range(lineNumber, 1, lineNumber, indentationEndIndex + 1), '');\n }\n else {\n this._addEditOperation(builder, new Range(lineNumber, 1, lineNumber, 1), oneIndent);\n if (lineNumber === startLine && !this._selection.isEmpty()) {\n // Force the startColumn to stay put because we're inserting after it\n this._selectionStartColumnStaysPut = (this._selection.startColumn === 1);\n }\n }\n }\n }\n this._selectionId = builder.trackSelection(this._selection);\n }\n computeCursorState(model, helper) {\n if (this._useLastEditRangeForCursorEndPosition) {\n const lastOp = helper.getInverseEditOperations()[0];\n return new Selection(lastOp.range.endLineNumber, lastOp.range.endColumn, lastOp.range.endLineNumber, lastOp.range.endColumn);\n }\n const result = helper.getTrackedSelection(this._selectionId);\n if (this._selectionStartColumnStaysPut) {\n // The selection start should not move\n const initialStartColumn = this._selection.startColumn;\n const resultStartColumn = result.startColumn;\n if (resultStartColumn <= initialStartColumn) {\n return result;\n }\n if (result.getDirection() === 0 /* SelectionDirection.LTR */) {\n return new Selection(result.startLineNumber, initialStartColumn, result.endLineNumber, result.endColumn);\n }\n return new Selection(result.endLineNumber, result.endColumn, result.startLineNumber, initialStartColumn);\n }\n return result;\n }\n};\nShiftCommand = __decorate([\n __param(2, ILanguageConfigurationService)\n], ShiftCommand);\nexport { ShiftCommand };\n","/*---------------------------------------------------------------------------------------------\n * 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 { editorOptionsRegistry } from './editorOptions.js';\nimport { EDITOR_MODEL_DEFAULTS } from '../core/textModelDefaults.js';\nimport * as nls from '../../../nls.js';\nimport { Extensions } from '../../../platform/configuration/common/configurationRegistry.js';\nimport { Registry } from '../../../platform/registry/common/platform.js';\nexport const editorConfigurationBaseNode = Object.freeze({\n id: 'editor',\n order: 5,\n type: 'object',\n title: nls.localize('editorConfigurationTitle', \"Editor\"),\n scope: 5 /* ConfigurationScope.LANGUAGE_OVERRIDABLE */,\n});\nconst editorConfiguration = Object.assign(Object.assign({}, editorConfigurationBaseNode), { properties: {\n 'editor.tabSize': {\n type: 'number',\n default: EDITOR_MODEL_DEFAULTS.tabSize,\n minimum: 1,\n markdownDescription: 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 },\n // 'editor.indentSize': {\n // \t'anyOf': [\n // \t\t{\n // \t\t\ttype: 'string',\n // \t\t\tenum: ['tabSize']\n // \t\t},\n // \t\t{\n // \t\t\ttype: 'number',\n // \t\t\tminimum: 1\n // \t\t}\n // \t],\n // \tdefault: 'tabSize',\n // \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 // },\n 'editor.insertSpaces': {\n type: 'boolean',\n default: EDITOR_MODEL_DEFAULTS.insertSpaces,\n markdownDescription: nls.localize('insertSpaces', \"Insert spaces when pressing `Tab`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.\")\n },\n 'editor.detectIndentation': {\n type: 'boolean',\n default: EDITOR_MODEL_DEFAULTS.detectIndentation,\n markdownDescription: 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 },\n 'editor.trimAutoWhitespace': {\n type: 'boolean',\n default: EDITOR_MODEL_DEFAULTS.trimAutoWhitespace,\n description: nls.localize('trimAutoWhitespace', \"Remove trailing auto inserted whitespace.\")\n },\n 'editor.largeFileOptimizations': {\n type: 'boolean',\n default: EDITOR_MODEL_DEFAULTS.largeFileOptimizations,\n description: nls.localize('largeFileOptimizations', \"Special handling for large files to disable certain memory intensive features.\")\n },\n 'editor.wordBasedSuggestions': {\n type: 'boolean',\n default: true,\n description: nls.localize('wordBasedSuggestions', \"Controls whether completions should be computed based on words in the document.\")\n },\n 'editor.wordBasedSuggestionsMode': {\n enum: ['currentDocument', 'matchingDocuments', 'allDocuments'],\n default: 'matchingDocuments',\n enumDescriptions: [\n nls.localize('wordBasedSuggestionsMode.currentDocument', 'Only suggest words from the active document.'),\n nls.localize('wordBasedSuggestionsMode.matchingDocuments', 'Suggest words from all open documents of the same language.'),\n nls.localize('wordBasedSuggestionsMode.allDocuments', 'Suggest words from all open documents.')\n ],\n description: nls.localize('wordBasedSuggestionsMode', \"Controls from which documents word based completions are computed.\")\n },\n 'editor.semanticHighlighting.enabled': {\n enum: [true, false, 'configuredByTheme'],\n enumDescriptions: [\n nls.localize('semanticHighlighting.true', 'Semantic highlighting enabled for all color themes.'),\n nls.localize('semanticHighlighting.false', 'Semantic highlighting disabled for all color themes.'),\n nls.localize('semanticHighlighting.configuredByTheme', 'Semantic highlighting is configured by the current color theme\\'s `semanticHighlighting` setting.')\n ],\n default: 'configuredByTheme',\n description: nls.localize('semanticHighlighting.enabled', \"Controls whether the semanticHighlighting is shown for the languages that support it.\")\n },\n 'editor.stablePeek': {\n type: 'boolean',\n default: false,\n markdownDescription: nls.localize('stablePeek', \"Keep peek editors open even when double clicking their content or when hitting `Escape`.\")\n },\n 'editor.maxTokenizationLineLength': {\n type: 'integer',\n default: 20000,\n description: nls.localize('maxTokenizationLineLength', \"Lines above this length will not be tokenized for performance reasons\")\n },\n 'editor.language.brackets': {\n type: ['array', 'null'],\n default: null,\n description: nls.localize('schema.brackets', 'Defines the bracket symbols that increase or decrease the indentation.'),\n items: {\n type: 'array',\n items: [\n {\n type: 'string',\n description: nls.localize('schema.openBracket', 'The opening bracket character or string sequence.')\n },\n {\n type: 'string',\n description: nls.localize('schema.closeBracket', 'The closing bracket character or string sequence.')\n }\n ]\n }\n },\n 'editor.language.colorizedBracketPairs': {\n type: ['array', 'null'],\n default: null,\n description: nls.localize('schema.colorizedBracketPairs', 'Defines the bracket pairs that are colorized by their nesting level if bracket pair colorization is enabled.'),\n items: {\n type: 'array',\n items: [\n {\n type: 'string',\n description: nls.localize('schema.openBracket', 'The opening bracket character or string sequence.')\n },\n {\n type: 'string',\n description: nls.localize('schema.closeBracket', 'The closing bracket character or string sequence.')\n }\n ]\n }\n },\n 'diffEditor.maxComputationTime': {\n type: 'number',\n default: 5000,\n description: nls.localize('maxComputationTime', \"Timeout in milliseconds after which diff computation is cancelled. Use 0 for no timeout.\")\n },\n 'diffEditor.maxFileSize': {\n type: 'number',\n default: 50,\n description: nls.localize('maxFileSize', \"Maximum file size in MB for which to compute diffs. Use 0 for no limit.\")\n },\n 'diffEditor.renderSideBySide': {\n type: 'boolean',\n default: true,\n description: nls.localize('sideBySide', \"Controls whether the diff editor shows the diff side by side or inline.\")\n },\n 'diffEditor.renderMarginRevertIcon': {\n type: 'boolean',\n default: true,\n description: nls.localize('renderMarginRevertIcon', \"When enabled, the diff editor shows arrows in its glyph margin to revert changes.\")\n },\n 'diffEditor.ignoreTrimWhitespace': {\n type: 'boolean',\n default: true,\n description: nls.localize('ignoreTrimWhitespace', \"When enabled, the diff editor ignores changes in leading or trailing whitespace.\")\n },\n 'diffEditor.renderIndicators': {\n type: 'boolean',\n default: true,\n description: nls.localize('renderIndicators', \"Controls whether the diff editor shows +/- indicators for added/removed changes.\")\n },\n 'diffEditor.codeLens': {\n type: 'boolean',\n default: false,\n description: nls.localize('codeLens', \"Controls whether the editor shows CodeLens.\")\n },\n 'diffEditor.wordWrap': {\n type: 'string',\n enum: ['off', 'on', 'inherit'],\n default: 'inherit',\n markdownEnumDescriptions: [\n nls.localize('wordWrap.off', \"Lines will never wrap.\"),\n nls.localize('wordWrap.on', \"Lines will wrap at the viewport width.\"),\n nls.localize('wordWrap.inherit', \"Lines will wrap according to the `#editor.wordWrap#` setting.\"),\n ]\n }\n } });\nfunction isConfigurationPropertySchema(x) {\n return (typeof x.type !== 'undefined' || typeof x.anyOf !== 'undefined');\n}\n// Add properties from the Editor Option Registry\nfor (const editorOption of editorOptionsRegistry) {\n const schema = editorOption.schema;\n if (typeof schema !== 'undefined') {\n if (isConfigurationPropertySchema(schema)) {\n // This is a single schema contribution\n editorConfiguration.properties[`editor.${editorOption.name}`] = schema;\n }\n else {\n for (const key in schema) {\n if (Object.hasOwnProperty.call(schema, key)) {\n editorConfiguration.properties[key] = schema[key];\n }\n }\n }\n }\n}\nlet cachedEditorConfigurationKeys = null;\nfunction getEditorConfigurationKeys() {\n if (cachedEditorConfigurationKeys === null) {\n cachedEditorConfigurationKeys = Object.create(null);\n Object.keys(editorConfiguration.properties).forEach((prop) => {\n cachedEditorConfigurationKeys[prop] = true;\n });\n }\n return cachedEditorConfigurationKeys;\n}\nexport function isEditorConfigurationKey(key) {\n const editorConfigurationKeys = getEditorConfigurationKeys();\n return (editorConfigurationKeys[`editor.${key}`] || false);\n}\nexport function isDiffEditorConfigurationKey(key) {\n const editorConfigurationKeys = getEditorConfigurationKeys();\n return (editorConfigurationKeys[`diffEditor.${key}`] || false);\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 *--------------------------------------------------------------------------------------------*/\nimport * as nls from '../../../nls.js';\nimport * as platform from '../../../base/common/platform.js';\nimport { USUAL_WORD_SEPARATORS } from '../core/wordHelper.js';\nimport * as arrays from '../../../base/common/arrays.js';\nimport * as objects from '../../../base/common/objects.js';\nimport { EDITOR_MODEL_DEFAULTS } from '../core/textModelDefaults.js';\n/**\n * @internal\n * The width of the minimap gutter, in pixels.\n */\nexport const MINIMAP_GUTTER_WIDTH = 8;\n//#endregion\n/**\n * An event describing that the configuration of the editor has changed.\n */\nexport class ConfigurationChangedEvent {\n /**\n * @internal\n */\n constructor(values) {\n this._values = values;\n }\n hasChanged(id) {\n return this._values[id];\n }\n}\n/**\n * @internal\n */\nexport class ComputeOptionsMemory {\n constructor() {\n this.stableMinimapLayoutInput = null;\n this.stableFitMaxMinimapScale = 0;\n this.stableFitRemainingWidth = 0;\n }\n}\n/**\n * @internal\n */\nclass BaseEditorOption {\n constructor(id, name, defaultValue, schema) {\n this.id = id;\n this.name = name;\n this.defaultValue = defaultValue;\n this.schema = schema;\n }\n applyUpdate(value, update) {\n return applyUpdate(value, update);\n }\n compute(env, options, value) {\n return value;\n }\n}\nexport class ApplyUpdateResult {\n constructor(newValue, didChange) {\n this.newValue = newValue;\n this.didChange = didChange;\n }\n}\nfunction applyUpdate(value, update) {\n if (typeof value !== 'object' || typeof update !== 'object' || !value || !update) {\n return new ApplyUpdateResult(update, value !== update);\n }\n if (Array.isArray(value) || Array.isArray(update)) {\n const arrayEquals = Array.isArray(value) && Array.isArray(update) && arrays.equals(value, update);\n return new ApplyUpdateResult(update, !arrayEquals);\n }\n let didChange = false;\n for (const key in update) {\n if (update.hasOwnProperty(key)) {\n const result = applyUpdate(value[key], update[key]);\n if (result.didChange) {\n value[key] = result.newValue;\n didChange = true;\n }\n }\n }\n return new ApplyUpdateResult(value, didChange);\n}\n/**\n * @internal\n */\nclass ComputedEditorOption {\n constructor(id) {\n this.schema = undefined;\n this.id = id;\n this.name = '_never_';\n this.defaultValue = undefined;\n }\n applyUpdate(value, update) {\n return applyUpdate(value, update);\n }\n validate(input) {\n return this.defaultValue;\n }\n}\nclass SimpleEditorOption {\n constructor(id, name, defaultValue, schema) {\n this.id = id;\n this.name = name;\n this.defaultValue = defaultValue;\n this.schema = schema;\n }\n applyUpdate(value, update) {\n return applyUpdate(value, update);\n }\n validate(input) {\n if (typeof input === 'undefined') {\n return this.defaultValue;\n }\n return input;\n }\n compute(env, options, value) {\n return value;\n }\n}\n/**\n * @internal\n */\nexport function boolean(value, defaultValue) {\n if (typeof value === 'undefined') {\n return defaultValue;\n }\n if (value === 'false') {\n // treat the string 'false' as false\n return false;\n }\n return Boolean(value);\n}\nclass EditorBooleanOption extends SimpleEditorOption {\n constructor(id, name, defaultValue, schema = undefined) {\n if (typeof schema !== 'undefined') {\n schema.type = 'boolean';\n schema.default = defaultValue;\n }\n super(id, name, defaultValue, schema);\n }\n validate(input) {\n return boolean(input, this.defaultValue);\n }\n}\n/**\n * @internal\n */\nexport function clampedInt(value, defaultValue, minimum, maximum) {\n if (typeof value === 'undefined') {\n return defaultValue;\n }\n let r = parseInt(value, 10);\n if (isNaN(r)) {\n return defaultValue;\n }\n r = Math.max(minimum, r);\n r = Math.min(maximum, r);\n return r | 0;\n}\nclass EditorIntOption extends SimpleEditorOption {\n constructor(id, name, defaultValue, minimum, maximum, schema = undefined) {\n if (typeof schema !== 'undefined') {\n schema.type = 'integer';\n schema.default = defaultValue;\n schema.minimum = minimum;\n schema.maximum = maximum;\n }\n super(id, name, defaultValue, schema);\n this.minimum = minimum;\n this.maximum = maximum;\n }\n static clampedInt(value, defaultValue, minimum, maximum) {\n return clampedInt(value, defaultValue, minimum, maximum);\n }\n validate(input) {\n return EditorIntOption.clampedInt(input, this.defaultValue, this.minimum, this.maximum);\n }\n}\nclass EditorFloatOption extends SimpleEditorOption {\n constructor(id, name, defaultValue, validationFn, schema) {\n if (typeof schema !== 'undefined') {\n schema.type = 'number';\n schema.default = defaultValue;\n }\n super(id, name, defaultValue, schema);\n this.validationFn = validationFn;\n }\n static clamp(n, min, max) {\n if (n < min) {\n return min;\n }\n if (n > max) {\n return max;\n }\n return n;\n }\n static float(value, defaultValue) {\n if (typeof value === 'number') {\n return value;\n }\n if (typeof value === 'undefined') {\n return defaultValue;\n }\n const r = parseFloat(value);\n return (isNaN(r) ? defaultValue : r);\n }\n validate(input) {\n return this.validationFn(EditorFloatOption.float(input, this.defaultValue));\n }\n}\nclass EditorStringOption extends SimpleEditorOption {\n static string(value, defaultValue) {\n if (typeof value !== 'string') {\n return defaultValue;\n }\n return value;\n }\n constructor(id, name, defaultValue, schema = undefined) {\n if (typeof schema !== 'undefined') {\n schema.type = 'string';\n schema.default = defaultValue;\n }\n super(id, name, defaultValue, schema);\n }\n validate(input) {\n return EditorStringOption.string(input, this.defaultValue);\n }\n}\n/**\n * @internal\n */\nexport function stringSet(value, defaultValue, allowedValues) {\n if (typeof value !== 'string') {\n return defaultValue;\n }\n if (allowedValues.indexOf(value) === -1) {\n return defaultValue;\n }\n return value;\n}\nclass EditorStringEnumOption extends SimpleEditorOption {\n constructor(id, name, defaultValue, allowedValues, schema = undefined) {\n if (typeof schema !== 'undefined') {\n schema.type = 'string';\n schema.enum = allowedValues;\n schema.default = defaultValue;\n }\n super(id, name, defaultValue, schema);\n this._allowedValues = allowedValues;\n }\n validate(input) {\n return stringSet(input, this.defaultValue, this._allowedValues);\n }\n}\nclass EditorEnumOption extends BaseEditorOption {\n constructor(id, name, defaultValue, defaultStringValue, allowedValues, convert, schema = undefined) {\n if (typeof schema !== 'undefined') {\n schema.type = 'string';\n schema.enum = allowedValues;\n schema.default = defaultStringValue;\n }\n super(id, name, defaultValue, schema);\n this._allowedValues = allowedValues;\n this._convert = convert;\n }\n validate(input) {\n if (typeof input !== 'string') {\n return this.defaultValue;\n }\n if (this._allowedValues.indexOf(input) === -1) {\n return this.defaultValue;\n }\n return this._convert(input);\n }\n}\n//#endregion\n//#region autoIndent\nfunction _autoIndentFromString(autoIndent) {\n switch (autoIndent) {\n case 'none': return 0 /* EditorAutoIndentStrategy.None */;\n case 'keep': return 1 /* EditorAutoIndentStrategy.Keep */;\n case 'brackets': return 2 /* EditorAutoIndentStrategy.Brackets */;\n case 'advanced': return 3 /* EditorAutoIndentStrategy.Advanced */;\n case 'full': return 4 /* EditorAutoIndentStrategy.Full */;\n }\n}\n//#endregion\n//#region accessibilitySupport\nclass EditorAccessibilitySupport extends BaseEditorOption {\n constructor() {\n super(2 /* EditorOption.accessibilitySupport */, 'accessibilitySupport', 0 /* AccessibilitySupport.Unknown */, {\n type: 'string',\n enum: ['auto', 'on', 'off'],\n enumDescriptions: [\n nls.localize('accessibilitySupport.auto', \"The editor will use platform APIs to detect when a Screen Reader is attached.\"),\n nls.localize('accessibilitySupport.on', \"The editor will be permanently optimized for usage with a Screen Reader. Word wrapping will be disabled.\"),\n nls.localize('accessibilitySupport.off', \"The editor will never be optimized for usage with a Screen Reader.\"),\n ],\n default: 'auto',\n description: 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 });\n }\n validate(input) {\n switch (input) {\n case 'auto': return 0 /* AccessibilitySupport.Unknown */;\n case 'off': return 1 /* AccessibilitySupport.Disabled */;\n case 'on': return 2 /* AccessibilitySupport.Enabled */;\n }\n return this.defaultValue;\n }\n compute(env, options, value) {\n if (value === 0 /* AccessibilitySupport.Unknown */) {\n // The editor reads the `accessibilitySupport` from the environment\n return env.accessibilitySupport;\n }\n return value;\n }\n}\nclass EditorComments extends BaseEditorOption {\n constructor() {\n const defaults = {\n insertSpace: true,\n ignoreEmptyLines: true,\n };\n super(19 /* EditorOption.comments */, 'comments', defaults, {\n 'editor.comments.insertSpace': {\n type: 'boolean',\n default: defaults.insertSpace,\n description: nls.localize('comments.insertSpace', \"Controls whether a space character is inserted when commenting.\")\n },\n 'editor.comments.ignoreEmptyLines': {\n type: 'boolean',\n default: defaults.ignoreEmptyLines,\n description: nls.localize('comments.ignoreEmptyLines', 'Controls if empty lines should be ignored with toggle, add or remove actions for line comments.')\n },\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n insertSpace: boolean(input.insertSpace, this.defaultValue.insertSpace),\n ignoreEmptyLines: boolean(input.ignoreEmptyLines, this.defaultValue.ignoreEmptyLines),\n };\n }\n}\nfunction _cursorBlinkingStyleFromString(cursorBlinkingStyle) {\n switch (cursorBlinkingStyle) {\n case 'blink': return 1 /* TextEditorCursorBlinkingStyle.Blink */;\n case 'smooth': return 2 /* TextEditorCursorBlinkingStyle.Smooth */;\n case 'phase': return 3 /* TextEditorCursorBlinkingStyle.Phase */;\n case 'expand': return 4 /* TextEditorCursorBlinkingStyle.Expand */;\n case 'solid': return 5 /* TextEditorCursorBlinkingStyle.Solid */;\n }\n}\n//#endregion\n//#region cursorStyle\n/**\n * The style in which the editor's cursor should be rendered.\n */\nexport var TextEditorCursorStyle;\n(function (TextEditorCursorStyle) {\n /**\n * As a vertical line (sitting between two characters).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"Line\"] = 1] = \"Line\";\n /**\n * As a block (sitting on top of a character).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"Block\"] = 2] = \"Block\";\n /**\n * As a horizontal line (sitting under a character).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"Underline\"] = 3] = \"Underline\";\n /**\n * As a thin vertical line (sitting between two characters).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"LineThin\"] = 4] = \"LineThin\";\n /**\n * As an outlined block (sitting on top of a character).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"BlockOutline\"] = 5] = \"BlockOutline\";\n /**\n * As a thin horizontal line (sitting under a character).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"UnderlineThin\"] = 6] = \"UnderlineThin\";\n})(TextEditorCursorStyle || (TextEditorCursorStyle = {}));\nfunction _cursorStyleFromString(cursorStyle) {\n switch (cursorStyle) {\n case 'line': return TextEditorCursorStyle.Line;\n case 'block': return TextEditorCursorStyle.Block;\n case 'underline': return TextEditorCursorStyle.Underline;\n case 'line-thin': return TextEditorCursorStyle.LineThin;\n case 'block-outline': return TextEditorCursorStyle.BlockOutline;\n case 'underline-thin': return TextEditorCursorStyle.UnderlineThin;\n }\n}\n//#endregion\n//#region editorClassName\nclass EditorClassName extends ComputedEditorOption {\n constructor() {\n super(130 /* EditorOption.editorClassName */);\n }\n compute(env, options, _) {\n const classNames = ['monaco-editor'];\n if (options.get(35 /* EditorOption.extraEditorClassName */)) {\n classNames.push(options.get(35 /* EditorOption.extraEditorClassName */));\n }\n if (env.extraEditorClassName) {\n classNames.push(env.extraEditorClassName);\n }\n if (options.get(68 /* EditorOption.mouseStyle */) === 'default') {\n classNames.push('mouse-default');\n }\n else if (options.get(68 /* EditorOption.mouseStyle */) === 'copy') {\n classNames.push('mouse-copy');\n }\n if (options.get(102 /* EditorOption.showUnused */)) {\n classNames.push('showUnused');\n }\n if (options.get(128 /* EditorOption.showDeprecated */)) {\n classNames.push('showDeprecated');\n }\n return classNames.join(' ');\n }\n}\n//#endregion\n//#region emptySelectionClipboard\nclass EditorEmptySelectionClipboard extends EditorBooleanOption {\n constructor() {\n super(33 /* EditorOption.emptySelectionClipboard */, 'emptySelectionClipboard', true, { description: nls.localize('emptySelectionClipboard', \"Controls whether copying without a selection copies the current line.\") });\n }\n compute(env, options, value) {\n return value && env.emptySelectionClipboard;\n }\n}\nclass EditorFind extends BaseEditorOption {\n constructor() {\n const defaults = {\n cursorMoveOnType: true,\n seedSearchStringFromSelection: 'always',\n autoFindInSelection: 'never',\n globalFindClipboard: false,\n addExtraSpaceOnTop: true,\n loop: true\n };\n super(37 /* EditorOption.find */, 'find', defaults, {\n 'editor.find.cursorMoveOnType': {\n type: 'boolean',\n default: defaults.cursorMoveOnType,\n description: nls.localize('find.cursorMoveOnType', \"Controls whether the cursor should jump to find matches while typing.\")\n },\n 'editor.find.seedSearchStringFromSelection': {\n type: 'string',\n enum: ['never', 'always', 'selection'],\n default: defaults.seedSearchStringFromSelection,\n enumDescriptions: [\n nls.localize('editor.find.seedSearchStringFromSelection.never', 'Never seed search string from the editor selection.'),\n nls.localize('editor.find.seedSearchStringFromSelection.always', 'Always seed search string from the editor selection, including word at cursor position.'),\n nls.localize('editor.find.seedSearchStringFromSelection.selection', 'Only seed search string from the editor selection.')\n ],\n description: nls.localize('find.seedSearchStringFromSelection', \"Controls whether the search string in the Find Widget is seeded from the editor selection.\")\n },\n 'editor.find.autoFindInSelection': {\n type: 'string',\n enum: ['never', 'always', 'multiline'],\n default: defaults.autoFindInSelection,\n enumDescriptions: [\n nls.localize('editor.find.autoFindInSelection.never', 'Never turn on Find in Selection automatically (default).'),\n nls.localize('editor.find.autoFindInSelection.always', 'Always turn on Find in Selection automatically.'),\n nls.localize('editor.find.autoFindInSelection.multiline', 'Turn on Find in Selection automatically when multiple lines of content are selected.')\n ],\n description: nls.localize('find.autoFindInSelection', \"Controls the condition for turning on Find in Selection automatically.\")\n },\n 'editor.find.globalFindClipboard': {\n type: 'boolean',\n default: defaults.globalFindClipboard,\n description: nls.localize('find.globalFindClipboard', \"Controls whether the Find Widget should read or modify the shared find clipboard on macOS.\"),\n included: platform.isMacintosh\n },\n 'editor.find.addExtraSpaceOnTop': {\n type: 'boolean',\n default: defaults.addExtraSpaceOnTop,\n description: 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 },\n 'editor.find.loop': {\n type: 'boolean',\n default: defaults.loop,\n description: nls.localize('find.loop', \"Controls whether the search automatically restarts from the beginning (or the end) when no further matches can be found.\")\n },\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n cursorMoveOnType: boolean(input.cursorMoveOnType, this.defaultValue.cursorMoveOnType),\n seedSearchStringFromSelection: typeof _input.seedSearchStringFromSelection === 'boolean'\n ? (_input.seedSearchStringFromSelection ? 'always' : 'never')\n : stringSet(input.seedSearchStringFromSelection, this.defaultValue.seedSearchStringFromSelection, ['never', 'always', 'selection']),\n autoFindInSelection: typeof _input.autoFindInSelection === 'boolean'\n ? (_input.autoFindInSelection ? 'always' : 'never')\n : stringSet(input.autoFindInSelection, this.defaultValue.autoFindInSelection, ['never', 'always', 'multiline']),\n globalFindClipboard: boolean(input.globalFindClipboard, this.defaultValue.globalFindClipboard),\n addExtraSpaceOnTop: boolean(input.addExtraSpaceOnTop, this.defaultValue.addExtraSpaceOnTop),\n loop: boolean(input.loop, this.defaultValue.loop),\n };\n }\n}\n//#endregion\n//#region fontLigatures\n/**\n * @internal\n */\nexport class EditorFontLigatures extends BaseEditorOption {\n constructor() {\n super(47 /* EditorOption.fontLigatures */, 'fontLigatures', EditorFontLigatures.OFF, {\n anyOf: [\n {\n type: 'boolean',\n description: 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 },\n {\n type: 'string',\n description: 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 }\n ],\n description: 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 default: false\n });\n }\n validate(input) {\n if (typeof input === 'undefined') {\n return this.defaultValue;\n }\n if (typeof input === 'string') {\n if (input === 'false') {\n return EditorFontLigatures.OFF;\n }\n if (input === 'true') {\n return EditorFontLigatures.ON;\n }\n return input;\n }\n if (Boolean(input)) {\n return EditorFontLigatures.ON;\n }\n return EditorFontLigatures.OFF;\n }\n}\nEditorFontLigatures.OFF = '\"liga\" off, \"calt\" off';\nEditorFontLigatures.ON = '\"liga\" on, \"calt\" on';\n//#endregion\n//#region fontInfo\nclass EditorFontInfo extends ComputedEditorOption {\n constructor() {\n super(46 /* EditorOption.fontInfo */);\n }\n compute(env, options, _) {\n return env.fontInfo;\n }\n}\n//#endregion\n//#region fontSize\nclass EditorFontSize extends SimpleEditorOption {\n constructor() {\n super(48 /* EditorOption.fontSize */, 'fontSize', EDITOR_FONT_DEFAULTS.fontSize, {\n type: 'number',\n minimum: 6,\n maximum: 100,\n default: EDITOR_FONT_DEFAULTS.fontSize,\n description: nls.localize('fontSize', \"Controls the font size in pixels.\")\n });\n }\n validate(input) {\n const r = EditorFloatOption.float(input, this.defaultValue);\n if (r === 0) {\n return EDITOR_FONT_DEFAULTS.fontSize;\n }\n return EditorFloatOption.clamp(r, 6, 100);\n }\n compute(env, options, value) {\n // The final fontSize respects the editor zoom level.\n // So take the result from env.fontInfo\n return env.fontInfo.fontSize;\n }\n}\n//#endregion\n//#region fontWeight\nclass EditorFontWeight extends BaseEditorOption {\n constructor() {\n super(49 /* EditorOption.fontWeight */, 'fontWeight', EDITOR_FONT_DEFAULTS.fontWeight, {\n anyOf: [\n {\n type: 'number',\n minimum: EditorFontWeight.MINIMUM_VALUE,\n maximum: EditorFontWeight.MAXIMUM_VALUE,\n errorMessage: nls.localize('fontWeightErrorMessage', \"Only \\\"normal\\\" and \\\"bold\\\" keywords or numbers between 1 and 1000 are allowed.\")\n },\n {\n type: 'string',\n pattern: '^(normal|bold|1000|[1-9][0-9]{0,2})$'\n },\n {\n enum: EditorFontWeight.SUGGESTION_VALUES\n }\n ],\n default: EDITOR_FONT_DEFAULTS.fontWeight,\n description: nls.localize('fontWeight', \"Controls the font weight. Accepts \\\"normal\\\" and \\\"bold\\\" keywords or numbers between 1 and 1000.\")\n });\n }\n validate(input) {\n if (input === 'normal' || input === 'bold') {\n return input;\n }\n return String(EditorIntOption.clampedInt(input, EDITOR_FONT_DEFAULTS.fontWeight, EditorFontWeight.MINIMUM_VALUE, EditorFontWeight.MAXIMUM_VALUE));\n }\n}\nEditorFontWeight.SUGGESTION_VALUES = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'];\nEditorFontWeight.MINIMUM_VALUE = 1;\nEditorFontWeight.MAXIMUM_VALUE = 1000;\nclass EditorGoToLocation extends BaseEditorOption {\n constructor() {\n const defaults = {\n multiple: 'peek',\n multipleDefinitions: 'peek',\n multipleTypeDefinitions: 'peek',\n multipleDeclarations: 'peek',\n multipleImplementations: 'peek',\n multipleReferences: 'peek',\n alternativeDefinitionCommand: 'editor.action.goToReferences',\n alternativeTypeDefinitionCommand: 'editor.action.goToReferences',\n alternativeDeclarationCommand: 'editor.action.goToReferences',\n alternativeImplementationCommand: '',\n alternativeReferenceCommand: '',\n };\n const jsonSubset = {\n type: 'string',\n enum: ['peek', 'gotoAndPeek', 'goto'],\n default: defaults.multiple,\n enumDescriptions: [\n nls.localize('editor.gotoLocation.multiple.peek', 'Show peek view of the results (default)'),\n nls.localize('editor.gotoLocation.multiple.gotoAndPeek', 'Go to the primary result and show a peek view'),\n nls.localize('editor.gotoLocation.multiple.goto', 'Go to the primary result and enable peek-less navigation to others')\n ]\n };\n const 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 super(53 /* EditorOption.gotoLocation */, 'gotoLocation', defaults, {\n 'editor.gotoLocation.multiple': {\n deprecationMessage: 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 },\n 'editor.gotoLocation.multipleDefinitions': Object.assign({ description: nls.localize('editor.editor.gotoLocation.multipleDefinitions', \"Controls the behavior the 'Go to Definition'-command when multiple target locations exist.\") }, jsonSubset),\n 'editor.gotoLocation.multipleTypeDefinitions': Object.assign({ description: nls.localize('editor.editor.gotoLocation.multipleTypeDefinitions', \"Controls the behavior the 'Go to Type Definition'-command when multiple target locations exist.\") }, jsonSubset),\n 'editor.gotoLocation.multipleDeclarations': Object.assign({ description: nls.localize('editor.editor.gotoLocation.multipleDeclarations', \"Controls the behavior the 'Go to Declaration'-command when multiple target locations exist.\") }, jsonSubset),\n 'editor.gotoLocation.multipleImplementations': Object.assign({ description: nls.localize('editor.editor.gotoLocation.multipleImplemenattions', \"Controls the behavior the 'Go to Implementations'-command when multiple target locations exist.\") }, jsonSubset),\n 'editor.gotoLocation.multipleReferences': Object.assign({ description: nls.localize('editor.editor.gotoLocation.multipleReferences', \"Controls the behavior the 'Go to References'-command when multiple target locations exist.\") }, jsonSubset),\n 'editor.gotoLocation.alternativeDefinitionCommand': {\n type: 'string',\n default: defaults.alternativeDefinitionCommand,\n enum: alternativeCommandOptions,\n description: nls.localize('alternativeDefinitionCommand', \"Alternative command id that is being executed when the result of 'Go to Definition' is the current location.\")\n },\n 'editor.gotoLocation.alternativeTypeDefinitionCommand': {\n type: 'string',\n default: defaults.alternativeTypeDefinitionCommand,\n enum: alternativeCommandOptions,\n description: nls.localize('alternativeTypeDefinitionCommand', \"Alternative command id that is being executed when the result of 'Go to Type Definition' is the current location.\")\n },\n 'editor.gotoLocation.alternativeDeclarationCommand': {\n type: 'string',\n default: defaults.alternativeDeclarationCommand,\n enum: alternativeCommandOptions,\n description: nls.localize('alternativeDeclarationCommand', \"Alternative command id that is being executed when the result of 'Go to Declaration' is the current location.\")\n },\n 'editor.gotoLocation.alternativeImplementationCommand': {\n type: 'string',\n default: defaults.alternativeImplementationCommand,\n enum: alternativeCommandOptions,\n description: nls.localize('alternativeImplementationCommand', \"Alternative command id that is being executed when the result of 'Go to Implementation' is the current location.\")\n },\n 'editor.gotoLocation.alternativeReferenceCommand': {\n type: 'string',\n default: defaults.alternativeReferenceCommand,\n enum: alternativeCommandOptions,\n description: nls.localize('alternativeReferenceCommand', \"Alternative command id that is being executed when the result of 'Go to Reference' is the current location.\")\n },\n });\n }\n validate(_input) {\n var _a, _b, _c, _d, _e;\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n multiple: stringSet(input.multiple, this.defaultValue.multiple, ['peek', 'gotoAndPeek', 'goto']),\n multipleDefinitions: (_a = input.multipleDefinitions) !== null && _a !== void 0 ? _a : stringSet(input.multipleDefinitions, 'peek', ['peek', 'gotoAndPeek', 'goto']),\n multipleTypeDefinitions: (_b = input.multipleTypeDefinitions) !== null && _b !== void 0 ? _b : stringSet(input.multipleTypeDefinitions, 'peek', ['peek', 'gotoAndPeek', 'goto']),\n multipleDeclarations: (_c = input.multipleDeclarations) !== null && _c !== void 0 ? _c : stringSet(input.multipleDeclarations, 'peek', ['peek', 'gotoAndPeek', 'goto']),\n multipleImplementations: (_d = input.multipleImplementations) !== null && _d !== void 0 ? _d : stringSet(input.multipleImplementations, 'peek', ['peek', 'gotoAndPeek', 'goto']),\n multipleReferences: (_e = input.multipleReferences) !== null && _e !== void 0 ? _e : stringSet(input.multipleReferences, 'peek', ['peek', 'gotoAndPeek', 'goto']),\n alternativeDefinitionCommand: EditorStringOption.string(input.alternativeDefinitionCommand, this.defaultValue.alternativeDefinitionCommand),\n alternativeTypeDefinitionCommand: EditorStringOption.string(input.alternativeTypeDefinitionCommand, this.defaultValue.alternativeTypeDefinitionCommand),\n alternativeDeclarationCommand: EditorStringOption.string(input.alternativeDeclarationCommand, this.defaultValue.alternativeDeclarationCommand),\n alternativeImplementationCommand: EditorStringOption.string(input.alternativeImplementationCommand, this.defaultValue.alternativeImplementationCommand),\n alternativeReferenceCommand: EditorStringOption.string(input.alternativeReferenceCommand, this.defaultValue.alternativeReferenceCommand),\n };\n }\n}\nclass EditorHover extends BaseEditorOption {\n constructor() {\n const defaults = {\n enabled: true,\n delay: 300,\n sticky: true,\n above: true,\n };\n super(55 /* EditorOption.hover */, 'hover', defaults, {\n 'editor.hover.enabled': {\n type: 'boolean',\n default: defaults.enabled,\n description: nls.localize('hover.enabled', \"Controls whether the hover is shown.\")\n },\n 'editor.hover.delay': {\n type: 'number',\n default: defaults.delay,\n minimum: 0,\n maximum: 10000,\n description: nls.localize('hover.delay', \"Controls the delay in milliseconds after which the hover is shown.\")\n },\n 'editor.hover.sticky': {\n type: 'boolean',\n default: defaults.sticky,\n description: nls.localize('hover.sticky', \"Controls whether the hover should remain visible when mouse is moved over it.\")\n },\n 'editor.hover.above': {\n type: 'boolean',\n default: defaults.above,\n description: nls.localize('hover.above', \"Prefer showing hovers above the line, if there's space.\")\n },\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n enabled: boolean(input.enabled, this.defaultValue.enabled),\n delay: EditorIntOption.clampedInt(input.delay, this.defaultValue.delay, 0, 10000),\n sticky: boolean(input.sticky, this.defaultValue.sticky),\n above: boolean(input.above, this.defaultValue.above),\n };\n }\n}\n/**\n * @internal\n */\nexport class EditorLayoutInfoComputer extends ComputedEditorOption {\n constructor() {\n super(133 /* EditorOption.layoutInfo */);\n }\n compute(env, options, _) {\n return EditorLayoutInfoComputer.computeLayout(options, {\n memory: env.memory,\n outerWidth: env.outerWidth,\n outerHeight: env.outerHeight,\n isDominatedByLongLines: env.isDominatedByLongLines,\n lineHeight: env.fontInfo.lineHeight,\n viewLineCount: env.viewLineCount,\n lineNumbersDigitCount: env.lineNumbersDigitCount,\n typicalHalfwidthCharacterWidth: env.fontInfo.typicalHalfwidthCharacterWidth,\n maxDigitWidth: env.fontInfo.maxDigitWidth,\n pixelRatio: env.pixelRatio\n });\n }\n static computeContainedMinimapLineCount(input) {\n const typicalViewportLineCount = input.height / input.lineHeight;\n const extraLinesBeyondLastLine = input.scrollBeyondLastLine ? (typicalViewportLineCount - 1) : 0;\n const desiredRatio = (input.viewLineCount + extraLinesBeyondLastLine) / (input.pixelRatio * input.height);\n const minimapLineCount = Math.floor(input.viewLineCount / desiredRatio);\n return { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount };\n }\n static _computeMinimapLayout(input, memory) {\n const outerWidth = input.outerWidth;\n const outerHeight = input.outerHeight;\n const pixelRatio = input.pixelRatio;\n if (!input.minimap.enabled) {\n return {\n renderMinimap: 0 /* RenderMinimap.None */,\n minimapLeft: 0,\n minimapWidth: 0,\n minimapHeightIsEditorHeight: false,\n minimapIsSampling: false,\n minimapScale: 1,\n minimapLineHeight: 1,\n minimapCanvasInnerWidth: 0,\n minimapCanvasInnerHeight: Math.floor(pixelRatio * outerHeight),\n minimapCanvasOuterWidth: 0,\n minimapCanvasOuterHeight: outerHeight,\n };\n }\n // Can use memory if only the `viewLineCount` and `remainingWidth` have changed\n const stableMinimapLayoutInput = memory.stableMinimapLayoutInput;\n const couldUseMemory = (stableMinimapLayoutInput\n // && input.outerWidth === lastMinimapLayoutInput.outerWidth !!! INTENTIONAL OMITTED\n && input.outerHeight === stableMinimapLayoutInput.outerHeight\n && input.lineHeight === stableMinimapLayoutInput.lineHeight\n && input.typicalHalfwidthCharacterWidth === stableMinimapLayoutInput.typicalHalfwidthCharacterWidth\n && input.pixelRatio === stableMinimapLayoutInput.pixelRatio\n && input.scrollBeyondLastLine === stableMinimapLayoutInput.scrollBeyondLastLine\n && input.minimap.enabled === stableMinimapLayoutInput.minimap.enabled\n && input.minimap.side === stableMinimapLayoutInput.minimap.side\n && input.minimap.size === stableMinimapLayoutInput.minimap.size\n && input.minimap.showSlider === stableMinimapLayoutInput.minimap.showSlider\n && input.minimap.renderCharacters === stableMinimapLayoutInput.minimap.renderCharacters\n && input.minimap.maxColumn === stableMinimapLayoutInput.minimap.maxColumn\n && input.minimap.scale === stableMinimapLayoutInput.minimap.scale\n && input.verticalScrollbarWidth === stableMinimapLayoutInput.verticalScrollbarWidth\n // && input.viewLineCount === lastMinimapLayoutInput.viewLineCount !!! INTENTIONAL OMITTED\n // && input.remainingWidth === lastMinimapLayoutInput.remainingWidth !!! INTENTIONAL OMITTED\n && input.isViewportWrapping === stableMinimapLayoutInput.isViewportWrapping);\n const lineHeight = input.lineHeight;\n const typicalHalfwidthCharacterWidth = input.typicalHalfwidthCharacterWidth;\n const scrollBeyondLastLine = input.scrollBeyondLastLine;\n const minimapRenderCharacters = input.minimap.renderCharacters;\n let minimapScale = (pixelRatio >= 2 ? Math.round(input.minimap.scale * 2) : input.minimap.scale);\n const minimapMaxColumn = input.minimap.maxColumn;\n const minimapSize = input.minimap.size;\n const minimapSide = input.minimap.side;\n const verticalScrollbarWidth = input.verticalScrollbarWidth;\n const viewLineCount = input.viewLineCount;\n const remainingWidth = input.remainingWidth;\n const isViewportWrapping = input.isViewportWrapping;\n const baseCharHeight = minimapRenderCharacters ? 2 : 3;\n let minimapCanvasInnerHeight = Math.floor(pixelRatio * outerHeight);\n const minimapCanvasOuterHeight = minimapCanvasInnerHeight / pixelRatio;\n let minimapHeightIsEditorHeight = false;\n let minimapIsSampling = false;\n let minimapLineHeight = baseCharHeight * minimapScale;\n let minimapCharWidth = minimapScale / pixelRatio;\n let minimapWidthMultiplier = 1;\n if (minimapSize === 'fill' || minimapSize === 'fit') {\n const { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({\n viewLineCount: viewLineCount,\n scrollBeyondLastLine: scrollBeyondLastLine,\n height: outerHeight,\n lineHeight: lineHeight,\n pixelRatio: pixelRatio\n });\n // ratio is intentionally not part of the layout to avoid the layout changing all the time\n // when doing sampling\n const ratio = viewLineCount / minimapLineCount;\n if (ratio > 1) {\n minimapHeightIsEditorHeight = true;\n minimapIsSampling = true;\n minimapScale = 1;\n minimapLineHeight = 1;\n minimapCharWidth = minimapScale / pixelRatio;\n }\n else {\n let fitBecomesFill = false;\n let maxMinimapScale = minimapScale + 1;\n if (minimapSize === 'fit') {\n const effectiveMinimapHeight = Math.ceil((viewLineCount + extraLinesBeyondLastLine) * minimapLineHeight);\n if (isViewportWrapping && couldUseMemory && remainingWidth <= memory.stableFitRemainingWidth) {\n // There is a loop when using `fit` and viewport wrapping:\n // - view line count impacts minimap layout\n // - minimap layout impacts viewport width\n // - viewport width impacts view line count\n // To break the loop, once we go to a smaller minimap scale, we try to stick with it.\n fitBecomesFill = true;\n maxMinimapScale = memory.stableFitMaxMinimapScale;\n }\n else {\n fitBecomesFill = (effectiveMinimapHeight > minimapCanvasInnerHeight);\n }\n }\n if (minimapSize === 'fill' || fitBecomesFill) {\n minimapHeightIsEditorHeight = true;\n const configuredMinimapScale = minimapScale;\n minimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio)));\n if (isViewportWrapping && couldUseMemory && remainingWidth <= memory.stableFitRemainingWidth) {\n // There is a loop when using `fill` and viewport wrapping:\n // - view line count impacts minimap layout\n // - minimap layout impacts viewport width\n // - viewport width impacts view line count\n // To break the loop, once we go to a smaller minimap scale, we try to stick with it.\n maxMinimapScale = memory.stableFitMaxMinimapScale;\n }\n minimapScale = Math.min(maxMinimapScale, Math.max(1, Math.floor(minimapLineHeight / baseCharHeight)));\n if (minimapScale > configuredMinimapScale) {\n minimapWidthMultiplier = Math.min(2, minimapScale / configuredMinimapScale);\n }\n minimapCharWidth = minimapScale / pixelRatio / minimapWidthMultiplier;\n minimapCanvasInnerHeight = Math.ceil((Math.max(typicalViewportLineCount, viewLineCount + extraLinesBeyondLastLine)) * minimapLineHeight);\n if (isViewportWrapping) {\n // remember for next time\n memory.stableMinimapLayoutInput = input;\n memory.stableFitRemainingWidth = remainingWidth;\n memory.stableFitMaxMinimapScale = minimapScale;\n }\n else {\n memory.stableMinimapLayoutInput = null;\n memory.stableFitRemainingWidth = 0;\n }\n }\n }\n }\n // Given:\n // (leaving 2px for the cursor to have space after the last character)\n // viewportColumn = (contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth\n // minimapWidth = viewportColumn * minimapCharWidth\n // contentWidth = remainingWidth - minimapWidth\n // What are good values for contentWidth and minimapWidth ?\n // minimapWidth = ((contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth) * minimapCharWidth\n // typicalHalfwidthCharacterWidth * minimapWidth = (contentWidth - verticalScrollbarWidth - 2) * minimapCharWidth\n // typicalHalfwidthCharacterWidth * minimapWidth = (remainingWidth - minimapWidth - verticalScrollbarWidth - 2) * minimapCharWidth\n // (typicalHalfwidthCharacterWidth + minimapCharWidth) * minimapWidth = (remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth\n // minimapWidth = ((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth)\n const minimapMaxWidth = Math.floor(minimapMaxColumn * minimapCharWidth);\n const minimapWidth = Math.min(minimapMaxWidth, Math.max(0, Math.floor(((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth))) + MINIMAP_GUTTER_WIDTH);\n let minimapCanvasInnerWidth = Math.floor(pixelRatio * minimapWidth);\n const minimapCanvasOuterWidth = minimapCanvasInnerWidth / pixelRatio;\n minimapCanvasInnerWidth = Math.floor(minimapCanvasInnerWidth * minimapWidthMultiplier);\n const renderMinimap = (minimapRenderCharacters ? 1 /* RenderMinimap.Text */ : 2 /* RenderMinimap.Blocks */);\n const minimapLeft = (minimapSide === 'left' ? 0 : (outerWidth - minimapWidth - verticalScrollbarWidth));\n return {\n renderMinimap,\n minimapLeft,\n minimapWidth,\n minimapHeightIsEditorHeight,\n minimapIsSampling,\n minimapScale,\n minimapLineHeight,\n minimapCanvasInnerWidth,\n minimapCanvasInnerHeight,\n minimapCanvasOuterWidth,\n minimapCanvasOuterHeight,\n };\n }\n static computeLayout(options, env) {\n const outerWidth = env.outerWidth | 0;\n const outerHeight = env.outerHeight | 0;\n const lineHeight = env.lineHeight | 0;\n const lineNumbersDigitCount = env.lineNumbersDigitCount | 0;\n const typicalHalfwidthCharacterWidth = env.typicalHalfwidthCharacterWidth;\n const maxDigitWidth = env.maxDigitWidth;\n const pixelRatio = env.pixelRatio;\n const viewLineCount = env.viewLineCount;\n const wordWrapOverride2 = options.get(125 /* EditorOption.wordWrapOverride2 */);\n const wordWrapOverride1 = (wordWrapOverride2 === 'inherit' ? options.get(124 /* EditorOption.wordWrapOverride1 */) : wordWrapOverride2);\n const wordWrap = (wordWrapOverride1 === 'inherit' ? options.get(120 /* EditorOption.wordWrap */) : wordWrapOverride1);\n const wordWrapColumn = options.get(123 /* EditorOption.wordWrapColumn */);\n const accessibilitySupport = options.get(2 /* EditorOption.accessibilitySupport */);\n const isDominatedByLongLines = env.isDominatedByLongLines;\n const showGlyphMargin = options.get(52 /* EditorOption.glyphMargin */);\n const showLineNumbers = (options.get(62 /* EditorOption.lineNumbers */).renderType !== 0 /* RenderLineNumbersType.Off */);\n const lineNumbersMinChars = options.get(63 /* EditorOption.lineNumbersMinChars */);\n const scrollBeyondLastLine = options.get(96 /* EditorOption.scrollBeyondLastLine */);\n const minimap = options.get(67 /* EditorOption.minimap */);\n const scrollbar = options.get(94 /* EditorOption.scrollbar */);\n const verticalScrollbarWidth = scrollbar.verticalScrollbarSize;\n const verticalScrollbarHasArrows = scrollbar.verticalHasArrows;\n const scrollbarArrowSize = scrollbar.arrowSize;\n const horizontalScrollbarHeight = scrollbar.horizontalScrollbarSize;\n const rawLineDecorationsWidth = options.get(60 /* EditorOption.lineDecorationsWidth */);\n const folding = options.get(39 /* EditorOption.folding */);\n const showFoldingDecoration = options.get(101 /* EditorOption.showFoldingControls */) !== 'never';\n let lineDecorationsWidth;\n if (typeof rawLineDecorationsWidth === 'string' && /^\\d+(\\.\\d+)?ch$/.test(rawLineDecorationsWidth)) {\n const multiple = parseFloat(rawLineDecorationsWidth.substr(0, rawLineDecorationsWidth.length - 2));\n lineDecorationsWidth = EditorIntOption.clampedInt(multiple * typicalHalfwidthCharacterWidth, 0, 0, 1000);\n }\n else {\n lineDecorationsWidth = EditorIntOption.clampedInt(rawLineDecorationsWidth, 0, 0, 1000);\n }\n if (folding && showFoldingDecoration) {\n lineDecorationsWidth += 16;\n }\n let lineNumbersWidth = 0;\n if (showLineNumbers) {\n const digitCount = Math.max(lineNumbersDigitCount, lineNumbersMinChars);\n lineNumbersWidth = Math.round(digitCount * maxDigitWidth);\n }\n let glyphMarginWidth = 0;\n if (showGlyphMargin) {\n glyphMarginWidth = lineHeight;\n }\n let glyphMarginLeft = 0;\n let lineNumbersLeft = glyphMarginLeft + glyphMarginWidth;\n let decorationsLeft = lineNumbersLeft + lineNumbersWidth;\n let contentLeft = decorationsLeft + lineDecorationsWidth;\n const remainingWidth = outerWidth - glyphMarginWidth - lineNumbersWidth - lineDecorationsWidth;\n let isWordWrapMinified = false;\n let isViewportWrapping = false;\n let wrappingColumn = -1;\n if (accessibilitySupport !== 2 /* AccessibilitySupport.Enabled */) {\n // See https://github.com/microsoft/vscode/issues/27766\n // Never enable wrapping when a screen reader is attached\n // because arrow down etc. will not move the cursor in the way\n // a screen reader expects.\n if (wordWrapOverride1 === 'inherit' && isDominatedByLongLines) {\n // Force viewport width wrapping if model is dominated by long lines\n isWordWrapMinified = true;\n isViewportWrapping = true;\n }\n else if (wordWrap === 'on' || wordWrap === 'bounded') {\n isViewportWrapping = true;\n }\n else if (wordWrap === 'wordWrapColumn') {\n wrappingColumn = wordWrapColumn;\n }\n }\n const minimapLayout = EditorLayoutInfoComputer._computeMinimapLayout({\n outerWidth: outerWidth,\n outerHeight: outerHeight,\n lineHeight: lineHeight,\n typicalHalfwidthCharacterWidth: typicalHalfwidthCharacterWidth,\n pixelRatio: pixelRatio,\n scrollBeyondLastLine: scrollBeyondLastLine,\n minimap: minimap,\n verticalScrollbarWidth: verticalScrollbarWidth,\n viewLineCount: viewLineCount,\n remainingWidth: remainingWidth,\n isViewportWrapping: isViewportWrapping,\n }, env.memory || new ComputeOptionsMemory());\n if (minimapLayout.renderMinimap !== 0 /* RenderMinimap.None */ && minimapLayout.minimapLeft === 0) {\n // the minimap is rendered to the left, so move everything to the right\n glyphMarginLeft += minimapLayout.minimapWidth;\n lineNumbersLeft += minimapLayout.minimapWidth;\n decorationsLeft += minimapLayout.minimapWidth;\n contentLeft += minimapLayout.minimapWidth;\n }\n const contentWidth = remainingWidth - minimapLayout.minimapWidth;\n // (leaving 2px for the cursor to have space after the last character)\n const viewportColumn = Math.max(1, Math.floor((contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth));\n const verticalArrowSize = (verticalScrollbarHasArrows ? scrollbarArrowSize : 0);\n if (isViewportWrapping) {\n // compute the actual wrappingColumn\n wrappingColumn = Math.max(1, viewportColumn);\n if (wordWrap === 'bounded') {\n wrappingColumn = Math.min(wrappingColumn, wordWrapColumn);\n }\n }\n return {\n width: outerWidth,\n height: outerHeight,\n glyphMarginLeft: glyphMarginLeft,\n glyphMarginWidth: glyphMarginWidth,\n lineNumbersLeft: lineNumbersLeft,\n lineNumbersWidth: lineNumbersWidth,\n decorationsLeft: decorationsLeft,\n decorationsWidth: lineDecorationsWidth,\n contentLeft: contentLeft,\n contentWidth: contentWidth,\n minimap: minimapLayout,\n viewportColumn: viewportColumn,\n isWordWrapMinified: isWordWrapMinified,\n isViewportWrapping: isViewportWrapping,\n wrappingColumn: wrappingColumn,\n verticalScrollbarWidth: verticalScrollbarWidth,\n horizontalScrollbarHeight: horizontalScrollbarHeight,\n overviewRuler: {\n top: verticalArrowSize,\n width: verticalScrollbarWidth,\n height: (outerHeight - 2 * verticalArrowSize),\n right: 0\n }\n };\n }\n}\nclass EditorLightbulb extends BaseEditorOption {\n constructor() {\n const defaults = { enabled: true };\n super(59 /* EditorOption.lightbulb */, 'lightbulb', defaults, {\n 'editor.lightbulb.enabled': {\n type: 'boolean',\n default: defaults.enabled,\n description: nls.localize('codeActions', \"Enables the code action lightbulb in the editor.\")\n },\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n enabled: boolean(input.enabled, this.defaultValue.enabled)\n };\n }\n}\nclass EditorExperimental extends BaseEditorOption {\n constructor() {\n const defaults = { stickyScroll: { enabled: false } };\n super(34 /* EditorOption.experimental */, 'experimental', defaults, {\n 'editor.experimental.stickyScroll.enabled': {\n type: 'boolean',\n default: defaults.stickyScroll.enabled,\n description: nls.localize('editor.experimental.stickyScroll', \"Shows the nested current scopes during the scroll at the top of the editor.\")\n },\n });\n }\n validate(_input) {\n var _a;\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n stickyScroll: {\n enabled: boolean((_a = input.stickyScroll) === null || _a === void 0 ? void 0 : _a.enabled, this.defaultValue.stickyScroll.enabled)\n }\n };\n }\n}\nclass EditorInlayHints extends BaseEditorOption {\n constructor() {\n const defaults = { enabled: 'on', fontSize: 0, fontFamily: '', padding: false };\n super(129 /* EditorOption.inlayHints */, 'inlayHints', defaults, {\n 'editor.inlayHints.enabled': {\n type: 'string',\n default: defaults.enabled,\n description: nls.localize('inlayHints.enable', \"Enables the inlay hints in the editor.\"),\n enum: ['on', 'onUnlessPressed', 'offUnlessPressed', 'off'],\n markdownEnumDescriptions: [\n nls.localize('editor.inlayHints.on', \"Inlay hints are enabled\"),\n nls.localize('editor.inlayHints.onUnlessPressed', \"Inlay hints are showing by default and hide when holding `Ctrl+Alt`\"),\n nls.localize('editor.inlayHints.offUnlessPressed', \"Inlay hints are hidden by default and show when holding `Ctrl+Alt`\"),\n nls.localize('editor.inlayHints.off', \"Inlay hints are disabled\"),\n ],\n },\n 'editor.inlayHints.fontSize': {\n type: 'number',\n default: defaults.fontSize,\n markdownDescription: nls.localize('inlayHints.fontSize', \"Controls font size of inlay hints in the editor. As default the {0} is used when the configured value is less than {1} or greater than the editor font size.\", '`#editor.fontSize#`', '`5`')\n },\n 'editor.inlayHints.fontFamily': {\n type: 'string',\n default: defaults.fontFamily,\n markdownDescription: nls.localize('inlayHints.fontFamily', \"Controls font family of inlay hints in the editor. When set to empty, the {0} is used.\", '`#editor.fontFamily#`')\n },\n 'editor.inlayHints.padding': {\n type: 'boolean',\n default: defaults.padding,\n description: nls.localize('inlayHints.padding', \"Enables the padding around the inlay hints in the editor.\")\n }\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n if (typeof input.enabled === 'boolean') {\n input.enabled = input.enabled ? 'on' : 'off';\n }\n return {\n enabled: stringSet(input.enabled, this.defaultValue.enabled, ['on', 'off', 'offUnlessPressed', 'onUnlessPressed']),\n fontSize: EditorIntOption.clampedInt(input.fontSize, this.defaultValue.fontSize, 0, 100),\n fontFamily: EditorStringOption.string(input.fontFamily, this.defaultValue.fontFamily),\n padding: boolean(input.padding, this.defaultValue.padding)\n };\n }\n}\n//#endregion\n//#region lineHeight\nclass EditorLineHeight extends EditorFloatOption {\n constructor() {\n super(61 /* EditorOption.lineHeight */, 'lineHeight', EDITOR_FONT_DEFAULTS.lineHeight, x => EditorFloatOption.clamp(x, 0, 150), { 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 }\n compute(env, options, value) {\n // The lineHeight is computed from the fontSize if it is 0.\n // Moreover, the final lineHeight respects the editor zoom level.\n // So take the result from env.fontInfo\n return env.fontInfo.lineHeight;\n }\n}\nclass EditorMinimap extends BaseEditorOption {\n constructor() {\n const defaults = {\n enabled: true,\n size: 'proportional',\n side: 'right',\n showSlider: 'mouseover',\n autohide: false,\n renderCharacters: true,\n maxColumn: 120,\n scale: 1,\n };\n super(67 /* EditorOption.minimap */, 'minimap', defaults, {\n 'editor.minimap.enabled': {\n type: 'boolean',\n default: defaults.enabled,\n description: nls.localize('minimap.enabled', \"Controls whether the minimap is shown.\")\n },\n 'editor.minimap.autohide': {\n type: 'boolean',\n default: defaults.autohide,\n description: nls.localize('minimap.autohide', \"Controls whether the minimap is hidden automatically.\")\n },\n 'editor.minimap.size': {\n type: 'string',\n enum: ['proportional', 'fill', 'fit'],\n enumDescriptions: [\n nls.localize('minimap.size.proportional', \"The minimap has the same size as the editor contents (and might scroll).\"),\n nls.localize('minimap.size.fill', \"The minimap will stretch or shrink as necessary to fill the height of the editor (no scrolling).\"),\n nls.localize('minimap.size.fit', \"The minimap will shrink as necessary to never be larger than the editor (no scrolling).\"),\n ],\n default: defaults.size,\n description: nls.localize('minimap.size', \"Controls the size of the minimap.\")\n },\n 'editor.minimap.side': {\n type: 'string',\n enum: ['left', 'right'],\n default: defaults.side,\n description: nls.localize('minimap.side', \"Controls the side where to render the minimap.\")\n },\n 'editor.minimap.showSlider': {\n type: 'string',\n enum: ['always', 'mouseover'],\n default: defaults.showSlider,\n description: nls.localize('minimap.showSlider', \"Controls when the minimap slider is shown.\")\n },\n 'editor.minimap.scale': {\n type: 'number',\n default: defaults.scale,\n minimum: 1,\n maximum: 3,\n enum: [1, 2, 3],\n description: nls.localize('minimap.scale', \"Scale of content drawn in the minimap: 1, 2 or 3.\")\n },\n 'editor.minimap.renderCharacters': {\n type: 'boolean',\n default: defaults.renderCharacters,\n description: nls.localize('minimap.renderCharacters', \"Render the actual characters on a line as opposed to color blocks.\")\n },\n 'editor.minimap.maxColumn': {\n type: 'number',\n default: defaults.maxColumn,\n description: nls.localize('minimap.maxColumn', \"Limit the width of the minimap to render at most a certain number of columns.\")\n }\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n enabled: boolean(input.enabled, this.defaultValue.enabled),\n autohide: boolean(input.autohide, this.defaultValue.autohide),\n size: stringSet(input.size, this.defaultValue.size, ['proportional', 'fill', 'fit']),\n side: stringSet(input.side, this.defaultValue.side, ['right', 'left']),\n showSlider: stringSet(input.showSlider, this.defaultValue.showSlider, ['always', 'mouseover']),\n renderCharacters: boolean(input.renderCharacters, this.defaultValue.renderCharacters),\n scale: EditorIntOption.clampedInt(input.scale, 1, 1, 3),\n maxColumn: EditorIntOption.clampedInt(input.maxColumn, this.defaultValue.maxColumn, 1, 10000),\n };\n }\n}\n//#endregion\n//#region multiCursorModifier\nfunction _multiCursorModifierFromString(multiCursorModifier) {\n if (multiCursorModifier === 'ctrlCmd') {\n return (platform.isMacintosh ? 'metaKey' : 'ctrlKey');\n }\n return 'altKey';\n}\nclass EditorPadding extends BaseEditorOption {\n constructor() {\n super(77 /* EditorOption.padding */, 'padding', { top: 0, bottom: 0 }, {\n 'editor.padding.top': {\n type: 'number',\n default: 0,\n minimum: 0,\n maximum: 1000,\n description: nls.localize('padding.top', \"Controls the amount of space between the top edge of the editor and the first line.\")\n },\n 'editor.padding.bottom': {\n type: 'number',\n default: 0,\n minimum: 0,\n maximum: 1000,\n description: nls.localize('padding.bottom', \"Controls the amount of space between the bottom edge of the editor and the last line.\")\n }\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n top: EditorIntOption.clampedInt(input.top, 0, 0, 1000),\n bottom: EditorIntOption.clampedInt(input.bottom, 0, 0, 1000)\n };\n }\n}\nclass EditorParameterHints extends BaseEditorOption {\n constructor() {\n const defaults = {\n enabled: true,\n cycle: false\n };\n super(78 /* EditorOption.parameterHints */, 'parameterHints', defaults, {\n 'editor.parameterHints.enabled': {\n type: 'boolean',\n default: defaults.enabled,\n description: nls.localize('parameterHints.enabled', \"Enables a pop-up that shows parameter documentation and type information as you type.\")\n },\n 'editor.parameterHints.cycle': {\n type: 'boolean',\n default: defaults.cycle,\n description: nls.localize('parameterHints.cycle', \"Controls whether the parameter hints menu cycles or closes when reaching the end of the list.\")\n },\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n enabled: boolean(input.enabled, this.defaultValue.enabled),\n cycle: boolean(input.cycle, this.defaultValue.cycle)\n };\n }\n}\n//#endregion\n//#region pixelRatio\nclass EditorPixelRatio extends ComputedEditorOption {\n constructor() {\n super(131 /* EditorOption.pixelRatio */);\n }\n compute(env, options, _) {\n return env.pixelRatio;\n }\n}\nclass EditorQuickSuggestions extends BaseEditorOption {\n constructor() {\n const defaults = {\n other: 'on',\n comments: 'off',\n strings: 'off'\n };\n const types = [\n { type: 'boolean' },\n {\n type: 'string',\n enum: ['on', 'inline', 'off'],\n enumDescriptions: [nls.localize('on', \"Quick suggestions show inside the suggest widget\"), nls.localize('inline', \"Quick suggestions show as ghost text\"), nls.localize('off', \"Quick suggestions are disabled\")]\n }\n ];\n super(81 /* EditorOption.quickSuggestions */, 'quickSuggestions', defaults, {\n type: 'object',\n additionalProperties: false,\n properties: {\n strings: {\n anyOf: types,\n default: defaults.strings,\n description: nls.localize('quickSuggestions.strings', \"Enable quick suggestions inside strings.\")\n },\n comments: {\n anyOf: types,\n default: defaults.comments,\n description: nls.localize('quickSuggestions.comments', \"Enable quick suggestions inside comments.\")\n },\n other: {\n anyOf: types,\n default: defaults.other,\n description: nls.localize('quickSuggestions.other', \"Enable quick suggestions outside of strings and comments.\")\n },\n },\n default: defaults,\n markdownDescription: nls.localize('quickSuggestions', \"Controls whether suggestions should automatically show up while typing. This can be controlled for typing in comments, strings, and other code. Quick suggestion can be configured to show as ghost text or with the suggest widget. Also be aware of the '{0}'-setting which controls if suggestions are triggered by special characters.\", `#editor.suggestOnTriggerCharacters#`)\n });\n this.defaultValue = defaults;\n }\n validate(input) {\n if (typeof input === 'boolean') {\n // boolean -> all on/off\n const value = input ? 'on' : 'off';\n return { comments: value, strings: value, other: value };\n }\n if (!input || typeof input !== 'object') {\n // invalid object\n return this.defaultValue;\n }\n const { other, comments, strings } = input;\n const allowedValues = ['on', 'inline', 'off'];\n let validatedOther;\n let validatedComments;\n let validatedStrings;\n if (typeof other === 'boolean') {\n validatedOther = other ? 'on' : 'off';\n }\n else {\n validatedOther = stringSet(other, this.defaultValue.other, allowedValues);\n }\n if (typeof comments === 'boolean') {\n validatedComments = comments ? 'on' : 'off';\n }\n else {\n validatedComments = stringSet(comments, this.defaultValue.comments, allowedValues);\n }\n if (typeof strings === 'boolean') {\n validatedStrings = strings ? 'on' : 'off';\n }\n else {\n validatedStrings = stringSet(strings, this.defaultValue.strings, allowedValues);\n }\n return {\n other: validatedOther,\n comments: validatedComments,\n strings: validatedStrings\n };\n }\n}\nclass EditorRenderLineNumbersOption extends BaseEditorOption {\n constructor() {\n super(62 /* EditorOption.lineNumbers */, 'lineNumbers', { renderType: 1 /* RenderLineNumbersType.On */, renderFn: null }, {\n type: 'string',\n enum: ['off', 'on', 'relative', 'interval'],\n enumDescriptions: [\n nls.localize('lineNumbers.off', \"Line numbers are not rendered.\"),\n nls.localize('lineNumbers.on', \"Line numbers are rendered as absolute number.\"),\n nls.localize('lineNumbers.relative', \"Line numbers are rendered as distance in lines to cursor position.\"),\n nls.localize('lineNumbers.interval', \"Line numbers are rendered every 10 lines.\")\n ],\n default: 'on',\n description: nls.localize('lineNumbers', \"Controls the display of line numbers.\")\n });\n }\n validate(lineNumbers) {\n let renderType = this.defaultValue.renderType;\n let renderFn = this.defaultValue.renderFn;\n if (typeof lineNumbers !== 'undefined') {\n if (typeof lineNumbers === 'function') {\n renderType = 4 /* RenderLineNumbersType.Custom */;\n renderFn = lineNumbers;\n }\n else if (lineNumbers === 'interval') {\n renderType = 3 /* RenderLineNumbersType.Interval */;\n }\n else if (lineNumbers === 'relative') {\n renderType = 2 /* RenderLineNumbersType.Relative */;\n }\n else if (lineNumbers === 'on') {\n renderType = 1 /* RenderLineNumbersType.On */;\n }\n else {\n renderType = 0 /* RenderLineNumbersType.Off */;\n }\n }\n return {\n renderType,\n renderFn\n };\n }\n}\n//#endregion\n//#region renderValidationDecorations\n/**\n * @internal\n */\nexport function filterValidationDecorations(options) {\n const renderValidationDecorations = options.get(89 /* EditorOption.renderValidationDecorations */);\n if (renderValidationDecorations === 'editable') {\n return options.get(83 /* EditorOption.readOnly */);\n }\n return renderValidationDecorations === 'on' ? false : true;\n}\nclass EditorRulers extends BaseEditorOption {\n constructor() {\n const defaults = [];\n const columnSchema = { type: 'number', description: nls.localize('rulers.size', \"Number of monospace characters at which this editor ruler will render.\") };\n super(93 /* EditorOption.rulers */, 'rulers', defaults, {\n type: 'array',\n items: {\n anyOf: [\n columnSchema,\n {\n type: [\n 'object'\n ],\n properties: {\n column: columnSchema,\n color: {\n type: 'string',\n description: nls.localize('rulers.color', \"Color of this editor ruler.\"),\n format: 'color-hex'\n }\n }\n }\n ]\n },\n default: defaults,\n description: 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 });\n }\n validate(input) {\n if (Array.isArray(input)) {\n const rulers = [];\n for (const _element of input) {\n if (typeof _element === 'number') {\n rulers.push({\n column: EditorIntOption.clampedInt(_element, 0, 0, 10000),\n color: null\n });\n }\n else if (_element && typeof _element === 'object') {\n const element = _element;\n rulers.push({\n column: EditorIntOption.clampedInt(element.column, 0, 0, 10000),\n color: element.color\n });\n }\n }\n rulers.sort((a, b) => a.column - b.column);\n return rulers;\n }\n return this.defaultValue;\n }\n}\nfunction _scrollbarVisibilityFromString(visibility, defaultValue) {\n if (typeof visibility !== 'string') {\n return defaultValue;\n }\n switch (visibility) {\n case 'hidden': return 2 /* ScrollbarVisibility.Hidden */;\n case 'visible': return 3 /* ScrollbarVisibility.Visible */;\n default: return 1 /* ScrollbarVisibility.Auto */;\n }\n}\nclass EditorScrollbar extends BaseEditorOption {\n constructor() {\n const defaults = {\n vertical: 1 /* ScrollbarVisibility.Auto */,\n horizontal: 1 /* ScrollbarVisibility.Auto */,\n arrowSize: 11,\n useShadows: true,\n verticalHasArrows: false,\n horizontalHasArrows: false,\n horizontalScrollbarSize: 12,\n horizontalSliderSize: 12,\n verticalScrollbarSize: 14,\n verticalSliderSize: 14,\n handleMouseWheel: true,\n alwaysConsumeMouseWheel: true,\n scrollByPage: false\n };\n super(94 /* EditorOption.scrollbar */, 'scrollbar', defaults, {\n 'editor.scrollbar.vertical': {\n type: 'string',\n enum: ['auto', 'visible', 'hidden'],\n enumDescriptions: [\n nls.localize('scrollbar.vertical.auto', \"The vertical scrollbar will be visible only when necessary.\"),\n nls.localize('scrollbar.vertical.visible', \"The vertical scrollbar will always be visible.\"),\n nls.localize('scrollbar.vertical.fit', \"The vertical scrollbar will always be hidden.\"),\n ],\n default: 'auto',\n description: nls.localize('scrollbar.vertical', \"Controls the visibility of the vertical scrollbar.\")\n },\n 'editor.scrollbar.horizontal': {\n type: 'string',\n enum: ['auto', 'visible', 'hidden'],\n enumDescriptions: [\n nls.localize('scrollbar.horizontal.auto', \"The horizontal scrollbar will be visible only when necessary.\"),\n nls.localize('scrollbar.horizontal.visible', \"The horizontal scrollbar will always be visible.\"),\n nls.localize('scrollbar.horizontal.fit', \"The horizontal scrollbar will always be hidden.\"),\n ],\n default: 'auto',\n description: nls.localize('scrollbar.horizontal', \"Controls the visibility of the horizontal scrollbar.\")\n },\n 'editor.scrollbar.verticalScrollbarSize': {\n type: 'number',\n default: defaults.verticalScrollbarSize,\n description: nls.localize('scrollbar.verticalScrollbarSize', \"The width of the vertical scrollbar.\")\n },\n 'editor.scrollbar.horizontalScrollbarSize': {\n type: 'number',\n default: defaults.horizontalScrollbarSize,\n description: nls.localize('scrollbar.horizontalScrollbarSize', \"The height of the horizontal scrollbar.\")\n },\n 'editor.scrollbar.scrollByPage': {\n type: 'boolean',\n default: defaults.scrollByPage,\n description: nls.localize('scrollbar.scrollByPage', \"Controls whether clicks scroll by page or jump to click position.\")\n }\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n const horizontalScrollbarSize = EditorIntOption.clampedInt(input.horizontalScrollbarSize, this.defaultValue.horizontalScrollbarSize, 0, 1000);\n const verticalScrollbarSize = EditorIntOption.clampedInt(input.verticalScrollbarSize, this.defaultValue.verticalScrollbarSize, 0, 1000);\n return {\n arrowSize: EditorIntOption.clampedInt(input.arrowSize, this.defaultValue.arrowSize, 0, 1000),\n vertical: _scrollbarVisibilityFromString(input.vertical, this.defaultValue.vertical),\n horizontal: _scrollbarVisibilityFromString(input.horizontal, this.defaultValue.horizontal),\n useShadows: boolean(input.useShadows, this.defaultValue.useShadows),\n verticalHasArrows: boolean(input.verticalHasArrows, this.defaultValue.verticalHasArrows),\n horizontalHasArrows: boolean(input.horizontalHasArrows, this.defaultValue.horizontalHasArrows),\n handleMouseWheel: boolean(input.handleMouseWheel, this.defaultValue.handleMouseWheel),\n alwaysConsumeMouseWheel: boolean(input.alwaysConsumeMouseWheel, this.defaultValue.alwaysConsumeMouseWheel),\n horizontalScrollbarSize: horizontalScrollbarSize,\n horizontalSliderSize: EditorIntOption.clampedInt(input.horizontalSliderSize, horizontalScrollbarSize, 0, 1000),\n verticalScrollbarSize: verticalScrollbarSize,\n verticalSliderSize: EditorIntOption.clampedInt(input.verticalSliderSize, verticalScrollbarSize, 0, 1000),\n scrollByPage: boolean(input.scrollByPage, this.defaultValue.scrollByPage),\n };\n }\n}\n/**\n * @internal\n*/\nexport const inUntrustedWorkspace = 'inUntrustedWorkspace';\n/**\n * @internal\n */\nexport const unicodeHighlightConfigKeys = {\n allowedCharacters: 'editor.unicodeHighlight.allowedCharacters',\n invisibleCharacters: 'editor.unicodeHighlight.invisibleCharacters',\n nonBasicASCII: 'editor.unicodeHighlight.nonBasicASCII',\n ambiguousCharacters: 'editor.unicodeHighlight.ambiguousCharacters',\n includeComments: 'editor.unicodeHighlight.includeComments',\n includeStrings: 'editor.unicodeHighlight.includeStrings',\n allowedLocales: 'editor.unicodeHighlight.allowedLocales',\n};\nclass UnicodeHighlight extends BaseEditorOption {\n constructor() {\n const defaults = {\n nonBasicASCII: inUntrustedWorkspace,\n invisibleCharacters: true,\n ambiguousCharacters: true,\n includeComments: inUntrustedWorkspace,\n includeStrings: true,\n allowedCharacters: {},\n allowedLocales: { _os: true, _vscode: true },\n };\n super(115 /* EditorOption.unicodeHighlighting */, 'unicodeHighlight', defaults, {\n [unicodeHighlightConfigKeys.nonBasicASCII]: {\n restricted: true,\n type: ['boolean', 'string'],\n enum: [true, false, inUntrustedWorkspace],\n default: defaults.nonBasicASCII,\n description: 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 },\n [unicodeHighlightConfigKeys.invisibleCharacters]: {\n restricted: true,\n type: 'boolean',\n default: defaults.invisibleCharacters,\n description: nls.localize('unicodeHighlight.invisibleCharacters', \"Controls whether characters that just reserve space or have no width at all are highlighted.\")\n },\n [unicodeHighlightConfigKeys.ambiguousCharacters]: {\n restricted: true,\n type: 'boolean',\n default: defaults.ambiguousCharacters,\n description: 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 },\n [unicodeHighlightConfigKeys.includeComments]: {\n restricted: true,\n type: ['boolean', 'string'],\n enum: [true, false, inUntrustedWorkspace],\n default: defaults.includeComments,\n description: nls.localize('unicodeHighlight.includeComments', \"Controls whether characters in comments should also be subject to unicode highlighting.\")\n },\n [unicodeHighlightConfigKeys.includeStrings]: {\n restricted: true,\n type: ['boolean', 'string'],\n enum: [true, false, inUntrustedWorkspace],\n default: defaults.includeStrings,\n description: nls.localize('unicodeHighlight.includeStrings', \"Controls whether characters in strings should also be subject to unicode highlighting.\")\n },\n [unicodeHighlightConfigKeys.allowedCharacters]: {\n restricted: true,\n type: 'object',\n default: defaults.allowedCharacters,\n description: nls.localize('unicodeHighlight.allowedCharacters', \"Defines allowed characters that are not being highlighted.\"),\n additionalProperties: {\n type: 'boolean'\n }\n },\n [unicodeHighlightConfigKeys.allowedLocales]: {\n restricted: true,\n type: 'object',\n additionalProperties: {\n type: 'boolean'\n },\n default: defaults.allowedLocales,\n description: nls.localize('unicodeHighlight.allowedLocales', \"Unicode characters that are common in allowed locales are not being highlighted.\")\n },\n });\n }\n applyUpdate(value, update) {\n let didChange = false;\n if (update.allowedCharacters && value) {\n // Treat allowedCharacters atomically\n if (!objects.equals(value.allowedCharacters, update.allowedCharacters)) {\n value = Object.assign(Object.assign({}, value), { allowedCharacters: update.allowedCharacters });\n didChange = true;\n }\n }\n if (update.allowedLocales && value) {\n // Treat allowedLocales atomically\n if (!objects.equals(value.allowedLocales, update.allowedLocales)) {\n value = Object.assign(Object.assign({}, value), { allowedLocales: update.allowedLocales });\n didChange = true;\n }\n }\n const result = super.applyUpdate(value, update);\n if (didChange) {\n return new ApplyUpdateResult(result.newValue, true);\n }\n return result;\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n nonBasicASCII: primitiveSet(input.nonBasicASCII, inUntrustedWorkspace, [true, false, inUntrustedWorkspace]),\n invisibleCharacters: boolean(input.invisibleCharacters, this.defaultValue.invisibleCharacters),\n ambiguousCharacters: boolean(input.ambiguousCharacters, this.defaultValue.ambiguousCharacters),\n includeComments: primitiveSet(input.includeComments, inUntrustedWorkspace, [true, false, inUntrustedWorkspace]),\n includeStrings: primitiveSet(input.includeStrings, inUntrustedWorkspace, [true, false, inUntrustedWorkspace]),\n allowedCharacters: this.validateBooleanMap(_input.allowedCharacters, this.defaultValue.allowedCharacters),\n allowedLocales: this.validateBooleanMap(_input.allowedLocales, this.defaultValue.allowedLocales),\n };\n }\n validateBooleanMap(map, defaultValue) {\n if ((typeof map !== 'object') || !map) {\n return defaultValue;\n }\n const result = {};\n for (const [key, value] of Object.entries(map)) {\n if (value === true) {\n result[key] = true;\n }\n }\n return result;\n }\n}\n/**\n * Configuration options for inline suggestions\n */\nclass InlineEditorSuggest extends BaseEditorOption {\n constructor() {\n const defaults = {\n enabled: true,\n mode: 'subwordSmart'\n };\n super(57 /* EditorOption.inlineSuggest */, 'inlineSuggest', defaults, {\n 'editor.inlineSuggest.enabled': {\n type: 'boolean',\n default: defaults.enabled,\n description: nls.localize('inlineSuggest.enabled', \"Controls whether to automatically show inline suggestions in the editor.\")\n }\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n enabled: boolean(input.enabled, this.defaultValue.enabled),\n mode: stringSet(input.mode, this.defaultValue.mode, ['prefix', 'subword', 'subwordSmart']),\n };\n }\n}\n/**\n * Configuration options for inline suggestions\n */\nclass BracketPairColorization extends BaseEditorOption {\n constructor() {\n const defaults = {\n enabled: EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions.enabled,\n independentColorPoolPerBracketType: EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions.independentColorPoolPerBracketType,\n };\n super(12 /* EditorOption.bracketPairColorization */, 'bracketPairColorization', defaults, {\n 'editor.bracketPairColorization.enabled': {\n type: 'boolean',\n default: defaults.enabled,\n markdownDescription: nls.localize('bracketPairColorization.enabled', \"Controls whether bracket pair colorization is enabled or not. Use {0} to override the bracket highlight colors.\", '`#workbench.colorCustomizations#`')\n },\n 'editor.bracketPairColorization.independentColorPoolPerBracketType': {\n type: 'boolean',\n default: defaults.independentColorPoolPerBracketType,\n description: nls.localize('bracketPairColorization.independentColorPoolPerBracketType', \"Controls whether each bracket type has its own independent color pool.\")\n },\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n enabled: boolean(input.enabled, this.defaultValue.enabled),\n independentColorPoolPerBracketType: boolean(input.independentColorPoolPerBracketType, this.defaultValue.independentColorPoolPerBracketType),\n };\n }\n}\n/**\n * Configuration options for inline suggestions\n */\nclass GuideOptions extends BaseEditorOption {\n constructor() {\n const defaults = {\n bracketPairs: false,\n bracketPairsHorizontal: 'active',\n highlightActiveBracketPair: true,\n indentation: true,\n highlightActiveIndentation: true\n };\n super(13 /* EditorOption.guides */, 'guides', defaults, {\n 'editor.guides.bracketPairs': {\n type: ['boolean', 'string'],\n enum: [true, 'active', false],\n enumDescriptions: [\n nls.localize('editor.guides.bracketPairs.true', \"Enables bracket pair guides.\"),\n nls.localize('editor.guides.bracketPairs.active', \"Enables bracket pair guides only for the active bracket pair.\"),\n nls.localize('editor.guides.bracketPairs.false', \"Disables bracket pair guides.\"),\n ],\n default: defaults.bracketPairs,\n description: nls.localize('editor.guides.bracketPairs', \"Controls whether bracket pair guides are enabled or not.\")\n },\n 'editor.guides.bracketPairsHorizontal': {\n type: ['boolean', 'string'],\n enum: [true, 'active', false],\n enumDescriptions: [\n nls.localize('editor.guides.bracketPairsHorizontal.true', \"Enables horizontal guides as addition to vertical bracket pair guides.\"),\n nls.localize('editor.guides.bracketPairsHorizontal.active', \"Enables horizontal guides only for the active bracket pair.\"),\n nls.localize('editor.guides.bracketPairsHorizontal.false', \"Disables horizontal bracket pair guides.\"),\n ],\n default: defaults.bracketPairsHorizontal,\n description: nls.localize('editor.guides.bracketPairsHorizontal', \"Controls whether horizontal bracket pair guides are enabled or not.\")\n },\n 'editor.guides.highlightActiveBracketPair': {\n type: 'boolean',\n default: defaults.highlightActiveBracketPair,\n description: nls.localize('editor.guides.highlightActiveBracketPair', \"Controls whether the editor should highlight the active bracket pair.\")\n },\n 'editor.guides.indentation': {\n type: 'boolean',\n default: defaults.indentation,\n description: nls.localize('editor.guides.indentation', \"Controls whether the editor should render indent guides.\")\n },\n 'editor.guides.highlightActiveIndentation': {\n type: ['boolean', 'string'],\n enum: [true, 'always', false],\n enumDescriptions: [\n nls.localize('editor.guides.highlightActiveIndentation.true', \"Highlights the active indent guide.\"),\n nls.localize('editor.guides.highlightActiveIndentation.always', \"Highlights the active indent guide even if bracket guides are highlighted.\"),\n nls.localize('editor.guides.highlightActiveIndentation.false', \"Do not highlight the active indent guide.\"),\n ],\n default: defaults.highlightActiveIndentation,\n description: nls.localize('editor.guides.highlightActiveIndentation', \"Controls whether the editor should highlight the active indent guide.\")\n }\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n bracketPairs: primitiveSet(input.bracketPairs, this.defaultValue.bracketPairs, [true, false, 'active']),\n bracketPairsHorizontal: primitiveSet(input.bracketPairsHorizontal, this.defaultValue.bracketPairsHorizontal, [true, false, 'active']),\n highlightActiveBracketPair: boolean(input.highlightActiveBracketPair, this.defaultValue.highlightActiveBracketPair),\n indentation: boolean(input.indentation, this.defaultValue.indentation),\n highlightActiveIndentation: primitiveSet(input.highlightActiveIndentation, this.defaultValue.highlightActiveIndentation, [true, false, 'always']),\n };\n }\n}\nfunction primitiveSet(value, defaultValue, allowedValues) {\n const idx = allowedValues.indexOf(value);\n if (idx === -1) {\n return defaultValue;\n }\n return allowedValues[idx];\n}\nclass EditorSuggest extends BaseEditorOption {\n constructor() {\n const defaults = {\n insertMode: 'insert',\n filterGraceful: true,\n snippetsPreventQuickSuggestions: true,\n localityBonus: false,\n shareSuggestSelections: false,\n showIcons: true,\n showStatusBar: false,\n preview: false,\n previewMode: 'subwordSmart',\n showInlineDetails: true,\n showMethods: true,\n showFunctions: true,\n showConstructors: true,\n showDeprecated: true,\n showFields: true,\n showVariables: true,\n showClasses: true,\n showStructs: true,\n showInterfaces: true,\n showModules: true,\n showProperties: true,\n showEvents: true,\n showOperators: true,\n showUnits: true,\n showValues: true,\n showConstants: true,\n showEnums: true,\n showEnumMembers: true,\n showKeywords: true,\n showWords: true,\n showColors: true,\n showFiles: true,\n showReferences: true,\n showFolders: true,\n showTypeParameters: true,\n showSnippets: true,\n showUsers: true,\n showIssues: true,\n };\n super(108 /* EditorOption.suggest */, 'suggest', defaults, {\n 'editor.suggest.insertMode': {\n type: 'string',\n enum: ['insert', 'replace'],\n enumDescriptions: [\n nls.localize('suggest.insertMode.insert', \"Insert suggestion without overwriting text right of the cursor.\"),\n nls.localize('suggest.insertMode.replace', \"Insert suggestion and overwrite text right of the cursor.\"),\n ],\n default: defaults.insertMode,\n description: nls.localize('suggest.insertMode', \"Controls whether words are overwritten when accepting completions. Note that this depends on extensions opting into this feature.\")\n },\n 'editor.suggest.filterGraceful': {\n type: 'boolean',\n default: defaults.filterGraceful,\n description: nls.localize('suggest.filterGraceful', \"Controls whether filtering and sorting suggestions accounts for small typos.\")\n },\n 'editor.suggest.localityBonus': {\n type: 'boolean',\n default: defaults.localityBonus,\n description: nls.localize('suggest.localityBonus', \"Controls whether sorting favors words that appear close to the cursor.\")\n },\n 'editor.suggest.shareSuggestSelections': {\n type: 'boolean',\n default: defaults.shareSuggestSelections,\n markdownDescription: nls.localize('suggest.shareSuggestSelections', \"Controls whether remembered suggestion selections are shared between multiple workspaces and windows (needs `#editor.suggestSelection#`).\")\n },\n 'editor.suggest.snippetsPreventQuickSuggestions': {\n type: 'boolean',\n default: defaults.snippetsPreventQuickSuggestions,\n description: nls.localize('suggest.snippetsPreventQuickSuggestions', \"Controls whether an active snippet prevents quick suggestions.\")\n },\n 'editor.suggest.showIcons': {\n type: 'boolean',\n default: defaults.showIcons,\n description: nls.localize('suggest.showIcons', \"Controls whether to show or hide icons in suggestions.\")\n },\n 'editor.suggest.showStatusBar': {\n type: 'boolean',\n default: defaults.showStatusBar,\n description: nls.localize('suggest.showStatusBar', \"Controls the visibility of the status bar at the bottom of the suggest widget.\")\n },\n 'editor.suggest.preview': {\n type: 'boolean',\n default: defaults.preview,\n description: nls.localize('suggest.preview', \"Controls whether to preview the suggestion outcome in the editor.\")\n },\n 'editor.suggest.showInlineDetails': {\n type: 'boolean',\n default: defaults.showInlineDetails,\n description: nls.localize('suggest.showInlineDetails', \"Controls whether suggest details show inline with the label or only in the details widget\")\n },\n 'editor.suggest.maxVisibleSuggestions': {\n type: 'number',\n deprecationMessage: nls.localize('suggest.maxVisibleSuggestions.dep', \"This setting is deprecated. The suggest widget can now be resized.\"),\n },\n 'editor.suggest.filteredTypes': {\n type: 'object',\n deprecationMessage: nls.localize('deprecated', \"This setting is deprecated, please use separate settings like 'editor.suggest.showKeywords' or 'editor.suggest.showSnippets' instead.\")\n },\n 'editor.suggest.showMethods': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showMethods', \"When enabled IntelliSense shows `method`-suggestions.\")\n },\n 'editor.suggest.showFunctions': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showFunctions', \"When enabled IntelliSense shows `function`-suggestions.\")\n },\n 'editor.suggest.showConstructors': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showConstructors', \"When enabled IntelliSense shows `constructor`-suggestions.\")\n },\n 'editor.suggest.showDeprecated': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showDeprecated', \"When enabled IntelliSense shows `deprecated`-suggestions.\")\n },\n 'editor.suggest.showFields': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showFields', \"When enabled IntelliSense shows `field`-suggestions.\")\n },\n 'editor.suggest.showVariables': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showVariables', \"When enabled IntelliSense shows `variable`-suggestions.\")\n },\n 'editor.suggest.showClasses': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showClasss', \"When enabled IntelliSense shows `class`-suggestions.\")\n },\n 'editor.suggest.showStructs': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showStructs', \"When enabled IntelliSense shows `struct`-suggestions.\")\n },\n 'editor.suggest.showInterfaces': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showInterfaces', \"When enabled IntelliSense shows `interface`-suggestions.\")\n },\n 'editor.suggest.showModules': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showModules', \"When enabled IntelliSense shows `module`-suggestions.\")\n },\n 'editor.suggest.showProperties': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showPropertys', \"When enabled IntelliSense shows `property`-suggestions.\")\n },\n 'editor.suggest.showEvents': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showEvents', \"When enabled IntelliSense shows `event`-suggestions.\")\n },\n 'editor.suggest.showOperators': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showOperators', \"When enabled IntelliSense shows `operator`-suggestions.\")\n },\n 'editor.suggest.showUnits': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showUnits', \"When enabled IntelliSense shows `unit`-suggestions.\")\n },\n 'editor.suggest.showValues': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showValues', \"When enabled IntelliSense shows `value`-suggestions.\")\n },\n 'editor.suggest.showConstants': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showConstants', \"When enabled IntelliSense shows `constant`-suggestions.\")\n },\n 'editor.suggest.showEnums': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showEnums', \"When enabled IntelliSense shows `enum`-suggestions.\")\n },\n 'editor.suggest.showEnumMembers': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showEnumMembers', \"When enabled IntelliSense shows `enumMember`-suggestions.\")\n },\n 'editor.suggest.showKeywords': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showKeywords', \"When enabled IntelliSense shows `keyword`-suggestions.\")\n },\n 'editor.suggest.showWords': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showTexts', \"When enabled IntelliSense shows `text`-suggestions.\")\n },\n 'editor.suggest.showColors': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showColors', \"When enabled IntelliSense shows `color`-suggestions.\")\n },\n 'editor.suggest.showFiles': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showFiles', \"When enabled IntelliSense shows `file`-suggestions.\")\n },\n 'editor.suggest.showReferences': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showReferences', \"When enabled IntelliSense shows `reference`-suggestions.\")\n },\n 'editor.suggest.showCustomcolors': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showCustomcolors', \"When enabled IntelliSense shows `customcolor`-suggestions.\")\n },\n 'editor.suggest.showFolders': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showFolders', \"When enabled IntelliSense shows `folder`-suggestions.\")\n },\n 'editor.suggest.showTypeParameters': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showTypeParameters', \"When enabled IntelliSense shows `typeParameter`-suggestions.\")\n },\n 'editor.suggest.showSnippets': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showSnippets', \"When enabled IntelliSense shows `snippet`-suggestions.\")\n },\n 'editor.suggest.showUsers': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showUsers', \"When enabled IntelliSense shows `user`-suggestions.\")\n },\n 'editor.suggest.showIssues': {\n type: 'boolean',\n default: true,\n markdownDescription: nls.localize('editor.suggest.showIssues', \"When enabled IntelliSense shows `issues`-suggestions.\")\n }\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n insertMode: stringSet(input.insertMode, this.defaultValue.insertMode, ['insert', 'replace']),\n filterGraceful: boolean(input.filterGraceful, this.defaultValue.filterGraceful),\n snippetsPreventQuickSuggestions: boolean(input.snippetsPreventQuickSuggestions, this.defaultValue.filterGraceful),\n localityBonus: boolean(input.localityBonus, this.defaultValue.localityBonus),\n shareSuggestSelections: boolean(input.shareSuggestSelections, this.defaultValue.shareSuggestSelections),\n showIcons: boolean(input.showIcons, this.defaultValue.showIcons),\n showStatusBar: boolean(input.showStatusBar, this.defaultValue.showStatusBar),\n preview: boolean(input.preview, this.defaultValue.preview),\n previewMode: stringSet(input.previewMode, this.defaultValue.previewMode, ['prefix', 'subword', 'subwordSmart']),\n showInlineDetails: boolean(input.showInlineDetails, this.defaultValue.showInlineDetails),\n showMethods: boolean(input.showMethods, this.defaultValue.showMethods),\n showFunctions: boolean(input.showFunctions, this.defaultValue.showFunctions),\n showConstructors: boolean(input.showConstructors, this.defaultValue.showConstructors),\n showDeprecated: boolean(input.showDeprecated, this.defaultValue.showDeprecated),\n showFields: boolean(input.showFields, this.defaultValue.showFields),\n showVariables: boolean(input.showVariables, this.defaultValue.showVariables),\n showClasses: boolean(input.showClasses, this.defaultValue.showClasses),\n showStructs: boolean(input.showStructs, this.defaultValue.showStructs),\n showInterfaces: boolean(input.showInterfaces, this.defaultValue.showInterfaces),\n showModules: boolean(input.showModules, this.defaultValue.showModules),\n showProperties: boolean(input.showProperties, this.defaultValue.showProperties),\n showEvents: boolean(input.showEvents, this.defaultValue.showEvents),\n showOperators: boolean(input.showOperators, this.defaultValue.showOperators),\n showUnits: boolean(input.showUnits, this.defaultValue.showUnits),\n showValues: boolean(input.showValues, this.defaultValue.showValues),\n showConstants: boolean(input.showConstants, this.defaultValue.showConstants),\n showEnums: boolean(input.showEnums, this.defaultValue.showEnums),\n showEnumMembers: boolean(input.showEnumMembers, this.defaultValue.showEnumMembers),\n showKeywords: boolean(input.showKeywords, this.defaultValue.showKeywords),\n showWords: boolean(input.showWords, this.defaultValue.showWords),\n showColors: boolean(input.showColors, this.defaultValue.showColors),\n showFiles: boolean(input.showFiles, this.defaultValue.showFiles),\n showReferences: boolean(input.showReferences, this.defaultValue.showReferences),\n showFolders: boolean(input.showFolders, this.defaultValue.showFolders),\n showTypeParameters: boolean(input.showTypeParameters, this.defaultValue.showTypeParameters),\n showSnippets: boolean(input.showSnippets, this.defaultValue.showSnippets),\n showUsers: boolean(input.showUsers, this.defaultValue.showUsers),\n showIssues: boolean(input.showIssues, this.defaultValue.showIssues),\n };\n }\n}\nclass SmartSelect extends BaseEditorOption {\n constructor() {\n super(104 /* EditorOption.smartSelect */, 'smartSelect', {\n selectLeadingAndTrailingWhitespace: true\n }, {\n 'editor.smartSelect.selectLeadingAndTrailingWhitespace': {\n description: nls.localize('selectLeadingAndTrailingWhitespace', \"Whether leading and trailing whitespace should always be selected.\"),\n default: true,\n type: 'boolean'\n }\n });\n }\n validate(input) {\n if (!input || typeof input !== 'object') {\n return this.defaultValue;\n }\n return {\n selectLeadingAndTrailingWhitespace: boolean(input.selectLeadingAndTrailingWhitespace, this.defaultValue.selectLeadingAndTrailingWhitespace)\n };\n }\n}\n//#endregion\n//#region tabFocusMode\nclass EditorTabFocusMode extends ComputedEditorOption {\n constructor() {\n super(132 /* EditorOption.tabFocusMode */);\n }\n compute(env, options, _) {\n const readOnly = options.get(83 /* EditorOption.readOnly */);\n return (readOnly ? true : env.tabFocusMode);\n }\n}\nfunction _wrappingIndentFromString(wrappingIndent) {\n switch (wrappingIndent) {\n case 'none': return 0 /* WrappingIndent.None */;\n case 'same': return 1 /* WrappingIndent.Same */;\n case 'indent': return 2 /* WrappingIndent.Indent */;\n case 'deepIndent': return 3 /* WrappingIndent.DeepIndent */;\n }\n}\nclass EditorWrappingInfoComputer extends ComputedEditorOption {\n constructor() {\n super(134 /* EditorOption.wrappingInfo */);\n }\n compute(env, options, _) {\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n return {\n isDominatedByLongLines: env.isDominatedByLongLines,\n isWordWrapMinified: layoutInfo.isWordWrapMinified,\n isViewportWrapping: layoutInfo.isViewportWrapping,\n wrappingColumn: layoutInfo.wrappingColumn,\n };\n }\n}\nclass EditorDropIntoEditor extends BaseEditorOption {\n constructor() {\n const defaults = { enabled: true };\n super(32 /* EditorOption.dropIntoEditor */, 'dropIntoEditor', defaults, {\n 'editor.dropIntoEditor.enabled': {\n type: 'boolean',\n default: defaults.enabled,\n markdownDescription: nls.localize('dropIntoEditor.enabled', \"Controls whether you can drag and drop a file into a text editor by holding down `shift` (instead of opening the file in an editor).\"),\n },\n });\n }\n validate(_input) {\n if (!_input || typeof _input !== 'object') {\n return this.defaultValue;\n }\n const input = _input;\n return {\n enabled: boolean(input.enabled, this.defaultValue.enabled)\n };\n }\n}\n//#endregion\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 * @internal\n */\nexport const EDITOR_FONT_DEFAULTS = {\n fontFamily: (platform.isMacintosh ? DEFAULT_MAC_FONT_FAMILY : (platform.isLinux ? DEFAULT_LINUX_FONT_FAMILY : DEFAULT_WINDOWS_FONT_FAMILY)),\n fontWeight: 'normal',\n fontSize: (platform.isMacintosh ? 12 : 14),\n lineHeight: 0,\n letterSpacing: 0,\n};\n/**\n * @internal\n */\nexport const editorOptionsRegistry = [];\nfunction register(option) {\n editorOptionsRegistry[option.id] = option;\n return option;\n}\nexport const EditorOptions = {\n acceptSuggestionOnCommitCharacter: register(new EditorBooleanOption(0 /* EditorOption.acceptSuggestionOnCommitCharacter */, 'acceptSuggestionOnCommitCharacter', true, { 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 acceptSuggestionOnEnter: register(new EditorStringEnumOption(1 /* EditorOption.acceptSuggestionOnEnter */, 'acceptSuggestionOnEnter', 'on', ['on', 'smart', 'off'], {\n markdownEnumDescriptions: [\n '',\n nls.localize('acceptSuggestionOnEnterSmart', \"Only accept a suggestion with `Enter` when it makes a textual change.\"),\n ''\n ],\n markdownDescription: 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 })),\n accessibilitySupport: register(new EditorAccessibilitySupport()),\n accessibilityPageSize: register(new EditorIntOption(3 /* EditorOption.accessibilityPageSize */, 'accessibilityPageSize', 10, 1, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, {\n description: 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 })),\n ariaLabel: register(new EditorStringOption(4 /* EditorOption.ariaLabel */, 'ariaLabel', nls.localize('editorViewAccessibleLabel', \"Editor content\"))),\n autoClosingBrackets: register(new EditorStringEnumOption(5 /* EditorOption.autoClosingBrackets */, 'autoClosingBrackets', 'languageDefined', ['always', 'languageDefined', 'beforeWhitespace', 'never'], {\n enumDescriptions: [\n '',\n nls.localize('editor.autoClosingBrackets.languageDefined', \"Use language configurations to determine when to autoclose brackets.\"),\n nls.localize('editor.autoClosingBrackets.beforeWhitespace', \"Autoclose brackets only when the cursor is to the left of whitespace.\"),\n '',\n ],\n description: nls.localize('autoClosingBrackets', \"Controls whether the editor should automatically close brackets after the user adds an opening bracket.\")\n })),\n autoClosingDelete: register(new EditorStringEnumOption(6 /* EditorOption.autoClosingDelete */, 'autoClosingDelete', 'auto', ['always', 'auto', 'never'], {\n enumDescriptions: [\n '',\n nls.localize('editor.autoClosingDelete.auto', \"Remove adjacent closing quotes or brackets only if they were automatically inserted.\"),\n '',\n ],\n description: nls.localize('autoClosingDelete', \"Controls whether the editor should remove adjacent closing quotes or brackets when deleting.\")\n })),\n autoClosingOvertype: register(new EditorStringEnumOption(7 /* EditorOption.autoClosingOvertype */, 'autoClosingOvertype', 'auto', ['always', 'auto', 'never'], {\n enumDescriptions: [\n '',\n nls.localize('editor.autoClosingOvertype.auto', \"Type over closing quotes or brackets only if they were automatically inserted.\"),\n '',\n ],\n description: nls.localize('autoClosingOvertype', \"Controls whether the editor should type over closing quotes or brackets.\")\n })),\n autoClosingQuotes: register(new EditorStringEnumOption(8 /* EditorOption.autoClosingQuotes */, 'autoClosingQuotes', 'languageDefined', ['always', 'languageDefined', 'beforeWhitespace', 'never'], {\n enumDescriptions: [\n '',\n nls.localize('editor.autoClosingQuotes.languageDefined', \"Use language configurations to determine when to autoclose quotes.\"),\n nls.localize('editor.autoClosingQuotes.beforeWhitespace', \"Autoclose quotes only when the cursor is to the left of whitespace.\"),\n '',\n ],\n description: nls.localize('autoClosingQuotes', \"Controls whether the editor should automatically close quotes after the user adds an opening quote.\")\n })),\n autoIndent: register(new EditorEnumOption(9 /* EditorOption.autoIndent */, 'autoIndent', 4 /* EditorAutoIndentStrategy.Full */, 'full', ['none', 'keep', 'brackets', 'advanced', 'full'], _autoIndentFromString, {\n enumDescriptions: [\n nls.localize('editor.autoIndent.none', \"The editor will not insert indentation automatically.\"),\n nls.localize('editor.autoIndent.keep', \"The editor will keep the current line's indentation.\"),\n nls.localize('editor.autoIndent.brackets', \"The editor will keep the current line's indentation and honor language defined brackets.\"),\n nls.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 nls.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 ],\n description: nls.localize('autoIndent', \"Controls whether the editor should automatically adjust the indentation when users type, paste, move or indent lines.\")\n })),\n automaticLayout: register(new EditorBooleanOption(10 /* EditorOption.automaticLayout */, 'automaticLayout', false)),\n autoSurround: register(new EditorStringEnumOption(11 /* EditorOption.autoSurround */, 'autoSurround', 'languageDefined', ['languageDefined', 'quotes', 'brackets', 'never'], {\n enumDescriptions: [\n nls.localize('editor.autoSurround.languageDefined', \"Use language configurations to determine when to automatically surround selections.\"),\n nls.localize('editor.autoSurround.quotes', \"Surround with quotes but not brackets.\"),\n nls.localize('editor.autoSurround.brackets', \"Surround with brackets but not quotes.\"),\n ''\n ],\n description: nls.localize('autoSurround', \"Controls whether the editor should automatically surround selections when typing quotes or brackets.\")\n })),\n bracketPairColorization: register(new BracketPairColorization()),\n bracketPairGuides: register(new GuideOptions()),\n stickyTabStops: register(new EditorBooleanOption(106 /* EditorOption.stickyTabStops */, 'stickyTabStops', false, { description: nls.localize('stickyTabStops', \"Emulate selection behavior of tab characters when using spaces for indentation. Selection will stick to tab stops.\") })),\n codeLens: register(new EditorBooleanOption(14 /* EditorOption.codeLens */, 'codeLens', true, { description: nls.localize('codeLens', \"Controls whether the editor shows CodeLens.\") })),\n codeLensFontFamily: register(new EditorStringOption(15 /* EditorOption.codeLensFontFamily */, 'codeLensFontFamily', '', { description: nls.localize('codeLensFontFamily', \"Controls the font family for CodeLens.\") })),\n codeLensFontSize: register(new EditorIntOption(16 /* EditorOption.codeLensFontSize */, 'codeLensFontSize', 0, 0, 100, {\n type: 'number',\n default: 0,\n minimum: 0,\n maximum: 100,\n markdownDescription: nls.localize('codeLensFontSize', \"Controls the font size in pixels for CodeLens. When set to `0`, 90% of `#editor.fontSize#` is used.\")\n })),\n colorDecorators: register(new EditorBooleanOption(17 /* EditorOption.colorDecorators */, 'colorDecorators', true, { description: nls.localize('colorDecorators', \"Controls whether the editor should render the inline color decorators and color picker.\") })),\n columnSelection: register(new EditorBooleanOption(18 /* EditorOption.columnSelection */, 'columnSelection', false, { description: nls.localize('columnSelection', \"Enable that the selection with the mouse and keys is doing column selection.\") })),\n comments: register(new EditorComments()),\n contextmenu: register(new EditorBooleanOption(20 /* EditorOption.contextmenu */, 'contextmenu', true)),\n copyWithSyntaxHighlighting: register(new EditorBooleanOption(21 /* EditorOption.copyWithSyntaxHighlighting */, 'copyWithSyntaxHighlighting', true, { description: nls.localize('copyWithSyntaxHighlighting', \"Controls whether syntax highlighting should be copied into the clipboard.\") })),\n cursorBlinking: register(new EditorEnumOption(22 /* EditorOption.cursorBlinking */, 'cursorBlinking', 1 /* TextEditorCursorBlinkingStyle.Blink */, 'blink', ['blink', 'smooth', 'phase', 'expand', 'solid'], _cursorBlinkingStyleFromString, { description: nls.localize('cursorBlinking', \"Control the cursor animation style.\") })),\n cursorSmoothCaretAnimation: register(new EditorBooleanOption(23 /* EditorOption.cursorSmoothCaretAnimation */, 'cursorSmoothCaretAnimation', false, { description: nls.localize('cursorSmoothCaretAnimation', \"Controls whether the smooth caret animation should be enabled.\") })),\n cursorStyle: register(new EditorEnumOption(24 /* EditorOption.cursorStyle */, 'cursorStyle', TextEditorCursorStyle.Line, 'line', ['line', 'block', 'underline', 'line-thin', 'block-outline', 'underline-thin'], _cursorStyleFromString, { description: nls.localize('cursorStyle', \"Controls the cursor style.\") })),\n cursorSurroundingLines: register(new EditorIntOption(25 /* EditorOption.cursorSurroundingLines */, 'cursorSurroundingLines', 0, 0, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, { 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 cursorSurroundingLinesStyle: register(new EditorStringEnumOption(26 /* EditorOption.cursorSurroundingLinesStyle */, 'cursorSurroundingLinesStyle', 'default', ['default', 'all'], {\n enumDescriptions: [\n nls.localize('cursorSurroundingLinesStyle.default', \"`cursorSurroundingLines` is enforced only when triggered via the keyboard or API.\"),\n nls.localize('cursorSurroundingLinesStyle.all', \"`cursorSurroundingLines` is enforced always.\")\n ],\n description: nls.localize('cursorSurroundingLinesStyle', \"Controls when `cursorSurroundingLines` should be enforced.\")\n })),\n cursorWidth: register(new EditorIntOption(27 /* EditorOption.cursorWidth */, 'cursorWidth', 0, 0, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, { markdownDescription: nls.localize('cursorWidth', \"Controls the width of the cursor when `#editor.cursorStyle#` is set to `line`.\") })),\n disableLayerHinting: register(new EditorBooleanOption(28 /* EditorOption.disableLayerHinting */, 'disableLayerHinting', false)),\n disableMonospaceOptimizations: register(new EditorBooleanOption(29 /* EditorOption.disableMonospaceOptimizations */, 'disableMonospaceOptimizations', false)),\n domReadOnly: register(new EditorBooleanOption(30 /* EditorOption.domReadOnly */, 'domReadOnly', false)),\n dragAndDrop: register(new EditorBooleanOption(31 /* EditorOption.dragAndDrop */, 'dragAndDrop', true, { description: nls.localize('dragAndDrop', \"Controls whether the editor should allow moving selections via drag and drop.\") })),\n emptySelectionClipboard: register(new EditorEmptySelectionClipboard()),\n dropIntoEditor: register(new EditorDropIntoEditor()),\n experimental: register(new EditorExperimental()),\n extraEditorClassName: register(new EditorStringOption(35 /* EditorOption.extraEditorClassName */, 'extraEditorClassName', '')),\n fastScrollSensitivity: register(new EditorFloatOption(36 /* EditorOption.fastScrollSensitivity */, 'fastScrollSensitivity', 5, x => (x <= 0 ? 5 : x), { markdownDescription: nls.localize('fastScrollSensitivity', \"Scrolling speed multiplier when pressing `Alt`.\") })),\n find: register(new EditorFind()),\n fixedOverflowWidgets: register(new EditorBooleanOption(38 /* EditorOption.fixedOverflowWidgets */, 'fixedOverflowWidgets', false)),\n folding: register(new EditorBooleanOption(39 /* EditorOption.folding */, 'folding', true, { description: nls.localize('folding', \"Controls whether the editor has code folding enabled.\") })),\n foldingStrategy: register(new EditorStringEnumOption(40 /* EditorOption.foldingStrategy */, 'foldingStrategy', 'auto', ['auto', 'indentation'], {\n enumDescriptions: [\n nls.localize('foldingStrategy.auto', \"Use a language-specific folding strategy if available, else the indentation-based one.\"),\n nls.localize('foldingStrategy.indentation', \"Use the indentation-based folding strategy.\"),\n ],\n description: nls.localize('foldingStrategy', \"Controls the strategy for computing folding ranges.\")\n })),\n foldingHighlight: register(new EditorBooleanOption(41 /* EditorOption.foldingHighlight */, 'foldingHighlight', true, { description: nls.localize('foldingHighlight', \"Controls whether the editor should highlight folded ranges.\") })),\n foldingImportsByDefault: register(new EditorBooleanOption(42 /* EditorOption.foldingImportsByDefault */, 'foldingImportsByDefault', false, { description: nls.localize('foldingImportsByDefault', \"Controls whether the editor automatically collapses import ranges.\") })),\n foldingMaximumRegions: register(new EditorIntOption(43 /* EditorOption.foldingMaximumRegions */, 'foldingMaximumRegions', 5000, 10, 65000, // limit must be less than foldingRanges MAX_FOLDING_REGIONS\n { 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 unfoldOnClickAfterEndOfLine: register(new EditorBooleanOption(44 /* EditorOption.unfoldOnClickAfterEndOfLine */, 'unfoldOnClickAfterEndOfLine', false, { description: nls.localize('unfoldOnClickAfterEndOfLine', \"Controls whether clicking on the empty content after a folded line will unfold the line.\") })),\n fontFamily: register(new EditorStringOption(45 /* EditorOption.fontFamily */, 'fontFamily', EDITOR_FONT_DEFAULTS.fontFamily, { description: nls.localize('fontFamily', \"Controls the font family.\") })),\n fontInfo: register(new EditorFontInfo()),\n fontLigatures2: register(new EditorFontLigatures()),\n fontSize: register(new EditorFontSize()),\n fontWeight: register(new EditorFontWeight()),\n formatOnPaste: register(new EditorBooleanOption(50 /* EditorOption.formatOnPaste */, 'formatOnPaste', false, { 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 formatOnType: register(new EditorBooleanOption(51 /* EditorOption.formatOnType */, 'formatOnType', false, { description: nls.localize('formatOnType', \"Controls whether the editor should automatically format the line after typing.\") })),\n glyphMargin: register(new EditorBooleanOption(52 /* EditorOption.glyphMargin */, 'glyphMargin', true, { description: nls.localize('glyphMargin', \"Controls whether the editor should render the vertical glyph margin. Glyph margin is mostly used for debugging.\") })),\n gotoLocation: register(new EditorGoToLocation()),\n hideCursorInOverviewRuler: register(new EditorBooleanOption(54 /* EditorOption.hideCursorInOverviewRuler */, 'hideCursorInOverviewRuler', false, { description: nls.localize('hideCursorInOverviewRuler', \"Controls whether the cursor should be hidden in the overview ruler.\") })),\n hover: register(new EditorHover()),\n inDiffEditor: register(new EditorBooleanOption(56 /* EditorOption.inDiffEditor */, 'inDiffEditor', false)),\n letterSpacing: register(new EditorFloatOption(58 /* EditorOption.letterSpacing */, 'letterSpacing', EDITOR_FONT_DEFAULTS.letterSpacing, x => EditorFloatOption.clamp(x, -5, 20), { description: nls.localize('letterSpacing', \"Controls the letter spacing in pixels.\") })),\n lightbulb: register(new EditorLightbulb()),\n lineDecorationsWidth: register(new SimpleEditorOption(60 /* EditorOption.lineDecorationsWidth */, 'lineDecorationsWidth', 10)),\n lineHeight: register(new EditorLineHeight()),\n lineNumbers: register(new EditorRenderLineNumbersOption()),\n lineNumbersMinChars: register(new EditorIntOption(63 /* EditorOption.lineNumbersMinChars */, 'lineNumbersMinChars', 5, 1, 300)),\n linkedEditing: register(new EditorBooleanOption(64 /* EditorOption.linkedEditing */, 'linkedEditing', false, { 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 links: register(new EditorBooleanOption(65 /* EditorOption.links */, 'links', true, { description: nls.localize('links', \"Controls whether the editor should detect links and make them clickable.\") })),\n matchBrackets: register(new EditorStringEnumOption(66 /* EditorOption.matchBrackets */, 'matchBrackets', 'always', ['always', 'near', 'never'], { description: nls.localize('matchBrackets', \"Highlight matching brackets.\") })),\n minimap: register(new EditorMinimap()),\n mouseStyle: register(new EditorStringEnumOption(68 /* EditorOption.mouseStyle */, 'mouseStyle', 'text', ['text', 'default', 'copy'])),\n mouseWheelScrollSensitivity: register(new EditorFloatOption(69 /* EditorOption.mouseWheelScrollSensitivity */, 'mouseWheelScrollSensitivity', 1, x => (x === 0 ? 1 : x), { markdownDescription: nls.localize('mouseWheelScrollSensitivity', \"A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.\") })),\n mouseWheelZoom: register(new EditorBooleanOption(70 /* EditorOption.mouseWheelZoom */, 'mouseWheelZoom', false, { markdownDescription: nls.localize('mouseWheelZoom', \"Zoom the font of the editor when using mouse wheel and holding `Ctrl`.\") })),\n multiCursorMergeOverlapping: register(new EditorBooleanOption(71 /* EditorOption.multiCursorMergeOverlapping */, 'multiCursorMergeOverlapping', true, { description: nls.localize('multiCursorMergeOverlapping', \"Merge multiple cursors when they are overlapping.\") })),\n multiCursorModifier: register(new EditorEnumOption(72 /* EditorOption.multiCursorModifier */, 'multiCursorModifier', 'altKey', 'alt', ['ctrlCmd', 'alt'], _multiCursorModifierFromString, {\n markdownEnumDescriptions: [\n nls.localize('multiCursorModifier.ctrlCmd', \"Maps to `Control` on Windows and Linux and to `Command` on macOS.\"),\n nls.localize('multiCursorModifier.alt', \"Maps to `Alt` on Windows and Linux and to `Option` on macOS.\")\n ],\n markdownDescription: nls.localize({\n key: 'multiCursorModifier',\n comment: [\n '- `ctrlCmd` refers to a value the setting can take and should not be localized.',\n '- `Control` and `Command` refer to the modifier keys Ctrl or Cmd on the keyboard and can be localized.'\n ]\n }, \"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](https://code.visualstudio.com/docs/editor/codebasics#_multicursor-modifier).\")\n })),\n multiCursorPaste: register(new EditorStringEnumOption(73 /* EditorOption.multiCursorPaste */, 'multiCursorPaste', 'spread', ['spread', 'full'], {\n markdownEnumDescriptions: [\n nls.localize('multiCursorPaste.spread', \"Each cursor pastes a single line of the text.\"),\n nls.localize('multiCursorPaste.full', \"Each cursor pastes the full text.\")\n ],\n markdownDescription: nls.localize('multiCursorPaste', \"Controls pasting when the line count of the pasted text matches the cursor count.\")\n })),\n occurrencesHighlight: register(new EditorBooleanOption(74 /* EditorOption.occurrencesHighlight */, 'occurrencesHighlight', true, { description: nls.localize('occurrencesHighlight', \"Controls whether the editor should highlight semantic symbol occurrences.\") })),\n overviewRulerBorder: register(new EditorBooleanOption(75 /* EditorOption.overviewRulerBorder */, 'overviewRulerBorder', true, { description: nls.localize('overviewRulerBorder', \"Controls whether a border should be drawn around the overview ruler.\") })),\n overviewRulerLanes: register(new EditorIntOption(76 /* EditorOption.overviewRulerLanes */, 'overviewRulerLanes', 3, 0, 3)),\n padding: register(new EditorPadding()),\n parameterHints: register(new EditorParameterHints()),\n peekWidgetDefaultFocus: register(new EditorStringEnumOption(79 /* EditorOption.peekWidgetDefaultFocus */, 'peekWidgetDefaultFocus', 'tree', ['tree', 'editor'], {\n enumDescriptions: [\n nls.localize('peekWidgetDefaultFocus.tree', \"Focus the tree when opening peek\"),\n nls.localize('peekWidgetDefaultFocus.editor', \"Focus the editor when opening peek\")\n ],\n description: nls.localize('peekWidgetDefaultFocus', \"Controls whether to focus the inline editor or the tree in the peek widget.\")\n })),\n definitionLinkOpensInPeek: register(new EditorBooleanOption(80 /* EditorOption.definitionLinkOpensInPeek */, 'definitionLinkOpensInPeek', false, { description: nls.localize('definitionLinkOpensInPeek', \"Controls whether the Go to Definition mouse gesture always opens the peek widget.\") })),\n quickSuggestions: register(new EditorQuickSuggestions()),\n quickSuggestionsDelay: register(new EditorIntOption(82 /* EditorOption.quickSuggestionsDelay */, 'quickSuggestionsDelay', 10, 0, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, { description: nls.localize('quickSuggestionsDelay', \"Controls the delay in milliseconds after which quick suggestions will show up.\") })),\n readOnly: register(new EditorBooleanOption(83 /* EditorOption.readOnly */, 'readOnly', false)),\n renameOnType: register(new EditorBooleanOption(84 /* EditorOption.renameOnType */, 'renameOnType', false, { description: nls.localize('renameOnType', \"Controls whether the editor auto renames on type.\"), markdownDeprecationMessage: nls.localize('renameOnTypeDeprecate', \"Deprecated, use `editor.linkedEditing` instead.\") })),\n renderControlCharacters: register(new EditorBooleanOption(85 /* EditorOption.renderControlCharacters */, 'renderControlCharacters', true, { description: nls.localize('renderControlCharacters', \"Controls whether the editor should render control characters.\"), restricted: true })),\n renderFinalNewline: register(new EditorBooleanOption(86 /* EditorOption.renderFinalNewline */, 'renderFinalNewline', true, { description: nls.localize('renderFinalNewline', \"Render last line number when the file ends with a newline.\") })),\n renderLineHighlight: register(new EditorStringEnumOption(87 /* EditorOption.renderLineHighlight */, 'renderLineHighlight', 'line', ['none', 'gutter', 'line', 'all'], {\n enumDescriptions: [\n '',\n '',\n '',\n nls.localize('renderLineHighlight.all', \"Highlights both the gutter and the current line.\"),\n ],\n description: nls.localize('renderLineHighlight', \"Controls how the editor should render the current line highlight.\")\n })),\n renderLineHighlightOnlyWhenFocus: register(new EditorBooleanOption(88 /* EditorOption.renderLineHighlightOnlyWhenFocus */, 'renderLineHighlightOnlyWhenFocus', false, { description: nls.localize('renderLineHighlightOnlyWhenFocus', \"Controls if the editor should render the current line highlight only when the editor is focused.\") })),\n renderValidationDecorations: register(new EditorStringEnumOption(89 /* EditorOption.renderValidationDecorations */, 'renderValidationDecorations', 'editable', ['editable', 'on', 'off'])),\n renderWhitespace: register(new EditorStringEnumOption(90 /* EditorOption.renderWhitespace */, 'renderWhitespace', 'selection', ['none', 'boundary', 'selection', 'trailing', 'all'], {\n enumDescriptions: [\n '',\n nls.localize('renderWhitespace.boundary', \"Render whitespace characters except for single spaces between words.\"),\n nls.localize('renderWhitespace.selection', \"Render whitespace characters only on selected text.\"),\n nls.localize('renderWhitespace.trailing', \"Render only trailing whitespace characters.\"),\n ''\n ],\n description: nls.localize('renderWhitespace', \"Controls how the editor should render whitespace characters.\")\n })),\n revealHorizontalRightPadding: register(new EditorIntOption(91 /* EditorOption.revealHorizontalRightPadding */, 'revealHorizontalRightPadding', 30, 0, 1000)),\n roundedSelection: register(new EditorBooleanOption(92 /* EditorOption.roundedSelection */, 'roundedSelection', true, { description: nls.localize('roundedSelection', \"Controls whether selections should have rounded corners.\") })),\n rulers: register(new EditorRulers()),\n scrollbar: register(new EditorScrollbar()),\n scrollBeyondLastColumn: register(new EditorIntOption(95 /* EditorOption.scrollBeyondLastColumn */, 'scrollBeyondLastColumn', 4, 0, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, { description: nls.localize('scrollBeyondLastColumn', \"Controls the number of extra characters beyond which the editor will scroll horizontally.\") })),\n scrollBeyondLastLine: register(new EditorBooleanOption(96 /* EditorOption.scrollBeyondLastLine */, 'scrollBeyondLastLine', true, { description: nls.localize('scrollBeyondLastLine', \"Controls whether the editor will scroll beyond the last line.\") })),\n scrollPredominantAxis: register(new EditorBooleanOption(97 /* EditorOption.scrollPredominantAxis */, 'scrollPredominantAxis', true, { 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 selectionClipboard: register(new EditorBooleanOption(98 /* EditorOption.selectionClipboard */, 'selectionClipboard', true, {\n description: nls.localize('selectionClipboard', \"Controls whether the Linux primary clipboard should be supported.\"),\n included: platform.isLinux\n })),\n selectionHighlight: register(new EditorBooleanOption(99 /* EditorOption.selectionHighlight */, 'selectionHighlight', true, { description: nls.localize('selectionHighlight', \"Controls whether the editor should highlight matches similar to the selection.\") })),\n selectOnLineNumbers: register(new EditorBooleanOption(100 /* EditorOption.selectOnLineNumbers */, 'selectOnLineNumbers', true)),\n showFoldingControls: register(new EditorStringEnumOption(101 /* EditorOption.showFoldingControls */, 'showFoldingControls', 'mouseover', ['always', 'never', 'mouseover'], {\n enumDescriptions: [\n nls.localize('showFoldingControls.always', \"Always show the folding controls.\"),\n nls.localize('showFoldingControls.never', \"Never show the folding controls and reduce the gutter size.\"),\n nls.localize('showFoldingControls.mouseover', \"Only show the folding controls when the mouse is over the gutter.\"),\n ],\n description: nls.localize('showFoldingControls', \"Controls when the folding controls on the gutter are shown.\")\n })),\n showUnused: register(new EditorBooleanOption(102 /* EditorOption.showUnused */, 'showUnused', true, { description: nls.localize('showUnused', \"Controls fading out of unused code.\") })),\n showDeprecated: register(new EditorBooleanOption(128 /* EditorOption.showDeprecated */, 'showDeprecated', true, { description: nls.localize('showDeprecated', \"Controls strikethrough deprecated variables.\") })),\n inlayHints: register(new EditorInlayHints()),\n snippetSuggestions: register(new EditorStringEnumOption(103 /* EditorOption.snippetSuggestions */, 'snippetSuggestions', 'inline', ['top', 'bottom', 'inline', 'none'], {\n enumDescriptions: [\n nls.localize('snippetSuggestions.top', \"Show snippet suggestions on top of other suggestions.\"),\n nls.localize('snippetSuggestions.bottom', \"Show snippet suggestions below other suggestions.\"),\n nls.localize('snippetSuggestions.inline', \"Show snippets suggestions with other suggestions.\"),\n nls.localize('snippetSuggestions.none', \"Do not show snippet suggestions.\"),\n ],\n description: nls.localize('snippetSuggestions', \"Controls whether snippets are shown with other suggestions and how they are sorted.\")\n })),\n smartSelect: register(new SmartSelect()),\n smoothScrolling: register(new EditorBooleanOption(105 /* EditorOption.smoothScrolling */, 'smoothScrolling', false, { description: nls.localize('smoothScrolling', \"Controls whether the editor will scroll using an animation.\") })),\n stopRenderingLineAfter: register(new EditorIntOption(107 /* EditorOption.stopRenderingLineAfter */, 'stopRenderingLineAfter', 10000, -1, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */)),\n suggest: register(new EditorSuggest()),\n inlineSuggest: register(new InlineEditorSuggest()),\n suggestFontSize: register(new EditorIntOption(109 /* EditorOption.suggestFontSize */, 'suggestFontSize', 0, 0, 1000, { markdownDescription: nls.localize('suggestFontSize', \"Font size for the suggest widget. When set to {0}, the value of {1} is used.\", '`0`', '`#editor.fontSize#`') })),\n suggestLineHeight: register(new EditorIntOption(110 /* EditorOption.suggestLineHeight */, 'suggestLineHeight', 0, 0, 1000, { markdownDescription: nls.localize('suggestLineHeight', \"Line height for the suggest widget. When set to {0}, the value of {1} is used. The minimum value is 8.\", '`0`', '`#editor.lineHeight#`') })),\n suggestOnTriggerCharacters: register(new EditorBooleanOption(111 /* EditorOption.suggestOnTriggerCharacters */, 'suggestOnTriggerCharacters', true, { description: nls.localize('suggestOnTriggerCharacters', \"Controls whether suggestions should automatically show up when typing trigger characters.\") })),\n suggestSelection: register(new EditorStringEnumOption(112 /* EditorOption.suggestSelection */, 'suggestSelection', 'first', ['first', 'recentlyUsed', 'recentlyUsedByPrefix'], {\n markdownEnumDescriptions: [\n nls.localize('suggestSelection.first', \"Always select the first suggestion.\"),\n nls.localize('suggestSelection.recentlyUsed', \"Select recent suggestions unless further typing selects one, e.g. `console.| -> console.log` because `log` has been completed recently.\"),\n nls.localize('suggestSelection.recentlyUsedByPrefix', \"Select suggestions based on previous prefixes that have completed those suggestions, e.g. `co -> console` and `con -> const`.\"),\n ],\n description: nls.localize('suggestSelection', \"Controls how suggestions are pre-selected when showing the suggest list.\")\n })),\n tabCompletion: register(new EditorStringEnumOption(113 /* EditorOption.tabCompletion */, 'tabCompletion', 'off', ['on', 'off', 'onlySnippets'], {\n enumDescriptions: [\n nls.localize('tabCompletion.on', \"Tab complete will insert the best matching suggestion when pressing tab.\"),\n nls.localize('tabCompletion.off', \"Disable tab completions.\"),\n nls.localize('tabCompletion.onlySnippets', \"Tab complete snippets when their prefix match. Works best when 'quickSuggestions' aren't enabled.\"),\n ],\n description: nls.localize('tabCompletion', \"Enables tab completions.\")\n })),\n tabIndex: register(new EditorIntOption(114 /* EditorOption.tabIndex */, 'tabIndex', 0, -1, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */)),\n unicodeHighlight: register(new UnicodeHighlight()),\n unusualLineTerminators: register(new EditorStringEnumOption(116 /* EditorOption.unusualLineTerminators */, 'unusualLineTerminators', 'prompt', ['auto', 'off', 'prompt'], {\n enumDescriptions: [\n nls.localize('unusualLineTerminators.auto', \"Unusual line terminators are automatically removed.\"),\n nls.localize('unusualLineTerminators.off', \"Unusual line terminators are ignored.\"),\n nls.localize('unusualLineTerminators.prompt', \"Unusual line terminators prompt to be removed.\"),\n ],\n description: nls.localize('unusualLineTerminators', \"Remove unusual line terminators that might cause problems.\")\n })),\n useShadowDOM: register(new EditorBooleanOption(117 /* EditorOption.useShadowDOM */, 'useShadowDOM', true)),\n useTabStops: register(new EditorBooleanOption(118 /* EditorOption.useTabStops */, 'useTabStops', true, { description: nls.localize('useTabStops', \"Inserting and deleting whitespace follows tab stops.\") })),\n wordSeparators: register(new EditorStringOption(119 /* EditorOption.wordSeparators */, 'wordSeparators', USUAL_WORD_SEPARATORS, { description: nls.localize('wordSeparators', \"Characters that will be used as word separators when doing word related navigations or operations.\") })),\n wordWrap: register(new EditorStringEnumOption(120 /* EditorOption.wordWrap */, 'wordWrap', 'off', ['off', 'on', 'wordWrapColumn', 'bounded'], {\n markdownEnumDescriptions: [\n nls.localize('wordWrap.off', \"Lines will never wrap.\"),\n nls.localize('wordWrap.on', \"Lines will wrap at the viewport width.\"),\n nls.localize({\n key: 'wordWrap.wordWrapColumn',\n comment: [\n '- `editor.wordWrapColumn` refers to a different setting and should not be localized.'\n ]\n }, \"Lines will wrap at `#editor.wordWrapColumn#`.\"),\n nls.localize({\n key: 'wordWrap.bounded',\n comment: [\n '- viewport means the edge of the visible window size.',\n '- `editor.wordWrapColumn` refers to a different setting and should not be localized.'\n ]\n }, \"Lines will wrap at the minimum of viewport and `#editor.wordWrapColumn#`.\"),\n ],\n description: nls.localize({\n key: 'wordWrap',\n comment: [\n '- \\'off\\', \\'on\\', \\'wordWrapColumn\\' and \\'bounded\\' refer to values the setting can take and should not be localized.',\n '- `editor.wordWrapColumn` refers to a different setting and should not be localized.'\n ]\n }, \"Controls how lines should wrap.\")\n })),\n wordWrapBreakAfterCharacters: register(new EditorStringOption(121 /* EditorOption.wordWrapBreakAfterCharacters */, 'wordWrapBreakAfterCharacters', \n // allow-any-unicode-next-line\n ' \\t})]?|/&.,;¢°′″‰℃、。。、¢,.:;?!%・・ゝゞヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻ァィゥェォャュョッー”〉》」』】〕)]}」')),\n wordWrapBreakBeforeCharacters: register(new EditorStringOption(122 /* EditorOption.wordWrapBreakBeforeCharacters */, 'wordWrapBreakBeforeCharacters', \n // allow-any-unicode-next-line\n '([{‘“〈《「『【〔([{「£¥$£¥++')),\n wordWrapColumn: register(new EditorIntOption(123 /* EditorOption.wordWrapColumn */, 'wordWrapColumn', 80, 1, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, {\n markdownDescription: nls.localize({\n key: 'wordWrapColumn',\n comment: [\n '- `editor.wordWrap` refers to a different setting and should not be localized.',\n '- \\'wordWrapColumn\\' and \\'bounded\\' refer to values the different setting can take and should not be localized.'\n ]\n }, \"Controls the wrapping column of the editor when `#editor.wordWrap#` is `wordWrapColumn` or `bounded`.\")\n })),\n wordWrapOverride1: register(new EditorStringEnumOption(124 /* EditorOption.wordWrapOverride1 */, 'wordWrapOverride1', 'inherit', ['off', 'on', 'inherit'])),\n wordWrapOverride2: register(new EditorStringEnumOption(125 /* EditorOption.wordWrapOverride2 */, 'wordWrapOverride2', 'inherit', ['off', 'on', 'inherit'])),\n wrappingIndent: register(new EditorEnumOption(126 /* EditorOption.wrappingIndent */, 'wrappingIndent', 1 /* WrappingIndent.Same */, 'same', ['none', 'same', 'indent', 'deepIndent'], _wrappingIndentFromString, {\n enumDescriptions: [\n nls.localize('wrappingIndent.none', \"No indentation. Wrapped lines begin at column 1.\"),\n nls.localize('wrappingIndent.same', \"Wrapped lines get the same indentation as the parent.\"),\n nls.localize('wrappingIndent.indent', \"Wrapped lines get +1 indentation toward the parent.\"),\n nls.localize('wrappingIndent.deepIndent', \"Wrapped lines get +2 indentation toward the parent.\"),\n ],\n description: nls.localize('wrappingIndent', \"Controls the indentation of wrapped lines.\"),\n })),\n wrappingStrategy: register(new EditorStringEnumOption(127 /* EditorOption.wrappingStrategy */, 'wrappingStrategy', 'simple', ['simple', 'advanced'], {\n enumDescriptions: [\n nls.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 nls.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 ],\n description: nls.localize('wrappingStrategy', \"Controls the algorithm that computes wrapping points.\")\n })),\n // Leave these at the end (because they have dependencies!)\n editorClassName: register(new EditorClassName()),\n pixelRatio: register(new EditorPixelRatio()),\n tabFocusMode: register(new EditorTabFocusMode()),\n layoutInfo: register(new EditorLayoutInfoComputer()),\n wrappingInfo: register(new EditorWrappingInfoComputer())\n};\n","/*---------------------------------------------------------------------------------------------\n * 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 { Emitter } from '../../../base/common/event.js';\nexport const EditorZoom = new class {\n constructor() {\n this._zoomLevel = 0;\n this._onDidChangeZoomLevel = new Emitter();\n this.onDidChangeZoomLevel = this._onDidChangeZoomLevel.event;\n }\n getZoomLevel() {\n return this._zoomLevel;\n }\n setZoomLevel(zoomLevel) {\n zoomLevel = Math.min(Math.max(-5, zoomLevel), 20);\n if (this._zoomLevel === zoomLevel) {\n return;\n }\n this._zoomLevel = zoomLevel;\n this._onDidChangeZoomLevel.fire(this._zoomLevel);\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 *--------------------------------------------------------------------------------------------*/\nimport * as platform from '../../../base/common/platform.js';\nimport { EDITOR_FONT_DEFAULTS } from './editorOptions.js';\nimport { EditorZoom } from './editorZoom.js';\n/**\n * Determined from empirical observations.\n * @internal\n */\nconst GOLDEN_LINE_HEIGHT_RATIO = platform.isMacintosh ? 1.5 : 1.35;\n/**\n * @internal\n */\nconst MINIMUM_LINE_HEIGHT = 8;\nexport class BareFontInfo {\n /**\n * @internal\n */\n constructor(opts) {\n this._bareFontInfoBrand = undefined;\n this.pixelRatio = opts.pixelRatio;\n this.fontFamily = String(opts.fontFamily);\n this.fontWeight = String(opts.fontWeight);\n this.fontSize = opts.fontSize;\n this.fontFeatureSettings = opts.fontFeatureSettings;\n this.lineHeight = opts.lineHeight | 0;\n this.letterSpacing = opts.letterSpacing;\n }\n /**\n * @internal\n */\n static createFromValidatedSettings(options, pixelRatio, ignoreEditorZoom) {\n const fontFamily = options.get(45 /* EditorOption.fontFamily */);\n const fontWeight = options.get(49 /* EditorOption.fontWeight */);\n const fontSize = options.get(48 /* EditorOption.fontSize */);\n const fontFeatureSettings = options.get(47 /* EditorOption.fontLigatures */);\n const lineHeight = options.get(61 /* EditorOption.lineHeight */);\n const letterSpacing = options.get(58 /* EditorOption.letterSpacing */);\n return BareFontInfo._create(fontFamily, fontWeight, fontSize, fontFeatureSettings, lineHeight, letterSpacing, pixelRatio, ignoreEditorZoom);\n }\n /**\n * @internal\n */\n static _create(fontFamily, fontWeight, fontSize, fontFeatureSettings, lineHeight, letterSpacing, pixelRatio, ignoreEditorZoom) {\n if (lineHeight === 0) {\n lineHeight = GOLDEN_LINE_HEIGHT_RATIO * fontSize;\n }\n else if (lineHeight < MINIMUM_LINE_HEIGHT) {\n // Values too small to be line heights in pixels are in ems.\n lineHeight = lineHeight * fontSize;\n }\n // Enforce integer, minimum constraints\n lineHeight = Math.round(lineHeight);\n if (lineHeight < MINIMUM_LINE_HEIGHT) {\n lineHeight = MINIMUM_LINE_HEIGHT;\n }\n const editorZoomLevelMultiplier = 1 + (ignoreEditorZoom ? 0 : EditorZoom.getZoomLevel() * 0.1);\n fontSize *= editorZoomLevelMultiplier;\n lineHeight *= editorZoomLevelMultiplier;\n return new BareFontInfo({\n pixelRatio: pixelRatio,\n fontFamily: fontFamily,\n fontWeight: fontWeight,\n fontSize: fontSize,\n fontFeatureSettings: fontFeatureSettings,\n lineHeight: lineHeight,\n letterSpacing: letterSpacing\n });\n }\n /**\n * @internal\n */\n getId() {\n return `${this.pixelRatio}-${this.fontFamily}-${this.fontWeight}-${this.fontSize}-${this.fontFeatureSettings}-${this.lineHeight}-${this.letterSpacing}`;\n }\n /**\n * @internal\n */\n getMassagedFontFamily() {\n const fallbackFontFamily = EDITOR_FONT_DEFAULTS.fontFamily;\n const fontFamily = BareFontInfo._wrapInQuotes(this.fontFamily);\n if (fallbackFontFamily && this.fontFamily !== fallbackFontFamily) {\n return `${fontFamily}, ${fallbackFontFamily}`;\n }\n return fontFamily;\n }\n static _wrapInQuotes(fontFamily) {\n if (/[,\"']/.test(fontFamily)) {\n // Looks like the font family might be already escaped\n return fontFamily;\n }\n if (/[+ ]/.test(fontFamily)) {\n // Wrap a font family using + or
with quotes\n return `\"${fontFamily}\"`;\n }\n return fontFamily;\n }\n}\n// change this whenever `FontInfo` members are changed\nexport const SERIALIZED_FONT_INFO_VERSION = 1;\nexport class FontInfo extends BareFontInfo {\n /**\n * @internal\n */\n constructor(opts, isTrusted) {\n super(opts);\n this._editorStylingBrand = undefined;\n this.version = SERIALIZED_FONT_INFO_VERSION;\n this.isTrusted = isTrusted;\n this.isMonospace = opts.isMonospace;\n this.typicalHalfwidthCharacterWidth = opts.typicalHalfwidthCharacterWidth;\n this.typicalFullwidthCharacterWidth = opts.typicalFullwidthCharacterWidth;\n this.canUseHalfwidthRightwardsArrow = opts.canUseHalfwidthRightwardsArrow;\n this.spaceWidth = opts.spaceWidth;\n this.middotWidth = opts.middotWidth;\n this.wsmiddotWidth = opts.wsmiddotWidth;\n this.maxDigitWidth = opts.maxDigitWidth;\n }\n /**\n * @internal\n */\n equals(other) {\n return (this.fontFamily === other.fontFamily\n && this.fontWeight === other.fontWeight\n && this.fontSize === other.fontSize\n && this.fontFeatureSettings === other.fontFeatureSettings\n && this.lineHeight === other.lineHeight\n && this.letterSpacing === other.letterSpacing\n && this.typicalHalfwidthCharacterWidth === other.typicalHalfwidthCharacterWidth\n && this.typicalFullwidthCharacterWidth === other.typicalFullwidthCharacterWidth\n && this.canUseHalfwidthRightwardsArrow === other.canUseHalfwidthRightwardsArrow\n && this.spaceWidth === other.spaceWidth\n && this.middotWidth === other.middotWidth\n && this.wsmiddotWidth === other.wsmiddotWidth\n && this.maxDigitWidth === other.maxDigitWidth);\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 *--------------------------------------------------------------------------------------------*/\nimport { toUint8 } from '../../../base/common/uint.js';\n/**\n * A fast character classifier that uses a compact array for ASCII values.\n */\nexport class CharacterClassifier {\n constructor(_defaultValue) {\n const defaultValue = toUint8(_defaultValue);\n this._defaultValue = defaultValue;\n this._asciiMap = CharacterClassifier._createAsciiMap(defaultValue);\n this._map = new Map();\n }\n static _createAsciiMap(defaultValue) {\n const asciiMap = new Uint8Array(256);\n for (let i = 0; i < 256; i++) {\n asciiMap[i] = defaultValue;\n }\n return asciiMap;\n }\n set(charCode, _value) {\n const value = toUint8(_value);\n if (charCode >= 0 && charCode < 256) {\n this._asciiMap[charCode] = value;\n }\n else {\n this._map.set(charCode, value);\n }\n }\n get(charCode) {\n if (charCode >= 0 && charCode < 256) {\n return this._asciiMap[charCode];\n }\n else {\n return (this._map.get(charCode) || this._defaultValue);\n }\n }\n}\nexport class CharacterSet {\n constructor() {\n this._actual = new CharacterClassifier(0 /* Boolean.False */);\n }\n add(charCode) {\n this._actual.set(charCode, 1 /* Boolean.True */);\n }\n has(charCode) {\n return (this._actual.get(charCode) === 1 /* Boolean.True */);\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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../base/common/strings.js';\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 static _nextVisibleColumn(codePoint, visibleColumn, tabSize) {\n if (codePoint === 9 /* CharCode.Tab */) {\n return CursorColumns.nextRenderTabStop(visibleColumn, tabSize);\n }\n if (strings.isFullWidthCharacter(codePoint) || strings.isEmojiImprecise(codePoint)) {\n return visibleColumn + 2;\n }\n return visibleColumn + 1;\n }\n /**\n * Returns a visible column from a column.\n * @see {@link CursorColumns}\n */\n static visibleColumnFromColumn(lineContent, column, tabSize) {\n const textLen = Math.min(column - 1, lineContent.length);\n const text = lineContent.substring(0, textLen);\n const iterator = new strings.GraphemeIterator(text);\n let result = 0;\n while (!iterator.eol()) {\n const codePoint = strings.getNextCodePoint(text, textLen, iterator.offset);\n iterator.nextGraphemeLength();\n result = this._nextVisibleColumn(codePoint, result, tabSize);\n }\n return result;\n }\n /**\n * Returns a column from a visible column.\n * @see {@link CursorColumns}\n */\n static columnFromVisibleColumn(lineContent, visibleColumn, tabSize) {\n if (visibleColumn <= 0) {\n return 1;\n }\n const lineContentLength = lineContent.length;\n const iterator = new strings.GraphemeIterator(lineContent);\n let beforeVisibleColumn = 0;\n let beforeColumn = 1;\n while (!iterator.eol()) {\n const codePoint = strings.getNextCodePoint(lineContent, lineContentLength, iterator.offset);\n iterator.nextGraphemeLength();\n const afterVisibleColumn = this._nextVisibleColumn(codePoint, beforeVisibleColumn, tabSize);\n const afterColumn = iterator.offset + 1;\n if (afterVisibleColumn >= visibleColumn) {\n const beforeDelta = visibleColumn - beforeVisibleColumn;\n const afterDelta = afterVisibleColumn - visibleColumn;\n if (afterDelta < beforeDelta) {\n return afterColumn;\n }\n else {\n return beforeColumn;\n }\n }\n beforeVisibleColumn = afterVisibleColumn;\n beforeColumn = afterColumn;\n }\n // walked the entire string\n return lineContentLength + 1;\n }\n /**\n * ATTENTION: This works with 0-based columns (as oposed to the regular 1-based columns)\n * @see {@link CursorColumns}\n */\n static nextRenderTabStop(visibleColumn, tabSize) {\n return visibleColumn + tabSize - visibleColumn % tabSize;\n }\n /**\n * ATTENTION: This works with 0-based columns (as oposed to the regular 1-based columns)\n * @see {@link CursorColumns}\n */\n static nextIndentTabStop(visibleColumn, indentSize) {\n return visibleColumn + indentSize - visibleColumn % indentSize;\n }\n /**\n * ATTENTION: This works with 0-based columns (as opposed to the regular 1-based columns)\n * @see {@link CursorColumns}\n */\n static prevRenderTabStop(column, tabSize) {\n return Math.max(0, column - 1 - (column - 1) % tabSize);\n }\n /**\n * ATTENTION: This works with 0-based columns (as opposed to the regular 1-based columns)\n * @see {@link CursorColumns}\n */\n static prevIndentTabStop(column, indentSize) {\n return Math.max(0, column - 1 - (column - 1) % indentSize);\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 *--------------------------------------------------------------------------------------------*/\nimport { Range } from './range.js';\nexport class EditOperation {\n static insert(position, text) {\n return {\n range: new Range(position.lineNumber, position.column, position.lineNumber, position.column),\n text: text,\n forceMoveMarkers: true\n };\n }\n static delete(range) {\n return {\n range: range,\n text: null\n };\n }\n static replace(range, text) {\n return {\n range: range,\n text: text\n };\n }\n static replaceMove(range, text) {\n return {\n range: range,\n text: text,\n forceMoveMarkers: true\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 *--------------------------------------------------------------------------------------------*/\nimport * as nls from '../../../nls.js';\nimport { Color, RGBA } from '../../../base/common/color.js';\nimport { activeContrastBorder, editorBackground, editorForeground, registerColor, editorWarningForeground, editorInfoForeground, editorWarningBorder, editorInfoBorder, contrastBorder, editorFindMatchHighlight } from '../../../platform/theme/common/colorRegistry.js';\nimport { registerThemingParticipant } from '../../../platform/theme/common/themeService.js';\nimport { isHighContrast } from '../../../platform/theme/common/theme.js';\n/**\n * Definition of the editor colors\n */\nexport const editorLineHighlight = registerColor('editor.lineHighlightBackground', { dark: null, light: null, hcDark: null, hcLight: null }, nls.localize('lineHighlight', 'Background color for the highlight of line at the cursor position.'));\nexport const editorLineHighlightBorder = registerColor('editor.lineHighlightBorder', { dark: '#282828', light: '#eeeeee', hcDark: '#f38518', hcLight: contrastBorder }, nls.localize('lineHighlightBorderBox', 'Background color for the border around the line at the cursor position.'));\nexport const editorRangeHighlight = registerColor('editor.rangeHighlightBackground', { dark: '#ffffff0b', light: '#fdff0033', hcDark: null, hcLight: null }, nls.localize('rangeHighlight', 'Background color of highlighted ranges, like by quick open and find features. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const editorRangeHighlightBorder = registerColor('editor.rangeHighlightBorder', { dark: null, light: null, hcDark: activeContrastBorder, hcLight: activeContrastBorder }, nls.localize('rangeHighlightBorder', 'Background color of the border around highlighted ranges.'), true);\nexport const editorSymbolHighlight = registerColor('editor.symbolHighlightBackground', { dark: editorFindMatchHighlight, light: editorFindMatchHighlight, hcDark: null, hcLight: null }, nls.localize('symbolHighlight', 'Background color of highlighted symbol, like for go to definition or go next/previous symbol. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const editorSymbolHighlightBorder = registerColor('editor.symbolHighlightBorder', { dark: null, light: null, hcDark: activeContrastBorder, hcLight: activeContrastBorder }, nls.localize('symbolHighlightBorder', 'Background color of the border around highlighted symbols.'), true);\nexport const editorCursorForeground = registerColor('editorCursor.foreground', { dark: '#AEAFAD', light: Color.black, hcDark: Color.white, hcLight: '#0F4A85' }, nls.localize('caret', 'Color of the editor cursor.'));\nexport const editorCursorBackground = registerColor('editorCursor.background', null, nls.localize('editorCursorBackground', 'The background color of the editor cursor. Allows customizing the color of a character overlapped by a block cursor.'));\nexport const editorWhitespaces = registerColor('editorWhitespace.foreground', { dark: '#e3e4e229', light: '#33333333', hcDark: '#e3e4e229', hcLight: '#CCCCCC' }, nls.localize('editorWhitespaces', 'Color of whitespace characters in the editor.'));\nexport const editorIndentGuides = registerColor('editorIndentGuide.background', { dark: editorWhitespaces, light: editorWhitespaces, hcDark: editorWhitespaces, hcLight: editorWhitespaces }, nls.localize('editorIndentGuides', 'Color of the editor indentation guides.'));\nexport const editorActiveIndentGuides = registerColor('editorIndentGuide.activeBackground', { dark: editorWhitespaces, light: editorWhitespaces, hcDark: editorWhitespaces, hcLight: editorWhitespaces }, nls.localize('editorActiveIndentGuide', 'Color of the active editor indentation guides.'));\nexport const editorLineNumbers = registerColor('editorLineNumber.foreground', { dark: '#858585', light: '#237893', hcDark: Color.white, hcLight: '#292929' }, nls.localize('editorLineNumbers', 'Color of editor line numbers.'));\nconst deprecatedEditorActiveLineNumber = registerColor('editorActiveLineNumber.foreground', { dark: '#c6c6c6', light: '#0B216F', hcDark: activeContrastBorder, hcLight: activeContrastBorder }, nls.localize('editorActiveLineNumber', 'Color of editor active line number'), false, nls.localize('deprecatedEditorActiveLineNumber', 'Id is deprecated. Use \\'editorLineNumber.activeForeground\\' instead.'));\nexport const editorActiveLineNumber = registerColor('editorLineNumber.activeForeground', { dark: deprecatedEditorActiveLineNumber, light: deprecatedEditorActiveLineNumber, hcDark: deprecatedEditorActiveLineNumber, hcLight: deprecatedEditorActiveLineNumber }, nls.localize('editorActiveLineNumber', 'Color of editor active line number'));\nexport const editorRuler = registerColor('editorRuler.foreground', { dark: '#5A5A5A', light: Color.lightgrey, hcDark: Color.white, hcLight: '#292929' }, nls.localize('editorRuler', 'Color of the editor rulers.'));\nexport const editorCodeLensForeground = registerColor('editorCodeLens.foreground', { dark: '#999999', light: '#919191', hcDark: '#999999', hcLight: '#292929' }, nls.localize('editorCodeLensForeground', 'Foreground color of editor CodeLens'));\nexport const editorBracketMatchBackground = registerColor('editorBracketMatch.background', { dark: '#0064001a', light: '#0064001a', hcDark: '#0064001a', hcLight: '#0000' }, nls.localize('editorBracketMatchBackground', 'Background color behind matching brackets'));\nexport const editorBracketMatchBorder = registerColor('editorBracketMatch.border', { dark: '#888', light: '#B9B9B9', hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('editorBracketMatchBorder', 'Color for matching brackets boxes'));\nexport const editorOverviewRulerBorder = registerColor('editorOverviewRuler.border', { dark: '#7f7f7f4d', light: '#7f7f7f4d', hcDark: '#7f7f7f4d', hcLight: '#666666' }, nls.localize('editorOverviewRulerBorder', 'Color of the overview ruler border.'));\nexport const editorOverviewRulerBackground = registerColor('editorOverviewRuler.background', null, nls.localize('editorOverviewRulerBackground', 'Background color of the editor overview ruler. Only used when the minimap is enabled and placed on the right side of the editor.'));\nexport const editorGutter = registerColor('editorGutter.background', { dark: editorBackground, light: editorBackground, hcDark: editorBackground, hcLight: editorBackground }, nls.localize('editorGutter', 'Background color of the editor gutter. The gutter contains the glyph margins and the line numbers.'));\nexport const editorUnnecessaryCodeBorder = registerColor('editorUnnecessaryCode.border', { dark: null, light: null, hcDark: Color.fromHex('#fff').transparent(0.8), hcLight: contrastBorder }, nls.localize('unnecessaryCodeBorder', 'Border color of unnecessary (unused) source code in the editor.'));\nexport const editorUnnecessaryCodeOpacity = registerColor('editorUnnecessaryCode.opacity', { dark: Color.fromHex('#000a'), light: Color.fromHex('#0007'), hcDark: null, hcLight: null }, nls.localize('unnecessaryCodeOpacity', 'Opacity of unnecessary (unused) source code in the editor. For example, \"#000000c0\" will render the code with 75% opacity. For high contrast themes, use the \\'editorUnnecessaryCode.border\\' theme color to underline unnecessary code instead of fading it out.'));\nexport const ghostTextBorder = registerColor('editorGhostText.border', { dark: null, light: null, hcDark: Color.fromHex('#fff').transparent(0.8), hcLight: Color.fromHex('#292929').transparent(0.8) }, nls.localize('editorGhostTextBorder', 'Border color of ghost text in the editor.'));\nexport const ghostTextForeground = registerColor('editorGhostText.foreground', { dark: Color.fromHex('#ffffff56'), light: Color.fromHex('#0007'), hcDark: null, hcLight: null }, nls.localize('editorGhostTextForeground', 'Foreground color of the ghost text in the editor.'));\nexport const ghostTextBackground = registerColor('editorGhostText.background', { dark: null, light: null, hcDark: null, hcLight: null }, nls.localize('editorGhostTextBackground', 'Background color of the ghost text in the editor.'));\nconst rulerRangeDefault = new Color(new RGBA(0, 122, 204, 0.6));\nexport const overviewRulerRangeHighlight = registerColor('editorOverviewRuler.rangeHighlightForeground', { dark: rulerRangeDefault, light: rulerRangeDefault, hcDark: rulerRangeDefault, hcLight: rulerRangeDefault }, nls.localize('overviewRulerRangeHighlight', 'Overview ruler marker color for range highlights. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const overviewRulerError = registerColor('editorOverviewRuler.errorForeground', { dark: new Color(new RGBA(255, 18, 18, 0.7)), light: new Color(new RGBA(255, 18, 18, 0.7)), hcDark: new Color(new RGBA(255, 50, 50, 1)), hcLight: '#B5200D' }, nls.localize('overviewRuleError', 'Overview ruler marker color for errors.'));\nexport const overviewRulerWarning = registerColor('editorOverviewRuler.warningForeground', { dark: editorWarningForeground, light: editorWarningForeground, hcDark: editorWarningBorder, hcLight: editorWarningBorder }, nls.localize('overviewRuleWarning', 'Overview ruler marker color for warnings.'));\nexport const overviewRulerInfo = registerColor('editorOverviewRuler.infoForeground', { dark: editorInfoForeground, light: editorInfoForeground, hcDark: editorInfoBorder, hcLight: editorInfoBorder }, nls.localize('overviewRuleInfo', 'Overview ruler marker color for infos.'));\nexport const editorBracketHighlightingForeground1 = registerColor('editorBracketHighlight.foreground1', { dark: '#FFD700', light: '#0431FAFF', hcDark: '#FFD700', hcLight: '#0431FAFF' }, nls.localize('editorBracketHighlightForeground1', 'Foreground color of brackets (1). Requires enabling bracket pair colorization.'));\nexport const editorBracketHighlightingForeground2 = registerColor('editorBracketHighlight.foreground2', { dark: '#DA70D6', light: '#319331FF', hcDark: '#DA70D6', hcLight: '#319331FF' }, nls.localize('editorBracketHighlightForeground2', 'Foreground color of brackets (2). Requires enabling bracket pair colorization.'));\nexport const editorBracketHighlightingForeground3 = registerColor('editorBracketHighlight.foreground3', { dark: '#179FFF', light: '#7B3814FF', hcDark: '#87CEFA', hcLight: '#7B3814FF' }, nls.localize('editorBracketHighlightForeground3', 'Foreground color of brackets (3). Requires enabling bracket pair colorization.'));\nexport const editorBracketHighlightingForeground4 = registerColor('editorBracketHighlight.foreground4', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketHighlightForeground4', 'Foreground color of brackets (4). Requires enabling bracket pair colorization.'));\nexport const editorBracketHighlightingForeground5 = registerColor('editorBracketHighlight.foreground5', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketHighlightForeground5', 'Foreground color of brackets (5). Requires enabling bracket pair colorization.'));\nexport const editorBracketHighlightingForeground6 = registerColor('editorBracketHighlight.foreground6', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketHighlightForeground6', 'Foreground color of brackets (6). Requires enabling bracket pair colorization.'));\nexport const editorBracketHighlightingUnexpectedBracketForeground = registerColor('editorBracketHighlight.unexpectedBracket.foreground', { dark: new Color(new RGBA(255, 18, 18, 0.8)), light: new Color(new RGBA(255, 18, 18, 0.8)), hcDark: new Color(new RGBA(255, 50, 50, 1)), hcLight: '' }, nls.localize('editorBracketHighlightUnexpectedBracketForeground', 'Foreground color of unexpected brackets.'));\nexport const editorBracketPairGuideBackground1 = registerColor('editorBracketPairGuide.background1', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.background1', 'Background color of inactive bracket pair guides (1). Requires enabling bracket pair guides.'));\nexport const editorBracketPairGuideBackground2 = registerColor('editorBracketPairGuide.background2', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.background2', 'Background color of inactive bracket pair guides (2). Requires enabling bracket pair guides.'));\nexport const editorBracketPairGuideBackground3 = registerColor('editorBracketPairGuide.background3', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.background3', 'Background color of inactive bracket pair guides (3). Requires enabling bracket pair guides.'));\nexport const editorBracketPairGuideBackground4 = registerColor('editorBracketPairGuide.background4', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.background4', 'Background color of inactive bracket pair guides (4). Requires enabling bracket pair guides.'));\nexport const editorBracketPairGuideBackground5 = registerColor('editorBracketPairGuide.background5', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.background5', 'Background color of inactive bracket pair guides (5). Requires enabling bracket pair guides.'));\nexport const editorBracketPairGuideBackground6 = registerColor('editorBracketPairGuide.background6', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.background6', 'Background color of inactive bracket pair guides (6). Requires enabling bracket pair guides.'));\nexport const editorBracketPairGuideActiveBackground1 = registerColor('editorBracketPairGuide.activeBackground1', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.activeBackground1', 'Background color of active bracket pair guides (1). Requires enabling bracket pair guides.'));\nexport const editorBracketPairGuideActiveBackground2 = registerColor('editorBracketPairGuide.activeBackground2', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.activeBackground2', 'Background color of active bracket pair guides (2). Requires enabling bracket pair guides.'));\nexport const editorBracketPairGuideActiveBackground3 = registerColor('editorBracketPairGuide.activeBackground3', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.activeBackground3', 'Background color of active bracket pair guides (3). Requires enabling bracket pair guides.'));\nexport const editorBracketPairGuideActiveBackground4 = registerColor('editorBracketPairGuide.activeBackground4', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.activeBackground4', 'Background color of active bracket pair guides (4). Requires enabling bracket pair guides.'));\nexport const editorBracketPairGuideActiveBackground5 = registerColor('editorBracketPairGuide.activeBackground5', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.activeBackground5', 'Background color of active bracket pair guides (5). Requires enabling bracket pair guides.'));\nexport const editorBracketPairGuideActiveBackground6 = registerColor('editorBracketPairGuide.activeBackground6', { dark: '#00000000', light: '#00000000', hcDark: '#00000000', hcLight: '#00000000' }, nls.localize('editorBracketPairGuide.activeBackground6', 'Background color of active bracket pair guides (6). Requires enabling bracket pair guides.'));\nexport const editorUnicodeHighlightBorder = registerColor('editorUnicodeHighlight.border', { dark: '#BD9B03', light: '#CEA33D', hcDark: '#ff0000', hcLight: '' }, nls.localize('editorUnicodeHighlight.border', 'Border color used to highlight unicode characters.'));\nexport const editorUnicodeHighlightBackground = registerColor('editorUnicodeHighlight.background', { dark: '#bd9b0326', light: '#cea33d14', hcDark: '#00000000', hcLight: '' }, nls.localize('editorUnicodeHighlight.background', 'Background color used to highlight unicode characters.'));\n// contains all color rules that used to defined in editor/browser/widget/editor.css\nregisterThemingParticipant((theme, collector) => {\n const background = theme.getColor(editorBackground);\n if (background) {\n collector.addRule(`.monaco-editor, .monaco-editor-background { background-color: ${background}; }`);\n }\n const lineHighlight = theme.getColor(editorLineHighlight);\n const imeBackground = (lineHighlight && !lineHighlight.isTransparent() ? lineHighlight : background);\n if (imeBackground) {\n collector.addRule(`.monaco-editor .inputarea.ime-input { background-color: ${imeBackground}; }`);\n }\n const foreground = theme.getColor(editorForeground);\n if (foreground) {\n collector.addRule(`.monaco-editor, .monaco-editor .inputarea.ime-input { color: ${foreground}; }`);\n }\n const gutter = theme.getColor(editorGutter);\n if (gutter) {\n collector.addRule(`.monaco-editor .margin { background-color: ${gutter}; }`);\n }\n const rangeHighlight = theme.getColor(editorRangeHighlight);\n if (rangeHighlight) {\n collector.addRule(`.monaco-editor .rangeHighlight { background-color: ${rangeHighlight}; }`);\n }\n const rangeHighlightBorder = theme.getColor(editorRangeHighlightBorder);\n if (rangeHighlightBorder) {\n collector.addRule(`.monaco-editor .rangeHighlight { border: 1px ${isHighContrast(theme.type) ? 'dotted' : 'solid'} ${rangeHighlightBorder}; }`);\n }\n const symbolHighlight = theme.getColor(editorSymbolHighlight);\n if (symbolHighlight) {\n collector.addRule(`.monaco-editor .symbolHighlight { background-color: ${symbolHighlight}; }`);\n }\n const symbolHighlightBorder = theme.getColor(editorSymbolHighlightBorder);\n if (symbolHighlightBorder) {\n collector.addRule(`.monaco-editor .symbolHighlight { border: 1px ${isHighContrast(theme.type) ? 'dotted' : 'solid'} ${symbolHighlightBorder}; }`);\n }\n const invisibles = theme.getColor(editorWhitespaces);\n if (invisibles) {\n collector.addRule(`.monaco-editor .mtkw { color: ${invisibles} !important; }`);\n collector.addRule(`.monaco-editor .mtkz { color: ${invisibles} !important; }`);\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 *--------------------------------------------------------------------------------------------*/\nexport function countEOL(text) {\n let eolCount = 0;\n let firstLineLength = 0;\n let lastLineStart = 0;\n let eol = 0 /* StringEOL.Unknown */;\n for (let i = 0, len = text.length; i < len; i++) {\n const chr = text.charCodeAt(i);\n if (chr === 13 /* CharCode.CarriageReturn */) {\n if (eolCount === 0) {\n firstLineLength = i;\n }\n eolCount++;\n if (i + 1 < len && text.charCodeAt(i + 1) === 10 /* CharCode.LineFeed */) {\n // \\r\\n... case\n eol |= 2 /* StringEOL.CRLF */;\n i++; // skip \\n\n }\n else {\n // \\r... case\n eol |= 3 /* StringEOL.Invalid */;\n }\n lastLineStart = i + 1;\n }\n else if (chr === 10 /* CharCode.LineFeed */) {\n // \\n... case\n eol |= 1 /* StringEOL.LF */;\n if (eolCount === 0) {\n firstLineLength = i;\n }\n eolCount++;\n lastLineStart = i + 1;\n }\n }\n if (eolCount === 0) {\n firstLineLength = text.length;\n }\n return [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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../base/common/strings.js';\nimport { CursorColumns } from './cursorColumns.js';\nfunction _normalizeIndentationFromWhitespace(str, indentSize, insertSpaces) {\n let spacesCnt = 0;\n for (let i = 0; i < str.length; i++) {\n if (str.charAt(i) === '\\t') {\n spacesCnt = CursorColumns.nextIndentTabStop(spacesCnt, indentSize);\n }\n else {\n spacesCnt++;\n }\n }\n let result = '';\n if (!insertSpaces) {\n const tabsCnt = Math.floor(spacesCnt / indentSize);\n spacesCnt = spacesCnt % indentSize;\n for (let i = 0; i < tabsCnt; i++) {\n result += '\\t';\n }\n }\n for (let i = 0; i < spacesCnt; i++) {\n result += ' ';\n }\n return result;\n}\nexport function normalizeIndentation(str, indentSize, insertSpaces) {\n let firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(str);\n if (firstNonWhitespaceIndex === -1) {\n firstNonWhitespaceIndex = str.length;\n }\n return _normalizeIndentationFromWhitespace(str.substring(0, firstNonWhitespaceIndex), indentSize, insertSpaces) + str.substring(firstNonWhitespaceIndex);\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (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 * A position in the editor.\n */\nexport class Position {\n constructor(lineNumber, column) {\n this.lineNumber = lineNumber;\n this.column = column;\n }\n /**\n * Create a new position from this position.\n *\n * @param newLineNumber new line number\n * @param newColumn new column\n */\n with(newLineNumber = this.lineNumber, newColumn = this.column) {\n if (newLineNumber === this.lineNumber && newColumn === this.column) {\n return this;\n }\n else {\n return new Position(newLineNumber, newColumn);\n }\n }\n /**\n * Derive a new position from this position.\n *\n * @param deltaLineNumber line number delta\n * @param deltaColumn column delta\n */\n delta(deltaLineNumber = 0, deltaColumn = 0) {\n return this.with(this.lineNumber + deltaLineNumber, this.column + deltaColumn);\n }\n /**\n * Test if this position equals other position\n */\n equals(other) {\n return Position.equals(this, other);\n }\n /**\n * Test if position `a` equals position `b`\n */\n static equals(a, b) {\n if (!a && !b) {\n return true;\n }\n return (!!a &&\n !!b &&\n a.lineNumber === b.lineNumber &&\n a.column === b.column);\n }\n /**\n * Test if this position is before other position.\n * If the two positions are equal, the result will be false.\n */\n isBefore(other) {\n return Position.isBefore(this, other);\n }\n /**\n * Test if position `a` is before position `b`.\n * If the two positions are equal, the result will be false.\n */\n static isBefore(a, b) {\n if (a.lineNumber < b.lineNumber) {\n return true;\n }\n if (b.lineNumber < a.lineNumber) {\n return false;\n }\n return a.column < b.column;\n }\n /**\n * Test if this position is before other position.\n * If the two positions are equal, the result will be true.\n */\n isBeforeOrEqual(other) {\n return Position.isBeforeOrEqual(this, other);\n }\n /**\n * Test if position `a` is before position `b`.\n * If the two positions are equal, the result will be true.\n */\n static isBeforeOrEqual(a, b) {\n if (a.lineNumber < b.lineNumber) {\n return true;\n }\n if (b.lineNumber < a.lineNumber) {\n return false;\n }\n return a.column <= b.column;\n }\n /**\n * A function that compares positions, useful for sorting\n */\n static compare(a, b) {\n const aLineNumber = a.lineNumber | 0;\n const bLineNumber = b.lineNumber | 0;\n if (aLineNumber === bLineNumber) {\n const aColumn = a.column | 0;\n const bColumn = b.column | 0;\n return aColumn - bColumn;\n }\n return aLineNumber - bLineNumber;\n }\n /**\n * Clone this position.\n */\n clone() {\n return new Position(this.lineNumber, this.column);\n }\n /**\n * Convert to a human-readable representation.\n */\n toString() {\n return '(' + this.lineNumber + ',' + this.column + ')';\n }\n // ---\n /**\n * Create a `Position` from an `IPosition`.\n */\n static lift(pos) {\n return new Position(pos.lineNumber, pos.column);\n }\n /**\n * Test if `obj` is an `IPosition`.\n */\n static isIPosition(obj) {\n return (obj\n && (typeof obj.lineNumber === 'number')\n && (typeof obj.column === 'number'));\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 *--------------------------------------------------------------------------------------------*/\nimport { Position } from './position.js';\n/**\n * A range in the editor. (startLineNumber,startColumn) is <= (endLineNumber,endColumn)\n */\nexport class Range {\n constructor(startLineNumber, startColumn, endLineNumber, endColumn) {\n if ((startLineNumber > endLineNumber) || (startLineNumber === endLineNumber && startColumn > endColumn)) {\n this.startLineNumber = endLineNumber;\n this.startColumn = endColumn;\n this.endLineNumber = startLineNumber;\n this.endColumn = startColumn;\n }\n else {\n this.startLineNumber = startLineNumber;\n this.startColumn = startColumn;\n this.endLineNumber = endLineNumber;\n this.endColumn = endColumn;\n }\n }\n /**\n * Test if this range is empty.\n */\n isEmpty() {\n return Range.isEmpty(this);\n }\n /**\n * Test if `range` is empty.\n */\n static isEmpty(range) {\n return (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn);\n }\n /**\n * Test if position is in this range. If the position is at the edges, will return true.\n */\n containsPosition(position) {\n return Range.containsPosition(this, position);\n }\n /**\n * Test if `position` is in `range`. If the position is at the edges, will return true.\n */\n static containsPosition(range, position) {\n if (position.lineNumber < range.startLineNumber || position.lineNumber > range.endLineNumber) {\n return false;\n }\n if (position.lineNumber === range.startLineNumber && position.column < range.startColumn) {\n return false;\n }\n if (position.lineNumber === range.endLineNumber && position.column > range.endColumn) {\n return false;\n }\n return true;\n }\n /**\n * Test if `position` is in `range`. If the position is at the edges, will return false.\n * @internal\n */\n static strictContainsPosition(range, position) {\n if (position.lineNumber < range.startLineNumber || position.lineNumber > range.endLineNumber) {\n return false;\n }\n if (position.lineNumber === range.startLineNumber && position.column <= range.startColumn) {\n return false;\n }\n if (position.lineNumber === range.endLineNumber && position.column >= range.endColumn) {\n return false;\n }\n return true;\n }\n /**\n * Test if range is in this range. If the range is equal to this range, will return true.\n */\n containsRange(range) {\n return Range.containsRange(this, range);\n }\n /**\n * Test if `otherRange` is in `range`. If the ranges are equal, will return true.\n */\n static containsRange(range, otherRange) {\n if (otherRange.startLineNumber < range.startLineNumber || otherRange.endLineNumber < range.startLineNumber) {\n return false;\n }\n if (otherRange.startLineNumber > range.endLineNumber || otherRange.endLineNumber > range.endLineNumber) {\n return false;\n }\n if (otherRange.startLineNumber === range.startLineNumber && otherRange.startColumn < range.startColumn) {\n return false;\n }\n if (otherRange.endLineNumber === range.endLineNumber && otherRange.endColumn > range.endColumn) {\n return false;\n }\n return true;\n }\n /**\n * Test if `range` is strictly in this range. `range` must start after and end before this range for the result to be true.\n */\n strictContainsRange(range) {\n return Range.strictContainsRange(this, range);\n }\n /**\n * Test if `otherRange` is strictly in `range` (must start after, and end before). If the ranges are equal, will return false.\n */\n static strictContainsRange(range, otherRange) {\n if (otherRange.startLineNumber < range.startLineNumber || otherRange.endLineNumber < range.startLineNumber) {\n return false;\n }\n if (otherRange.startLineNumber > range.endLineNumber || otherRange.endLineNumber > range.endLineNumber) {\n return false;\n }\n if (otherRange.startLineNumber === range.startLineNumber && otherRange.startColumn <= range.startColumn) {\n return false;\n }\n if (otherRange.endLineNumber === range.endLineNumber && otherRange.endColumn >= range.endColumn) {\n return false;\n }\n return true;\n }\n /**\n * A reunion of the two ranges.\n * The smallest position will be used as the start point, and the largest one as the end point.\n */\n plusRange(range) {\n return Range.plusRange(this, range);\n }\n /**\n * A reunion of the two ranges.\n * The smallest position will be used as the start point, and the largest one as the end point.\n */\n static plusRange(a, b) {\n let startLineNumber;\n let startColumn;\n let endLineNumber;\n let endColumn;\n if (b.startLineNumber < a.startLineNumber) {\n startLineNumber = b.startLineNumber;\n startColumn = b.startColumn;\n }\n else if (b.startLineNumber === a.startLineNumber) {\n startLineNumber = b.startLineNumber;\n startColumn = Math.min(b.startColumn, a.startColumn);\n }\n else {\n startLineNumber = a.startLineNumber;\n startColumn = a.startColumn;\n }\n if (b.endLineNumber > a.endLineNumber) {\n endLineNumber = b.endLineNumber;\n endColumn = b.endColumn;\n }\n else if (b.endLineNumber === a.endLineNumber) {\n endLineNumber = b.endLineNumber;\n endColumn = Math.max(b.endColumn, a.endColumn);\n }\n else {\n endLineNumber = a.endLineNumber;\n endColumn = a.endColumn;\n }\n return new Range(startLineNumber, startColumn, endLineNumber, endColumn);\n }\n /**\n * A intersection of the two ranges.\n */\n intersectRanges(range) {\n return Range.intersectRanges(this, range);\n }\n /**\n * A intersection of the two ranges.\n */\n static intersectRanges(a, b) {\n let resultStartLineNumber = a.startLineNumber;\n let resultStartColumn = a.startColumn;\n let resultEndLineNumber = a.endLineNumber;\n let resultEndColumn = a.endColumn;\n const otherStartLineNumber = b.startLineNumber;\n const otherStartColumn = b.startColumn;\n const otherEndLineNumber = b.endLineNumber;\n const otherEndColumn = b.endColumn;\n if (resultStartLineNumber < otherStartLineNumber) {\n resultStartLineNumber = otherStartLineNumber;\n resultStartColumn = otherStartColumn;\n }\n else if (resultStartLineNumber === otherStartLineNumber) {\n resultStartColumn = Math.max(resultStartColumn, otherStartColumn);\n }\n if (resultEndLineNumber > otherEndLineNumber) {\n resultEndLineNumber = otherEndLineNumber;\n resultEndColumn = otherEndColumn;\n }\n else if (resultEndLineNumber === otherEndLineNumber) {\n resultEndColumn = Math.min(resultEndColumn, otherEndColumn);\n }\n // Check if selection is now empty\n if (resultStartLineNumber > resultEndLineNumber) {\n return null;\n }\n if (resultStartLineNumber === resultEndLineNumber && resultStartColumn > resultEndColumn) {\n return null;\n }\n return new Range(resultStartLineNumber, resultStartColumn, resultEndLineNumber, resultEndColumn);\n }\n /**\n * Test if this range equals other.\n */\n equalsRange(other) {\n return Range.equalsRange(this, other);\n }\n /**\n * Test if range `a` equals `b`.\n */\n static equalsRange(a, b) {\n return (!!a &&\n !!b &&\n a.startLineNumber === b.startLineNumber &&\n a.startColumn === b.startColumn &&\n a.endLineNumber === b.endLineNumber &&\n a.endColumn === b.endColumn);\n }\n /**\n * Return the end position (which will be after or equal to the start position)\n */\n getEndPosition() {\n return Range.getEndPosition(this);\n }\n /**\n * Return the end position (which will be after or equal to the start position)\n */\n static getEndPosition(range) {\n return new Position(range.endLineNumber, range.endColumn);\n }\n /**\n * Return the start position (which will be before or equal to the end position)\n */\n getStartPosition() {\n return Range.getStartPosition(this);\n }\n /**\n * Return the start position (which will be before or equal to the end position)\n */\n static getStartPosition(range) {\n return new Position(range.startLineNumber, range.startColumn);\n }\n /**\n * Transform to a user presentable string representation.\n */\n toString() {\n return '[' + this.startLineNumber + ',' + this.startColumn + ' -> ' + this.endLineNumber + ',' + this.endColumn + ']';\n }\n /**\n * Create a new range using this range's start position, and using endLineNumber and endColumn as the end position.\n */\n setEndPosition(endLineNumber, endColumn) {\n return new Range(this.startLineNumber, this.startColumn, endLineNumber, endColumn);\n }\n /**\n * Create a new range using this range's end position, and using startLineNumber and startColumn as the start position.\n */\n setStartPosition(startLineNumber, startColumn) {\n return new Range(startLineNumber, startColumn, this.endLineNumber, this.endColumn);\n }\n /**\n * Create a new empty range using this range's start position.\n */\n collapseToStart() {\n return Range.collapseToStart(this);\n }\n /**\n * Create a new empty range using this range's start position.\n */\n static collapseToStart(range) {\n return new Range(range.startLineNumber, range.startColumn, range.startLineNumber, range.startColumn);\n }\n // ---\n static fromPositions(start, end = start) {\n return new Range(start.lineNumber, start.column, end.lineNumber, end.column);\n }\n static lift(range) {\n if (!range) {\n return null;\n }\n return new Range(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);\n }\n /**\n * Test if `obj` is an `IRange`.\n */\n static isIRange(obj) {\n return (obj\n && (typeof obj.startLineNumber === 'number')\n && (typeof obj.startColumn === 'number')\n && (typeof obj.endLineNumber === 'number')\n && (typeof obj.endColumn === 'number'));\n }\n /**\n * Test if the two ranges are touching in any way.\n */\n static areIntersectingOrTouching(a, b) {\n // Check if `a` is before `b`\n if (a.endLineNumber < b.startLineNumber || (a.endLineNumber === b.startLineNumber && a.endColumn < b.startColumn)) {\n return false;\n }\n // Check if `b` is before `a`\n if (b.endLineNumber < a.startLineNumber || (b.endLineNumber === a.startLineNumber && b.endColumn < a.startColumn)) {\n return false;\n }\n // These ranges must intersect\n return true;\n }\n /**\n * Test if the two ranges are intersecting. If the ranges are touching it returns true.\n */\n static areIntersecting(a, b) {\n // Check if `a` is before `b`\n if (a.endLineNumber < b.startLineNumber || (a.endLineNumber === b.startLineNumber && a.endColumn <= b.startColumn)) {\n return false;\n }\n // Check if `b` is before `a`\n if (b.endLineNumber < a.startLineNumber || (b.endLineNumber === a.startLineNumber && b.endColumn <= a.startColumn)) {\n return false;\n }\n // These ranges must intersect\n return true;\n }\n /**\n * A function that compares ranges, useful for sorting ranges\n * It will first compare ranges on the startPosition and then on the endPosition\n */\n static compareRangesUsingStarts(a, b) {\n if (a && b) {\n const aStartLineNumber = a.startLineNumber | 0;\n const bStartLineNumber = b.startLineNumber | 0;\n if (aStartLineNumber === bStartLineNumber) {\n const aStartColumn = a.startColumn | 0;\n const bStartColumn = b.startColumn | 0;\n if (aStartColumn === bStartColumn) {\n const aEndLineNumber = a.endLineNumber | 0;\n const bEndLineNumber = b.endLineNumber | 0;\n if (aEndLineNumber === bEndLineNumber) {\n const aEndColumn = a.endColumn | 0;\n const bEndColumn = b.endColumn | 0;\n return aEndColumn - bEndColumn;\n }\n return aEndLineNumber - bEndLineNumber;\n }\n return aStartColumn - bStartColumn;\n }\n return aStartLineNumber - bStartLineNumber;\n }\n const aExists = (a ? 1 : 0);\n const bExists = (b ? 1 : 0);\n return aExists - bExists;\n }\n /**\n * A function that compares ranges, useful for sorting ranges\n * It will first compare ranges on the endPosition and then on the startPosition\n */\n static compareRangesUsingEnds(a, b) {\n if (a.endLineNumber === b.endLineNumber) {\n if (a.endColumn === b.endColumn) {\n if (a.startLineNumber === b.startLineNumber) {\n return a.startColumn - b.startColumn;\n }\n return a.startLineNumber - b.startLineNumber;\n }\n return a.endColumn - b.endColumn;\n }\n return a.endLineNumber - b.endLineNumber;\n }\n /**\n * Test if the range spans multiple lines.\n */\n static spansMultipleLines(range) {\n return range.endLineNumber > range.startLineNumber;\n }\n toJSON() {\n return this;\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 *--------------------------------------------------------------------------------------------*/\nimport { Position } from './position.js';\nimport { Range } from './range.js';\n/**\n * A selection in the editor.\n * The selection is a range that has an orientation.\n */\nexport class Selection extends Range {\n constructor(selectionStartLineNumber, selectionStartColumn, positionLineNumber, positionColumn) {\n super(selectionStartLineNumber, selectionStartColumn, positionLineNumber, positionColumn);\n this.selectionStartLineNumber = selectionStartLineNumber;\n this.selectionStartColumn = selectionStartColumn;\n this.positionLineNumber = positionLineNumber;\n this.positionColumn = positionColumn;\n }\n /**\n * Transform to a human-readable representation.\n */\n toString() {\n return '[' + this.selectionStartLineNumber + ',' + this.selectionStartColumn + ' -> ' + this.positionLineNumber + ',' + this.positionColumn + ']';\n }\n /**\n * Test if equals other selection.\n */\n equalsSelection(other) {\n return (Selection.selectionsEqual(this, other));\n }\n /**\n * Test if the two selections are equal.\n */\n static selectionsEqual(a, b) {\n return (a.selectionStartLineNumber === b.selectionStartLineNumber &&\n a.selectionStartColumn === b.selectionStartColumn &&\n a.positionLineNumber === b.positionLineNumber &&\n a.positionColumn === b.positionColumn);\n }\n /**\n * Get directions (LTR or RTL).\n */\n getDirection() {\n if (this.selectionStartLineNumber === this.startLineNumber && this.selectionStartColumn === this.startColumn) {\n return 0 /* SelectionDirection.LTR */;\n }\n return 1 /* SelectionDirection.RTL */;\n }\n /**\n * Create a new selection with a different `positionLineNumber` and `positionColumn`.\n */\n setEndPosition(endLineNumber, endColumn) {\n if (this.getDirection() === 0 /* SelectionDirection.LTR */) {\n return new Selection(this.startLineNumber, this.startColumn, endLineNumber, endColumn);\n }\n return new Selection(endLineNumber, endColumn, this.startLineNumber, this.startColumn);\n }\n /**\n * Get the position at `positionLineNumber` and `positionColumn`.\n */\n getPosition() {\n return new Position(this.positionLineNumber, this.positionColumn);\n }\n /**\n * Get the position at the start of the selection.\n */\n getSelectionStart() {\n return new Position(this.selectionStartLineNumber, this.selectionStartColumn);\n }\n /**\n * Create a new selection with a different `selectionStartLineNumber` and `selectionStartColumn`.\n */\n setStartPosition(startLineNumber, startColumn) {\n if (this.getDirection() === 0 /* SelectionDirection.LTR */) {\n return new Selection(startLineNumber, startColumn, this.endLineNumber, this.endColumn);\n }\n return new Selection(this.endLineNumber, this.endColumn, startLineNumber, startColumn);\n }\n // ----\n /**\n * Create a `Selection` from one or two positions\n */\n static fromPositions(start, end = start) {\n return new Selection(start.lineNumber, start.column, end.lineNumber, end.column);\n }\n /**\n * Creates a `Selection` from a range, given a direction.\n */\n static fromRange(range, direction) {\n if (direction === 0 /* SelectionDirection.LTR */) {\n return new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);\n }\n else {\n return new Selection(range.endLineNumber, range.endColumn, range.startLineNumber, range.startColumn);\n }\n }\n /**\n * Create a `Selection` from an `ISelection`.\n */\n static liftSelection(sel) {\n return new Selection(sel.selectionStartLineNumber, sel.selectionStartColumn, sel.positionLineNumber, sel.positionColumn);\n }\n /**\n * `a` equals `b`.\n */\n static selectionsArrEqual(a, b) {\n if (a && !b || !a && b) {\n return false;\n }\n if (!a && !b) {\n return true;\n }\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0, len = a.length; i < len; i++) {\n if (!this.selectionsEqual(a[i], b[i])) {\n return false;\n }\n }\n return true;\n }\n /**\n * Test if `obj` is an `ISelection`.\n */\n static isISelection(obj) {\n return (obj\n && (typeof obj.selectionStartLineNumber === 'number')\n && (typeof obj.selectionStartColumn === 'number')\n && (typeof obj.positionLineNumber === 'number')\n && (typeof obj.positionColumn === 'number'));\n }\n /**\n * Create with a direction.\n */\n static createWithDirection(startLineNumber, startColumn, endLineNumber, endColumn, direction) {\n if (direction === 0 /* SelectionDirection.LTR */) {\n return new Selection(startLineNumber, startColumn, endLineNumber, endColumn);\n }\n return new Selection(endLineNumber, endColumn, startLineNumber, startColumn);\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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../base/common/strings.js';\nimport * as platform from '../../../base/common/platform.js';\nimport * as buffer from '../../../base/common/buffer.js';\nlet _utf16LE_TextDecoder;\nfunction getUTF16LE_TextDecoder() {\n if (!_utf16LE_TextDecoder) {\n _utf16LE_TextDecoder = new TextDecoder('UTF-16LE');\n }\n return _utf16LE_TextDecoder;\n}\nlet _utf16BE_TextDecoder;\nfunction getUTF16BE_TextDecoder() {\n if (!_utf16BE_TextDecoder) {\n _utf16BE_TextDecoder = new TextDecoder('UTF-16BE');\n }\n return _utf16BE_TextDecoder;\n}\nlet _platformTextDecoder;\nexport function getPlatformTextDecoder() {\n if (!_platformTextDecoder) {\n _platformTextDecoder = platform.isLittleEndian() ? getUTF16LE_TextDecoder() : getUTF16BE_TextDecoder();\n }\n return _platformTextDecoder;\n}\nexport const hasTextDecoder = (typeof TextDecoder !== 'undefined');\nexport let createStringBuilder;\nexport let decodeUTF16LE;\nif (hasTextDecoder) {\n createStringBuilder = (capacity) => new StringBuilder(capacity);\n decodeUTF16LE = standardDecodeUTF16LE;\n}\nelse {\n createStringBuilder = (capacity) => new CompatStringBuilder();\n decodeUTF16LE = compatDecodeUTF16LE;\n}\nfunction standardDecodeUTF16LE(source, offset, len) {\n const view = new Uint16Array(source.buffer, offset, len);\n if (len > 0 && (view[0] === 0xFEFF || view[0] === 0xFFFE)) {\n // UTF16 sometimes starts with a BOM https://de.wikipedia.org/wiki/Byte_Order_Mark\n // It looks like TextDecoder.decode will eat up a leading BOM (0xFEFF or 0xFFFE)\n // We don't want that behavior because we know the string is UTF16LE and the BOM should be maintained\n // So we use the manual decoder\n return compatDecodeUTF16LE(source, offset, len);\n }\n return getUTF16LE_TextDecoder().decode(view);\n}\nfunction compatDecodeUTF16LE(source, offset, len) {\n const result = [];\n let resultLen = 0;\n for (let i = 0; i < len; i++) {\n const charCode = buffer.readUInt16LE(source, offset);\n offset += 2;\n result[resultLen++] = String.fromCharCode(charCode);\n }\n return result.join('');\n}\nclass StringBuilder {\n constructor(capacity) {\n this._capacity = capacity | 0;\n this._buffer = new Uint16Array(this._capacity);\n this._completedStrings = null;\n this._bufferLength = 0;\n }\n reset() {\n this._completedStrings = null;\n this._bufferLength = 0;\n }\n build() {\n if (this._completedStrings !== null) {\n this._flushBuffer();\n return this._completedStrings.join('');\n }\n return this._buildBuffer();\n }\n _buildBuffer() {\n if (this._bufferLength === 0) {\n return '';\n }\n const view = new Uint16Array(this._buffer.buffer, 0, this._bufferLength);\n return getPlatformTextDecoder().decode(view);\n }\n _flushBuffer() {\n const bufferString = this._buildBuffer();\n this._bufferLength = 0;\n if (this._completedStrings === null) {\n this._completedStrings = [bufferString];\n }\n else {\n this._completedStrings[this._completedStrings.length] = bufferString;\n }\n }\n write1(charCode) {\n const remainingSpace = this._capacity - this._bufferLength;\n if (remainingSpace <= 1) {\n if (remainingSpace === 0 || strings.isHighSurrogate(charCode)) {\n this._flushBuffer();\n }\n }\n this._buffer[this._bufferLength++] = charCode;\n }\n appendASCII(charCode) {\n if (this._bufferLength === this._capacity) {\n // buffer is full\n this._flushBuffer();\n }\n this._buffer[this._bufferLength++] = charCode;\n }\n appendASCIIString(str) {\n const strLen = str.length;\n if (this._bufferLength + strLen >= this._capacity) {\n // This string does not fit in the remaining buffer space\n this._flushBuffer();\n this._completedStrings[this._completedStrings.length] = str;\n return;\n }\n for (let i = 0; i < strLen; i++) {\n this._buffer[this._bufferLength++] = str.charCodeAt(i);\n }\n }\n}\nclass CompatStringBuilder {\n constructor() {\n this._pieces = [];\n this._piecesLen = 0;\n }\n reset() {\n this._pieces = [];\n this._piecesLen = 0;\n }\n build() {\n return this._pieces.join('');\n }\n write1(charCode) {\n this._pieces[this._piecesLen++] = String.fromCharCode(charCode);\n }\n appendASCII(charCode) {\n this._pieces[this._piecesLen++] = String.fromCharCode(charCode);\n }\n appendASCIIString(str) {\n this._pieces[this._piecesLen++] = str;\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 *--------------------------------------------------------------------------------------------*/\nimport * as buffer from '../../../base/common/buffer.js';\nimport { decodeUTF16LE } from './stringBuilder.js';\nfunction escapeNewLine(str) {\n return (str\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r'));\n}\nexport class TextChange {\n constructor(oldPosition, oldText, newPosition, newText) {\n this.oldPosition = oldPosition;\n this.oldText = oldText;\n this.newPosition = newPosition;\n this.newText = newText;\n }\n get oldLength() {\n return this.oldText.length;\n }\n get oldEnd() {\n return this.oldPosition + this.oldText.length;\n }\n get newLength() {\n return this.newText.length;\n }\n get newEnd() {\n return this.newPosition + this.newText.length;\n }\n toString() {\n if (this.oldText.length === 0) {\n return `(insert@${this.oldPosition} \"${escapeNewLine(this.newText)}\")`;\n }\n if (this.newText.length === 0) {\n return `(delete@${this.oldPosition} \"${escapeNewLine(this.oldText)}\")`;\n }\n return `(replace@${this.oldPosition} \"${escapeNewLine(this.oldText)}\" with \"${escapeNewLine(this.newText)}\")`;\n }\n static _writeStringSize(str) {\n return (4 + 2 * str.length);\n }\n static _writeString(b, str, offset) {\n const len = str.length;\n buffer.writeUInt32BE(b, len, offset);\n offset += 4;\n for (let i = 0; i < len; i++) {\n buffer.writeUInt16LE(b, str.charCodeAt(i), offset);\n offset += 2;\n }\n return offset;\n }\n static _readString(b, offset) {\n const len = buffer.readUInt32BE(b, offset);\n offset += 4;\n return decodeUTF16LE(b, offset, len);\n }\n writeSize() {\n return (+4 // oldPosition\n + 4 // newPosition\n + TextChange._writeStringSize(this.oldText)\n + TextChange._writeStringSize(this.newText));\n }\n write(b, offset) {\n buffer.writeUInt32BE(b, this.oldPosition, offset);\n offset += 4;\n buffer.writeUInt32BE(b, this.newPosition, offset);\n offset += 4;\n offset = TextChange._writeString(b, this.oldText, offset);\n offset = TextChange._writeString(b, this.newText, offset);\n return offset;\n }\n static read(b, offset, dest) {\n const oldPosition = buffer.readUInt32BE(b, offset);\n offset += 4;\n const newPosition = buffer.readUInt32BE(b, offset);\n offset += 4;\n const oldText = TextChange._readString(b, offset);\n offset += TextChange._writeStringSize(oldText);\n const newText = TextChange._readString(b, offset);\n offset += TextChange._writeStringSize(newText);\n dest.push(new TextChange(oldPosition, oldText, newPosition, newText));\n return offset;\n }\n}\nexport function compressConsecutiveTextChanges(prevEdits, currEdits) {\n if (prevEdits === null || prevEdits.length === 0) {\n return currEdits;\n }\n const compressor = new TextChangeCompressor(prevEdits, currEdits);\n return compressor.compress();\n}\nclass TextChangeCompressor {\n constructor(prevEdits, currEdits) {\n this._prevEdits = prevEdits;\n this._currEdits = currEdits;\n this._result = [];\n this._resultLen = 0;\n this._prevLen = this._prevEdits.length;\n this._prevDeltaOffset = 0;\n this._currLen = this._currEdits.length;\n this._currDeltaOffset = 0;\n }\n compress() {\n let prevIndex = 0;\n let currIndex = 0;\n let prevEdit = this._getPrev(prevIndex);\n let currEdit = this._getCurr(currIndex);\n while (prevIndex < this._prevLen || currIndex < this._currLen) {\n if (prevEdit === null) {\n this._acceptCurr(currEdit);\n currEdit = this._getCurr(++currIndex);\n continue;\n }\n if (currEdit === null) {\n this._acceptPrev(prevEdit);\n prevEdit = this._getPrev(++prevIndex);\n continue;\n }\n if (currEdit.oldEnd <= prevEdit.newPosition) {\n this._acceptCurr(currEdit);\n currEdit = this._getCurr(++currIndex);\n continue;\n }\n if (prevEdit.newEnd <= currEdit.oldPosition) {\n this._acceptPrev(prevEdit);\n prevEdit = this._getPrev(++prevIndex);\n continue;\n }\n if (currEdit.oldPosition < prevEdit.newPosition) {\n const [e1, e2] = TextChangeCompressor._splitCurr(currEdit, prevEdit.newPosition - currEdit.oldPosition);\n this._acceptCurr(e1);\n currEdit = e2;\n continue;\n }\n if (prevEdit.newPosition < currEdit.oldPosition) {\n const [e1, e2] = TextChangeCompressor._splitPrev(prevEdit, currEdit.oldPosition - prevEdit.newPosition);\n this._acceptPrev(e1);\n prevEdit = e2;\n continue;\n }\n // At this point, currEdit.oldPosition === prevEdit.newPosition\n let mergePrev;\n let mergeCurr;\n if (currEdit.oldEnd === prevEdit.newEnd) {\n mergePrev = prevEdit;\n mergeCurr = currEdit;\n prevEdit = this._getPrev(++prevIndex);\n currEdit = this._getCurr(++currIndex);\n }\n else if (currEdit.oldEnd < prevEdit.newEnd) {\n const [e1, e2] = TextChangeCompressor._splitPrev(prevEdit, currEdit.oldLength);\n mergePrev = e1;\n mergeCurr = currEdit;\n prevEdit = e2;\n currEdit = this._getCurr(++currIndex);\n }\n else {\n const [e1, e2] = TextChangeCompressor._splitCurr(currEdit, prevEdit.newLength);\n mergePrev = prevEdit;\n mergeCurr = e1;\n prevEdit = this._getPrev(++prevIndex);\n currEdit = e2;\n }\n this._result[this._resultLen++] = new TextChange(mergePrev.oldPosition, mergePrev.oldText, mergeCurr.newPosition, mergeCurr.newText);\n this._prevDeltaOffset += mergePrev.newLength - mergePrev.oldLength;\n this._currDeltaOffset += mergeCurr.newLength - mergeCurr.oldLength;\n }\n const merged = TextChangeCompressor._merge(this._result);\n const cleaned = TextChangeCompressor._removeNoOps(merged);\n return cleaned;\n }\n _acceptCurr(currEdit) {\n this._result[this._resultLen++] = TextChangeCompressor._rebaseCurr(this._prevDeltaOffset, currEdit);\n this._currDeltaOffset += currEdit.newLength - currEdit.oldLength;\n }\n _getCurr(currIndex) {\n return (currIndex < this._currLen ? this._currEdits[currIndex] : null);\n }\n _acceptPrev(prevEdit) {\n this._result[this._resultLen++] = TextChangeCompressor._rebasePrev(this._currDeltaOffset, prevEdit);\n this._prevDeltaOffset += prevEdit.newLength - prevEdit.oldLength;\n }\n _getPrev(prevIndex) {\n return (prevIndex < this._prevLen ? this._prevEdits[prevIndex] : null);\n }\n static _rebaseCurr(prevDeltaOffset, currEdit) {\n return new TextChange(currEdit.oldPosition - prevDeltaOffset, currEdit.oldText, currEdit.newPosition, currEdit.newText);\n }\n static _rebasePrev(currDeltaOffset, prevEdit) {\n return new TextChange(prevEdit.oldPosition, prevEdit.oldText, prevEdit.newPosition + currDeltaOffset, prevEdit.newText);\n }\n static _splitPrev(edit, offset) {\n const preText = edit.newText.substr(0, offset);\n const postText = edit.newText.substr(offset);\n return [\n new TextChange(edit.oldPosition, edit.oldText, edit.newPosition, preText),\n new TextChange(edit.oldEnd, '', edit.newPosition + offset, postText)\n ];\n }\n static _splitCurr(edit, offset) {\n const preText = edit.oldText.substr(0, offset);\n const postText = edit.oldText.substr(offset);\n return [\n new TextChange(edit.oldPosition, preText, edit.newPosition, edit.newText),\n new TextChange(edit.oldPosition + offset, postText, edit.newEnd, '')\n ];\n }\n static _merge(edits) {\n if (edits.length === 0) {\n return edits;\n }\n const result = [];\n let resultLen = 0;\n let prev = edits[0];\n for (let i = 1; i < edits.length; i++) {\n const curr = edits[i];\n if (prev.oldEnd === curr.oldPosition) {\n // Merge into `prev`\n prev = new TextChange(prev.oldPosition, prev.oldText + curr.oldText, prev.newPosition, prev.newText + curr.newText);\n }\n else {\n result[resultLen++] = prev;\n prev = curr;\n }\n }\n result[resultLen++] = prev;\n return result;\n }\n static _removeNoOps(edits) {\n if (edits.length === 0) {\n return edits;\n }\n const result = [];\n let resultLen = 0;\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n if (edit.oldText === edit.newText) {\n continue;\n }\n result[resultLen++] = edit;\n }\n return result;\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 *--------------------------------------------------------------------------------------------*/\nexport const EDITOR_MODEL_DEFAULTS = {\n tabSize: 4,\n indentSize: 4,\n insertSpaces: true,\n detectIndentation: true,\n trimAutoWhitespace: true,\n largeFileOptimizations: true,\n bracketPairColorizationOptions: {\n enabled: true,\n independentColorPoolPerBracketType: false,\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 *--------------------------------------------------------------------------------------------*/\nimport { CharacterClassifier } from './characterClassifier.js';\nexport class WordCharacterClassifier extends CharacterClassifier {\n constructor(wordSeparators) {\n super(0 /* WordCharacterClass.Regular */);\n for (let i = 0, len = wordSeparators.length; i < len; i++) {\n this.set(wordSeparators.charCodeAt(i), 2 /* WordCharacterClass.WordSeparator */);\n }\n this.set(32 /* CharCode.Space */, 1 /* WordCharacterClass.Whitespace */);\n this.set(9 /* CharCode.Tab */, 1 /* WordCharacterClass.Whitespace */);\n }\n}\nfunction once(computeFn) {\n const cache = {}; // TODO@Alex unbounded cache\n return (input) => {\n if (!cache.hasOwnProperty(input)) {\n cache[input] = computeFn(input);\n }\n return cache[input];\n };\n}\nexport const getMapForWordSeparators = once((input) => new WordCharacterClassifier(input));\n","/*---------------------------------------------------------------------------------------------\n * 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 { Iterable } from '../../../base/common/iterator.js';\nimport { LinkedList } from '../../../base/common/linkedList.js';\nexport const USUAL_WORD_SEPARATORS = '`~!@#$%^&*()-=+[{]}\\\\|;:\\'\",.<>/?';\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 = '') {\n let source = '(-?\\\\d*\\\\.\\\\d\\\\w*)|([^';\n for (const sep of USUAL_WORD_SEPARATORS) {\n if (allowInWords.indexOf(sep) >= 0) {\n continue;\n }\n source += '\\\\' + sep;\n }\n source += '\\\\s]+)';\n return new RegExp(source, 'g');\n}\n// catches numbers (including floating numbers) in the first group, and alphanum in the second\nexport const DEFAULT_WORD_REGEXP = createWordRegExp();\nexport function ensureValidWordDefinition(wordDefinition) {\n let result = DEFAULT_WORD_REGEXP;\n if (wordDefinition && (wordDefinition instanceof RegExp)) {\n if (!wordDefinition.global) {\n let flags = 'g';\n if (wordDefinition.ignoreCase) {\n flags += 'i';\n }\n if (wordDefinition.multiline) {\n flags += 'm';\n }\n if (wordDefinition.unicode) {\n flags += 'u';\n }\n result = new RegExp(wordDefinition.source, flags);\n }\n else {\n result = wordDefinition;\n }\n }\n result.lastIndex = 0;\n return result;\n}\nconst _defaultConfig = new LinkedList();\n_defaultConfig.unshift({\n maxLen: 1000,\n windowSize: 15,\n timeBudget: 150\n});\nexport function getWordAtText(column, wordDefinition, text, textOffset, config) {\n if (!config) {\n config = Iterable.first(_defaultConfig);\n }\n if (text.length > config.maxLen) {\n // don't throw strings that long at the regexp\n // but use a sub-string in which a word must occur\n let start = column - config.maxLen / 2;\n if (start < 0) {\n start = 0;\n }\n else {\n textOffset += start;\n }\n text = text.substring(start, column + config.maxLen / 2);\n return getWordAtText(column, wordDefinition, text, textOffset, config);\n }\n const t1 = Date.now();\n const pos = column - 1 - textOffset;\n let prevRegexIndex = -1;\n let match = null;\n for (let i = 1;; i++) {\n // check time budget\n if (Date.now() - t1 >= config.timeBudget) {\n break;\n }\n // reset the index at which the regexp should start matching, also know where it\n // should stop so that subsequent search don't repeat previous searches\n const regexIndex = pos - config.windowSize * i;\n wordDefinition.lastIndex = Math.max(0, regexIndex);\n const thisMatch = _findRegexMatchEnclosingPosition(wordDefinition, text, pos, prevRegexIndex);\n if (!thisMatch && match) {\n // stop: we have something\n break;\n }\n match = thisMatch;\n // stop: searched at start\n if (regexIndex <= 0) {\n break;\n }\n prevRegexIndex = regexIndex;\n }\n if (match) {\n const result = {\n word: match[0],\n startColumn: textOffset + 1 + match.index,\n endColumn: textOffset + 1 + match.index + match[0].length\n };\n wordDefinition.lastIndex = 0;\n return result;\n }\n return null;\n}\nfunction _findRegexMatchEnclosingPosition(wordDefinition, text, pos, stopPos) {\n let match;\n while (match = wordDefinition.exec(text)) {\n const matchIndex = match.index || 0;\n if (matchIndex <= pos && wordDefinition.lastIndex >= pos) {\n return match;\n }\n else if (stopPos > 0 && matchIndex > stopPos) {\n return null;\n }\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { CursorColumns } from '../core/cursorColumns.js';\nexport class AtomicTabMoveOperations {\n /**\n * Get the visible column at the position. If we get to a non-whitespace character first\n * or past the end of string then return -1.\n *\n * **Note** `position` and the return value are 0-based.\n */\n static whitespaceVisibleColumn(lineContent, position, tabSize) {\n const lineLength = lineContent.length;\n let visibleColumn = 0;\n let prevTabStopPosition = -1;\n let prevTabStopVisibleColumn = -1;\n for (let i = 0; i < lineLength; i++) {\n if (i === position) {\n return [prevTabStopPosition, prevTabStopVisibleColumn, visibleColumn];\n }\n if (visibleColumn % tabSize === 0) {\n prevTabStopPosition = i;\n prevTabStopVisibleColumn = visibleColumn;\n }\n const chCode = lineContent.charCodeAt(i);\n switch (chCode) {\n case 32 /* CharCode.Space */:\n visibleColumn += 1;\n break;\n case 9 /* CharCode.Tab */:\n // Skip to the next multiple of tabSize.\n visibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize);\n break;\n default:\n return [-1, -1, -1];\n }\n }\n if (position === lineLength) {\n return [prevTabStopPosition, prevTabStopVisibleColumn, visibleColumn];\n }\n return [-1, -1, -1];\n }\n /**\n * Return the position that should result from a move left, right or to the\n * nearest tab, if atomic tabs are enabled. Left and right are used for the\n * arrow key movements, nearest is used for mouse selection. It returns\n * -1 if atomic tabs are not relevant and you should fall back to normal\n * behaviour.\n *\n * **Note**: `position` and the return value are 0-based.\n */\n static atomicPosition(lineContent, position, tabSize, direction) {\n const lineLength = lineContent.length;\n // Get the 0-based visible column corresponding to the position, or return\n // -1 if it is not in the initial whitespace.\n const [prevTabStopPosition, prevTabStopVisibleColumn, visibleColumn] = AtomicTabMoveOperations.whitespaceVisibleColumn(lineContent, position, tabSize);\n if (visibleColumn === -1) {\n return -1;\n }\n // Is the output left or right of the current position. The case for nearest\n // where it is the same as the current position is handled in the switch.\n let left;\n switch (direction) {\n case 0 /* Direction.Left */:\n left = true;\n break;\n case 1 /* Direction.Right */:\n left = false;\n break;\n case 2 /* Direction.Nearest */:\n // The code below assumes the output position is either left or right\n // of the input position. If it is the same, return immediately.\n if (visibleColumn % tabSize === 0) {\n return position;\n }\n // Go to the nearest indentation.\n left = visibleColumn % tabSize <= (tabSize / 2);\n break;\n }\n // If going left, we can just use the info about the last tab stop position and\n // last tab stop visible column that we computed in the first walk over the whitespace.\n if (left) {\n if (prevTabStopPosition === -1) {\n return -1;\n }\n // If the direction is left, we need to keep scanning right to ensure\n // that targetVisibleColumn + tabSize is before non-whitespace.\n // This is so that when we press left at the end of a partial\n // indentation it only goes one character. For example ' foo' with\n // tabSize 4, should jump from position 6 to position 5, not 4.\n let currentVisibleColumn = prevTabStopVisibleColumn;\n for (let i = prevTabStopPosition; i < lineLength; ++i) {\n if (currentVisibleColumn === prevTabStopVisibleColumn + tabSize) {\n // It is a full indentation.\n return prevTabStopPosition;\n }\n const chCode = lineContent.charCodeAt(i);\n switch (chCode) {\n case 32 /* CharCode.Space */:\n currentVisibleColumn += 1;\n break;\n case 9 /* CharCode.Tab */:\n currentVisibleColumn = CursorColumns.nextRenderTabStop(currentVisibleColumn, tabSize);\n break;\n default:\n return -1;\n }\n }\n if (currentVisibleColumn === prevTabStopVisibleColumn + tabSize) {\n return prevTabStopPosition;\n }\n // It must have been a partial indentation.\n return -1;\n }\n // We are going right.\n const targetVisibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize);\n // We can just continue from where whitespaceVisibleColumn got to.\n let currentVisibleColumn = visibleColumn;\n for (let i = position; i < lineLength; i++) {\n if (currentVisibleColumn === targetVisibleColumn) {\n return i;\n }\n const chCode = lineContent.charCodeAt(i);\n switch (chCode) {\n case 32 /* CharCode.Space */:\n currentVisibleColumn += 1;\n break;\n case 9 /* CharCode.Tab */:\n currentVisibleColumn = CursorColumns.nextRenderTabStop(currentVisibleColumn, tabSize);\n break;\n default:\n return -1;\n }\n }\n // This condition handles when the target column is at the end of the line.\n if (currentVisibleColumn === targetVisibleColumn) {\n return lineLength;\n }\n return -1;\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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../base/common/strings.js';\nimport { ReplaceCommand } from '../commands/replaceCommand.js';\nimport { EditOperationResult, isQuote } from '../cursorCommon.js';\nimport { CursorColumns } from '../core/cursorColumns.js';\nimport { MoveOperations } from './cursorMoveOperations.js';\nimport { Range } from '../core/range.js';\nimport { Position } from '../core/position.js';\nexport class DeleteOperations {\n static deleteRight(prevEditOperationType, config, model, selections) {\n const commands = [];\n let shouldPushStackElementBefore = (prevEditOperationType !== 3 /* EditOperationType.DeletingRight */);\n for (let i = 0, len = selections.length; i < len; i++) {\n const selection = selections[i];\n let deleteSelection = selection;\n if (deleteSelection.isEmpty()) {\n const position = selection.getPosition();\n const rightOfPosition = MoveOperations.right(config, model, position);\n deleteSelection = new Range(rightOfPosition.lineNumber, rightOfPosition.column, position.lineNumber, position.column);\n }\n if (deleteSelection.isEmpty()) {\n // Probably at end of file => ignore\n commands[i] = null;\n continue;\n }\n if (deleteSelection.startLineNumber !== deleteSelection.endLineNumber) {\n shouldPushStackElementBefore = true;\n }\n commands[i] = new ReplaceCommand(deleteSelection, '');\n }\n return [shouldPushStackElementBefore, commands];\n }\n static isAutoClosingPairDelete(autoClosingDelete, autoClosingBrackets, autoClosingQuotes, autoClosingPairsOpen, model, selections, autoClosedCharacters) {\n if (autoClosingBrackets === 'never' && autoClosingQuotes === 'never') {\n return false;\n }\n if (autoClosingDelete === 'never') {\n return false;\n }\n for (let i = 0, len = selections.length; i < len; i++) {\n const selection = selections[i];\n const position = selection.getPosition();\n if (!selection.isEmpty()) {\n return false;\n }\n const lineText = model.getLineContent(position.lineNumber);\n if (position.column < 2 || position.column >= lineText.length + 1) {\n return false;\n }\n const character = lineText.charAt(position.column - 2);\n const autoClosingPairCandidates = autoClosingPairsOpen.get(character);\n if (!autoClosingPairCandidates) {\n return false;\n }\n if (isQuote(character)) {\n if (autoClosingQuotes === 'never') {\n return false;\n }\n }\n else {\n if (autoClosingBrackets === 'never') {\n return false;\n }\n }\n const afterCharacter = lineText.charAt(position.column - 1);\n let foundAutoClosingPair = false;\n for (const autoClosingPairCandidate of autoClosingPairCandidates) {\n if (autoClosingPairCandidate.open === character && autoClosingPairCandidate.close === afterCharacter) {\n foundAutoClosingPair = true;\n }\n }\n if (!foundAutoClosingPair) {\n return false;\n }\n // Must delete the pair only if it was automatically inserted by the editor\n if (autoClosingDelete === 'auto') {\n let found = false;\n for (let j = 0, lenJ = autoClosedCharacters.length; j < lenJ; j++) {\n const autoClosedCharacter = autoClosedCharacters[j];\n if (position.lineNumber === autoClosedCharacter.startLineNumber && position.column === autoClosedCharacter.startColumn) {\n found = true;\n break;\n }\n }\n if (!found) {\n return false;\n }\n }\n }\n return true;\n }\n static _runAutoClosingPairDelete(config, model, selections) {\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n const position = selections[i].getPosition();\n const deleteSelection = new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1);\n commands[i] = new ReplaceCommand(deleteSelection, '');\n }\n return [true, commands];\n }\n static deleteLeft(prevEditOperationType, config, model, selections, autoClosedCharacters) {\n if (this.isAutoClosingPairDelete(config.autoClosingDelete, config.autoClosingBrackets, config.autoClosingQuotes, config.autoClosingPairs.autoClosingPairsOpenByEnd, model, selections, autoClosedCharacters)) {\n return this._runAutoClosingPairDelete(config, model, selections);\n }\n const commands = [];\n let shouldPushStackElementBefore = (prevEditOperationType !== 2 /* EditOperationType.DeletingLeft */);\n for (let i = 0, len = selections.length; i < len; i++) {\n const deleteRange = DeleteOperations.getDeleteRange(selections[i], model, config);\n // Ignore empty delete ranges, as they have no effect\n // They happen if the cursor is at the beginning of the file.\n if (deleteRange.isEmpty()) {\n commands[i] = null;\n continue;\n }\n if (deleteRange.startLineNumber !== deleteRange.endLineNumber) {\n shouldPushStackElementBefore = true;\n }\n commands[i] = new ReplaceCommand(deleteRange, '');\n }\n return [shouldPushStackElementBefore, commands];\n }\n static getDeleteRange(selection, model, config) {\n if (!selection.isEmpty()) {\n return selection;\n }\n const position = selection.getPosition();\n // Unintend when using tab stops and cursor is within indentation\n if (config.useTabStops && position.column > 1) {\n const lineContent = model.getLineContent(position.lineNumber);\n const firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineContent);\n const lastIndentationColumn = (firstNonWhitespaceIndex === -1\n ? /* entire string is whitespace */ lineContent.length + 1\n : firstNonWhitespaceIndex + 1);\n if (position.column <= lastIndentationColumn) {\n const fromVisibleColumn = config.visibleColumnFromColumn(model, position);\n const toVisibleColumn = CursorColumns.prevIndentTabStop(fromVisibleColumn, config.indentSize);\n const toColumn = config.columnFromVisibleColumn(model, position.lineNumber, toVisibleColumn);\n return new Range(position.lineNumber, toColumn, position.lineNumber, position.column);\n }\n }\n return Range.fromPositions(DeleteOperations.getPositionAfterDeleteLeft(position, model), position);\n }\n static getPositionAfterDeleteLeft(position, model) {\n if (position.column > 1) {\n // Convert 1-based columns to 0-based offsets and back.\n const idx = strings.getLeftDeleteOffset(position.column - 1, model.getLineContent(position.lineNumber));\n return position.with(undefined, idx + 1);\n }\n else if (position.lineNumber > 1) {\n const newLine = position.lineNumber - 1;\n return new Position(newLine, model.getLineMaxColumn(newLine));\n }\n else {\n return position;\n }\n }\n static cut(config, model, selections) {\n const commands = [];\n let lastCutRange = null;\n selections.sort((a, b) => Position.compare(a.getStartPosition(), b.getEndPosition()));\n for (let i = 0, len = selections.length; i < len; i++) {\n const selection = selections[i];\n if (selection.isEmpty()) {\n if (config.emptySelectionClipboard) {\n // This is a full line cut\n const position = selection.getPosition();\n let startLineNumber, startColumn, endLineNumber, endColumn;\n if (position.lineNumber < model.getLineCount()) {\n // Cutting a line in the middle of the model\n startLineNumber = position.lineNumber;\n startColumn = 1;\n endLineNumber = position.lineNumber + 1;\n endColumn = 1;\n }\n else if (position.lineNumber > 1 && (lastCutRange === null || lastCutRange === void 0 ? void 0 : lastCutRange.endLineNumber) !== position.lineNumber) {\n // Cutting the last line & there are more than 1 lines in the model & a previous cut operation does not touch the current cut operation\n startLineNumber = position.lineNumber - 1;\n startColumn = model.getLineMaxColumn(position.lineNumber - 1);\n endLineNumber = position.lineNumber;\n endColumn = model.getLineMaxColumn(position.lineNumber);\n }\n else {\n // Cutting the single line that the model contains\n startLineNumber = position.lineNumber;\n startColumn = 1;\n endLineNumber = position.lineNumber;\n endColumn = model.getLineMaxColumn(position.lineNumber);\n }\n const deleteSelection = new Range(startLineNumber, startColumn, endLineNumber, endColumn);\n lastCutRange = deleteSelection;\n if (!deleteSelection.isEmpty()) {\n commands[i] = new ReplaceCommand(deleteSelection, '');\n }\n else {\n commands[i] = null;\n }\n }\n else {\n // Cannot cut empty selection\n commands[i] = null;\n }\n }\n else {\n commands[i] = new ReplaceCommand(selection, '');\n }\n }\n return new EditOperationResult(0 /* EditOperationType.Other */, commands, {\n shouldPushStackElementBefore: true,\n shouldPushStackElementAfter: true\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 *--------------------------------------------------------------------------------------------*/\nimport * as types from '../../../base/common/types.js';\nimport { CursorState, SingleCursorState } from '../cursorCommon.js';\nimport { MoveOperations } from './cursorMoveOperations.js';\nimport { WordOperations } from './cursorWordOperations.js';\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nexport class CursorMoveCommands {\n static addCursorDown(viewModel, cursors, useLogicalLine) {\n const result = [];\n let resultLen = 0;\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState);\n if (useLogicalLine) {\n result[resultLen++] = CursorState.fromModelState(MoveOperations.translateDown(viewModel.cursorConfig, viewModel.model, cursor.modelState));\n }\n else {\n result[resultLen++] = CursorState.fromViewState(MoveOperations.translateDown(viewModel.cursorConfig, viewModel, cursor.viewState));\n }\n }\n return result;\n }\n static addCursorUp(viewModel, cursors, useLogicalLine) {\n const result = [];\n let resultLen = 0;\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState);\n if (useLogicalLine) {\n result[resultLen++] = CursorState.fromModelState(MoveOperations.translateUp(viewModel.cursorConfig, viewModel.model, cursor.modelState));\n }\n else {\n result[resultLen++] = CursorState.fromViewState(MoveOperations.translateUp(viewModel.cursorConfig, viewModel, cursor.viewState));\n }\n }\n return result;\n }\n static moveToBeginningOfLine(viewModel, cursors, inSelectionMode) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n result[i] = this._moveToLineStart(viewModel, cursor, inSelectionMode);\n }\n return result;\n }\n static _moveToLineStart(viewModel, cursor, inSelectionMode) {\n const currentViewStateColumn = cursor.viewState.position.column;\n const currentModelStateColumn = cursor.modelState.position.column;\n const isFirstLineOfWrappedLine = currentViewStateColumn === currentModelStateColumn;\n const currentViewStatelineNumber = cursor.viewState.position.lineNumber;\n const firstNonBlankColumn = viewModel.getLineFirstNonWhitespaceColumn(currentViewStatelineNumber);\n const isBeginningOfViewLine = currentViewStateColumn === firstNonBlankColumn;\n if (!isFirstLineOfWrappedLine && !isBeginningOfViewLine) {\n return this._moveToLineStartByView(viewModel, cursor, inSelectionMode);\n }\n else {\n return this._moveToLineStartByModel(viewModel, cursor, inSelectionMode);\n }\n }\n static _moveToLineStartByView(viewModel, cursor, inSelectionMode) {\n return CursorState.fromViewState(MoveOperations.moveToBeginningOfLine(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode));\n }\n static _moveToLineStartByModel(viewModel, cursor, inSelectionMode) {\n return CursorState.fromModelState(MoveOperations.moveToBeginningOfLine(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode));\n }\n static moveToEndOfLine(viewModel, cursors, inSelectionMode, sticky) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n result[i] = this._moveToLineEnd(viewModel, cursor, inSelectionMode, sticky);\n }\n return result;\n }\n static _moveToLineEnd(viewModel, cursor, inSelectionMode, sticky) {\n const viewStatePosition = cursor.viewState.position;\n const viewModelMaxColumn = viewModel.getLineMaxColumn(viewStatePosition.lineNumber);\n const isEndOfViewLine = viewStatePosition.column === viewModelMaxColumn;\n const modelStatePosition = cursor.modelState.position;\n const modelMaxColumn = viewModel.model.getLineMaxColumn(modelStatePosition.lineNumber);\n const isEndLineOfWrappedLine = viewModelMaxColumn - viewStatePosition.column === modelMaxColumn - modelStatePosition.column;\n if (isEndOfViewLine || isEndLineOfWrappedLine) {\n return this._moveToLineEndByModel(viewModel, cursor, inSelectionMode, sticky);\n }\n else {\n return this._moveToLineEndByView(viewModel, cursor, inSelectionMode, sticky);\n }\n }\n static _moveToLineEndByView(viewModel, cursor, inSelectionMode, sticky) {\n return CursorState.fromViewState(MoveOperations.moveToEndOfLine(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, sticky));\n }\n static _moveToLineEndByModel(viewModel, cursor, inSelectionMode, sticky) {\n return CursorState.fromModelState(MoveOperations.moveToEndOfLine(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode, sticky));\n }\n static expandLineSelection(viewModel, cursors) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n const startLineNumber = cursor.modelState.selection.startLineNumber;\n const lineCount = viewModel.model.getLineCount();\n let endLineNumber = cursor.modelState.selection.endLineNumber;\n let endColumn;\n if (endLineNumber === lineCount) {\n endColumn = viewModel.model.getLineMaxColumn(lineCount);\n }\n else {\n endLineNumber++;\n endColumn = 1;\n }\n result[i] = CursorState.fromModelState(new SingleCursorState(new Range(startLineNumber, 1, startLineNumber, 1), 0, new Position(endLineNumber, endColumn), 0));\n }\n return result;\n }\n static moveToBeginningOfBuffer(viewModel, cursors, inSelectionMode) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n result[i] = CursorState.fromModelState(MoveOperations.moveToBeginningOfBuffer(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode));\n }\n return result;\n }\n static moveToEndOfBuffer(viewModel, cursors, inSelectionMode) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n result[i] = CursorState.fromModelState(MoveOperations.moveToEndOfBuffer(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode));\n }\n return result;\n }\n static selectAll(viewModel, cursor) {\n const lineCount = viewModel.model.getLineCount();\n const maxColumn = viewModel.model.getLineMaxColumn(lineCount);\n return CursorState.fromModelState(new SingleCursorState(new Range(1, 1, 1, 1), 0, new Position(lineCount, maxColumn), 0));\n }\n static line(viewModel, cursor, inSelectionMode, _position, _viewPosition) {\n const position = viewModel.model.validatePosition(_position);\n const viewPosition = (_viewPosition\n ? viewModel.coordinatesConverter.validateViewPosition(new Position(_viewPosition.lineNumber, _viewPosition.column), position)\n : viewModel.coordinatesConverter.convertModelPositionToViewPosition(position));\n if (!inSelectionMode || !cursor.modelState.hasSelection()) {\n // Entering line selection for the first time\n const lineCount = viewModel.model.getLineCount();\n let selectToLineNumber = position.lineNumber + 1;\n let selectToColumn = 1;\n if (selectToLineNumber > lineCount) {\n selectToLineNumber = lineCount;\n selectToColumn = viewModel.model.getLineMaxColumn(selectToLineNumber);\n }\n return CursorState.fromModelState(new SingleCursorState(new Range(position.lineNumber, 1, selectToLineNumber, selectToColumn), 0, new Position(selectToLineNumber, selectToColumn), 0));\n }\n // Continuing line selection\n const enteringLineNumber = cursor.modelState.selectionStart.getStartPosition().lineNumber;\n if (position.lineNumber < enteringLineNumber) {\n return CursorState.fromViewState(cursor.viewState.move(cursor.modelState.hasSelection(), viewPosition.lineNumber, 1, 0));\n }\n else if (position.lineNumber > enteringLineNumber) {\n const lineCount = viewModel.getLineCount();\n let selectToViewLineNumber = viewPosition.lineNumber + 1;\n let selectToViewColumn = 1;\n if (selectToViewLineNumber > lineCount) {\n selectToViewLineNumber = lineCount;\n selectToViewColumn = viewModel.getLineMaxColumn(selectToViewLineNumber);\n }\n return CursorState.fromViewState(cursor.viewState.move(cursor.modelState.hasSelection(), selectToViewLineNumber, selectToViewColumn, 0));\n }\n else {\n const endPositionOfSelectionStart = cursor.modelState.selectionStart.getEndPosition();\n return CursorState.fromModelState(cursor.modelState.move(cursor.modelState.hasSelection(), endPositionOfSelectionStart.lineNumber, endPositionOfSelectionStart.column, 0));\n }\n }\n static word(viewModel, cursor, inSelectionMode, _position) {\n const position = viewModel.model.validatePosition(_position);\n return CursorState.fromModelState(WordOperations.word(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode, position));\n }\n static cancelSelection(viewModel, cursor) {\n if (!cursor.modelState.hasSelection()) {\n return new CursorState(cursor.modelState, cursor.viewState);\n }\n const lineNumber = cursor.viewState.position.lineNumber;\n const column = cursor.viewState.position.column;\n return CursorState.fromViewState(new SingleCursorState(new Range(lineNumber, column, lineNumber, column), 0, new Position(lineNumber, column), 0));\n }\n static moveTo(viewModel, cursor, inSelectionMode, _position, _viewPosition) {\n const position = viewModel.model.validatePosition(_position);\n const viewPosition = (_viewPosition\n ? viewModel.coordinatesConverter.validateViewPosition(new Position(_viewPosition.lineNumber, _viewPosition.column), position)\n : viewModel.coordinatesConverter.convertModelPositionToViewPosition(position));\n return CursorState.fromViewState(cursor.viewState.move(inSelectionMode, viewPosition.lineNumber, viewPosition.column, 0));\n }\n static simpleMove(viewModel, cursors, direction, inSelectionMode, value, unit) {\n switch (direction) {\n case 0 /* CursorMove.Direction.Left */: {\n if (unit === 4 /* CursorMove.Unit.HalfLine */) {\n // Move left by half the current line length\n return this._moveHalfLineLeft(viewModel, cursors, inSelectionMode);\n }\n else {\n // Move left by `moveParams.value` columns\n return this._moveLeft(viewModel, cursors, inSelectionMode, value);\n }\n }\n case 1 /* CursorMove.Direction.Right */: {\n if (unit === 4 /* CursorMove.Unit.HalfLine */) {\n // Move right by half the current line length\n return this._moveHalfLineRight(viewModel, cursors, inSelectionMode);\n }\n else {\n // Move right by `moveParams.value` columns\n return this._moveRight(viewModel, cursors, inSelectionMode, value);\n }\n }\n case 2 /* CursorMove.Direction.Up */: {\n if (unit === 2 /* CursorMove.Unit.WrappedLine */) {\n // Move up by view lines\n return this._moveUpByViewLines(viewModel, cursors, inSelectionMode, value);\n }\n else {\n // Move up by model lines\n return this._moveUpByModelLines(viewModel, cursors, inSelectionMode, value);\n }\n }\n case 3 /* CursorMove.Direction.Down */: {\n if (unit === 2 /* CursorMove.Unit.WrappedLine */) {\n // Move down by view lines\n return this._moveDownByViewLines(viewModel, cursors, inSelectionMode, value);\n }\n else {\n // Move down by model lines\n return this._moveDownByModelLines(viewModel, cursors, inSelectionMode, value);\n }\n }\n case 4 /* CursorMove.Direction.PrevBlankLine */: {\n if (unit === 2 /* CursorMove.Unit.WrappedLine */) {\n return cursors.map(cursor => CursorState.fromViewState(MoveOperations.moveToPrevBlankLine(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode)));\n }\n else {\n return cursors.map(cursor => CursorState.fromModelState(MoveOperations.moveToPrevBlankLine(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode)));\n }\n }\n case 5 /* CursorMove.Direction.NextBlankLine */: {\n if (unit === 2 /* CursorMove.Unit.WrappedLine */) {\n return cursors.map(cursor => CursorState.fromViewState(MoveOperations.moveToNextBlankLine(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode)));\n }\n else {\n return cursors.map(cursor => CursorState.fromModelState(MoveOperations.moveToNextBlankLine(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode)));\n }\n }\n case 6 /* CursorMove.Direction.WrappedLineStart */: {\n // Move to the beginning of the current view line\n return this._moveToViewMinColumn(viewModel, cursors, inSelectionMode);\n }\n case 7 /* CursorMove.Direction.WrappedLineFirstNonWhitespaceCharacter */: {\n // Move to the first non-whitespace column of the current view line\n return this._moveToViewFirstNonWhitespaceColumn(viewModel, cursors, inSelectionMode);\n }\n case 8 /* CursorMove.Direction.WrappedLineColumnCenter */: {\n // Move to the \"center\" of the current view line\n return this._moveToViewCenterColumn(viewModel, cursors, inSelectionMode);\n }\n case 9 /* CursorMove.Direction.WrappedLineEnd */: {\n // Move to the end of the current view line\n return this._moveToViewMaxColumn(viewModel, cursors, inSelectionMode);\n }\n case 10 /* CursorMove.Direction.WrappedLineLastNonWhitespaceCharacter */: {\n // Move to the last non-whitespace column of the current view line\n return this._moveToViewLastNonWhitespaceColumn(viewModel, cursors, inSelectionMode);\n }\n default:\n return null;\n }\n }\n static viewportMove(viewModel, cursors, direction, inSelectionMode, value) {\n const visibleViewRange = viewModel.getCompletelyVisibleViewRange();\n const visibleModelRange = viewModel.coordinatesConverter.convertViewRangeToModelRange(visibleViewRange);\n switch (direction) {\n case 11 /* CursorMove.Direction.ViewPortTop */: {\n // Move to the nth line start in the viewport (from the top)\n const modelLineNumber = this._firstLineNumberInRange(viewModel.model, visibleModelRange, value);\n const modelColumn = viewModel.model.getLineFirstNonWhitespaceColumn(modelLineNumber);\n return [this._moveToModelPosition(viewModel, cursors[0], inSelectionMode, modelLineNumber, modelColumn)];\n }\n case 13 /* CursorMove.Direction.ViewPortBottom */: {\n // Move to the nth line start in the viewport (from the bottom)\n const modelLineNumber = this._lastLineNumberInRange(viewModel.model, visibleModelRange, value);\n const modelColumn = viewModel.model.getLineFirstNonWhitespaceColumn(modelLineNumber);\n return [this._moveToModelPosition(viewModel, cursors[0], inSelectionMode, modelLineNumber, modelColumn)];\n }\n case 12 /* CursorMove.Direction.ViewPortCenter */: {\n // Move to the line start in the viewport center\n const modelLineNumber = Math.round((visibleModelRange.startLineNumber + visibleModelRange.endLineNumber) / 2);\n const modelColumn = viewModel.model.getLineFirstNonWhitespaceColumn(modelLineNumber);\n return [this._moveToModelPosition(viewModel, cursors[0], inSelectionMode, modelLineNumber, modelColumn)];\n }\n case 14 /* CursorMove.Direction.ViewPortIfOutside */: {\n // Move to a position inside the viewport\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n result[i] = this.findPositionInViewportIfOutside(viewModel, cursor, visibleViewRange, inSelectionMode);\n }\n return result;\n }\n default:\n return null;\n }\n }\n static findPositionInViewportIfOutside(viewModel, cursor, visibleViewRange, inSelectionMode) {\n const viewLineNumber = cursor.viewState.position.lineNumber;\n if (visibleViewRange.startLineNumber <= viewLineNumber && viewLineNumber <= visibleViewRange.endLineNumber - 1) {\n // Nothing to do, cursor is in viewport\n return new CursorState(cursor.modelState, cursor.viewState);\n }\n else {\n let newViewLineNumber;\n if (viewLineNumber > visibleViewRange.endLineNumber - 1) {\n newViewLineNumber = visibleViewRange.endLineNumber - 1;\n }\n else if (viewLineNumber < visibleViewRange.startLineNumber) {\n newViewLineNumber = visibleViewRange.startLineNumber;\n }\n else {\n newViewLineNumber = viewLineNumber;\n }\n const position = MoveOperations.vertical(viewModel.cursorConfig, viewModel, viewLineNumber, cursor.viewState.position.column, cursor.viewState.leftoverVisibleColumns, newViewLineNumber, false);\n return CursorState.fromViewState(cursor.viewState.move(inSelectionMode, position.lineNumber, position.column, position.leftoverVisibleColumns));\n }\n }\n /**\n * Find the nth line start included in the range (from the start).\n */\n static _firstLineNumberInRange(model, range, count) {\n let startLineNumber = range.startLineNumber;\n if (range.startColumn !== model.getLineMinColumn(startLineNumber)) {\n // Move on to the second line if the first line start is not included in the range\n startLineNumber++;\n }\n return Math.min(range.endLineNumber, startLineNumber + count - 1);\n }\n /**\n * Find the nth line start included in the range (from the end).\n */\n static _lastLineNumberInRange(model, range, count) {\n let startLineNumber = range.startLineNumber;\n if (range.startColumn !== model.getLineMinColumn(startLineNumber)) {\n // Move on to the second line if the first line start is not included in the range\n startLineNumber++;\n }\n return Math.max(startLineNumber, range.endLineNumber - count + 1);\n }\n static _moveLeft(viewModel, cursors, inSelectionMode, noOfColumns) {\n return cursors.map(cursor => CursorState.fromViewState(MoveOperations.moveLeft(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, noOfColumns)));\n }\n static _moveHalfLineLeft(viewModel, cursors, inSelectionMode) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n const viewLineNumber = cursor.viewState.position.lineNumber;\n const halfLine = Math.round(viewModel.getLineContent(viewLineNumber).length / 2);\n result[i] = CursorState.fromViewState(MoveOperations.moveLeft(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, halfLine));\n }\n return result;\n }\n static _moveRight(viewModel, cursors, inSelectionMode, noOfColumns) {\n return cursors.map(cursor => CursorState.fromViewState(MoveOperations.moveRight(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, noOfColumns)));\n }\n static _moveHalfLineRight(viewModel, cursors, inSelectionMode) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n const viewLineNumber = cursor.viewState.position.lineNumber;\n const halfLine = Math.round(viewModel.getLineContent(viewLineNumber).length / 2);\n result[i] = CursorState.fromViewState(MoveOperations.moveRight(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, halfLine));\n }\n return result;\n }\n static _moveDownByViewLines(viewModel, cursors, inSelectionMode, linesCount) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n result[i] = CursorState.fromViewState(MoveOperations.moveDown(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, linesCount));\n }\n return result;\n }\n static _moveDownByModelLines(viewModel, cursors, inSelectionMode, linesCount) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n result[i] = CursorState.fromModelState(MoveOperations.moveDown(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode, linesCount));\n }\n return result;\n }\n static _moveUpByViewLines(viewModel, cursors, inSelectionMode, linesCount) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n result[i] = CursorState.fromViewState(MoveOperations.moveUp(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, linesCount));\n }\n return result;\n }\n static _moveUpByModelLines(viewModel, cursors, inSelectionMode, linesCount) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n result[i] = CursorState.fromModelState(MoveOperations.moveUp(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode, linesCount));\n }\n return result;\n }\n static _moveToViewPosition(viewModel, cursor, inSelectionMode, toViewLineNumber, toViewColumn) {\n return CursorState.fromViewState(cursor.viewState.move(inSelectionMode, toViewLineNumber, toViewColumn, 0));\n }\n static _moveToModelPosition(viewModel, cursor, inSelectionMode, toModelLineNumber, toModelColumn) {\n return CursorState.fromModelState(cursor.modelState.move(inSelectionMode, toModelLineNumber, toModelColumn, 0));\n }\n static _moveToViewMinColumn(viewModel, cursors, inSelectionMode) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n const viewLineNumber = cursor.viewState.position.lineNumber;\n const viewColumn = viewModel.getLineMinColumn(viewLineNumber);\n result[i] = this._moveToViewPosition(viewModel, cursor, inSelectionMode, viewLineNumber, viewColumn);\n }\n return result;\n }\n static _moveToViewFirstNonWhitespaceColumn(viewModel, cursors, inSelectionMode) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n const viewLineNumber = cursor.viewState.position.lineNumber;\n const viewColumn = viewModel.getLineFirstNonWhitespaceColumn(viewLineNumber);\n result[i] = this._moveToViewPosition(viewModel, cursor, inSelectionMode, viewLineNumber, viewColumn);\n }\n return result;\n }\n static _moveToViewCenterColumn(viewModel, cursors, inSelectionMode) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n const viewLineNumber = cursor.viewState.position.lineNumber;\n const viewColumn = Math.round((viewModel.getLineMaxColumn(viewLineNumber) + viewModel.getLineMinColumn(viewLineNumber)) / 2);\n result[i] = this._moveToViewPosition(viewModel, cursor, inSelectionMode, viewLineNumber, viewColumn);\n }\n return result;\n }\n static _moveToViewMaxColumn(viewModel, cursors, inSelectionMode) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n const viewLineNumber = cursor.viewState.position.lineNumber;\n const viewColumn = viewModel.getLineMaxColumn(viewLineNumber);\n result[i] = this._moveToViewPosition(viewModel, cursor, inSelectionMode, viewLineNumber, viewColumn);\n }\n return result;\n }\n static _moveToViewLastNonWhitespaceColumn(viewModel, cursors, inSelectionMode) {\n const result = [];\n for (let i = 0, len = cursors.length; i < len; i++) {\n const cursor = cursors[i];\n const viewLineNumber = cursor.viewState.position.lineNumber;\n const viewColumn = viewModel.getLineLastNonWhitespaceColumn(viewLineNumber);\n result[i] = this._moveToViewPosition(viewModel, cursor, inSelectionMode, viewLineNumber, viewColumn);\n }\n return result;\n }\n}\nexport var CursorMove;\n(function (CursorMove) {\n const isCursorMoveArgs = function (arg) {\n if (!types.isObject(arg)) {\n return false;\n }\n const cursorMoveArg = arg;\n if (!types.isString(cursorMoveArg.to)) {\n return false;\n }\n if (!types.isUndefined(cursorMoveArg.select) && !types.isBoolean(cursorMoveArg.select)) {\n return false;\n }\n if (!types.isUndefined(cursorMoveArg.by) && !types.isString(cursorMoveArg.by)) {\n return false;\n }\n if (!types.isUndefined(cursorMoveArg.value) && !types.isNumber(cursorMoveArg.value)) {\n return false;\n }\n return true;\n };\n CursorMove.description = {\n description: 'Move cursor to a logical position in the view',\n args: [\n {\n name: 'Cursor move argument object',\n description: `Property-value pairs that can be passed through this argument:\n\t\t\t\t\t* 'to': A mandatory logical position value providing where to move the cursor.\n\t\t\t\t\t\t\\`\\`\\`\n\t\t\t\t\t\t'left', 'right', 'up', 'down', 'prevBlankLine', 'nextBlankLine',\n\t\t\t\t\t\t'wrappedLineStart', 'wrappedLineEnd', 'wrappedLineColumnCenter'\n\t\t\t\t\t\t'wrappedLineFirstNonWhitespaceCharacter', 'wrappedLineLastNonWhitespaceCharacter'\n\t\t\t\t\t\t'viewPortTop', 'viewPortCenter', 'viewPortBottom', 'viewPortIfOutside'\n\t\t\t\t\t\t\\`\\`\\`\n\t\t\t\t\t* 'by': Unit to move. Default is computed based on 'to' value.\n\t\t\t\t\t\t\\`\\`\\`\n\t\t\t\t\t\t'line', 'wrappedLine', 'character', 'halfLine'\n\t\t\t\t\t\t\\`\\`\\`\n\t\t\t\t\t* 'value': Number of units to move. Default is '1'.\n\t\t\t\t\t* 'select': If 'true' makes the selection. Default is 'false'.\n\t\t\t\t`,\n constraint: isCursorMoveArgs,\n schema: {\n 'type': 'object',\n 'required': ['to'],\n 'properties': {\n 'to': {\n 'type': 'string',\n 'enum': ['left', 'right', 'up', 'down', 'prevBlankLine', 'nextBlankLine', 'wrappedLineStart', 'wrappedLineEnd', 'wrappedLineColumnCenter', 'wrappedLineFirstNonWhitespaceCharacter', 'wrappedLineLastNonWhitespaceCharacter', 'viewPortTop', 'viewPortCenter', 'viewPortBottom', 'viewPortIfOutside']\n },\n 'by': {\n 'type': 'string',\n 'enum': ['line', 'wrappedLine', 'character', 'halfLine']\n },\n 'value': {\n 'type': 'number',\n 'default': 1\n },\n 'select': {\n 'type': 'boolean',\n 'default': false\n }\n }\n }\n }\n ]\n };\n /**\n * Positions in the view for cursor move command.\n */\n CursorMove.RawDirection = {\n Left: 'left',\n Right: 'right',\n Up: 'up',\n Down: 'down',\n PrevBlankLine: 'prevBlankLine',\n NextBlankLine: 'nextBlankLine',\n WrappedLineStart: 'wrappedLineStart',\n WrappedLineFirstNonWhitespaceCharacter: 'wrappedLineFirstNonWhitespaceCharacter',\n WrappedLineColumnCenter: 'wrappedLineColumnCenter',\n WrappedLineEnd: 'wrappedLineEnd',\n WrappedLineLastNonWhitespaceCharacter: 'wrappedLineLastNonWhitespaceCharacter',\n ViewPortTop: 'viewPortTop',\n ViewPortCenter: 'viewPortCenter',\n ViewPortBottom: 'viewPortBottom',\n ViewPortIfOutside: 'viewPortIfOutside'\n };\n /**\n * Units for Cursor move 'by' argument\n */\n CursorMove.RawUnit = {\n Line: 'line',\n WrappedLine: 'wrappedLine',\n Character: 'character',\n HalfLine: 'halfLine'\n };\n function parse(args) {\n if (!args.to) {\n // illegal arguments\n return null;\n }\n let direction;\n switch (args.to) {\n case CursorMove.RawDirection.Left:\n direction = 0 /* Direction.Left */;\n break;\n case CursorMove.RawDirection.Right:\n direction = 1 /* Direction.Right */;\n break;\n case CursorMove.RawDirection.Up:\n direction = 2 /* Direction.Up */;\n break;\n case CursorMove.RawDirection.Down:\n direction = 3 /* Direction.Down */;\n break;\n case CursorMove.RawDirection.PrevBlankLine:\n direction = 4 /* Direction.PrevBlankLine */;\n break;\n case CursorMove.RawDirection.NextBlankLine:\n direction = 5 /* Direction.NextBlankLine */;\n break;\n case CursorMove.RawDirection.WrappedLineStart:\n direction = 6 /* Direction.WrappedLineStart */;\n break;\n case CursorMove.RawDirection.WrappedLineFirstNonWhitespaceCharacter:\n direction = 7 /* Direction.WrappedLineFirstNonWhitespaceCharacter */;\n break;\n case CursorMove.RawDirection.WrappedLineColumnCenter:\n direction = 8 /* Direction.WrappedLineColumnCenter */;\n break;\n case CursorMove.RawDirection.WrappedLineEnd:\n direction = 9 /* Direction.WrappedLineEnd */;\n break;\n case CursorMove.RawDirection.WrappedLineLastNonWhitespaceCharacter:\n direction = 10 /* Direction.WrappedLineLastNonWhitespaceCharacter */;\n break;\n case CursorMove.RawDirection.ViewPortTop:\n direction = 11 /* Direction.ViewPortTop */;\n break;\n case CursorMove.RawDirection.ViewPortBottom:\n direction = 13 /* Direction.ViewPortBottom */;\n break;\n case CursorMove.RawDirection.ViewPortCenter:\n direction = 12 /* Direction.ViewPortCenter */;\n break;\n case CursorMove.RawDirection.ViewPortIfOutside:\n direction = 14 /* Direction.ViewPortIfOutside */;\n break;\n default:\n // illegal arguments\n return null;\n }\n let unit = 0 /* Unit.None */;\n switch (args.by) {\n case CursorMove.RawUnit.Line:\n unit = 1 /* Unit.Line */;\n break;\n case CursorMove.RawUnit.WrappedLine:\n unit = 2 /* Unit.WrappedLine */;\n break;\n case CursorMove.RawUnit.Character:\n unit = 3 /* Unit.Character */;\n break;\n case CursorMove.RawUnit.HalfLine:\n unit = 4 /* Unit.HalfLine */;\n break;\n }\n return {\n direction: direction,\n unit: unit,\n select: (!!args.select),\n value: (args.value || 1)\n };\n }\n CursorMove.parse = parse;\n})(CursorMove || (CursorMove = {}));\n","/*---------------------------------------------------------------------------------------------\n * 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 { SingleCursorState } from '../cursorCommon.js';\nimport { CursorColumns } from '../core/cursorColumns.js';\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nimport * as strings from '../../../base/common/strings.js';\nimport { AtomicTabMoveOperations } from './cursorAtomicMoveOperations.js';\nexport class CursorPosition {\n constructor(lineNumber, column, leftoverVisibleColumns) {\n this._cursorPositionBrand = undefined;\n this.lineNumber = lineNumber;\n this.column = column;\n this.leftoverVisibleColumns = leftoverVisibleColumns;\n }\n}\nexport class MoveOperations {\n static leftPosition(model, position) {\n if (position.column > model.getLineMinColumn(position.lineNumber)) {\n return position.delta(undefined, -strings.prevCharLength(model.getLineContent(position.lineNumber), position.column - 1));\n }\n else if (position.lineNumber > 1) {\n const newLineNumber = position.lineNumber - 1;\n return new Position(newLineNumber, model.getLineMaxColumn(newLineNumber));\n }\n else {\n return position;\n }\n }\n static leftPositionAtomicSoftTabs(model, position, tabSize) {\n if (position.column <= model.getLineIndentColumn(position.lineNumber)) {\n const minColumn = model.getLineMinColumn(position.lineNumber);\n const lineContent = model.getLineContent(position.lineNumber);\n const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - 1, tabSize, 0 /* Direction.Left */);\n if (newPosition !== -1 && newPosition + 1 >= minColumn) {\n return new Position(position.lineNumber, newPosition + 1);\n }\n }\n return this.leftPosition(model, position);\n }\n static left(config, model, position) {\n const pos = config.stickyTabStops\n ? MoveOperations.leftPositionAtomicSoftTabs(model, position, config.tabSize)\n : MoveOperations.leftPosition(model, position);\n return new CursorPosition(pos.lineNumber, pos.column, 0);\n }\n /**\n * @param noOfColumns Must be either `1`\n * or `Math.round(viewModel.getLineContent(viewLineNumber).length / 2)` (for half lines).\n */\n static moveLeft(config, model, cursor, inSelectionMode, noOfColumns) {\n let lineNumber, column;\n if (cursor.hasSelection() && !inSelectionMode) {\n // If the user has a selection and does not want to extend it,\n // put the cursor at the beginning of the selection.\n lineNumber = cursor.selection.startLineNumber;\n column = cursor.selection.startColumn;\n }\n else {\n // This has no effect if noOfColumns === 1.\n // It is ok to do so in the half-line scenario.\n const pos = cursor.position.delta(undefined, -(noOfColumns - 1));\n // We clip the position before normalization, as normalization is not defined\n // for possibly negative columns.\n const normalizedPos = model.normalizePosition(MoveOperations.clipPositionColumn(pos, model), 0 /* PositionAffinity.Left */);\n const p = MoveOperations.left(config, model, normalizedPos);\n lineNumber = p.lineNumber;\n column = p.column;\n }\n return cursor.move(inSelectionMode, lineNumber, column, 0);\n }\n /**\n * Adjusts the column so that it is within min/max of the line.\n */\n static clipPositionColumn(position, model) {\n return new Position(position.lineNumber, MoveOperations.clipRange(position.column, model.getLineMinColumn(position.lineNumber), model.getLineMaxColumn(position.lineNumber)));\n }\n static clipRange(value, min, max) {\n if (value < min) {\n return min;\n }\n if (value > max) {\n return max;\n }\n return value;\n }\n static rightPosition(model, lineNumber, column) {\n if (column < model.getLineMaxColumn(lineNumber)) {\n column = column + strings.nextCharLength(model.getLineContent(lineNumber), column - 1);\n }\n else if (lineNumber < model.getLineCount()) {\n lineNumber = lineNumber + 1;\n column = model.getLineMinColumn(lineNumber);\n }\n return new Position(lineNumber, column);\n }\n static rightPositionAtomicSoftTabs(model, lineNumber, column, tabSize, indentSize) {\n if (column < model.getLineIndentColumn(lineNumber)) {\n const lineContent = model.getLineContent(lineNumber);\n const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - 1, tabSize, 1 /* Direction.Right */);\n if (newPosition !== -1) {\n return new Position(lineNumber, newPosition + 1);\n }\n }\n return this.rightPosition(model, lineNumber, column);\n }\n static right(config, model, position) {\n const pos = config.stickyTabStops\n ? MoveOperations.rightPositionAtomicSoftTabs(model, position.lineNumber, position.column, config.tabSize, config.indentSize)\n : MoveOperations.rightPosition(model, position.lineNumber, position.column);\n return new CursorPosition(pos.lineNumber, pos.column, 0);\n }\n static moveRight(config, model, cursor, inSelectionMode, noOfColumns) {\n let lineNumber, column;\n if (cursor.hasSelection() && !inSelectionMode) {\n // If we are in selection mode, move right without selection cancels selection and puts cursor at the end of the selection\n lineNumber = cursor.selection.endLineNumber;\n column = cursor.selection.endColumn;\n }\n else {\n const pos = cursor.position.delta(undefined, noOfColumns - 1);\n const normalizedPos = model.normalizePosition(MoveOperations.clipPositionColumn(pos, model), 1 /* PositionAffinity.Right */);\n const r = MoveOperations.right(config, model, normalizedPos);\n lineNumber = r.lineNumber;\n column = r.column;\n }\n return cursor.move(inSelectionMode, lineNumber, column, 0);\n }\n static vertical(config, model, lineNumber, column, leftoverVisibleColumns, newLineNumber, allowMoveOnEdgeLine, normalizationAffinity) {\n const currentVisibleColumn = CursorColumns.visibleColumnFromColumn(model.getLineContent(lineNumber), column, config.tabSize) + leftoverVisibleColumns;\n const lineCount = model.getLineCount();\n const wasOnFirstPosition = (lineNumber === 1 && column === 1);\n const wasOnLastPosition = (lineNumber === lineCount && column === model.getLineMaxColumn(lineNumber));\n const wasAtEdgePosition = (newLineNumber < lineNumber ? wasOnFirstPosition : wasOnLastPosition);\n lineNumber = newLineNumber;\n if (lineNumber < 1) {\n lineNumber = 1;\n if (allowMoveOnEdgeLine) {\n column = model.getLineMinColumn(lineNumber);\n }\n else {\n column = Math.min(model.getLineMaxColumn(lineNumber), column);\n }\n }\n else if (lineNumber > lineCount) {\n lineNumber = lineCount;\n if (allowMoveOnEdgeLine) {\n column = model.getLineMaxColumn(lineNumber);\n }\n else {\n column = Math.min(model.getLineMaxColumn(lineNumber), column);\n }\n }\n else {\n column = config.columnFromVisibleColumn(model, lineNumber, currentVisibleColumn);\n }\n if (wasAtEdgePosition) {\n leftoverVisibleColumns = 0;\n }\n else {\n leftoverVisibleColumns = currentVisibleColumn - CursorColumns.visibleColumnFromColumn(model.getLineContent(lineNumber), column, config.tabSize);\n }\n if (normalizationAffinity !== undefined) {\n const position = new Position(lineNumber, column);\n const newPosition = model.normalizePosition(position, normalizationAffinity);\n leftoverVisibleColumns = leftoverVisibleColumns + (column - newPosition.column);\n lineNumber = newPosition.lineNumber;\n column = newPosition.column;\n }\n return new CursorPosition(lineNumber, column, leftoverVisibleColumns);\n }\n static down(config, model, lineNumber, column, leftoverVisibleColumns, count, allowMoveOnLastLine) {\n return this.vertical(config, model, lineNumber, column, leftoverVisibleColumns, lineNumber + count, allowMoveOnLastLine, 4 /* PositionAffinity.RightOfInjectedText */);\n }\n static moveDown(config, model, cursor, inSelectionMode, linesCount) {\n let lineNumber, column;\n if (cursor.hasSelection() && !inSelectionMode) {\n // If we are in selection mode, move down acts relative to the end of selection\n lineNumber = cursor.selection.endLineNumber;\n column = cursor.selection.endColumn;\n }\n else {\n lineNumber = cursor.position.lineNumber;\n column = cursor.position.column;\n }\n const r = MoveOperations.down(config, model, lineNumber, column, cursor.leftoverVisibleColumns, linesCount, true);\n return cursor.move(inSelectionMode, r.lineNumber, r.column, r.leftoverVisibleColumns);\n }\n static translateDown(config, model, cursor) {\n const selection = cursor.selection;\n const selectionStart = MoveOperations.down(config, model, selection.selectionStartLineNumber, selection.selectionStartColumn, cursor.selectionStartLeftoverVisibleColumns, 1, false);\n const position = MoveOperations.down(config, model, selection.positionLineNumber, selection.positionColumn, cursor.leftoverVisibleColumns, 1, false);\n return new SingleCursorState(new Range(selectionStart.lineNumber, selectionStart.column, selectionStart.lineNumber, selectionStart.column), selectionStart.leftoverVisibleColumns, new Position(position.lineNumber, position.column), position.leftoverVisibleColumns);\n }\n static up(config, model, lineNumber, column, leftoverVisibleColumns, count, allowMoveOnFirstLine) {\n return this.vertical(config, model, lineNumber, column, leftoverVisibleColumns, lineNumber - count, allowMoveOnFirstLine, 3 /* PositionAffinity.LeftOfInjectedText */);\n }\n static moveUp(config, model, cursor, inSelectionMode, linesCount) {\n let lineNumber, column;\n if (cursor.hasSelection() && !inSelectionMode) {\n // If we are in selection mode, move up acts relative to the beginning of selection\n lineNumber = cursor.selection.startLineNumber;\n column = cursor.selection.startColumn;\n }\n else {\n lineNumber = cursor.position.lineNumber;\n column = cursor.position.column;\n }\n const r = MoveOperations.up(config, model, lineNumber, column, cursor.leftoverVisibleColumns, linesCount, true);\n return cursor.move(inSelectionMode, r.lineNumber, r.column, r.leftoverVisibleColumns);\n }\n static translateUp(config, model, cursor) {\n const selection = cursor.selection;\n const selectionStart = MoveOperations.up(config, model, selection.selectionStartLineNumber, selection.selectionStartColumn, cursor.selectionStartLeftoverVisibleColumns, 1, false);\n const position = MoveOperations.up(config, model, selection.positionLineNumber, selection.positionColumn, cursor.leftoverVisibleColumns, 1, false);\n return new SingleCursorState(new Range(selectionStart.lineNumber, selectionStart.column, selectionStart.lineNumber, selectionStart.column), selectionStart.leftoverVisibleColumns, new Position(position.lineNumber, position.column), position.leftoverVisibleColumns);\n }\n static _isBlankLine(model, lineNumber) {\n if (model.getLineFirstNonWhitespaceColumn(lineNumber) === 0) {\n // empty or contains only whitespace\n return true;\n }\n return false;\n }\n static moveToPrevBlankLine(config, model, cursor, inSelectionMode) {\n let lineNumber = cursor.position.lineNumber;\n // If our current line is blank, move to the previous non-blank line\n while (lineNumber > 1 && this._isBlankLine(model, lineNumber)) {\n lineNumber--;\n }\n // Find the previous blank line\n while (lineNumber > 1 && !this._isBlankLine(model, lineNumber)) {\n lineNumber--;\n }\n return cursor.move(inSelectionMode, lineNumber, model.getLineMinColumn(lineNumber), 0);\n }\n static moveToNextBlankLine(config, model, cursor, inSelectionMode) {\n const lineCount = model.getLineCount();\n let lineNumber = cursor.position.lineNumber;\n // If our current line is blank, move to the next non-blank line\n while (lineNumber < lineCount && this._isBlankLine(model, lineNumber)) {\n lineNumber++;\n }\n // Find the next blank line\n while (lineNumber < lineCount && !this._isBlankLine(model, lineNumber)) {\n lineNumber++;\n }\n return cursor.move(inSelectionMode, lineNumber, model.getLineMinColumn(lineNumber), 0);\n }\n static moveToBeginningOfLine(config, model, cursor, inSelectionMode) {\n const lineNumber = cursor.position.lineNumber;\n const minColumn = model.getLineMinColumn(lineNumber);\n const firstNonBlankColumn = model.getLineFirstNonWhitespaceColumn(lineNumber) || minColumn;\n let column;\n const relevantColumnNumber = cursor.position.column;\n if (relevantColumnNumber === firstNonBlankColumn) {\n column = minColumn;\n }\n else {\n column = firstNonBlankColumn;\n }\n return cursor.move(inSelectionMode, lineNumber, column, 0);\n }\n static moveToEndOfLine(config, model, cursor, inSelectionMode, sticky) {\n const lineNumber = cursor.position.lineNumber;\n const maxColumn = model.getLineMaxColumn(lineNumber);\n return cursor.move(inSelectionMode, lineNumber, maxColumn, sticky ? 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */ - maxColumn : 0);\n }\n static moveToBeginningOfBuffer(config, model, cursor, inSelectionMode) {\n return cursor.move(inSelectionMode, 1, 1, 0);\n }\n static moveToEndOfBuffer(config, model, cursor, inSelectionMode) {\n const lastLineNumber = model.getLineCount();\n const lastColumn = model.getLineMaxColumn(lastLineNumber);\n return cursor.move(inSelectionMode, lastLineNumber, lastColumn, 0);\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 *--------------------------------------------------------------------------------------------*/\nimport { Range } from '../core/range.js';\nimport { Selection } from '../core/selection.js';\nexport class SurroundSelectionCommand {\n constructor(range, charBeforeSelection, charAfterSelection) {\n this._range = range;\n this._charBeforeSelection = charBeforeSelection;\n this._charAfterSelection = charAfterSelection;\n }\n getEditOperations(model, builder) {\n builder.addTrackedEditOperation(new Range(this._range.startLineNumber, this._range.startColumn, this._range.startLineNumber, this._range.startColumn), this._charBeforeSelection);\n builder.addTrackedEditOperation(new Range(this._range.endLineNumber, this._range.endColumn, this._range.endLineNumber, this._range.endColumn), this._charAfterSelection);\n }\n computeCursorState(model, helper) {\n const inverseEditOperations = helper.getInverseEditOperations();\n const firstOperationRange = inverseEditOperations[0].range;\n const secondOperationRange = inverseEditOperations[1].range;\n return new Selection(firstOperationRange.endLineNumber, firstOperationRange.endColumn, secondOperationRange.endLineNumber, secondOperationRange.endColumn - this._charAfterSelection.length);\n }\n}\n/**\n * A surround selection command that runs after composition finished.\n */\nexport class CompositionSurroundSelectionCommand {\n constructor(_position, _text, _charAfter) {\n this._position = _position;\n this._text = _text;\n this._charAfter = _charAfter;\n }\n getEditOperations(model, builder) {\n builder.addTrackedEditOperation(new Range(this._position.lineNumber, this._position.column, this._position.lineNumber, this._position.column), this._text + this._charAfter);\n }\n computeCursorState(model, helper) {\n const inverseEditOperations = helper.getInverseEditOperations();\n const opRange = inverseEditOperations[0].range;\n return new Selection(opRange.endLineNumber, opRange.startColumn, opRange.endLineNumber, opRange.endColumn - this._charAfter.length);\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 *--------------------------------------------------------------------------------------------*/\nimport { onUnexpectedError } from '../../../base/common/errors.js';\nimport * as strings from '../../../base/common/strings.js';\nimport { ReplaceCommand, ReplaceCommandWithOffsetCursorState, ReplaceCommandWithoutChangingPosition, ReplaceCommandThatPreservesSelection } from '../commands/replaceCommand.js';\nimport { ShiftCommand } from '../commands/shiftCommand.js';\nimport { CompositionSurroundSelectionCommand, SurroundSelectionCommand } from '../commands/surroundSelectionCommand.js';\nimport { EditOperationResult, isQuote } from '../cursorCommon.js';\nimport { getMapForWordSeparators } from '../core/wordCharacterClassifier.js';\nimport { Range } from '../core/range.js';\nimport { Position } from '../core/position.js';\nimport { IndentAction } from '../languages/languageConfiguration.js';\nimport { getIndentationAtPosition } from '../languages/languageConfigurationRegistry.js';\nimport { createScopedLineTokens } from '../languages/supports.js';\nimport { getIndentActionForType, getIndentForEnter, getInheritIndentForLine } from '../languages/autoIndent.js';\nimport { getEnterAction } from '../languages/enterAction.js';\nexport class TypeOperations {\n static indent(config, model, selections) {\n if (model === null || selections === null) {\n return [];\n }\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n commands[i] = new ShiftCommand(selections[i], {\n isUnshift: false,\n tabSize: config.tabSize,\n indentSize: config.indentSize,\n insertSpaces: config.insertSpaces,\n useTabStops: config.useTabStops,\n autoIndent: config.autoIndent\n }, config.languageConfigurationService);\n }\n return commands;\n }\n static outdent(config, model, selections) {\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n commands[i] = new ShiftCommand(selections[i], {\n isUnshift: true,\n tabSize: config.tabSize,\n indentSize: config.indentSize,\n insertSpaces: config.insertSpaces,\n useTabStops: config.useTabStops,\n autoIndent: config.autoIndent\n }, config.languageConfigurationService);\n }\n return commands;\n }\n static shiftIndent(config, indentation, count) {\n count = count || 1;\n return ShiftCommand.shiftIndent(indentation, indentation.length + count, config.tabSize, config.indentSize, config.insertSpaces);\n }\n static unshiftIndent(config, indentation, count) {\n count = count || 1;\n return ShiftCommand.unshiftIndent(indentation, indentation.length + count, config.tabSize, config.indentSize, config.insertSpaces);\n }\n static _distributedPaste(config, model, selections, text) {\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n commands[i] = new ReplaceCommand(selections[i], text[i]);\n }\n return new EditOperationResult(0 /* EditOperationType.Other */, commands, {\n shouldPushStackElementBefore: true,\n shouldPushStackElementAfter: true\n });\n }\n static _simplePaste(config, model, selections, text, pasteOnNewLine) {\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n const selection = selections[i];\n const position = selection.getPosition();\n if (pasteOnNewLine && !selection.isEmpty()) {\n pasteOnNewLine = false;\n }\n if (pasteOnNewLine && text.indexOf('\\n') !== text.length - 1) {\n pasteOnNewLine = false;\n }\n if (pasteOnNewLine) {\n // Paste entire line at the beginning of line\n const typeSelection = new Range(position.lineNumber, 1, position.lineNumber, 1);\n commands[i] = new ReplaceCommandThatPreservesSelection(typeSelection, text, selection, true);\n }\n else {\n commands[i] = new ReplaceCommand(selection, text);\n }\n }\n return new EditOperationResult(0 /* EditOperationType.Other */, commands, {\n shouldPushStackElementBefore: true,\n shouldPushStackElementAfter: true\n });\n }\n static _distributePasteToCursors(config, selections, text, pasteOnNewLine, multicursorText) {\n if (pasteOnNewLine) {\n return null;\n }\n if (selections.length === 1) {\n return null;\n }\n if (multicursorText && multicursorText.length === selections.length) {\n return multicursorText;\n }\n if (config.multiCursorPaste === 'spread') {\n // Try to spread the pasted text in case the line count matches the cursor count\n // Remove trailing \\n if present\n if (text.charCodeAt(text.length - 1) === 10 /* CharCode.LineFeed */) {\n text = text.substr(0, text.length - 1);\n }\n // Remove trailing \\r if present\n if (text.charCodeAt(text.length - 1) === 13 /* CharCode.CarriageReturn */) {\n text = text.substr(0, text.length - 1);\n }\n const lines = strings.splitLines(text);\n if (lines.length === selections.length) {\n return lines;\n }\n }\n return null;\n }\n static paste(config, model, selections, text, pasteOnNewLine, multicursorText) {\n const distributedPaste = this._distributePasteToCursors(config, selections, text, pasteOnNewLine, multicursorText);\n if (distributedPaste) {\n selections = selections.sort(Range.compareRangesUsingStarts);\n return this._distributedPaste(config, model, selections, distributedPaste);\n }\n else {\n return this._simplePaste(config, model, selections, text, pasteOnNewLine);\n }\n }\n static _goodIndentForLine(config, model, lineNumber) {\n let action = null;\n let indentation = '';\n const expectedIndentAction = getInheritIndentForLine(config.autoIndent, model, lineNumber, false, config.languageConfigurationService);\n if (expectedIndentAction) {\n action = expectedIndentAction.action;\n indentation = expectedIndentAction.indentation;\n }\n else if (lineNumber > 1) {\n let lastLineNumber;\n for (lastLineNumber = lineNumber - 1; lastLineNumber >= 1; lastLineNumber--) {\n const lineText = model.getLineContent(lastLineNumber);\n const nonWhitespaceIdx = strings.lastNonWhitespaceIndex(lineText);\n if (nonWhitespaceIdx >= 0) {\n break;\n }\n }\n if (lastLineNumber < 1) {\n // No previous line with content found\n return null;\n }\n const maxColumn = model.getLineMaxColumn(lastLineNumber);\n const expectedEnterAction = getEnterAction(config.autoIndent, model, new Range(lastLineNumber, maxColumn, lastLineNumber, maxColumn), config.languageConfigurationService);\n if (expectedEnterAction) {\n indentation = expectedEnterAction.indentation + expectedEnterAction.appendText;\n }\n }\n if (action) {\n if (action === IndentAction.Indent) {\n indentation = TypeOperations.shiftIndent(config, indentation);\n }\n if (action === IndentAction.Outdent) {\n indentation = TypeOperations.unshiftIndent(config, indentation);\n }\n indentation = config.normalizeIndentation(indentation);\n }\n if (!indentation) {\n return null;\n }\n return indentation;\n }\n static _replaceJumpToNextIndent(config, model, selection, insertsAutoWhitespace) {\n let typeText = '';\n const position = selection.getStartPosition();\n if (config.insertSpaces) {\n const visibleColumnFromColumn = config.visibleColumnFromColumn(model, position);\n const indentSize = config.indentSize;\n const spacesCnt = indentSize - (visibleColumnFromColumn % indentSize);\n for (let i = 0; i < spacesCnt; i++) {\n typeText += ' ';\n }\n }\n else {\n typeText = '\\t';\n }\n return new ReplaceCommand(selection, typeText, insertsAutoWhitespace);\n }\n static tab(config, model, selections) {\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n const selection = selections[i];\n if (selection.isEmpty()) {\n const lineText = model.getLineContent(selection.startLineNumber);\n if (/^\\s*$/.test(lineText) && model.tokenization.isCheapToTokenize(selection.startLineNumber)) {\n let goodIndent = this._goodIndentForLine(config, model, selection.startLineNumber);\n goodIndent = goodIndent || '\\t';\n const possibleTypeText = config.normalizeIndentation(goodIndent);\n if (!lineText.startsWith(possibleTypeText)) {\n commands[i] = new ReplaceCommand(new Range(selection.startLineNumber, 1, selection.startLineNumber, lineText.length + 1), possibleTypeText, true);\n continue;\n }\n }\n commands[i] = this._replaceJumpToNextIndent(config, model, selection, true);\n }\n else {\n if (selection.startLineNumber === selection.endLineNumber) {\n const lineMaxColumn = model.getLineMaxColumn(selection.startLineNumber);\n if (selection.startColumn !== 1 || selection.endColumn !== lineMaxColumn) {\n // This is a single line selection that is not the entire line\n commands[i] = this._replaceJumpToNextIndent(config, model, selection, false);\n continue;\n }\n }\n commands[i] = new ShiftCommand(selection, {\n isUnshift: false,\n tabSize: config.tabSize,\n indentSize: config.indentSize,\n insertSpaces: config.insertSpaces,\n useTabStops: config.useTabStops,\n autoIndent: config.autoIndent\n }, config.languageConfigurationService);\n }\n }\n return commands;\n }\n static compositionType(prevEditOperationType, config, model, selections, text, replacePrevCharCnt, replaceNextCharCnt, positionDelta) {\n const commands = selections.map(selection => this._compositionType(model, selection, text, replacePrevCharCnt, replaceNextCharCnt, positionDelta));\n return new EditOperationResult(4 /* EditOperationType.TypingOther */, commands, {\n shouldPushStackElementBefore: shouldPushStackElementBetween(prevEditOperationType, 4 /* EditOperationType.TypingOther */),\n shouldPushStackElementAfter: false\n });\n }\n static _compositionType(model, selection, text, replacePrevCharCnt, replaceNextCharCnt, positionDelta) {\n if (!selection.isEmpty()) {\n // looks like https://github.com/microsoft/vscode/issues/2773\n // where a cursor operation occurred before a canceled composition\n // => ignore composition\n return null;\n }\n const pos = selection.getPosition();\n const startColumn = Math.max(1, pos.column - replacePrevCharCnt);\n const endColumn = Math.min(model.getLineMaxColumn(pos.lineNumber), pos.column + replaceNextCharCnt);\n const range = new Range(pos.lineNumber, startColumn, pos.lineNumber, endColumn);\n const oldText = model.getValueInRange(range);\n if (oldText === text && positionDelta === 0) {\n // => ignore composition that doesn't do anything\n return null;\n }\n return new ReplaceCommandWithOffsetCursorState(range, text, 0, positionDelta);\n }\n static _typeCommand(range, text, keepPosition) {\n if (keepPosition) {\n return new ReplaceCommandWithoutChangingPosition(range, text, true);\n }\n else {\n return new ReplaceCommand(range, text, true);\n }\n }\n static _enter(config, model, keepPosition, range) {\n if (config.autoIndent === 0 /* EditorAutoIndentStrategy.None */) {\n return TypeOperations._typeCommand(range, '\\n', keepPosition);\n }\n if (!model.tokenization.isCheapToTokenize(range.getStartPosition().lineNumber) || config.autoIndent === 1 /* EditorAutoIndentStrategy.Keep */) {\n const lineText = model.getLineContent(range.startLineNumber);\n const indentation = strings.getLeadingWhitespace(lineText).substring(0, range.startColumn - 1);\n return TypeOperations._typeCommand(range, '\\n' + config.normalizeIndentation(indentation), keepPosition);\n }\n const r = getEnterAction(config.autoIndent, model, range, config.languageConfigurationService);\n if (r) {\n if (r.indentAction === IndentAction.None) {\n // Nothing special\n return TypeOperations._typeCommand(range, '\\n' + config.normalizeIndentation(r.indentation + r.appendText), keepPosition);\n }\n else if (r.indentAction === IndentAction.Indent) {\n // Indent once\n return TypeOperations._typeCommand(range, '\\n' + config.normalizeIndentation(r.indentation + r.appendText), keepPosition);\n }\n else if (r.indentAction === IndentAction.IndentOutdent) {\n // Ultra special\n const normalIndent = config.normalizeIndentation(r.indentation);\n const increasedIndent = config.normalizeIndentation(r.indentation + r.appendText);\n const typeText = '\\n' + increasedIndent + '\\n' + normalIndent;\n if (keepPosition) {\n return new ReplaceCommandWithoutChangingPosition(range, typeText, true);\n }\n else {\n return new ReplaceCommandWithOffsetCursorState(range, typeText, -1, increasedIndent.length - normalIndent.length, true);\n }\n }\n else if (r.indentAction === IndentAction.Outdent) {\n const actualIndentation = TypeOperations.unshiftIndent(config, r.indentation);\n return TypeOperations._typeCommand(range, '\\n' + config.normalizeIndentation(actualIndentation + r.appendText), keepPosition);\n }\n }\n const lineText = model.getLineContent(range.startLineNumber);\n const indentation = strings.getLeadingWhitespace(lineText).substring(0, range.startColumn - 1);\n if (config.autoIndent >= 4 /* EditorAutoIndentStrategy.Full */) {\n const ir = getIndentForEnter(config.autoIndent, model, range, {\n unshiftIndent: (indent) => {\n return TypeOperations.unshiftIndent(config, indent);\n },\n shiftIndent: (indent) => {\n return TypeOperations.shiftIndent(config, indent);\n },\n normalizeIndentation: (indent) => {\n return config.normalizeIndentation(indent);\n }\n }, config.languageConfigurationService);\n if (ir) {\n let oldEndViewColumn = config.visibleColumnFromColumn(model, range.getEndPosition());\n const oldEndColumn = range.endColumn;\n const newLineContent = model.getLineContent(range.endLineNumber);\n const firstNonWhitespace = strings.firstNonWhitespaceIndex(newLineContent);\n if (firstNonWhitespace >= 0) {\n range = range.setEndPosition(range.endLineNumber, Math.max(range.endColumn, firstNonWhitespace + 1));\n }\n else {\n range = range.setEndPosition(range.endLineNumber, model.getLineMaxColumn(range.endLineNumber));\n }\n if (keepPosition) {\n return new ReplaceCommandWithoutChangingPosition(range, '\\n' + config.normalizeIndentation(ir.afterEnter), true);\n }\n else {\n let offset = 0;\n if (oldEndColumn <= firstNonWhitespace + 1) {\n if (!config.insertSpaces) {\n oldEndViewColumn = Math.ceil(oldEndViewColumn / config.indentSize);\n }\n offset = Math.min(oldEndViewColumn + 1 - config.normalizeIndentation(ir.afterEnter).length - 1, 0);\n }\n return new ReplaceCommandWithOffsetCursorState(range, '\\n' + config.normalizeIndentation(ir.afterEnter), 0, offset, true);\n }\n }\n }\n return TypeOperations._typeCommand(range, '\\n' + config.normalizeIndentation(indentation), keepPosition);\n }\n static _isAutoIndentType(config, model, selections) {\n if (config.autoIndent < 4 /* EditorAutoIndentStrategy.Full */) {\n return false;\n }\n for (let i = 0, len = selections.length; i < len; i++) {\n if (!model.tokenization.isCheapToTokenize(selections[i].getEndPosition().lineNumber)) {\n return false;\n }\n }\n return true;\n }\n static _runAutoIndentType(config, model, range, ch) {\n const currentIndentation = getIndentationAtPosition(model, range.startLineNumber, range.startColumn);\n const actualIndentation = getIndentActionForType(config.autoIndent, model, range, ch, {\n shiftIndent: (indentation) => {\n return TypeOperations.shiftIndent(config, indentation);\n },\n unshiftIndent: (indentation) => {\n return TypeOperations.unshiftIndent(config, indentation);\n },\n }, config.languageConfigurationService);\n if (actualIndentation === null) {\n return null;\n }\n if (actualIndentation !== config.normalizeIndentation(currentIndentation)) {\n const firstNonWhitespace = model.getLineFirstNonWhitespaceColumn(range.startLineNumber);\n if (firstNonWhitespace === 0) {\n return TypeOperations._typeCommand(new Range(range.startLineNumber, 1, range.endLineNumber, range.endColumn), config.normalizeIndentation(actualIndentation) + ch, false);\n }\n else {\n return TypeOperations._typeCommand(new Range(range.startLineNumber, 1, range.endLineNumber, range.endColumn), config.normalizeIndentation(actualIndentation) +\n model.getLineContent(range.startLineNumber).substring(firstNonWhitespace - 1, range.startColumn - 1) + ch, false);\n }\n }\n return null;\n }\n static _isAutoClosingOvertype(config, model, selections, autoClosedCharacters, ch) {\n if (config.autoClosingOvertype === 'never') {\n return false;\n }\n if (!config.autoClosingPairs.autoClosingPairsCloseSingleChar.has(ch)) {\n return false;\n }\n for (let i = 0, len = selections.length; i < len; i++) {\n const selection = selections[i];\n if (!selection.isEmpty()) {\n return false;\n }\n const position = selection.getPosition();\n const lineText = model.getLineContent(position.lineNumber);\n const afterCharacter = lineText.charAt(position.column - 1);\n if (afterCharacter !== ch) {\n return false;\n }\n // Do not over-type quotes after a backslash\n const chIsQuote = isQuote(ch);\n const beforeCharacter = position.column > 2 ? lineText.charCodeAt(position.column - 2) : 0 /* CharCode.Null */;\n if (beforeCharacter === 92 /* CharCode.Backslash */ && chIsQuote) {\n return false;\n }\n // Must over-type a closing character typed by the editor\n if (config.autoClosingOvertype === 'auto') {\n let found = false;\n for (let j = 0, lenJ = autoClosedCharacters.length; j < lenJ; j++) {\n const autoClosedCharacter = autoClosedCharacters[j];\n if (position.lineNumber === autoClosedCharacter.startLineNumber && position.column === autoClosedCharacter.startColumn) {\n found = true;\n break;\n }\n }\n if (!found) {\n return false;\n }\n }\n }\n return true;\n }\n static _runAutoClosingOvertype(prevEditOperationType, config, model, selections, ch) {\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n const selection = selections[i];\n const position = selection.getPosition();\n const typeSelection = new Range(position.lineNumber, position.column, position.lineNumber, position.column + 1);\n commands[i] = new ReplaceCommand(typeSelection, ch);\n }\n return new EditOperationResult(4 /* EditOperationType.TypingOther */, commands, {\n shouldPushStackElementBefore: shouldPushStackElementBetween(prevEditOperationType, 4 /* EditOperationType.TypingOther */),\n shouldPushStackElementAfter: false\n });\n }\n static _isBeforeClosingBrace(config, lineAfter) {\n // If the start of lineAfter can be interpretted as both a starting or ending brace, default to returning false\n const nextChar = lineAfter.charAt(0);\n const potentialStartingBraces = config.autoClosingPairs.autoClosingPairsOpenByStart.get(nextChar) || [];\n const potentialClosingBraces = config.autoClosingPairs.autoClosingPairsCloseByStart.get(nextChar) || [];\n const isBeforeStartingBrace = potentialStartingBraces.some(x => lineAfter.startsWith(x.open));\n const isBeforeClosingBrace = potentialClosingBraces.some(x => lineAfter.startsWith(x.close));\n return !isBeforeStartingBrace && isBeforeClosingBrace;\n }\n /**\n * Determine if typing `ch` at all `positions` in the `model` results in an\n * auto closing open sequence being typed.\n *\n * Auto closing open sequences can consist of multiple characters, which\n * can lead to ambiguities. In such a case, the longest auto-closing open\n * sequence is returned.\n */\n static _findAutoClosingPairOpen(config, model, positions, ch) {\n const candidates = config.autoClosingPairs.autoClosingPairsOpenByEnd.get(ch);\n if (!candidates) {\n return null;\n }\n // Determine which auto-closing pair it is\n let result = null;\n for (const candidate of candidates) {\n if (result === null || candidate.open.length > result.open.length) {\n let candidateIsMatch = true;\n for (const position of positions) {\n const relevantText = model.getValueInRange(new Range(position.lineNumber, position.column - candidate.open.length + 1, position.lineNumber, position.column));\n if (relevantText + ch !== candidate.open) {\n candidateIsMatch = false;\n break;\n }\n }\n if (candidateIsMatch) {\n result = candidate;\n }\n }\n }\n return result;\n }\n /**\n * Find another auto-closing pair that is contained by the one passed in.\n *\n * e.g. when having [(,)] and [(*,*)] as auto-closing pairs\n * this method will find [(,)] as a containment pair for [(*,*)]\n */\n static _findContainedAutoClosingPair(config, pair) {\n if (pair.open.length <= 1) {\n return null;\n }\n const lastChar = pair.close.charAt(pair.close.length - 1);\n // get candidates with the same last character as close\n const candidates = config.autoClosingPairs.autoClosingPairsCloseByEnd.get(lastChar) || [];\n let result = null;\n for (const candidate of candidates) {\n if (candidate.open !== pair.open && pair.open.includes(candidate.open) && pair.close.endsWith(candidate.close)) {\n if (!result || candidate.open.length > result.open.length) {\n result = candidate;\n }\n }\n }\n return result;\n }\n static _getAutoClosingPairClose(config, model, selections, ch, chIsAlreadyTyped) {\n const chIsQuote = isQuote(ch);\n const autoCloseConfig = (chIsQuote ? config.autoClosingQuotes : config.autoClosingBrackets);\n const shouldAutoCloseBefore = (chIsQuote ? config.shouldAutoCloseBefore.quote : config.shouldAutoCloseBefore.bracket);\n if (autoCloseConfig === 'never') {\n return null;\n }\n for (const selection of selections) {\n if (!selection.isEmpty()) {\n return null;\n }\n }\n // This method is called both when typing (regularly) and when composition ends\n // This means that we need to work with a text buffer where sometimes `ch` is not\n // there (it is being typed right now) or with a text buffer where `ch` has already been typed\n //\n // In order to avoid adding checks for `chIsAlreadyTyped` in all places, we will work\n // with two conceptual positions, the position before `ch` and the position after `ch`\n //\n const positions = selections.map((s) => {\n const position = s.getPosition();\n if (chIsAlreadyTyped) {\n return { lineNumber: position.lineNumber, beforeColumn: position.column - ch.length, afterColumn: position.column };\n }\n else {\n return { lineNumber: position.lineNumber, beforeColumn: position.column, afterColumn: position.column };\n }\n });\n // Find the longest auto-closing open pair in case of multiple ending in `ch`\n // e.g. when having [f\",\"] and [\",\"], it picks [f\",\"] if the character before is f\n const pair = this._findAutoClosingPairOpen(config, model, positions.map(p => new Position(p.lineNumber, p.beforeColumn)), ch);\n if (!pair) {\n return null;\n }\n // Sometimes, it is possible to have two auto-closing pairs that have a containment relationship\n // e.g. when having [(,)] and [(*,*)]\n // - when typing (, the resulting state is (|)\n // - when typing *, the desired resulting state is (*|*), not (*|*))\n const containedPair = this._findContainedAutoClosingPair(config, pair);\n const containedPairClose = containedPair ? containedPair.close : '';\n let isContainedPairPresent = true;\n for (const position of positions) {\n const { lineNumber, beforeColumn, afterColumn } = position;\n const lineText = model.getLineContent(lineNumber);\n const lineBefore = lineText.substring(0, beforeColumn - 1);\n const lineAfter = lineText.substring(afterColumn - 1);\n if (!lineAfter.startsWith(containedPairClose)) {\n isContainedPairPresent = false;\n }\n // Only consider auto closing the pair if an allowed character follows or if another autoclosed pair closing brace follows\n if (lineAfter.length > 0) {\n const characterAfter = lineAfter.charAt(0);\n const isBeforeCloseBrace = TypeOperations._isBeforeClosingBrace(config, lineAfter);\n if (!isBeforeCloseBrace && !shouldAutoCloseBefore(characterAfter)) {\n return null;\n }\n }\n // Do not auto-close ' or \" after a word character\n if (pair.open.length === 1 && (ch === '\\'' || ch === '\"') && autoCloseConfig !== 'always') {\n const wordSeparators = getMapForWordSeparators(config.wordSeparators);\n if (lineBefore.length > 0) {\n const characterBefore = lineBefore.charCodeAt(lineBefore.length - 1);\n if (wordSeparators.get(characterBefore) === 0 /* WordCharacterClass.Regular */) {\n return null;\n }\n }\n }\n if (!model.tokenization.isCheapToTokenize(lineNumber)) {\n // Do not force tokenization\n return null;\n }\n model.tokenization.forceTokenization(lineNumber);\n const lineTokens = model.tokenization.getLineTokens(lineNumber);\n const scopedLineTokens = createScopedLineTokens(lineTokens, beforeColumn - 1);\n if (!pair.shouldAutoClose(scopedLineTokens, beforeColumn - scopedLineTokens.firstCharOffset)) {\n return null;\n }\n // Typing for example a quote could either start a new string, in which case auto-closing is desirable\n // or it could end a previously started string, in which case auto-closing is not desirable\n //\n // In certain cases, it is really not possible to look at the previous token to determine\n // what would happen. That's why we do something really unusual, we pretend to type a different\n // character and ask the tokenizer what the outcome of doing that is: after typing a neutral\n // character, are we in a string (i.e. the quote would most likely end a string) or not?\n //\n const neutralCharacter = pair.findNeutralCharacter();\n if (neutralCharacter) {\n const tokenType = model.tokenization.getTokenTypeIfInsertingCharacter(lineNumber, beforeColumn, neutralCharacter);\n if (!pair.isOK(tokenType)) {\n return null;\n }\n }\n }\n if (isContainedPairPresent) {\n return pair.close.substring(0, pair.close.length - containedPairClose.length);\n }\n else {\n return pair.close;\n }\n }\n static _runAutoClosingOpenCharType(prevEditOperationType, config, model, selections, ch, chIsAlreadyTyped, autoClosingPairClose) {\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n const selection = selections[i];\n commands[i] = new TypeWithAutoClosingCommand(selection, ch, !chIsAlreadyTyped, autoClosingPairClose);\n }\n return new EditOperationResult(4 /* EditOperationType.TypingOther */, commands, {\n shouldPushStackElementBefore: true,\n shouldPushStackElementAfter: false\n });\n }\n static _shouldSurroundChar(config, ch) {\n if (isQuote(ch)) {\n return (config.autoSurround === 'quotes' || config.autoSurround === 'languageDefined');\n }\n else {\n // Character is a bracket\n return (config.autoSurround === 'brackets' || config.autoSurround === 'languageDefined');\n }\n }\n static _isSurroundSelectionType(config, model, selections, ch) {\n if (!TypeOperations._shouldSurroundChar(config, ch) || !config.surroundingPairs.hasOwnProperty(ch)) {\n return false;\n }\n const isTypingAQuoteCharacter = isQuote(ch);\n for (const selection of selections) {\n if (selection.isEmpty()) {\n return false;\n }\n let selectionContainsOnlyWhitespace = true;\n for (let lineNumber = selection.startLineNumber; lineNumber <= selection.endLineNumber; lineNumber++) {\n const lineText = model.getLineContent(lineNumber);\n const startIndex = (lineNumber === selection.startLineNumber ? selection.startColumn - 1 : 0);\n const endIndex = (lineNumber === selection.endLineNumber ? selection.endColumn - 1 : lineText.length);\n const selectedText = lineText.substring(startIndex, endIndex);\n if (/[^ \\t]/.test(selectedText)) {\n // this selected text contains something other than whitespace\n selectionContainsOnlyWhitespace = false;\n break;\n }\n }\n if (selectionContainsOnlyWhitespace) {\n return false;\n }\n if (isTypingAQuoteCharacter && selection.startLineNumber === selection.endLineNumber && selection.startColumn + 1 === selection.endColumn) {\n const selectionText = model.getValueInRange(selection);\n if (isQuote(selectionText)) {\n // Typing a quote character on top of another quote character\n // => disable surround selection type\n return false;\n }\n }\n }\n return true;\n }\n static _runSurroundSelectionType(prevEditOperationType, config, model, selections, ch) {\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n const selection = selections[i];\n const closeCharacter = config.surroundingPairs[ch];\n commands[i] = new SurroundSelectionCommand(selection, ch, closeCharacter);\n }\n return new EditOperationResult(0 /* EditOperationType.Other */, commands, {\n shouldPushStackElementBefore: true,\n shouldPushStackElementAfter: true\n });\n }\n static _isTypeInterceptorElectricChar(config, model, selections) {\n if (selections.length === 1 && model.tokenization.isCheapToTokenize(selections[0].getEndPosition().lineNumber)) {\n return true;\n }\n return false;\n }\n static _typeInterceptorElectricChar(prevEditOperationType, config, model, selection, ch) {\n if (!config.electricChars.hasOwnProperty(ch) || !selection.isEmpty()) {\n return null;\n }\n const position = selection.getPosition();\n model.tokenization.forceTokenization(position.lineNumber);\n const lineTokens = model.tokenization.getLineTokens(position.lineNumber);\n let electricAction;\n try {\n electricAction = config.onElectricCharacter(ch, lineTokens, position.column);\n }\n catch (e) {\n onUnexpectedError(e);\n return null;\n }\n if (!electricAction) {\n return null;\n }\n if (electricAction.matchOpenBracket) {\n const endColumn = (lineTokens.getLineContent() + ch).lastIndexOf(electricAction.matchOpenBracket) + 1;\n const match = model.bracketPairs.findMatchingBracketUp(electricAction.matchOpenBracket, {\n lineNumber: position.lineNumber,\n column: endColumn\n }, 500 /* give at most 500ms to compute */);\n if (match) {\n if (match.startLineNumber === position.lineNumber) {\n // matched something on the same line => no change in indentation\n return null;\n }\n const matchLine = model.getLineContent(match.startLineNumber);\n const matchLineIndentation = strings.getLeadingWhitespace(matchLine);\n const newIndentation = config.normalizeIndentation(matchLineIndentation);\n const lineText = model.getLineContent(position.lineNumber);\n const lineFirstNonBlankColumn = model.getLineFirstNonWhitespaceColumn(position.lineNumber) || position.column;\n const prefix = lineText.substring(lineFirstNonBlankColumn - 1, position.column - 1);\n const typeText = newIndentation + prefix + ch;\n const typeSelection = new Range(position.lineNumber, 1, position.lineNumber, position.column);\n const command = new ReplaceCommand(typeSelection, typeText);\n return new EditOperationResult(getTypingOperation(typeText, prevEditOperationType), [command], {\n shouldPushStackElementBefore: false,\n shouldPushStackElementAfter: true\n });\n }\n }\n return null;\n }\n /**\n * This is very similar with typing, but the character is already in the text buffer!\n */\n static compositionEndWithInterceptors(prevEditOperationType, config, model, compositions, selections, autoClosedCharacters) {\n if (!compositions) {\n // could not deduce what the composition did\n return null;\n }\n let insertedText = null;\n for (const composition of compositions) {\n if (insertedText === null) {\n insertedText = composition.insertedText;\n }\n else if (insertedText !== composition.insertedText) {\n // not all selections agree on what was typed\n return null;\n }\n }\n if (!insertedText || insertedText.length !== 1) {\n // we're only interested in the case where a single character was inserted\n return null;\n }\n const ch = insertedText;\n let hasDeletion = false;\n for (const composition of compositions) {\n if (composition.deletedText.length !== 0) {\n hasDeletion = true;\n break;\n }\n }\n if (hasDeletion) {\n // Check if this could have been a surround selection\n if (!TypeOperations._shouldSurroundChar(config, ch) || !config.surroundingPairs.hasOwnProperty(ch)) {\n return null;\n }\n const isTypingAQuoteCharacter = isQuote(ch);\n for (const composition of compositions) {\n if (composition.deletedSelectionStart !== 0 || composition.deletedSelectionEnd !== composition.deletedText.length) {\n // more text was deleted than was selected, so this could not have been a surround selection\n return null;\n }\n if (/^[ \\t]+$/.test(composition.deletedText)) {\n // deleted text was only whitespace\n return null;\n }\n if (isTypingAQuoteCharacter && isQuote(composition.deletedText)) {\n // deleted text was a quote\n return null;\n }\n }\n const positions = [];\n for (const selection of selections) {\n if (!selection.isEmpty()) {\n return null;\n }\n positions.push(selection.getPosition());\n }\n if (positions.length !== compositions.length) {\n return null;\n }\n const commands = [];\n for (let i = 0, len = positions.length; i < len; i++) {\n commands.push(new CompositionSurroundSelectionCommand(positions[i], compositions[i].deletedText, ch));\n }\n return new EditOperationResult(4 /* EditOperationType.TypingOther */, commands, {\n shouldPushStackElementBefore: true,\n shouldPushStackElementAfter: false\n });\n }\n if (this._isAutoClosingOvertype(config, model, selections, autoClosedCharacters, ch)) {\n // Unfortunately, the close character is at this point \"doubled\", so we need to delete it...\n const commands = selections.map(s => new ReplaceCommand(new Range(s.positionLineNumber, s.positionColumn, s.positionLineNumber, s.positionColumn + 1), '', false));\n return new EditOperationResult(4 /* EditOperationType.TypingOther */, commands, {\n shouldPushStackElementBefore: true,\n shouldPushStackElementAfter: false\n });\n }\n const autoClosingPairClose = this._getAutoClosingPairClose(config, model, selections, ch, true);\n if (autoClosingPairClose !== null) {\n return this._runAutoClosingOpenCharType(prevEditOperationType, config, model, selections, ch, true, autoClosingPairClose);\n }\n return null;\n }\n static typeWithInterceptors(isDoingComposition, prevEditOperationType, config, model, selections, autoClosedCharacters, ch) {\n if (!isDoingComposition && ch === '\\n') {\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n commands[i] = TypeOperations._enter(config, model, false, selections[i]);\n }\n return new EditOperationResult(4 /* EditOperationType.TypingOther */, commands, {\n shouldPushStackElementBefore: true,\n shouldPushStackElementAfter: false,\n });\n }\n if (!isDoingComposition && this._isAutoIndentType(config, model, selections)) {\n const commands = [];\n let autoIndentFails = false;\n for (let i = 0, len = selections.length; i < len; i++) {\n commands[i] = this._runAutoIndentType(config, model, selections[i], ch);\n if (!commands[i]) {\n autoIndentFails = true;\n break;\n }\n }\n if (!autoIndentFails) {\n return new EditOperationResult(4 /* EditOperationType.TypingOther */, commands, {\n shouldPushStackElementBefore: true,\n shouldPushStackElementAfter: false,\n });\n }\n }\n if (this._isAutoClosingOvertype(config, model, selections, autoClosedCharacters, ch)) {\n return this._runAutoClosingOvertype(prevEditOperationType, config, model, selections, ch);\n }\n if (!isDoingComposition) {\n const autoClosingPairClose = this._getAutoClosingPairClose(config, model, selections, ch, false);\n if (autoClosingPairClose) {\n return this._runAutoClosingOpenCharType(prevEditOperationType, config, model, selections, ch, false, autoClosingPairClose);\n }\n }\n if (!isDoingComposition && this._isSurroundSelectionType(config, model, selections, ch)) {\n return this._runSurroundSelectionType(prevEditOperationType, config, model, selections, ch);\n }\n // Electric characters make sense only when dealing with a single cursor,\n // as multiple cursors typing brackets for example would interfer with bracket matching\n if (!isDoingComposition && this._isTypeInterceptorElectricChar(config, model, selections)) {\n const r = this._typeInterceptorElectricChar(prevEditOperationType, config, model, selections[0], ch);\n if (r) {\n return r;\n }\n }\n // A simple character type\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n commands[i] = new ReplaceCommand(selections[i], ch);\n }\n const opType = getTypingOperation(ch, prevEditOperationType);\n return new EditOperationResult(opType, commands, {\n shouldPushStackElementBefore: shouldPushStackElementBetween(prevEditOperationType, opType),\n shouldPushStackElementAfter: false\n });\n }\n static typeWithoutInterceptors(prevEditOperationType, config, model, selections, str) {\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n commands[i] = new ReplaceCommand(selections[i], str);\n }\n const opType = getTypingOperation(str, prevEditOperationType);\n return new EditOperationResult(opType, commands, {\n shouldPushStackElementBefore: shouldPushStackElementBetween(prevEditOperationType, opType),\n shouldPushStackElementAfter: false\n });\n }\n static lineInsertBefore(config, model, selections) {\n if (model === null || selections === null) {\n return [];\n }\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n let lineNumber = selections[i].positionLineNumber;\n if (lineNumber === 1) {\n commands[i] = new ReplaceCommandWithoutChangingPosition(new Range(1, 1, 1, 1), '\\n');\n }\n else {\n lineNumber--;\n const column = model.getLineMaxColumn(lineNumber);\n commands[i] = this._enter(config, model, false, new Range(lineNumber, column, lineNumber, column));\n }\n }\n return commands;\n }\n static lineInsertAfter(config, model, selections) {\n if (model === null || selections === null) {\n return [];\n }\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n const lineNumber = selections[i].positionLineNumber;\n const column = model.getLineMaxColumn(lineNumber);\n commands[i] = this._enter(config, model, false, new Range(lineNumber, column, lineNumber, column));\n }\n return commands;\n }\n static lineBreakInsert(config, model, selections) {\n const commands = [];\n for (let i = 0, len = selections.length; i < len; i++) {\n commands[i] = this._enter(config, model, true, selections[i]);\n }\n return commands;\n }\n}\nexport class TypeWithAutoClosingCommand extends ReplaceCommandWithOffsetCursorState {\n constructor(selection, openCharacter, insertOpenCharacter, closeCharacter) {\n super(selection, (insertOpenCharacter ? openCharacter : '') + closeCharacter, 0, -closeCharacter.length);\n this._openCharacter = openCharacter;\n this._closeCharacter = closeCharacter;\n this.closeCharacterRange = null;\n this.enclosingRange = null;\n }\n computeCursorState(model, helper) {\n const inverseEditOperations = helper.getInverseEditOperations();\n const range = inverseEditOperations[0].range;\n this.closeCharacterRange = new Range(range.startLineNumber, range.endColumn - this._closeCharacter.length, range.endLineNumber, range.endColumn);\n this.enclosingRange = new Range(range.startLineNumber, range.endColumn - this._openCharacter.length - this._closeCharacter.length, range.endLineNumber, range.endColumn);\n return super.computeCursorState(model, helper);\n }\n}\nexport class CompositionOutcome {\n constructor(deletedText, deletedSelectionStart, deletedSelectionEnd, insertedText, insertedSelectionStart, insertedSelectionEnd) {\n this.deletedText = deletedText;\n this.deletedSelectionStart = deletedSelectionStart;\n this.deletedSelectionEnd = deletedSelectionEnd;\n this.insertedText = insertedText;\n this.insertedSelectionStart = insertedSelectionStart;\n this.insertedSelectionEnd = insertedSelectionEnd;\n }\n}\nfunction getTypingOperation(typedText, previousTypingOperation) {\n if (typedText === ' ') {\n return previousTypingOperation === 5 /* EditOperationType.TypingFirstSpace */\n || previousTypingOperation === 6 /* EditOperationType.TypingConsecutiveSpace */\n ? 6 /* EditOperationType.TypingConsecutiveSpace */\n : 5 /* EditOperationType.TypingFirstSpace */;\n }\n return 4 /* EditOperationType.TypingOther */;\n}\nfunction shouldPushStackElementBetween(previousTypingOperation, typingOperation) {\n if (isTypingOperation(previousTypingOperation) && !isTypingOperation(typingOperation)) {\n // Always set an undo stop before non-type operations\n return true;\n }\n if (previousTypingOperation === 5 /* EditOperationType.TypingFirstSpace */) {\n // `abc |d`: No undo stop\n // `abc |d`: Undo stop\n return false;\n }\n // Insert undo stop between different operation types\n return normalizeOperationType(previousTypingOperation) !== normalizeOperationType(typingOperation);\n}\nfunction normalizeOperationType(type) {\n return (type === 6 /* EditOperationType.TypingConsecutiveSpace */ || type === 5 /* EditOperationType.TypingFirstSpace */)\n ? 'space'\n : type;\n}\nfunction isTypingOperation(type) {\n return type === 4 /* EditOperationType.TypingOther */\n || type === 5 /* EditOperationType.TypingFirstSpace */\n || type === 6 /* EditOperationType.TypingConsecutiveSpace */;\n}\n","/*---------------------------------------------------------------------------------------------\n * 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 * as strings from '../../../base/common/strings.js';\nimport { SingleCursorState } from '../cursorCommon.js';\nimport { DeleteOperations } from './cursorDeleteOperations.js';\nimport { getMapForWordSeparators } from '../core/wordCharacterClassifier.js';\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nexport class WordOperations {\n static _createWord(lineContent, wordType, nextCharClass, start, end) {\n // console.log('WORD ==> ' + start + ' => ' + end + ':::: <<<' + lineContent.substring(start, end) + '>>>');\n return { start: start, end: end, wordType: wordType, nextCharClass: nextCharClass };\n }\n static _findPreviousWordOnLine(wordSeparators, model, position) {\n const lineContent = model.getLineContent(position.lineNumber);\n return this._doFindPreviousWordOnLine(lineContent, wordSeparators, position);\n }\n static _doFindPreviousWordOnLine(lineContent, wordSeparators, position) {\n let wordType = 0 /* WordType.None */;\n for (let chIndex = position.column - 2; chIndex >= 0; chIndex--) {\n const chCode = lineContent.charCodeAt(chIndex);\n const chClass = wordSeparators.get(chCode);\n if (chClass === 0 /* WordCharacterClass.Regular */) {\n if (wordType === 2 /* WordType.Separator */) {\n return this._createWord(lineContent, wordType, chClass, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1));\n }\n wordType = 1 /* WordType.Regular */;\n }\n else if (chClass === 2 /* WordCharacterClass.WordSeparator */) {\n if (wordType === 1 /* WordType.Regular */) {\n return this._createWord(lineContent, wordType, chClass, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1));\n }\n wordType = 2 /* WordType.Separator */;\n }\n else if (chClass === 1 /* WordCharacterClass.Whitespace */) {\n if (wordType !== 0 /* WordType.None */) {\n return this._createWord(lineContent, wordType, chClass, chIndex + 1, this._findEndOfWord(lineContent, wordSeparators, wordType, chIndex + 1));\n }\n }\n }\n if (wordType !== 0 /* WordType.None */) {\n return this._createWord(lineContent, wordType, 1 /* WordCharacterClass.Whitespace */, 0, this._findEndOfWord(lineContent, wordSeparators, wordType, 0));\n }\n return null;\n }\n static _findEndOfWord(lineContent, wordSeparators, wordType, startIndex) {\n const len = lineContent.length;\n for (let chIndex = startIndex; chIndex < len; chIndex++) {\n const chCode = lineContent.charCodeAt(chIndex);\n const chClass = wordSeparators.get(chCode);\n if (chClass === 1 /* WordCharacterClass.Whitespace */) {\n return chIndex;\n }\n if (wordType === 1 /* WordType.Regular */ && chClass === 2 /* WordCharacterClass.WordSeparator */) {\n return chIndex;\n }\n if (wordType === 2 /* WordType.Separator */ && chClass === 0 /* WordCharacterClass.Regular */) {\n return chIndex;\n }\n }\n return len;\n }\n static _findNextWordOnLine(wordSeparators, model, position) {\n const lineContent = model.getLineContent(position.lineNumber);\n return this._doFindNextWordOnLine(lineContent, wordSeparators, position);\n }\n static _doFindNextWordOnLine(lineContent, wordSeparators, position) {\n let wordType = 0 /* WordType.None */;\n const len = lineContent.length;\n for (let chIndex = position.column - 1; chIndex < len; chIndex++) {\n const chCode = lineContent.charCodeAt(chIndex);\n const chClass = wordSeparators.get(chCode);\n if (chClass === 0 /* WordCharacterClass.Regular */) {\n if (wordType === 2 /* WordType.Separator */) {\n return this._createWord(lineContent, wordType, chClass, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex);\n }\n wordType = 1 /* WordType.Regular */;\n }\n else if (chClass === 2 /* WordCharacterClass.WordSeparator */) {\n if (wordType === 1 /* WordType.Regular */) {\n return this._createWord(lineContent, wordType, chClass, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex);\n }\n wordType = 2 /* WordType.Separator */;\n }\n else if (chClass === 1 /* WordCharacterClass.Whitespace */) {\n if (wordType !== 0 /* WordType.None */) {\n return this._createWord(lineContent, wordType, chClass, this._findStartOfWord(lineContent, wordSeparators, wordType, chIndex - 1), chIndex);\n }\n }\n }\n if (wordType !== 0 /* WordType.None */) {\n return this._createWord(lineContent, wordType, 1 /* WordCharacterClass.Whitespace */, this._findStartOfWord(lineContent, wordSeparators, wordType, len - 1), len);\n }\n return null;\n }\n static _findStartOfWord(lineContent, wordSeparators, wordType, startIndex) {\n for (let chIndex = startIndex; chIndex >= 0; chIndex--) {\n const chCode = lineContent.charCodeAt(chIndex);\n const chClass = wordSeparators.get(chCode);\n if (chClass === 1 /* WordCharacterClass.Whitespace */) {\n return chIndex + 1;\n }\n if (wordType === 1 /* WordType.Regular */ && chClass === 2 /* WordCharacterClass.WordSeparator */) {\n return chIndex + 1;\n }\n if (wordType === 2 /* WordType.Separator */ && chClass === 0 /* WordCharacterClass.Regular */) {\n return chIndex + 1;\n }\n }\n return 0;\n }\n static moveWordLeft(wordSeparators, model, position, wordNavigationType) {\n let lineNumber = position.lineNumber;\n let column = position.column;\n if (column === 1) {\n if (lineNumber > 1) {\n lineNumber = lineNumber - 1;\n column = model.getLineMaxColumn(lineNumber);\n }\n }\n let prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, column));\n if (wordNavigationType === 0 /* WordNavigationType.WordStart */) {\n return new Position(lineNumber, prevWordOnLine ? prevWordOnLine.start + 1 : 1);\n }\n if (wordNavigationType === 1 /* WordNavigationType.WordStartFast */) {\n if (prevWordOnLine\n && prevWordOnLine.wordType === 2 /* WordType.Separator */\n && prevWordOnLine.end - prevWordOnLine.start === 1\n && prevWordOnLine.nextCharClass === 0 /* WordCharacterClass.Regular */) {\n // Skip over a word made up of one single separator and followed by a regular character\n prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1));\n }\n return new Position(lineNumber, prevWordOnLine ? prevWordOnLine.start + 1 : 1);\n }\n if (wordNavigationType === 3 /* WordNavigationType.WordAccessibility */) {\n while (prevWordOnLine\n && prevWordOnLine.wordType === 2 /* WordType.Separator */) {\n // Skip over words made up of only separators\n prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1));\n }\n return new Position(lineNumber, prevWordOnLine ? prevWordOnLine.start + 1 : 1);\n }\n // We are stopping at the ending of words\n if (prevWordOnLine && column <= prevWordOnLine.end + 1) {\n prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1));\n }\n return new Position(lineNumber, prevWordOnLine ? prevWordOnLine.end + 1 : 1);\n }\n static _moveWordPartLeft(model, position) {\n const lineNumber = position.lineNumber;\n const maxColumn = model.getLineMaxColumn(lineNumber);\n if (position.column === 1) {\n return (lineNumber > 1 ? new Position(lineNumber - 1, model.getLineMaxColumn(lineNumber - 1)) : position);\n }\n const lineContent = model.getLineContent(lineNumber);\n for (let column = position.column - 1; column > 1; column--) {\n const left = lineContent.charCodeAt(column - 2);\n const right = lineContent.charCodeAt(column - 1);\n if (left === 95 /* CharCode.Underline */ && right !== 95 /* CharCode.Underline */) {\n // snake_case_variables\n return new Position(lineNumber, column);\n }\n if ((strings.isLowerAsciiLetter(left) || strings.isAsciiDigit(left)) && strings.isUpperAsciiLetter(right)) {\n // camelCaseVariables\n return new Position(lineNumber, column);\n }\n if (strings.isUpperAsciiLetter(left) && strings.isUpperAsciiLetter(right)) {\n // thisIsACamelCaseWithOneLetterWords\n if (column + 1 < maxColumn) {\n const rightRight = lineContent.charCodeAt(column);\n if (strings.isLowerAsciiLetter(rightRight) || strings.isAsciiDigit(rightRight)) {\n return new Position(lineNumber, column);\n }\n }\n }\n }\n return new Position(lineNumber, 1);\n }\n static moveWordRight(wordSeparators, model, position, wordNavigationType) {\n let lineNumber = position.lineNumber;\n let column = position.column;\n let movedDown = false;\n if (column === model.getLineMaxColumn(lineNumber)) {\n if (lineNumber < model.getLineCount()) {\n movedDown = true;\n lineNumber = lineNumber + 1;\n column = 1;\n }\n }\n let nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, column));\n if (wordNavigationType === 2 /* WordNavigationType.WordEnd */) {\n if (nextWordOnLine && nextWordOnLine.wordType === 2 /* WordType.Separator */) {\n if (nextWordOnLine.end - nextWordOnLine.start === 1 && nextWordOnLine.nextCharClass === 0 /* WordCharacterClass.Regular */) {\n // Skip over a word made up of one single separator and followed by a regular character\n nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1));\n }\n }\n if (nextWordOnLine) {\n column = nextWordOnLine.end + 1;\n }\n else {\n column = model.getLineMaxColumn(lineNumber);\n }\n }\n else if (wordNavigationType === 3 /* WordNavigationType.WordAccessibility */) {\n if (movedDown) {\n // If we move to the next line, pretend that the cursor is right before the first character.\n // This is needed when the first word starts right at the first character - and in order not to miss it,\n // we need to start before.\n column = 0;\n }\n while (nextWordOnLine\n && (nextWordOnLine.wordType === 2 /* WordType.Separator */\n || nextWordOnLine.start + 1 <= column)) {\n // Skip over a word made up of one single separator\n // Also skip over word if it begins before current cursor position to ascertain we're moving forward at least 1 character.\n nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1));\n }\n if (nextWordOnLine) {\n column = nextWordOnLine.start + 1;\n }\n else {\n column = model.getLineMaxColumn(lineNumber);\n }\n }\n else {\n if (nextWordOnLine && !movedDown && column >= nextWordOnLine.start + 1) {\n nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1));\n }\n if (nextWordOnLine) {\n column = nextWordOnLine.start + 1;\n }\n else {\n column = model.getLineMaxColumn(lineNumber);\n }\n }\n return new Position(lineNumber, column);\n }\n static _moveWordPartRight(model, position) {\n const lineNumber = position.lineNumber;\n const maxColumn = model.getLineMaxColumn(lineNumber);\n if (position.column === maxColumn) {\n return (lineNumber < model.getLineCount() ? new Position(lineNumber + 1, 1) : position);\n }\n const lineContent = model.getLineContent(lineNumber);\n for (let column = position.column + 1; column < maxColumn; column++) {\n const left = lineContent.charCodeAt(column - 2);\n const right = lineContent.charCodeAt(column - 1);\n if (left !== 95 /* CharCode.Underline */ && right === 95 /* CharCode.Underline */) {\n // snake_case_variables\n return new Position(lineNumber, column);\n }\n if ((strings.isLowerAsciiLetter(left) || strings.isAsciiDigit(left)) && strings.isUpperAsciiLetter(right)) {\n // camelCaseVariables\n return new Position(lineNumber, column);\n }\n if (strings.isUpperAsciiLetter(left) && strings.isUpperAsciiLetter(right)) {\n // thisIsACamelCaseWithOneLetterWords\n if (column + 1 < maxColumn) {\n const rightRight = lineContent.charCodeAt(column);\n if (strings.isLowerAsciiLetter(rightRight) || strings.isAsciiDigit(rightRight)) {\n return new Position(lineNumber, column);\n }\n }\n }\n }\n return new Position(lineNumber, maxColumn);\n }\n static _deleteWordLeftWhitespace(model, position) {\n const lineContent = model.getLineContent(position.lineNumber);\n const startIndex = position.column - 2;\n const lastNonWhitespace = strings.lastNonWhitespaceIndex(lineContent, startIndex);\n if (lastNonWhitespace + 1 < startIndex) {\n return new Range(position.lineNumber, lastNonWhitespace + 2, position.lineNumber, position.column);\n }\n return null;\n }\n static deleteWordLeft(ctx, wordNavigationType) {\n const wordSeparators = ctx.wordSeparators;\n const model = ctx.model;\n const selection = ctx.selection;\n const whitespaceHeuristics = ctx.whitespaceHeuristics;\n if (!selection.isEmpty()) {\n return selection;\n }\n if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingDelete, ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpenByEnd, ctx.model, [ctx.selection], ctx.autoClosedCharacters)) {\n const position = ctx.selection.getPosition();\n return new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1);\n }\n const position = new Position(selection.positionLineNumber, selection.positionColumn);\n let lineNumber = position.lineNumber;\n let column = position.column;\n if (lineNumber === 1 && column === 1) {\n // Ignore deleting at beginning of file\n return null;\n }\n if (whitespaceHeuristics) {\n const r = this._deleteWordLeftWhitespace(model, position);\n if (r) {\n return r;\n }\n }\n let prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, position);\n if (wordNavigationType === 0 /* WordNavigationType.WordStart */) {\n if (prevWordOnLine) {\n column = prevWordOnLine.start + 1;\n }\n else {\n if (column > 1) {\n column = 1;\n }\n else {\n lineNumber--;\n column = model.getLineMaxColumn(lineNumber);\n }\n }\n }\n else {\n if (prevWordOnLine && column <= prevWordOnLine.end + 1) {\n prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1));\n }\n if (prevWordOnLine) {\n column = prevWordOnLine.end + 1;\n }\n else {\n if (column > 1) {\n column = 1;\n }\n else {\n lineNumber--;\n column = model.getLineMaxColumn(lineNumber);\n }\n }\n }\n return new Range(lineNumber, column, position.lineNumber, position.column);\n }\n static deleteInsideWord(wordSeparators, model, selection) {\n if (!selection.isEmpty()) {\n return selection;\n }\n const position = new Position(selection.positionLineNumber, selection.positionColumn);\n const r = this._deleteInsideWordWhitespace(model, position);\n if (r) {\n return r;\n }\n return this._deleteInsideWordDetermineDeleteRange(wordSeparators, model, position);\n }\n static _charAtIsWhitespace(str, index) {\n const charCode = str.charCodeAt(index);\n return (charCode === 32 /* CharCode.Space */ || charCode === 9 /* CharCode.Tab */);\n }\n static _deleteInsideWordWhitespace(model, position) {\n const lineContent = model.getLineContent(position.lineNumber);\n const lineContentLength = lineContent.length;\n if (lineContentLength === 0) {\n // empty line\n return null;\n }\n let leftIndex = Math.max(position.column - 2, 0);\n if (!this._charAtIsWhitespace(lineContent, leftIndex)) {\n // touches a non-whitespace character to the left\n return null;\n }\n let rightIndex = Math.min(position.column - 1, lineContentLength - 1);\n if (!this._charAtIsWhitespace(lineContent, rightIndex)) {\n // touches a non-whitespace character to the right\n return null;\n }\n // walk over whitespace to the left\n while (leftIndex > 0 && this._charAtIsWhitespace(lineContent, leftIndex - 1)) {\n leftIndex--;\n }\n // walk over whitespace to the right\n while (rightIndex + 1 < lineContentLength && this._charAtIsWhitespace(lineContent, rightIndex + 1)) {\n rightIndex++;\n }\n return new Range(position.lineNumber, leftIndex + 1, position.lineNumber, rightIndex + 2);\n }\n static _deleteInsideWordDetermineDeleteRange(wordSeparators, model, position) {\n const lineContent = model.getLineContent(position.lineNumber);\n const lineLength = lineContent.length;\n if (lineLength === 0) {\n // empty line\n if (position.lineNumber > 1) {\n return new Range(position.lineNumber - 1, model.getLineMaxColumn(position.lineNumber - 1), position.lineNumber, 1);\n }\n else {\n if (position.lineNumber < model.getLineCount()) {\n return new Range(position.lineNumber, 1, position.lineNumber + 1, 1);\n }\n else {\n // empty model\n return new Range(position.lineNumber, 1, position.lineNumber, 1);\n }\n }\n }\n const touchesWord = (word) => {\n return (word.start + 1 <= position.column && position.column <= word.end + 1);\n };\n const createRangeWithPosition = (startColumn, endColumn) => {\n startColumn = Math.min(startColumn, position.column);\n endColumn = Math.max(endColumn, position.column);\n return new Range(position.lineNumber, startColumn, position.lineNumber, endColumn);\n };\n const deleteWordAndAdjacentWhitespace = (word) => {\n let startColumn = word.start + 1;\n let endColumn = word.end + 1;\n let expandedToTheRight = false;\n while (endColumn - 1 < lineLength && this._charAtIsWhitespace(lineContent, endColumn - 1)) {\n expandedToTheRight = true;\n endColumn++;\n }\n if (!expandedToTheRight) {\n while (startColumn > 1 && this._charAtIsWhitespace(lineContent, startColumn - 2)) {\n startColumn--;\n }\n }\n return createRangeWithPosition(startColumn, endColumn);\n };\n const prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, position);\n if (prevWordOnLine && touchesWord(prevWordOnLine)) {\n return deleteWordAndAdjacentWhitespace(prevWordOnLine);\n }\n const nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, position);\n if (nextWordOnLine && touchesWord(nextWordOnLine)) {\n return deleteWordAndAdjacentWhitespace(nextWordOnLine);\n }\n if (prevWordOnLine && nextWordOnLine) {\n return createRangeWithPosition(prevWordOnLine.end + 1, nextWordOnLine.start + 1);\n }\n if (prevWordOnLine) {\n return createRangeWithPosition(prevWordOnLine.start + 1, prevWordOnLine.end + 1);\n }\n if (nextWordOnLine) {\n return createRangeWithPosition(nextWordOnLine.start + 1, nextWordOnLine.end + 1);\n }\n return createRangeWithPosition(1, lineLength + 1);\n }\n static _deleteWordPartLeft(model, selection) {\n if (!selection.isEmpty()) {\n return selection;\n }\n const pos = selection.getPosition();\n const toPosition = WordOperations._moveWordPartLeft(model, pos);\n return new Range(pos.lineNumber, pos.column, toPosition.lineNumber, toPosition.column);\n }\n static _findFirstNonWhitespaceChar(str, startIndex) {\n const len = str.length;\n for (let chIndex = startIndex; chIndex < len; chIndex++) {\n const ch = str.charAt(chIndex);\n if (ch !== ' ' && ch !== '\\t') {\n return chIndex;\n }\n }\n return len;\n }\n static _deleteWordRightWhitespace(model, position) {\n const lineContent = model.getLineContent(position.lineNumber);\n const startIndex = position.column - 1;\n const firstNonWhitespace = this._findFirstNonWhitespaceChar(lineContent, startIndex);\n if (startIndex + 1 < firstNonWhitespace) {\n // bingo\n return new Range(position.lineNumber, position.column, position.lineNumber, firstNonWhitespace + 1);\n }\n return null;\n }\n static deleteWordRight(ctx, wordNavigationType) {\n const wordSeparators = ctx.wordSeparators;\n const model = ctx.model;\n const selection = ctx.selection;\n const whitespaceHeuristics = ctx.whitespaceHeuristics;\n if (!selection.isEmpty()) {\n return selection;\n }\n const position = new Position(selection.positionLineNumber, selection.positionColumn);\n let lineNumber = position.lineNumber;\n let column = position.column;\n const lineCount = model.getLineCount();\n const maxColumn = model.getLineMaxColumn(lineNumber);\n if (lineNumber === lineCount && column === maxColumn) {\n // Ignore deleting at end of file\n return null;\n }\n if (whitespaceHeuristics) {\n const r = this._deleteWordRightWhitespace(model, position);\n if (r) {\n return r;\n }\n }\n let nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, position);\n if (wordNavigationType === 2 /* WordNavigationType.WordEnd */) {\n if (nextWordOnLine) {\n column = nextWordOnLine.end + 1;\n }\n else {\n if (column < maxColumn || lineNumber === lineCount) {\n column = maxColumn;\n }\n else {\n lineNumber++;\n nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, 1));\n if (nextWordOnLine) {\n column = nextWordOnLine.start + 1;\n }\n else {\n column = model.getLineMaxColumn(lineNumber);\n }\n }\n }\n }\n else {\n if (nextWordOnLine && column >= nextWordOnLine.start + 1) {\n nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1));\n }\n if (nextWordOnLine) {\n column = nextWordOnLine.start + 1;\n }\n else {\n if (column < maxColumn || lineNumber === lineCount) {\n column = maxColumn;\n }\n else {\n lineNumber++;\n nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, 1));\n if (nextWordOnLine) {\n column = nextWordOnLine.start + 1;\n }\n else {\n column = model.getLineMaxColumn(lineNumber);\n }\n }\n }\n }\n return new Range(lineNumber, column, position.lineNumber, position.column);\n }\n static _deleteWordPartRight(model, selection) {\n if (!selection.isEmpty()) {\n return selection;\n }\n const pos = selection.getPosition();\n const toPosition = WordOperations._moveWordPartRight(model, pos);\n return new Range(pos.lineNumber, pos.column, toPosition.lineNumber, toPosition.column);\n }\n static _createWordAtPosition(model, lineNumber, word) {\n const range = new Range(lineNumber, word.start + 1, lineNumber, word.end + 1);\n return {\n word: model.getValueInRange(range),\n startColumn: range.startColumn,\n endColumn: range.endColumn\n };\n }\n static getWordAtPosition(model, _wordSeparators, position) {\n const wordSeparators = getMapForWordSeparators(_wordSeparators);\n const prevWord = WordOperations._findPreviousWordOnLine(wordSeparators, model, position);\n if (prevWord && prevWord.wordType === 1 /* WordType.Regular */ && prevWord.start <= position.column - 1 && position.column - 1 <= prevWord.end) {\n return WordOperations._createWordAtPosition(model, position.lineNumber, prevWord);\n }\n const nextWord = WordOperations._findNextWordOnLine(wordSeparators, model, position);\n if (nextWord && nextWord.wordType === 1 /* WordType.Regular */ && nextWord.start <= position.column - 1 && position.column - 1 <= nextWord.end) {\n return WordOperations._createWordAtPosition(model, position.lineNumber, nextWord);\n }\n return null;\n }\n static word(config, model, cursor, inSelectionMode, position) {\n const wordSeparators = getMapForWordSeparators(config.wordSeparators);\n const prevWord = WordOperations._findPreviousWordOnLine(wordSeparators, model, position);\n const nextWord = WordOperations._findNextWordOnLine(wordSeparators, model, position);\n if (!inSelectionMode) {\n // Entering word selection for the first time\n let startColumn;\n let endColumn;\n if (prevWord && prevWord.wordType === 1 /* WordType.Regular */ && prevWord.start <= position.column - 1 && position.column - 1 <= prevWord.end) {\n // isTouchingPrevWord\n startColumn = prevWord.start + 1;\n endColumn = prevWord.end + 1;\n }\n else if (nextWord && nextWord.wordType === 1 /* WordType.Regular */ && nextWord.start <= position.column - 1 && position.column - 1 <= nextWord.end) {\n // isTouchingNextWord\n startColumn = nextWord.start + 1;\n endColumn = nextWord.end + 1;\n }\n else {\n if (prevWord) {\n startColumn = prevWord.end + 1;\n }\n else {\n startColumn = 1;\n }\n if (nextWord) {\n endColumn = nextWord.start + 1;\n }\n else {\n endColumn = model.getLineMaxColumn(position.lineNumber);\n }\n }\n return new SingleCursorState(new Range(position.lineNumber, startColumn, position.lineNumber, endColumn), 0, new Position(position.lineNumber, endColumn), 0);\n }\n let startColumn;\n let endColumn;\n if (prevWord && prevWord.wordType === 1 /* WordType.Regular */ && prevWord.start < position.column - 1 && position.column - 1 < prevWord.end) {\n // isInsidePrevWord\n startColumn = prevWord.start + 1;\n endColumn = prevWord.end + 1;\n }\n else if (nextWord && nextWord.wordType === 1 /* WordType.Regular */ && nextWord.start < position.column - 1 && position.column - 1 < nextWord.end) {\n // isInsideNextWord\n startColumn = nextWord.start + 1;\n endColumn = nextWord.end + 1;\n }\n else {\n startColumn = position.column;\n endColumn = position.column;\n }\n const lineNumber = position.lineNumber;\n let column;\n if (cursor.selectionStart.containsPosition(position)) {\n column = cursor.selectionStart.endColumn;\n }\n else if (position.isBeforeOrEqual(cursor.selectionStart.getStartPosition())) {\n column = startColumn;\n const possiblePosition = new Position(lineNumber, column);\n if (cursor.selectionStart.containsPosition(possiblePosition)) {\n column = cursor.selectionStart.endColumn;\n }\n }\n else {\n column = endColumn;\n const possiblePosition = new Position(lineNumber, column);\n if (cursor.selectionStart.containsPosition(possiblePosition)) {\n column = cursor.selectionStart.startColumn;\n }\n }\n return cursor.move(true, lineNumber, column, 0);\n }\n}\nexport class WordPartOperations extends WordOperations {\n static deleteWordPartLeft(ctx) {\n const candidates = enforceDefined([\n WordOperations.deleteWordLeft(ctx, 0 /* WordNavigationType.WordStart */),\n WordOperations.deleteWordLeft(ctx, 2 /* WordNavigationType.WordEnd */),\n WordOperations._deleteWordPartLeft(ctx.model, ctx.selection)\n ]);\n candidates.sort(Range.compareRangesUsingEnds);\n return candidates[2];\n }\n static deleteWordPartRight(ctx) {\n const candidates = enforceDefined([\n WordOperations.deleteWordRight(ctx, 0 /* WordNavigationType.WordStart */),\n WordOperations.deleteWordRight(ctx, 2 /* WordNavigationType.WordEnd */),\n WordOperations._deleteWordPartRight(ctx.model, ctx.selection)\n ]);\n candidates.sort(Range.compareRangesUsingStarts);\n return candidates[0];\n }\n static moveWordPartLeft(wordSeparators, model, position) {\n const candidates = enforceDefined([\n WordOperations.moveWordLeft(wordSeparators, model, position, 0 /* WordNavigationType.WordStart */),\n WordOperations.moveWordLeft(wordSeparators, model, position, 2 /* WordNavigationType.WordEnd */),\n WordOperations._moveWordPartLeft(model, position)\n ]);\n candidates.sort(Position.compare);\n return candidates[2];\n }\n static moveWordPartRight(wordSeparators, model, position) {\n const candidates = enforceDefined([\n WordOperations.moveWordRight(wordSeparators, model, position, 0 /* WordNavigationType.WordStart */),\n WordOperations.moveWordRight(wordSeparators, model, position, 2 /* WordNavigationType.WordEnd */),\n WordOperations._moveWordPartRight(model, position)\n ]);\n candidates.sort(Position.compare);\n return candidates[0];\n }\n}\nfunction enforceDefined(arr) {\n return arr.filter(el => Boolean(el));\n}\n","/*---------------------------------------------------------------------------------------------\n * 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 { Position } from './core/position.js';\nimport { Range } from './core/range.js';\nimport { Selection } from './core/selection.js';\nimport { createScopedLineTokens } from './languages/supports.js';\nimport { CursorColumns } from './core/cursorColumns.js';\nimport { normalizeIndentation } from './core/indentation.js';\nconst autoCloseAlways = () => true;\nconst autoCloseNever = () => false;\nconst autoCloseBeforeWhitespace = (chr) => (chr === ' ' || chr === '\\t');\nexport class CursorConfiguration {\n constructor(languageId, modelOptions, configuration, languageConfigurationService) {\n this.languageConfigurationService = languageConfigurationService;\n this._cursorMoveConfigurationBrand = undefined;\n this._languageId = languageId;\n const options = configuration.options;\n const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);\n this.readOnly = options.get(83 /* EditorOption.readOnly */);\n this.tabSize = modelOptions.tabSize;\n this.indentSize = modelOptions.indentSize;\n this.insertSpaces = modelOptions.insertSpaces;\n this.stickyTabStops = options.get(106 /* EditorOption.stickyTabStops */);\n this.lineHeight = options.get(61 /* EditorOption.lineHeight */);\n this.pageSize = Math.max(1, Math.floor(layoutInfo.height / this.lineHeight) - 2);\n this.useTabStops = options.get(118 /* EditorOption.useTabStops */);\n this.wordSeparators = options.get(119 /* EditorOption.wordSeparators */);\n this.emptySelectionClipboard = options.get(33 /* EditorOption.emptySelectionClipboard */);\n this.copyWithSyntaxHighlighting = options.get(21 /* EditorOption.copyWithSyntaxHighlighting */);\n this.multiCursorMergeOverlapping = options.get(71 /* EditorOption.multiCursorMergeOverlapping */);\n this.multiCursorPaste = options.get(73 /* EditorOption.multiCursorPaste */);\n this.autoClosingBrackets = options.get(5 /* EditorOption.autoClosingBrackets */);\n this.autoClosingQuotes = options.get(8 /* EditorOption.autoClosingQuotes */);\n this.autoClosingDelete = options.get(6 /* EditorOption.autoClosingDelete */);\n this.autoClosingOvertype = options.get(7 /* EditorOption.autoClosingOvertype */);\n this.autoSurround = options.get(11 /* EditorOption.autoSurround */);\n this.autoIndent = options.get(9 /* EditorOption.autoIndent */);\n this.surroundingPairs = {};\n this._electricChars = null;\n this.shouldAutoCloseBefore = {\n quote: this._getShouldAutoClose(languageId, this.autoClosingQuotes),\n bracket: this._getShouldAutoClose(languageId, this.autoClosingBrackets)\n };\n this.autoClosingPairs = this.languageConfigurationService.getLanguageConfiguration(languageId).getAutoClosingPairs();\n const surroundingPairs = this.languageConfigurationService.getLanguageConfiguration(languageId).getSurroundingPairs();\n if (surroundingPairs) {\n for (const pair of surroundingPairs) {\n this.surroundingPairs[pair.open] = pair.close;\n }\n }\n }\n static shouldRecreate(e) {\n return (e.hasChanged(133 /* EditorOption.layoutInfo */)\n || e.hasChanged(119 /* EditorOption.wordSeparators */)\n || e.hasChanged(33 /* EditorOption.emptySelectionClipboard */)\n || e.hasChanged(71 /* EditorOption.multiCursorMergeOverlapping */)\n || e.hasChanged(73 /* EditorOption.multiCursorPaste */)\n || e.hasChanged(5 /* EditorOption.autoClosingBrackets */)\n || e.hasChanged(8 /* EditorOption.autoClosingQuotes */)\n || e.hasChanged(6 /* EditorOption.autoClosingDelete */)\n || e.hasChanged(7 /* EditorOption.autoClosingOvertype */)\n || e.hasChanged(11 /* EditorOption.autoSurround */)\n || e.hasChanged(118 /* EditorOption.useTabStops */)\n || e.hasChanged(61 /* EditorOption.lineHeight */)\n || e.hasChanged(83 /* EditorOption.readOnly */));\n }\n get electricChars() {\n var _a;\n if (!this._electricChars) {\n this._electricChars = {};\n const electricChars = (_a = this.languageConfigurationService.getLanguageConfiguration(this._languageId).electricCharacter) === null || _a === void 0 ? void 0 : _a.getElectricCharacters();\n if (electricChars) {\n for (const char of electricChars) {\n this._electricChars[char] = true;\n }\n }\n }\n return this._electricChars;\n }\n /**\n * Should return opening bracket type to match indentation with\n */\n onElectricCharacter(character, context, column) {\n const scopedLineTokens = createScopedLineTokens(context, column - 1);\n const electricCharacterSupport = this.languageConfigurationService.getLanguageConfiguration(scopedLineTokens.languageId).electricCharacter;\n if (!electricCharacterSupport) {\n return null;\n }\n return electricCharacterSupport.onElectricCharacter(character, scopedLineTokens, column - scopedLineTokens.firstCharOffset);\n }\n normalizeIndentation(str) {\n return normalizeIndentation(str, this.indentSize, this.insertSpaces);\n }\n _getShouldAutoClose(languageId, autoCloseConfig) {\n switch (autoCloseConfig) {\n case 'beforeWhitespace':\n return autoCloseBeforeWhitespace;\n case 'languageDefined':\n return this._getLanguageDefinedShouldAutoClose(languageId);\n case 'always':\n return autoCloseAlways;\n case 'never':\n return autoCloseNever;\n }\n }\n _getLanguageDefinedShouldAutoClose(languageId) {\n const autoCloseBeforeSet = this.languageConfigurationService.getLanguageConfiguration(languageId).getAutoCloseBeforeSet();\n return c => autoCloseBeforeSet.indexOf(c) !== -1;\n }\n /**\n * Returns a visible column from a column.\n * @see {@link CursorColumns}\n */\n visibleColumnFromColumn(model, position) {\n return CursorColumns.visibleColumnFromColumn(model.getLineContent(position.lineNumber), position.column, this.tabSize);\n }\n /**\n * Returns a visible column from a column.\n * @see {@link CursorColumns}\n */\n columnFromVisibleColumn(model, lineNumber, visibleColumn) {\n const result = CursorColumns.columnFromVisibleColumn(model.getLineContent(lineNumber), visibleColumn, this.tabSize);\n const minColumn = model.getLineMinColumn(lineNumber);\n if (result < minColumn) {\n return minColumn;\n }\n const maxColumn = model.getLineMaxColumn(lineNumber);\n if (result > maxColumn) {\n return maxColumn;\n }\n return result;\n }\n}\nexport class CursorState {\n constructor(modelState, viewState) {\n this._cursorStateBrand = undefined;\n this.modelState = modelState;\n this.viewState = viewState;\n }\n static fromModelState(modelState) {\n return new PartialModelCursorState(modelState);\n }\n static fromViewState(viewState) {\n return new PartialViewCursorState(viewState);\n }\n static fromModelSelection(modelSelection) {\n const selection = Selection.liftSelection(modelSelection);\n const modelState = new SingleCursorState(Range.fromPositions(selection.getSelectionStart()), 0, selection.getPosition(), 0);\n return CursorState.fromModelState(modelState);\n }\n static fromModelSelections(modelSelections) {\n const states = [];\n for (let i = 0, len = modelSelections.length; i < len; i++) {\n states[i] = this.fromModelSelection(modelSelections[i]);\n }\n return states;\n }\n equals(other) {\n return (this.viewState.equals(other.viewState) && this.modelState.equals(other.modelState));\n }\n}\nexport class PartialModelCursorState {\n constructor(modelState) {\n this.modelState = modelState;\n this.viewState = null;\n }\n}\nexport class PartialViewCursorState {\n constructor(viewState) {\n this.modelState = null;\n this.viewState = viewState;\n }\n}\n/**\n * Represents the cursor state on either the model or on the view model.\n */\nexport class SingleCursorState {\n constructor(selectionStart, selectionStartLeftoverVisibleColumns, position, leftoverVisibleColumns) {\n this._singleCursorStateBrand = undefined;\n this.selectionStart = selectionStart;\n this.selectionStartLeftoverVisibleColumns = selectionStartLeftoverVisibleColumns;\n this.position = position;\n this.leftoverVisibleColumns = leftoverVisibleColumns;\n this.selection = SingleCursorState._computeSelection(this.selectionStart, this.position);\n }\n equals(other) {\n return (this.selectionStartLeftoverVisibleColumns === other.selectionStartLeftoverVisibleColumns\n && this.leftoverVisibleColumns === other.leftoverVisibleColumns\n && this.position.equals(other.position)\n && this.selectionStart.equalsRange(other.selectionStart));\n }\n hasSelection() {\n return (!this.selection.isEmpty() || !this.selectionStart.isEmpty());\n }\n move(inSelectionMode, lineNumber, column, leftoverVisibleColumns) {\n if (inSelectionMode) {\n // move just position\n return new SingleCursorState(this.selectionStart, this.selectionStartLeftoverVisibleColumns, new Position(lineNumber, column), leftoverVisibleColumns);\n }\n else {\n // move everything\n return new SingleCursorState(new Range(lineNumber, column, lineNumber, column), leftoverVisibleColumns, new Position(lineNumber, column), leftoverVisibleColumns);\n }\n }\n static _computeSelection(selectionStart, position) {\n if (selectionStart.isEmpty() || !position.isBeforeOrEqual(selectionStart.getStartPosition())) {\n return Selection.fromPositions(selectionStart.getStartPosition(), position);\n }\n else {\n return Selection.fromPositions(selectionStart.getEndPosition(), position);\n }\n }\n}\nexport class EditOperationResult {\n constructor(type, commands, opts) {\n this._editOperationResultBrand = undefined;\n this.type = type;\n this.commands = commands;\n this.shouldPushStackElementBefore = opts.shouldPushStackElementBefore;\n this.shouldPushStackElementAfter = opts.shouldPushStackElementAfter;\n }\n}\nexport function isQuote(ch) {\n return (ch === '\\'' || ch === '\"' || ch === '`');\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nexport class InternalEditorAction {\n constructor(id, label, alias, precondition, run, contextKeyService) {\n this.id = id;\n this.label = label;\n this.alias = alias;\n this._precondition = precondition;\n this._run = run;\n this._contextKeyService = contextKeyService;\n }\n isSupported() {\n return this._contextKeyService.contextMatchesRules(this._precondition);\n }\n run() {\n if (!this.isSupported()) {\n return Promise.resolve(undefined);\n }\n return this._run();\n }\n}\n","/**\n * The type of the `IEditor`.\n */\nexport const EditorType = {\n ICodeEditor: 'vs.editor.ICodeEditor',\n IDiffEditor: 'vs.editor.IDiffEditor'\n};\n","/*---------------------------------------------------------------------------------------------\n * 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 * as nls from '../../nls.js';\nimport { RawContextKey } from '../../platform/contextkey/common/contextkey.js';\nexport var EditorContextKeys;\n(function (EditorContextKeys) {\n EditorContextKeys.editorSimpleInput = new RawContextKey('editorSimpleInput', false, true);\n /**\n * A context key that is set when the editor's text has focus (cursor is blinking).\n * Is false when focus is in simple editor widgets (repl input, scm commit input).\n */\n EditorContextKeys.editorTextFocus = new RawContextKey('editorTextFocus', false, nls.localize('editorTextFocus', \"Whether the editor text has focus (cursor is blinking)\"));\n /**\n * A context key that is set when the editor's text or an editor's widget has focus.\n */\n EditorContextKeys.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 * A context key that is set when any editor input has focus (regular editor, repl input...).\n */\n EditorContextKeys.textInputFocus = new RawContextKey('textInputFocus', false, nls.localize('textInputFocus', \"Whether an editor or a rich text input has focus (cursor is blinking)\"));\n EditorContextKeys.readOnly = new RawContextKey('editorReadonly', false, nls.localize('editorReadonly', \"Whether the editor is read only\"));\n EditorContextKeys.inDiffEditor = new RawContextKey('inDiffEditor', false, nls.localize('inDiffEditor', \"Whether the context is a diff editor\"));\n EditorContextKeys.columnSelection = new RawContextKey('editorColumnSelection', false, nls.localize('editorColumnSelection', \"Whether `editor.columnSelection` is enabled\"));\n EditorContextKeys.writable = EditorContextKeys.readOnly.toNegated();\n EditorContextKeys.hasNonEmptySelection = new RawContextKey('editorHasSelection', false, nls.localize('editorHasSelection', \"Whether the editor has text selected\"));\n EditorContextKeys.hasOnlyEmptySelection = EditorContextKeys.hasNonEmptySelection.toNegated();\n EditorContextKeys.hasMultipleSelections = new RawContextKey('editorHasMultipleSelections', false, nls.localize('editorHasMultipleSelections', \"Whether the editor has multiple selections\"));\n EditorContextKeys.hasSingleSelection = EditorContextKeys.hasMultipleSelections.toNegated();\n EditorContextKeys.tabMovesFocus = new RawContextKey('editorTabMovesFocus', false, nls.localize('editorTabMovesFocus', \"Whether `Tab` will move focus out of the editor\"));\n EditorContextKeys.tabDoesNotMoveFocus = EditorContextKeys.tabMovesFocus.toNegated();\n EditorContextKeys.isInWalkThroughSnippet = new RawContextKey('isInEmbeddedEditor', false, true);\n EditorContextKeys.canUndo = new RawContextKey('canUndo', false, true);\n EditorContextKeys.canRedo = new RawContextKey('canRedo', false, true);\n EditorContextKeys.hoverVisible = new RawContextKey('editorHoverVisible', false, nls.localize('editorHoverVisible', \"Whether the editor hover is visible\"));\n /**\n * A context key that is set when an editor is part of a larger editor, like notebooks or\n * (future) a diff editor\n */\n EditorContextKeys.inCompositeEditor = new RawContextKey('inCompositeEditor', undefined, nls.localize('inCompositeEditor', \"Whether the editor is part of a larger editor (e.g. notebooks)\"));\n EditorContextKeys.notInCompositeEditor = EditorContextKeys.inCompositeEditor.toNegated();\n // -- mode context keys\n EditorContextKeys.languageId = new RawContextKey('editorLangId', '', nls.localize('editorLangId', \"The language identifier of the editor\"));\n EditorContextKeys.hasCompletionItemProvider = new RawContextKey('editorHasCompletionItemProvider', false, nls.localize('editorHasCompletionItemProvider', \"Whether the editor has a completion item provider\"));\n EditorContextKeys.hasCodeActionsProvider = new RawContextKey('editorHasCodeActionsProvider', false, nls.localize('editorHasCodeActionsProvider', \"Whether the editor has a code actions provider\"));\n EditorContextKeys.hasCodeLensProvider = new RawContextKey('editorHasCodeLensProvider', false, nls.localize('editorHasCodeLensProvider', \"Whether the editor has a code lens provider\"));\n EditorContextKeys.hasDefinitionProvider = new RawContextKey('editorHasDefinitionProvider', false, nls.localize('editorHasDefinitionProvider', \"Whether the editor has a definition provider\"));\n EditorContextKeys.hasDeclarationProvider = new RawContextKey('editorHasDeclarationProvider', false, nls.localize('editorHasDeclarationProvider', \"Whether the editor has a declaration provider\"));\n EditorContextKeys.hasImplementationProvider = new RawContextKey('editorHasImplementationProvider', false, nls.localize('editorHasImplementationProvider', \"Whether the editor has an implementation provider\"));\n EditorContextKeys.hasTypeDefinitionProvider = new RawContextKey('editorHasTypeDefinitionProvider', false, nls.localize('editorHasTypeDefinitionProvider', \"Whether the editor has a type definition provider\"));\n EditorContextKeys.hasHoverProvider = new RawContextKey('editorHasHoverProvider', false, nls.localize('editorHasHoverProvider', \"Whether the editor has a hover provider\"));\n EditorContextKeys.hasDocumentHighlightProvider = new RawContextKey('editorHasDocumentHighlightProvider', false, nls.localize('editorHasDocumentHighlightProvider', \"Whether the editor has a document highlight provider\"));\n EditorContextKeys.hasDocumentSymbolProvider = new RawContextKey('editorHasDocumentSymbolProvider', false, nls.localize('editorHasDocumentSymbolProvider', \"Whether the editor has a document symbol provider\"));\n EditorContextKeys.hasReferenceProvider = new RawContextKey('editorHasReferenceProvider', false, nls.localize('editorHasReferenceProvider', \"Whether the editor has a reference provider\"));\n EditorContextKeys.hasRenameProvider = new RawContextKey('editorHasRenameProvider', false, nls.localize('editorHasRenameProvider', \"Whether the editor has a rename provider\"));\n EditorContextKeys.hasSignatureHelpProvider = new RawContextKey('editorHasSignatureHelpProvider', false, nls.localize('editorHasSignatureHelpProvider', \"Whether the editor has a signature help provider\"));\n EditorContextKeys.hasInlayHintsProvider = new RawContextKey('editorHasInlayHintsProvider', false, nls.localize('editorHasInlayHintsProvider', \"Whether the editor has an inline hints provider\"));\n // -- mode context keys: formatting\n EditorContextKeys.hasDocumentFormattingProvider = new RawContextKey('editorHasDocumentFormattingProvider', false, nls.localize('editorHasDocumentFormattingProvider', \"Whether the editor has a document formatting provider\"));\n EditorContextKeys.hasDocumentSelectionFormattingProvider = new RawContextKey('editorHasDocumentSelectionFormattingProvider', false, nls.localize('editorHasDocumentSelectionFormattingProvider', \"Whether the editor has a document selection formatting provider\"));\n EditorContextKeys.hasMultipleDocumentFormattingProvider = new RawContextKey('editorHasMultipleDocumentFormattingProvider', false, nls.localize('editorHasMultipleDocumentFormattingProvider', \"Whether the editor has multiple document formatting providers\"));\n EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider = new RawContextKey('editorHasMultipleDocumentSelectionFormattingProvider', false, nls.localize('editorHasMultipleDocumentSelectionFormattingProvider', \"Whether the editor has multiple document selection formatting providers\"));\n})(EditorContextKeys || (EditorContextKeys = {}));\n","/*---------------------------------------------------------------------------------------------\n * Copyright (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 */\nexport class TokenMetadata {\n static getLanguageId(metadata) {\n return (metadata & 255 /* MetadataConsts.LANGUAGEID_MASK */) >>> 0 /* MetadataConsts.LANGUAGEID_OFFSET */;\n }\n static getTokenType(metadata) {\n return (metadata & 768 /* MetadataConsts.TOKEN_TYPE_MASK */) >>> 8 /* MetadataConsts.TOKEN_TYPE_OFFSET */;\n }\n static containsBalancedBrackets(metadata) {\n return (metadata & 1024 /* MetadataConsts.BALANCED_BRACKETS_MASK */) !== 0;\n }\n static getFontStyle(metadata) {\n return (metadata & 30720 /* MetadataConsts.FONT_STYLE_MASK */) >>> 11 /* MetadataConsts.FONT_STYLE_OFFSET */;\n }\n static getForeground(metadata) {\n return (metadata & 16744448 /* MetadataConsts.FOREGROUND_MASK */) >>> 15 /* MetadataConsts.FOREGROUND_OFFSET */;\n }\n static getBackground(metadata) {\n return (metadata & 4278190080 /* MetadataConsts.BACKGROUND_MASK */) >>> 24 /* MetadataConsts.BACKGROUND_OFFSET */;\n }\n static getClassNameFromMetadata(metadata) {\n const foreground = this.getForeground(metadata);\n let className = 'mtk' + foreground;\n const fontStyle = this.getFontStyle(metadata);\n if (fontStyle & 1 /* FontStyle.Italic */) {\n className += ' mtki';\n }\n if (fontStyle & 2 /* FontStyle.Bold */) {\n className += ' mtkb';\n }\n if (fontStyle & 4 /* FontStyle.Underline */) {\n className += ' mtku';\n }\n if (fontStyle & 8 /* FontStyle.Strikethrough */) {\n className += ' mtks';\n }\n return className;\n }\n static getInlineStyleFromMetadata(metadata, colorMap) {\n const foreground = this.getForeground(metadata);\n const fontStyle = this.getFontStyle(metadata);\n let result = `color: ${colorMap[foreground]};`;\n if (fontStyle & 1 /* FontStyle.Italic */) {\n result += 'font-style: italic;';\n }\n if (fontStyle & 2 /* FontStyle.Bold */) {\n result += 'font-weight: bold;';\n }\n let textDecoration = '';\n if (fontStyle & 4 /* FontStyle.Underline */) {\n textDecoration += ' underline';\n }\n if (fontStyle & 8 /* FontStyle.Strikethrough */) {\n textDecoration += ' line-through';\n }\n if (textDecoration) {\n result += `text-decoration:${textDecoration};`;\n }\n return result;\n }\n static getPresentationFromMetadata(metadata) {\n const foreground = this.getForeground(metadata);\n const fontStyle = this.getFontStyle(metadata);\n return {\n foreground: foreground,\n italic: Boolean(fontStyle & 1 /* FontStyle.Italic */),\n bold: Boolean(fontStyle & 2 /* FontStyle.Bold */),\n underline: Boolean(fontStyle & 4 /* FontStyle.Underline */),\n strikethrough: Boolean(fontStyle & 8 /* FontStyle.Strikethrough */),\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 *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { Emitter } from '../../base/common/event.js';\nimport { Disposable, toDisposable } from '../../base/common/lifecycle.js';\nexport class TokenizationRegistry {\n constructor() {\n this._map = new Map();\n this._factories = new Map();\n this._onDidChange = new Emitter();\n this.onDidChange = this._onDidChange.event;\n this._colorMap = null;\n }\n fire(languages) {\n this._onDidChange.fire({\n changedLanguages: languages,\n changedColorMap: false\n });\n }\n register(language, support) {\n this._map.set(language, support);\n this.fire([language]);\n return toDisposable(() => {\n if (this._map.get(language) !== support) {\n return;\n }\n this._map.delete(language);\n this.fire([language]);\n });\n }\n registerFactory(languageId, factory) {\n var _a;\n (_a = this._factories.get(languageId)) === null || _a === void 0 ? void 0 : _a.dispose();\n const myData = new TokenizationSupportFactoryData(this, languageId, factory);\n this._factories.set(languageId, myData);\n return toDisposable(() => {\n const v = this._factories.get(languageId);\n if (!v || v !== myData) {\n return;\n }\n this._factories.delete(languageId);\n v.dispose();\n });\n }\n getOrCreate(languageId) {\n return __awaiter(this, void 0, void 0, function* () {\n // check first if the support is already set\n const tokenizationSupport = this.get(languageId);\n if (tokenizationSupport) {\n return tokenizationSupport;\n }\n const factory = this._factories.get(languageId);\n if (!factory || factory.isResolved) {\n // no factory or factory.resolve already finished\n return null;\n }\n yield factory.resolve();\n return this.get(languageId);\n });\n }\n get(language) {\n return (this._map.get(language) || null);\n }\n isResolved(languageId) {\n const tokenizationSupport = this.get(languageId);\n if (tokenizationSupport) {\n return true;\n }\n const factory = this._factories.get(languageId);\n if (!factory || factory.isResolved) {\n return true;\n }\n return false;\n }\n setColorMap(colorMap) {\n this._colorMap = colorMap;\n this._onDidChange.fire({\n changedLanguages: Array.from(this._map.keys()),\n changedColorMap: true\n });\n }\n getColorMap() {\n return this._colorMap;\n }\n getDefaultBackground() {\n if (this._colorMap && this._colorMap.length > 2 /* ColorId.DefaultBackground */) {\n return this._colorMap[2 /* ColorId.DefaultBackground */];\n }\n return null;\n }\n}\nclass TokenizationSupportFactoryData extends Disposable {\n constructor(_registry, _languageId, _factory) {\n super();\n this._registry = _registry;\n this._languageId = _languageId;\n this._factory = _factory;\n this._isDisposed = false;\n this._resolvePromise = null;\n this._isResolved = false;\n }\n get isResolved() {\n return this._isResolved;\n }\n dispose() {\n this._isDisposed = true;\n super.dispose();\n }\n resolve() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this._resolvePromise) {\n this._resolvePromise = this._create();\n }\n return this._resolvePromise;\n });\n }\n _create() {\n return __awaiter(this, void 0, void 0, function* () {\n const value = yield Promise.resolve(this._factory.createTokenizationSupport());\n this._isResolved = true;\n if (value && !this._isDisposed) {\n this._register(this._registry.register(this._languageId, value));\n }\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 *--------------------------------------------------------------------------------------------*/\nimport { Codicon } from '../../base/common/codicons.js';\nimport { URI } from '../../base/common/uri.js';\nimport { Range } from './core/range.js';\nimport { TokenizationRegistry as TokenizationRegistryImpl } from './tokenizationRegistry.js';\nexport class Token {\n constructor(offset, type, language) {\n this._tokenBrand = undefined;\n this.offset = offset;\n this.type = type;\n this.language = language;\n }\n toString() {\n return '(' + this.offset + ', ' + this.type + ')';\n }\n}\n/**\n * @internal\n */\nexport class TokenizationResult {\n constructor(tokens, endState) {\n this._tokenizationResultBrand = undefined;\n this.tokens = tokens;\n this.endState = endState;\n }\n}\n/**\n * @internal\n */\nexport class EncodedTokenizationResult {\n constructor(tokens, endState) {\n this._encodedTokenizationResultBrand = undefined;\n this.tokens = tokens;\n this.endState = endState;\n }\n}\n/**\n * @internal\n */\nexport var CompletionItemKinds;\n(function (CompletionItemKinds) {\n const byKind = new Map();\n byKind.set(0 /* CompletionItemKind.Method */, Codicon.symbolMethod);\n byKind.set(1 /* CompletionItemKind.Function */, Codicon.symbolFunction);\n byKind.set(2 /* CompletionItemKind.Constructor */, Codicon.symbolConstructor);\n byKind.set(3 /* CompletionItemKind.Field */, Codicon.symbolField);\n byKind.set(4 /* CompletionItemKind.Variable */, Codicon.symbolVariable);\n byKind.set(5 /* CompletionItemKind.Class */, Codicon.symbolClass);\n byKind.set(6 /* CompletionItemKind.Struct */, Codicon.symbolStruct);\n byKind.set(7 /* CompletionItemKind.Interface */, Codicon.symbolInterface);\n byKind.set(8 /* CompletionItemKind.Module */, Codicon.symbolModule);\n byKind.set(9 /* CompletionItemKind.Property */, Codicon.symbolProperty);\n byKind.set(10 /* CompletionItemKind.Event */, Codicon.symbolEvent);\n byKind.set(11 /* CompletionItemKind.Operator */, Codicon.symbolOperator);\n byKind.set(12 /* CompletionItemKind.Unit */, Codicon.symbolUnit);\n byKind.set(13 /* CompletionItemKind.Value */, Codicon.symbolValue);\n byKind.set(15 /* CompletionItemKind.Enum */, Codicon.symbolEnum);\n byKind.set(14 /* CompletionItemKind.Constant */, Codicon.symbolConstant);\n byKind.set(15 /* CompletionItemKind.Enum */, Codicon.symbolEnum);\n byKind.set(16 /* CompletionItemKind.EnumMember */, Codicon.symbolEnumMember);\n byKind.set(17 /* CompletionItemKind.Keyword */, Codicon.symbolKeyword);\n byKind.set(27 /* CompletionItemKind.Snippet */, Codicon.symbolSnippet);\n byKind.set(18 /* CompletionItemKind.Text */, Codicon.symbolText);\n byKind.set(19 /* CompletionItemKind.Color */, Codicon.symbolColor);\n byKind.set(20 /* CompletionItemKind.File */, Codicon.symbolFile);\n byKind.set(21 /* CompletionItemKind.Reference */, Codicon.symbolReference);\n byKind.set(22 /* CompletionItemKind.Customcolor */, Codicon.symbolCustomColor);\n byKind.set(23 /* CompletionItemKind.Folder */, Codicon.symbolFolder);\n byKind.set(24 /* CompletionItemKind.TypeParameter */, Codicon.symbolTypeParameter);\n byKind.set(25 /* CompletionItemKind.User */, Codicon.account);\n byKind.set(26 /* CompletionItemKind.Issue */, Codicon.issues);\n /**\n * @internal\n */\n function toIcon(kind) {\n let codicon = byKind.get(kind);\n if (!codicon) {\n console.info('No codicon found for CompletionItemKind ' + kind);\n codicon = Codicon.symbolProperty;\n }\n return codicon;\n }\n CompletionItemKinds.toIcon = toIcon;\n const data = new Map();\n data.set('method', 0 /* CompletionItemKind.Method */);\n data.set('function', 1 /* CompletionItemKind.Function */);\n data.set('constructor', 2 /* CompletionItemKind.Constructor */);\n data.set('field', 3 /* CompletionItemKind.Field */);\n data.set('variable', 4 /* CompletionItemKind.Variable */);\n data.set('class', 5 /* CompletionItemKind.Class */);\n data.set('struct', 6 /* CompletionItemKind.Struct */);\n data.set('interface', 7 /* CompletionItemKind.Interface */);\n data.set('module', 8 /* CompletionItemKind.Module */);\n data.set('property', 9 /* CompletionItemKind.Property */);\n data.set('event', 10 /* CompletionItemKind.Event */);\n data.set('operator', 11 /* CompletionItemKind.Operator */);\n data.set('unit', 12 /* CompletionItemKind.Unit */);\n data.set('value', 13 /* CompletionItemKind.Value */);\n data.set('constant', 14 /* CompletionItemKind.Constant */);\n data.set('enum', 15 /* CompletionItemKind.Enum */);\n data.set('enum-member', 16 /* CompletionItemKind.EnumMember */);\n data.set('enumMember', 16 /* CompletionItemKind.EnumMember */);\n data.set('keyword', 17 /* CompletionItemKind.Keyword */);\n data.set('snippet', 27 /* CompletionItemKind.Snippet */);\n data.set('text', 18 /* CompletionItemKind.Text */);\n data.set('color', 19 /* CompletionItemKind.Color */);\n data.set('file', 20 /* CompletionItemKind.File */);\n data.set('reference', 21 /* CompletionItemKind.Reference */);\n data.set('customcolor', 22 /* CompletionItemKind.Customcolor */);\n data.set('folder', 23 /* CompletionItemKind.Folder */);\n data.set('type-parameter', 24 /* CompletionItemKind.TypeParameter */);\n data.set('typeParameter', 24 /* CompletionItemKind.TypeParameter */);\n data.set('account', 25 /* CompletionItemKind.User */);\n data.set('issue', 26 /* CompletionItemKind.Issue */);\n /**\n * @internal\n */\n function fromString(value, strict) {\n let res = data.get(value);\n if (typeof res === 'undefined' && !strict) {\n res = 9 /* CompletionItemKind.Property */;\n }\n return res;\n }\n CompletionItemKinds.fromString = fromString;\n})(CompletionItemKinds || (CompletionItemKinds = {}));\n/**\n * How an {@link InlineCompletionsProvider inline completion provider} was triggered.\n */\nexport var InlineCompletionTriggerKind;\n(function (InlineCompletionTriggerKind) {\n /**\n * Completion was triggered automatically while editing.\n * It is sufficient to return a single completion item in this case.\n */\n InlineCompletionTriggerKind[InlineCompletionTriggerKind[\"Automatic\"] = 0] = \"Automatic\";\n /**\n * Completion was triggered explicitly by a user gesture.\n * Return multiple completion items to enable cycling through them.\n */\n InlineCompletionTriggerKind[InlineCompletionTriggerKind[\"Explicit\"] = 1] = \"Explicit\";\n})(InlineCompletionTriggerKind || (InlineCompletionTriggerKind = {}));\nexport var SignatureHelpTriggerKind;\n(function (SignatureHelpTriggerKind) {\n SignatureHelpTriggerKind[SignatureHelpTriggerKind[\"Invoke\"] = 1] = \"Invoke\";\n SignatureHelpTriggerKind[SignatureHelpTriggerKind[\"TriggerCharacter\"] = 2] = \"TriggerCharacter\";\n SignatureHelpTriggerKind[SignatureHelpTriggerKind[\"ContentChange\"] = 3] = \"ContentChange\";\n})(SignatureHelpTriggerKind || (SignatureHelpTriggerKind = {}));\n/**\n * A document highlight kind.\n */\nexport var DocumentHighlightKind;\n(function (DocumentHighlightKind) {\n /**\n * A textual occurrence.\n */\n DocumentHighlightKind[DocumentHighlightKind[\"Text\"] = 0] = \"Text\";\n /**\n * Read-access of a symbol, like reading a variable.\n */\n DocumentHighlightKind[DocumentHighlightKind[\"Read\"] = 1] = \"Read\";\n /**\n * Write-access of a symbol, like writing to a variable.\n */\n DocumentHighlightKind[DocumentHighlightKind[\"Write\"] = 2] = \"Write\";\n})(DocumentHighlightKind || (DocumentHighlightKind = {}));\n/**\n * @internal\n */\nexport function isLocationLink(thing) {\n return thing\n && URI.isUri(thing.uri)\n && Range.isIRange(thing.range)\n && (Range.isIRange(thing.originSelectionRange) || Range.isIRange(thing.targetSelectionRange));\n}\n/**\n * @internal\n */\nexport var SymbolKinds;\n(function (SymbolKinds) {\n const byKind = new Map();\n byKind.set(0 /* SymbolKind.File */, Codicon.symbolFile);\n byKind.set(1 /* SymbolKind.Module */, Codicon.symbolModule);\n byKind.set(2 /* SymbolKind.Namespace */, Codicon.symbolNamespace);\n byKind.set(3 /* SymbolKind.Package */, Codicon.symbolPackage);\n byKind.set(4 /* SymbolKind.Class */, Codicon.symbolClass);\n byKind.set(5 /* SymbolKind.Method */, Codicon.symbolMethod);\n byKind.set(6 /* SymbolKind.Property */, Codicon.symbolProperty);\n byKind.set(7 /* SymbolKind.Field */, Codicon.symbolField);\n byKind.set(8 /* SymbolKind.Constructor */, Codicon.symbolConstructor);\n byKind.set(9 /* SymbolKind.Enum */, Codicon.symbolEnum);\n byKind.set(10 /* SymbolKind.Interface */, Codicon.symbolInterface);\n byKind.set(11 /* SymbolKind.Function */, Codicon.symbolFunction);\n byKind.set(12 /* SymbolKind.Variable */, Codicon.symbolVariable);\n byKind.set(13 /* SymbolKind.Constant */, Codicon.symbolConstant);\n byKind.set(14 /* SymbolKind.String */, Codicon.symbolString);\n byKind.set(15 /* SymbolKind.Number */, Codicon.symbolNumber);\n byKind.set(16 /* SymbolKind.Boolean */, Codicon.symbolBoolean);\n byKind.set(17 /* SymbolKind.Array */, Codicon.symbolArray);\n byKind.set(18 /* SymbolKind.Object */, Codicon.symbolObject);\n byKind.set(19 /* SymbolKind.Key */, Codicon.symbolKey);\n byKind.set(20 /* SymbolKind.Null */, Codicon.symbolNull);\n byKind.set(21 /* SymbolKind.EnumMember */, Codicon.symbolEnumMember);\n byKind.set(22 /* SymbolKind.Struct */, Codicon.symbolStruct);\n byKind.set(23 /* SymbolKind.Event */, Codicon.symbolEvent);\n byKind.set(24 /* SymbolKind.Operator */, Codicon.symbolOperator);\n byKind.set(25 /* SymbolKind.TypeParameter */, Codicon.symbolTypeParameter);\n /**\n * @internal\n */\n function toIcon(kind) {\n let icon = byKind.get(kind);\n if (!icon) {\n console.info('No codicon found for SymbolKind ' + kind);\n icon = Codicon.symbolProperty;\n }\n return icon;\n }\n SymbolKinds.toIcon = toIcon;\n})(SymbolKinds || (SymbolKinds = {}));\nexport class FoldingRangeKind {\n /**\n * Creates a new {@link FoldingRangeKind}.\n *\n * @param value of the kind.\n */\n constructor(value) {\n this.value = value;\n }\n}\n/**\n * Kind for folding range representing a comment. The value of the kind is 'comment'.\n */\nFoldingRangeKind.Comment = new FoldingRangeKind('comment');\n/**\n * Kind for folding range representing a import. The value of the kind is 'imports'.\n */\nFoldingRangeKind.Imports = new FoldingRangeKind('imports');\n/**\n * Kind for folding range representing regions (for example marked by `#region`, `#endregion`).\n * The value of the kind is 'region'.\n */\nFoldingRangeKind.Region = new FoldingRangeKind('region');\n/**\n * @internal\n */\nexport var Command;\n(function (Command) {\n /**\n * @internal\n */\n function is(obj) {\n if (!obj || typeof obj !== 'object') {\n return false;\n }\n return typeof obj.id === 'string' &&\n typeof obj.title === 'string';\n }\n Command.is = is;\n})(Command || (Command = {}));\nexport var InlayHintKind;\n(function (InlayHintKind) {\n InlayHintKind[InlayHintKind[\"Type\"] = 1] = \"Type\";\n InlayHintKind[InlayHintKind[\"Parameter\"] = 2] = \"Parameter\";\n})(InlayHintKind || (InlayHintKind = {}));\n/**\n * @internal\n */\nexport const TokenizationRegistry = 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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../base/common/strings.js';\nimport { IndentAction } from './languageConfiguration.js';\nimport { createScopedLineTokens } from './supports.js';\nimport { getScopedLineTokens } from './languageConfigurationRegistry.js';\n/**\n * Get nearest preceding line which doesn't match unIndentPattern or contains all whitespace.\n * Result:\n * -1: run into the boundary of embedded languages\n * 0: every line above are invalid\n * else: nearest preceding line of the same language\n */\nfunction getPrecedingValidLine(model, lineNumber, indentRulesSupport) {\n const languageId = model.tokenization.getLanguageIdAtPosition(lineNumber, 0);\n if (lineNumber > 1) {\n let lastLineNumber;\n let resultLineNumber = -1;\n for (lastLineNumber = lineNumber - 1; lastLineNumber >= 1; lastLineNumber--) {\n if (model.tokenization.getLanguageIdAtPosition(lastLineNumber, 0) !== languageId) {\n return resultLineNumber;\n }\n const text = model.getLineContent(lastLineNumber);\n if (indentRulesSupport.shouldIgnore(text) || /^\\s+$/.test(text) || text === '') {\n resultLineNumber = lastLineNumber;\n continue;\n }\n return lastLineNumber;\n }\n }\n return -1;\n}\n/**\n * Get inherited indentation from above lines.\n * 1. Find the nearest preceding line which doesn't match unIndentedLinePattern.\n * 2. If this line matches indentNextLinePattern or increaseIndentPattern, it means that the indent level of `lineNumber` should be 1 greater than this line.\n * 3. If this line doesn't match any indent rules\n * a. check whether the line above it matches indentNextLinePattern\n * b. If not, the indent level of this line is the result\n * 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 * 4. Otherwise, we fail to get an inherited indent from aboves. Return null and we should not touch the indent of `lineNumber`\n *\n * This function only return the inherited indent based on above lines, it doesn't check whether current line should decrease or not.\n */\nexport function getInheritIndentForLine(autoIndent, model, lineNumber, honorIntentialIndent = true, languageConfigurationService) {\n if (autoIndent < 4 /* EditorAutoIndentStrategy.Full */) {\n return null;\n }\n const indentRulesSupport = languageConfigurationService.getLanguageConfiguration(model.tokenization.getLanguageId()).indentRulesSupport;\n if (!indentRulesSupport) {\n return null;\n }\n if (lineNumber <= 1) {\n return {\n indentation: '',\n action: null\n };\n }\n const precedingUnIgnoredLine = getPrecedingValidLine(model, lineNumber, indentRulesSupport);\n if (precedingUnIgnoredLine < 0) {\n return null;\n }\n else if (precedingUnIgnoredLine < 1) {\n return {\n indentation: '',\n action: null\n };\n }\n const precedingUnIgnoredLineContent = model.getLineContent(precedingUnIgnoredLine);\n if (indentRulesSupport.shouldIncrease(precedingUnIgnoredLineContent) || indentRulesSupport.shouldIndentNextLine(precedingUnIgnoredLineContent)) {\n return {\n indentation: strings.getLeadingWhitespace(precedingUnIgnoredLineContent),\n action: IndentAction.Indent,\n line: precedingUnIgnoredLine\n };\n }\n else if (indentRulesSupport.shouldDecrease(precedingUnIgnoredLineContent)) {\n return {\n indentation: strings.getLeadingWhitespace(precedingUnIgnoredLineContent),\n action: null,\n line: precedingUnIgnoredLine\n };\n }\n else {\n // precedingUnIgnoredLine can not be ignored.\n // it doesn't increase indent of following lines\n // it doesn't increase just next line\n // so current line is not affect by precedingUnIgnoredLine\n // and then we should get a correct inheritted indentation from above lines\n if (precedingUnIgnoredLine === 1) {\n return {\n indentation: strings.getLeadingWhitespace(model.getLineContent(precedingUnIgnoredLine)),\n action: null,\n line: precedingUnIgnoredLine\n };\n }\n const previousLine = precedingUnIgnoredLine - 1;\n const previousLineIndentMetadata = indentRulesSupport.getIndentMetadata(model.getLineContent(previousLine));\n if (!(previousLineIndentMetadata & (1 /* IndentConsts.INCREASE_MASK */ | 2 /* IndentConsts.DECREASE_MASK */)) &&\n (previousLineIndentMetadata & 4 /* IndentConsts.INDENT_NEXTLINE_MASK */)) {\n let stopLine = 0;\n for (let i = previousLine - 1; i > 0; i--) {\n if (indentRulesSupport.shouldIndentNextLine(model.getLineContent(i))) {\n continue;\n }\n stopLine = i;\n break;\n }\n return {\n indentation: strings.getLeadingWhitespace(model.getLineContent(stopLine + 1)),\n action: null,\n line: stopLine + 1\n };\n }\n if (honorIntentialIndent) {\n return {\n indentation: strings.getLeadingWhitespace(model.getLineContent(precedingUnIgnoredLine)),\n action: null,\n line: precedingUnIgnoredLine\n };\n }\n else {\n // search from precedingUnIgnoredLine until we find one whose indent is not temporary\n for (let i = precedingUnIgnoredLine; i > 0; i--) {\n const lineContent = model.getLineContent(i);\n if (indentRulesSupport.shouldIncrease(lineContent)) {\n return {\n indentation: strings.getLeadingWhitespace(lineContent),\n action: IndentAction.Indent,\n line: i\n };\n }\n else if (indentRulesSupport.shouldIndentNextLine(lineContent)) {\n let stopLine = 0;\n for (let j = i - 1; j > 0; j--) {\n if (indentRulesSupport.shouldIndentNextLine(model.getLineContent(i))) {\n continue;\n }\n stopLine = j;\n break;\n }\n return {\n indentation: strings.getLeadingWhitespace(model.getLineContent(stopLine + 1)),\n action: null,\n line: stopLine + 1\n };\n }\n else if (indentRulesSupport.shouldDecrease(lineContent)) {\n return {\n indentation: strings.getLeadingWhitespace(lineContent),\n action: null,\n line: i\n };\n }\n }\n return {\n indentation: strings.getLeadingWhitespace(model.getLineContent(1)),\n action: null,\n line: 1\n };\n }\n }\n}\nexport function getGoodIndentForLine(autoIndent, virtualModel, languageId, lineNumber, indentConverter, languageConfigurationService) {\n if (autoIndent < 4 /* EditorAutoIndentStrategy.Full */) {\n return null;\n }\n const richEditSupport = languageConfigurationService.getLanguageConfiguration(languageId);\n if (!richEditSupport) {\n return null;\n }\n const indentRulesSupport = languageConfigurationService.getLanguageConfiguration(languageId).indentRulesSupport;\n if (!indentRulesSupport) {\n return null;\n }\n const indent = getInheritIndentForLine(autoIndent, virtualModel, lineNumber, undefined, languageConfigurationService);\n const lineContent = virtualModel.getLineContent(lineNumber);\n if (indent) {\n const inheritLine = indent.line;\n if (inheritLine !== undefined) {\n const enterResult = richEditSupport.onEnter(autoIndent, '', virtualModel.getLineContent(inheritLine), '');\n if (enterResult) {\n let indentation = strings.getLeadingWhitespace(virtualModel.getLineContent(inheritLine));\n if (enterResult.removeText) {\n indentation = indentation.substring(0, indentation.length - enterResult.removeText);\n }\n if ((enterResult.indentAction === IndentAction.Indent) ||\n (enterResult.indentAction === IndentAction.IndentOutdent)) {\n indentation = indentConverter.shiftIndent(indentation);\n }\n else if (enterResult.indentAction === IndentAction.Outdent) {\n indentation = indentConverter.unshiftIndent(indentation);\n }\n if (indentRulesSupport.shouldDecrease(lineContent)) {\n indentation = indentConverter.unshiftIndent(indentation);\n }\n if (enterResult.appendText) {\n indentation += enterResult.appendText;\n }\n return strings.getLeadingWhitespace(indentation);\n }\n }\n if (indentRulesSupport.shouldDecrease(lineContent)) {\n if (indent.action === IndentAction.Indent) {\n return indent.indentation;\n }\n else {\n return indentConverter.unshiftIndent(indent.indentation);\n }\n }\n else {\n if (indent.action === IndentAction.Indent) {\n return indentConverter.shiftIndent(indent.indentation);\n }\n else {\n return indent.indentation;\n }\n }\n }\n return null;\n}\nexport function getIndentForEnter(autoIndent, model, range, indentConverter, languageConfigurationService) {\n if (autoIndent < 4 /* EditorAutoIndentStrategy.Full */) {\n return null;\n }\n model.tokenization.forceTokenization(range.startLineNumber);\n const lineTokens = model.tokenization.getLineTokens(range.startLineNumber);\n const scopedLineTokens = createScopedLineTokens(lineTokens, range.startColumn - 1);\n const scopedLineText = scopedLineTokens.getLineContent();\n let embeddedLanguage = false;\n let beforeEnterText;\n if (scopedLineTokens.firstCharOffset > 0 && lineTokens.getLanguageId(0) !== scopedLineTokens.languageId) {\n // we are in the embeded language content\n embeddedLanguage = true; // if embeddedLanguage is true, then we don't touch the indentation of current line\n beforeEnterText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n }\n else {\n beforeEnterText = lineTokens.getLineContent().substring(0, range.startColumn - 1);\n }\n let afterEnterText;\n if (range.isEmpty()) {\n afterEnterText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n }\n else {\n const endScopedLineTokens = getScopedLineTokens(model, range.endLineNumber, range.endColumn);\n afterEnterText = endScopedLineTokens.getLineContent().substr(range.endColumn - 1 - scopedLineTokens.firstCharOffset);\n }\n const indentRulesSupport = languageConfigurationService.getLanguageConfiguration(scopedLineTokens.languageId).indentRulesSupport;\n if (!indentRulesSupport) {\n return null;\n }\n const beforeEnterResult = beforeEnterText;\n const beforeEnterIndent = strings.getLeadingWhitespace(beforeEnterText);\n const virtualModel = {\n tokenization: {\n getLineTokens: (lineNumber) => {\n return model.tokenization.getLineTokens(lineNumber);\n },\n getLanguageId: () => {\n return model.getLanguageId();\n },\n getLanguageIdAtPosition: (lineNumber, column) => {\n return model.getLanguageIdAtPosition(lineNumber, column);\n },\n },\n getLineContent: (lineNumber) => {\n if (lineNumber === range.startLineNumber) {\n return beforeEnterResult;\n }\n else {\n return model.getLineContent(lineNumber);\n }\n }\n };\n const currentLineIndent = strings.getLeadingWhitespace(lineTokens.getLineContent());\n const afterEnterAction = getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1, undefined, languageConfigurationService);\n if (!afterEnterAction) {\n const beforeEnter = embeddedLanguage ? currentLineIndent : beforeEnterIndent;\n return {\n beforeEnter: beforeEnter,\n afterEnter: beforeEnter\n };\n }\n let afterEnterIndent = embeddedLanguage ? currentLineIndent : afterEnterAction.indentation;\n if (afterEnterAction.action === IndentAction.Indent) {\n afterEnterIndent = indentConverter.shiftIndent(afterEnterIndent);\n }\n if (indentRulesSupport.shouldDecrease(afterEnterText)) {\n afterEnterIndent = indentConverter.unshiftIndent(afterEnterIndent);\n }\n return {\n beforeEnter: embeddedLanguage ? currentLineIndent : beforeEnterIndent,\n afterEnter: afterEnterIndent\n };\n}\n/**\n * We should always allow intentional indentation. It means, if users change the indentation of `lineNumber` and the content of\n * this line doesn't match decreaseIndentPattern, we should not adjust the indentation.\n */\nexport function getIndentActionForType(autoIndent, model, range, ch, indentConverter, languageConfigurationService) {\n if (autoIndent < 4 /* EditorAutoIndentStrategy.Full */) {\n return null;\n }\n const scopedLineTokens = getScopedLineTokens(model, range.startLineNumber, range.startColumn);\n if (scopedLineTokens.firstCharOffset) {\n // this line has mixed languages and indentation rules will not work\n return null;\n }\n const indentRulesSupport = languageConfigurationService.getLanguageConfiguration(scopedLineTokens.languageId).indentRulesSupport;\n if (!indentRulesSupport) {\n return null;\n }\n const scopedLineText = scopedLineTokens.getLineContent();\n const beforeTypeText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n // selection support\n let afterTypeText;\n if (range.isEmpty()) {\n afterTypeText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n }\n else {\n const endScopedLineTokens = getScopedLineTokens(model, range.endLineNumber, range.endColumn);\n afterTypeText = endScopedLineTokens.getLineContent().substr(range.endColumn - 1 - scopedLineTokens.firstCharOffset);\n }\n // If previous content already matches decreaseIndentPattern, it means indentation of this line should already be adjusted\n // Users might change the indentation by purpose and we should honor that instead of readjusting.\n if (!indentRulesSupport.shouldDecrease(beforeTypeText + afterTypeText) && indentRulesSupport.shouldDecrease(beforeTypeText + ch + afterTypeText)) {\n // after typing `ch`, the content matches decreaseIndentPattern, we should adjust the indent to a good manner.\n // 1. Get inherited indent action\n const r = getInheritIndentForLine(autoIndent, model, range.startLineNumber, false, languageConfigurationService);\n if (!r) {\n return null;\n }\n let indentation = r.indentation;\n if (r.action !== IndentAction.Indent) {\n indentation = indentConverter.unshiftIndent(indentation);\n }\n return indentation;\n }\n return null;\n}\nexport function getIndentMetadata(model, lineNumber, languageConfigurationService) {\n const indentRulesSupport = languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).indentRulesSupport;\n if (!indentRulesSupport) {\n return null;\n }\n if (lineNumber < 1 || lineNumber > model.getLineCount()) {\n return null;\n }\n return indentRulesSupport.getIndentMetadata(model.getLineContent(lineNumber));\n}\n","/*---------------------------------------------------------------------------------------------\n * 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 { IndentAction } from './languageConfiguration.js';\nimport { getIndentationAtPosition, getScopedLineTokens } from './languageConfigurationRegistry.js';\nexport function getEnterAction(autoIndent, model, range, languageConfigurationService) {\n const scopedLineTokens = getScopedLineTokens(model, range.startLineNumber, range.startColumn);\n const richEditSupport = languageConfigurationService.getLanguageConfiguration(scopedLineTokens.languageId);\n if (!richEditSupport) {\n return null;\n }\n const scopedLineText = scopedLineTokens.getLineContent();\n const beforeEnterText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n // selection support\n let afterEnterText;\n if (range.isEmpty()) {\n afterEnterText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset);\n }\n else {\n const endScopedLineTokens = getScopedLineTokens(model, range.endLineNumber, range.endColumn);\n afterEnterText = endScopedLineTokens.getLineContent().substr(range.endColumn - 1 - scopedLineTokens.firstCharOffset);\n }\n let previousLineText = '';\n if (range.startLineNumber > 1 && scopedLineTokens.firstCharOffset === 0) {\n // This is not the first line and the entire line belongs to this mode\n const oneLineAboveScopedLineTokens = getScopedLineTokens(model, range.startLineNumber - 1);\n if (oneLineAboveScopedLineTokens.languageId === scopedLineTokens.languageId) {\n // The line above ends with text belonging to the same mode\n previousLineText = oneLineAboveScopedLineTokens.getLineContent();\n }\n }\n const enterResult = richEditSupport.onEnter(autoIndent, previousLineText, beforeEnterText, afterEnterText);\n if (!enterResult) {\n return null;\n }\n const indentAction = enterResult.indentAction;\n let appendText = enterResult.appendText;\n const removeText = enterResult.removeText || 0;\n // Here we add `\\t` to appendText first because enterAction is leveraging appendText and removeText to change indentation.\n if (!appendText) {\n if ((indentAction === IndentAction.Indent) ||\n (indentAction === IndentAction.IndentOutdent)) {\n appendText = '\\t';\n }\n else {\n appendText = '';\n }\n }\n else if (indentAction === IndentAction.Indent) {\n appendText = '\\t' + appendText;\n }\n let indentation = getIndentationAtPosition(model, range.startLineNumber, range.startColumn);\n if (removeText) {\n indentation = indentation.substring(0, indentation.length - removeText);\n }\n return {\n indentAction: indentAction,\n appendText: appendText,\n removeText: removeText,\n indentation: indentation\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 *--------------------------------------------------------------------------------------------*/\nimport { createDecorator } from '../../../platform/instantiation/common/instantiation.js';\nexport const ILanguageService = createDecorator('languageService');\n","/*---------------------------------------------------------------------------------------------\n * Copyright (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 * Describes what to do with the indentation when pressing Enter.\n */\nexport var IndentAction;\n(function (IndentAction) {\n /**\n * Insert new line and copy the previous line's indentation.\n */\n IndentAction[IndentAction[\"None\"] = 0] = \"None\";\n /**\n * Insert new line and indent once (relative to the previous line's indentation).\n */\n IndentAction[IndentAction[\"Indent\"] = 1] = \"Indent\";\n /**\n * Insert two new lines:\n * - the first one indented which will hold the cursor\n * - the second one at the same indentation level\n */\n IndentAction[IndentAction[\"IndentOutdent\"] = 2] = \"IndentOutdent\";\n /**\n * Insert new line and outdent once (relative to the previous line's indentation).\n */\n IndentAction[IndentAction[\"Outdent\"] = 3] = \"Outdent\";\n})(IndentAction || (IndentAction = {}));\n/**\n * @internal\n */\nexport class StandardAutoClosingPairConditional {\n constructor(source) {\n this._neutralCharacter = null;\n this._neutralCharacterSearched = false;\n this.open = source.open;\n this.close = source.close;\n // initially allowed in all tokens\n this._inString = true;\n this._inComment = true;\n this._inRegEx = true;\n if (Array.isArray(source.notIn)) {\n for (let i = 0, len = source.notIn.length; i < len; i++) {\n const notIn = source.notIn[i];\n switch (notIn) {\n case 'string':\n this._inString = false;\n break;\n case 'comment':\n this._inComment = false;\n break;\n case 'regex':\n this._inRegEx = false;\n break;\n }\n }\n }\n }\n isOK(standardToken) {\n switch (standardToken) {\n case 0 /* StandardTokenType.Other */:\n return true;\n case 1 /* StandardTokenType.Comment */:\n return this._inComment;\n case 2 /* StandardTokenType.String */:\n return this._inString;\n case 3 /* StandardTokenType.RegEx */:\n return this._inRegEx;\n }\n }\n shouldAutoClose(context, column) {\n // Always complete on empty line\n if (context.getTokenCount() === 0) {\n return true;\n }\n const tokenIndex = context.findTokenIndexAtOffset(column - 2);\n const standardTokenType = context.getStandardTokenType(tokenIndex);\n return this.isOK(standardTokenType);\n }\n _findNeutralCharacterInRange(fromCharCode, toCharCode) {\n for (let charCode = fromCharCode; charCode <= toCharCode; charCode++) {\n const character = String.fromCharCode(charCode);\n if (!this.open.includes(character) && !this.close.includes(character)) {\n return character;\n }\n }\n return null;\n }\n /**\n * Find a character in the range [0-9a-zA-Z] that does not appear in the open or close\n */\n findNeutralCharacter() {\n if (!this._neutralCharacterSearched) {\n this._neutralCharacterSearched = true;\n if (!this._neutralCharacter) {\n this._neutralCharacter = this._findNeutralCharacterInRange(48 /* CharCode.Digit0 */, 57 /* CharCode.Digit9 */);\n }\n if (!this._neutralCharacter) {\n this._neutralCharacter = this._findNeutralCharacterInRange(97 /* CharCode.a */, 122 /* CharCode.z */);\n }\n if (!this._neutralCharacter) {\n this._neutralCharacter = this._findNeutralCharacterInRange(65 /* CharCode.A */, 90 /* CharCode.Z */);\n }\n }\n return this._neutralCharacter;\n }\n}\n/**\n * @internal\n */\nexport class AutoClosingPairs {\n constructor(autoClosingPairs) {\n this.autoClosingPairsOpenByStart = new Map();\n this.autoClosingPairsOpenByEnd = new Map();\n this.autoClosingPairsCloseByStart = new Map();\n this.autoClosingPairsCloseByEnd = new Map();\n this.autoClosingPairsCloseSingleChar = new Map();\n for (const pair of autoClosingPairs) {\n appendEntry(this.autoClosingPairsOpenByStart, pair.open.charAt(0), pair);\n appendEntry(this.autoClosingPairsOpenByEnd, pair.open.charAt(pair.open.length - 1), pair);\n appendEntry(this.autoClosingPairsCloseByStart, pair.close.charAt(0), pair);\n appendEntry(this.autoClosingPairsCloseByEnd, pair.close.charAt(pair.close.length - 1), pair);\n if (pair.close.length === 1 && pair.open.length === 1) {\n appendEntry(this.autoClosingPairsCloseSingleChar, pair.close, pair);\n }\n }\n }\n}\nfunction appendEntry(target, key, value) {\n if (target.has(key)) {\n target.get(key).push(value);\n }\n else {\n target.set(key, [value]);\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 *--------------------------------------------------------------------------------------------*/\nimport { StandardAutoClosingPairConditional } from '../languageConfiguration.js';\nexport class CharacterPairSupport {\n constructor(config) {\n if (config.autoClosingPairs) {\n this._autoClosingPairs = config.autoClosingPairs.map(el => new StandardAutoClosingPairConditional(el));\n }\n else if (config.brackets) {\n this._autoClosingPairs = config.brackets.map(b => new StandardAutoClosingPairConditional({ open: b[0], close: b[1] }));\n }\n else {\n this._autoClosingPairs = [];\n }\n if (config.__electricCharacterSupport && config.__electricCharacterSupport.docComment) {\n const docComment = config.__electricCharacterSupport.docComment;\n // IDocComment is legacy, only partially supported\n this._autoClosingPairs.push(new StandardAutoClosingPairConditional({ open: docComment.open, close: docComment.close || '' }));\n }\n this._autoCloseBefore = typeof config.autoCloseBefore === 'string' ? config.autoCloseBefore : CharacterPairSupport.DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED;\n this._surroundingPairs = config.surroundingPairs || this._autoClosingPairs;\n }\n getAutoClosingPairs() {\n return this._autoClosingPairs;\n }\n getAutoCloseBeforeSet() {\n return this._autoCloseBefore;\n }\n getSurroundingPairs() {\n return this._surroundingPairs;\n }\n}\nCharacterPairSupport.DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED = ';:.,=}])> \\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 *--------------------------------------------------------------------------------------------*/\nimport { distinct } from '../../../../base/common/arrays.js';\nimport { ignoreBracketsInToken } from '../supports.js';\nimport { BracketsUtils } from './richEditBrackets.js';\nexport class BracketElectricCharacterSupport {\n constructor(richEditBrackets) {\n this._richEditBrackets = richEditBrackets;\n }\n getElectricCharacters() {\n const result = [];\n if (this._richEditBrackets) {\n for (const bracket of this._richEditBrackets.brackets) {\n for (const close of bracket.close) {\n const lastChar = close.charAt(close.length - 1);\n result.push(lastChar);\n }\n }\n }\n return distinct(result);\n }\n onElectricCharacter(character, context, column) {\n if (!this._richEditBrackets || this._richEditBrackets.brackets.length === 0) {\n return null;\n }\n const tokenIndex = context.findTokenIndexAtOffset(column - 1);\n if (ignoreBracketsInToken(context.getStandardTokenType(tokenIndex))) {\n return null;\n }\n const reversedBracketRegex = this._richEditBrackets.reversedRegex;\n const text = context.getLineContent().substring(0, column - 1) + character;\n const r = BracketsUtils.findPrevBracketInRange(reversedBracketRegex, 1, text, 0, text.length);\n if (!r) {\n return null;\n }\n const bracketText = text.substring(r.startColumn - 1, r.endColumn - 1).toLowerCase();\n const isOpen = this._richEditBrackets.textIsOpenBracket[bracketText];\n if (isOpen) {\n return null;\n }\n const textBeforeBracket = context.getActualLineContentBefore(r.startColumn - 1);\n if (!/^\\s*$/.test(textBeforeBracket)) {\n // There is other text on the line before the bracket\n return null;\n }\n return {\n matchOpenBracket: bracketText\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 *--------------------------------------------------------------------------------------------*/\nfunction resetGlobalRegex(reg) {\n if (reg.global) {\n reg.lastIndex = 0;\n }\n return true;\n}\nexport class IndentRulesSupport {\n constructor(indentationRules) {\n this._indentationRules = indentationRules;\n }\n shouldIncrease(text) {\n if (this._indentationRules) {\n if (this._indentationRules.increaseIndentPattern && resetGlobalRegex(this._indentationRules.increaseIndentPattern) && this._indentationRules.increaseIndentPattern.test(text)) {\n return true;\n }\n // if (this._indentationRules.indentNextLinePattern && this._indentationRules.indentNextLinePattern.test(text)) {\n // \treturn true;\n // }\n }\n return false;\n }\n shouldDecrease(text) {\n if (this._indentationRules && this._indentationRules.decreaseIndentPattern && resetGlobalRegex(this._indentationRules.decreaseIndentPattern) && this._indentationRules.decreaseIndentPattern.test(text)) {\n return true;\n }\n return false;\n }\n shouldIndentNextLine(text) {\n if (this._indentationRules && this._indentationRules.indentNextLinePattern && resetGlobalRegex(this._indentationRules.indentNextLinePattern) && this._indentationRules.indentNextLinePattern.test(text)) {\n return true;\n }\n return false;\n }\n shouldIgnore(text) {\n // the text matches `unIndentedLinePattern`\n if (this._indentationRules && this._indentationRules.unIndentedLinePattern && resetGlobalRegex(this._indentationRules.unIndentedLinePattern) && this._indentationRules.unIndentedLinePattern.test(text)) {\n return true;\n }\n return false;\n }\n getIndentMetadata(text) {\n let ret = 0;\n if (this.shouldIncrease(text)) {\n ret += 1 /* IndentConsts.INCREASE_MASK */;\n }\n if (this.shouldDecrease(text)) {\n ret += 2 /* IndentConsts.DECREASE_MASK */;\n }\n if (this.shouldIndentNextLine(text)) {\n ret += 4 /* IndentConsts.INDENT_NEXTLINE_MASK */;\n }\n if (this.shouldIgnore(text)) {\n ret += 8 /* IndentConsts.UNINDENT_MASK */;\n }\n return ret;\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 *--------------------------------------------------------------------------------------------*/\nimport { onUnexpectedError } from '../../../../base/common/errors.js';\nimport * as strings from '../../../../base/common/strings.js';\nimport { IndentAction } from '../languageConfiguration.js';\nexport class OnEnterSupport {\n constructor(opts) {\n opts = opts || {};\n opts.brackets = opts.brackets || [\n ['(', ')'],\n ['{', '}'],\n ['[', ']']\n ];\n this._brackets = [];\n opts.brackets.forEach((bracket) => {\n const openRegExp = OnEnterSupport._createOpenBracketRegExp(bracket[0]);\n const closeRegExp = OnEnterSupport._createCloseBracketRegExp(bracket[1]);\n if (openRegExp && closeRegExp) {\n this._brackets.push({\n open: bracket[0],\n openRegExp: openRegExp,\n close: bracket[1],\n closeRegExp: closeRegExp,\n });\n }\n });\n this._regExpRules = opts.onEnterRules || [];\n }\n onEnter(autoIndent, previousLineText, beforeEnterText, afterEnterText) {\n // (1): `regExpRules`\n if (autoIndent >= 3 /* EditorAutoIndentStrategy.Advanced */) {\n for (let i = 0, len = this._regExpRules.length; i < len; i++) {\n const rule = this._regExpRules[i];\n const regResult = [{\n reg: rule.beforeText,\n text: beforeEnterText\n }, {\n reg: rule.afterText,\n text: afterEnterText\n }, {\n reg: rule.previousLineText,\n text: previousLineText\n }].every((obj) => {\n if (!obj.reg) {\n return true;\n }\n obj.reg.lastIndex = 0; // To disable the effect of the \"g\" flag.\n return obj.reg.test(obj.text);\n });\n if (regResult) {\n return rule.action;\n }\n }\n }\n // (2): Special indent-outdent\n if (autoIndent >= 2 /* EditorAutoIndentStrategy.Brackets */) {\n if (beforeEnterText.length > 0 && afterEnterText.length > 0) {\n for (let i = 0, len = this._brackets.length; i < len; i++) {\n const bracket = this._brackets[i];\n if (bracket.openRegExp.test(beforeEnterText) && bracket.closeRegExp.test(afterEnterText)) {\n return { indentAction: IndentAction.IndentOutdent };\n }\n }\n }\n }\n // (4): Open bracket based logic\n if (autoIndent >= 2 /* EditorAutoIndentStrategy.Brackets */) {\n if (beforeEnterText.length > 0) {\n for (let i = 0, len = this._brackets.length; i < len; i++) {\n const bracket = this._brackets[i];\n if (bracket.openRegExp.test(beforeEnterText)) {\n return { indentAction: IndentAction.Indent };\n }\n }\n }\n }\n return null;\n }\n static _createOpenBracketRegExp(bracket) {\n let str = strings.escapeRegExpCharacters(bracket);\n if (!/\\B/.test(str.charAt(0))) {\n str = '\\\\b' + str;\n }\n str += '\\\\s*$';\n return OnEnterSupport._safeRegExp(str);\n }\n static _createCloseBracketRegExp(bracket) {\n let str = strings.escapeRegExpCharacters(bracket);\n if (!/\\B/.test(str.charAt(str.length - 1))) {\n str = str + '\\\\b';\n }\n str = '^\\\\s*' + str;\n return OnEnterSupport._safeRegExp(str);\n }\n static _safeRegExp(def) {\n try {\n return new RegExp(def);\n }\n catch (err) {\n onUnexpectedError(err);\n return null;\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 *--------------------------------------------------------------------------------------------*/\nimport { CachedFunction } from '../../../../base/common/cache.js';\nimport { BugIndicatingError } from '../../../../base/common/errors.js';\n/**\n * Captures all bracket related configurations for a single language.\n * Immutable.\n*/\nexport class LanguageBracketsConfiguration {\n constructor(languageId, config) {\n this.languageId = languageId;\n let brackets;\n // Prefer colorized bracket pairs, as they are more accurate.\n // TODO@hediet: Deprecate `colorizedBracketPairs` and increase accuracy for brackets.\n if (config.colorizedBracketPairs) {\n brackets = filterValidBrackets(config.colorizedBracketPairs.map(b => [b[0], b[1]]));\n }\n else if (config.brackets) {\n brackets = filterValidBrackets(config.brackets\n .map((b) => [b[0], b[1]])\n // Many languages set < ... > as bracket pair, even though they also use it as comparison operator.\n // This leads to problems when colorizing this bracket, so we exclude it by default.\n // Languages can still override this by configuring `colorizedBracketPairs`\n // https://github.com/microsoft/vscode/issues/132476\n .filter((p) => !(p[0] === '<' && p[1] === '>')));\n }\n else {\n brackets = [];\n }\n const openingBracketInfos = new CachedFunction((bracket) => {\n const closing = new Set();\n return {\n info: new OpeningBracketKind(this, bracket, closing),\n closing,\n };\n });\n const closingBracketInfos = new CachedFunction((bracket) => {\n const opening = new Set();\n return {\n info: new ClosingBracketKind(this, bracket, opening),\n opening,\n };\n });\n for (const [open, close] of brackets) {\n const opening = openingBracketInfos.get(open);\n const closing = closingBracketInfos.get(close);\n opening.closing.add(closing.info);\n closing.opening.add(opening.info);\n }\n this._openingBrackets = new Map([...openingBracketInfos.cachedValues].map(([k, v]) => [k, v.info]));\n this._closingBrackets = new Map([...closingBracketInfos.cachedValues].map(([k, v]) => [k, v.info]));\n }\n /**\n * No two brackets have the same bracket text.\n */\n get openingBrackets() {\n return [...this._openingBrackets.values()];\n }\n /**\n * No two brackets have the same bracket text.\n */\n get closingBrackets() {\n return [...this._closingBrackets.values()];\n }\n getOpeningBracketInfo(bracketText) {\n return this._openingBrackets.get(bracketText);\n }\n getClosingBracketInfo(bracketText) {\n return this._closingBrackets.get(bracketText);\n }\n getBracketInfo(bracketText) {\n return this.getOpeningBracketInfo(bracketText) || this.getClosingBracketInfo(bracketText);\n }\n}\nfunction filterValidBrackets(bracketPairs) {\n return bracketPairs.filter(([open, close]) => open !== '' && close !== '');\n}\nexport class BracketKindBase {\n constructor(config, bracketText) {\n this.config = config;\n this.bracketText = bracketText;\n }\n get languageId() {\n return this.config.languageId;\n }\n}\nexport class OpeningBracketKind extends BracketKindBase {\n constructor(config, bracketText, openedBrackets) {\n super(config, bracketText);\n this.openedBrackets = openedBrackets;\n this.isOpeningBracket = true;\n }\n}\nexport class ClosingBracketKind extends BracketKindBase {\n constructor(config, bracketText, \n /**\n * Non empty array of all opening brackets this bracket closes.\n */\n closedBrackets) {\n super(config, bracketText);\n this.closedBrackets = closedBrackets;\n this.isOpeningBracket = false;\n }\n /**\n * Checks if this bracket closes the given other bracket.\n * Brackets from other language configuration can be used (they will always return false).\n * If other is a bracket with the same language id, they have to be from the same configuration.\n */\n closes(other) {\n if (other.languageId === this.languageId) {\n if (other['config'] !== this.config) {\n throw new BugIndicatingError('Brackets from different language configuration cannot be used.');\n }\n }\n return this.closedBrackets.has(other);\n }\n getClosedBrackets() {\n return [...this.closedBrackets];\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable, toDisposable } from '../../../base/common/lifecycle.js';\nimport * as strings from '../../../base/common/strings.js';\nimport { DEFAULT_WORD_REGEXP, ensureValidWordDefinition } from '../core/wordHelper.js';\nimport { AutoClosingPairs } from './languageConfiguration.js';\nimport { createScopedLineTokens } from './supports.js';\nimport { CharacterPairSupport } from './supports/characterPair.js';\nimport { BracketElectricCharacterSupport } from './supports/electricCharacter.js';\nimport { IndentRulesSupport } from './supports/indentRules.js';\nimport { OnEnterSupport } from './supports/onEnter.js';\nimport { RichEditBrackets } from './supports/richEditBrackets.js';\nimport { createDecorator } from '../../../platform/instantiation/common/instantiation.js';\nimport { IConfigurationService } from '../../../platform/configuration/common/configuration.js';\nimport { ILanguageService } from './language.js';\nimport { registerSingleton } from '../../../platform/instantiation/common/extensions.js';\nimport { PLAINTEXT_LANGUAGE_ID } from './modesRegistry.js';\nimport { LanguageBracketsConfiguration } from './supports/languageBracketsConfiguration.js';\nexport class LanguageConfigurationServiceChangeEvent {\n constructor(languageId) {\n this.languageId = languageId;\n }\n affects(languageId) {\n return !this.languageId ? true : this.languageId === languageId;\n }\n}\nexport const ILanguageConfigurationService = createDecorator('languageConfigurationService');\nlet LanguageConfigurationService = class LanguageConfigurationService extends Disposable {\n constructor(configurationService, languageService) {\n super();\n this.configurationService = configurationService;\n this.languageService = languageService;\n this._registry = this._register(new LanguageConfigurationRegistry());\n this.onDidChangeEmitter = this._register(new Emitter());\n this.onDidChange = this.onDidChangeEmitter.event;\n this.configurations = new Map();\n const languageConfigKeys = new Set(Object.values(customizedLanguageConfigKeys));\n this._register(this.configurationService.onDidChangeConfiguration((e) => {\n const globalConfigChanged = e.change.keys.some((k) => languageConfigKeys.has(k));\n const localConfigChanged = e.change.overrides\n .filter(([overrideLangName, keys]) => keys.some((k) => languageConfigKeys.has(k)))\n .map(([overrideLangName]) => overrideLangName);\n if (globalConfigChanged) {\n this.configurations.clear();\n this.onDidChangeEmitter.fire(new LanguageConfigurationServiceChangeEvent(undefined));\n }\n else {\n for (const languageId of localConfigChanged) {\n if (this.languageService.isRegisteredLanguageId(languageId)) {\n this.configurations.delete(languageId);\n this.onDidChangeEmitter.fire(new LanguageConfigurationServiceChangeEvent(languageId));\n }\n }\n }\n }));\n this._register(this._registry.onDidChange((e) => {\n this.configurations.delete(e.languageId);\n this.onDidChangeEmitter.fire(new LanguageConfigurationServiceChangeEvent(e.languageId));\n }));\n }\n register(languageId, configuration, priority) {\n return this._registry.register(languageId, configuration, priority);\n }\n getLanguageConfiguration(languageId) {\n let result = this.configurations.get(languageId);\n if (!result) {\n result = computeConfig(languageId, this._registry, this.configurationService, this.languageService);\n this.configurations.set(languageId, result);\n }\n return result;\n }\n};\nLanguageConfigurationService = __decorate([\n __param(0, IConfigurationService),\n __param(1, ILanguageService)\n], LanguageConfigurationService);\nexport { LanguageConfigurationService };\nfunction computeConfig(languageId, registry, configurationService, languageService) {\n let languageConfig = registry.getLanguageConfiguration(languageId);\n if (!languageConfig) {\n if (!languageService.isRegisteredLanguageId(languageId)) {\n throw new Error(`Language id \"${languageId}\" is not configured nor known`);\n }\n languageConfig = new ResolvedLanguageConfiguration(languageId, {});\n }\n const customizedConfig = getCustomizedLanguageConfig(languageConfig.languageId, configurationService);\n const data = combineLanguageConfigurations([languageConfig.underlyingConfig, customizedConfig]);\n const config = new ResolvedLanguageConfiguration(languageConfig.languageId, data);\n return config;\n}\nconst customizedLanguageConfigKeys = {\n brackets: 'editor.language.brackets',\n colorizedBracketPairs: 'editor.language.colorizedBracketPairs'\n};\nfunction getCustomizedLanguageConfig(languageId, configurationService) {\n const brackets = configurationService.getValue(customizedLanguageConfigKeys.brackets, {\n overrideIdentifier: languageId,\n });\n const colorizedBracketPairs = configurationService.getValue(customizedLanguageConfigKeys.colorizedBracketPairs, {\n overrideIdentifier: languageId,\n });\n return {\n brackets: validateBracketPairs(brackets),\n colorizedBracketPairs: validateBracketPairs(colorizedBracketPairs),\n };\n}\nfunction validateBracketPairs(data) {\n if (!Array.isArray(data)) {\n return undefined;\n }\n return data.map(pair => {\n if (!Array.isArray(pair) || pair.length !== 2) {\n return undefined;\n }\n return [pair[0], pair[1]];\n }).filter((p) => !!p);\n}\nexport function getIndentationAtPosition(model, lineNumber, column) {\n const lineText = model.getLineContent(lineNumber);\n let indentation = strings.getLeadingWhitespace(lineText);\n if (indentation.length > column - 1) {\n indentation = indentation.substring(0, column - 1);\n }\n return indentation;\n}\nexport function getScopedLineTokens(model, lineNumber, columnNumber) {\n model.tokenization.forceTokenization(lineNumber);\n const lineTokens = model.tokenization.getLineTokens(lineNumber);\n const column = (typeof columnNumber === 'undefined' ? model.getLineMaxColumn(lineNumber) - 1 : columnNumber - 1);\n return createScopedLineTokens(lineTokens, column);\n}\nclass ComposedLanguageConfiguration {\n constructor(languageId) {\n this.languageId = languageId;\n this._resolved = null;\n this._entries = [];\n this._order = 0;\n this._resolved = null;\n }\n register(configuration, priority) {\n const entry = new LanguageConfigurationContribution(configuration, priority, ++this._order);\n this._entries.push(entry);\n this._resolved = null;\n return toDisposable(() => {\n for (let i = 0; i < this._entries.length; i++) {\n if (this._entries[i] === entry) {\n this._entries.splice(i, 1);\n this._resolved = null;\n break;\n }\n }\n });\n }\n getResolvedConfiguration() {\n if (!this._resolved) {\n const config = this._resolve();\n if (config) {\n this._resolved = new ResolvedLanguageConfiguration(this.languageId, config);\n }\n }\n return this._resolved;\n }\n _resolve() {\n if (this._entries.length === 0) {\n return null;\n }\n this._entries.sort(LanguageConfigurationContribution.cmp);\n return combineLanguageConfigurations(this._entries.map(e => e.configuration));\n }\n}\nfunction combineLanguageConfigurations(configs) {\n let result = {\n comments: undefined,\n brackets: undefined,\n wordPattern: undefined,\n indentationRules: undefined,\n onEnterRules: undefined,\n autoClosingPairs: undefined,\n surroundingPairs: undefined,\n autoCloseBefore: undefined,\n folding: undefined,\n colorizedBracketPairs: undefined,\n __electricCharacterSupport: undefined,\n };\n for (const entry of configs) {\n result = {\n comments: entry.comments || result.comments,\n brackets: entry.brackets || result.brackets,\n wordPattern: entry.wordPattern || result.wordPattern,\n indentationRules: entry.indentationRules || result.indentationRules,\n onEnterRules: entry.onEnterRules || result.onEnterRules,\n autoClosingPairs: entry.autoClosingPairs || result.autoClosingPairs,\n surroundingPairs: entry.surroundingPairs || result.surroundingPairs,\n autoCloseBefore: entry.autoCloseBefore || result.autoCloseBefore,\n folding: entry.folding || result.folding,\n colorizedBracketPairs: entry.colorizedBracketPairs || result.colorizedBracketPairs,\n __electricCharacterSupport: entry.__electricCharacterSupport || result.__electricCharacterSupport,\n };\n }\n return result;\n}\nclass LanguageConfigurationContribution {\n constructor(configuration, priority, order) {\n this.configuration = configuration;\n this.priority = priority;\n this.order = order;\n }\n static cmp(a, b) {\n if (a.priority === b.priority) {\n // higher order last\n return a.order - b.order;\n }\n // higher priority last\n return a.priority - b.priority;\n }\n}\nexport class LanguageConfigurationChangeEvent {\n constructor(languageId) {\n this.languageId = languageId;\n }\n}\nexport class LanguageConfigurationRegistry extends Disposable {\n constructor() {\n super();\n this._entries = new Map();\n this._onDidChange = this._register(new Emitter());\n this.onDidChange = this._onDidChange.event;\n this._register(this.register(PLAINTEXT_LANGUAGE_ID, {\n brackets: [\n ['(', ')'],\n ['[', ']'],\n ['{', '}'],\n ],\n surroundingPairs: [\n { open: '{', close: '}' },\n { open: '[', close: ']' },\n { open: '(', close: ')' },\n { open: '<', close: '>' },\n { open: '\\\"', close: '\\\"' },\n { open: '\\'', close: '\\'' },\n { open: '`', close: '`' },\n ],\n colorizedBracketPairs: [],\n folding: {\n offSide: true\n }\n }, 0));\n }\n /**\n * @param priority Use a higher number for higher priority\n */\n register(languageId, configuration, priority = 0) {\n let entries = this._entries.get(languageId);\n if (!entries) {\n entries = new ComposedLanguageConfiguration(languageId);\n this._entries.set(languageId, entries);\n }\n const disposable = entries.register(configuration, priority);\n this._onDidChange.fire(new LanguageConfigurationChangeEvent(languageId));\n return toDisposable(() => {\n disposable.dispose();\n this._onDidChange.fire(new LanguageConfigurationChangeEvent(languageId));\n });\n }\n getLanguageConfiguration(languageId) {\n const entries = this._entries.get(languageId);\n return (entries === null || entries === void 0 ? void 0 : entries.getResolvedConfiguration()) || null;\n }\n}\n/**\n * Immutable.\n*/\nexport class ResolvedLanguageConfiguration {\n constructor(languageId, underlyingConfig) {\n this.languageId = languageId;\n this.underlyingConfig = underlyingConfig;\n this._brackets = null;\n this._electricCharacter = null;\n this._onEnterSupport =\n this.underlyingConfig.brackets ||\n this.underlyingConfig.indentationRules ||\n this.underlyingConfig.onEnterRules\n ? new OnEnterSupport(this.underlyingConfig)\n : null;\n this.comments = ResolvedLanguageConfiguration._handleComments(this.underlyingConfig);\n this.characterPair = new CharacterPairSupport(this.underlyingConfig);\n this.wordDefinition = this.underlyingConfig.wordPattern || DEFAULT_WORD_REGEXP;\n this.indentationRules = this.underlyingConfig.indentationRules;\n if (this.underlyingConfig.indentationRules) {\n this.indentRulesSupport = new IndentRulesSupport(this.underlyingConfig.indentationRules);\n }\n else {\n this.indentRulesSupport = null;\n }\n this.foldingRules = this.underlyingConfig.folding || {};\n this.bracketsNew = new LanguageBracketsConfiguration(languageId, this.underlyingConfig);\n }\n getWordDefinition() {\n return ensureValidWordDefinition(this.wordDefinition);\n }\n get brackets() {\n if (!this._brackets && this.underlyingConfig.brackets) {\n this._brackets = new RichEditBrackets(this.languageId, this.underlyingConfig.brackets);\n }\n return this._brackets;\n }\n get electricCharacter() {\n if (!this._electricCharacter) {\n this._electricCharacter = new BracketElectricCharacterSupport(this.brackets);\n }\n return this._electricCharacter;\n }\n onEnter(autoIndent, previousLineText, beforeEnterText, afterEnterText) {\n if (!this._onEnterSupport) {\n return null;\n }\n return this._onEnterSupport.onEnter(autoIndent, previousLineText, beforeEnterText, afterEnterText);\n }\n getAutoClosingPairs() {\n return new AutoClosingPairs(this.characterPair.getAutoClosingPairs());\n }\n getAutoCloseBeforeSet() {\n return this.characterPair.getAutoCloseBeforeSet();\n }\n getSurroundingPairs() {\n return this.characterPair.getSurroundingPairs();\n }\n static _handleComments(conf) {\n const commentRule = conf.comments;\n if (!commentRule) {\n return null;\n }\n // comment configuration\n const comments = {};\n if (commentRule.lineComment) {\n comments.lineCommentToken = commentRule.lineComment;\n }\n if (commentRule.blockComment) {\n const [blockStart, blockEnd] = commentRule.blockComment;\n comments.blockCommentStartToken = blockStart;\n comments.blockCommentEndToken = blockEnd;\n }\n return comments;\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 *--------------------------------------------------------------------------------------------*/\nimport * as nls from '../../../nls.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { Registry } from '../../../platform/registry/common/platform.js';\nimport { Mimes } from '../../../base/common/mime.js';\nimport { Extensions as ConfigurationExtensions } from '../../../platform/configuration/common/configurationRegistry.js';\n// Define extension point ids\nexport const Extensions = {\n ModesRegistry: 'editor.modesRegistry'\n};\nexport class EditorModesRegistry {\n constructor() {\n this._onDidChangeLanguages = new Emitter();\n this.onDidChangeLanguages = this._onDidChangeLanguages.event;\n this._languages = [];\n }\n registerLanguage(def) {\n this._languages.push(def);\n this._onDidChangeLanguages.fire(undefined);\n return {\n dispose: () => {\n for (let i = 0, len = this._languages.length; i < len; i++) {\n if (this._languages[i] === def) {\n this._languages.splice(i, 1);\n return;\n }\n }\n }\n };\n }\n getLanguages() {\n return this._languages;\n }\n}\nexport const ModesRegistry = new EditorModesRegistry();\nRegistry.add(Extensions.ModesRegistry, ModesRegistry);\nexport const PLAINTEXT_LANGUAGE_ID = 'plaintext';\nexport const PLAINTEXT_EXTENSION = '.txt';\nModesRegistry.registerLanguage({\n id: PLAINTEXT_LANGUAGE_ID,\n extensions: [PLAINTEXT_EXTENSION],\n aliases: [nls.localize('plainText.alias', \"Plain Text\"), 'text'],\n mimetypes: [Mimes.text]\n});\nRegistry.as(ConfigurationExtensions.Configuration)\n .registerDefaultConfigurations([{\n overrides: {\n '[plaintext]': {\n 'editor.unicodeHighlight.ambiguousCharacters': false,\n 'editor.unicodeHighlight.invisibleCharacters': false\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 *--------------------------------------------------------------------------------------------*/\nimport { Token, TokenizationResult, EncodedTokenizationResult } from '../languages.js';\nexport const NullState = new class {\n clone() {\n return this;\n }\n equals(other) {\n return (this === other);\n }\n};\nexport function nullTokenize(languageId, state) {\n return new TokenizationResult([new Token(0, '', languageId)], state);\n}\nexport function nullTokenizeEncoded(languageId, state) {\n const tokens = new Uint32Array(2);\n tokens[0] = 0;\n tokens[1] = ((languageId << 0 /* MetadataConsts.LANGUAGEID_OFFSET */)\n | (0 /* StandardTokenType.Other */ << 8 /* MetadataConsts.TOKEN_TYPE_OFFSET */)\n | (0 /* FontStyle.None */ << 11 /* MetadataConsts.FONT_STYLE_OFFSET */)\n | (1 /* ColorId.DefaultForeground */ << 15 /* MetadataConsts.FOREGROUND_OFFSET */)\n | (2 /* ColorId.DefaultBackground */ << 24 /* MetadataConsts.BACKGROUND_OFFSET */)) >>> 0;\n return 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 *--------------------------------------------------------------------------------------------*/\nexport function createScopedLineTokens(context, offset) {\n const tokenCount = context.getCount();\n const tokenIndex = context.findTokenIndexAtOffset(offset);\n const desiredLanguageId = context.getLanguageId(tokenIndex);\n let lastTokenIndex = tokenIndex;\n while (lastTokenIndex + 1 < tokenCount && context.getLanguageId(lastTokenIndex + 1) === desiredLanguageId) {\n lastTokenIndex++;\n }\n let firstTokenIndex = tokenIndex;\n while (firstTokenIndex > 0 && context.getLanguageId(firstTokenIndex - 1) === desiredLanguageId) {\n firstTokenIndex--;\n }\n return new ScopedLineTokens(context, desiredLanguageId, firstTokenIndex, lastTokenIndex + 1, context.getStartOffset(firstTokenIndex), context.getEndOffset(lastTokenIndex));\n}\nexport class ScopedLineTokens {\n constructor(actual, languageId, firstTokenIndex, lastTokenIndex, firstCharOffset, lastCharOffset) {\n this._scopedLineTokensBrand = undefined;\n this._actual = actual;\n this.languageId = languageId;\n this._firstTokenIndex = firstTokenIndex;\n this._lastTokenIndex = lastTokenIndex;\n this.firstCharOffset = firstCharOffset;\n this._lastCharOffset = lastCharOffset;\n }\n getLineContent() {\n const actualLineContent = this._actual.getLineContent();\n return actualLineContent.substring(this.firstCharOffset, this._lastCharOffset);\n }\n getActualLineContentBefore(offset) {\n const actualLineContent = this._actual.getLineContent();\n return actualLineContent.substring(0, this.firstCharOffset + offset);\n }\n getTokenCount() {\n return this._lastTokenIndex - this._firstTokenIndex;\n }\n findTokenIndexAtOffset(offset) {\n return this._actual.findTokenIndexAtOffset(offset + this.firstCharOffset) - this._firstTokenIndex;\n }\n getStandardTokenType(tokenIndex) {\n return this._actual.getStandardTokenType(tokenIndex + this._firstTokenIndex);\n }\n}\nexport function ignoreBracketsInToken(standardTokenType) {\n return (standardTokenType & 3 /* 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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../../base/common/strings.js';\nimport * as stringBuilder from '../../core/stringBuilder.js';\nimport { Range } from '../../core/range.js';\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 constructor(languageId, index, open, close, forwardRegex, reversedRegex) {\n this._richEditBracketBrand = undefined;\n this.languageId = languageId;\n this.index = index;\n this.open = open;\n this.close = close;\n this.forwardRegex = forwardRegex;\n this.reversedRegex = reversedRegex;\n this._openSet = RichEditBracket._toSet(this.open);\n this._closeSet = RichEditBracket._toSet(this.close);\n }\n /**\n * Check if the provided `text` is an open bracket in this group.\n */\n isOpen(text) {\n return this._openSet.has(text);\n }\n /**\n * Check if the provided `text` is a close bracket in this group.\n */\n isClose(text) {\n return this._closeSet.has(text);\n }\n static _toSet(arr) {\n const result = new Set();\n for (const element of arr) {\n result.add(element);\n }\n return result;\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) {\n const N = brackets.length;\n brackets = brackets.map(b => [b[0].toLowerCase(), b[1].toLowerCase()]);\n const group = [];\n for (let i = 0; i < N; i++) {\n group[i] = i;\n }\n const areOverlapping = (a, b) => {\n const [aOpen, aClose] = a;\n const [bOpen, bClose] = b;\n return (aOpen === bOpen || aOpen === bClose || aClose === bOpen || aClose === bClose);\n };\n const mergeGroups = (g1, g2) => {\n const newG = Math.min(g1, g2);\n const oldG = Math.max(g1, g2);\n for (let i = 0; i < N; i++) {\n if (group[i] === oldG) {\n group[i] = newG;\n }\n }\n };\n // group together brackets that have the same open or the same close sequence\n for (let i = 0; i < N; i++) {\n const a = brackets[i];\n for (let j = i + 1; j < N; j++) {\n const b = brackets[j];\n if (areOverlapping(a, b)) {\n mergeGroups(group[i], group[j]);\n }\n }\n }\n const result = [];\n for (let g = 0; g < N; g++) {\n const currentOpen = [];\n const currentClose = [];\n for (let i = 0; i < N; i++) {\n if (group[i] === g) {\n const [open, close] = brackets[i];\n currentOpen.push(open);\n currentClose.push(close);\n }\n }\n if (currentOpen.length > 0) {\n result.push({\n open: currentOpen,\n close: currentClose\n });\n }\n }\n return result;\n}\nexport class RichEditBrackets {\n constructor(languageId, _brackets) {\n this._richEditBracketsBrand = undefined;\n const brackets = groupFuzzyBrackets(_brackets);\n this.brackets = brackets.map((b, index) => {\n return new RichEditBracket(languageId, index, b.open, b.close, getRegexForBracketPair(b.open, b.close, brackets, index), getReversedRegexForBracketPair(b.open, b.close, brackets, index));\n });\n this.forwardRegex = getRegexForBrackets(this.brackets);\n this.reversedRegex = getReversedRegexForBrackets(this.brackets);\n this.textIsBracket = {};\n this.textIsOpenBracket = {};\n this.maxBracketLength = 0;\n for (const bracket of this.brackets) {\n for (const open of bracket.open) {\n this.textIsBracket[open] = bracket;\n this.textIsOpenBracket[open] = true;\n this.maxBracketLength = Math.max(this.maxBracketLength, open.length);\n }\n for (const close of bracket.close) {\n this.textIsBracket[close] = bracket;\n this.textIsOpenBracket[close] = false;\n this.maxBracketLength = Math.max(this.maxBracketLength, close.length);\n }\n }\n }\n}\nfunction collectSuperstrings(str, brackets, currentIndex, dest) {\n for (let i = 0, len = brackets.length; i < len; i++) {\n if (i === currentIndex) {\n continue;\n }\n const bracket = brackets[i];\n for (const open of bracket.open) {\n if (open.indexOf(str) >= 0) {\n dest.push(open);\n }\n }\n for (const close of bracket.close) {\n if (close.indexOf(str) >= 0) {\n dest.push(close);\n }\n }\n }\n}\nfunction lengthcmp(a, b) {\n return a.length - b.length;\n}\nfunction unique(arr) {\n if (arr.length <= 1) {\n return arr;\n }\n const result = [];\n const seen = new Set();\n for (const element of arr) {\n if (seen.has(element)) {\n continue;\n }\n result.push(element);\n seen.add(element);\n }\n return result;\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, close, brackets, currentIndex) {\n // search in all brackets for other brackets that are a superstring of these brackets\n let pieces = [];\n pieces = pieces.concat(open);\n pieces = pieces.concat(close);\n for (let i = 0, len = pieces.length; i < len; i++) {\n collectSuperstrings(pieces[i], brackets, currentIndex, pieces);\n }\n pieces = unique(pieces);\n pieces.sort(lengthcmp);\n pieces.reverse();\n return createBracketOrRegExp(pieces);\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, close, brackets, currentIndex) {\n // search in all brackets for other brackets that are a superstring of these brackets\n let pieces = [];\n pieces = pieces.concat(open);\n pieces = pieces.concat(close);\n for (let i = 0, len = pieces.length; i < len; i++) {\n collectSuperstrings(pieces[i], brackets, currentIndex, pieces);\n }\n pieces = unique(pieces);\n pieces.sort(lengthcmp);\n pieces.reverse();\n return createBracketOrRegExp(pieces.map(toReversedString));\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) {\n let pieces = [];\n for (const bracket of brackets) {\n for (const open of bracket.open) {\n pieces.push(open);\n }\n for (const close of bracket.close) {\n pieces.push(close);\n }\n }\n pieces = unique(pieces);\n return createBracketOrRegExp(pieces);\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) {\n let pieces = [];\n for (const bracket of brackets) {\n for (const open of bracket.open) {\n pieces.push(open);\n }\n for (const close of bracket.close) {\n pieces.push(close);\n }\n }\n pieces = unique(pieces);\n return createBracketOrRegExp(pieces.map(toReversedString));\n}\nfunction prepareBracketForRegExp(str) {\n // This bracket pair uses letters like e.g. \"begin\" - \"end\"\n const insertWordBoundaries = (/^[\\w ]+$/.test(str));\n str = strings.escapeRegExpCharacters(str);\n return (insertWordBoundaries ? `\\\\b${str}\\\\b` : str);\n}\nfunction createBracketOrRegExp(pieces) {\n const regexStr = `(${pieces.map(prepareBracketForRegExp).join(')|(')})`;\n return strings.createRegExp(regexStr, true);\n}\nconst toReversedString = (function () {\n function reverse(str) {\n if (stringBuilder.hasTextDecoder) {\n // create a Uint16Array and then use a TextDecoder to create a string\n const arr = new Uint16Array(str.length);\n let offset = 0;\n for (let i = str.length - 1; i >= 0; i--) {\n arr[offset++] = str.charCodeAt(i);\n }\n return stringBuilder.getPlatformTextDecoder().decode(arr);\n }\n else {\n const result = [];\n let resultLen = 0;\n for (let i = str.length - 1; i >= 0; i--) {\n result[resultLen++] = str.charAt(i);\n }\n return result.join('');\n }\n }\n let lastInput = null;\n let lastOutput = null;\n return function toReversedString(str) {\n if (lastInput !== str) {\n lastInput = str;\n lastOutput = reverse(lastInput);\n }\n return lastOutput;\n };\n})();\nexport class BracketsUtils {\n static _findPrevBracketInText(reversedBracketRegex, lineNumber, reversedText, offset) {\n const m = reversedText.match(reversedBracketRegex);\n if (!m) {\n return null;\n }\n const matchOffset = reversedText.length - (m.index || 0);\n const matchLength = m[0].length;\n const absoluteMatchOffset = offset + matchOffset;\n return new Range(lineNumber, absoluteMatchOffset - matchLength + 1, lineNumber, absoluteMatchOffset + 1);\n }\n static findPrevBracketInRange(reversedBracketRegex, lineNumber, lineText, startOffset, endOffset) {\n // Because JS does not support backwards regex search, we search forwards in a reversed string with a reversed regex ;)\n const reversedLineText = toReversedString(lineText);\n const reversedSubstr = reversedLineText.substring(lineText.length - endOffset, lineText.length - startOffset);\n return this._findPrevBracketInText(reversedBracketRegex, lineNumber, reversedSubstr, startOffset);\n }\n static findNextBracketInText(bracketRegex, lineNumber, text, offset) {\n const m = text.match(bracketRegex);\n if (!m) {\n return null;\n }\n const matchOffset = m.index || 0;\n const matchLength = m[0].length;\n if (matchLength === 0) {\n return null;\n }\n const absoluteMatchOffset = offset + matchOffset;\n return new Range(lineNumber, absoluteMatchOffset + 1, lineNumber, absoluteMatchOffset + 1 + matchLength);\n }\n static findNextBracketInRange(bracketRegex, lineNumber, lineText, startOffset, endOffset) {\n const substr = lineText.substring(startOffset, endOffset);\n return this.findNextBracketInText(bracketRegex, lineNumber, substr, startOffset);\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 *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport * as strings from '../../../base/common/strings.js';\nimport { LineTokens } from '../tokens/lineTokens.js';\nimport { TokenizationRegistry } from '../languages.js';\nimport { NullState, nullTokenizeEncoded } from './nullTokenize.js';\nconst fallback = {\n getInitialState: () => NullState,\n tokenizeEncoded: (buffer, hasEOL, state) => nullTokenizeEncoded(0 /* LanguageId.Null */, state)\n};\nexport function tokenizeToString(languageService, text, languageId) {\n return __awaiter(this, void 0, void 0, function* () {\n if (!languageId) {\n return _tokenizeToString(text, languageService.languageIdCodec, fallback);\n }\n const tokenizationSupport = yield TokenizationRegistry.getOrCreate(languageId);\n return _tokenizeToString(text, languageService.languageIdCodec, tokenizationSupport || fallback);\n });\n}\nexport function tokenizeLineToHTML(text, viewLineTokens, colorMap, startOffset, endOffset, tabSize, useNbsp) {\n let result = ``;\n let charIndex = startOffset;\n let tabsCharDelta = 0;\n let prevIsSpace = true;\n for (let tokenIndex = 0, tokenCount = viewLineTokens.getCount(); tokenIndex < tokenCount; tokenIndex++) {\n const tokenEndIndex = viewLineTokens.getEndOffset(tokenIndex);\n if (tokenEndIndex <= startOffset) {\n continue;\n }\n let partContent = '';\n for (; charIndex < tokenEndIndex && charIndex < endOffset; charIndex++) {\n const charCode = text.charCodeAt(charIndex);\n switch (charCode) {\n case 9 /* CharCode.Tab */: {\n let insertSpacesCount = tabSize - (charIndex + tabsCharDelta) % tabSize;\n tabsCharDelta += insertSpacesCount - 1;\n while (insertSpacesCount > 0) {\n if (useNbsp && prevIsSpace) {\n partContent += ' ';\n prevIsSpace = false;\n }\n else {\n partContent += ' ';\n prevIsSpace = true;\n }\n insertSpacesCount--;\n }\n break;\n }\n case 60 /* CharCode.LessThan */:\n partContent += '<';\n prevIsSpace = false;\n break;\n case 62 /* CharCode.GreaterThan */:\n partContent += '>';\n prevIsSpace = false;\n break;\n case 38 /* CharCode.Ampersand */:\n partContent += '&';\n prevIsSpace = false;\n break;\n case 0 /* CharCode.Null */:\n partContent += '';\n prevIsSpace = false;\n break;\n case 65279 /* CharCode.UTF8_BOM */:\n case 8232 /* CharCode.LINE_SEPARATOR */:\n case 8233 /* CharCode.PARAGRAPH_SEPARATOR */:\n case 133 /* CharCode.NEXT_LINE */:\n partContent += '\\ufffd';\n prevIsSpace = false;\n break;\n case 13 /* CharCode.CarriageReturn */:\n // zero width space, because carriage return would introduce a line break\n partContent += '';\n prevIsSpace = false;\n break;\n case 32 /* CharCode.Space */:\n if (useNbsp && prevIsSpace) {\n partContent += ' ';\n prevIsSpace = false;\n }\n else {\n partContent += ' ';\n prevIsSpace = true;\n }\n break;\n default:\n partContent += String.fromCharCode(charCode);\n prevIsSpace = false;\n }\n }\n result += `${partContent}`;\n if (tokenEndIndex > endOffset || charIndex >= endOffset) {\n break;\n }\n }\n result += `
`;\n return result;\n}\nexport function _tokenizeToString(text, languageIdCodec, tokenizationSupport) {\n let result = ``;\n const lines = strings.splitLines(text);\n let currentState = tokenizationSupport.getInitialState();\n for (let i = 0, len = lines.length; i < len; i++) {\n const line = lines[i];\n if (i > 0) {\n result += `
`;\n }\n const tokenizationResult = tokenizationSupport.tokenizeEncoded(line, true, currentState);\n LineTokens.convertToEndOffset(tokenizationResult.tokens, line.length);\n const lineTokens = new LineTokens(tokenizationResult.tokens, line, languageIdCodec);\n const viewLineTokens = lineTokens.inflate();\n let startOffset = 0;\n for (let j = 0, lenJ = viewLineTokens.getCount(); j < lenJ; j++) {\n const type = viewLineTokens.getClassName(j);\n const endIndex = viewLineTokens.getEndOffset(j);\n result += `${strings.escape(line.substring(startOffset, endIndex))}`;\n startOffset = endIndex;\n }\n currentState = tokenizationResult.endState;\n }\n result += `
`;\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { equals } from '../../base/common/objects.js';\n/**\n * Vertical Lane in the overview ruler of the editor.\n */\nexport var OverviewRulerLane;\n(function (OverviewRulerLane) {\n OverviewRulerLane[OverviewRulerLane[\"Left\"] = 1] = \"Left\";\n OverviewRulerLane[OverviewRulerLane[\"Center\"] = 2] = \"Center\";\n OverviewRulerLane[OverviewRulerLane[\"Right\"] = 4] = \"Right\";\n OverviewRulerLane[OverviewRulerLane[\"Full\"] = 7] = \"Full\";\n})(OverviewRulerLane || (OverviewRulerLane = {}));\n/**\n * Position in the minimap to render the decoration.\n */\nexport var MinimapPosition;\n(function (MinimapPosition) {\n MinimapPosition[MinimapPosition[\"Inline\"] = 1] = \"Inline\";\n MinimapPosition[MinimapPosition[\"Gutter\"] = 2] = \"Gutter\";\n})(MinimapPosition || (MinimapPosition = {}));\nexport var InjectedTextCursorStops;\n(function (InjectedTextCursorStops) {\n InjectedTextCursorStops[InjectedTextCursorStops[\"Both\"] = 0] = \"Both\";\n InjectedTextCursorStops[InjectedTextCursorStops[\"Right\"] = 1] = \"Right\";\n InjectedTextCursorStops[InjectedTextCursorStops[\"Left\"] = 2] = \"Left\";\n InjectedTextCursorStops[InjectedTextCursorStops[\"None\"] = 3] = \"None\";\n})(InjectedTextCursorStops || (InjectedTextCursorStops = {}));\nexport class TextModelResolvedOptions {\n /**\n * @internal\n */\n constructor(src) {\n this._textModelResolvedOptionsBrand = undefined;\n this.tabSize = Math.max(1, src.tabSize | 0);\n this.indentSize = src.tabSize | 0;\n this.insertSpaces = Boolean(src.insertSpaces);\n this.defaultEOL = src.defaultEOL | 0;\n this.trimAutoWhitespace = Boolean(src.trimAutoWhitespace);\n this.bracketPairColorizationOptions = src.bracketPairColorizationOptions;\n }\n /**\n * @internal\n */\n equals(other) {\n return (this.tabSize === other.tabSize\n && this.indentSize === other.indentSize\n && this.insertSpaces === other.insertSpaces\n && this.defaultEOL === other.defaultEOL\n && this.trimAutoWhitespace === other.trimAutoWhitespace\n && equals(this.bracketPairColorizationOptions, other.bracketPairColorizationOptions));\n }\n /**\n * @internal\n */\n createChangeEvent(newOpts) {\n return {\n tabSize: this.tabSize !== newOpts.tabSize,\n indentSize: this.indentSize !== newOpts.indentSize,\n insertSpaces: this.insertSpaces !== newOpts.insertSpaces,\n trimAutoWhitespace: this.trimAutoWhitespace !== newOpts.trimAutoWhitespace,\n };\n }\n}\nexport class FindMatch {\n /**\n * @internal\n */\n constructor(range, matches) {\n this._findMatchBrand = undefined;\n this.range = range;\n this.matches = matches;\n }\n}\n/**\n * @internal\n */\nexport function isITextSnapshot(obj) {\n return (obj && typeof obj.read === 'function');\n}\n/**\n * @internal\n */\nexport class ValidAnnotatedEditOperation {\n constructor(identifier, range, text, forceMoveMarkers, isAutoWhitespaceEdit, _isTracked) {\n this.identifier = identifier;\n this.range = range;\n this.text = text;\n this.forceMoveMarkers = forceMoveMarkers;\n this.isAutoWhitespaceEdit = isAutoWhitespaceEdit;\n this._isTracked = _isTracked;\n }\n}\n/**\n * @internal\n */\nexport class SearchData {\n constructor(regex, wordSeparators, simpleSearch) {\n this.regex = regex;\n this.wordSeparators = wordSeparators;\n this.simpleSearch = simpleSearch;\n }\n}\n/**\n * @internal\n */\nexport class ApplyEditsResult {\n constructor(reverseEdits, changes, trimAutoWhitespaceLineNumbers) {\n this.reverseEdits = reverseEdits;\n this.changes = changes;\n this.trimAutoWhitespaceLineNumbers = trimAutoWhitespaceLineNumbers;\n }\n}\n/**\n * @internal\n */\nexport function shouldSynchronizeModel(model) {\n return (!model.isTooLargeForSyncing() && !model.isForSimpleWidget);\n}\n","/*---------------------------------------------------------------------------------------------\n * 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 { CursorColumns } from '../../../core/cursorColumns.js';\nimport { lengthAdd, lengthGetLineCount, lengthToObj, lengthZero } from './length.js';\nimport { SmallImmutableSet } from './smallImmutableSet.js';\n/**\n * The base implementation for all AST nodes.\n*/\nclass BaseAstNode {\n constructor(length) {\n this._length = length;\n }\n /**\n * The length of the entire node, which should equal the sum of lengths of all children.\n */\n get length() {\n return this._length;\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 constructor(length, openingBracket, child, closingBracket, missingOpeningBracketIds) {\n super(length);\n this.openingBracket = openingBracket;\n this.child = child;\n this.closingBracket = closingBracket;\n this.missingOpeningBracketIds = missingOpeningBracketIds;\n }\n static create(openingBracket, child, closingBracket) {\n let length = openingBracket.length;\n if (child) {\n length = lengthAdd(length, child.length);\n }\n if (closingBracket) {\n length = lengthAdd(length, closingBracket.length);\n }\n return new PairAstNode(length, openingBracket, child, closingBracket, child ? child.missingOpeningBracketIds : SmallImmutableSet.getEmpty());\n }\n get kind() {\n return 2 /* AstNodeKind.Pair */;\n }\n get listHeight() {\n return 0;\n }\n get childrenLength() {\n return 3;\n }\n getChild(idx) {\n switch (idx) {\n case 0: return this.openingBracket;\n case 1: return this.child;\n case 2: return this.closingBracket;\n }\n throw new Error('Invalid child index');\n }\n /**\n * Avoid using this property, it allocates an array!\n */\n get children() {\n const result = new Array();\n result.push(this.openingBracket);\n if (this.child) {\n result.push(this.child);\n }\n if (this.closingBracket) {\n result.push(this.closingBracket);\n }\n return result;\n }\n canBeReused(openBracketIds) {\n if (this.closingBracket === null) {\n // Unclosed pair ast nodes only\n // end at the end of the document\n // or when a parent node is closed.\n // This could be improved:\n // Only return false if some next token is neither \"undefined\" nor a bracket that closes a parent.\n return false;\n }\n if (openBracketIds.intersects(this.missingOpeningBracketIds)) {\n return false;\n }\n return true;\n }\n deepClone() {\n return new PairAstNode(this.length, this.openingBracket.deepClone(), this.child && this.child.deepClone(), this.closingBracket && this.closingBracket.deepClone(), this.missingOpeningBracketIds);\n }\n computeMinIndentation(offset, textModel) {\n return this.child ? this.child.computeMinIndentation(lengthAdd(offset, this.openingBracket.length), textModel) : Number.MAX_SAFE_INTEGER;\n }\n}\nexport class ListAstNode extends BaseAstNode {\n /**\n * Use ListAstNode.create.\n */\n constructor(length, listHeight, _missingOpeningBracketIds) {\n super(length);\n this.listHeight = listHeight;\n this._missingOpeningBracketIds = _missingOpeningBracketIds;\n this.cachedMinIndentation = -1;\n }\n /**\n * This method uses more memory-efficient list nodes that can only store 2 or 3 children.\n */\n static create23(item1, item2, item3, immutable = false) {\n let length = item1.length;\n let missingBracketIds = item1.missingOpeningBracketIds;\n if (item1.listHeight !== item2.listHeight) {\n throw new Error('Invalid list heights');\n }\n length = lengthAdd(length, item2.length);\n missingBracketIds = missingBracketIds.merge(item2.missingOpeningBracketIds);\n if (item3) {\n if (item1.listHeight !== item3.listHeight) {\n throw new Error('Invalid list heights');\n }\n length = lengthAdd(length, item3.length);\n missingBracketIds = missingBracketIds.merge(item3.missingOpeningBracketIds);\n }\n return immutable\n ? new Immutable23ListAstNode(length, item1.listHeight + 1, item1, item2, item3, missingBracketIds)\n : new TwoThreeListAstNode(length, item1.listHeight + 1, item1, item2, item3, missingBracketIds);\n }\n static getEmpty() {\n return new ImmutableArrayListAstNode(lengthZero, 0, [], SmallImmutableSet.getEmpty());\n }\n get kind() {\n return 4 /* AstNodeKind.List */;\n }\n get missingOpeningBracketIds() {\n return this._missingOpeningBracketIds;\n }\n throwIfImmutable() {\n // NOOP\n }\n makeLastElementMutable() {\n this.throwIfImmutable();\n const childCount = this.childrenLength;\n if (childCount === 0) {\n return undefined;\n }\n const lastChild = this.getChild(childCount - 1);\n const mutable = lastChild.kind === 4 /* AstNodeKind.List */ ? lastChild.toMutable() : lastChild;\n if (lastChild !== mutable) {\n this.setChild(childCount - 1, mutable);\n }\n return mutable;\n }\n makeFirstElementMutable() {\n this.throwIfImmutable();\n const childCount = this.childrenLength;\n if (childCount === 0) {\n return undefined;\n }\n const firstChild = this.getChild(0);\n const mutable = firstChild.kind === 4 /* AstNodeKind.List */ ? firstChild.toMutable() : firstChild;\n if (firstChild !== mutable) {\n this.setChild(0, mutable);\n }\n return mutable;\n }\n canBeReused(openBracketIds) {\n if (openBracketIds.intersects(this.missingOpeningBracketIds)) {\n return false;\n }\n let lastChild = this;\n let lastLength;\n while (lastChild.kind === 4 /* AstNodeKind.List */ && (lastLength = lastChild.childrenLength) > 0) {\n lastChild = lastChild.getChild(lastLength - 1);\n }\n return lastChild.canBeReused(openBracketIds);\n }\n handleChildrenChanged() {\n this.throwIfImmutable();\n const count = this.childrenLength;\n let length = this.getChild(0).length;\n let unopenedBrackets = this.getChild(0).missingOpeningBracketIds;\n for (let i = 1; i < count; i++) {\n const child = this.getChild(i);\n length = lengthAdd(length, child.length);\n unopenedBrackets = unopenedBrackets.merge(child.missingOpeningBracketIds);\n }\n this._length = length;\n this._missingOpeningBracketIds = unopenedBrackets;\n this.cachedMinIndentation = -1;\n }\n computeMinIndentation(offset, textModel) {\n if (this.cachedMinIndentation !== -1) {\n return this.cachedMinIndentation;\n }\n let minIndentation = Number.MAX_SAFE_INTEGER;\n let childOffset = offset;\n for (let i = 0; i < this.childrenLength; i++) {\n const child = this.getChild(i);\n if (child) {\n minIndentation = Math.min(minIndentation, child.computeMinIndentation(childOffset, textModel));\n childOffset = lengthAdd(childOffset, child.length);\n }\n }\n this.cachedMinIndentation = minIndentation;\n return minIndentation;\n }\n}\nclass TwoThreeListAstNode extends ListAstNode {\n constructor(length, listHeight, _item1, _item2, _item3, missingOpeningBracketIds) {\n super(length, listHeight, missingOpeningBracketIds);\n this._item1 = _item1;\n this._item2 = _item2;\n this._item3 = _item3;\n }\n get childrenLength() {\n return this._item3 !== null ? 3 : 2;\n }\n getChild(idx) {\n switch (idx) {\n case 0: return this._item1;\n case 1: return this._item2;\n case 2: return this._item3;\n }\n throw new Error('Invalid child index');\n }\n setChild(idx, node) {\n switch (idx) {\n case 0:\n this._item1 = node;\n return;\n case 1:\n this._item2 = node;\n return;\n case 2:\n this._item3 = node;\n return;\n }\n throw new Error('Invalid child index');\n }\n get children() {\n return this._item3 ? [this._item1, this._item2, this._item3] : [this._item1, this._item2];\n }\n get item1() {\n return this._item1;\n }\n get item2() {\n return this._item2;\n }\n get item3() {\n return this._item3;\n }\n deepClone() {\n return new TwoThreeListAstNode(this.length, this.listHeight, this._item1.deepClone(), this._item2.deepClone(), this._item3 ? this._item3.deepClone() : null, this.missingOpeningBracketIds);\n }\n appendChildOfSameHeight(node) {\n if (this._item3) {\n throw new Error('Cannot append to a full (2,3) tree node');\n }\n this.throwIfImmutable();\n this._item3 = node;\n this.handleChildrenChanged();\n }\n unappendChild() {\n if (!this._item3) {\n throw new Error('Cannot remove from a non-full (2,3) tree node');\n }\n this.throwIfImmutable();\n const result = this._item3;\n this._item3 = null;\n this.handleChildrenChanged();\n return result;\n }\n prependChildOfSameHeight(node) {\n if (this._item3) {\n throw new Error('Cannot prepend to a full (2,3) tree node');\n }\n this.throwIfImmutable();\n this._item3 = this._item2;\n this._item2 = this._item1;\n this._item1 = node;\n this.handleChildrenChanged();\n }\n unprependChild() {\n if (!this._item3) {\n throw new Error('Cannot remove from a non-full (2,3) tree node');\n }\n this.throwIfImmutable();\n const result = this._item1;\n this._item1 = this._item2;\n this._item2 = this._item3;\n this._item3 = null;\n this.handleChildrenChanged();\n return result;\n }\n toMutable() {\n return this;\n }\n}\n/**\n * Immutable, if all children are immutable.\n*/\nclass Immutable23ListAstNode extends TwoThreeListAstNode {\n toMutable() {\n return new TwoThreeListAstNode(this.length, this.listHeight, this.item1, this.item2, this.item3, this.missingOpeningBracketIds);\n }\n throwIfImmutable() {\n throw new Error('this instance is immutable');\n }\n}\n/**\n * For debugging.\n*/\nclass ArrayListAstNode extends ListAstNode {\n constructor(length, listHeight, _children, missingOpeningBracketIds) {\n super(length, listHeight, missingOpeningBracketIds);\n this._children = _children;\n }\n get childrenLength() {\n return this._children.length;\n }\n getChild(idx) {\n return this._children[idx];\n }\n setChild(idx, child) {\n this._children[idx] = child;\n }\n get children() {\n return this._children;\n }\n deepClone() {\n const children = new Array(this._children.length);\n for (let i = 0; i < this._children.length; i++) {\n children[i] = this._children[i].deepClone();\n }\n return new ArrayListAstNode(this.length, this.listHeight, children, this.missingOpeningBracketIds);\n }\n appendChildOfSameHeight(node) {\n this.throwIfImmutable();\n this._children.push(node);\n this.handleChildrenChanged();\n }\n unappendChild() {\n this.throwIfImmutable();\n const item = this._children.pop();\n this.handleChildrenChanged();\n return item;\n }\n prependChildOfSameHeight(node) {\n this.throwIfImmutable();\n this._children.unshift(node);\n this.handleChildrenChanged();\n }\n unprependChild() {\n this.throwIfImmutable();\n const item = this._children.shift();\n this.handleChildrenChanged();\n return item;\n }\n toMutable() {\n return this;\n }\n}\n/**\n * Immutable, if all children are immutable.\n*/\nclass ImmutableArrayListAstNode extends ArrayListAstNode {\n toMutable() {\n return new ArrayListAstNode(this.length, this.listHeight, [...this.children], this.missingOpeningBracketIds);\n }\n throwIfImmutable() {\n throw new Error('this instance is immutable');\n }\n}\nconst emptyArray = [];\nclass ImmutableLeafAstNode extends BaseAstNode {\n get listHeight() {\n return 0;\n }\n get childrenLength() {\n return 0;\n }\n getChild(idx) {\n return null;\n }\n get children() {\n return emptyArray;\n }\n deepClone() {\n return this;\n }\n}\nexport class TextAstNode extends ImmutableLeafAstNode {\n get kind() {\n return 0 /* AstNodeKind.Text */;\n }\n get missingOpeningBracketIds() {\n return SmallImmutableSet.getEmpty();\n }\n canBeReused(_openedBracketIds) {\n return true;\n }\n computeMinIndentation(offset, textModel) {\n const start = lengthToObj(offset);\n // Text ast nodes don't have partial indentation (ensured by the tokenizer).\n // Thus, if this text node does not start at column 0, the first line cannot have any indentation at all.\n const startLineNumber = (start.columnCount === 0 ? start.lineCount : start.lineCount + 1) + 1;\n const endLineNumber = lengthGetLineCount(lengthAdd(offset, this.length)) + 1;\n let result = Number.MAX_SAFE_INTEGER;\n for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n const firstNonWsColumn = textModel.getLineFirstNonWhitespaceColumn(lineNumber);\n const lineContent = textModel.getLineContent(lineNumber);\n if (firstNonWsColumn === 0) {\n continue;\n }\n const visibleColumn = CursorColumns.visibleColumnFromColumn(lineContent, firstNonWsColumn, textModel.getOptions().tabSize);\n result = Math.min(result, visibleColumn);\n }\n return result;\n }\n}\nexport class BracketAstNode extends ImmutableLeafAstNode {\n constructor(length, bracketInfo, \n /**\n * In case of a opening bracket, this is the id of the opening bracket.\n * In case of a closing bracket, this contains the ids of all opening brackets it can close.\n */\n bracketIds) {\n super(length);\n this.bracketInfo = bracketInfo;\n this.bracketIds = bracketIds;\n }\n static create(length, bracketInfo, bracketIds) {\n const node = new BracketAstNode(length, bracketInfo, bracketIds);\n return node;\n }\n get kind() {\n return 1 /* AstNodeKind.Bracket */;\n }\n get missingOpeningBracketIds() {\n return SmallImmutableSet.getEmpty();\n }\n get text() {\n return this.bracketInfo.bracketText;\n }\n get languageId() {\n return this.bracketInfo.languageId;\n }\n canBeReused(_openedBracketIds) {\n // These nodes could be reused,\n // but not in a general way.\n // Their parent may be reused.\n return false;\n }\n computeMinIndentation(offset, textModel) {\n return Number.MAX_SAFE_INTEGER;\n }\n}\nexport class InvalidBracketAstNode extends ImmutableLeafAstNode {\n constructor(closingBrackets, length) {\n super(length);\n this.missingOpeningBracketIds = closingBrackets;\n }\n get kind() {\n return 3 /* AstNodeKind.UnexpectedClosingBracket */;\n }\n canBeReused(openedBracketIds) {\n return !openedBracketIds.intersects(this.missingOpeningBracketIds);\n }\n computeMinIndentation(offset, textModel) {\n return Number.MAX_SAFE_INTEGER;\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 *--------------------------------------------------------------------------------------------*/\nimport { lengthAdd, lengthDiffNonNegative, lengthLessThanEqual, lengthToObj, toLength } from './length.js';\nexport class TextEditInfo {\n constructor(startOffset, endOffset, newLength) {\n this.startOffset = startOffset;\n this.endOffset = endOffset;\n this.newLength = newLength;\n }\n}\nexport class BeforeEditPositionMapper {\n /**\n * @param edits Must be sorted by offset in ascending order.\n */\n constructor(edits, documentLength) {\n this.documentLength = documentLength;\n this.nextEditIdx = 0;\n this.deltaOldToNewLineCount = 0;\n this.deltaOldToNewColumnCount = 0;\n this.deltaLineIdxInOld = -1;\n this.edits = edits.map(edit => TextEditInfoCache.from(edit));\n }\n /**\n * @param offset Must be equal to or greater than the last offset this method has been called with.\n */\n getOffsetBeforeChange(offset) {\n this.adjustNextEdit(offset);\n return this.translateCurToOld(offset);\n }\n /**\n * @param offset Must be equal to or greater than the last offset this method has been called with.\n */\n getDistanceToNextChange(offset) {\n this.adjustNextEdit(offset);\n const nextEdit = this.edits[this.nextEditIdx];\n const nextChangeOffset = nextEdit ? this.translateOldToCur(nextEdit.offsetObj) : this.documentLength;\n return lengthDiffNonNegative(offset, nextChangeOffset);\n }\n translateOldToCur(oldOffsetObj) {\n if (oldOffsetObj.lineCount === this.deltaLineIdxInOld) {\n return toLength(oldOffsetObj.lineCount + this.deltaOldToNewLineCount, oldOffsetObj.columnCount + this.deltaOldToNewColumnCount);\n }\n else {\n return toLength(oldOffsetObj.lineCount + this.deltaOldToNewLineCount, oldOffsetObj.columnCount);\n }\n }\n translateCurToOld(newOffset) {\n const offsetObj = lengthToObj(newOffset);\n if (offsetObj.lineCount - this.deltaOldToNewLineCount === this.deltaLineIdxInOld) {\n return toLength(offsetObj.lineCount - this.deltaOldToNewLineCount, offsetObj.columnCount - this.deltaOldToNewColumnCount);\n }\n else {\n return toLength(offsetObj.lineCount - this.deltaOldToNewLineCount, offsetObj.columnCount);\n }\n }\n adjustNextEdit(offset) {\n while (this.nextEditIdx < this.edits.length) {\n const nextEdit = this.edits[this.nextEditIdx];\n // After applying the edit, what is its end offset (considering all previous edits)?\n const nextEditEndOffsetInCur = this.translateOldToCur(nextEdit.endOffsetAfterObj);\n if (lengthLessThanEqual(nextEditEndOffsetInCur, offset)) {\n // We are after the edit, skip it\n this.nextEditIdx++;\n const nextEditEndOffsetInCurObj = lengthToObj(nextEditEndOffsetInCur);\n // Before applying the edit, what is its end offset (considering all previous edits)?\n const nextEditEndOffsetBeforeInCurObj = lengthToObj(this.translateOldToCur(nextEdit.endOffsetBeforeObj));\n const lineDelta = nextEditEndOffsetInCurObj.lineCount - nextEditEndOffsetBeforeInCurObj.lineCount;\n this.deltaOldToNewLineCount += lineDelta;\n const previousColumnDelta = this.deltaLineIdxInOld === nextEdit.endOffsetBeforeObj.lineCount ? this.deltaOldToNewColumnCount : 0;\n const columnDelta = nextEditEndOffsetInCurObj.columnCount - nextEditEndOffsetBeforeInCurObj.columnCount;\n this.deltaOldToNewColumnCount = previousColumnDelta + columnDelta;\n this.deltaLineIdxInOld = nextEdit.endOffsetBeforeObj.lineCount;\n }\n else {\n // We are in or before the edit.\n break;\n }\n }\n }\n}\nclass TextEditInfoCache {\n constructor(startOffset, endOffset, textLength) {\n this.endOffsetBeforeObj = lengthToObj(endOffset);\n this.endOffsetAfterObj = lengthToObj(lengthAdd(startOffset, textLength));\n this.offsetObj = lengthToObj(startOffset);\n }\n static from(edit) {\n return new TextEditInfoCache(edit.startOffset, edit.endOffset, edit.newLength);\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 *--------------------------------------------------------------------------------------------*/\nimport { escapeRegExpCharacters } from '../../../../../base/common/strings.js';\nimport { BracketAstNode } from './ast.js';\nimport { toLength } from './length.js';\nimport { identityKeyProvider, SmallImmutableSet } from './smallImmutableSet.js';\nimport { Token } from './tokenizer.js';\nexport class BracketTokens {\n constructor(map) {\n this.map = map;\n this.hasRegExp = false;\n this._regExpGlobal = null;\n }\n static createFromLanguage(configuration, denseKeyProvider) {\n function getId(bracketInfo) {\n return denseKeyProvider.getKey(`${bracketInfo.languageId}:::${bracketInfo.bracketText}`);\n }\n const map = new Map();\n for (const openingBracket of configuration.bracketsNew.openingBrackets) {\n const length = toLength(0, openingBracket.bracketText.length);\n const openingTextId = getId(openingBracket);\n const bracketIds = SmallImmutableSet.getEmpty().add(openingTextId, identityKeyProvider);\n map.set(openingBracket.bracketText, new Token(length, 1 /* TokenKind.OpeningBracket */, openingTextId, bracketIds, BracketAstNode.create(length, openingBracket, bracketIds)));\n }\n for (const closingBracket of configuration.bracketsNew.closingBrackets) {\n const length = toLength(0, closingBracket.bracketText.length);\n let bracketIds = SmallImmutableSet.getEmpty();\n const closingBrackets = closingBracket.getClosedBrackets();\n for (const bracket of closingBrackets) {\n bracketIds = bracketIds.add(getId(bracket), identityKeyProvider);\n }\n map.set(closingBracket.bracketText, new Token(length, 2 /* TokenKind.ClosingBracket */, getId(closingBrackets[0]), bracketIds, BracketAstNode.create(length, closingBracket, bracketIds)));\n }\n return new BracketTokens(map);\n }\n getRegExpStr() {\n if (this.isEmpty) {\n return null;\n }\n else {\n const keys = [...this.map.keys()];\n keys.sort();\n keys.reverse();\n return keys.map(k => prepareBracketForRegExp(k)).join('|');\n }\n }\n /**\n * Returns null if there is no such regexp (because there are no brackets).\n */\n get regExpGlobal() {\n if (!this.hasRegExp) {\n const regExpStr = this.getRegExpStr();\n this._regExpGlobal = regExpStr ? new RegExp(regExpStr, 'gi') : null;\n this.hasRegExp = true;\n }\n return this._regExpGlobal;\n }\n getToken(value) {\n return this.map.get(value.toLowerCase());\n }\n findClosingTokenText(openingBracketIds) {\n for (const [closingText, info] of this.map) {\n if (info.kind === 2 /* TokenKind.ClosingBracket */ && info.bracketIds.intersects(openingBracketIds)) {\n return closingText;\n }\n }\n return undefined;\n }\n get isEmpty() {\n return this.map.size === 0;\n }\n}\nfunction prepareBracketForRegExp(str) {\n let escaped = escapeRegExpCharacters(str);\n // These bracket pair delimiters start or end with letters\n // see https://github.com/microsoft/vscode/issues/132162 https://github.com/microsoft/vscode/issues/150440\n if (/^[\\w ]+/.test(str)) {\n escaped = `\\\\b${escaped}`;\n }\n if (/[\\w ]+$/.test(str)) {\n escaped = `${escaped}\\\\b`;\n }\n return escaped;\n}\nexport class LanguageAgnosticBracketTokens {\n constructor(denseKeyProvider, getLanguageConfiguration) {\n this.denseKeyProvider = denseKeyProvider;\n this.getLanguageConfiguration = getLanguageConfiguration;\n this.languageIdToBracketTokens = new Map();\n }\n didLanguageChange(languageId) {\n // Report a change whenever the language configuration updates.\n return this.languageIdToBracketTokens.has(languageId);\n }\n getSingleLanguageBracketTokens(languageId) {\n let singleLanguageBracketTokens = this.languageIdToBracketTokens.get(languageId);\n if (!singleLanguageBracketTokens) {\n singleLanguageBracketTokens = BracketTokens.createFromLanguage(this.getLanguageConfiguration(languageId), this.denseKeyProvider);\n this.languageIdToBracketTokens.set(languageId, singleLanguageBracketTokens);\n }\n return singleLanguageBracketTokens;\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 *--------------------------------------------------------------------------------------------*/\nimport { splitLines } from '../../../../../base/common/strings.js';\nimport { Range } from '../../../core/range.js';\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 constructor(lineCount, columnCount) {\n this.lineCount = lineCount;\n this.columnCount = columnCount;\n }\n toString() {\n return `${this.lineCount},${this.columnCount}`;\n }\n}\nLengthObj.zero = new LengthObj(0, 0);\n/**\n * The end must be greater than or equal to the start.\n*/\nexport function lengthDiff(startLineCount, startColumnCount, endLineCount, endColumnCount) {\n return (startLineCount !== endLineCount)\n ? toLength(endLineCount - startLineCount, endColumnCount)\n : toLength(0, endColumnCount - startColumnCount);\n}\nexport const lengthZero = 0;\nexport function lengthIsZero(length) {\n return length === 0;\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 : Math.pow(2, 26);\nexport function toLength(lineCount, columnCount) {\n // llllllllllllllllllllllllllcccccccccccccccccccccccccc (52 bits)\n // line count (26 bits) column count (26 bits)\n // If there is no overflow (all values/sums below 2^26 = 67108864),\n // we have `toLength(lns1, cols1) + toLength(lns2, cols2) = toLength(lns1 + lns2, cols1 + cols2)`.\n return (lineCount * factor + columnCount);\n}\nexport function lengthToObj(length) {\n const l = length;\n const lineCount = Math.floor(l / factor);\n const columnCount = l - lineCount * factor;\n return new LengthObj(lineCount, columnCount);\n}\nexport function lengthGetLineCount(length) {\n return Math.floor(length / factor);\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) {\n return length;\n}\nexport function lengthAdd(l1, l2) {\n return ((l2 < factor)\n ? (l1 + l2) // l2 is the amount of columns (zero line count). Keep the column count from l1.\n : (l1 - (l1 % factor) + l2)); // l1 - (l1 % factor) equals toLength(l1.lineCount, 0)\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, length2) {\n const l1 = length1;\n const l2 = length2;\n const diff = l2 - l1;\n if (diff <= 0) {\n // line-count of length1 is higher than line-count of length2\n // or they are equal and column-count of length1 is higher than column-count of length2\n return lengthZero;\n }\n const lineCount1 = Math.floor(l1 / factor);\n const lineCount2 = Math.floor(l2 / factor);\n const colCount2 = l2 - lineCount2 * factor;\n if (lineCount1 === lineCount2) {\n const colCount1 = l1 - lineCount1 * factor;\n return toLength(0, colCount2 - colCount1);\n }\n else {\n return toLength(lineCount2 - lineCount1, colCount2);\n }\n}\nexport function lengthLessThan(length1, length2) {\n // First, compare line counts, then column counts.\n return length1 < length2;\n}\nexport function lengthLessThanEqual(length1, length2) {\n return length1 <= length2;\n}\nexport function lengthGreaterThanEqual(length1, length2) {\n return length1 >= length2;\n}\nexport function positionToLength(position) {\n return toLength(position.lineNumber - 1, position.column - 1);\n}\nexport function lengthsToRange(lengthStart, lengthEnd) {\n const l = lengthStart;\n const lineCount = Math.floor(l / factor);\n const colCount = l - lineCount * factor;\n const l2 = lengthEnd;\n const lineCount2 = Math.floor(l2 / factor);\n const colCount2 = l2 - lineCount2 * factor;\n return new Range(lineCount + 1, colCount + 1, lineCount2 + 1, colCount2 + 1);\n}\nexport function lengthOfString(str) {\n const lines = splitLines(str);\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { ListAstNode } from './ast.js';\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) {\n if (items.length === 0) {\n return null;\n }\n if (items.length === 1) {\n return items[0];\n }\n let i = 0;\n /**\n * Reads nodes of same height and concatenates them to a single node.\n */\n function readNode() {\n if (i >= items.length) {\n return null;\n }\n const start = i;\n const height = items[start].listHeight;\n i++;\n while (i < items.length && items[i].listHeight === height) {\n i++;\n }\n if (i - start >= 2) {\n return concat23TreesOfSameHeight(start === 0 && i === items.length ? items : items.slice(start, i), false);\n }\n else {\n return items[start];\n }\n }\n // The items might not have the same height.\n // We merge all items by using a binary concat operator.\n let first = readNode(); // There must be a first item\n let second = readNode();\n if (!second) {\n return first;\n }\n for (let item = readNode(); item; item = readNode()) {\n // Prefer concatenating smaller trees, as the runtime of concat depends on the tree height.\n if (heightDiff(first, second) <= heightDiff(second, item)) {\n first = concat(first, second);\n second = item;\n }\n else {\n second = concat(second, item);\n }\n }\n const result = concat(first, second);\n return result;\n}\nexport function concat23TreesOfSameHeight(items, createImmutableLists = false) {\n if (items.length === 0) {\n return null;\n }\n if (items.length === 1) {\n return items[0];\n }\n let length = items.length;\n // All trees have same height, just create parent nodes.\n while (length > 3) {\n const newLength = length >> 1;\n for (let i = 0; i < newLength; i++) {\n const j = i << 1;\n items[i] = ListAstNode.create23(items[j], items[j + 1], j + 3 === length ? items[j + 2] : null, createImmutableLists);\n }\n length = newLength;\n }\n return ListAstNode.create23(items[0], items[1], length >= 3 ? items[2] : null, createImmutableLists);\n}\nfunction heightDiff(node1, node2) {\n return Math.abs(node1.listHeight - node2.listHeight);\n}\nfunction concat(node1, node2) {\n if (node1.listHeight === node2.listHeight) {\n return ListAstNode.create23(node1, node2, null, false);\n }\n else if (node1.listHeight > node2.listHeight) {\n // node1 is the tree we want to insert into\n return append(node1, node2);\n }\n else {\n return prepend(node2, node1);\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, nodeToAppend) {\n list = list.toMutable();\n let curNode = list;\n const parents = new Array();\n let nodeToAppendOfCorrectHeight;\n while (true) {\n // assert nodeToInsert.listHeight <= curNode.listHeight\n if (nodeToAppend.listHeight === curNode.listHeight) {\n nodeToAppendOfCorrectHeight = nodeToAppend;\n break;\n }\n // assert 0 <= nodeToInsert.listHeight < curNode.listHeight\n if (curNode.kind !== 4 /* AstNodeKind.List */) {\n throw new Error('unexpected');\n }\n parents.push(curNode);\n // assert 2 <= curNode.childrenLength <= 3\n curNode = curNode.makeLastElementMutable();\n }\n // assert nodeToAppendOfCorrectHeight!.listHeight === curNode.listHeight\n for (let i = parents.length - 1; i >= 0; i--) {\n const parent = parents[i];\n if (nodeToAppendOfCorrectHeight) {\n // Can we take the element?\n if (parent.childrenLength >= 3) {\n // assert parent.childrenLength === 3 && parent.listHeight === nodeToAppendOfCorrectHeight.listHeight + 1\n // we need to split to maintain (2,3)-tree property.\n // Send the third element + the new element to the parent.\n nodeToAppendOfCorrectHeight = ListAstNode.create23(parent.unappendChild(), nodeToAppendOfCorrectHeight, null, false);\n }\n else {\n parent.appendChildOfSameHeight(nodeToAppendOfCorrectHeight);\n nodeToAppendOfCorrectHeight = undefined;\n }\n }\n else {\n parent.handleChildrenChanged();\n }\n }\n if (nodeToAppendOfCorrectHeight) {\n return ListAstNode.create23(list, nodeToAppendOfCorrectHeight, null, false);\n }\n else {\n return list;\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, nodeToAppend) {\n list = list.toMutable();\n let curNode = list;\n const parents = new Array();\n // assert nodeToInsert.listHeight <= curNode.listHeight\n while (nodeToAppend.listHeight !== curNode.listHeight) {\n // assert 0 <= nodeToInsert.listHeight < curNode.listHeight\n if (curNode.kind !== 4 /* AstNodeKind.List */) {\n throw new Error('unexpected');\n }\n parents.push(curNode);\n // assert 2 <= curNode.childrenFast.length <= 3\n curNode = curNode.makeFirstElementMutable();\n }\n let nodeToPrependOfCorrectHeight = nodeToAppend;\n // assert nodeToAppendOfCorrectHeight!.listHeight === curNode.listHeight\n for (let i = parents.length - 1; i >= 0; i--) {\n const parent = parents[i];\n if (nodeToPrependOfCorrectHeight) {\n // Can we take the element?\n if (parent.childrenLength >= 3) {\n // assert parent.childrenLength === 3 && parent.listHeight === nodeToAppendOfCorrectHeight.listHeight + 1\n // we need to split to maintain (2,3)-tree property.\n // Send the third element + the new element to the parent.\n nodeToPrependOfCorrectHeight = ListAstNode.create23(nodeToPrependOfCorrectHeight, parent.unprependChild(), null, false);\n }\n else {\n parent.prependChildOfSameHeight(nodeToPrependOfCorrectHeight);\n nodeToPrependOfCorrectHeight = undefined;\n }\n }\n else {\n parent.handleChildrenChanged();\n }\n }\n if (nodeToPrependOfCorrectHeight) {\n return ListAstNode.create23(nodeToPrependOfCorrectHeight, list, null, false);\n }\n else {\n return list;\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 *--------------------------------------------------------------------------------------------*/\nimport { lengthAdd, lengthZero, lengthLessThan } from './length.js';\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 constructor(node) {\n this.lastOffset = lengthZero;\n this.nextNodes = [node];\n this.offsets = [lengthZero];\n this.idxs = [];\n }\n /**\n * Returns the longest node at `offset` that satisfies the predicate.\n * @param offset must be greater than or equal to the last offset this method has been called with!\n */\n readLongestNodeAt(offset, predicate) {\n if (lengthLessThan(offset, this.lastOffset)) {\n throw new Error('Invalid offset');\n }\n this.lastOffset = offset;\n // Find the longest node of all those that are closest to the current offset.\n while (true) {\n const curNode = lastOrUndefined(this.nextNodes);\n if (!curNode) {\n return undefined;\n }\n const curNodeOffset = lastOrUndefined(this.offsets);\n if (lengthLessThan(offset, curNodeOffset)) {\n // The next best node is not here yet.\n // The reader must advance before a cached node is hit.\n return undefined;\n }\n if (lengthLessThan(curNodeOffset, offset)) {\n // The reader is ahead of the current node.\n if (lengthAdd(curNodeOffset, curNode.length) <= offset) {\n // The reader is after the end of the current node.\n this.nextNodeAfterCurrent();\n }\n else {\n // The reader is somewhere in the current node.\n const nextChildIdx = getNextChildIdx(curNode);\n if (nextChildIdx !== -1) {\n // Go to the first child and repeat.\n this.nextNodes.push(curNode.getChild(nextChildIdx));\n this.offsets.push(curNodeOffset);\n this.idxs.push(nextChildIdx);\n }\n else {\n // We don't have children\n this.nextNodeAfterCurrent();\n }\n }\n }\n else {\n // readerOffsetBeforeChange === curNodeOffset\n if (predicate(curNode)) {\n this.nextNodeAfterCurrent();\n return curNode;\n }\n else {\n const nextChildIdx = getNextChildIdx(curNode);\n // look for shorter node\n if (nextChildIdx === -1) {\n // There is no shorter node.\n this.nextNodeAfterCurrent();\n return undefined;\n }\n else {\n // Descend into first child & repeat.\n this.nextNodes.push(curNode.getChild(nextChildIdx));\n this.offsets.push(curNodeOffset);\n this.idxs.push(nextChildIdx);\n }\n }\n }\n }\n }\n // Navigates to the longest node that continues after the current node.\n nextNodeAfterCurrent() {\n while (true) {\n const currentOffset = lastOrUndefined(this.offsets);\n const currentNode = lastOrUndefined(this.nextNodes);\n this.nextNodes.pop();\n this.offsets.pop();\n if (this.idxs.length === 0) {\n // We just popped the root node, there is no next node.\n break;\n }\n // Parent is not undefined, because idxs is not empty\n const parent = lastOrUndefined(this.nextNodes);\n const nextChildIdx = getNextChildIdx(parent, this.idxs[this.idxs.length - 1]);\n if (nextChildIdx !== -1) {\n this.nextNodes.push(parent.getChild(nextChildIdx));\n this.offsets.push(lengthAdd(currentOffset, currentNode.length));\n this.idxs[this.idxs.length - 1] = nextChildIdx;\n break;\n }\n else {\n this.idxs.pop();\n }\n // We fully consumed the parent.\n // Current node is now parent, so call nextNodeAfterCurrent again\n }\n }\n}\nfunction getNextChildIdx(node, curIdx = -1) {\n while (true) {\n curIdx++;\n if (curIdx >= node.childrenLength) {\n return -1;\n }\n if (node.getChild(curIdx)) {\n return curIdx;\n }\n }\n}\nfunction lastOrUndefined(arr) {\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { InvalidBracketAstNode, ListAstNode, PairAstNode } from './ast.js';\nimport { BeforeEditPositionMapper } from './beforeEditPositionMapper.js';\nimport { SmallImmutableSet } from './smallImmutableSet.js';\nimport { lengthIsZero, lengthLessThan } from './length.js';\nimport { concat23Trees, concat23TreesOfSameHeight } from './concat23Trees.js';\nimport { NodeReader } from './nodeReader.js';\n/**\n * Non incrementally built ASTs are immutable.\n*/\nexport function parseDocument(tokenizer, edits, oldNode, createImmutableLists) {\n const parser = new Parser(tokenizer, edits, oldNode, createImmutableLists);\n return parser.parseDocument();\n}\n/**\n * Non incrementally built ASTs are immutable.\n*/\nclass Parser {\n constructor(tokenizer, edits, oldNode, createImmutableLists) {\n this.tokenizer = tokenizer;\n this.createImmutableLists = createImmutableLists;\n this._itemsConstructed = 0;\n this._itemsFromCache = 0;\n if (oldNode && createImmutableLists) {\n throw new Error('Not supported');\n }\n this.oldNodeReader = oldNode ? new NodeReader(oldNode) : undefined;\n this.positionMapper = new BeforeEditPositionMapper(edits, tokenizer.length);\n }\n parseDocument() {\n this._itemsConstructed = 0;\n this._itemsFromCache = 0;\n let result = this.parseList(SmallImmutableSet.getEmpty());\n if (!result) {\n result = ListAstNode.getEmpty();\n }\n return result;\n }\n parseList(openedBracketIds) {\n const items = new Array();\n while (true) {\n const token = this.tokenizer.peek();\n if (!token ||\n (token.kind === 2 /* TokenKind.ClosingBracket */ &&\n token.bracketIds.intersects(openedBracketIds))) {\n break;\n }\n const child = this.parseChild(openedBracketIds);\n if (child.kind === 4 /* AstNodeKind.List */ && child.childrenLength === 0) {\n continue;\n }\n items.push(child);\n }\n // When there is no oldNodeReader, all items are created from scratch and must have the same height.\n const result = this.oldNodeReader ? concat23Trees(items) : concat23TreesOfSameHeight(items, this.createImmutableLists);\n return result;\n }\n parseChild(openedBracketIds) {\n if (this.oldNodeReader) {\n const maxCacheableLength = this.positionMapper.getDistanceToNextChange(this.tokenizer.offset);\n if (!lengthIsZero(maxCacheableLength)) {\n const cachedNode = this.oldNodeReader.readLongestNodeAt(this.positionMapper.getOffsetBeforeChange(this.tokenizer.offset), curNode => {\n if (!lengthLessThan(curNode.length, maxCacheableLength)) {\n // Either the node contains edited text or touches edited text.\n // In the latter case, brackets might have been extended (`end` -> `ending`), so even touching nodes cannot be reused.\n return false;\n }\n const canBeReused = curNode.canBeReused(openedBracketIds);\n return canBeReused;\n });\n if (cachedNode) {\n this._itemsFromCache++;\n this.tokenizer.skip(cachedNode.length);\n return cachedNode;\n }\n }\n }\n this._itemsConstructed++;\n const token = this.tokenizer.read();\n switch (token.kind) {\n case 2 /* TokenKind.ClosingBracket */:\n return new InvalidBracketAstNode(token.bracketIds, token.length);\n case 0 /* TokenKind.Text */:\n return token.astNode;\n case 1 /* TokenKind.OpeningBracket */: {\n const set = openedBracketIds.merge(token.bracketIds);\n const child = this.parseList(set);\n const nextToken = this.tokenizer.peek();\n if (nextToken &&\n nextToken.kind === 2 /* TokenKind.ClosingBracket */ &&\n (nextToken.bracketId === token.bracketId || nextToken.bracketIds.intersects(token.bracketIds))) {\n this.tokenizer.read();\n return PairAstNode.create(token.astNode, child, nextToken.astNode);\n }\n else {\n return PairAstNode.create(token.astNode, child, null);\n }\n }\n default:\n throw new Error('unexpected');\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 *--------------------------------------------------------------------------------------------*/\nconst emptyArr = new Array();\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 constructor(items, additionalItems) {\n this.items = items;\n this.additionalItems = additionalItems;\n }\n static create(items, additionalItems) {\n if (items <= 128 && additionalItems.length === 0) {\n // We create a cache of 128=2^7 elements to cover all sets with up to 7 (dense) elements.\n let cached = SmallImmutableSet.cache[items];\n if (!cached) {\n cached = new SmallImmutableSet(items, additionalItems);\n SmallImmutableSet.cache[items] = cached;\n }\n return cached;\n }\n return new SmallImmutableSet(items, additionalItems);\n }\n static getEmpty() {\n return this.empty;\n }\n add(value, keyProvider) {\n const key = keyProvider.getKey(value);\n let idx = key >> 5; // divided by 32\n if (idx === 0) {\n // fast path\n const newItem = (1 << key) | this.items;\n if (newItem === this.items) {\n return this;\n }\n return SmallImmutableSet.create(newItem, this.additionalItems);\n }\n idx--;\n const newItems = this.additionalItems.slice(0);\n while (newItems.length < idx) {\n newItems.push(0);\n }\n newItems[idx] |= 1 << (key & 31);\n return SmallImmutableSet.create(this.items, newItems);\n }\n merge(other) {\n const merged = this.items | other.items;\n if (this.additionalItems === emptyArr && other.additionalItems === emptyArr) {\n // fast path\n if (merged === this.items) {\n return this;\n }\n if (merged === other.items) {\n return other;\n }\n return SmallImmutableSet.create(merged, emptyArr);\n }\n // This can be optimized, but it's not a common case\n const newItems = new Array();\n for (let i = 0; i < Math.max(this.additionalItems.length, other.additionalItems.length); i++) {\n const item1 = this.additionalItems[i] || 0;\n const item2 = other.additionalItems[i] || 0;\n newItems.push(item1 | item2);\n }\n return SmallImmutableSet.create(merged, newItems);\n }\n intersects(other) {\n if ((this.items & other.items) !== 0) {\n return true;\n }\n for (let i = 0; i < Math.min(this.additionalItems.length, other.additionalItems.length); i++) {\n if ((this.additionalItems[i] & other.additionalItems[i]) !== 0) {\n return true;\n }\n }\n return false;\n }\n}\nSmallImmutableSet.cache = new Array(129);\nSmallImmutableSet.empty = SmallImmutableSet.create(0, emptyArr);\nexport const identityKeyProvider = {\n getKey(value) {\n return value;\n }\n};\n/**\n * Assigns values a unique incrementing key.\n*/\nexport class DenseKeyProvider {\n constructor() {\n this.items = new Map();\n }\n getKey(value) {\n let existing = this.items.get(value);\n if (existing === undefined) {\n existing = this.items.size;\n this.items.set(value, existing);\n }\n return existing;\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 *--------------------------------------------------------------------------------------------*/\nimport { NotSupportedError } from '../../../../../base/common/errors.js';\nimport { TokenMetadata } from '../../../encodedTokenAttributes.js';\nimport { TextAstNode } from './ast.js';\nimport { lengthAdd, lengthDiff, lengthGetColumnCountIfZeroLineCount, lengthToObj, lengthZero, toLength } from './length.js';\nimport { SmallImmutableSet } from './smallImmutableSet.js';\nexport class Token {\n constructor(length, kind, \n /**\n * If this token is an opening bracket, this is the id of the opening bracket.\n * If this token is a closing bracket, this is the id of the first opening bracket that is closed by this bracket.\n * Otherwise, it is -1.\n */\n bracketId, \n /**\n * If this token is an opening bracket, this just contains `bracketId`.\n * If this token is a closing bracket, this lists all opening bracket ids, that it closes.\n * Otherwise, it is empty.\n */\n bracketIds, astNode) {\n this.length = length;\n this.kind = kind;\n this.bracketId = bracketId;\n this.bracketIds = bracketIds;\n this.astNode = astNode;\n }\n}\nexport class TextBufferTokenizer {\n constructor(textModel, bracketTokens) {\n this.textModel = textModel;\n this.bracketTokens = bracketTokens;\n this.reader = new NonPeekableTextBufferTokenizer(this.textModel, this.bracketTokens);\n this._offset = lengthZero;\n this.didPeek = false;\n this.peeked = null;\n this.textBufferLineCount = textModel.getLineCount();\n this.textBufferLastLineLength = textModel.getLineLength(this.textBufferLineCount);\n }\n get offset() {\n return this._offset;\n }\n get length() {\n return toLength(this.textBufferLineCount, this.textBufferLastLineLength);\n }\n skip(length) {\n this.didPeek = false;\n this._offset = lengthAdd(this._offset, length);\n const obj = lengthToObj(this._offset);\n this.reader.setPosition(obj.lineCount, obj.columnCount);\n }\n read() {\n let token;\n if (this.peeked) {\n this.didPeek = false;\n token = this.peeked;\n }\n else {\n token = this.reader.read();\n }\n if (token) {\n this._offset = lengthAdd(this._offset, token.length);\n }\n return token;\n }\n peek() {\n if (!this.didPeek) {\n this.peeked = this.reader.read();\n this.didPeek = true;\n }\n return this.peeked;\n }\n}\n/**\n * Does not support peek.\n*/\nclass NonPeekableTextBufferTokenizer {\n constructor(textModel, bracketTokens) {\n this.textModel = textModel;\n this.bracketTokens = bracketTokens;\n this.lineIdx = 0;\n this.line = null;\n this.lineCharOffset = 0;\n this.lineTokens = null;\n this.lineTokenOffset = 0;\n /** Must be a zero line token. The end of the document cannot be peeked. */\n this.peekedToken = null;\n this.textBufferLineCount = textModel.getLineCount();\n this.textBufferLastLineLength = textModel.getLineLength(this.textBufferLineCount);\n }\n setPosition(lineIdx, column) {\n // We must not jump into a token!\n if (lineIdx === this.lineIdx) {\n this.lineCharOffset = column;\n this.lineTokenOffset = this.lineCharOffset === 0 ? 0 : this.lineTokens.findTokenIndexAtOffset(this.lineCharOffset);\n }\n else {\n this.lineIdx = lineIdx;\n this.lineCharOffset = column;\n this.line = null;\n }\n this.peekedToken = null;\n }\n read() {\n if (this.peekedToken) {\n const token = this.peekedToken;\n this.peekedToken = null;\n this.lineCharOffset += lengthGetColumnCountIfZeroLineCount(token.length);\n return token;\n }\n if (this.lineIdx > this.textBufferLineCount - 1 || (this.lineIdx === this.textBufferLineCount - 1 && this.lineCharOffset >= this.textBufferLastLineLength)) {\n // We are after the end\n return null;\n }\n if (this.line === null) {\n this.lineTokens = this.textModel.tokenization.getLineTokens(this.lineIdx + 1);\n this.line = this.lineTokens.getLineContent();\n this.lineTokenOffset = this.lineCharOffset === 0 ? 0 : this.lineTokens.findTokenIndexAtOffset(this.lineCharOffset);\n }\n const startLineIdx = this.lineIdx;\n const startLineCharOffset = this.lineCharOffset;\n // limits the length of text tokens.\n // If text tokens get too long, incremental updates will be slow\n let lengthHeuristic = 0;\n while (true) {\n const lineTokens = this.lineTokens;\n const tokenCount = lineTokens.getCount();\n let peekedBracketToken = null;\n if (this.lineTokenOffset < tokenCount) {\n const tokenMetadata = lineTokens.getMetadata(this.lineTokenOffset);\n while (this.lineTokenOffset + 1 < tokenCount && tokenMetadata === lineTokens.getMetadata(this.lineTokenOffset + 1)) {\n // Skip tokens that are identical.\n // Sometimes, (bracket) identifiers are split up into multiple tokens.\n this.lineTokenOffset++;\n }\n const isOther = TokenMetadata.getTokenType(tokenMetadata) === 0 /* StandardTokenType.Other */;\n const containsBracketType = TokenMetadata.containsBalancedBrackets(tokenMetadata);\n const endOffset = lineTokens.getEndOffset(this.lineTokenOffset);\n // Is there a bracket token next? Only consume text.\n if (containsBracketType && isOther && this.lineCharOffset < endOffset) {\n const languageId = lineTokens.getLanguageId(this.lineTokenOffset);\n const text = this.line.substring(this.lineCharOffset, endOffset);\n const brackets = this.bracketTokens.getSingleLanguageBracketTokens(languageId);\n const regexp = brackets.regExpGlobal;\n if (regexp) {\n regexp.lastIndex = 0;\n const match = regexp.exec(text);\n if (match) {\n peekedBracketToken = brackets.getToken(match[0]);\n if (peekedBracketToken) {\n // Consume leading text of the token\n this.lineCharOffset += match.index;\n }\n }\n }\n }\n lengthHeuristic += endOffset - this.lineCharOffset;\n if (peekedBracketToken) {\n // Don't skip the entire token, as a single token could contain multiple brackets.\n if (startLineIdx !== this.lineIdx || startLineCharOffset !== this.lineCharOffset) {\n // There is text before the bracket\n this.peekedToken = peekedBracketToken;\n break;\n }\n else {\n // Consume the peeked token\n this.lineCharOffset += lengthGetColumnCountIfZeroLineCount(peekedBracketToken.length);\n return peekedBracketToken;\n }\n }\n else {\n // Skip the entire token, as the token contains no brackets at all.\n this.lineTokenOffset++;\n this.lineCharOffset = endOffset;\n }\n }\n else {\n if (this.lineIdx === this.textBufferLineCount - 1) {\n break;\n }\n this.lineIdx++;\n this.lineTokens = this.textModel.tokenization.getLineTokens(this.lineIdx + 1);\n this.lineTokenOffset = 0;\n this.line = this.lineTokens.getLineContent();\n this.lineCharOffset = 0;\n lengthHeuristic += 33; // max 1000/33 = 30 lines\n // This limits the amount of work to recompute min-indentation\n if (lengthHeuristic > 1000) {\n // only break (automatically) at the end of line.\n break;\n }\n }\n if (lengthHeuristic > 1500) {\n // Eventually break regardless of the line length so that\n // very long lines do not cause bad performance.\n // This effective limits max indentation to 500, as\n // indentation is not computed across multiple text nodes.\n break;\n }\n }\n // If a token contains some proper indentation, it also contains \\n{INDENTATION+}(?!{INDENTATION}),\n // unless the line is too long.\n // Thus, the min indentation of the document is the minimum min indentation of every text node.\n const length = lengthDiff(startLineIdx, startLineCharOffset, this.lineIdx, this.lineCharOffset);\n return new Token(length, 0 /* TokenKind.Text */, -1, SmallImmutableSet.getEmpty(), new TextAstNode(length));\n }\n}\nexport class FastTokenizer {\n constructor(text, brackets) {\n this.text = text;\n this._offset = lengthZero;\n this.idx = 0;\n const regExpStr = brackets.getRegExpStr();\n const regexp = regExpStr ? new RegExp(regExpStr + '|\\n', 'gi') : null;\n const tokens = [];\n let match;\n let curLineCount = 0;\n let lastLineBreakOffset = 0;\n let lastTokenEndOffset = 0;\n let lastTokenEndLine = 0;\n const smallTextTokens0Line = new Array();\n for (let i = 0; i < 60; i++) {\n smallTextTokens0Line.push(new Token(toLength(0, i), 0 /* TokenKind.Text */, -1, SmallImmutableSet.getEmpty(), new TextAstNode(toLength(0, i))));\n }\n const smallTextTokens1Line = new Array();\n for (let i = 0; i < 60; i++) {\n smallTextTokens1Line.push(new Token(toLength(1, i), 0 /* TokenKind.Text */, -1, SmallImmutableSet.getEmpty(), new TextAstNode(toLength(1, i))));\n }\n if (regexp) {\n regexp.lastIndex = 0;\n // If a token contains indentation, it also contains \\n{INDENTATION+}(?!{INDENTATION})\n while ((match = regexp.exec(text)) !== null) {\n const curOffset = match.index;\n const value = match[0];\n if (value === '\\n') {\n curLineCount++;\n lastLineBreakOffset = curOffset + 1;\n }\n else {\n if (lastTokenEndOffset !== curOffset) {\n let token;\n if (lastTokenEndLine === curLineCount) {\n const colCount = curOffset - lastTokenEndOffset;\n if (colCount < smallTextTokens0Line.length) {\n token = smallTextTokens0Line[colCount];\n }\n else {\n const length = toLength(0, colCount);\n token = new Token(length, 0 /* TokenKind.Text */, -1, SmallImmutableSet.getEmpty(), new TextAstNode(length));\n }\n }\n else {\n const lineCount = curLineCount - lastTokenEndLine;\n const colCount = curOffset - lastLineBreakOffset;\n if (lineCount === 1 && colCount < smallTextTokens1Line.length) {\n token = smallTextTokens1Line[colCount];\n }\n else {\n const length = toLength(lineCount, colCount);\n token = new Token(length, 0 /* TokenKind.Text */, -1, SmallImmutableSet.getEmpty(), new TextAstNode(length));\n }\n }\n tokens.push(token);\n }\n // value is matched by regexp, so the token must exist\n tokens.push(brackets.getToken(value));\n lastTokenEndOffset = curOffset + value.length;\n lastTokenEndLine = curLineCount;\n }\n }\n }\n const offset = text.length;\n if (lastTokenEndOffset !== offset) {\n const length = (lastTokenEndLine === curLineCount)\n ? toLength(0, offset - lastTokenEndOffset)\n : toLength(curLineCount - lastTokenEndLine, offset - lastLineBreakOffset);\n tokens.push(new Token(length, 0 /* TokenKind.Text */, -1, SmallImmutableSet.getEmpty(), new TextAstNode(length)));\n }\n this.length = toLength(curLineCount, offset - lastLineBreakOffset);\n this.tokens = tokens;\n }\n get offset() {\n return this._offset;\n }\n read() {\n return this.tokens[this.idx++] || null;\n }\n peek() {\n return this.tokens[this.idx] || null;\n }\n skip(length) {\n throw new NotSupportedError();\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 *--------------------------------------------------------------------------------------------*/\nimport * as nls from '../../../nls.js';\nimport { onUnexpectedError } from '../../../base/common/errors.js';\nimport { Selection } from '../core/selection.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { TextChange, compressConsecutiveTextChanges } from '../core/textChange.js';\nimport * as buffer from '../../../base/common/buffer.js';\nimport { basename } from '../../../base/common/resources.js';\nfunction uriGetComparisonKey(resource) {\n return resource.toString();\n}\nexport class SingleModelEditStackData {\n constructor(beforeVersionId, afterVersionId, beforeEOL, afterEOL, beforeCursorState, afterCursorState, changes) {\n this.beforeVersionId = beforeVersionId;\n this.afterVersionId = afterVersionId;\n this.beforeEOL = beforeEOL;\n this.afterEOL = afterEOL;\n this.beforeCursorState = beforeCursorState;\n this.afterCursorState = afterCursorState;\n this.changes = changes;\n }\n static create(model, beforeCursorState) {\n const alternativeVersionId = model.getAlternativeVersionId();\n const eol = getModelEOL(model);\n return new SingleModelEditStackData(alternativeVersionId, alternativeVersionId, eol, eol, beforeCursorState, beforeCursorState, []);\n }\n append(model, textChanges, afterEOL, afterVersionId, afterCursorState) {\n if (textChanges.length > 0) {\n this.changes = compressConsecutiveTextChanges(this.changes, textChanges);\n }\n this.afterEOL = afterEOL;\n this.afterVersionId = afterVersionId;\n this.afterCursorState = afterCursorState;\n }\n static _writeSelectionsSize(selections) {\n return 4 + 4 * 4 * (selections ? selections.length : 0);\n }\n static _writeSelections(b, selections, offset) {\n buffer.writeUInt32BE(b, (selections ? selections.length : 0), offset);\n offset += 4;\n if (selections) {\n for (const selection of selections) {\n buffer.writeUInt32BE(b, selection.selectionStartLineNumber, offset);\n offset += 4;\n buffer.writeUInt32BE(b, selection.selectionStartColumn, offset);\n offset += 4;\n buffer.writeUInt32BE(b, selection.positionLineNumber, offset);\n offset += 4;\n buffer.writeUInt32BE(b, selection.positionColumn, offset);\n offset += 4;\n }\n }\n return offset;\n }\n static _readSelections(b, offset, dest) {\n const count = buffer.readUInt32BE(b, offset);\n offset += 4;\n for (let i = 0; i < count; i++) {\n const selectionStartLineNumber = buffer.readUInt32BE(b, offset);\n offset += 4;\n const selectionStartColumn = buffer.readUInt32BE(b, offset);\n offset += 4;\n const positionLineNumber = buffer.readUInt32BE(b, offset);\n offset += 4;\n const positionColumn = buffer.readUInt32BE(b, offset);\n offset += 4;\n dest.push(new Selection(selectionStartLineNumber, selectionStartColumn, positionLineNumber, positionColumn));\n }\n return offset;\n }\n serialize() {\n let necessarySize = (+4 // beforeVersionId\n + 4 // afterVersionId\n + 1 // beforeEOL\n + 1 // afterEOL\n + SingleModelEditStackData._writeSelectionsSize(this.beforeCursorState)\n + SingleModelEditStackData._writeSelectionsSize(this.afterCursorState)\n + 4 // change count\n );\n for (const change of this.changes) {\n necessarySize += change.writeSize();\n }\n const b = new Uint8Array(necessarySize);\n let offset = 0;\n buffer.writeUInt32BE(b, this.beforeVersionId, offset);\n offset += 4;\n buffer.writeUInt32BE(b, this.afterVersionId, offset);\n offset += 4;\n buffer.writeUInt8(b, this.beforeEOL, offset);\n offset += 1;\n buffer.writeUInt8(b, this.afterEOL, offset);\n offset += 1;\n offset = SingleModelEditStackData._writeSelections(b, this.beforeCursorState, offset);\n offset = SingleModelEditStackData._writeSelections(b, this.afterCursorState, offset);\n buffer.writeUInt32BE(b, this.changes.length, offset);\n offset += 4;\n for (const change of this.changes) {\n offset = change.write(b, offset);\n }\n return b.buffer;\n }\n static deserialize(source) {\n const b = new Uint8Array(source);\n let offset = 0;\n const beforeVersionId = buffer.readUInt32BE(b, offset);\n offset += 4;\n const afterVersionId = buffer.readUInt32BE(b, offset);\n offset += 4;\n const beforeEOL = buffer.readUInt8(b, offset);\n offset += 1;\n const afterEOL = buffer.readUInt8(b, offset);\n offset += 1;\n const beforeCursorState = [];\n offset = SingleModelEditStackData._readSelections(b, offset, beforeCursorState);\n const afterCursorState = [];\n offset = SingleModelEditStackData._readSelections(b, offset, afterCursorState);\n const changeCount = buffer.readUInt32BE(b, offset);\n offset += 4;\n const changes = [];\n for (let i = 0; i < changeCount; i++) {\n offset = TextChange.read(b, offset, changes);\n }\n return new SingleModelEditStackData(beforeVersionId, afterVersionId, beforeEOL, afterEOL, beforeCursorState, afterCursorState, changes);\n }\n}\nexport class SingleModelEditStackElement {\n constructor(label, code, model, beforeCursorState) {\n this.label = label;\n this.code = code;\n this.model = model;\n this._data = SingleModelEditStackData.create(model, beforeCursorState);\n }\n get type() {\n return 0 /* UndoRedoElementType.Resource */;\n }\n get resource() {\n if (URI.isUri(this.model)) {\n return this.model;\n }\n return this.model.uri;\n }\n toString() {\n const data = (this._data instanceof SingleModelEditStackData ? this._data : SingleModelEditStackData.deserialize(this._data));\n return data.changes.map(change => change.toString()).join(', ');\n }\n matchesResource(resource) {\n const uri = (URI.isUri(this.model) ? this.model : this.model.uri);\n return (uri.toString() === resource.toString());\n }\n setModel(model) {\n this.model = model;\n }\n canAppend(model) {\n return (this.model === model && this._data instanceof SingleModelEditStackData);\n }\n append(model, textChanges, afterEOL, afterVersionId, afterCursorState) {\n if (this._data instanceof SingleModelEditStackData) {\n this._data.append(model, textChanges, afterEOL, afterVersionId, afterCursorState);\n }\n }\n close() {\n if (this._data instanceof SingleModelEditStackData) {\n this._data = this._data.serialize();\n }\n }\n open() {\n if (!(this._data instanceof SingleModelEditStackData)) {\n this._data = SingleModelEditStackData.deserialize(this._data);\n }\n }\n undo() {\n if (URI.isUri(this.model)) {\n // don't have a model\n throw new Error(`Invalid SingleModelEditStackElement`);\n }\n if (this._data instanceof SingleModelEditStackData) {\n this._data = this._data.serialize();\n }\n const data = SingleModelEditStackData.deserialize(this._data);\n this.model._applyUndo(data.changes, data.beforeEOL, data.beforeVersionId, data.beforeCursorState);\n }\n redo() {\n if (URI.isUri(this.model)) {\n // don't have a model\n throw new Error(`Invalid SingleModelEditStackElement`);\n }\n if (this._data instanceof SingleModelEditStackData) {\n this._data = this._data.serialize();\n }\n const data = SingleModelEditStackData.deserialize(this._data);\n this.model._applyRedo(data.changes, data.afterEOL, data.afterVersionId, data.afterCursorState);\n }\n heapSize() {\n if (this._data instanceof SingleModelEditStackData) {\n this._data = this._data.serialize();\n }\n return this._data.byteLength + 168 /*heap overhead*/;\n }\n}\nexport class MultiModelEditStackElement {\n constructor(label, code, editStackElements) {\n this.label = label;\n this.code = code;\n this.type = 1 /* UndoRedoElementType.Workspace */;\n this._isOpen = true;\n this._editStackElementsArr = editStackElements.slice(0);\n this._editStackElementsMap = new Map();\n for (const editStackElement of this._editStackElementsArr) {\n const key = uriGetComparisonKey(editStackElement.resource);\n this._editStackElementsMap.set(key, editStackElement);\n }\n this._delegate = null;\n }\n get resources() {\n return this._editStackElementsArr.map(editStackElement => editStackElement.resource);\n }\n prepareUndoRedo() {\n if (this._delegate) {\n return this._delegate.prepareUndoRedo(this);\n }\n }\n matchesResource(resource) {\n const key = uriGetComparisonKey(resource);\n return (this._editStackElementsMap.has(key));\n }\n setModel(model) {\n const key = uriGetComparisonKey(URI.isUri(model) ? model : model.uri);\n if (this._editStackElementsMap.has(key)) {\n this._editStackElementsMap.get(key).setModel(model);\n }\n }\n canAppend(model) {\n if (!this._isOpen) {\n return false;\n }\n const key = uriGetComparisonKey(model.uri);\n if (this._editStackElementsMap.has(key)) {\n const editStackElement = this._editStackElementsMap.get(key);\n return editStackElement.canAppend(model);\n }\n return false;\n }\n append(model, textChanges, afterEOL, afterVersionId, afterCursorState) {\n const key = uriGetComparisonKey(model.uri);\n const editStackElement = this._editStackElementsMap.get(key);\n editStackElement.append(model, textChanges, afterEOL, afterVersionId, afterCursorState);\n }\n close() {\n this._isOpen = false;\n }\n open() {\n // cannot reopen\n }\n undo() {\n this._isOpen = false;\n for (const editStackElement of this._editStackElementsArr) {\n editStackElement.undo();\n }\n }\n redo() {\n for (const editStackElement of this._editStackElementsArr) {\n editStackElement.redo();\n }\n }\n heapSize(resource) {\n const key = uriGetComparisonKey(resource);\n if (this._editStackElementsMap.has(key)) {\n const editStackElement = this._editStackElementsMap.get(key);\n return editStackElement.heapSize();\n }\n return 0;\n }\n split() {\n return this._editStackElementsArr;\n }\n toString() {\n const result = [];\n for (const editStackElement of this._editStackElementsArr) {\n result.push(`${basename(editStackElement.resource)}: ${editStackElement}`);\n }\n return `{${result.join(', ')}}`;\n }\n}\nfunction getModelEOL(model) {\n const eol = model.getEOL();\n if (eol === '\\n') {\n return 0 /* EndOfLineSequence.LF */;\n }\n else {\n return 1 /* EndOfLineSequence.CRLF */;\n }\n}\nexport function isEditStackElement(element) {\n if (!element) {\n return false;\n }\n return ((element instanceof SingleModelEditStackElement) || (element instanceof MultiModelEditStackElement));\n}\nexport class EditStack {\n constructor(model, undoRedoService) {\n this._model = model;\n this._undoRedoService = undoRedoService;\n }\n pushStackElement() {\n const lastElement = this._undoRedoService.getLastElement(this._model.uri);\n if (isEditStackElement(lastElement)) {\n lastElement.close();\n }\n }\n popStackElement() {\n const lastElement = this._undoRedoService.getLastElement(this._model.uri);\n if (isEditStackElement(lastElement)) {\n lastElement.open();\n }\n }\n clear() {\n this._undoRedoService.removeElements(this._model.uri);\n }\n _getOrCreateEditStackElement(beforeCursorState) {\n const lastElement = this._undoRedoService.getLastElement(this._model.uri);\n if (isEditStackElement(lastElement) && lastElement.canAppend(this._model)) {\n return lastElement;\n }\n const newElement = new SingleModelEditStackElement(nls.localize('edit', \"Typing\"), 'undoredo.textBufferEdit', this._model, beforeCursorState);\n this._undoRedoService.pushElement(newElement);\n return newElement;\n }\n pushEOL(eol) {\n const editStackElement = this._getOrCreateEditStackElement(null);\n this._model.setEOL(eol);\n editStackElement.append(this._model, [], getModelEOL(this._model), this._model.getAlternativeVersionId(), null);\n }\n pushEditOperation(beforeCursorState, editOperations, cursorStateComputer) {\n const editStackElement = this._getOrCreateEditStackElement(beforeCursorState);\n const inverseEditOperations = this._model.applyEdits(editOperations, true);\n const afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperations);\n const textChanges = inverseEditOperations.map((op, index) => ({ index: index, textChange: op.textChange }));\n textChanges.sort((a, b) => {\n if (a.textChange.oldPosition === b.textChange.oldPosition) {\n return a.index - b.index;\n }\n return a.textChange.oldPosition - b.textChange.oldPosition;\n });\n editStackElement.append(this._model, textChanges.map(op => op.textChange), getModelEOL(this._model), this._model.getAlternativeVersionId(), afterCursorState);\n return afterCursorState;\n }\n static _computeCursorState(cursorStateComputer, inverseEditOperations) {\n try {\n return cursorStateComputer ? cursorStateComputer(inverseEditOperations) : null;\n }\n catch (e) {\n onUnexpectedError(e);\n return null;\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 *--------------------------------------------------------------------------------------------*/\nimport { findLast } from '../../../base/common/arrays.js';\nimport * as strings from '../../../base/common/strings.js';\nimport { CursorColumns } from '../core/cursorColumns.js';\nimport { Range } from '../core/range.js';\nimport { TextModelPart } from './textModelPart.js';\nimport { computeIndentLevel } from './utils.js';\nimport { HorizontalGuidesState, IndentGuide, IndentGuideHorizontalLine } from '../textModelGuides.js';\nexport class GuidesTextModelPart extends TextModelPart {\n constructor(textModel, languageConfigurationService) {\n super();\n this.textModel = textModel;\n this.languageConfigurationService = languageConfigurationService;\n }\n getLanguageConfiguration(languageId) {\n return this.languageConfigurationService.getLanguageConfiguration(languageId);\n }\n _computeIndentLevel(lineIndex) {\n return computeIndentLevel(this.textModel.getLineContent(lineIndex + 1), this.textModel.getOptions().tabSize);\n }\n getActiveIndentGuide(lineNumber, minLineNumber, maxLineNumber) {\n this.assertNotDisposed();\n const lineCount = this.textModel.getLineCount();\n if (lineNumber < 1 || lineNumber > lineCount) {\n throw new Error('Illegal value for lineNumber');\n }\n const foldingRules = this.getLanguageConfiguration(this.textModel.getLanguageId()).foldingRules;\n const offSide = Boolean(foldingRules && foldingRules.offSide);\n let up_aboveContentLineIndex = -2; /* -2 is a marker for not having computed it */\n let up_aboveContentLineIndent = -1;\n let up_belowContentLineIndex = -2; /* -2 is a marker for not having computed it */\n let up_belowContentLineIndent = -1;\n const up_resolveIndents = (lineNumber) => {\n if (up_aboveContentLineIndex !== -1 &&\n (up_aboveContentLineIndex === -2 ||\n up_aboveContentLineIndex > lineNumber - 1)) {\n up_aboveContentLineIndex = -1;\n up_aboveContentLineIndent = -1;\n // must find previous line with content\n for (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) {\n const indent = this._computeIndentLevel(lineIndex);\n if (indent >= 0) {\n up_aboveContentLineIndex = lineIndex;\n up_aboveContentLineIndent = indent;\n break;\n }\n }\n }\n if (up_belowContentLineIndex === -2) {\n up_belowContentLineIndex = -1;\n up_belowContentLineIndent = -1;\n // must find next line with content\n for (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) {\n const indent = this._computeIndentLevel(lineIndex);\n if (indent >= 0) {\n up_belowContentLineIndex = lineIndex;\n up_belowContentLineIndent = indent;\n break;\n }\n }\n }\n };\n let down_aboveContentLineIndex = -2; /* -2 is a marker for not having computed it */\n let down_aboveContentLineIndent = -1;\n let down_belowContentLineIndex = -2; /* -2 is a marker for not having computed it */\n let down_belowContentLineIndent = -1;\n const down_resolveIndents = (lineNumber) => {\n if (down_aboveContentLineIndex === -2) {\n down_aboveContentLineIndex = -1;\n down_aboveContentLineIndent = -1;\n // must find previous line with content\n for (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) {\n const indent = this._computeIndentLevel(lineIndex);\n if (indent >= 0) {\n down_aboveContentLineIndex = lineIndex;\n down_aboveContentLineIndent = indent;\n break;\n }\n }\n }\n if (down_belowContentLineIndex !== -1 &&\n (down_belowContentLineIndex === -2 ||\n down_belowContentLineIndex < lineNumber - 1)) {\n down_belowContentLineIndex = -1;\n down_belowContentLineIndent = -1;\n // must find next line with content\n for (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) {\n const indent = this._computeIndentLevel(lineIndex);\n if (indent >= 0) {\n down_belowContentLineIndex = lineIndex;\n down_belowContentLineIndent = indent;\n break;\n }\n }\n }\n };\n let startLineNumber = 0;\n let goUp = true;\n let endLineNumber = 0;\n let goDown = true;\n let indent = 0;\n let initialIndent = 0;\n for (let distance = 0; goUp || goDown; distance++) {\n const upLineNumber = lineNumber - distance;\n const downLineNumber = lineNumber + distance;\n if (distance > 1 && (upLineNumber < 1 || upLineNumber < minLineNumber)) {\n goUp = false;\n }\n if (distance > 1 &&\n (downLineNumber > lineCount || downLineNumber > maxLineNumber)) {\n goDown = false;\n }\n if (distance > 50000) {\n // stop processing\n goUp = false;\n goDown = false;\n }\n let upLineIndentLevel = -1;\n if (goUp && upLineNumber >= 1) {\n // compute indent level going up\n const currentIndent = this._computeIndentLevel(upLineNumber - 1);\n if (currentIndent >= 0) {\n // This line has content (besides whitespace)\n // Use the line's indent\n up_belowContentLineIndex = upLineNumber - 1;\n up_belowContentLineIndent = currentIndent;\n upLineIndentLevel = Math.ceil(currentIndent / this.textModel.getOptions().indentSize);\n }\n else {\n up_resolveIndents(upLineNumber);\n upLineIndentLevel = this._getIndentLevelForWhitespaceLine(offSide, up_aboveContentLineIndent, up_belowContentLineIndent);\n }\n }\n let downLineIndentLevel = -1;\n if (goDown && downLineNumber <= lineCount) {\n // compute indent level going down\n const currentIndent = this._computeIndentLevel(downLineNumber - 1);\n if (currentIndent >= 0) {\n // This line has content (besides whitespace)\n // Use the line's indent\n down_aboveContentLineIndex = downLineNumber - 1;\n down_aboveContentLineIndent = currentIndent;\n downLineIndentLevel = Math.ceil(currentIndent / this.textModel.getOptions().indentSize);\n }\n else {\n down_resolveIndents(downLineNumber);\n downLineIndentLevel = this._getIndentLevelForWhitespaceLine(offSide, down_aboveContentLineIndent, down_belowContentLineIndent);\n }\n }\n if (distance === 0) {\n initialIndent = upLineIndentLevel;\n continue;\n }\n if (distance === 1) {\n if (downLineNumber <= lineCount &&\n downLineIndentLevel >= 0 &&\n initialIndent + 1 === downLineIndentLevel) {\n // This is the beginning of a scope, we have special handling here, since we want the\n // child scope indent to be active, not the parent scope\n goUp = false;\n startLineNumber = downLineNumber;\n endLineNumber = downLineNumber;\n indent = downLineIndentLevel;\n continue;\n }\n if (upLineNumber >= 1 &&\n upLineIndentLevel >= 0 &&\n upLineIndentLevel - 1 === initialIndent) {\n // This is the end of a scope, just like above\n goDown = false;\n startLineNumber = upLineNumber;\n endLineNumber = upLineNumber;\n indent = upLineIndentLevel;\n continue;\n }\n startLineNumber = lineNumber;\n endLineNumber = lineNumber;\n indent = initialIndent;\n if (indent === 0) {\n // No need to continue\n return { startLineNumber, endLineNumber, indent };\n }\n }\n if (goUp) {\n if (upLineIndentLevel >= indent) {\n startLineNumber = upLineNumber;\n }\n else {\n goUp = false;\n }\n }\n if (goDown) {\n if (downLineIndentLevel >= indent) {\n endLineNumber = downLineNumber;\n }\n else {\n goDown = false;\n }\n }\n }\n return { startLineNumber, endLineNumber, indent };\n }\n getLinesBracketGuides(startLineNumber, endLineNumber, activePosition, options) {\n var _a;\n const result = [];\n for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n result.push([]);\n }\n // If requested, this could be made configurable.\n const includeSingleLinePairs = true;\n const bracketPairs = this.textModel.bracketPairs.getBracketPairsInRangeWithMinIndentation(new Range(startLineNumber, 1, endLineNumber, this.textModel.getLineMaxColumn(endLineNumber)));\n let activeBracketPairRange = undefined;\n if (activePosition && bracketPairs.length > 0) {\n const bracketsContainingActivePosition = (startLineNumber <= activePosition.lineNumber &&\n activePosition.lineNumber <= endLineNumber\n // We don't need to query the brackets again if the cursor is in the viewport\n ? bracketPairs\n : this.textModel.bracketPairs.getBracketPairsInRange(Range.fromPositions(activePosition))).filter((bp) => Range.strictContainsPosition(bp.range, activePosition));\n activeBracketPairRange = (_a = findLast(bracketsContainingActivePosition, (i) => includeSingleLinePairs || i.range.startLineNumber !== i.range.endLineNumber)) === null || _a === void 0 ? void 0 : _a.range;\n }\n const independentColorPoolPerBracketType = this.textModel.getOptions().bracketPairColorizationOptions.independentColorPoolPerBracketType;\n const colorProvider = new BracketPairGuidesClassNames();\n for (const pair of bracketPairs) {\n /*\n\n\n {\n |\n }\n\n {\n |\n ----}\n\n ____{\n |test\n ----}\n\n renderHorizontalEndLineAtTheBottom:\n {\n |\n |x}\n --\n renderHorizontalEndLineAtTheBottom:\n ____{\n |test\n | x }\n ----\n */\n if (!pair.closingBracketRange) {\n continue;\n }\n const isActive = activeBracketPairRange && pair.range.equalsRange(activeBracketPairRange);\n if (!isActive && !options.includeInactive) {\n continue;\n }\n const className = colorProvider.getInlineClassName(pair.nestingLevel, pair.nestingLevelOfEqualBracketType, independentColorPoolPerBracketType) +\n (options.highlightActive && isActive\n ? ' ' + colorProvider.activeClassName\n : '');\n const start = pair.openingBracketRange.getStartPosition();\n const end = pair.closingBracketRange.getStartPosition();\n const horizontalGuides = options.horizontalGuides === HorizontalGuidesState.Enabled || (options.horizontalGuides === HorizontalGuidesState.EnabledForActive && isActive);\n if (pair.range.startLineNumber === pair.range.endLineNumber) {\n if (includeSingleLinePairs && horizontalGuides) {\n result[pair.range.startLineNumber - startLineNumber].push(new IndentGuide(-1, pair.openingBracketRange.getEndPosition().column, className, new IndentGuideHorizontalLine(false, end.column), -1, -1));\n }\n continue;\n }\n const endVisibleColumn = this.getVisibleColumnFromPosition(end);\n const startVisibleColumn = this.getVisibleColumnFromPosition(pair.openingBracketRange.getStartPosition());\n const guideVisibleColumn = Math.min(startVisibleColumn, endVisibleColumn, pair.minVisibleColumnIndentation + 1);\n let renderHorizontalEndLineAtTheBottom = false;\n const firstNonWsIndex = strings.firstNonWhitespaceIndex(this.textModel.getLineContent(pair.closingBracketRange.startLineNumber));\n const hasTextBeforeClosingBracket = firstNonWsIndex < pair.closingBracketRange.startColumn - 1;\n if (hasTextBeforeClosingBracket) {\n renderHorizontalEndLineAtTheBottom = true;\n }\n const visibleGuideStartLineNumber = Math.max(start.lineNumber, startLineNumber);\n const visibleGuideEndLineNumber = Math.min(end.lineNumber, endLineNumber);\n const offset = renderHorizontalEndLineAtTheBottom ? 1 : 0;\n for (let l = visibleGuideStartLineNumber; l < visibleGuideEndLineNumber + offset; l++) {\n result[l - startLineNumber].push(new IndentGuide(guideVisibleColumn, -1, className, null, l === start.lineNumber ? start.column : -1, l === end.lineNumber ? end.column : -1));\n }\n if (horizontalGuides) {\n if (start.lineNumber >= startLineNumber && startVisibleColumn > guideVisibleColumn) {\n result[start.lineNumber - startLineNumber].push(new IndentGuide(guideVisibleColumn, -1, className, new IndentGuideHorizontalLine(false, start.column), -1, -1));\n }\n if (end.lineNumber <= endLineNumber && endVisibleColumn > guideVisibleColumn) {\n result[end.lineNumber - startLineNumber].push(new IndentGuide(guideVisibleColumn, -1, className, new IndentGuideHorizontalLine(!renderHorizontalEndLineAtTheBottom, end.column), -1, -1));\n }\n }\n }\n for (const guides of result) {\n guides.sort((a, b) => a.visibleColumn - b.visibleColumn);\n }\n return result;\n }\n getVisibleColumnFromPosition(position) {\n return (CursorColumns.visibleColumnFromColumn(this.textModel.getLineContent(position.lineNumber), position.column, this.textModel.getOptions().tabSize) + 1);\n }\n getLinesIndentGuides(startLineNumber, endLineNumber) {\n this.assertNotDisposed();\n const lineCount = this.textModel.getLineCount();\n if (startLineNumber < 1 || startLineNumber > lineCount) {\n throw new Error('Illegal value for startLineNumber');\n }\n if (endLineNumber < 1 || endLineNumber > lineCount) {\n throw new Error('Illegal value for endLineNumber');\n }\n const options = this.textModel.getOptions();\n const foldingRules = this.getLanguageConfiguration(this.textModel.getLanguageId()).foldingRules;\n const offSide = Boolean(foldingRules && foldingRules.offSide);\n const result = new Array(endLineNumber - startLineNumber + 1);\n let aboveContentLineIndex = -2; /* -2 is a marker for not having computed it */\n let aboveContentLineIndent = -1;\n let belowContentLineIndex = -2; /* -2 is a marker for not having computed it */\n let belowContentLineIndent = -1;\n for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n const resultIndex = lineNumber - startLineNumber;\n const currentIndent = this._computeIndentLevel(lineNumber - 1);\n if (currentIndent >= 0) {\n // This line has content (besides whitespace)\n // Use the line's indent\n aboveContentLineIndex = lineNumber - 1;\n aboveContentLineIndent = currentIndent;\n result[resultIndex] = Math.ceil(currentIndent / options.indentSize);\n continue;\n }\n if (aboveContentLineIndex === -2) {\n aboveContentLineIndex = -1;\n aboveContentLineIndent = -1;\n // must find previous line with content\n for (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) {\n const indent = this._computeIndentLevel(lineIndex);\n if (indent >= 0) {\n aboveContentLineIndex = lineIndex;\n aboveContentLineIndent = indent;\n break;\n }\n }\n }\n if (belowContentLineIndex !== -1 &&\n (belowContentLineIndex === -2 || belowContentLineIndex < lineNumber - 1)) {\n belowContentLineIndex = -1;\n belowContentLineIndent = -1;\n // must find next line with content\n for (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) {\n const indent = this._computeIndentLevel(lineIndex);\n if (indent >= 0) {\n belowContentLineIndex = lineIndex;\n belowContentLineIndent = indent;\n break;\n }\n }\n }\n result[resultIndex] = this._getIndentLevelForWhitespaceLine(offSide, aboveContentLineIndent, belowContentLineIndent);\n }\n return result;\n }\n _getIndentLevelForWhitespaceLine(offSide, aboveContentLineIndent, belowContentLineIndent) {\n const options = this.textModel.getOptions();\n if (aboveContentLineIndent === -1 || belowContentLineIndent === -1) {\n // At the top or bottom of the file\n return 0;\n }\n else if (aboveContentLineIndent < belowContentLineIndent) {\n // we are inside the region above\n return 1 + Math.floor(aboveContentLineIndent / options.indentSize);\n }\n else if (aboveContentLineIndent === belowContentLineIndent) {\n // we are in between two regions\n return Math.ceil(belowContentLineIndent / options.indentSize);\n }\n else {\n if (offSide) {\n // same level as region below\n return Math.ceil(belowContentLineIndent / options.indentSize);\n }\n else {\n // we are inside the region that ends below\n return 1 + Math.floor(belowContentLineIndent / options.indentSize);\n }\n }\n }\n}\nexport class BracketPairGuidesClassNames {\n constructor() {\n this.activeClassName = 'indent-active';\n }\n getInlineClassName(nestingLevel, nestingLevelOfEqualBracketType, independentColorPoolPerBracketType) {\n return this.getInlineClassNameOfLevel(independentColorPoolPerBracketType ? nestingLevelOfEqualBracketType : nestingLevel);\n }\n getInlineClassNameOfLevel(level) {\n // To support a dynamic amount of colors up to 6 colors,\n // we use a number that is a lcm of all numbers from 1 to 6.\n return `bracket-indent-guide lvl-${level % 30}`;\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 *--------------------------------------------------------------------------------------------*/\nimport { arrayInsert } from '../../../base/common/arrays.js';\nimport { toUint32 } from '../../../base/common/uint.js';\nexport class PrefixSumComputer {\n constructor(values) {\n this.values = values;\n this.prefixSum = new Uint32Array(values.length);\n this.prefixSumValidIndex = new Int32Array(1);\n this.prefixSumValidIndex[0] = -1;\n }\n insertValues(insertIndex, insertValues) {\n insertIndex = toUint32(insertIndex);\n const oldValues = this.values;\n const oldPrefixSum = this.prefixSum;\n const insertValuesLen = insertValues.length;\n if (insertValuesLen === 0) {\n return false;\n }\n this.values = new Uint32Array(oldValues.length + insertValuesLen);\n this.values.set(oldValues.subarray(0, insertIndex), 0);\n this.values.set(oldValues.subarray(insertIndex), insertIndex + insertValuesLen);\n this.values.set(insertValues, insertIndex);\n if (insertIndex - 1 < this.prefixSumValidIndex[0]) {\n this.prefixSumValidIndex[0] = insertIndex - 1;\n }\n this.prefixSum = new Uint32Array(this.values.length);\n if (this.prefixSumValidIndex[0] >= 0) {\n this.prefixSum.set(oldPrefixSum.subarray(0, this.prefixSumValidIndex[0] + 1));\n }\n return true;\n }\n setValue(index, value) {\n index = toUint32(index);\n value = toUint32(value);\n if (this.values[index] === value) {\n return false;\n }\n this.values[index] = value;\n if (index - 1 < this.prefixSumValidIndex[0]) {\n this.prefixSumValidIndex[0] = index - 1;\n }\n return true;\n }\n removeValues(startIndex, count) {\n startIndex = toUint32(startIndex);\n count = toUint32(count);\n const oldValues = this.values;\n const oldPrefixSum = this.prefixSum;\n if (startIndex >= oldValues.length) {\n return false;\n }\n const maxCount = oldValues.length - startIndex;\n if (count >= maxCount) {\n count = maxCount;\n }\n if (count === 0) {\n return false;\n }\n this.values = new Uint32Array(oldValues.length - count);\n this.values.set(oldValues.subarray(0, startIndex), 0);\n this.values.set(oldValues.subarray(startIndex + count), startIndex);\n this.prefixSum = new Uint32Array(this.values.length);\n if (startIndex - 1 < this.prefixSumValidIndex[0]) {\n this.prefixSumValidIndex[0] = startIndex - 1;\n }\n if (this.prefixSumValidIndex[0] >= 0) {\n this.prefixSum.set(oldPrefixSum.subarray(0, this.prefixSumValidIndex[0] + 1));\n }\n return true;\n }\n getTotalSum() {\n if (this.values.length === 0) {\n return 0;\n }\n return this._getPrefixSum(this.values.length - 1);\n }\n /**\n * Returns the sum of the first `index + 1` many items.\n * @returns `SUM(0 <= j <= index, values[j])`.\n */\n getPrefixSum(index) {\n if (index < 0) {\n return 0;\n }\n index = toUint32(index);\n return this._getPrefixSum(index);\n }\n _getPrefixSum(index) {\n if (index <= this.prefixSumValidIndex[0]) {\n return this.prefixSum[index];\n }\n let startIndex = this.prefixSumValidIndex[0] + 1;\n if (startIndex === 0) {\n this.prefixSum[0] = this.values[0];\n startIndex++;\n }\n if (index >= this.values.length) {\n index = this.values.length - 1;\n }\n for (let i = startIndex; i <= index; i++) {\n this.prefixSum[i] = this.prefixSum[i - 1] + this.values[i];\n }\n this.prefixSumValidIndex[0] = Math.max(this.prefixSumValidIndex[0], index);\n return this.prefixSum[index];\n }\n getIndexOf(sum) {\n sum = Math.floor(sum);\n // Compute all sums (to get a fully valid prefixSum)\n this.getTotalSum();\n let low = 0;\n let high = this.values.length - 1;\n let mid = 0;\n let midStop = 0;\n let midStart = 0;\n while (low <= high) {\n mid = low + ((high - low) / 2) | 0;\n midStop = this.prefixSum[mid];\n midStart = midStop - this.values[mid];\n if (sum < midStart) {\n high = mid - 1;\n }\n else if (sum >= midStop) {\n low = mid + 1;\n }\n else {\n break;\n }\n }\n return new PrefixSumIndexOfResult(mid, sum - midStart);\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 constructor(values) {\n this._values = values;\n this._isValid = false;\n this._validEndIndex = -1;\n this._prefixSum = [];\n this._indexBySum = [];\n }\n /**\n * @returns SUM(0 <= j < values.length, values[j])\n */\n getTotalSum() {\n this._ensureValid();\n return this._indexBySum.length;\n }\n /**\n * Returns the sum of the first `count` many items.\n * @returns `SUM(0 <= j < count, values[j])`.\n */\n getPrefixSum(count) {\n this._ensureValid();\n if (count === 0) {\n return 0;\n }\n return this._prefixSum[count - 1];\n }\n /**\n * @returns `result`, such that `getPrefixSum(result.index) + result.remainder = sum`\n */\n getIndexOf(sum) {\n this._ensureValid();\n const idx = this._indexBySum[sum];\n const viewLinesAbove = idx > 0 ? this._prefixSum[idx - 1] : 0;\n return new PrefixSumIndexOfResult(idx, sum - viewLinesAbove);\n }\n removeValues(start, deleteCount) {\n this._values.splice(start, deleteCount);\n this._invalidate(start);\n }\n insertValues(insertIndex, insertArr) {\n this._values = arrayInsert(this._values, insertIndex, insertArr);\n this._invalidate(insertIndex);\n }\n _invalidate(index) {\n this._isValid = false;\n this._validEndIndex = Math.min(this._validEndIndex, index - 1);\n }\n _ensureValid() {\n if (this._isValid) {\n return;\n }\n for (let i = this._validEndIndex + 1, len = this._values.length; i < len; i++) {\n const value = this._values[i];\n const sumAbove = i > 0 ? this._prefixSum[i - 1] : 0;\n this._prefixSum[i] = sumAbove + value;\n for (let j = 0; j < value; j++) {\n this._indexBySum[sumAbove + j] = i;\n }\n }\n // trim things\n this._prefixSum.length = this._values.length;\n this._indexBySum.length = this._prefixSum[this._prefixSum.length - 1];\n // mark as valid\n this._isValid = true;\n this._validEndIndex = this._values.length - 1;\n }\n setValue(index, value) {\n if (this._values[index] === value) {\n // no change\n return;\n }\n this._values[index] = value;\n this._invalidate(index);\n }\n}\nexport class PrefixSumIndexOfResult {\n constructor(index, remainder) {\n this.index = index;\n this.remainder = remainder;\n this._prefixSumIndexOfResultBrand = undefined;\n this.index = index;\n this.remainder = remainder;\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 *--------------------------------------------------------------------------------------------*/\nexport class BracketInfo {\n constructor(range, \n /** 0-based level */\n nestingLevel, nestingLevelOfEqualBracketType, isInvalid) {\n this.range = range;\n this.nestingLevel = nestingLevel;\n this.nestingLevelOfEqualBracketType = nestingLevelOfEqualBracketType;\n this.isInvalid = isInvalid;\n }\n}\nexport class BracketPairInfo {\n constructor(range, openingBracketRange, closingBracketRange, \n /** 0-based */\n nestingLevel, nestingLevelOfEqualBracketType, bracketPairNode) {\n this.range = range;\n this.openingBracketRange = openingBracketRange;\n this.closingBracketRange = closingBracketRange;\n this.nestingLevel = nestingLevel;\n this.nestingLevelOfEqualBracketType = nestingLevelOfEqualBracketType;\n this.bracketPairNode = bracketPairNode;\n }\n get openingBracketInfo() {\n return this.bracketPairNode.openingBracket.bracketInfo;\n }\n}\nexport class BracketPairWithMinIndentationInfo extends BracketPairInfo {\n constructor(range, openingBracketRange, closingBracketRange, \n /**\n * 0-based\n */\n nestingLevel, nestingLevelOfEqualBracketType, bracketPairNode, \n /**\n * -1 if not requested, otherwise the size of the minimum indentation in the bracket pair in terms of visible columns.\n */\n minVisibleColumnIndentation) {\n super(range, openingBracketRange, closingBracketRange, nestingLevel, nestingLevelOfEqualBracketType, bracketPairNode);\n this.minVisibleColumnIndentation = minVisibleColumnIndentation;\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 *--------------------------------------------------------------------------------------------*/\nimport { Emitter } from '../../../../../base/common/event.js';\nimport { Disposable } from '../../../../../base/common/lifecycle.js';\nimport { Range } from '../../../core/range.js';\nimport { BracketInfo, BracketPairWithMinIndentationInfo } from '../../../textModelBracketPairs.js';\nimport { TextEditInfo } from './beforeEditPositionMapper.js';\nimport { LanguageAgnosticBracketTokens } from './brackets.js';\nimport { lengthAdd, lengthGreaterThanEqual, lengthLessThan, lengthLessThanEqual, lengthOfString, lengthsToRange, lengthZero, positionToLength, toLength } from './length.js';\nimport { parseDocument } from './parser.js';\nimport { DenseKeyProvider } from './smallImmutableSet.js';\nimport { FastTokenizer, TextBufferTokenizer } from './tokenizer.js';\nexport class BracketPairsTree extends Disposable {\n constructor(textModel, getLanguageConfiguration) {\n super();\n this.textModel = textModel;\n this.getLanguageConfiguration = getLanguageConfiguration;\n this.didChangeEmitter = new Emitter();\n this.denseKeyProvider = new DenseKeyProvider();\n this.brackets = new LanguageAgnosticBracketTokens(this.denseKeyProvider, this.getLanguageConfiguration);\n this.onDidChange = this.didChangeEmitter.event;\n if (textModel.tokenization.backgroundTokenizationState === 0 /* BackgroundTokenizationState.Uninitialized */) {\n // There are no token information yet\n const brackets = this.brackets.getSingleLanguageBracketTokens(this.textModel.getLanguageId());\n const tokenizer = new FastTokenizer(this.textModel.getValue(), brackets);\n this.initialAstWithoutTokens = parseDocument(tokenizer, [], undefined, true);\n this.astWithTokens = this.initialAstWithoutTokens;\n }\n else if (textModel.tokenization.backgroundTokenizationState === 2 /* BackgroundTokenizationState.Completed */) {\n // Skip the initial ast, as there is no flickering.\n // Directly create the tree with token information.\n this.initialAstWithoutTokens = undefined;\n this.astWithTokens = this.parseDocumentFromTextBuffer([], undefined, false);\n }\n else if (textModel.tokenization.backgroundTokenizationState === 1 /* BackgroundTokenizationState.InProgress */) {\n this.initialAstWithoutTokens = this.parseDocumentFromTextBuffer([], undefined, true);\n this.astWithTokens = this.initialAstWithoutTokens;\n }\n }\n didLanguageChange(languageId) {\n return this.brackets.didLanguageChange(languageId);\n }\n //#region TextModel events\n handleDidChangeBackgroundTokenizationState() {\n if (this.textModel.tokenization.backgroundTokenizationState === 2 /* BackgroundTokenizationState.Completed */) {\n const wasUndefined = this.initialAstWithoutTokens === undefined;\n // Clear the initial tree as we can use the tree with token information now.\n this.initialAstWithoutTokens = undefined;\n if (!wasUndefined) {\n this.didChangeEmitter.fire();\n }\n }\n }\n handleDidChangeTokens({ ranges }) {\n const edits = ranges.map(r => new TextEditInfo(toLength(r.fromLineNumber - 1, 0), toLength(r.toLineNumber, 0), toLength(r.toLineNumber - r.fromLineNumber + 1, 0)));\n this.astWithTokens = this.parseDocumentFromTextBuffer(edits, this.astWithTokens, false);\n if (!this.initialAstWithoutTokens) {\n this.didChangeEmitter.fire();\n }\n }\n handleContentChanged(change) {\n const edits = change.changes.map(c => {\n const range = Range.lift(c.range);\n return new TextEditInfo(positionToLength(range.getStartPosition()), positionToLength(range.getEndPosition()), lengthOfString(c.text));\n }).reverse();\n this.astWithTokens = this.parseDocumentFromTextBuffer(edits, this.astWithTokens, false);\n if (this.initialAstWithoutTokens) {\n this.initialAstWithoutTokens = this.parseDocumentFromTextBuffer(edits, this.initialAstWithoutTokens, false);\n }\n }\n //#endregion\n /**\n * @pure (only if isPure = true)\n */\n parseDocumentFromTextBuffer(edits, previousAst, immutable) {\n // Is much faster if `isPure = false`.\n const isPure = false;\n const previousAstClone = isPure ? previousAst === null || previousAst === void 0 ? void 0 : previousAst.deepClone() : previousAst;\n const tokenizer = new TextBufferTokenizer(this.textModel, this.brackets);\n const result = parseDocument(tokenizer, edits, previousAstClone, immutable);\n return result;\n }\n getBracketsInRange(range) {\n const startOffset = toLength(range.startLineNumber - 1, range.startColumn - 1);\n const endOffset = toLength(range.endLineNumber - 1, range.endColumn - 1);\n const result = new Array();\n const node = this.initialAstWithoutTokens || this.astWithTokens;\n collectBrackets(node, lengthZero, node.length, startOffset, endOffset, result, 0, new Map());\n return result;\n }\n getBracketPairsInRange(range, includeMinIndentation) {\n const result = new Array();\n const startLength = positionToLength(range.getStartPosition());\n const endLength = positionToLength(range.getEndPosition());\n const node = this.initialAstWithoutTokens || this.astWithTokens;\n const context = new CollectBracketPairsContext(result, includeMinIndentation, this.textModel);\n collectBracketPairs(node, lengthZero, node.length, startLength, endLength, context, 0, new Map());\n return result;\n }\n getFirstBracketAfter(position) {\n const node = this.initialAstWithoutTokens || this.astWithTokens;\n return getFirstBracketAfter(node, lengthZero, node.length, positionToLength(position));\n }\n getFirstBracketBefore(position) {\n const node = this.initialAstWithoutTokens || this.astWithTokens;\n return getFirstBracketBefore(node, lengthZero, node.length, positionToLength(position));\n }\n}\nfunction getFirstBracketBefore(node, nodeOffsetStart, nodeOffsetEnd, position) {\n if (node.kind === 4 /* AstNodeKind.List */ || node.kind === 2 /* AstNodeKind.Pair */) {\n const lengths = [];\n for (const child of node.children) {\n nodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length);\n lengths.push({ nodeOffsetStart, nodeOffsetEnd });\n nodeOffsetStart = nodeOffsetEnd;\n }\n for (let i = lengths.length - 1; i >= 0; i--) {\n const { nodeOffsetStart, nodeOffsetEnd } = lengths[i];\n if (lengthLessThan(nodeOffsetStart, position)) {\n const result = getFirstBracketBefore(node.children[i], nodeOffsetStart, nodeOffsetEnd, position);\n if (result) {\n return result;\n }\n }\n }\n return null;\n }\n else if (node.kind === 3 /* AstNodeKind.UnexpectedClosingBracket */) {\n return null;\n }\n else if (node.kind === 1 /* AstNodeKind.Bracket */) {\n const range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd);\n return {\n bracketInfo: node.bracketInfo,\n range\n };\n }\n return null;\n}\nfunction getFirstBracketAfter(node, nodeOffsetStart, nodeOffsetEnd, position) {\n if (node.kind === 4 /* AstNodeKind.List */ || node.kind === 2 /* AstNodeKind.Pair */) {\n for (const child of node.children) {\n nodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length);\n if (lengthLessThan(position, nodeOffsetEnd)) {\n const result = getFirstBracketAfter(child, nodeOffsetStart, nodeOffsetEnd, position);\n if (result) {\n return result;\n }\n }\n nodeOffsetStart = nodeOffsetEnd;\n }\n return null;\n }\n else if (node.kind === 3 /* AstNodeKind.UnexpectedClosingBracket */) {\n return null;\n }\n else if (node.kind === 1 /* AstNodeKind.Bracket */) {\n const range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd);\n return {\n bracketInfo: node.bracketInfo,\n range\n };\n }\n return null;\n}\nfunction collectBrackets(node, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, result, level, levelPerBracketType) {\n if (level > 200) {\n return;\n }\n if (node.kind === 4 /* AstNodeKind.List */) {\n for (const child of node.children) {\n nodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length);\n if (lengthLessThanEqual(nodeOffsetStart, endOffset) &&\n lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) {\n collectBrackets(child, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, result, level, levelPerBracketType);\n }\n nodeOffsetStart = nodeOffsetEnd;\n }\n }\n else if (node.kind === 2 /* AstNodeKind.Pair */) {\n let levelPerBracket = 0;\n if (levelPerBracketType) {\n let existing = levelPerBracketType.get(node.openingBracket.text);\n if (existing === undefined) {\n existing = 0;\n }\n levelPerBracket = existing;\n existing++;\n levelPerBracketType.set(node.openingBracket.text, existing);\n }\n // Don't use node.children here to improve performance\n {\n const child = node.openingBracket;\n nodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length);\n if (lengthLessThanEqual(nodeOffsetStart, endOffset) &&\n lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) {\n const range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd);\n result.push(new BracketInfo(range, level, levelPerBracket, !node.closingBracket));\n }\n nodeOffsetStart = nodeOffsetEnd;\n }\n if (node.child) {\n const child = node.child;\n nodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length);\n if (lengthLessThanEqual(nodeOffsetStart, endOffset) &&\n lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) {\n collectBrackets(child, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, result, level + 1, levelPerBracketType);\n }\n nodeOffsetStart = nodeOffsetEnd;\n }\n if (node.closingBracket) {\n const child = node.closingBracket;\n nodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length);\n if (lengthLessThanEqual(nodeOffsetStart, endOffset) &&\n lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) {\n const range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd);\n result.push(new BracketInfo(range, level, levelPerBracket, false));\n }\n nodeOffsetStart = nodeOffsetEnd;\n }\n levelPerBracketType === null || levelPerBracketType === void 0 ? void 0 : levelPerBracketType.set(node.openingBracket.text, levelPerBracket);\n }\n else if (node.kind === 3 /* AstNodeKind.UnexpectedClosingBracket */) {\n const range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd);\n result.push(new BracketInfo(range, level - 1, 0, true));\n }\n else if (node.kind === 1 /* AstNodeKind.Bracket */) {\n const range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd);\n result.push(new BracketInfo(range, level - 1, 0, false));\n }\n}\nclass CollectBracketPairsContext {\n constructor(result, includeMinIndentation, textModel) {\n this.result = result;\n this.includeMinIndentation = includeMinIndentation;\n this.textModel = textModel;\n }\n}\nfunction collectBracketPairs(node, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, context, level, levelPerBracketType) {\n var _a;\n if (level > 200) {\n return;\n }\n if (node.kind === 2 /* AstNodeKind.Pair */) {\n let levelPerBracket = 0;\n if (levelPerBracketType) {\n let existing = levelPerBracketType.get(node.openingBracket.text);\n if (existing === undefined) {\n existing = 0;\n }\n levelPerBracket = existing;\n existing++;\n levelPerBracketType.set(node.openingBracket.text, existing);\n }\n const openingBracketEnd = lengthAdd(nodeOffsetStart, node.openingBracket.length);\n let minIndentation = -1;\n if (context.includeMinIndentation) {\n minIndentation = node.computeMinIndentation(nodeOffsetStart, context.textModel);\n }\n context.result.push(new BracketPairWithMinIndentationInfo(lengthsToRange(nodeOffsetStart, nodeOffsetEnd), lengthsToRange(nodeOffsetStart, openingBracketEnd), node.closingBracket\n ? lengthsToRange(lengthAdd(openingBracketEnd, ((_a = node.child) === null || _a === void 0 ? void 0 : _a.length) || lengthZero), nodeOffsetEnd)\n : undefined, level, levelPerBracket, node, minIndentation));\n nodeOffsetStart = openingBracketEnd;\n if (node.child) {\n const child = node.child;\n nodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length);\n if (lengthLessThanEqual(nodeOffsetStart, endOffset) &&\n lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) {\n collectBracketPairs(child, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, context, level + 1, levelPerBracketType);\n }\n }\n levelPerBracketType === null || levelPerBracketType === void 0 ? void 0 : levelPerBracketType.set(node.openingBracket.text, levelPerBracket);\n }\n else {\n let curOffset = nodeOffsetStart;\n for (const child of node.children) {\n const childOffset = curOffset;\n curOffset = lengthAdd(curOffset, child.length);\n if (lengthLessThanEqual(childOffset, endOffset) &&\n lengthLessThanEqual(startOffset, curOffset)) {\n collectBracketPairs(child, childOffset, curOffset, startOffset, endOffset, context, level, levelPerBracketType);\n }\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 *--------------------------------------------------------------------------------------------*/\nimport { Emitter } from '../../../../base/common/event.js';\nimport { Disposable, DisposableStore, MutableDisposable } from '../../../../base/common/lifecycle.js';\nimport { Range } from '../../core/range.js';\nimport { BracketPairsTree } from './bracketPairsTree/bracketPairsTree.js';\nimport { ignoreBracketsInToken } from '../../languages/supports.js';\nimport { BracketsUtils } from '../../languages/supports/richEditBrackets.js';\nimport { compareBy, findLast, findLastMaxBy } from '../../../../base/common/arrays.js';\nexport class BracketPairsTextModelPart extends Disposable {\n constructor(textModel, languageConfigurationService) {\n super();\n this.textModel = textModel;\n this.languageConfigurationService = languageConfigurationService;\n this.bracketPairsTree = this._register(new MutableDisposable());\n this.onDidChangeEmitter = new Emitter();\n this.onDidChange = this.onDidChangeEmitter.event;\n this.bracketsRequested = false;\n this._register(this.languageConfigurationService.onDidChange(e => {\n var _a;\n if (!e.languageId || ((_a = this.bracketPairsTree.value) === null || _a === void 0 ? void 0 : _a.object.didLanguageChange(e.languageId))) {\n this.bracketPairsTree.clear();\n this.updateBracketPairsTree();\n }\n }));\n }\n get canBuildAST() {\n const maxSupportedDocumentLength = /* max lines */ 50000 * /* average column count */ 100;\n return this.textModel.getValueLength() <= maxSupportedDocumentLength;\n }\n //#region TextModel events\n handleDidChangeOptions(e) {\n this.bracketPairsTree.clear();\n this.updateBracketPairsTree();\n }\n handleDidChangeLanguage(e) {\n this.bracketPairsTree.clear();\n this.updateBracketPairsTree();\n }\n handleDidChangeContent(change) {\n var _a;\n (_a = this.bracketPairsTree.value) === null || _a === void 0 ? void 0 : _a.object.handleContentChanged(change);\n }\n handleDidChangeBackgroundTokenizationState() {\n var _a;\n (_a = this.bracketPairsTree.value) === null || _a === void 0 ? void 0 : _a.object.handleDidChangeBackgroundTokenizationState();\n }\n handleDidChangeTokens(e) {\n var _a;\n (_a = this.bracketPairsTree.value) === null || _a === void 0 ? void 0 : _a.object.handleDidChangeTokens(e);\n }\n //#endregion\n updateBracketPairsTree() {\n if (this.bracketsRequested && this.canBuildAST) {\n if (!this.bracketPairsTree.value) {\n const store = new DisposableStore();\n this.bracketPairsTree.value = createDisposableRef(store.add(new BracketPairsTree(this.textModel, (languageId) => {\n return this.languageConfigurationService.getLanguageConfiguration(languageId);\n })), store);\n store.add(this.bracketPairsTree.value.object.onDidChange(e => this.onDidChangeEmitter.fire(e)));\n this.onDidChangeEmitter.fire();\n }\n }\n else {\n if (this.bracketPairsTree.value) {\n this.bracketPairsTree.clear();\n // Important: Don't call fire if there was no change!\n this.onDidChangeEmitter.fire();\n }\n }\n }\n /**\n * Returns all bracket pairs that intersect the given range.\n * The result is sorted by the start position.\n */\n getBracketPairsInRange(range) {\n var _a;\n this.bracketsRequested = true;\n this.updateBracketPairsTree();\n return ((_a = this.bracketPairsTree.value) === null || _a === void 0 ? void 0 : _a.object.getBracketPairsInRange(range, false)) || [];\n }\n getBracketPairsInRangeWithMinIndentation(range) {\n var _a;\n this.bracketsRequested = true;\n this.updateBracketPairsTree();\n return ((_a = this.bracketPairsTree.value) === null || _a === void 0 ? void 0 : _a.object.getBracketPairsInRange(range, true)) || [];\n }\n getBracketsInRange(range) {\n var _a;\n this.bracketsRequested = true;\n this.updateBracketPairsTree();\n return ((_a = this.bracketPairsTree.value) === null || _a === void 0 ? void 0 : _a.object.getBracketsInRange(range)) || [];\n }\n findMatchingBracketUp(_bracket, _position, maxDuration) {\n const position = this.textModel.validatePosition(_position);\n const languageId = this.textModel.getLanguageIdAtPosition(position.lineNumber, position.column);\n if (this.canBuildAST) {\n const closingBracketInfo = this.languageConfigurationService\n .getLanguageConfiguration(languageId)\n .bracketsNew.getClosingBracketInfo(_bracket);\n if (!closingBracketInfo) {\n return null;\n }\n const bracketPair = findLast(this.getBracketPairsInRange(Range.fromPositions(_position, _position)) || [], (b) => closingBracketInfo.closes(b.openingBracketInfo));\n if (bracketPair) {\n return bracketPair.openingBracketRange;\n }\n return null;\n }\n else {\n // Fallback to old bracket matching code:\n const bracket = _bracket.toLowerCase();\n const bracketsSupport = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n if (!bracketsSupport) {\n return null;\n }\n const data = bracketsSupport.textIsBracket[bracket];\n if (!data) {\n return null;\n }\n return stripBracketSearchCanceled(this._findMatchingBracketUp(data, position, createTimeBasedContinueBracketSearchPredicate(maxDuration)));\n }\n }\n matchBracket(position, maxDuration) {\n if (this.canBuildAST) {\n const bracketPair = findLastMaxBy(this.getBracketPairsInRange(Range.fromPositions(position, position)).filter((item) => item.closingBracketRange !== undefined &&\n (item.openingBracketRange.containsPosition(position) ||\n item.closingBracketRange.containsPosition(position))), compareBy((item) => item.openingBracketRange.containsPosition(position)\n ? item.openingBracketRange\n : item.closingBracketRange, Range.compareRangesUsingStarts));\n if (bracketPair) {\n return [bracketPair.openingBracketRange, bracketPair.closingBracketRange];\n }\n return null;\n }\n else {\n // Fallback to old bracket matching code:\n const continueSearchPredicate = createTimeBasedContinueBracketSearchPredicate(maxDuration);\n return this._matchBracket(this.textModel.validatePosition(position), continueSearchPredicate);\n }\n }\n _establishBracketSearchOffsets(position, lineTokens, modeBrackets, tokenIndex) {\n const tokenCount = lineTokens.getCount();\n const currentLanguageId = lineTokens.getLanguageId(tokenIndex);\n // limit search to not go before `maxBracketLength`\n let searchStartOffset = Math.max(0, position.column - 1 - modeBrackets.maxBracketLength);\n for (let i = tokenIndex - 1; i >= 0; i--) {\n const tokenEndOffset = lineTokens.getEndOffset(i);\n if (tokenEndOffset <= searchStartOffset) {\n break;\n }\n if (ignoreBracketsInToken(lineTokens.getStandardTokenType(i)) || lineTokens.getLanguageId(i) !== currentLanguageId) {\n searchStartOffset = tokenEndOffset;\n break;\n }\n }\n // limit search to not go after `maxBracketLength`\n let searchEndOffset = Math.min(lineTokens.getLineContent().length, position.column - 1 + modeBrackets.maxBracketLength);\n for (let i = tokenIndex + 1; i < tokenCount; i++) {\n const tokenStartOffset = lineTokens.getStartOffset(i);\n if (tokenStartOffset >= searchEndOffset) {\n break;\n }\n if (ignoreBracketsInToken(lineTokens.getStandardTokenType(i)) || lineTokens.getLanguageId(i) !== currentLanguageId) {\n searchEndOffset = tokenStartOffset;\n break;\n }\n }\n return { searchStartOffset, searchEndOffset };\n }\n _matchBracket(position, continueSearchPredicate) {\n const lineNumber = position.lineNumber;\n const lineTokens = this.textModel.tokenization.getLineTokens(lineNumber);\n const lineText = this.textModel.getLineContent(lineNumber);\n const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n if (tokenIndex < 0) {\n return null;\n }\n const currentModeBrackets = this.languageConfigurationService.getLanguageConfiguration(lineTokens.getLanguageId(tokenIndex)).brackets;\n // check that the token is not to be ignored\n if (currentModeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex))) {\n let { searchStartOffset, searchEndOffset } = this._establishBracketSearchOffsets(position, lineTokens, currentModeBrackets, tokenIndex);\n // it might be the case that [currentTokenStart -> currentTokenEnd] contains multiple brackets\n // `bestResult` will contain the most right-side result\n let bestResult = null;\n while (true) {\n const foundBracket = BracketsUtils.findNextBracketInRange(currentModeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (!foundBracket) {\n // there are no more brackets in this text\n break;\n }\n // check that we didn't hit a bracket too far away from position\n if (foundBracket.startColumn <= position.column && position.column <= foundBracket.endColumn) {\n const foundBracketText = lineText.substring(foundBracket.startColumn - 1, foundBracket.endColumn - 1).toLowerCase();\n const r = this._matchFoundBracket(foundBracket, currentModeBrackets.textIsBracket[foundBracketText], currentModeBrackets.textIsOpenBracket[foundBracketText], continueSearchPredicate);\n if (r) {\n if (r instanceof BracketSearchCanceled) {\n return null;\n }\n bestResult = r;\n }\n }\n searchStartOffset = foundBracket.endColumn - 1;\n }\n if (bestResult) {\n return bestResult;\n }\n }\n // If position is in between two tokens, try also looking in the previous token\n if (tokenIndex > 0 && lineTokens.getStartOffset(tokenIndex) === position.column - 1) {\n const prevTokenIndex = tokenIndex - 1;\n const prevModeBrackets = this.languageConfigurationService.getLanguageConfiguration(lineTokens.getLanguageId(prevTokenIndex)).brackets;\n // check that previous token is not to be ignored\n if (prevModeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(prevTokenIndex))) {\n const { searchStartOffset, searchEndOffset } = this._establishBracketSearchOffsets(position, lineTokens, prevModeBrackets, prevTokenIndex);\n const foundBracket = BracketsUtils.findPrevBracketInRange(prevModeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n // check that we didn't hit a bracket too far away from position\n if (foundBracket && foundBracket.startColumn <= position.column && position.column <= foundBracket.endColumn) {\n const foundBracketText = lineText.substring(foundBracket.startColumn - 1, foundBracket.endColumn - 1).toLowerCase();\n const r = this._matchFoundBracket(foundBracket, prevModeBrackets.textIsBracket[foundBracketText], prevModeBrackets.textIsOpenBracket[foundBracketText], continueSearchPredicate);\n if (r) {\n if (r instanceof BracketSearchCanceled) {\n return null;\n }\n return r;\n }\n }\n }\n }\n return null;\n }\n _matchFoundBracket(foundBracket, data, isOpen, continueSearchPredicate) {\n if (!data) {\n return null;\n }\n const matched = (isOpen\n ? this._findMatchingBracketDown(data, foundBracket.getEndPosition(), continueSearchPredicate)\n : this._findMatchingBracketUp(data, foundBracket.getStartPosition(), continueSearchPredicate));\n if (!matched) {\n return null;\n }\n if (matched instanceof BracketSearchCanceled) {\n return matched;\n }\n return [foundBracket, matched];\n }\n _findMatchingBracketUp(bracket, position, continueSearchPredicate) {\n // console.log('_findMatchingBracketUp: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position));\n const languageId = bracket.languageId;\n const reversedBracketRegex = bracket.reversedRegex;\n let count = -1;\n let totalCallCount = 0;\n const searchPrevMatchingBracketInRange = (lineNumber, lineText, searchStartOffset, searchEndOffset) => {\n while (true) {\n if (continueSearchPredicate && (++totalCallCount) % 100 === 0 && !continueSearchPredicate()) {\n return BracketSearchCanceled.INSTANCE;\n }\n const r = BracketsUtils.findPrevBracketInRange(reversedBracketRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (!r) {\n break;\n }\n const hitText = lineText.substring(r.startColumn - 1, r.endColumn - 1).toLowerCase();\n if (bracket.isOpen(hitText)) {\n count++;\n }\n else if (bracket.isClose(hitText)) {\n count--;\n }\n if (count === 0) {\n return r;\n }\n searchEndOffset = r.startColumn - 1;\n }\n return null;\n };\n for (let lineNumber = position.lineNumber; lineNumber >= 1; lineNumber--) {\n const lineTokens = this.textModel.tokenization.getLineTokens(lineNumber);\n const tokenCount = lineTokens.getCount();\n const lineText = this.textModel.getLineContent(lineNumber);\n let tokenIndex = tokenCount - 1;\n let searchStartOffset = lineText.length;\n let searchEndOffset = lineText.length;\n if (lineNumber === position.lineNumber) {\n tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n searchStartOffset = position.column - 1;\n searchEndOffset = position.column - 1;\n }\n let prevSearchInToken = true;\n for (; tokenIndex >= 0; tokenIndex--) {\n const searchInToken = (lineTokens.getLanguageId(tokenIndex) === languageId && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));\n if (searchInToken) {\n // this token should be searched\n if (prevSearchInToken) {\n // the previous token should be searched, simply extend searchStartOffset\n searchStartOffset = lineTokens.getStartOffset(tokenIndex);\n }\n else {\n // the previous token should not be searched\n searchStartOffset = lineTokens.getStartOffset(tokenIndex);\n searchEndOffset = lineTokens.getEndOffset(tokenIndex);\n }\n }\n else {\n // this token should not be searched\n if (prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = searchPrevMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return r;\n }\n }\n }\n prevSearchInToken = searchInToken;\n }\n if (prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = searchPrevMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return r;\n }\n }\n }\n return null;\n }\n _findMatchingBracketDown(bracket, position, continueSearchPredicate) {\n // console.log('_findMatchingBracketDown: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position));\n const languageId = bracket.languageId;\n const bracketRegex = bracket.forwardRegex;\n let count = 1;\n let totalCallCount = 0;\n const searchNextMatchingBracketInRange = (lineNumber, lineText, searchStartOffset, searchEndOffset) => {\n while (true) {\n if (continueSearchPredicate && (++totalCallCount) % 100 === 0 && !continueSearchPredicate()) {\n return BracketSearchCanceled.INSTANCE;\n }\n const r = BracketsUtils.findNextBracketInRange(bracketRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (!r) {\n break;\n }\n const hitText = lineText.substring(r.startColumn - 1, r.endColumn - 1).toLowerCase();\n if (bracket.isOpen(hitText)) {\n count++;\n }\n else if (bracket.isClose(hitText)) {\n count--;\n }\n if (count === 0) {\n return r;\n }\n searchStartOffset = r.endColumn - 1;\n }\n return null;\n };\n const lineCount = this.textModel.getLineCount();\n for (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {\n const lineTokens = this.textModel.tokenization.getLineTokens(lineNumber);\n const tokenCount = lineTokens.getCount();\n const lineText = this.textModel.getLineContent(lineNumber);\n let tokenIndex = 0;\n let searchStartOffset = 0;\n let searchEndOffset = 0;\n if (lineNumber === position.lineNumber) {\n tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n searchStartOffset = position.column - 1;\n searchEndOffset = position.column - 1;\n }\n let prevSearchInToken = true;\n for (; tokenIndex < tokenCount; tokenIndex++) {\n const searchInToken = (lineTokens.getLanguageId(tokenIndex) === languageId && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));\n if (searchInToken) {\n // this token should be searched\n if (prevSearchInToken) {\n // the previous token should be searched, simply extend searchEndOffset\n searchEndOffset = lineTokens.getEndOffset(tokenIndex);\n }\n else {\n // the previous token should not be searched\n searchStartOffset = lineTokens.getStartOffset(tokenIndex);\n searchEndOffset = lineTokens.getEndOffset(tokenIndex);\n }\n }\n else {\n // this token should not be searched\n if (prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = searchNextMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return r;\n }\n }\n }\n prevSearchInToken = searchInToken;\n }\n if (prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = searchNextMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return r;\n }\n }\n }\n return null;\n }\n findPrevBracket(_position) {\n var _a;\n const position = this.textModel.validatePosition(_position);\n if (this.canBuildAST) {\n this.bracketsRequested = true;\n this.updateBracketPairsTree();\n return ((_a = this.bracketPairsTree.value) === null || _a === void 0 ? void 0 : _a.object.getFirstBracketBefore(position)) || null;\n }\n let languageId = null;\n let modeBrackets = null;\n let bracketConfig = null;\n for (let lineNumber = position.lineNumber; lineNumber >= 1; lineNumber--) {\n const lineTokens = this.textModel.tokenization.getLineTokens(lineNumber);\n const tokenCount = lineTokens.getCount();\n const lineText = this.textModel.getLineContent(lineNumber);\n let tokenIndex = tokenCount - 1;\n let searchStartOffset = lineText.length;\n let searchEndOffset = lineText.length;\n if (lineNumber === position.lineNumber) {\n tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n searchStartOffset = position.column - 1;\n searchEndOffset = position.column - 1;\n const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n if (languageId !== tokenLanguageId) {\n languageId = tokenLanguageId;\n modeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n bracketConfig = this.languageConfigurationService.getLanguageConfiguration(languageId).bracketsNew;\n }\n }\n let prevSearchInToken = true;\n for (; tokenIndex >= 0; tokenIndex--) {\n const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n if (languageId !== tokenLanguageId) {\n // language id change!\n if (modeBrackets && bracketConfig && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = BracketsUtils.findPrevBracketInRange(modeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return this._toFoundBracket(bracketConfig, r);\n }\n prevSearchInToken = false;\n }\n languageId = tokenLanguageId;\n modeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n bracketConfig = this.languageConfigurationService.getLanguageConfiguration(languageId).bracketsNew;\n }\n const searchInToken = (!!modeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));\n if (searchInToken) {\n // this token should be searched\n if (prevSearchInToken) {\n // the previous token should be searched, simply extend searchStartOffset\n searchStartOffset = lineTokens.getStartOffset(tokenIndex);\n }\n else {\n // the previous token should not be searched\n searchStartOffset = lineTokens.getStartOffset(tokenIndex);\n searchEndOffset = lineTokens.getEndOffset(tokenIndex);\n }\n }\n else {\n // this token should not be searched\n if (bracketConfig && modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = BracketsUtils.findPrevBracketInRange(modeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return this._toFoundBracket(bracketConfig, r);\n }\n }\n }\n prevSearchInToken = searchInToken;\n }\n if (bracketConfig && modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = BracketsUtils.findPrevBracketInRange(modeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return this._toFoundBracket(bracketConfig, r);\n }\n }\n }\n return null;\n }\n findNextBracket(_position) {\n var _a;\n const position = this.textModel.validatePosition(_position);\n if (this.canBuildAST) {\n this.bracketsRequested = true;\n this.updateBracketPairsTree();\n return ((_a = this.bracketPairsTree.value) === null || _a === void 0 ? void 0 : _a.object.getFirstBracketAfter(position)) || null;\n }\n const lineCount = this.textModel.getLineCount();\n let languageId = null;\n let modeBrackets = null;\n let bracketConfig = null;\n for (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {\n const lineTokens = this.textModel.tokenization.getLineTokens(lineNumber);\n const tokenCount = lineTokens.getCount();\n const lineText = this.textModel.getLineContent(lineNumber);\n let tokenIndex = 0;\n let searchStartOffset = 0;\n let searchEndOffset = 0;\n if (lineNumber === position.lineNumber) {\n tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n searchStartOffset = position.column - 1;\n searchEndOffset = position.column - 1;\n const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n if (languageId !== tokenLanguageId) {\n languageId = tokenLanguageId;\n modeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n bracketConfig = this.languageConfigurationService.getLanguageConfiguration(languageId).bracketsNew;\n }\n }\n let prevSearchInToken = true;\n for (; tokenIndex < tokenCount; tokenIndex++) {\n const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n if (languageId !== tokenLanguageId) {\n // language id change!\n if (bracketConfig && modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return this._toFoundBracket(bracketConfig, r);\n }\n prevSearchInToken = false;\n }\n languageId = tokenLanguageId;\n modeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n bracketConfig = this.languageConfigurationService.getLanguageConfiguration(languageId).bracketsNew;\n }\n const searchInToken = (!!modeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));\n if (searchInToken) {\n // this token should be searched\n if (prevSearchInToken) {\n // the previous token should be searched, simply extend searchEndOffset\n searchEndOffset = lineTokens.getEndOffset(tokenIndex);\n }\n else {\n // the previous token should not be searched\n searchStartOffset = lineTokens.getStartOffset(tokenIndex);\n searchEndOffset = lineTokens.getEndOffset(tokenIndex);\n }\n }\n else {\n // this token should not be searched\n if (bracketConfig && modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return this._toFoundBracket(bracketConfig, r);\n }\n }\n }\n prevSearchInToken = searchInToken;\n }\n if (bracketConfig && modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return this._toFoundBracket(bracketConfig, r);\n }\n }\n }\n return null;\n }\n findEnclosingBrackets(_position, maxDuration) {\n const position = this.textModel.validatePosition(_position);\n if (this.canBuildAST) {\n const range = Range.fromPositions(position);\n const bracketPair = findLast(this.getBracketPairsInRange(Range.fromPositions(position, position)), (item) => item.closingBracketRange !== undefined && item.range.strictContainsRange(range));\n if (bracketPair) {\n return [bracketPair.openingBracketRange, bracketPair.closingBracketRange];\n }\n return null;\n }\n const continueSearchPredicate = createTimeBasedContinueBracketSearchPredicate(maxDuration);\n const lineCount = this.textModel.getLineCount();\n const savedCounts = new Map();\n let counts = [];\n const resetCounts = (languageId, modeBrackets) => {\n if (!savedCounts.has(languageId)) {\n const tmp = [];\n for (let i = 0, len = modeBrackets ? modeBrackets.brackets.length : 0; i < len; i++) {\n tmp[i] = 0;\n }\n savedCounts.set(languageId, tmp);\n }\n counts = savedCounts.get(languageId);\n };\n let totalCallCount = 0;\n const searchInRange = (modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset) => {\n while (true) {\n if (continueSearchPredicate && (++totalCallCount) % 100 === 0 && !continueSearchPredicate()) {\n return BracketSearchCanceled.INSTANCE;\n }\n const r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (!r) {\n break;\n }\n const hitText = lineText.substring(r.startColumn - 1, r.endColumn - 1).toLowerCase();\n const bracket = modeBrackets.textIsBracket[hitText];\n if (bracket) {\n if (bracket.isOpen(hitText)) {\n counts[bracket.index]++;\n }\n else if (bracket.isClose(hitText)) {\n counts[bracket.index]--;\n }\n if (counts[bracket.index] === -1) {\n return this._matchFoundBracket(r, bracket, false, continueSearchPredicate);\n }\n }\n searchStartOffset = r.endColumn - 1;\n }\n return null;\n };\n let languageId = null;\n let modeBrackets = null;\n for (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {\n const lineTokens = this.textModel.tokenization.getLineTokens(lineNumber);\n const tokenCount = lineTokens.getCount();\n const lineText = this.textModel.getLineContent(lineNumber);\n let tokenIndex = 0;\n let searchStartOffset = 0;\n let searchEndOffset = 0;\n if (lineNumber === position.lineNumber) {\n tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n searchStartOffset = position.column - 1;\n searchEndOffset = position.column - 1;\n const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n if (languageId !== tokenLanguageId) {\n languageId = tokenLanguageId;\n modeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n resetCounts(languageId, modeBrackets);\n }\n }\n let prevSearchInToken = true;\n for (; tokenIndex < tokenCount; tokenIndex++) {\n const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);\n if (languageId !== tokenLanguageId) {\n // language id change!\n if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return stripBracketSearchCanceled(r);\n }\n prevSearchInToken = false;\n }\n languageId = tokenLanguageId;\n modeBrackets = this.languageConfigurationService.getLanguageConfiguration(languageId).brackets;\n resetCounts(languageId, modeBrackets);\n }\n const searchInToken = (!!modeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));\n if (searchInToken) {\n // this token should be searched\n if (prevSearchInToken) {\n // the previous token should be searched, simply extend searchEndOffset\n searchEndOffset = lineTokens.getEndOffset(tokenIndex);\n }\n else {\n // the previous token should not be searched\n searchStartOffset = lineTokens.getStartOffset(tokenIndex);\n searchEndOffset = lineTokens.getEndOffset(tokenIndex);\n }\n }\n else {\n // this token should not be searched\n if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return stripBracketSearchCanceled(r);\n }\n }\n }\n prevSearchInToken = searchInToken;\n }\n if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {\n const r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);\n if (r) {\n return stripBracketSearchCanceled(r);\n }\n }\n }\n return null;\n }\n _toFoundBracket(bracketConfig, r) {\n if (!r) {\n return null;\n }\n let text = this.textModel.getValueInRange(r);\n text = text.toLowerCase();\n const bracketInfo = bracketConfig.getBracketInfo(text);\n if (!bracketInfo) {\n return null;\n }\n return {\n range: r,\n bracketInfo\n };\n }\n}\nfunction createDisposableRef(object, disposable) {\n return {\n object,\n dispose: () => disposable === null || disposable === void 0 ? void 0 : disposable.dispose(),\n };\n}\nfunction createTimeBasedContinueBracketSearchPredicate(maxDuration) {\n if (typeof maxDuration === 'undefined') {\n return () => true;\n }\n else {\n const startTime = Date.now();\n return () => {\n return (Date.now() - startTime <= maxDuration);\n };\n }\n}\nclass BracketSearchCanceled {\n constructor() {\n this._searchCanceledBrand = undefined;\n }\n}\nBracketSearchCanceled.INSTANCE = new BracketSearchCanceled();\nfunction stripBracketSearchCanceled(result) {\n if (result instanceof BracketSearchCanceled) {\n return null;\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { Emitter } from '../../../../base/common/event.js';\nimport { Disposable } from '../../../../base/common/lifecycle.js';\nimport { Range } from '../../core/range.js';\nimport { editorBracketHighlightingForeground1, editorBracketHighlightingForeground2, editorBracketHighlightingForeground3, editorBracketHighlightingForeground4, editorBracketHighlightingForeground5, editorBracketHighlightingForeground6, editorBracketHighlightingUnexpectedBracketForeground } from '../../core/editorColorRegistry.js';\nimport { registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';\nexport class ColorizedBracketPairsDecorationProvider extends Disposable {\n constructor(textModel) {\n super();\n this.textModel = textModel;\n this.colorProvider = new ColorProvider();\n this.onDidChangeEmitter = new Emitter();\n this.onDidChange = this.onDidChangeEmitter.event;\n this.colorizationOptions = textModel.getOptions().bracketPairColorizationOptions;\n this._register(textModel.bracketPairs.onDidChange(e => {\n this.onDidChangeEmitter.fire();\n }));\n }\n //#region TextModel events\n handleDidChangeOptions(e) {\n this.colorizationOptions = this.textModel.getOptions().bracketPairColorizationOptions;\n }\n //#endregion\n getDecorationsInRange(range, ownerId, filterOutValidation) {\n if (ownerId === undefined) {\n return [];\n }\n if (!this.colorizationOptions.enabled) {\n return [];\n }\n const result = new Array();\n const bracketsInRange = this.textModel.bracketPairs.getBracketsInRange(range);\n for (const bracket of bracketsInRange) {\n result.push({\n id: `bracket${bracket.range.toString()}-${bracket.nestingLevel}`,\n options: {\n description: 'BracketPairColorization',\n inlineClassName: this.colorProvider.getInlineClassName(bracket, this.colorizationOptions.independentColorPoolPerBracketType),\n },\n ownerId: 0,\n range: bracket.range,\n });\n }\n return result;\n }\n getAllDecorations(ownerId, filterOutValidation) {\n if (ownerId === undefined) {\n return [];\n }\n if (!this.colorizationOptions.enabled) {\n return [];\n }\n return this.getDecorationsInRange(new Range(1, 1, this.textModel.getLineCount(), 1), ownerId, filterOutValidation);\n }\n}\nclass ColorProvider {\n constructor() {\n this.unexpectedClosingBracketClassName = 'unexpected-closing-bracket';\n }\n getInlineClassName(bracket, independentColorPoolPerBracketType) {\n if (bracket.isInvalid) {\n return this.unexpectedClosingBracketClassName;\n }\n return this.getInlineClassNameOfLevel(independentColorPoolPerBracketType ? bracket.nestingLevelOfEqualBracketType : bracket.nestingLevel);\n }\n getInlineClassNameOfLevel(level) {\n // To support a dynamic amount of colors up to 6 colors,\n // we use a number that is a lcm of all numbers from 1 to 6.\n return `bracket-highlighting-${level % 30}`;\n }\n}\nregisterThemingParticipant((theme, collector) => {\n const colors = [\n editorBracketHighlightingForeground1,\n editorBracketHighlightingForeground2,\n editorBracketHighlightingForeground3,\n editorBracketHighlightingForeground4,\n editorBracketHighlightingForeground5,\n editorBracketHighlightingForeground6\n ];\n const colorProvider = new ColorProvider();\n collector.addRule(`.monaco-editor .${colorProvider.unexpectedClosingBracketClassName} { color: ${theme.getColor(editorBracketHighlightingUnexpectedBracketForeground)}; }`);\n const colorValues = colors\n .map(c => theme.getColor(c))\n .filter((c) => !!c)\n .filter(c => !c.isTransparent());\n for (let level = 0; level < 30; level++) {\n const color = colorValues[level % colorValues.length];\n collector.addRule(`.monaco-editor .${colorProvider.getInlineClassNameOfLevel(level)} { color: ${color}; }`);\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 *--------------------------------------------------------------------------------------------*/\nclass SpacesDiffResult {\n constructor() {\n this.spacesDiff = 0;\n this.looksLikeAlignment = false;\n }\n}\n/**\n * Compute the diff in spaces between two line's indentation.\n */\nfunction spacesDiff(a, aLength, b, bLength, result) {\n result.spacesDiff = 0;\n result.looksLikeAlignment = false;\n // This can go both ways (e.g.):\n // - a: \"\\t\"\n // - b: \"\\t \"\n // => This should count 1 tab and 4 spaces\n let i;\n for (i = 0; i < aLength && i < bLength; i++) {\n const aCharCode = a.charCodeAt(i);\n const bCharCode = b.charCodeAt(i);\n if (aCharCode !== bCharCode) {\n break;\n }\n }\n let aSpacesCnt = 0, aTabsCount = 0;\n for (let j = i; j < aLength; j++) {\n const aCharCode = a.charCodeAt(j);\n if (aCharCode === 32 /* CharCode.Space */) {\n aSpacesCnt++;\n }\n else {\n aTabsCount++;\n }\n }\n let bSpacesCnt = 0, bTabsCount = 0;\n for (let j = i; j < bLength; j++) {\n const bCharCode = b.charCodeAt(j);\n if (bCharCode === 32 /* CharCode.Space */) {\n bSpacesCnt++;\n }\n else {\n bTabsCount++;\n }\n }\n if (aSpacesCnt > 0 && aTabsCount > 0) {\n return;\n }\n if (bSpacesCnt > 0 && bTabsCount > 0) {\n return;\n }\n const tabsDiff = Math.abs(aTabsCount - bTabsCount);\n const spacesDiff = Math.abs(aSpacesCnt - bSpacesCnt);\n if (tabsDiff === 0) {\n // check if the indentation difference might be caused by alignment reasons\n // sometime folks like to align their code, but this should not be used as a hint\n result.spacesDiff = spacesDiff;\n if (spacesDiff > 0 && 0 <= bSpacesCnt - 1 && bSpacesCnt - 1 < a.length && bSpacesCnt < b.length) {\n if (b.charCodeAt(bSpacesCnt) !== 32 /* CharCode.Space */ && a.charCodeAt(bSpacesCnt - 1) === 32 /* CharCode.Space */) {\n if (a.charCodeAt(a.length - 1) === 44 /* CharCode.Comma */) {\n // This looks like an alignment desire: e.g.\n // const a = b + c,\n // d = b - c;\n result.looksLikeAlignment = true;\n }\n }\n }\n return;\n }\n if (spacesDiff % tabsDiff === 0) {\n result.spacesDiff = spacesDiff / tabsDiff;\n return;\n }\n}\nexport function guessIndentation(source, defaultTabSize, defaultInsertSpaces) {\n // Look at most at the first 10k lines\n const linesCount = Math.min(source.getLineCount(), 10000);\n let linesIndentedWithTabsCount = 0; // number of lines that contain at least one tab in indentation\n let linesIndentedWithSpacesCount = 0; // number of lines that contain only spaces in indentation\n let previousLineText = ''; // content of latest line that contained non-whitespace chars\n let previousLineIndentation = 0; // index at which latest line contained the first non-whitespace char\n const ALLOWED_TAB_SIZE_GUESSES = [2, 4, 6, 8, 3, 5, 7]; // prefer even guesses for `tabSize`, limit to [2, 8].\n const MAX_ALLOWED_TAB_SIZE_GUESS = 8; // max(ALLOWED_TAB_SIZE_GUESSES) = 8\n const spacesDiffCount = [0, 0, 0, 0, 0, 0, 0, 0, 0]; // `tabSize` scores\n const tmp = new SpacesDiffResult();\n for (let lineNumber = 1; lineNumber <= linesCount; lineNumber++) {\n const currentLineLength = source.getLineLength(lineNumber);\n const currentLineText = source.getLineContent(lineNumber);\n // if the text buffer is chunk based, so long lines are cons-string, v8 will flattern the string when we check charCode.\n // checking charCode on chunks directly is cheaper.\n const useCurrentLineText = (currentLineLength <= 65536);\n let currentLineHasContent = false; // does `currentLineText` contain non-whitespace chars\n let currentLineIndentation = 0; // index at which `currentLineText` contains the first non-whitespace char\n let currentLineSpacesCount = 0; // count of spaces found in `currentLineText` indentation\n let currentLineTabsCount = 0; // count of tabs found in `currentLineText` indentation\n for (let j = 0, lenJ = currentLineLength; j < lenJ; j++) {\n const charCode = (useCurrentLineText ? currentLineText.charCodeAt(j) : source.getLineCharCode(lineNumber, j));\n if (charCode === 9 /* CharCode.Tab */) {\n currentLineTabsCount++;\n }\n else if (charCode === 32 /* CharCode.Space */) {\n currentLineSpacesCount++;\n }\n else {\n // Hit non whitespace character on this line\n currentLineHasContent = true;\n currentLineIndentation = j;\n break;\n }\n }\n // Ignore empty or only whitespace lines\n if (!currentLineHasContent) {\n continue;\n }\n if (currentLineTabsCount > 0) {\n linesIndentedWithTabsCount++;\n }\n else if (currentLineSpacesCount > 1) {\n linesIndentedWithSpacesCount++;\n }\n spacesDiff(previousLineText, previousLineIndentation, currentLineText, currentLineIndentation, tmp);\n if (tmp.looksLikeAlignment) {\n // if defaultInsertSpaces === true && the spaces count == tabSize, we may want to count it as valid indentation\n //\n // - item1\n // - item2\n //\n // otherwise skip this line entirely\n //\n // const a = 1,\n // b = 2;\n if (!(defaultInsertSpaces && defaultTabSize === tmp.spacesDiff)) {\n continue;\n }\n }\n const currentSpacesDiff = tmp.spacesDiff;\n if (currentSpacesDiff <= MAX_ALLOWED_TAB_SIZE_GUESS) {\n spacesDiffCount[currentSpacesDiff]++;\n }\n previousLineText = currentLineText;\n previousLineIndentation = currentLineIndentation;\n }\n let insertSpaces = defaultInsertSpaces;\n if (linesIndentedWithTabsCount !== linesIndentedWithSpacesCount) {\n insertSpaces = (linesIndentedWithTabsCount < linesIndentedWithSpacesCount);\n }\n let tabSize = defaultTabSize;\n // Guess tabSize only if inserting spaces...\n if (insertSpaces) {\n let tabSizeScore = (insertSpaces ? 0 : 0.1 * linesCount);\n // console.log(\"score threshold: \" + tabSizeScore);\n ALLOWED_TAB_SIZE_GUESSES.forEach((possibleTabSize) => {\n const possibleTabSizeScore = spacesDiffCount[possibleTabSize];\n if (possibleTabSizeScore > tabSizeScore) {\n tabSizeScore = possibleTabSizeScore;\n tabSize = possibleTabSize;\n }\n });\n // Let a tabSize of 2 win even if it is not the maximum\n // (only in case 4 was guessed)\n if (tabSize === 4 && spacesDiffCount[4] > 0 && spacesDiffCount[2] > 0 && spacesDiffCount[2] >= spacesDiffCount[4] / 2) {\n tabSize = 2;\n }\n }\n // console.log('--------------------------');\n // console.log('linesIndentedWithTabsCount: ' + linesIndentedWithTabsCount + ', linesIndentedWithSpacesCount: ' + linesIndentedWithSpacesCount);\n // console.log('spacesDiffCount: ' + spacesDiffCount);\n // console.log('tabSize: ' + tabSize + ', tabSizeScore: ' + tabSizeScore);\n return {\n insertSpaces: insertSpaces,\n tabSize: tabSize\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 *--------------------------------------------------------------------------------------------*/\nexport function getNodeColor(node) {\n return ((node.metadata & 1 /* Constants.ColorMask */) >>> 0 /* Constants.ColorOffset */);\n}\nfunction setNodeColor(node, color) {\n node.metadata = ((node.metadata & 254 /* Constants.ColorMaskInverse */) | (color << 0 /* Constants.ColorOffset */));\n}\nfunction getNodeIsVisited(node) {\n return ((node.metadata & 2 /* Constants.IsVisitedMask */) >>> 1 /* Constants.IsVisitedOffset */) === 1;\n}\nfunction setNodeIsVisited(node, value) {\n node.metadata = ((node.metadata & 253 /* Constants.IsVisitedMaskInverse */) | ((value ? 1 : 0) << 1 /* Constants.IsVisitedOffset */));\n}\nfunction getNodeIsForValidation(node) {\n return ((node.metadata & 4 /* Constants.IsForValidationMask */) >>> 2 /* Constants.IsForValidationOffset */) === 1;\n}\nfunction setNodeIsForValidation(node, value) {\n node.metadata = ((node.metadata & 251 /* Constants.IsForValidationMaskInverse */) | ((value ? 1 : 0) << 2 /* Constants.IsForValidationOffset */));\n}\nfunction getNodeStickiness(node) {\n return ((node.metadata & 24 /* Constants.StickinessMask */) >>> 3 /* Constants.StickinessOffset */);\n}\nfunction _setNodeStickiness(node, stickiness) {\n node.metadata = ((node.metadata & 231 /* Constants.StickinessMaskInverse */) | (stickiness << 3 /* Constants.StickinessOffset */));\n}\nfunction getCollapseOnReplaceEdit(node) {\n return ((node.metadata & 32 /* Constants.CollapseOnReplaceEditMask */) >>> 5 /* Constants.CollapseOnReplaceEditOffset */) === 1;\n}\nfunction setCollapseOnReplaceEdit(node, value) {\n node.metadata = ((node.metadata & 223 /* Constants.CollapseOnReplaceEditMaskInverse */) | ((value ? 1 : 0) << 5 /* Constants.CollapseOnReplaceEditOffset */));\n}\nexport class IntervalNode {\n constructor(id, start, end) {\n this.metadata = 0;\n this.parent = this;\n this.left = this;\n this.right = this;\n setNodeColor(this, 1 /* NodeColor.Red */);\n this.start = start;\n this.end = end;\n // FORCE_OVERFLOWING_TEST: this.delta = start;\n this.delta = 0;\n this.maxEnd = end;\n this.id = id;\n this.ownerId = 0;\n this.options = null;\n setNodeIsForValidation(this, false);\n _setNodeStickiness(this, 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */);\n setCollapseOnReplaceEdit(this, false);\n this.cachedVersionId = 0;\n this.cachedAbsoluteStart = start;\n this.cachedAbsoluteEnd = end;\n this.range = null;\n setNodeIsVisited(this, false);\n }\n reset(versionId, start, end, range) {\n this.start = start;\n this.end = end;\n this.maxEnd = end;\n this.cachedVersionId = versionId;\n this.cachedAbsoluteStart = start;\n this.cachedAbsoluteEnd = end;\n this.range = range;\n }\n setOptions(options) {\n this.options = options;\n const className = this.options.className;\n setNodeIsForValidation(this, (className === \"squiggly-error\" /* ClassName.EditorErrorDecoration */\n || className === \"squiggly-warning\" /* ClassName.EditorWarningDecoration */\n || className === \"squiggly-info\" /* ClassName.EditorInfoDecoration */));\n _setNodeStickiness(this, this.options.stickiness);\n setCollapseOnReplaceEdit(this, this.options.collapseOnReplaceEdit);\n }\n setCachedOffsets(absoluteStart, absoluteEnd, cachedVersionId) {\n if (this.cachedVersionId !== cachedVersionId) {\n this.range = null;\n }\n this.cachedVersionId = cachedVersionId;\n this.cachedAbsoluteStart = absoluteStart;\n this.cachedAbsoluteEnd = absoluteEnd;\n }\n detach() {\n this.parent = null;\n this.left = null;\n this.right = null;\n }\n}\nexport const SENTINEL = new IntervalNode(null, 0, 0);\nSENTINEL.parent = SENTINEL;\nSENTINEL.left = SENTINEL;\nSENTINEL.right = SENTINEL;\nsetNodeColor(SENTINEL, 0 /* NodeColor.Black */);\nexport class IntervalTree {\n constructor() {\n this.root = SENTINEL;\n this.requestNormalizeDelta = false;\n }\n intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId) {\n if (this.root === SENTINEL) {\n return [];\n }\n return intervalSearch(this, start, end, filterOwnerId, filterOutValidation, cachedVersionId);\n }\n search(filterOwnerId, filterOutValidation, cachedVersionId) {\n if (this.root === SENTINEL) {\n return [];\n }\n return search(this, filterOwnerId, filterOutValidation, cachedVersionId);\n }\n /**\n * Will not set `cachedAbsoluteStart` nor `cachedAbsoluteEnd` on the returned nodes!\n */\n collectNodesFromOwner(ownerId) {\n return collectNodesFromOwner(this, ownerId);\n }\n /**\n * Will not set `cachedAbsoluteStart` nor `cachedAbsoluteEnd` on the returned nodes!\n */\n collectNodesPostOrder() {\n return collectNodesPostOrder(this);\n }\n insert(node) {\n rbTreeInsert(this, node);\n this._normalizeDeltaIfNecessary();\n }\n delete(node) {\n rbTreeDelete(this, node);\n this._normalizeDeltaIfNecessary();\n }\n resolveNode(node, cachedVersionId) {\n const initialNode = node;\n let delta = 0;\n while (node !== this.root) {\n if (node === node.parent.right) {\n delta += node.parent.delta;\n }\n node = node.parent;\n }\n const nodeStart = initialNode.start + delta;\n const nodeEnd = initialNode.end + delta;\n initialNode.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId);\n }\n acceptReplace(offset, length, textLength, forceMoveMarkers) {\n // Our strategy is to remove all directly impacted nodes, and then add them back to the tree.\n // (1) collect all nodes that are intersecting this edit as nodes of interest\n const nodesOfInterest = searchForEditing(this, offset, offset + length);\n // (2) remove all nodes that are intersecting this edit\n for (let i = 0, len = nodesOfInterest.length; i < len; i++) {\n const node = nodesOfInterest[i];\n rbTreeDelete(this, node);\n }\n this._normalizeDeltaIfNecessary();\n // (3) edit all tree nodes except the nodes of interest\n noOverlapReplace(this, offset, offset + length, textLength);\n this._normalizeDeltaIfNecessary();\n // (4) edit the nodes of interest and insert them back in the tree\n for (let i = 0, len = nodesOfInterest.length; i < len; i++) {\n const node = nodesOfInterest[i];\n node.start = node.cachedAbsoluteStart;\n node.end = node.cachedAbsoluteEnd;\n nodeAcceptEdit(node, offset, (offset + length), textLength, forceMoveMarkers);\n node.maxEnd = node.end;\n rbTreeInsert(this, node);\n }\n this._normalizeDeltaIfNecessary();\n }\n _normalizeDeltaIfNecessary() {\n if (!this.requestNormalizeDelta) {\n return;\n }\n this.requestNormalizeDelta = false;\n normalizeDelta(this);\n }\n}\n//#region Delta Normalization\nfunction normalizeDelta(T) {\n let node = T.root;\n let delta = 0;\n while (node !== SENTINEL) {\n if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {\n // go left\n node = node.left;\n continue;\n }\n if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n // go right\n delta += node.delta;\n node = node.right;\n continue;\n }\n // handle current node\n node.start = delta + node.start;\n node.end = delta + node.end;\n node.delta = 0;\n recomputeMaxEnd(node);\n setNodeIsVisited(node, true);\n // going up from this node\n setNodeIsVisited(node.left, false);\n setNodeIsVisited(node.right, false);\n if (node === node.parent.right) {\n delta -= node.parent.delta;\n }\n node = node.parent;\n }\n setNodeIsVisited(T.root, false);\n}\nfunction adjustMarkerBeforeColumn(markerOffset, markerStickToPreviousCharacter, checkOffset, moveSemantics) {\n if (markerOffset < checkOffset) {\n return true;\n }\n if (markerOffset > checkOffset) {\n return false;\n }\n if (moveSemantics === 1 /* MarkerMoveSemantics.ForceMove */) {\n return false;\n }\n if (moveSemantics === 2 /* MarkerMoveSemantics.ForceStay */) {\n return true;\n }\n return markerStickToPreviousCharacter;\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, start, end, textLength, forceMoveMarkers) {\n const nodeStickiness = getNodeStickiness(node);\n const startStickToPreviousCharacter = (nodeStickiness === 0 /* TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges */\n || nodeStickiness === 2 /* TrackedRangeStickiness.GrowsOnlyWhenTypingBefore */);\n const endStickToPreviousCharacter = (nodeStickiness === 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */\n || nodeStickiness === 2 /* TrackedRangeStickiness.GrowsOnlyWhenTypingBefore */);\n const deletingCnt = (end - start);\n const insertingCnt = textLength;\n const commonLength = Math.min(deletingCnt, insertingCnt);\n const nodeStart = node.start;\n let startDone = false;\n const nodeEnd = node.end;\n let endDone = false;\n if (start <= nodeStart && nodeEnd <= end && getCollapseOnReplaceEdit(node)) {\n // This edit encompasses the entire decoration range\n // and the decoration has asked to become collapsed\n node.start = start;\n startDone = true;\n node.end = start;\n endDone = true;\n }\n {\n const moveSemantics = forceMoveMarkers ? 1 /* MarkerMoveSemantics.ForceMove */ : (deletingCnt > 0 ? 2 /* MarkerMoveSemantics.ForceStay */ : 0 /* MarkerMoveSemantics.MarkerDefined */);\n if (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, start, moveSemantics)) {\n startDone = true;\n }\n if (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, start, moveSemantics)) {\n endDone = true;\n }\n }\n if (commonLength > 0 && !forceMoveMarkers) {\n const moveSemantics = (deletingCnt > insertingCnt ? 2 /* MarkerMoveSemantics.ForceStay */ : 0 /* MarkerMoveSemantics.MarkerDefined */);\n if (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, start + commonLength, moveSemantics)) {\n startDone = true;\n }\n if (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, start + commonLength, moveSemantics)) {\n endDone = true;\n }\n }\n {\n const moveSemantics = forceMoveMarkers ? 1 /* MarkerMoveSemantics.ForceMove */ : 0 /* MarkerMoveSemantics.MarkerDefined */;\n if (!startDone && adjustMarkerBeforeColumn(nodeStart, startStickToPreviousCharacter, end, moveSemantics)) {\n node.start = start + insertingCnt;\n startDone = true;\n }\n if (!endDone && adjustMarkerBeforeColumn(nodeEnd, endStickToPreviousCharacter, end, moveSemantics)) {\n node.end = start + insertingCnt;\n endDone = true;\n }\n }\n // Finish\n const deltaColumn = (insertingCnt - deletingCnt);\n if (!startDone) {\n node.start = Math.max(0, nodeStart + deltaColumn);\n }\n if (!endDone) {\n node.end = Math.max(0, nodeEnd + deltaColumn);\n }\n if (node.start > node.end) {\n node.end = node.start;\n }\n}\nfunction searchForEditing(T, start, end) {\n // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree\n // Now, it is known that two intervals A and B overlap only when both\n // A.low <= B.high and A.high >= B.low. When searching the trees for\n // nodes overlapping with a given interval, you can immediately skip:\n // a) all nodes to the right of nodes whose low value is past the end of the given interval.\n // b) all nodes that have their maximum 'high' value below the start of the given interval.\n let node = T.root;\n let delta = 0;\n let nodeMaxEnd = 0;\n let nodeStart = 0;\n let nodeEnd = 0;\n const result = [];\n let resultLen = 0;\n while (node !== SENTINEL) {\n if (getNodeIsVisited(node)) {\n // going up from this node\n setNodeIsVisited(node.left, false);\n setNodeIsVisited(node.right, false);\n if (node === node.parent.right) {\n delta -= node.parent.delta;\n }\n node = node.parent;\n continue;\n }\n if (!getNodeIsVisited(node.left)) {\n // first time seeing this node\n nodeMaxEnd = delta + node.maxEnd;\n if (nodeMaxEnd < start) {\n // cover case b) from above\n // there is no need to search this node or its children\n setNodeIsVisited(node, true);\n continue;\n }\n if (node.left !== SENTINEL) {\n // go left\n node = node.left;\n continue;\n }\n }\n // handle current node\n nodeStart = delta + node.start;\n if (nodeStart > end) {\n // cover case a) from above\n // there is no need to search this node or its right subtree\n setNodeIsVisited(node, true);\n continue;\n }\n nodeEnd = delta + node.end;\n if (nodeEnd >= start) {\n node.setCachedOffsets(nodeStart, nodeEnd, 0);\n result[resultLen++] = node;\n }\n setNodeIsVisited(node, true);\n if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n // go right\n delta += node.delta;\n node = node.right;\n continue;\n }\n }\n setNodeIsVisited(T.root, false);\n return result;\n}\nfunction noOverlapReplace(T, start, end, textLength) {\n // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree\n // Now, it is known that two intervals A and B overlap only when both\n // A.low <= B.high and A.high >= B.low. When searching the trees for\n // nodes overlapping with a given interval, you can immediately skip:\n // a) all nodes to the right of nodes whose low value is past the end of the given interval.\n // b) all nodes that have their maximum 'high' value below the start of the given interval.\n let node = T.root;\n let delta = 0;\n let nodeMaxEnd = 0;\n let nodeStart = 0;\n const editDelta = (textLength - (end - start));\n while (node !== SENTINEL) {\n if (getNodeIsVisited(node)) {\n // going up from this node\n setNodeIsVisited(node.left, false);\n setNodeIsVisited(node.right, false);\n if (node === node.parent.right) {\n delta -= node.parent.delta;\n }\n recomputeMaxEnd(node);\n node = node.parent;\n continue;\n }\n if (!getNodeIsVisited(node.left)) {\n // first time seeing this node\n nodeMaxEnd = delta + node.maxEnd;\n if (nodeMaxEnd < start) {\n // cover case b) from above\n // there is no need to search this node or its children\n setNodeIsVisited(node, true);\n continue;\n }\n if (node.left !== SENTINEL) {\n // go left\n node = node.left;\n continue;\n }\n }\n // handle current node\n nodeStart = delta + node.start;\n if (nodeStart > end) {\n node.start += editDelta;\n node.end += editDelta;\n node.delta += editDelta;\n if (node.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || node.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {\n T.requestNormalizeDelta = true;\n }\n // cover case a) from above\n // there is no need to search this node or its right subtree\n setNodeIsVisited(node, true);\n continue;\n }\n setNodeIsVisited(node, true);\n if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n // go right\n delta += node.delta;\n node = node.right;\n continue;\n }\n }\n setNodeIsVisited(T.root, false);\n}\n//#endregion\n//#region Searching\nfunction collectNodesFromOwner(T, ownerId) {\n let node = T.root;\n const result = [];\n let resultLen = 0;\n while (node !== SENTINEL) {\n if (getNodeIsVisited(node)) {\n // going up from this node\n setNodeIsVisited(node.left, false);\n setNodeIsVisited(node.right, false);\n node = node.parent;\n continue;\n }\n if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {\n // go left\n node = node.left;\n continue;\n }\n // handle current node\n if (node.ownerId === ownerId) {\n result[resultLen++] = node;\n }\n setNodeIsVisited(node, true);\n if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n // go right\n node = node.right;\n continue;\n }\n }\n setNodeIsVisited(T.root, false);\n return result;\n}\nfunction collectNodesPostOrder(T) {\n let node = T.root;\n const result = [];\n let resultLen = 0;\n while (node !== SENTINEL) {\n if (getNodeIsVisited(node)) {\n // going up from this node\n setNodeIsVisited(node.left, false);\n setNodeIsVisited(node.right, false);\n node = node.parent;\n continue;\n }\n if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {\n // go left\n node = node.left;\n continue;\n }\n if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n // go right\n node = node.right;\n continue;\n }\n // handle current node\n result[resultLen++] = node;\n setNodeIsVisited(node, true);\n }\n setNodeIsVisited(T.root, false);\n return result;\n}\nfunction search(T, filterOwnerId, filterOutValidation, cachedVersionId) {\n let node = T.root;\n let delta = 0;\n let nodeStart = 0;\n let nodeEnd = 0;\n const result = [];\n let resultLen = 0;\n while (node !== SENTINEL) {\n if (getNodeIsVisited(node)) {\n // going up from this node\n setNodeIsVisited(node.left, false);\n setNodeIsVisited(node.right, false);\n if (node === node.parent.right) {\n delta -= node.parent.delta;\n }\n node = node.parent;\n continue;\n }\n if (node.left !== SENTINEL && !getNodeIsVisited(node.left)) {\n // go left\n node = node.left;\n continue;\n }\n // handle current node\n nodeStart = delta + node.start;\n nodeEnd = delta + node.end;\n node.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId);\n let include = true;\n if (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) {\n include = false;\n }\n if (filterOutValidation && getNodeIsForValidation(node)) {\n include = false;\n }\n if (include) {\n result[resultLen++] = node;\n }\n setNodeIsVisited(node, true);\n if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n // go right\n delta += node.delta;\n node = node.right;\n continue;\n }\n }\n setNodeIsVisited(T.root, false);\n return result;\n}\nfunction intervalSearch(T, intervalStart, intervalEnd, filterOwnerId, filterOutValidation, cachedVersionId) {\n // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree\n // Now, it is known that two intervals A and B overlap only when both\n // A.low <= B.high and A.high >= B.low. When searching the trees for\n // nodes overlapping with a given interval, you can immediately skip:\n // a) all nodes to the right of nodes whose low value is past the end of the given interval.\n // b) all nodes that have their maximum 'high' value below the start of the given interval.\n let node = T.root;\n let delta = 0;\n let nodeMaxEnd = 0;\n let nodeStart = 0;\n let nodeEnd = 0;\n const result = [];\n let resultLen = 0;\n while (node !== SENTINEL) {\n if (getNodeIsVisited(node)) {\n // going up from this node\n setNodeIsVisited(node.left, false);\n setNodeIsVisited(node.right, false);\n if (node === node.parent.right) {\n delta -= node.parent.delta;\n }\n node = node.parent;\n continue;\n }\n if (!getNodeIsVisited(node.left)) {\n // first time seeing this node\n nodeMaxEnd = delta + node.maxEnd;\n if (nodeMaxEnd < intervalStart) {\n // cover case b) from above\n // there is no need to search this node or its children\n setNodeIsVisited(node, true);\n continue;\n }\n if (node.left !== SENTINEL) {\n // go left\n node = node.left;\n continue;\n }\n }\n // handle current node\n nodeStart = delta + node.start;\n if (nodeStart > intervalEnd) {\n // cover case a) from above\n // there is no need to search this node or its right subtree\n setNodeIsVisited(node, true);\n continue;\n }\n nodeEnd = delta + node.end;\n if (nodeEnd >= intervalStart) {\n // There is overlap\n node.setCachedOffsets(nodeStart, nodeEnd, cachedVersionId);\n let include = true;\n if (filterOwnerId && node.ownerId && node.ownerId !== filterOwnerId) {\n include = false;\n }\n if (filterOutValidation && getNodeIsForValidation(node)) {\n include = false;\n }\n if (include) {\n result[resultLen++] = node;\n }\n }\n setNodeIsVisited(node, true);\n if (node.right !== SENTINEL && !getNodeIsVisited(node.right)) {\n // go right\n delta += node.delta;\n node = node.right;\n continue;\n }\n }\n setNodeIsVisited(T.root, false);\n return result;\n}\n//#endregion\n//#region Insertion\nfunction rbTreeInsert(T, newNode) {\n if (T.root === SENTINEL) {\n newNode.parent = SENTINEL;\n newNode.left = SENTINEL;\n newNode.right = SENTINEL;\n setNodeColor(newNode, 0 /* NodeColor.Black */);\n T.root = newNode;\n return T.root;\n }\n treeInsert(T, newNode);\n recomputeMaxEndWalkToRoot(newNode.parent);\n // repair tree\n let x = newNode;\n while (x !== T.root && getNodeColor(x.parent) === 1 /* NodeColor.Red */) {\n if (x.parent === x.parent.parent.left) {\n const y = x.parent.parent.right;\n if (getNodeColor(y) === 1 /* NodeColor.Red */) {\n setNodeColor(x.parent, 0 /* NodeColor.Black */);\n setNodeColor(y, 0 /* NodeColor.Black */);\n setNodeColor(x.parent.parent, 1 /* NodeColor.Red */);\n x = x.parent.parent;\n }\n else {\n if (x === x.parent.right) {\n x = x.parent;\n leftRotate(T, x);\n }\n setNodeColor(x.parent, 0 /* NodeColor.Black */);\n setNodeColor(x.parent.parent, 1 /* NodeColor.Red */);\n rightRotate(T, x.parent.parent);\n }\n }\n else {\n const y = x.parent.parent.left;\n if (getNodeColor(y) === 1 /* NodeColor.Red */) {\n setNodeColor(x.parent, 0 /* NodeColor.Black */);\n setNodeColor(y, 0 /* NodeColor.Black */);\n setNodeColor(x.parent.parent, 1 /* NodeColor.Red */);\n x = x.parent.parent;\n }\n else {\n if (x === x.parent.left) {\n x = x.parent;\n rightRotate(T, x);\n }\n setNodeColor(x.parent, 0 /* NodeColor.Black */);\n setNodeColor(x.parent.parent, 1 /* NodeColor.Red */);\n leftRotate(T, x.parent.parent);\n }\n }\n }\n setNodeColor(T.root, 0 /* NodeColor.Black */);\n return newNode;\n}\nfunction treeInsert(T, z) {\n let delta = 0;\n let x = T.root;\n const zAbsoluteStart = z.start;\n const zAbsoluteEnd = z.end;\n while (true) {\n const cmp = intervalCompare(zAbsoluteStart, zAbsoluteEnd, x.start + delta, x.end + delta);\n if (cmp < 0) {\n // this node should be inserted to the left\n // => it is not affected by the node's delta\n if (x.left === SENTINEL) {\n z.start -= delta;\n z.end -= delta;\n z.maxEnd -= delta;\n x.left = z;\n break;\n }\n else {\n x = x.left;\n }\n }\n else {\n // this node should be inserted to the right\n // => it is not affected by the node's delta\n if (x.right === SENTINEL) {\n z.start -= (delta + x.delta);\n z.end -= (delta + x.delta);\n z.maxEnd -= (delta + x.delta);\n x.right = z;\n break;\n }\n else {\n delta += x.delta;\n x = x.right;\n }\n }\n }\n z.parent = x;\n z.left = SENTINEL;\n z.right = SENTINEL;\n setNodeColor(z, 1 /* NodeColor.Red */);\n}\n//#endregion\n//#region Deletion\nfunction rbTreeDelete(T, z) {\n let x;\n let y;\n // RB-DELETE except we don't swap z and y in case c)\n // i.e. we always delete what's pointed at by z.\n if (z.left === SENTINEL) {\n x = z.right;\n y = z;\n // x's delta is no longer influenced by z's delta\n x.delta += z.delta;\n if (x.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || x.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {\n T.requestNormalizeDelta = true;\n }\n x.start += z.delta;\n x.end += z.delta;\n }\n else if (z.right === SENTINEL) {\n x = z.left;\n y = z;\n }\n else {\n y = leftest(z.right);\n x = y.right;\n // y's delta is no longer influenced by z's delta,\n // but we don't want to walk the entire right-hand-side subtree of x.\n // we therefore maintain z's delta in y, and adjust only x\n x.start += y.delta;\n x.end += y.delta;\n x.delta += y.delta;\n if (x.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || x.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {\n T.requestNormalizeDelta = true;\n }\n y.start += z.delta;\n y.end += z.delta;\n y.delta = z.delta;\n if (y.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || y.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {\n T.requestNormalizeDelta = true;\n }\n }\n if (y === T.root) {\n T.root = x;\n setNodeColor(x, 0 /* NodeColor.Black */);\n z.detach();\n resetSentinel();\n recomputeMaxEnd(x);\n T.root.parent = SENTINEL;\n return;\n }\n const yWasRed = (getNodeColor(y) === 1 /* NodeColor.Red */);\n if (y === y.parent.left) {\n y.parent.left = x;\n }\n else {\n y.parent.right = x;\n }\n if (y === z) {\n x.parent = y.parent;\n }\n else {\n if (y.parent === z) {\n x.parent = y;\n }\n else {\n x.parent = y.parent;\n }\n y.left = z.left;\n y.right = z.right;\n y.parent = z.parent;\n setNodeColor(y, getNodeColor(z));\n if (z === T.root) {\n T.root = y;\n }\n else {\n if (z === z.parent.left) {\n z.parent.left = y;\n }\n else {\n z.parent.right = y;\n }\n }\n if (y.left !== SENTINEL) {\n y.left.parent = y;\n }\n if (y.right !== SENTINEL) {\n y.right.parent = y;\n }\n }\n z.detach();\n if (yWasRed) {\n recomputeMaxEndWalkToRoot(x.parent);\n if (y !== z) {\n recomputeMaxEndWalkToRoot(y);\n recomputeMaxEndWalkToRoot(y.parent);\n }\n resetSentinel();\n return;\n }\n recomputeMaxEndWalkToRoot(x);\n recomputeMaxEndWalkToRoot(x.parent);\n if (y !== z) {\n recomputeMaxEndWalkToRoot(y);\n recomputeMaxEndWalkToRoot(y.parent);\n }\n // RB-DELETE-FIXUP\n let w;\n while (x !== T.root && getNodeColor(x) === 0 /* NodeColor.Black */) {\n if (x === x.parent.left) {\n w = x.parent.right;\n if (getNodeColor(w) === 1 /* NodeColor.Red */) {\n setNodeColor(w, 0 /* NodeColor.Black */);\n setNodeColor(x.parent, 1 /* NodeColor.Red */);\n leftRotate(T, x.parent);\n w = x.parent.right;\n }\n if (getNodeColor(w.left) === 0 /* NodeColor.Black */ && getNodeColor(w.right) === 0 /* NodeColor.Black */) {\n setNodeColor(w, 1 /* NodeColor.Red */);\n x = x.parent;\n }\n else {\n if (getNodeColor(w.right) === 0 /* NodeColor.Black */) {\n setNodeColor(w.left, 0 /* NodeColor.Black */);\n setNodeColor(w, 1 /* NodeColor.Red */);\n rightRotate(T, w);\n w = x.parent.right;\n }\n setNodeColor(w, getNodeColor(x.parent));\n setNodeColor(x.parent, 0 /* NodeColor.Black */);\n setNodeColor(w.right, 0 /* NodeColor.Black */);\n leftRotate(T, x.parent);\n x = T.root;\n }\n }\n else {\n w = x.parent.left;\n if (getNodeColor(w) === 1 /* NodeColor.Red */) {\n setNodeColor(w, 0 /* NodeColor.Black */);\n setNodeColor(x.parent, 1 /* NodeColor.Red */);\n rightRotate(T, x.parent);\n w = x.parent.left;\n }\n if (getNodeColor(w.left) === 0 /* NodeColor.Black */ && getNodeColor(w.right) === 0 /* NodeColor.Black */) {\n setNodeColor(w, 1 /* NodeColor.Red */);\n x = x.parent;\n }\n else {\n if (getNodeColor(w.left) === 0 /* NodeColor.Black */) {\n setNodeColor(w.right, 0 /* NodeColor.Black */);\n setNodeColor(w, 1 /* NodeColor.Red */);\n leftRotate(T, w);\n w = x.parent.left;\n }\n setNodeColor(w, getNodeColor(x.parent));\n setNodeColor(x.parent, 0 /* NodeColor.Black */);\n setNodeColor(w.left, 0 /* NodeColor.Black */);\n rightRotate(T, x.parent);\n x = T.root;\n }\n }\n }\n setNodeColor(x, 0 /* NodeColor.Black */);\n resetSentinel();\n}\nfunction leftest(node) {\n while (node.left !== SENTINEL) {\n node = node.left;\n }\n return node;\n}\nfunction resetSentinel() {\n SENTINEL.parent = SENTINEL;\n SENTINEL.delta = 0; // optional\n SENTINEL.start = 0; // optional\n SENTINEL.end = 0; // optional\n}\n//#endregion\n//#region Rotations\nfunction leftRotate(T, x) {\n const y = x.right; // set y.\n y.delta += x.delta; // y's delta is no longer influenced by x's delta\n if (y.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || y.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {\n T.requestNormalizeDelta = true;\n }\n y.start += x.delta;\n y.end += x.delta;\n x.right = y.left; // turn y's left subtree into x's right subtree.\n if (y.left !== SENTINEL) {\n y.left.parent = x;\n }\n y.parent = x.parent; // link x's parent to y.\n if (x.parent === SENTINEL) {\n T.root = y;\n }\n else if (x === x.parent.left) {\n x.parent.left = y;\n }\n else {\n x.parent.right = y;\n }\n y.left = x; // put x on y's left.\n x.parent = y;\n recomputeMaxEnd(x);\n recomputeMaxEnd(y);\n}\nfunction rightRotate(T, y) {\n const x = y.left;\n y.delta -= x.delta;\n if (y.delta < -1073741824 /* Constants.MIN_SAFE_DELTA */ || y.delta > 1073741824 /* Constants.MAX_SAFE_DELTA */) {\n T.requestNormalizeDelta = true;\n }\n y.start -= x.delta;\n y.end -= x.delta;\n y.left = x.right;\n if (x.right !== SENTINEL) {\n x.right.parent = y;\n }\n x.parent = y.parent;\n if (y.parent === SENTINEL) {\n T.root = x;\n }\n else if (y === y.parent.right) {\n y.parent.right = x;\n }\n else {\n y.parent.left = x;\n }\n x.right = y;\n y.parent = x;\n recomputeMaxEnd(y);\n recomputeMaxEnd(x);\n}\n//#endregion\n//#region max end computation\nfunction computeMaxEnd(node) {\n let maxEnd = node.end;\n if (node.left !== SENTINEL) {\n const leftMaxEnd = node.left.maxEnd;\n if (leftMaxEnd > maxEnd) {\n maxEnd = leftMaxEnd;\n }\n }\n if (node.right !== SENTINEL) {\n const rightMaxEnd = node.right.maxEnd + node.delta;\n if (rightMaxEnd > maxEnd) {\n maxEnd = rightMaxEnd;\n }\n }\n return maxEnd;\n}\nexport function recomputeMaxEnd(node) {\n node.maxEnd = computeMaxEnd(node);\n}\nfunction recomputeMaxEndWalkToRoot(node) {\n while (node !== SENTINEL) {\n const maxEnd = computeMaxEnd(node);\n if (node.maxEnd === maxEnd) {\n // no need to go further\n return;\n }\n node.maxEnd = maxEnd;\n node = node.parent;\n }\n}\n//#endregion\n//#region utils\nexport function intervalCompare(aStart, aEnd, bStart, bEnd) {\n if (aStart === bStart) {\n return aEnd - bEnd;\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nexport class TreeNode {\n constructor(piece, color) {\n this.piece = piece;\n this.color = color;\n this.size_left = 0;\n this.lf_left = 0;\n this.parent = this;\n this.left = this;\n this.right = this;\n }\n next() {\n if (this.right !== SENTINEL) {\n return leftest(this.right);\n }\n let node = this;\n while (node.parent !== SENTINEL) {\n if (node.parent.left === node) {\n break;\n }\n node = node.parent;\n }\n if (node.parent === SENTINEL) {\n return SENTINEL;\n }\n else {\n return node.parent;\n }\n }\n prev() {\n if (this.left !== SENTINEL) {\n return righttest(this.left);\n }\n let node = this;\n while (node.parent !== SENTINEL) {\n if (node.parent.right === node) {\n break;\n }\n node = node.parent;\n }\n if (node.parent === SENTINEL) {\n return SENTINEL;\n }\n else {\n return node.parent;\n }\n }\n detach() {\n this.parent = null;\n this.left = null;\n this.right = null;\n }\n}\nexport const SENTINEL = new TreeNode(null, 0 /* NodeColor.Black */);\nSENTINEL.parent = SENTINEL;\nSENTINEL.left = SENTINEL;\nSENTINEL.right = SENTINEL;\nSENTINEL.color = 0 /* NodeColor.Black */;\nexport function leftest(node) {\n while (node.left !== SENTINEL) {\n node = node.left;\n }\n return node;\n}\nexport function righttest(node) {\n while (node.right !== SENTINEL) {\n node = node.right;\n }\n return node;\n}\nexport function calculateSize(node) {\n if (node === SENTINEL) {\n return 0;\n }\n return node.size_left + node.piece.length + calculateSize(node.right);\n}\nexport function calculateLF(node) {\n if (node === SENTINEL) {\n return 0;\n }\n return node.lf_left + node.piece.lineFeedCnt + calculateLF(node.right);\n}\nexport function resetSentinel() {\n SENTINEL.parent = SENTINEL;\n}\nexport function leftRotate(tree, x) {\n const y = x.right;\n // fix size_left\n y.size_left += x.size_left + (x.piece ? x.piece.length : 0);\n y.lf_left += x.lf_left + (x.piece ? x.piece.lineFeedCnt : 0);\n x.right = y.left;\n if (y.left !== SENTINEL) {\n y.left.parent = x;\n }\n y.parent = x.parent;\n if (x.parent === SENTINEL) {\n tree.root = y;\n }\n else if (x.parent.left === x) {\n x.parent.left = y;\n }\n else {\n x.parent.right = y;\n }\n y.left = x;\n x.parent = y;\n}\nexport function rightRotate(tree, y) {\n const x = y.left;\n y.left = x.right;\n if (x.right !== SENTINEL) {\n x.right.parent = y;\n }\n x.parent = y.parent;\n // fix size_left\n y.size_left -= x.size_left + (x.piece ? x.piece.length : 0);\n y.lf_left -= x.lf_left + (x.piece ? x.piece.lineFeedCnt : 0);\n if (y.parent === SENTINEL) {\n tree.root = x;\n }\n else if (y === y.parent.right) {\n y.parent.right = x;\n }\n else {\n y.parent.left = x;\n }\n x.right = y;\n y.parent = x;\n}\nexport function rbDelete(tree, z) {\n let x;\n let y;\n if (z.left === SENTINEL) {\n y = z;\n x = y.right;\n }\n else if (z.right === SENTINEL) {\n y = z;\n x = y.left;\n }\n else {\n y = leftest(z.right);\n x = y.right;\n }\n if (y === tree.root) {\n tree.root = x;\n // if x is null, we are removing the only node\n x.color = 0 /* NodeColor.Black */;\n z.detach();\n resetSentinel();\n tree.root.parent = SENTINEL;\n return;\n }\n const yWasRed = (y.color === 1 /* NodeColor.Red */);\n if (y === y.parent.left) {\n y.parent.left = x;\n }\n else {\n y.parent.right = x;\n }\n if (y === z) {\n x.parent = y.parent;\n recomputeTreeMetadata(tree, x);\n }\n else {\n if (y.parent === z) {\n x.parent = y;\n }\n else {\n x.parent = y.parent;\n }\n // as we make changes to x's hierarchy, update size_left of subtree first\n recomputeTreeMetadata(tree, x);\n y.left = z.left;\n y.right = z.right;\n y.parent = z.parent;\n y.color = z.color;\n if (z === tree.root) {\n tree.root = y;\n }\n else {\n if (z === z.parent.left) {\n z.parent.left = y;\n }\n else {\n z.parent.right = y;\n }\n }\n if (y.left !== SENTINEL) {\n y.left.parent = y;\n }\n if (y.right !== SENTINEL) {\n y.right.parent = y;\n }\n // update metadata\n // we replace z with y, so in this sub tree, the length change is z.item.length\n y.size_left = z.size_left;\n y.lf_left = z.lf_left;\n recomputeTreeMetadata(tree, y);\n }\n z.detach();\n if (x.parent.left === x) {\n const newSizeLeft = calculateSize(x);\n const newLFLeft = calculateLF(x);\n if (newSizeLeft !== x.parent.size_left || newLFLeft !== x.parent.lf_left) {\n const delta = newSizeLeft - x.parent.size_left;\n const lf_delta = newLFLeft - x.parent.lf_left;\n x.parent.size_left = newSizeLeft;\n x.parent.lf_left = newLFLeft;\n updateTreeMetadata(tree, x.parent, delta, lf_delta);\n }\n }\n recomputeTreeMetadata(tree, x.parent);\n if (yWasRed) {\n resetSentinel();\n return;\n }\n // RB-DELETE-FIXUP\n let w;\n while (x !== tree.root && x.color === 0 /* NodeColor.Black */) {\n if (x === x.parent.left) {\n w = x.parent.right;\n if (w.color === 1 /* NodeColor.Red */) {\n w.color = 0 /* NodeColor.Black */;\n x.parent.color = 1 /* NodeColor.Red */;\n leftRotate(tree, x.parent);\n w = x.parent.right;\n }\n if (w.left.color === 0 /* NodeColor.Black */ && w.right.color === 0 /* NodeColor.Black */) {\n w.color = 1 /* NodeColor.Red */;\n x = x.parent;\n }\n else {\n if (w.right.color === 0 /* NodeColor.Black */) {\n w.left.color = 0 /* NodeColor.Black */;\n w.color = 1 /* NodeColor.Red */;\n rightRotate(tree, w);\n w = x.parent.right;\n }\n w.color = x.parent.color;\n x.parent.color = 0 /* NodeColor.Black */;\n w.right.color = 0 /* NodeColor.Black */;\n leftRotate(tree, x.parent);\n x = tree.root;\n }\n }\n else {\n w = x.parent.left;\n if (w.color === 1 /* NodeColor.Red */) {\n w.color = 0 /* NodeColor.Black */;\n x.parent.color = 1 /* NodeColor.Red */;\n rightRotate(tree, x.parent);\n w = x.parent.left;\n }\n if (w.left.color === 0 /* NodeColor.Black */ && w.right.color === 0 /* NodeColor.Black */) {\n w.color = 1 /* NodeColor.Red */;\n x = x.parent;\n }\n else {\n if (w.left.color === 0 /* NodeColor.Black */) {\n w.right.color = 0 /* NodeColor.Black */;\n w.color = 1 /* NodeColor.Red */;\n leftRotate(tree, w);\n w = x.parent.left;\n }\n w.color = x.parent.color;\n x.parent.color = 0 /* NodeColor.Black */;\n w.left.color = 0 /* NodeColor.Black */;\n rightRotate(tree, x.parent);\n x = tree.root;\n }\n }\n }\n x.color = 0 /* NodeColor.Black */;\n resetSentinel();\n}\nexport function fixInsert(tree, x) {\n recomputeTreeMetadata(tree, x);\n while (x !== tree.root && x.parent.color === 1 /* NodeColor.Red */) {\n if (x.parent === x.parent.parent.left) {\n const y = x.parent.parent.right;\n if (y.color === 1 /* NodeColor.Red */) {\n x.parent.color = 0 /* NodeColor.Black */;\n y.color = 0 /* NodeColor.Black */;\n x.parent.parent.color = 1 /* NodeColor.Red */;\n x = x.parent.parent;\n }\n else {\n if (x === x.parent.right) {\n x = x.parent;\n leftRotate(tree, x);\n }\n x.parent.color = 0 /* NodeColor.Black */;\n x.parent.parent.color = 1 /* NodeColor.Red */;\n rightRotate(tree, x.parent.parent);\n }\n }\n else {\n const y = x.parent.parent.left;\n if (y.color === 1 /* NodeColor.Red */) {\n x.parent.color = 0 /* NodeColor.Black */;\n y.color = 0 /* NodeColor.Black */;\n x.parent.parent.color = 1 /* NodeColor.Red */;\n x = x.parent.parent;\n }\n else {\n if (x === x.parent.left) {\n x = x.parent;\n rightRotate(tree, x);\n }\n x.parent.color = 0 /* NodeColor.Black */;\n x.parent.parent.color = 1 /* NodeColor.Red */;\n leftRotate(tree, x.parent.parent);\n }\n }\n }\n tree.root.color = 0 /* NodeColor.Black */;\n}\nexport function updateTreeMetadata(tree, x, delta, lineFeedCntDelta) {\n // node length change or line feed count change\n while (x !== tree.root && x !== SENTINEL) {\n if (x.parent.left === x) {\n x.parent.size_left += delta;\n x.parent.lf_left += lineFeedCntDelta;\n }\n x = x.parent;\n }\n}\nexport function recomputeTreeMetadata(tree, x) {\n let delta = 0;\n let lf_delta = 0;\n if (x === tree.root) {\n return;\n }\n // go upwards till the node whose left subtree is changed.\n while (x !== tree.root && x === x.parent.right) {\n x = x.parent;\n }\n if (x === tree.root) {\n // well, it means we add a node to the end (inorder)\n return;\n }\n // x is the node whose right subtree is changed.\n x = x.parent;\n delta = calculateSize(x.left) - x.size_left;\n lf_delta = calculateLF(x.left) - x.lf_left;\n x.size_left += delta;\n x.lf_left += lf_delta;\n // go upwards till root. O(logN)\n while (x !== tree.root && (delta !== 0 || lf_delta !== 0)) {\n if (x.parent.left === x) {\n x.parent.size_left += delta;\n x.parent.lf_left += lf_delta;\n }\n x = x.parent;\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 *--------------------------------------------------------------------------------------------*/\nimport { Position } from '../../core/position.js';\nimport { Range } from '../../core/range.js';\nimport { FindMatch } from '../../model.js';\nimport { SENTINEL, TreeNode, fixInsert, leftest, rbDelete, righttest, updateTreeMetadata } from './rbTreeBase.js';\nimport { Searcher, createFindMatch, isValidMatch } from '../textModelSearch.js';\n// const lfRegex = new RegExp(/\\r\\n|\\r|\\n/g);\nexport const AverageBufferSize = 65535;\nexport function createUintArray(arr) {\n let r;\n if (arr[arr.length - 1] < 65536) {\n r = new Uint16Array(arr.length);\n }\n else {\n r = new Uint32Array(arr.length);\n }\n r.set(arr, 0);\n return r;\n}\nexport class LineStarts {\n constructor(lineStarts, cr, lf, crlf, isBasicASCII) {\n this.lineStarts = lineStarts;\n this.cr = cr;\n this.lf = lf;\n this.crlf = crlf;\n this.isBasicASCII = isBasicASCII;\n }\n}\nexport function createLineStartsFast(str, readonly = true) {\n const r = [0];\n let rLength = 1;\n for (let i = 0, len = str.length; i < len; i++) {\n const chr = str.charCodeAt(i);\n if (chr === 13 /* CharCode.CarriageReturn */) {\n if (i + 1 < len && str.charCodeAt(i + 1) === 10 /* CharCode.LineFeed */) {\n // \\r\\n... case\n r[rLength++] = i + 2;\n i++; // skip \\n\n }\n else {\n // \\r... case\n r[rLength++] = i + 1;\n }\n }\n else if (chr === 10 /* CharCode.LineFeed */) {\n r[rLength++] = i + 1;\n }\n }\n if (readonly) {\n return createUintArray(r);\n }\n else {\n return r;\n }\n}\nexport function createLineStarts(r, str) {\n r.length = 0;\n r[0] = 0;\n let rLength = 1;\n let cr = 0, lf = 0, crlf = 0;\n let isBasicASCII = true;\n for (let i = 0, len = str.length; i < len; i++) {\n const chr = str.charCodeAt(i);\n if (chr === 13 /* CharCode.CarriageReturn */) {\n if (i + 1 < len && str.charCodeAt(i + 1) === 10 /* CharCode.LineFeed */) {\n // \\r\\n... case\n crlf++;\n r[rLength++] = i + 2;\n i++; // skip \\n\n }\n else {\n cr++;\n // \\r... case\n r[rLength++] = i + 1;\n }\n }\n else if (chr === 10 /* CharCode.LineFeed */) {\n lf++;\n r[rLength++] = i + 1;\n }\n else {\n if (isBasicASCII) {\n if (chr !== 9 /* CharCode.Tab */ && (chr < 32 || chr > 126)) {\n isBasicASCII = false;\n }\n }\n }\n }\n const result = new LineStarts(createUintArray(r), cr, lf, crlf, isBasicASCII);\n r.length = 0;\n return result;\n}\nexport class Piece {\n constructor(bufferIndex, start, end, lineFeedCnt, length) {\n this.bufferIndex = bufferIndex;\n this.start = start;\n this.end = end;\n this.lineFeedCnt = lineFeedCnt;\n this.length = length;\n }\n}\nexport class StringBuffer {\n constructor(buffer, lineStarts) {\n this.buffer = buffer;\n this.lineStarts = lineStarts;\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 {\n constructor(tree, BOM) {\n this._pieces = [];\n this._tree = tree;\n this._BOM = BOM;\n this._index = 0;\n if (tree.root !== SENTINEL) {\n tree.iterate(tree.root, node => {\n if (node !== SENTINEL) {\n this._pieces.push(node.piece);\n }\n return true;\n });\n }\n }\n read() {\n if (this._pieces.length === 0) {\n if (this._index === 0) {\n this._index++;\n return this._BOM;\n }\n else {\n return null;\n }\n }\n if (this._index > this._pieces.length - 1) {\n return null;\n }\n if (this._index === 0) {\n return this._BOM + this._tree.getPieceContent(this._pieces[this._index++]);\n }\n return this._tree.getPieceContent(this._pieces[this._index++]);\n }\n}\nclass PieceTreeSearchCache {\n constructor(limit) {\n this._limit = limit;\n this._cache = [];\n }\n get(offset) {\n for (let i = this._cache.length - 1; i >= 0; i--) {\n const nodePos = this._cache[i];\n if (nodePos.nodeStartOffset <= offset && nodePos.nodeStartOffset + nodePos.node.piece.length >= offset) {\n return nodePos;\n }\n }\n return null;\n }\n get2(lineNumber) {\n for (let i = this._cache.length - 1; i >= 0; i--) {\n const nodePos = this._cache[i];\n if (nodePos.nodeStartLineNumber && nodePos.nodeStartLineNumber < lineNumber && nodePos.nodeStartLineNumber + nodePos.node.piece.lineFeedCnt >= lineNumber) {\n return nodePos;\n }\n }\n return null;\n }\n set(nodePosition) {\n if (this._cache.length >= this._limit) {\n this._cache.shift();\n }\n this._cache.push(nodePosition);\n }\n validate(offset) {\n let hasInvalidVal = false;\n const tmp = this._cache;\n for (let i = 0; i < tmp.length; i++) {\n const nodePos = tmp[i];\n if (nodePos.node.parent === null || nodePos.nodeStartOffset >= offset) {\n tmp[i] = null;\n hasInvalidVal = true;\n continue;\n }\n }\n if (hasInvalidVal) {\n const newArr = [];\n for (const entry of tmp) {\n if (entry !== null) {\n newArr.push(entry);\n }\n }\n this._cache = newArr;\n }\n }\n}\nexport class PieceTreeBase {\n constructor(chunks, eol, eolNormalized) {\n this.create(chunks, eol, eolNormalized);\n }\n create(chunks, eol, eolNormalized) {\n this._buffers = [\n new StringBuffer('', [0])\n ];\n this._lastChangeBufferPos = { line: 0, column: 0 };\n this.root = SENTINEL;\n this._lineCnt = 1;\n this._length = 0;\n this._EOL = eol;\n this._EOLLength = eol.length;\n this._EOLNormalized = eolNormalized;\n let lastNode = null;\n for (let i = 0, len = chunks.length; i < len; i++) {\n if (chunks[i].buffer.length > 0) {\n if (!chunks[i].lineStarts) {\n chunks[i].lineStarts = createLineStartsFast(chunks[i].buffer);\n }\n const piece = new Piece(i + 1, { line: 0, column: 0 }, { line: chunks[i].lineStarts.length - 1, column: chunks[i].buffer.length - chunks[i].lineStarts[chunks[i].lineStarts.length - 1] }, chunks[i].lineStarts.length - 1, chunks[i].buffer.length);\n this._buffers.push(chunks[i]);\n lastNode = this.rbInsertRight(lastNode, piece);\n }\n }\n this._searchCache = new PieceTreeSearchCache(1);\n this._lastVisitedLine = { lineNumber: 0, value: '' };\n this.computeBufferMetadata();\n }\n normalizeEOL(eol) {\n const averageBufferSize = AverageBufferSize;\n const min = averageBufferSize - Math.floor(averageBufferSize / 3);\n const max = min * 2;\n let tempChunk = '';\n let tempChunkLen = 0;\n const chunks = [];\n this.iterate(this.root, node => {\n const str = this.getNodeContent(node);\n const len = str.length;\n if (tempChunkLen <= min || tempChunkLen + len < max) {\n tempChunk += str;\n tempChunkLen += len;\n return true;\n }\n // flush anyways\n const text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n chunks.push(new StringBuffer(text, createLineStartsFast(text)));\n tempChunk = str;\n tempChunkLen = len;\n return true;\n });\n if (tempChunkLen > 0) {\n const text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n chunks.push(new StringBuffer(text, createLineStartsFast(text)));\n }\n this.create(chunks, eol, true);\n }\n // #region Buffer API\n getEOL() {\n return this._EOL;\n }\n setEOL(newEOL) {\n this._EOL = newEOL;\n this._EOLLength = this._EOL.length;\n this.normalizeEOL(newEOL);\n }\n createSnapshot(BOM) {\n return new PieceTreeSnapshot(this, BOM);\n }\n getOffsetAt(lineNumber, column) {\n let leftLen = 0; // inorder\n let x = this.root;\n while (x !== SENTINEL) {\n if (x.left !== SENTINEL && x.lf_left + 1 >= lineNumber) {\n x = x.left;\n }\n else if (x.lf_left + x.piece.lineFeedCnt + 1 >= lineNumber) {\n leftLen += x.size_left;\n // lineNumber >= 2\n const accumualtedValInCurrentIndex = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n return leftLen += accumualtedValInCurrentIndex + column - 1;\n }\n else {\n lineNumber -= x.lf_left + x.piece.lineFeedCnt;\n leftLen += x.size_left + x.piece.length;\n x = x.right;\n }\n }\n return leftLen;\n }\n getPositionAt(offset) {\n offset = Math.floor(offset);\n offset = Math.max(0, offset);\n let x = this.root;\n let lfCnt = 0;\n const originalOffset = offset;\n while (x !== SENTINEL) {\n if (x.size_left !== 0 && x.size_left >= offset) {\n x = x.left;\n }\n else if (x.size_left + x.piece.length >= offset) {\n const out = this.getIndexOf(x, offset - x.size_left);\n lfCnt += x.lf_left + out.index;\n if (out.index === 0) {\n const lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n const column = originalOffset - lineStartOffset;\n return new Position(lfCnt + 1, column + 1);\n }\n return new Position(lfCnt + 1, out.remainder + 1);\n }\n else {\n offset -= x.size_left + x.piece.length;\n lfCnt += x.lf_left + x.piece.lineFeedCnt;\n if (x.right === SENTINEL) {\n // last node\n const lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n const column = originalOffset - offset - lineStartOffset;\n return new Position(lfCnt + 1, column + 1);\n }\n else {\n x = x.right;\n }\n }\n }\n return new Position(1, 1);\n }\n getValueInRange(range, eol) {\n if (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {\n return '';\n }\n const startPosition = this.nodeAt2(range.startLineNumber, range.startColumn);\n const endPosition = this.nodeAt2(range.endLineNumber, range.endColumn);\n const value = this.getValueInRange2(startPosition, endPosition);\n if (eol) {\n if (eol !== this._EOL || !this._EOLNormalized) {\n return value.replace(/\\r\\n|\\r|\\n/g, eol);\n }\n if (eol === this.getEOL() && this._EOLNormalized) {\n if (eol === '\\r\\n') {\n }\n return value;\n }\n return value.replace(/\\r\\n|\\r|\\n/g, eol);\n }\n return value;\n }\n getValueInRange2(startPosition, endPosition) {\n if (startPosition.node === endPosition.node) {\n const node = startPosition.node;\n const buffer = this._buffers[node.piece.bufferIndex].buffer;\n const startOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n return buffer.substring(startOffset + startPosition.remainder, startOffset + endPosition.remainder);\n }\n let x = startPosition.node;\n const buffer = this._buffers[x.piece.bufferIndex].buffer;\n const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n let ret = buffer.substring(startOffset + startPosition.remainder, startOffset + x.piece.length);\n x = x.next();\n while (x !== SENTINEL) {\n const buffer = this._buffers[x.piece.bufferIndex].buffer;\n const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n if (x === endPosition.node) {\n ret += buffer.substring(startOffset, startOffset + endPosition.remainder);\n break;\n }\n else {\n ret += buffer.substr(startOffset, x.piece.length);\n }\n x = x.next();\n }\n return ret;\n }\n getLinesContent() {\n const lines = [];\n let linesLength = 0;\n let currentLine = '';\n let danglingCR = false;\n this.iterate(this.root, node => {\n if (node === SENTINEL) {\n return true;\n }\n const piece = node.piece;\n let pieceLength = piece.length;\n if (pieceLength === 0) {\n return true;\n }\n const buffer = this._buffers[piece.bufferIndex].buffer;\n const lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n const pieceStartLine = piece.start.line;\n const pieceEndLine = piece.end.line;\n let pieceStartOffset = lineStarts[pieceStartLine] + piece.start.column;\n if (danglingCR) {\n if (buffer.charCodeAt(pieceStartOffset) === 10 /* CharCode.LineFeed */) {\n // pretend the \\n was in the previous piece..\n pieceStartOffset++;\n pieceLength--;\n }\n lines[linesLength++] = currentLine;\n currentLine = '';\n danglingCR = false;\n if (pieceLength === 0) {\n return true;\n }\n }\n if (pieceStartLine === pieceEndLine) {\n // this piece has no new lines\n if (!this._EOLNormalized && buffer.charCodeAt(pieceStartOffset + pieceLength - 1) === 13 /* CharCode.CarriageReturn */) {\n danglingCR = true;\n currentLine += buffer.substr(pieceStartOffset, pieceLength - 1);\n }\n else {\n currentLine += buffer.substr(pieceStartOffset, pieceLength);\n }\n return true;\n }\n // add the text before the first line start in this piece\n currentLine += (this._EOLNormalized\n ? buffer.substring(pieceStartOffset, Math.max(pieceStartOffset, lineStarts[pieceStartLine + 1] - this._EOLLength))\n : buffer.substring(pieceStartOffset, lineStarts[pieceStartLine + 1]).replace(/(\\r\\n|\\r|\\n)$/, ''));\n lines[linesLength++] = currentLine;\n for (let line = pieceStartLine + 1; line < pieceEndLine; line++) {\n currentLine = (this._EOLNormalized\n ? buffer.substring(lineStarts[line], lineStarts[line + 1] - this._EOLLength)\n : buffer.substring(lineStarts[line], lineStarts[line + 1]).replace(/(\\r\\n|\\r|\\n)$/, ''));\n lines[linesLength++] = currentLine;\n }\n if (!this._EOLNormalized && buffer.charCodeAt(lineStarts[pieceEndLine] + piece.end.column - 1) === 13 /* CharCode.CarriageReturn */) {\n danglingCR = true;\n if (piece.end.column === 0) {\n // The last line ended with a \\r, let's undo the push, it will be pushed by next iteration\n linesLength--;\n }\n else {\n currentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column - 1);\n }\n }\n else {\n currentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column);\n }\n return true;\n });\n if (danglingCR) {\n lines[linesLength++] = currentLine;\n currentLine = '';\n }\n lines[linesLength++] = currentLine;\n return lines;\n }\n getLength() {\n return this._length;\n }\n getLineCount() {\n return this._lineCnt;\n }\n getLineContent(lineNumber) {\n if (this._lastVisitedLine.lineNumber === lineNumber) {\n return this._lastVisitedLine.value;\n }\n this._lastVisitedLine.lineNumber = lineNumber;\n if (lineNumber === this._lineCnt) {\n this._lastVisitedLine.value = this.getLineRawContent(lineNumber);\n }\n else if (this._EOLNormalized) {\n this._lastVisitedLine.value = this.getLineRawContent(lineNumber, this._EOLLength);\n }\n else {\n this._lastVisitedLine.value = this.getLineRawContent(lineNumber).replace(/(\\r\\n|\\r|\\n)$/, '');\n }\n return this._lastVisitedLine.value;\n }\n _getCharCode(nodePos) {\n if (nodePos.remainder === nodePos.node.piece.length) {\n // the char we want to fetch is at the head of next node.\n const matchingNode = nodePos.node.next();\n if (!matchingNode) {\n return 0;\n }\n const buffer = this._buffers[matchingNode.piece.bufferIndex];\n const startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);\n return buffer.buffer.charCodeAt(startOffset);\n }\n else {\n const buffer = this._buffers[nodePos.node.piece.bufferIndex];\n const startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);\n const targetOffset = startOffset + nodePos.remainder;\n return buffer.buffer.charCodeAt(targetOffset);\n }\n }\n getLineCharCode(lineNumber, index) {\n const nodePos = this.nodeAt2(lineNumber, index + 1);\n return this._getCharCode(nodePos);\n }\n getLineLength(lineNumber) {\n if (lineNumber === this.getLineCount()) {\n const startOffset = this.getOffsetAt(lineNumber, 1);\n return this.getLength() - startOffset;\n }\n return this.getOffsetAt(lineNumber + 1, 1) - this.getOffsetAt(lineNumber, 1) - this._EOLLength;\n }\n findMatchesInNode(node, searcher, startLineNumber, startColumn, startCursor, endCursor, searchData, captureMatches, limitResultCount, resultLen, result) {\n const buffer = this._buffers[node.piece.bufferIndex];\n const startOffsetInBuffer = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n const start = this.offsetInBuffer(node.piece.bufferIndex, startCursor);\n const end = this.offsetInBuffer(node.piece.bufferIndex, endCursor);\n let m;\n // Reset regex to search from the beginning\n const ret = { line: 0, column: 0 };\n let searchText;\n let offsetInBuffer;\n if (searcher._wordSeparators) {\n searchText = buffer.buffer.substring(start, end);\n offsetInBuffer = (offset) => offset + start;\n searcher.reset(0);\n }\n else {\n searchText = buffer.buffer;\n offsetInBuffer = (offset) => offset;\n searcher.reset(start);\n }\n do {\n m = searcher.next(searchText);\n if (m) {\n if (offsetInBuffer(m.index) >= end) {\n return resultLen;\n }\n this.positionInBuffer(node, offsetInBuffer(m.index) - startOffsetInBuffer, ret);\n const lineFeedCnt = this.getLineFeedCnt(node.piece.bufferIndex, startCursor, ret);\n const retStartColumn = ret.line === startCursor.line ? ret.column - startCursor.column + startColumn : ret.column + 1;\n const retEndColumn = retStartColumn + m[0].length;\n result[resultLen++] = createFindMatch(new Range(startLineNumber + lineFeedCnt, retStartColumn, startLineNumber + lineFeedCnt, retEndColumn), m, captureMatches);\n if (offsetInBuffer(m.index) + m[0].length >= end) {\n return resultLen;\n }\n if (resultLen >= limitResultCount) {\n return resultLen;\n }\n }\n } while (m);\n return resultLen;\n }\n findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount) {\n const result = [];\n let resultLen = 0;\n const searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n let startPosition = this.nodeAt2(searchRange.startLineNumber, searchRange.startColumn);\n if (startPosition === null) {\n return [];\n }\n const endPosition = this.nodeAt2(searchRange.endLineNumber, searchRange.endColumn);\n if (endPosition === null) {\n return [];\n }\n let start = this.positionInBuffer(startPosition.node, startPosition.remainder);\n const end = this.positionInBuffer(endPosition.node, endPosition.remainder);\n if (startPosition.node === endPosition.node) {\n this.findMatchesInNode(startPosition.node, searcher, searchRange.startLineNumber, searchRange.startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n return result;\n }\n let startLineNumber = searchRange.startLineNumber;\n let currentNode = startPosition.node;\n while (currentNode !== endPosition.node) {\n const lineBreakCnt = this.getLineFeedCnt(currentNode.piece.bufferIndex, start, currentNode.piece.end);\n if (lineBreakCnt >= 1) {\n // last line break position\n const lineStarts = this._buffers[currentNode.piece.bufferIndex].lineStarts;\n const startOffsetInBuffer = this.offsetInBuffer(currentNode.piece.bufferIndex, currentNode.piece.start);\n const nextLineStartOffset = lineStarts[start.line + lineBreakCnt];\n const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n resultLen = this.findMatchesInNode(currentNode, searcher, startLineNumber, startColumn, start, this.positionInBuffer(currentNode, nextLineStartOffset - startOffsetInBuffer), searchData, captureMatches, limitResultCount, resultLen, result);\n if (resultLen >= limitResultCount) {\n return result;\n }\n startLineNumber += lineBreakCnt;\n }\n const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n // search for the remaining content\n if (startLineNumber === searchRange.endLineNumber) {\n const text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n resultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n return result;\n }\n resultLen = this._findMatchesInLine(searchData, searcher, this.getLineContent(startLineNumber).substr(startColumn), startLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n if (resultLen >= limitResultCount) {\n return result;\n }\n startLineNumber++;\n startPosition = this.nodeAt2(startLineNumber, 1);\n currentNode = startPosition.node;\n start = this.positionInBuffer(startPosition.node, startPosition.remainder);\n }\n if (startLineNumber === searchRange.endLineNumber) {\n const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n const text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n resultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n return result;\n }\n const startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n resultLen = this.findMatchesInNode(endPosition.node, searcher, startLineNumber, startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n return result;\n }\n _findMatchesInLine(searchData, searcher, text, lineNumber, deltaOffset, resultLen, result, captureMatches, limitResultCount) {\n const wordSeparators = searchData.wordSeparators;\n if (!captureMatches && searchData.simpleSearch) {\n const searchString = searchData.simpleSearch;\n const searchStringLen = searchString.length;\n const textLength = text.length;\n let lastMatchIndex = -searchStringLen;\n while ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {\n if (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {\n result[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);\n if (resultLen >= limitResultCount) {\n return resultLen;\n }\n }\n }\n return resultLen;\n }\n let m;\n // Reset regex to search from the beginning\n searcher.reset(0);\n do {\n m = searcher.next(text);\n if (m) {\n result[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);\n if (resultLen >= limitResultCount) {\n return resultLen;\n }\n }\n } while (m);\n return resultLen;\n }\n // #endregion\n // #region Piece Table\n insert(offset, value, eolNormalized = false) {\n this._EOLNormalized = this._EOLNormalized && eolNormalized;\n this._lastVisitedLine.lineNumber = 0;\n this._lastVisitedLine.value = '';\n if (this.root !== SENTINEL) {\n const { node, remainder, nodeStartOffset } = this.nodeAt(offset);\n const piece = node.piece;\n const bufferIndex = piece.bufferIndex;\n const insertPosInBuffer = this.positionInBuffer(node, remainder);\n if (node.piece.bufferIndex === 0 &&\n piece.end.line === this._lastChangeBufferPos.line &&\n piece.end.column === this._lastChangeBufferPos.column &&\n (nodeStartOffset + piece.length === offset) &&\n value.length < AverageBufferSize) {\n // changed buffer\n this.appendToNode(node, value);\n this.computeBufferMetadata();\n return;\n }\n if (nodeStartOffset === offset) {\n this.insertContentToNodeLeft(value, node);\n this._searchCache.validate(offset);\n }\n else if (nodeStartOffset + node.piece.length > offset) {\n // we are inserting into the middle of a node.\n const nodesToDel = [];\n let newRightPiece = new Piece(piece.bufferIndex, insertPosInBuffer, piece.end, this.getLineFeedCnt(piece.bufferIndex, insertPosInBuffer, piece.end), this.offsetInBuffer(bufferIndex, piece.end) - this.offsetInBuffer(bufferIndex, insertPosInBuffer));\n if (this.shouldCheckCRLF() && this.endWithCR(value)) {\n const headOfRight = this.nodeCharCodeAt(node, remainder);\n if (headOfRight === 10 /** \\n */) {\n const newStart = { line: newRightPiece.start.line + 1, column: 0 };\n newRightPiece = new Piece(newRightPiece.bufferIndex, newStart, newRightPiece.end, this.getLineFeedCnt(newRightPiece.bufferIndex, newStart, newRightPiece.end), newRightPiece.length - 1);\n value += '\\n';\n }\n }\n // reuse node for content before insertion point.\n if (this.shouldCheckCRLF() && this.startWithLF(value)) {\n const tailOfLeft = this.nodeCharCodeAt(node, remainder - 1);\n if (tailOfLeft === 13 /** \\r */) {\n const previousPos = this.positionInBuffer(node, remainder - 1);\n this.deleteNodeTail(node, previousPos);\n value = '\\r' + value;\n if (node.piece.length === 0) {\n nodesToDel.push(node);\n }\n }\n else {\n this.deleteNodeTail(node, insertPosInBuffer);\n }\n }\n else {\n this.deleteNodeTail(node, insertPosInBuffer);\n }\n const newPieces = this.createNewPieces(value);\n if (newRightPiece.length > 0) {\n this.rbInsertRight(node, newRightPiece);\n }\n let tmpNode = node;\n for (let k = 0; k < newPieces.length; k++) {\n tmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n }\n this.deleteNodes(nodesToDel);\n }\n else {\n this.insertContentToNodeRight(value, node);\n }\n }\n else {\n // insert new node\n const pieces = this.createNewPieces(value);\n let node = this.rbInsertLeft(null, pieces[0]);\n for (let k = 1; k < pieces.length; k++) {\n node = this.rbInsertRight(node, pieces[k]);\n }\n }\n // todo, this is too brutal. Total line feed count should be updated the same way as lf_left.\n this.computeBufferMetadata();\n }\n delete(offset, cnt) {\n this._lastVisitedLine.lineNumber = 0;\n this._lastVisitedLine.value = '';\n if (cnt <= 0 || this.root === SENTINEL) {\n return;\n }\n const startPosition = this.nodeAt(offset);\n const endPosition = this.nodeAt(offset + cnt);\n const startNode = startPosition.node;\n const endNode = endPosition.node;\n if (startNode === endNode) {\n const startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n const endSplitPosInBuffer = this.positionInBuffer(startNode, endPosition.remainder);\n if (startPosition.nodeStartOffset === offset) {\n if (cnt === startNode.piece.length) { // delete node\n const next = startNode.next();\n rbDelete(this, startNode);\n this.validateCRLFWithPrevNode(next);\n this.computeBufferMetadata();\n return;\n }\n this.deleteNodeHead(startNode, endSplitPosInBuffer);\n this._searchCache.validate(offset);\n this.validateCRLFWithPrevNode(startNode);\n this.computeBufferMetadata();\n return;\n }\n if (startPosition.nodeStartOffset + startNode.piece.length === offset + cnt) {\n this.deleteNodeTail(startNode, startSplitPosInBuffer);\n this.validateCRLFWithNextNode(startNode);\n this.computeBufferMetadata();\n return;\n }\n // delete content in the middle, this node will be splitted to nodes\n this.shrinkNode(startNode, startSplitPosInBuffer, endSplitPosInBuffer);\n this.computeBufferMetadata();\n return;\n }\n const nodesToDel = [];\n const startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n this.deleteNodeTail(startNode, startSplitPosInBuffer);\n this._searchCache.validate(offset);\n if (startNode.piece.length === 0) {\n nodesToDel.push(startNode);\n }\n // update last touched node\n const endSplitPosInBuffer = this.positionInBuffer(endNode, endPosition.remainder);\n this.deleteNodeHead(endNode, endSplitPosInBuffer);\n if (endNode.piece.length === 0) {\n nodesToDel.push(endNode);\n }\n // delete nodes in between\n const secondNode = startNode.next();\n for (let node = secondNode; node !== SENTINEL && node !== endNode; node = node.next()) {\n nodesToDel.push(node);\n }\n const prev = startNode.piece.length === 0 ? startNode.prev() : startNode;\n this.deleteNodes(nodesToDel);\n this.validateCRLFWithNextNode(prev);\n this.computeBufferMetadata();\n }\n insertContentToNodeLeft(value, node) {\n // we are inserting content to the beginning of node\n const nodesToDel = [];\n if (this.shouldCheckCRLF() && this.endWithCR(value) && this.startWithLF(node)) {\n // move `\\n` to new node.\n const piece = node.piece;\n const newStart = { line: piece.start.line + 1, column: 0 };\n const nPiece = new Piece(piece.bufferIndex, newStart, piece.end, this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end), piece.length - 1);\n node.piece = nPiece;\n value += '\\n';\n updateTreeMetadata(this, node, -1, -1);\n if (node.piece.length === 0) {\n nodesToDel.push(node);\n }\n }\n const newPieces = this.createNewPieces(value);\n let newNode = this.rbInsertLeft(node, newPieces[newPieces.length - 1]);\n for (let k = newPieces.length - 2; k >= 0; k--) {\n newNode = this.rbInsertLeft(newNode, newPieces[k]);\n }\n this.validateCRLFWithPrevNode(newNode);\n this.deleteNodes(nodesToDel);\n }\n insertContentToNodeRight(value, node) {\n // we are inserting to the right of this node.\n if (this.adjustCarriageReturnFromNext(value, node)) {\n // move \\n to the new node.\n value += '\\n';\n }\n const newPieces = this.createNewPieces(value);\n const newNode = this.rbInsertRight(node, newPieces[0]);\n let tmpNode = newNode;\n for (let k = 1; k < newPieces.length; k++) {\n tmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n }\n this.validateCRLFWithPrevNode(newNode);\n }\n positionInBuffer(node, remainder, ret) {\n const piece = node.piece;\n const bufferIndex = node.piece.bufferIndex;\n const lineStarts = this._buffers[bufferIndex].lineStarts;\n const startOffset = lineStarts[piece.start.line] + piece.start.column;\n const offset = startOffset + remainder;\n // binary search offset between startOffset and endOffset\n let low = piece.start.line;\n let high = piece.end.line;\n let mid = 0;\n let midStop = 0;\n let midStart = 0;\n while (low <= high) {\n mid = low + ((high - low) / 2) | 0;\n midStart = lineStarts[mid];\n if (mid === high) {\n break;\n }\n midStop = lineStarts[mid + 1];\n if (offset < midStart) {\n high = mid - 1;\n }\n else if (offset >= midStop) {\n low = mid + 1;\n }\n else {\n break;\n }\n }\n if (ret) {\n ret.line = mid;\n ret.column = offset - midStart;\n return null;\n }\n return {\n line: mid,\n column: offset - midStart\n };\n }\n getLineFeedCnt(bufferIndex, start, end) {\n // 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 // 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 if (end.column === 0) {\n return end.line - start.line;\n }\n const lineStarts = this._buffers[bufferIndex].lineStarts;\n if (end.line === lineStarts.length - 1) { // it means, there is no \\n after end, otherwise, there will be one more lineStart.\n return end.line - start.line;\n }\n const nextLineStartOffset = lineStarts[end.line + 1];\n const endOffset = lineStarts[end.line] + end.column;\n if (nextLineStartOffset > endOffset + 1) { // there are more than 1 character after end, which means it can't be \\n\n return end.line - start.line;\n }\n // endOffset + 1 === nextLineStartOffset\n // character at endOffset is \\n, so we check the character before first\n // if character at endOffset is \\r, end.column is 0 and we can't get here.\n const previousCharOffset = endOffset - 1; // end.column > 0 so it's okay.\n const buffer = this._buffers[bufferIndex].buffer;\n if (buffer.charCodeAt(previousCharOffset) === 13) {\n return end.line - start.line + 1;\n }\n else {\n return end.line - start.line;\n }\n }\n offsetInBuffer(bufferIndex, cursor) {\n const lineStarts = this._buffers[bufferIndex].lineStarts;\n return lineStarts[cursor.line] + cursor.column;\n }\n deleteNodes(nodes) {\n for (let i = 0; i < nodes.length; i++) {\n rbDelete(this, nodes[i]);\n }\n }\n createNewPieces(text) {\n if (text.length > AverageBufferSize) {\n // the content is large, operations like substring, charCode becomes slow\n // so here we split it into smaller chunks, just like what we did for CR/LF normalization\n const newPieces = [];\n while (text.length > AverageBufferSize) {\n const lastChar = text.charCodeAt(AverageBufferSize - 1);\n let splitText;\n if (lastChar === 13 /* CharCode.CarriageReturn */ || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {\n // last character is \\r or a high surrogate => keep it back\n splitText = text.substring(0, AverageBufferSize - 1);\n text = text.substring(AverageBufferSize - 1);\n }\n else {\n splitText = text.substring(0, AverageBufferSize);\n text = text.substring(AverageBufferSize);\n }\n const lineStarts = createLineStartsFast(splitText);\n newPieces.push(new Piece(this._buffers.length, /* buffer index */ { line: 0, column: 0 }, { line: lineStarts.length - 1, column: splitText.length - lineStarts[lineStarts.length - 1] }, lineStarts.length - 1, splitText.length));\n this._buffers.push(new StringBuffer(splitText, lineStarts));\n }\n const lineStarts = createLineStartsFast(text);\n newPieces.push(new Piece(this._buffers.length, /* buffer index */ { line: 0, column: 0 }, { line: lineStarts.length - 1, column: text.length - lineStarts[lineStarts.length - 1] }, lineStarts.length - 1, text.length));\n this._buffers.push(new StringBuffer(text, lineStarts));\n return newPieces;\n }\n let startOffset = this._buffers[0].buffer.length;\n const lineStarts = createLineStartsFast(text, false);\n let start = this._lastChangeBufferPos;\n if (this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 1] === startOffset\n && startOffset !== 0\n && this.startWithLF(text)\n && this.endWithCR(this._buffers[0].buffer) // todo, we can check this._lastChangeBufferPos's column as it's the last one\n ) {\n this._lastChangeBufferPos = { line: this._lastChangeBufferPos.line, column: this._lastChangeBufferPos.column + 1 };\n start = this._lastChangeBufferPos;\n for (let i = 0; i < lineStarts.length; i++) {\n lineStarts[i] += startOffset + 1;\n }\n this._buffers[0].lineStarts = this._buffers[0].lineStarts.concat(lineStarts.slice(1));\n this._buffers[0].buffer += '_' + text;\n startOffset += 1;\n }\n else {\n if (startOffset !== 0) {\n for (let i = 0; i < lineStarts.length; i++) {\n lineStarts[i] += startOffset;\n }\n }\n this._buffers[0].lineStarts = this._buffers[0].lineStarts.concat(lineStarts.slice(1));\n this._buffers[0].buffer += text;\n }\n const endOffset = this._buffers[0].buffer.length;\n const endIndex = this._buffers[0].lineStarts.length - 1;\n const endColumn = endOffset - this._buffers[0].lineStarts[endIndex];\n const endPos = { line: endIndex, column: endColumn };\n const newPiece = new Piece(0, /** todo@peng */ start, endPos, this.getLineFeedCnt(0, start, endPos), endOffset - startOffset);\n this._lastChangeBufferPos = endPos;\n return [newPiece];\n }\n getLineRawContent(lineNumber, endOffset = 0) {\n let x = this.root;\n let ret = '';\n const cache = this._searchCache.get2(lineNumber);\n if (cache) {\n x = cache.node;\n const prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber - 1);\n const buffer = this._buffers[x.piece.bufferIndex].buffer;\n const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n if (cache.nodeStartLineNumber + x.piece.lineFeedCnt === lineNumber) {\n ret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n }\n else {\n const accumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber);\n return buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n }\n }\n else {\n let nodeStartOffset = 0;\n const originalLineNumber = lineNumber;\n while (x !== SENTINEL) {\n if (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n x = x.left;\n }\n else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n const prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n const accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n const buffer = this._buffers[x.piece.bufferIndex].buffer;\n const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n nodeStartOffset += x.size_left;\n this._searchCache.set({\n node: x,\n nodeStartOffset,\n nodeStartLineNumber: originalLineNumber - (lineNumber - 1 - x.lf_left)\n });\n return buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n }\n else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n const prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n const buffer = this._buffers[x.piece.bufferIndex].buffer;\n const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n ret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n break;\n }\n else {\n lineNumber -= x.lf_left + x.piece.lineFeedCnt;\n nodeStartOffset += x.size_left + x.piece.length;\n x = x.right;\n }\n }\n }\n // search in order, to find the node contains end column\n x = x.next();\n while (x !== SENTINEL) {\n const buffer = this._buffers[x.piece.bufferIndex].buffer;\n if (x.piece.lineFeedCnt > 0) {\n const accumulatedValue = this.getAccumulatedValue(x, 0);\n const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n ret += buffer.substring(startOffset, startOffset + accumulatedValue - endOffset);\n return ret;\n }\n else {\n const startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n ret += buffer.substr(startOffset, x.piece.length);\n }\n x = x.next();\n }\n return ret;\n }\n computeBufferMetadata() {\n let x = this.root;\n let lfCnt = 1;\n let len = 0;\n while (x !== SENTINEL) {\n lfCnt += x.lf_left + x.piece.lineFeedCnt;\n len += x.size_left + x.piece.length;\n x = x.right;\n }\n this._lineCnt = lfCnt;\n this._length = len;\n this._searchCache.validate(this._length);\n }\n // #region node operations\n getIndexOf(node, accumulatedValue) {\n const piece = node.piece;\n const pos = this.positionInBuffer(node, accumulatedValue);\n const lineCnt = pos.line - piece.start.line;\n if (this.offsetInBuffer(piece.bufferIndex, piece.end) - this.offsetInBuffer(piece.bufferIndex, piece.start) === accumulatedValue) {\n // we are checking the end of this node, so a CRLF check is necessary.\n const realLineCnt = this.getLineFeedCnt(node.piece.bufferIndex, piece.start, pos);\n if (realLineCnt !== lineCnt) {\n // aha yes, CRLF\n return { index: realLineCnt, remainder: 0 };\n }\n }\n return { index: lineCnt, remainder: pos.column };\n }\n getAccumulatedValue(node, index) {\n if (index < 0) {\n return 0;\n }\n const piece = node.piece;\n const lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n const expectedLineStartIndex = piece.start.line + index + 1;\n if (expectedLineStartIndex > piece.end.line) {\n return lineStarts[piece.end.line] + piece.end.column - lineStarts[piece.start.line] - piece.start.column;\n }\n else {\n return lineStarts[expectedLineStartIndex] - lineStarts[piece.start.line] - piece.start.column;\n }\n }\n deleteNodeTail(node, pos) {\n const piece = node.piece;\n const originalLFCnt = piece.lineFeedCnt;\n const originalEndOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n const newEnd = pos;\n const newEndOffset = this.offsetInBuffer(piece.bufferIndex, newEnd);\n const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n const lf_delta = newLineFeedCnt - originalLFCnt;\n const size_delta = newEndOffset - originalEndOffset;\n const newLength = piece.length + size_delta;\n node.piece = new Piece(piece.bufferIndex, piece.start, newEnd, newLineFeedCnt, newLength);\n updateTreeMetadata(this, node, size_delta, lf_delta);\n }\n deleteNodeHead(node, pos) {\n const piece = node.piece;\n const originalLFCnt = piece.lineFeedCnt;\n const originalStartOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n const newStart = pos;\n const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n const newStartOffset = this.offsetInBuffer(piece.bufferIndex, newStart);\n const lf_delta = newLineFeedCnt - originalLFCnt;\n const size_delta = originalStartOffset - newStartOffset;\n const newLength = piece.length + size_delta;\n node.piece = new Piece(piece.bufferIndex, newStart, piece.end, newLineFeedCnt, newLength);\n updateTreeMetadata(this, node, size_delta, lf_delta);\n }\n shrinkNode(node, start, end) {\n const piece = node.piece;\n const originalStartPos = piece.start;\n const originalEndPos = piece.end;\n // old piece, originalStartPos, start\n const oldLength = piece.length;\n const oldLFCnt = piece.lineFeedCnt;\n const newEnd = start;\n const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n const newLength = this.offsetInBuffer(piece.bufferIndex, start) - this.offsetInBuffer(piece.bufferIndex, originalStartPos);\n node.piece = new Piece(piece.bufferIndex, piece.start, newEnd, newLineFeedCnt, newLength);\n updateTreeMetadata(this, node, newLength - oldLength, newLineFeedCnt - oldLFCnt);\n // new right piece, end, originalEndPos\n const newPiece = new Piece(piece.bufferIndex, end, originalEndPos, this.getLineFeedCnt(piece.bufferIndex, end, originalEndPos), this.offsetInBuffer(piece.bufferIndex, originalEndPos) - this.offsetInBuffer(piece.bufferIndex, end));\n const newNode = this.rbInsertRight(node, newPiece);\n this.validateCRLFWithPrevNode(newNode);\n }\n appendToNode(node, value) {\n if (this.adjustCarriageReturnFromNext(value, node)) {\n value += '\\n';\n }\n const hitCRLF = this.shouldCheckCRLF() && this.startWithLF(value) && this.endWithCR(node);\n const startOffset = this._buffers[0].buffer.length;\n this._buffers[0].buffer += value;\n const lineStarts = createLineStartsFast(value, false);\n for (let i = 0; i < lineStarts.length; i++) {\n lineStarts[i] += startOffset;\n }\n if (hitCRLF) {\n const prevStartOffset = this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 2];\n this._buffers[0].lineStarts.pop();\n // _lastChangeBufferPos is already wrong\n this._lastChangeBufferPos = { line: this._lastChangeBufferPos.line - 1, column: startOffset - prevStartOffset };\n }\n this._buffers[0].lineStarts = this._buffers[0].lineStarts.concat(lineStarts.slice(1));\n const endIndex = this._buffers[0].lineStarts.length - 1;\n const endColumn = this._buffers[0].buffer.length - this._buffers[0].lineStarts[endIndex];\n const newEnd = { line: endIndex, column: endColumn };\n const newLength = node.piece.length + value.length;\n const oldLineFeedCnt = node.piece.lineFeedCnt;\n const newLineFeedCnt = this.getLineFeedCnt(0, node.piece.start, newEnd);\n const lf_delta = newLineFeedCnt - oldLineFeedCnt;\n node.piece = new Piece(node.piece.bufferIndex, node.piece.start, newEnd, newLineFeedCnt, newLength);\n this._lastChangeBufferPos = newEnd;\n updateTreeMetadata(this, node, value.length, lf_delta);\n }\n nodeAt(offset) {\n let x = this.root;\n const cache = this._searchCache.get(offset);\n if (cache) {\n return {\n node: cache.node,\n nodeStartOffset: cache.nodeStartOffset,\n remainder: offset - cache.nodeStartOffset\n };\n }\n let nodeStartOffset = 0;\n while (x !== SENTINEL) {\n if (x.size_left > offset) {\n x = x.left;\n }\n else if (x.size_left + x.piece.length >= offset) {\n nodeStartOffset += x.size_left;\n const ret = {\n node: x,\n remainder: offset - x.size_left,\n nodeStartOffset\n };\n this._searchCache.set(ret);\n return ret;\n }\n else {\n offset -= x.size_left + x.piece.length;\n nodeStartOffset += x.size_left + x.piece.length;\n x = x.right;\n }\n }\n return null;\n }\n nodeAt2(lineNumber, column) {\n let x = this.root;\n let nodeStartOffset = 0;\n while (x !== SENTINEL) {\n if (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n x = x.left;\n }\n else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n const prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n const accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n nodeStartOffset += x.size_left;\n return {\n node: x,\n remainder: Math.min(prevAccumualtedValue + column - 1, accumulatedValue),\n nodeStartOffset\n };\n }\n else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n const prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n if (prevAccumualtedValue + column - 1 <= x.piece.length) {\n return {\n node: x,\n remainder: prevAccumualtedValue + column - 1,\n nodeStartOffset\n };\n }\n else {\n column -= x.piece.length - prevAccumualtedValue;\n break;\n }\n }\n else {\n lineNumber -= x.lf_left + x.piece.lineFeedCnt;\n nodeStartOffset += x.size_left + x.piece.length;\n x = x.right;\n }\n }\n // search in order, to find the node contains position.column\n x = x.next();\n while (x !== SENTINEL) {\n if (x.piece.lineFeedCnt > 0) {\n const accumulatedValue = this.getAccumulatedValue(x, 0);\n const nodeStartOffset = this.offsetOfNode(x);\n return {\n node: x,\n remainder: Math.min(column - 1, accumulatedValue),\n nodeStartOffset\n };\n }\n else {\n if (x.piece.length >= column - 1) {\n const nodeStartOffset = this.offsetOfNode(x);\n return {\n node: x,\n remainder: column - 1,\n nodeStartOffset\n };\n }\n else {\n column -= x.piece.length;\n }\n }\n x = x.next();\n }\n return null;\n }\n nodeCharCodeAt(node, offset) {\n if (node.piece.lineFeedCnt < 1) {\n return -1;\n }\n const buffer = this._buffers[node.piece.bufferIndex];\n const newOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start) + offset;\n return buffer.buffer.charCodeAt(newOffset);\n }\n offsetOfNode(node) {\n if (!node) {\n return 0;\n }\n let pos = node.size_left;\n while (node !== this.root) {\n if (node.parent.right === node) {\n pos += node.parent.size_left + node.parent.piece.length;\n }\n node = node.parent;\n }\n return pos;\n }\n // #endregion\n // #region CRLF\n shouldCheckCRLF() {\n return !(this._EOLNormalized && this._EOL === '\\n');\n }\n startWithLF(val) {\n if (typeof val === 'string') {\n return val.charCodeAt(0) === 10;\n }\n if (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n return false;\n }\n const piece = val.piece;\n const lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n const line = piece.start.line;\n const startOffset = lineStarts[line] + piece.start.column;\n if (line === lineStarts.length - 1) {\n // last line, so there is no line feed at the end of this line\n return false;\n }\n const nextLineOffset = lineStarts[line + 1];\n if (nextLineOffset > startOffset + 1) {\n return false;\n }\n return this._buffers[piece.bufferIndex].buffer.charCodeAt(startOffset) === 10;\n }\n endWithCR(val) {\n if (typeof val === 'string') {\n return val.charCodeAt(val.length - 1) === 13;\n }\n if (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n return false;\n }\n return this.nodeCharCodeAt(val, val.piece.length - 1) === 13;\n }\n validateCRLFWithPrevNode(nextNode) {\n if (this.shouldCheckCRLF() && this.startWithLF(nextNode)) {\n const node = nextNode.prev();\n if (this.endWithCR(node)) {\n this.fixCRLF(node, nextNode);\n }\n }\n }\n validateCRLFWithNextNode(node) {\n if (this.shouldCheckCRLF() && this.endWithCR(node)) {\n const nextNode = node.next();\n if (this.startWithLF(nextNode)) {\n this.fixCRLF(node, nextNode);\n }\n }\n }\n fixCRLF(prev, next) {\n const nodesToDel = [];\n // update node\n const lineStarts = this._buffers[prev.piece.bufferIndex].lineStarts;\n let newEnd;\n if (prev.piece.end.column === 0) {\n // it means, last line ends with \\r, not \\r\\n\n newEnd = { line: prev.piece.end.line - 1, column: lineStarts[prev.piece.end.line] - lineStarts[prev.piece.end.line - 1] - 1 };\n }\n else {\n // \\r\\n\n newEnd = { line: prev.piece.end.line, column: prev.piece.end.column - 1 };\n }\n const prevNewLength = prev.piece.length - 1;\n const prevNewLFCnt = prev.piece.lineFeedCnt - 1;\n prev.piece = new Piece(prev.piece.bufferIndex, prev.piece.start, newEnd, prevNewLFCnt, prevNewLength);\n updateTreeMetadata(this, prev, -1, -1);\n if (prev.piece.length === 0) {\n nodesToDel.push(prev);\n }\n // update nextNode\n const newStart = { line: next.piece.start.line + 1, column: 0 };\n const newLength = next.piece.length - 1;\n const newLineFeedCnt = this.getLineFeedCnt(next.piece.bufferIndex, newStart, next.piece.end);\n next.piece = new Piece(next.piece.bufferIndex, newStart, next.piece.end, newLineFeedCnt, newLength);\n updateTreeMetadata(this, next, -1, -1);\n if (next.piece.length === 0) {\n nodesToDel.push(next);\n }\n // create new piece which contains \\r\\n\n const pieces = this.createNewPieces('\\r\\n');\n this.rbInsertRight(prev, pieces[0]);\n // delete empty nodes\n for (let i = 0; i < nodesToDel.length; i++) {\n rbDelete(this, nodesToDel[i]);\n }\n }\n adjustCarriageReturnFromNext(value, node) {\n if (this.shouldCheckCRLF() && this.endWithCR(value)) {\n const nextNode = node.next();\n if (this.startWithLF(nextNode)) {\n // move `\\n` forward\n value += '\\n';\n if (nextNode.piece.length === 1) {\n rbDelete(this, nextNode);\n }\n else {\n const piece = nextNode.piece;\n const newStart = { line: piece.start.line + 1, column: 0 };\n const newLength = piece.length - 1;\n const newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n nextNode.piece = new Piece(piece.bufferIndex, newStart, piece.end, newLineFeedCnt, newLength);\n updateTreeMetadata(this, nextNode, -1, -1);\n }\n return true;\n }\n }\n return false;\n }\n // #endregion\n // #endregion\n // #region Tree operations\n iterate(node, callback) {\n if (node === SENTINEL) {\n return callback(SENTINEL);\n }\n const leftRet = this.iterate(node.left, callback);\n if (!leftRet) {\n return leftRet;\n }\n return callback(node) && this.iterate(node.right, callback);\n }\n getNodeContent(node) {\n if (node === SENTINEL) {\n return '';\n }\n const buffer = this._buffers[node.piece.bufferIndex];\n const piece = node.piece;\n const startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n const endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n const currentContent = buffer.buffer.substring(startOffset, endOffset);\n return currentContent;\n }\n getPieceContent(piece) {\n const buffer = this._buffers[piece.bufferIndex];\n const startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n const endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n const currentContent = buffer.buffer.substring(startOffset, endOffset);\n return currentContent;\n }\n /**\n * node node\n * / \\ / \\\n * a b <---- a b\n * /\n * z\n */\n rbInsertRight(node, p) {\n const z = new TreeNode(p, 1 /* NodeColor.Red */);\n z.left = SENTINEL;\n z.right = SENTINEL;\n z.parent = SENTINEL;\n z.size_left = 0;\n z.lf_left = 0;\n const x = this.root;\n if (x === SENTINEL) {\n this.root = z;\n z.color = 0 /* NodeColor.Black */;\n }\n else if (node.right === SENTINEL) {\n node.right = z;\n z.parent = node;\n }\n else {\n const nextNode = leftest(node.right);\n nextNode.left = z;\n z.parent = nextNode;\n }\n fixInsert(this, z);\n return z;\n }\n /**\n * node node\n * / \\ / \\\n * a b ----> a b\n * \\\n * z\n */\n rbInsertLeft(node, p) {\n const z = new TreeNode(p, 1 /* NodeColor.Red */);\n z.left = SENTINEL;\n z.right = SENTINEL;\n z.parent = SENTINEL;\n z.size_left = 0;\n z.lf_left = 0;\n if (this.root === SENTINEL) {\n this.root = z;\n z.color = 0 /* NodeColor.Black */;\n }\n else if (node.left === SENTINEL) {\n node.left = z;\n z.parent = node;\n }\n else {\n const prevNode = righttest(node.left); // a\n prevNode.right = z;\n z.parent = prevNode;\n }\n fixInsert(this, z);\n return z;\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 *--------------------------------------------------------------------------------------------*/\nimport { Emitter } from '../../../../base/common/event.js';\nimport * as strings from '../../../../base/common/strings.js';\nimport { Range } from '../../core/range.js';\nimport { ApplyEditsResult } from '../../model.js';\nimport { PieceTreeBase } from './pieceTreeBase.js';\nimport { countEOL } from '../../core/eolCounter.js';\nimport { TextChange } from '../../core/textChange.js';\nimport { Disposable } from '../../../../base/common/lifecycle.js';\nexport class PieceTreeTextBuffer extends Disposable {\n constructor(chunks, BOM, eol, containsRTL, containsUnusualLineTerminators, isBasicASCII, eolNormalized) {\n super();\n this._onDidChangeContent = this._register(new Emitter());\n this._BOM = BOM;\n this._mightContainNonBasicASCII = !isBasicASCII;\n this._mightContainRTL = containsRTL;\n this._mightContainUnusualLineTerminators = containsUnusualLineTerminators;\n this._pieceTree = new PieceTreeBase(chunks, eol, eolNormalized);\n }\n mightContainRTL() {\n return this._mightContainRTL;\n }\n mightContainUnusualLineTerminators() {\n return this._mightContainUnusualLineTerminators;\n }\n resetMightContainUnusualLineTerminators() {\n this._mightContainUnusualLineTerminators = false;\n }\n mightContainNonBasicASCII() {\n return this._mightContainNonBasicASCII;\n }\n getBOM() {\n return this._BOM;\n }\n getEOL() {\n return this._pieceTree.getEOL();\n }\n createSnapshot(preserveBOM) {\n return this._pieceTree.createSnapshot(preserveBOM ? this._BOM : '');\n }\n getOffsetAt(lineNumber, column) {\n return this._pieceTree.getOffsetAt(lineNumber, column);\n }\n getPositionAt(offset) {\n return this._pieceTree.getPositionAt(offset);\n }\n getRangeAt(start, length) {\n const end = start + length;\n const startPosition = this.getPositionAt(start);\n const endPosition = this.getPositionAt(end);\n return new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column);\n }\n getValueInRange(range, eol = 0 /* EndOfLinePreference.TextDefined */) {\n if (range.isEmpty()) {\n return '';\n }\n const lineEnding = this._getEndOfLine(eol);\n return this._pieceTree.getValueInRange(range, lineEnding);\n }\n getValueLengthInRange(range, eol = 0 /* EndOfLinePreference.TextDefined */) {\n if (range.isEmpty()) {\n return 0;\n }\n if (range.startLineNumber === range.endLineNumber) {\n return (range.endColumn - range.startColumn);\n }\n const startOffset = this.getOffsetAt(range.startLineNumber, range.startColumn);\n const endOffset = this.getOffsetAt(range.endLineNumber, range.endColumn);\n return endOffset - startOffset;\n }\n getCharacterCountInRange(range, eol = 0 /* EndOfLinePreference.TextDefined */) {\n if (this._mightContainNonBasicASCII) {\n // we must count by iterating\n let result = 0;\n const fromLineNumber = range.startLineNumber;\n const toLineNumber = range.endLineNumber;\n for (let lineNumber = fromLineNumber; lineNumber <= toLineNumber; lineNumber++) {\n const lineContent = this.getLineContent(lineNumber);\n const fromOffset = (lineNumber === fromLineNumber ? range.startColumn - 1 : 0);\n const toOffset = (lineNumber === toLineNumber ? range.endColumn - 1 : lineContent.length);\n for (let offset = fromOffset; offset < toOffset; offset++) {\n if (strings.isHighSurrogate(lineContent.charCodeAt(offset))) {\n result = result + 1;\n offset = offset + 1;\n }\n else {\n result = result + 1;\n }\n }\n }\n result += this._getEndOfLine(eol).length * (toLineNumber - fromLineNumber);\n return result;\n }\n return this.getValueLengthInRange(range, eol);\n }\n getLength() {\n return this._pieceTree.getLength();\n }\n getLineCount() {\n return this._pieceTree.getLineCount();\n }\n getLinesContent() {\n return this._pieceTree.getLinesContent();\n }\n getLineContent(lineNumber) {\n return this._pieceTree.getLineContent(lineNumber);\n }\n getLineCharCode(lineNumber, index) {\n return this._pieceTree.getLineCharCode(lineNumber, index);\n }\n getLineLength(lineNumber) {\n return this._pieceTree.getLineLength(lineNumber);\n }\n getLineFirstNonWhitespaceColumn(lineNumber) {\n const result = strings.firstNonWhitespaceIndex(this.getLineContent(lineNumber));\n if (result === -1) {\n return 0;\n }\n return result + 1;\n }\n getLineLastNonWhitespaceColumn(lineNumber) {\n const result = strings.lastNonWhitespaceIndex(this.getLineContent(lineNumber));\n if (result === -1) {\n return 0;\n }\n return result + 2;\n }\n _getEndOfLine(eol) {\n switch (eol) {\n case 1 /* EndOfLinePreference.LF */:\n return '\\n';\n case 2 /* EndOfLinePreference.CRLF */:\n return '\\r\\n';\n case 0 /* EndOfLinePreference.TextDefined */:\n return this.getEOL();\n default:\n throw new Error('Unknown EOL preference');\n }\n }\n setEOL(newEOL) {\n this._pieceTree.setEOL(newEOL);\n }\n applyEdits(rawOperations, recordTrimAutoWhitespace, computeUndoEdits) {\n let mightContainRTL = this._mightContainRTL;\n let mightContainUnusualLineTerminators = this._mightContainUnusualLineTerminators;\n let mightContainNonBasicASCII = this._mightContainNonBasicASCII;\n let canReduceOperations = true;\n let operations = [];\n for (let i = 0; i < rawOperations.length; i++) {\n const op = rawOperations[i];\n if (canReduceOperations && op._isTracked) {\n canReduceOperations = false;\n }\n const validatedRange = op.range;\n if (op.text) {\n let textMightContainNonBasicASCII = true;\n if (!mightContainNonBasicASCII) {\n textMightContainNonBasicASCII = !strings.isBasicASCII(op.text);\n mightContainNonBasicASCII = textMightContainNonBasicASCII;\n }\n if (!mightContainRTL && textMightContainNonBasicASCII) {\n // check if the new inserted text contains RTL\n mightContainRTL = strings.containsRTL(op.text);\n }\n if (!mightContainUnusualLineTerminators && textMightContainNonBasicASCII) {\n // check if the new inserted text contains unusual line terminators\n mightContainUnusualLineTerminators = strings.containsUnusualLineTerminators(op.text);\n }\n }\n let validText = '';\n let eolCount = 0;\n let firstLineLength = 0;\n let lastLineLength = 0;\n if (op.text) {\n let strEOL;\n [eolCount, firstLineLength, lastLineLength, strEOL] = countEOL(op.text);\n const bufferEOL = this.getEOL();\n const expectedStrEOL = (bufferEOL === '\\r\\n' ? 2 /* StringEOL.CRLF */ : 1 /* StringEOL.LF */);\n if (strEOL === 0 /* StringEOL.Unknown */ || strEOL === expectedStrEOL) {\n validText = op.text;\n }\n else {\n validText = op.text.replace(/\\r\\n|\\r|\\n/g, bufferEOL);\n }\n }\n operations[i] = {\n sortIndex: i,\n identifier: op.identifier || null,\n range: validatedRange,\n rangeOffset: this.getOffsetAt(validatedRange.startLineNumber, validatedRange.startColumn),\n rangeLength: this.getValueLengthInRange(validatedRange),\n text: validText,\n eolCount: eolCount,\n firstLineLength: firstLineLength,\n lastLineLength: lastLineLength,\n forceMoveMarkers: Boolean(op.forceMoveMarkers),\n isAutoWhitespaceEdit: op.isAutoWhitespaceEdit || false\n };\n }\n // Sort operations ascending\n operations.sort(PieceTreeTextBuffer._sortOpsAscending);\n let hasTouchingRanges = false;\n for (let i = 0, count = operations.length - 1; i < count; i++) {\n const rangeEnd = operations[i].range.getEndPosition();\n const nextRangeStart = operations[i + 1].range.getStartPosition();\n if (nextRangeStart.isBeforeOrEqual(rangeEnd)) {\n if (nextRangeStart.isBefore(rangeEnd)) {\n // overlapping ranges\n throw new Error('Overlapping ranges are not allowed!');\n }\n hasTouchingRanges = true;\n }\n }\n if (canReduceOperations) {\n operations = this._reduceOperations(operations);\n }\n // Delta encode operations\n const reverseRanges = (computeUndoEdits || recordTrimAutoWhitespace ? PieceTreeTextBuffer._getInverseEditRanges(operations) : []);\n const newTrimAutoWhitespaceCandidates = [];\n if (recordTrimAutoWhitespace) {\n for (let i = 0; i < operations.length; i++) {\n const op = operations[i];\n const reverseRange = reverseRanges[i];\n if (op.isAutoWhitespaceEdit && op.range.isEmpty()) {\n // Record already the future line numbers that might be auto whitespace removal candidates on next edit\n for (let lineNumber = reverseRange.startLineNumber; lineNumber <= reverseRange.endLineNumber; lineNumber++) {\n let currentLineContent = '';\n if (lineNumber === reverseRange.startLineNumber) {\n currentLineContent = this.getLineContent(op.range.startLineNumber);\n if (strings.firstNonWhitespaceIndex(currentLineContent) !== -1) {\n continue;\n }\n }\n newTrimAutoWhitespaceCandidates.push({ lineNumber: lineNumber, oldContent: currentLineContent });\n }\n }\n }\n }\n let reverseOperations = null;\n if (computeUndoEdits) {\n let reverseRangeDeltaOffset = 0;\n reverseOperations = [];\n for (let i = 0; i < operations.length; i++) {\n const op = operations[i];\n const reverseRange = reverseRanges[i];\n const bufferText = this.getValueInRange(op.range);\n const reverseRangeOffset = op.rangeOffset + reverseRangeDeltaOffset;\n reverseRangeDeltaOffset += (op.text.length - bufferText.length);\n reverseOperations[i] = {\n sortIndex: op.sortIndex,\n identifier: op.identifier,\n range: reverseRange,\n text: bufferText,\n textChange: new TextChange(op.rangeOffset, bufferText, reverseRangeOffset, op.text)\n };\n }\n // Can only sort reverse operations when the order is not significant\n if (!hasTouchingRanges) {\n reverseOperations.sort((a, b) => a.sortIndex - b.sortIndex);\n }\n }\n this._mightContainRTL = mightContainRTL;\n this._mightContainUnusualLineTerminators = mightContainUnusualLineTerminators;\n this._mightContainNonBasicASCII = mightContainNonBasicASCII;\n const contentChanges = this._doApplyEdits(operations);\n let trimAutoWhitespaceLineNumbers = null;\n if (recordTrimAutoWhitespace && newTrimAutoWhitespaceCandidates.length > 0) {\n // sort line numbers auto whitespace removal candidates for next edit descending\n newTrimAutoWhitespaceCandidates.sort((a, b) => b.lineNumber - a.lineNumber);\n trimAutoWhitespaceLineNumbers = [];\n for (let i = 0, len = newTrimAutoWhitespaceCandidates.length; i < len; i++) {\n const lineNumber = newTrimAutoWhitespaceCandidates[i].lineNumber;\n if (i > 0 && newTrimAutoWhitespaceCandidates[i - 1].lineNumber === lineNumber) {\n // Do not have the same line number twice\n continue;\n }\n const prevContent = newTrimAutoWhitespaceCandidates[i].oldContent;\n const lineContent = this.getLineContent(lineNumber);\n if (lineContent.length === 0 || lineContent === prevContent || strings.firstNonWhitespaceIndex(lineContent) !== -1) {\n continue;\n }\n trimAutoWhitespaceLineNumbers.push(lineNumber);\n }\n }\n this._onDidChangeContent.fire();\n return new ApplyEditsResult(reverseOperations, contentChanges, trimAutoWhitespaceLineNumbers);\n }\n /**\n * Transform operations such that they represent the same logic edit,\n * but that they also do not cause OOM crashes.\n */\n _reduceOperations(operations) {\n if (operations.length < 1000) {\n // We know from empirical testing that a thousand edits work fine regardless of their shape.\n return operations;\n }\n // At one point, due to how events are emitted and how each operation is handled,\n // some operations can trigger a high amount of temporary string allocations,\n // that will immediately get edited again.\n // e.g. a formatter inserting ridiculous ammounts of \\n on a model with a single line\n // Therefore, the strategy is to collapse all the operations into a huge single edit operation\n return [this._toSingleEditOperation(operations)];\n }\n _toSingleEditOperation(operations) {\n let forceMoveMarkers = false;\n const firstEditRange = operations[0].range;\n const lastEditRange = operations[operations.length - 1].range;\n const entireEditRange = new Range(firstEditRange.startLineNumber, firstEditRange.startColumn, lastEditRange.endLineNumber, lastEditRange.endColumn);\n let lastEndLineNumber = firstEditRange.startLineNumber;\n let lastEndColumn = firstEditRange.startColumn;\n const result = [];\n for (let i = 0, len = operations.length; i < len; i++) {\n const operation = operations[i];\n const range = operation.range;\n forceMoveMarkers = forceMoveMarkers || operation.forceMoveMarkers;\n // (1) -- Push old text\n result.push(this.getValueInRange(new Range(lastEndLineNumber, lastEndColumn, range.startLineNumber, range.startColumn)));\n // (2) -- Push new text\n if (operation.text.length > 0) {\n result.push(operation.text);\n }\n lastEndLineNumber = range.endLineNumber;\n lastEndColumn = range.endColumn;\n }\n const text = result.join('');\n const [eolCount, firstLineLength, lastLineLength] = countEOL(text);\n return {\n sortIndex: 0,\n identifier: operations[0].identifier,\n range: entireEditRange,\n rangeOffset: this.getOffsetAt(entireEditRange.startLineNumber, entireEditRange.startColumn),\n rangeLength: this.getValueLengthInRange(entireEditRange, 0 /* EndOfLinePreference.TextDefined */),\n text: text,\n eolCount: eolCount,\n firstLineLength: firstLineLength,\n lastLineLength: lastLineLength,\n forceMoveMarkers: forceMoveMarkers,\n isAutoWhitespaceEdit: false\n };\n }\n _doApplyEdits(operations) {\n operations.sort(PieceTreeTextBuffer._sortOpsDescending);\n const contentChanges = [];\n // operations are from bottom to top\n for (let i = 0; i < operations.length; i++) {\n const op = operations[i];\n const startLineNumber = op.range.startLineNumber;\n const startColumn = op.range.startColumn;\n const endLineNumber = op.range.endLineNumber;\n const endColumn = op.range.endColumn;\n if (startLineNumber === endLineNumber && startColumn === endColumn && op.text.length === 0) {\n // no-op\n continue;\n }\n if (op.text) {\n // replacement\n this._pieceTree.delete(op.rangeOffset, op.rangeLength);\n this._pieceTree.insert(op.rangeOffset, op.text, true);\n }\n else {\n // deletion\n this._pieceTree.delete(op.rangeOffset, op.rangeLength);\n }\n const contentChangeRange = new Range(startLineNumber, startColumn, endLineNumber, endColumn);\n contentChanges.push({\n range: contentChangeRange,\n rangeLength: op.rangeLength,\n text: op.text,\n rangeOffset: op.rangeOffset,\n forceMoveMarkers: op.forceMoveMarkers\n });\n }\n return contentChanges;\n }\n findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount) {\n return this._pieceTree.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);\n }\n /**\n * Assumes `operations` are validated and sorted ascending\n */\n static _getInverseEditRanges(operations) {\n const result = [];\n let prevOpEndLineNumber = 0;\n let prevOpEndColumn = 0;\n let prevOp = null;\n for (let i = 0, len = operations.length; i < len; i++) {\n const op = operations[i];\n let startLineNumber;\n let startColumn;\n if (prevOp) {\n if (prevOp.range.endLineNumber === op.range.startLineNumber) {\n startLineNumber = prevOpEndLineNumber;\n startColumn = prevOpEndColumn + (op.range.startColumn - prevOp.range.endColumn);\n }\n else {\n startLineNumber = prevOpEndLineNumber + (op.range.startLineNumber - prevOp.range.endLineNumber);\n startColumn = op.range.startColumn;\n }\n }\n else {\n startLineNumber = op.range.startLineNumber;\n startColumn = op.range.startColumn;\n }\n let resultRange;\n if (op.text.length > 0) {\n // the operation inserts something\n const lineCount = op.eolCount + 1;\n if (lineCount === 1) {\n // single line insert\n resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn + op.firstLineLength);\n }\n else {\n // multi line insert\n resultRange = new Range(startLineNumber, startColumn, startLineNumber + lineCount - 1, op.lastLineLength + 1);\n }\n }\n else {\n // There is nothing to insert\n resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn);\n }\n prevOpEndLineNumber = resultRange.endLineNumber;\n prevOpEndColumn = resultRange.endColumn;\n result.push(resultRange);\n prevOp = op;\n }\n return result;\n }\n static _sortOpsAscending(a, b) {\n const r = Range.compareRangesUsingEnds(a.range, b.range);\n if (r === 0) {\n return a.sortIndex - b.sortIndex;\n }\n return r;\n }\n static _sortOpsDescending(a, b) {\n const r = Range.compareRangesUsingEnds(a.range, b.range);\n if (r === 0) {\n return b.sortIndex - a.sortIndex;\n }\n return -r;\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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../../base/common/strings.js';\nimport { StringBuffer, createLineStarts, createLineStartsFast } from './pieceTreeBase.js';\nimport { PieceTreeTextBuffer } from './pieceTreeTextBuffer.js';\nexport class PieceTreeTextBufferFactory {\n constructor(_chunks, _bom, _cr, _lf, _crlf, _containsRTL, _containsUnusualLineTerminators, _isBasicASCII, _normalizeEOL) {\n this._chunks = _chunks;\n this._bom = _bom;\n this._cr = _cr;\n this._lf = _lf;\n this._crlf = _crlf;\n this._containsRTL = _containsRTL;\n this._containsUnusualLineTerminators = _containsUnusualLineTerminators;\n this._isBasicASCII = _isBasicASCII;\n this._normalizeEOL = _normalizeEOL;\n }\n _getEOL(defaultEOL) {\n const totalEOLCount = this._cr + this._lf + this._crlf;\n const totalCRCount = this._cr + this._crlf;\n if (totalEOLCount === 0) {\n // This is an empty file or a file with precisely one line\n return (defaultEOL === 1 /* DefaultEndOfLine.LF */ ? '\\n' : '\\r\\n');\n }\n if (totalCRCount > totalEOLCount / 2) {\n // More than half of the file contains \\r\\n ending lines\n return '\\r\\n';\n }\n // At least one line more ends in \\n\n return '\\n';\n }\n create(defaultEOL) {\n const eol = this._getEOL(defaultEOL);\n const chunks = this._chunks;\n if (this._normalizeEOL &&\n ((eol === '\\r\\n' && (this._cr > 0 || this._lf > 0))\n || (eol === '\\n' && (this._cr > 0 || this._crlf > 0)))) {\n // Normalize pieces\n for (let i = 0, len = chunks.length; i < len; i++) {\n const str = chunks[i].buffer.replace(/\\r\\n|\\r|\\n/g, eol);\n const newLineStart = createLineStartsFast(str);\n chunks[i] = new StringBuffer(str, newLineStart);\n }\n }\n const textBuffer = new PieceTreeTextBuffer(chunks, this._bom, eol, this._containsRTL, this._containsUnusualLineTerminators, this._isBasicASCII, this._normalizeEOL);\n return { textBuffer: textBuffer, disposable: textBuffer };\n }\n}\nexport class PieceTreeTextBufferBuilder {\n constructor() {\n this.chunks = [];\n this.BOM = '';\n this._hasPreviousChar = false;\n this._previousChar = 0;\n this._tmpLineStarts = [];\n this.cr = 0;\n this.lf = 0;\n this.crlf = 0;\n this.containsRTL = false;\n this.containsUnusualLineTerminators = false;\n this.isBasicASCII = true;\n }\n acceptChunk(chunk) {\n if (chunk.length === 0) {\n return;\n }\n if (this.chunks.length === 0) {\n if (strings.startsWithUTF8BOM(chunk)) {\n this.BOM = strings.UTF8_BOM_CHARACTER;\n chunk = chunk.substr(1);\n }\n }\n const lastChar = chunk.charCodeAt(chunk.length - 1);\n if (lastChar === 13 /* CharCode.CarriageReturn */ || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {\n // last character is \\r or a high surrogate => keep it back\n this._acceptChunk1(chunk.substr(0, chunk.length - 1), false);\n this._hasPreviousChar = true;\n this._previousChar = lastChar;\n }\n else {\n this._acceptChunk1(chunk, false);\n this._hasPreviousChar = false;\n this._previousChar = lastChar;\n }\n }\n _acceptChunk1(chunk, allowEmptyStrings) {\n if (!allowEmptyStrings && chunk.length === 0) {\n // Nothing to do\n return;\n }\n if (this._hasPreviousChar) {\n this._acceptChunk2(String.fromCharCode(this._previousChar) + chunk);\n }\n else {\n this._acceptChunk2(chunk);\n }\n }\n _acceptChunk2(chunk) {\n const lineStarts = createLineStarts(this._tmpLineStarts, chunk);\n this.chunks.push(new StringBuffer(chunk, lineStarts.lineStarts));\n this.cr += lineStarts.cr;\n this.lf += lineStarts.lf;\n this.crlf += lineStarts.crlf;\n if (this.isBasicASCII) {\n this.isBasicASCII = lineStarts.isBasicASCII;\n }\n if (!this.isBasicASCII && !this.containsRTL) {\n // No need to check if it is basic ASCII\n this.containsRTL = strings.containsRTL(chunk);\n }\n if (!this.isBasicASCII && !this.containsUnusualLineTerminators) {\n // No need to check if it is basic ASCII\n this.containsUnusualLineTerminators = strings.containsUnusualLineTerminators(chunk);\n }\n }\n finish(normalizeEOL = true) {\n this._finish();\n return new PieceTreeTextBufferFactory(this.chunks, this.BOM, this.cr, this.lf, this.crlf, this.containsRTL, this.containsUnusualLineTerminators, this.isBasicASCII, normalizeEOL);\n }\n _finish() {\n if (this.chunks.length === 0) {\n this._acceptChunk1('', true);\n }\n if (this._hasPreviousChar) {\n this._hasPreviousChar = false;\n // recreate last chunk\n const lastChunk = this.chunks[this.chunks.length - 1];\n lastChunk.buffer += String.fromCharCode(this._previousChar);\n const newLineStarts = createLineStartsFast(lastChunk.buffer);\n lastChunk.lineStarts = newLineStarts;\n if (this._previousChar === 13 /* CharCode.CarriageReturn */) {\n this.cr++;\n }\n }\n }\n}\n","/**\n * Represents contiguous tokens over a contiguous range of lines.\n */\nexport class ContiguousMultilineTokens {\n constructor(startLineNumber, tokens) {\n this._startLineNumber = startLineNumber;\n this._tokens = tokens;\n }\n /**\n * (Inclusive) start line number for these tokens.\n */\n get startLineNumber() {\n return this._startLineNumber;\n }\n /**\n * (Inclusive) end line number for these tokens.\n */\n get endLineNumber() {\n return this._startLineNumber + this._tokens.length - 1;\n }\n /**\n * @see {@link _tokens}\n */\n getLineTokens(lineNumber) {\n return this._tokens[lineNumber - this._startLineNumber];\n }\n appendLineTokens(lineTokens) {\n this._tokens.push(lineTokens);\n }\n}\n","import { ContiguousMultilineTokens } from './contiguousMultilineTokens.js';\nexport class ContiguousMultilineTokensBuilder {\n constructor() {\n this._tokens = [];\n }\n add(lineNumber, lineTokens) {\n if (this._tokens.length > 0) {\n const last = this._tokens[this._tokens.length - 1];\n if (last.endLineNumber + 1 === lineNumber) {\n // append\n last.appendLineTokens(lineTokens);\n return;\n }\n }\n this._tokens.push(new ContiguousMultilineTokens(lineNumber, [lineTokens]));\n }\n finalize() {\n return this._tokens;\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 *--------------------------------------------------------------------------------------------*/\nimport * as arrays from '../../../base/common/arrays.js';\nimport { onUnexpectedError } from '../../../base/common/errors.js';\nimport { LineTokens } from '../tokens/lineTokens.js';\nimport { TokenizationRegistry } from '../languages.js';\nimport { nullTokenizeEncoded } from '../languages/nullTokenize.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { StopWatch } from '../../../base/common/stopwatch.js';\nimport { countEOL } from '../core/eolCounter.js';\nimport { ContiguousMultilineTokensBuilder } from '../tokens/contiguousMultilineTokensBuilder.js';\nimport { runWhenIdle } from '../../../base/common/async.js';\nimport { setTimeout0 } from '../../../base/common/platform.js';\n/**\n * An array that avoids being sparse by always\n * filling up unused indices with a default value.\n */\nclass ContiguousGrowingArray {\n constructor(_default) {\n this._default = _default;\n this._store = [];\n }\n get(index) {\n if (index < this._store.length) {\n return this._store[index];\n }\n return this._default;\n }\n set(index, value) {\n while (index >= this._store.length) {\n this._store[this._store.length] = this._default;\n }\n this._store[index] = value;\n }\n delete(deleteIndex, deleteCount) {\n if (deleteCount === 0 || deleteIndex >= this._store.length) {\n return;\n }\n this._store.splice(deleteIndex, deleteCount);\n }\n insert(insertIndex, insertCount) {\n if (insertCount === 0 || insertIndex >= this._store.length) {\n return;\n }\n const arr = [];\n for (let i = 0; i < insertCount; i++) {\n arr[i] = this._default;\n }\n this._store = arrays.arrayInsert(this._store, insertIndex, arr);\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 constructor(tokenizationSupport, initialState) {\n this.tokenizationSupport = tokenizationSupport;\n this.initialState = initialState;\n /**\n * `lineBeginState[i]` contains the begin state used to tokenize line number `i + 1`.\n */\n this._lineBeginState = new ContiguousGrowingArray(null);\n /**\n * `lineNeedsTokenization[i]` describes if line number `i + 1` needs to be tokenized.\n */\n this._lineNeedsTokenization = new ContiguousGrowingArray(true);\n this._firstLineNeedsTokenization = 0;\n this._lineBeginState.set(0, this.initialState);\n }\n get invalidLineStartIndex() {\n return this._firstLineNeedsTokenization;\n }\n markMustBeTokenized(lineIndex) {\n this._lineNeedsTokenization.set(lineIndex, true);\n this._firstLineNeedsTokenization = Math.min(this._firstLineNeedsTokenization, lineIndex);\n }\n getBeginState(lineIndex) {\n return this._lineBeginState.get(lineIndex);\n }\n setEndState(linesLength, lineIndex, endState) {\n this._lineNeedsTokenization.set(lineIndex, false);\n this._firstLineNeedsTokenization = lineIndex + 1;\n // Check if this was the last line\n if (lineIndex === linesLength - 1) {\n return;\n }\n // Check if the end state has changed\n const previousEndState = this._lineBeginState.get(lineIndex + 1);\n if (previousEndState === null || !endState.equals(previousEndState)) {\n this._lineBeginState.set(lineIndex + 1, endState);\n this.markMustBeTokenized(lineIndex + 1);\n return;\n }\n // Perhaps we can skip tokenizing some lines...\n let i = lineIndex + 1;\n while (i < linesLength) {\n if (this._lineNeedsTokenization.get(i)) {\n break;\n }\n i++;\n }\n this._firstLineNeedsTokenization = i;\n }\n //#region Editing\n applyEdits(range, eolCount) {\n this.markMustBeTokenized(range.startLineNumber - 1);\n this._lineBeginState.delete(range.startLineNumber, range.endLineNumber - range.startLineNumber);\n this._lineNeedsTokenization.delete(range.startLineNumber, range.endLineNumber - range.startLineNumber);\n this._lineBeginState.insert(range.startLineNumber, eolCount);\n this._lineNeedsTokenization.insert(range.startLineNumber, eolCount);\n }\n}\nexport class TextModelTokenization extends Disposable {\n constructor(_textModel, _tokenizationPart, _languageIdCodec) {\n super();\n this._textModel = _textModel;\n this._tokenizationPart = _tokenizationPart;\n this._languageIdCodec = _languageIdCodec;\n this._isScheduled = false;\n this._isDisposed = false;\n this._tokenizationStateStore = null;\n this._register(TokenizationRegistry.onDidChange((e) => {\n const languageId = this._textModel.getLanguageId();\n if (e.changedLanguages.indexOf(languageId) === -1) {\n return;\n }\n this._resetTokenizationState();\n this._tokenizationPart.clearTokens();\n }));\n this._resetTokenizationState();\n }\n dispose() {\n this._isDisposed = true;\n super.dispose();\n }\n //#region TextModel events\n handleDidChangeContent(e) {\n if (e.isFlush) {\n this._resetTokenizationState();\n return;\n }\n if (this._tokenizationStateStore) {\n for (let i = 0, len = e.changes.length; i < len; i++) {\n const change = e.changes[i];\n const [eolCount] = countEOL(change.text);\n this._tokenizationStateStore.applyEdits(change.range, eolCount);\n }\n }\n this._beginBackgroundTokenization();\n }\n handleDidChangeAttached() {\n this._beginBackgroundTokenization();\n }\n handleDidChangeLanguage(e) {\n this._resetTokenizationState();\n this._tokenizationPart.clearTokens();\n }\n //#endregion\n _resetTokenizationState() {\n const [tokenizationSupport, initialState] = initializeTokenization(this._textModel, this._tokenizationPart);\n if (tokenizationSupport && initialState) {\n this._tokenizationStateStore = new TokenizationStateStore(tokenizationSupport, initialState);\n }\n else {\n this._tokenizationStateStore = null;\n }\n this._beginBackgroundTokenization();\n }\n _beginBackgroundTokenization() {\n if (this._isScheduled || !this._textModel.isAttachedToEditor() || !this._hasLinesToTokenize()) {\n return;\n }\n this._isScheduled = true;\n runWhenIdle((deadline) => {\n this._isScheduled = false;\n this._backgroundTokenizeWithDeadline(deadline);\n });\n }\n /**\n * Tokenize until the deadline occurs, but try to yield every 1-2ms.\n */\n _backgroundTokenizeWithDeadline(deadline) {\n // Read the time remaining from the `deadline` immediately because it is unclear\n // if the `deadline` object will be valid after execution leaves this function.\n const endTime = Date.now() + deadline.timeRemaining();\n const execute = () => {\n if (this._isDisposed || !this._textModel.isAttachedToEditor() || !this._hasLinesToTokenize()) {\n // disposed in the meantime or detached or finished\n return;\n }\n this._backgroundTokenizeForAtLeast1ms();\n if (Date.now() < endTime) {\n // There is still time before reaching the deadline, so yield to the browser and then\n // continue execution\n setTimeout0(execute);\n }\n else {\n // The deadline has been reached, so schedule a new idle callback if necessary\n this._beginBackgroundTokenization();\n }\n };\n execute();\n }\n /**\n * Tokenize for at least 1ms.\n */\n _backgroundTokenizeForAtLeast1ms() {\n const lineCount = this._textModel.getLineCount();\n const builder = new ContiguousMultilineTokensBuilder();\n const sw = StopWatch.create(false);\n do {\n if (sw.elapsed() > 1) {\n // the comparison is intentionally > 1 and not >= 1 to ensure that\n // a full millisecond has elapsed, given how microseconds are rounded\n // to milliseconds\n break;\n }\n const tokenizedLineNumber = this._tokenizeOneInvalidLine(builder);\n if (tokenizedLineNumber >= lineCount) {\n break;\n }\n } while (this._hasLinesToTokenize());\n this._tokenizationPart.setTokens(builder.finalize(), this._isTokenizationComplete());\n }\n tokenizeViewport(startLineNumber, endLineNumber) {\n const builder = new ContiguousMultilineTokensBuilder();\n this._tokenizeViewport(builder, startLineNumber, endLineNumber);\n this._tokenizationPart.setTokens(builder.finalize(), this._isTokenizationComplete());\n }\n reset() {\n this._resetTokenizationState();\n this._tokenizationPart.clearTokens();\n }\n forceTokenization(lineNumber) {\n const builder = new ContiguousMultilineTokensBuilder();\n this._updateTokensUntilLine(builder, lineNumber);\n this._tokenizationPart.setTokens(builder.finalize(), this._isTokenizationComplete());\n }\n getTokenTypeIfInsertingCharacter(position, character) {\n if (!this._tokenizationStateStore) {\n return 0 /* StandardTokenType.Other */;\n }\n this.forceTokenization(position.lineNumber);\n const lineStartState = this._tokenizationStateStore.getBeginState(position.lineNumber - 1);\n if (!lineStartState) {\n return 0 /* StandardTokenType.Other */;\n }\n const languageId = this._textModel.getLanguageId();\n const lineContent = this._textModel.getLineContent(position.lineNumber);\n // Create the text as if `character` was inserted\n const text = (lineContent.substring(0, position.column - 1)\n + character\n + lineContent.substring(position.column - 1));\n const r = safeTokenize(this._languageIdCodec, languageId, this._tokenizationStateStore.tokenizationSupport, text, true, lineStartState);\n const lineTokens = new LineTokens(r.tokens, text, this._languageIdCodec);\n if (lineTokens.getCount() === 0) {\n return 0 /* StandardTokenType.Other */;\n }\n const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n return lineTokens.getStandardTokenType(tokenIndex);\n }\n tokenizeLineWithEdit(position, length, newText) {\n const lineNumber = position.lineNumber;\n const column = position.column;\n if (!this._tokenizationStateStore) {\n return null;\n }\n this.forceTokenization(lineNumber);\n const lineStartState = this._tokenizationStateStore.getBeginState(lineNumber - 1);\n if (!lineStartState) {\n return null;\n }\n const curLineContent = this._textModel.getLineContent(lineNumber);\n const newLineContent = curLineContent.substring(0, column - 1)\n + newText + curLineContent.substring(column - 1 + length);\n const languageId = this._textModel.getLanguageIdAtPosition(lineNumber, 0);\n const result = safeTokenize(this._languageIdCodec, languageId, this._tokenizationStateStore.tokenizationSupport, newLineContent, true, lineStartState);\n const lineTokens = new LineTokens(result.tokens, newLineContent, this._languageIdCodec);\n return lineTokens;\n }\n isCheapToTokenize(lineNumber) {\n if (!this._tokenizationStateStore) {\n return true;\n }\n const firstInvalidLineNumber = this._tokenizationStateStore.invalidLineStartIndex + 1;\n if (lineNumber > firstInvalidLineNumber) {\n return false;\n }\n if (lineNumber < firstInvalidLineNumber) {\n return true;\n }\n if (this._textModel.getLineLength(lineNumber) < 2048 /* Constants.CHEAP_TOKENIZATION_LENGTH_LIMIT */) {\n return true;\n }\n return false;\n }\n _hasLinesToTokenize() {\n if (!this._tokenizationStateStore) {\n return false;\n }\n return (this._tokenizationStateStore.invalidLineStartIndex < this._textModel.getLineCount());\n }\n _isTokenizationComplete() {\n if (!this._tokenizationStateStore) {\n return false;\n }\n return (this._tokenizationStateStore.invalidLineStartIndex >= this._textModel.getLineCount());\n }\n _tokenizeOneInvalidLine(builder) {\n if (!this._tokenizationStateStore || !this._hasLinesToTokenize()) {\n return this._textModel.getLineCount() + 1;\n }\n const lineNumber = this._tokenizationStateStore.invalidLineStartIndex + 1;\n this._updateTokensUntilLine(builder, lineNumber);\n return lineNumber;\n }\n _updateTokensUntilLine(builder, lineNumber) {\n if (!this._tokenizationStateStore) {\n return;\n }\n const languageId = this._textModel.getLanguageId();\n const linesLength = this._textModel.getLineCount();\n const endLineIndex = lineNumber - 1;\n // Validate all states up to and including endLineIndex\n for (let lineIndex = this._tokenizationStateStore.invalidLineStartIndex; lineIndex <= endLineIndex; lineIndex++) {\n const text = this._textModel.getLineContent(lineIndex + 1);\n const lineStartState = this._tokenizationStateStore.getBeginState(lineIndex);\n const r = safeTokenize(this._languageIdCodec, languageId, this._tokenizationStateStore.tokenizationSupport, text, true, lineStartState);\n builder.add(lineIndex + 1, r.tokens);\n this._tokenizationStateStore.setEndState(linesLength, lineIndex, r.endState);\n lineIndex = this._tokenizationStateStore.invalidLineStartIndex - 1; // -1 because the outer loop increments it\n }\n }\n _tokenizeViewport(builder, startLineNumber, endLineNumber) {\n if (!this._tokenizationStateStore) {\n // nothing to do\n return;\n }\n if (endLineNumber <= this._tokenizationStateStore.invalidLineStartIndex) {\n // nothing to do\n return;\n }\n if (startLineNumber <= this._tokenizationStateStore.invalidLineStartIndex) {\n // tokenization has reached the viewport start...\n this._updateTokensUntilLine(builder, endLineNumber);\n return;\n }\n let nonWhitespaceColumn = this._textModel.getLineFirstNonWhitespaceColumn(startLineNumber);\n const fakeLines = [];\n let initialState = null;\n for (let i = startLineNumber - 1; nonWhitespaceColumn > 1 && i >= 1; i--) {\n const newNonWhitespaceIndex = this._textModel.getLineFirstNonWhitespaceColumn(i);\n if (newNonWhitespaceIndex === 0) {\n continue;\n }\n if (newNonWhitespaceIndex < nonWhitespaceColumn) {\n fakeLines.push(this._textModel.getLineContent(i));\n nonWhitespaceColumn = newNonWhitespaceIndex;\n initialState = this._tokenizationStateStore.getBeginState(i - 1);\n if (initialState) {\n break;\n }\n }\n }\n if (!initialState) {\n initialState = this._tokenizationStateStore.initialState;\n }\n const languageId = this._textModel.getLanguageId();\n let state = initialState;\n for (let i = fakeLines.length - 1; i >= 0; i--) {\n const r = safeTokenize(this._languageIdCodec, languageId, this._tokenizationStateStore.tokenizationSupport, fakeLines[i], false, state);\n state = r.endState;\n }\n for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {\n const text = this._textModel.getLineContent(lineNumber);\n const r = safeTokenize(this._languageIdCodec, languageId, this._tokenizationStateStore.tokenizationSupport, text, true, state);\n builder.add(lineNumber, r.tokens);\n this._tokenizationStateStore.markMustBeTokenized(lineNumber - 1);\n state = r.endState;\n }\n }\n}\nfunction initializeTokenization(textModel, tokenizationPart) {\n if (textModel.isTooLargeForTokenization()) {\n return [null, null];\n }\n const tokenizationSupport = TokenizationRegistry.get(tokenizationPart.getLanguageId());\n if (!tokenizationSupport) {\n return [null, null];\n }\n let initialState;\n try {\n initialState = tokenizationSupport.getInitialState();\n }\n catch (e) {\n onUnexpectedError(e);\n return [null, null];\n }\n return [tokenizationSupport, initialState];\n}\nfunction safeTokenize(languageIdCodec, languageId, tokenizationSupport, text, hasEOL, state) {\n let r = null;\n if (tokenizationSupport) {\n try {\n r = tokenizationSupport.tokenizeEncoded(text, hasEOL, state.clone());\n }\n catch (e) {\n onUnexpectedError(e);\n }\n }\n if (!r) {\n r = nullTokenizeEncoded(languageIdCodec.encodeLanguageId(languageId), state);\n }\n LineTokens.convertToEndOffset(r.tokens, text.length);\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { LineTokens } from './lineTokens.js';\nexport const EMPTY_LINE_TOKENS = (new Uint32Array(0)).buffer;\nexport class ContiguousTokensEditing {\n static deleteBeginning(lineTokens, toChIndex) {\n if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {\n return lineTokens;\n }\n return ContiguousTokensEditing.delete(lineTokens, 0, toChIndex);\n }\n static deleteEnding(lineTokens, fromChIndex) {\n if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {\n return lineTokens;\n }\n const tokens = toUint32Array(lineTokens);\n const lineTextLength = tokens[tokens.length - 2];\n return ContiguousTokensEditing.delete(lineTokens, fromChIndex, lineTextLength);\n }\n static delete(lineTokens, fromChIndex, toChIndex) {\n if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS || fromChIndex === toChIndex) {\n return lineTokens;\n }\n const tokens = toUint32Array(lineTokens);\n const tokensCount = (tokens.length >>> 1);\n // special case: deleting everything\n if (fromChIndex === 0 && tokens[tokens.length - 2] === toChIndex) {\n return EMPTY_LINE_TOKENS;\n }\n const fromTokenIndex = LineTokens.findIndexInTokensArray(tokens, fromChIndex);\n const fromTokenStartOffset = (fromTokenIndex > 0 ? tokens[(fromTokenIndex - 1) << 1] : 0);\n const fromTokenEndOffset = tokens[fromTokenIndex << 1];\n if (toChIndex < fromTokenEndOffset) {\n // the delete range is inside a single token\n const delta = (toChIndex - fromChIndex);\n for (let i = fromTokenIndex; i < tokensCount; i++) {\n tokens[i << 1] -= delta;\n }\n return lineTokens;\n }\n let dest;\n let lastEnd;\n if (fromTokenStartOffset !== fromChIndex) {\n tokens[fromTokenIndex << 1] = fromChIndex;\n dest = ((fromTokenIndex + 1) << 1);\n lastEnd = fromChIndex;\n }\n else {\n dest = (fromTokenIndex << 1);\n lastEnd = fromTokenStartOffset;\n }\n const delta = (toChIndex - fromChIndex);\n for (let tokenIndex = fromTokenIndex + 1; tokenIndex < tokensCount; tokenIndex++) {\n const tokenEndOffset = tokens[tokenIndex << 1] - delta;\n if (tokenEndOffset > lastEnd) {\n tokens[dest++] = tokenEndOffset;\n tokens[dest++] = tokens[(tokenIndex << 1) + 1];\n lastEnd = tokenEndOffset;\n }\n }\n if (dest === tokens.length) {\n // nothing to trim\n return lineTokens;\n }\n const tmp = new Uint32Array(dest);\n tmp.set(tokens.subarray(0, dest), 0);\n return tmp.buffer;\n }\n static append(lineTokens, _otherTokens) {\n if (_otherTokens === EMPTY_LINE_TOKENS) {\n return lineTokens;\n }\n if (lineTokens === EMPTY_LINE_TOKENS) {\n return _otherTokens;\n }\n if (lineTokens === null) {\n return lineTokens;\n }\n if (_otherTokens === null) {\n // cannot determine combined line length...\n return null;\n }\n const myTokens = toUint32Array(lineTokens);\n const otherTokens = toUint32Array(_otherTokens);\n const otherTokensCount = (otherTokens.length >>> 1);\n const result = new Uint32Array(myTokens.length + otherTokens.length);\n result.set(myTokens, 0);\n let dest = myTokens.length;\n const delta = myTokens[myTokens.length - 2];\n for (let i = 0; i < otherTokensCount; i++) {\n result[dest++] = otherTokens[(i << 1)] + delta;\n result[dest++] = otherTokens[(i << 1) + 1];\n }\n return result.buffer;\n }\n static insert(lineTokens, chIndex, textLength) {\n if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {\n // nothing to do\n return lineTokens;\n }\n const tokens = toUint32Array(lineTokens);\n const tokensCount = (tokens.length >>> 1);\n let fromTokenIndex = LineTokens.findIndexInTokensArray(tokens, chIndex);\n if (fromTokenIndex > 0) {\n const fromTokenStartOffset = tokens[(fromTokenIndex - 1) << 1];\n if (fromTokenStartOffset === chIndex) {\n fromTokenIndex--;\n }\n }\n for (let tokenIndex = fromTokenIndex; tokenIndex < tokensCount; tokenIndex++) {\n tokens[tokenIndex << 1] += textLength;\n }\n return lineTokens;\n }\n}\nexport function toUint32Array(arr) {\n if (arr instanceof Uint32Array) {\n return arr;\n }\n else {\n return new Uint32Array(arr);\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 *--------------------------------------------------------------------------------------------*/\nimport * as arrays from '../../../base/common/arrays.js';\nimport { Position } from '../core/position.js';\nimport { ContiguousTokensEditing, EMPTY_LINE_TOKENS, toUint32Array } from './contiguousTokensEditing.js';\nimport { LineTokens } from './lineTokens.js';\nimport { TokenMetadata } from '../encodedTokenAttributes.js';\n/**\n * Represents contiguous tokens in a text model.\n */\nexport class ContiguousTokensStore {\n constructor(languageIdCodec) {\n this._lineTokens = [];\n this._len = 0;\n this._languageIdCodec = languageIdCodec;\n }\n flush() {\n this._lineTokens = [];\n this._len = 0;\n }\n getTokens(topLevelLanguageId, lineIndex, lineText) {\n let rawLineTokens = null;\n if (lineIndex < this._len) {\n rawLineTokens = this._lineTokens[lineIndex];\n }\n if (rawLineTokens !== null && rawLineTokens !== EMPTY_LINE_TOKENS) {\n return new LineTokens(toUint32Array(rawLineTokens), lineText, this._languageIdCodec);\n }\n const lineTokens = new Uint32Array(2);\n lineTokens[0] = lineText.length;\n lineTokens[1] = getDefaultMetadata(this._languageIdCodec.encodeLanguageId(topLevelLanguageId));\n return new LineTokens(lineTokens, lineText, this._languageIdCodec);\n }\n static _massageTokens(topLevelLanguageId, lineTextLength, _tokens) {\n const tokens = _tokens ? toUint32Array(_tokens) : null;\n if (lineTextLength === 0) {\n let hasDifferentLanguageId = false;\n if (tokens && tokens.length > 1) {\n hasDifferentLanguageId = (TokenMetadata.getLanguageId(tokens[1]) !== topLevelLanguageId);\n }\n if (!hasDifferentLanguageId) {\n return EMPTY_LINE_TOKENS;\n }\n }\n if (!tokens || tokens.length === 0) {\n const tokens = new Uint32Array(2);\n tokens[0] = lineTextLength;\n tokens[1] = getDefaultMetadata(topLevelLanguageId);\n return tokens.buffer;\n }\n // Ensure the last token covers the end of the text\n tokens[tokens.length - 2] = lineTextLength;\n if (tokens.byteOffset === 0 && tokens.byteLength === tokens.buffer.byteLength) {\n // Store directly the ArrayBuffer pointer to save an object\n return tokens.buffer;\n }\n return tokens;\n }\n _ensureLine(lineIndex) {\n while (lineIndex >= this._len) {\n this._lineTokens[this._len] = null;\n this._len++;\n }\n }\n _deleteLines(start, deleteCount) {\n if (deleteCount === 0) {\n return;\n }\n if (start + deleteCount > this._len) {\n deleteCount = this._len - start;\n }\n this._lineTokens.splice(start, deleteCount);\n this._len -= deleteCount;\n }\n _insertLines(insertIndex, insertCount) {\n if (insertCount === 0) {\n return;\n }\n const lineTokens = [];\n for (let i = 0; i < insertCount; i++) {\n lineTokens[i] = null;\n }\n this._lineTokens = arrays.arrayInsert(this._lineTokens, insertIndex, lineTokens);\n this._len += insertCount;\n }\n setTokens(topLevelLanguageId, lineIndex, lineTextLength, _tokens, checkEquality) {\n const tokens = ContiguousTokensStore._massageTokens(this._languageIdCodec.encodeLanguageId(topLevelLanguageId), lineTextLength, _tokens);\n this._ensureLine(lineIndex);\n const oldTokens = this._lineTokens[lineIndex];\n this._lineTokens[lineIndex] = tokens;\n if (checkEquality) {\n return !ContiguousTokensStore._equals(oldTokens, tokens);\n }\n return false;\n }\n static _equals(_a, _b) {\n if (!_a || !_b) {\n return !_a && !_b;\n }\n const a = toUint32Array(_a);\n const b = toUint32Array(_b);\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0, len = a.length; i < len; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n }\n //#region Editing\n acceptEdit(range, eolCount, firstLineLength) {\n this._acceptDeleteRange(range);\n this._acceptInsertText(new Position(range.startLineNumber, range.startColumn), eolCount, firstLineLength);\n }\n _acceptDeleteRange(range) {\n const firstLineIndex = range.startLineNumber - 1;\n if (firstLineIndex >= this._len) {\n return;\n }\n if (range.startLineNumber === range.endLineNumber) {\n if (range.startColumn === range.endColumn) {\n // Nothing to delete\n return;\n }\n this._lineTokens[firstLineIndex] = ContiguousTokensEditing.delete(this._lineTokens[firstLineIndex], range.startColumn - 1, range.endColumn - 1);\n return;\n }\n this._lineTokens[firstLineIndex] = ContiguousTokensEditing.deleteEnding(this._lineTokens[firstLineIndex], range.startColumn - 1);\n const lastLineIndex = range.endLineNumber - 1;\n let lastLineTokens = null;\n if (lastLineIndex < this._len) {\n lastLineTokens = ContiguousTokensEditing.deleteBeginning(this._lineTokens[lastLineIndex], range.endColumn - 1);\n }\n // Take remaining text on last line and append it to remaining text on first line\n this._lineTokens[firstLineIndex] = ContiguousTokensEditing.append(this._lineTokens[firstLineIndex], lastLineTokens);\n // Delete middle lines\n this._deleteLines(range.startLineNumber, range.endLineNumber - range.startLineNumber);\n }\n _acceptInsertText(position, eolCount, firstLineLength) {\n if (eolCount === 0 && firstLineLength === 0) {\n // Nothing to insert\n return;\n }\n const lineIndex = position.lineNumber - 1;\n if (lineIndex >= this._len) {\n return;\n }\n if (eolCount === 0) {\n // Inserting text on one line\n this._lineTokens[lineIndex] = ContiguousTokensEditing.insert(this._lineTokens[lineIndex], position.column - 1, firstLineLength);\n return;\n }\n this._lineTokens[lineIndex] = ContiguousTokensEditing.deleteEnding(this._lineTokens[lineIndex], position.column - 1);\n this._lineTokens[lineIndex] = ContiguousTokensEditing.insert(this._lineTokens[lineIndex], position.column - 1, firstLineLength);\n this._insertLines(position.lineNumber, eolCount);\n }\n}\nfunction getDefaultMetadata(topLevelLanguageId) {\n return ((topLevelLanguageId << 0 /* MetadataConsts.LANGUAGEID_OFFSET */)\n | (0 /* StandardTokenType.Other */ << 8 /* MetadataConsts.TOKEN_TYPE_OFFSET */)\n | (0 /* FontStyle.None */ << 11 /* MetadataConsts.FONT_STYLE_OFFSET */)\n | (1 /* ColorId.DefaultForeground */ << 15 /* MetadataConsts.FOREGROUND_OFFSET */)\n | (2 /* ColorId.DefaultBackground */ << 24 /* MetadataConsts.BACKGROUND_OFFSET */)\n // If there is no grammar, we just take a guess and try to match brackets.\n | (1024 /* MetadataConsts.BALANCED_BRACKETS_MASK */)) >>> 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 *--------------------------------------------------------------------------------------------*/\nimport * as arrays from '../../../base/common/arrays.js';\nimport { LineTokens } from './lineTokens.js';\n/**\n * Represents sparse tokens in a text model.\n */\nexport class SparseTokensStore {\n constructor(languageIdCodec) {\n this._pieces = [];\n this._isComplete = false;\n this._languageIdCodec = languageIdCodec;\n }\n flush() {\n this._pieces = [];\n this._isComplete = false;\n }\n isEmpty() {\n return (this._pieces.length === 0);\n }\n set(pieces, isComplete) {\n this._pieces = pieces || [];\n this._isComplete = isComplete;\n }\n setPartial(_range, pieces) {\n // console.log(`setPartial ${_range} ${pieces.map(p => p.toString()).join(', ')}`);\n let range = _range;\n if (pieces.length > 0) {\n const _firstRange = pieces[0].getRange();\n const _lastRange = pieces[pieces.length - 1].getRange();\n if (!_firstRange || !_lastRange) {\n return _range;\n }\n range = _range.plusRange(_firstRange).plusRange(_lastRange);\n }\n let insertPosition = null;\n for (let i = 0, len = this._pieces.length; i < len; i++) {\n const piece = this._pieces[i];\n if (piece.endLineNumber < range.startLineNumber) {\n // this piece is before the range\n continue;\n }\n if (piece.startLineNumber > range.endLineNumber) {\n // this piece is after the range, so mark the spot before this piece\n // as a good insertion position and stop looping\n insertPosition = insertPosition || { index: i };\n break;\n }\n // this piece might intersect with the range\n piece.removeTokens(range);\n if (piece.isEmpty()) {\n // remove the piece if it became empty\n this._pieces.splice(i, 1);\n i--;\n len--;\n continue;\n }\n if (piece.endLineNumber < range.startLineNumber) {\n // after removal, this piece is before the range\n continue;\n }\n if (piece.startLineNumber > range.endLineNumber) {\n // after removal, this piece is after the range\n insertPosition = insertPosition || { index: i };\n continue;\n }\n // after removal, this piece contains the range\n const [a, b] = piece.split(range);\n if (a.isEmpty()) {\n // this piece is actually after the range\n insertPosition = insertPosition || { index: i };\n continue;\n }\n if (b.isEmpty()) {\n // this piece is actually before the range\n continue;\n }\n this._pieces.splice(i, 1, a, b);\n i++;\n len++;\n insertPosition = insertPosition || { index: i };\n }\n insertPosition = insertPosition || { index: this._pieces.length };\n if (pieces.length > 0) {\n this._pieces = arrays.arrayInsert(this._pieces, insertPosition.index, pieces);\n }\n // console.log(`I HAVE ${this._pieces.length} pieces`);\n // console.log(`${this._pieces.map(p => p.toString()).join('\\n')}`);\n return range;\n }\n isComplete() {\n return this._isComplete;\n }\n addSparseTokens(lineNumber, aTokens) {\n if (aTokens.getLineContent().length === 0) {\n // Don't do anything for empty lines\n return aTokens;\n }\n const pieces = this._pieces;\n if (pieces.length === 0) {\n return aTokens;\n }\n const pieceIndex = SparseTokensStore._findFirstPieceWithLine(pieces, lineNumber);\n const bTokens = pieces[pieceIndex].getLineTokens(lineNumber);\n if (!bTokens) {\n return aTokens;\n }\n const aLen = aTokens.getCount();\n const bLen = bTokens.getCount();\n let aIndex = 0;\n const result = [];\n let resultLen = 0;\n let lastEndOffset = 0;\n const emitToken = (endOffset, metadata) => {\n if (endOffset === lastEndOffset) {\n return;\n }\n lastEndOffset = endOffset;\n result[resultLen++] = endOffset;\n result[resultLen++] = metadata;\n };\n for (let bIndex = 0; bIndex < bLen; bIndex++) {\n const bStartCharacter = bTokens.getStartCharacter(bIndex);\n const bEndCharacter = bTokens.getEndCharacter(bIndex);\n const bMetadata = bTokens.getMetadata(bIndex);\n const bMask = (((bMetadata & 1 /* MetadataConsts.SEMANTIC_USE_ITALIC */) ? 2048 /* MetadataConsts.ITALIC_MASK */ : 0)\n | ((bMetadata & 2 /* MetadataConsts.SEMANTIC_USE_BOLD */) ? 4096 /* MetadataConsts.BOLD_MASK */ : 0)\n | ((bMetadata & 4 /* MetadataConsts.SEMANTIC_USE_UNDERLINE */) ? 8192 /* MetadataConsts.UNDERLINE_MASK */ : 0)\n | ((bMetadata & 8 /* MetadataConsts.SEMANTIC_USE_STRIKETHROUGH */) ? 16384 /* MetadataConsts.STRIKETHROUGH_MASK */ : 0)\n | ((bMetadata & 16 /* MetadataConsts.SEMANTIC_USE_FOREGROUND */) ? 16744448 /* MetadataConsts.FOREGROUND_MASK */ : 0)\n | ((bMetadata & 32 /* MetadataConsts.SEMANTIC_USE_BACKGROUND */) ? 4278190080 /* MetadataConsts.BACKGROUND_MASK */ : 0)) >>> 0;\n const aMask = (~bMask) >>> 0;\n // push any token from `a` that is before `b`\n while (aIndex < aLen && aTokens.getEndOffset(aIndex) <= bStartCharacter) {\n emitToken(aTokens.getEndOffset(aIndex), aTokens.getMetadata(aIndex));\n aIndex++;\n }\n // push the token from `a` if it intersects the token from `b`\n if (aIndex < aLen && aTokens.getStartOffset(aIndex) < bStartCharacter) {\n emitToken(bStartCharacter, aTokens.getMetadata(aIndex));\n }\n // skip any tokens from `a` that are contained inside `b`\n while (aIndex < aLen && aTokens.getEndOffset(aIndex) < bEndCharacter) {\n emitToken(aTokens.getEndOffset(aIndex), (aTokens.getMetadata(aIndex) & aMask) | (bMetadata & bMask));\n aIndex++;\n }\n if (aIndex < aLen) {\n emitToken(bEndCharacter, (aTokens.getMetadata(aIndex) & aMask) | (bMetadata & bMask));\n if (aTokens.getEndOffset(aIndex) === bEndCharacter) {\n // `a` ends exactly at the same spot as `b`!\n aIndex++;\n }\n }\n else {\n const aMergeIndex = Math.min(Math.max(0, aIndex - 1), aLen - 1);\n // push the token from `b`\n emitToken(bEndCharacter, (aTokens.getMetadata(aMergeIndex) & aMask) | (bMetadata & bMask));\n }\n }\n // push the remaining tokens from `a`\n while (aIndex < aLen) {\n emitToken(aTokens.getEndOffset(aIndex), aTokens.getMetadata(aIndex));\n aIndex++;\n }\n return new LineTokens(new Uint32Array(result), aTokens.getLineContent(), this._languageIdCodec);\n }\n static _findFirstPieceWithLine(pieces, lineNumber) {\n let low = 0;\n let high = pieces.length - 1;\n while (low < high) {\n let mid = low + Math.floor((high - low) / 2);\n if (pieces[mid].endLineNumber < lineNumber) {\n low = mid + 1;\n }\n else if (pieces[mid].startLineNumber > lineNumber) {\n high = mid - 1;\n }\n else {\n while (mid > low && pieces[mid - 1].startLineNumber <= lineNumber && lineNumber <= pieces[mid - 1].endLineNumber) {\n mid--;\n }\n return mid;\n }\n }\n return low;\n }\n acceptEdit(range, eolCount, firstLineLength, lastLineLength, firstCharCode) {\n for (const piece of this._pieces) {\n piece.acceptEdit(range, eolCount, firstLineLength, lastLineLength, firstCharCode);\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 *--------------------------------------------------------------------------------------------*/\nimport { Emitter } from '../../../base/common/event.js';\nimport { Position } from '../core/position.js';\nimport { getWordAtText } from '../core/wordHelper.js';\nimport { TextModelPart } from './textModelPart.js';\nimport { TextModelTokenization } from './textModelTokens.js';\nimport { ContiguousTokensStore } from '../tokens/contiguousTokensStore.js';\nimport { SparseTokensStore } from '../tokens/sparseTokensStore.js';\nexport class TokenizationTextModelPart extends TextModelPart {\n constructor(_languageService, _languageConfigurationService, _textModel, bracketPairsTextModelPart, _languageId) {\n super();\n this._languageService = _languageService;\n this._languageConfigurationService = _languageConfigurationService;\n this._textModel = _textModel;\n this.bracketPairsTextModelPart = bracketPairsTextModelPart;\n this._languageId = _languageId;\n this._onDidChangeLanguage = this._register(new Emitter());\n this.onDidChangeLanguage = this._onDidChangeLanguage.event;\n this._onDidChangeLanguageConfiguration = this._register(new Emitter());\n this.onDidChangeLanguageConfiguration = this._onDidChangeLanguageConfiguration.event;\n this._onDidChangeTokens = this._register(new Emitter());\n this.onDidChangeTokens = this._onDidChangeTokens.event;\n this._backgroundTokenizationState = 0 /* BackgroundTokenizationState.Uninitialized */;\n this._onBackgroundTokenizationStateChanged = this._register(new Emitter());\n this._tokens = new ContiguousTokensStore(this._languageService.languageIdCodec);\n this._semanticTokens = new SparseTokensStore(this._languageService.languageIdCodec);\n this._tokenization = new TextModelTokenization(_textModel, this, this._languageService.languageIdCodec);\n this._languageRegistryListener = this._languageConfigurationService.onDidChange(e => {\n if (e.affects(this._languageId)) {\n this._onDidChangeLanguageConfiguration.fire({});\n }\n });\n }\n acceptEdit(range, text, eolCount, firstLineLength, lastLineLength) {\n this._tokens.acceptEdit(range, eolCount, firstLineLength);\n this._semanticTokens.acceptEdit(range, eolCount, firstLineLength, lastLineLength, text.length > 0 ? text.charCodeAt(0) : 0 /* CharCode.Null */);\n }\n handleDidChangeAttached() {\n this._tokenization.handleDidChangeAttached();\n }\n flush() {\n this._tokens.flush();\n this._semanticTokens.flush();\n }\n handleDidChangeContent(change) {\n this._tokenization.handleDidChangeContent(change);\n }\n dispose() {\n this._languageRegistryListener.dispose();\n this._tokenization.dispose();\n super.dispose();\n }\n get backgroundTokenizationState() {\n return this._backgroundTokenizationState;\n }\n handleTokenizationProgress(completed) {\n if (this._backgroundTokenizationState === 2 /* BackgroundTokenizationState.Completed */) {\n // We already did a full tokenization and don't go back to progressing.\n return;\n }\n const newState = completed ? 2 /* BackgroundTokenizationState.Completed */ : 1 /* BackgroundTokenizationState.InProgress */;\n if (this._backgroundTokenizationState !== newState) {\n this._backgroundTokenizationState = newState;\n this.bracketPairsTextModelPart.handleDidChangeBackgroundTokenizationState();\n this._onBackgroundTokenizationStateChanged.fire();\n }\n }\n setTokens(tokens, backgroundTokenizationCompleted = false) {\n if (tokens.length !== 0) {\n const ranges = [];\n for (let i = 0, len = tokens.length; i < len; i++) {\n const element = tokens[i];\n let minChangedLineNumber = 0;\n let maxChangedLineNumber = 0;\n let hasChange = false;\n for (let lineNumber = element.startLineNumber; lineNumber <= element.endLineNumber; lineNumber++) {\n if (hasChange) {\n this._tokens.setTokens(this._languageId, lineNumber - 1, this._textModel.getLineLength(lineNumber), element.getLineTokens(lineNumber), false);\n maxChangedLineNumber = lineNumber;\n }\n else {\n const lineHasChange = this._tokens.setTokens(this._languageId, lineNumber - 1, this._textModel.getLineLength(lineNumber), element.getLineTokens(lineNumber), true);\n if (lineHasChange) {\n hasChange = true;\n minChangedLineNumber = lineNumber;\n maxChangedLineNumber = lineNumber;\n }\n }\n }\n if (hasChange) {\n ranges.push({\n fromLineNumber: minChangedLineNumber,\n toLineNumber: maxChangedLineNumber,\n });\n }\n }\n if (ranges.length > 0) {\n this._emitModelTokensChangedEvent({\n tokenizationSupportChanged: false,\n semanticTokensApplied: false,\n ranges: ranges,\n });\n }\n }\n this.handleTokenizationProgress(backgroundTokenizationCompleted);\n }\n setSemanticTokens(tokens, isComplete) {\n this._semanticTokens.set(tokens, isComplete);\n this._emitModelTokensChangedEvent({\n tokenizationSupportChanged: false,\n semanticTokensApplied: tokens !== null,\n ranges: [{ fromLineNumber: 1, toLineNumber: this._textModel.getLineCount() }],\n });\n }\n hasCompleteSemanticTokens() {\n return this._semanticTokens.isComplete();\n }\n hasSomeSemanticTokens() {\n return !this._semanticTokens.isEmpty();\n }\n setPartialSemanticTokens(range, tokens) {\n if (this.hasCompleteSemanticTokens()) {\n return;\n }\n const changedRange = this._textModel.validateRange(this._semanticTokens.setPartial(range, tokens));\n this._emitModelTokensChangedEvent({\n tokenizationSupportChanged: false,\n semanticTokensApplied: true,\n ranges: [\n {\n fromLineNumber: changedRange.startLineNumber,\n toLineNumber: changedRange.endLineNumber,\n },\n ],\n });\n }\n tokenizeViewport(startLineNumber, endLineNumber) {\n startLineNumber = Math.max(1, startLineNumber);\n endLineNumber = Math.min(this._textModel.getLineCount(), endLineNumber);\n this._tokenization.tokenizeViewport(startLineNumber, endLineNumber);\n }\n clearTokens() {\n this._tokens.flush();\n this._emitModelTokensChangedEvent({\n tokenizationSupportChanged: true,\n semanticTokensApplied: false,\n ranges: [\n {\n fromLineNumber: 1,\n toLineNumber: this._textModel.getLineCount(),\n },\n ],\n });\n }\n _emitModelTokensChangedEvent(e) {\n if (!this._textModel._isDisposing()) {\n this.bracketPairsTextModelPart.handleDidChangeTokens(e);\n this._onDidChangeTokens.fire(e);\n }\n }\n resetTokenization() {\n this._tokenization.reset();\n }\n forceTokenization(lineNumber) {\n if (lineNumber < 1 || lineNumber > this._textModel.getLineCount()) {\n throw new Error('Illegal value for lineNumber');\n }\n this._tokenization.forceTokenization(lineNumber);\n }\n isCheapToTokenize(lineNumber) {\n return this._tokenization.isCheapToTokenize(lineNumber);\n }\n tokenizeIfCheap(lineNumber) {\n if (this.isCheapToTokenize(lineNumber)) {\n this.forceTokenization(lineNumber);\n }\n }\n getLineTokens(lineNumber) {\n if (lineNumber < 1 || lineNumber > this._textModel.getLineCount()) {\n throw new Error('Illegal value for lineNumber');\n }\n return this._getLineTokens(lineNumber);\n }\n _getLineTokens(lineNumber) {\n const lineText = this._textModel.getLineContent(lineNumber);\n const syntacticTokens = this._tokens.getTokens(this._languageId, lineNumber - 1, lineText);\n return this._semanticTokens.addSparseTokens(lineNumber, syntacticTokens);\n }\n getTokenTypeIfInsertingCharacter(lineNumber, column, character) {\n const position = this._textModel.validatePosition(new Position(lineNumber, column));\n return this._tokenization.getTokenTypeIfInsertingCharacter(position, character);\n }\n tokenizeLineWithEdit(position, length, newText) {\n const validatedPosition = this._textModel.validatePosition(position);\n return this._tokenization.tokenizeLineWithEdit(validatedPosition, length, newText);\n }\n getLanguageConfiguration(languageId) {\n return this._languageConfigurationService.getLanguageConfiguration(languageId);\n }\n // Having tokens allows implementing additional helper methods\n getWordAtPosition(_position) {\n this.assertNotDisposed();\n const position = this._textModel.validatePosition(_position);\n const lineContent = this._textModel.getLineContent(position.lineNumber);\n const lineTokens = this._getLineTokens(position.lineNumber);\n const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);\n // (1). First try checking right biased word\n const [rbStartOffset, rbEndOffset] = TokenizationTextModelPart._findLanguageBoundaries(lineTokens, tokenIndex);\n const rightBiasedWord = getWordAtText(position.column, this.getLanguageConfiguration(lineTokens.getLanguageId(tokenIndex)).getWordDefinition(), lineContent.substring(rbStartOffset, rbEndOffset), rbStartOffset);\n // Make sure the result touches the original passed in position\n if (rightBiasedWord &&\n rightBiasedWord.startColumn <= _position.column &&\n _position.column <= rightBiasedWord.endColumn) {\n return rightBiasedWord;\n }\n // (2). Else, if we were at a language boundary, check the left biased word\n if (tokenIndex > 0 && rbStartOffset === position.column - 1) {\n // edge case, where `position` sits between two tokens belonging to two different languages\n const [lbStartOffset, lbEndOffset] = TokenizationTextModelPart._findLanguageBoundaries(lineTokens, tokenIndex - 1);\n const leftBiasedWord = getWordAtText(position.column, this.getLanguageConfiguration(lineTokens.getLanguageId(tokenIndex - 1)).getWordDefinition(), lineContent.substring(lbStartOffset, lbEndOffset), lbStartOffset);\n // Make sure the result touches the original passed in position\n if (leftBiasedWord &&\n leftBiasedWord.startColumn <= _position.column &&\n _position.column <= leftBiasedWord.endColumn) {\n return leftBiasedWord;\n }\n }\n return null;\n }\n static _findLanguageBoundaries(lineTokens, tokenIndex) {\n const languageId = lineTokens.getLanguageId(tokenIndex);\n // go left until a different language is hit\n let startOffset = 0;\n for (let i = tokenIndex; i >= 0 && lineTokens.getLanguageId(i) === languageId; i--) {\n startOffset = lineTokens.getStartOffset(i);\n }\n // go right until a different language is hit\n let endOffset = lineTokens.getLineContent().length;\n for (let i = tokenIndex, tokenCount = lineTokens.getCount(); i < tokenCount && lineTokens.getLanguageId(i) === languageId; i++) {\n endOffset = lineTokens.getEndOffset(i);\n }\n return [startOffset, endOffset];\n }\n getWordUntilPosition(position) {\n const wordAtPosition = this.getWordAtPosition(position);\n if (!wordAtPosition) {\n return {\n word: '',\n startColumn: position.column,\n endColumn: position.column,\n };\n }\n return {\n word: wordAtPosition.word.substr(0, position.column - wordAtPosition.startColumn),\n startColumn: wordAtPosition.startColumn,\n endColumn: position.column,\n };\n }\n getLanguageId() {\n return this._languageId;\n }\n getLanguageIdAtPosition(lineNumber, column) {\n const position = this._textModel.validatePosition(new Position(lineNumber, column));\n const lineTokens = this.getLineTokens(position.lineNumber);\n return lineTokens.getLanguageId(lineTokens.findTokenIndexAtOffset(position.column - 1));\n }\n setLanguageId(languageId) {\n if (this._languageId === languageId) {\n // There's nothing to do\n return;\n }\n const e = {\n oldLanguage: this._languageId,\n newLanguage: languageId\n };\n this._languageId = languageId;\n this.bracketPairsTextModelPart.handleDidChangeLanguage(e);\n this._tokenization.handleDidChangeLanguage(e);\n this._onDidChangeLanguage.fire(e);\n this._onDidChangeLanguageConfiguration.fire({});\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { ArrayQueue, pushMany } from '../../../base/common/arrays.js';\nimport { Color } from '../../../base/common/color.js';\nimport { onUnexpectedError } from '../../../base/common/errors.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { combinedDisposable, Disposable } from '../../../base/common/lifecycle.js';\nimport * as strings from '../../../base/common/strings.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { countEOL } from '../core/eolCounter.js';\nimport { normalizeIndentation } from '../core/indentation.js';\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nimport { Selection } from '../core/selection.js';\nimport { EDITOR_MODEL_DEFAULTS } from '../core/textModelDefaults.js';\nimport { ILanguageService } from '../languages/language.js';\nimport { ILanguageConfigurationService } from '../languages/languageConfigurationRegistry.js';\nimport * as model from '../model.js';\nimport { BracketPairsTextModelPart } from './bracketPairsTextModelPart/bracketPairsImpl.js';\nimport { ColorizedBracketPairsDecorationProvider } from './bracketPairsTextModelPart/colorizedBracketPairsDecorationProvider.js';\nimport { EditStack } from './editStack.js';\nimport { GuidesTextModelPart } from './guidesTextModelPart.js';\nimport { guessIndentation } from './indentationGuesser.js';\nimport { IntervalNode, IntervalTree, recomputeMaxEnd } from './intervalTree.js';\nimport { PieceTreeTextBuffer } from './pieceTreeTextBuffer/pieceTreeTextBuffer.js';\nimport { PieceTreeTextBufferBuilder } from './pieceTreeTextBuffer/pieceTreeTextBufferBuilder.js';\nimport { SearchParams, TextModelSearch } from './textModelSearch.js';\nimport { TokenizationTextModelPart } from './tokenizationTextModelPart.js';\nimport { InternalModelContentChangeEvent, LineInjectedText, ModelInjectedTextChangedEvent, ModelRawContentChangedEvent, ModelRawEOLChanged, ModelRawFlush, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from '../textModelEvents.js';\nimport { IUndoRedoService } from '../../../platform/undoRedo/common/undoRedo.js';\nexport function createTextBufferFactory(text) {\n const builder = new PieceTreeTextBufferBuilder();\n builder.acceptChunk(text);\n return builder.finish();\n}\nexport function createTextBufferFactoryFromSnapshot(snapshot) {\n const builder = new PieceTreeTextBufferBuilder();\n let chunk;\n while (typeof (chunk = snapshot.read()) === 'string') {\n builder.acceptChunk(chunk);\n }\n return builder.finish();\n}\nexport function createTextBuffer(value, defaultEOL) {\n let factory;\n if (typeof value === 'string') {\n factory = createTextBufferFactory(value);\n }\n else if (model.isITextSnapshot(value)) {\n factory = createTextBufferFactoryFromSnapshot(value);\n }\n else {\n factory = value;\n }\n return factory.create(defaultEOL);\n}\nlet MODEL_ID = 0;\nconst LIMIT_FIND_COUNT = 999;\nexport const LONG_LINE_BOUNDARY = 10000;\nclass TextModelSnapshot {\n constructor(source) {\n this._source = source;\n this._eos = false;\n }\n read() {\n if (this._eos) {\n return null;\n }\n const result = [];\n let resultCnt = 0;\n let resultLength = 0;\n do {\n const tmp = this._source.read();\n if (tmp === null) {\n // end-of-stream\n this._eos = true;\n if (resultCnt === 0) {\n return null;\n }\n else {\n return result.join('');\n }\n }\n if (tmp.length > 0) {\n result[resultCnt++] = tmp;\n resultLength += tmp.length;\n }\n if (resultLength >= 64 * 1024) {\n return result.join('');\n }\n } while (true);\n }\n}\nconst invalidFunc = () => { throw new Error(`Invalid change accessor`); };\nlet TextModel = class TextModel extends Disposable {\n constructor(source, languageId, creationOptions, associatedResource = null, _undoRedoService, _languageService, _languageConfigurationService) {\n super();\n this._undoRedoService = _undoRedoService;\n this._languageService = _languageService;\n this._languageConfigurationService = _languageConfigurationService;\n //#region Events\n this._onWillDispose = this._register(new Emitter());\n this.onWillDispose = this._onWillDispose.event;\n this._onDidChangeDecorations = this._register(new DidChangeDecorationsEmitter(affectedInjectedTextLines => this.handleBeforeFireDecorationsChangedEvent(affectedInjectedTextLines)));\n this.onDidChangeDecorations = this._onDidChangeDecorations.event;\n this._onDidChangeOptions = this._register(new Emitter());\n this.onDidChangeOptions = this._onDidChangeOptions.event;\n this._onDidChangeAttached = this._register(new Emitter());\n this.onDidChangeAttached = this._onDidChangeAttached.event;\n this._onDidChangeInjectedText = this._register(new Emitter());\n this._eventEmitter = this._register(new DidChangeContentEmitter());\n this._deltaDecorationCallCnt = 0;\n // Generate a new unique model id\n MODEL_ID++;\n this.id = '$model' + MODEL_ID;\n this.isForSimpleWidget = creationOptions.isForSimpleWidget;\n if (typeof associatedResource === 'undefined' || associatedResource === null) {\n this._associatedResource = URI.parse('inmemory://model/' + MODEL_ID);\n }\n else {\n this._associatedResource = associatedResource;\n }\n this._attachedEditorCount = 0;\n const { textBuffer, disposable } = createTextBuffer(source, creationOptions.defaultEOL);\n this._buffer = textBuffer;\n this._bufferDisposable = disposable;\n this._options = TextModel.resolveOptions(this._buffer, creationOptions);\n this._bracketPairs = this._register(new BracketPairsTextModelPart(this, this._languageConfigurationService));\n this._guidesTextModelPart = this._register(new GuidesTextModelPart(this, this._languageConfigurationService));\n this._decorationProvider = this._register(new ColorizedBracketPairsDecorationProvider(this));\n this._tokenizationTextModelPart = new TokenizationTextModelPart(this._languageService, this._languageConfigurationService, this, this._bracketPairs, languageId);\n const bufferLineCount = this._buffer.getLineCount();\n const bufferTextLength = this._buffer.getValueLengthInRange(new Range(1, 1, bufferLineCount, this._buffer.getLineLength(bufferLineCount) + 1), 0 /* model.EndOfLinePreference.TextDefined */);\n // !!! Make a decision in the ctor and permanently respect this decision !!!\n // If a model is too large at construction time, it will never get tokenized,\n // under no circumstances.\n if (creationOptions.largeFileOptimizations) {\n this._isTooLargeForTokenization = ((bufferTextLength > TextModel.LARGE_FILE_SIZE_THRESHOLD)\n || (bufferLineCount > TextModel.LARGE_FILE_LINE_COUNT_THRESHOLD));\n }\n else {\n this._isTooLargeForTokenization = false;\n }\n this._isTooLargeForSyncing = (bufferTextLength > TextModel.MODEL_SYNC_LIMIT);\n this._versionId = 1;\n this._alternativeVersionId = 1;\n this._initialUndoRedoSnapshot = null;\n this._isDisposed = false;\n this.__isDisposing = false;\n this._instanceId = strings.singleLetterHash(MODEL_ID);\n this._lastDecorationId = 0;\n this._decorations = Object.create(null);\n this._decorationsTree = new DecorationsTrees();\n this._commandManager = new EditStack(this, this._undoRedoService);\n this._isUndoing = false;\n this._isRedoing = false;\n this._trimAutoWhitespaceLines = null;\n this._register(this._decorationProvider.onDidChange(() => {\n this._onDidChangeDecorations.beginDeferredEmit();\n this._onDidChangeDecorations.fire();\n this._onDidChangeDecorations.endDeferredEmit();\n }));\n }\n static resolveOptions(textBuffer, options) {\n if (options.detectIndentation) {\n const guessedIndentation = guessIndentation(textBuffer, options.tabSize, options.insertSpaces);\n return new model.TextModelResolvedOptions({\n tabSize: guessedIndentation.tabSize,\n indentSize: guessedIndentation.tabSize,\n insertSpaces: guessedIndentation.insertSpaces,\n trimAutoWhitespace: options.trimAutoWhitespace,\n defaultEOL: options.defaultEOL,\n bracketPairColorizationOptions: options.bracketPairColorizationOptions,\n });\n }\n return new model.TextModelResolvedOptions({\n tabSize: options.tabSize,\n indentSize: options.indentSize,\n insertSpaces: options.insertSpaces,\n trimAutoWhitespace: options.trimAutoWhitespace,\n defaultEOL: options.defaultEOL,\n bracketPairColorizationOptions: options.bracketPairColorizationOptions,\n });\n }\n get onDidChangeLanguage() { return this._tokenizationTextModelPart.onDidChangeLanguage; }\n get onDidChangeLanguageConfiguration() { return this._tokenizationTextModelPart.onDidChangeLanguageConfiguration; }\n get onDidChangeTokens() { return this._tokenizationTextModelPart.onDidChangeTokens; }\n onDidChangeContent(listener) {\n return this._eventEmitter.slowEvent((e) => listener(e.contentChangedEvent));\n }\n onDidChangeContentOrInjectedText(listener) {\n return combinedDisposable(this._eventEmitter.fastEvent(e => listener(e)), this._onDidChangeInjectedText.event(e => listener(e)));\n }\n _isDisposing() { return this.__isDisposing; }\n get tokenization() { return this._tokenizationTextModelPart; }\n get bracketPairs() { return this._bracketPairs; }\n get guides() { return this._guidesTextModelPart; }\n dispose() {\n this.__isDisposing = true;\n this._onWillDispose.fire();\n this._tokenizationTextModelPart.dispose();\n this._isDisposed = true;\n super.dispose();\n this._bufferDisposable.dispose();\n this.__isDisposing = false;\n // Manually release reference to previous text buffer to avoid large leaks\n // in case someone leaks a TextModel reference\n const emptyDisposedTextBuffer = new PieceTreeTextBuffer([], '', '\\n', false, false, true, true);\n emptyDisposedTextBuffer.dispose();\n this._buffer = emptyDisposedTextBuffer;\n this._bufferDisposable = Disposable.None;\n }\n _assertNotDisposed() {\n if (this._isDisposed) {\n throw new Error('Model is disposed!');\n }\n }\n _emitContentChangedEvent(rawChange, change) {\n if (this.__isDisposing) {\n // Do not confuse listeners by emitting any event after disposing\n return;\n }\n this._tokenizationTextModelPart.handleDidChangeContent(change);\n this._bracketPairs.handleDidChangeContent(change);\n this._eventEmitter.fire(new InternalModelContentChangeEvent(rawChange, change));\n }\n setValue(value) {\n this._assertNotDisposed();\n if (value === null) {\n // There's nothing to do\n return;\n }\n const { textBuffer, disposable } = createTextBuffer(value, this._options.defaultEOL);\n this._setValueFromTextBuffer(textBuffer, disposable);\n }\n _createContentChanged2(range, rangeOffset, rangeLength, text, isUndoing, isRedoing, isFlush) {\n return {\n changes: [{\n range: range,\n rangeOffset: rangeOffset,\n rangeLength: rangeLength,\n text: text,\n }],\n eol: this._buffer.getEOL(),\n versionId: this.getVersionId(),\n isUndoing: isUndoing,\n isRedoing: isRedoing,\n isFlush: isFlush\n };\n }\n _setValueFromTextBuffer(textBuffer, textBufferDisposable) {\n this._assertNotDisposed();\n const oldFullModelRange = this.getFullModelRange();\n const oldModelValueLength = this.getValueLengthInRange(oldFullModelRange);\n const endLineNumber = this.getLineCount();\n const endColumn = this.getLineMaxColumn(endLineNumber);\n this._buffer = textBuffer;\n this._bufferDisposable.dispose();\n this._bufferDisposable = textBufferDisposable;\n this._increaseVersionId();\n // Flush all tokens\n this._tokenizationTextModelPart.flush();\n // Destroy all my decorations\n this._decorations = Object.create(null);\n this._decorationsTree = new DecorationsTrees();\n // Destroy my edit history and settings\n this._commandManager.clear();\n this._trimAutoWhitespaceLines = null;\n this._emitContentChangedEvent(new ModelRawContentChangedEvent([\n new ModelRawFlush()\n ], this._versionId, false, false), this._createContentChanged2(new Range(1, 1, endLineNumber, endColumn), 0, oldModelValueLength, this.getValue(), false, false, true));\n }\n setEOL(eol) {\n this._assertNotDisposed();\n const newEOL = (eol === 1 /* model.EndOfLineSequence.CRLF */ ? '\\r\\n' : '\\n');\n if (this._buffer.getEOL() === newEOL) {\n // Nothing to do\n return;\n }\n const oldFullModelRange = this.getFullModelRange();\n const oldModelValueLength = this.getValueLengthInRange(oldFullModelRange);\n const endLineNumber = this.getLineCount();\n const endColumn = this.getLineMaxColumn(endLineNumber);\n this._onBeforeEOLChange();\n this._buffer.setEOL(newEOL);\n this._increaseVersionId();\n this._onAfterEOLChange();\n this._emitContentChangedEvent(new ModelRawContentChangedEvent([\n new ModelRawEOLChanged()\n ], this._versionId, false, false), this._createContentChanged2(new Range(1, 1, endLineNumber, endColumn), 0, oldModelValueLength, this.getValue(), false, false, false));\n }\n _onBeforeEOLChange() {\n // Ensure all decorations get their `range` set.\n this._decorationsTree.ensureAllNodesHaveRanges(this);\n }\n _onAfterEOLChange() {\n // Transform back `range` to offsets\n const versionId = this.getVersionId();\n const allDecorations = this._decorationsTree.collectNodesPostOrder();\n for (let i = 0, len = allDecorations.length; i < len; i++) {\n const node = allDecorations[i];\n const range = node.range; // the range is defined due to `_onBeforeEOLChange`\n const delta = node.cachedAbsoluteStart - node.start;\n const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);\n const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);\n node.cachedAbsoluteStart = startOffset;\n node.cachedAbsoluteEnd = endOffset;\n node.cachedVersionId = versionId;\n node.start = startOffset - delta;\n node.end = endOffset - delta;\n recomputeMaxEnd(node);\n }\n }\n onBeforeAttached() {\n this._attachedEditorCount++;\n if (this._attachedEditorCount === 1) {\n this._tokenizationTextModelPart.handleDidChangeAttached();\n this._onDidChangeAttached.fire(undefined);\n }\n }\n onBeforeDetached() {\n this._attachedEditorCount--;\n if (this._attachedEditorCount === 0) {\n this._tokenizationTextModelPart.handleDidChangeAttached();\n this._onDidChangeAttached.fire(undefined);\n }\n }\n isAttachedToEditor() {\n return this._attachedEditorCount > 0;\n }\n getAttachedEditorCount() {\n return this._attachedEditorCount;\n }\n isTooLargeForSyncing() {\n return this._isTooLargeForSyncing;\n }\n isTooLargeForTokenization() {\n return this._isTooLargeForTokenization;\n }\n isDisposed() {\n return this._isDisposed;\n }\n isDominatedByLongLines() {\n this._assertNotDisposed();\n if (this.isTooLargeForTokenization()) {\n // Cannot word wrap huge files anyways, so it doesn't really matter\n return false;\n }\n let smallLineCharCount = 0;\n let longLineCharCount = 0;\n const lineCount = this._buffer.getLineCount();\n for (let lineNumber = 1; lineNumber <= lineCount; lineNumber++) {\n const lineLength = this._buffer.getLineLength(lineNumber);\n if (lineLength >= LONG_LINE_BOUNDARY) {\n longLineCharCount += lineLength;\n }\n else {\n smallLineCharCount += lineLength;\n }\n }\n return (longLineCharCount > smallLineCharCount);\n }\n get uri() {\n return this._associatedResource;\n }\n //#region Options\n getOptions() {\n this._assertNotDisposed();\n return this._options;\n }\n getFormattingOptions() {\n return {\n tabSize: this._options.indentSize,\n insertSpaces: this._options.insertSpaces\n };\n }\n updateOptions(_newOpts) {\n this._assertNotDisposed();\n const tabSize = (typeof _newOpts.tabSize !== 'undefined') ? _newOpts.tabSize : this._options.tabSize;\n const indentSize = (typeof _newOpts.indentSize !== 'undefined') ? _newOpts.indentSize : this._options.indentSize;\n const insertSpaces = (typeof _newOpts.insertSpaces !== 'undefined') ? _newOpts.insertSpaces : this._options.insertSpaces;\n const trimAutoWhitespace = (typeof _newOpts.trimAutoWhitespace !== 'undefined') ? _newOpts.trimAutoWhitespace : this._options.trimAutoWhitespace;\n const bracketPairColorizationOptions = (typeof _newOpts.bracketColorizationOptions !== 'undefined') ? _newOpts.bracketColorizationOptions : this._options.bracketPairColorizationOptions;\n const newOpts = new model.TextModelResolvedOptions({\n tabSize: tabSize,\n indentSize: indentSize,\n insertSpaces: insertSpaces,\n defaultEOL: this._options.defaultEOL,\n trimAutoWhitespace: trimAutoWhitespace,\n bracketPairColorizationOptions,\n });\n if (this._options.equals(newOpts)) {\n return;\n }\n const e = this._options.createChangeEvent(newOpts);\n this._options = newOpts;\n this._bracketPairs.handleDidChangeOptions(e);\n this._decorationProvider.handleDidChangeOptions(e);\n this._onDidChangeOptions.fire(e);\n }\n detectIndentation(defaultInsertSpaces, defaultTabSize) {\n this._assertNotDisposed();\n const guessedIndentation = guessIndentation(this._buffer, defaultTabSize, defaultInsertSpaces);\n this.updateOptions({\n insertSpaces: guessedIndentation.insertSpaces,\n tabSize: guessedIndentation.tabSize,\n indentSize: guessedIndentation.tabSize, // TODO@Alex: guess indentSize independent of tabSize\n });\n }\n normalizeIndentation(str) {\n this._assertNotDisposed();\n return normalizeIndentation(str, this._options.indentSize, this._options.insertSpaces);\n }\n //#endregion\n //#region Reading\n getVersionId() {\n this._assertNotDisposed();\n return this._versionId;\n }\n mightContainRTL() {\n return this._buffer.mightContainRTL();\n }\n mightContainUnusualLineTerminators() {\n return this._buffer.mightContainUnusualLineTerminators();\n }\n removeUnusualLineTerminators(selections = null) {\n const matches = this.findMatches(strings.UNUSUAL_LINE_TERMINATORS.source, false, true, false, null, false, 1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */);\n this._buffer.resetMightContainUnusualLineTerminators();\n this.pushEditOperations(selections, matches.map(m => ({ range: m.range, text: null })), () => null);\n }\n mightContainNonBasicASCII() {\n return this._buffer.mightContainNonBasicASCII();\n }\n getAlternativeVersionId() {\n this._assertNotDisposed();\n return this._alternativeVersionId;\n }\n getInitialUndoRedoSnapshot() {\n this._assertNotDisposed();\n return this._initialUndoRedoSnapshot;\n }\n getOffsetAt(rawPosition) {\n this._assertNotDisposed();\n const position = this._validatePosition(rawPosition.lineNumber, rawPosition.column, 0 /* StringOffsetValidationType.Relaxed */);\n return this._buffer.getOffsetAt(position.lineNumber, position.column);\n }\n getPositionAt(rawOffset) {\n this._assertNotDisposed();\n const offset = (Math.min(this._buffer.getLength(), Math.max(0, rawOffset)));\n return this._buffer.getPositionAt(offset);\n }\n _increaseVersionId() {\n this._versionId = this._versionId + 1;\n this._alternativeVersionId = this._versionId;\n }\n _overwriteVersionId(versionId) {\n this._versionId = versionId;\n }\n _overwriteAlternativeVersionId(newAlternativeVersionId) {\n this._alternativeVersionId = newAlternativeVersionId;\n }\n _overwriteInitialUndoRedoSnapshot(newInitialUndoRedoSnapshot) {\n this._initialUndoRedoSnapshot = newInitialUndoRedoSnapshot;\n }\n getValue(eol, preserveBOM = false) {\n this._assertNotDisposed();\n const fullModelRange = this.getFullModelRange();\n const fullModelValue = this.getValueInRange(fullModelRange, eol);\n if (preserveBOM) {\n return this._buffer.getBOM() + fullModelValue;\n }\n return fullModelValue;\n }\n createSnapshot(preserveBOM = false) {\n return new TextModelSnapshot(this._buffer.createSnapshot(preserveBOM));\n }\n getValueLength(eol, preserveBOM = false) {\n this._assertNotDisposed();\n const fullModelRange = this.getFullModelRange();\n const fullModelValue = this.getValueLengthInRange(fullModelRange, eol);\n if (preserveBOM) {\n return this._buffer.getBOM().length + fullModelValue;\n }\n return fullModelValue;\n }\n getValueInRange(rawRange, eol = 0 /* model.EndOfLinePreference.TextDefined */) {\n this._assertNotDisposed();\n return this._buffer.getValueInRange(this.validateRange(rawRange), eol);\n }\n getValueLengthInRange(rawRange, eol = 0 /* model.EndOfLinePreference.TextDefined */) {\n this._assertNotDisposed();\n return this._buffer.getValueLengthInRange(this.validateRange(rawRange), eol);\n }\n getCharacterCountInRange(rawRange, eol = 0 /* model.EndOfLinePreference.TextDefined */) {\n this._assertNotDisposed();\n return this._buffer.getCharacterCountInRange(this.validateRange(rawRange), eol);\n }\n getLineCount() {\n this._assertNotDisposed();\n return this._buffer.getLineCount();\n }\n getLineContent(lineNumber) {\n this._assertNotDisposed();\n if (lineNumber < 1 || lineNumber > this.getLineCount()) {\n throw new Error('Illegal value for lineNumber');\n }\n return this._buffer.getLineContent(lineNumber);\n }\n getLineLength(lineNumber) {\n this._assertNotDisposed();\n if (lineNumber < 1 || lineNumber > this.getLineCount()) {\n throw new Error('Illegal value for lineNumber');\n }\n return this._buffer.getLineLength(lineNumber);\n }\n getLinesContent() {\n this._assertNotDisposed();\n return this._buffer.getLinesContent();\n }\n getEOL() {\n this._assertNotDisposed();\n return this._buffer.getEOL();\n }\n getEndOfLineSequence() {\n this._assertNotDisposed();\n return (this._buffer.getEOL() === '\\n'\n ? 0 /* model.EndOfLineSequence.LF */\n : 1 /* model.EndOfLineSequence.CRLF */);\n }\n getLineMinColumn(lineNumber) {\n this._assertNotDisposed();\n return 1;\n }\n getLineMaxColumn(lineNumber) {\n this._assertNotDisposed();\n if (lineNumber < 1 || lineNumber > this.getLineCount()) {\n throw new Error('Illegal value for lineNumber');\n }\n return this._buffer.getLineLength(lineNumber) + 1;\n }\n getLineFirstNonWhitespaceColumn(lineNumber) {\n this._assertNotDisposed();\n if (lineNumber < 1 || lineNumber > this.getLineCount()) {\n throw new Error('Illegal value for lineNumber');\n }\n return this._buffer.getLineFirstNonWhitespaceColumn(lineNumber);\n }\n getLineLastNonWhitespaceColumn(lineNumber) {\n this._assertNotDisposed();\n if (lineNumber < 1 || lineNumber > this.getLineCount()) {\n throw new Error('Illegal value for lineNumber');\n }\n return this._buffer.getLineLastNonWhitespaceColumn(lineNumber);\n }\n /**\n * Validates `range` is within buffer bounds, but allows it to sit in between surrogate pairs, etc.\n * Will try to not allocate if possible.\n */\n _validateRangeRelaxedNoAllocations(range) {\n const linesCount = this._buffer.getLineCount();\n const initialStartLineNumber = range.startLineNumber;\n const initialStartColumn = range.startColumn;\n let startLineNumber = Math.floor((typeof initialStartLineNumber === 'number' && !isNaN(initialStartLineNumber)) ? initialStartLineNumber : 1);\n let startColumn = Math.floor((typeof initialStartColumn === 'number' && !isNaN(initialStartColumn)) ? initialStartColumn : 1);\n if (startLineNumber < 1) {\n startLineNumber = 1;\n startColumn = 1;\n }\n else if (startLineNumber > linesCount) {\n startLineNumber = linesCount;\n startColumn = this.getLineMaxColumn(startLineNumber);\n }\n else {\n if (startColumn <= 1) {\n startColumn = 1;\n }\n else {\n const maxColumn = this.getLineMaxColumn(startLineNumber);\n if (startColumn >= maxColumn) {\n startColumn = maxColumn;\n }\n }\n }\n const initialEndLineNumber = range.endLineNumber;\n const initialEndColumn = range.endColumn;\n let endLineNumber = Math.floor((typeof initialEndLineNumber === 'number' && !isNaN(initialEndLineNumber)) ? initialEndLineNumber : 1);\n let endColumn = Math.floor((typeof initialEndColumn === 'number' && !isNaN(initialEndColumn)) ? initialEndColumn : 1);\n if (endLineNumber < 1) {\n endLineNumber = 1;\n endColumn = 1;\n }\n else if (endLineNumber > linesCount) {\n endLineNumber = linesCount;\n endColumn = this.getLineMaxColumn(endLineNumber);\n }\n else {\n if (endColumn <= 1) {\n endColumn = 1;\n }\n else {\n const maxColumn = this.getLineMaxColumn(endLineNumber);\n if (endColumn >= maxColumn) {\n endColumn = maxColumn;\n }\n }\n }\n if (initialStartLineNumber === startLineNumber\n && initialStartColumn === startColumn\n && initialEndLineNumber === endLineNumber\n && initialEndColumn === endColumn\n && range instanceof Range\n && !(range instanceof Selection)) {\n return range;\n }\n return new Range(startLineNumber, startColumn, endLineNumber, endColumn);\n }\n _isValidPosition(lineNumber, column, validationType) {\n if (typeof lineNumber !== 'number' || typeof column !== 'number') {\n return false;\n }\n if (isNaN(lineNumber) || isNaN(column)) {\n return false;\n }\n if (lineNumber < 1 || column < 1) {\n return false;\n }\n if ((lineNumber | 0) !== lineNumber || (column | 0) !== column) {\n return false;\n }\n const lineCount = this._buffer.getLineCount();\n if (lineNumber > lineCount) {\n return false;\n }\n if (column === 1) {\n return true;\n }\n const maxColumn = this.getLineMaxColumn(lineNumber);\n if (column > maxColumn) {\n return false;\n }\n if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {\n // !!At this point, column > 1\n const charCodeBefore = this._buffer.getLineCharCode(lineNumber, column - 2);\n if (strings.isHighSurrogate(charCodeBefore)) {\n return false;\n }\n }\n return true;\n }\n _validatePosition(_lineNumber, _column, validationType) {\n const lineNumber = Math.floor((typeof _lineNumber === 'number' && !isNaN(_lineNumber)) ? _lineNumber : 1);\n const column = Math.floor((typeof _column === 'number' && !isNaN(_column)) ? _column : 1);\n const lineCount = this._buffer.getLineCount();\n if (lineNumber < 1) {\n return new Position(1, 1);\n }\n if (lineNumber > lineCount) {\n return new Position(lineCount, this.getLineMaxColumn(lineCount));\n }\n if (column <= 1) {\n return new Position(lineNumber, 1);\n }\n const maxColumn = this.getLineMaxColumn(lineNumber);\n if (column >= maxColumn) {\n return new Position(lineNumber, maxColumn);\n }\n if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {\n // If the position would end up in the middle of a high-low surrogate pair,\n // we move it to before the pair\n // !!At this point, column > 1\n const charCodeBefore = this._buffer.getLineCharCode(lineNumber, column - 2);\n if (strings.isHighSurrogate(charCodeBefore)) {\n return new Position(lineNumber, column - 1);\n }\n }\n return new Position(lineNumber, column);\n }\n validatePosition(position) {\n const validationType = 1 /* StringOffsetValidationType.SurrogatePairs */;\n this._assertNotDisposed();\n // Avoid object allocation and cover most likely case\n if (position instanceof Position) {\n if (this._isValidPosition(position.lineNumber, position.column, validationType)) {\n return position;\n }\n }\n return this._validatePosition(position.lineNumber, position.column, validationType);\n }\n _isValidRange(range, validationType) {\n const startLineNumber = range.startLineNumber;\n const startColumn = range.startColumn;\n const endLineNumber = range.endLineNumber;\n const endColumn = range.endColumn;\n if (!this._isValidPosition(startLineNumber, startColumn, 0 /* StringOffsetValidationType.Relaxed */)) {\n return false;\n }\n if (!this._isValidPosition(endLineNumber, endColumn, 0 /* StringOffsetValidationType.Relaxed */)) {\n return false;\n }\n if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {\n const charCodeBeforeStart = (startColumn > 1 ? this._buffer.getLineCharCode(startLineNumber, startColumn - 2) : 0);\n const charCodeBeforeEnd = (endColumn > 1 && endColumn <= this._buffer.getLineLength(endLineNumber) ? this._buffer.getLineCharCode(endLineNumber, endColumn - 2) : 0);\n const startInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeStart);\n const endInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeEnd);\n if (!startInsideSurrogatePair && !endInsideSurrogatePair) {\n return true;\n }\n return false;\n }\n return true;\n }\n validateRange(_range) {\n const validationType = 1 /* StringOffsetValidationType.SurrogatePairs */;\n this._assertNotDisposed();\n // Avoid object allocation and cover most likely case\n if ((_range instanceof Range) && !(_range instanceof Selection)) {\n if (this._isValidRange(_range, validationType)) {\n return _range;\n }\n }\n const start = this._validatePosition(_range.startLineNumber, _range.startColumn, 0 /* StringOffsetValidationType.Relaxed */);\n const end = this._validatePosition(_range.endLineNumber, _range.endColumn, 0 /* StringOffsetValidationType.Relaxed */);\n const startLineNumber = start.lineNumber;\n const startColumn = start.column;\n const endLineNumber = end.lineNumber;\n const endColumn = end.column;\n if (validationType === 1 /* StringOffsetValidationType.SurrogatePairs */) {\n const charCodeBeforeStart = (startColumn > 1 ? this._buffer.getLineCharCode(startLineNumber, startColumn - 2) : 0);\n const charCodeBeforeEnd = (endColumn > 1 && endColumn <= this._buffer.getLineLength(endLineNumber) ? this._buffer.getLineCharCode(endLineNumber, endColumn - 2) : 0);\n const startInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeStart);\n const endInsideSurrogatePair = strings.isHighSurrogate(charCodeBeforeEnd);\n if (!startInsideSurrogatePair && !endInsideSurrogatePair) {\n return new Range(startLineNumber, startColumn, endLineNumber, endColumn);\n }\n if (startLineNumber === endLineNumber && startColumn === endColumn) {\n // do not expand a collapsed range, simply move it to a valid location\n return new Range(startLineNumber, startColumn - 1, endLineNumber, endColumn - 1);\n }\n if (startInsideSurrogatePair && endInsideSurrogatePair) {\n // expand range at both ends\n return new Range(startLineNumber, startColumn - 1, endLineNumber, endColumn + 1);\n }\n if (startInsideSurrogatePair) {\n // only expand range at the start\n return new Range(startLineNumber, startColumn - 1, endLineNumber, endColumn);\n }\n // only expand range at the end\n return new Range(startLineNumber, startColumn, endLineNumber, endColumn + 1);\n }\n return new Range(startLineNumber, startColumn, endLineNumber, endColumn);\n }\n modifyPosition(rawPosition, offset) {\n this._assertNotDisposed();\n const candidate = this.getOffsetAt(rawPosition) + offset;\n return this.getPositionAt(Math.min(this._buffer.getLength(), Math.max(0, candidate)));\n }\n getFullModelRange() {\n this._assertNotDisposed();\n const lineCount = this.getLineCount();\n return new Range(1, 1, lineCount, this.getLineMaxColumn(lineCount));\n }\n findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount) {\n return this._buffer.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);\n }\n findMatches(searchString, rawSearchScope, isRegex, matchCase, wordSeparators, captureMatches, limitResultCount = LIMIT_FIND_COUNT) {\n this._assertNotDisposed();\n let searchRanges = null;\n if (rawSearchScope !== null) {\n if (!Array.isArray(rawSearchScope)) {\n rawSearchScope = [rawSearchScope];\n }\n if (rawSearchScope.every((searchScope) => Range.isIRange(searchScope))) {\n searchRanges = rawSearchScope.map((searchScope) => this.validateRange(searchScope));\n }\n }\n if (searchRanges === null) {\n searchRanges = [this.getFullModelRange()];\n }\n searchRanges = searchRanges.sort((d1, d2) => d1.startLineNumber - d2.startLineNumber || d1.startColumn - d2.startColumn);\n const uniqueSearchRanges = [];\n uniqueSearchRanges.push(searchRanges.reduce((prev, curr) => {\n if (Range.areIntersecting(prev, curr)) {\n return prev.plusRange(curr);\n }\n uniqueSearchRanges.push(prev);\n return curr;\n }));\n let matchMapper;\n if (!isRegex && searchString.indexOf('\\n') < 0) {\n // not regex, not multi line\n const searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators);\n const searchData = searchParams.parseSearchRequest();\n if (!searchData) {\n return [];\n }\n matchMapper = (searchRange) => this.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);\n }\n else {\n matchMapper = (searchRange) => TextModelSearch.findMatches(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchRange, captureMatches, limitResultCount);\n }\n return uniqueSearchRanges.map(matchMapper).reduce((arr, matches) => arr.concat(matches), []);\n }\n findNextMatch(searchString, rawSearchStart, isRegex, matchCase, wordSeparators, captureMatches) {\n this._assertNotDisposed();\n const searchStart = this.validatePosition(rawSearchStart);\n if (!isRegex && searchString.indexOf('\\n') < 0) {\n const searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators);\n const searchData = searchParams.parseSearchRequest();\n if (!searchData) {\n return null;\n }\n const lineCount = this.getLineCount();\n let searchRange = new Range(searchStart.lineNumber, searchStart.column, lineCount, this.getLineMaxColumn(lineCount));\n let ret = this.findMatchesLineByLine(searchRange, searchData, captureMatches, 1);\n TextModelSearch.findNextMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches);\n if (ret.length > 0) {\n return ret[0];\n }\n searchRange = new Range(1, 1, searchStart.lineNumber, this.getLineMaxColumn(searchStart.lineNumber));\n ret = this.findMatchesLineByLine(searchRange, searchData, captureMatches, 1);\n if (ret.length > 0) {\n return ret[0];\n }\n return null;\n }\n return TextModelSearch.findNextMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches);\n }\n findPreviousMatch(searchString, rawSearchStart, isRegex, matchCase, wordSeparators, captureMatches) {\n this._assertNotDisposed();\n const searchStart = this.validatePosition(rawSearchStart);\n return TextModelSearch.findPreviousMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches);\n }\n //#endregion\n //#region Editing\n pushStackElement() {\n this._commandManager.pushStackElement();\n }\n popStackElement() {\n this._commandManager.popStackElement();\n }\n pushEOL(eol) {\n const currentEOL = (this.getEOL() === '\\n' ? 0 /* model.EndOfLineSequence.LF */ : 1 /* model.EndOfLineSequence.CRLF */);\n if (currentEOL === eol) {\n return;\n }\n try {\n this._onDidChangeDecorations.beginDeferredEmit();\n this._eventEmitter.beginDeferredEmit();\n if (this._initialUndoRedoSnapshot === null) {\n this._initialUndoRedoSnapshot = this._undoRedoService.createSnapshot(this.uri);\n }\n this._commandManager.pushEOL(eol);\n }\n finally {\n this._eventEmitter.endDeferredEmit();\n this._onDidChangeDecorations.endDeferredEmit();\n }\n }\n _validateEditOperation(rawOperation) {\n if (rawOperation instanceof model.ValidAnnotatedEditOperation) {\n return rawOperation;\n }\n return new model.ValidAnnotatedEditOperation(rawOperation.identifier || null, this.validateRange(rawOperation.range), rawOperation.text, rawOperation.forceMoveMarkers || false, rawOperation.isAutoWhitespaceEdit || false, rawOperation._isTracked || false);\n }\n _validateEditOperations(rawOperations) {\n const result = [];\n for (let i = 0, len = rawOperations.length; i < len; i++) {\n result[i] = this._validateEditOperation(rawOperations[i]);\n }\n return result;\n }\n pushEditOperations(beforeCursorState, editOperations, cursorStateComputer) {\n try {\n this._onDidChangeDecorations.beginDeferredEmit();\n this._eventEmitter.beginDeferredEmit();\n return this._pushEditOperations(beforeCursorState, this._validateEditOperations(editOperations), cursorStateComputer);\n }\n finally {\n this._eventEmitter.endDeferredEmit();\n this._onDidChangeDecorations.endDeferredEmit();\n }\n }\n _pushEditOperations(beforeCursorState, editOperations, cursorStateComputer) {\n if (this._options.trimAutoWhitespace && this._trimAutoWhitespaceLines) {\n // Go through each saved line number and insert a trim whitespace edit\n // if it is safe to do so (no conflicts with other edits).\n const incomingEdits = editOperations.map((op) => {\n return {\n range: this.validateRange(op.range),\n text: op.text\n };\n });\n // Sometimes, auto-formatters change ranges automatically which can cause undesired auto whitespace trimming near the cursor\n // We'll use the following heuristic: if the edits occur near the cursor, then it's ok to trim auto whitespace\n let editsAreNearCursors = true;\n if (beforeCursorState) {\n for (let i = 0, len = beforeCursorState.length; i < len; i++) {\n const sel = beforeCursorState[i];\n let foundEditNearSel = false;\n for (let j = 0, lenJ = incomingEdits.length; j < lenJ; j++) {\n const editRange = incomingEdits[j].range;\n const selIsAbove = editRange.startLineNumber > sel.endLineNumber;\n const selIsBelow = sel.startLineNumber > editRange.endLineNumber;\n if (!selIsAbove && !selIsBelow) {\n foundEditNearSel = true;\n break;\n }\n }\n if (!foundEditNearSel) {\n editsAreNearCursors = false;\n break;\n }\n }\n }\n if (editsAreNearCursors) {\n for (let i = 0, len = this._trimAutoWhitespaceLines.length; i < len; i++) {\n const trimLineNumber = this._trimAutoWhitespaceLines[i];\n const maxLineColumn = this.getLineMaxColumn(trimLineNumber);\n let allowTrimLine = true;\n for (let j = 0, lenJ = incomingEdits.length; j < lenJ; j++) {\n const editRange = incomingEdits[j].range;\n const editText = incomingEdits[j].text;\n if (trimLineNumber < editRange.startLineNumber || trimLineNumber > editRange.endLineNumber) {\n // `trimLine` is completely outside this edit\n continue;\n }\n // At this point:\n // editRange.startLineNumber <= trimLine <= editRange.endLineNumber\n if (trimLineNumber === editRange.startLineNumber && editRange.startColumn === maxLineColumn\n && editRange.isEmpty() && editText && editText.length > 0 && editText.charAt(0) === '\\n') {\n // This edit inserts a new line (and maybe other text) after `trimLine`\n continue;\n }\n if (trimLineNumber === editRange.startLineNumber && editRange.startColumn === 1\n && editRange.isEmpty() && editText && editText.length > 0 && editText.charAt(editText.length - 1) === '\\n') {\n // This edit inserts a new line (and maybe other text) before `trimLine`\n continue;\n }\n // Looks like we can't trim this line as it would interfere with an incoming edit\n allowTrimLine = false;\n break;\n }\n if (allowTrimLine) {\n const trimRange = new Range(trimLineNumber, 1, trimLineNumber, maxLineColumn);\n editOperations.push(new model.ValidAnnotatedEditOperation(null, trimRange, null, false, false, false));\n }\n }\n }\n this._trimAutoWhitespaceLines = null;\n }\n if (this._initialUndoRedoSnapshot === null) {\n this._initialUndoRedoSnapshot = this._undoRedoService.createSnapshot(this.uri);\n }\n return this._commandManager.pushEditOperation(beforeCursorState, editOperations, cursorStateComputer);\n }\n _applyUndo(changes, eol, resultingAlternativeVersionId, resultingSelection) {\n const edits = changes.map((change) => {\n const rangeStart = this.getPositionAt(change.newPosition);\n const rangeEnd = this.getPositionAt(change.newEnd);\n return {\n range: new Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column),\n text: change.oldText\n };\n });\n this._applyUndoRedoEdits(edits, eol, true, false, resultingAlternativeVersionId, resultingSelection);\n }\n _applyRedo(changes, eol, resultingAlternativeVersionId, resultingSelection) {\n const edits = changes.map((change) => {\n const rangeStart = this.getPositionAt(change.oldPosition);\n const rangeEnd = this.getPositionAt(change.oldEnd);\n return {\n range: new Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column),\n text: change.newText\n };\n });\n this._applyUndoRedoEdits(edits, eol, false, true, resultingAlternativeVersionId, resultingSelection);\n }\n _applyUndoRedoEdits(edits, eol, isUndoing, isRedoing, resultingAlternativeVersionId, resultingSelection) {\n try {\n this._onDidChangeDecorations.beginDeferredEmit();\n this._eventEmitter.beginDeferredEmit();\n this._isUndoing = isUndoing;\n this._isRedoing = isRedoing;\n this.applyEdits(edits, false);\n this.setEOL(eol);\n this._overwriteAlternativeVersionId(resultingAlternativeVersionId);\n }\n finally {\n this._isUndoing = false;\n this._isRedoing = false;\n this._eventEmitter.endDeferredEmit(resultingSelection);\n this._onDidChangeDecorations.endDeferredEmit();\n }\n }\n applyEdits(rawOperations, computeUndoEdits = false) {\n try {\n this._onDidChangeDecorations.beginDeferredEmit();\n this._eventEmitter.beginDeferredEmit();\n const operations = this._validateEditOperations(rawOperations);\n return this._doApplyEdits(operations, computeUndoEdits);\n }\n finally {\n this._eventEmitter.endDeferredEmit();\n this._onDidChangeDecorations.endDeferredEmit();\n }\n }\n _doApplyEdits(rawOperations, computeUndoEdits) {\n const oldLineCount = this._buffer.getLineCount();\n const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace, computeUndoEdits);\n const newLineCount = this._buffer.getLineCount();\n const contentChanges = result.changes;\n this._trimAutoWhitespaceLines = result.trimAutoWhitespaceLineNumbers;\n if (contentChanges.length !== 0) {\n // We do a first pass to update tokens and decorations\n // because we want to read decorations in the second pass\n // where we will emit content change events\n // and we want to read the final decorations\n for (let i = 0, len = contentChanges.length; i < len; i++) {\n const change = contentChanges[i];\n const [eolCount, firstLineLength, lastLineLength] = countEOL(change.text);\n this._tokenizationTextModelPart.acceptEdit(change.range, change.text, eolCount, firstLineLength, lastLineLength);\n this._decorationsTree.acceptReplace(change.rangeOffset, change.rangeLength, change.text.length, change.forceMoveMarkers);\n }\n const rawContentChanges = [];\n this._increaseVersionId();\n let lineCount = oldLineCount;\n for (let i = 0, len = contentChanges.length; i < len; i++) {\n const change = contentChanges[i];\n const [eolCount] = countEOL(change.text);\n this._onDidChangeDecorations.fire();\n const startLineNumber = change.range.startLineNumber;\n const endLineNumber = change.range.endLineNumber;\n const deletingLinesCnt = endLineNumber - startLineNumber;\n const insertingLinesCnt = eolCount;\n const editingLinesCnt = Math.min(deletingLinesCnt, insertingLinesCnt);\n const changeLineCountDelta = (insertingLinesCnt - deletingLinesCnt);\n const currentEditStartLineNumber = newLineCount - lineCount - changeLineCountDelta + startLineNumber;\n const firstEditLineNumber = currentEditStartLineNumber;\n const lastInsertedLineNumber = currentEditStartLineNumber + insertingLinesCnt;\n const decorationsWithInjectedTextInEditedRange = this._decorationsTree.getInjectedTextInInterval(this, this.getOffsetAt(new Position(firstEditLineNumber, 1)), this.getOffsetAt(new Position(lastInsertedLineNumber, this.getLineMaxColumn(lastInsertedLineNumber))), 0);\n const injectedTextInEditedRange = LineInjectedText.fromDecorations(decorationsWithInjectedTextInEditedRange);\n const injectedTextInEditedRangeQueue = new ArrayQueue(injectedTextInEditedRange);\n for (let j = editingLinesCnt; j >= 0; j--) {\n const editLineNumber = startLineNumber + j;\n const currentEditLineNumber = currentEditStartLineNumber + j;\n injectedTextInEditedRangeQueue.takeFromEndWhile(r => r.lineNumber > currentEditLineNumber);\n const decorationsInCurrentLine = injectedTextInEditedRangeQueue.takeFromEndWhile(r => r.lineNumber === currentEditLineNumber);\n rawContentChanges.push(new ModelRawLineChanged(editLineNumber, this.getLineContent(currentEditLineNumber), decorationsInCurrentLine));\n }\n if (editingLinesCnt < deletingLinesCnt) {\n // Must delete some lines\n const spliceStartLineNumber = startLineNumber + editingLinesCnt;\n rawContentChanges.push(new ModelRawLinesDeleted(spliceStartLineNumber + 1, endLineNumber));\n }\n if (editingLinesCnt < insertingLinesCnt) {\n const injectedTextInEditedRangeQueue = new ArrayQueue(injectedTextInEditedRange);\n // Must insert some lines\n const spliceLineNumber = startLineNumber + editingLinesCnt;\n const cnt = insertingLinesCnt - editingLinesCnt;\n const fromLineNumber = newLineCount - lineCount - cnt + spliceLineNumber + 1;\n const injectedTexts = [];\n const newLines = [];\n for (let i = 0; i < cnt; i++) {\n const lineNumber = fromLineNumber + i;\n newLines[i] = this.getLineContent(lineNumber);\n injectedTextInEditedRangeQueue.takeWhile(r => r.lineNumber < lineNumber);\n injectedTexts[i] = injectedTextInEditedRangeQueue.takeWhile(r => r.lineNumber === lineNumber);\n }\n rawContentChanges.push(new ModelRawLinesInserted(spliceLineNumber + 1, startLineNumber + insertingLinesCnt, newLines, injectedTexts));\n }\n lineCount += changeLineCountDelta;\n }\n this._emitContentChangedEvent(new ModelRawContentChangedEvent(rawContentChanges, this.getVersionId(), this._isUndoing, this._isRedoing), {\n changes: contentChanges,\n eol: this._buffer.getEOL(),\n versionId: this.getVersionId(),\n isUndoing: this._isUndoing,\n isRedoing: this._isRedoing,\n isFlush: false\n });\n }\n return (result.reverseEdits === null ? undefined : result.reverseEdits);\n }\n undo() {\n return this._undoRedoService.undo(this.uri);\n }\n canUndo() {\n return this._undoRedoService.canUndo(this.uri);\n }\n redo() {\n return this._undoRedoService.redo(this.uri);\n }\n canRedo() {\n return this._undoRedoService.canRedo(this.uri);\n }\n //#endregion\n //#region Decorations\n handleBeforeFireDecorationsChangedEvent(affectedInjectedTextLines) {\n // This is called before the decoration changed event is fired.\n if (affectedInjectedTextLines === null || affectedInjectedTextLines.size === 0) {\n return;\n }\n const affectedLines = Array.from(affectedInjectedTextLines);\n const lineChangeEvents = affectedLines.map(lineNumber => new ModelRawLineChanged(lineNumber, this.getLineContent(lineNumber), this._getInjectedTextInLine(lineNumber)));\n this._onDidChangeInjectedText.fire(new ModelInjectedTextChangedEvent(lineChangeEvents));\n }\n changeDecorations(callback, ownerId = 0) {\n this._assertNotDisposed();\n try {\n this._onDidChangeDecorations.beginDeferredEmit();\n return this._changeDecorations(ownerId, callback);\n }\n finally {\n this._onDidChangeDecorations.endDeferredEmit();\n }\n }\n _changeDecorations(ownerId, callback) {\n const changeAccessor = {\n addDecoration: (range, options) => {\n return this._deltaDecorationsImpl(ownerId, [], [{ range: range, options: options }])[0];\n },\n changeDecoration: (id, newRange) => {\n this._changeDecorationImpl(id, newRange);\n },\n changeDecorationOptions: (id, options) => {\n this._changeDecorationOptionsImpl(id, _normalizeOptions(options));\n },\n removeDecoration: (id) => {\n this._deltaDecorationsImpl(ownerId, [id], []);\n },\n deltaDecorations: (oldDecorations, newDecorations) => {\n if (oldDecorations.length === 0 && newDecorations.length === 0) {\n // nothing to do\n return [];\n }\n return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);\n }\n };\n let result = null;\n try {\n result = callback(changeAccessor);\n }\n catch (e) {\n onUnexpectedError(e);\n }\n // Invalidate change accessor\n changeAccessor.addDecoration = invalidFunc;\n changeAccessor.changeDecoration = invalidFunc;\n changeAccessor.changeDecorationOptions = invalidFunc;\n changeAccessor.removeDecoration = invalidFunc;\n changeAccessor.deltaDecorations = invalidFunc;\n return result;\n }\n deltaDecorations(oldDecorations, newDecorations, ownerId = 0) {\n this._assertNotDisposed();\n if (!oldDecorations) {\n oldDecorations = [];\n }\n if (oldDecorations.length === 0 && newDecorations.length === 0) {\n // nothing to do\n return [];\n }\n try {\n this._deltaDecorationCallCnt++;\n if (this._deltaDecorationCallCnt > 1) {\n console.warn(`Invoking deltaDecorations recursively could lead to leaking decorations.`);\n onUnexpectedError(new Error(`Invoking deltaDecorations recursively could lead to leaking decorations.`));\n }\n this._onDidChangeDecorations.beginDeferredEmit();\n return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);\n }\n finally {\n this._onDidChangeDecorations.endDeferredEmit();\n this._deltaDecorationCallCnt--;\n }\n }\n _getTrackedRange(id) {\n return this.getDecorationRange(id);\n }\n _setTrackedRange(id, newRange, newStickiness) {\n const node = (id ? this._decorations[id] : null);\n if (!node) {\n if (!newRange) {\n // node doesn't exist, the request is to delete => nothing to do\n return null;\n }\n // node doesn't exist, the request is to set => add the tracked range\n return this._deltaDecorationsImpl(0, [], [{ range: newRange, options: TRACKED_RANGE_OPTIONS[newStickiness] }])[0];\n }\n if (!newRange) {\n // node exists, the request is to delete => delete node\n this._decorationsTree.delete(node);\n delete this._decorations[node.id];\n return null;\n }\n // node exists, the request is to set => change the tracked range and its options\n const range = this._validateRangeRelaxedNoAllocations(newRange);\n const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);\n const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);\n this._decorationsTree.delete(node);\n node.reset(this.getVersionId(), startOffset, endOffset, range);\n node.setOptions(TRACKED_RANGE_OPTIONS[newStickiness]);\n this._decorationsTree.insert(node);\n return node.id;\n }\n removeAllDecorationsWithOwnerId(ownerId) {\n if (this._isDisposed) {\n return;\n }\n const nodes = this._decorationsTree.collectNodesFromOwner(ownerId);\n for (let i = 0, len = nodes.length; i < len; i++) {\n const node = nodes[i];\n this._decorationsTree.delete(node);\n delete this._decorations[node.id];\n }\n }\n getDecorationOptions(decorationId) {\n const node = this._decorations[decorationId];\n if (!node) {\n return null;\n }\n return node.options;\n }\n getDecorationRange(decorationId) {\n const node = this._decorations[decorationId];\n if (!node) {\n return null;\n }\n return this._decorationsTree.getNodeRange(this, node);\n }\n getLineDecorations(lineNumber, ownerId = 0, filterOutValidation = false) {\n if (lineNumber < 1 || lineNumber > this.getLineCount()) {\n return [];\n }\n return this.getLinesDecorations(lineNumber, lineNumber, ownerId, filterOutValidation);\n }\n getLinesDecorations(_startLineNumber, _endLineNumber, ownerId = 0, filterOutValidation = false) {\n const lineCount = this.getLineCount();\n const startLineNumber = Math.min(lineCount, Math.max(1, _startLineNumber));\n const endLineNumber = Math.min(lineCount, Math.max(1, _endLineNumber));\n const endColumn = this.getLineMaxColumn(endLineNumber);\n const range = new Range(startLineNumber, 1, endLineNumber, endColumn);\n const decorations = this._getDecorationsInRange(range, ownerId, filterOutValidation);\n pushMany(decorations, this._decorationProvider.getDecorationsInRange(range, ownerId, filterOutValidation));\n return decorations;\n }\n getDecorationsInRange(range, ownerId = 0, filterOutValidation = false) {\n const validatedRange = this.validateRange(range);\n const decorations = this._getDecorationsInRange(validatedRange, ownerId, filterOutValidation);\n pushMany(decorations, this._decorationProvider.getDecorationsInRange(validatedRange, ownerId, filterOutValidation));\n return decorations;\n }\n getOverviewRulerDecorations(ownerId = 0, filterOutValidation = false) {\n return this._decorationsTree.getAll(this, ownerId, filterOutValidation, true);\n }\n getInjectedTextDecorations(ownerId = 0) {\n return this._decorationsTree.getAllInjectedText(this, ownerId);\n }\n _getInjectedTextInLine(lineNumber) {\n const startOffset = this._buffer.getOffsetAt(lineNumber, 1);\n const endOffset = startOffset + this._buffer.getLineLength(lineNumber);\n const result = this._decorationsTree.getInjectedTextInInterval(this, startOffset, endOffset, 0);\n return LineInjectedText.fromDecorations(result).filter(t => t.lineNumber === lineNumber);\n }\n getAllDecorations(ownerId = 0, filterOutValidation = false) {\n let result = this._decorationsTree.getAll(this, ownerId, filterOutValidation, false);\n result = result.concat(this._decorationProvider.getAllDecorations(ownerId, filterOutValidation));\n return result;\n }\n _getDecorationsInRange(filterRange, filterOwnerId, filterOutValidation) {\n const startOffset = this._buffer.getOffsetAt(filterRange.startLineNumber, filterRange.startColumn);\n const endOffset = this._buffer.getOffsetAt(filterRange.endLineNumber, filterRange.endColumn);\n return this._decorationsTree.getAllInInterval(this, startOffset, endOffset, filterOwnerId, filterOutValidation);\n }\n getRangeAt(start, end) {\n return this._buffer.getRangeAt(start, end - start);\n }\n _changeDecorationImpl(decorationId, _range) {\n const node = this._decorations[decorationId];\n if (!node) {\n return;\n }\n if (node.options.after) {\n const oldRange = this.getDecorationRange(decorationId);\n this._onDidChangeDecorations.recordLineAffectedByInjectedText(oldRange.endLineNumber);\n }\n if (node.options.before) {\n const oldRange = this.getDecorationRange(decorationId);\n this._onDidChangeDecorations.recordLineAffectedByInjectedText(oldRange.startLineNumber);\n }\n const range = this._validateRangeRelaxedNoAllocations(_range);\n const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);\n const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);\n this._decorationsTree.delete(node);\n node.reset(this.getVersionId(), startOffset, endOffset, range);\n this._decorationsTree.insert(node);\n this._onDidChangeDecorations.checkAffectedAndFire(node.options);\n if (node.options.after) {\n this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.endLineNumber);\n }\n if (node.options.before) {\n this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.startLineNumber);\n }\n }\n _changeDecorationOptionsImpl(decorationId, options) {\n const node = this._decorations[decorationId];\n if (!node) {\n return;\n }\n const nodeWasInOverviewRuler = (node.options.overviewRuler && node.options.overviewRuler.color ? true : false);\n const nodeIsInOverviewRuler = (options.overviewRuler && options.overviewRuler.color ? true : false);\n this._onDidChangeDecorations.checkAffectedAndFire(node.options);\n this._onDidChangeDecorations.checkAffectedAndFire(options);\n if (node.options.after || options.after) {\n const nodeRange = this._decorationsTree.getNodeRange(this, node);\n this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.endLineNumber);\n }\n if (node.options.before || options.before) {\n const nodeRange = this._decorationsTree.getNodeRange(this, node);\n this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.startLineNumber);\n }\n if (nodeWasInOverviewRuler !== nodeIsInOverviewRuler) {\n // Delete + Insert due to an overview ruler status change\n this._decorationsTree.delete(node);\n node.setOptions(options);\n this._decorationsTree.insert(node);\n }\n else {\n node.setOptions(options);\n }\n }\n _deltaDecorationsImpl(ownerId, oldDecorationsIds, newDecorations) {\n const versionId = this.getVersionId();\n const oldDecorationsLen = oldDecorationsIds.length;\n let oldDecorationIndex = 0;\n const newDecorationsLen = newDecorations.length;\n let newDecorationIndex = 0;\n const result = new Array(newDecorationsLen);\n while (oldDecorationIndex < oldDecorationsLen || newDecorationIndex < newDecorationsLen) {\n let node = null;\n if (oldDecorationIndex < oldDecorationsLen) {\n // (1) get ourselves an old node\n do {\n node = this._decorations[oldDecorationsIds[oldDecorationIndex++]];\n } while (!node && oldDecorationIndex < oldDecorationsLen);\n // (2) remove the node from the tree (if it exists)\n if (node) {\n if (node.options.after) {\n const nodeRange = this._decorationsTree.getNodeRange(this, node);\n this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.endLineNumber);\n }\n if (node.options.before) {\n const nodeRange = this._decorationsTree.getNodeRange(this, node);\n this._onDidChangeDecorations.recordLineAffectedByInjectedText(nodeRange.startLineNumber);\n }\n this._decorationsTree.delete(node);\n this._onDidChangeDecorations.checkAffectedAndFire(node.options);\n }\n }\n if (newDecorationIndex < newDecorationsLen) {\n // (3) create a new node if necessary\n if (!node) {\n const internalDecorationId = (++this._lastDecorationId);\n const decorationId = `${this._instanceId};${internalDecorationId}`;\n node = new IntervalNode(decorationId, 0, 0);\n this._decorations[decorationId] = node;\n }\n // (4) initialize node\n const newDecoration = newDecorations[newDecorationIndex];\n const range = this._validateRangeRelaxedNoAllocations(newDecoration.range);\n const options = _normalizeOptions(newDecoration.options);\n const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn);\n const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn);\n node.ownerId = ownerId;\n node.reset(versionId, startOffset, endOffset, range);\n node.setOptions(options);\n if (node.options.after) {\n this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.endLineNumber);\n }\n if (node.options.before) {\n this._onDidChangeDecorations.recordLineAffectedByInjectedText(range.startLineNumber);\n }\n this._onDidChangeDecorations.checkAffectedAndFire(options);\n this._decorationsTree.insert(node);\n result[newDecorationIndex] = node.id;\n newDecorationIndex++;\n }\n else {\n if (node) {\n delete this._decorations[node.id];\n }\n }\n }\n return result;\n }\n //#endregion\n //#region Tokenization\n // TODO move them to the tokenization part.\n getLanguageId() {\n return this.tokenization.getLanguageId();\n }\n setMode(languageId) {\n this.tokenization.setLanguageId(languageId);\n }\n getLanguageIdAtPosition(lineNumber, column) {\n return this.tokenization.getLanguageIdAtPosition(lineNumber, column);\n }\n getWordAtPosition(position) {\n return this._tokenizationTextModelPart.getWordAtPosition(position);\n }\n getWordUntilPosition(position) {\n return this._tokenizationTextModelPart.getWordUntilPosition(position);\n }\n //#endregion\n normalizePosition(position, affinity) {\n return position;\n }\n /**\n * Gets the column at which indentation stops at a given line.\n * @internal\n */\n getLineIndentColumn(lineNumber) {\n // Columns start with 1.\n return indentOfLine(this.getLineContent(lineNumber)) + 1;\n }\n};\nTextModel.MODEL_SYNC_LIMIT = 50 * 1024 * 1024; // 50 MB\nTextModel.LARGE_FILE_SIZE_THRESHOLD = 20 * 1024 * 1024; // 20 MB;\nTextModel.LARGE_FILE_LINE_COUNT_THRESHOLD = 300 * 1000; // 300K lines\nTextModel.DEFAULT_CREATION_OPTIONS = {\n isForSimpleWidget: false,\n tabSize: EDITOR_MODEL_DEFAULTS.tabSize,\n indentSize: EDITOR_MODEL_DEFAULTS.indentSize,\n insertSpaces: EDITOR_MODEL_DEFAULTS.insertSpaces,\n detectIndentation: false,\n defaultEOL: 1 /* model.DefaultEndOfLine.LF */,\n trimAutoWhitespace: EDITOR_MODEL_DEFAULTS.trimAutoWhitespace,\n largeFileOptimizations: EDITOR_MODEL_DEFAULTS.largeFileOptimizations,\n bracketPairColorizationOptions: EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions,\n};\nTextModel = __decorate([\n __param(4, IUndoRedoService),\n __param(5, ILanguageService),\n __param(6, ILanguageConfigurationService)\n], TextModel);\nexport { TextModel };\nfunction indentOfLine(line) {\n let indent = 0;\n for (const c of line) {\n if (c === ' ' || c === '\\t') {\n indent++;\n }\n else {\n break;\n }\n }\n return indent;\n}\n//#region Decorations\nfunction isNodeInOverviewRuler(node) {\n return (node.options.overviewRuler && node.options.overviewRuler.color ? true : false);\n}\nfunction isNodeInjectedText(node) {\n return !!node.options.after || !!node.options.before;\n}\nclass DecorationsTrees {\n constructor() {\n this._decorationsTree0 = new IntervalTree();\n this._decorationsTree1 = new IntervalTree();\n this._injectedTextDecorationsTree = new IntervalTree();\n }\n ensureAllNodesHaveRanges(host) {\n this.getAll(host, 0, false, false);\n }\n _ensureNodesHaveRanges(host, nodes) {\n for (const node of nodes) {\n if (node.range === null) {\n node.range = host.getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd);\n }\n }\n return nodes;\n }\n getAllInInterval(host, start, end, filterOwnerId, filterOutValidation) {\n const versionId = host.getVersionId();\n const result = this._intervalSearch(start, end, filterOwnerId, filterOutValidation, versionId);\n return this._ensureNodesHaveRanges(host, result);\n }\n _intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId) {\n const r0 = this._decorationsTree0.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId);\n const r1 = this._decorationsTree1.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId);\n const r2 = this._injectedTextDecorationsTree.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId);\n return r0.concat(r1).concat(r2);\n }\n getInjectedTextInInterval(host, start, end, filterOwnerId) {\n const versionId = host.getVersionId();\n const result = this._injectedTextDecorationsTree.intervalSearch(start, end, filterOwnerId, false, versionId);\n return this._ensureNodesHaveRanges(host, result).filter((i) => i.options.showIfCollapsed || !i.range.isEmpty());\n }\n getAllInjectedText(host, filterOwnerId) {\n const versionId = host.getVersionId();\n const result = this._injectedTextDecorationsTree.search(filterOwnerId, false, versionId);\n return this._ensureNodesHaveRanges(host, result).filter((i) => i.options.showIfCollapsed || !i.range.isEmpty());\n }\n getAll(host, filterOwnerId, filterOutValidation, overviewRulerOnly) {\n const versionId = host.getVersionId();\n const result = this._search(filterOwnerId, filterOutValidation, overviewRulerOnly, versionId);\n return this._ensureNodesHaveRanges(host, result);\n }\n _search(filterOwnerId, filterOutValidation, overviewRulerOnly, cachedVersionId) {\n if (overviewRulerOnly) {\n return this._decorationsTree1.search(filterOwnerId, filterOutValidation, cachedVersionId);\n }\n else {\n const r0 = this._decorationsTree0.search(filterOwnerId, filterOutValidation, cachedVersionId);\n const r1 = this._decorationsTree1.search(filterOwnerId, filterOutValidation, cachedVersionId);\n const r2 = this._injectedTextDecorationsTree.search(filterOwnerId, filterOutValidation, cachedVersionId);\n return r0.concat(r1).concat(r2);\n }\n }\n collectNodesFromOwner(ownerId) {\n const r0 = this._decorationsTree0.collectNodesFromOwner(ownerId);\n const r1 = this._decorationsTree1.collectNodesFromOwner(ownerId);\n const r2 = this._injectedTextDecorationsTree.collectNodesFromOwner(ownerId);\n return r0.concat(r1).concat(r2);\n }\n collectNodesPostOrder() {\n const r0 = this._decorationsTree0.collectNodesPostOrder();\n const r1 = this._decorationsTree1.collectNodesPostOrder();\n const r2 = this._injectedTextDecorationsTree.collectNodesPostOrder();\n return r0.concat(r1).concat(r2);\n }\n insert(node) {\n if (isNodeInjectedText(node)) {\n this._injectedTextDecorationsTree.insert(node);\n }\n else if (isNodeInOverviewRuler(node)) {\n this._decorationsTree1.insert(node);\n }\n else {\n this._decorationsTree0.insert(node);\n }\n }\n delete(node) {\n if (isNodeInjectedText(node)) {\n this._injectedTextDecorationsTree.delete(node);\n }\n else if (isNodeInOverviewRuler(node)) {\n this._decorationsTree1.delete(node);\n }\n else {\n this._decorationsTree0.delete(node);\n }\n }\n getNodeRange(host, node) {\n const versionId = host.getVersionId();\n if (node.cachedVersionId !== versionId) {\n this._resolveNode(node, versionId);\n }\n if (node.range === null) {\n node.range = host.getRangeAt(node.cachedAbsoluteStart, node.cachedAbsoluteEnd);\n }\n return node.range;\n }\n _resolveNode(node, cachedVersionId) {\n if (isNodeInjectedText(node)) {\n this._injectedTextDecorationsTree.resolveNode(node, cachedVersionId);\n }\n else if (isNodeInOverviewRuler(node)) {\n this._decorationsTree1.resolveNode(node, cachedVersionId);\n }\n else {\n this._decorationsTree0.resolveNode(node, cachedVersionId);\n }\n }\n acceptReplace(offset, length, textLength, forceMoveMarkers) {\n this._decorationsTree0.acceptReplace(offset, length, textLength, forceMoveMarkers);\n this._decorationsTree1.acceptReplace(offset, length, textLength, forceMoveMarkers);\n this._injectedTextDecorationsTree.acceptReplace(offset, length, textLength, forceMoveMarkers);\n }\n}\nfunction cleanClassName(className) {\n return className.replace(/[^a-z0-9\\-_]/gi, ' ');\n}\nclass DecorationOptions {\n constructor(options) {\n this.color = options.color || '';\n this.darkColor = options.darkColor || '';\n }\n}\nexport class ModelDecorationOverviewRulerOptions extends DecorationOptions {\n constructor(options) {\n super(options);\n this._resolvedColor = null;\n this.position = (typeof options.position === 'number' ? options.position : model.OverviewRulerLane.Center);\n }\n getColor(theme) {\n if (!this._resolvedColor) {\n if (theme.type !== 'light' && this.darkColor) {\n this._resolvedColor = this._resolveColor(this.darkColor, theme);\n }\n else {\n this._resolvedColor = this._resolveColor(this.color, theme);\n }\n }\n return this._resolvedColor;\n }\n invalidateCachedColor() {\n this._resolvedColor = null;\n }\n _resolveColor(color, theme) {\n if (typeof color === 'string') {\n return color;\n }\n const c = color ? theme.getColor(color.id) : null;\n if (!c) {\n return '';\n }\n return c.toString();\n }\n}\nexport class ModelDecorationMinimapOptions extends DecorationOptions {\n constructor(options) {\n super(options);\n this.position = options.position;\n }\n getColor(theme) {\n if (!this._resolvedColor) {\n if (theme.type !== 'light' && this.darkColor) {\n this._resolvedColor = this._resolveColor(this.darkColor, theme);\n }\n else {\n this._resolvedColor = this._resolveColor(this.color, theme);\n }\n }\n return this._resolvedColor;\n }\n invalidateCachedColor() {\n this._resolvedColor = undefined;\n }\n _resolveColor(color, theme) {\n if (typeof color === 'string') {\n return Color.fromHex(color);\n }\n return theme.getColor(color.id);\n }\n}\nexport class ModelDecorationInjectedTextOptions {\n constructor(options) {\n this.content = options.content || '';\n this.inlineClassName = options.inlineClassName || null;\n this.inlineClassNameAffectsLetterSpacing = options.inlineClassNameAffectsLetterSpacing || false;\n this.attachedData = options.attachedData || null;\n this.cursorStops = options.cursorStops || null;\n }\n static from(options) {\n if (options instanceof ModelDecorationInjectedTextOptions) {\n return options;\n }\n return new ModelDecorationInjectedTextOptions(options);\n }\n}\nexport class ModelDecorationOptions {\n constructor(options) {\n var _a, _b;\n this.description = options.description;\n this.blockClassName = options.blockClassName ? cleanClassName(options.blockClassName) : null;\n this.stickiness = options.stickiness || 0 /* model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges */;\n this.zIndex = options.zIndex || 0;\n this.className = options.className ? cleanClassName(options.className) : null;\n this.hoverMessage = options.hoverMessage || null;\n this.glyphMarginHoverMessage = options.glyphMarginHoverMessage || null;\n this.isWholeLine = options.isWholeLine || false;\n this.showIfCollapsed = options.showIfCollapsed || false;\n this.collapseOnReplaceEdit = options.collapseOnReplaceEdit || false;\n this.overviewRuler = options.overviewRuler ? new ModelDecorationOverviewRulerOptions(options.overviewRuler) : null;\n this.minimap = options.minimap ? new ModelDecorationMinimapOptions(options.minimap) : null;\n this.glyphMarginClassName = options.glyphMarginClassName ? cleanClassName(options.glyphMarginClassName) : null;\n this.linesDecorationsClassName = options.linesDecorationsClassName ? cleanClassName(options.linesDecorationsClassName) : null;\n this.firstLineDecorationClassName = options.firstLineDecorationClassName ? cleanClassName(options.firstLineDecorationClassName) : null;\n this.marginClassName = options.marginClassName ? cleanClassName(options.marginClassName) : null;\n this.inlineClassName = options.inlineClassName ? cleanClassName(options.inlineClassName) : null;\n this.inlineClassNameAffectsLetterSpacing = options.inlineClassNameAffectsLetterSpacing || false;\n this.beforeContentClassName = options.beforeContentClassName ? cleanClassName(options.beforeContentClassName) : null;\n this.afterContentClassName = options.afterContentClassName ? cleanClassName(options.afterContentClassName) : null;\n this.after = options.after ? ModelDecorationInjectedTextOptions.from(options.after) : null;\n this.before = options.before ? ModelDecorationInjectedTextOptions.from(options.before) : null;\n this.hideInCommentTokens = (_a = options.hideInCommentTokens) !== null && _a !== void 0 ? _a : false;\n this.hideInStringTokens = (_b = options.hideInStringTokens) !== null && _b !== void 0 ? _b : false;\n }\n static register(options) {\n return new ModelDecorationOptions(options);\n }\n static createDynamic(options) {\n return new ModelDecorationOptions(options);\n }\n}\nModelDecorationOptions.EMPTY = ModelDecorationOptions.register({ description: 'empty' });\n/**\n * The order carefully matches the values of the enum.\n */\nconst TRACKED_RANGE_OPTIONS = [\n ModelDecorationOptions.register({ description: 'tracked-range-always-grows-when-typing-at-edges', stickiness: 0 /* model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges */ }),\n ModelDecorationOptions.register({ description: 'tracked-range-never-grows-when-typing-at-edges', stickiness: 1 /* model.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */ }),\n ModelDecorationOptions.register({ description: 'tracked-range-grows-only-when-typing-before', stickiness: 2 /* model.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore */ }),\n ModelDecorationOptions.register({ description: 'tracked-range-grows-only-when-typing-after', stickiness: 3 /* model.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter */ }),\n];\nfunction _normalizeOptions(options) {\n if (options instanceof ModelDecorationOptions) {\n return options;\n }\n return ModelDecorationOptions.createDynamic(options);\n}\nexport class DidChangeDecorationsEmitter extends Disposable {\n constructor(handleBeforeFire) {\n super();\n this.handleBeforeFire = handleBeforeFire;\n this._actual = this._register(new Emitter());\n this.event = this._actual.event;\n this._affectedInjectedTextLines = null;\n this._deferredCnt = 0;\n this._shouldFire = false;\n this._affectsMinimap = false;\n this._affectsOverviewRuler = false;\n }\n beginDeferredEmit() {\n this._deferredCnt++;\n }\n endDeferredEmit() {\n var _a;\n this._deferredCnt--;\n if (this._deferredCnt === 0) {\n if (this._shouldFire) {\n this.handleBeforeFire(this._affectedInjectedTextLines);\n const event = {\n affectsMinimap: this._affectsMinimap,\n affectsOverviewRuler: this._affectsOverviewRuler\n };\n this._shouldFire = false;\n this._affectsMinimap = false;\n this._affectsOverviewRuler = false;\n this._actual.fire(event);\n }\n (_a = this._affectedInjectedTextLines) === null || _a === void 0 ? void 0 : _a.clear();\n this._affectedInjectedTextLines = null;\n }\n }\n recordLineAffectedByInjectedText(lineNumber) {\n if (!this._affectedInjectedTextLines) {\n this._affectedInjectedTextLines = new Set();\n }\n this._affectedInjectedTextLines.add(lineNumber);\n }\n checkAffectedAndFire(options) {\n if (!this._affectsMinimap) {\n this._affectsMinimap = options.minimap && options.minimap.position ? true : false;\n }\n if (!this._affectsOverviewRuler) {\n this._affectsOverviewRuler = options.overviewRuler && options.overviewRuler.color ? true : false;\n }\n this._shouldFire = true;\n }\n fire() {\n this._affectsMinimap = true;\n this._affectsOverviewRuler = true;\n this._shouldFire = true;\n }\n}\n//#endregion\nexport class DidChangeContentEmitter extends Disposable {\n constructor() {\n super();\n /**\n * Both `fastEvent` and `slowEvent` work the same way and contain the same events, but first we invoke `fastEvent` and then `slowEvent`.\n */\n this._fastEmitter = this._register(new Emitter());\n this.fastEvent = this._fastEmitter.event;\n this._slowEmitter = this._register(new Emitter());\n this.slowEvent = this._slowEmitter.event;\n this._deferredCnt = 0;\n this._deferredEvent = null;\n }\n beginDeferredEmit() {\n this._deferredCnt++;\n }\n endDeferredEmit(resultingSelection = null) {\n this._deferredCnt--;\n if (this._deferredCnt === 0) {\n if (this._deferredEvent !== null) {\n this._deferredEvent.rawContentChangedEvent.resultingSelection = resultingSelection;\n const e = this._deferredEvent;\n this._deferredEvent = null;\n this._fastEmitter.fire(e);\n this._slowEmitter.fire(e);\n }\n }\n }\n fire(e) {\n if (this._deferredCnt > 0) {\n if (this._deferredEvent) {\n this._deferredEvent = this._deferredEvent.merge(e);\n }\n else {\n this._deferredEvent = e;\n }\n return;\n }\n this._fastEmitter.fire(e);\n this._slowEmitter.fire(e);\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 *--------------------------------------------------------------------------------------------*/\nimport { Disposable } from '../../../base/common/lifecycle.js';\nexport class TextModelPart extends Disposable {\n constructor() {\n super(...arguments);\n this._isDisposed = false;\n }\n dispose() {\n super.dispose();\n this._isDisposed = true;\n }\n assertNotDisposed() {\n if (this._isDisposed) {\n throw new Error('TextModelPart is disposed!');\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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../base/common/strings.js';\nimport { getMapForWordSeparators } from '../core/wordCharacterClassifier.js';\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nimport { FindMatch, SearchData } from '../model.js';\nconst LIMIT_FIND_COUNT = 999;\nexport class SearchParams {\n constructor(searchString, isRegex, matchCase, wordSeparators) {\n this.searchString = searchString;\n this.isRegex = isRegex;\n this.matchCase = matchCase;\n this.wordSeparators = wordSeparators;\n }\n parseSearchRequest() {\n if (this.searchString === '') {\n return null;\n }\n // Try to create a RegExp out of the params\n let multiline;\n if (this.isRegex) {\n multiline = isMultilineRegexSource(this.searchString);\n }\n else {\n multiline = (this.searchString.indexOf('\\n') >= 0);\n }\n let regex = null;\n try {\n regex = strings.createRegExp(this.searchString, this.isRegex, {\n matchCase: this.matchCase,\n wholeWord: false,\n multiline: multiline,\n global: true,\n unicode: true\n });\n }\n catch (err) {\n return null;\n }\n if (!regex) {\n return null;\n }\n let canUseSimpleSearch = (!this.isRegex && !multiline);\n if (canUseSimpleSearch && this.searchString.toLowerCase() !== this.searchString.toUpperCase()) {\n // casing might make a difference\n canUseSimpleSearch = this.matchCase;\n }\n return new SearchData(regex, this.wordSeparators ? getMapForWordSeparators(this.wordSeparators) : null, canUseSimpleSearch ? this.searchString : null);\n }\n}\nexport function isMultilineRegexSource(searchString) {\n if (!searchString || searchString.length === 0) {\n return false;\n }\n for (let i = 0, len = searchString.length; i < len; i++) {\n const chCode = searchString.charCodeAt(i);\n if (chCode === 10 /* CharCode.LineFeed */) {\n return true;\n }\n if (chCode === 92 /* CharCode.Backslash */) {\n // move to next char\n i++;\n if (i >= len) {\n // string ends with a \\\n break;\n }\n const nextChCode = searchString.charCodeAt(i);\n if (nextChCode === 110 /* CharCode.n */ || nextChCode === 114 /* CharCode.r */ || nextChCode === 87 /* CharCode.W */) {\n return true;\n }\n }\n }\n return false;\n}\nexport function createFindMatch(range, rawMatches, captureMatches) {\n if (!captureMatches) {\n return new FindMatch(range, null);\n }\n const matches = [];\n for (let i = 0, len = rawMatches.length; i < len; i++) {\n matches[i] = rawMatches[i];\n }\n return new FindMatch(range, matches);\n}\nclass LineFeedCounter {\n constructor(text) {\n const lineFeedsOffsets = [];\n let lineFeedsOffsetsLen = 0;\n for (let i = 0, textLen = text.length; i < textLen; i++) {\n if (text.charCodeAt(i) === 10 /* CharCode.LineFeed */) {\n lineFeedsOffsets[lineFeedsOffsetsLen++] = i;\n }\n }\n this._lineFeedsOffsets = lineFeedsOffsets;\n }\n findLineFeedCountBeforeOffset(offset) {\n const lineFeedsOffsets = this._lineFeedsOffsets;\n let min = 0;\n let max = lineFeedsOffsets.length - 1;\n if (max === -1) {\n // no line feeds\n return 0;\n }\n if (offset <= lineFeedsOffsets[0]) {\n // before first line feed\n return 0;\n }\n while (min < max) {\n const mid = min + ((max - min) / 2 >> 0);\n if (lineFeedsOffsets[mid] >= offset) {\n max = mid - 1;\n }\n else {\n if (lineFeedsOffsets[mid + 1] >= offset) {\n // bingo!\n min = mid;\n max = mid;\n }\n else {\n min = mid + 1;\n }\n }\n }\n return min + 1;\n }\n}\nexport class TextModelSearch {\n static findMatches(model, searchParams, searchRange, captureMatches, limitResultCount) {\n const searchData = searchParams.parseSearchRequest();\n if (!searchData) {\n return [];\n }\n if (searchData.regex.multiline) {\n return this._doFindMatchesMultiline(model, searchRange, new Searcher(searchData.wordSeparators, searchData.regex), captureMatches, limitResultCount);\n }\n return this._doFindMatchesLineByLine(model, searchRange, searchData, captureMatches, limitResultCount);\n }\n /**\n * Multiline search always executes on the lines concatenated with \\n.\n * We must therefore compensate for the count of \\n in case the model is CRLF\n */\n static _getMultilineMatchRange(model, deltaOffset, text, lfCounter, matchIndex, match0) {\n let startOffset;\n let lineFeedCountBeforeMatch = 0;\n if (lfCounter) {\n lineFeedCountBeforeMatch = lfCounter.findLineFeedCountBeforeOffset(matchIndex);\n startOffset = deltaOffset + matchIndex + lineFeedCountBeforeMatch /* add as many \\r as there were \\n */;\n }\n else {\n startOffset = deltaOffset + matchIndex;\n }\n let endOffset;\n if (lfCounter) {\n const lineFeedCountBeforeEndOfMatch = lfCounter.findLineFeedCountBeforeOffset(matchIndex + match0.length);\n const lineFeedCountInMatch = lineFeedCountBeforeEndOfMatch - lineFeedCountBeforeMatch;\n endOffset = startOffset + match0.length + lineFeedCountInMatch /* add as many \\r as there were \\n */;\n }\n else {\n endOffset = startOffset + match0.length;\n }\n const startPosition = model.getPositionAt(startOffset);\n const endPosition = model.getPositionAt(endOffset);\n return new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column);\n }\n static _doFindMatchesMultiline(model, searchRange, searcher, captureMatches, limitResultCount) {\n const deltaOffset = model.getOffsetAt(searchRange.getStartPosition());\n // We always execute multiline search over the lines joined with \\n\n // This makes it that \\n will match the EOL for both CRLF and LF models\n // We compensate for offset errors in `_getMultilineMatchRange`\n const text = model.getValueInRange(searchRange, 1 /* EndOfLinePreference.LF */);\n const lfCounter = (model.getEOL() === '\\r\\n' ? new LineFeedCounter(text) : null);\n const result = [];\n let counter = 0;\n let m;\n searcher.reset(0);\n while ((m = searcher.next(text))) {\n result[counter++] = createFindMatch(this._getMultilineMatchRange(model, deltaOffset, text, lfCounter, m.index, m[0]), m, captureMatches);\n if (counter >= limitResultCount) {\n return result;\n }\n }\n return result;\n }\n static _doFindMatchesLineByLine(model, searchRange, searchData, captureMatches, limitResultCount) {\n const result = [];\n let resultLen = 0;\n // Early case for a search range that starts & stops on the same line number\n if (searchRange.startLineNumber === searchRange.endLineNumber) {\n const text = model.getLineContent(searchRange.startLineNumber).substring(searchRange.startColumn - 1, searchRange.endColumn - 1);\n resultLen = this._findMatchesInLine(searchData, text, searchRange.startLineNumber, searchRange.startColumn - 1, resultLen, result, captureMatches, limitResultCount);\n return result;\n }\n // Collect results from first line\n const text = model.getLineContent(searchRange.startLineNumber).substring(searchRange.startColumn - 1);\n resultLen = this._findMatchesInLine(searchData, text, searchRange.startLineNumber, searchRange.startColumn - 1, resultLen, result, captureMatches, limitResultCount);\n // Collect results from middle lines\n for (let lineNumber = searchRange.startLineNumber + 1; lineNumber < searchRange.endLineNumber && resultLen < limitResultCount; lineNumber++) {\n resultLen = this._findMatchesInLine(searchData, model.getLineContent(lineNumber), lineNumber, 0, resultLen, result, captureMatches, limitResultCount);\n }\n // Collect results from last line\n if (resultLen < limitResultCount) {\n const text = model.getLineContent(searchRange.endLineNumber).substring(0, searchRange.endColumn - 1);\n resultLen = this._findMatchesInLine(searchData, text, searchRange.endLineNumber, 0, resultLen, result, captureMatches, limitResultCount);\n }\n return result;\n }\n static _findMatchesInLine(searchData, text, lineNumber, deltaOffset, resultLen, result, captureMatches, limitResultCount) {\n const wordSeparators = searchData.wordSeparators;\n if (!captureMatches && searchData.simpleSearch) {\n const searchString = searchData.simpleSearch;\n const searchStringLen = searchString.length;\n const textLength = text.length;\n let lastMatchIndex = -searchStringLen;\n while ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {\n if (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {\n result[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);\n if (resultLen >= limitResultCount) {\n return resultLen;\n }\n }\n }\n return resultLen;\n }\n const searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n let m;\n // Reset regex to search from the beginning\n searcher.reset(0);\n do {\n m = searcher.next(text);\n if (m) {\n result[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);\n if (resultLen >= limitResultCount) {\n return resultLen;\n }\n }\n } while (m);\n return resultLen;\n }\n static findNextMatch(model, searchParams, searchStart, captureMatches) {\n const searchData = searchParams.parseSearchRequest();\n if (!searchData) {\n return null;\n }\n const searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n if (searchData.regex.multiline) {\n return this._doFindNextMatchMultiline(model, searchStart, searcher, captureMatches);\n }\n return this._doFindNextMatchLineByLine(model, searchStart, searcher, captureMatches);\n }\n static _doFindNextMatchMultiline(model, searchStart, searcher, captureMatches) {\n const searchTextStart = new Position(searchStart.lineNumber, 1);\n const deltaOffset = model.getOffsetAt(searchTextStart);\n const lineCount = model.getLineCount();\n // We always execute multiline search over the lines joined with \\n\n // This makes it that \\n will match the EOL for both CRLF and LF models\n // We compensate for offset errors in `_getMultilineMatchRange`\n const text = model.getValueInRange(new Range(searchTextStart.lineNumber, searchTextStart.column, lineCount, model.getLineMaxColumn(lineCount)), 1 /* EndOfLinePreference.LF */);\n const lfCounter = (model.getEOL() === '\\r\\n' ? new LineFeedCounter(text) : null);\n searcher.reset(searchStart.column - 1);\n const m = searcher.next(text);\n if (m) {\n return createFindMatch(this._getMultilineMatchRange(model, deltaOffset, text, lfCounter, m.index, m[0]), m, captureMatches);\n }\n if (searchStart.lineNumber !== 1 || searchStart.column !== 1) {\n // Try again from the top\n return this._doFindNextMatchMultiline(model, new Position(1, 1), searcher, captureMatches);\n }\n return null;\n }\n static _doFindNextMatchLineByLine(model, searchStart, searcher, captureMatches) {\n const lineCount = model.getLineCount();\n const startLineNumber = searchStart.lineNumber;\n // Look in first line\n const text = model.getLineContent(startLineNumber);\n const r = this._findFirstMatchInLine(searcher, text, startLineNumber, searchStart.column, captureMatches);\n if (r) {\n return r;\n }\n for (let i = 1; i <= lineCount; i++) {\n const lineIndex = (startLineNumber + i - 1) % lineCount;\n const text = model.getLineContent(lineIndex + 1);\n const r = this._findFirstMatchInLine(searcher, text, lineIndex + 1, 1, captureMatches);\n if (r) {\n return r;\n }\n }\n return null;\n }\n static _findFirstMatchInLine(searcher, text, lineNumber, fromColumn, captureMatches) {\n // Set regex to search from column\n searcher.reset(fromColumn - 1);\n const m = searcher.next(text);\n if (m) {\n return createFindMatch(new Range(lineNumber, m.index + 1, lineNumber, m.index + 1 + m[0].length), m, captureMatches);\n }\n return null;\n }\n static findPreviousMatch(model, searchParams, searchStart, captureMatches) {\n const searchData = searchParams.parseSearchRequest();\n if (!searchData) {\n return null;\n }\n const searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n if (searchData.regex.multiline) {\n return this._doFindPreviousMatchMultiline(model, searchStart, searcher, captureMatches);\n }\n return this._doFindPreviousMatchLineByLine(model, searchStart, searcher, captureMatches);\n }\n static _doFindPreviousMatchMultiline(model, searchStart, searcher, captureMatches) {\n const matches = this._doFindMatchesMultiline(model, new Range(1, 1, searchStart.lineNumber, searchStart.column), searcher, captureMatches, 10 * LIMIT_FIND_COUNT);\n if (matches.length > 0) {\n return matches[matches.length - 1];\n }\n const lineCount = model.getLineCount();\n if (searchStart.lineNumber !== lineCount || searchStart.column !== model.getLineMaxColumn(lineCount)) {\n // Try again with all content\n return this._doFindPreviousMatchMultiline(model, new Position(lineCount, model.getLineMaxColumn(lineCount)), searcher, captureMatches);\n }\n return null;\n }\n static _doFindPreviousMatchLineByLine(model, searchStart, searcher, captureMatches) {\n const lineCount = model.getLineCount();\n const startLineNumber = searchStart.lineNumber;\n // Look in first line\n const text = model.getLineContent(startLineNumber).substring(0, searchStart.column - 1);\n const r = this._findLastMatchInLine(searcher, text, startLineNumber, captureMatches);\n if (r) {\n return r;\n }\n for (let i = 1; i <= lineCount; i++) {\n const lineIndex = (lineCount + startLineNumber - i - 1) % lineCount;\n const text = model.getLineContent(lineIndex + 1);\n const r = this._findLastMatchInLine(searcher, text, lineIndex + 1, captureMatches);\n if (r) {\n return r;\n }\n }\n return null;\n }\n static _findLastMatchInLine(searcher, text, lineNumber, captureMatches) {\n let bestResult = null;\n let m;\n searcher.reset(0);\n while ((m = searcher.next(text))) {\n bestResult = createFindMatch(new Range(lineNumber, m.index + 1, lineNumber, m.index + 1 + m[0].length), m, captureMatches);\n }\n return bestResult;\n }\n}\nfunction leftIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength) {\n if (matchStartIndex === 0) {\n // Match starts at start of string\n return true;\n }\n const charBefore = text.charCodeAt(matchStartIndex - 1);\n if (wordSeparators.get(charBefore) !== 0 /* WordCharacterClass.Regular */) {\n // The character before the match is a word separator\n return true;\n }\n if (charBefore === 13 /* CharCode.CarriageReturn */ || charBefore === 10 /* CharCode.LineFeed */) {\n // The character before the match is line break or carriage return.\n return true;\n }\n if (matchLength > 0) {\n const firstCharInMatch = text.charCodeAt(matchStartIndex);\n if (wordSeparators.get(firstCharInMatch) !== 0 /* WordCharacterClass.Regular */) {\n // The first character inside the match is a word separator\n return true;\n }\n }\n return false;\n}\nfunction rightIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength) {\n if (matchStartIndex + matchLength === textLength) {\n // Match ends at end of string\n return true;\n }\n const charAfter = text.charCodeAt(matchStartIndex + matchLength);\n if (wordSeparators.get(charAfter) !== 0 /* WordCharacterClass.Regular */) {\n // The character after the match is a word separator\n return true;\n }\n if (charAfter === 13 /* CharCode.CarriageReturn */ || charAfter === 10 /* CharCode.LineFeed */) {\n // The character after the match is line break or carriage return.\n return true;\n }\n if (matchLength > 0) {\n const lastCharInMatch = text.charCodeAt(matchStartIndex + matchLength - 1);\n if (wordSeparators.get(lastCharInMatch) !== 0 /* WordCharacterClass.Regular */) {\n // The last character in the match is a word separator\n return true;\n }\n }\n return false;\n}\nexport function isValidMatch(wordSeparators, text, textLength, matchStartIndex, matchLength) {\n return (leftIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength)\n && rightIsWordBounday(wordSeparators, text, textLength, matchStartIndex, matchLength));\n}\nexport class Searcher {\n constructor(wordSeparators, searchRegex) {\n this._wordSeparators = wordSeparators;\n this._searchRegex = searchRegex;\n this._prevMatchStartIndex = -1;\n this._prevMatchLength = 0;\n }\n reset(lastIndex) {\n this._searchRegex.lastIndex = lastIndex;\n this._prevMatchStartIndex = -1;\n this._prevMatchLength = 0;\n }\n next(text) {\n const textLength = text.length;\n let m;\n do {\n if (this._prevMatchStartIndex + this._prevMatchLength === textLength) {\n // Reached the end of the line\n return null;\n }\n m = this._searchRegex.exec(text);\n if (!m) {\n return null;\n }\n const matchStartIndex = m.index;\n const matchLength = m[0].length;\n if (matchStartIndex === this._prevMatchStartIndex && matchLength === this._prevMatchLength) {\n if (matchLength === 0) {\n // the search result is an empty string and won't advance `regex.lastIndex`, so `regex.exec` will stuck here\n // we attempt to recover from that by advancing by two if surrogate pair found and by one otherwise\n if (strings.getNextCodePoint(text, textLength, this._searchRegex.lastIndex) > 0xFFFF) {\n this._searchRegex.lastIndex += 2;\n }\n else {\n this._searchRegex.lastIndex += 1;\n }\n continue;\n }\n // Exit early if the regex matches the same range twice\n return null;\n }\n this._prevMatchStartIndex = matchStartIndex;\n this._prevMatchLength = matchLength;\n if (!this._wordSeparators || isValidMatch(this._wordSeparators, text, textLength, matchStartIndex, matchLength)) {\n return m;\n }\n } while (m);\n return null;\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/**\n * Returns:\n * - -1 => the line consists of whitespace\n * - otherwise => the indent level is returned value\n */\nexport function computeIndentLevel(line, tabSize) {\n let indent = 0;\n let i = 0;\n const len = line.length;\n while (i < len) {\n const chCode = line.charCodeAt(i);\n if (chCode === 32 /* CharCode.Space */) {\n indent++;\n }\n else if (chCode === 9 /* CharCode.Tab */) {\n indent = indent - indent % tabSize + tabSize;\n }\n else {\n break;\n }\n i++;\n }\n if (i === len) {\n return -1; // line only consists of whitespace\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { createDecorator } from '../../../platform/instantiation/common/instantiation.js';\nexport const ID_EDITOR_WORKER_SERVICE = 'editorWorkerService';\nexport const IEditorWorkerService = createDecorator(ID_EDITOR_WORKER_SERVICE);\n","/*---------------------------------------------------------------------------------------------\n * 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 { VSBuffer } from '../../../base/common/buffer.js';\nimport * as platform from '../../../base/common/platform.js';\nfunction reverseEndianness(arr) {\n for (let i = 0, len = arr.length; i < len; i += 4) {\n // flip bytes 0<->3 and 1<->2\n const b0 = arr[i + 0];\n const b1 = arr[i + 1];\n const b2 = arr[i + 2];\n const b3 = arr[i + 3];\n arr[i + 0] = b3;\n arr[i + 1] = b2;\n arr[i + 2] = b1;\n arr[i + 3] = b0;\n }\n}\nfunction toLittleEndianBuffer(arr) {\n const uint8Arr = new Uint8Array(arr.buffer, arr.byteOffset, arr.length * 4);\n if (!platform.isLittleEndian()) {\n // the byte order must be changed\n reverseEndianness(uint8Arr);\n }\n return VSBuffer.wrap(uint8Arr);\n}\nexport function encodeSemanticTokensDto(semanticTokens) {\n const dest = new Uint32Array(encodeSemanticTokensDtoSize(semanticTokens));\n let offset = 0;\n dest[offset++] = semanticTokens.id;\n if (semanticTokens.type === 'full') {\n dest[offset++] = 1 /* EncodedSemanticTokensType.Full */;\n dest[offset++] = semanticTokens.data.length;\n dest.set(semanticTokens.data, offset);\n offset += semanticTokens.data.length;\n }\n else {\n dest[offset++] = 2 /* EncodedSemanticTokensType.Delta */;\n dest[offset++] = semanticTokens.deltas.length;\n for (const delta of semanticTokens.deltas) {\n dest[offset++] = delta.start;\n dest[offset++] = delta.deleteCount;\n if (delta.data) {\n dest[offset++] = delta.data.length;\n dest.set(delta.data, offset);\n offset += delta.data.length;\n }\n else {\n dest[offset++] = 0;\n }\n }\n }\n return toLittleEndianBuffer(dest);\n}\nfunction encodeSemanticTokensDtoSize(semanticTokens) {\n let result = 0;\n result += (+1 // id\n + 1 // type\n );\n if (semanticTokens.type === 'full') {\n result += (+1 // data length\n + semanticTokens.data.length);\n }\n else {\n result += (+1 // delta count\n );\n result += (+1 // start\n + 1 // deleteCount\n + 1 // data length\n ) * semanticTokens.deltas.length;\n for (const delta of semanticTokens.deltas) {\n if (delta.data) {\n result += delta.data.length;\n }\n }\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { CancellationToken } from '../../../base/common/cancellation.js';\nimport { onUnexpectedExternalError } from '../../../base/common/errors.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { IModelService } from './model.js';\nimport { CommandsRegistry, ICommandService } from '../../../platform/commands/common/commands.js';\nimport { assertType } from '../../../base/common/types.js';\nimport { encodeSemanticTokensDto } from './semanticTokensDto.js';\nimport { Range } from '../core/range.js';\nimport { ILanguageFeaturesService } from './languageFeatures.js';\nexport function isSemanticTokens(v) {\n return v && !!(v.data);\n}\nexport function isSemanticTokensEdits(v) {\n return v && Array.isArray(v.edits);\n}\nexport class DocumentSemanticTokensResult {\n constructor(provider, tokens, error) {\n this.provider = provider;\n this.tokens = tokens;\n this.error = error;\n }\n}\nexport function hasDocumentSemanticTokensProvider(registry, model) {\n return registry.has(model);\n}\nfunction getDocumentSemanticTokensProviders(registry, model) {\n const groups = registry.orderedGroups(model);\n return (groups.length > 0 ? groups[0] : []);\n}\nexport function getDocumentSemanticTokens(registry, model, lastProvider, lastResultId, token) {\n return __awaiter(this, void 0, void 0, function* () {\n const providers = getDocumentSemanticTokensProviders(registry, model);\n // Get tokens from all providers at the same time.\n const results = yield Promise.all(providers.map((provider) => __awaiter(this, void 0, void 0, function* () {\n let result;\n let error = null;\n try {\n result = yield provider.provideDocumentSemanticTokens(model, (provider === lastProvider ? lastResultId : null), token);\n }\n catch (err) {\n error = err;\n result = null;\n }\n if (!result || (!isSemanticTokens(result) && !isSemanticTokensEdits(result))) {\n result = null;\n }\n return new DocumentSemanticTokensResult(provider, result, error);\n })));\n // Try to return the first result with actual tokens or\n // the first result which threw an error (!!)\n for (const result of results) {\n if (result.error) {\n throw result.error;\n }\n if (result.tokens) {\n return result;\n }\n }\n // Return the first result, even if it doesn't have tokens\n if (results.length > 0) {\n return results[0];\n }\n return null;\n });\n}\nfunction _getDocumentSemanticTokensProviderHighestGroup(registry, model) {\n const result = registry.orderedGroups(model);\n return (result.length > 0 ? result[0] : null);\n}\nclass DocumentRangeSemanticTokensResult {\n constructor(provider, tokens) {\n this.provider = provider;\n this.tokens = tokens;\n }\n}\nexport function hasDocumentRangeSemanticTokensProvider(providers, model) {\n return providers.has(model);\n}\nfunction getDocumentRangeSemanticTokensProviders(providers, model) {\n const groups = providers.orderedGroups(model);\n return (groups.length > 0 ? groups[0] : []);\n}\nexport function getDocumentRangeSemanticTokens(registry, model, range, token) {\n return __awaiter(this, void 0, void 0, function* () {\n const providers = getDocumentRangeSemanticTokensProviders(registry, model);\n // Get tokens from all providers at the same time.\n const results = yield Promise.all(providers.map((provider) => __awaiter(this, void 0, void 0, function* () {\n let result;\n try {\n result = yield provider.provideDocumentRangeSemanticTokens(model, range, token);\n }\n catch (err) {\n onUnexpectedExternalError(err);\n result = null;\n }\n if (!result || !isSemanticTokens(result)) {\n result = null;\n }\n return new DocumentRangeSemanticTokensResult(provider, result);\n })));\n // Try to return the first result with actual tokens\n for (const result of results) {\n if (result.tokens) {\n return result;\n }\n }\n // Return the first result, even if it doesn't have tokens\n if (results.length > 0) {\n return results[0];\n }\n return null;\n });\n}\nCommandsRegistry.registerCommand('_provideDocumentSemanticTokensLegend', (accessor, ...args) => __awaiter(void 0, void 0, void 0, function* () {\n const [uri] = args;\n assertType(uri instanceof URI);\n const model = accessor.get(IModelService).getModel(uri);\n if (!model) {\n return undefined;\n }\n const { documentSemanticTokensProvider } = accessor.get(ILanguageFeaturesService);\n const providers = _getDocumentSemanticTokensProviderHighestGroup(documentSemanticTokensProvider, model);\n if (!providers) {\n // there is no provider => fall back to a document range semantic tokens provider\n return accessor.get(ICommandService).executeCommand('_provideDocumentRangeSemanticTokensLegend', uri);\n }\n return providers[0].getLegend();\n}));\nCommandsRegistry.registerCommand('_provideDocumentSemanticTokens', (accessor, ...args) => __awaiter(void 0, void 0, void 0, function* () {\n const [uri] = args;\n assertType(uri instanceof URI);\n const model = accessor.get(IModelService).getModel(uri);\n if (!model) {\n return undefined;\n }\n const { documentSemanticTokensProvider } = accessor.get(ILanguageFeaturesService);\n if (!hasDocumentSemanticTokensProvider(documentSemanticTokensProvider, model)) {\n // there is no provider => fall back to a document range semantic tokens provider\n return accessor.get(ICommandService).executeCommand('_provideDocumentRangeSemanticTokens', uri, model.getFullModelRange());\n }\n const r = yield getDocumentSemanticTokens(documentSemanticTokensProvider, model, null, null, CancellationToken.None);\n if (!r) {\n return undefined;\n }\n const { provider, tokens } = r;\n if (!tokens || !isSemanticTokens(tokens)) {\n return undefined;\n }\n const buff = encodeSemanticTokensDto({\n id: 0,\n type: 'full',\n data: tokens.data\n });\n if (tokens.resultId) {\n provider.releaseDocumentSemanticTokens(tokens.resultId);\n }\n return buff;\n}));\nCommandsRegistry.registerCommand('_provideDocumentRangeSemanticTokensLegend', (accessor, ...args) => __awaiter(void 0, void 0, void 0, function* () {\n const [uri, range] = args;\n assertType(uri instanceof URI);\n const model = accessor.get(IModelService).getModel(uri);\n if (!model) {\n return undefined;\n }\n const { documentRangeSemanticTokensProvider } = accessor.get(ILanguageFeaturesService);\n const providers = getDocumentRangeSemanticTokensProviders(documentRangeSemanticTokensProvider, model);\n if (providers.length === 0) {\n // no providers\n return undefined;\n }\n if (providers.length === 1) {\n // straight forward case, just a single provider\n return providers[0].getLegend();\n }\n if (!range || !Range.isIRange(range)) {\n // if no range is provided, we cannot support multiple providers\n // as we cannot fall back to the one which would give results\n // => return the first legend for backwards compatibility and print a warning\n console.warn(`provideDocumentRangeSemanticTokensLegend might be out-of-sync with provideDocumentRangeSemanticTokens unless a range argument is passed in`);\n return providers[0].getLegend();\n }\n const result = yield getDocumentRangeSemanticTokens(documentRangeSemanticTokensProvider, model, Range.lift(range), CancellationToken.None);\n if (!result) {\n return undefined;\n }\n return result.provider.getLegend();\n}));\nCommandsRegistry.registerCommand('_provideDocumentRangeSemanticTokens', (accessor, ...args) => __awaiter(void 0, void 0, void 0, function* () {\n const [uri, range] = args;\n assertType(uri instanceof URI);\n assertType(Range.isIRange(range));\n const model = accessor.get(IModelService).getModel(uri);\n if (!model) {\n return undefined;\n }\n const { documentRangeSemanticTokensProvider } = accessor.get(ILanguageFeaturesService);\n const result = yield getDocumentRangeSemanticTokens(documentRangeSemanticTokensProvider, model, Range.lift(range), CancellationToken.None);\n if (!result || !result.tokens) {\n // there is no provider or it didn't return tokens\n return undefined;\n }\n return encodeSemanticTokensDto({\n id: 0,\n type: 'full',\n data: result.tokens.data\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { doHash } from '../../../base/common/hash.js';\nimport { LRUCache } from '../../../base/common/map.js';\nimport { clamp, MovingAverage, SlidingWindowAverage } from '../../../base/common/numbers.js';\nimport { registerSingleton } from '../../../platform/instantiation/common/extensions.js';\nimport { createDecorator } from '../../../platform/instantiation/common/instantiation.js';\nimport { ILogService } from '../../../platform/log/common/log.js';\nimport { matchesScheme } from '../../../platform/opener/common/opener.js';\nexport const ILanguageFeatureDebounceService = createDecorator('ILanguageFeatureDebounceService');\nvar IdentityHash;\n(function (IdentityHash) {\n const _hashes = new WeakMap();\n let pool = 0;\n function of(obj) {\n let value = _hashes.get(obj);\n if (value === undefined) {\n value = ++pool;\n _hashes.set(obj, value);\n }\n return value;\n }\n IdentityHash.of = of;\n})(IdentityHash || (IdentityHash = {}));\nclass FeatureDebounceInformation {\n constructor(_logService, _name, _registry, _default, _min, _max) {\n this._logService = _logService;\n this._name = _name;\n this._registry = _registry;\n this._default = _default;\n this._min = _min;\n this._max = _max;\n this._cache = new LRUCache(50, 0.7);\n }\n _key(model) {\n return model.id + this._registry.all(model).reduce((hashVal, obj) => doHash(IdentityHash.of(obj), hashVal), 0);\n }\n get(model) {\n const key = this._key(model);\n const avg = this._cache.get(key);\n return avg\n ? clamp(avg.value, this._min, this._max)\n : this.default();\n }\n update(model, value) {\n const key = this._key(model);\n let avg = this._cache.get(key);\n if (!avg) {\n avg = new SlidingWindowAverage(6);\n this._cache.set(key, avg);\n }\n const newValue = clamp(avg.update(value), this._min, this._max);\n if (!matchesScheme(model.uri, 'output')) {\n this._logService.trace(`[DEBOUNCE: ${this._name}] for ${model.uri.toString()} is ${newValue}ms`);\n }\n return newValue;\n }\n _overall() {\n const result = new MovingAverage();\n for (const [, avg] of this._cache) {\n result.update(avg.value);\n }\n return result.value;\n }\n default() {\n const value = (this._overall() | 0) || this._default;\n return clamp(value, this._min, this._max);\n }\n}\nlet LanguageFeatureDebounceService = class LanguageFeatureDebounceService {\n constructor(_logService) {\n this._logService = _logService;\n this._data = new Map();\n }\n for(feature, name, config) {\n var _a, _b, _c;\n const min = (_a = config === null || config === void 0 ? void 0 : config.min) !== null && _a !== void 0 ? _a : 50;\n const max = (_b = config === null || config === void 0 ? void 0 : config.max) !== null && _b !== void 0 ? _b : Math.pow(min, 2);\n const extra = (_c = config === null || config === void 0 ? void 0 : config.key) !== null && _c !== void 0 ? _c : undefined;\n const key = `${IdentityHash.of(feature)},${min}${extra ? ',' + extra : ''}`;\n let info = this._data.get(key);\n if (!info) {\n info = new FeatureDebounceInformation(this._logService, name, feature, (this._overallAverage() | 0) || (min * 1.5), // default is overall default or derived from min-value\n min, max);\n this._data.set(key, info);\n }\n return info;\n }\n _overallAverage() {\n // Average of all language features. Not a great value but an approximation\n const result = new MovingAverage();\n for (const info of this._data.values()) {\n result.update(info.default());\n }\n return result.value;\n }\n};\nLanguageFeatureDebounceService = __decorate([\n __param(0, ILogService)\n], LanguageFeatureDebounceService);\nexport { LanguageFeatureDebounceService };\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 *--------------------------------------------------------------------------------------------*/\nimport { createDecorator } from '../../../platform/instantiation/common/instantiation.js';\nexport const ILanguageFeaturesService = createDecorator('ILanguageFeaturesService');\n","/*---------------------------------------------------------------------------------------------\n * 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 { createDecorator } from '../../../platform/instantiation/common/instantiation.js';\nexport const IMarkerDecorationsService = createDecorator('markerDecorationsService');\n","/*---------------------------------------------------------------------------------------------\n * 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 { createDecorator } from '../../../platform/instantiation/common/instantiation.js';\nexport const IModelService = createDecorator('modelService');\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable, DisposableStore, dispose } from '../../../base/common/lifecycle.js';\nimport * as platform from '../../../base/common/platform.js';\nimport * as errors from '../../../base/common/errors.js';\nimport { TextModel } from '../model/textModel.js';\nimport { EDITOR_MODEL_DEFAULTS } from '../core/textModelDefaults.js';\nimport { PLAINTEXT_LANGUAGE_ID } from '../languages/modesRegistry.js';\nimport { ILanguageService } from '../languages/language.js';\nimport { IModelService } from './model.js';\nimport { ITextResourcePropertiesService } from './textResourceConfiguration.js';\nimport { IConfigurationService } from '../../../platform/configuration/common/configuration.js';\nimport { RunOnceScheduler } from '../../../base/common/async.js';\nimport { CancellationTokenSource } from '../../../base/common/cancellation.js';\nimport { IThemeService } from '../../../platform/theme/common/themeService.js';\nimport { ILogService } from '../../../platform/log/common/log.js';\nimport { IUndoRedoService } from '../../../platform/undoRedo/common/undoRedo.js';\nimport { StringSHA1 } from '../../../base/common/hash.js';\nimport { isEditStackElement } from '../model/editStack.js';\nimport { Schemas } from '../../../base/common/network.js';\nimport { SemanticTokensProviderStyling, toMultilineTokens2 } from './semanticTokensProviderStyling.js';\nimport { getDocumentSemanticTokens, hasDocumentSemanticTokensProvider, isSemanticTokens, isSemanticTokensEdits } from './getSemanticTokens.js';\nimport { equals } from '../../../base/common/objects.js';\nimport { ILanguageConfigurationService } from '../languages/languageConfigurationRegistry.js';\nimport { ILanguageFeatureDebounceService } from './languageFeatureDebounce.js';\nimport { StopWatch } from '../../../base/common/stopwatch.js';\nimport { ILanguageFeaturesService } from './languageFeatures.js';\nfunction MODEL_ID(resource) {\n return resource.toString();\n}\nfunction computeModelSha1(model) {\n // compute the sha1\n const shaComputer = new StringSHA1();\n const snapshot = model.createSnapshot();\n let text;\n while ((text = snapshot.read())) {\n shaComputer.update(text);\n }\n return shaComputer.digest();\n}\nclass ModelData {\n constructor(model, onWillDispose, onDidChangeLanguage) {\n this._modelEventListeners = new DisposableStore();\n this.model = model;\n this._languageSelection = null;\n this._languageSelectionListener = null;\n this._modelEventListeners.add(model.onWillDispose(() => onWillDispose(model)));\n this._modelEventListeners.add(model.onDidChangeLanguage((e) => onDidChangeLanguage(model, e)));\n }\n _disposeLanguageSelection() {\n if (this._languageSelectionListener) {\n this._languageSelectionListener.dispose();\n this._languageSelectionListener = null;\n }\n }\n dispose() {\n this._modelEventListeners.dispose();\n this._disposeLanguageSelection();\n }\n setLanguage(languageSelection) {\n this._disposeLanguageSelection();\n this._languageSelection = languageSelection;\n this._languageSelectionListener = this._languageSelection.onDidChange(() => this.model.setMode(languageSelection.languageId));\n this.model.setMode(languageSelection.languageId);\n }\n}\nconst DEFAULT_EOL = (platform.isLinux || platform.isMacintosh) ? 1 /* DefaultEndOfLine.LF */ : 2 /* DefaultEndOfLine.CRLF */;\nclass DisposedModelInfo {\n constructor(uri, initialUndoRedoSnapshot, time, sharesUndoRedoStack, heapSize, sha1, versionId, alternativeVersionId) {\n this.uri = uri;\n this.initialUndoRedoSnapshot = initialUndoRedoSnapshot;\n this.time = time;\n this.sharesUndoRedoStack = sharesUndoRedoStack;\n this.heapSize = heapSize;\n this.sha1 = sha1;\n this.versionId = versionId;\n this.alternativeVersionId = alternativeVersionId;\n }\n}\nlet ModelService = class ModelService extends Disposable {\n constructor(_configurationService, _resourcePropertiesService, _themeService, _logService, _undoRedoService, _languageService, _languageConfigurationService, _languageFeatureDebounceService, languageFeaturesService) {\n super();\n this._configurationService = _configurationService;\n this._resourcePropertiesService = _resourcePropertiesService;\n this._themeService = _themeService;\n this._logService = _logService;\n this._undoRedoService = _undoRedoService;\n this._languageService = _languageService;\n this._languageConfigurationService = _languageConfigurationService;\n this._languageFeatureDebounceService = _languageFeatureDebounceService;\n this._onModelAdded = this._register(new Emitter());\n this.onModelAdded = this._onModelAdded.event;\n this._onModelRemoved = this._register(new Emitter());\n this.onModelRemoved = this._onModelRemoved.event;\n this._onModelModeChanged = this._register(new Emitter());\n this.onModelLanguageChanged = this._onModelModeChanged.event;\n this._modelCreationOptionsByLanguageAndResource = Object.create(null);\n this._models = {};\n this._disposedModels = new Map();\n this._disposedModelsHeapSize = 0;\n this._semanticStyling = this._register(new SemanticStyling(this._themeService, this._languageService, this._logService));\n this._register(this._configurationService.onDidChangeConfiguration(() => this._updateModelOptions()));\n this._updateModelOptions();\n this._register(new SemanticColoringFeature(this._semanticStyling, this, this._themeService, this._configurationService, this._languageFeatureDebounceService, languageFeaturesService));\n }\n static _readModelOptions(config, isForSimpleWidget) {\n var _a;\n let tabSize = EDITOR_MODEL_DEFAULTS.tabSize;\n if (config.editor && typeof config.editor.tabSize !== 'undefined') {\n const parsedTabSize = parseInt(config.editor.tabSize, 10);\n if (!isNaN(parsedTabSize)) {\n tabSize = parsedTabSize;\n }\n if (tabSize < 1) {\n tabSize = 1;\n }\n }\n let indentSize = tabSize;\n if (config.editor && typeof config.editor.indentSize !== 'undefined' && config.editor.indentSize !== 'tabSize') {\n const parsedIndentSize = parseInt(config.editor.indentSize, 10);\n if (!isNaN(parsedIndentSize)) {\n indentSize = parsedIndentSize;\n }\n if (indentSize < 1) {\n indentSize = 1;\n }\n }\n let insertSpaces = EDITOR_MODEL_DEFAULTS.insertSpaces;\n if (config.editor && typeof config.editor.insertSpaces !== 'undefined') {\n insertSpaces = (config.editor.insertSpaces === 'false' ? false : Boolean(config.editor.insertSpaces));\n }\n let newDefaultEOL = DEFAULT_EOL;\n const eol = config.eol;\n if (eol === '\\r\\n') {\n newDefaultEOL = 2 /* DefaultEndOfLine.CRLF */;\n }\n else if (eol === '\\n') {\n newDefaultEOL = 1 /* DefaultEndOfLine.LF */;\n }\n let trimAutoWhitespace = EDITOR_MODEL_DEFAULTS.trimAutoWhitespace;\n if (config.editor && typeof config.editor.trimAutoWhitespace !== 'undefined') {\n trimAutoWhitespace = (config.editor.trimAutoWhitespace === 'false' ? false : Boolean(config.editor.trimAutoWhitespace));\n }\n let detectIndentation = EDITOR_MODEL_DEFAULTS.detectIndentation;\n if (config.editor && typeof config.editor.detectIndentation !== 'undefined') {\n detectIndentation = (config.editor.detectIndentation === 'false' ? false : Boolean(config.editor.detectIndentation));\n }\n let largeFileOptimizations = EDITOR_MODEL_DEFAULTS.largeFileOptimizations;\n if (config.editor && typeof config.editor.largeFileOptimizations !== 'undefined') {\n largeFileOptimizations = (config.editor.largeFileOptimizations === 'false' ? false : Boolean(config.editor.largeFileOptimizations));\n }\n let bracketPairColorizationOptions = EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions;\n if (((_a = config.editor) === null || _a === void 0 ? void 0 : _a.bracketPairColorization) && typeof config.editor.bracketPairColorization === 'object') {\n bracketPairColorizationOptions = {\n enabled: !!config.editor.bracketPairColorization.enabled,\n independentColorPoolPerBracketType: !!config.editor.bracketPairColorization.independentColorPoolPerBracketType\n };\n }\n return {\n isForSimpleWidget: isForSimpleWidget,\n tabSize: tabSize,\n indentSize: indentSize,\n insertSpaces: insertSpaces,\n detectIndentation: detectIndentation,\n defaultEOL: newDefaultEOL,\n trimAutoWhitespace: trimAutoWhitespace,\n largeFileOptimizations: largeFileOptimizations,\n bracketPairColorizationOptions\n };\n }\n _getEOL(resource, language) {\n if (resource) {\n return this._resourcePropertiesService.getEOL(resource, language);\n }\n const eol = this._configurationService.getValue('files.eol', { overrideIdentifier: language });\n if (eol && typeof eol === 'string' && eol !== 'auto') {\n return eol;\n }\n return platform.OS === 3 /* platform.OperatingSystem.Linux */ || platform.OS === 2 /* platform.OperatingSystem.Macintosh */ ? '\\n' : '\\r\\n';\n }\n _shouldRestoreUndoStack() {\n const result = this._configurationService.getValue('files.restoreUndoStack');\n if (typeof result === 'boolean') {\n return result;\n }\n return true;\n }\n getCreationOptions(language, resource, isForSimpleWidget) {\n let creationOptions = this._modelCreationOptionsByLanguageAndResource[language + resource];\n if (!creationOptions) {\n const editor = this._configurationService.getValue('editor', { overrideIdentifier: language, resource });\n const eol = this._getEOL(resource, language);\n creationOptions = ModelService._readModelOptions({ editor, eol }, isForSimpleWidget);\n this._modelCreationOptionsByLanguageAndResource[language + resource] = creationOptions;\n }\n return creationOptions;\n }\n _updateModelOptions() {\n const oldOptionsByLanguageAndResource = this._modelCreationOptionsByLanguageAndResource;\n this._modelCreationOptionsByLanguageAndResource = Object.create(null);\n // Update options on all models\n const keys = Object.keys(this._models);\n for (let i = 0, len = keys.length; i < len; i++) {\n const modelId = keys[i];\n const modelData = this._models[modelId];\n const language = modelData.model.getLanguageId();\n const uri = modelData.model.uri;\n const oldOptions = oldOptionsByLanguageAndResource[language + uri];\n const newOptions = this.getCreationOptions(language, uri, modelData.model.isForSimpleWidget);\n ModelService._setModelOptionsForModel(modelData.model, newOptions, oldOptions);\n }\n }\n static _setModelOptionsForModel(model, newOptions, currentOptions) {\n if (currentOptions && currentOptions.defaultEOL !== newOptions.defaultEOL && model.getLineCount() === 1) {\n model.setEOL(newOptions.defaultEOL === 1 /* DefaultEndOfLine.LF */ ? 0 /* EndOfLineSequence.LF */ : 1 /* EndOfLineSequence.CRLF */);\n }\n if (currentOptions\n && (currentOptions.detectIndentation === newOptions.detectIndentation)\n && (currentOptions.insertSpaces === newOptions.insertSpaces)\n && (currentOptions.tabSize === newOptions.tabSize)\n && (currentOptions.indentSize === newOptions.indentSize)\n && (currentOptions.trimAutoWhitespace === newOptions.trimAutoWhitespace)\n && equals(currentOptions.bracketPairColorizationOptions, newOptions.bracketPairColorizationOptions)) {\n // Same indent opts, no need to touch the model\n return;\n }\n if (newOptions.detectIndentation) {\n model.detectIndentation(newOptions.insertSpaces, newOptions.tabSize);\n model.updateOptions({\n trimAutoWhitespace: newOptions.trimAutoWhitespace,\n bracketColorizationOptions: newOptions.bracketPairColorizationOptions\n });\n }\n else {\n model.updateOptions({\n insertSpaces: newOptions.insertSpaces,\n tabSize: newOptions.tabSize,\n indentSize: newOptions.indentSize,\n trimAutoWhitespace: newOptions.trimAutoWhitespace,\n bracketColorizationOptions: newOptions.bracketPairColorizationOptions\n });\n }\n }\n // --- begin IModelService\n _insertDisposedModel(disposedModelData) {\n this._disposedModels.set(MODEL_ID(disposedModelData.uri), disposedModelData);\n this._disposedModelsHeapSize += disposedModelData.heapSize;\n }\n _removeDisposedModel(resource) {\n const disposedModelData = this._disposedModels.get(MODEL_ID(resource));\n if (disposedModelData) {\n this._disposedModelsHeapSize -= disposedModelData.heapSize;\n }\n this._disposedModels.delete(MODEL_ID(resource));\n return disposedModelData;\n }\n _ensureDisposedModelsHeapSize(maxModelsHeapSize) {\n if (this._disposedModelsHeapSize > maxModelsHeapSize) {\n // we must remove some old undo stack elements to free up some memory\n const disposedModels = [];\n this._disposedModels.forEach(entry => {\n if (!entry.sharesUndoRedoStack) {\n disposedModels.push(entry);\n }\n });\n disposedModels.sort((a, b) => a.time - b.time);\n while (disposedModels.length > 0 && this._disposedModelsHeapSize > maxModelsHeapSize) {\n const disposedModel = disposedModels.shift();\n this._removeDisposedModel(disposedModel.uri);\n if (disposedModel.initialUndoRedoSnapshot !== null) {\n this._undoRedoService.restoreSnapshot(disposedModel.initialUndoRedoSnapshot);\n }\n }\n }\n }\n _createModelData(value, languageId, resource, isForSimpleWidget) {\n // create & save the model\n const options = this.getCreationOptions(languageId, resource, isForSimpleWidget);\n const model = new TextModel(value, languageId, options, resource, this._undoRedoService, this._languageService, this._languageConfigurationService);\n if (resource && this._disposedModels.has(MODEL_ID(resource))) {\n const disposedModelData = this._removeDisposedModel(resource);\n const elements = this._undoRedoService.getElements(resource);\n const sha1IsEqual = (computeModelSha1(model) === disposedModelData.sha1);\n if (sha1IsEqual || disposedModelData.sharesUndoRedoStack) {\n for (const element of elements.past) {\n if (isEditStackElement(element) && element.matchesResource(resource)) {\n element.setModel(model);\n }\n }\n for (const element of elements.future) {\n if (isEditStackElement(element) && element.matchesResource(resource)) {\n element.setModel(model);\n }\n }\n this._undoRedoService.setElementsValidFlag(resource, true, (element) => (isEditStackElement(element) && element.matchesResource(resource)));\n if (sha1IsEqual) {\n model._overwriteVersionId(disposedModelData.versionId);\n model._overwriteAlternativeVersionId(disposedModelData.alternativeVersionId);\n model._overwriteInitialUndoRedoSnapshot(disposedModelData.initialUndoRedoSnapshot);\n }\n }\n else {\n if (disposedModelData.initialUndoRedoSnapshot !== null) {\n this._undoRedoService.restoreSnapshot(disposedModelData.initialUndoRedoSnapshot);\n }\n }\n }\n const modelId = MODEL_ID(model.uri);\n if (this._models[modelId]) {\n // There already exists a model with this id => this is a programmer error\n throw new Error('ModelService: Cannot add model because it already exists!');\n }\n const modelData = new ModelData(model, (model) => this._onWillDispose(model), (model, e) => this._onDidChangeLanguage(model, e));\n this._models[modelId] = modelData;\n return modelData;\n }\n createModel(value, languageSelection, resource, isForSimpleWidget = false) {\n let modelData;\n if (languageSelection) {\n modelData = this._createModelData(value, languageSelection.languageId, resource, isForSimpleWidget);\n this.setMode(modelData.model, languageSelection);\n }\n else {\n modelData = this._createModelData(value, PLAINTEXT_LANGUAGE_ID, resource, isForSimpleWidget);\n }\n this._onModelAdded.fire(modelData.model);\n return modelData.model;\n }\n setMode(model, languageSelection) {\n if (!languageSelection) {\n return;\n }\n const modelData = this._models[MODEL_ID(model.uri)];\n if (!modelData) {\n return;\n }\n modelData.setLanguage(languageSelection);\n }\n getModels() {\n const ret = [];\n const keys = Object.keys(this._models);\n for (let i = 0, len = keys.length; i < len; i++) {\n const modelId = keys[i];\n ret.push(this._models[modelId].model);\n }\n return ret;\n }\n getModel(resource) {\n const modelId = MODEL_ID(resource);\n const modelData = this._models[modelId];\n if (!modelData) {\n return null;\n }\n return modelData.model;\n }\n getSemanticTokensProviderStyling(provider) {\n return this._semanticStyling.get(provider);\n }\n // --- end IModelService\n _schemaShouldMaintainUndoRedoElements(resource) {\n return (resource.scheme === Schemas.file\n || resource.scheme === Schemas.vscodeRemote\n || resource.scheme === Schemas.vscodeUserData\n || resource.scheme === Schemas.vscodeNotebookCell\n || resource.scheme === 'fake-fs' // for tests\n );\n }\n _onWillDispose(model) {\n const modelId = MODEL_ID(model.uri);\n const modelData = this._models[modelId];\n const sharesUndoRedoStack = (this._undoRedoService.getUriComparisonKey(model.uri) !== model.uri.toString());\n let maintainUndoRedoStack = false;\n let heapSize = 0;\n if (sharesUndoRedoStack || (this._shouldRestoreUndoStack() && this._schemaShouldMaintainUndoRedoElements(model.uri))) {\n const elements = this._undoRedoService.getElements(model.uri);\n if (elements.past.length > 0 || elements.future.length > 0) {\n for (const element of elements.past) {\n if (isEditStackElement(element) && element.matchesResource(model.uri)) {\n maintainUndoRedoStack = true;\n heapSize += element.heapSize(model.uri);\n element.setModel(model.uri); // remove reference from text buffer instance\n }\n }\n for (const element of elements.future) {\n if (isEditStackElement(element) && element.matchesResource(model.uri)) {\n maintainUndoRedoStack = true;\n heapSize += element.heapSize(model.uri);\n element.setModel(model.uri); // remove reference from text buffer instance\n }\n }\n }\n }\n const maxMemory = ModelService.MAX_MEMORY_FOR_CLOSED_FILES_UNDO_STACK;\n if (!maintainUndoRedoStack) {\n if (!sharesUndoRedoStack) {\n const initialUndoRedoSnapshot = modelData.model.getInitialUndoRedoSnapshot();\n if (initialUndoRedoSnapshot !== null) {\n this._undoRedoService.restoreSnapshot(initialUndoRedoSnapshot);\n }\n }\n }\n else if (!sharesUndoRedoStack && heapSize > maxMemory) {\n // the undo stack for this file would never fit in the configured memory, so don't bother with it.\n const initialUndoRedoSnapshot = modelData.model.getInitialUndoRedoSnapshot();\n if (initialUndoRedoSnapshot !== null) {\n this._undoRedoService.restoreSnapshot(initialUndoRedoSnapshot);\n }\n }\n else {\n this._ensureDisposedModelsHeapSize(maxMemory - heapSize);\n // We only invalidate the elements, but they remain in the undo-redo service.\n this._undoRedoService.setElementsValidFlag(model.uri, false, (element) => (isEditStackElement(element) && element.matchesResource(model.uri)));\n this._insertDisposedModel(new DisposedModelInfo(model.uri, modelData.model.getInitialUndoRedoSnapshot(), Date.now(), sharesUndoRedoStack, heapSize, computeModelSha1(model), model.getVersionId(), model.getAlternativeVersionId()));\n }\n delete this._models[modelId];\n modelData.dispose();\n // clean up cache\n delete this._modelCreationOptionsByLanguageAndResource[model.getLanguageId() + model.uri];\n this._onModelRemoved.fire(model);\n }\n _onDidChangeLanguage(model, e) {\n const oldLanguageId = e.oldLanguage;\n const newLanguageId = model.getLanguageId();\n const oldOptions = this.getCreationOptions(oldLanguageId, model.uri, model.isForSimpleWidget);\n const newOptions = this.getCreationOptions(newLanguageId, model.uri, model.isForSimpleWidget);\n ModelService._setModelOptionsForModel(model, newOptions, oldOptions);\n this._onModelModeChanged.fire({ model, oldLanguageId: oldLanguageId });\n }\n};\nModelService.MAX_MEMORY_FOR_CLOSED_FILES_UNDO_STACK = 20 * 1024 * 1024;\nModelService = __decorate([\n __param(0, IConfigurationService),\n __param(1, ITextResourcePropertiesService),\n __param(2, IThemeService),\n __param(3, ILogService),\n __param(4, IUndoRedoService),\n __param(5, ILanguageService),\n __param(6, ILanguageConfigurationService),\n __param(7, ILanguageFeatureDebounceService),\n __param(8, ILanguageFeaturesService)\n], ModelService);\nexport { ModelService };\nexport const SEMANTIC_HIGHLIGHTING_SETTING_ID = 'editor.semanticHighlighting';\nexport function isSemanticColoringEnabled(model, themeService, configurationService) {\n var _a;\n const setting = (_a = configurationService.getValue(SEMANTIC_HIGHLIGHTING_SETTING_ID, { overrideIdentifier: model.getLanguageId(), resource: model.uri })) === null || _a === void 0 ? void 0 : _a.enabled;\n if (typeof setting === 'boolean') {\n return setting;\n }\n return themeService.getColorTheme().semanticHighlighting;\n}\nlet SemanticColoringFeature = class SemanticColoringFeature extends Disposable {\n constructor(semanticStyling, modelService, themeService, configurationService, languageFeatureDebounceService, languageFeaturesService) {\n super();\n this._watchers = Object.create(null);\n this._semanticStyling = semanticStyling;\n const register = (model) => {\n this._watchers[model.uri.toString()] = new ModelSemanticColoring(model, this._semanticStyling, themeService, languageFeatureDebounceService, languageFeaturesService);\n };\n const deregister = (model, modelSemanticColoring) => {\n modelSemanticColoring.dispose();\n delete this._watchers[model.uri.toString()];\n };\n const handleSettingOrThemeChange = () => {\n for (const model of modelService.getModels()) {\n const curr = this._watchers[model.uri.toString()];\n if (isSemanticColoringEnabled(model, themeService, configurationService)) {\n if (!curr) {\n register(model);\n }\n }\n else {\n if (curr) {\n deregister(model, curr);\n }\n }\n }\n };\n this._register(modelService.onModelAdded((model) => {\n if (isSemanticColoringEnabled(model, themeService, configurationService)) {\n register(model);\n }\n }));\n this._register(modelService.onModelRemoved((model) => {\n const curr = this._watchers[model.uri.toString()];\n if (curr) {\n deregister(model, curr);\n }\n }));\n this._register(configurationService.onDidChangeConfiguration(e => {\n if (e.affectsConfiguration(SEMANTIC_HIGHLIGHTING_SETTING_ID)) {\n handleSettingOrThemeChange();\n }\n }));\n this._register(themeService.onDidColorThemeChange(handleSettingOrThemeChange));\n }\n dispose() {\n // Dispose all watchers\n for (const watcher of Object.values(this._watchers)) {\n watcher.dispose();\n }\n super.dispose();\n }\n};\nSemanticColoringFeature = __decorate([\n __param(1, IModelService),\n __param(2, IThemeService),\n __param(3, IConfigurationService),\n __param(4, ILanguageFeatureDebounceService),\n __param(5, ILanguageFeaturesService)\n], SemanticColoringFeature);\nclass SemanticStyling extends Disposable {\n constructor(_themeService, _languageService, _logService) {\n super();\n this._themeService = _themeService;\n this._languageService = _languageService;\n this._logService = _logService;\n this._caches = new WeakMap();\n this._register(this._themeService.onDidColorThemeChange(() => {\n this._caches = new WeakMap();\n }));\n }\n get(provider) {\n if (!this._caches.has(provider)) {\n this._caches.set(provider, new SemanticTokensProviderStyling(provider.getLegend(), this._themeService, this._languageService, this._logService));\n }\n return this._caches.get(provider);\n }\n}\nclass SemanticTokensResponse {\n constructor(provider, resultId, data) {\n this.provider = provider;\n this.resultId = resultId;\n this.data = data;\n }\n dispose() {\n this.provider.releaseDocumentSemanticTokens(this.resultId);\n }\n}\nlet ModelSemanticColoring = class ModelSemanticColoring extends Disposable {\n constructor(model, stylingProvider, themeService, languageFeatureDebounceService, languageFeaturesService) {\n super();\n this._isDisposed = false;\n this._model = model;\n this._semanticStyling = stylingProvider;\n this._provider = languageFeaturesService.documentSemanticTokensProvider;\n this._debounceInformation = languageFeatureDebounceService.for(this._provider, 'DocumentSemanticTokens', { min: ModelSemanticColoring.REQUEST_MIN_DELAY, max: ModelSemanticColoring.REQUEST_MAX_DELAY });\n this._fetchDocumentSemanticTokens = this._register(new RunOnceScheduler(() => this._fetchDocumentSemanticTokensNow(), ModelSemanticColoring.REQUEST_MIN_DELAY));\n this._currentDocumentResponse = null;\n this._currentDocumentRequestCancellationTokenSource = null;\n this._documentProvidersChangeListeners = [];\n this._register(this._model.onDidChangeContent(() => {\n if (!this._fetchDocumentSemanticTokens.isScheduled()) {\n this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model));\n }\n }));\n this._register(this._model.onDidChangeLanguage(() => {\n // clear any outstanding state\n if (this._currentDocumentResponse) {\n this._currentDocumentResponse.dispose();\n this._currentDocumentResponse = null;\n }\n if (this._currentDocumentRequestCancellationTokenSource) {\n this._currentDocumentRequestCancellationTokenSource.cancel();\n this._currentDocumentRequestCancellationTokenSource = null;\n }\n this._setDocumentSemanticTokens(null, null, null, []);\n this._fetchDocumentSemanticTokens.schedule(0);\n }));\n const bindDocumentChangeListeners = () => {\n dispose(this._documentProvidersChangeListeners);\n this._documentProvidersChangeListeners = [];\n for (const provider of this._provider.all(model)) {\n if (typeof provider.onDidChange === 'function') {\n this._documentProvidersChangeListeners.push(provider.onDidChange(() => this._fetchDocumentSemanticTokens.schedule(0)));\n }\n }\n };\n bindDocumentChangeListeners();\n this._register(this._provider.onDidChange(() => {\n bindDocumentChangeListeners();\n this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model));\n }));\n this._register(themeService.onDidColorThemeChange(_ => {\n // clear out existing tokens\n this._setDocumentSemanticTokens(null, null, null, []);\n this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model));\n }));\n this._fetchDocumentSemanticTokens.schedule(0);\n }\n dispose() {\n if (this._currentDocumentResponse) {\n this._currentDocumentResponse.dispose();\n this._currentDocumentResponse = null;\n }\n if (this._currentDocumentRequestCancellationTokenSource) {\n this._currentDocumentRequestCancellationTokenSource.cancel();\n this._currentDocumentRequestCancellationTokenSource = null;\n }\n this._setDocumentSemanticTokens(null, null, null, []);\n this._isDisposed = true;\n super.dispose();\n }\n _fetchDocumentSemanticTokensNow() {\n if (this._currentDocumentRequestCancellationTokenSource) {\n // there is already a request running, let it finish...\n return;\n }\n if (!hasDocumentSemanticTokensProvider(this._provider, this._model)) {\n // there is no provider\n if (this._currentDocumentResponse) {\n // there are semantic tokens set\n this._model.tokenization.setSemanticTokens(null, false);\n }\n return;\n }\n const cancellationTokenSource = new CancellationTokenSource();\n const lastProvider = this._currentDocumentResponse ? this._currentDocumentResponse.provider : null;\n const lastResultId = this._currentDocumentResponse ? this._currentDocumentResponse.resultId || null : null;\n const request = getDocumentSemanticTokens(this._provider, this._model, lastProvider, lastResultId, cancellationTokenSource.token);\n this._currentDocumentRequestCancellationTokenSource = cancellationTokenSource;\n const pendingChanges = [];\n const contentChangeListener = this._model.onDidChangeContent((e) => {\n pendingChanges.push(e);\n });\n const sw = new StopWatch(false);\n request.then((res) => {\n this._debounceInformation.update(this._model, sw.elapsed());\n this._currentDocumentRequestCancellationTokenSource = null;\n contentChangeListener.dispose();\n if (!res) {\n this._setDocumentSemanticTokens(null, null, null, pendingChanges);\n }\n else {\n const { provider, tokens } = res;\n const styling = this._semanticStyling.get(provider);\n this._setDocumentSemanticTokens(provider, tokens || null, styling, pendingChanges);\n }\n }, (err) => {\n const isExpectedError = err && (errors.isCancellationError(err) || (typeof err.message === 'string' && err.message.indexOf('busy') !== -1));\n if (!isExpectedError) {\n errors.onUnexpectedError(err);\n }\n // Semantic tokens eats up all errors and considers errors to mean that the result is temporarily not available\n // The API does not have a special error kind to express this...\n this._currentDocumentRequestCancellationTokenSource = null;\n contentChangeListener.dispose();\n if (pendingChanges.length > 0) {\n // More changes occurred while the request was running\n if (!this._fetchDocumentSemanticTokens.isScheduled()) {\n this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model));\n }\n }\n });\n }\n static _copy(src, srcOffset, dest, destOffset, length) {\n // protect against overflows\n length = Math.min(length, dest.length - destOffset, src.length - srcOffset);\n for (let i = 0; i < length; i++) {\n dest[destOffset + i] = src[srcOffset + i];\n }\n }\n _setDocumentSemanticTokens(provider, tokens, styling, pendingChanges) {\n const currentResponse = this._currentDocumentResponse;\n const rescheduleIfNeeded = () => {\n if (pendingChanges.length > 0 && !this._fetchDocumentSemanticTokens.isScheduled()) {\n this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model));\n }\n };\n if (this._currentDocumentResponse) {\n this._currentDocumentResponse.dispose();\n this._currentDocumentResponse = null;\n }\n if (this._isDisposed) {\n // disposed!\n if (provider && tokens) {\n provider.releaseDocumentSemanticTokens(tokens.resultId);\n }\n return;\n }\n if (!provider || !styling) {\n this._model.tokenization.setSemanticTokens(null, false);\n return;\n }\n if (!tokens) {\n this._model.tokenization.setSemanticTokens(null, true);\n rescheduleIfNeeded();\n return;\n }\n if (isSemanticTokensEdits(tokens)) {\n if (!currentResponse) {\n // not possible!\n this._model.tokenization.setSemanticTokens(null, true);\n return;\n }\n if (tokens.edits.length === 0) {\n // nothing to do!\n tokens = {\n resultId: tokens.resultId,\n data: currentResponse.data\n };\n }\n else {\n let deltaLength = 0;\n for (const edit of tokens.edits) {\n deltaLength += (edit.data ? edit.data.length : 0) - edit.deleteCount;\n }\n const srcData = currentResponse.data;\n const destData = new Uint32Array(srcData.length + deltaLength);\n let srcLastStart = srcData.length;\n let destLastStart = destData.length;\n for (let i = tokens.edits.length - 1; i >= 0; i--) {\n const edit = tokens.edits[i];\n if (edit.start > srcData.length) {\n styling.warnInvalidEditStart(currentResponse.resultId, tokens.resultId, i, edit.start, srcData.length);\n // The edits are invalid and there's no way to recover\n this._model.tokenization.setSemanticTokens(null, true);\n return;\n }\n const copyCount = srcLastStart - (edit.start + edit.deleteCount);\n if (copyCount > 0) {\n ModelSemanticColoring._copy(srcData, srcLastStart - copyCount, destData, destLastStart - copyCount, copyCount);\n destLastStart -= copyCount;\n }\n if (edit.data) {\n ModelSemanticColoring._copy(edit.data, 0, destData, destLastStart - edit.data.length, edit.data.length);\n destLastStart -= edit.data.length;\n }\n srcLastStart = edit.start;\n }\n if (srcLastStart > 0) {\n ModelSemanticColoring._copy(srcData, 0, destData, 0, srcLastStart);\n }\n tokens = {\n resultId: tokens.resultId,\n data: destData\n };\n }\n }\n if (isSemanticTokens(tokens)) {\n this._currentDocumentResponse = new SemanticTokensResponse(provider, tokens.resultId, tokens.data);\n const result = toMultilineTokens2(tokens, styling, this._model.getLanguageId());\n // Adjust incoming semantic tokens\n if (pendingChanges.length > 0) {\n // More changes occurred while the request was running\n // We need to:\n // 1. Adjust incoming semantic tokens\n // 2. Request them again\n for (const change of pendingChanges) {\n for (const area of result) {\n for (const singleChange of change.changes) {\n area.applyEdit(singleChange.range, singleChange.text);\n }\n }\n }\n }\n this._model.tokenization.setSemanticTokens(result, true);\n }\n else {\n this._model.tokenization.setSemanticTokens(null, true);\n }\n rescheduleIfNeeded();\n }\n};\nModelSemanticColoring.REQUEST_MIN_DELAY = 300;\nModelSemanticColoring.REQUEST_MAX_DELAY = 2000;\nModelSemanticColoring = __decorate([\n __param(2, IThemeService),\n __param(3, ILanguageFeatureDebounceService),\n __param(4, ILanguageFeaturesService)\n], ModelSemanticColoring);\nexport { ModelSemanticColoring };\n","/*---------------------------------------------------------------------------------------------\n * 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 { createDecorator } from '../../../platform/instantiation/common/instantiation.js';\nexport const ITextModelService = createDecorator('textModelService');\n","/*---------------------------------------------------------------------------------------------\n * 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 { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nimport { countEOL } from '../core/eolCounter.js';\n/**\n * Represents sparse tokens over a contiguous range of lines.\n */\nexport class SparseMultilineTokens {\n constructor(startLineNumber, tokens) {\n this._startLineNumber = startLineNumber;\n this._tokens = tokens;\n this._endLineNumber = this._startLineNumber + this._tokens.getMaxDeltaLine();\n }\n static create(startLineNumber, tokens) {\n return new SparseMultilineTokens(startLineNumber, new SparseMultilineTokensStorage(tokens));\n }\n /**\n * (Inclusive) start line number for these tokens.\n */\n get startLineNumber() {\n return this._startLineNumber;\n }\n /**\n * (Inclusive) end line number for these tokens.\n */\n get endLineNumber() {\n return this._endLineNumber;\n }\n toString() {\n return this._tokens.toString(this._startLineNumber);\n }\n _updateEndLineNumber() {\n this._endLineNumber = this._startLineNumber + this._tokens.getMaxDeltaLine();\n }\n isEmpty() {\n return this._tokens.isEmpty();\n }\n getLineTokens(lineNumber) {\n if (this._startLineNumber <= lineNumber && lineNumber <= this._endLineNumber) {\n return this._tokens.getLineTokens(lineNumber - this._startLineNumber);\n }\n return null;\n }\n getRange() {\n const deltaRange = this._tokens.getRange();\n if (!deltaRange) {\n return deltaRange;\n }\n return new Range(this._startLineNumber + deltaRange.startLineNumber, deltaRange.startColumn, this._startLineNumber + deltaRange.endLineNumber, deltaRange.endColumn);\n }\n removeTokens(range) {\n const startLineIndex = range.startLineNumber - this._startLineNumber;\n const endLineIndex = range.endLineNumber - this._startLineNumber;\n this._startLineNumber += this._tokens.removeTokens(startLineIndex, range.startColumn - 1, endLineIndex, range.endColumn - 1);\n this._updateEndLineNumber();\n }\n split(range) {\n // split tokens to two:\n // a) all the tokens before `range`\n // b) all the tokens after `range`\n const startLineIndex = range.startLineNumber - this._startLineNumber;\n const endLineIndex = range.endLineNumber - this._startLineNumber;\n const [a, b, bDeltaLine] = this._tokens.split(startLineIndex, range.startColumn - 1, endLineIndex, range.endColumn - 1);\n return [new SparseMultilineTokens(this._startLineNumber, a), new SparseMultilineTokens(this._startLineNumber + bDeltaLine, b)];\n }\n applyEdit(range, text) {\n const [eolCount, firstLineLength, lastLineLength] = countEOL(text);\n this.acceptEdit(range, eolCount, firstLineLength, lastLineLength, text.length > 0 ? text.charCodeAt(0) : 0 /* CharCode.Null */);\n }\n acceptEdit(range, eolCount, firstLineLength, lastLineLength, firstCharCode) {\n this._acceptDeleteRange(range);\n this._acceptInsertText(new Position(range.startLineNumber, range.startColumn), eolCount, firstLineLength, lastLineLength, firstCharCode);\n this._updateEndLineNumber();\n }\n _acceptDeleteRange(range) {\n if (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {\n // Nothing to delete\n return;\n }\n const firstLineIndex = range.startLineNumber - this._startLineNumber;\n const lastLineIndex = range.endLineNumber - this._startLineNumber;\n if (lastLineIndex < 0) {\n // this deletion occurs entirely before this block, so we only need to adjust line numbers\n const deletedLinesCount = lastLineIndex - firstLineIndex;\n this._startLineNumber -= deletedLinesCount;\n return;\n }\n const tokenMaxDeltaLine = this._tokens.getMaxDeltaLine();\n if (firstLineIndex >= tokenMaxDeltaLine + 1) {\n // this deletion occurs entirely after this block, so there is nothing to do\n return;\n }\n if (firstLineIndex < 0 && lastLineIndex >= tokenMaxDeltaLine + 1) {\n // this deletion completely encompasses this block\n this._startLineNumber = 0;\n this._tokens.clear();\n return;\n }\n if (firstLineIndex < 0) {\n const deletedBefore = -firstLineIndex;\n this._startLineNumber -= deletedBefore;\n this._tokens.acceptDeleteRange(range.startColumn - 1, 0, 0, lastLineIndex, range.endColumn - 1);\n }\n else {\n this._tokens.acceptDeleteRange(0, firstLineIndex, range.startColumn - 1, lastLineIndex, range.endColumn - 1);\n }\n }\n _acceptInsertText(position, eolCount, firstLineLength, lastLineLength, firstCharCode) {\n if (eolCount === 0 && firstLineLength === 0) {\n // Nothing to insert\n return;\n }\n const lineIndex = position.lineNumber - this._startLineNumber;\n if (lineIndex < 0) {\n // this insertion occurs before this block, so we only need to adjust line numbers\n this._startLineNumber += eolCount;\n return;\n }\n const tokenMaxDeltaLine = this._tokens.getMaxDeltaLine();\n if (lineIndex >= tokenMaxDeltaLine + 1) {\n // this insertion occurs after this block, so there is nothing to do\n return;\n }\n this._tokens.acceptInsertText(lineIndex, position.column - 1, eolCount, firstLineLength, lastLineLength, firstCharCode);\n }\n}\nclass SparseMultilineTokensStorage {\n constructor(tokens) {\n this._tokens = tokens;\n this._tokenCount = tokens.length / 4;\n }\n toString(startLineNumber) {\n const pieces = [];\n for (let i = 0; i < this._tokenCount; i++) {\n pieces.push(`(${this._getDeltaLine(i) + startLineNumber},${this._getStartCharacter(i)}-${this._getEndCharacter(i)})`);\n }\n return `[${pieces.join(',')}]`;\n }\n getMaxDeltaLine() {\n const tokenCount = this._getTokenCount();\n if (tokenCount === 0) {\n return -1;\n }\n return this._getDeltaLine(tokenCount - 1);\n }\n getRange() {\n const tokenCount = this._getTokenCount();\n if (tokenCount === 0) {\n return null;\n }\n const startChar = this._getStartCharacter(0);\n const maxDeltaLine = this._getDeltaLine(tokenCount - 1);\n const endChar = this._getEndCharacter(tokenCount - 1);\n return new Range(0, startChar + 1, maxDeltaLine, endChar + 1);\n }\n _getTokenCount() {\n return this._tokenCount;\n }\n _getDeltaLine(tokenIndex) {\n return this._tokens[4 * tokenIndex];\n }\n _getStartCharacter(tokenIndex) {\n return this._tokens[4 * tokenIndex + 1];\n }\n _getEndCharacter(tokenIndex) {\n return this._tokens[4 * tokenIndex + 2];\n }\n isEmpty() {\n return (this._getTokenCount() === 0);\n }\n getLineTokens(deltaLine) {\n let low = 0;\n let high = this._getTokenCount() - 1;\n while (low < high) {\n const mid = low + Math.floor((high - low) / 2);\n const midDeltaLine = this._getDeltaLine(mid);\n if (midDeltaLine < deltaLine) {\n low = mid + 1;\n }\n else if (midDeltaLine > deltaLine) {\n high = mid - 1;\n }\n else {\n let min = mid;\n while (min > low && this._getDeltaLine(min - 1) === deltaLine) {\n min--;\n }\n let max = mid;\n while (max < high && this._getDeltaLine(max + 1) === deltaLine) {\n max++;\n }\n return new SparseLineTokens(this._tokens.subarray(4 * min, 4 * max + 4));\n }\n }\n if (this._getDeltaLine(low) === deltaLine) {\n return new SparseLineTokens(this._tokens.subarray(4 * low, 4 * low + 4));\n }\n return null;\n }\n clear() {\n this._tokenCount = 0;\n }\n removeTokens(startDeltaLine, startChar, endDeltaLine, endChar) {\n const tokens = this._tokens;\n const tokenCount = this._tokenCount;\n let newTokenCount = 0;\n let hasDeletedTokens = false;\n let firstDeltaLine = 0;\n for (let i = 0; i < tokenCount; i++) {\n const srcOffset = 4 * i;\n const tokenDeltaLine = tokens[srcOffset];\n const tokenStartCharacter = tokens[srcOffset + 1];\n const tokenEndCharacter = tokens[srcOffset + 2];\n const tokenMetadata = tokens[srcOffset + 3];\n if ((tokenDeltaLine > startDeltaLine || (tokenDeltaLine === startDeltaLine && tokenEndCharacter >= startChar))\n && (tokenDeltaLine < endDeltaLine || (tokenDeltaLine === endDeltaLine && tokenStartCharacter <= endChar))) {\n hasDeletedTokens = true;\n }\n else {\n if (newTokenCount === 0) {\n firstDeltaLine = tokenDeltaLine;\n }\n if (hasDeletedTokens) {\n // must move the token to the left\n const destOffset = 4 * newTokenCount;\n tokens[destOffset] = tokenDeltaLine - firstDeltaLine;\n tokens[destOffset + 1] = tokenStartCharacter;\n tokens[destOffset + 2] = tokenEndCharacter;\n tokens[destOffset + 3] = tokenMetadata;\n }\n newTokenCount++;\n }\n }\n this._tokenCount = newTokenCount;\n return firstDeltaLine;\n }\n split(startDeltaLine, startChar, endDeltaLine, endChar) {\n const tokens = this._tokens;\n const tokenCount = this._tokenCount;\n const aTokens = [];\n const bTokens = [];\n let destTokens = aTokens;\n let destOffset = 0;\n let destFirstDeltaLine = 0;\n for (let i = 0; i < tokenCount; i++) {\n const srcOffset = 4 * i;\n const tokenDeltaLine = tokens[srcOffset];\n const tokenStartCharacter = tokens[srcOffset + 1];\n const tokenEndCharacter = tokens[srcOffset + 2];\n const tokenMetadata = tokens[srcOffset + 3];\n if ((tokenDeltaLine > startDeltaLine || (tokenDeltaLine === startDeltaLine && tokenEndCharacter >= startChar))) {\n if ((tokenDeltaLine < endDeltaLine || (tokenDeltaLine === endDeltaLine && tokenStartCharacter <= endChar))) {\n // this token is touching the range\n continue;\n }\n else {\n // this token is after the range\n if (destTokens !== bTokens) {\n // this token is the first token after the range\n destTokens = bTokens;\n destOffset = 0;\n destFirstDeltaLine = tokenDeltaLine;\n }\n }\n }\n destTokens[destOffset++] = tokenDeltaLine - destFirstDeltaLine;\n destTokens[destOffset++] = tokenStartCharacter;\n destTokens[destOffset++] = tokenEndCharacter;\n destTokens[destOffset++] = tokenMetadata;\n }\n return [new SparseMultilineTokensStorage(new Uint32Array(aTokens)), new SparseMultilineTokensStorage(new Uint32Array(bTokens)), destFirstDeltaLine];\n }\n acceptDeleteRange(horizontalShiftForFirstLineTokens, startDeltaLine, startCharacter, endDeltaLine, endCharacter) {\n // This is a bit complex, here are the cases I used to think about this:\n //\n // 1. The token starts before the deletion range\n // 1a. The token is completely before the deletion range\n // -----------\n // xxxxxxxxxxx\n // 1b. The token starts before, the deletion range ends after the token\n // -----------\n // xxxxxxxxxxx\n // 1c. The token starts before, the deletion range ends precisely with the token\n // ---------------\n // xxxxxxxx\n // 1d. The token starts before, the deletion range is inside the token\n // ---------------\n // xxxxx\n //\n // 2. The token starts at the same position with the deletion range\n // 2a. The token starts at the same position, and ends inside the deletion range\n // -------\n // xxxxxxxxxxx\n // 2b. The token starts at the same position, and ends at the same position as the deletion range\n // ----------\n // xxxxxxxxxx\n // 2c. The token starts at the same position, and ends after the deletion range\n // -------------\n // xxxxxxx\n //\n // 3. The token starts inside the deletion range\n // 3a. The token is inside the deletion range\n // -------\n // xxxxxxxxxxxxx\n // 3b. The token starts inside the deletion range, and ends at the same position as the deletion range\n // ----------\n // xxxxxxxxxxxxx\n // 3c. The token starts inside the deletion range, and ends after the deletion range\n // ------------\n // xxxxxxxxxxx\n //\n // 4. The token starts after the deletion range\n // -----------\n // xxxxxxxx\n //\n const tokens = this._tokens;\n const tokenCount = this._tokenCount;\n const deletedLineCount = (endDeltaLine - startDeltaLine);\n let newTokenCount = 0;\n let hasDeletedTokens = false;\n for (let i = 0; i < tokenCount; i++) {\n const srcOffset = 4 * i;\n let tokenDeltaLine = tokens[srcOffset];\n let tokenStartCharacter = tokens[srcOffset + 1];\n let tokenEndCharacter = tokens[srcOffset + 2];\n const tokenMetadata = tokens[srcOffset + 3];\n if (tokenDeltaLine < startDeltaLine || (tokenDeltaLine === startDeltaLine && tokenEndCharacter <= startCharacter)) {\n // 1a. The token is completely before the deletion range\n // => nothing to do\n newTokenCount++;\n continue;\n }\n else if (tokenDeltaLine === startDeltaLine && tokenStartCharacter < startCharacter) {\n // 1b, 1c, 1d\n // => the token survives, but it needs to shrink\n if (tokenDeltaLine === endDeltaLine && tokenEndCharacter > endCharacter) {\n // 1d. The token starts before, the deletion range is inside the token\n // => the token shrinks by the deletion character count\n tokenEndCharacter -= (endCharacter - startCharacter);\n }\n else {\n // 1b. The token starts before, the deletion range ends after the token\n // 1c. The token starts before, the deletion range ends precisely with the token\n // => the token shrinks its ending to the deletion start\n tokenEndCharacter = startCharacter;\n }\n }\n else if (tokenDeltaLine === startDeltaLine && tokenStartCharacter === startCharacter) {\n // 2a, 2b, 2c\n if (tokenDeltaLine === endDeltaLine && tokenEndCharacter > endCharacter) {\n // 2c. The token starts at the same position, and ends after the deletion range\n // => the token shrinks by the deletion character count\n tokenEndCharacter -= (endCharacter - startCharacter);\n }\n else {\n // 2a. The token starts at the same position, and ends inside the deletion range\n // 2b. The token starts at the same position, and ends at the same position as the deletion range\n // => the token is deleted\n hasDeletedTokens = true;\n continue;\n }\n }\n else if (tokenDeltaLine < endDeltaLine || (tokenDeltaLine === endDeltaLine && tokenStartCharacter < endCharacter)) {\n // 3a, 3b, 3c\n if (tokenDeltaLine === endDeltaLine && tokenEndCharacter > endCharacter) {\n // 3c. The token starts inside the deletion range, and ends after the deletion range\n // => the token moves left and shrinks\n if (tokenDeltaLine === startDeltaLine) {\n // the deletion started on the same line as the token\n // => the token moves left and shrinks\n tokenStartCharacter = startCharacter;\n tokenEndCharacter = tokenStartCharacter + (tokenEndCharacter - endCharacter);\n }\n else {\n // the deletion started on a line above the token\n // => the token moves to the beginning of the line\n tokenStartCharacter = 0;\n tokenEndCharacter = tokenStartCharacter + (tokenEndCharacter - endCharacter);\n }\n }\n else {\n // 3a. The token is inside the deletion range\n // 3b. The token starts inside the deletion range, and ends at the same position as the deletion range\n // => the token is deleted\n hasDeletedTokens = true;\n continue;\n }\n }\n else if (tokenDeltaLine > endDeltaLine) {\n // 4. (partial) The token starts after the deletion range, on a line below...\n if (deletedLineCount === 0 && !hasDeletedTokens) {\n // early stop, there is no need to walk all the tokens and do nothing...\n newTokenCount = tokenCount;\n break;\n }\n tokenDeltaLine -= deletedLineCount;\n }\n else if (tokenDeltaLine === endDeltaLine && tokenStartCharacter >= endCharacter) {\n // 4. (continued) The token starts after the deletion range, on the last line where a deletion occurs\n if (horizontalShiftForFirstLineTokens && tokenDeltaLine === 0) {\n tokenStartCharacter += horizontalShiftForFirstLineTokens;\n tokenEndCharacter += horizontalShiftForFirstLineTokens;\n }\n tokenDeltaLine -= deletedLineCount;\n tokenStartCharacter -= (endCharacter - startCharacter);\n tokenEndCharacter -= (endCharacter - startCharacter);\n }\n else {\n throw new Error(`Not possible!`);\n }\n const destOffset = 4 * newTokenCount;\n tokens[destOffset] = tokenDeltaLine;\n tokens[destOffset + 1] = tokenStartCharacter;\n tokens[destOffset + 2] = tokenEndCharacter;\n tokens[destOffset + 3] = tokenMetadata;\n newTokenCount++;\n }\n this._tokenCount = newTokenCount;\n }\n acceptInsertText(deltaLine, character, eolCount, firstLineLength, lastLineLength, firstCharCode) {\n // Here are the cases I used to think about this:\n //\n // 1. The token is completely before the insertion point\n // ----------- |\n // 2. The token ends precisely at the insertion point\n // -----------|\n // 3. The token contains the insertion point\n // -----|------\n // 4. The token starts precisely at the insertion point\n // |-----------\n // 5. The token is completely after the insertion point\n // | -----------\n //\n const isInsertingPreciselyOneWordCharacter = (eolCount === 0\n && firstLineLength === 1\n && ((firstCharCode >= 48 /* CharCode.Digit0 */ && firstCharCode <= 57 /* CharCode.Digit9 */)\n || (firstCharCode >= 65 /* CharCode.A */ && firstCharCode <= 90 /* CharCode.Z */)\n || (firstCharCode >= 97 /* CharCode.a */ && firstCharCode <= 122 /* CharCode.z */)));\n const tokens = this._tokens;\n const tokenCount = this._tokenCount;\n for (let i = 0; i < tokenCount; i++) {\n const offset = 4 * i;\n let tokenDeltaLine = tokens[offset];\n let tokenStartCharacter = tokens[offset + 1];\n let tokenEndCharacter = tokens[offset + 2];\n if (tokenDeltaLine < deltaLine || (tokenDeltaLine === deltaLine && tokenEndCharacter < character)) {\n // 1. The token is completely before the insertion point\n // => nothing to do\n continue;\n }\n else if (tokenDeltaLine === deltaLine && tokenEndCharacter === character) {\n // 2. The token ends precisely at the insertion point\n // => expand the end character only if inserting precisely one character that is a word character\n if (isInsertingPreciselyOneWordCharacter) {\n tokenEndCharacter += 1;\n }\n else {\n continue;\n }\n }\n else if (tokenDeltaLine === deltaLine && tokenStartCharacter < character && character < tokenEndCharacter) {\n // 3. The token contains the insertion point\n if (eolCount === 0) {\n // => just expand the end character\n tokenEndCharacter += firstLineLength;\n }\n else {\n // => cut off the token\n tokenEndCharacter = character;\n }\n }\n else {\n // 4. or 5.\n if (tokenDeltaLine === deltaLine && tokenStartCharacter === character) {\n // 4. The token starts precisely at the insertion point\n // => grow the token (by keeping its start constant) only if inserting precisely one character that is a word character\n // => otherwise behave as in case 5.\n if (isInsertingPreciselyOneWordCharacter) {\n continue;\n }\n }\n // => the token must move and keep its size constant\n if (tokenDeltaLine === deltaLine) {\n tokenDeltaLine += eolCount;\n // this token is on the line where the insertion is taking place\n if (eolCount === 0) {\n tokenStartCharacter += firstLineLength;\n tokenEndCharacter += firstLineLength;\n }\n else {\n const tokenLength = tokenEndCharacter - tokenStartCharacter;\n tokenStartCharacter = lastLineLength + (tokenStartCharacter - character);\n tokenEndCharacter = tokenStartCharacter + tokenLength;\n }\n }\n else {\n tokenDeltaLine += eolCount;\n }\n }\n tokens[offset] = tokenDeltaLine;\n tokens[offset + 1] = tokenStartCharacter;\n tokens[offset + 2] = tokenEndCharacter;\n }\n }\n}\nexport class SparseLineTokens {\n constructor(tokens) {\n this._tokens = tokens;\n }\n getCount() {\n return this._tokens.length / 4;\n }\n getStartCharacter(tokenIndex) {\n return this._tokens[4 * tokenIndex + 1];\n }\n getEndCharacter(tokenIndex) {\n return this._tokens[4 * tokenIndex + 2];\n }\n getMetadata(tokenIndex) {\n return this._tokens[4 * tokenIndex + 3];\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { TokenMetadata } from '../encodedTokenAttributes.js';\nimport { IThemeService } from '../../../platform/theme/common/themeService.js';\nimport { ILogService, LogLevel } from '../../../platform/log/common/log.js';\nimport { SparseMultilineTokens } from '../tokens/sparseMultilineTokens.js';\nimport { ILanguageService } from '../languages/language.js';\nlet SemanticTokensProviderStyling = class SemanticTokensProviderStyling {\n constructor(_legend, _themeService, _languageService, _logService) {\n this._legend = _legend;\n this._themeService = _themeService;\n this._languageService = _languageService;\n this._logService = _logService;\n this._hasWarnedOverlappingTokens = false;\n this._hasWarnedInvalidLengthTokens = false;\n this._hasWarnedInvalidEditStart = false;\n this._hashTable = new HashTable();\n }\n getMetadata(tokenTypeIndex, tokenModifierSet, languageId) {\n const encodedLanguageId = this._languageService.languageIdCodec.encodeLanguageId(languageId);\n const entry = this._hashTable.get(tokenTypeIndex, tokenModifierSet, encodedLanguageId);\n let metadata;\n if (entry) {\n metadata = entry.metadata;\n if (this._logService.getLevel() === LogLevel.Trace) {\n this._logService.trace(`SemanticTokensProviderStyling [CACHED] ${tokenTypeIndex} / ${tokenModifierSet}: foreground ${TokenMetadata.getForeground(metadata)}, fontStyle ${TokenMetadata.getFontStyle(metadata).toString(2)}`);\n }\n }\n else {\n let tokenType = this._legend.tokenTypes[tokenTypeIndex];\n const tokenModifiers = [];\n if (tokenType) {\n let modifierSet = tokenModifierSet;\n for (let modifierIndex = 0; modifierSet > 0 && modifierIndex < this._legend.tokenModifiers.length; modifierIndex++) {\n if (modifierSet & 1) {\n tokenModifiers.push(this._legend.tokenModifiers[modifierIndex]);\n }\n modifierSet = modifierSet >> 1;\n }\n if (modifierSet > 0 && this._logService.getLevel() === LogLevel.Trace) {\n this._logService.trace(`SemanticTokensProviderStyling: unknown token modifier index: ${tokenModifierSet.toString(2)} for legend: ${JSON.stringify(this._legend.tokenModifiers)}`);\n tokenModifiers.push('not-in-legend');\n }\n const tokenStyle = this._themeService.getColorTheme().getTokenStyleMetadata(tokenType, tokenModifiers, languageId);\n if (typeof tokenStyle === 'undefined') {\n metadata = 2147483647 /* SemanticTokensProviderStylingConstants.NO_STYLING */;\n }\n else {\n metadata = 0;\n if (typeof tokenStyle.italic !== 'undefined') {\n const italicBit = (tokenStyle.italic ? 1 /* FontStyle.Italic */ : 0) << 11 /* MetadataConsts.FONT_STYLE_OFFSET */;\n metadata |= italicBit | 1 /* MetadataConsts.SEMANTIC_USE_ITALIC */;\n }\n if (typeof tokenStyle.bold !== 'undefined') {\n const boldBit = (tokenStyle.bold ? 2 /* FontStyle.Bold */ : 0) << 11 /* MetadataConsts.FONT_STYLE_OFFSET */;\n metadata |= boldBit | 2 /* MetadataConsts.SEMANTIC_USE_BOLD */;\n }\n if (typeof tokenStyle.underline !== 'undefined') {\n const underlineBit = (tokenStyle.underline ? 4 /* FontStyle.Underline */ : 0) << 11 /* MetadataConsts.FONT_STYLE_OFFSET */;\n metadata |= underlineBit | 4 /* MetadataConsts.SEMANTIC_USE_UNDERLINE */;\n }\n if (typeof tokenStyle.strikethrough !== 'undefined') {\n const strikethroughBit = (tokenStyle.strikethrough ? 8 /* FontStyle.Strikethrough */ : 0) << 11 /* MetadataConsts.FONT_STYLE_OFFSET */;\n metadata |= strikethroughBit | 8 /* MetadataConsts.SEMANTIC_USE_STRIKETHROUGH */;\n }\n if (tokenStyle.foreground) {\n const foregroundBits = (tokenStyle.foreground) << 15 /* MetadataConsts.FOREGROUND_OFFSET */;\n metadata |= foregroundBits | 16 /* MetadataConsts.SEMANTIC_USE_FOREGROUND */;\n }\n if (metadata === 0) {\n // Nothing!\n metadata = 2147483647 /* SemanticTokensProviderStylingConstants.NO_STYLING */;\n }\n }\n }\n else {\n if (this._logService.getLevel() === LogLevel.Trace) {\n this._logService.trace(`SemanticTokensProviderStyling: unknown token type index: ${tokenTypeIndex} for legend: ${JSON.stringify(this._legend.tokenTypes)}`);\n }\n metadata = 2147483647 /* SemanticTokensProviderStylingConstants.NO_STYLING */;\n tokenType = 'not-in-legend';\n }\n this._hashTable.add(tokenTypeIndex, tokenModifierSet, encodedLanguageId, metadata);\n if (this._logService.getLevel() === LogLevel.Trace) {\n this._logService.trace(`SemanticTokensProviderStyling ${tokenTypeIndex} (${tokenType}) / ${tokenModifierSet} (${tokenModifiers.join(' ')}): foreground ${TokenMetadata.getForeground(metadata)}, fontStyle ${TokenMetadata.getFontStyle(metadata).toString(2)}`);\n }\n }\n return metadata;\n }\n warnOverlappingSemanticTokens(lineNumber, startColumn) {\n if (!this._hasWarnedOverlappingTokens) {\n this._hasWarnedOverlappingTokens = true;\n console.warn(`Overlapping semantic tokens detected at lineNumber ${lineNumber}, column ${startColumn}`);\n }\n }\n warnInvalidLengthSemanticTokens(lineNumber, startColumn) {\n if (!this._hasWarnedInvalidLengthTokens) {\n this._hasWarnedInvalidLengthTokens = true;\n console.warn(`Semantic token with invalid length detected at lineNumber ${lineNumber}, column ${startColumn}`);\n }\n }\n warnInvalidEditStart(previousResultId, resultId, editIndex, editStart, maxExpectedStart) {\n if (!this._hasWarnedInvalidEditStart) {\n this._hasWarnedInvalidEditStart = true;\n console.warn(`Invalid semantic tokens edit detected (previousResultId: ${previousResultId}, resultId: ${resultId}) at edit #${editIndex}: The provided start offset ${editStart} is outside the previous data (length ${maxExpectedStart}).`);\n }\n }\n};\nSemanticTokensProviderStyling = __decorate([\n __param(1, IThemeService),\n __param(2, ILanguageService),\n __param(3, ILogService)\n], SemanticTokensProviderStyling);\nexport { SemanticTokensProviderStyling };\nexport function toMultilineTokens2(tokens, styling, languageId) {\n const srcData = tokens.data;\n const tokenCount = (tokens.data.length / 5) | 0;\n const tokensPerArea = Math.max(Math.ceil(tokenCount / 1024 /* SemanticColoringConstants.DesiredMaxAreas */), 400 /* SemanticColoringConstants.DesiredTokensPerArea */);\n const result = [];\n let tokenIndex = 0;\n let lastLineNumber = 1;\n let lastStartCharacter = 0;\n while (tokenIndex < tokenCount) {\n const tokenStartIndex = tokenIndex;\n let tokenEndIndex = Math.min(tokenStartIndex + tokensPerArea, tokenCount);\n // Keep tokens on the same line in the same area...\n if (tokenEndIndex < tokenCount) {\n let smallTokenEndIndex = tokenEndIndex;\n while (smallTokenEndIndex - 1 > tokenStartIndex && srcData[5 * smallTokenEndIndex] === 0) {\n smallTokenEndIndex--;\n }\n if (smallTokenEndIndex - 1 === tokenStartIndex) {\n // there are so many tokens on this line that our area would be empty, we must now go right\n let bigTokenEndIndex = tokenEndIndex;\n while (bigTokenEndIndex + 1 < tokenCount && srcData[5 * bigTokenEndIndex] === 0) {\n bigTokenEndIndex++;\n }\n tokenEndIndex = bigTokenEndIndex;\n }\n else {\n tokenEndIndex = smallTokenEndIndex;\n }\n }\n let destData = new Uint32Array((tokenEndIndex - tokenStartIndex) * 4);\n let destOffset = 0;\n let areaLine = 0;\n let prevLineNumber = 0;\n let prevEndCharacter = 0;\n while (tokenIndex < tokenEndIndex) {\n const srcOffset = 5 * tokenIndex;\n const deltaLine = srcData[srcOffset];\n const deltaCharacter = srcData[srcOffset + 1];\n // Casting both `lineNumber`, `startCharacter` and `endCharacter` here to uint32 using `|0`\n // to validate below with the actual values that will be inserted in the Uint32Array result\n const lineNumber = (lastLineNumber + deltaLine) | 0;\n const startCharacter = (deltaLine === 0 ? (lastStartCharacter + deltaCharacter) | 0 : deltaCharacter);\n const length = srcData[srcOffset + 2];\n const endCharacter = (startCharacter + length) | 0;\n const tokenTypeIndex = srcData[srcOffset + 3];\n const tokenModifierSet = srcData[srcOffset + 4];\n if (endCharacter <= startCharacter) {\n // this token is invalid (most likely a negative length casted to uint32)\n styling.warnInvalidLengthSemanticTokens(lineNumber, startCharacter + 1);\n }\n else if (prevLineNumber === lineNumber && prevEndCharacter > startCharacter) {\n // this token overlaps with the previous token\n styling.warnOverlappingSemanticTokens(lineNumber, startCharacter + 1);\n }\n else {\n const metadata = styling.getMetadata(tokenTypeIndex, tokenModifierSet, languageId);\n if (metadata !== 2147483647 /* SemanticTokensProviderStylingConstants.NO_STYLING */) {\n if (areaLine === 0) {\n areaLine = lineNumber;\n }\n destData[destOffset] = lineNumber - areaLine;\n destData[destOffset + 1] = startCharacter;\n destData[destOffset + 2] = endCharacter;\n destData[destOffset + 3] = metadata;\n destOffset += 4;\n prevLineNumber = lineNumber;\n prevEndCharacter = endCharacter;\n }\n }\n lastLineNumber = lineNumber;\n lastStartCharacter = startCharacter;\n tokenIndex++;\n }\n if (destOffset !== destData.length) {\n destData = destData.subarray(0, destOffset);\n }\n const tokens = SparseMultilineTokens.create(areaLine, destData);\n result.push(tokens);\n }\n return result;\n}\nclass HashTableEntry {\n constructor(tokenTypeIndex, tokenModifierSet, languageId, metadata) {\n this.tokenTypeIndex = tokenTypeIndex;\n this.tokenModifierSet = tokenModifierSet;\n this.languageId = languageId;\n this.metadata = metadata;\n this.next = null;\n }\n}\nclass HashTable {\n constructor() {\n this._elementsCount = 0;\n this._currentLengthIndex = 0;\n this._currentLength = HashTable._SIZES[this._currentLengthIndex];\n this._growCount = Math.round(this._currentLengthIndex + 1 < HashTable._SIZES.length ? 2 / 3 * this._currentLength : 0);\n this._elements = [];\n HashTable._nullOutEntries(this._elements, this._currentLength);\n }\n static _nullOutEntries(entries, length) {\n for (let i = 0; i < length; i++) {\n entries[i] = null;\n }\n }\n _hash2(n1, n2) {\n return (((n1 << 5) - n1) + n2) | 0; // n1 * 31 + n2, keep as int32\n }\n _hashFunc(tokenTypeIndex, tokenModifierSet, languageId) {\n return this._hash2(this._hash2(tokenTypeIndex, tokenModifierSet), languageId) % this._currentLength;\n }\n get(tokenTypeIndex, tokenModifierSet, languageId) {\n const hash = this._hashFunc(tokenTypeIndex, tokenModifierSet, languageId);\n let p = this._elements[hash];\n while (p) {\n if (p.tokenTypeIndex === tokenTypeIndex && p.tokenModifierSet === tokenModifierSet && p.languageId === languageId) {\n return p;\n }\n p = p.next;\n }\n return null;\n }\n add(tokenTypeIndex, tokenModifierSet, languageId, metadata) {\n this._elementsCount++;\n if (this._growCount !== 0 && this._elementsCount >= this._growCount) {\n // expand!\n const oldElements = this._elements;\n this._currentLengthIndex++;\n this._currentLength = HashTable._SIZES[this._currentLengthIndex];\n this._growCount = Math.round(this._currentLengthIndex + 1 < HashTable._SIZES.length ? 2 / 3 * this._currentLength : 0);\n this._elements = [];\n HashTable._nullOutEntries(this._elements, this._currentLength);\n for (const first of oldElements) {\n let p = first;\n while (p) {\n const oldNext = p.next;\n p.next = null;\n this._add(p);\n p = oldNext;\n }\n }\n }\n this._add(new HashTableEntry(tokenTypeIndex, tokenModifierSet, languageId, metadata));\n }\n _add(element) {\n const hash = this._hashFunc(element.tokenTypeIndex, element.tokenModifierSet, element.languageId);\n element.next = this._elements[hash];\n this._elements[hash] = element;\n }\n}\nHashTable._SIZES = [3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143];\n","import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';\nexport const ITextResourceConfigurationService = createDecorator('textResourceConfigurationService');\nexport const ITextResourcePropertiesService = createDecorator('textResourcePropertiesService');\n","/*---------------------------------------------------------------------------------------------\n * 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 { Range } from '../core/range.js';\nimport { Searcher } from '../model/textModelSearch.js';\nimport * as strings from '../../../base/common/strings.js';\nimport { assertNever } from '../../../base/common/types.js';\nimport { DEFAULT_WORD_REGEXP, getWordAtText } from '../core/wordHelper.js';\nexport class UnicodeTextModelHighlighter {\n static computeUnicodeHighlights(model, options, range) {\n const startLine = range ? range.startLineNumber : 1;\n const endLine = range ? range.endLineNumber : model.getLineCount();\n const codePointHighlighter = new CodePointHighlighter(options);\n const candidates = codePointHighlighter.getCandidateCodePoints();\n let regex;\n if (candidates === 'allNonBasicAscii') {\n regex = new RegExp('[^\\\\t\\\\n\\\\r\\\\x20-\\\\x7E]', 'g');\n }\n else {\n regex = new RegExp(`${buildRegExpCharClassExpr(Array.from(candidates))}`, 'g');\n }\n const searcher = new Searcher(null, regex);\n const ranges = [];\n let hasMore = false;\n let m;\n let ambiguousCharacterCount = 0;\n let invisibleCharacterCount = 0;\n let nonBasicAsciiCharacterCount = 0;\n forLoop: for (let lineNumber = startLine, lineCount = endLine; lineNumber <= lineCount; lineNumber++) {\n const lineContent = model.getLineContent(lineNumber);\n const lineLength = lineContent.length;\n // Reset regex to search from the beginning\n searcher.reset(0);\n do {\n m = searcher.next(lineContent);\n if (m) {\n let startIndex = m.index;\n let endIndex = m.index + m[0].length;\n // Extend range to entire code point\n if (startIndex > 0) {\n const charCodeBefore = lineContent.charCodeAt(startIndex - 1);\n if (strings.isHighSurrogate(charCodeBefore)) {\n startIndex--;\n }\n }\n if (endIndex + 1 < lineLength) {\n const charCodeBefore = lineContent.charCodeAt(endIndex - 1);\n if (strings.isHighSurrogate(charCodeBefore)) {\n endIndex++;\n }\n }\n const str = lineContent.substring(startIndex, endIndex);\n const word = getWordAtText(startIndex + 1, DEFAULT_WORD_REGEXP, lineContent, 0);\n const highlightReason = codePointHighlighter.shouldHighlightNonBasicASCII(str, word ? word.word : null);\n if (highlightReason !== 0 /* SimpleHighlightReason.None */) {\n if (highlightReason === 3 /* SimpleHighlightReason.Ambiguous */) {\n ambiguousCharacterCount++;\n }\n else if (highlightReason === 2 /* SimpleHighlightReason.Invisible */) {\n invisibleCharacterCount++;\n }\n else if (highlightReason === 1 /* SimpleHighlightReason.NonBasicASCII */) {\n nonBasicAsciiCharacterCount++;\n }\n else {\n assertNever(highlightReason);\n }\n const MAX_RESULT_LENGTH = 1000;\n if (ranges.length >= MAX_RESULT_LENGTH) {\n hasMore = true;\n break forLoop;\n }\n ranges.push(new Range(lineNumber, startIndex + 1, lineNumber, endIndex + 1));\n }\n }\n } while (m);\n }\n return {\n ranges,\n hasMore,\n ambiguousCharacterCount,\n invisibleCharacterCount,\n nonBasicAsciiCharacterCount\n };\n }\n static computeUnicodeHighlightReason(char, options) {\n const codePointHighlighter = new CodePointHighlighter(options);\n const reason = codePointHighlighter.shouldHighlightNonBasicASCII(char, null);\n switch (reason) {\n case 0 /* SimpleHighlightReason.None */:\n return null;\n case 2 /* SimpleHighlightReason.Invisible */:\n return { kind: 1 /* UnicodeHighlighterReasonKind.Invisible */ };\n case 3 /* SimpleHighlightReason.Ambiguous */: {\n const codePoint = char.codePointAt(0);\n const primaryConfusable = codePointHighlighter.ambiguousCharacters.getPrimaryConfusable(codePoint);\n const notAmbiguousInLocales = strings.AmbiguousCharacters.getLocales().filter((l) => !strings.AmbiguousCharacters.getInstance(new Set([...options.allowedLocales, l])).isAmbiguous(codePoint));\n return { kind: 0 /* UnicodeHighlighterReasonKind.Ambiguous */, confusableWith: String.fromCodePoint(primaryConfusable), notAmbiguousInLocales };\n }\n case 1 /* SimpleHighlightReason.NonBasicASCII */:\n return { kind: 2 /* UnicodeHighlighterReasonKind.NonBasicAscii */ };\n }\n }\n}\nfunction buildRegExpCharClassExpr(codePoints, flags) {\n const src = `[${strings.escapeRegExpCharacters(codePoints.map((i) => String.fromCodePoint(i)).join(''))}]`;\n return src;\n}\nclass CodePointHighlighter {\n constructor(options) {\n this.options = options;\n this.allowedCodePoints = new Set(options.allowedCodePoints);\n this.ambiguousCharacters = strings.AmbiguousCharacters.getInstance(new Set(options.allowedLocales));\n }\n getCandidateCodePoints() {\n if (this.options.nonBasicASCII) {\n return 'allNonBasicAscii';\n }\n const set = new Set();\n if (this.options.invisibleCharacters) {\n for (const cp of strings.InvisibleCharacters.codePoints) {\n if (!isAllowedInvisibleCharacter(String.fromCodePoint(cp))) {\n set.add(cp);\n }\n }\n }\n if (this.options.ambiguousCharacters) {\n for (const cp of this.ambiguousCharacters.getConfusableCodePoints()) {\n set.add(cp);\n }\n }\n for (const cp of this.allowedCodePoints) {\n set.delete(cp);\n }\n return set;\n }\n shouldHighlightNonBasicASCII(character, wordContext) {\n const codePoint = character.codePointAt(0);\n if (this.allowedCodePoints.has(codePoint)) {\n return 0 /* SimpleHighlightReason.None */;\n }\n if (this.options.nonBasicASCII) {\n return 1 /* SimpleHighlightReason.NonBasicASCII */;\n }\n let hasBasicASCIICharacters = false;\n let hasNonConfusableNonBasicAsciiCharacter = false;\n if (wordContext) {\n for (const char of wordContext) {\n const codePoint = char.codePointAt(0);\n const isBasicASCII = strings.isBasicASCII(char);\n hasBasicASCIICharacters = hasBasicASCIICharacters || isBasicASCII;\n if (!isBasicASCII &&\n !this.ambiguousCharacters.isAmbiguous(codePoint) &&\n !strings.InvisibleCharacters.isInvisibleCharacter(codePoint)) {\n hasNonConfusableNonBasicAsciiCharacter = true;\n }\n }\n }\n if (\n /* Don't allow mixing weird looking characters with ASCII */ !hasBasicASCIICharacters &&\n /* Is there an obviously weird looking character? */ hasNonConfusableNonBasicAsciiCharacter) {\n return 0 /* SimpleHighlightReason.None */;\n }\n if (this.options.invisibleCharacters) {\n // TODO check for emojis\n if (!isAllowedInvisibleCharacter(character) && strings.InvisibleCharacters.isInvisibleCharacter(codePoint)) {\n return 2 /* SimpleHighlightReason.Invisible */;\n }\n }\n if (this.options.ambiguousCharacters) {\n if (this.ambiguousCharacters.isAmbiguous(codePoint)) {\n return 3 /* SimpleHighlightReason.Ambiguous */;\n }\n }\n return 0 /* SimpleHighlightReason.None */;\n }\n}\nfunction isAllowedInvisibleCharacter(character) {\n return character === ' ' || character === '\\n' || character === '\\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// THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY.\nexport var AccessibilitySupport;\n(function (AccessibilitySupport) {\n /**\n * This should be the browser case where it is not known if a screen reader is attached or no.\n */\n AccessibilitySupport[AccessibilitySupport[\"Unknown\"] = 0] = \"Unknown\";\n AccessibilitySupport[AccessibilitySupport[\"Disabled\"] = 1] = \"Disabled\";\n AccessibilitySupport[AccessibilitySupport[\"Enabled\"] = 2] = \"Enabled\";\n})(AccessibilitySupport || (AccessibilitySupport = {}));\nexport var CodeActionTriggerType;\n(function (CodeActionTriggerType) {\n CodeActionTriggerType[CodeActionTriggerType[\"Invoke\"] = 1] = \"Invoke\";\n CodeActionTriggerType[CodeActionTriggerType[\"Auto\"] = 2] = \"Auto\";\n})(CodeActionTriggerType || (CodeActionTriggerType = {}));\nexport var CompletionItemInsertTextRule;\n(function (CompletionItemInsertTextRule) {\n /**\n * Adjust whitespace/indentation of multiline insert texts to\n * match the current line indentation.\n */\n CompletionItemInsertTextRule[CompletionItemInsertTextRule[\"KeepWhitespace\"] = 1] = \"KeepWhitespace\";\n /**\n * `insertText` is a snippet.\n */\n CompletionItemInsertTextRule[CompletionItemInsertTextRule[\"InsertAsSnippet\"] = 4] = \"InsertAsSnippet\";\n})(CompletionItemInsertTextRule || (CompletionItemInsertTextRule = {}));\nexport var CompletionItemKind;\n(function (CompletionItemKind) {\n CompletionItemKind[CompletionItemKind[\"Method\"] = 0] = \"Method\";\n CompletionItemKind[CompletionItemKind[\"Function\"] = 1] = \"Function\";\n CompletionItemKind[CompletionItemKind[\"Constructor\"] = 2] = \"Constructor\";\n CompletionItemKind[CompletionItemKind[\"Field\"] = 3] = \"Field\";\n CompletionItemKind[CompletionItemKind[\"Variable\"] = 4] = \"Variable\";\n CompletionItemKind[CompletionItemKind[\"Class\"] = 5] = \"Class\";\n CompletionItemKind[CompletionItemKind[\"Struct\"] = 6] = \"Struct\";\n CompletionItemKind[CompletionItemKind[\"Interface\"] = 7] = \"Interface\";\n CompletionItemKind[CompletionItemKind[\"Module\"] = 8] = \"Module\";\n CompletionItemKind[CompletionItemKind[\"Property\"] = 9] = \"Property\";\n CompletionItemKind[CompletionItemKind[\"Event\"] = 10] = \"Event\";\n CompletionItemKind[CompletionItemKind[\"Operator\"] = 11] = \"Operator\";\n CompletionItemKind[CompletionItemKind[\"Unit\"] = 12] = \"Unit\";\n CompletionItemKind[CompletionItemKind[\"Value\"] = 13] = \"Value\";\n CompletionItemKind[CompletionItemKind[\"Constant\"] = 14] = \"Constant\";\n CompletionItemKind[CompletionItemKind[\"Enum\"] = 15] = \"Enum\";\n CompletionItemKind[CompletionItemKind[\"EnumMember\"] = 16] = \"EnumMember\";\n CompletionItemKind[CompletionItemKind[\"Keyword\"] = 17] = \"Keyword\";\n CompletionItemKind[CompletionItemKind[\"Text\"] = 18] = \"Text\";\n CompletionItemKind[CompletionItemKind[\"Color\"] = 19] = \"Color\";\n CompletionItemKind[CompletionItemKind[\"File\"] = 20] = \"File\";\n CompletionItemKind[CompletionItemKind[\"Reference\"] = 21] = \"Reference\";\n CompletionItemKind[CompletionItemKind[\"Customcolor\"] = 22] = \"Customcolor\";\n CompletionItemKind[CompletionItemKind[\"Folder\"] = 23] = \"Folder\";\n CompletionItemKind[CompletionItemKind[\"TypeParameter\"] = 24] = \"TypeParameter\";\n CompletionItemKind[CompletionItemKind[\"User\"] = 25] = \"User\";\n CompletionItemKind[CompletionItemKind[\"Issue\"] = 26] = \"Issue\";\n CompletionItemKind[CompletionItemKind[\"Snippet\"] = 27] = \"Snippet\";\n})(CompletionItemKind || (CompletionItemKind = {}));\nexport var CompletionItemTag;\n(function (CompletionItemTag) {\n CompletionItemTag[CompletionItemTag[\"Deprecated\"] = 1] = \"Deprecated\";\n})(CompletionItemTag || (CompletionItemTag = {}));\n/**\n * How a suggest provider was triggered.\n */\nexport var CompletionTriggerKind;\n(function (CompletionTriggerKind) {\n CompletionTriggerKind[CompletionTriggerKind[\"Invoke\"] = 0] = \"Invoke\";\n CompletionTriggerKind[CompletionTriggerKind[\"TriggerCharacter\"] = 1] = \"TriggerCharacter\";\n CompletionTriggerKind[CompletionTriggerKind[\"TriggerForIncompleteCompletions\"] = 2] = \"TriggerForIncompleteCompletions\";\n})(CompletionTriggerKind || (CompletionTriggerKind = {}));\n/**\n * A positioning preference for rendering content widgets.\n */\nexport var ContentWidgetPositionPreference;\n(function (ContentWidgetPositionPreference) {\n /**\n * Place the content widget exactly at a position\n */\n ContentWidgetPositionPreference[ContentWidgetPositionPreference[\"EXACT\"] = 0] = \"EXACT\";\n /**\n * Place the content widget above a position\n */\n ContentWidgetPositionPreference[ContentWidgetPositionPreference[\"ABOVE\"] = 1] = \"ABOVE\";\n /**\n * Place the content widget below a position\n */\n ContentWidgetPositionPreference[ContentWidgetPositionPreference[\"BELOW\"] = 2] = \"BELOW\";\n})(ContentWidgetPositionPreference || (ContentWidgetPositionPreference = {}));\n/**\n * Describes the reason the cursor has changed its position.\n */\nexport var CursorChangeReason;\n(function (CursorChangeReason) {\n /**\n * Unknown or not set.\n */\n CursorChangeReason[CursorChangeReason[\"NotSet\"] = 0] = \"NotSet\";\n /**\n * A `model.setValue()` was called.\n */\n CursorChangeReason[CursorChangeReason[\"ContentFlush\"] = 1] = \"ContentFlush\";\n /**\n * The `model` has been changed outside of this cursor and the cursor recovers its position from associated markers.\n */\n CursorChangeReason[CursorChangeReason[\"RecoverFromMarkers\"] = 2] = \"RecoverFromMarkers\";\n /**\n * There was an explicit user gesture.\n */\n CursorChangeReason[CursorChangeReason[\"Explicit\"] = 3] = \"Explicit\";\n /**\n * There was a Paste.\n */\n CursorChangeReason[CursorChangeReason[\"Paste\"] = 4] = \"Paste\";\n /**\n * There was an Undo.\n */\n CursorChangeReason[CursorChangeReason[\"Undo\"] = 5] = \"Undo\";\n /**\n * There was a Redo.\n */\n CursorChangeReason[CursorChangeReason[\"Redo\"] = 6] = \"Redo\";\n})(CursorChangeReason || (CursorChangeReason = {}));\n/**\n * The default end of line to use when instantiating models.\n */\nexport var DefaultEndOfLine;\n(function (DefaultEndOfLine) {\n /**\n * Use line feed (\\n) as the end of line character.\n */\n DefaultEndOfLine[DefaultEndOfLine[\"LF\"] = 1] = \"LF\";\n /**\n * Use carriage return and line feed (\\r\\n) as the end of line character.\n */\n DefaultEndOfLine[DefaultEndOfLine[\"CRLF\"] = 2] = \"CRLF\";\n})(DefaultEndOfLine || (DefaultEndOfLine = {}));\n/**\n * A document highlight kind.\n */\nexport var DocumentHighlightKind;\n(function (DocumentHighlightKind) {\n /**\n * A textual occurrence.\n */\n DocumentHighlightKind[DocumentHighlightKind[\"Text\"] = 0] = \"Text\";\n /**\n * Read-access of a symbol, like reading a variable.\n */\n DocumentHighlightKind[DocumentHighlightKind[\"Read\"] = 1] = \"Read\";\n /**\n * Write-access of a symbol, like writing to a variable.\n */\n DocumentHighlightKind[DocumentHighlightKind[\"Write\"] = 2] = \"Write\";\n})(DocumentHighlightKind || (DocumentHighlightKind = {}));\n/**\n * Configuration options for auto indentation in the editor\n */\nexport var EditorAutoIndentStrategy;\n(function (EditorAutoIndentStrategy) {\n EditorAutoIndentStrategy[EditorAutoIndentStrategy[\"None\"] = 0] = \"None\";\n EditorAutoIndentStrategy[EditorAutoIndentStrategy[\"Keep\"] = 1] = \"Keep\";\n EditorAutoIndentStrategy[EditorAutoIndentStrategy[\"Brackets\"] = 2] = \"Brackets\";\n EditorAutoIndentStrategy[EditorAutoIndentStrategy[\"Advanced\"] = 3] = \"Advanced\";\n EditorAutoIndentStrategy[EditorAutoIndentStrategy[\"Full\"] = 4] = \"Full\";\n})(EditorAutoIndentStrategy || (EditorAutoIndentStrategy = {}));\nexport var EditorOption;\n(function (EditorOption) {\n EditorOption[EditorOption[\"acceptSuggestionOnCommitCharacter\"] = 0] = \"acceptSuggestionOnCommitCharacter\";\n EditorOption[EditorOption[\"acceptSuggestionOnEnter\"] = 1] = \"acceptSuggestionOnEnter\";\n EditorOption[EditorOption[\"accessibilitySupport\"] = 2] = \"accessibilitySupport\";\n EditorOption[EditorOption[\"accessibilityPageSize\"] = 3] = \"accessibilityPageSize\";\n EditorOption[EditorOption[\"ariaLabel\"] = 4] = \"ariaLabel\";\n EditorOption[EditorOption[\"autoClosingBrackets\"] = 5] = \"autoClosingBrackets\";\n EditorOption[EditorOption[\"autoClosingDelete\"] = 6] = \"autoClosingDelete\";\n EditorOption[EditorOption[\"autoClosingOvertype\"] = 7] = \"autoClosingOvertype\";\n EditorOption[EditorOption[\"autoClosingQuotes\"] = 8] = \"autoClosingQuotes\";\n EditorOption[EditorOption[\"autoIndent\"] = 9] = \"autoIndent\";\n EditorOption[EditorOption[\"automaticLayout\"] = 10] = \"automaticLayout\";\n EditorOption[EditorOption[\"autoSurround\"] = 11] = \"autoSurround\";\n EditorOption[EditorOption[\"bracketPairColorization\"] = 12] = \"bracketPairColorization\";\n EditorOption[EditorOption[\"guides\"] = 13] = \"guides\";\n EditorOption[EditorOption[\"codeLens\"] = 14] = \"codeLens\";\n EditorOption[EditorOption[\"codeLensFontFamily\"] = 15] = \"codeLensFontFamily\";\n EditorOption[EditorOption[\"codeLensFontSize\"] = 16] = \"codeLensFontSize\";\n EditorOption[EditorOption[\"colorDecorators\"] = 17] = \"colorDecorators\";\n EditorOption[EditorOption[\"columnSelection\"] = 18] = \"columnSelection\";\n EditorOption[EditorOption[\"comments\"] = 19] = \"comments\";\n EditorOption[EditorOption[\"contextmenu\"] = 20] = \"contextmenu\";\n EditorOption[EditorOption[\"copyWithSyntaxHighlighting\"] = 21] = \"copyWithSyntaxHighlighting\";\n EditorOption[EditorOption[\"cursorBlinking\"] = 22] = \"cursorBlinking\";\n EditorOption[EditorOption[\"cursorSmoothCaretAnimation\"] = 23] = \"cursorSmoothCaretAnimation\";\n EditorOption[EditorOption[\"cursorStyle\"] = 24] = \"cursorStyle\";\n EditorOption[EditorOption[\"cursorSurroundingLines\"] = 25] = \"cursorSurroundingLines\";\n EditorOption[EditorOption[\"cursorSurroundingLinesStyle\"] = 26] = \"cursorSurroundingLinesStyle\";\n EditorOption[EditorOption[\"cursorWidth\"] = 27] = \"cursorWidth\";\n EditorOption[EditorOption[\"disableLayerHinting\"] = 28] = \"disableLayerHinting\";\n EditorOption[EditorOption[\"disableMonospaceOptimizations\"] = 29] = \"disableMonospaceOptimizations\";\n EditorOption[EditorOption[\"domReadOnly\"] = 30] = \"domReadOnly\";\n EditorOption[EditorOption[\"dragAndDrop\"] = 31] = \"dragAndDrop\";\n EditorOption[EditorOption[\"dropIntoEditor\"] = 32] = \"dropIntoEditor\";\n EditorOption[EditorOption[\"emptySelectionClipboard\"] = 33] = \"emptySelectionClipboard\";\n EditorOption[EditorOption[\"experimental\"] = 34] = \"experimental\";\n EditorOption[EditorOption[\"extraEditorClassName\"] = 35] = \"extraEditorClassName\";\n EditorOption[EditorOption[\"fastScrollSensitivity\"] = 36] = \"fastScrollSensitivity\";\n EditorOption[EditorOption[\"find\"] = 37] = \"find\";\n EditorOption[EditorOption[\"fixedOverflowWidgets\"] = 38] = \"fixedOverflowWidgets\";\n EditorOption[EditorOption[\"folding\"] = 39] = \"folding\";\n EditorOption[EditorOption[\"foldingStrategy\"] = 40] = \"foldingStrategy\";\n EditorOption[EditorOption[\"foldingHighlight\"] = 41] = \"foldingHighlight\";\n EditorOption[EditorOption[\"foldingImportsByDefault\"] = 42] = \"foldingImportsByDefault\";\n EditorOption[EditorOption[\"foldingMaximumRegions\"] = 43] = \"foldingMaximumRegions\";\n EditorOption[EditorOption[\"unfoldOnClickAfterEndOfLine\"] = 44] = \"unfoldOnClickAfterEndOfLine\";\n EditorOption[EditorOption[\"fontFamily\"] = 45] = \"fontFamily\";\n EditorOption[EditorOption[\"fontInfo\"] = 46] = \"fontInfo\";\n EditorOption[EditorOption[\"fontLigatures\"] = 47] = \"fontLigatures\";\n EditorOption[EditorOption[\"fontSize\"] = 48] = \"fontSize\";\n EditorOption[EditorOption[\"fontWeight\"] = 49] = \"fontWeight\";\n EditorOption[EditorOption[\"formatOnPaste\"] = 50] = \"formatOnPaste\";\n EditorOption[EditorOption[\"formatOnType\"] = 51] = \"formatOnType\";\n EditorOption[EditorOption[\"glyphMargin\"] = 52] = \"glyphMargin\";\n EditorOption[EditorOption[\"gotoLocation\"] = 53] = \"gotoLocation\";\n EditorOption[EditorOption[\"hideCursorInOverviewRuler\"] = 54] = \"hideCursorInOverviewRuler\";\n EditorOption[EditorOption[\"hover\"] = 55] = \"hover\";\n EditorOption[EditorOption[\"inDiffEditor\"] = 56] = \"inDiffEditor\";\n EditorOption[EditorOption[\"inlineSuggest\"] = 57] = \"inlineSuggest\";\n EditorOption[EditorOption[\"letterSpacing\"] = 58] = \"letterSpacing\";\n EditorOption[EditorOption[\"lightbulb\"] = 59] = \"lightbulb\";\n EditorOption[EditorOption[\"lineDecorationsWidth\"] = 60] = \"lineDecorationsWidth\";\n EditorOption[EditorOption[\"lineHeight\"] = 61] = \"lineHeight\";\n EditorOption[EditorOption[\"lineNumbers\"] = 62] = \"lineNumbers\";\n EditorOption[EditorOption[\"lineNumbersMinChars\"] = 63] = \"lineNumbersMinChars\";\n EditorOption[EditorOption[\"linkedEditing\"] = 64] = \"linkedEditing\";\n EditorOption[EditorOption[\"links\"] = 65] = \"links\";\n EditorOption[EditorOption[\"matchBrackets\"] = 66] = \"matchBrackets\";\n EditorOption[EditorOption[\"minimap\"] = 67] = \"minimap\";\n EditorOption[EditorOption[\"mouseStyle\"] = 68] = \"mouseStyle\";\n EditorOption[EditorOption[\"mouseWheelScrollSensitivity\"] = 69] = \"mouseWheelScrollSensitivity\";\n EditorOption[EditorOption[\"mouseWheelZoom\"] = 70] = \"mouseWheelZoom\";\n EditorOption[EditorOption[\"multiCursorMergeOverlapping\"] = 71] = \"multiCursorMergeOverlapping\";\n EditorOption[EditorOption[\"multiCursorModifier\"] = 72] = \"multiCursorModifier\";\n EditorOption[EditorOption[\"multiCursorPaste\"] = 73] = \"multiCursorPaste\";\n EditorOption[EditorOption[\"occurrencesHighlight\"] = 74] = \"occurrencesHighlight\";\n EditorOption[EditorOption[\"overviewRulerBorder\"] = 75] = \"overviewRulerBorder\";\n EditorOption[EditorOption[\"overviewRulerLanes\"] = 76] = \"overviewRulerLanes\";\n EditorOption[EditorOption[\"padding\"] = 77] = \"padding\";\n EditorOption[EditorOption[\"parameterHints\"] = 78] = \"parameterHints\";\n EditorOption[EditorOption[\"peekWidgetDefaultFocus\"] = 79] = \"peekWidgetDefaultFocus\";\n EditorOption[EditorOption[\"definitionLinkOpensInPeek\"] = 80] = \"definitionLinkOpensInPeek\";\n EditorOption[EditorOption[\"quickSuggestions\"] = 81] = \"quickSuggestions\";\n EditorOption[EditorOption[\"quickSuggestionsDelay\"] = 82] = \"quickSuggestionsDelay\";\n EditorOption[EditorOption[\"readOnly\"] = 83] = \"readOnly\";\n EditorOption[EditorOption[\"renameOnType\"] = 84] = \"renameOnType\";\n EditorOption[EditorOption[\"renderControlCharacters\"] = 85] = \"renderControlCharacters\";\n EditorOption[EditorOption[\"renderFinalNewline\"] = 86] = \"renderFinalNewline\";\n EditorOption[EditorOption[\"renderLineHighlight\"] = 87] = \"renderLineHighlight\";\n EditorOption[EditorOption[\"renderLineHighlightOnlyWhenFocus\"] = 88] = \"renderLineHighlightOnlyWhenFocus\";\n EditorOption[EditorOption[\"renderValidationDecorations\"] = 89] = \"renderValidationDecorations\";\n EditorOption[EditorOption[\"renderWhitespace\"] = 90] = \"renderWhitespace\";\n EditorOption[EditorOption[\"revealHorizontalRightPadding\"] = 91] = \"revealHorizontalRightPadding\";\n EditorOption[EditorOption[\"roundedSelection\"] = 92] = \"roundedSelection\";\n EditorOption[EditorOption[\"rulers\"] = 93] = \"rulers\";\n EditorOption[EditorOption[\"scrollbar\"] = 94] = \"scrollbar\";\n EditorOption[EditorOption[\"scrollBeyondLastColumn\"] = 95] = \"scrollBeyondLastColumn\";\n EditorOption[EditorOption[\"scrollBeyondLastLine\"] = 96] = \"scrollBeyondLastLine\";\n EditorOption[EditorOption[\"scrollPredominantAxis\"] = 97] = \"scrollPredominantAxis\";\n EditorOption[EditorOption[\"selectionClipboard\"] = 98] = \"selectionClipboard\";\n EditorOption[EditorOption[\"selectionHighlight\"] = 99] = \"selectionHighlight\";\n EditorOption[EditorOption[\"selectOnLineNumbers\"] = 100] = \"selectOnLineNumbers\";\n EditorOption[EditorOption[\"showFoldingControls\"] = 101] = \"showFoldingControls\";\n EditorOption[EditorOption[\"showUnused\"] = 102] = \"showUnused\";\n EditorOption[EditorOption[\"snippetSuggestions\"] = 103] = \"snippetSuggestions\";\n EditorOption[EditorOption[\"smartSelect\"] = 104] = \"smartSelect\";\n EditorOption[EditorOption[\"smoothScrolling\"] = 105] = \"smoothScrolling\";\n EditorOption[EditorOption[\"stickyTabStops\"] = 106] = \"stickyTabStops\";\n EditorOption[EditorOption[\"stopRenderingLineAfter\"] = 107] = \"stopRenderingLineAfter\";\n EditorOption[EditorOption[\"suggest\"] = 108] = \"suggest\";\n EditorOption[EditorOption[\"suggestFontSize\"] = 109] = \"suggestFontSize\";\n EditorOption[EditorOption[\"suggestLineHeight\"] = 110] = \"suggestLineHeight\";\n EditorOption[EditorOption[\"suggestOnTriggerCharacters\"] = 111] = \"suggestOnTriggerCharacters\";\n EditorOption[EditorOption[\"suggestSelection\"] = 112] = \"suggestSelection\";\n EditorOption[EditorOption[\"tabCompletion\"] = 113] = \"tabCompletion\";\n EditorOption[EditorOption[\"tabIndex\"] = 114] = \"tabIndex\";\n EditorOption[EditorOption[\"unicodeHighlighting\"] = 115] = \"unicodeHighlighting\";\n EditorOption[EditorOption[\"unusualLineTerminators\"] = 116] = \"unusualLineTerminators\";\n EditorOption[EditorOption[\"useShadowDOM\"] = 117] = \"useShadowDOM\";\n EditorOption[EditorOption[\"useTabStops\"] = 118] = \"useTabStops\";\n EditorOption[EditorOption[\"wordSeparators\"] = 119] = \"wordSeparators\";\n EditorOption[EditorOption[\"wordWrap\"] = 120] = \"wordWrap\";\n EditorOption[EditorOption[\"wordWrapBreakAfterCharacters\"] = 121] = \"wordWrapBreakAfterCharacters\";\n EditorOption[EditorOption[\"wordWrapBreakBeforeCharacters\"] = 122] = \"wordWrapBreakBeforeCharacters\";\n EditorOption[EditorOption[\"wordWrapColumn\"] = 123] = \"wordWrapColumn\";\n EditorOption[EditorOption[\"wordWrapOverride1\"] = 124] = \"wordWrapOverride1\";\n EditorOption[EditorOption[\"wordWrapOverride2\"] = 125] = \"wordWrapOverride2\";\n EditorOption[EditorOption[\"wrappingIndent\"] = 126] = \"wrappingIndent\";\n EditorOption[EditorOption[\"wrappingStrategy\"] = 127] = \"wrappingStrategy\";\n EditorOption[EditorOption[\"showDeprecated\"] = 128] = \"showDeprecated\";\n EditorOption[EditorOption[\"inlayHints\"] = 129] = \"inlayHints\";\n EditorOption[EditorOption[\"editorClassName\"] = 130] = \"editorClassName\";\n EditorOption[EditorOption[\"pixelRatio\"] = 131] = \"pixelRatio\";\n EditorOption[EditorOption[\"tabFocusMode\"] = 132] = \"tabFocusMode\";\n EditorOption[EditorOption[\"layoutInfo\"] = 133] = \"layoutInfo\";\n EditorOption[EditorOption[\"wrappingInfo\"] = 134] = \"wrappingInfo\";\n})(EditorOption || (EditorOption = {}));\n/**\n * End of line character preference.\n */\nexport var EndOfLinePreference;\n(function (EndOfLinePreference) {\n /**\n * Use the end of line character identified in the text buffer.\n */\n EndOfLinePreference[EndOfLinePreference[\"TextDefined\"] = 0] = \"TextDefined\";\n /**\n * Use line feed (\\n) as the end of line character.\n */\n EndOfLinePreference[EndOfLinePreference[\"LF\"] = 1] = \"LF\";\n /**\n * Use carriage return and line feed (\\r\\n) as the end of line character.\n */\n EndOfLinePreference[EndOfLinePreference[\"CRLF\"] = 2] = \"CRLF\";\n})(EndOfLinePreference || (EndOfLinePreference = {}));\n/**\n * End of line character preference.\n */\nexport var EndOfLineSequence;\n(function (EndOfLineSequence) {\n /**\n * Use line feed (\\n) as the end of line character.\n */\n EndOfLineSequence[EndOfLineSequence[\"LF\"] = 0] = \"LF\";\n /**\n * Use carriage return and line feed (\\r\\n) as the end of line character.\n */\n EndOfLineSequence[EndOfLineSequence[\"CRLF\"] = 1] = \"CRLF\";\n})(EndOfLineSequence || (EndOfLineSequence = {}));\n/**\n * Describes what to do with the indentation when pressing Enter.\n */\nexport var IndentAction;\n(function (IndentAction) {\n /**\n * Insert new line and copy the previous line's indentation.\n */\n IndentAction[IndentAction[\"None\"] = 0] = \"None\";\n /**\n * Insert new line and indent once (relative to the previous line's indentation).\n */\n IndentAction[IndentAction[\"Indent\"] = 1] = \"Indent\";\n /**\n * Insert two new lines:\n * - the first one indented which will hold the cursor\n * - the second one at the same indentation level\n */\n IndentAction[IndentAction[\"IndentOutdent\"] = 2] = \"IndentOutdent\";\n /**\n * Insert new line and outdent once (relative to the previous line's indentation).\n */\n IndentAction[IndentAction[\"Outdent\"] = 3] = \"Outdent\";\n})(IndentAction || (IndentAction = {}));\nexport var InjectedTextCursorStops;\n(function (InjectedTextCursorStops) {\n InjectedTextCursorStops[InjectedTextCursorStops[\"Both\"] = 0] = \"Both\";\n InjectedTextCursorStops[InjectedTextCursorStops[\"Right\"] = 1] = \"Right\";\n InjectedTextCursorStops[InjectedTextCursorStops[\"Left\"] = 2] = \"Left\";\n InjectedTextCursorStops[InjectedTextCursorStops[\"None\"] = 3] = \"None\";\n})(InjectedTextCursorStops || (InjectedTextCursorStops = {}));\nexport var InlayHintKind;\n(function (InlayHintKind) {\n InlayHintKind[InlayHintKind[\"Type\"] = 1] = \"Type\";\n InlayHintKind[InlayHintKind[\"Parameter\"] = 2] = \"Parameter\";\n})(InlayHintKind || (InlayHintKind = {}));\n/**\n * How an {@link InlineCompletionsProvider inline completion provider} was triggered.\n */\nexport var InlineCompletionTriggerKind;\n(function (InlineCompletionTriggerKind) {\n /**\n * Completion was triggered automatically while editing.\n * It is sufficient to return a single completion item in this case.\n */\n InlineCompletionTriggerKind[InlineCompletionTriggerKind[\"Automatic\"] = 0] = \"Automatic\";\n /**\n * Completion was triggered explicitly by a user gesture.\n * Return multiple completion items to enable cycling through them.\n */\n InlineCompletionTriggerKind[InlineCompletionTriggerKind[\"Explicit\"] = 1] = \"Explicit\";\n})(InlineCompletionTriggerKind || (InlineCompletionTriggerKind = {}));\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 var KeyCode;\n(function (KeyCode) {\n KeyCode[KeyCode[\"DependsOnKbLayout\"] = -1] = \"DependsOnKbLayout\";\n /**\n * Placed first to cover the 0 value of the enum.\n */\n KeyCode[KeyCode[\"Unknown\"] = 0] = \"Unknown\";\n KeyCode[KeyCode[\"Backspace\"] = 1] = \"Backspace\";\n KeyCode[KeyCode[\"Tab\"] = 2] = \"Tab\";\n KeyCode[KeyCode[\"Enter\"] = 3] = \"Enter\";\n KeyCode[KeyCode[\"Shift\"] = 4] = \"Shift\";\n KeyCode[KeyCode[\"Ctrl\"] = 5] = \"Ctrl\";\n KeyCode[KeyCode[\"Alt\"] = 6] = \"Alt\";\n KeyCode[KeyCode[\"PauseBreak\"] = 7] = \"PauseBreak\";\n KeyCode[KeyCode[\"CapsLock\"] = 8] = \"CapsLock\";\n KeyCode[KeyCode[\"Escape\"] = 9] = \"Escape\";\n KeyCode[KeyCode[\"Space\"] = 10] = \"Space\";\n KeyCode[KeyCode[\"PageUp\"] = 11] = \"PageUp\";\n KeyCode[KeyCode[\"PageDown\"] = 12] = \"PageDown\";\n KeyCode[KeyCode[\"End\"] = 13] = \"End\";\n KeyCode[KeyCode[\"Home\"] = 14] = \"Home\";\n KeyCode[KeyCode[\"LeftArrow\"] = 15] = \"LeftArrow\";\n KeyCode[KeyCode[\"UpArrow\"] = 16] = \"UpArrow\";\n KeyCode[KeyCode[\"RightArrow\"] = 17] = \"RightArrow\";\n KeyCode[KeyCode[\"DownArrow\"] = 18] = \"DownArrow\";\n KeyCode[KeyCode[\"Insert\"] = 19] = \"Insert\";\n KeyCode[KeyCode[\"Delete\"] = 20] = \"Delete\";\n KeyCode[KeyCode[\"Digit0\"] = 21] = \"Digit0\";\n KeyCode[KeyCode[\"Digit1\"] = 22] = \"Digit1\";\n KeyCode[KeyCode[\"Digit2\"] = 23] = \"Digit2\";\n KeyCode[KeyCode[\"Digit3\"] = 24] = \"Digit3\";\n KeyCode[KeyCode[\"Digit4\"] = 25] = \"Digit4\";\n KeyCode[KeyCode[\"Digit5\"] = 26] = \"Digit5\";\n KeyCode[KeyCode[\"Digit6\"] = 27] = \"Digit6\";\n KeyCode[KeyCode[\"Digit7\"] = 28] = \"Digit7\";\n KeyCode[KeyCode[\"Digit8\"] = 29] = \"Digit8\";\n KeyCode[KeyCode[\"Digit9\"] = 30] = \"Digit9\";\n KeyCode[KeyCode[\"KeyA\"] = 31] = \"KeyA\";\n KeyCode[KeyCode[\"KeyB\"] = 32] = \"KeyB\";\n KeyCode[KeyCode[\"KeyC\"] = 33] = \"KeyC\";\n KeyCode[KeyCode[\"KeyD\"] = 34] = \"KeyD\";\n KeyCode[KeyCode[\"KeyE\"] = 35] = \"KeyE\";\n KeyCode[KeyCode[\"KeyF\"] = 36] = \"KeyF\";\n KeyCode[KeyCode[\"KeyG\"] = 37] = \"KeyG\";\n KeyCode[KeyCode[\"KeyH\"] = 38] = \"KeyH\";\n KeyCode[KeyCode[\"KeyI\"] = 39] = \"KeyI\";\n KeyCode[KeyCode[\"KeyJ\"] = 40] = \"KeyJ\";\n KeyCode[KeyCode[\"KeyK\"] = 41] = \"KeyK\";\n KeyCode[KeyCode[\"KeyL\"] = 42] = \"KeyL\";\n KeyCode[KeyCode[\"KeyM\"] = 43] = \"KeyM\";\n KeyCode[KeyCode[\"KeyN\"] = 44] = \"KeyN\";\n KeyCode[KeyCode[\"KeyO\"] = 45] = \"KeyO\";\n KeyCode[KeyCode[\"KeyP\"] = 46] = \"KeyP\";\n KeyCode[KeyCode[\"KeyQ\"] = 47] = \"KeyQ\";\n KeyCode[KeyCode[\"KeyR\"] = 48] = \"KeyR\";\n KeyCode[KeyCode[\"KeyS\"] = 49] = \"KeyS\";\n KeyCode[KeyCode[\"KeyT\"] = 50] = \"KeyT\";\n KeyCode[KeyCode[\"KeyU\"] = 51] = \"KeyU\";\n KeyCode[KeyCode[\"KeyV\"] = 52] = \"KeyV\";\n KeyCode[KeyCode[\"KeyW\"] = 53] = \"KeyW\";\n KeyCode[KeyCode[\"KeyX\"] = 54] = \"KeyX\";\n KeyCode[KeyCode[\"KeyY\"] = 55] = \"KeyY\";\n KeyCode[KeyCode[\"KeyZ\"] = 56] = \"KeyZ\";\n KeyCode[KeyCode[\"Meta\"] = 57] = \"Meta\";\n KeyCode[KeyCode[\"ContextMenu\"] = 58] = \"ContextMenu\";\n KeyCode[KeyCode[\"F1\"] = 59] = \"F1\";\n KeyCode[KeyCode[\"F2\"] = 60] = \"F2\";\n KeyCode[KeyCode[\"F3\"] = 61] = \"F3\";\n KeyCode[KeyCode[\"F4\"] = 62] = \"F4\";\n KeyCode[KeyCode[\"F5\"] = 63] = \"F5\";\n KeyCode[KeyCode[\"F6\"] = 64] = \"F6\";\n KeyCode[KeyCode[\"F7\"] = 65] = \"F7\";\n KeyCode[KeyCode[\"F8\"] = 66] = \"F8\";\n KeyCode[KeyCode[\"F9\"] = 67] = \"F9\";\n KeyCode[KeyCode[\"F10\"] = 68] = \"F10\";\n KeyCode[KeyCode[\"F11\"] = 69] = \"F11\";\n KeyCode[KeyCode[\"F12\"] = 70] = \"F12\";\n KeyCode[KeyCode[\"F13\"] = 71] = \"F13\";\n KeyCode[KeyCode[\"F14\"] = 72] = \"F14\";\n KeyCode[KeyCode[\"F15\"] = 73] = \"F15\";\n KeyCode[KeyCode[\"F16\"] = 74] = \"F16\";\n KeyCode[KeyCode[\"F17\"] = 75] = \"F17\";\n KeyCode[KeyCode[\"F18\"] = 76] = \"F18\";\n KeyCode[KeyCode[\"F19\"] = 77] = \"F19\";\n KeyCode[KeyCode[\"NumLock\"] = 78] = \"NumLock\";\n KeyCode[KeyCode[\"ScrollLock\"] = 79] = \"ScrollLock\";\n /**\n * Used for miscellaneous characters; it can vary by keyboard.\n * For the US standard keyboard, the ';:' key\n */\n KeyCode[KeyCode[\"Semicolon\"] = 80] = \"Semicolon\";\n /**\n * For any country/region, the '+' key\n * For the US standard keyboard, the '=+' key\n */\n KeyCode[KeyCode[\"Equal\"] = 81] = \"Equal\";\n /**\n * For any country/region, the ',' key\n * For the US standard keyboard, the ',<' key\n */\n KeyCode[KeyCode[\"Comma\"] = 82] = \"Comma\";\n /**\n * For any country/region, the '-' key\n * For the US standard keyboard, the '-_' key\n */\n KeyCode[KeyCode[\"Minus\"] = 83] = \"Minus\";\n /**\n * For any country/region, the '.' key\n * For the US standard keyboard, the '.>' key\n */\n KeyCode[KeyCode[\"Period\"] = 84] = \"Period\";\n /**\n * Used for miscellaneous characters; it can vary by keyboard.\n * For the US standard keyboard, the '/?' key\n */\n KeyCode[KeyCode[\"Slash\"] = 85] = \"Slash\";\n /**\n * Used for miscellaneous characters; it can vary by keyboard.\n * For the US standard keyboard, the '`~' key\n */\n KeyCode[KeyCode[\"Backquote\"] = 86] = \"Backquote\";\n /**\n * Used for miscellaneous characters; it can vary by keyboard.\n * For the US standard keyboard, the '[{' key\n */\n KeyCode[KeyCode[\"BracketLeft\"] = 87] = \"BracketLeft\";\n /**\n * Used for miscellaneous characters; it can vary by keyboard.\n * For the US standard keyboard, the '\\|' key\n */\n KeyCode[KeyCode[\"Backslash\"] = 88] = \"Backslash\";\n /**\n * Used for miscellaneous characters; it can vary by keyboard.\n * For the US standard keyboard, the ']}' key\n */\n KeyCode[KeyCode[\"BracketRight\"] = 89] = \"BracketRight\";\n /**\n * Used for miscellaneous characters; it can vary by keyboard.\n * For the US standard keyboard, the ''\"' key\n */\n KeyCode[KeyCode[\"Quote\"] = 90] = \"Quote\";\n /**\n * Used for miscellaneous characters; it can vary by keyboard.\n */\n KeyCode[KeyCode[\"OEM_8\"] = 91] = \"OEM_8\";\n /**\n * Either the angle bracket key or the backslash key on the RT 102-key keyboard.\n */\n KeyCode[KeyCode[\"IntlBackslash\"] = 92] = \"IntlBackslash\";\n KeyCode[KeyCode[\"Numpad0\"] = 93] = \"Numpad0\";\n KeyCode[KeyCode[\"Numpad1\"] = 94] = \"Numpad1\";\n KeyCode[KeyCode[\"Numpad2\"] = 95] = \"Numpad2\";\n KeyCode[KeyCode[\"Numpad3\"] = 96] = \"Numpad3\";\n KeyCode[KeyCode[\"Numpad4\"] = 97] = \"Numpad4\";\n KeyCode[KeyCode[\"Numpad5\"] = 98] = \"Numpad5\";\n KeyCode[KeyCode[\"Numpad6\"] = 99] = \"Numpad6\";\n KeyCode[KeyCode[\"Numpad7\"] = 100] = \"Numpad7\";\n KeyCode[KeyCode[\"Numpad8\"] = 101] = \"Numpad8\";\n KeyCode[KeyCode[\"Numpad9\"] = 102] = \"Numpad9\";\n KeyCode[KeyCode[\"NumpadMultiply\"] = 103] = \"NumpadMultiply\";\n KeyCode[KeyCode[\"NumpadAdd\"] = 104] = \"NumpadAdd\";\n KeyCode[KeyCode[\"NUMPAD_SEPARATOR\"] = 105] = \"NUMPAD_SEPARATOR\";\n KeyCode[KeyCode[\"NumpadSubtract\"] = 106] = \"NumpadSubtract\";\n KeyCode[KeyCode[\"NumpadDecimal\"] = 107] = \"NumpadDecimal\";\n KeyCode[KeyCode[\"NumpadDivide\"] = 108] = \"NumpadDivide\";\n /**\n * Cover all key codes when IME is processing input.\n */\n KeyCode[KeyCode[\"KEY_IN_COMPOSITION\"] = 109] = \"KEY_IN_COMPOSITION\";\n KeyCode[KeyCode[\"ABNT_C1\"] = 110] = \"ABNT_C1\";\n KeyCode[KeyCode[\"ABNT_C2\"] = 111] = \"ABNT_C2\";\n KeyCode[KeyCode[\"AudioVolumeMute\"] = 112] = \"AudioVolumeMute\";\n KeyCode[KeyCode[\"AudioVolumeUp\"] = 113] = \"AudioVolumeUp\";\n KeyCode[KeyCode[\"AudioVolumeDown\"] = 114] = \"AudioVolumeDown\";\n KeyCode[KeyCode[\"BrowserSearch\"] = 115] = \"BrowserSearch\";\n KeyCode[KeyCode[\"BrowserHome\"] = 116] = \"BrowserHome\";\n KeyCode[KeyCode[\"BrowserBack\"] = 117] = \"BrowserBack\";\n KeyCode[KeyCode[\"BrowserForward\"] = 118] = \"BrowserForward\";\n KeyCode[KeyCode[\"MediaTrackNext\"] = 119] = \"MediaTrackNext\";\n KeyCode[KeyCode[\"MediaTrackPrevious\"] = 120] = \"MediaTrackPrevious\";\n KeyCode[KeyCode[\"MediaStop\"] = 121] = \"MediaStop\";\n KeyCode[KeyCode[\"MediaPlayPause\"] = 122] = \"MediaPlayPause\";\n KeyCode[KeyCode[\"LaunchMediaPlayer\"] = 123] = \"LaunchMediaPlayer\";\n KeyCode[KeyCode[\"LaunchMail\"] = 124] = \"LaunchMail\";\n KeyCode[KeyCode[\"LaunchApp2\"] = 125] = \"LaunchApp2\";\n /**\n * VK_CLEAR, 0x0C, CLEAR key\n */\n KeyCode[KeyCode[\"Clear\"] = 126] = \"Clear\";\n /**\n * Placed last to cover the length of the enum.\n * Please do not depend on this value!\n */\n KeyCode[KeyCode[\"MAX_VALUE\"] = 127] = \"MAX_VALUE\";\n})(KeyCode || (KeyCode = {}));\nexport var MarkerSeverity;\n(function (MarkerSeverity) {\n MarkerSeverity[MarkerSeverity[\"Hint\"] = 1] = \"Hint\";\n MarkerSeverity[MarkerSeverity[\"Info\"] = 2] = \"Info\";\n MarkerSeverity[MarkerSeverity[\"Warning\"] = 4] = \"Warning\";\n MarkerSeverity[MarkerSeverity[\"Error\"] = 8] = \"Error\";\n})(MarkerSeverity || (MarkerSeverity = {}));\nexport var MarkerTag;\n(function (MarkerTag) {\n MarkerTag[MarkerTag[\"Unnecessary\"] = 1] = \"Unnecessary\";\n MarkerTag[MarkerTag[\"Deprecated\"] = 2] = \"Deprecated\";\n})(MarkerTag || (MarkerTag = {}));\n/**\n * Position in the minimap to render the decoration.\n */\nexport var MinimapPosition;\n(function (MinimapPosition) {\n MinimapPosition[MinimapPosition[\"Inline\"] = 1] = \"Inline\";\n MinimapPosition[MinimapPosition[\"Gutter\"] = 2] = \"Gutter\";\n})(MinimapPosition || (MinimapPosition = {}));\n/**\n * Type of hit element with the mouse in the editor.\n */\nexport var MouseTargetType;\n(function (MouseTargetType) {\n /**\n * Mouse is on top of an unknown element.\n */\n MouseTargetType[MouseTargetType[\"UNKNOWN\"] = 0] = \"UNKNOWN\";\n /**\n * Mouse is on top of the textarea used for input.\n */\n MouseTargetType[MouseTargetType[\"TEXTAREA\"] = 1] = \"TEXTAREA\";\n /**\n * Mouse is on top of the glyph margin\n */\n MouseTargetType[MouseTargetType[\"GUTTER_GLYPH_MARGIN\"] = 2] = \"GUTTER_GLYPH_MARGIN\";\n /**\n * Mouse is on top of the line numbers\n */\n MouseTargetType[MouseTargetType[\"GUTTER_LINE_NUMBERS\"] = 3] = \"GUTTER_LINE_NUMBERS\";\n /**\n * Mouse is on top of the line decorations\n */\n MouseTargetType[MouseTargetType[\"GUTTER_LINE_DECORATIONS\"] = 4] = \"GUTTER_LINE_DECORATIONS\";\n /**\n * Mouse is on top of the whitespace left in the gutter by a view zone.\n */\n MouseTargetType[MouseTargetType[\"GUTTER_VIEW_ZONE\"] = 5] = \"GUTTER_VIEW_ZONE\";\n /**\n * Mouse is on top of text in the content.\n */\n MouseTargetType[MouseTargetType[\"CONTENT_TEXT\"] = 6] = \"CONTENT_TEXT\";\n /**\n * Mouse is on top of empty space in the content (e.g. after line text or below last line)\n */\n MouseTargetType[MouseTargetType[\"CONTENT_EMPTY\"] = 7] = \"CONTENT_EMPTY\";\n /**\n * Mouse is on top of a view zone in the content.\n */\n MouseTargetType[MouseTargetType[\"CONTENT_VIEW_ZONE\"] = 8] = \"CONTENT_VIEW_ZONE\";\n /**\n * Mouse is on top of a content widget.\n */\n MouseTargetType[MouseTargetType[\"CONTENT_WIDGET\"] = 9] = \"CONTENT_WIDGET\";\n /**\n * Mouse is on top of the decorations overview ruler.\n */\n MouseTargetType[MouseTargetType[\"OVERVIEW_RULER\"] = 10] = \"OVERVIEW_RULER\";\n /**\n * Mouse is on top of a scrollbar.\n */\n MouseTargetType[MouseTargetType[\"SCROLLBAR\"] = 11] = \"SCROLLBAR\";\n /**\n * Mouse is on top of an overlay widget.\n */\n MouseTargetType[MouseTargetType[\"OVERLAY_WIDGET\"] = 12] = \"OVERLAY_WIDGET\";\n /**\n * Mouse is outside of the editor.\n */\n MouseTargetType[MouseTargetType[\"OUTSIDE_EDITOR\"] = 13] = \"OUTSIDE_EDITOR\";\n})(MouseTargetType || (MouseTargetType = {}));\n/**\n * A positioning preference for rendering overlay widgets.\n */\nexport var OverlayWidgetPositionPreference;\n(function (OverlayWidgetPositionPreference) {\n /**\n * Position the overlay widget in the top right corner\n */\n OverlayWidgetPositionPreference[OverlayWidgetPositionPreference[\"TOP_RIGHT_CORNER\"] = 0] = \"TOP_RIGHT_CORNER\";\n /**\n * Position the overlay widget in the bottom right corner\n */\n OverlayWidgetPositionPreference[OverlayWidgetPositionPreference[\"BOTTOM_RIGHT_CORNER\"] = 1] = \"BOTTOM_RIGHT_CORNER\";\n /**\n * Position the overlay widget in the top center\n */\n OverlayWidgetPositionPreference[OverlayWidgetPositionPreference[\"TOP_CENTER\"] = 2] = \"TOP_CENTER\";\n})(OverlayWidgetPositionPreference || (OverlayWidgetPositionPreference = {}));\n/**\n * Vertical Lane in the overview ruler of the editor.\n */\nexport var OverviewRulerLane;\n(function (OverviewRulerLane) {\n OverviewRulerLane[OverviewRulerLane[\"Left\"] = 1] = \"Left\";\n OverviewRulerLane[OverviewRulerLane[\"Center\"] = 2] = \"Center\";\n OverviewRulerLane[OverviewRulerLane[\"Right\"] = 4] = \"Right\";\n OverviewRulerLane[OverviewRulerLane[\"Full\"] = 7] = \"Full\";\n})(OverviewRulerLane || (OverviewRulerLane = {}));\nexport var PositionAffinity;\n(function (PositionAffinity) {\n /**\n * Prefers the left most position.\n */\n PositionAffinity[PositionAffinity[\"Left\"] = 0] = \"Left\";\n /**\n * Prefers the right most position.\n */\n PositionAffinity[PositionAffinity[\"Right\"] = 1] = \"Right\";\n /**\n * No preference.\n */\n PositionAffinity[PositionAffinity[\"None\"] = 2] = \"None\";\n /**\n * If the given position is on injected text, prefers the position left of it.\n */\n PositionAffinity[PositionAffinity[\"LeftOfInjectedText\"] = 3] = \"LeftOfInjectedText\";\n /**\n * If the given position is on injected text, prefers the position right of it.\n */\n PositionAffinity[PositionAffinity[\"RightOfInjectedText\"] = 4] = \"RightOfInjectedText\";\n})(PositionAffinity || (PositionAffinity = {}));\nexport var RenderLineNumbersType;\n(function (RenderLineNumbersType) {\n RenderLineNumbersType[RenderLineNumbersType[\"Off\"] = 0] = \"Off\";\n RenderLineNumbersType[RenderLineNumbersType[\"On\"] = 1] = \"On\";\n RenderLineNumbersType[RenderLineNumbersType[\"Relative\"] = 2] = \"Relative\";\n RenderLineNumbersType[RenderLineNumbersType[\"Interval\"] = 3] = \"Interval\";\n RenderLineNumbersType[RenderLineNumbersType[\"Custom\"] = 4] = \"Custom\";\n})(RenderLineNumbersType || (RenderLineNumbersType = {}));\nexport var RenderMinimap;\n(function (RenderMinimap) {\n RenderMinimap[RenderMinimap[\"None\"] = 0] = \"None\";\n RenderMinimap[RenderMinimap[\"Text\"] = 1] = \"Text\";\n RenderMinimap[RenderMinimap[\"Blocks\"] = 2] = \"Blocks\";\n})(RenderMinimap || (RenderMinimap = {}));\nexport var ScrollType;\n(function (ScrollType) {\n ScrollType[ScrollType[\"Smooth\"] = 0] = \"Smooth\";\n ScrollType[ScrollType[\"Immediate\"] = 1] = \"Immediate\";\n})(ScrollType || (ScrollType = {}));\nexport var ScrollbarVisibility;\n(function (ScrollbarVisibility) {\n ScrollbarVisibility[ScrollbarVisibility[\"Auto\"] = 1] = \"Auto\";\n ScrollbarVisibility[ScrollbarVisibility[\"Hidden\"] = 2] = \"Hidden\";\n ScrollbarVisibility[ScrollbarVisibility[\"Visible\"] = 3] = \"Visible\";\n})(ScrollbarVisibility || (ScrollbarVisibility = {}));\n/**\n * The direction of a selection.\n */\nexport var SelectionDirection;\n(function (SelectionDirection) {\n /**\n * The selection starts above where it ends.\n */\n SelectionDirection[SelectionDirection[\"LTR\"] = 0] = \"LTR\";\n /**\n * The selection starts below where it ends.\n */\n SelectionDirection[SelectionDirection[\"RTL\"] = 1] = \"RTL\";\n})(SelectionDirection || (SelectionDirection = {}));\nexport var SignatureHelpTriggerKind;\n(function (SignatureHelpTriggerKind) {\n SignatureHelpTriggerKind[SignatureHelpTriggerKind[\"Invoke\"] = 1] = \"Invoke\";\n SignatureHelpTriggerKind[SignatureHelpTriggerKind[\"TriggerCharacter\"] = 2] = \"TriggerCharacter\";\n SignatureHelpTriggerKind[SignatureHelpTriggerKind[\"ContentChange\"] = 3] = \"ContentChange\";\n})(SignatureHelpTriggerKind || (SignatureHelpTriggerKind = {}));\n/**\n * A symbol kind.\n */\nexport var SymbolKind;\n(function (SymbolKind) {\n SymbolKind[SymbolKind[\"File\"] = 0] = \"File\";\n SymbolKind[SymbolKind[\"Module\"] = 1] = \"Module\";\n SymbolKind[SymbolKind[\"Namespace\"] = 2] = \"Namespace\";\n SymbolKind[SymbolKind[\"Package\"] = 3] = \"Package\";\n SymbolKind[SymbolKind[\"Class\"] = 4] = \"Class\";\n SymbolKind[SymbolKind[\"Method\"] = 5] = \"Method\";\n SymbolKind[SymbolKind[\"Property\"] = 6] = \"Property\";\n SymbolKind[SymbolKind[\"Field\"] = 7] = \"Field\";\n SymbolKind[SymbolKind[\"Constructor\"] = 8] = \"Constructor\";\n SymbolKind[SymbolKind[\"Enum\"] = 9] = \"Enum\";\n SymbolKind[SymbolKind[\"Interface\"] = 10] = \"Interface\";\n SymbolKind[SymbolKind[\"Function\"] = 11] = \"Function\";\n SymbolKind[SymbolKind[\"Variable\"] = 12] = \"Variable\";\n SymbolKind[SymbolKind[\"Constant\"] = 13] = \"Constant\";\n SymbolKind[SymbolKind[\"String\"] = 14] = \"String\";\n SymbolKind[SymbolKind[\"Number\"] = 15] = \"Number\";\n SymbolKind[SymbolKind[\"Boolean\"] = 16] = \"Boolean\";\n SymbolKind[SymbolKind[\"Array\"] = 17] = \"Array\";\n SymbolKind[SymbolKind[\"Object\"] = 18] = \"Object\";\n SymbolKind[SymbolKind[\"Key\"] = 19] = \"Key\";\n SymbolKind[SymbolKind[\"Null\"] = 20] = \"Null\";\n SymbolKind[SymbolKind[\"EnumMember\"] = 21] = \"EnumMember\";\n SymbolKind[SymbolKind[\"Struct\"] = 22] = \"Struct\";\n SymbolKind[SymbolKind[\"Event\"] = 23] = \"Event\";\n SymbolKind[SymbolKind[\"Operator\"] = 24] = \"Operator\";\n SymbolKind[SymbolKind[\"TypeParameter\"] = 25] = \"TypeParameter\";\n})(SymbolKind || (SymbolKind = {}));\nexport var SymbolTag;\n(function (SymbolTag) {\n SymbolTag[SymbolTag[\"Deprecated\"] = 1] = \"Deprecated\";\n})(SymbolTag || (SymbolTag = {}));\n/**\n * The kind of animation in which the editor's cursor should be rendered.\n */\nexport var TextEditorCursorBlinkingStyle;\n(function (TextEditorCursorBlinkingStyle) {\n /**\n * Hidden\n */\n TextEditorCursorBlinkingStyle[TextEditorCursorBlinkingStyle[\"Hidden\"] = 0] = \"Hidden\";\n /**\n * Blinking\n */\n TextEditorCursorBlinkingStyle[TextEditorCursorBlinkingStyle[\"Blink\"] = 1] = \"Blink\";\n /**\n * Blinking with smooth fading\n */\n TextEditorCursorBlinkingStyle[TextEditorCursorBlinkingStyle[\"Smooth\"] = 2] = \"Smooth\";\n /**\n * Blinking with prolonged filled state and smooth fading\n */\n TextEditorCursorBlinkingStyle[TextEditorCursorBlinkingStyle[\"Phase\"] = 3] = \"Phase\";\n /**\n * Expand collapse animation on the y axis\n */\n TextEditorCursorBlinkingStyle[TextEditorCursorBlinkingStyle[\"Expand\"] = 4] = \"Expand\";\n /**\n * No-Blinking\n */\n TextEditorCursorBlinkingStyle[TextEditorCursorBlinkingStyle[\"Solid\"] = 5] = \"Solid\";\n})(TextEditorCursorBlinkingStyle || (TextEditorCursorBlinkingStyle = {}));\n/**\n * The style in which the editor's cursor should be rendered.\n */\nexport var TextEditorCursorStyle;\n(function (TextEditorCursorStyle) {\n /**\n * As a vertical line (sitting between two characters).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"Line\"] = 1] = \"Line\";\n /**\n * As a block (sitting on top of a character).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"Block\"] = 2] = \"Block\";\n /**\n * As a horizontal line (sitting under a character).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"Underline\"] = 3] = \"Underline\";\n /**\n * As a thin vertical line (sitting between two characters).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"LineThin\"] = 4] = \"LineThin\";\n /**\n * As an outlined block (sitting on top of a character).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"BlockOutline\"] = 5] = \"BlockOutline\";\n /**\n * As a thin horizontal line (sitting under a character).\n */\n TextEditorCursorStyle[TextEditorCursorStyle[\"UnderlineThin\"] = 6] = \"UnderlineThin\";\n})(TextEditorCursorStyle || (TextEditorCursorStyle = {}));\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 var TrackedRangeStickiness;\n(function (TrackedRangeStickiness) {\n TrackedRangeStickiness[TrackedRangeStickiness[\"AlwaysGrowsWhenTypingAtEdges\"] = 0] = \"AlwaysGrowsWhenTypingAtEdges\";\n TrackedRangeStickiness[TrackedRangeStickiness[\"NeverGrowsWhenTypingAtEdges\"] = 1] = \"NeverGrowsWhenTypingAtEdges\";\n TrackedRangeStickiness[TrackedRangeStickiness[\"GrowsOnlyWhenTypingBefore\"] = 2] = \"GrowsOnlyWhenTypingBefore\";\n TrackedRangeStickiness[TrackedRangeStickiness[\"GrowsOnlyWhenTypingAfter\"] = 3] = \"GrowsOnlyWhenTypingAfter\";\n})(TrackedRangeStickiness || (TrackedRangeStickiness = {}));\n/**\n * Describes how to indent wrapped lines.\n */\nexport var WrappingIndent;\n(function (WrappingIndent) {\n /**\n * No indentation => wrapped lines begin at column 1.\n */\n WrappingIndent[WrappingIndent[\"None\"] = 0] = \"None\";\n /**\n * Same => wrapped lines get the same indentation as the parent.\n */\n WrappingIndent[WrappingIndent[\"Same\"] = 1] = \"Same\";\n /**\n * Indent => wrapped lines get +1 indentation toward the parent.\n */\n WrappingIndent[WrappingIndent[\"Indent\"] = 2] = \"Indent\";\n /**\n * DeepIndent => wrapped lines get +2 indentation toward the parent.\n */\n WrappingIndent[WrappingIndent[\"DeepIndent\"] = 3] = \"DeepIndent\";\n})(WrappingIndent || (WrappingIndent = {}));\n","/*---------------------------------------------------------------------------------------------\n * 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 * as nls from '../../nls.js';\nexport var AccessibilityHelpNLS;\n(function (AccessibilityHelpNLS) {\n AccessibilityHelpNLS.noSelection = nls.localize(\"noSelection\", \"No selection\");\n AccessibilityHelpNLS.singleSelectionRange = nls.localize(\"singleSelectionRange\", \"Line {0}, Column {1} ({2} selected)\");\n AccessibilityHelpNLS.singleSelection = nls.localize(\"singleSelection\", \"Line {0}, Column {1}\");\n AccessibilityHelpNLS.multiSelectionRange = nls.localize(\"multiSelectionRange\", \"{0} selections ({1} characters selected)\");\n AccessibilityHelpNLS.multiSelection = nls.localize(\"multiSelection\", \"{0} selections\");\n AccessibilityHelpNLS.emergencyConfOn = nls.localize(\"emergencyConfOn\", \"Now changing the setting `accessibilitySupport` to 'on'.\");\n AccessibilityHelpNLS.openingDocs = nls.localize(\"openingDocs\", \"Now opening the Editor Accessibility documentation page.\");\n AccessibilityHelpNLS.readonlyDiffEditor = nls.localize(\"readonlyDiffEditor\", \" in a read-only pane of a diff editor.\");\n AccessibilityHelpNLS.editableDiffEditor = nls.localize(\"editableDiffEditor\", \" in a pane of a diff editor.\");\n AccessibilityHelpNLS.readonlyEditor = nls.localize(\"readonlyEditor\", \" in a read-only code editor\");\n AccessibilityHelpNLS.editableEditor = nls.localize(\"editableEditor\", \" in a code editor\");\n AccessibilityHelpNLS.changeConfigToOnMac = nls.localize(\"changeConfigToOnMac\", \"To configure the editor to be optimized for usage with a Screen Reader press Command+E now.\");\n AccessibilityHelpNLS.changeConfigToOnWinLinux = nls.localize(\"changeConfigToOnWinLinux\", \"To configure the editor to be optimized for usage with a Screen Reader press Control+E now.\");\n AccessibilityHelpNLS.auto_on = nls.localize(\"auto_on\", \"The editor is configured to be optimized for usage with a Screen Reader.\");\n AccessibilityHelpNLS.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 AccessibilityHelpNLS.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 AccessibilityHelpNLS.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 AccessibilityHelpNLS.tabFocusModeOffMsg = nls.localize(\"tabFocusModeOffMsg\", \"Pressing Tab in the current editor will insert the tab character. Toggle this behavior by pressing {0}.\");\n AccessibilityHelpNLS.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 AccessibilityHelpNLS.openDocMac = nls.localize(\"openDocMac\", \"Press Command+H now to open a browser window with more information related to editor accessibility.\");\n AccessibilityHelpNLS.openDocWinLinux = nls.localize(\"openDocWinLinux\", \"Press Control+H now to open a browser window with more information related to editor accessibility.\");\n AccessibilityHelpNLS.outroMsg = nls.localize(\"outroMsg\", \"You can dismiss this tooltip and return to the editor by pressing Escape or Shift+Escape.\");\n AccessibilityHelpNLS.showAccessibilityHelpAction = nls.localize(\"showAccessibilityHelpAction\", \"Show Accessibility Help\");\n})(AccessibilityHelpNLS || (AccessibilityHelpNLS = {}));\nexport var InspectTokensNLS;\n(function (InspectTokensNLS) {\n InspectTokensNLS.inspectTokensAction = nls.localize('inspectTokens', \"Developer: Inspect Tokens\");\n})(InspectTokensNLS || (InspectTokensNLS = {}));\nexport var GoToLineNLS;\n(function (GoToLineNLS) {\n GoToLineNLS.gotoLineActionLabel = nls.localize('gotoLineActionLabel', \"Go to Line/Column...\");\n})(GoToLineNLS || (GoToLineNLS = {}));\nexport var QuickHelpNLS;\n(function (QuickHelpNLS) {\n QuickHelpNLS.helpQuickAccessActionLabel = nls.localize('helpQuickAccess', \"Show all Quick Access Providers\");\n})(QuickHelpNLS || (QuickHelpNLS = {}));\nexport var QuickCommandNLS;\n(function (QuickCommandNLS) {\n QuickCommandNLS.quickCommandActionLabel = nls.localize('quickCommandActionLabel', \"Command Palette\");\n QuickCommandNLS.quickCommandHelp = nls.localize('quickCommandActionHelp', \"Show And Run Commands\");\n})(QuickCommandNLS || (QuickCommandNLS = {}));\nexport var QuickOutlineNLS;\n(function (QuickOutlineNLS) {\n QuickOutlineNLS.quickOutlineActionLabel = nls.localize('quickOutlineActionLabel', \"Go to Symbol...\");\n QuickOutlineNLS.quickOutlineByCategoryActionLabel = nls.localize('quickOutlineByCategoryActionLabel', \"Go to Symbol by Category...\");\n})(QuickOutlineNLS || (QuickOutlineNLS = {}));\nexport var StandaloneCodeEditorNLS;\n(function (StandaloneCodeEditorNLS) {\n StandaloneCodeEditorNLS.editorViewAccessibleLabel = nls.localize('editorViewAccessibleLabel', \"Editor content\");\n StandaloneCodeEditorNLS.accessibilityHelpMessage = nls.localize('accessibilityHelpMessage', \"Press Alt+F1 for Accessibility Options.\");\n})(StandaloneCodeEditorNLS || (StandaloneCodeEditorNLS = {}));\nexport var ToggleHighContrastNLS;\n(function (ToggleHighContrastNLS) {\n ToggleHighContrastNLS.toggleHighContrast = nls.localize('toggleHighContrast', \"Toggle High Contrast Theme\");\n})(ToggleHighContrastNLS || (ToggleHighContrastNLS = {}));\nexport var StandaloneServicesNLS;\n(function (StandaloneServicesNLS) {\n StandaloneServicesNLS.bulkEditServiceSummary = nls.localize('bulkEditServiceSummary', \"Made {0} edits in {1} files\");\n})(StandaloneServicesNLS || (StandaloneServicesNLS = {}));\n","/*---------------------------------------------------------------------------------------------\n * Copyright (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 * An event describing that a model has been reset to a new value.\n * @internal\n */\nexport class ModelRawFlush {\n constructor() {\n this.changeType = 1 /* RawContentChangedType.Flush */;\n }\n}\n/**\n * Represents text injected on a line\n * @internal\n */\nexport class LineInjectedText {\n constructor(ownerId, lineNumber, column, options, order) {\n this.ownerId = ownerId;\n this.lineNumber = lineNumber;\n this.column = column;\n this.options = options;\n this.order = order;\n }\n static applyInjectedText(lineText, injectedTexts) {\n if (!injectedTexts || injectedTexts.length === 0) {\n return lineText;\n }\n let result = '';\n let lastOriginalOffset = 0;\n for (const injectedText of injectedTexts) {\n result += lineText.substring(lastOriginalOffset, injectedText.column - 1);\n lastOriginalOffset = injectedText.column - 1;\n result += injectedText.options.content;\n }\n result += lineText.substring(lastOriginalOffset);\n return result;\n }\n static fromDecorations(decorations) {\n const result = [];\n for (const decoration of decorations) {\n if (decoration.options.before && decoration.options.before.content.length > 0) {\n result.push(new LineInjectedText(decoration.ownerId, decoration.range.startLineNumber, decoration.range.startColumn, decoration.options.before, 0));\n }\n if (decoration.options.after && decoration.options.after.content.length > 0) {\n result.push(new LineInjectedText(decoration.ownerId, decoration.range.endLineNumber, decoration.range.endColumn, decoration.options.after, 1));\n }\n }\n result.sort((a, b) => {\n if (a.lineNumber === b.lineNumber) {\n if (a.column === b.column) {\n return a.order - b.order;\n }\n return a.column - b.column;\n }\n return a.lineNumber - b.lineNumber;\n });\n return result;\n }\n}\n/**\n * An event describing that a line has changed in a model.\n * @internal\n */\nexport class ModelRawLineChanged {\n constructor(lineNumber, detail, injectedText) {\n this.changeType = 2 /* RawContentChangedType.LineChanged */;\n this.lineNumber = lineNumber;\n this.detail = detail;\n this.injectedText = injectedText;\n }\n}\n/**\n * An event describing that line(s) have been deleted in a model.\n * @internal\n */\nexport class ModelRawLinesDeleted {\n constructor(fromLineNumber, toLineNumber) {\n this.changeType = 3 /* RawContentChangedType.LinesDeleted */;\n this.fromLineNumber = fromLineNumber;\n this.toLineNumber = toLineNumber;\n }\n}\n/**\n * An event describing that line(s) have been inserted in a model.\n * @internal\n */\nexport class ModelRawLinesInserted {\n constructor(fromLineNumber, toLineNumber, detail, injectedTexts) {\n this.changeType = 4 /* RawContentChangedType.LinesInserted */;\n this.injectedTexts = injectedTexts;\n this.fromLineNumber = fromLineNumber;\n this.toLineNumber = toLineNumber;\n this.detail = detail;\n }\n}\n/**\n * An event describing that a model has had its EOL changed.\n * @internal\n */\nexport class ModelRawEOLChanged {\n constructor() {\n this.changeType = 5 /* RawContentChangedType.EOLChanged */;\n }\n}\n/**\n * An event describing a change in the text of a model.\n * @internal\n */\nexport class ModelRawContentChangedEvent {\n constructor(changes, versionId, isUndoing, isRedoing) {\n this.changes = changes;\n this.versionId = versionId;\n this.isUndoing = isUndoing;\n this.isRedoing = isRedoing;\n this.resultingSelection = null;\n }\n containsEvent(type) {\n for (let i = 0, len = this.changes.length; i < len; i++) {\n const change = this.changes[i];\n if (change.changeType === type) {\n return true;\n }\n }\n return false;\n }\n static merge(a, b) {\n const changes = [].concat(a.changes).concat(b.changes);\n const versionId = b.versionId;\n const isUndoing = (a.isUndoing || b.isUndoing);\n const isRedoing = (a.isRedoing || b.isRedoing);\n return new ModelRawContentChangedEvent(changes, versionId, isUndoing, isRedoing);\n }\n}\n/**\n * An event describing a change in injected text.\n * @internal\n */\nexport class ModelInjectedTextChangedEvent {\n constructor(changes) {\n this.changes = changes;\n }\n}\n/**\n * @internal\n */\nexport class InternalModelContentChangeEvent {\n constructor(rawContentChangedEvent, contentChangedEvent) {\n this.rawContentChangedEvent = rawContentChangedEvent;\n this.contentChangedEvent = contentChangedEvent;\n }\n merge(other) {\n const rawContentChangedEvent = ModelRawContentChangedEvent.merge(this.rawContentChangedEvent, other.rawContentChangedEvent);\n const contentChangedEvent = InternalModelContentChangeEvent._mergeChangeEvents(this.contentChangedEvent, other.contentChangedEvent);\n return new InternalModelContentChangeEvent(rawContentChangedEvent, contentChangedEvent);\n }\n static _mergeChangeEvents(a, b) {\n const changes = [].concat(a.changes).concat(b.changes);\n const eol = b.eol;\n const versionId = b.versionId;\n const isUndoing = (a.isUndoing || b.isUndoing);\n const isRedoing = (a.isRedoing || b.isRedoing);\n const isFlush = (a.isFlush || b.isFlush);\n return {\n changes: changes,\n eol: eol,\n versionId: versionId,\n isUndoing: isUndoing,\n isRedoing: isRedoing,\n isFlush: isFlush\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 *--------------------------------------------------------------------------------------------*/\nexport var HorizontalGuidesState;\n(function (HorizontalGuidesState) {\n HorizontalGuidesState[HorizontalGuidesState[\"Disabled\"] = 0] = \"Disabled\";\n HorizontalGuidesState[HorizontalGuidesState[\"EnabledForActive\"] = 1] = \"EnabledForActive\";\n HorizontalGuidesState[HorizontalGuidesState[\"Enabled\"] = 2] = \"Enabled\";\n})(HorizontalGuidesState || (HorizontalGuidesState = {}));\nexport class IndentGuide {\n constructor(visibleColumn, column, className, \n /**\n * If set, this indent guide is a horizontal guide (no vertical part).\n * It starts at visibleColumn and continues until endColumn.\n */\n horizontalLine, \n /**\n * If set (!= -1), only show this guide for wrapped lines that don't contain this model column, but are after it.\n */\n forWrappedLinesAfterColumn, forWrappedLinesBeforeOrAtColumn) {\n this.visibleColumn = visibleColumn;\n this.column = column;\n this.className = className;\n this.horizontalLine = horizontalLine;\n this.forWrappedLinesAfterColumn = forWrappedLinesAfterColumn;\n this.forWrappedLinesBeforeOrAtColumn = forWrappedLinesBeforeOrAtColumn;\n if ((visibleColumn !== -1) === (column !== -1)) {\n throw new Error();\n }\n }\n}\nexport class IndentGuideHorizontalLine {\n constructor(top, endColumn) {\n this.top = top;\n this.endColumn = endColumn;\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 *--------------------------------------------------------------------------------------------*/\nimport { TokenMetadata } from '../encodedTokenAttributes.js';\nexport class LineTokens {\n constructor(tokens, text, decoder) {\n this._lineTokensBrand = undefined;\n this._tokens = tokens;\n this._tokensCount = (this._tokens.length >>> 1);\n this._text = text;\n this._languageIdCodec = decoder;\n }\n static createEmpty(lineContent, decoder) {\n const defaultMetadata = LineTokens.defaultTokenMetadata;\n const tokens = new Uint32Array(2);\n tokens[0] = lineContent.length;\n tokens[1] = defaultMetadata;\n return new LineTokens(tokens, lineContent, decoder);\n }\n equals(other) {\n if (other instanceof LineTokens) {\n return this.slicedEquals(other, 0, this._tokensCount);\n }\n return false;\n }\n slicedEquals(other, sliceFromTokenIndex, sliceTokenCount) {\n if (this._text !== other._text) {\n return false;\n }\n if (this._tokensCount !== other._tokensCount) {\n return false;\n }\n const from = (sliceFromTokenIndex << 1);\n const to = from + (sliceTokenCount << 1);\n for (let i = from; i < to; i++) {\n if (this._tokens[i] !== other._tokens[i]) {\n return false;\n }\n }\n return true;\n }\n getLineContent() {\n return this._text;\n }\n getCount() {\n return this._tokensCount;\n }\n getStartOffset(tokenIndex) {\n if (tokenIndex > 0) {\n return this._tokens[(tokenIndex - 1) << 1];\n }\n return 0;\n }\n getMetadata(tokenIndex) {\n const metadata = this._tokens[(tokenIndex << 1) + 1];\n return metadata;\n }\n getLanguageId(tokenIndex) {\n const metadata = this._tokens[(tokenIndex << 1) + 1];\n const languageId = TokenMetadata.getLanguageId(metadata);\n return this._languageIdCodec.decodeLanguageId(languageId);\n }\n getStandardTokenType(tokenIndex) {\n const metadata = this._tokens[(tokenIndex << 1) + 1];\n return TokenMetadata.getTokenType(metadata);\n }\n getForeground(tokenIndex) {\n const metadata = this._tokens[(tokenIndex << 1) + 1];\n return TokenMetadata.getForeground(metadata);\n }\n getClassName(tokenIndex) {\n const metadata = this._tokens[(tokenIndex << 1) + 1];\n return TokenMetadata.getClassNameFromMetadata(metadata);\n }\n getInlineStyle(tokenIndex, colorMap) {\n const metadata = this._tokens[(tokenIndex << 1) + 1];\n return TokenMetadata.getInlineStyleFromMetadata(metadata, colorMap);\n }\n getPresentation(tokenIndex) {\n const metadata = this._tokens[(tokenIndex << 1) + 1];\n return TokenMetadata.getPresentationFromMetadata(metadata);\n }\n getEndOffset(tokenIndex) {\n return this._tokens[tokenIndex << 1];\n }\n /**\n * Find the token containing offset `offset`.\n * @param offset The search offset\n * @return The index of the token containing the offset.\n */\n findTokenIndexAtOffset(offset) {\n return LineTokens.findIndexInTokensArray(this._tokens, offset);\n }\n inflate() {\n return this;\n }\n sliceAndInflate(startOffset, endOffset, deltaOffset) {\n return new SliceLineTokens(this, startOffset, endOffset, deltaOffset);\n }\n static convertToEndOffset(tokens, lineTextLength) {\n const tokenCount = (tokens.length >>> 1);\n const lastTokenIndex = tokenCount - 1;\n for (let tokenIndex = 0; tokenIndex < lastTokenIndex; tokenIndex++) {\n tokens[tokenIndex << 1] = tokens[(tokenIndex + 1) << 1];\n }\n tokens[lastTokenIndex << 1] = lineTextLength;\n }\n static findIndexInTokensArray(tokens, desiredIndex) {\n if (tokens.length <= 2) {\n return 0;\n }\n let low = 0;\n let high = (tokens.length >>> 1) - 1;\n while (low < high) {\n const mid = low + Math.floor((high - low) / 2);\n const endOffset = tokens[(mid << 1)];\n if (endOffset === desiredIndex) {\n return mid + 1;\n }\n else if (endOffset < desiredIndex) {\n low = mid + 1;\n }\n else if (endOffset > desiredIndex) {\n high = mid;\n }\n }\n return low;\n }\n /**\n * @pure\n * @param insertTokens Must be sorted by offset.\n */\n withInserted(insertTokens) {\n if (insertTokens.length === 0) {\n return this;\n }\n let nextOriginalTokenIdx = 0;\n let nextInsertTokenIdx = 0;\n let text = '';\n const newTokens = new Array();\n let originalEndOffset = 0;\n while (true) {\n const nextOriginalTokenEndOffset = nextOriginalTokenIdx < this._tokensCount ? this._tokens[nextOriginalTokenIdx << 1] : -1;\n const nextInsertToken = nextInsertTokenIdx < insertTokens.length ? insertTokens[nextInsertTokenIdx] : null;\n if (nextOriginalTokenEndOffset !== -1 && (nextInsertToken === null || nextOriginalTokenEndOffset <= nextInsertToken.offset)) {\n // original token ends before next insert token\n text += this._text.substring(originalEndOffset, nextOriginalTokenEndOffset);\n const metadata = this._tokens[(nextOriginalTokenIdx << 1) + 1];\n newTokens.push(text.length, metadata);\n nextOriginalTokenIdx++;\n originalEndOffset = nextOriginalTokenEndOffset;\n }\n else if (nextInsertToken) {\n if (nextInsertToken.offset > originalEndOffset) {\n // insert token is in the middle of the next token.\n text += this._text.substring(originalEndOffset, nextInsertToken.offset);\n const metadata = this._tokens[(nextOriginalTokenIdx << 1) + 1];\n newTokens.push(text.length, metadata);\n originalEndOffset = nextInsertToken.offset;\n }\n text += nextInsertToken.text;\n newTokens.push(text.length, nextInsertToken.tokenMetadata);\n nextInsertTokenIdx++;\n }\n else {\n break;\n }\n }\n return new LineTokens(new Uint32Array(newTokens), text, this._languageIdCodec);\n }\n}\nLineTokens.defaultTokenMetadata = ((0 /* FontStyle.None */ << 11 /* MetadataConsts.FONT_STYLE_OFFSET */)\n | (1 /* ColorId.DefaultForeground */ << 15 /* MetadataConsts.FOREGROUND_OFFSET */)\n | (2 /* ColorId.DefaultBackground */ << 24 /* MetadataConsts.BACKGROUND_OFFSET */)) >>> 0;\nclass SliceLineTokens {\n constructor(source, startOffset, endOffset, deltaOffset) {\n this._source = source;\n this._startOffset = startOffset;\n this._endOffset = endOffset;\n this._deltaOffset = deltaOffset;\n this._firstTokenIndex = source.findTokenIndexAtOffset(startOffset);\n this._tokensCount = 0;\n for (let i = this._firstTokenIndex, len = source.getCount(); i < len; i++) {\n const tokenStartOffset = source.getStartOffset(i);\n if (tokenStartOffset >= endOffset) {\n break;\n }\n this._tokensCount++;\n }\n }\n getMetadata(tokenIndex) {\n return this._source.getMetadata(this._firstTokenIndex + tokenIndex);\n }\n getLanguageId(tokenIndex) {\n return this._source.getLanguageId(this._firstTokenIndex + tokenIndex);\n }\n getLineContent() {\n return this._source.getLineContent().substring(this._startOffset, this._endOffset);\n }\n equals(other) {\n if (other instanceof SliceLineTokens) {\n return (this._startOffset === other._startOffset\n && this._endOffset === other._endOffset\n && this._deltaOffset === other._deltaOffset\n && this._source.slicedEquals(other._source, this._firstTokenIndex, this._tokensCount));\n }\n return false;\n }\n getCount() {\n return this._tokensCount;\n }\n getForeground(tokenIndex) {\n return this._source.getForeground(this._firstTokenIndex + tokenIndex);\n }\n getEndOffset(tokenIndex) {\n const tokenEndOffset = this._source.getEndOffset(this._firstTokenIndex + tokenIndex);\n return Math.min(this._endOffset, tokenEndOffset) - this._startOffset + this._deltaOffset;\n }\n getClassName(tokenIndex) {\n return this._source.getClassName(this._firstTokenIndex + tokenIndex);\n }\n getInlineStyle(tokenIndex, colorMap) {\n return this._source.getInlineStyle(this._firstTokenIndex + tokenIndex, colorMap);\n }\n getPresentation(tokenIndex) {\n return this._source.getPresentation(this._firstTokenIndex + tokenIndex);\n }\n findTokenIndexAtOffset(offset) {\n return this._source.findTokenIndexAtOffset(offset + this._startOffset - this._deltaOffset) - this._firstTokenIndex;\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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../base/common/strings.js';\nexport class LineDecoration {\n constructor(startColumn, endColumn, className, type) {\n this.startColumn = startColumn;\n this.endColumn = endColumn;\n this.className = className;\n this.type = type;\n this._lineDecorationBrand = undefined;\n }\n static _equals(a, b) {\n return (a.startColumn === b.startColumn\n && a.endColumn === b.endColumn\n && a.className === b.className\n && a.type === b.type);\n }\n static equalsArr(a, b) {\n const aLen = a.length;\n const bLen = b.length;\n if (aLen !== bLen) {\n return false;\n }\n for (let i = 0; i < aLen; i++) {\n if (!LineDecoration._equals(a[i], b[i])) {\n return false;\n }\n }\n return true;\n }\n static extractWrapped(arr, startOffset, endOffset) {\n if (arr.length === 0) {\n return arr;\n }\n const startColumn = startOffset + 1;\n const endColumn = endOffset + 1;\n const lineLength = endOffset - startOffset;\n const r = [];\n let rLength = 0;\n for (const dec of arr) {\n if (dec.endColumn <= startColumn || dec.startColumn >= endColumn) {\n continue;\n }\n r[rLength++] = new LineDecoration(Math.max(1, dec.startColumn - startColumn + 1), Math.min(lineLength + 1, dec.endColumn - startColumn + 1), dec.className, dec.type);\n }\n return r;\n }\n static filter(lineDecorations, lineNumber, minLineColumn, maxLineColumn) {\n if (lineDecorations.length === 0) {\n return [];\n }\n const result = [];\n let resultLen = 0;\n for (let i = 0, len = lineDecorations.length; i < len; i++) {\n const d = lineDecorations[i];\n const range = d.range;\n if (range.endLineNumber < lineNumber || range.startLineNumber > lineNumber) {\n // Ignore decorations that sit outside this line\n continue;\n }\n if (range.isEmpty() && (d.type === 0 /* InlineDecorationType.Regular */ || d.type === 3 /* InlineDecorationType.RegularAffectingLetterSpacing */)) {\n // Ignore empty range decorations\n continue;\n }\n const startColumn = (range.startLineNumber === lineNumber ? range.startColumn : minLineColumn);\n const endColumn = (range.endLineNumber === lineNumber ? range.endColumn : maxLineColumn);\n result[resultLen++] = new LineDecoration(startColumn, endColumn, d.inlineClassName, d.type);\n }\n return result;\n }\n static _typeCompare(a, b) {\n const ORDER = [2, 0, 1, 3];\n return ORDER[a] - ORDER[b];\n }\n static compare(a, b) {\n if (a.startColumn !== b.startColumn) {\n return a.startColumn - b.startColumn;\n }\n if (a.endColumn !== b.endColumn) {\n return a.endColumn - b.endColumn;\n }\n const typeCmp = LineDecoration._typeCompare(a.type, b.type);\n if (typeCmp !== 0) {\n return typeCmp;\n }\n if (a.className !== b.className) {\n return a.className < b.className ? -1 : 1;\n }\n return 0;\n }\n}\nexport class DecorationSegment {\n constructor(startOffset, endOffset, className, metadata) {\n this.startOffset = startOffset;\n this.endOffset = endOffset;\n this.className = className;\n this.metadata = metadata;\n }\n}\nclass Stack {\n constructor() {\n this.stopOffsets = [];\n this.classNames = [];\n this.metadata = [];\n this.count = 0;\n }\n static _metadata(metadata) {\n let result = 0;\n for (let i = 0, len = metadata.length; i < len; i++) {\n result |= metadata[i];\n }\n return result;\n }\n consumeLowerThan(maxStopOffset, nextStartOffset, result) {\n while (this.count > 0 && this.stopOffsets[0] < maxStopOffset) {\n let i = 0;\n // Take all equal stopping offsets\n while (i + 1 < this.count && this.stopOffsets[i] === this.stopOffsets[i + 1]) {\n i++;\n }\n // Basically we are consuming the first i + 1 elements of the stack\n result.push(new DecorationSegment(nextStartOffset, this.stopOffsets[i], this.classNames.join(' '), Stack._metadata(this.metadata)));\n nextStartOffset = this.stopOffsets[i] + 1;\n // Consume them\n this.stopOffsets.splice(0, i + 1);\n this.classNames.splice(0, i + 1);\n this.metadata.splice(0, i + 1);\n this.count -= (i + 1);\n }\n if (this.count > 0 && nextStartOffset < maxStopOffset) {\n result.push(new DecorationSegment(nextStartOffset, maxStopOffset - 1, this.classNames.join(' '), Stack._metadata(this.metadata)));\n nextStartOffset = maxStopOffset;\n }\n return nextStartOffset;\n }\n insert(stopOffset, className, metadata) {\n if (this.count === 0 || this.stopOffsets[this.count - 1] <= stopOffset) {\n // Insert at the end\n this.stopOffsets.push(stopOffset);\n this.classNames.push(className);\n this.metadata.push(metadata);\n }\n else {\n // Find the insertion position for `stopOffset`\n for (let i = 0; i < this.count; i++) {\n if (this.stopOffsets[i] >= stopOffset) {\n this.stopOffsets.splice(i, 0, stopOffset);\n this.classNames.splice(i, 0, className);\n this.metadata.splice(i, 0, metadata);\n break;\n }\n }\n }\n this.count++;\n return;\n }\n}\nexport class LineDecorationsNormalizer {\n /**\n * Normalize line decorations. Overlapping decorations will generate multiple segments\n */\n static normalize(lineContent, lineDecorations) {\n if (lineDecorations.length === 0) {\n return [];\n }\n const result = [];\n const stack = new Stack();\n let nextStartOffset = 0;\n for (let i = 0, len = lineDecorations.length; i < len; i++) {\n const d = lineDecorations[i];\n let startColumn = d.startColumn;\n let endColumn = d.endColumn;\n const className = d.className;\n const metadata = (d.type === 1 /* InlineDecorationType.Before */\n ? 2 /* LinePartMetadata.PSEUDO_BEFORE */\n : d.type === 2 /* InlineDecorationType.After */\n ? 4 /* LinePartMetadata.PSEUDO_AFTER */\n : 0);\n // If the position would end up in the middle of a high-low surrogate pair, we move it to before the pair\n if (startColumn > 1) {\n const charCodeBefore = lineContent.charCodeAt(startColumn - 2);\n if (strings.isHighSurrogate(charCodeBefore)) {\n startColumn--;\n }\n }\n if (endColumn > 1) {\n const charCodeBefore = lineContent.charCodeAt(endColumn - 2);\n if (strings.isHighSurrogate(charCodeBefore)) {\n endColumn--;\n }\n }\n const currentStartOffset = startColumn - 1;\n const currentEndOffset = endColumn - 2;\n nextStartOffset = stack.consumeLowerThan(currentStartOffset, nextStartOffset, result);\n if (stack.count === 0) {\n nextStartOffset = currentStartOffset;\n }\n stack.insert(currentEndOffset, className, metadata);\n }\n stack.consumeLowerThan(1073741824 /* Constants.MAX_SAFE_SMALL_INTEGER */, nextStartOffset, result);\n return result;\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 *--------------------------------------------------------------------------------------------*/\nexport class LinePart {\n constructor(\n /**\n * last char index of this token (not inclusive).\n */\n endIndex, type, metadata, containsRTL) {\n this.endIndex = endIndex;\n this.type = type;\n this.metadata = metadata;\n this.containsRTL = containsRTL;\n this._linePartBrand = undefined;\n }\n isWhitespace() {\n return (this.metadata & 1 /* LinePartMetadata.IS_WHITESPACE_MASK */ ? true : false);\n }\n isPseudoAfter() {\n return (this.metadata & 4 /* LinePartMetadata.PSEUDO_AFTER_MASK */ ? true : false);\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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../base/common/strings.js';\nimport { createStringBuilder } from '../core/stringBuilder.js';\nimport { LineDecoration, LineDecorationsNormalizer } from './lineDecorations.js';\nimport { LinePart } from './linePart.js';\nexport class LineRange {\n constructor(startIndex, endIndex) {\n this.startOffset = startIndex;\n this.endOffset = endIndex;\n }\n equals(otherLineRange) {\n return this.startOffset === otherLineRange.startOffset\n && this.endOffset === otherLineRange.endOffset;\n }\n}\nexport class RenderLineInput {\n constructor(useMonospaceOptimizations, canUseHalfwidthRightwardsArrow, lineContent, continuesWithWrappedLine, isBasicASCII, containsRTL, fauxIndentLength, lineTokens, lineDecorations, tabSize, startVisibleColumn, spaceWidth, middotWidth, wsmiddotWidth, stopRenderingLineAfter, renderWhitespace, renderControlCharacters, fontLigatures, selectionsOnLine) {\n this.useMonospaceOptimizations = useMonospaceOptimizations;\n this.canUseHalfwidthRightwardsArrow = canUseHalfwidthRightwardsArrow;\n this.lineContent = lineContent;\n this.continuesWithWrappedLine = continuesWithWrappedLine;\n this.isBasicASCII = isBasicASCII;\n this.containsRTL = containsRTL;\n this.fauxIndentLength = fauxIndentLength;\n this.lineTokens = lineTokens;\n this.lineDecorations = lineDecorations.sort(LineDecoration.compare);\n this.tabSize = tabSize;\n this.startVisibleColumn = startVisibleColumn;\n this.spaceWidth = spaceWidth;\n this.stopRenderingLineAfter = stopRenderingLineAfter;\n this.renderWhitespace = (renderWhitespace === 'all'\n ? 4 /* RenderWhitespace.All */\n : renderWhitespace === 'boundary'\n ? 1 /* RenderWhitespace.Boundary */\n : renderWhitespace === 'selection'\n ? 2 /* RenderWhitespace.Selection */\n : renderWhitespace === 'trailing'\n ? 3 /* RenderWhitespace.Trailing */\n : 0 /* RenderWhitespace.None */);\n this.renderControlCharacters = renderControlCharacters;\n this.fontLigatures = fontLigatures;\n this.selectionsOnLine = selectionsOnLine && selectionsOnLine.sort((a, b) => a.startOffset < b.startOffset ? -1 : 1);\n const wsmiddotDiff = Math.abs(wsmiddotWidth - spaceWidth);\n const middotDiff = Math.abs(middotWidth - spaceWidth);\n if (wsmiddotDiff < middotDiff) {\n this.renderSpaceWidth = wsmiddotWidth;\n this.renderSpaceCharCode = 0x2E31; // U+2E31 - WORD SEPARATOR MIDDLE DOT\n }\n else {\n this.renderSpaceWidth = middotWidth;\n this.renderSpaceCharCode = 0xB7; // U+00B7 - MIDDLE DOT\n }\n }\n sameSelection(otherSelections) {\n if (this.selectionsOnLine === null) {\n return otherSelections === null;\n }\n if (otherSelections === null) {\n return false;\n }\n if (otherSelections.length !== this.selectionsOnLine.length) {\n return false;\n }\n for (let i = 0; i < this.selectionsOnLine.length; i++) {\n if (!this.selectionsOnLine[i].equals(otherSelections[i])) {\n return false;\n }\n }\n return true;\n }\n equals(other) {\n return (this.useMonospaceOptimizations === other.useMonospaceOptimizations\n && this.canUseHalfwidthRightwardsArrow === other.canUseHalfwidthRightwardsArrow\n && this.lineContent === other.lineContent\n && this.continuesWithWrappedLine === other.continuesWithWrappedLine\n && this.isBasicASCII === other.isBasicASCII\n && this.containsRTL === other.containsRTL\n && this.fauxIndentLength === other.fauxIndentLength\n && this.tabSize === other.tabSize\n && this.startVisibleColumn === other.startVisibleColumn\n && this.spaceWidth === other.spaceWidth\n && this.renderSpaceWidth === other.renderSpaceWidth\n && this.renderSpaceCharCode === other.renderSpaceCharCode\n && this.stopRenderingLineAfter === other.stopRenderingLineAfter\n && this.renderWhitespace === other.renderWhitespace\n && this.renderControlCharacters === other.renderControlCharacters\n && this.fontLigatures === other.fontLigatures\n && LineDecoration.equalsArr(this.lineDecorations, other.lineDecorations)\n && this.lineTokens.equals(other.lineTokens)\n && this.sameSelection(other.selectionsOnLine));\n }\n}\nexport class DomPosition {\n constructor(partIndex, charIndex) {\n this.partIndex = partIndex;\n this.charIndex = charIndex;\n }\n}\n/**\n * Provides a both direction mapping between a line's character and its rendered position.\n */\nexport class CharacterMapping {\n constructor(length, partCount) {\n this.length = length;\n this._data = new Uint32Array(this.length);\n this._horizontalOffset = new Uint32Array(this.length);\n }\n static getPartIndex(partData) {\n return (partData & 4294901760 /* CharacterMappingConstants.PART_INDEX_MASK */) >>> 16 /* CharacterMappingConstants.PART_INDEX_OFFSET */;\n }\n static getCharIndex(partData) {\n return (partData & 65535 /* CharacterMappingConstants.CHAR_INDEX_MASK */) >>> 0 /* CharacterMappingConstants.CHAR_INDEX_OFFSET */;\n }\n setColumnInfo(column, partIndex, charIndex, horizontalOffset) {\n const partData = ((partIndex << 16 /* CharacterMappingConstants.PART_INDEX_OFFSET */)\n | (charIndex << 0 /* CharacterMappingConstants.CHAR_INDEX_OFFSET */)) >>> 0;\n this._data[column - 1] = partData;\n this._horizontalOffset[column - 1] = horizontalOffset;\n }\n getHorizontalOffset(column) {\n if (this._horizontalOffset.length === 0) {\n // No characters on this line\n return 0;\n }\n return this._horizontalOffset[column - 1];\n }\n charOffsetToPartData(charOffset) {\n if (this.length === 0) {\n return 0;\n }\n if (charOffset < 0) {\n return this._data[0];\n }\n if (charOffset >= this.length) {\n return this._data[this.length - 1];\n }\n return this._data[charOffset];\n }\n getDomPosition(column) {\n const partData = this.charOffsetToPartData(column - 1);\n const partIndex = CharacterMapping.getPartIndex(partData);\n const charIndex = CharacterMapping.getCharIndex(partData);\n return new DomPosition(partIndex, charIndex);\n }\n getColumn(domPosition, partLength) {\n const charOffset = this.partDataToCharOffset(domPosition.partIndex, partLength, domPosition.charIndex);\n return charOffset + 1;\n }\n partDataToCharOffset(partIndex, partLength, charIndex) {\n if (this.length === 0) {\n return 0;\n }\n const searchEntry = ((partIndex << 16 /* CharacterMappingConstants.PART_INDEX_OFFSET */)\n | (charIndex << 0 /* CharacterMappingConstants.CHAR_INDEX_OFFSET */)) >>> 0;\n let min = 0;\n let max = this.length - 1;\n while (min + 1 < max) {\n const mid = ((min + max) >>> 1);\n const midEntry = this._data[mid];\n if (midEntry === searchEntry) {\n return mid;\n }\n else if (midEntry > searchEntry) {\n max = mid;\n }\n else {\n min = mid;\n }\n }\n if (min === max) {\n return min;\n }\n const minEntry = this._data[min];\n const maxEntry = this._data[max];\n if (minEntry === searchEntry) {\n return min;\n }\n if (maxEntry === searchEntry) {\n return max;\n }\n const minPartIndex = CharacterMapping.getPartIndex(minEntry);\n const minCharIndex = CharacterMapping.getCharIndex(minEntry);\n const maxPartIndex = CharacterMapping.getPartIndex(maxEntry);\n let maxCharIndex;\n if (minPartIndex !== maxPartIndex) {\n // sitting between parts\n maxCharIndex = partLength;\n }\n else {\n maxCharIndex = CharacterMapping.getCharIndex(maxEntry);\n }\n const minEntryDistance = charIndex - minCharIndex;\n const maxEntryDistance = maxCharIndex - charIndex;\n if (minEntryDistance <= maxEntryDistance) {\n return min;\n }\n return max;\n }\n}\nexport class RenderLineOutput {\n constructor(characterMapping, containsRTL, containsForeignElements) {\n this._renderLineOutputBrand = undefined;\n this.characterMapping = characterMapping;\n this.containsRTL = containsRTL;\n this.containsForeignElements = containsForeignElements;\n }\n}\nexport function renderViewLine(input, sb) {\n if (input.lineContent.length === 0) {\n if (input.lineDecorations.length > 0) {\n // This line is empty, but it contains inline decorations\n sb.appendASCIIString(``);\n let beforeCount = 0;\n let afterCount = 0;\n let containsForeignElements = 0 /* ForeignElementType.None */;\n for (const lineDecoration of input.lineDecorations) {\n if (lineDecoration.type === 1 /* InlineDecorationType.Before */ || lineDecoration.type === 2 /* InlineDecorationType.After */) {\n sb.appendASCIIString(``);\n if (lineDecoration.type === 1 /* InlineDecorationType.Before */) {\n containsForeignElements |= 1 /* ForeignElementType.Before */;\n beforeCount++;\n }\n if (lineDecoration.type === 2 /* InlineDecorationType.After */) {\n containsForeignElements |= 2 /* ForeignElementType.After */;\n afterCount++;\n }\n }\n }\n sb.appendASCIIString(``);\n const characterMapping = new CharacterMapping(1, beforeCount + afterCount);\n characterMapping.setColumnInfo(1, beforeCount, 0, 0);\n return new RenderLineOutput(characterMapping, false, containsForeignElements);\n }\n // completely empty line\n sb.appendASCIIString('');\n return new RenderLineOutput(new CharacterMapping(0, 0), false, 0 /* ForeignElementType.None */);\n }\n return _renderLine(resolveRenderLineInput(input), sb);\n}\nexport class RenderLineOutput2 {\n constructor(characterMapping, html, containsRTL, containsForeignElements) {\n this.characterMapping = characterMapping;\n this.html = html;\n this.containsRTL = containsRTL;\n this.containsForeignElements = containsForeignElements;\n }\n}\nexport function renderViewLine2(input) {\n const sb = createStringBuilder(10000);\n const out = renderViewLine(input, sb);\n return new RenderLineOutput2(out.characterMapping, sb.build(), out.containsRTL, out.containsForeignElements);\n}\nclass ResolvedRenderLineInput {\n constructor(fontIsMonospace, canUseHalfwidthRightwardsArrow, lineContent, len, isOverflowing, parts, containsForeignElements, fauxIndentLength, tabSize, startVisibleColumn, containsRTL, spaceWidth, renderSpaceCharCode, renderWhitespace, renderControlCharacters) {\n this.fontIsMonospace = fontIsMonospace;\n this.canUseHalfwidthRightwardsArrow = canUseHalfwidthRightwardsArrow;\n this.lineContent = lineContent;\n this.len = len;\n this.isOverflowing = isOverflowing;\n this.parts = parts;\n this.containsForeignElements = containsForeignElements;\n this.fauxIndentLength = fauxIndentLength;\n this.tabSize = tabSize;\n this.startVisibleColumn = startVisibleColumn;\n this.containsRTL = containsRTL;\n this.spaceWidth = spaceWidth;\n this.renderSpaceCharCode = renderSpaceCharCode;\n this.renderWhitespace = renderWhitespace;\n this.renderControlCharacters = renderControlCharacters;\n //\n }\n}\nfunction resolveRenderLineInput(input) {\n const lineContent = input.lineContent;\n let isOverflowing;\n let len;\n if (input.stopRenderingLineAfter !== -1 && input.stopRenderingLineAfter < lineContent.length) {\n isOverflowing = true;\n len = input.stopRenderingLineAfter;\n }\n else {\n isOverflowing = false;\n len = lineContent.length;\n }\n let tokens = transformAndRemoveOverflowing(lineContent, input.containsRTL, input.lineTokens, input.fauxIndentLength, len);\n if (input.renderControlCharacters && !input.isBasicASCII) {\n // Calling `extractControlCharacters` before adding (possibly empty) line parts\n // for inline decorations. `extractControlCharacters` removes empty line parts.\n tokens = extractControlCharacters(lineContent, tokens);\n }\n if (input.renderWhitespace === 4 /* RenderWhitespace.All */ ||\n input.renderWhitespace === 1 /* RenderWhitespace.Boundary */ ||\n (input.renderWhitespace === 2 /* RenderWhitespace.Selection */ && !!input.selectionsOnLine) ||\n input.renderWhitespace === 3 /* RenderWhitespace.Trailing */) {\n tokens = _applyRenderWhitespace(input, lineContent, len, tokens);\n }\n let containsForeignElements = 0 /* ForeignElementType.None */;\n if (input.lineDecorations.length > 0) {\n for (let i = 0, len = input.lineDecorations.length; i < len; i++) {\n const lineDecoration = input.lineDecorations[i];\n if (lineDecoration.type === 3 /* InlineDecorationType.RegularAffectingLetterSpacing */) {\n // Pretend there are foreign elements... although not 100% accurate.\n containsForeignElements |= 1 /* ForeignElementType.Before */;\n }\n else if (lineDecoration.type === 1 /* InlineDecorationType.Before */) {\n containsForeignElements |= 1 /* ForeignElementType.Before */;\n }\n else if (lineDecoration.type === 2 /* InlineDecorationType.After */) {\n containsForeignElements |= 2 /* ForeignElementType.After */;\n }\n }\n tokens = _applyInlineDecorations(lineContent, len, tokens, input.lineDecorations);\n }\n if (!input.containsRTL) {\n // We can never split RTL text, as it ruins the rendering\n tokens = splitLargeTokens(lineContent, tokens, !input.isBasicASCII || input.fontLigatures);\n }\n return new ResolvedRenderLineInput(input.useMonospaceOptimizations, input.canUseHalfwidthRightwardsArrow, lineContent, len, isOverflowing, tokens, containsForeignElements, input.fauxIndentLength, input.tabSize, input.startVisibleColumn, input.containsRTL, input.spaceWidth, input.renderSpaceCharCode, input.renderWhitespace, input.renderControlCharacters);\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(lineContent, lineContainsRTL, tokens, fauxIndentLength, len) {\n const result = [];\n let resultLen = 0;\n // The faux indent part of the line should have no token type\n if (fauxIndentLength > 0) {\n result[resultLen++] = new LinePart(fauxIndentLength, '', 0, false);\n }\n let startOffset = fauxIndentLength;\n for (let tokenIndex = 0, tokensLen = tokens.getCount(); tokenIndex < tokensLen; tokenIndex++) {\n const endIndex = tokens.getEndOffset(tokenIndex);\n if (endIndex <= fauxIndentLength) {\n // The faux indent part of the line should have no token type\n continue;\n }\n const type = tokens.getClassName(tokenIndex);\n if (endIndex >= len) {\n const tokenContainsRTL = (lineContainsRTL ? strings.containsRTL(lineContent.substring(startOffset, len)) : false);\n result[resultLen++] = new LinePart(len, type, 0, tokenContainsRTL);\n break;\n }\n const tokenContainsRTL = (lineContainsRTL ? strings.containsRTL(lineContent.substring(startOffset, endIndex)) : false);\n result[resultLen++] = new LinePart(endIndex, type, 0, tokenContainsRTL);\n startOffset = endIndex;\n }\n return result;\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, tokens, onlyAtSpaces) {\n let lastTokenEndIndex = 0;\n const result = [];\n let resultLen = 0;\n if (onlyAtSpaces) {\n // Split only at spaces => we need to walk each character\n for (let i = 0, len = tokens.length; i < len; i++) {\n const token = tokens[i];\n const tokenEndIndex = token.endIndex;\n if (lastTokenEndIndex + 50 /* Constants.LongToken */ < tokenEndIndex) {\n const tokenType = token.type;\n const tokenMetadata = token.metadata;\n const tokenContainsRTL = token.containsRTL;\n let lastSpaceOffset = -1;\n let currTokenStart = lastTokenEndIndex;\n for (let j = lastTokenEndIndex; j < tokenEndIndex; j++) {\n if (lineContent.charCodeAt(j) === 32 /* CharCode.Space */) {\n lastSpaceOffset = j;\n }\n if (lastSpaceOffset !== -1 && j - currTokenStart >= 50 /* Constants.LongToken */) {\n // Split at `lastSpaceOffset` + 1\n result[resultLen++] = new LinePart(lastSpaceOffset + 1, tokenType, tokenMetadata, tokenContainsRTL);\n currTokenStart = lastSpaceOffset + 1;\n lastSpaceOffset = -1;\n }\n }\n if (currTokenStart !== tokenEndIndex) {\n result[resultLen++] = new LinePart(tokenEndIndex, tokenType, tokenMetadata, tokenContainsRTL);\n }\n }\n else {\n result[resultLen++] = token;\n }\n lastTokenEndIndex = tokenEndIndex;\n }\n }\n else {\n // Split anywhere => we don't need to walk each character\n for (let i = 0, len = tokens.length; i < len; i++) {\n const token = tokens[i];\n const tokenEndIndex = token.endIndex;\n const diff = (tokenEndIndex - lastTokenEndIndex);\n if (diff > 50 /* Constants.LongToken */) {\n const tokenType = token.type;\n const tokenMetadata = token.metadata;\n const tokenContainsRTL = token.containsRTL;\n const piecesCount = Math.ceil(diff / 50 /* Constants.LongToken */);\n for (let j = 1; j < piecesCount; j++) {\n const pieceEndIndex = lastTokenEndIndex + (j * 50 /* Constants.LongToken */);\n result[resultLen++] = new LinePart(pieceEndIndex, tokenType, tokenMetadata, tokenContainsRTL);\n }\n result[resultLen++] = new LinePart(tokenEndIndex, tokenType, tokenMetadata, tokenContainsRTL);\n }\n else {\n result[resultLen++] = token;\n }\n lastTokenEndIndex = tokenEndIndex;\n }\n }\n return result;\n}\nfunction isControlCharacter(charCode) {\n if (charCode < 32) {\n return (charCode !== 9 /* CharCode.Tab */);\n }\n if (charCode === 127) {\n // DEL\n return true;\n }\n if ((charCode >= 0x202A && charCode <= 0x202E)\n || (charCode >= 0x2066 && charCode <= 0x2069)\n || (charCode >= 0x200E && charCode <= 0x200F)\n || charCode === 0x061C) {\n // Unicode Directional Formatting Characters\n // LRE\tU+202A\tLEFT-TO-RIGHT EMBEDDING\n // RLE\tU+202B\tRIGHT-TO-LEFT EMBEDDING\n // PDF\tU+202C\tPOP DIRECTIONAL FORMATTING\n // LRO\tU+202D\tLEFT-TO-RIGHT OVERRIDE\n // RLO\tU+202E\tRIGHT-TO-LEFT OVERRIDE\n // LRI\tU+2066\tLEFT-TO-RIGHT ISOLATE\n // RLI\tU+2067\tRIGHT-TO-LEFT ISOLATE\n // FSI\tU+2068\tFIRST STRONG ISOLATE\n // PDI\tU+2069\tPOP DIRECTIONAL ISOLATE\n // LRM\tU+200E\tLEFT-TO-RIGHT MARK\n // RLM\tU+200F\tRIGHT-TO-LEFT MARK\n // ALM\tU+061C\tARABIC LETTER MARK\n return true;\n }\n return false;\n}\nfunction extractControlCharacters(lineContent, tokens) {\n const result = [];\n let lastLinePart = new LinePart(0, '', 0, false);\n let charOffset = 0;\n for (const token of tokens) {\n const tokenEndIndex = token.endIndex;\n for (; charOffset < tokenEndIndex; charOffset++) {\n const charCode = lineContent.charCodeAt(charOffset);\n if (isControlCharacter(charCode)) {\n if (charOffset > lastLinePart.endIndex) {\n // emit previous part if it has text\n lastLinePart = new LinePart(charOffset, token.type, token.metadata, token.containsRTL);\n result.push(lastLinePart);\n }\n lastLinePart = new LinePart(charOffset + 1, 'mtkcontrol', token.metadata, false);\n result.push(lastLinePart);\n }\n }\n if (charOffset > lastLinePart.endIndex) {\n // emit previous part if it has text\n lastLinePart = new LinePart(tokenEndIndex, token.type, token.metadata, token.containsRTL);\n result.push(lastLinePart);\n }\n }\n return result;\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, lineContent, len, tokens) {\n const continuesWithWrappedLine = input.continuesWithWrappedLine;\n const fauxIndentLength = input.fauxIndentLength;\n const tabSize = input.tabSize;\n const startVisibleColumn = input.startVisibleColumn;\n const useMonospaceOptimizations = input.useMonospaceOptimizations;\n const selections = input.selectionsOnLine;\n const onlyBoundary = (input.renderWhitespace === 1 /* RenderWhitespace.Boundary */);\n const onlyTrailing = (input.renderWhitespace === 3 /* RenderWhitespace.Trailing */);\n const generateLinePartForEachWhitespace = (input.renderSpaceWidth !== input.spaceWidth);\n const result = [];\n let resultLen = 0;\n let tokenIndex = 0;\n let tokenType = tokens[tokenIndex].type;\n let tokenContainsRTL = tokens[tokenIndex].containsRTL;\n let tokenEndIndex = tokens[tokenIndex].endIndex;\n const tokensLength = tokens.length;\n let lineIsEmptyOrWhitespace = false;\n let firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineContent);\n let lastNonWhitespaceIndex;\n if (firstNonWhitespaceIndex === -1) {\n lineIsEmptyOrWhitespace = true;\n firstNonWhitespaceIndex = len;\n lastNonWhitespaceIndex = len;\n }\n else {\n lastNonWhitespaceIndex = strings.lastNonWhitespaceIndex(lineContent);\n }\n let wasInWhitespace = false;\n let currentSelectionIndex = 0;\n let currentSelection = selections && selections[currentSelectionIndex];\n let tmpIndent = startVisibleColumn % tabSize;\n for (let charIndex = fauxIndentLength; charIndex < len; charIndex++) {\n const chCode = lineContent.charCodeAt(charIndex);\n if (currentSelection && charIndex >= currentSelection.endOffset) {\n currentSelectionIndex++;\n currentSelection = selections && selections[currentSelectionIndex];\n }\n let isInWhitespace;\n if (charIndex < firstNonWhitespaceIndex || charIndex > lastNonWhitespaceIndex) {\n // in leading or trailing whitespace\n isInWhitespace = true;\n }\n else if (chCode === 9 /* CharCode.Tab */) {\n // a tab character is rendered both in all and boundary cases\n isInWhitespace = true;\n }\n else if (chCode === 32 /* CharCode.Space */) {\n // hit a space character\n if (onlyBoundary) {\n // rendering only boundary whitespace\n if (wasInWhitespace) {\n isInWhitespace = true;\n }\n else {\n const nextChCode = (charIndex + 1 < len ? lineContent.charCodeAt(charIndex + 1) : 0 /* CharCode.Null */);\n isInWhitespace = (nextChCode === 32 /* CharCode.Space */ || nextChCode === 9 /* CharCode.Tab */);\n }\n }\n else {\n isInWhitespace = true;\n }\n }\n else {\n isInWhitespace = false;\n }\n // If rendering whitespace on selection, check that the charIndex falls within a selection\n if (isInWhitespace && selections) {\n isInWhitespace = !!currentSelection && currentSelection.startOffset <= charIndex && currentSelection.endOffset > charIndex;\n }\n // If rendering only trailing whitespace, check that the charIndex points to trailing whitespace.\n if (isInWhitespace && onlyTrailing) {\n isInWhitespace = lineIsEmptyOrWhitespace || charIndex > lastNonWhitespaceIndex;\n }\n if (isInWhitespace && tokenContainsRTL) {\n // If the token contains RTL text, breaking it up into multiple line parts\n // to render whitespace might affect the browser's bidi layout.\n //\n // We render whitespace in such tokens only if the whitespace\n // is the leading or the trailing whitespace of the line,\n // which doesn't affect the browser's bidi layout.\n if (charIndex >= firstNonWhitespaceIndex && charIndex <= lastNonWhitespaceIndex) {\n isInWhitespace = false;\n }\n }\n if (wasInWhitespace) {\n // was in whitespace token\n if (!isInWhitespace || (!useMonospaceOptimizations && tmpIndent >= tabSize)) {\n // leaving whitespace token or entering a new indent\n if (generateLinePartForEachWhitespace) {\n const lastEndIndex = (resultLen > 0 ? result[resultLen - 1].endIndex : fauxIndentLength);\n for (let i = lastEndIndex + 1; i <= charIndex; i++) {\n result[resultLen++] = new LinePart(i, 'mtkw', 1 /* LinePartMetadata.IS_WHITESPACE */, false);\n }\n }\n else {\n result[resultLen++] = new LinePart(charIndex, 'mtkw', 1 /* LinePartMetadata.IS_WHITESPACE */, false);\n }\n tmpIndent = tmpIndent % tabSize;\n }\n }\n else {\n // was in regular token\n if (charIndex === tokenEndIndex || (isInWhitespace && charIndex > fauxIndentLength)) {\n result[resultLen++] = new LinePart(charIndex, tokenType, 0, tokenContainsRTL);\n tmpIndent = tmpIndent % tabSize;\n }\n }\n if (chCode === 9 /* CharCode.Tab */) {\n tmpIndent = tabSize;\n }\n else if (strings.isFullWidthCharacter(chCode)) {\n tmpIndent += 2;\n }\n else {\n tmpIndent++;\n }\n wasInWhitespace = isInWhitespace;\n while (charIndex === tokenEndIndex) {\n tokenIndex++;\n if (tokenIndex < tokensLength) {\n tokenType = tokens[tokenIndex].type;\n tokenContainsRTL = tokens[tokenIndex].containsRTL;\n tokenEndIndex = tokens[tokenIndex].endIndex;\n }\n else {\n break;\n }\n }\n }\n let generateWhitespace = false;\n if (wasInWhitespace) {\n // was in whitespace token\n if (continuesWithWrappedLine && onlyBoundary) {\n const lastCharCode = (len > 0 ? lineContent.charCodeAt(len - 1) : 0 /* CharCode.Null */);\n const prevCharCode = (len > 1 ? lineContent.charCodeAt(len - 2) : 0 /* CharCode.Null */);\n const isSingleTrailingSpace = (lastCharCode === 32 /* CharCode.Space */ && (prevCharCode !== 32 /* CharCode.Space */ && prevCharCode !== 9 /* CharCode.Tab */));\n if (!isSingleTrailingSpace) {\n generateWhitespace = true;\n }\n }\n else {\n generateWhitespace = true;\n }\n }\n if (generateWhitespace) {\n if (generateLinePartForEachWhitespace) {\n const lastEndIndex = (resultLen > 0 ? result[resultLen - 1].endIndex : fauxIndentLength);\n for (let i = lastEndIndex + 1; i <= len; i++) {\n result[resultLen++] = new LinePart(i, 'mtkw', 1 /* LinePartMetadata.IS_WHITESPACE */, false);\n }\n }\n else {\n result[resultLen++] = new LinePart(len, 'mtkw', 1 /* LinePartMetadata.IS_WHITESPACE */, false);\n }\n }\n else {\n result[resultLen++] = new LinePart(len, tokenType, 0, tokenContainsRTL);\n }\n return result;\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, len, tokens, _lineDecorations) {\n _lineDecorations.sort(LineDecoration.compare);\n const lineDecorations = LineDecorationsNormalizer.normalize(lineContent, _lineDecorations);\n const lineDecorationsLen = lineDecorations.length;\n let lineDecorationIndex = 0;\n const result = [];\n let resultLen = 0;\n let lastResultEndIndex = 0;\n for (let tokenIndex = 0, len = tokens.length; tokenIndex < len; tokenIndex++) {\n const token = tokens[tokenIndex];\n const tokenEndIndex = token.endIndex;\n const tokenType = token.type;\n const tokenMetadata = token.metadata;\n const tokenContainsRTL = token.containsRTL;\n while (lineDecorationIndex < lineDecorationsLen && lineDecorations[lineDecorationIndex].startOffset < tokenEndIndex) {\n const lineDecoration = lineDecorations[lineDecorationIndex];\n if (lineDecoration.startOffset > lastResultEndIndex) {\n lastResultEndIndex = lineDecoration.startOffset;\n result[resultLen++] = new LinePart(lastResultEndIndex, tokenType, tokenMetadata, tokenContainsRTL);\n }\n if (lineDecoration.endOffset + 1 <= tokenEndIndex) {\n // This line decoration ends before this token ends\n lastResultEndIndex = lineDecoration.endOffset + 1;\n result[resultLen++] = new LinePart(lastResultEndIndex, tokenType + ' ' + lineDecoration.className, tokenMetadata | lineDecoration.metadata, tokenContainsRTL);\n lineDecorationIndex++;\n }\n else {\n // This line decoration continues on to the next token\n lastResultEndIndex = tokenEndIndex;\n result[resultLen++] = new LinePart(lastResultEndIndex, tokenType + ' ' + lineDecoration.className, tokenMetadata | lineDecoration.metadata, tokenContainsRTL);\n break;\n }\n }\n if (tokenEndIndex > lastResultEndIndex) {\n lastResultEndIndex = tokenEndIndex;\n result[resultLen++] = new LinePart(lastResultEndIndex, tokenType, tokenMetadata, tokenContainsRTL);\n }\n }\n const lastTokenEndIndex = tokens[tokens.length - 1].endIndex;\n if (lineDecorationIndex < lineDecorationsLen && lineDecorations[lineDecorationIndex].startOffset === lastTokenEndIndex) {\n while (lineDecorationIndex < lineDecorationsLen && lineDecorations[lineDecorationIndex].startOffset === lastTokenEndIndex) {\n const lineDecoration = lineDecorations[lineDecorationIndex];\n result[resultLen++] = new LinePart(lastResultEndIndex, lineDecoration.className, lineDecoration.metadata, false);\n lineDecorationIndex++;\n }\n }\n return result;\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, sb) {\n const fontIsMonospace = input.fontIsMonospace;\n const canUseHalfwidthRightwardsArrow = input.canUseHalfwidthRightwardsArrow;\n const containsForeignElements = input.containsForeignElements;\n const lineContent = input.lineContent;\n const len = input.len;\n const isOverflowing = input.isOverflowing;\n const parts = input.parts;\n const fauxIndentLength = input.fauxIndentLength;\n const tabSize = input.tabSize;\n const startVisibleColumn = input.startVisibleColumn;\n const containsRTL = input.containsRTL;\n const spaceWidth = input.spaceWidth;\n const renderSpaceCharCode = input.renderSpaceCharCode;\n const renderWhitespace = input.renderWhitespace;\n const renderControlCharacters = input.renderControlCharacters;\n const characterMapping = new CharacterMapping(len + 1, parts.length);\n let lastCharacterMappingDefined = false;\n let charIndex = 0;\n let visibleColumn = startVisibleColumn;\n let charOffsetInPart = 0; // the character offset in the current part\n let charHorizontalOffset = 0; // the character horizontal position in terms of chars relative to line start\n let partDisplacement = 0;\n if (containsRTL) {\n sb.appendASCIIString('');\n }\n else {\n sb.appendASCIIString('');\n }\n for (let partIndex = 0, tokensLen = parts.length; partIndex < tokensLen; partIndex++) {\n const part = parts[partIndex];\n const partEndIndex = part.endIndex;\n const partType = part.type;\n const partContainsRTL = part.containsRTL;\n const partRendersWhitespace = (renderWhitespace !== 0 /* RenderWhitespace.None */ && part.isWhitespace());\n const partRendersWhitespaceWithWidth = partRendersWhitespace && !fontIsMonospace && (partType === 'mtkw' /*only whitespace*/ || !containsForeignElements);\n const partIsEmptyAndHasPseudoAfter = (charIndex === partEndIndex && part.isPseudoAfter());\n charOffsetInPart = 0;\n sb.appendASCIIString('= fauxIndentLength) {\n _visibleColumn += charWidth;\n }\n }\n }\n if (partRendersWhitespaceWithWidth) {\n sb.appendASCIIString(' style=\"width:');\n sb.appendASCIIString(String(spaceWidth * partWidth));\n sb.appendASCIIString('px\"');\n }\n sb.appendASCII(62 /* CharCode.GreaterThan */);\n for (; charIndex < partEndIndex; charIndex++) {\n characterMapping.setColumnInfo(charIndex + 1, partIndex - partDisplacement, charOffsetInPart, charHorizontalOffset);\n partDisplacement = 0;\n const charCode = lineContent.charCodeAt(charIndex);\n let producedCharacters;\n let charWidth;\n if (charCode === 9 /* CharCode.Tab */) {\n producedCharacters = (tabSize - (visibleColumn % tabSize)) | 0;\n charWidth = producedCharacters;\n if (!canUseHalfwidthRightwardsArrow || charWidth > 1) {\n sb.write1(0x2192); // RIGHTWARDS ARROW\n }\n else {\n sb.write1(0xFFEB); // HALFWIDTH RIGHTWARDS ARROW\n }\n for (let space = 2; space <= charWidth; space++) {\n sb.write1(0xA0); // \n }\n }\n else { // must be CharCode.Space\n producedCharacters = 2;\n charWidth = 1;\n sb.write1(renderSpaceCharCode); // · or word separator middle dot\n sb.write1(0x200C); // ZERO WIDTH NON-JOINER\n }\n charOffsetInPart += producedCharacters;\n charHorizontalOffset += charWidth;\n if (charIndex >= fauxIndentLength) {\n visibleColumn += charWidth;\n }\n }\n }\n else {\n sb.appendASCII(62 /* CharCode.GreaterThan */);\n for (; charIndex < partEndIndex; charIndex++) {\n characterMapping.setColumnInfo(charIndex + 1, partIndex - partDisplacement, charOffsetInPart, charHorizontalOffset);\n partDisplacement = 0;\n const charCode = lineContent.charCodeAt(charIndex);\n let producedCharacters = 1;\n let charWidth = 1;\n switch (charCode) {\n case 9 /* CharCode.Tab */:\n producedCharacters = (tabSize - (visibleColumn % tabSize));\n charWidth = producedCharacters;\n for (let space = 1; space <= producedCharacters; space++) {\n sb.write1(0xA0); // \n }\n break;\n case 32 /* CharCode.Space */:\n sb.write1(0xA0); // \n break;\n case 60 /* CharCode.LessThan */:\n sb.appendASCIIString('<');\n break;\n case 62 /* CharCode.GreaterThan */:\n sb.appendASCIIString('>');\n break;\n case 38 /* CharCode.Ampersand */:\n sb.appendASCIIString('&');\n break;\n case 0 /* CharCode.Null */:\n if (renderControlCharacters) {\n // See https://unicode-table.com/en/blocks/control-pictures/\n sb.write1(9216);\n }\n else {\n sb.appendASCIIString('');\n }\n break;\n case 65279 /* CharCode.UTF8_BOM */:\n case 8232 /* CharCode.LINE_SEPARATOR */:\n case 8233 /* CharCode.PARAGRAPH_SEPARATOR */:\n case 133 /* CharCode.NEXT_LINE */:\n sb.write1(0xFFFD);\n break;\n default:\n if (strings.isFullWidthCharacter(charCode)) {\n charWidth++;\n }\n // See https://unicode-table.com/en/blocks/control-pictures/\n if (renderControlCharacters && charCode < 32) {\n sb.write1(9216 + charCode);\n }\n else if (renderControlCharacters && charCode === 127) {\n // DEL\n sb.write1(9249);\n }\n else if (renderControlCharacters && isControlCharacter(charCode)) {\n sb.appendASCIIString('[U+');\n sb.appendASCIIString(to4CharHex(charCode));\n sb.appendASCIIString(']');\n producedCharacters = 8;\n charWidth = producedCharacters;\n }\n else {\n sb.write1(charCode);\n }\n }\n charOffsetInPart += producedCharacters;\n charHorizontalOffset += charWidth;\n if (charIndex >= fauxIndentLength) {\n visibleColumn += charWidth;\n }\n }\n }\n if (partIsEmptyAndHasPseudoAfter) {\n partDisplacement++;\n }\n else {\n partDisplacement = 0;\n }\n if (charIndex >= len && !lastCharacterMappingDefined && part.isPseudoAfter()) {\n lastCharacterMappingDefined = true;\n characterMapping.setColumnInfo(charIndex + 1, partIndex, charOffsetInPart, charHorizontalOffset);\n }\n sb.appendASCIIString('');\n }\n if (!lastCharacterMappingDefined) {\n // When getting client rects for the last character, we will position the\n // text range at the end of the span, insteaf of at the beginning of next span\n characterMapping.setColumnInfo(len + 1, parts.length - 1, charOffsetInPart, charHorizontalOffset);\n }\n if (isOverflowing) {\n sb.appendASCIIString('…');\n }\n sb.appendASCIIString('');\n return new RenderLineOutput(characterMapping, containsRTL, containsForeignElements);\n}\nfunction to4CharHex(n) {\n return 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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../base/common/strings.js';\nimport { Range } from './core/range.js';\nexport class Viewport {\n constructor(top, left, width, height) {\n this._viewportBrand = undefined;\n this.top = top | 0;\n this.left = left | 0;\n this.width = width | 0;\n this.height = height | 0;\n }\n}\nexport class MinimapLinesRenderingData {\n constructor(tabSize, data) {\n this.tabSize = tabSize;\n this.data = data;\n }\n}\nexport class ViewLineData {\n constructor(content, continuesWithWrappedLine, minColumn, maxColumn, startVisibleColumn, tokens, inlineDecorations) {\n this._viewLineDataBrand = undefined;\n this.content = content;\n this.continuesWithWrappedLine = continuesWithWrappedLine;\n this.minColumn = minColumn;\n this.maxColumn = maxColumn;\n this.startVisibleColumn = startVisibleColumn;\n this.tokens = tokens;\n this.inlineDecorations = inlineDecorations;\n }\n}\nexport class ViewLineRenderingData {\n constructor(minColumn, maxColumn, content, continuesWithWrappedLine, mightContainRTL, mightContainNonBasicASCII, tokens, inlineDecorations, tabSize, startVisibleColumn) {\n this.minColumn = minColumn;\n this.maxColumn = maxColumn;\n this.content = content;\n this.continuesWithWrappedLine = continuesWithWrappedLine;\n this.isBasicASCII = ViewLineRenderingData.isBasicASCII(content, mightContainNonBasicASCII);\n this.containsRTL = ViewLineRenderingData.containsRTL(content, this.isBasicASCII, mightContainRTL);\n this.tokens = tokens;\n this.inlineDecorations = inlineDecorations;\n this.tabSize = tabSize;\n this.startVisibleColumn = startVisibleColumn;\n }\n static isBasicASCII(lineContent, mightContainNonBasicASCII) {\n if (mightContainNonBasicASCII) {\n return strings.isBasicASCII(lineContent);\n }\n return true;\n }\n static containsRTL(lineContent, isBasicASCII, mightContainRTL) {\n if (!isBasicASCII && mightContainRTL) {\n return strings.containsRTL(lineContent);\n }\n return false;\n }\n}\nexport class InlineDecoration {\n constructor(range, inlineClassName, type) {\n this.range = range;\n this.inlineClassName = inlineClassName;\n this.type = type;\n }\n}\nexport class SingleLineInlineDecoration {\n constructor(startOffset, endOffset, inlineClassName, inlineClassNameAffectsLetterSpacing) {\n this.startOffset = startOffset;\n this.endOffset = endOffset;\n this.inlineClassName = inlineClassName;\n this.inlineClassNameAffectsLetterSpacing = inlineClassNameAffectsLetterSpacing;\n }\n toInlineDecoration(lineNumber) {\n return new InlineDecoration(new Range(lineNumber, this.startOffset + 1, lineNumber, this.endOffset + 1), this.inlineClassName, this.inlineClassNameAffectsLetterSpacing ? 3 /* InlineDecorationType.RegularAffectingLetterSpacing */ : 0 /* InlineDecorationType.Regular */);\n }\n}\nexport class ViewModelDecoration {\n constructor(range, options) {\n this._viewModelDecorationBrand = undefined;\n this.range = range;\n this.options = options;\n }\n}\nexport class OverviewRulerDecorationsGroup {\n constructor(color, zIndex, \n /**\n * Decorations are encoded in a number array using the following scheme:\n * - 3*i = lane\n * - 3*i+1 = startLineNumber\n * - 3*i+2 = endLineNumber\n */\n data) {\n this.color = color;\n this.zIndex = zIndex;\n this.data = data;\n }\n static cmp(a, b) {\n if (a.zIndex === b.zIndex) {\n if (a.color < b.color) {\n return -1;\n }\n if (a.color > b.color) {\n return 1;\n }\n return 0;\n }\n return a.zIndex - b.zIndex;\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 *--------------------------------------------------------------------------------------------*/\nexport class ColorZone {\n constructor(from, to, colorId) {\n this._colorZoneBrand = undefined;\n this.from = from | 0;\n this.to = to | 0;\n this.colorId = colorId | 0;\n }\n static compare(a, b) {\n if (a.colorId === b.colorId) {\n if (a.from === b.from) {\n return a.to - b.to;\n }\n return a.from - b.from;\n }\n return a.colorId - b.colorId;\n }\n}\n/**\n * A zone in the overview ruler\n */\nexport class OverviewRulerZone {\n constructor(startLineNumber, endLineNumber, heightInLines, color) {\n this._overviewRulerZoneBrand = undefined;\n this.startLineNumber = startLineNumber;\n this.endLineNumber = endLineNumber;\n this.heightInLines = heightInLines;\n this.color = color;\n this._colorZone = null;\n }\n static compare(a, b) {\n if (a.color === b.color) {\n if (a.startLineNumber === b.startLineNumber) {\n if (a.heightInLines === b.heightInLines) {\n return a.endLineNumber - b.endLineNumber;\n }\n return a.heightInLines - b.heightInLines;\n }\n return a.startLineNumber - b.startLineNumber;\n }\n return a.color < b.color ? -1 : 1;\n }\n setColorZone(colorZone) {\n this._colorZone = colorZone;\n }\n getColorZones() {\n return this._colorZone;\n }\n}\nexport class OverviewZoneManager {\n constructor(getVerticalOffsetForLine) {\n this._getVerticalOffsetForLine = getVerticalOffsetForLine;\n this._zones = [];\n this._colorZonesInvalid = false;\n this._lineHeight = 0;\n this._domWidth = 0;\n this._domHeight = 0;\n this._outerHeight = 0;\n this._pixelRatio = 1;\n this._lastAssignedId = 0;\n this._color2Id = Object.create(null);\n this._id2Color = [];\n }\n getId2Color() {\n return this._id2Color;\n }\n setZones(newZones) {\n this._zones = newZones;\n this._zones.sort(OverviewRulerZone.compare);\n }\n setLineHeight(lineHeight) {\n if (this._lineHeight === lineHeight) {\n return false;\n }\n this._lineHeight = lineHeight;\n this._colorZonesInvalid = true;\n return true;\n }\n setPixelRatio(pixelRatio) {\n this._pixelRatio = pixelRatio;\n this._colorZonesInvalid = true;\n }\n getDOMWidth() {\n return this._domWidth;\n }\n getCanvasWidth() {\n return this._domWidth * this._pixelRatio;\n }\n setDOMWidth(width) {\n if (this._domWidth === width) {\n return false;\n }\n this._domWidth = width;\n this._colorZonesInvalid = true;\n return true;\n }\n getDOMHeight() {\n return this._domHeight;\n }\n getCanvasHeight() {\n return this._domHeight * this._pixelRatio;\n }\n setDOMHeight(height) {\n if (this._domHeight === height) {\n return false;\n }\n this._domHeight = height;\n this._colorZonesInvalid = true;\n return true;\n }\n getOuterHeight() {\n return this._outerHeight;\n }\n setOuterHeight(outerHeight) {\n if (this._outerHeight === outerHeight) {\n return false;\n }\n this._outerHeight = outerHeight;\n this._colorZonesInvalid = true;\n return true;\n }\n resolveColorZones() {\n const colorZonesInvalid = this._colorZonesInvalid;\n const lineHeight = Math.floor(this._lineHeight);\n const totalHeight = Math.floor(this.getCanvasHeight());\n const outerHeight = Math.floor(this._outerHeight);\n const heightRatio = totalHeight / outerHeight;\n const halfMinimumHeight = Math.floor(4 /* Constants.MINIMUM_HEIGHT */ * this._pixelRatio / 2);\n const allColorZones = [];\n for (let i = 0, len = this._zones.length; i < len; i++) {\n const zone = this._zones[i];\n if (!colorZonesInvalid) {\n const colorZone = zone.getColorZones();\n if (colorZone) {\n allColorZones.push(colorZone);\n continue;\n }\n }\n const offset1 = this._getVerticalOffsetForLine(zone.startLineNumber);\n const offset2 = (zone.heightInLines === 0\n ? this._getVerticalOffsetForLine(zone.endLineNumber) + lineHeight\n : offset1 + zone.heightInLines * lineHeight);\n const y1 = Math.floor(heightRatio * offset1);\n const y2 = Math.floor(heightRatio * offset2);\n let ycenter = Math.floor((y1 + y2) / 2);\n let halfHeight = (y2 - ycenter);\n if (halfHeight < halfMinimumHeight) {\n halfHeight = halfMinimumHeight;\n }\n if (ycenter - halfHeight < 0) {\n ycenter = halfHeight;\n }\n if (ycenter + halfHeight > totalHeight) {\n ycenter = totalHeight - halfHeight;\n }\n const color = zone.color;\n let colorId = this._color2Id[color];\n if (!colorId) {\n colorId = (++this._lastAssignedId);\n this._color2Id[color] = colorId;\n this._id2Color[colorId] = color;\n }\n const colorZone = new ColorZone(ycenter - halfHeight, ycenter + halfHeight, colorId);\n zone.setColorZone(colorZone);\n allColorZones.push(colorZone);\n }\n this._colorZonesInvalid = false;\n allColorZones.sort(ColorZone.compare);\n return allColorZones;\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 *--------------------------------------------------------------------------------------------*/\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nimport { InlineDecoration, ViewModelDecoration } from '../viewModel.js';\nimport { filterValidationDecorations } from '../config/editorOptions.js';\nexport class ViewModelDecorations {\n constructor(editorId, model, configuration, linesCollection, coordinatesConverter) {\n this.editorId = editorId;\n this.model = model;\n this.configuration = configuration;\n this._linesCollection = linesCollection;\n this._coordinatesConverter = coordinatesConverter;\n this._decorationsCache = Object.create(null);\n this._cachedModelDecorationsResolver = null;\n this._cachedModelDecorationsResolverViewRange = null;\n }\n _clearCachedModelDecorationsResolver() {\n this._cachedModelDecorationsResolver = null;\n this._cachedModelDecorationsResolverViewRange = null;\n }\n dispose() {\n this._decorationsCache = Object.create(null);\n this._clearCachedModelDecorationsResolver();\n }\n reset() {\n this._decorationsCache = Object.create(null);\n this._clearCachedModelDecorationsResolver();\n }\n onModelDecorationsChanged() {\n this._decorationsCache = Object.create(null);\n this._clearCachedModelDecorationsResolver();\n }\n onLineMappingChanged() {\n this._decorationsCache = Object.create(null);\n this._clearCachedModelDecorationsResolver();\n }\n _getOrCreateViewModelDecoration(modelDecoration) {\n const id = modelDecoration.id;\n let r = this._decorationsCache[id];\n if (!r) {\n const modelRange = modelDecoration.range;\n const options = modelDecoration.options;\n let viewRange;\n if (options.isWholeLine) {\n const start = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.startLineNumber, 1), 0 /* PositionAffinity.Left */);\n const end = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.endLineNumber, this.model.getLineMaxColumn(modelRange.endLineNumber)), 1 /* PositionAffinity.Right */);\n viewRange = new Range(start.lineNumber, start.column, end.lineNumber, end.column);\n }\n else {\n // For backwards compatibility reasons, we want injected text before any decoration.\n // Thus, move decorations to the right.\n viewRange = this._coordinatesConverter.convertModelRangeToViewRange(modelRange, 1 /* PositionAffinity.Right */);\n }\n r = new ViewModelDecoration(viewRange, options);\n this._decorationsCache[id] = r;\n }\n return r;\n }\n getDecorationsViewportData(viewRange) {\n let cacheIsValid = (this._cachedModelDecorationsResolver !== null);\n cacheIsValid = cacheIsValid && (viewRange.equalsRange(this._cachedModelDecorationsResolverViewRange));\n if (!cacheIsValid) {\n this._cachedModelDecorationsResolver = this._getDecorationsInRange(viewRange);\n this._cachedModelDecorationsResolverViewRange = viewRange;\n }\n return this._cachedModelDecorationsResolver;\n }\n getInlineDecorationsOnLine(lineNumber) {\n const range = new Range(lineNumber, this._linesCollection.getViewLineMinColumn(lineNumber), lineNumber, this._linesCollection.getViewLineMaxColumn(lineNumber));\n return this._getDecorationsInRange(range).inlineDecorations[0];\n }\n _getDecorationsInRange(viewRange) {\n const modelDecorations = this._linesCollection.getDecorationsInRange(viewRange, this.editorId, filterValidationDecorations(this.configuration.options));\n const startLineNumber = viewRange.startLineNumber;\n const endLineNumber = viewRange.endLineNumber;\n const decorationsInViewport = [];\n let decorationsInViewportLen = 0;\n const inlineDecorations = [];\n for (let j = startLineNumber; j <= endLineNumber; j++) {\n inlineDecorations[j - startLineNumber] = [];\n }\n for (let i = 0, len = modelDecorations.length; i < len; i++) {\n const modelDecoration = modelDecorations[i];\n const decorationOptions = modelDecoration.options;\n if (!isModelDecorationVisible(this.model, modelDecoration)) {\n continue;\n }\n const viewModelDecoration = this._getOrCreateViewModelDecoration(modelDecoration);\n const viewRange = viewModelDecoration.range;\n decorationsInViewport[decorationsInViewportLen++] = viewModelDecoration;\n if (decorationOptions.inlineClassName) {\n const inlineDecoration = new InlineDecoration(viewRange, decorationOptions.inlineClassName, decorationOptions.inlineClassNameAffectsLetterSpacing ? 3 /* InlineDecorationType.RegularAffectingLetterSpacing */ : 0 /* InlineDecorationType.Regular */);\n const intersectedStartLineNumber = Math.max(startLineNumber, viewRange.startLineNumber);\n const intersectedEndLineNumber = Math.min(endLineNumber, viewRange.endLineNumber);\n for (let j = intersectedStartLineNumber; j <= intersectedEndLineNumber; j++) {\n inlineDecorations[j - startLineNumber].push(inlineDecoration);\n }\n }\n if (decorationOptions.beforeContentClassName) {\n if (startLineNumber <= viewRange.startLineNumber && viewRange.startLineNumber <= endLineNumber) {\n const inlineDecoration = new InlineDecoration(new Range(viewRange.startLineNumber, viewRange.startColumn, viewRange.startLineNumber, viewRange.startColumn), decorationOptions.beforeContentClassName, 1 /* InlineDecorationType.Before */);\n inlineDecorations[viewRange.startLineNumber - startLineNumber].push(inlineDecoration);\n }\n }\n if (decorationOptions.afterContentClassName) {\n if (startLineNumber <= viewRange.endLineNumber && viewRange.endLineNumber <= endLineNumber) {\n const inlineDecoration = new InlineDecoration(new Range(viewRange.endLineNumber, viewRange.endColumn, viewRange.endLineNumber, viewRange.endColumn), decorationOptions.afterContentClassName, 2 /* InlineDecorationType.After */);\n inlineDecorations[viewRange.endLineNumber - startLineNumber].push(inlineDecoration);\n }\n }\n }\n return {\n decorations: decorationsInViewport,\n inlineDecorations: inlineDecorations\n };\n }\n}\nexport function isModelDecorationVisible(model, decoration) {\n if (decoration.options.hideInCommentTokens && isModelDecorationInComment(model, decoration)) {\n return false;\n }\n if (decoration.options.hideInStringTokens && isModelDecorationInString(model, decoration)) {\n return false;\n }\n return true;\n}\nexport function isModelDecorationInComment(model, decoration) {\n return testTokensInRange(model, decoration.range, (tokenType) => tokenType === 1 /* StandardTokenType.Comment */);\n}\nexport function isModelDecorationInString(model, decoration) {\n return testTokensInRange(model, decoration.range, (tokenType) => tokenType === 2 /* StandardTokenType.String */);\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, range, callback) {\n for (let lineNumber = range.startLineNumber; lineNumber <= range.endLineNumber; lineNumber++) {\n const lineTokens = model.tokenization.getLineTokens(lineNumber);\n const isFirstLine = lineNumber === range.startLineNumber;\n const isEndLine = lineNumber === range.endLineNumber;\n let tokenIdx = isFirstLine ? lineTokens.findTokenIndexAtOffset(range.startColumn - 1) : 0;\n while (tokenIdx < lineTokens.getCount()) {\n if (isEndLine) {\n const startOffset = lineTokens.getStartOffset(tokenIdx);\n if (startOffset > range.endColumn - 1) {\n break;\n }\n }\n const callbackResult = callback(lineTokens.getStandardTokenType(tokenIdx));\n if (!callbackResult) {\n return false;\n }\n tokenIdx++;\n }\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { EditorCommand, registerEditorCommand } from '../../../browser/editorExtensions.js';\nimport { IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';\nimport { CancellationTokenSource } from '../../../../base/common/cancellation.js';\nimport { LinkedList } from '../../../../base/common/linkedList.js';\nimport { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';\nimport { registerSingleton } from '../../../../platform/instantiation/common/extensions.js';\nimport { localize } from '../../../../nls.js';\nconst IEditorCancellationTokens = createDecorator('IEditorCancelService');\nconst ctxCancellableOperation = new RawContextKey('cancellableOperation', false, localize('cancellableOperation', 'Whether the editor runs a cancellable operation, e.g. like \\'Peek References\\''));\nregisterSingleton(IEditorCancellationTokens, class {\n constructor() {\n this._tokens = new WeakMap();\n }\n add(editor, cts) {\n let data = this._tokens.get(editor);\n if (!data) {\n data = editor.invokeWithinContext(accessor => {\n const key = ctxCancellableOperation.bindTo(accessor.get(IContextKeyService));\n const tokens = new LinkedList();\n return { key, tokens };\n });\n this._tokens.set(editor, data);\n }\n let removeFn;\n data.key.set(true);\n removeFn = data.tokens.push(cts);\n return () => {\n // remove w/o cancellation\n if (removeFn) {\n removeFn();\n data.key.set(!data.tokens.isEmpty());\n removeFn = undefined;\n }\n };\n }\n cancel(editor) {\n const data = this._tokens.get(editor);\n if (!data) {\n return;\n }\n // remove with cancellation\n const cts = data.tokens.pop();\n if (cts) {\n cts.cancel();\n data.key.set(!data.tokens.isEmpty());\n }\n }\n}, true);\nexport class EditorKeybindingCancellationTokenSource extends CancellationTokenSource {\n constructor(editor, parent) {\n super(parent);\n this.editor = editor;\n this._unregister = editor.invokeWithinContext(accessor => accessor.get(IEditorCancellationTokens).add(editor, this));\n }\n dispose() {\n this._unregister();\n super.dispose();\n }\n}\nregisterEditorCommand(new class extends EditorCommand {\n constructor() {\n super({\n id: 'editor.cancelOperation',\n kbOpts: {\n weight: 100 /* KeybindingWeight.EditorContrib */,\n primary: 9 /* KeyCode.Escape */\n },\n precondition: ctxCancellableOperation\n });\n }\n runEditorCommand(accessor, editor) {\n accessor.get(IEditorCancellationTokens).cancel(editor);\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 *--------------------------------------------------------------------------------------------*/\nimport * as strings from '../../../../base/common/strings.js';\nimport { Range } from '../../../common/core/range.js';\nimport { CancellationTokenSource } from '../../../../base/common/cancellation.js';\nimport { DisposableStore } from '../../../../base/common/lifecycle.js';\nimport { EditorKeybindingCancellationTokenSource } from './keybindingCancellation.js';\nexport class EditorState {\n constructor(editor, flags) {\n this.flags = flags;\n if ((this.flags & 1 /* CodeEditorStateFlag.Value */) !== 0) {\n const model = editor.getModel();\n this.modelVersionId = model ? strings.format('{0}#{1}', model.uri.toString(), model.getVersionId()) : null;\n }\n else {\n this.modelVersionId = null;\n }\n if ((this.flags & 4 /* CodeEditorStateFlag.Position */) !== 0) {\n this.position = editor.getPosition();\n }\n else {\n this.position = null;\n }\n if ((this.flags & 2 /* CodeEditorStateFlag.Selection */) !== 0) {\n this.selection = editor.getSelection();\n }\n else {\n this.selection = null;\n }\n if ((this.flags & 8 /* CodeEditorStateFlag.Scroll */) !== 0) {\n this.scrollLeft = editor.getScrollLeft();\n this.scrollTop = editor.getScrollTop();\n }\n else {\n this.scrollLeft = -1;\n this.scrollTop = -1;\n }\n }\n _equals(other) {\n if (!(other instanceof EditorState)) {\n return false;\n }\n const state = other;\n if (this.modelVersionId !== state.modelVersionId) {\n return false;\n }\n if (this.scrollLeft !== state.scrollLeft || this.scrollTop !== state.scrollTop) {\n return false;\n }\n if (!this.position && state.position || this.position && !state.position || this.position && state.position && !this.position.equals(state.position)) {\n return false;\n }\n if (!this.selection && state.selection || this.selection && !state.selection || this.selection && state.selection && !this.selection.equalsRange(state.selection)) {\n return false;\n }\n return true;\n }\n validate(editor) {\n return this._equals(new EditorState(editor, this.flags));\n }\n}\n/**\n * A cancellation token source that cancels when the editor changes as expressed\n * by the provided flags\n * @param range If provided, changes in position and selection within this range will not trigger cancellation\n */\nexport class EditorStateCancellationTokenSource extends EditorKeybindingCancellationTokenSource {\n constructor(editor, flags, range, parent) {\n super(editor, parent);\n this._listener = new DisposableStore();\n if (flags & 4 /* CodeEditorStateFlag.Position */) {\n this._listener.add(editor.onDidChangeCursorPosition(e => {\n if (!range || !Range.containsPosition(range, e.position)) {\n this.cancel();\n }\n }));\n }\n if (flags & 2 /* CodeEditorStateFlag.Selection */) {\n this._listener.add(editor.onDidChangeCursorSelection(e => {\n if (!range || !Range.containsRange(range, e.selection)) {\n this.cancel();\n }\n }));\n }\n if (flags & 8 /* CodeEditorStateFlag.Scroll */) {\n this._listener.add(editor.onDidScrollChange(_ => this.cancel()));\n }\n if (flags & 1 /* CodeEditorStateFlag.Value */) {\n this._listener.add(editor.onDidChangeModel(_ => this.cancel()));\n this._listener.add(editor.onDidChangeModelContent(_ => this.cancel()));\n }\n }\n dispose() {\n this._listener.dispose();\n super.dispose();\n }\n}\n/**\n * A cancellation token source that cancels when the provided model changes\n */\nexport class TextModelCancellationTokenSource extends CancellationTokenSource {\n constructor(model, parent) {\n super(parent);\n this._listener = model.onDidChangeContent(() => this.cancel());\n }\n dispose() {\n this._listener.dispose();\n super.dispose();\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 constructor(value) {\n this.value = value;\n this._lower = value.toLowerCase();\n }\n /**\n * Gives the value by which to index (for equality).\n */\n static toKey(id) {\n if (typeof id === 'string') {\n return id.toLowerCase();\n }\n return id._lower;\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 *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { alert } from '../../../../base/browser/ui/aria/aria.js';\nimport { asArray, isNonEmptyArray } from '../../../../base/common/arrays.js';\nimport { CancellationToken } from '../../../../base/common/cancellation.js';\nimport { onUnexpectedExternalError } from '../../../../base/common/errors.js';\nimport { Iterable } from '../../../../base/common/iterator.js';\nimport { LinkedList } from '../../../../base/common/linkedList.js';\nimport { assertType } from '../../../../base/common/types.js';\nimport { URI } from '../../../../base/common/uri.js';\nimport { EditorStateCancellationTokenSource, TextModelCancellationTokenSource } from '../../editorState/browser/editorState.js';\nimport { isCodeEditor } from '../../../browser/editorBrowser.js';\nimport { Position } from '../../../common/core/position.js';\nimport { Range } from '../../../common/core/range.js';\nimport { Selection } from '../../../common/core/selection.js';\nimport { IEditorWorkerService } from '../../../common/services/editorWorker.js';\nimport { ITextModelService } from '../../../common/services/resolverService.js';\nimport { FormattingEdit } from './formattingEdit.js';\nimport * as nls from '../../../../nls.js';\nimport { CommandsRegistry } from '../../../../platform/commands/common/commands.js';\nimport { ExtensionIdentifier } from '../../../../platform/extensions/common/extensions.js';\nimport { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';\nimport { ILanguageFeaturesService } from '../../../common/services/languageFeatures.js';\nexport function alertFormattingEdits(edits) {\n edits = edits.filter(edit => edit.range);\n if (!edits.length) {\n return;\n }\n let { range } = edits[0];\n for (let i = 1; i < edits.length; i++) {\n range = Range.plusRange(range, edits[i].range);\n }\n const { startLineNumber, endLineNumber } = range;\n if (startLineNumber === endLineNumber) {\n if (edits.length === 1) {\n alert(nls.localize('hint11', \"Made 1 formatting edit on line {0}\", startLineNumber));\n }\n else {\n alert(nls.localize('hintn1', \"Made {0} formatting edits on line {1}\", edits.length, startLineNumber));\n }\n }\n else {\n if (edits.length === 1) {\n alert(nls.localize('hint1n', \"Made 1 formatting edit between lines {0} and {1}\", startLineNumber, endLineNumber));\n }\n else {\n alert(nls.localize('hintnn', \"Made {0} formatting edits between lines {1} and {2}\", edits.length, startLineNumber, endLineNumber));\n }\n }\n}\nexport function getRealAndSyntheticDocumentFormattersOrdered(documentFormattingEditProvider, documentRangeFormattingEditProvider, model) {\n const result = [];\n const seen = new Set();\n // (1) add all document formatter\n const docFormatter = documentFormattingEditProvider.ordered(model);\n for (const formatter of docFormatter) {\n result.push(formatter);\n if (formatter.extensionId) {\n seen.add(ExtensionIdentifier.toKey(formatter.extensionId));\n }\n }\n // (2) add all range formatter as document formatter (unless the same extension already did that)\n const rangeFormatter = documentRangeFormattingEditProvider.ordered(model);\n for (const formatter of rangeFormatter) {\n if (formatter.extensionId) {\n if (seen.has(ExtensionIdentifier.toKey(formatter.extensionId))) {\n continue;\n }\n seen.add(ExtensionIdentifier.toKey(formatter.extensionId));\n }\n result.push({\n displayName: formatter.displayName,\n extensionId: formatter.extensionId,\n provideDocumentFormattingEdits(model, options, token) {\n return formatter.provideDocumentRangeFormattingEdits(model, model.getFullModelRange(), options, token);\n }\n });\n }\n return result;\n}\nexport class FormattingConflicts {\n static setFormatterSelector(selector) {\n const remove = FormattingConflicts._selectors.unshift(selector);\n return { dispose: remove };\n }\n static select(formatter, document, mode) {\n return __awaiter(this, void 0, void 0, function* () {\n if (formatter.length === 0) {\n return undefined;\n }\n const selector = Iterable.first(FormattingConflicts._selectors);\n if (selector) {\n return yield selector(formatter, document, mode);\n }\n return undefined;\n });\n }\n}\nFormattingConflicts._selectors = new LinkedList();\nexport function formatDocumentRangesWithSelectedProvider(accessor, editorOrModel, rangeOrRanges, mode, progress, token) {\n return __awaiter(this, void 0, void 0, function* () {\n const instaService = accessor.get(IInstantiationService);\n const { documentRangeFormattingEditProvider: documentRangeFormattingEditProviderRegistry } = accessor.get(ILanguageFeaturesService);\n const model = isCodeEditor(editorOrModel) ? editorOrModel.getModel() : editorOrModel;\n const provider = documentRangeFormattingEditProviderRegistry.ordered(model);\n const selected = yield FormattingConflicts.select(provider, model, mode);\n if (selected) {\n progress.report(selected);\n yield instaService.invokeFunction(formatDocumentRangesWithProvider, selected, editorOrModel, rangeOrRanges, token);\n }\n });\n}\nexport function formatDocumentRangesWithProvider(accessor, provider, editorOrModel, rangeOrRanges, token) {\n return __awaiter(this, void 0, void 0, function* () {\n const workerService = accessor.get(IEditorWorkerService);\n let model;\n let cts;\n if (isCodeEditor(editorOrModel)) {\n model = editorOrModel.getModel();\n cts = new EditorStateCancellationTokenSource(editorOrModel, 1 /* CodeEditorStateFlag.Value */ | 4 /* CodeEditorStateFlag.Position */, undefined, token);\n }\n else {\n model = editorOrModel;\n cts = new TextModelCancellationTokenSource(editorOrModel, token);\n }\n // make sure that ranges don't overlap nor touch each other\n const ranges = [];\n let len = 0;\n for (const range of asArray(rangeOrRanges).sort(Range.compareRangesUsingStarts)) {\n if (len > 0 && Range.areIntersectingOrTouching(ranges[len - 1], range)) {\n ranges[len - 1] = Range.fromPositions(ranges[len - 1].getStartPosition(), range.getEndPosition());\n }\n else {\n len = ranges.push(range);\n }\n }\n const computeEdits = (range) => __awaiter(this, void 0, void 0, function* () {\n return (yield provider.provideDocumentRangeFormattingEdits(model, range, model.getFormattingOptions(), cts.token)) || [];\n });\n const hasIntersectingEdit = (a, b) => {\n if (!a.length || !b.length) {\n return false;\n }\n // quick exit if the list of ranges are completely unrelated [O(n)]\n const mergedA = a.reduce((acc, val) => { return Range.plusRange(acc, val.range); }, a[0].range);\n if (!b.some(x => { return Range.intersectRanges(mergedA, x.range); })) {\n return false;\n }\n // fallback to a complete check [O(n^2)]\n for (const edit of a) {\n for (const otherEdit of b) {\n if (Range.intersectRanges(edit.range, otherEdit.range)) {\n return true;\n }\n }\n }\n return false;\n };\n const allEdits = [];\n const rawEditsList = [];\n try {\n for (const range of ranges) {\n if (cts.token.isCancellationRequested) {\n return true;\n }\n rawEditsList.push(yield computeEdits(range));\n }\n for (let i = 0; i < ranges.length; ++i) {\n for (let j = i + 1; j < ranges.length; ++j) {\n if (cts.token.isCancellationRequested) {\n return true;\n }\n if (hasIntersectingEdit(rawEditsList[i], rawEditsList[j])) {\n // Merge ranges i and j into a single range, recompute the associated edits\n const mergedRange = Range.plusRange(ranges[i], ranges[j]);\n const edits = yield computeEdits(mergedRange);\n ranges.splice(j, 1);\n ranges.splice(i, 1);\n ranges.push(mergedRange);\n rawEditsList.splice(j, 1);\n rawEditsList.splice(i, 1);\n rawEditsList.push(edits);\n // Restart scanning\n i = 0;\n j = 0;\n }\n }\n }\n for (const rawEdits of rawEditsList) {\n if (cts.token.isCancellationRequested) {\n return true;\n }\n const minimalEdits = yield workerService.computeMoreMinimalEdits(model.uri, rawEdits);\n if (minimalEdits) {\n allEdits.push(...minimalEdits);\n }\n }\n }\n finally {\n cts.dispose();\n }\n if (allEdits.length === 0) {\n return false;\n }\n if (isCodeEditor(editorOrModel)) {\n // use editor to apply edits\n FormattingEdit.execute(editorOrModel, allEdits, true);\n alertFormattingEdits(allEdits);\n editorOrModel.revealPositionInCenterIfOutsideViewport(editorOrModel.getPosition(), 1 /* ScrollType.Immediate */);\n }\n else {\n // use model to apply edits\n const [{ range }] = allEdits;\n const initialSelection = new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);\n model.pushEditOperations([initialSelection], allEdits.map(edit => {\n return {\n text: edit.text,\n range: Range.lift(edit.range),\n forceMoveMarkers: true\n };\n }), undoEdits => {\n for (const { range } of undoEdits) {\n if (Range.areIntersectingOrTouching(range, initialSelection)) {\n return [new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn)];\n }\n }\n return null;\n });\n }\n return true;\n });\n}\nexport function formatDocumentWithSelectedProvider(accessor, editorOrModel, mode, progress, token) {\n return __awaiter(this, void 0, void 0, function* () {\n const instaService = accessor.get(IInstantiationService);\n const languageFeaturesService = accessor.get(ILanguageFeaturesService);\n const model = isCodeEditor(editorOrModel) ? editorOrModel.getModel() : editorOrModel;\n const provider = getRealAndSyntheticDocumentFormattersOrdered(languageFeaturesService.documentFormattingEditProvider, languageFeaturesService.documentRangeFormattingEditProvider, model);\n const selected = yield FormattingConflicts.select(provider, model, mode);\n if (selected) {\n progress.report(selected);\n yield instaService.invokeFunction(formatDocumentWithProvider, selected, editorOrModel, mode, token);\n }\n });\n}\nexport function formatDocumentWithProvider(accessor, provider, editorOrModel, mode, token) {\n return __awaiter(this, void 0, void 0, function* () {\n const workerService = accessor.get(IEditorWorkerService);\n let model;\n let cts;\n if (isCodeEditor(editorOrModel)) {\n model = editorOrModel.getModel();\n cts = new EditorStateCancellationTokenSource(editorOrModel, 1 /* CodeEditorStateFlag.Value */ | 4 /* CodeEditorStateFlag.Position */, undefined, token);\n }\n else {\n model = editorOrModel;\n cts = new TextModelCancellationTokenSource(editorOrModel, token);\n }\n let edits;\n try {\n const rawEdits = yield provider.provideDocumentFormattingEdits(model, model.getFormattingOptions(), cts.token);\n edits = yield workerService.computeMoreMinimalEdits(model.uri, rawEdits);\n if (cts.token.isCancellationRequested) {\n return true;\n }\n }\n finally {\n cts.dispose();\n }\n if (!edits || edits.length === 0) {\n return false;\n }\n if (isCodeEditor(editorOrModel)) {\n // use editor to apply edits\n FormattingEdit.execute(editorOrModel, edits, mode !== 2 /* FormattingMode.Silent */);\n if (mode !== 2 /* FormattingMode.Silent */) {\n alertFormattingEdits(edits);\n editorOrModel.revealPositionInCenterIfOutsideViewport(editorOrModel.getPosition(), 1 /* ScrollType.Immediate */);\n }\n }\n else {\n // use model to apply edits\n const [{ range }] = edits;\n const initialSelection = new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);\n model.pushEditOperations([initialSelection], edits.map(edit => {\n return {\n text: edit.text,\n range: Range.lift(edit.range),\n forceMoveMarkers: true\n };\n }), undoEdits => {\n for (const { range } of undoEdits) {\n if (Range.areIntersectingOrTouching(range, initialSelection)) {\n return [new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn)];\n }\n }\n return null;\n });\n }\n return true;\n });\n}\nexport function getDocumentRangeFormattingEditsUntilResult(workerService, languageFeaturesService, model, range, options, token) {\n return __awaiter(this, void 0, void 0, function* () {\n const providers = languageFeaturesService.documentRangeFormattingEditProvider.ordered(model);\n for (const provider of providers) {\n const rawEdits = yield Promise.resolve(provider.provideDocumentRangeFormattingEdits(model, range, options, token)).catch(onUnexpectedExternalError);\n if (isNonEmptyArray(rawEdits)) {\n return yield workerService.computeMoreMinimalEdits(model.uri, rawEdits);\n }\n }\n return undefined;\n });\n}\nexport function getDocumentFormattingEditsUntilResult(workerService, languageFeaturesService, model, options, token) {\n return __awaiter(this, void 0, void 0, function* () {\n const providers = getRealAndSyntheticDocumentFormattersOrdered(languageFeaturesService.documentFormattingEditProvider, languageFeaturesService.documentRangeFormattingEditProvider, model);\n for (const provider of providers) {\n const rawEdits = yield Promise.resolve(provider.provideDocumentFormattingEdits(model, options, token)).catch(onUnexpectedExternalError);\n if (isNonEmptyArray(rawEdits)) {\n return yield workerService.computeMoreMinimalEdits(model.uri, rawEdits);\n }\n }\n return undefined;\n });\n}\nexport function getOnTypeFormattingEdits(workerService, languageFeaturesService, model, position, ch, options, token) {\n const providers = languageFeaturesService.onTypeFormattingEditProvider.ordered(model);\n if (providers.length === 0) {\n return Promise.resolve(undefined);\n }\n if (providers[0].autoFormatTriggerCharacters.indexOf(ch) < 0) {\n return Promise.resolve(undefined);\n }\n return Promise.resolve(providers[0].provideOnTypeFormattingEdits(model, position, ch, options, token)).catch(onUnexpectedExternalError).then(edits => {\n return workerService.computeMoreMinimalEdits(model.uri, edits);\n });\n}\nCommandsRegistry.registerCommand('_executeFormatRangeProvider', function (accessor, ...args) {\n return __awaiter(this, void 0, void 0, function* () {\n const [resource, range, options] = args;\n assertType(URI.isUri(resource));\n assertType(Range.isIRange(range));\n const resolverService = accessor.get(ITextModelService);\n const workerService = accessor.get(IEditorWorkerService);\n const languageFeaturesService = accessor.get(ILanguageFeaturesService);\n const reference = yield resolverService.createModelReference(resource);\n try {\n return getDocumentRangeFormattingEditsUntilResult(workerService, languageFeaturesService, reference.object.textEditorModel, Range.lift(range), options, CancellationToken.None);\n }\n finally {\n reference.dispose();\n }\n });\n});\nCommandsRegistry.registerCommand('_executeFormatDocumentProvider', function (accessor, ...args) {\n return __awaiter(this, void 0, void 0, function* () {\n const [resource, options] = args;\n assertType(URI.isUri(resource));\n const resolverService = accessor.get(ITextModelService);\n const workerService = accessor.get(IEditorWorkerService);\n const languageFeaturesService = accessor.get(ILanguageFeaturesService);\n const reference = yield resolverService.createModelReference(resource);\n try {\n return getDocumentFormattingEditsUntilResult(workerService, languageFeaturesService, reference.object.textEditorModel, options, CancellationToken.None);\n }\n finally {\n reference.dispose();\n }\n });\n});\nCommandsRegistry.registerCommand('_executeFormatOnTypeProvider', function (accessor, ...args) {\n return __awaiter(this, void 0, void 0, function* () {\n const [resource, position, ch, options] = args;\n assertType(URI.isUri(resource));\n assertType(Position.isIPosition(position));\n assertType(typeof ch === 'string');\n const resolverService = accessor.get(ITextModelService);\n const workerService = accessor.get(IEditorWorkerService);\n const languageFeaturesService = accessor.get(ILanguageFeaturesService);\n const reference = yield resolverService.createModelReference(resource);\n try {\n return getOnTypeFormattingEdits(workerService, languageFeaturesService, reference.object.textEditorModel, Position.lift(position), ch, options, CancellationToken.None);\n }\n finally {\n reference.dispose();\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 *--------------------------------------------------------------------------------------------*/\nimport { EditOperation } from '../../../common/core/editOperation.js';\nimport { Range } from '../../../common/core/range.js';\nexport class FormattingEdit {\n static _handleEolEdits(editor, edits) {\n let newEol = undefined;\n const singleEdits = [];\n for (const edit of edits) {\n if (typeof edit.eol === 'number') {\n newEol = edit.eol;\n }\n if (edit.range && typeof edit.text === 'string') {\n singleEdits.push(edit);\n }\n }\n if (typeof newEol === 'number') {\n if (editor.hasModel()) {\n editor.getModel().pushEOL(newEol);\n }\n }\n return singleEdits;\n }\n static _isFullModelReplaceEdit(editor, edit) {\n if (!editor.hasModel()) {\n return false;\n }\n const model = editor.getModel();\n const editRange = model.validateRange(edit.range);\n const fullModelRange = model.getFullModelRange();\n return fullModelRange.equalsRange(editRange);\n }\n static execute(editor, _edits, addUndoStops) {\n if (addUndoStops) {\n editor.pushUndoStop();\n }\n const edits = FormattingEdit._handleEolEdits(editor, _edits);\n if (edits.length === 1 && FormattingEdit._isFullModelReplaceEdit(editor, edits[0])) {\n // We use replace semantics and hope that markers stay put...\n editor.executeEdits('formatEditsCommand', edits.map(edit => EditOperation.replace(Range.lift(edit.range), edit.text)));\n }\n else {\n editor.executeEdits('formatEditsCommand', edits.map(edit => EditOperation.replaceMove(Range.lift(edit.range), edit.text)));\n }\n if (addUndoStops) {\n editor.pushUndoStop();\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 *--------------------------------------------------------------------------------------------*/\nimport { CancellationTokenSource } from '../../../base/common/cancellation.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { KeyChord } from '../../../base/common/keyCodes.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nimport { Selection } from '../core/selection.js';\nimport { Token } from '../languages.js';\nimport * as standaloneEnums from '../standalone/standaloneEnums.js';\nexport class KeyMod {\n static chord(firstPart, secondPart) {\n return KeyChord(firstPart, secondPart);\n }\n}\nKeyMod.CtrlCmd = 2048 /* ConstKeyMod.CtrlCmd */;\nKeyMod.Shift = 1024 /* ConstKeyMod.Shift */;\nKeyMod.Alt = 512 /* ConstKeyMod.Alt */;\nKeyMod.WinCtrl = 256 /* ConstKeyMod.WinCtrl */;\nexport function createMonacoBaseAPI() {\n return {\n editor: undefined,\n languages: undefined,\n CancellationTokenSource: CancellationTokenSource,\n Emitter: Emitter,\n KeyCode: standaloneEnums.KeyCode,\n KeyMod: KeyMod,\n Position: Position,\n Range: Range,\n Selection: Selection,\n SelectionDirection: standaloneEnums.SelectionDirection,\n MarkerSeverity: standaloneEnums.MarkerSeverity,\n MarkerTag: standaloneEnums.MarkerTag,\n Uri: URI,\n Token: Token\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 *--------------------------------------------------------------------------------------------*/\nimport { transformErrorForSerialization } from '../errors.js';\nimport { Emitter } from '../event.js';\nimport { Disposable } from '../lifecycle.js';\nimport { globals, isWeb } from '../platform.js';\nimport * as types from '../types.js';\nimport * as strings from '../strings.js';\nconst INITIALIZE = '$initialize';\nlet webWorkerWarningLogged = false;\nexport function logOnceWebWorkerWarning(err) {\n if (!isWeb) {\n // running tests\n return;\n }\n if (!webWorkerWarningLogged) {\n webWorkerWarningLogged = true;\n console.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 }\n console.warn(err.message);\n}\nclass RequestMessage {\n constructor(vsWorker, req, method, args) {\n this.vsWorker = vsWorker;\n this.req = req;\n this.method = method;\n this.args = args;\n this.type = 0 /* MessageType.Request */;\n }\n}\nclass ReplyMessage {\n constructor(vsWorker, seq, res, err) {\n this.vsWorker = vsWorker;\n this.seq = seq;\n this.res = res;\n this.err = err;\n this.type = 1 /* MessageType.Reply */;\n }\n}\nclass SubscribeEventMessage {\n constructor(vsWorker, req, eventName, arg) {\n this.vsWorker = vsWorker;\n this.req = req;\n this.eventName = eventName;\n this.arg = arg;\n this.type = 2 /* MessageType.SubscribeEvent */;\n }\n}\nclass EventMessage {\n constructor(vsWorker, req, event) {\n this.vsWorker = vsWorker;\n this.req = req;\n this.event = event;\n this.type = 3 /* MessageType.Event */;\n }\n}\nclass UnsubscribeEventMessage {\n constructor(vsWorker, req) {\n this.vsWorker = vsWorker;\n this.req = req;\n this.type = 4 /* MessageType.UnsubscribeEvent */;\n }\n}\nclass SimpleWorkerProtocol {\n constructor(handler) {\n this._workerId = -1;\n this._handler = handler;\n this._lastSentReq = 0;\n this._pendingReplies = Object.create(null);\n this._pendingEmitters = new Map();\n this._pendingEvents = new Map();\n }\n setWorkerId(workerId) {\n this._workerId = workerId;\n }\n sendMessage(method, args) {\n const req = String(++this._lastSentReq);\n return new Promise((resolve, reject) => {\n this._pendingReplies[req] = {\n resolve: resolve,\n reject: reject\n };\n this._send(new RequestMessage(this._workerId, req, method, args));\n });\n }\n listen(eventName, arg) {\n let req = null;\n const emitter = new Emitter({\n onFirstListenerAdd: () => {\n req = String(++this._lastSentReq);\n this._pendingEmitters.set(req, emitter);\n this._send(new SubscribeEventMessage(this._workerId, req, eventName, arg));\n },\n onLastListenerRemove: () => {\n this._pendingEmitters.delete(req);\n this._send(new UnsubscribeEventMessage(this._workerId, req));\n req = null;\n }\n });\n return emitter.event;\n }\n handleMessage(message) {\n if (!message || !message.vsWorker) {\n return;\n }\n if (this._workerId !== -1 && message.vsWorker !== this._workerId) {\n return;\n }\n this._handleMessage(message);\n }\n _handleMessage(msg) {\n switch (msg.type) {\n case 1 /* MessageType.Reply */:\n return this._handleReplyMessage(msg);\n case 0 /* MessageType.Request */:\n return this._handleRequestMessage(msg);\n case 2 /* MessageType.SubscribeEvent */:\n return this._handleSubscribeEventMessage(msg);\n case 3 /* MessageType.Event */:\n return this._handleEventMessage(msg);\n case 4 /* MessageType.UnsubscribeEvent */:\n return this._handleUnsubscribeEventMessage(msg);\n }\n }\n _handleReplyMessage(replyMessage) {\n if (!this._pendingReplies[replyMessage.seq]) {\n console.warn('Got reply to unknown seq');\n return;\n }\n const reply = this._pendingReplies[replyMessage.seq];\n delete this._pendingReplies[replyMessage.seq];\n if (replyMessage.err) {\n let err = replyMessage.err;\n if (replyMessage.err.$isError) {\n err = new Error();\n err.name = replyMessage.err.name;\n err.message = replyMessage.err.message;\n err.stack = replyMessage.err.stack;\n }\n reply.reject(err);\n return;\n }\n reply.resolve(replyMessage.res);\n }\n _handleRequestMessage(requestMessage) {\n const req = requestMessage.req;\n const result = this._handler.handleMessage(requestMessage.method, requestMessage.args);\n result.then((r) => {\n this._send(new ReplyMessage(this._workerId, req, r, undefined));\n }, (e) => {\n if (e.detail instanceof Error) {\n // Loading errors have a detail property that points to the actual error\n e.detail = transformErrorForSerialization(e.detail);\n }\n this._send(new ReplyMessage(this._workerId, req, undefined, transformErrorForSerialization(e)));\n });\n }\n _handleSubscribeEventMessage(msg) {\n const req = msg.req;\n const disposable = this._handler.handleEvent(msg.eventName, msg.arg)((event) => {\n this._send(new EventMessage(this._workerId, req, event));\n });\n this._pendingEvents.set(req, disposable);\n }\n _handleEventMessage(msg) {\n if (!this._pendingEmitters.has(msg.req)) {\n console.warn('Got event for unknown req');\n return;\n }\n this._pendingEmitters.get(msg.req).fire(msg.event);\n }\n _handleUnsubscribeEventMessage(msg) {\n if (!this._pendingEvents.has(msg.req)) {\n console.warn('Got unsubscribe for unknown req');\n return;\n }\n this._pendingEvents.get(msg.req).dispose();\n this._pendingEvents.delete(msg.req);\n }\n _send(msg) {\n const transfer = [];\n if (msg.type === 0 /* MessageType.Request */) {\n for (let i = 0; i < msg.args.length; i++) {\n if (msg.args[i] instanceof ArrayBuffer) {\n transfer.push(msg.args[i]);\n }\n }\n }\n else if (msg.type === 1 /* MessageType.Reply */) {\n if (msg.res instanceof ArrayBuffer) {\n transfer.push(msg.res);\n }\n }\n this._handler.sendMessage(msg, transfer);\n }\n}\n/**\n * Main thread side\n */\nexport class SimpleWorkerClient extends Disposable {\n constructor(workerFactory, moduleId, host) {\n super();\n let lazyProxyReject = null;\n this._worker = this._register(workerFactory.create('vs/base/common/worker/simpleWorker', (msg) => {\n this._protocol.handleMessage(msg);\n }, (err) => {\n // in Firefox, web workers fail lazily :(\n // we will reject the proxy\n lazyProxyReject === null || lazyProxyReject === void 0 ? void 0 : lazyProxyReject(err);\n }));\n this._protocol = new SimpleWorkerProtocol({\n sendMessage: (msg, transfer) => {\n this._worker.postMessage(msg, transfer);\n },\n handleMessage: (method, args) => {\n if (typeof host[method] !== 'function') {\n return Promise.reject(new Error('Missing method ' + method + ' on main thread host.'));\n }\n try {\n return Promise.resolve(host[method].apply(host, args));\n }\n catch (e) {\n return Promise.reject(e);\n }\n },\n handleEvent: (eventName, arg) => {\n if (propertyIsDynamicEvent(eventName)) {\n const event = host[eventName].call(host, arg);\n if (typeof event !== 'function') {\n throw new Error(`Missing dynamic event ${eventName} on main thread host.`);\n }\n return event;\n }\n if (propertyIsEvent(eventName)) {\n const event = host[eventName];\n if (typeof event !== 'function') {\n throw new Error(`Missing event ${eventName} on main thread host.`);\n }\n return event;\n }\n throw new Error(`Malformed event name ${eventName}`);\n }\n });\n this._protocol.setWorkerId(this._worker.getId());\n // Gather loader configuration\n let loaderConfiguration = null;\n if (typeof globals.require !== 'undefined' && typeof globals.require.getConfig === 'function') {\n // Get the configuration from the Monaco AMD Loader\n loaderConfiguration = globals.require.getConfig();\n }\n else if (typeof globals.requirejs !== 'undefined') {\n // Get the configuration from requirejs\n loaderConfiguration = globals.requirejs.s.contexts._.config;\n }\n const hostMethods = types.getAllMethodNames(host);\n // Send initialize message\n this._onModuleLoaded = this._protocol.sendMessage(INITIALIZE, [\n this._worker.getId(),\n JSON.parse(JSON.stringify(loaderConfiguration)),\n moduleId,\n hostMethods,\n ]);\n // Create proxy to loaded code\n const proxyMethodRequest = (method, args) => {\n return this._request(method, args);\n };\n const proxyListen = (eventName, arg) => {\n return this._protocol.listen(eventName, arg);\n };\n this._lazyProxy = new Promise((resolve, reject) => {\n lazyProxyReject = reject;\n this._onModuleLoaded.then((availableMethods) => {\n resolve(createProxyObject(availableMethods, proxyMethodRequest, proxyListen));\n }, (e) => {\n reject(e);\n this._onError('Worker failed to load ' + moduleId, e);\n });\n });\n }\n getProxyObject() {\n return this._lazyProxy;\n }\n _request(method, args) {\n return new Promise((resolve, reject) => {\n this._onModuleLoaded.then(() => {\n this._protocol.sendMessage(method, args).then(resolve, reject);\n }, reject);\n });\n }\n _onError(message, error) {\n console.error(message);\n console.info(error);\n }\n}\nfunction propertyIsEvent(name) {\n // Assume a property is an event if it has a form of \"onSomething\"\n return name[0] === 'o' && name[1] === 'n' && strings.isUpperAsciiLetter(name.charCodeAt(2));\n}\nfunction propertyIsDynamicEvent(name) {\n // Assume a property is a dynamic event (a method that returns an event) if it has a form of \"onDynamicSomething\"\n return /^onDynamic/.test(name) && strings.isUpperAsciiLetter(name.charCodeAt(9));\n}\nfunction createProxyObject(methodNames, invoke, proxyListen) {\n const createProxyMethod = (method) => {\n return function () {\n const args = Array.prototype.slice.call(arguments, 0);\n return invoke(method, args);\n };\n };\n const createProxyDynamicEvent = (eventName) => {\n return function (arg) {\n return proxyListen(eventName, arg);\n };\n };\n const result = {};\n for (const methodName of methodNames) {\n if (propertyIsDynamicEvent(methodName)) {\n result[methodName] = createProxyDynamicEvent(methodName);\n continue;\n }\n if (propertyIsEvent(methodName)) {\n result[methodName] = proxyListen(methodName, undefined);\n continue;\n }\n result[methodName] = createProxyMethod(methodName);\n }\n return result;\n}\n/**\n * Worker side\n */\nexport class SimpleWorkerServer {\n constructor(postMessage, requestHandlerFactory) {\n this._requestHandlerFactory = requestHandlerFactory;\n this._requestHandler = null;\n this._protocol = new SimpleWorkerProtocol({\n sendMessage: (msg, transfer) => {\n postMessage(msg, transfer);\n },\n handleMessage: (method, args) => this._handleMessage(method, args),\n handleEvent: (eventName, arg) => this._handleEvent(eventName, arg)\n });\n }\n onmessage(msg) {\n this._protocol.handleMessage(msg);\n }\n _handleMessage(method, args) {\n if (method === INITIALIZE) {\n return this.initialize(args[0], args[1], args[2], args[3]);\n }\n if (!this._requestHandler || typeof this._requestHandler[method] !== 'function') {\n return Promise.reject(new Error('Missing requestHandler or method: ' + method));\n }\n try {\n return Promise.resolve(this._requestHandler[method].apply(this._requestHandler, args));\n }\n catch (e) {\n return Promise.reject(e);\n }\n }\n _handleEvent(eventName, arg) {\n if (!this._requestHandler) {\n throw new Error(`Missing requestHandler`);\n }\n if (propertyIsDynamicEvent(eventName)) {\n const event = this._requestHandler[eventName].call(this._requestHandler, arg);\n if (typeof event !== 'function') {\n throw new Error(`Missing dynamic event ${eventName} on request handler.`);\n }\n return event;\n }\n if (propertyIsEvent(eventName)) {\n const event = this._requestHandler[eventName];\n if (typeof event !== 'function') {\n throw new Error(`Missing event ${eventName} on request handler.`);\n }\n return event;\n }\n throw new Error(`Malformed event name ${eventName}`);\n }\n initialize(workerId, loaderConfig, moduleId, hostMethods) {\n this._protocol.setWorkerId(workerId);\n const proxyMethodRequest = (method, args) => {\n return this._protocol.sendMessage(method, args);\n };\n const proxyListen = (eventName, arg) => {\n return this._protocol.listen(eventName, arg);\n };\n const hostProxy = createProxyObject(hostMethods, proxyMethodRequest, proxyListen);\n if (this._requestHandlerFactory) {\n // static request handler\n this._requestHandler = this._requestHandlerFactory(hostProxy);\n return Promise.resolve(types.getAllMethodNames(this._requestHandler));\n }\n if (loaderConfig) {\n // Remove 'baseUrl', handling it is beyond scope for now\n if (typeof loaderConfig.baseUrl !== 'undefined') {\n delete loaderConfig['baseUrl'];\n }\n if (typeof loaderConfig.paths !== 'undefined') {\n if (typeof loaderConfig.paths.vs !== 'undefined') {\n delete loaderConfig.paths['vs'];\n }\n }\n if (typeof loaderConfig.trustedTypesPolicy !== undefined) {\n // don't use, it has been destroyed during serialize\n delete loaderConfig['trustedTypesPolicy'];\n }\n // Since this is in a web worker, enable catching errors\n loaderConfig.catchError = true;\n globals.require.config(loaderConfig);\n }\n return new Promise((resolve, reject) => {\n // Use the global require to be sure to get the global config\n // ESM-comment-begin\n // \t\t\tconst req = (globals.require || require);\n // ESM-comment-end\n // ESM-uncomment-begin\n const req = globals.require;\n // ESM-uncomment-end\n req([moduleId], (module) => {\n this._requestHandler = module.create(hostProxy);\n if (!this._requestHandler) {\n reject(new Error(`No RequestHandler!`));\n return;\n }\n resolve(types.getAllMethodNames(this._requestHandler));\n }, reject);\n });\n }\n}\n/**\n * Called on the worker side\n */\nexport function create(postMessage) {\n return 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 *--------------------------------------------------------------------------------------------*/\nvar _a;\nimport { globals } from '../common/platform.js';\nimport { logOnceWebWorkerWarning } from '../common/worker/simpleWorker.js';\nconst ttPolicy = (_a = window.trustedTypes) === null || _a === void 0 ? void 0 : _a.createPolicy('defaultWorkerFactory', { createScriptURL: value => value });\nfunction getWorker(label) {\n // Option for hosts to overwrite the worker script (used in the standalone editor)\n if (globals.MonacoEnvironment) {\n if (typeof globals.MonacoEnvironment.getWorker === 'function') {\n return globals.MonacoEnvironment.getWorker('workerMain.js', label);\n }\n if (typeof globals.MonacoEnvironment.getWorkerUrl === 'function') {\n const workerUrl = globals.MonacoEnvironment.getWorkerUrl('workerMain.js', label);\n return new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) : workerUrl, { name: label });\n }\n }\n // 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 // ESM-comment-end\n throw new Error(`You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker`);\n}\n// ESM-comment-begin\n// export 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\nfunction isPromiseLike(obj) {\n if (typeof obj.then === 'function') {\n return true;\n }\n return false;\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 {\n constructor(moduleId, id, label, onMessageCallback, onErrorCallback) {\n this.id = id;\n const workerOrPromise = getWorker(label);\n if (isPromiseLike(workerOrPromise)) {\n this.worker = workerOrPromise;\n }\n else {\n this.worker = Promise.resolve(workerOrPromise);\n }\n this.postMessage(moduleId, []);\n this.worker.then((w) => {\n w.onmessage = function (ev) {\n onMessageCallback(ev.data);\n };\n w.onmessageerror = onErrorCallback;\n if (typeof w.addEventListener === 'function') {\n w.addEventListener('error', onErrorCallback);\n }\n });\n }\n getId() {\n return this.id;\n }\n postMessage(message, transfer) {\n var _a;\n (_a = this.worker) === null || _a === void 0 ? void 0 : _a.then(w => w.postMessage(message, transfer));\n }\n dispose() {\n var _a;\n (_a = this.worker) === null || _a === void 0 ? void 0 : _a.then(w => w.terminate());\n this.worker = null;\n }\n}\nexport class DefaultWorkerFactory {\n constructor(label) {\n this._label = label;\n this._webWorkerFailedBeforeError = false;\n }\n create(moduleId, onMessageCallback, onErrorCallback) {\n const workerId = (++DefaultWorkerFactory.LAST_WORKER_ID);\n if (this._webWorkerFailedBeforeError) {\n throw this._webWorkerFailedBeforeError;\n }\n return new WebWorker(moduleId, workerId, this._label || 'anonymous' + workerId, onMessageCallback, (err) => {\n logOnceWebWorkerWarning(err);\n this._webWorkerFailedBeforeError = err;\n onErrorCallback(err);\n });\n }\n}\nDefaultWorkerFactory.LAST_WORKER_ID = 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 *--------------------------------------------------------------------------------------------*/\nimport { LcsDiff } from '../../../base/common/diff/diff.js';\nimport * as strings from '../../../base/common/strings.js';\nconst MINIMUM_MATCHING_CHARACTER_LENGTH = 3;\nfunction computeDiff(originalSequence, modifiedSequence, continueProcessingPredicate, pretty) {\n const diffAlgo = new LcsDiff(originalSequence, modifiedSequence, continueProcessingPredicate);\n return diffAlgo.ComputeDiff(pretty);\n}\nclass LineSequence {\n constructor(lines) {\n const startColumns = [];\n const endColumns = [];\n for (let i = 0, length = lines.length; i < length; i++) {\n startColumns[i] = getFirstNonBlankColumn(lines[i], 1);\n endColumns[i] = getLastNonBlankColumn(lines[i], 1);\n }\n this.lines = lines;\n this._startColumns = startColumns;\n this._endColumns = endColumns;\n }\n getElements() {\n const elements = [];\n for (let i = 0, len = this.lines.length; i < len; i++) {\n elements[i] = this.lines[i].substring(this._startColumns[i] - 1, this._endColumns[i] - 1);\n }\n return elements;\n }\n getStrictElement(index) {\n return this.lines[index];\n }\n getStartLineNumber(i) {\n return i + 1;\n }\n getEndLineNumber(i) {\n return i + 1;\n }\n createCharSequence(shouldIgnoreTrimWhitespace, startIndex, endIndex) {\n const charCodes = [];\n const lineNumbers = [];\n const columns = [];\n let len = 0;\n for (let index = startIndex; index <= endIndex; index++) {\n const lineContent = this.lines[index];\n const startColumn = (shouldIgnoreTrimWhitespace ? this._startColumns[index] : 1);\n const endColumn = (shouldIgnoreTrimWhitespace ? this._endColumns[index] : lineContent.length + 1);\n for (let col = startColumn; col < endColumn; col++) {\n charCodes[len] = lineContent.charCodeAt(col - 1);\n lineNumbers[len] = index + 1;\n columns[len] = col;\n len++;\n }\n if (!shouldIgnoreTrimWhitespace && index < endIndex) {\n // Add \\n if trim whitespace is not ignored\n charCodes[len] = 10 /* CharCode.LineFeed */;\n lineNumbers[len] = index + 1;\n columns[len] = lineContent.length + 1;\n len++;\n }\n }\n return new CharSequence(charCodes, lineNumbers, columns);\n }\n}\nclass CharSequence {\n constructor(charCodes, lineNumbers, columns) {\n this._charCodes = charCodes;\n this._lineNumbers = lineNumbers;\n this._columns = columns;\n }\n toString() {\n return ('[' + this._charCodes.map((s, idx) => (s === 10 /* CharCode.LineFeed */ ? '\\\\n' : String.fromCharCode(s)) + `-(${this._lineNumbers[idx]},${this._columns[idx]})`).join(', ') + ']');\n }\n _assertIndex(index, arr) {\n if (index < 0 || index >= arr.length) {\n throw new Error(`Illegal index`);\n }\n }\n getElements() {\n return this._charCodes;\n }\n getStartLineNumber(i) {\n if (i > 0 && i === this._lineNumbers.length) {\n // the start line number of the element after the last element\n // is the end line number of the last element\n return this.getEndLineNumber(i - 1);\n }\n this._assertIndex(i, this._lineNumbers);\n return this._lineNumbers[i];\n }\n getEndLineNumber(i) {\n if (i === -1) {\n // the end line number of the element before the first element\n // is the start line number of the first element\n return this.getStartLineNumber(i + 1);\n }\n this._assertIndex(i, this._lineNumbers);\n if (this._charCodes[i] === 10 /* CharCode.LineFeed */) {\n return this._lineNumbers[i] + 1;\n }\n return this._lineNumbers[i];\n }\n getStartColumn(i) {\n if (i > 0 && i === this._columns.length) {\n // the start column of the element after the last element\n // is the end column of the last element\n return this.getEndColumn(i - 1);\n }\n this._assertIndex(i, this._columns);\n return this._columns[i];\n }\n getEndColumn(i) {\n if (i === -1) {\n // the end column of the element before the first element\n // is the start column of the first element\n return this.getStartColumn(i + 1);\n }\n this._assertIndex(i, this._columns);\n if (this._charCodes[i] === 10 /* CharCode.LineFeed */) {\n return 1;\n }\n return this._columns[i] + 1;\n }\n}\nclass CharChange {\n constructor(originalStartLineNumber, originalStartColumn, originalEndLineNumber, originalEndColumn, modifiedStartLineNumber, modifiedStartColumn, modifiedEndLineNumber, modifiedEndColumn) {\n this.originalStartLineNumber = originalStartLineNumber;\n this.originalStartColumn = originalStartColumn;\n this.originalEndLineNumber = originalEndLineNumber;\n this.originalEndColumn = originalEndColumn;\n this.modifiedStartLineNumber = modifiedStartLineNumber;\n this.modifiedStartColumn = modifiedStartColumn;\n this.modifiedEndLineNumber = modifiedEndLineNumber;\n this.modifiedEndColumn = modifiedEndColumn;\n }\n static createFromDiffChange(diffChange, originalCharSequence, modifiedCharSequence) {\n const originalStartLineNumber = originalCharSequence.getStartLineNumber(diffChange.originalStart);\n const originalStartColumn = originalCharSequence.getStartColumn(diffChange.originalStart);\n const originalEndLineNumber = originalCharSequence.getEndLineNumber(diffChange.originalStart + diffChange.originalLength - 1);\n const originalEndColumn = originalCharSequence.getEndColumn(diffChange.originalStart + diffChange.originalLength - 1);\n const modifiedStartLineNumber = modifiedCharSequence.getStartLineNumber(diffChange.modifiedStart);\n const modifiedStartColumn = modifiedCharSequence.getStartColumn(diffChange.modifiedStart);\n const modifiedEndLineNumber = modifiedCharSequence.getEndLineNumber(diffChange.modifiedStart + diffChange.modifiedLength - 1);\n const modifiedEndColumn = modifiedCharSequence.getEndColumn(diffChange.modifiedStart + diffChange.modifiedLength - 1);\n return new CharChange(originalStartLineNumber, originalStartColumn, originalEndLineNumber, originalEndColumn, modifiedStartLineNumber, modifiedStartColumn, modifiedEndLineNumber, modifiedEndColumn);\n }\n}\nfunction postProcessCharChanges(rawChanges) {\n if (rawChanges.length <= 1) {\n return rawChanges;\n }\n const result = [rawChanges[0]];\n let prevChange = result[0];\n for (let i = 1, len = rawChanges.length; i < len; i++) {\n const currChange = rawChanges[i];\n const originalMatchingLength = currChange.originalStart - (prevChange.originalStart + prevChange.originalLength);\n const modifiedMatchingLength = currChange.modifiedStart - (prevChange.modifiedStart + prevChange.modifiedLength);\n // Both of the above should be equal, but the continueProcessingPredicate may prevent this from being true\n const matchingLength = Math.min(originalMatchingLength, modifiedMatchingLength);\n if (matchingLength < MINIMUM_MATCHING_CHARACTER_LENGTH) {\n // Merge the current change into the previous one\n prevChange.originalLength = (currChange.originalStart + currChange.originalLength) - prevChange.originalStart;\n prevChange.modifiedLength = (currChange.modifiedStart + currChange.modifiedLength) - prevChange.modifiedStart;\n }\n else {\n // Add the current change\n result.push(currChange);\n prevChange = currChange;\n }\n }\n return result;\n}\nclass LineChange {\n constructor(originalStartLineNumber, originalEndLineNumber, modifiedStartLineNumber, modifiedEndLineNumber, charChanges) {\n this.originalStartLineNumber = originalStartLineNumber;\n this.originalEndLineNumber = originalEndLineNumber;\n this.modifiedStartLineNumber = modifiedStartLineNumber;\n this.modifiedEndLineNumber = modifiedEndLineNumber;\n this.charChanges = charChanges;\n }\n static createFromDiffResult(shouldIgnoreTrimWhitespace, diffChange, originalLineSequence, modifiedLineSequence, continueCharDiff, shouldComputeCharChanges, shouldPostProcessCharChanges) {\n let originalStartLineNumber;\n let originalEndLineNumber;\n let modifiedStartLineNumber;\n let modifiedEndLineNumber;\n let charChanges = undefined;\n if (diffChange.originalLength === 0) {\n originalStartLineNumber = originalLineSequence.getStartLineNumber(diffChange.originalStart) - 1;\n originalEndLineNumber = 0;\n }\n else {\n originalStartLineNumber = originalLineSequence.getStartLineNumber(diffChange.originalStart);\n originalEndLineNumber = originalLineSequence.getEndLineNumber(diffChange.originalStart + diffChange.originalLength - 1);\n }\n if (diffChange.modifiedLength === 0) {\n modifiedStartLineNumber = modifiedLineSequence.getStartLineNumber(diffChange.modifiedStart) - 1;\n modifiedEndLineNumber = 0;\n }\n else {\n modifiedStartLineNumber = modifiedLineSequence.getStartLineNumber(diffChange.modifiedStart);\n modifiedEndLineNumber = modifiedLineSequence.getEndLineNumber(diffChange.modifiedStart + diffChange.modifiedLength - 1);\n }\n if (shouldComputeCharChanges && diffChange.originalLength > 0 && diffChange.originalLength < 20 && diffChange.modifiedLength > 0 && diffChange.modifiedLength < 20 && continueCharDiff()) {\n // Compute character changes for diff chunks of at most 20 lines...\n const originalCharSequence = originalLineSequence.createCharSequence(shouldIgnoreTrimWhitespace, diffChange.originalStart, diffChange.originalStart + diffChange.originalLength - 1);\n const modifiedCharSequence = modifiedLineSequence.createCharSequence(shouldIgnoreTrimWhitespace, diffChange.modifiedStart, diffChange.modifiedStart + diffChange.modifiedLength - 1);\n if (originalCharSequence.getElements().length > 0 && modifiedCharSequence.getElements().length > 0) {\n let rawChanges = computeDiff(originalCharSequence, modifiedCharSequence, continueCharDiff, true).changes;\n if (shouldPostProcessCharChanges) {\n rawChanges = postProcessCharChanges(rawChanges);\n }\n charChanges = [];\n for (let i = 0, length = rawChanges.length; i < length; i++) {\n charChanges.push(CharChange.createFromDiffChange(rawChanges[i], originalCharSequence, modifiedCharSequence));\n }\n }\n }\n return new LineChange(originalStartLineNumber, originalEndLineNumber, modifiedStartLineNumber, modifiedEndLineNumber, charChanges);\n }\n}\nexport class DiffComputer {\n constructor(originalLines, modifiedLines, opts) {\n this.shouldComputeCharChanges = opts.shouldComputeCharChanges;\n this.shouldPostProcessCharChanges = opts.shouldPostProcessCharChanges;\n this.shouldIgnoreTrimWhitespace = opts.shouldIgnoreTrimWhitespace;\n this.shouldMakePrettyDiff = opts.shouldMakePrettyDiff;\n this.originalLines = originalLines;\n this.modifiedLines = modifiedLines;\n this.original = new LineSequence(originalLines);\n this.modified = new LineSequence(modifiedLines);\n this.continueLineDiff = createContinueProcessingPredicate(opts.maxComputationTime);\n this.continueCharDiff = createContinueProcessingPredicate(opts.maxComputationTime === 0 ? 0 : Math.min(opts.maxComputationTime, 5000)); // never run after 5s for character changes...\n }\n computeDiff() {\n if (this.original.lines.length === 1 && this.original.lines[0].length === 0) {\n // empty original => fast path\n if (this.modified.lines.length === 1 && this.modified.lines[0].length === 0) {\n return {\n quitEarly: false,\n changes: []\n };\n }\n return {\n quitEarly: false,\n changes: [{\n originalStartLineNumber: 1,\n originalEndLineNumber: 1,\n modifiedStartLineNumber: 1,\n modifiedEndLineNumber: this.modified.lines.length,\n charChanges: [{\n modifiedEndColumn: 0,\n modifiedEndLineNumber: 0,\n modifiedStartColumn: 0,\n modifiedStartLineNumber: 0,\n originalEndColumn: 0,\n originalEndLineNumber: 0,\n originalStartColumn: 0,\n originalStartLineNumber: 0\n }]\n }]\n };\n }\n if (this.modified.lines.length === 1 && this.modified.lines[0].length === 0) {\n // empty modified => fast path\n return {\n quitEarly: false,\n changes: [{\n originalStartLineNumber: 1,\n originalEndLineNumber: this.original.lines.length,\n modifiedStartLineNumber: 1,\n modifiedEndLineNumber: 1,\n charChanges: [{\n modifiedEndColumn: 0,\n modifiedEndLineNumber: 0,\n modifiedStartColumn: 0,\n modifiedStartLineNumber: 0,\n originalEndColumn: 0,\n originalEndLineNumber: 0,\n originalStartColumn: 0,\n originalStartLineNumber: 0\n }]\n }]\n };\n }\n const diffResult = computeDiff(this.original, this.modified, this.continueLineDiff, this.shouldMakePrettyDiff);\n const rawChanges = diffResult.changes;\n const quitEarly = diffResult.quitEarly;\n // The diff is always computed with ignoring trim whitespace\n // This ensures we get the prettiest diff\n if (this.shouldIgnoreTrimWhitespace) {\n const lineChanges = [];\n for (let i = 0, length = rawChanges.length; i < length; i++) {\n lineChanges.push(LineChange.createFromDiffResult(this.shouldIgnoreTrimWhitespace, rawChanges[i], this.original, this.modified, this.continueCharDiff, this.shouldComputeCharChanges, this.shouldPostProcessCharChanges));\n }\n return {\n quitEarly: quitEarly,\n changes: lineChanges\n };\n }\n // Need to post-process and introduce changes where the trim whitespace is different\n // Note that we are looping starting at -1 to also cover the lines before the first change\n const result = [];\n let originalLineIndex = 0;\n let modifiedLineIndex = 0;\n for (let i = -1 /* !!!! */, len = rawChanges.length; i < len; i++) {\n const nextChange = (i + 1 < len ? rawChanges[i + 1] : null);\n const originalStop = (nextChange ? nextChange.originalStart : this.originalLines.length);\n const modifiedStop = (nextChange ? nextChange.modifiedStart : this.modifiedLines.length);\n while (originalLineIndex < originalStop && modifiedLineIndex < modifiedStop) {\n const originalLine = this.originalLines[originalLineIndex];\n const modifiedLine = this.modifiedLines[modifiedLineIndex];\n if (originalLine !== modifiedLine) {\n // These lines differ only in trim whitespace\n // Check the leading whitespace\n {\n let originalStartColumn = getFirstNonBlankColumn(originalLine, 1);\n let modifiedStartColumn = getFirstNonBlankColumn(modifiedLine, 1);\n while (originalStartColumn > 1 && modifiedStartColumn > 1) {\n const originalChar = originalLine.charCodeAt(originalStartColumn - 2);\n const modifiedChar = modifiedLine.charCodeAt(modifiedStartColumn - 2);\n if (originalChar !== modifiedChar) {\n break;\n }\n originalStartColumn--;\n modifiedStartColumn--;\n }\n if (originalStartColumn > 1 || modifiedStartColumn > 1) {\n this._pushTrimWhitespaceCharChange(result, originalLineIndex + 1, 1, originalStartColumn, modifiedLineIndex + 1, 1, modifiedStartColumn);\n }\n }\n // Check the trailing whitespace\n {\n let originalEndColumn = getLastNonBlankColumn(originalLine, 1);\n let modifiedEndColumn = getLastNonBlankColumn(modifiedLine, 1);\n const originalMaxColumn = originalLine.length + 1;\n const modifiedMaxColumn = modifiedLine.length + 1;\n while (originalEndColumn < originalMaxColumn && modifiedEndColumn < modifiedMaxColumn) {\n const originalChar = originalLine.charCodeAt(originalEndColumn - 1);\n const modifiedChar = originalLine.charCodeAt(modifiedEndColumn - 1);\n if (originalChar !== modifiedChar) {\n break;\n }\n originalEndColumn++;\n modifiedEndColumn++;\n }\n if (originalEndColumn < originalMaxColumn || modifiedEndColumn < modifiedMaxColumn) {\n this._pushTrimWhitespaceCharChange(result, originalLineIndex + 1, originalEndColumn, originalMaxColumn, modifiedLineIndex + 1, modifiedEndColumn, modifiedMaxColumn);\n }\n }\n }\n originalLineIndex++;\n modifiedLineIndex++;\n }\n if (nextChange) {\n // Emit the actual change\n result.push(LineChange.createFromDiffResult(this.shouldIgnoreTrimWhitespace, nextChange, this.original, this.modified, this.continueCharDiff, this.shouldComputeCharChanges, this.shouldPostProcessCharChanges));\n originalLineIndex += nextChange.originalLength;\n modifiedLineIndex += nextChange.modifiedLength;\n }\n }\n return {\n quitEarly: quitEarly,\n changes: result\n };\n }\n _pushTrimWhitespaceCharChange(result, originalLineNumber, originalStartColumn, originalEndColumn, modifiedLineNumber, modifiedStartColumn, modifiedEndColumn) {\n if (this._mergeTrimWhitespaceCharChange(result, originalLineNumber, originalStartColumn, originalEndColumn, modifiedLineNumber, modifiedStartColumn, modifiedEndColumn)) {\n // Merged into previous\n return;\n }\n let charChanges = undefined;\n if (this.shouldComputeCharChanges) {\n charChanges = [new CharChange(originalLineNumber, originalStartColumn, originalLineNumber, originalEndColumn, modifiedLineNumber, modifiedStartColumn, modifiedLineNumber, modifiedEndColumn)];\n }\n result.push(new LineChange(originalLineNumber, originalLineNumber, modifiedLineNumber, modifiedLineNumber, charChanges));\n }\n _mergeTrimWhitespaceCharChange(result, originalLineNumber, originalStartColumn, originalEndColumn, modifiedLineNumber, modifiedStartColumn, modifiedEndColumn) {\n const len = result.length;\n if (len === 0) {\n return false;\n }\n const prevChange = result[len - 1];\n if (prevChange.originalEndLineNumber === 0 || prevChange.modifiedEndLineNumber === 0) {\n // Don't merge with inserts/deletes\n return false;\n }\n if (prevChange.originalEndLineNumber + 1 === originalLineNumber && prevChange.modifiedEndLineNumber + 1 === modifiedLineNumber) {\n prevChange.originalEndLineNumber = originalLineNumber;\n prevChange.modifiedEndLineNumber = modifiedLineNumber;\n if (this.shouldComputeCharChanges && prevChange.charChanges) {\n prevChange.charChanges.push(new CharChange(originalLineNumber, originalStartColumn, originalLineNumber, originalEndColumn, modifiedLineNumber, modifiedStartColumn, modifiedLineNumber, modifiedEndColumn));\n }\n return true;\n }\n return false;\n }\n}\nfunction getFirstNonBlankColumn(txt, defaultValue) {\n const r = strings.firstNonWhitespaceIndex(txt);\n if (r === -1) {\n return defaultValue;\n }\n return r + 1;\n}\nfunction getLastNonBlankColumn(txt, defaultValue) {\n const r = strings.lastNonWhitespaceIndex(txt);\n if (r === -1) {\n return defaultValue;\n }\n return r + 2;\n}\nfunction createContinueProcessingPredicate(maximumRuntime) {\n if (maximumRuntime === 0) {\n return () => true;\n }\n const startTime = Date.now();\n return () => {\n return Date.now() - startTime < maximumRuntime;\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 *--------------------------------------------------------------------------------------------*/\nimport { splitLines } from '../../../base/common/strings.js';\nimport { Position } from '../core/position.js';\nimport { PrefixSumComputer } from './prefixSumComputer.js';\nexport class MirrorTextModel {\n constructor(uri, lines, eol, versionId) {\n this._uri = uri;\n this._lines = lines;\n this._eol = eol;\n this._versionId = versionId;\n this._lineStarts = null;\n this._cachedTextValue = null;\n }\n dispose() {\n this._lines.length = 0;\n }\n get version() {\n return this._versionId;\n }\n getText() {\n if (this._cachedTextValue === null) {\n this._cachedTextValue = this._lines.join(this._eol);\n }\n return this._cachedTextValue;\n }\n onEvents(e) {\n if (e.eol && e.eol !== this._eol) {\n this._eol = e.eol;\n this._lineStarts = null;\n }\n // Update my lines\n const changes = e.changes;\n for (const change of changes) {\n this._acceptDeleteRange(change.range);\n this._acceptInsertText(new Position(change.range.startLineNumber, change.range.startColumn), change.text);\n }\n this._versionId = e.versionId;\n this._cachedTextValue = null;\n }\n _ensureLineStarts() {\n if (!this._lineStarts) {\n const eolLength = this._eol.length;\n const linesLength = this._lines.length;\n const lineStartValues = new Uint32Array(linesLength);\n for (let i = 0; i < linesLength; i++) {\n lineStartValues[i] = this._lines[i].length + eolLength;\n }\n this._lineStarts = new PrefixSumComputer(lineStartValues);\n }\n }\n /**\n * All changes to a line's text go through this method\n */\n _setLineText(lineIndex, newValue) {\n this._lines[lineIndex] = newValue;\n if (this._lineStarts) {\n // update prefix sum\n this._lineStarts.setValue(lineIndex, this._lines[lineIndex].length + this._eol.length);\n }\n }\n _acceptDeleteRange(range) {\n if (range.startLineNumber === range.endLineNumber) {\n if (range.startColumn === range.endColumn) {\n // Nothing to delete\n return;\n }\n // Delete text on the affected line\n this._setLineText(range.startLineNumber - 1, this._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1)\n + this._lines[range.startLineNumber - 1].substring(range.endColumn - 1));\n return;\n }\n // Take remaining text on last line and append it to remaining text on first line\n this._setLineText(range.startLineNumber - 1, this._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1)\n + this._lines[range.endLineNumber - 1].substring(range.endColumn - 1));\n // Delete middle lines\n this._lines.splice(range.startLineNumber, range.endLineNumber - range.startLineNumber);\n if (this._lineStarts) {\n // update prefix sum\n this._lineStarts.removeValues(range.startLineNumber, range.endLineNumber - range.startLineNumber);\n }\n }\n _acceptInsertText(position, insertText) {\n if (insertText.length === 0) {\n // Nothing to insert\n return;\n }\n const insertLines = splitLines(insertText);\n if (insertLines.length === 1) {\n // Inserting text on one line\n this._setLineText(position.lineNumber - 1, this._lines[position.lineNumber - 1].substring(0, position.column - 1)\n + insertLines[0]\n + this._lines[position.lineNumber - 1].substring(position.column - 1));\n return;\n }\n // Append overflowing text from first line to the end of text to insert\n insertLines[insertLines.length - 1] += this._lines[position.lineNumber - 1].substring(position.column - 1);\n // Delete overflowing text from first line and insert text on first line\n this._setLineText(position.lineNumber - 1, this._lines[position.lineNumber - 1].substring(0, position.column - 1)\n + insertLines[0]);\n // Insert new lines & store lengths\n const newLengths = new Uint32Array(insertLines.length - 1);\n for (let i = 1; i < insertLines.length; i++) {\n this._lines.splice(position.lineNumber + i - 1, 0, insertLines[i]);\n newLengths[i - 1] = insertLines[i].length + this._eol.length;\n }\n if (this._lineStarts) {\n // update prefix sum\n this._lineStarts.insertValues(position.lineNumber, newLengths);\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 *--------------------------------------------------------------------------------------------*/\nimport { CharacterClassifier } from '../core/characterClassifier.js';\nexport class Uint8Matrix {\n constructor(rows, cols, defaultValue) {\n const data = new Uint8Array(rows * cols);\n for (let i = 0, len = rows * cols; i < len; i++) {\n data[i] = defaultValue;\n }\n this._data = data;\n this.rows = rows;\n this.cols = cols;\n }\n get(row, col) {\n return this._data[row * this.cols + col];\n }\n set(row, col, value) {\n this._data[row * this.cols + col] = value;\n }\n}\nexport class StateMachine {\n constructor(edges) {\n let maxCharCode = 0;\n let maxState = 0 /* State.Invalid */;\n for (let i = 0, len = edges.length; i < len; i++) {\n const [from, chCode, to] = edges[i];\n if (chCode > maxCharCode) {\n maxCharCode = chCode;\n }\n if (from > maxState) {\n maxState = from;\n }\n if (to > maxState) {\n maxState = to;\n }\n }\n maxCharCode++;\n maxState++;\n const states = new Uint8Matrix(maxState, maxCharCode, 0 /* State.Invalid */);\n for (let i = 0, len = edges.length; i < len; i++) {\n const [from, chCode, to] = edges[i];\n states.set(from, chCode, to);\n }\n this._states = states;\n this._maxCharCode = maxCharCode;\n }\n nextState(currentState, chCode) {\n if (chCode < 0 || chCode >= this._maxCharCode) {\n return 0 /* State.Invalid */;\n }\n return this._states.get(currentState, chCode);\n }\n}\n// State machine for http:// or https:// or file://\nlet _stateMachine = null;\nfunction getStateMachine() {\n if (_stateMachine === null) {\n _stateMachine = new StateMachine([\n [1 /* State.Start */, 104 /* CharCode.h */, 2 /* State.H */],\n [1 /* State.Start */, 72 /* CharCode.H */, 2 /* State.H */],\n [1 /* State.Start */, 102 /* CharCode.f */, 6 /* State.F */],\n [1 /* State.Start */, 70 /* CharCode.F */, 6 /* State.F */],\n [2 /* State.H */, 116 /* CharCode.t */, 3 /* State.HT */],\n [2 /* State.H */, 84 /* CharCode.T */, 3 /* State.HT */],\n [3 /* State.HT */, 116 /* CharCode.t */, 4 /* State.HTT */],\n [3 /* State.HT */, 84 /* CharCode.T */, 4 /* State.HTT */],\n [4 /* State.HTT */, 112 /* CharCode.p */, 5 /* State.HTTP */],\n [4 /* State.HTT */, 80 /* CharCode.P */, 5 /* State.HTTP */],\n [5 /* State.HTTP */, 115 /* CharCode.s */, 9 /* State.BeforeColon */],\n [5 /* State.HTTP */, 83 /* CharCode.S */, 9 /* State.BeforeColon */],\n [5 /* State.HTTP */, 58 /* CharCode.Colon */, 10 /* State.AfterColon */],\n [6 /* State.F */, 105 /* CharCode.i */, 7 /* State.FI */],\n [6 /* State.F */, 73 /* CharCode.I */, 7 /* State.FI */],\n [7 /* State.FI */, 108 /* CharCode.l */, 8 /* State.FIL */],\n [7 /* State.FI */, 76 /* CharCode.L */, 8 /* State.FIL */],\n [8 /* State.FIL */, 101 /* CharCode.e */, 9 /* State.BeforeColon */],\n [8 /* State.FIL */, 69 /* CharCode.E */, 9 /* State.BeforeColon */],\n [9 /* State.BeforeColon */, 58 /* CharCode.Colon */, 10 /* State.AfterColon */],\n [10 /* State.AfterColon */, 47 /* CharCode.Slash */, 11 /* State.AlmostThere */],\n [11 /* State.AlmostThere */, 47 /* CharCode.Slash */, 12 /* State.End */],\n ]);\n }\n return _stateMachine;\n}\nlet _classifier = null;\nfunction getClassifier() {\n if (_classifier === null) {\n _classifier = new CharacterClassifier(0 /* CharacterClass.None */);\n // allow-any-unicode-next-line\n const FORCE_TERMINATION_CHARACTERS = ' \\t<>\\'\\\"、。。、,.:;‘〈「『〔([{「」}])〕』」〉’`~…';\n for (let i = 0; i < FORCE_TERMINATION_CHARACTERS.length; i++) {\n _classifier.set(FORCE_TERMINATION_CHARACTERS.charCodeAt(i), 1 /* CharacterClass.ForceTermination */);\n }\n const CANNOT_END_WITH_CHARACTERS = '.,;:';\n for (let i = 0; i < CANNOT_END_WITH_CHARACTERS.length; i++) {\n _classifier.set(CANNOT_END_WITH_CHARACTERS.charCodeAt(i), 2 /* CharacterClass.CannotEndIn */);\n }\n }\n return _classifier;\n}\nexport class LinkComputer {\n static _createLink(classifier, line, lineNumber, linkBeginIndex, linkEndIndex) {\n // Do not allow to end link in certain characters...\n let lastIncludedCharIndex = linkEndIndex - 1;\n do {\n const chCode = line.charCodeAt(lastIncludedCharIndex);\n const chClass = classifier.get(chCode);\n if (chClass !== 2 /* CharacterClass.CannotEndIn */) {\n break;\n }\n lastIncludedCharIndex--;\n } while (lastIncludedCharIndex > linkBeginIndex);\n // Handle links enclosed in parens, square brackets and curlys.\n if (linkBeginIndex > 0) {\n const charCodeBeforeLink = line.charCodeAt(linkBeginIndex - 1);\n const lastCharCodeInLink = line.charCodeAt(lastIncludedCharIndex);\n if ((charCodeBeforeLink === 40 /* CharCode.OpenParen */ && lastCharCodeInLink === 41 /* CharCode.CloseParen */)\n || (charCodeBeforeLink === 91 /* CharCode.OpenSquareBracket */ && lastCharCodeInLink === 93 /* CharCode.CloseSquareBracket */)\n || (charCodeBeforeLink === 123 /* CharCode.OpenCurlyBrace */ && lastCharCodeInLink === 125 /* CharCode.CloseCurlyBrace */)) {\n // Do not end in ) if ( is before the link start\n // Do not end in ] if [ is before the link start\n // Do not end in } if { is before the link start\n lastIncludedCharIndex--;\n }\n }\n return {\n range: {\n startLineNumber: lineNumber,\n startColumn: linkBeginIndex + 1,\n endLineNumber: lineNumber,\n endColumn: lastIncludedCharIndex + 2\n },\n url: line.substring(linkBeginIndex, lastIncludedCharIndex + 1)\n };\n }\n static computeLinks(model, stateMachine = getStateMachine()) {\n const classifier = getClassifier();\n const result = [];\n for (let i = 1, lineCount = model.getLineCount(); i <= lineCount; i++) {\n const line = model.getLineContent(i);\n const len = line.length;\n let j = 0;\n let linkBeginIndex = 0;\n let linkBeginChCode = 0;\n let state = 1 /* State.Start */;\n let hasOpenParens = false;\n let hasOpenSquareBracket = false;\n let inSquareBrackets = false;\n let hasOpenCurlyBracket = false;\n while (j < len) {\n let resetStateMachine = false;\n const chCode = line.charCodeAt(j);\n if (state === 13 /* State.Accept */) {\n let chClass;\n switch (chCode) {\n case 40 /* CharCode.OpenParen */:\n hasOpenParens = true;\n chClass = 0 /* CharacterClass.None */;\n break;\n case 41 /* CharCode.CloseParen */:\n chClass = (hasOpenParens ? 0 /* CharacterClass.None */ : 1 /* CharacterClass.ForceTermination */);\n break;\n case 91 /* CharCode.OpenSquareBracket */:\n inSquareBrackets = true;\n hasOpenSquareBracket = true;\n chClass = 0 /* CharacterClass.None */;\n break;\n case 93 /* CharCode.CloseSquareBracket */:\n inSquareBrackets = false;\n chClass = (hasOpenSquareBracket ? 0 /* CharacterClass.None */ : 1 /* CharacterClass.ForceTermination */);\n break;\n case 123 /* CharCode.OpenCurlyBrace */:\n hasOpenCurlyBracket = true;\n chClass = 0 /* CharacterClass.None */;\n break;\n case 125 /* CharCode.CloseCurlyBrace */:\n chClass = (hasOpenCurlyBracket ? 0 /* CharacterClass.None */ : 1 /* CharacterClass.ForceTermination */);\n break;\n /* The following three rules make it that ' or \" or ` are allowed inside links if the link didn't begin with them */\n case 39 /* CharCode.SingleQuote */:\n chClass = (linkBeginChCode === 39 /* CharCode.SingleQuote */ ? 1 /* CharacterClass.ForceTermination */ : 0 /* CharacterClass.None */);\n break;\n case 34 /* CharCode.DoubleQuote */:\n chClass = (linkBeginChCode === 34 /* CharCode.DoubleQuote */ ? 1 /* CharacterClass.ForceTermination */ : 0 /* CharacterClass.None */);\n break;\n case 96 /* CharCode.BackTick */:\n chClass = (linkBeginChCode === 96 /* CharCode.BackTick */ ? 1 /* CharacterClass.ForceTermination */ : 0 /* CharacterClass.None */);\n break;\n case 42 /* CharCode.Asterisk */:\n // `*` terminates a link if the link began with `*`\n chClass = (linkBeginChCode === 42 /* CharCode.Asterisk */) ? 1 /* CharacterClass.ForceTermination */ : 0 /* CharacterClass.None */;\n break;\n case 124 /* CharCode.Pipe */:\n // `|` terminates a link if the link began with `|`\n chClass = (linkBeginChCode === 124 /* CharCode.Pipe */) ? 1 /* CharacterClass.ForceTermination */ : 0 /* CharacterClass.None */;\n break;\n case 32 /* CharCode.Space */:\n // ` ` allow space in between [ and ]\n chClass = (inSquareBrackets ? 0 /* CharacterClass.None */ : 1 /* CharacterClass.ForceTermination */);\n break;\n default:\n chClass = classifier.get(chCode);\n }\n // Check if character terminates link\n if (chClass === 1 /* CharacterClass.ForceTermination */) {\n result.push(LinkComputer._createLink(classifier, line, i, linkBeginIndex, j));\n resetStateMachine = true;\n }\n }\n else if (state === 12 /* State.End */) {\n let chClass;\n if (chCode === 91 /* CharCode.OpenSquareBracket */) {\n // Allow for the authority part to contain ipv6 addresses which contain [ and ]\n hasOpenSquareBracket = true;\n chClass = 0 /* CharacterClass.None */;\n }\n else {\n chClass = classifier.get(chCode);\n }\n // Check if character terminates link\n if (chClass === 1 /* CharacterClass.ForceTermination */) {\n resetStateMachine = true;\n }\n else {\n state = 13 /* State.Accept */;\n }\n }\n else {\n state = stateMachine.nextState(state, chCode);\n if (state === 0 /* State.Invalid */) {\n resetStateMachine = true;\n }\n }\n if (resetStateMachine) {\n state = 1 /* State.Start */;\n hasOpenParens = false;\n hasOpenSquareBracket = false;\n hasOpenCurlyBracket = false;\n // Record where the link started\n linkBeginIndex = j + 1;\n linkBeginChCode = chCode;\n }\n j++;\n }\n if (state === 13 /* State.Accept */) {\n result.push(LinkComputer._createLink(classifier, line, i, linkBeginIndex, len));\n }\n }\n return result;\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) {\n if (!model || typeof model.getLineCount !== 'function' || typeof model.getLineContent !== 'function') {\n // Unknown caller!\n return [];\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nexport class BasicInplaceReplace {\n constructor() {\n this._defaultValueSet = [\n ['true', 'false'],\n ['True', 'False'],\n ['Private', 'Public', 'Friend', 'ReadOnly', 'Partial', 'Protected', 'WriteOnly'],\n ['public', 'protected', 'private'],\n ];\n }\n navigateValueSet(range1, text1, range2, text2, up) {\n if (range1 && text1) {\n const result = this.doNavigateValueSet(text1, up);\n if (result) {\n return {\n range: range1,\n value: result\n };\n }\n }\n if (range2 && text2) {\n const result = this.doNavigateValueSet(text2, up);\n if (result) {\n return {\n range: range2,\n value: result\n };\n }\n }\n return null;\n }\n doNavigateValueSet(text, up) {\n const numberResult = this.numberReplace(text, up);\n if (numberResult !== null) {\n return numberResult;\n }\n return this.textReplace(text, up);\n }\n numberReplace(value, up) {\n const precision = Math.pow(10, value.length - (value.lastIndexOf('.') + 1));\n let n1 = Number(value);\n const n2 = parseFloat(value);\n if (!isNaN(n1) && !isNaN(n2) && n1 === n2) {\n if (n1 === 0 && !up) {\n return null; // don't do negative\n //\t\t\t} else if(n1 === 9 && up) {\n //\t\t\t\treturn null; // don't insert 10 into a number\n }\n else {\n n1 = Math.floor(n1 * precision);\n n1 += up ? precision : -precision;\n return String(n1 / precision);\n }\n }\n return null;\n }\n textReplace(value, up) {\n return this.valueSetsReplace(this._defaultValueSet, value, up);\n }\n valueSetsReplace(valueSets, value, up) {\n let result = null;\n for (let i = 0, len = valueSets.length; result === null && i < len; i++) {\n result = this.valueSetReplace(valueSets[i], value, up);\n }\n return result;\n }\n valueSetReplace(valueSet, value, up) {\n let idx = valueSet.indexOf(value);\n if (idx >= 0) {\n idx += up ? +1 : -1;\n if (idx < 0) {\n idx = valueSet.length - 1;\n }\n else {\n idx %= valueSet.length;\n }\n return valueSet[idx];\n }\n return null;\n }\n}\nBasicInplaceReplace.INSTANCE = new BasicInplaceReplace();\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { stringDiff } from '../../../base/common/diff/diff.js';\nimport { globals } from '../../../base/common/platform.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { Position } from '../core/position.js';\nimport { Range } from '../core/range.js';\nimport { DiffComputer } from '../diff/diffComputer.js';\nimport { MirrorTextModel as BaseMirrorModel } from '../model/mirrorTextModel.js';\nimport { ensureValidWordDefinition, getWordAtText } from '../core/wordHelper.js';\nimport { computeLinks } from '../languages/linkComputer.js';\nimport { BasicInplaceReplace } from '../languages/supports/inplaceReplaceSupport.js';\nimport { createMonacoBaseAPI } from './editorBaseApi.js';\nimport * as types from '../../../base/common/types.js';\nimport { StopWatch } from '../../../base/common/stopwatch.js';\nimport { UnicodeTextModelHighlighter } from './unicodeTextModelHighlighter.js';\n/**\n * @internal\n */\nexport class MirrorModel extends BaseMirrorModel {\n get uri() {\n return this._uri;\n }\n get eol() {\n return this._eol;\n }\n getValue() {\n return this.getText();\n }\n getLinesContent() {\n return this._lines.slice(0);\n }\n getLineCount() {\n return this._lines.length;\n }\n getLineContent(lineNumber) {\n return this._lines[lineNumber - 1];\n }\n getWordAtPosition(position, wordDefinition) {\n const wordAtText = getWordAtText(position.column, ensureValidWordDefinition(wordDefinition), this._lines[position.lineNumber - 1], 0);\n if (wordAtText) {\n return new Range(position.lineNumber, wordAtText.startColumn, position.lineNumber, wordAtText.endColumn);\n }\n return null;\n }\n words(wordDefinition) {\n const lines = this._lines;\n const wordenize = this._wordenize.bind(this);\n let lineNumber = 0;\n let lineText = '';\n let wordRangesIdx = 0;\n let wordRanges = [];\n return {\n *[Symbol.iterator]() {\n while (true) {\n if (wordRangesIdx < wordRanges.length) {\n const value = lineText.substring(wordRanges[wordRangesIdx].start, wordRanges[wordRangesIdx].end);\n wordRangesIdx += 1;\n yield value;\n }\n else {\n if (lineNumber < lines.length) {\n lineText = lines[lineNumber];\n wordRanges = wordenize(lineText, wordDefinition);\n wordRangesIdx = 0;\n lineNumber += 1;\n }\n else {\n break;\n }\n }\n }\n }\n };\n }\n getLineWords(lineNumber, wordDefinition) {\n const content = this._lines[lineNumber - 1];\n const ranges = this._wordenize(content, wordDefinition);\n const words = [];\n for (const range of ranges) {\n words.push({\n word: content.substring(range.start, range.end),\n startColumn: range.start + 1,\n endColumn: range.end + 1\n });\n }\n return words;\n }\n _wordenize(content, wordDefinition) {\n const result = [];\n let match;\n wordDefinition.lastIndex = 0; // reset lastIndex just to be sure\n while (match = wordDefinition.exec(content)) {\n if (match[0].length === 0) {\n // it did match the empty string\n break;\n }\n result.push({ start: match.index, end: match.index + match[0].length });\n }\n return result;\n }\n getValueInRange(range) {\n range = this._validateRange(range);\n if (range.startLineNumber === range.endLineNumber) {\n return this._lines[range.startLineNumber - 1].substring(range.startColumn - 1, range.endColumn - 1);\n }\n const lineEnding = this._eol;\n const startLineIndex = range.startLineNumber - 1;\n const endLineIndex = range.endLineNumber - 1;\n const resultLines = [];\n resultLines.push(this._lines[startLineIndex].substring(range.startColumn - 1));\n for (let i = startLineIndex + 1; i < endLineIndex; i++) {\n resultLines.push(this._lines[i]);\n }\n resultLines.push(this._lines[endLineIndex].substring(0, range.endColumn - 1));\n return resultLines.join(lineEnding);\n }\n offsetAt(position) {\n position = this._validatePosition(position);\n this._ensureLineStarts();\n return this._lineStarts.getPrefixSum(position.lineNumber - 2) + (position.column - 1);\n }\n positionAt(offset) {\n offset = Math.floor(offset);\n offset = Math.max(0, offset);\n this._ensureLineStarts();\n const out = this._lineStarts.getIndexOf(offset);\n const lineLength = this._lines[out.index].length;\n // Ensure we return a valid position\n return {\n lineNumber: 1 + out.index,\n column: 1 + Math.min(out.remainder, lineLength)\n };\n }\n _validateRange(range) {\n const start = this._validatePosition({ lineNumber: range.startLineNumber, column: range.startColumn });\n const end = this._validatePosition({ lineNumber: range.endLineNumber, column: range.endColumn });\n if (start.lineNumber !== range.startLineNumber\n || start.column !== range.startColumn\n || end.lineNumber !== range.endLineNumber\n || end.column !== range.endColumn) {\n return {\n startLineNumber: start.lineNumber,\n startColumn: start.column,\n endLineNumber: end.lineNumber,\n endColumn: end.column\n };\n }\n return range;\n }\n _validatePosition(position) {\n if (!Position.isIPosition(position)) {\n throw new Error('bad position');\n }\n let { lineNumber, column } = position;\n let hasChanged = false;\n if (lineNumber < 1) {\n lineNumber = 1;\n column = 1;\n hasChanged = true;\n }\n else if (lineNumber > this._lines.length) {\n lineNumber = this._lines.length;\n column = this._lines[lineNumber - 1].length + 1;\n hasChanged = true;\n }\n else {\n const maxCharacter = this._lines[lineNumber - 1].length + 1;\n if (column < 1) {\n column = 1;\n hasChanged = true;\n }\n else if (column > maxCharacter) {\n column = maxCharacter;\n hasChanged = true;\n }\n }\n if (!hasChanged) {\n return position;\n }\n else {\n return { lineNumber, column };\n }\n }\n}\n/**\n * @internal\n */\nexport class EditorSimpleWorker {\n constructor(host, foreignModuleFactory) {\n this._host = host;\n this._models = Object.create(null);\n this._foreignModuleFactory = foreignModuleFactory;\n this._foreignModule = null;\n }\n dispose() {\n this._models = Object.create(null);\n }\n _getModel(uri) {\n return this._models[uri];\n }\n _getModels() {\n const all = [];\n Object.keys(this._models).forEach((key) => all.push(this._models[key]));\n return all;\n }\n acceptNewModel(data) {\n this._models[data.url] = new MirrorModel(URI.parse(data.url), data.lines, data.EOL, data.versionId);\n }\n acceptModelChanged(strURL, e) {\n if (!this._models[strURL]) {\n return;\n }\n const model = this._models[strURL];\n model.onEvents(e);\n }\n acceptRemovedModel(strURL) {\n if (!this._models[strURL]) {\n return;\n }\n delete this._models[strURL];\n }\n computeUnicodeHighlights(url, options, range) {\n return __awaiter(this, void 0, void 0, function* () {\n const model = this._getModel(url);\n if (!model) {\n return { ranges: [], hasMore: false, ambiguousCharacterCount: 0, invisibleCharacterCount: 0, nonBasicAsciiCharacterCount: 0 };\n }\n return UnicodeTextModelHighlighter.computeUnicodeHighlights(model, options, range);\n });\n }\n // ---- BEGIN diff --------------------------------------------------------------------------\n computeDiff(originalUrl, modifiedUrl, ignoreTrimWhitespace, maxComputationTime) {\n return __awaiter(this, void 0, void 0, function* () {\n const original = this._getModel(originalUrl);\n const modified = this._getModel(modifiedUrl);\n if (!original || !modified) {\n return null;\n }\n return EditorSimpleWorker.computeDiff(original, modified, ignoreTrimWhitespace, maxComputationTime);\n });\n }\n static computeDiff(originalTextModel, modifiedTextModel, ignoreTrimWhitespace, maxComputationTime) {\n const originalLines = originalTextModel.getLinesContent();\n const modifiedLines = modifiedTextModel.getLinesContent();\n const diffComputer = new DiffComputer(originalLines, modifiedLines, {\n shouldComputeCharChanges: true,\n shouldPostProcessCharChanges: true,\n shouldIgnoreTrimWhitespace: ignoreTrimWhitespace,\n shouldMakePrettyDiff: true,\n maxComputationTime: maxComputationTime\n });\n const diffResult = diffComputer.computeDiff();\n const identical = (diffResult.changes.length > 0 ? false : this._modelsAreIdentical(originalTextModel, modifiedTextModel));\n return {\n quitEarly: diffResult.quitEarly,\n identical: identical,\n changes: diffResult.changes\n };\n }\n static _modelsAreIdentical(original, modified) {\n const originalLineCount = original.getLineCount();\n const modifiedLineCount = modified.getLineCount();\n if (originalLineCount !== modifiedLineCount) {\n return false;\n }\n for (let line = 1; line <= originalLineCount; line++) {\n const originalLine = original.getLineContent(line);\n const modifiedLine = modified.getLineContent(line);\n if (originalLine !== modifiedLine) {\n return false;\n }\n }\n return true;\n }\n computeMoreMinimalEdits(modelUrl, edits) {\n return __awaiter(this, void 0, void 0, function* () {\n const model = this._getModel(modelUrl);\n if (!model) {\n return edits;\n }\n const result = [];\n let lastEol = undefined;\n edits = edits.slice(0).sort((a, b) => {\n if (a.range && b.range) {\n return Range.compareRangesUsingStarts(a.range, b.range);\n }\n // eol only changes should go to the end\n const aRng = a.range ? 0 : 1;\n const bRng = b.range ? 0 : 1;\n return aRng - bRng;\n });\n for (let { range, text, eol } of edits) {\n if (typeof eol === 'number') {\n lastEol = eol;\n }\n if (Range.isEmpty(range) && !text) {\n // empty change\n continue;\n }\n const original = model.getValueInRange(range);\n text = text.replace(/\\r\\n|\\n|\\r/g, model.eol);\n if (original === text) {\n // noop\n continue;\n }\n // make sure diff won't take too long\n if (Math.max(text.length, original.length) > EditorSimpleWorker._diffLimit) {\n result.push({ range, text });\n continue;\n }\n // compute diff between original and edit.text\n const changes = stringDiff(original, text, false);\n const editOffset = model.offsetAt(Range.lift(range).getStartPosition());\n for (const change of changes) {\n const start = model.positionAt(editOffset + change.originalStart);\n const end = model.positionAt(editOffset + change.originalStart + change.originalLength);\n const newEdit = {\n text: text.substr(change.modifiedStart, change.modifiedLength),\n range: { startLineNumber: start.lineNumber, startColumn: start.column, endLineNumber: end.lineNumber, endColumn: end.column }\n };\n if (model.getValueInRange(newEdit.range) !== newEdit.text) {\n result.push(newEdit);\n }\n }\n }\n if (typeof lastEol === 'number') {\n result.push({ eol: lastEol, text: '', range: { startLineNumber: 0, startColumn: 0, endLineNumber: 0, endColumn: 0 } });\n }\n return result;\n });\n }\n // ---- END minimal edits ---------------------------------------------------------------\n computeLinks(modelUrl) {\n return __awaiter(this, void 0, void 0, function* () {\n const model = this._getModel(modelUrl);\n if (!model) {\n return null;\n }\n return computeLinks(model);\n });\n }\n textualSuggest(modelUrls, leadingWord, wordDef, wordDefFlags) {\n return __awaiter(this, void 0, void 0, function* () {\n const sw = new StopWatch(true);\n const wordDefRegExp = new RegExp(wordDef, wordDefFlags);\n const seen = new Set();\n outer: for (const url of modelUrls) {\n const model = this._getModel(url);\n if (!model) {\n continue;\n }\n for (const word of model.words(wordDefRegExp)) {\n if (word === leadingWord || !isNaN(Number(word))) {\n continue;\n }\n seen.add(word);\n if (seen.size > EditorSimpleWorker._suggestionsLimit) {\n break outer;\n }\n }\n }\n return { words: Array.from(seen), duration: sw.elapsed() };\n });\n }\n // ---- END suggest --------------------------------------------------------------------------\n //#region -- word ranges --\n computeWordRanges(modelUrl, range, wordDef, wordDefFlags) {\n return __awaiter(this, void 0, void 0, function* () {\n const model = this._getModel(modelUrl);\n if (!model) {\n return Object.create(null);\n }\n const wordDefRegExp = new RegExp(wordDef, wordDefFlags);\n const result = Object.create(null);\n for (let line = range.startLineNumber; line < range.endLineNumber; line++) {\n const words = model.getLineWords(line, wordDefRegExp);\n for (const word of words) {\n if (!isNaN(Number(word.word))) {\n continue;\n }\n let array = result[word.word];\n if (!array) {\n array = [];\n result[word.word] = array;\n }\n array.push({\n startLineNumber: line,\n startColumn: word.startColumn,\n endLineNumber: line,\n endColumn: word.endColumn\n });\n }\n }\n return result;\n });\n }\n //#endregion\n navigateValueSet(modelUrl, range, up, wordDef, wordDefFlags) {\n return __awaiter(this, void 0, void 0, function* () {\n const model = this._getModel(modelUrl);\n if (!model) {\n return null;\n }\n const wordDefRegExp = new RegExp(wordDef, wordDefFlags);\n if (range.startColumn === range.endColumn) {\n range = {\n startLineNumber: range.startLineNumber,\n startColumn: range.startColumn,\n endLineNumber: range.endLineNumber,\n endColumn: range.endColumn + 1\n };\n }\n const selectionText = model.getValueInRange(range);\n const wordRange = model.getWordAtPosition({ lineNumber: range.startLineNumber, column: range.startColumn }, wordDefRegExp);\n if (!wordRange) {\n return null;\n }\n const word = model.getValueInRange(wordRange);\n const result = BasicInplaceReplace.INSTANCE.navigateValueSet(range, selectionText, wordRange, word, up);\n return result;\n });\n }\n // ---- BEGIN foreign module support --------------------------------------------------------------------------\n loadForeignModule(moduleId, createData, foreignHostMethods) {\n const proxyMethodRequest = (method, args) => {\n return this._host.fhr(method, args);\n };\n const foreignHost = types.createProxyObject(foreignHostMethods, proxyMethodRequest);\n const ctx = {\n host: foreignHost,\n getMirrorModels: () => {\n return this._getModels();\n }\n };\n if (this._foreignModuleFactory) {\n this._foreignModule = this._foreignModuleFactory(ctx, createData);\n // static foreing module\n return Promise.resolve(types.getAllMethodNames(this._foreignModule));\n }\n // 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 // ESM-comment-end\n // ESM-uncomment-begin\n return Promise.reject(new Error(`Unexpected usage`));\n // ESM-uncomment-end\n }\n // foreign method request\n fmr(method, args) {\n if (!this._foreignModule || typeof this._foreignModule[method] !== 'function') {\n return Promise.reject(new Error('Missing requestHandler or method: ' + method));\n }\n try {\n return Promise.resolve(this._foreignModule[method].apply(this._foreignModule, args));\n }\n catch (e) {\n return Promise.reject(e);\n }\n }\n}\n// ---- END diff --------------------------------------------------------------------------\n// ---- BEGIN minimal edits ---------------------------------------------------------------\nEditorSimpleWorker._diffLimit = 100000;\n// ---- BEGIN suggest --------------------------------------------------------------------------\nEditorSimpleWorker._suggestionsLimit = 10000;\n/**\n * Called on the worker side\n * @internal\n */\nexport function create(host) {\n return new EditorSimpleWorker(host, null);\n}\nif (typeof importScripts === 'function') {\n // Running in a web worker\n globals.monaco = createMonacoBaseAPI();\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { IntervalTimer, timeout } from '../../../base/common/async.js';\nimport { Disposable, dispose, toDisposable, DisposableStore } from '../../../base/common/lifecycle.js';\nimport { SimpleWorkerClient, logOnceWebWorkerWarning } from '../../../base/common/worker/simpleWorker.js';\nimport { DefaultWorkerFactory } from '../../../base/browser/defaultWorkerFactory.js';\nimport { Range } from '../../common/core/range.js';\nimport { ILanguageConfigurationService } from '../../common/languages/languageConfigurationRegistry.js';\nimport { EditorSimpleWorker } from '../../common/services/editorSimpleWorker.js';\nimport { IModelService } from '../../common/services/model.js';\nimport { ITextResourceConfigurationService } from '../../common/services/textResourceConfiguration.js';\nimport { regExpFlags } from '../../../base/common/strings.js';\nimport { isNonEmptyArray } from '../../../base/common/arrays.js';\nimport { ILogService } from '../../../platform/log/common/log.js';\nimport { StopWatch } from '../../../base/common/stopwatch.js';\nimport { canceled } from '../../../base/common/errors.js';\nimport { ILanguageFeaturesService } from '../../common/services/languageFeatures.js';\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 * Stop the worker if it was not needed for 5 min.\n */\nconst STOP_WORKER_DELTA_TIME_MS = 5 * 60 * 1000;\nfunction canSyncModel(modelService, resource) {\n const model = modelService.getModel(resource);\n if (!model) {\n return false;\n }\n if (model.isTooLargeForSyncing()) {\n return false;\n }\n return true;\n}\nlet EditorWorkerService = class EditorWorkerService extends Disposable {\n constructor(modelService, configurationService, logService, languageConfigurationService, languageFeaturesService) {\n super();\n this._modelService = modelService;\n this._workerManager = this._register(new WorkerManager(this._modelService, languageConfigurationService));\n this._logService = logService;\n // register default link-provider and default completions-provider\n this._register(languageFeaturesService.linkProvider.register({ language: '*', hasAccessToAllModels: true }, {\n provideLinks: (model, token) => {\n if (!canSyncModel(this._modelService, model.uri)) {\n return Promise.resolve({ links: [] }); // File too large\n }\n return this._workerManager.withWorker().then(client => client.computeLinks(model.uri)).then(links => {\n return links && { links };\n });\n }\n }));\n this._register(languageFeaturesService.completionProvider.register('*', new WordBasedCompletionItemProvider(this._workerManager, configurationService, this._modelService, languageConfigurationService)));\n }\n dispose() {\n super.dispose();\n }\n canComputeUnicodeHighlights(uri) {\n return canSyncModel(this._modelService, uri);\n }\n computedUnicodeHighlights(uri, options, range) {\n return this._workerManager.withWorker().then(client => client.computedUnicodeHighlights(uri, options, range));\n }\n computeDiff(original, modified, ignoreTrimWhitespace, maxComputationTime) {\n return this._workerManager.withWorker().then(client => client.computeDiff(original, modified, ignoreTrimWhitespace, maxComputationTime));\n }\n computeMoreMinimalEdits(resource, edits) {\n if (isNonEmptyArray(edits)) {\n if (!canSyncModel(this._modelService, resource)) {\n return Promise.resolve(edits); // File too large\n }\n const sw = StopWatch.create(true);\n const result = this._workerManager.withWorker().then(client => client.computeMoreMinimalEdits(resource, edits));\n result.finally(() => this._logService.trace('FORMAT#computeMoreMinimalEdits', resource.toString(true), sw.elapsed()));\n return Promise.race([result, timeout(1000).then(() => edits)]);\n }\n else {\n return Promise.resolve(undefined);\n }\n }\n canNavigateValueSet(resource) {\n return (canSyncModel(this._modelService, resource));\n }\n navigateValueSet(resource, range, up) {\n return this._workerManager.withWorker().then(client => client.navigateValueSet(resource, range, up));\n }\n canComputeWordRanges(resource) {\n return canSyncModel(this._modelService, resource);\n }\n computeWordRanges(resource, range) {\n return this._workerManager.withWorker().then(client => client.computeWordRanges(resource, range));\n }\n};\nEditorWorkerService = __decorate([\n __param(0, IModelService),\n __param(1, ITextResourceConfigurationService),\n __param(2, ILogService),\n __param(3, ILanguageConfigurationService),\n __param(4, ILanguageFeaturesService)\n], EditorWorkerService);\nexport { EditorWorkerService };\nclass WordBasedCompletionItemProvider {\n constructor(workerManager, configurationService, modelService, languageConfigurationService) {\n this.languageConfigurationService = languageConfigurationService;\n this._debugDisplayName = 'wordbasedCompletions';\n this._workerManager = workerManager;\n this._configurationService = configurationService;\n this._modelService = modelService;\n }\n provideCompletionItems(model, position) {\n return __awaiter(this, void 0, void 0, function* () {\n const config = this._configurationService.getValue(model.uri, position, 'editor');\n if (!config.wordBasedSuggestions) {\n return undefined;\n }\n const models = [];\n if (config.wordBasedSuggestionsMode === 'currentDocument') {\n // only current file and only if not too large\n if (canSyncModel(this._modelService, model.uri)) {\n models.push(model.uri);\n }\n }\n else {\n // either all files or files of same language\n for (const candidate of this._modelService.getModels()) {\n if (!canSyncModel(this._modelService, candidate.uri)) {\n continue;\n }\n if (candidate === model) {\n models.unshift(candidate.uri);\n }\n else if (config.wordBasedSuggestionsMode === 'allDocuments' || candidate.getLanguageId() === model.getLanguageId()) {\n models.push(candidate.uri);\n }\n }\n }\n if (models.length === 0) {\n return undefined; // File too large, no other files\n }\n const wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition();\n const word = model.getWordAtPosition(position);\n const replace = !word ? Range.fromPositions(position) : new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn);\n const insert = replace.setEndPosition(position.lineNumber, position.column);\n const client = yield this._workerManager.withWorker();\n const data = yield client.textualSuggest(models, word === null || word === void 0 ? void 0 : word.word, wordDefRegExp);\n if (!data) {\n return undefined;\n }\n return {\n duration: data.duration,\n suggestions: data.words.map((word) => {\n return {\n kind: 18 /* languages.CompletionItemKind.Text */,\n label: word,\n insertText: word,\n range: { insert, replace }\n };\n }),\n };\n });\n }\n}\nclass WorkerManager extends Disposable {\n constructor(modelService, languageConfigurationService) {\n super();\n this.languageConfigurationService = languageConfigurationService;\n this._modelService = modelService;\n this._editorWorkerClient = null;\n this._lastWorkerUsedTime = (new Date()).getTime();\n const stopWorkerInterval = this._register(new IntervalTimer());\n stopWorkerInterval.cancelAndSet(() => this._checkStopIdleWorker(), Math.round(STOP_WORKER_DELTA_TIME_MS / 2));\n this._register(this._modelService.onModelRemoved(_ => this._checkStopEmptyWorker()));\n }\n dispose() {\n if (this._editorWorkerClient) {\n this._editorWorkerClient.dispose();\n this._editorWorkerClient = null;\n }\n super.dispose();\n }\n /**\n * Check if the model service has no more models and stop the worker if that is the case.\n */\n _checkStopEmptyWorker() {\n if (!this._editorWorkerClient) {\n return;\n }\n const models = this._modelService.getModels();\n if (models.length === 0) {\n // There are no more models => nothing possible for me to do\n this._editorWorkerClient.dispose();\n this._editorWorkerClient = null;\n }\n }\n /**\n * Check if the worker has been idle for a while and then stop it.\n */\n _checkStopIdleWorker() {\n if (!this._editorWorkerClient) {\n return;\n }\n const timeSinceLastWorkerUsedTime = (new Date()).getTime() - this._lastWorkerUsedTime;\n if (timeSinceLastWorkerUsedTime > STOP_WORKER_DELTA_TIME_MS) {\n this._editorWorkerClient.dispose();\n this._editorWorkerClient = null;\n }\n }\n withWorker() {\n this._lastWorkerUsedTime = (new Date()).getTime();\n if (!this._editorWorkerClient) {\n this._editorWorkerClient = new EditorWorkerClient(this._modelService, false, 'editorWorkerService', this.languageConfigurationService);\n }\n return Promise.resolve(this._editorWorkerClient);\n }\n}\nclass EditorModelManager extends Disposable {\n constructor(proxy, modelService, keepIdleModels) {\n super();\n this._syncedModels = Object.create(null);\n this._syncedModelsLastUsedTime = Object.create(null);\n this._proxy = proxy;\n this._modelService = modelService;\n if (!keepIdleModels) {\n const timer = new IntervalTimer();\n timer.cancelAndSet(() => this._checkStopModelSync(), Math.round(STOP_SYNC_MODEL_DELTA_TIME_MS / 2));\n this._register(timer);\n }\n }\n dispose() {\n for (const modelUrl in this._syncedModels) {\n dispose(this._syncedModels[modelUrl]);\n }\n this._syncedModels = Object.create(null);\n this._syncedModelsLastUsedTime = Object.create(null);\n super.dispose();\n }\n ensureSyncedResources(resources, forceLargeModels) {\n for (const resource of resources) {\n const resourceStr = resource.toString();\n if (!this._syncedModels[resourceStr]) {\n this._beginModelSync(resource, forceLargeModels);\n }\n if (this._syncedModels[resourceStr]) {\n this._syncedModelsLastUsedTime[resourceStr] = (new Date()).getTime();\n }\n }\n }\n _checkStopModelSync() {\n const currentTime = (new Date()).getTime();\n const toRemove = [];\n for (const modelUrl in this._syncedModelsLastUsedTime) {\n const elapsedTime = currentTime - this._syncedModelsLastUsedTime[modelUrl];\n if (elapsedTime > STOP_SYNC_MODEL_DELTA_TIME_MS) {\n toRemove.push(modelUrl);\n }\n }\n for (const e of toRemove) {\n this._stopModelSync(e);\n }\n }\n _beginModelSync(resource, forceLargeModels) {\n const model = this._modelService.getModel(resource);\n if (!model) {\n return;\n }\n if (!forceLargeModels && model.isTooLargeForSyncing()) {\n return;\n }\n const modelUrl = resource.toString();\n this._proxy.acceptNewModel({\n url: model.uri.toString(),\n lines: model.getLinesContent(),\n EOL: model.getEOL(),\n versionId: model.getVersionId()\n });\n const toDispose = new DisposableStore();\n toDispose.add(model.onDidChangeContent((e) => {\n this._proxy.acceptModelChanged(modelUrl.toString(), e);\n }));\n toDispose.add(model.onWillDispose(() => {\n this._stopModelSync(modelUrl);\n }));\n toDispose.add(toDisposable(() => {\n this._proxy.acceptRemovedModel(modelUrl);\n }));\n this._syncedModels[modelUrl] = toDispose;\n }\n _stopModelSync(modelUrl) {\n const toDispose = this._syncedModels[modelUrl];\n delete this._syncedModels[modelUrl];\n delete this._syncedModelsLastUsedTime[modelUrl];\n dispose(toDispose);\n }\n}\nclass SynchronousWorkerClient {\n constructor(instance) {\n this._instance = instance;\n this._proxyObj = Promise.resolve(this._instance);\n }\n dispose() {\n this._instance.dispose();\n }\n getProxyObject() {\n return this._proxyObj;\n }\n}\nexport class EditorWorkerHost {\n constructor(workerClient) {\n this._workerClient = workerClient;\n }\n // foreign host request\n fhr(method, args) {\n return this._workerClient.fhr(method, args);\n }\n}\nexport class EditorWorkerClient extends Disposable {\n constructor(modelService, keepIdleModels, label, languageConfigurationService) {\n super();\n this.languageConfigurationService = languageConfigurationService;\n this._disposed = false;\n this._modelService = modelService;\n this._keepIdleModels = keepIdleModels;\n this._workerFactory = new DefaultWorkerFactory(label);\n this._worker = null;\n this._modelManager = null;\n }\n // foreign host request\n fhr(method, args) {\n throw new Error(`Not implemented!`);\n }\n _getOrCreateWorker() {\n if (!this._worker) {\n try {\n this._worker = this._register(new SimpleWorkerClient(this._workerFactory, 'vs/editor/common/services/editorSimpleWorker', new EditorWorkerHost(this)));\n }\n catch (err) {\n logOnceWebWorkerWarning(err);\n this._worker = new SynchronousWorkerClient(new EditorSimpleWorker(new EditorWorkerHost(this), null));\n }\n }\n return this._worker;\n }\n _getProxy() {\n return this._getOrCreateWorker().getProxyObject().then(undefined, (err) => {\n logOnceWebWorkerWarning(err);\n this._worker = new SynchronousWorkerClient(new EditorSimpleWorker(new EditorWorkerHost(this), null));\n return this._getOrCreateWorker().getProxyObject();\n });\n }\n _getOrCreateModelManager(proxy) {\n if (!this._modelManager) {\n this._modelManager = this._register(new EditorModelManager(proxy, this._modelService, this._keepIdleModels));\n }\n return this._modelManager;\n }\n _withSyncedResources(resources, forceLargeModels = false) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this._disposed) {\n return Promise.reject(canceled());\n }\n return this._getProxy().then((proxy) => {\n this._getOrCreateModelManager(proxy).ensureSyncedResources(resources, forceLargeModels);\n return proxy;\n });\n });\n }\n computedUnicodeHighlights(uri, options, range) {\n return this._withSyncedResources([uri]).then(proxy => {\n return proxy.computeUnicodeHighlights(uri.toString(), options, range);\n });\n }\n computeDiff(original, modified, ignoreTrimWhitespace, maxComputationTime) {\n return this._withSyncedResources([original, modified], /* forceLargeModels */ true).then(proxy => {\n return proxy.computeDiff(original.toString(), modified.toString(), ignoreTrimWhitespace, maxComputationTime);\n });\n }\n computeMoreMinimalEdits(resource, edits) {\n return this._withSyncedResources([resource]).then(proxy => {\n return proxy.computeMoreMinimalEdits(resource.toString(), edits);\n });\n }\n computeLinks(resource) {\n return this._withSyncedResources([resource]).then(proxy => {\n return proxy.computeLinks(resource.toString());\n });\n }\n textualSuggest(resources, leadingWord, wordDefRegExp) {\n return __awaiter(this, void 0, void 0, function* () {\n const proxy = yield this._withSyncedResources(resources);\n const wordDef = wordDefRegExp.source;\n const wordDefFlags = regExpFlags(wordDefRegExp);\n return proxy.textualSuggest(resources.map(r => r.toString()), leadingWord, wordDef, wordDefFlags);\n });\n }\n computeWordRanges(resource, range) {\n return this._withSyncedResources([resource]).then(proxy => {\n const model = this._modelService.getModel(resource);\n if (!model) {\n return Promise.resolve(null);\n }\n const wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition();\n const wordDef = wordDefRegExp.source;\n const wordDefFlags = regExpFlags(wordDefRegExp);\n return proxy.computeWordRanges(resource.toString(), range, wordDef, wordDefFlags);\n });\n }\n navigateValueSet(resource, range, up) {\n return this._withSyncedResources([resource]).then(proxy => {\n const model = this._modelService.getModel(resource);\n if (!model) {\n return null;\n }\n const wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition();\n const wordDef = wordDefRegExp.source;\n const wordDefFlags = regExpFlags(wordDefRegExp);\n return proxy.navigateValueSet(resource.toString(), range, up, wordDef, wordDefFlags);\n });\n }\n dispose() {\n super.dispose();\n this._disposed = true;\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 *--------------------------------------------------------------------------------------------*/\nimport { EditorWorkerClient } from './editorWorkerService.js';\nimport * as types from '../../../base/common/types.js';\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, languageConfigurationService, opts) {\n return new MonacoWebWorkerImpl(modelService, languageConfigurationService, opts);\n}\nclass MonacoWebWorkerImpl extends EditorWorkerClient {\n constructor(modelService, languageConfigurationService, opts) {\n super(modelService, opts.keepIdleModels || false, opts.label, languageConfigurationService);\n this._foreignModuleId = opts.moduleId;\n this._foreignModuleCreateData = opts.createData || null;\n this._foreignModuleHost = opts.host || null;\n this._foreignProxy = null;\n }\n // foreign host request\n fhr(method, args) {\n if (!this._foreignModuleHost || typeof this._foreignModuleHost[method] !== 'function') {\n return Promise.reject(new Error('Missing method ' + method + ' or missing main thread foreign host.'));\n }\n try {\n return Promise.resolve(this._foreignModuleHost[method].apply(this._foreignModuleHost, args));\n }\n catch (e) {\n return Promise.reject(e);\n }\n }\n _getForeignProxy() {\n if (!this._foreignProxy) {\n this._foreignProxy = this._getProxy().then((proxy) => {\n const foreignHostMethods = this._foreignModuleHost ? types.getAllMethodNames(this._foreignModuleHost) : [];\n return proxy.loadForeignModule(this._foreignModuleId, this._foreignModuleCreateData, foreignHostMethods).then((foreignMethods) => {\n this._foreignModuleCreateData = null;\n const proxyMethodRequest = (method, args) => {\n return proxy.fmr(method, args);\n };\n const createProxyMethod = (method, proxyMethodRequest) => {\n return function () {\n const args = Array.prototype.slice.call(arguments, 0);\n return proxyMethodRequest(method, args);\n };\n };\n const foreignProxy = {};\n for (const foreignMethod of foreignMethods) {\n foreignProxy[foreignMethod] = createProxyMethod(foreignMethod, proxyMethodRequest);\n }\n return foreignProxy;\n });\n });\n }\n return this._foreignProxy;\n }\n getProxy() {\n return this._getForeignProxy();\n }\n withSyncedResources(resources) {\n return this._withSyncedResources(resources).then(_ => this.getProxy());\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 *--------------------------------------------------------------------------------------------*/\nexport function isFuzzyActionArr(what) {\n return (Array.isArray(what));\n}\nexport function isFuzzyAction(what) {\n return !isFuzzyActionArr(what);\n}\nexport function isString(what) {\n return (typeof what === 'string');\n}\nexport function isIAction(what) {\n return !isString(what);\n}\n// Small helper functions\n/**\n * Is a string null, undefined, or empty?\n */\nexport function empty(s) {\n return (s ? false : true);\n}\n/**\n * Puts a string to lower case if 'ignoreCase' is set.\n */\nexport function fixCase(lexer, str) {\n return (lexer.ignoreCase && str ? str.toLowerCase() : str);\n}\n/**\n * Ensures there are no bad characters in a CSS token class.\n */\nexport function sanitize(s) {\n return s.replace(/[&<>'\"_]/g, '-'); // used on all output token CSS classes\n}\n// Logging\n/**\n * Logs a message.\n */\nexport function log(lexer, msg) {\n console.log(`${lexer.languageId}: ${msg}`);\n}\n// Throwing errors\nexport function createError(lexer, msg) {\n return new Error(`${lexer.languageId}: ${msg}`);\n}\n// Helper functions for rule finding and substitution\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, str, id, matches, state) {\n const re = /\\$((\\$)|(#)|(\\d\\d?)|[sS](\\d\\d?)|@(\\w+))/g;\n let stateMatches = null;\n return str.replace(re, function (full, sub, dollar, hash, n, s, attr, ofs, total) {\n if (!empty(dollar)) {\n return '$'; // $$\n }\n if (!empty(hash)) {\n return fixCase(lexer, id); // default $#\n }\n if (!empty(n) && n < matches.length) {\n return fixCase(lexer, matches[n]); // $n\n }\n if (!empty(attr) && lexer && typeof (lexer[attr]) === 'string') {\n return lexer[attr]; //@attribute\n }\n if (stateMatches === null) { // split state on demand\n stateMatches = state.split('.');\n stateMatches.unshift(state);\n }\n if (!empty(s) && s < stateMatches.length) {\n return fixCase(lexer, stateMatches[s]); //$Sn\n }\n return '';\n });\n}\n/**\n * Find the tokenizer rules for a specific state (i.e. next action)\n */\nexport function findRules(lexer, inState) {\n let state = inState;\n while (state && state.length > 0) {\n const rules = lexer.tokenizer[state];\n if (rules) {\n return rules;\n }\n const idx = state.lastIndexOf('.');\n if (idx < 0) {\n state = null; // no further parent\n }\n else {\n state = state.substr(0, idx);\n }\n }\n return null;\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, inState) {\n let state = inState;\n while (state && state.length > 0) {\n const exist = lexer.stateNames[state];\n if (exist) {\n return true;\n }\n const idx = state.lastIndexOf('.');\n if (idx < 0) {\n state = null; // no further parent\n }\n else {\n state = state.substr(0, idx);\n }\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport * as languages from '../../../common/languages.js';\nimport { NullState, nullTokenizeEncoded, nullTokenize } from '../../../common/languages/nullTokenize.js';\nimport * as monarchCommon from './monarchCommon.js';\nimport { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';\nconst CACHE_STACK_DEPTH = 5;\n/**\n * Reuse the same stack elements up to a certain depth.\n */\nclass MonarchStackElementFactory {\n constructor(maxCacheDepth) {\n this._maxCacheDepth = maxCacheDepth;\n this._entries = Object.create(null);\n }\n static create(parent, state) {\n return this._INSTANCE.create(parent, state);\n }\n create(parent, state) {\n if (parent !== null && parent.depth >= this._maxCacheDepth) {\n // no caching above a certain depth\n return new MonarchStackElement(parent, state);\n }\n let stackElementId = MonarchStackElement.getStackElementId(parent);\n if (stackElementId.length > 0) {\n stackElementId += '|';\n }\n stackElementId += state;\n let result = this._entries[stackElementId];\n if (result) {\n return result;\n }\n result = new MonarchStackElement(parent, state);\n this._entries[stackElementId] = result;\n return result;\n }\n}\nMonarchStackElementFactory._INSTANCE = new MonarchStackElementFactory(CACHE_STACK_DEPTH);\nclass MonarchStackElement {\n constructor(parent, state) {\n this.parent = parent;\n this.state = state;\n this.depth = (this.parent ? this.parent.depth : 0) + 1;\n }\n static getStackElementId(element) {\n let result = '';\n while (element !== null) {\n if (result.length > 0) {\n result += '|';\n }\n result += element.state;\n element = element.parent;\n }\n return result;\n }\n static _equals(a, b) {\n while (a !== null && b !== null) {\n if (a === b) {\n return true;\n }\n if (a.state !== b.state) {\n return false;\n }\n a = a.parent;\n b = b.parent;\n }\n if (a === null && b === null) {\n return true;\n }\n return false;\n }\n equals(other) {\n return MonarchStackElement._equals(this, other);\n }\n push(state) {\n return MonarchStackElementFactory.create(this, state);\n }\n pop() {\n return this.parent;\n }\n popall() {\n let result = this;\n while (result.parent) {\n result = result.parent;\n }\n return result;\n }\n switchTo(state) {\n return MonarchStackElementFactory.create(this.parent, state);\n }\n}\nclass EmbeddedLanguageData {\n constructor(languageId, state) {\n this.languageId = languageId;\n this.state = state;\n }\n equals(other) {\n return (this.languageId === other.languageId\n && this.state.equals(other.state));\n }\n clone() {\n const stateClone = this.state.clone();\n // save an object\n if (stateClone === this.state) {\n return this;\n }\n return new EmbeddedLanguageData(this.languageId, this.state);\n }\n}\n/**\n * Reuse the same line states up to a certain depth.\n */\nclass MonarchLineStateFactory {\n constructor(maxCacheDepth) {\n this._maxCacheDepth = maxCacheDepth;\n this._entries = Object.create(null);\n }\n static create(stack, embeddedLanguageData) {\n return this._INSTANCE.create(stack, embeddedLanguageData);\n }\n create(stack, embeddedLanguageData) {\n if (embeddedLanguageData !== null) {\n // no caching when embedding\n return new MonarchLineState(stack, embeddedLanguageData);\n }\n if (stack !== null && stack.depth >= this._maxCacheDepth) {\n // no caching above a certain depth\n return new MonarchLineState(stack, embeddedLanguageData);\n }\n const stackElementId = MonarchStackElement.getStackElementId(stack);\n let result = this._entries[stackElementId];\n if (result) {\n return result;\n }\n result = new MonarchLineState(stack, null);\n this._entries[stackElementId] = result;\n return result;\n }\n}\nMonarchLineStateFactory._INSTANCE = new MonarchLineStateFactory(CACHE_STACK_DEPTH);\nclass MonarchLineState {\n constructor(stack, embeddedLanguageData) {\n this.stack = stack;\n this.embeddedLanguageData = embeddedLanguageData;\n }\n clone() {\n const embeddedlanguageDataClone = this.embeddedLanguageData ? this.embeddedLanguageData.clone() : null;\n // save an object\n if (embeddedlanguageDataClone === this.embeddedLanguageData) {\n return this;\n }\n return MonarchLineStateFactory.create(this.stack, this.embeddedLanguageData);\n }\n equals(other) {\n if (!(other instanceof MonarchLineState)) {\n return false;\n }\n if (!this.stack.equals(other.stack)) {\n return false;\n }\n if (this.embeddedLanguageData === null && other.embeddedLanguageData === null) {\n return true;\n }\n if (this.embeddedLanguageData === null || other.embeddedLanguageData === null) {\n return false;\n }\n return this.embeddedLanguageData.equals(other.embeddedLanguageData);\n }\n}\nclass MonarchClassicTokensCollector {\n constructor() {\n this._tokens = [];\n this._languageId = null;\n this._lastTokenType = null;\n this._lastTokenLanguage = null;\n }\n enterLanguage(languageId) {\n this._languageId = languageId;\n }\n emit(startOffset, type) {\n if (this._lastTokenType === type && this._lastTokenLanguage === this._languageId) {\n return;\n }\n this._lastTokenType = type;\n this._lastTokenLanguage = this._languageId;\n this._tokens.push(new languages.Token(startOffset, type, this._languageId));\n }\n nestedLanguageTokenize(embeddedLanguageLine, hasEOL, embeddedLanguageData, offsetDelta) {\n const nestedLanguageId = embeddedLanguageData.languageId;\n const embeddedModeState = embeddedLanguageData.state;\n const nestedLanguageTokenizationSupport = languages.TokenizationRegistry.get(nestedLanguageId);\n if (!nestedLanguageTokenizationSupport) {\n this.enterLanguage(nestedLanguageId);\n this.emit(offsetDelta, '');\n return embeddedModeState;\n }\n const nestedResult = nestedLanguageTokenizationSupport.tokenize(embeddedLanguageLine, hasEOL, embeddedModeState);\n if (offsetDelta !== 0) {\n for (const token of nestedResult.tokens) {\n this._tokens.push(new languages.Token(token.offset + offsetDelta, token.type, token.language));\n }\n }\n else {\n this._tokens = this._tokens.concat(nestedResult.tokens);\n }\n this._lastTokenType = null;\n this._lastTokenLanguage = null;\n this._languageId = null;\n return nestedResult.endState;\n }\n finalize(endState) {\n return new languages.TokenizationResult(this._tokens, endState);\n }\n}\nclass MonarchModernTokensCollector {\n constructor(languageService, theme) {\n this._languageService = languageService;\n this._theme = theme;\n this._prependTokens = null;\n this._tokens = [];\n this._currentLanguageId = 0 /* LanguageId.Null */;\n this._lastTokenMetadata = 0;\n }\n enterLanguage(languageId) {\n this._currentLanguageId = this._languageService.languageIdCodec.encodeLanguageId(languageId);\n }\n emit(startOffset, type) {\n const metadata = this._theme.match(this._currentLanguageId, type);\n if (this._lastTokenMetadata === metadata) {\n return;\n }\n this._lastTokenMetadata = metadata;\n this._tokens.push(startOffset);\n this._tokens.push(metadata);\n }\n static _merge(a, b, c) {\n const aLen = (a !== null ? a.length : 0);\n const bLen = b.length;\n const cLen = (c !== null ? c.length : 0);\n if (aLen === 0 && bLen === 0 && cLen === 0) {\n return new Uint32Array(0);\n }\n if (aLen === 0 && bLen === 0) {\n return c;\n }\n if (bLen === 0 && cLen === 0) {\n return a;\n }\n const result = new Uint32Array(aLen + bLen + cLen);\n if (a !== null) {\n result.set(a);\n }\n for (let i = 0; i < bLen; i++) {\n result[aLen + i] = b[i];\n }\n if (c !== null) {\n result.set(c, aLen + bLen);\n }\n return result;\n }\n nestedLanguageTokenize(embeddedLanguageLine, hasEOL, embeddedLanguageData, offsetDelta) {\n const nestedLanguageId = embeddedLanguageData.languageId;\n const embeddedModeState = embeddedLanguageData.state;\n const nestedLanguageTokenizationSupport = languages.TokenizationRegistry.get(nestedLanguageId);\n if (!nestedLanguageTokenizationSupport) {\n this.enterLanguage(nestedLanguageId);\n this.emit(offsetDelta, '');\n return embeddedModeState;\n }\n const nestedResult = nestedLanguageTokenizationSupport.tokenizeEncoded(embeddedLanguageLine, hasEOL, embeddedModeState);\n if (offsetDelta !== 0) {\n for (let i = 0, len = nestedResult.tokens.length; i < len; i += 2) {\n nestedResult.tokens[i] += offsetDelta;\n }\n }\n this._prependTokens = MonarchModernTokensCollector._merge(this._prependTokens, this._tokens, nestedResult.tokens);\n this._tokens = [];\n this._currentLanguageId = 0;\n this._lastTokenMetadata = 0;\n return nestedResult.endState;\n }\n finalize(endState) {\n return new languages.EncodedTokenizationResult(MonarchModernTokensCollector._merge(this._prependTokens, this._tokens, null), endState);\n }\n}\nlet MonarchTokenizer = class MonarchTokenizer {\n constructor(languageService, standaloneThemeService, languageId, lexer, _configurationService) {\n this._configurationService = _configurationService;\n this._languageService = languageService;\n this._standaloneThemeService = standaloneThemeService;\n this._languageId = languageId;\n this._lexer = lexer;\n this._embeddedLanguages = Object.create(null);\n this.embeddedLoaded = Promise.resolve(undefined);\n // Set up listening for embedded modes\n let emitting = false;\n this._tokenizationRegistryListener = languages.TokenizationRegistry.onDidChange((e) => {\n if (emitting) {\n return;\n }\n let isOneOfMyEmbeddedModes = false;\n for (let i = 0, len = e.changedLanguages.length; i < len; i++) {\n const language = e.changedLanguages[i];\n if (this._embeddedLanguages[language]) {\n isOneOfMyEmbeddedModes = true;\n break;\n }\n }\n if (isOneOfMyEmbeddedModes) {\n emitting = true;\n languages.TokenizationRegistry.fire([this._languageId]);\n emitting = false;\n }\n });\n this._maxTokenizationLineLength = this._configurationService.getValue('editor.maxTokenizationLineLength', {\n overrideIdentifier: this._languageId\n });\n this._configurationService.onDidChangeConfiguration(e => {\n if (e.affectsConfiguration('editor.maxTokenizationLineLength')) {\n this._maxTokenizationLineLength = this._configurationService.getValue('editor.maxTokenizationLineLength', {\n overrideIdentifier: this._languageId\n });\n }\n });\n }\n dispose() {\n this._tokenizationRegistryListener.dispose();\n }\n getLoadStatus() {\n const promises = [];\n for (const nestedLanguageId in this._embeddedLanguages) {\n const tokenizationSupport = languages.TokenizationRegistry.get(nestedLanguageId);\n if (tokenizationSupport) {\n // The nested language is already loaded\n if (tokenizationSupport instanceof MonarchTokenizer) {\n const nestedModeStatus = tokenizationSupport.getLoadStatus();\n if (nestedModeStatus.loaded === false) {\n promises.push(nestedModeStatus.promise);\n }\n }\n continue;\n }\n if (!languages.TokenizationRegistry.isResolved(nestedLanguageId)) {\n // The nested language is in the process of being loaded\n promises.push(languages.TokenizationRegistry.getOrCreate(nestedLanguageId));\n }\n }\n if (promises.length === 0) {\n return {\n loaded: true\n };\n }\n return {\n loaded: false,\n promise: Promise.all(promises).then(_ => undefined)\n };\n }\n getInitialState() {\n const rootState = MonarchStackElementFactory.create(null, this._lexer.start);\n return MonarchLineStateFactory.create(rootState, null);\n }\n tokenize(line, hasEOL, lineState) {\n if (line.length >= this._maxTokenizationLineLength) {\n return nullTokenize(this._languageId, lineState);\n }\n const tokensCollector = new MonarchClassicTokensCollector();\n const endLineState = this._tokenize(line, hasEOL, lineState, tokensCollector);\n return tokensCollector.finalize(endLineState);\n }\n tokenizeEncoded(line, hasEOL, lineState) {\n if (line.length >= this._maxTokenizationLineLength) {\n return nullTokenizeEncoded(this._languageService.languageIdCodec.encodeLanguageId(this._languageId), lineState);\n }\n const tokensCollector = new MonarchModernTokensCollector(this._languageService, this._standaloneThemeService.getColorTheme().tokenTheme);\n const endLineState = this._tokenize(line, hasEOL, lineState, tokensCollector);\n return tokensCollector.finalize(endLineState);\n }\n _tokenize(line, hasEOL, lineState, collector) {\n if (lineState.embeddedLanguageData) {\n return this._nestedTokenize(line, hasEOL, lineState, 0, collector);\n }\n else {\n return this._myTokenize(line, hasEOL, lineState, 0, collector);\n }\n }\n _findLeavingNestedLanguageOffset(line, state) {\n let rules = this._lexer.tokenizer[state.stack.state];\n if (!rules) {\n rules = monarchCommon.findRules(this._lexer, state.stack.state); // do parent matching\n if (!rules) {\n throw monarchCommon.createError(this._lexer, 'tokenizer state is not defined: ' + state.stack.state);\n }\n }\n let popOffset = -1;\n let hasEmbeddedPopRule = false;\n for (const rule of rules) {\n if (!monarchCommon.isIAction(rule.action) || rule.action.nextEmbedded !== '@pop') {\n continue;\n }\n hasEmbeddedPopRule = true;\n let regex = rule.regex;\n const regexSource = rule.regex.source;\n if (regexSource.substr(0, 4) === '^(?:' && regexSource.substr(regexSource.length - 1, 1) === ')') {\n const flags = (regex.ignoreCase ? 'i' : '') + (regex.unicode ? 'u' : '');\n regex = new RegExp(regexSource.substr(4, regexSource.length - 5), flags);\n }\n const result = line.search(regex);\n if (result === -1 || (result !== 0 && rule.matchOnlyAtLineStart)) {\n continue;\n }\n if (popOffset === -1 || result < popOffset) {\n popOffset = result;\n }\n }\n if (!hasEmbeddedPopRule) {\n throw monarchCommon.createError(this._lexer, 'no rule containing nextEmbedded: \"@pop\" in tokenizer embedded state: ' + state.stack.state);\n }\n return popOffset;\n }\n _nestedTokenize(line, hasEOL, lineState, offsetDelta, tokensCollector) {\n const popOffset = this._findLeavingNestedLanguageOffset(line, lineState);\n if (popOffset === -1) {\n // tokenization will not leave nested language\n const nestedEndState = tokensCollector.nestedLanguageTokenize(line, hasEOL, lineState.embeddedLanguageData, offsetDelta);\n return MonarchLineStateFactory.create(lineState.stack, new EmbeddedLanguageData(lineState.embeddedLanguageData.languageId, nestedEndState));\n }\n const nestedLanguageLine = line.substring(0, popOffset);\n if (nestedLanguageLine.length > 0) {\n // tokenize with the nested language\n tokensCollector.nestedLanguageTokenize(nestedLanguageLine, false, lineState.embeddedLanguageData, offsetDelta);\n }\n const restOfTheLine = line.substring(popOffset);\n return this._myTokenize(restOfTheLine, hasEOL, lineState, offsetDelta + popOffset, tokensCollector);\n }\n _safeRuleName(rule) {\n if (rule) {\n return rule.name;\n }\n return '(unknown)';\n }\n _myTokenize(lineWithoutLF, hasEOL, lineState, offsetDelta, tokensCollector) {\n tokensCollector.enterLanguage(this._languageId);\n const lineWithoutLFLength = lineWithoutLF.length;\n const line = (hasEOL && this._lexer.includeLF ? lineWithoutLF + '\\n' : lineWithoutLF);\n const lineLength = line.length;\n let embeddedLanguageData = lineState.embeddedLanguageData;\n let stack = lineState.stack;\n let pos = 0;\n let groupMatching = null;\n // See https://github.com/microsoft/monaco-editor/issues/1235\n // Evaluate rules at least once for an empty line\n let forceEvaluation = true;\n while (forceEvaluation || pos < lineLength) {\n const pos0 = pos;\n const stackLen0 = stack.depth;\n const groupLen0 = groupMatching ? groupMatching.groups.length : 0;\n const state = stack.state;\n let matches = null;\n let matched = null;\n let action = null;\n let rule = null;\n let enteringEmbeddedLanguage = null;\n // check if we need to process group matches first\n if (groupMatching) {\n matches = groupMatching.matches;\n const groupEntry = groupMatching.groups.shift();\n matched = groupEntry.matched;\n action = groupEntry.action;\n rule = groupMatching.rule;\n // cleanup if necessary\n if (groupMatching.groups.length === 0) {\n groupMatching = null;\n }\n }\n else {\n // otherwise we match on the token stream\n if (!forceEvaluation && pos >= lineLength) {\n // nothing to do\n break;\n }\n forceEvaluation = false;\n // get the rules for this state\n let rules = this._lexer.tokenizer[state];\n if (!rules) {\n rules = monarchCommon.findRules(this._lexer, state); // do parent matching\n if (!rules) {\n throw monarchCommon.createError(this._lexer, 'tokenizer state is not defined: ' + state);\n }\n }\n // try each rule until we match\n const restOfLine = line.substr(pos);\n for (const rule of rules) {\n if (pos === 0 || !rule.matchOnlyAtLineStart) {\n matches = restOfLine.match(rule.regex);\n if (matches) {\n matched = matches[0];\n action = rule.action;\n break;\n }\n }\n }\n }\n // We matched 'rule' with 'matches' and 'action'\n if (!matches) {\n matches = [''];\n matched = '';\n }\n if (!action) {\n // bad: we didn't match anything, and there is no action to take\n // we need to advance the stream or we get progress trouble\n if (pos < lineLength) {\n matches = [line.charAt(pos)];\n matched = matches[0];\n }\n action = this._lexer.defaultToken;\n }\n if (matched === null) {\n // should never happen, needed for strict null checking\n break;\n }\n // advance stream\n pos += matched.length;\n // maybe call action function (used for 'cases')\n while (monarchCommon.isFuzzyAction(action) && monarchCommon.isIAction(action) && action.test) {\n action = action.test(matched, matches, state, pos === lineLength);\n }\n let result = null;\n // set the result: either a string or an array of actions\n if (typeof action === 'string' || Array.isArray(action)) {\n result = action;\n }\n else if (action.group) {\n result = action.group;\n }\n else if (action.token !== null && action.token !== undefined) {\n // do $n replacements?\n if (action.tokenSubst) {\n result = monarchCommon.substituteMatches(this._lexer, action.token, matched, matches, state);\n }\n else {\n result = action.token;\n }\n // enter embedded language?\n if (action.nextEmbedded) {\n if (action.nextEmbedded === '@pop') {\n if (!embeddedLanguageData) {\n throw monarchCommon.createError(this._lexer, 'cannot pop embedded language if not inside one');\n }\n embeddedLanguageData = null;\n }\n else if (embeddedLanguageData) {\n throw monarchCommon.createError(this._lexer, 'cannot enter embedded language from within an embedded language');\n }\n else {\n enteringEmbeddedLanguage = monarchCommon.substituteMatches(this._lexer, action.nextEmbedded, matched, matches, state);\n }\n }\n // state transformations\n if (action.goBack) { // back up the stream..\n pos = Math.max(0, pos - action.goBack);\n }\n if (action.switchTo && typeof action.switchTo === 'string') {\n let nextState = monarchCommon.substituteMatches(this._lexer, action.switchTo, matched, matches, state); // switch state without a push...\n if (nextState[0] === '@') {\n nextState = nextState.substr(1); // peel off starting '@'\n }\n if (!monarchCommon.findRules(this._lexer, nextState)) {\n throw monarchCommon.createError(this._lexer, 'trying to switch to a state \\'' + nextState + '\\' that is undefined in rule: ' + this._safeRuleName(rule));\n }\n else {\n stack = stack.switchTo(nextState);\n }\n }\n else if (action.transform && typeof action.transform === 'function') {\n throw monarchCommon.createError(this._lexer, 'action.transform not supported');\n }\n else if (action.next) {\n if (action.next === '@push') {\n if (stack.depth >= this._lexer.maxStack) {\n throw monarchCommon.createError(this._lexer, 'maximum tokenizer stack size reached: [' +\n stack.state + ',' + stack.parent.state + ',...]');\n }\n else {\n stack = stack.push(state);\n }\n }\n else if (action.next === '@pop') {\n if (stack.depth <= 1) {\n throw monarchCommon.createError(this._lexer, 'trying to pop an empty stack in rule: ' + this._safeRuleName(rule));\n }\n else {\n stack = stack.pop();\n }\n }\n else if (action.next === '@popall') {\n stack = stack.popall();\n }\n else {\n let nextState = monarchCommon.substituteMatches(this._lexer, action.next, matched, matches, state);\n if (nextState[0] === '@') {\n nextState = nextState.substr(1); // peel off starting '@'\n }\n if (!monarchCommon.findRules(this._lexer, nextState)) {\n throw monarchCommon.createError(this._lexer, 'trying to set a next state \\'' + nextState + '\\' that is undefined in rule: ' + this._safeRuleName(rule));\n }\n else {\n stack = stack.push(nextState);\n }\n }\n }\n if (action.log && typeof (action.log) === 'string') {\n monarchCommon.log(this._lexer, this._lexer.languageId + ': ' + monarchCommon.substituteMatches(this._lexer, action.log, matched, matches, state));\n }\n }\n // check result\n if (result === null) {\n throw monarchCommon.createError(this._lexer, 'lexer rule has no well-defined action in rule: ' + this._safeRuleName(rule));\n }\n const computeNewStateForEmbeddedLanguage = (enteringEmbeddedLanguage) => {\n // support language names, mime types, and language ids\n const languageId = (this._languageService.getLanguageIdByLanguageName(enteringEmbeddedLanguage)\n || this._languageService.getLanguageIdByMimeType(enteringEmbeddedLanguage)\n || enteringEmbeddedLanguage);\n const embeddedLanguageData = this._getNestedEmbeddedLanguageData(languageId);\n if (pos < lineLength) {\n // there is content from the embedded language on this line\n const restOfLine = lineWithoutLF.substr(pos);\n return this._nestedTokenize(restOfLine, hasEOL, MonarchLineStateFactory.create(stack, embeddedLanguageData), offsetDelta + pos, tokensCollector);\n }\n else {\n return MonarchLineStateFactory.create(stack, embeddedLanguageData);\n }\n };\n // is the result a group match?\n if (Array.isArray(result)) {\n if (groupMatching && groupMatching.groups.length > 0) {\n throw monarchCommon.createError(this._lexer, 'groups cannot be nested: ' + this._safeRuleName(rule));\n }\n if (matches.length !== result.length + 1) {\n throw monarchCommon.createError(this._lexer, 'matched number of groups does not match the number of actions in rule: ' + this._safeRuleName(rule));\n }\n let totalLen = 0;\n for (let i = 1; i < matches.length; i++) {\n totalLen += matches[i].length;\n }\n if (totalLen !== matched.length) {\n throw monarchCommon.createError(this._lexer, 'with groups, all characters should be matched in consecutive groups in rule: ' + this._safeRuleName(rule));\n }\n groupMatching = {\n rule: rule,\n matches: matches,\n groups: []\n };\n for (let i = 0; i < result.length; i++) {\n groupMatching.groups[i] = {\n action: result[i],\n matched: matches[i + 1]\n };\n }\n pos -= matched.length;\n // call recursively to initiate first result match\n continue;\n }\n else {\n // regular result\n // check for '@rematch'\n if (result === '@rematch') {\n pos -= matched.length;\n matched = ''; // better set the next state too..\n matches = null;\n result = '';\n // Even though `@rematch` was specified, if `nextEmbedded` also specified,\n // a state transition should occur.\n if (enteringEmbeddedLanguage !== null) {\n return computeNewStateForEmbeddedLanguage(enteringEmbeddedLanguage);\n }\n }\n // check progress\n if (matched.length === 0) {\n if (lineLength === 0 || stackLen0 !== stack.depth || state !== stack.state || (!groupMatching ? 0 : groupMatching.groups.length) !== groupLen0) {\n continue;\n }\n else {\n throw monarchCommon.createError(this._lexer, 'no progress in tokenizer in rule: ' + this._safeRuleName(rule));\n }\n }\n // return the result (and check for brace matching)\n // todo: for efficiency we could pre-sanitize tokenPostfix and substitutions\n let tokenType = null;\n if (monarchCommon.isString(result) && result.indexOf('@brackets') === 0) {\n const rest = result.substr('@brackets'.length);\n const bracket = findBracket(this._lexer, matched);\n if (!bracket) {\n throw monarchCommon.createError(this._lexer, '@brackets token returned but no bracket defined as: ' + matched);\n }\n tokenType = monarchCommon.sanitize(bracket.token + rest);\n }\n else {\n const token = (result === '' ? '' : result + this._lexer.tokenPostfix);\n tokenType = monarchCommon.sanitize(token);\n }\n if (pos0 < lineWithoutLFLength) {\n tokensCollector.emit(pos0 + offsetDelta, tokenType);\n }\n }\n if (enteringEmbeddedLanguage !== null) {\n return computeNewStateForEmbeddedLanguage(enteringEmbeddedLanguage);\n }\n }\n return MonarchLineStateFactory.create(stack, embeddedLanguageData);\n }\n _getNestedEmbeddedLanguageData(languageId) {\n if (!this._languageService.isRegisteredLanguageId(languageId)) {\n return new EmbeddedLanguageData(languageId, NullState);\n }\n if (languageId !== this._languageId) {\n // Fire language loading event\n languages.TokenizationRegistry.getOrCreate(languageId);\n this._embeddedLanguages[languageId] = true;\n }\n const tokenizationSupport = languages.TokenizationRegistry.get(languageId);\n if (tokenizationSupport) {\n return new EmbeddedLanguageData(languageId, tokenizationSupport.getInitialState());\n }\n return new EmbeddedLanguageData(languageId, NullState);\n }\n};\nMonarchTokenizer = __decorate([\n __param(4, IConfigurationService)\n], MonarchTokenizer);\nexport { MonarchTokenizer };\n/**\n * Searches for a bracket in the 'brackets' attribute that matches the input.\n */\nfunction findBracket(lexer, matched) {\n if (!matched) {\n return null;\n }\n matched = monarchCommon.fixCase(lexer, matched);\n const brackets = lexer.brackets;\n for (const bracket of brackets) {\n if (bracket.open === matched) {\n return { token: bracket.token, bracketType: 1 /* monarchCommon.MonarchBracket.Open */ };\n }\n else if (bracket.close === matched) {\n return { token: bracket.token, bracketType: -1 /* monarchCommon.MonarchBracket.Close */ };\n }\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar _a;\nimport * as strings from '../../../base/common/strings.js';\nimport { LineTokens } from '../../common/tokens/lineTokens.js';\nimport { TokenizationRegistry } from '../../common/languages.js';\nimport { RenderLineInput, renderViewLine2 as renderViewLine } from '../../common/viewLayout/viewLineRenderer.js';\nimport { ViewLineRenderingData } from '../../common/viewModel.js';\nimport { MonarchTokenizer } from '../common/monarch/monarchLexer.js';\nconst ttPolicy = (_a = window.trustedTypes) === null || _a === void 0 ? void 0 : _a.createPolicy('standaloneColorizer', { createHTML: value => value });\nexport class Colorizer {\n static colorizeElement(themeService, languageService, domNode, options) {\n options = options || {};\n const theme = options.theme || 'vs';\n const mimeType = options.mimeType || domNode.getAttribute('lang') || domNode.getAttribute('data-lang');\n if (!mimeType) {\n console.error('Mode not detected');\n return Promise.resolve();\n }\n const languageId = languageService.getLanguageIdByMimeType(mimeType) || mimeType;\n themeService.setTheme(theme);\n const text = domNode.firstChild ? domNode.firstChild.nodeValue : '';\n domNode.className += ' ' + theme;\n const render = (str) => {\n var _a;\n const trustedhtml = (_a = ttPolicy === null || ttPolicy === void 0 ? void 0 : ttPolicy.createHTML(str)) !== null && _a !== void 0 ? _a : str;\n domNode.innerHTML = trustedhtml;\n };\n return this.colorize(languageService, text || '', languageId, options).then(render, (err) => console.error(err));\n }\n static colorize(languageService, text, languageId, options) {\n return __awaiter(this, void 0, void 0, function* () {\n const languageIdCodec = languageService.languageIdCodec;\n let tabSize = 4;\n if (options && typeof options.tabSize === 'number') {\n tabSize = options.tabSize;\n }\n if (strings.startsWithUTF8BOM(text)) {\n text = text.substr(1);\n }\n const lines = strings.splitLines(text);\n if (!languageService.isRegisteredLanguageId(languageId)) {\n return _fakeColorize(lines, tabSize, languageIdCodec);\n }\n const tokenizationSupport = yield TokenizationRegistry.getOrCreate(languageId);\n if (tokenizationSupport) {\n return _colorize(lines, tabSize, tokenizationSupport, languageIdCodec);\n }\n return _fakeColorize(lines, tabSize, languageIdCodec);\n });\n }\n static colorizeLine(line, mightContainNonBasicASCII, mightContainRTL, tokens, tabSize = 4) {\n const isBasicASCII = ViewLineRenderingData.isBasicASCII(line, mightContainNonBasicASCII);\n const containsRTL = ViewLineRenderingData.containsRTL(line, isBasicASCII, mightContainRTL);\n const renderResult = renderViewLine(new RenderLineInput(false, true, line, false, isBasicASCII, containsRTL, 0, tokens, [], tabSize, 0, 0, 0, 0, -1, 'none', false, false, null));\n return renderResult.html;\n }\n static colorizeModelLine(model, lineNumber, tabSize = 4) {\n const content = model.getLineContent(lineNumber);\n model.tokenization.forceTokenization(lineNumber);\n const tokens = model.tokenization.getLineTokens(lineNumber);\n const inflatedTokens = tokens.inflate();\n return this.colorizeLine(content, model.mightContainNonBasicASCII(), model.mightContainRTL(), inflatedTokens, tabSize);\n }\n}\nfunction _colorize(lines, tabSize, tokenizationSupport, languageIdCodec) {\n return new Promise((c, e) => {\n const execute = () => {\n const result = _actualColorize(lines, tabSize, tokenizationSupport, languageIdCodec);\n if (tokenizationSupport instanceof MonarchTokenizer) {\n const status = tokenizationSupport.getLoadStatus();\n if (status.loaded === false) {\n status.promise.then(execute, e);\n return;\n }\n }\n c(result);\n };\n execute();\n });\n}\nfunction _fakeColorize(lines, tabSize, languageIdCodec) {\n let html = [];\n const defaultMetadata = ((0 /* FontStyle.None */ << 11 /* MetadataConsts.FONT_STYLE_OFFSET */)\n | (1 /* ColorId.DefaultForeground */ << 15 /* MetadataConsts.FOREGROUND_OFFSET */)\n | (2 /* ColorId.DefaultBackground */ << 24 /* MetadataConsts.BACKGROUND_OFFSET */)) >>> 0;\n const tokens = new Uint32Array(2);\n tokens[0] = 0;\n tokens[1] = defaultMetadata;\n for (let i = 0, length = lines.length; i < length; i++) {\n const line = lines[i];\n tokens[0] = line.length;\n const lineTokens = new LineTokens(tokens, line, languageIdCodec);\n const isBasicASCII = ViewLineRenderingData.isBasicASCII(line, /* check for basic ASCII */ true);\n const containsRTL = ViewLineRenderingData.containsRTL(line, isBasicASCII, /* check for RTL */ true);\n const renderResult = renderViewLine(new RenderLineInput(false, true, line, false, isBasicASCII, containsRTL, 0, lineTokens, [], tabSize, 0, 0, 0, 0, -1, 'none', false, false, null));\n html = html.concat(renderResult.html);\n html.push('
');\n }\n return html.join('');\n}\nfunction _actualColorize(lines, tabSize, tokenizationSupport, languageIdCodec) {\n let html = [];\n let state = tokenizationSupport.getInitialState();\n for (let i = 0, length = lines.length; i < length; i++) {\n const line = lines[i];\n const tokenizeResult = tokenizationSupport.tokenizeEncoded(line, true, state);\n LineTokens.convertToEndOffset(tokenizeResult.tokens, line.length);\n const lineTokens = new LineTokens(tokenizeResult.tokens, line, languageIdCodec);\n const isBasicASCII = ViewLineRenderingData.isBasicASCII(line, /* check for basic ASCII */ true);\n const containsRTL = ViewLineRenderingData.containsRTL(line, isBasicASCII, /* check for RTL */ true);\n const renderResult = renderViewLine(new RenderLineInput(false, true, line, false, isBasicASCII, containsRTL, 0, lineTokens.inflate(), [], tabSize, 0, 0, 0, 0, -1, 'none', false, false, null));\n html = html.concat(renderResult.html);\n html.push('
');\n state = tokenizeResult.endState;\n }\n return html.join('');\n}\n","var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable, toDisposable } from '../../../base/common/lifecycle.js';\nimport { LinkedList } from '../../../base/common/linkedList.js';\nimport { IThemeService } from '../../../platform/theme/common/themeService.js';\nlet AbstractCodeEditorService = class AbstractCodeEditorService extends Disposable {\n constructor(_themeService) {\n super();\n this._themeService = _themeService;\n this._onCodeEditorAdd = this._register(new Emitter());\n this.onCodeEditorAdd = this._onCodeEditorAdd.event;\n this._onCodeEditorRemove = this._register(new Emitter());\n this.onCodeEditorRemove = this._onCodeEditorRemove.event;\n this._onDiffEditorAdd = this._register(new Emitter());\n this.onDiffEditorAdd = this._onDiffEditorAdd.event;\n this._onDiffEditorRemove = this._register(new Emitter());\n this.onDiffEditorRemove = this._onDiffEditorRemove.event;\n this._decorationOptionProviders = new Map();\n this._codeEditorOpenHandlers = new LinkedList();\n this._modelProperties = new Map();\n this._codeEditors = Object.create(null);\n this._diffEditors = Object.create(null);\n this._globalStyleSheet = null;\n }\n addCodeEditor(editor) {\n this._codeEditors[editor.getId()] = editor;\n this._onCodeEditorAdd.fire(editor);\n }\n removeCodeEditor(editor) {\n if (delete this._codeEditors[editor.getId()]) {\n this._onCodeEditorRemove.fire(editor);\n }\n }\n listCodeEditors() {\n return Object.keys(this._codeEditors).map(id => this._codeEditors[id]);\n }\n addDiffEditor(editor) {\n this._diffEditors[editor.getId()] = editor;\n this._onDiffEditorAdd.fire(editor);\n }\n removeDiffEditor(editor) {\n if (delete this._diffEditors[editor.getId()]) {\n this._onDiffEditorRemove.fire(editor);\n }\n }\n listDiffEditors() {\n return Object.keys(this._diffEditors).map(id => this._diffEditors[id]);\n }\n getFocusedCodeEditor() {\n let editorWithWidgetFocus = null;\n const editors = this.listCodeEditors();\n for (const editor of editors) {\n if (editor.hasTextFocus()) {\n // bingo!\n return editor;\n }\n if (editor.hasWidgetFocus()) {\n editorWithWidgetFocus = editor;\n }\n }\n return editorWithWidgetFocus;\n }\n removeDecorationType(key) {\n const provider = this._decorationOptionProviders.get(key);\n if (provider) {\n provider.refCount--;\n if (provider.refCount <= 0) {\n this._decorationOptionProviders.delete(key);\n provider.dispose();\n this.listCodeEditors().forEach((ed) => ed.removeDecorationsByType(key));\n }\n }\n }\n setModelProperty(resource, key, value) {\n const key1 = resource.toString();\n let dest;\n if (this._modelProperties.has(key1)) {\n dest = this._modelProperties.get(key1);\n }\n else {\n dest = new Map();\n this._modelProperties.set(key1, dest);\n }\n dest.set(key, value);\n }\n getModelProperty(resource, key) {\n const key1 = resource.toString();\n if (this._modelProperties.has(key1)) {\n const innerMap = this._modelProperties.get(key1);\n return innerMap.get(key);\n }\n return undefined;\n }\n openCodeEditor(input, source, sideBySide) {\n return __awaiter(this, void 0, void 0, function* () {\n for (const handler of this._codeEditorOpenHandlers) {\n const candidate = yield handler(input, source, sideBySide);\n if (candidate !== null) {\n return candidate;\n }\n }\n return null;\n });\n }\n registerCodeEditorOpenHandler(handler) {\n const rm = this._codeEditorOpenHandlers.unshift(handler);\n return toDisposable(rm);\n }\n};\nAbstractCodeEditorService = __decorate([\n __param(0, IThemeService)\n], AbstractCodeEditorService);\nexport { AbstractCodeEditorService };\nexport class GlobalStyleSheet {\n constructor(styleSheet) {\n this._styleSheet = styleSheet;\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { windowOpenNoOpener } from '../../../base/browser/dom.js';\nimport { Schemas } from '../../../base/common/network.js';\nimport { AbstractCodeEditorService } from '../../browser/services/abstractCodeEditorService.js';\nimport { ICodeEditorService } from '../../browser/services/codeEditorService.js';\nimport { IContextKeyService } from '../../../platform/contextkey/common/contextkey.js';\nimport { registerSingleton } from '../../../platform/instantiation/common/extensions.js';\nimport { IThemeService } from '../../../platform/theme/common/themeService.js';\nlet StandaloneCodeEditorService = class StandaloneCodeEditorService extends AbstractCodeEditorService {\n constructor(contextKeyService, themeService) {\n super(themeService);\n this.onCodeEditorAdd(() => this._checkContextKey());\n this.onCodeEditorRemove(() => this._checkContextKey());\n this._editorIsOpen = contextKeyService.createKey('editorIsOpen', false);\n this._activeCodeEditor = null;\n this.registerCodeEditorOpenHandler((input, source, sideBySide) => __awaiter(this, void 0, void 0, function* () {\n if (!source) {\n return null;\n }\n return this.doOpenEditor(source, input);\n }));\n }\n _checkContextKey() {\n let hasCodeEditor = false;\n for (const editor of this.listCodeEditors()) {\n if (!editor.isSimpleWidget) {\n hasCodeEditor = true;\n break;\n }\n }\n this._editorIsOpen.set(hasCodeEditor);\n }\n setActiveCodeEditor(activeCodeEditor) {\n this._activeCodeEditor = activeCodeEditor;\n }\n getActiveCodeEditor() {\n return this._activeCodeEditor;\n }\n doOpenEditor(editor, input) {\n const model = this.findModel(editor, input.resource);\n if (!model) {\n if (input.resource) {\n const schema = input.resource.scheme;\n if (schema === Schemas.http || schema === Schemas.https) {\n // This is a fully qualified http or https URL\n windowOpenNoOpener(input.resource.toString());\n return editor;\n }\n }\n return null;\n }\n const selection = (input.options ? input.options.selection : null);\n if (selection) {\n if (typeof selection.endLineNumber === 'number' && typeof selection.endColumn === 'number') {\n editor.setSelection(selection);\n editor.revealRangeInCenter(selection, 1 /* ScrollType.Immediate */);\n }\n else {\n const pos = {\n lineNumber: selection.startLineNumber,\n column: selection.startColumn\n };\n editor.setPosition(pos);\n editor.revealPositionInCenter(pos, 1 /* ScrollType.Immediate */);\n }\n }\n return editor;\n }\n findModel(editor, resource) {\n const model = editor.getModel();\n if (model && model.uri.toString() !== resource.toString()) {\n return null;\n }\n return model;\n }\n};\nStandaloneCodeEditorService = __decorate([\n __param(0, IContextKeyService),\n __param(1, IThemeService)\n], StandaloneCodeEditorService);\nexport { StandaloneCodeEditorService };\nregisterSingleton(ICodeEditorService, StandaloneCodeEditorService);\n","/*---------------------------------------------------------------------------------------------\n * 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 { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const ILayoutService = createDecorator('layoutService');\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport * as dom from '../../../base/browser/dom.js';\nimport { Event } from '../../../base/common/event.js';\nimport { ILayoutService } from '../../../platform/layout/browser/layoutService.js';\nimport { ICodeEditorService } from '../../browser/services/codeEditorService.js';\nimport { registerSingleton } from '../../../platform/instantiation/common/extensions.js';\nlet StandaloneLayoutService = class StandaloneLayoutService {\n constructor(_codeEditorService) {\n this._codeEditorService = _codeEditorService;\n this.onDidLayout = Event.None;\n this.offset = { top: 0, quickPickTop: 0 };\n }\n get dimension() {\n if (!this._dimension) {\n this._dimension = dom.getClientArea(window.document.body);\n }\n return this._dimension;\n }\n get hasContainer() {\n return false;\n }\n get container() {\n // On a page, multiple editors can be created. Therefore, there are multiple containers, not\n // just a single one. Please use `ICodeEditorService` to get the current focused code editor\n // and use its container if necessary. You can also instantiate `EditorScopedLayoutService`\n // which implements `ILayoutService` but is not a part of the service collection because\n // it is code editor instance specific.\n throw new Error(`ILayoutService.container is not available in the standalone editor!`);\n }\n focus() {\n var _a;\n (_a = this._codeEditorService.getFocusedCodeEditor()) === null || _a === void 0 ? void 0 : _a.focus();\n }\n};\nStandaloneLayoutService = __decorate([\n __param(0, ICodeEditorService)\n], StandaloneLayoutService);\nlet EditorScopedLayoutService = class EditorScopedLayoutService extends StandaloneLayoutService {\n constructor(_container, codeEditorService) {\n super(codeEditorService);\n this._container = _container;\n }\n get hasContainer() {\n return false;\n }\n get container() {\n return this._container;\n }\n};\nEditorScopedLayoutService = __decorate([\n __param(1, ICodeEditorService)\n], EditorScopedLayoutService);\nexport { EditorScopedLayoutService };\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { onUnexpectedError } from '../../../base/common/errors.js';\nimport { Disposable, isDisposable } from '../../../base/common/lifecycle.js';\nimport { Schemas } from '../../../base/common/network.js';\nimport Severity from '../../../base/common/severity.js';\nimport * as nls from '../../../nls.js';\nimport { IDialogService } from '../../dialogs/common/dialogs.js';\nimport { registerSingleton } from '../../instantiation/common/extensions.js';\nimport { INotificationService } from '../../notification/common/notification.js';\nimport { IUndoRedoService, ResourceEditStackSnapshot, UndoRedoGroup, UndoRedoSource } from './undoRedo.js';\nconst DEBUG = false;\nfunction getResourceLabel(resource) {\n return resource.scheme === Schemas.file ? resource.fsPath : resource.path;\n}\nlet stackElementCounter = 0;\nclass ResourceStackElement {\n constructor(actual, resourceLabel, strResource, groupId, groupOrder, sourceId, sourceOrder) {\n this.id = (++stackElementCounter);\n this.type = 0 /* UndoRedoElementType.Resource */;\n this.actual = actual;\n this.label = actual.label;\n this.confirmBeforeUndo = actual.confirmBeforeUndo || false;\n this.resourceLabel = resourceLabel;\n this.strResource = strResource;\n this.resourceLabels = [this.resourceLabel];\n this.strResources = [this.strResource];\n this.groupId = groupId;\n this.groupOrder = groupOrder;\n this.sourceId = sourceId;\n this.sourceOrder = sourceOrder;\n this.isValid = true;\n }\n setValid(isValid) {\n this.isValid = isValid;\n }\n toString() {\n return `[id:${this.id}] [group:${this.groupId}] [${this.isValid ? ' VALID' : 'INVALID'}] ${this.actual.constructor.name} - ${this.actual}`;\n }\n}\nclass ResourceReasonPair {\n constructor(resourceLabel, reason) {\n this.resourceLabel = resourceLabel;\n this.reason = reason;\n }\n}\nclass RemovedResources {\n constructor() {\n this.elements = new Map();\n }\n createMessage() {\n const externalRemoval = [];\n const noParallelUniverses = [];\n for (const [, element] of this.elements) {\n const dest = (element.reason === 0 /* RemovedResourceReason.ExternalRemoval */\n ? externalRemoval\n : noParallelUniverses);\n dest.push(element.resourceLabel);\n }\n const messages = [];\n if (externalRemoval.length > 0) {\n messages.push(nls.localize({ key: 'externalRemoval', comment: ['{0} is a list of filenames'] }, \"The following files have been closed and modified on disk: {0}.\", externalRemoval.join(', ')));\n }\n if (noParallelUniverses.length > 0) {\n messages.push(nls.localize({ key: 'noParallelUniverses', comment: ['{0} is a list of filenames'] }, \"The following files have been modified in an incompatible way: {0}.\", noParallelUniverses.join(', ')));\n }\n return messages.join('\\n');\n }\n get size() {\n return this.elements.size;\n }\n has(strResource) {\n return this.elements.has(strResource);\n }\n set(strResource, value) {\n this.elements.set(strResource, value);\n }\n delete(strResource) {\n return this.elements.delete(strResource);\n }\n}\nclass WorkspaceStackElement {\n constructor(actual, resourceLabels, strResources, groupId, groupOrder, sourceId, sourceOrder) {\n this.id = (++stackElementCounter);\n this.type = 1 /* UndoRedoElementType.Workspace */;\n this.actual = actual;\n this.label = actual.label;\n this.confirmBeforeUndo = actual.confirmBeforeUndo || false;\n this.resourceLabels = resourceLabels;\n this.strResources = strResources;\n this.groupId = groupId;\n this.groupOrder = groupOrder;\n this.sourceId = sourceId;\n this.sourceOrder = sourceOrder;\n this.removedResources = null;\n this.invalidatedResources = null;\n }\n canSplit() {\n return (typeof this.actual.split === 'function');\n }\n removeResource(resourceLabel, strResource, reason) {\n if (!this.removedResources) {\n this.removedResources = new RemovedResources();\n }\n if (!this.removedResources.has(strResource)) {\n this.removedResources.set(strResource, new ResourceReasonPair(resourceLabel, reason));\n }\n }\n setValid(resourceLabel, strResource, isValid) {\n if (isValid) {\n if (this.invalidatedResources) {\n this.invalidatedResources.delete(strResource);\n if (this.invalidatedResources.size === 0) {\n this.invalidatedResources = null;\n }\n }\n }\n else {\n if (!this.invalidatedResources) {\n this.invalidatedResources = new RemovedResources();\n }\n if (!this.invalidatedResources.has(strResource)) {\n this.invalidatedResources.set(strResource, new ResourceReasonPair(resourceLabel, 0 /* RemovedResourceReason.ExternalRemoval */));\n }\n }\n }\n toString() {\n return `[id:${this.id}] [group:${this.groupId}] [${this.invalidatedResources ? 'INVALID' : ' VALID'}] ${this.actual.constructor.name} - ${this.actual}`;\n }\n}\nclass ResourceEditStack {\n constructor(resourceLabel, strResource) {\n this.resourceLabel = resourceLabel;\n this.strResource = strResource;\n this._past = [];\n this._future = [];\n this.locked = false;\n this.versionId = 1;\n }\n dispose() {\n for (const element of this._past) {\n if (element.type === 1 /* UndoRedoElementType.Workspace */) {\n element.removeResource(this.resourceLabel, this.strResource, 0 /* RemovedResourceReason.ExternalRemoval */);\n }\n }\n for (const element of this._future) {\n if (element.type === 1 /* UndoRedoElementType.Workspace */) {\n element.removeResource(this.resourceLabel, this.strResource, 0 /* RemovedResourceReason.ExternalRemoval */);\n }\n }\n this.versionId++;\n }\n toString() {\n const result = [];\n result.push(`* ${this.strResource}:`);\n for (let i = 0; i < this._past.length; i++) {\n result.push(` * [UNDO] ${this._past[i]}`);\n }\n for (let i = this._future.length - 1; i >= 0; i--) {\n result.push(` * [REDO] ${this._future[i]}`);\n }\n return result.join('\\n');\n }\n flushAllElements() {\n this._past = [];\n this._future = [];\n this.versionId++;\n }\n _setElementValidFlag(element, isValid) {\n if (element.type === 1 /* UndoRedoElementType.Workspace */) {\n element.setValid(this.resourceLabel, this.strResource, isValid);\n }\n else {\n element.setValid(isValid);\n }\n }\n setElementsValidFlag(isValid, filter) {\n for (const element of this._past) {\n if (filter(element.actual)) {\n this._setElementValidFlag(element, isValid);\n }\n }\n for (const element of this._future) {\n if (filter(element.actual)) {\n this._setElementValidFlag(element, isValid);\n }\n }\n }\n pushElement(element) {\n // remove the future\n for (const futureElement of this._future) {\n if (futureElement.type === 1 /* UndoRedoElementType.Workspace */) {\n futureElement.removeResource(this.resourceLabel, this.strResource, 1 /* RemovedResourceReason.NoParallelUniverses */);\n }\n }\n this._future = [];\n this._past.push(element);\n this.versionId++;\n }\n createSnapshot(resource) {\n const elements = [];\n for (let i = 0, len = this._past.length; i < len; i++) {\n elements.push(this._past[i].id);\n }\n for (let i = this._future.length - 1; i >= 0; i--) {\n elements.push(this._future[i].id);\n }\n return new ResourceEditStackSnapshot(resource, elements);\n }\n restoreSnapshot(snapshot) {\n const snapshotLength = snapshot.elements.length;\n let isOK = true;\n let snapshotIndex = 0;\n let removePastAfter = -1;\n for (let i = 0, len = this._past.length; i < len; i++, snapshotIndex++) {\n const element = this._past[i];\n if (isOK && (snapshotIndex >= snapshotLength || element.id !== snapshot.elements[snapshotIndex])) {\n isOK = false;\n removePastAfter = 0;\n }\n if (!isOK && element.type === 1 /* UndoRedoElementType.Workspace */) {\n element.removeResource(this.resourceLabel, this.strResource, 0 /* RemovedResourceReason.ExternalRemoval */);\n }\n }\n let removeFutureBefore = -1;\n for (let i = this._future.length - 1; i >= 0; i--, snapshotIndex++) {\n const element = this._future[i];\n if (isOK && (snapshotIndex >= snapshotLength || element.id !== snapshot.elements[snapshotIndex])) {\n isOK = false;\n removeFutureBefore = i;\n }\n if (!isOK && element.type === 1 /* UndoRedoElementType.Workspace */) {\n element.removeResource(this.resourceLabel, this.strResource, 0 /* RemovedResourceReason.ExternalRemoval */);\n }\n }\n if (removePastAfter !== -1) {\n this._past = this._past.slice(0, removePastAfter);\n }\n if (removeFutureBefore !== -1) {\n this._future = this._future.slice(removeFutureBefore + 1);\n }\n this.versionId++;\n }\n getElements() {\n const past = [];\n const future = [];\n for (const element of this._past) {\n past.push(element.actual);\n }\n for (const element of this._future) {\n future.push(element.actual);\n }\n return { past, future };\n }\n getClosestPastElement() {\n if (this._past.length === 0) {\n return null;\n }\n return this._past[this._past.length - 1];\n }\n getSecondClosestPastElement() {\n if (this._past.length < 2) {\n return null;\n }\n return this._past[this._past.length - 2];\n }\n getClosestFutureElement() {\n if (this._future.length === 0) {\n return null;\n }\n return this._future[this._future.length - 1];\n }\n hasPastElements() {\n return (this._past.length > 0);\n }\n hasFutureElements() {\n return (this._future.length > 0);\n }\n splitPastWorkspaceElement(toRemove, individualMap) {\n for (let j = this._past.length - 1; j >= 0; j--) {\n if (this._past[j] === toRemove) {\n if (individualMap.has(this.strResource)) {\n // gets replaced\n this._past[j] = individualMap.get(this.strResource);\n }\n else {\n // gets deleted\n this._past.splice(j, 1);\n }\n break;\n }\n }\n this.versionId++;\n }\n splitFutureWorkspaceElement(toRemove, individualMap) {\n for (let j = this._future.length - 1; j >= 0; j--) {\n if (this._future[j] === toRemove) {\n if (individualMap.has(this.strResource)) {\n // gets replaced\n this._future[j] = individualMap.get(this.strResource);\n }\n else {\n // gets deleted\n this._future.splice(j, 1);\n }\n break;\n }\n }\n this.versionId++;\n }\n moveBackward(element) {\n this._past.pop();\n this._future.push(element);\n this.versionId++;\n }\n moveForward(element) {\n this._future.pop();\n this._past.push(element);\n this.versionId++;\n }\n}\nclass EditStackSnapshot {\n constructor(editStacks) {\n this.editStacks = editStacks;\n this._versionIds = [];\n for (let i = 0, len = this.editStacks.length; i < len; i++) {\n this._versionIds[i] = this.editStacks[i].versionId;\n }\n }\n isValid() {\n for (let i = 0, len = this.editStacks.length; i < len; i++) {\n if (this._versionIds[i] !== this.editStacks[i].versionId) {\n return false;\n }\n }\n return true;\n }\n}\nconst missingEditStack = new ResourceEditStack('', '');\nmissingEditStack.locked = true;\nlet UndoRedoService = class UndoRedoService {\n constructor(_dialogService, _notificationService) {\n this._dialogService = _dialogService;\n this._notificationService = _notificationService;\n this._editStacks = new Map();\n this._uriComparisonKeyComputers = [];\n }\n getUriComparisonKey(resource) {\n for (const uriComparisonKeyComputer of this._uriComparisonKeyComputers) {\n if (uriComparisonKeyComputer[0] === resource.scheme) {\n return uriComparisonKeyComputer[1].getComparisonKey(resource);\n }\n }\n return resource.toString();\n }\n _print(label) {\n console.log(`------------------------------------`);\n console.log(`AFTER ${label}: `);\n const str = [];\n for (const element of this._editStacks) {\n str.push(element[1].toString());\n }\n console.log(str.join('\\n'));\n }\n pushElement(element, group = UndoRedoGroup.None, source = UndoRedoSource.None) {\n if (element.type === 0 /* UndoRedoElementType.Resource */) {\n const resourceLabel = getResourceLabel(element.resource);\n const strResource = this.getUriComparisonKey(element.resource);\n this._pushElement(new ResourceStackElement(element, resourceLabel, strResource, group.id, group.nextOrder(), source.id, source.nextOrder()));\n }\n else {\n const seen = new Set();\n const resourceLabels = [];\n const strResources = [];\n for (const resource of element.resources) {\n const resourceLabel = getResourceLabel(resource);\n const strResource = this.getUriComparisonKey(resource);\n if (seen.has(strResource)) {\n continue;\n }\n seen.add(strResource);\n resourceLabels.push(resourceLabel);\n strResources.push(strResource);\n }\n if (resourceLabels.length === 1) {\n this._pushElement(new ResourceStackElement(element, resourceLabels[0], strResources[0], group.id, group.nextOrder(), source.id, source.nextOrder()));\n }\n else {\n this._pushElement(new WorkspaceStackElement(element, resourceLabels, strResources, group.id, group.nextOrder(), source.id, source.nextOrder()));\n }\n }\n if (DEBUG) {\n this._print('pushElement');\n }\n }\n _pushElement(element) {\n for (let i = 0, len = element.strResources.length; i < len; i++) {\n const resourceLabel = element.resourceLabels[i];\n const strResource = element.strResources[i];\n let editStack;\n if (this._editStacks.has(strResource)) {\n editStack = this._editStacks.get(strResource);\n }\n else {\n editStack = new ResourceEditStack(resourceLabel, strResource);\n this._editStacks.set(strResource, editStack);\n }\n editStack.pushElement(element);\n }\n }\n getLastElement(resource) {\n const strResource = this.getUriComparisonKey(resource);\n if (this._editStacks.has(strResource)) {\n const editStack = this._editStacks.get(strResource);\n if (editStack.hasFutureElements()) {\n return null;\n }\n const closestPastElement = editStack.getClosestPastElement();\n return closestPastElement ? closestPastElement.actual : null;\n }\n return null;\n }\n _splitPastWorkspaceElement(toRemove, ignoreResources) {\n const individualArr = toRemove.actual.split();\n const individualMap = new Map();\n for (const _element of individualArr) {\n const resourceLabel = getResourceLabel(_element.resource);\n const strResource = this.getUriComparisonKey(_element.resource);\n const element = new ResourceStackElement(_element, resourceLabel, strResource, 0, 0, 0, 0);\n individualMap.set(element.strResource, element);\n }\n for (const strResource of toRemove.strResources) {\n if (ignoreResources && ignoreResources.has(strResource)) {\n continue;\n }\n const editStack = this._editStacks.get(strResource);\n editStack.splitPastWorkspaceElement(toRemove, individualMap);\n }\n }\n _splitFutureWorkspaceElement(toRemove, ignoreResources) {\n const individualArr = toRemove.actual.split();\n const individualMap = new Map();\n for (const _element of individualArr) {\n const resourceLabel = getResourceLabel(_element.resource);\n const strResource = this.getUriComparisonKey(_element.resource);\n const element = new ResourceStackElement(_element, resourceLabel, strResource, 0, 0, 0, 0);\n individualMap.set(element.strResource, element);\n }\n for (const strResource of toRemove.strResources) {\n if (ignoreResources && ignoreResources.has(strResource)) {\n continue;\n }\n const editStack = this._editStacks.get(strResource);\n editStack.splitFutureWorkspaceElement(toRemove, individualMap);\n }\n }\n removeElements(resource) {\n const strResource = typeof resource === 'string' ? resource : this.getUriComparisonKey(resource);\n if (this._editStacks.has(strResource)) {\n const editStack = this._editStacks.get(strResource);\n editStack.dispose();\n this._editStacks.delete(strResource);\n }\n if (DEBUG) {\n this._print('removeElements');\n }\n }\n setElementsValidFlag(resource, isValid, filter) {\n const strResource = this.getUriComparisonKey(resource);\n if (this._editStacks.has(strResource)) {\n const editStack = this._editStacks.get(strResource);\n editStack.setElementsValidFlag(isValid, filter);\n }\n if (DEBUG) {\n this._print('setElementsValidFlag');\n }\n }\n createSnapshot(resource) {\n const strResource = this.getUriComparisonKey(resource);\n if (this._editStacks.has(strResource)) {\n const editStack = this._editStacks.get(strResource);\n return editStack.createSnapshot(resource);\n }\n return new ResourceEditStackSnapshot(resource, []);\n }\n restoreSnapshot(snapshot) {\n const strResource = this.getUriComparisonKey(snapshot.resource);\n if (this._editStacks.has(strResource)) {\n const editStack = this._editStacks.get(strResource);\n editStack.restoreSnapshot(snapshot);\n if (!editStack.hasPastElements() && !editStack.hasFutureElements()) {\n // the edit stack is now empty, just remove it entirely\n editStack.dispose();\n this._editStacks.delete(strResource);\n }\n }\n if (DEBUG) {\n this._print('restoreSnapshot');\n }\n }\n getElements(resource) {\n const strResource = this.getUriComparisonKey(resource);\n if (this._editStacks.has(strResource)) {\n const editStack = this._editStacks.get(strResource);\n return editStack.getElements();\n }\n return { past: [], future: [] };\n }\n _findClosestUndoElementWithSource(sourceId) {\n if (!sourceId) {\n return [null, null];\n }\n // find an element with the sourceId and with the highest sourceOrder ready to be undone\n let matchedElement = null;\n let matchedStrResource = null;\n for (const [strResource, editStack] of this._editStacks) {\n const candidate = editStack.getClosestPastElement();\n if (!candidate) {\n continue;\n }\n if (candidate.sourceId === sourceId) {\n if (!matchedElement || candidate.sourceOrder > matchedElement.sourceOrder) {\n matchedElement = candidate;\n matchedStrResource = strResource;\n }\n }\n }\n return [matchedElement, matchedStrResource];\n }\n canUndo(resourceOrSource) {\n if (resourceOrSource instanceof UndoRedoSource) {\n const [, matchedStrResource] = this._findClosestUndoElementWithSource(resourceOrSource.id);\n return matchedStrResource ? true : false;\n }\n const strResource = this.getUriComparisonKey(resourceOrSource);\n if (this._editStacks.has(strResource)) {\n const editStack = this._editStacks.get(strResource);\n return editStack.hasPastElements();\n }\n return false;\n }\n _onError(err, element) {\n onUnexpectedError(err);\n // An error occurred while undoing or redoing => drop the undo/redo stack for all affected resources\n for (const strResource of element.strResources) {\n this.removeElements(strResource);\n }\n this._notificationService.error(err);\n }\n _acquireLocks(editStackSnapshot) {\n // first, check if all locks can be acquired\n for (const editStack of editStackSnapshot.editStacks) {\n if (editStack.locked) {\n throw new Error('Cannot acquire edit stack lock');\n }\n }\n // can acquire all locks\n for (const editStack of editStackSnapshot.editStacks) {\n editStack.locked = true;\n }\n return () => {\n // release all locks\n for (const editStack of editStackSnapshot.editStacks) {\n editStack.locked = false;\n }\n };\n }\n _safeInvokeWithLocks(element, invoke, editStackSnapshot, cleanup, continuation) {\n const releaseLocks = this._acquireLocks(editStackSnapshot);\n let result;\n try {\n result = invoke();\n }\n catch (err) {\n releaseLocks();\n cleanup.dispose();\n return this._onError(err, element);\n }\n if (result) {\n // result is Promise\n return result.then(() => {\n releaseLocks();\n cleanup.dispose();\n return continuation();\n }, (err) => {\n releaseLocks();\n cleanup.dispose();\n return this._onError(err, element);\n });\n }\n else {\n // result is void\n releaseLocks();\n cleanup.dispose();\n return continuation();\n }\n }\n _invokeWorkspacePrepare(element) {\n return __awaiter(this, void 0, void 0, function* () {\n if (typeof element.actual.prepareUndoRedo === 'undefined') {\n return Disposable.None;\n }\n const result = element.actual.prepareUndoRedo();\n if (typeof result === 'undefined') {\n return Disposable.None;\n }\n return result;\n });\n }\n _invokeResourcePrepare(element, callback) {\n if (element.actual.type !== 1 /* UndoRedoElementType.Workspace */ || typeof element.actual.prepareUndoRedo === 'undefined') {\n // no preparation needed\n return callback(Disposable.None);\n }\n const r = element.actual.prepareUndoRedo();\n if (!r) {\n // nothing to clean up\n return callback(Disposable.None);\n }\n if (isDisposable(r)) {\n return callback(r);\n }\n return r.then((disposable) => {\n return callback(disposable);\n });\n }\n _getAffectedEditStacks(element) {\n const affectedEditStacks = [];\n for (const strResource of element.strResources) {\n affectedEditStacks.push(this._editStacks.get(strResource) || missingEditStack);\n }\n return new EditStackSnapshot(affectedEditStacks);\n }\n _tryToSplitAndUndo(strResource, element, ignoreResources, message) {\n if (element.canSplit()) {\n this._splitPastWorkspaceElement(element, ignoreResources);\n this._notificationService.warn(message);\n return new WorkspaceVerificationError(this._undo(strResource, 0, true));\n }\n else {\n // Cannot safely split this workspace element => flush all undo/redo stacks\n for (const strResource of element.strResources) {\n this.removeElements(strResource);\n }\n this._notificationService.warn(message);\n return new WorkspaceVerificationError();\n }\n }\n _checkWorkspaceUndo(strResource, element, editStackSnapshot, checkInvalidatedResources) {\n if (element.removedResources) {\n return this._tryToSplitAndUndo(strResource, element, element.removedResources, nls.localize({ key: 'cannotWorkspaceUndo', comment: ['{0} is a label for an operation. {1} is another message.'] }, \"Could not undo '{0}' across all files. {1}\", element.label, element.removedResources.createMessage()));\n }\n if (checkInvalidatedResources && element.invalidatedResources) {\n return this._tryToSplitAndUndo(strResource, element, element.invalidatedResources, nls.localize({ key: 'cannotWorkspaceUndo', comment: ['{0} is a label for an operation. {1} is another message.'] }, \"Could not undo '{0}' across all files. {1}\", element.label, element.invalidatedResources.createMessage()));\n }\n // this must be the last past element in all the impacted resources!\n const cannotUndoDueToResources = [];\n for (const editStack of editStackSnapshot.editStacks) {\n if (editStack.getClosestPastElement() !== element) {\n cannotUndoDueToResources.push(editStack.resourceLabel);\n }\n }\n if (cannotUndoDueToResources.length > 0) {\n return this._tryToSplitAndUndo(strResource, element, null, nls.localize({ key: 'cannotWorkspaceUndoDueToChanges', comment: ['{0} is a label for an operation. {1} is a list of filenames.'] }, \"Could not undo '{0}' across all files because changes were made to {1}\", element.label, cannotUndoDueToResources.join(', ')));\n }\n const cannotLockDueToResources = [];\n for (const editStack of editStackSnapshot.editStacks) {\n if (editStack.locked) {\n cannotLockDueToResources.push(editStack.resourceLabel);\n }\n }\n if (cannotLockDueToResources.length > 0) {\n return this._tryToSplitAndUndo(strResource, element, null, nls.localize({ key: 'cannotWorkspaceUndoDueToInProgressUndoRedo', comment: ['{0} is a label for an operation. {1} is a list of filenames.'] }, \"Could not undo '{0}' across all files because there is already an undo or redo operation running on {1}\", element.label, cannotLockDueToResources.join(', ')));\n }\n // check if new stack elements were added in the meantime...\n if (!editStackSnapshot.isValid()) {\n return this._tryToSplitAndUndo(strResource, element, null, nls.localize({ key: 'cannotWorkspaceUndoDueToInMeantimeUndoRedo', comment: ['{0} is a label for an operation. {1} is a list of filenames.'] }, \"Could not undo '{0}' across all files because an undo or redo operation occurred in the meantime\", element.label));\n }\n return null;\n }\n _workspaceUndo(strResource, element, undoConfirmed) {\n const affectedEditStacks = this._getAffectedEditStacks(element);\n const verificationError = this._checkWorkspaceUndo(strResource, element, affectedEditStacks, /*invalidated resources will be checked after the prepare call*/ false);\n if (verificationError) {\n return verificationError.returnValue;\n }\n return this._confirmAndExecuteWorkspaceUndo(strResource, element, affectedEditStacks, undoConfirmed);\n }\n _isPartOfUndoGroup(element) {\n if (!element.groupId) {\n return false;\n }\n // check that there is at least another element with the same groupId ready to be undone\n for (const [, editStack] of this._editStacks) {\n const pastElement = editStack.getClosestPastElement();\n if (!pastElement) {\n continue;\n }\n if (pastElement === element) {\n const secondPastElement = editStack.getSecondClosestPastElement();\n if (secondPastElement && secondPastElement.groupId === element.groupId) {\n // there is another element with the same group id in the same stack!\n return true;\n }\n }\n if (pastElement.groupId === element.groupId) {\n // there is another element with the same group id in another stack!\n return true;\n }\n }\n return false;\n }\n _confirmAndExecuteWorkspaceUndo(strResource, element, editStackSnapshot, undoConfirmed) {\n return __awaiter(this, void 0, void 0, function* () {\n if (element.canSplit() && !this._isPartOfUndoGroup(element)) {\n // this element can be split\n const result = yield this._dialogService.show(Severity.Info, nls.localize('confirmWorkspace', \"Would you like to undo '{0}' across all files?\", element.label), [\n nls.localize({ key: 'ok', comment: ['{0} denotes a number that is > 1'] }, \"Undo in {0} Files\", editStackSnapshot.editStacks.length),\n nls.localize('nok', \"Undo this File\"),\n nls.localize('cancel', \"Cancel\"),\n ], {\n cancelId: 2\n });\n if (result.choice === 2) {\n // choice: cancel\n return;\n }\n if (result.choice === 1) {\n // choice: undo this file\n this._splitPastWorkspaceElement(element, null);\n return this._undo(strResource, 0, true);\n }\n // choice: undo in all files\n // At this point, it is possible that the element has been made invalid in the meantime (due to the confirmation await)\n const verificationError1 = this._checkWorkspaceUndo(strResource, element, editStackSnapshot, /*invalidated resources will be checked after the prepare call*/ false);\n if (verificationError1) {\n return verificationError1.returnValue;\n }\n undoConfirmed = true;\n }\n // prepare\n let cleanup;\n try {\n cleanup = yield this._invokeWorkspacePrepare(element);\n }\n catch (err) {\n return this._onError(err, element);\n }\n // At this point, it is possible that the element has been made invalid in the meantime (due to the prepare await)\n const verificationError2 = this._checkWorkspaceUndo(strResource, element, editStackSnapshot, /*now also check that there are no more invalidated resources*/ true);\n if (verificationError2) {\n cleanup.dispose();\n return verificationError2.returnValue;\n }\n for (const editStack of editStackSnapshot.editStacks) {\n editStack.moveBackward(element);\n }\n return this._safeInvokeWithLocks(element, () => element.actual.undo(), editStackSnapshot, cleanup, () => this._continueUndoInGroup(element.groupId, undoConfirmed));\n });\n }\n _resourceUndo(editStack, element, undoConfirmed) {\n if (!element.isValid) {\n // invalid element => immediately flush edit stack!\n editStack.flushAllElements();\n return;\n }\n if (editStack.locked) {\n const message = nls.localize({ key: 'cannotResourceUndoDueToInProgressUndoRedo', comment: ['{0} is a label for an operation.'] }, \"Could not undo '{0}' because there is already an undo or redo operation running.\", element.label);\n this._notificationService.warn(message);\n return;\n }\n return this._invokeResourcePrepare(element, (cleanup) => {\n editStack.moveBackward(element);\n return this._safeInvokeWithLocks(element, () => element.actual.undo(), new EditStackSnapshot([editStack]), cleanup, () => this._continueUndoInGroup(element.groupId, undoConfirmed));\n });\n }\n _findClosestUndoElementInGroup(groupId) {\n if (!groupId) {\n return [null, null];\n }\n // find another element with the same groupId and with the highest groupOrder ready to be undone\n let matchedElement = null;\n let matchedStrResource = null;\n for (const [strResource, editStack] of this._editStacks) {\n const candidate = editStack.getClosestPastElement();\n if (!candidate) {\n continue;\n }\n if (candidate.groupId === groupId) {\n if (!matchedElement || candidate.groupOrder > matchedElement.groupOrder) {\n matchedElement = candidate;\n matchedStrResource = strResource;\n }\n }\n }\n return [matchedElement, matchedStrResource];\n }\n _continueUndoInGroup(groupId, undoConfirmed) {\n if (!groupId) {\n return;\n }\n const [, matchedStrResource] = this._findClosestUndoElementInGroup(groupId);\n if (matchedStrResource) {\n return this._undo(matchedStrResource, 0, undoConfirmed);\n }\n }\n undo(resourceOrSource) {\n if (resourceOrSource instanceof UndoRedoSource) {\n const [, matchedStrResource] = this._findClosestUndoElementWithSource(resourceOrSource.id);\n return matchedStrResource ? this._undo(matchedStrResource, resourceOrSource.id, false) : undefined;\n }\n if (typeof resourceOrSource === 'string') {\n return this._undo(resourceOrSource, 0, false);\n }\n return this._undo(this.getUriComparisonKey(resourceOrSource), 0, false);\n }\n _undo(strResource, sourceId = 0, undoConfirmed) {\n if (!this._editStacks.has(strResource)) {\n return;\n }\n const editStack = this._editStacks.get(strResource);\n const element = editStack.getClosestPastElement();\n if (!element) {\n return;\n }\n if (element.groupId) {\n // this element is a part of a group, we need to make sure undoing in a group is in order\n const [matchedElement, matchedStrResource] = this._findClosestUndoElementInGroup(element.groupId);\n if (element !== matchedElement && matchedStrResource) {\n // there is an element in the same group that should be undone before this one\n return this._undo(matchedStrResource, sourceId, undoConfirmed);\n }\n }\n const shouldPromptForConfirmation = (element.sourceId !== sourceId || element.confirmBeforeUndo);\n if (shouldPromptForConfirmation && !undoConfirmed) {\n // Hit a different source or the element asks for prompt before undo, prompt for confirmation\n return this._confirmAndContinueUndo(strResource, sourceId, element);\n }\n try {\n if (element.type === 1 /* UndoRedoElementType.Workspace */) {\n return this._workspaceUndo(strResource, element, undoConfirmed);\n }\n else {\n return this._resourceUndo(editStack, element, undoConfirmed);\n }\n }\n finally {\n if (DEBUG) {\n this._print('undo');\n }\n }\n }\n _confirmAndContinueUndo(strResource, sourceId, element) {\n return __awaiter(this, void 0, void 0, function* () {\n const result = yield this._dialogService.show(Severity.Info, nls.localize('confirmDifferentSource', \"Would you like to undo '{0}'?\", element.label), [\n nls.localize('confirmDifferentSource.yes', \"Yes\"),\n nls.localize('confirmDifferentSource.no', \"No\"),\n ], {\n cancelId: 1\n });\n if (result.choice === 1) {\n // choice: cancel\n return;\n }\n // choice: undo\n return this._undo(strResource, sourceId, true);\n });\n }\n _findClosestRedoElementWithSource(sourceId) {\n if (!sourceId) {\n return [null, null];\n }\n // find an element with sourceId and with the lowest sourceOrder ready to be redone\n let matchedElement = null;\n let matchedStrResource = null;\n for (const [strResource, editStack] of this._editStacks) {\n const candidate = editStack.getClosestFutureElement();\n if (!candidate) {\n continue;\n }\n if (candidate.sourceId === sourceId) {\n if (!matchedElement || candidate.sourceOrder < matchedElement.sourceOrder) {\n matchedElement = candidate;\n matchedStrResource = strResource;\n }\n }\n }\n return [matchedElement, matchedStrResource];\n }\n canRedo(resourceOrSource) {\n if (resourceOrSource instanceof UndoRedoSource) {\n const [, matchedStrResource] = this._findClosestRedoElementWithSource(resourceOrSource.id);\n return matchedStrResource ? true : false;\n }\n const strResource = this.getUriComparisonKey(resourceOrSource);\n if (this._editStacks.has(strResource)) {\n const editStack = this._editStacks.get(strResource);\n return editStack.hasFutureElements();\n }\n return false;\n }\n _tryToSplitAndRedo(strResource, element, ignoreResources, message) {\n if (element.canSplit()) {\n this._splitFutureWorkspaceElement(element, ignoreResources);\n this._notificationService.warn(message);\n return new WorkspaceVerificationError(this._redo(strResource));\n }\n else {\n // Cannot safely split this workspace element => flush all undo/redo stacks\n for (const strResource of element.strResources) {\n this.removeElements(strResource);\n }\n this._notificationService.warn(message);\n return new WorkspaceVerificationError();\n }\n }\n _checkWorkspaceRedo(strResource, element, editStackSnapshot, checkInvalidatedResources) {\n if (element.removedResources) {\n return this._tryToSplitAndRedo(strResource, element, element.removedResources, nls.localize({ key: 'cannotWorkspaceRedo', comment: ['{0} is a label for an operation. {1} is another message.'] }, \"Could not redo '{0}' across all files. {1}\", element.label, element.removedResources.createMessage()));\n }\n if (checkInvalidatedResources && element.invalidatedResources) {\n return this._tryToSplitAndRedo(strResource, element, element.invalidatedResources, nls.localize({ key: 'cannotWorkspaceRedo', comment: ['{0} is a label for an operation. {1} is another message.'] }, \"Could not redo '{0}' across all files. {1}\", element.label, element.invalidatedResources.createMessage()));\n }\n // this must be the last future element in all the impacted resources!\n const cannotRedoDueToResources = [];\n for (const editStack of editStackSnapshot.editStacks) {\n if (editStack.getClosestFutureElement() !== element) {\n cannotRedoDueToResources.push(editStack.resourceLabel);\n }\n }\n if (cannotRedoDueToResources.length > 0) {\n return this._tryToSplitAndRedo(strResource, element, null, nls.localize({ key: 'cannotWorkspaceRedoDueToChanges', comment: ['{0} is a label for an operation. {1} is a list of filenames.'] }, \"Could not redo '{0}' across all files because changes were made to {1}\", element.label, cannotRedoDueToResources.join(', ')));\n }\n const cannotLockDueToResources = [];\n for (const editStack of editStackSnapshot.editStacks) {\n if (editStack.locked) {\n cannotLockDueToResources.push(editStack.resourceLabel);\n }\n }\n if (cannotLockDueToResources.length > 0) {\n return this._tryToSplitAndRedo(strResource, element, null, nls.localize({ key: 'cannotWorkspaceRedoDueToInProgressUndoRedo', comment: ['{0} is a label for an operation. {1} is a list of filenames.'] }, \"Could not redo '{0}' across all files because there is already an undo or redo operation running on {1}\", element.label, cannotLockDueToResources.join(', ')));\n }\n // check if new stack elements were added in the meantime...\n if (!editStackSnapshot.isValid()) {\n return this._tryToSplitAndRedo(strResource, element, null, nls.localize({ key: 'cannotWorkspaceRedoDueToInMeantimeUndoRedo', comment: ['{0} is a label for an operation. {1} is a list of filenames.'] }, \"Could not redo '{0}' across all files because an undo or redo operation occurred in the meantime\", element.label));\n }\n return null;\n }\n _workspaceRedo(strResource, element) {\n const affectedEditStacks = this._getAffectedEditStacks(element);\n const verificationError = this._checkWorkspaceRedo(strResource, element, affectedEditStacks, /*invalidated resources will be checked after the prepare call*/ false);\n if (verificationError) {\n return verificationError.returnValue;\n }\n return this._executeWorkspaceRedo(strResource, element, affectedEditStacks);\n }\n _executeWorkspaceRedo(strResource, element, editStackSnapshot) {\n return __awaiter(this, void 0, void 0, function* () {\n // prepare\n let cleanup;\n try {\n cleanup = yield this._invokeWorkspacePrepare(element);\n }\n catch (err) {\n return this._onError(err, element);\n }\n // At this point, it is possible that the element has been made invalid in the meantime (due to the prepare await)\n const verificationError = this._checkWorkspaceRedo(strResource, element, editStackSnapshot, /*now also check that there are no more invalidated resources*/ true);\n if (verificationError) {\n cleanup.dispose();\n return verificationError.returnValue;\n }\n for (const editStack of editStackSnapshot.editStacks) {\n editStack.moveForward(element);\n }\n return this._safeInvokeWithLocks(element, () => element.actual.redo(), editStackSnapshot, cleanup, () => this._continueRedoInGroup(element.groupId));\n });\n }\n _resourceRedo(editStack, element) {\n if (!element.isValid) {\n // invalid element => immediately flush edit stack!\n editStack.flushAllElements();\n return;\n }\n if (editStack.locked) {\n const message = nls.localize({ key: 'cannotResourceRedoDueToInProgressUndoRedo', comment: ['{0} is a label for an operation.'] }, \"Could not redo '{0}' because there is already an undo or redo operation running.\", element.label);\n this._notificationService.warn(message);\n return;\n }\n return this._invokeResourcePrepare(element, (cleanup) => {\n editStack.moveForward(element);\n return this._safeInvokeWithLocks(element, () => element.actual.redo(), new EditStackSnapshot([editStack]), cleanup, () => this._continueRedoInGroup(element.groupId));\n });\n }\n _findClosestRedoElementInGroup(groupId) {\n if (!groupId) {\n return [null, null];\n }\n // find another element with the same groupId and with the lowest groupOrder ready to be redone\n let matchedElement = null;\n let matchedStrResource = null;\n for (const [strResource, editStack] of this._editStacks) {\n const candidate = editStack.getClosestFutureElement();\n if (!candidate) {\n continue;\n }\n if (candidate.groupId === groupId) {\n if (!matchedElement || candidate.groupOrder < matchedElement.groupOrder) {\n matchedElement = candidate;\n matchedStrResource = strResource;\n }\n }\n }\n return [matchedElement, matchedStrResource];\n }\n _continueRedoInGroup(groupId) {\n if (!groupId) {\n return;\n }\n const [, matchedStrResource] = this._findClosestRedoElementInGroup(groupId);\n if (matchedStrResource) {\n return this._redo(matchedStrResource);\n }\n }\n redo(resourceOrSource) {\n if (resourceOrSource instanceof UndoRedoSource) {\n const [, matchedStrResource] = this._findClosestRedoElementWithSource(resourceOrSource.id);\n return matchedStrResource ? this._redo(matchedStrResource) : undefined;\n }\n if (typeof resourceOrSource === 'string') {\n return this._redo(resourceOrSource);\n }\n return this._redo(this.getUriComparisonKey(resourceOrSource));\n }\n _redo(strResource) {\n if (!this._editStacks.has(strResource)) {\n return;\n }\n const editStack = this._editStacks.get(strResource);\n const element = editStack.getClosestFutureElement();\n if (!element) {\n return;\n }\n if (element.groupId) {\n // this element is a part of a group, we need to make sure redoing in a group is in order\n const [matchedElement, matchedStrResource] = this._findClosestRedoElementInGroup(element.groupId);\n if (element !== matchedElement && matchedStrResource) {\n // there is an element in the same group that should be redone before this one\n return this._redo(matchedStrResource);\n }\n }\n try {\n if (element.type === 1 /* UndoRedoElementType.Workspace */) {\n return this._workspaceRedo(strResource, element);\n }\n else {\n return this._resourceRedo(editStack, element);\n }\n }\n finally {\n if (DEBUG) {\n this._print('redo');\n }\n }\n }\n};\nUndoRedoService = __decorate([\n __param(0, IDialogService),\n __param(1, INotificationService)\n], UndoRedoService);\nexport { UndoRedoService };\nclass WorkspaceVerificationError {\n constructor(returnValue) {\n this.returnValue = returnValue;\n }\n}\nregisterSingleton(IUndoRedoService, UndoRedoService);\n","/*---------------------------------------------------------------------------------------------\n * 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 * as arrays from '../../../base/common/arrays.js';\nimport { ResourceMap } from '../../../base/common/map.js';\nimport * as objects from '../../../base/common/objects.js';\nimport * as types from '../../../base/common/types.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { addToValueTree, getConfigurationValue, removeFromValueTree, toValuesTree } from './configuration.js';\nexport class ConfigurationModel {\n constructor(_contents = {}, _keys = [], _overrides = []) {\n this._contents = _contents;\n this._keys = _keys;\n this._overrides = _overrides;\n this.frozen = false;\n this.overrideConfigurations = new Map();\n }\n get contents() {\n return this.checkAndFreeze(this._contents);\n }\n get overrides() {\n return this.checkAndFreeze(this._overrides);\n }\n get keys() {\n return this.checkAndFreeze(this._keys);\n }\n isEmpty() {\n return this._keys.length === 0 && Object.keys(this._contents).length === 0 && this._overrides.length === 0;\n }\n getValue(section) {\n return section ? getConfigurationValue(this.contents, section) : this.contents;\n }\n getOverrideValue(section, overrideIdentifier) {\n const overrideContents = this.getContentsForOverrideIdentifer(overrideIdentifier);\n return overrideContents\n ? section ? getConfigurationValue(overrideContents, section) : overrideContents\n : undefined;\n }\n override(identifier) {\n let overrideConfigurationModel = this.overrideConfigurations.get(identifier);\n if (!overrideConfigurationModel) {\n overrideConfigurationModel = this.createOverrideConfigurationModel(identifier);\n this.overrideConfigurations.set(identifier, overrideConfigurationModel);\n }\n return overrideConfigurationModel;\n }\n merge(...others) {\n const contents = objects.deepClone(this.contents);\n const overrides = objects.deepClone(this.overrides);\n const keys = [...this.keys];\n for (const other of others) {\n if (other.isEmpty()) {\n continue;\n }\n this.mergeContents(contents, other.contents);\n for (const otherOverride of other.overrides) {\n const [override] = overrides.filter(o => arrays.equals(o.identifiers, otherOverride.identifiers));\n if (override) {\n this.mergeContents(override.contents, otherOverride.contents);\n override.keys.push(...otherOverride.keys);\n override.keys = arrays.distinct(override.keys);\n }\n else {\n overrides.push(objects.deepClone(otherOverride));\n }\n }\n for (const key of other.keys) {\n if (keys.indexOf(key) === -1) {\n keys.push(key);\n }\n }\n }\n return new ConfigurationModel(contents, keys, overrides);\n }\n freeze() {\n this.frozen = true;\n return this;\n }\n createOverrideConfigurationModel(identifier) {\n const overrideContents = this.getContentsForOverrideIdentifer(identifier);\n if (!overrideContents || typeof overrideContents !== 'object' || !Object.keys(overrideContents).length) {\n // If there are no valid overrides, return self\n return this;\n }\n const contents = {};\n for (const key of arrays.distinct([...Object.keys(this.contents), ...Object.keys(overrideContents)])) {\n let contentsForKey = this.contents[key];\n const overrideContentsForKey = overrideContents[key];\n // If there are override contents for the key, clone and merge otherwise use base contents\n if (overrideContentsForKey) {\n // Clone and merge only if base contents and override contents are of type object otherwise just override\n if (typeof contentsForKey === 'object' && typeof overrideContentsForKey === 'object') {\n contentsForKey = objects.deepClone(contentsForKey);\n this.mergeContents(contentsForKey, overrideContentsForKey);\n }\n else {\n contentsForKey = overrideContentsForKey;\n }\n }\n contents[key] = contentsForKey;\n }\n return new ConfigurationModel(contents, this.keys, this.overrides);\n }\n mergeContents(source, target) {\n for (const key of Object.keys(target)) {\n if (key in source) {\n if (types.isObject(source[key]) && types.isObject(target[key])) {\n this.mergeContents(source[key], target[key]);\n continue;\n }\n }\n source[key] = objects.deepClone(target[key]);\n }\n }\n checkAndFreeze(data) {\n if (this.frozen && !Object.isFrozen(data)) {\n return objects.deepFreeze(data);\n }\n return data;\n }\n getContentsForOverrideIdentifer(identifier) {\n let contentsForIdentifierOnly = null;\n let contents = null;\n const mergeContents = (contentsToMerge) => {\n if (contentsToMerge) {\n if (contents) {\n this.mergeContents(contents, contentsToMerge);\n }\n else {\n contents = objects.deepClone(contentsToMerge);\n }\n }\n };\n for (const override of this.overrides) {\n if (arrays.equals(override.identifiers, [identifier])) {\n contentsForIdentifierOnly = override.contents;\n }\n else if (override.identifiers.includes(identifier)) {\n mergeContents(override.contents);\n }\n }\n // Merge contents of the identifier only at the end to take precedence.\n mergeContents(contentsForIdentifierOnly);\n return contents;\n }\n toJSON() {\n return {\n contents: this.contents,\n overrides: this.overrides,\n keys: this.keys\n };\n }\n // Update methods\n setValue(key, value) {\n this.addKey(key);\n addToValueTree(this.contents, key, value, e => { throw new Error(e); });\n }\n removeValue(key) {\n if (this.removeKey(key)) {\n removeFromValueTree(this.contents, key);\n }\n }\n addKey(key) {\n let index = this.keys.length;\n for (let i = 0; i < index; i++) {\n if (key.indexOf(this.keys[i]) === 0) {\n index = i;\n }\n }\n this.keys.splice(index, 1, key);\n }\n removeKey(key) {\n const index = this.keys.indexOf(key);\n if (index !== -1) {\n this.keys.splice(index, 1);\n return true;\n }\n return false;\n }\n}\nexport class Configuration {\n constructor(_defaultConfiguration, _policyConfiguration, _applicationConfiguration, _localUserConfiguration, _remoteUserConfiguration = new ConfigurationModel(), _workspaceConfiguration = new ConfigurationModel(), _folderConfigurations = new ResourceMap(), _memoryConfiguration = new ConfigurationModel(), _memoryConfigurationByResource = new ResourceMap(), _freeze = true) {\n this._defaultConfiguration = _defaultConfiguration;\n this._policyConfiguration = _policyConfiguration;\n this._applicationConfiguration = _applicationConfiguration;\n this._localUserConfiguration = _localUserConfiguration;\n this._remoteUserConfiguration = _remoteUserConfiguration;\n this._workspaceConfiguration = _workspaceConfiguration;\n this._folderConfigurations = _folderConfigurations;\n this._memoryConfiguration = _memoryConfiguration;\n this._memoryConfigurationByResource = _memoryConfigurationByResource;\n this._freeze = _freeze;\n this._workspaceConsolidatedConfiguration = null;\n this._foldersConsolidatedConfigurations = new ResourceMap();\n this._userConfiguration = null;\n }\n getValue(section, overrides, workspace) {\n const consolidateConfigurationModel = this.getConsolidatedConfigurationModel(section, overrides, workspace);\n return consolidateConfigurationModel.getValue(section);\n }\n updateValue(key, value, overrides = {}) {\n let memoryConfiguration;\n if (overrides.resource) {\n memoryConfiguration = this._memoryConfigurationByResource.get(overrides.resource);\n if (!memoryConfiguration) {\n memoryConfiguration = new ConfigurationModel();\n this._memoryConfigurationByResource.set(overrides.resource, memoryConfiguration);\n }\n }\n else {\n memoryConfiguration = this._memoryConfiguration;\n }\n if (value === undefined) {\n memoryConfiguration.removeValue(key);\n }\n else {\n memoryConfiguration.setValue(key, value);\n }\n if (!overrides.resource) {\n this._workspaceConsolidatedConfiguration = null;\n }\n }\n inspect(key, overrides, workspace) {\n const consolidateConfigurationModel = this.getConsolidatedConfigurationModel(key, overrides, workspace);\n const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource, workspace);\n const memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration;\n const defaultValue = overrides.overrideIdentifier ? this._defaultConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this._defaultConfiguration.freeze().getValue(key);\n const policyValue = this._policyConfiguration.isEmpty() ? undefined : this._policyConfiguration.freeze().getValue(key);\n const applicationValue = this.applicationConfiguration.isEmpty() ? undefined : this.applicationConfiguration.freeze().getValue(key);\n const userValue = overrides.overrideIdentifier ? this.userConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.userConfiguration.freeze().getValue(key);\n const userLocalValue = overrides.overrideIdentifier ? this.localUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.localUserConfiguration.freeze().getValue(key);\n const userRemoteValue = overrides.overrideIdentifier ? this.remoteUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.remoteUserConfiguration.freeze().getValue(key);\n const 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 const workspaceFolderValue = folderConfigurationModel ? overrides.overrideIdentifier ? folderConfigurationModel.freeze().override(overrides.overrideIdentifier).getValue(key) : folderConfigurationModel.freeze().getValue(key) : undefined;\n const memoryValue = overrides.overrideIdentifier ? memoryConfigurationModel.override(overrides.overrideIdentifier).getValue(key) : memoryConfigurationModel.getValue(key);\n const value = consolidateConfigurationModel.getValue(key);\n const overrideIdentifiers = arrays.distinct(consolidateConfigurationModel.overrides.map(override => override.identifiers).flat()).filter(overrideIdentifier => consolidateConfigurationModel.getOverrideValue(key, overrideIdentifier) !== undefined);\n return {\n defaultValue,\n policyValue,\n applicationValue,\n userValue,\n userLocalValue,\n userRemoteValue,\n workspaceValue,\n workspaceFolderValue,\n memoryValue,\n value,\n default: defaultValue !== undefined ? { value: this._defaultConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this._defaultConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n policy: policyValue !== undefined ? { value: policyValue } : undefined,\n application: applicationValue !== undefined ? { value: applicationValue, override: overrides.overrideIdentifier ? this.applicationConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n user: userValue !== undefined ? { value: this.userConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.userConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n userLocal: userLocalValue !== undefined ? { value: this.localUserConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.localUserConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n userRemote: userRemoteValue !== undefined ? { value: this.remoteUserConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.remoteUserConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n workspace: workspaceValue !== undefined ? { value: this._workspaceConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this._workspaceConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n workspaceFolder: workspaceFolderValue !== undefined ? { value: folderConfigurationModel === null || folderConfigurationModel === void 0 ? void 0 : folderConfigurationModel.freeze().getValue(key), override: overrides.overrideIdentifier ? folderConfigurationModel === null || folderConfigurationModel === void 0 ? void 0 : folderConfigurationModel.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n memory: memoryValue !== undefined ? { value: memoryConfigurationModel.getValue(key), override: overrides.overrideIdentifier ? memoryConfigurationModel.getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,\n overrideIdentifiers: overrideIdentifiers.length ? overrideIdentifiers : undefined\n };\n }\n get applicationConfiguration() {\n return this._applicationConfiguration;\n }\n get userConfiguration() {\n if (!this._userConfiguration) {\n this._userConfiguration = this._remoteUserConfiguration.isEmpty() ? this._localUserConfiguration : this._localUserConfiguration.merge(this._remoteUserConfiguration);\n if (this._freeze) {\n this._userConfiguration.freeze();\n }\n }\n return this._userConfiguration;\n }\n get localUserConfiguration() {\n return this._localUserConfiguration;\n }\n get remoteUserConfiguration() {\n return this._remoteUserConfiguration;\n }\n getConsolidatedConfigurationModel(section, overrides, workspace) {\n let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides, workspace);\n if (overrides.overrideIdentifier) {\n configurationModel = configurationModel.override(overrides.overrideIdentifier);\n }\n if (!this._policyConfiguration.isEmpty() && this._policyConfiguration.getValue(section) !== undefined) {\n configurationModel = configurationModel.merge(this._policyConfiguration);\n }\n return configurationModel;\n }\n getConsolidatedConfigurationModelForResource({ resource }, workspace) {\n let consolidateConfiguration = this.getWorkspaceConsolidatedConfiguration();\n if (workspace && resource) {\n const root = workspace.getFolder(resource);\n if (root) {\n consolidateConfiguration = this.getFolderConsolidatedConfiguration(root.uri) || consolidateConfiguration;\n }\n const memoryConfigurationForResource = this._memoryConfigurationByResource.get(resource);\n if (memoryConfigurationForResource) {\n consolidateConfiguration = consolidateConfiguration.merge(memoryConfigurationForResource);\n }\n }\n return consolidateConfiguration;\n }\n getWorkspaceConsolidatedConfiguration() {\n if (!this._workspaceConsolidatedConfiguration) {\n this._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this.applicationConfiguration, this.userConfiguration, this._workspaceConfiguration, this._memoryConfiguration);\n if (this._freeze) {\n this._workspaceConfiguration = this._workspaceConfiguration.freeze();\n }\n }\n return this._workspaceConsolidatedConfiguration;\n }\n getFolderConsolidatedConfiguration(folder) {\n let folderConsolidatedConfiguration = this._foldersConsolidatedConfigurations.get(folder);\n if (!folderConsolidatedConfiguration) {\n const workspaceConsolidateConfiguration = this.getWorkspaceConsolidatedConfiguration();\n const folderConfiguration = this._folderConfigurations.get(folder);\n if (folderConfiguration) {\n folderConsolidatedConfiguration = workspaceConsolidateConfiguration.merge(folderConfiguration);\n if (this._freeze) {\n folderConsolidatedConfiguration = folderConsolidatedConfiguration.freeze();\n }\n this._foldersConsolidatedConfigurations.set(folder, folderConsolidatedConfiguration);\n }\n else {\n folderConsolidatedConfiguration = workspaceConsolidateConfiguration;\n }\n }\n return folderConsolidatedConfiguration;\n }\n getFolderConfigurationModelForResource(resource, workspace) {\n if (workspace && resource) {\n const root = workspace.getFolder(resource);\n if (root) {\n return this._folderConfigurations.get(root.uri);\n }\n }\n return undefined;\n }\n toData() {\n return {\n defaults: {\n contents: this._defaultConfiguration.contents,\n overrides: this._defaultConfiguration.overrides,\n keys: this._defaultConfiguration.keys\n },\n policy: {\n contents: this._policyConfiguration.contents,\n overrides: this._policyConfiguration.overrides,\n keys: this._policyConfiguration.keys\n },\n application: {\n contents: this.applicationConfiguration.contents,\n overrides: this.applicationConfiguration.overrides,\n keys: this.applicationConfiguration.keys\n },\n user: {\n contents: this.userConfiguration.contents,\n overrides: this.userConfiguration.overrides,\n keys: this.userConfiguration.keys\n },\n workspace: {\n contents: this._workspaceConfiguration.contents,\n overrides: this._workspaceConfiguration.overrides,\n keys: this._workspaceConfiguration.keys\n },\n folders: [...this._folderConfigurations.keys()].reduce((result, folder) => {\n const { contents, overrides, keys } = this._folderConfigurations.get(folder);\n result.push([folder, { contents, overrides, keys }]);\n return result;\n }, [])\n };\n }\n static parse(data) {\n const defaultConfiguration = this.parseConfigurationModel(data.defaults);\n const policyConfiguration = this.parseConfigurationModel(data.policy);\n const applicationConfiguration = this.parseConfigurationModel(data.application);\n const userConfiguration = this.parseConfigurationModel(data.user);\n const workspaceConfiguration = this.parseConfigurationModel(data.workspace);\n const folders = data.folders.reduce((result, value) => {\n result.set(URI.revive(value[0]), this.parseConfigurationModel(value[1]));\n return result;\n }, new ResourceMap());\n return new Configuration(defaultConfiguration, policyConfiguration, applicationConfiguration, userConfiguration, new ConfigurationModel(), workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap(), false);\n }\n static parseConfigurationModel(model) {\n return new ConfigurationModel(model.contents, model.keys, model.overrides).freeze();\n }\n}\nexport class ConfigurationChangeEvent {\n constructor(change, previous, currentConfiguraiton, currentWorkspace) {\n this.change = change;\n this.previous = previous;\n this.currentConfiguraiton = currentConfiguraiton;\n this.currentWorkspace = currentWorkspace;\n this._previousConfiguration = undefined;\n const keysSet = new Set();\n change.keys.forEach(key => keysSet.add(key));\n change.overrides.forEach(([, keys]) => keys.forEach(key => keysSet.add(key)));\n this.affectedKeys = [...keysSet.values()];\n const configurationModel = new ConfigurationModel();\n this.affectedKeys.forEach(key => configurationModel.setValue(key, {}));\n this.affectedKeysTree = configurationModel.contents;\n }\n get previousConfiguration() {\n if (!this._previousConfiguration && this.previous) {\n this._previousConfiguration = Configuration.parse(this.previous.data);\n }\n return this._previousConfiguration;\n }\n affectsConfiguration(section, overrides) {\n var _a;\n if (this.doesAffectedKeysTreeContains(this.affectedKeysTree, section)) {\n if (overrides) {\n const value1 = this.previousConfiguration ? this.previousConfiguration.getValue(section, overrides, (_a = this.previous) === null || _a === void 0 ? void 0 : _a.workspace) : undefined;\n const value2 = this.currentConfiguraiton.getValue(section, overrides, this.currentWorkspace);\n return !objects.equals(value1, value2);\n }\n return true;\n }\n return false;\n }\n doesAffectedKeysTreeContains(affectedKeysTree, section) {\n let requestedTree = toValuesTree({ [section]: true }, () => { });\n let key;\n while (typeof requestedTree === 'object' && (key = Object.keys(requestedTree)[0])) { // Only one key should present, since we added only one property\n affectedKeysTree = affectedKeysTree[key];\n if (!affectedKeysTree) {\n return false; // Requested tree is not found\n }\n requestedTree = requestedTree[key];\n }\n return true;\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 *--------------------------------------------------------------------------------------------*/\nimport { IntervalTimer, TimeoutTimer } from '../../../base/common/async.js';\nimport { Emitter, Event } from '../../../base/common/event.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport * as nls from '../../../nls.js';\nconst HIGH_FREQ_COMMANDS = /^(cursor|delete)/;\nexport class AbstractKeybindingService extends Disposable {\n constructor(_contextKeyService, _commandService, _telemetryService, _notificationService, _logService) {\n super();\n this._contextKeyService = _contextKeyService;\n this._commandService = _commandService;\n this._telemetryService = _telemetryService;\n this._notificationService = _notificationService;\n this._logService = _logService;\n this._onDidUpdateKeybindings = this._register(new Emitter());\n this._currentChord = null;\n this._currentChordChecker = new IntervalTimer();\n this._currentChordStatusMessage = null;\n this._ignoreSingleModifiers = KeybindingModifierSet.EMPTY;\n this._currentSingleModifier = null;\n this._currentSingleModifierClearTimeout = new TimeoutTimer();\n this._logging = false;\n }\n get onDidUpdateKeybindings() {\n return this._onDidUpdateKeybindings ? this._onDidUpdateKeybindings.event : Event.None; // Sinon stubbing walks properties on prototype\n }\n dispose() {\n super.dispose();\n }\n _log(str) {\n if (this._logging) {\n this._logService.info(`[KeybindingService]: ${str}`);\n }\n }\n getKeybindings() {\n return this._getResolver().getKeybindings();\n }\n lookupKeybinding(commandId, context) {\n const result = this._getResolver().lookupPrimaryKeybinding(commandId, context || this._contextKeyService);\n if (!result) {\n return undefined;\n }\n return result.resolvedKeybinding;\n }\n dispatchEvent(e, target) {\n return this._dispatch(e, target);\n }\n softDispatch(e, target) {\n this._log(`/ Soft dispatching keyboard event`);\n const keybinding = this.resolveKeyboardEvent(e);\n if (keybinding.isChord()) {\n console.warn('Unexpected keyboard event mapped to a chord');\n return null;\n }\n const [firstPart,] = keybinding.getDispatchParts();\n if (firstPart === null) {\n // cannot be dispatched, probably only modifier keys\n this._log(`\\\\ Keyboard event cannot be dispatched`);\n return null;\n }\n const contextValue = this._contextKeyService.getContext(target);\n const currentChord = this._currentChord ? this._currentChord.keypress : null;\n return this._getResolver().resolve(contextValue, currentChord, firstPart);\n }\n _enterChordMode(firstPart, keypressLabel) {\n this._currentChord = {\n keypress: firstPart,\n label: keypressLabel\n };\n this._currentChordStatusMessage = this._notificationService.status(nls.localize('first.chord', \"({0}) was pressed. Waiting for second key of chord...\", keypressLabel));\n const chordEnterTime = Date.now();\n this._currentChordChecker.cancelAndSet(() => {\n if (!this._documentHasFocus()) {\n // Focus has been lost => leave chord mode\n this._leaveChordMode();\n return;\n }\n if (Date.now() - chordEnterTime > 5000) {\n // 5 seconds elapsed => leave chord mode\n this._leaveChordMode();\n }\n }, 500);\n }\n _leaveChordMode() {\n if (this._currentChordStatusMessage) {\n this._currentChordStatusMessage.dispose();\n this._currentChordStatusMessage = null;\n }\n this._currentChordChecker.cancel();\n this._currentChord = null;\n }\n _dispatch(e, target) {\n return this._doDispatch(this.resolveKeyboardEvent(e), target, /*isSingleModiferChord*/ false);\n }\n _singleModifierDispatch(e, target) {\n const keybinding = this.resolveKeyboardEvent(e);\n const [singleModifier,] = keybinding.getSingleModifierDispatchParts();\n if (singleModifier) {\n if (this._ignoreSingleModifiers.has(singleModifier)) {\n this._log(`+ Ignoring single modifier ${singleModifier} due to it being pressed together with other keys.`);\n this._ignoreSingleModifiers = KeybindingModifierSet.EMPTY;\n this._currentSingleModifierClearTimeout.cancel();\n this._currentSingleModifier = null;\n return false;\n }\n this._ignoreSingleModifiers = KeybindingModifierSet.EMPTY;\n if (this._currentSingleModifier === null) {\n // we have a valid `singleModifier`, store it for the next keyup, but clear it in 300ms\n this._log(`+ Storing single modifier for possible chord ${singleModifier}.`);\n this._currentSingleModifier = singleModifier;\n this._currentSingleModifierClearTimeout.cancelAndSet(() => {\n this._log(`+ Clearing single modifier due to 300ms elapsed.`);\n this._currentSingleModifier = null;\n }, 300);\n return false;\n }\n if (singleModifier === this._currentSingleModifier) {\n // bingo!\n this._log(`/ Dispatching single modifier chord ${singleModifier} ${singleModifier}`);\n this._currentSingleModifierClearTimeout.cancel();\n this._currentSingleModifier = null;\n return this._doDispatch(keybinding, target, /*isSingleModiferChord*/ true);\n }\n this._log(`+ Clearing single modifier due to modifier mismatch: ${this._currentSingleModifier} ${singleModifier}`);\n this._currentSingleModifierClearTimeout.cancel();\n this._currentSingleModifier = null;\n return false;\n }\n // When pressing a modifier and holding it pressed with any other modifier or key combination,\n // the pressed modifiers should no longer be considered for single modifier dispatch.\n const [firstPart,] = keybinding.getParts();\n this._ignoreSingleModifiers = new KeybindingModifierSet(firstPart);\n if (this._currentSingleModifier !== null) {\n this._log(`+ Clearing single modifier due to other key up.`);\n }\n this._currentSingleModifierClearTimeout.cancel();\n this._currentSingleModifier = null;\n return false;\n }\n _doDispatch(keybinding, target, isSingleModiferChord = false) {\n let shouldPreventDefault = false;\n if (keybinding.isChord()) {\n console.warn('Unexpected keyboard event mapped to a chord');\n return false;\n }\n let firstPart = null; // the first keybinding i.e. Ctrl+K\n let currentChord = null; // the \"second\" keybinding i.e. Ctrl+K \"Ctrl+D\"\n if (isSingleModiferChord) {\n const [dispatchKeyname,] = keybinding.getSingleModifierDispatchParts();\n firstPart = dispatchKeyname;\n currentChord = dispatchKeyname;\n }\n else {\n [firstPart,] = keybinding.getDispatchParts();\n currentChord = this._currentChord ? this._currentChord.keypress : null;\n }\n if (firstPart === null) {\n this._log(`\\\\ Keyboard event cannot be dispatched in keydown phase.`);\n // cannot be dispatched, probably only modifier keys\n return shouldPreventDefault;\n }\n const contextValue = this._contextKeyService.getContext(target);\n const keypressLabel = keybinding.getLabel();\n const resolveResult = this._getResolver().resolve(contextValue, currentChord, firstPart);\n this._logService.trace('KeybindingService#dispatch', keypressLabel, resolveResult === null || resolveResult === void 0 ? void 0 : resolveResult.commandId);\n if (resolveResult && resolveResult.enterChord) {\n shouldPreventDefault = true;\n this._enterChordMode(firstPart, keypressLabel);\n this._log(`+ Entering chord mode...`);\n return shouldPreventDefault;\n }\n if (this._currentChord) {\n if (!resolveResult || !resolveResult.commandId) {\n this._log(`+ Leaving chord mode: Nothing bound to \"${this._currentChord.label} ${keypressLabel}\".`);\n this._notificationService.status(nls.localize('missing.chord', \"The key combination ({0}, {1}) is not a command.\", this._currentChord.label, keypressLabel), { hideAfter: 10 * 1000 /* 10s */ });\n shouldPreventDefault = true;\n }\n }\n this._leaveChordMode();\n if (resolveResult && resolveResult.commandId) {\n if (!resolveResult.bubble) {\n shouldPreventDefault = true;\n }\n this._log(`+ Invoking command ${resolveResult.commandId}.`);\n if (typeof resolveResult.commandArgs === 'undefined') {\n this._commandService.executeCommand(resolveResult.commandId).then(undefined, err => this._notificationService.warn(err));\n }\n else {\n this._commandService.executeCommand(resolveResult.commandId, resolveResult.commandArgs).then(undefined, err => this._notificationService.warn(err));\n }\n if (!HIGH_FREQ_COMMANDS.test(resolveResult.commandId)) {\n this._telemetryService.publicLog2('workbenchActionExecuted', { id: resolveResult.commandId, from: 'keybinding' });\n }\n }\n return shouldPreventDefault;\n }\n mightProducePrintableCharacter(event) {\n if (event.ctrlKey || event.metaKey) {\n // ignore ctrl/cmd-combination but not shift/alt-combinatios\n return false;\n }\n // weak check for certain ranges. this is properly implemented in a subclass\n // with access to the KeyboardMapperFactory.\n if ((event.keyCode >= 31 /* KeyCode.KeyA */ && event.keyCode <= 56 /* KeyCode.KeyZ */)\n || (event.keyCode >= 21 /* KeyCode.Digit0 */ && event.keyCode <= 30 /* KeyCode.Digit9 */)) {\n return true;\n }\n return false;\n }\n}\nclass KeybindingModifierSet {\n constructor(source) {\n this._ctrlKey = source ? source.ctrlKey : false;\n this._shiftKey = source ? source.shiftKey : false;\n this._altKey = source ? source.altKey : false;\n this._metaKey = source ? source.metaKey : false;\n }\n has(modifier) {\n switch (modifier) {\n case 'ctrl': return this._ctrlKey;\n case 'shift': return this._shiftKey;\n case 'alt': return this._altKey;\n case 'meta': return this._metaKey;\n }\n }\n}\nKeybindingModifierSet.EMPTY = new KeybindingModifierSet(null);\n","/*---------------------------------------------------------------------------------------------\n * 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 { implies, expressionsAreEqualWithConstantSubstitution } from '../../contextkey/common/contextkey.js';\nexport class KeybindingResolver {\n constructor(defaultKeybindings, overrides, log) {\n this._log = log;\n this._defaultKeybindings = defaultKeybindings;\n this._defaultBoundCommands = new Map();\n for (const defaultKeybinding of defaultKeybindings) {\n const command = defaultKeybinding.command;\n if (command && command.charAt(0) !== '-') {\n this._defaultBoundCommands.set(command, true);\n }\n }\n this._map = new Map();\n this._lookupMap = new Map();\n this._keybindings = KeybindingResolver.handleRemovals([].concat(defaultKeybindings).concat(overrides));\n for (let i = 0, len = this._keybindings.length; i < len; i++) {\n const k = this._keybindings[i];\n if (k.keypressParts.length === 0) {\n // unbound\n continue;\n }\n if (k.when && k.when.type === 0 /* ContextKeyExprType.False */) {\n // when condition is false\n continue;\n }\n // TODO@chords\n this._addKeyPress(k.keypressParts[0], k);\n }\n }\n static _isTargetedForRemoval(defaultKb, keypressFirstPart, keypressChordPart, when) {\n // TODO@chords\n if (keypressFirstPart && defaultKb.keypressParts[0] !== keypressFirstPart) {\n return false;\n }\n // TODO@chords\n if (keypressChordPart && defaultKb.keypressParts[1] !== keypressChordPart) {\n return false;\n }\n if (when) {\n if (!defaultKb.when) {\n return false;\n }\n if (!expressionsAreEqualWithConstantSubstitution(when, defaultKb.when)) {\n return false;\n }\n }\n return true;\n }\n /**\n * Looks for rules containing \"-commandId\" and removes them.\n */\n static handleRemovals(rules) {\n // Do a first pass and construct a hash-map for removals\n const removals = new Map();\n for (let i = 0, len = rules.length; i < len; i++) {\n const rule = rules[i];\n if (rule.command && rule.command.charAt(0) === '-') {\n const command = rule.command.substring(1);\n if (!removals.has(command)) {\n removals.set(command, [rule]);\n }\n else {\n removals.get(command).push(rule);\n }\n }\n }\n if (removals.size === 0) {\n // There are no removals\n return rules;\n }\n // Do a second pass and keep only non-removed keybindings\n const result = [];\n for (let i = 0, len = rules.length; i < len; i++) {\n const rule = rules[i];\n if (!rule.command || rule.command.length === 0) {\n result.push(rule);\n continue;\n }\n if (rule.command.charAt(0) === '-') {\n continue;\n }\n const commandRemovals = removals.get(rule.command);\n if (!commandRemovals || !rule.isDefault) {\n result.push(rule);\n continue;\n }\n let isRemoved = false;\n for (const commandRemoval of commandRemovals) {\n // TODO@chords\n const keypressFirstPart = commandRemoval.keypressParts[0];\n const keypressChordPart = commandRemoval.keypressParts[1];\n const when = commandRemoval.when;\n if (this._isTargetedForRemoval(rule, keypressFirstPart, keypressChordPart, when)) {\n isRemoved = true;\n break;\n }\n }\n if (!isRemoved) {\n result.push(rule);\n continue;\n }\n }\n return result;\n }\n _addKeyPress(keypress, item) {\n const conflicts = this._map.get(keypress);\n if (typeof conflicts === 'undefined') {\n // There is no conflict so far\n this._map.set(keypress, [item]);\n this._addToLookupMap(item);\n return;\n }\n for (let i = conflicts.length - 1; i >= 0; i--) {\n const conflict = conflicts[i];\n if (conflict.command === item.command) {\n continue;\n }\n const conflictIsChord = (conflict.keypressParts.length > 1);\n const itemIsChord = (item.keypressParts.length > 1);\n // TODO@chords\n if (conflictIsChord && itemIsChord && conflict.keypressParts[1] !== item.keypressParts[1]) {\n // The conflict only shares the chord start with this command\n continue;\n }\n if (KeybindingResolver.whenIsEntirelyIncluded(conflict.when, item.when)) {\n // `item` completely overwrites `conflict`\n // Remove conflict from the lookupMap\n this._removeFromLookupMap(conflict);\n }\n }\n conflicts.push(item);\n this._addToLookupMap(item);\n }\n _addToLookupMap(item) {\n if (!item.command) {\n return;\n }\n let arr = this._lookupMap.get(item.command);\n if (typeof arr === 'undefined') {\n arr = [item];\n this._lookupMap.set(item.command, arr);\n }\n else {\n arr.push(item);\n }\n }\n _removeFromLookupMap(item) {\n if (!item.command) {\n return;\n }\n const arr = this._lookupMap.get(item.command);\n if (typeof arr === 'undefined') {\n return;\n }\n for (let i = 0, len = arr.length; i < len; i++) {\n if (arr[i] === item) {\n arr.splice(i, 1);\n return;\n }\n }\n }\n /**\n * Returns true if it is provable `a` implies `b`.\n */\n static whenIsEntirelyIncluded(a, b) {\n if (!b || b.type === 1 /* ContextKeyExprType.True */) {\n return true;\n }\n if (!a || a.type === 1 /* ContextKeyExprType.True */) {\n return false;\n }\n return implies(a, b);\n }\n getKeybindings() {\n return this._keybindings;\n }\n lookupPrimaryKeybinding(commandId, context) {\n const items = this._lookupMap.get(commandId);\n if (typeof items === 'undefined' || items.length === 0) {\n return null;\n }\n if (items.length === 1) {\n return items[0];\n }\n for (let i = items.length - 1; i >= 0; i--) {\n const item = items[i];\n if (context.contextMatchesRules(item.when)) {\n return item;\n }\n }\n return items[items.length - 1];\n }\n resolve(context, currentChord, keypress) {\n this._log(`| Resolving ${keypress}${currentChord ? ` chorded from ${currentChord}` : ``}`);\n let lookupMap = null;\n if (currentChord !== null) {\n // Fetch all chord bindings for `currentChord`\n const candidates = this._map.get(currentChord);\n if (typeof candidates === 'undefined') {\n // No chords starting with `currentChord`\n this._log(`\\\\ No keybinding entries.`);\n return null;\n }\n lookupMap = [];\n for (let i = 0, len = candidates.length; i < len; i++) {\n const candidate = candidates[i];\n // TODO@chords\n if (candidate.keypressParts[1] === keypress) {\n lookupMap.push(candidate);\n }\n }\n }\n else {\n const candidates = this._map.get(keypress);\n if (typeof candidates === 'undefined') {\n // No bindings with `keypress`\n this._log(`\\\\ No keybinding entries.`);\n return null;\n }\n lookupMap = candidates;\n }\n const result = this._findCommand(context, lookupMap);\n if (!result) {\n this._log(`\\\\ From ${lookupMap.length} keybinding entries, no when clauses matched the context.`);\n return null;\n }\n // TODO@chords\n if (currentChord === null && result.keypressParts.length > 1 && result.keypressParts[1] !== null) {\n this._log(`\\\\ From ${lookupMap.length} keybinding entries, matched chord, when: ${printWhenExplanation(result.when)}, source: ${printSourceExplanation(result)}.`);\n return {\n enterChord: true,\n leaveChord: false,\n commandId: null,\n commandArgs: null,\n bubble: false\n };\n }\n this._log(`\\\\ From ${lookupMap.length} keybinding entries, matched ${result.command}, when: ${printWhenExplanation(result.when)}, source: ${printSourceExplanation(result)}.`);\n return {\n enterChord: false,\n leaveChord: result.keypressParts.length > 1,\n commandId: result.command,\n commandArgs: result.commandArgs,\n bubble: result.bubble\n };\n }\n _findCommand(context, matches) {\n for (let i = matches.length - 1; i >= 0; i--) {\n const k = matches[i];\n if (!KeybindingResolver._contextMatchesRules(context, k.when)) {\n continue;\n }\n return k;\n }\n return null;\n }\n static _contextMatchesRules(context, rules) {\n if (!rules) {\n return true;\n }\n return rules.evaluate(context);\n }\n}\nfunction printWhenExplanation(when) {\n if (!when) {\n return `no when condition`;\n }\n return `${when.serialize()}`;\n}\nfunction printSourceExplanation(kb) {\n return (kb.extensionId\n ? (kb.isBuiltinExtension ? `built-in extension ${kb.extensionId}` : `user extension ${kb.extensionId}`)\n : (kb.isDefault ? `built-in` : `user`));\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nexport class ResolvedKeybindingItem {\n constructor(resolvedKeybinding, command, commandArgs, when, isDefault, extensionId, isBuiltinExtension) {\n this._resolvedKeybindingItemBrand = undefined;\n this.resolvedKeybinding = resolvedKeybinding;\n this.keypressParts = resolvedKeybinding ? removeElementsAfterNulls(resolvedKeybinding.getDispatchParts()) : [];\n if (resolvedKeybinding && this.keypressParts.length === 0) {\n // handle possible single modifier chord keybindings\n this.keypressParts = removeElementsAfterNulls(resolvedKeybinding.getSingleModifierDispatchParts());\n }\n this.bubble = (command ? command.charCodeAt(0) === 94 /* CharCode.Caret */ : false);\n this.command = this.bubble ? command.substr(1) : command;\n this.commandArgs = commandArgs;\n this.when = when;\n this.isDefault = isDefault;\n this.extensionId = extensionId;\n this.isBuiltinExtension = isBuiltinExtension;\n }\n}\nexport function removeElementsAfterNulls(arr) {\n const result = [];\n for (let i = 0, len = arr.length; i < len; i++) {\n const element = arr[i];\n if (!element) {\n // stop processing at first encountered null\n return result;\n }\n result.push(element);\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { illegalArgument } from '../../../base/common/errors.js';\nimport { AriaLabelProvider, ElectronAcceleratorLabelProvider, UILabelProvider } from '../../../base/common/keybindingLabels.js';\nimport { ResolvedKeybinding, ResolvedKeybindingPart } from '../../../base/common/keybindings.js';\nexport class BaseResolvedKeybinding extends ResolvedKeybinding {\n constructor(os, parts) {\n super();\n if (parts.length === 0) {\n throw illegalArgument(`parts`);\n }\n this._os = os;\n this._parts = parts;\n }\n getLabel() {\n return UILabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getLabel(keybinding));\n }\n getAriaLabel() {\n return AriaLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getAriaLabel(keybinding));\n }\n getElectronAccelerator() {\n if (this._parts.length > 1) {\n // [Electron Accelerators] Electron cannot handle chords\n return null;\n }\n if (this._parts[0].isDuplicateModifierCase()) {\n // [Electron Accelerators] Electron cannot handle modifier only keybindings\n // e.g. \"shift shift\"\n return null;\n }\n return ElectronAcceleratorLabelProvider.toLabel(this._os, this._parts, (keybinding) => this._getElectronAccelerator(keybinding));\n }\n isChord() {\n return (this._parts.length > 1);\n }\n getParts() {\n return this._parts.map((keybinding) => this._getPart(keybinding));\n }\n _getPart(keybinding) {\n return new ResolvedKeybindingPart(keybinding.ctrlKey, keybinding.shiftKey, keybinding.altKey, keybinding.metaKey, this._getLabel(keybinding), this._getAriaLabel(keybinding));\n }\n getDispatchParts() {\n return this._parts.map((keybinding) => this._getDispatchPart(keybinding));\n }\n getSingleModifierDispatchParts() {\n return this._parts.map((keybinding) => this._getSingleModifierDispatchPart(keybinding));\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 *--------------------------------------------------------------------------------------------*/\nimport { KeyCodeUtils, IMMUTABLE_CODE_TO_KEY_CODE } from '../../../base/common/keyCodes.js';\nimport { ChordKeybinding, SimpleKeybinding } from '../../../base/common/keybindings.js';\nimport { BaseResolvedKeybinding } from './baseResolvedKeybinding.js';\nimport { removeElementsAfterNulls } from './resolvedKeybindingItem.js';\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 constructor(actual, os) {\n super(os, actual.parts);\n }\n _keyCodeToUILabel(keyCode) {\n if (this._os === 2 /* OperatingSystem.Macintosh */) {\n switch (keyCode) {\n case 15 /* KeyCode.LeftArrow */:\n return '←';\n case 16 /* KeyCode.UpArrow */:\n return '↑';\n case 17 /* KeyCode.RightArrow */:\n return '→';\n case 18 /* KeyCode.DownArrow */:\n return '↓';\n }\n }\n return KeyCodeUtils.toString(keyCode);\n }\n _getLabel(keybinding) {\n if (keybinding.isDuplicateModifierCase()) {\n return '';\n }\n return this._keyCodeToUILabel(keybinding.keyCode);\n }\n _getAriaLabel(keybinding) {\n if (keybinding.isDuplicateModifierCase()) {\n return '';\n }\n return KeyCodeUtils.toString(keybinding.keyCode);\n }\n _getElectronAccelerator(keybinding) {\n return KeyCodeUtils.toElectronAccelerator(keybinding.keyCode);\n }\n _getDispatchPart(keybinding) {\n return USLayoutResolvedKeybinding.getDispatchStr(keybinding);\n }\n static getDispatchStr(keybinding) {\n if (keybinding.isModifierKey()) {\n return null;\n }\n let result = '';\n if (keybinding.ctrlKey) {\n result += 'ctrl+';\n }\n if (keybinding.shiftKey) {\n result += 'shift+';\n }\n if (keybinding.altKey) {\n result += 'alt+';\n }\n if (keybinding.metaKey) {\n result += 'meta+';\n }\n result += KeyCodeUtils.toString(keybinding.keyCode);\n return result;\n }\n _getSingleModifierDispatchPart(keybinding) {\n if (keybinding.keyCode === 5 /* KeyCode.Ctrl */ && !keybinding.shiftKey && !keybinding.altKey && !keybinding.metaKey) {\n return 'ctrl';\n }\n if (keybinding.keyCode === 4 /* KeyCode.Shift */ && !keybinding.ctrlKey && !keybinding.altKey && !keybinding.metaKey) {\n return 'shift';\n }\n if (keybinding.keyCode === 6 /* KeyCode.Alt */ && !keybinding.ctrlKey && !keybinding.shiftKey && !keybinding.metaKey) {\n return 'alt';\n }\n if (keybinding.keyCode === 57 /* KeyCode.Meta */ && !keybinding.ctrlKey && !keybinding.shiftKey && !keybinding.altKey) {\n return 'meta';\n }\n return null;\n }\n /**\n * *NOTE*: Check return value for `KeyCode.Unknown`.\n */\n static _scanCodeToKeyCode(scanCode) {\n const immutableKeyCode = IMMUTABLE_CODE_TO_KEY_CODE[scanCode];\n if (immutableKeyCode !== -1 /* KeyCode.DependsOnKbLayout */) {\n return immutableKeyCode;\n }\n switch (scanCode) {\n case 10 /* ScanCode.KeyA */: return 31 /* KeyCode.KeyA */;\n case 11 /* ScanCode.KeyB */: return 32 /* KeyCode.KeyB */;\n case 12 /* ScanCode.KeyC */: return 33 /* KeyCode.KeyC */;\n case 13 /* ScanCode.KeyD */: return 34 /* KeyCode.KeyD */;\n case 14 /* ScanCode.KeyE */: return 35 /* KeyCode.KeyE */;\n case 15 /* ScanCode.KeyF */: return 36 /* KeyCode.KeyF */;\n case 16 /* ScanCode.KeyG */: return 37 /* KeyCode.KeyG */;\n case 17 /* ScanCode.KeyH */: return 38 /* KeyCode.KeyH */;\n case 18 /* ScanCode.KeyI */: return 39 /* KeyCode.KeyI */;\n case 19 /* ScanCode.KeyJ */: return 40 /* KeyCode.KeyJ */;\n case 20 /* ScanCode.KeyK */: return 41 /* KeyCode.KeyK */;\n case 21 /* ScanCode.KeyL */: return 42 /* KeyCode.KeyL */;\n case 22 /* ScanCode.KeyM */: return 43 /* KeyCode.KeyM */;\n case 23 /* ScanCode.KeyN */: return 44 /* KeyCode.KeyN */;\n case 24 /* ScanCode.KeyO */: return 45 /* KeyCode.KeyO */;\n case 25 /* ScanCode.KeyP */: return 46 /* KeyCode.KeyP */;\n case 26 /* ScanCode.KeyQ */: return 47 /* KeyCode.KeyQ */;\n case 27 /* ScanCode.KeyR */: return 48 /* KeyCode.KeyR */;\n case 28 /* ScanCode.KeyS */: return 49 /* KeyCode.KeyS */;\n case 29 /* ScanCode.KeyT */: return 50 /* KeyCode.KeyT */;\n case 30 /* ScanCode.KeyU */: return 51 /* KeyCode.KeyU */;\n case 31 /* ScanCode.KeyV */: return 52 /* KeyCode.KeyV */;\n case 32 /* ScanCode.KeyW */: return 53 /* KeyCode.KeyW */;\n case 33 /* ScanCode.KeyX */: return 54 /* KeyCode.KeyX */;\n case 34 /* ScanCode.KeyY */: return 55 /* KeyCode.KeyY */;\n case 35 /* ScanCode.KeyZ */: return 56 /* KeyCode.KeyZ */;\n case 36 /* ScanCode.Digit1 */: return 22 /* KeyCode.Digit1 */;\n case 37 /* ScanCode.Digit2 */: return 23 /* KeyCode.Digit2 */;\n case 38 /* ScanCode.Digit3 */: return 24 /* KeyCode.Digit3 */;\n case 39 /* ScanCode.Digit4 */: return 25 /* KeyCode.Digit4 */;\n case 40 /* ScanCode.Digit5 */: return 26 /* KeyCode.Digit5 */;\n case 41 /* ScanCode.Digit6 */: return 27 /* KeyCode.Digit6 */;\n case 42 /* ScanCode.Digit7 */: return 28 /* KeyCode.Digit7 */;\n case 43 /* ScanCode.Digit8 */: return 29 /* KeyCode.Digit8 */;\n case 44 /* ScanCode.Digit9 */: return 30 /* KeyCode.Digit9 */;\n case 45 /* ScanCode.Digit0 */: return 21 /* KeyCode.Digit0 */;\n case 51 /* ScanCode.Minus */: return 83 /* KeyCode.Minus */;\n case 52 /* ScanCode.Equal */: return 81 /* KeyCode.Equal */;\n case 53 /* ScanCode.BracketLeft */: return 87 /* KeyCode.BracketLeft */;\n case 54 /* ScanCode.BracketRight */: return 89 /* KeyCode.BracketRight */;\n case 55 /* ScanCode.Backslash */: return 88 /* KeyCode.Backslash */;\n case 56 /* ScanCode.IntlHash */: return 0 /* KeyCode.Unknown */; // missing\n case 57 /* ScanCode.Semicolon */: return 80 /* KeyCode.Semicolon */;\n case 58 /* ScanCode.Quote */: return 90 /* KeyCode.Quote */;\n case 59 /* ScanCode.Backquote */: return 86 /* KeyCode.Backquote */;\n case 60 /* ScanCode.Comma */: return 82 /* KeyCode.Comma */;\n case 61 /* ScanCode.Period */: return 84 /* KeyCode.Period */;\n case 62 /* ScanCode.Slash */: return 85 /* KeyCode.Slash */;\n case 106 /* ScanCode.IntlBackslash */: return 92 /* KeyCode.IntlBackslash */;\n }\n return 0 /* KeyCode.Unknown */;\n }\n static _resolveSimpleUserBinding(binding) {\n if (!binding) {\n return null;\n }\n if (binding instanceof SimpleKeybinding) {\n return binding;\n }\n const keyCode = this._scanCodeToKeyCode(binding.scanCode);\n if (keyCode === 0 /* KeyCode.Unknown */) {\n return null;\n }\n return new SimpleKeybinding(binding.ctrlKey, binding.shiftKey, binding.altKey, binding.metaKey, keyCode);\n }\n static resolveUserBinding(input, os) {\n const parts = removeElementsAfterNulls(input.map(keybinding => this._resolveSimpleUserBinding(keybinding)));\n if (parts.length > 0) {\n return [new USLayoutResolvedKeybinding(new ChordKeybinding(parts), os)];\n }\n return [];\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 *--------------------------------------------------------------------------------------------*/\nimport { BrowserFeatures } from '../../canIUse.js';\nimport * as DOM from '../../dom.js';\nimport { Disposable, DisposableStore, toDisposable } from '../../../common/lifecycle.js';\nimport * as platform from '../../../common/platform.js';\nimport { Range } from '../../../common/range.js';\nimport './contextview.css';\nexport var LayoutAnchorMode;\n(function (LayoutAnchorMode) {\n LayoutAnchorMode[LayoutAnchorMode[\"AVOID\"] = 0] = \"AVOID\";\n LayoutAnchorMode[LayoutAnchorMode[\"ALIGN\"] = 1] = \"ALIGN\";\n})(LayoutAnchorMode || (LayoutAnchorMode = {}));\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, viewSize, anchor) {\n const layoutAfterAnchorBoundary = anchor.mode === LayoutAnchorMode.ALIGN ? anchor.offset : anchor.offset + anchor.size;\n const layoutBeforeAnchorBoundary = anchor.mode === LayoutAnchorMode.ALIGN ? anchor.offset + anchor.size : anchor.offset;\n if (anchor.position === 0 /* LayoutAnchorPosition.Before */) {\n if (viewSize <= viewportSize - layoutAfterAnchorBoundary) {\n return layoutAfterAnchorBoundary; // happy case, lay it out after the anchor\n }\n if (viewSize <= layoutBeforeAnchorBoundary) {\n return layoutBeforeAnchorBoundary - viewSize; // ok case, lay it out before the anchor\n }\n return Math.max(viewportSize - viewSize, 0); // sad case, lay it over the anchor\n }\n else {\n if (viewSize <= layoutBeforeAnchorBoundary) {\n return layoutBeforeAnchorBoundary - viewSize; // happy case, lay it out before the anchor\n }\n if (viewSize <= viewportSize - layoutAfterAnchorBoundary) {\n return layoutAfterAnchorBoundary; // ok case, lay it out after the anchor\n }\n return 0; // sad case, lay it over the anchor\n }\n}\nexport class ContextView extends Disposable {\n constructor(container, domPosition) {\n super();\n this.container = null;\n this.delegate = null;\n this.toDisposeOnClean = Disposable.None;\n this.toDisposeOnSetContainer = Disposable.None;\n this.shadowRoot = null;\n this.shadowRootHostElement = null;\n this.view = DOM.$('.context-view');\n this.useFixedPosition = false;\n this.useShadowDOM = false;\n DOM.hide(this.view);\n this.setContainer(container, domPosition);\n this._register(toDisposable(() => this.setContainer(null, 1 /* ContextViewDOMPosition.ABSOLUTE */)));\n }\n setContainer(container, domPosition) {\n var _a;\n if (this.container) {\n this.toDisposeOnSetContainer.dispose();\n if (this.shadowRoot) {\n this.shadowRoot.removeChild(this.view);\n this.shadowRoot = null;\n (_a = this.shadowRootHostElement) === null || _a === void 0 ? void 0 : _a.remove();\n this.shadowRootHostElement = null;\n }\n else {\n this.container.removeChild(this.view);\n }\n this.container = null;\n }\n if (container) {\n this.container = container;\n this.useFixedPosition = domPosition !== 1 /* ContextViewDOMPosition.ABSOLUTE */;\n this.useShadowDOM = domPosition === 3 /* ContextViewDOMPosition.FIXED_SHADOW */;\n if (this.useShadowDOM) {\n this.shadowRootHostElement = DOM.$('.shadow-root-host');\n this.container.appendChild(this.shadowRootHostElement);\n this.shadowRoot = this.shadowRootHostElement.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = SHADOW_ROOT_CSS;\n this.shadowRoot.appendChild(style);\n this.shadowRoot.appendChild(this.view);\n this.shadowRoot.appendChild(DOM.$('slot'));\n }\n else {\n this.container.appendChild(this.view);\n }\n const toDisposeOnSetContainer = new DisposableStore();\n ContextView.BUBBLE_UP_EVENTS.forEach(event => {\n toDisposeOnSetContainer.add(DOM.addStandardDisposableListener(this.container, event, (e) => {\n this.onDOMEvent(e, false);\n }));\n });\n ContextView.BUBBLE_DOWN_EVENTS.forEach(event => {\n toDisposeOnSetContainer.add(DOM.addStandardDisposableListener(this.container, event, (e) => {\n this.onDOMEvent(e, true);\n }, true));\n });\n this.toDisposeOnSetContainer = toDisposeOnSetContainer;\n }\n }\n show(delegate) {\n var _a, _b;\n if (this.isVisible()) {\n this.hide();\n }\n // Show static box\n DOM.clearNode(this.view);\n this.view.className = 'context-view';\n this.view.style.top = '0px';\n this.view.style.left = '0px';\n this.view.style.zIndex = '2575';\n this.view.style.position = this.useFixedPosition ? 'fixed' : 'absolute';\n DOM.show(this.view);\n // Render content\n this.toDisposeOnClean = delegate.render(this.view) || Disposable.None;\n // Set active delegate\n this.delegate = delegate;\n // Layout\n this.doLayout();\n // Focus\n (_b = (_a = this.delegate).focus) === null || _b === void 0 ? void 0 : _b.call(_a);\n }\n getViewElement() {\n return this.view;\n }\n layout() {\n if (!this.isVisible()) {\n return;\n }\n if (this.delegate.canRelayout === false && !(platform.isIOS && BrowserFeatures.pointerEvents)) {\n this.hide();\n return;\n }\n if (this.delegate.layout) {\n this.delegate.layout();\n }\n this.doLayout();\n }\n doLayout() {\n // Check that we still have a delegate - this.delegate.layout may have hidden\n if (!this.isVisible()) {\n return;\n }\n // Get anchor\n const anchor = this.delegate.getAnchor();\n // Compute around\n let around;\n // Get the element's position and size (to anchor the view)\n if (DOM.isHTMLElement(anchor)) {\n const elementPosition = DOM.getDomNodePagePosition(anchor);\n // In areas where zoom is applied to the element or its ancestors, we need to adjust the size of the element\n // e.g. The title bar has counter zoom behavior meaning it applies the inverse of zoom level.\n // Window Zoom Level: 1.5, Title Bar Zoom: 1/1.5, Size Multiplier: 1.5\n const zoom = DOM.getDomNodeZoomLevel(anchor);\n around = {\n top: elementPosition.top * zoom,\n left: elementPosition.left * zoom,\n width: elementPosition.width * zoom,\n height: elementPosition.height * zoom\n };\n }\n else {\n around = {\n top: anchor.y,\n left: anchor.x,\n width: anchor.width || 1,\n height: anchor.height || 2\n };\n }\n const viewSizeWidth = DOM.getTotalWidth(this.view);\n const viewSizeHeight = DOM.getTotalHeight(this.view);\n const anchorPosition = this.delegate.anchorPosition || 0 /* AnchorPosition.BELOW */;\n const anchorAlignment = this.delegate.anchorAlignment || 0 /* AnchorAlignment.LEFT */;\n const anchorAxisAlignment = this.delegate.anchorAxisAlignment || 0 /* AnchorAxisAlignment.VERTICAL */;\n let top;\n let left;\n if (anchorAxisAlignment === 0 /* AnchorAxisAlignment.VERTICAL */) {\n const verticalAnchor = { offset: around.top - window.pageYOffset, size: around.height, position: anchorPosition === 0 /* AnchorPosition.BELOW */ ? 0 /* LayoutAnchorPosition.Before */ : 1 /* LayoutAnchorPosition.After */ };\n const horizontalAnchor = { offset: around.left, size: around.width, position: anchorAlignment === 0 /* AnchorAlignment.LEFT */ ? 0 /* LayoutAnchorPosition.Before */ : 1 /* LayoutAnchorPosition.After */, mode: LayoutAnchorMode.ALIGN };\n top = layout(window.innerHeight, viewSizeHeight, verticalAnchor) + window.pageYOffset;\n // if view intersects vertically with anchor, we must avoid the anchor\n if (Range.intersects({ start: top, end: top + viewSizeHeight }, { start: verticalAnchor.offset, end: verticalAnchor.offset + verticalAnchor.size })) {\n horizontalAnchor.mode = LayoutAnchorMode.AVOID;\n }\n left = layout(window.innerWidth, viewSizeWidth, horizontalAnchor);\n }\n else {\n const horizontalAnchor = { offset: around.left, size: around.width, position: anchorAlignment === 0 /* AnchorAlignment.LEFT */ ? 0 /* LayoutAnchorPosition.Before */ : 1 /* LayoutAnchorPosition.After */ };\n const verticalAnchor = { offset: around.top, size: around.height, position: anchorPosition === 0 /* AnchorPosition.BELOW */ ? 0 /* LayoutAnchorPosition.Before */ : 1 /* LayoutAnchorPosition.After */, mode: LayoutAnchorMode.ALIGN };\n left = layout(window.innerWidth, viewSizeWidth, horizontalAnchor);\n // if view intersects horizontally with anchor, we must avoid the anchor\n if (Range.intersects({ start: left, end: left + viewSizeWidth }, { start: horizontalAnchor.offset, end: horizontalAnchor.offset + horizontalAnchor.size })) {\n verticalAnchor.mode = LayoutAnchorMode.AVOID;\n }\n top = layout(window.innerHeight, viewSizeHeight, verticalAnchor) + window.pageYOffset;\n }\n this.view.classList.remove('top', 'bottom', 'left', 'right');\n this.view.classList.add(anchorPosition === 0 /* AnchorPosition.BELOW */ ? 'bottom' : 'top');\n this.view.classList.add(anchorAlignment === 0 /* AnchorAlignment.LEFT */ ? 'left' : 'right');\n this.view.classList.toggle('fixed', this.useFixedPosition);\n const containerPosition = DOM.getDomNodePagePosition(this.container);\n this.view.style.top = `${top - (this.useFixedPosition ? DOM.getDomNodePagePosition(this.view).top : containerPosition.top)}px`;\n this.view.style.left = `${left - (this.useFixedPosition ? DOM.getDomNodePagePosition(this.view).left : containerPosition.left)}px`;\n this.view.style.width = 'initial';\n }\n hide(data) {\n const delegate = this.delegate;\n this.delegate = null;\n if (delegate === null || delegate === void 0 ? void 0 : delegate.onHide) {\n delegate.onHide(data);\n }\n this.toDisposeOnClean.dispose();\n DOM.hide(this.view);\n }\n isVisible() {\n return !!this.delegate;\n }\n onDOMEvent(e, onCapture) {\n if (this.delegate) {\n if (this.delegate.onDOMEvent) {\n this.delegate.onDOMEvent(e, document.activeElement);\n }\n else if (onCapture && !DOM.isAncestor(e.target, this.container)) {\n this.hide();\n }\n }\n }\n dispose() {\n this.hide();\n super.dispose();\n }\n}\nContextView.BUBBLE_UP_EVENTS = ['click', 'keydown', 'focus', 'blur'];\nContextView.BUBBLE_DOWN_EVENTS = ['click'];\nconst 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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { ContextView } from '../../../base/browser/ui/contextview/contextview.js';\nimport { Disposable, toDisposable } from '../../../base/common/lifecycle.js';\nimport { ILayoutService } from '../../layout/browser/layoutService.js';\nlet ContextViewService = class ContextViewService extends Disposable {\n constructor(layoutService) {\n super();\n this.layoutService = layoutService;\n this.currentViewDisposable = Disposable.None;\n this.container = layoutService.hasContainer ? layoutService.container : null;\n this.contextView = this._register(new ContextView(this.container, 1 /* ContextViewDOMPosition.ABSOLUTE */));\n this.layout();\n this._register(layoutService.onDidLayout(() => this.layout()));\n }\n // ContextView\n setContainer(container, domPosition) {\n this.contextView.setContainer(container, domPosition || 1 /* ContextViewDOMPosition.ABSOLUTE */);\n }\n showContextView(delegate, container, shadowRoot) {\n if (container) {\n if (container !== this.container || this.shadowRoot !== shadowRoot) {\n this.container = container;\n this.setContainer(container, shadowRoot ? 3 /* ContextViewDOMPosition.FIXED_SHADOW */ : 2 /* ContextViewDOMPosition.FIXED */);\n }\n }\n else {\n if (this.layoutService.hasContainer && this.container !== this.layoutService.container) {\n this.container = this.layoutService.container;\n this.setContainer(this.container, 1 /* ContextViewDOMPosition.ABSOLUTE */);\n }\n }\n this.shadowRoot = shadowRoot;\n this.contextView.show(delegate);\n const disposable = toDisposable(() => {\n if (this.currentViewDisposable === disposable) {\n this.hideContextView();\n }\n });\n this.currentViewDisposable = disposable;\n return disposable;\n }\n getContextViewElement() {\n return this.contextView.getViewElement();\n }\n layout() {\n this.contextView.layout();\n }\n hideContextView(data) {\n this.contextView.hide(data);\n }\n};\nContextViewService = __decorate([\n __param(0, ILayoutService)\n], ContextViewService);\nexport { ContextViewService };\n","var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { isThenable } from './async.js';\nimport { isEqualOrParent } from './extpath.js';\nimport { LRUCache } from './map.js';\nimport { basename, extname, posix, sep } from './path.js';\nimport { isLinux } from './platform.js';\nimport { escapeRegExpCharacters } from './strings.js';\nexport const GLOBSTAR = '**';\nexport const GLOB_SPLIT = '/';\nconst PATH_REGEX = '[/\\\\\\\\]'; // any slash or backslash\nconst NO_PATH_REGEX = '[^/\\\\\\\\]'; // any non-slash and non-backslash\nconst ALL_FORWARD_SLASHES = /\\//g;\nfunction starsToRegExp(starCount, isLastPattern) {\n switch (starCount) {\n case 0:\n return '';\n case 1:\n return `${NO_PATH_REGEX}*?`; // 1 star matches any number of characters except path separator (/ and \\) - non greedy (?)\n default:\n // Matches: (Path Sep OR Path Val followed by Path Sep) 0-many times except when it's the last pattern\n // in which case also matches (Path Sep followed by Path Val)\n // Group is non capturing because we don't need to capture at all (?:...)\n // Overall we use non-greedy matching because it could be that we match too much\n return `(?:${PATH_REGEX}|${NO_PATH_REGEX}+${PATH_REGEX}${isLastPattern ? `|${PATH_REGEX}${NO_PATH_REGEX}+` : ''})*?`;\n }\n}\nexport function splitGlobAware(pattern, splitChar) {\n if (!pattern) {\n return [];\n }\n const segments = [];\n let inBraces = false;\n let inBrackets = false;\n let curVal = '';\n for (const char of pattern) {\n switch (char) {\n case splitChar:\n if (!inBraces && !inBrackets) {\n segments.push(curVal);\n curVal = '';\n continue;\n }\n break;\n case '{':\n inBraces = true;\n break;\n case '}':\n inBraces = false;\n break;\n case '[':\n inBrackets = true;\n break;\n case ']':\n inBrackets = false;\n break;\n }\n curVal += char;\n }\n // Tail\n if (curVal) {\n segments.push(curVal);\n }\n return segments;\n}\nfunction parseRegExp(pattern) {\n if (!pattern) {\n return '';\n }\n let regEx = '';\n // Split up into segments for each slash found\n const segments = splitGlobAware(pattern, GLOB_SPLIT);\n // Special case where we only have globstars\n if (segments.every(segment => segment === GLOBSTAR)) {\n regEx = '.*';\n }\n // Build regex over segments\n else {\n let previousSegmentWasGlobStar = false;\n segments.forEach((segment, index) => {\n // Treat globstar specially\n if (segment === GLOBSTAR) {\n // if we have more than one globstar after another, just ignore it\n if (previousSegmentWasGlobStar) {\n return;\n }\n regEx += starsToRegExp(2, index === segments.length - 1);\n }\n // Anything else, not globstar\n else {\n // States\n let inBraces = false;\n let braceVal = '';\n let inBrackets = false;\n let bracketVal = '';\n for (const char of segment) {\n // Support brace expansion\n if (char !== '}' && inBraces) {\n braceVal += char;\n continue;\n }\n // Support brackets\n if (inBrackets && (char !== ']' || !bracketVal) /* ] is literally only allowed as first character in brackets to match it */) {\n let res;\n // range operator\n if (char === '-') {\n res = char;\n }\n // negation operator (only valid on first index in bracket)\n else if ((char === '^' || char === '!') && !bracketVal) {\n res = '^';\n }\n // glob split matching is not allowed within character ranges\n // see http://man7.org/linux/man-pages/man7/glob.7.html\n else if (char === GLOB_SPLIT) {\n res = '';\n }\n // anything else gets escaped\n else {\n res = escapeRegExpCharacters(char);\n }\n bracketVal += res;\n continue;\n }\n switch (char) {\n case '{':\n inBraces = true;\n continue;\n case '[':\n inBrackets = true;\n continue;\n case '}': {\n const choices = splitGlobAware(braceVal, ',');\n // Converts {foo,bar} => [foo|bar]\n const braceRegExp = `(?:${choices.map(choice => parseRegExp(choice)).join('|')})`;\n regEx += braceRegExp;\n inBraces = false;\n braceVal = '';\n break;\n }\n case ']': {\n regEx += ('[' + bracketVal + ']');\n inBrackets = false;\n bracketVal = '';\n break;\n }\n case '?':\n regEx += NO_PATH_REGEX; // 1 ? matches any single character except path separator (/ and \\)\n continue;\n case '*':\n regEx += starsToRegExp(1);\n continue;\n default:\n regEx += escapeRegExpCharacters(char);\n }\n }\n // Tail: Add the slash we had split on if there is more to\n // come and the remaining pattern is not a globstar\n // For example if pattern: some/**/*.js we want the \"/\" after\n // some to be included in the RegEx to prevent a folder called\n // \"something\" to match as well.\n if (index < segments.length - 1 && // more segments to come after this\n (segments[index + 1] !== GLOBSTAR || // next segment is not **, or...\n index + 2 < segments.length // ...next segment is ** but there is more segments after that\n )) {\n regEx += PATH_REGEX;\n }\n }\n // update globstar state\n previousSegmentWasGlobStar = (segment === GLOBSTAR);\n });\n }\n return regEx;\n}\n// regexes to check for trivial glob patterns that just check for String#endsWith\nconst T1 = /^\\*\\*\\/\\*\\.[\\w\\.-]+$/; // **/*.something\nconst T2 = /^\\*\\*\\/([\\w\\.-]+)\\/?$/; // **/something\nconst T3 = /^{\\*\\*\\/\\*?[\\w\\.-]+\\/?(,\\*\\*\\/\\*?[\\w\\.-]+\\/?)*}$/; // {**/*.something,**/*.else} or {**/package.json,**/project.json}\nconst T3_2 = /^{\\*\\*\\/\\*?[\\w\\.-]+(\\/(\\*\\*)?)?(,\\*\\*\\/\\*?[\\w\\.-]+(\\/(\\*\\*)?)?)*}$/; // Like T3, with optional trailing /**\nconst T4 = /^\\*\\*((\\/[\\w\\.-]+)+)\\/?$/; // **/something/else\nconst T5 = /^([\\w\\.-]+(\\/[\\w\\.-]+)*)\\/?$/; // something/else\nconst CACHE = new LRUCache(10000); // bounded to 10000 elements\nconst FALSE = function () {\n return false;\n};\nconst NULL = function () {\n return null;\n};\nfunction parsePattern(arg1, options) {\n if (!arg1) {\n return NULL;\n }\n // Handle relative patterns\n let pattern;\n if (typeof arg1 !== 'string') {\n pattern = arg1.pattern;\n }\n else {\n pattern = arg1;\n }\n // Whitespace trimming\n pattern = pattern.trim();\n // Check cache\n const patternKey = `${pattern}_${!!options.trimForExclusions}`;\n let parsedPattern = CACHE.get(patternKey);\n if (parsedPattern) {\n return wrapRelativePattern(parsedPattern, arg1);\n }\n // Check for Trivials\n let match;\n if (T1.test(pattern)) {\n parsedPattern = trivia1(pattern.substr(4), pattern); // common pattern: **/*.txt just need endsWith check\n }\n else if (match = T2.exec(trimForExclusions(pattern, options))) { // common pattern: **/some.txt just need basename check\n parsedPattern = trivia2(match[1], pattern);\n }\n else if ((options.trimForExclusions ? T3_2 : T3).test(pattern)) { // repetition of common patterns (see above) {**/*.txt,**/*.png}\n parsedPattern = trivia3(pattern, options);\n }\n else if (match = T4.exec(trimForExclusions(pattern, options))) { // common pattern: **/something/else just need endsWith check\n parsedPattern = trivia4and5(match[1].substr(1), pattern, true);\n }\n else if (match = T5.exec(trimForExclusions(pattern, options))) { // common pattern: something/else just need equals check\n parsedPattern = trivia4and5(match[1], pattern, false);\n }\n // Otherwise convert to pattern\n else {\n parsedPattern = toRegExp(pattern);\n }\n // Cache\n CACHE.set(patternKey, parsedPattern);\n return wrapRelativePattern(parsedPattern, arg1);\n}\nfunction wrapRelativePattern(parsedPattern, arg2) {\n if (typeof arg2 === 'string') {\n return parsedPattern;\n }\n const wrappedPattern = function (path, basename) {\n if (!isEqualOrParent(path, arg2.base, !isLinux)) {\n // skip glob matching if `base` is not a parent of `path`\n return null;\n }\n // Given we have checked `base` being a parent of `path`,\n // we can now remove the `base` portion of the `path`\n // and only match on the remaining path components\n return parsedPattern(path.substr(arg2.base.length + 1), basename);\n };\n // Make sure to preserve associated metadata\n wrappedPattern.allBasenames = parsedPattern.allBasenames;\n wrappedPattern.allPaths = parsedPattern.allPaths;\n wrappedPattern.basenames = parsedPattern.basenames;\n wrappedPattern.patterns = parsedPattern.patterns;\n return wrappedPattern;\n}\nfunction trimForExclusions(pattern, options) {\n return options.trimForExclusions && pattern.endsWith('/**') ? pattern.substr(0, pattern.length - 2) : pattern; // dropping **, tailing / is dropped later\n}\n// common pattern: **/*.txt just need endsWith check\nfunction trivia1(base, pattern) {\n return function (path, basename) {\n return typeof path === 'string' && path.endsWith(base) ? pattern : null;\n };\n}\n// common pattern: **/some.txt just need basename check\nfunction trivia2(base, pattern) {\n const slashBase = `/${base}`;\n const backslashBase = `\\\\${base}`;\n const parsedPattern = function (path, basename) {\n if (typeof path !== 'string') {\n return null;\n }\n if (basename) {\n return basename === base ? pattern : null;\n }\n return path === base || path.endsWith(slashBase) || path.endsWith(backslashBase) ? pattern : null;\n };\n const basenames = [base];\n parsedPattern.basenames = basenames;\n parsedPattern.patterns = [pattern];\n parsedPattern.allBasenames = basenames;\n return parsedPattern;\n}\n// repetition of common patterns (see above) {**/*.txt,**/*.png}\nfunction trivia3(pattern, options) {\n const parsedPatterns = aggregateBasenameMatches(pattern.slice(1, -1)\n .split(',')\n .map(pattern => parsePattern(pattern, options))\n .filter(pattern => pattern !== NULL), pattern);\n const patternsLength = parsedPatterns.length;\n if (!patternsLength) {\n return NULL;\n }\n if (patternsLength === 1) {\n return parsedPatterns[0];\n }\n const parsedPattern = function (path, basename) {\n for (let i = 0, n = parsedPatterns.length; i < n; i++) {\n if (parsedPatterns[i](path, basename)) {\n return pattern;\n }\n }\n return null;\n };\n const withBasenames = parsedPatterns.find(pattern => !!pattern.allBasenames);\n if (withBasenames) {\n parsedPattern.allBasenames = withBasenames.allBasenames;\n }\n const allPaths = parsedPatterns.reduce((all, current) => current.allPaths ? all.concat(current.allPaths) : all, []);\n if (allPaths.length) {\n parsedPattern.allPaths = allPaths;\n }\n return parsedPattern;\n}\n// common patterns: **/something/else just need endsWith check, something/else just needs and equals check\nfunction trivia4and5(targetPath, pattern, matchPathEnds) {\n const usingPosixSep = sep === posix.sep;\n const nativePath = usingPosixSep ? targetPath : targetPath.replace(ALL_FORWARD_SLASHES, sep);\n const nativePathEnd = sep + nativePath;\n const targetPathEnd = posix.sep + targetPath;\n let parsedPattern;\n if (matchPathEnds) {\n parsedPattern = function (path, basename) {\n return typeof path === 'string' && ((path === nativePath || path.endsWith(nativePathEnd)) || !usingPosixSep && (path === targetPath || path.endsWith(targetPathEnd))) ? pattern : null;\n };\n }\n else {\n parsedPattern = function (path, basename) {\n return typeof path === 'string' && (path === nativePath || (!usingPosixSep && path === targetPath)) ? pattern : null;\n };\n }\n parsedPattern.allPaths = [(matchPathEnds ? '*/' : './') + targetPath];\n return parsedPattern;\n}\nfunction toRegExp(pattern) {\n try {\n const regExp = new RegExp(`^${parseRegExp(pattern)}$`);\n return function (path) {\n regExp.lastIndex = 0; // reset RegExp to its initial state to reuse it!\n return typeof path === 'string' && regExp.test(path) ? pattern : null;\n };\n }\n catch (error) {\n return NULL;\n }\n}\nexport function match(arg1, path, hasSibling) {\n if (!arg1 || typeof path !== 'string') {\n return false;\n }\n return parse(arg1)(path, undefined, hasSibling);\n}\nexport function parse(arg1, options = {}) {\n if (!arg1) {\n return FALSE;\n }\n // Glob with String\n if (typeof arg1 === 'string' || isRelativePattern(arg1)) {\n const parsedPattern = parsePattern(arg1, options);\n if (parsedPattern === NULL) {\n return FALSE;\n }\n const resultPattern = function (path, basename) {\n return !!parsedPattern(path, basename);\n };\n if (parsedPattern.allBasenames) {\n resultPattern.allBasenames = parsedPattern.allBasenames;\n }\n if (parsedPattern.allPaths) {\n resultPattern.allPaths = parsedPattern.allPaths;\n }\n return resultPattern;\n }\n // Glob with Expression\n return parsedExpression(arg1, options);\n}\nexport function isRelativePattern(obj) {\n const rp = obj;\n if (!rp) {\n return false;\n }\n return typeof rp.base === 'string' && typeof rp.pattern === 'string';\n}\nfunction parsedExpression(expression, options) {\n const parsedPatterns = aggregateBasenameMatches(Object.getOwnPropertyNames(expression)\n .map(pattern => parseExpressionPattern(pattern, expression[pattern], options))\n .filter(pattern => pattern !== NULL));\n const patternsLength = parsedPatterns.length;\n if (!patternsLength) {\n return NULL;\n }\n if (!parsedPatterns.some(parsedPattern => !!parsedPattern.requiresSiblings)) {\n if (patternsLength === 1) {\n return parsedPatterns[0];\n }\n const resultExpression = function (path, basename) {\n let resultPromises = undefined;\n for (let i = 0, n = parsedPatterns.length; i < n; i++) {\n const result = parsedPatterns[i](path, basename);\n if (typeof result === 'string') {\n return result; // immediately return as soon as the first expression matches\n }\n // If the result is a promise, we have to keep it for\n // later processing and await the result properly.\n if (isThenable(result)) {\n if (!resultPromises) {\n resultPromises = [];\n }\n resultPromises.push(result);\n }\n }\n // With result promises, we have to loop over each and\n // await the result before we can return any result.\n if (resultPromises) {\n return (() => __awaiter(this, void 0, void 0, function* () {\n for (const resultPromise of resultPromises) {\n const result = yield resultPromise;\n if (typeof result === 'string') {\n return result;\n }\n }\n return null;\n }))();\n }\n return null;\n };\n const withBasenames = parsedPatterns.find(pattern => !!pattern.allBasenames);\n if (withBasenames) {\n resultExpression.allBasenames = withBasenames.allBasenames;\n }\n const allPaths = parsedPatterns.reduce((all, current) => current.allPaths ? all.concat(current.allPaths) : all, []);\n if (allPaths.length) {\n resultExpression.allPaths = allPaths;\n }\n return resultExpression;\n }\n const resultExpression = function (path, base, hasSibling) {\n let name = undefined;\n let resultPromises = undefined;\n for (let i = 0, n = parsedPatterns.length; i < n; i++) {\n // Pattern matches path\n const parsedPattern = parsedPatterns[i];\n if (parsedPattern.requiresSiblings && hasSibling) {\n if (!base) {\n base = basename(path);\n }\n if (!name) {\n name = base.substr(0, base.length - extname(path).length);\n }\n }\n const result = parsedPattern(path, base, name, hasSibling);\n if (typeof result === 'string') {\n return result; // immediately return as soon as the first expression matches\n }\n // If the result is a promise, we have to keep it for\n // later processing and await the result properly.\n if (isThenable(result)) {\n if (!resultPromises) {\n resultPromises = [];\n }\n resultPromises.push(result);\n }\n }\n // With result promises, we have to loop over each and\n // await the result before we can return any result.\n if (resultPromises) {\n return (() => __awaiter(this, void 0, void 0, function* () {\n for (const resultPromise of resultPromises) {\n const result = yield resultPromise;\n if (typeof result === 'string') {\n return result;\n }\n }\n return null;\n }))();\n }\n return null;\n };\n const withBasenames = parsedPatterns.find(pattern => !!pattern.allBasenames);\n if (withBasenames) {\n resultExpression.allBasenames = withBasenames.allBasenames;\n }\n const allPaths = parsedPatterns.reduce((all, current) => current.allPaths ? all.concat(current.allPaths) : all, []);\n if (allPaths.length) {\n resultExpression.allPaths = allPaths;\n }\n return resultExpression;\n}\nfunction parseExpressionPattern(pattern, value, options) {\n if (value === false) {\n return NULL; // pattern is disabled\n }\n const parsedPattern = parsePattern(pattern, options);\n if (parsedPattern === NULL) {\n return NULL;\n }\n // Expression Pattern is \n if (typeof value === 'boolean') {\n return parsedPattern;\n }\n // Expression Pattern is \n if (value) {\n const when = value.when;\n if (typeof when === 'string') {\n const result = (path, basename, name, hasSibling) => {\n if (!hasSibling || !parsedPattern(path, basename)) {\n return null;\n }\n const clausePattern = when.replace('$(basename)', name);\n const matched = hasSibling(clausePattern);\n return isThenable(matched) ?\n matched.then(match => match ? pattern : null) :\n matched ? pattern : null;\n };\n result.requiresSiblings = true;\n return result;\n }\n }\n // Expression is anything\n return parsedPattern;\n}\nfunction aggregateBasenameMatches(parsedPatterns, result) {\n const basenamePatterns = parsedPatterns.filter(parsedPattern => !!parsedPattern.basenames);\n if (basenamePatterns.length < 2) {\n return parsedPatterns;\n }\n const basenames = basenamePatterns.reduce((all, current) => {\n const basenames = current.basenames;\n return basenames ? all.concat(basenames) : all;\n }, []);\n let patterns;\n if (result) {\n patterns = [];\n for (let i = 0, n = basenames.length; i < n; i++) {\n patterns.push(result);\n }\n }\n else {\n patterns = basenamePatterns.reduce((all, current) => {\n const patterns = current.patterns;\n return patterns ? all.concat(patterns) : all;\n }, []);\n }\n const aggregate = function (path, basename) {\n if (typeof path !== 'string') {\n return null;\n }\n if (!basename) {\n let i;\n for (i = path.length; i > 0; i--) {\n const ch = path.charCodeAt(i - 1);\n if (ch === 47 /* CharCode.Slash */ || ch === 92 /* CharCode.Backslash */) {\n break;\n }\n }\n basename = path.substr(i);\n }\n const index = basenames.indexOf(basename);\n return index !== -1 ? patterns[index] : null;\n };\n aggregate.basenames = basenames;\n aggregate.patterns = patterns;\n aggregate.allBasenames = basenames;\n const aggregatedPatterns = parsedPatterns.filter(parsedPattern => !parsedPattern.basenames);\n aggregatedPatterns.push(aggregate);\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { parse } from '../../../base/common/glob.js';\nimport { Mimes } from '../../../base/common/mime.js';\nimport { Schemas } from '../../../base/common/network.js';\nimport { basename, posix } from '../../../base/common/path.js';\nimport { DataUri } from '../../../base/common/resources.js';\nimport { startsWithUTF8BOM } from '../../../base/common/strings.js';\nimport { PLAINTEXT_LANGUAGE_ID } from '../languages/modesRegistry.js';\nlet registeredAssociations = [];\nlet nonUserRegisteredAssociations = [];\nlet userRegisteredAssociations = [];\n/**\n * Associate a language to the registry (platform).\n * * **NOTE**: This association will lose over associations registered using `registerConfiguredLanguageAssociation`.\n * * **NOTE**: Use `clearPlatformLanguageAssociations` to remove all associations registered using this function.\n */\nexport function registerPlatformLanguageAssociation(association, warnOnOverwrite = false) {\n _registerLanguageAssociation(association, false, warnOnOverwrite);\n}\nfunction _registerLanguageAssociation(association, userConfigured, warnOnOverwrite) {\n // Register\n const associationItem = toLanguageAssociationItem(association, userConfigured);\n registeredAssociations.push(associationItem);\n if (!associationItem.userConfigured) {\n nonUserRegisteredAssociations.push(associationItem);\n }\n else {\n userRegisteredAssociations.push(associationItem);\n }\n // Check for conflicts unless this is a user configured association\n if (warnOnOverwrite && !associationItem.userConfigured) {\n registeredAssociations.forEach(a => {\n if (a.mime === associationItem.mime || a.userConfigured) {\n return; // same mime or userConfigured is ok\n }\n if (associationItem.extension && a.extension === associationItem.extension) {\n console.warn(`Overwriting extension <<${associationItem.extension}>> to now point to mime <<${associationItem.mime}>>`);\n }\n if (associationItem.filename && a.filename === associationItem.filename) {\n console.warn(`Overwriting filename <<${associationItem.filename}>> to now point to mime <<${associationItem.mime}>>`);\n }\n if (associationItem.filepattern && a.filepattern === associationItem.filepattern) {\n console.warn(`Overwriting filepattern <<${associationItem.filepattern}>> to now point to mime <<${associationItem.mime}>>`);\n }\n if (associationItem.firstline && a.firstline === associationItem.firstline) {\n console.warn(`Overwriting firstline <<${associationItem.firstline}>> to now point to mime <<${associationItem.mime}>>`);\n }\n });\n }\n}\nfunction toLanguageAssociationItem(association, userConfigured) {\n return {\n id: association.id,\n mime: association.mime,\n filename: association.filename,\n extension: association.extension,\n filepattern: association.filepattern,\n firstline: association.firstline,\n userConfigured: userConfigured,\n filenameLowercase: association.filename ? association.filename.toLowerCase() : undefined,\n extensionLowercase: association.extension ? association.extension.toLowerCase() : undefined,\n filepatternLowercase: association.filepattern ? parse(association.filepattern.toLowerCase()) : undefined,\n filepatternOnPath: association.filepattern ? association.filepattern.indexOf(posix.sep) >= 0 : false\n };\n}\n/**\n * Clear language associations from the registry (platform).\n */\nexport function clearPlatformLanguageAssociations() {\n registeredAssociations = registeredAssociations.filter(a => a.userConfigured);\n nonUserRegisteredAssociations = [];\n}\n/**\n * @see `getMimeTypes`\n */\nexport function getLanguageIds(resource, firstLine) {\n return getAssociations(resource, firstLine).map(item => item.id);\n}\nfunction getAssociations(resource, firstLine) {\n let path;\n if (resource) {\n switch (resource.scheme) {\n case Schemas.file:\n path = resource.fsPath;\n break;\n case Schemas.data: {\n const metadata = DataUri.parseMetaData(resource);\n path = metadata.get(DataUri.META_DATA_LABEL);\n break;\n }\n case Schemas.vscodeNotebookCell:\n // File path not relevant for language detection of cell\n path = undefined;\n break;\n default:\n path = resource.path;\n }\n }\n if (!path) {\n return [{ id: 'unknown', mime: Mimes.unknown }];\n }\n path = path.toLowerCase();\n const filename = basename(path);\n // 1.) User configured mappings have highest priority\n const configuredLanguage = getAssociationByPath(path, filename, userRegisteredAssociations);\n if (configuredLanguage) {\n return [configuredLanguage, { id: PLAINTEXT_LANGUAGE_ID, mime: Mimes.text }];\n }\n // 2.) Registered mappings have middle priority\n const registeredLanguage = getAssociationByPath(path, filename, nonUserRegisteredAssociations);\n if (registeredLanguage) {\n return [registeredLanguage, { id: PLAINTEXT_LANGUAGE_ID, mime: Mimes.text }];\n }\n // 3.) Firstline has lowest priority\n if (firstLine) {\n const firstlineLanguage = getAssociationByFirstline(firstLine);\n if (firstlineLanguage) {\n return [firstlineLanguage, { id: PLAINTEXT_LANGUAGE_ID, mime: Mimes.text }];\n }\n }\n return [{ id: 'unknown', mime: Mimes.unknown }];\n}\nfunction getAssociationByPath(path, filename, associations) {\n var _a;\n let filenameMatch = undefined;\n let patternMatch = undefined;\n let extensionMatch = undefined;\n // We want to prioritize associations based on the order they are registered so that the last registered\n // association wins over all other. This is for https://github.com/microsoft/vscode/issues/20074\n for (let i = associations.length - 1; i >= 0; i--) {\n const association = associations[i];\n // First exact name match\n if (filename === association.filenameLowercase) {\n filenameMatch = association;\n break; // take it!\n }\n // Longest pattern match\n if (association.filepattern) {\n if (!patternMatch || association.filepattern.length > patternMatch.filepattern.length) {\n const target = association.filepatternOnPath ? path : filename; // match on full path if pattern contains path separator\n if ((_a = association.filepatternLowercase) === null || _a === void 0 ? void 0 : _a.call(association, target)) {\n patternMatch = association;\n }\n }\n }\n // Longest extension match\n if (association.extension) {\n if (!extensionMatch || association.extension.length > extensionMatch.extension.length) {\n if (filename.endsWith(association.extensionLowercase)) {\n extensionMatch = association;\n }\n }\n }\n }\n // 1.) Exact name match has second highest priority\n if (filenameMatch) {\n return filenameMatch;\n }\n // 2.) Match on pattern\n if (patternMatch) {\n return patternMatch;\n }\n // 3.) Match on extension comes next\n if (extensionMatch) {\n return extensionMatch;\n }\n return undefined;\n}\nfunction getAssociationByFirstline(firstLine) {\n if (startsWithUTF8BOM(firstLine)) {\n firstLine = firstLine.substr(1);\n }\n if (firstLine.length > 0) {\n // We want to prioritize associations based on the order they are registered so that the last registered\n // association wins over all other. This is for https://github.com/microsoft/vscode/issues/20074\n for (let i = registeredAssociations.length - 1; i >= 0; i--) {\n const association = registeredAssociations[i];\n if (!association.firstline) {\n continue;\n }\n const matches = firstLine.match(association.firstline);\n if (matches && matches.length > 0) {\n return association;\n }\n }\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { onUnexpectedError } from '../../../base/common/errors.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { regExpLeadsToEndlessLoop } from '../../../base/common/strings.js';\nimport { clearPlatformLanguageAssociations, getLanguageIds, registerPlatformLanguageAssociation } from './languagesAssociations.js';\nimport { ModesRegistry, PLAINTEXT_LANGUAGE_ID } from '../languages/modesRegistry.js';\nimport { Extensions } from '../../../platform/configuration/common/configurationRegistry.js';\nimport { Registry } from '../../../platform/registry/common/platform.js';\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst NULL_LANGUAGE_ID = 'vs.editor.nullLanguage';\nexport class LanguageIdCodec {\n constructor() {\n this._languageIdToLanguage = [];\n this._languageToLanguageId = new Map();\n this._register(NULL_LANGUAGE_ID, 0 /* LanguageId.Null */);\n this._register(PLAINTEXT_LANGUAGE_ID, 1 /* LanguageId.PlainText */);\n this._nextLanguageId = 2;\n }\n _register(language, languageId) {\n this._languageIdToLanguage[languageId] = language;\n this._languageToLanguageId.set(language, languageId);\n }\n register(language) {\n if (this._languageToLanguageId.has(language)) {\n return;\n }\n const languageId = this._nextLanguageId++;\n this._register(language, languageId);\n }\n encodeLanguageId(languageId) {\n return this._languageToLanguageId.get(languageId) || 0 /* LanguageId.Null */;\n }\n decodeLanguageId(languageId) {\n return this._languageIdToLanguage[languageId] || NULL_LANGUAGE_ID;\n }\n}\nexport class LanguagesRegistry extends Disposable {\n constructor(useModesRegistry = true, warnOnOverwrite = false) {\n super();\n this._onDidChange = this._register(new Emitter());\n this.onDidChange = this._onDidChange.event;\n LanguagesRegistry.instanceCount++;\n this._warnOnOverwrite = warnOnOverwrite;\n this.languageIdCodec = new LanguageIdCodec();\n this._dynamicLanguages = [];\n this._languages = {};\n this._mimeTypesMap = {};\n this._nameMap = {};\n this._lowercaseNameMap = {};\n if (useModesRegistry) {\n this._initializeFromRegistry();\n this._register(ModesRegistry.onDidChangeLanguages((m) => {\n this._initializeFromRegistry();\n }));\n }\n }\n dispose() {\n LanguagesRegistry.instanceCount--;\n super.dispose();\n }\n _initializeFromRegistry() {\n this._languages = {};\n this._mimeTypesMap = {};\n this._nameMap = {};\n this._lowercaseNameMap = {};\n clearPlatformLanguageAssociations();\n const desc = [].concat(ModesRegistry.getLanguages()).concat(this._dynamicLanguages);\n this._registerLanguages(desc);\n }\n _registerLanguages(desc) {\n for (const d of desc) {\n this._registerLanguage(d);\n }\n // Rebuild fast path maps\n this._mimeTypesMap = {};\n this._nameMap = {};\n this._lowercaseNameMap = {};\n Object.keys(this._languages).forEach((langId) => {\n const language = this._languages[langId];\n if (language.name) {\n this._nameMap[language.name] = language.identifier;\n }\n language.aliases.forEach((alias) => {\n this._lowercaseNameMap[alias.toLowerCase()] = language.identifier;\n });\n language.mimetypes.forEach((mimetype) => {\n this._mimeTypesMap[mimetype] = language.identifier;\n });\n });\n Registry.as(Extensions.Configuration).registerOverrideIdentifiers(this.getRegisteredLanguageIds());\n this._onDidChange.fire();\n }\n _registerLanguage(lang) {\n const langId = lang.id;\n let resolvedLanguage;\n if (hasOwnProperty.call(this._languages, langId)) {\n resolvedLanguage = this._languages[langId];\n }\n else {\n this.languageIdCodec.register(langId);\n resolvedLanguage = {\n identifier: langId,\n name: null,\n mimetypes: [],\n aliases: [],\n extensions: [],\n filenames: [],\n configurationFiles: [],\n icons: []\n };\n this._languages[langId] = resolvedLanguage;\n }\n this._mergeLanguage(resolvedLanguage, lang);\n }\n _mergeLanguage(resolvedLanguage, lang) {\n const langId = lang.id;\n let primaryMime = null;\n if (Array.isArray(lang.mimetypes) && lang.mimetypes.length > 0) {\n resolvedLanguage.mimetypes.push(...lang.mimetypes);\n primaryMime = lang.mimetypes[0];\n }\n if (!primaryMime) {\n primaryMime = `text/x-${langId}`;\n resolvedLanguage.mimetypes.push(primaryMime);\n }\n if (Array.isArray(lang.extensions)) {\n if (lang.configuration) {\n // insert first as this appears to be the 'primary' language definition\n resolvedLanguage.extensions = lang.extensions.concat(resolvedLanguage.extensions);\n }\n else {\n resolvedLanguage.extensions = resolvedLanguage.extensions.concat(lang.extensions);\n }\n for (const extension of lang.extensions) {\n registerPlatformLanguageAssociation({ id: langId, mime: primaryMime, extension: extension }, this._warnOnOverwrite);\n }\n }\n if (Array.isArray(lang.filenames)) {\n for (const filename of lang.filenames) {\n registerPlatformLanguageAssociation({ id: langId, mime: primaryMime, filename: filename }, this._warnOnOverwrite);\n resolvedLanguage.filenames.push(filename);\n }\n }\n if (Array.isArray(lang.filenamePatterns)) {\n for (const filenamePattern of lang.filenamePatterns) {\n registerPlatformLanguageAssociation({ id: langId, mime: primaryMime, filepattern: filenamePattern }, this._warnOnOverwrite);\n }\n }\n if (typeof lang.firstLine === 'string' && lang.firstLine.length > 0) {\n let firstLineRegexStr = lang.firstLine;\n if (firstLineRegexStr.charAt(0) !== '^') {\n firstLineRegexStr = '^' + firstLineRegexStr;\n }\n try {\n const firstLineRegex = new RegExp(firstLineRegexStr);\n if (!regExpLeadsToEndlessLoop(firstLineRegex)) {\n registerPlatformLanguageAssociation({ id: langId, mime: primaryMime, firstline: firstLineRegex }, this._warnOnOverwrite);\n }\n }\n catch (err) {\n // Most likely, the regex was bad\n onUnexpectedError(err);\n }\n }\n resolvedLanguage.aliases.push(langId);\n let langAliases = null;\n if (typeof lang.aliases !== 'undefined' && Array.isArray(lang.aliases)) {\n if (lang.aliases.length === 0) {\n // signal that this language should not get a name\n langAliases = [null];\n }\n else {\n langAliases = lang.aliases;\n }\n }\n if (langAliases !== null) {\n for (const langAlias of langAliases) {\n if (!langAlias || langAlias.length === 0) {\n continue;\n }\n resolvedLanguage.aliases.push(langAlias);\n }\n }\n const containsAliases = (langAliases !== null && langAliases.length > 0);\n if (containsAliases && langAliases[0] === null) {\n // signal that this language should not get a name\n }\n else {\n const bestName = (containsAliases ? langAliases[0] : null) || langId;\n if (containsAliases || !resolvedLanguage.name) {\n resolvedLanguage.name = bestName;\n }\n }\n if (lang.configuration) {\n resolvedLanguage.configurationFiles.push(lang.configuration);\n }\n if (lang.icon) {\n resolvedLanguage.icons.push(lang.icon);\n }\n }\n isRegisteredLanguageId(languageId) {\n if (!languageId) {\n return false;\n }\n return hasOwnProperty.call(this._languages, languageId);\n }\n getRegisteredLanguageIds() {\n return Object.keys(this._languages);\n }\n getLanguageIdByLanguageName(languageName) {\n const languageNameLower = languageName.toLowerCase();\n if (!hasOwnProperty.call(this._lowercaseNameMap, languageNameLower)) {\n return null;\n }\n return this._lowercaseNameMap[languageNameLower];\n }\n getLanguageIdByMimeType(mimeType) {\n if (!mimeType) {\n return null;\n }\n if (hasOwnProperty.call(this._mimeTypesMap, mimeType)) {\n return this._mimeTypesMap[mimeType];\n }\n return null;\n }\n guessLanguageIdByFilepathOrFirstLine(resource, firstLine) {\n if (!resource && !firstLine) {\n return [];\n }\n return getLanguageIds(resource, firstLine);\n }\n}\nLanguagesRegistry.instanceCount = 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 *--------------------------------------------------------------------------------------------*/\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { LanguagesRegistry } from './languagesRegistry.js';\nimport { firstOrDefault } from '../../../base/common/arrays.js';\nimport { TokenizationRegistry } from '../languages.js';\nimport { PLAINTEXT_LANGUAGE_ID } from '../languages/modesRegistry.js';\nexport class LanguageService extends Disposable {\n constructor(warnOnOverwrite = false) {\n super();\n this._onDidEncounterLanguage = this._register(new Emitter());\n this.onDidEncounterLanguage = this._onDidEncounterLanguage.event;\n this._onDidChange = this._register(new Emitter({ leakWarningThreshold: 200 /* https://github.com/microsoft/vscode/issues/119968 */ }));\n this.onDidChange = this._onDidChange.event;\n LanguageService.instanceCount++;\n this._encounteredLanguages = new Set();\n this._registry = this._register(new LanguagesRegistry(true, warnOnOverwrite));\n this.languageIdCodec = this._registry.languageIdCodec;\n this._register(this._registry.onDidChange(() => this._onDidChange.fire()));\n }\n dispose() {\n LanguageService.instanceCount--;\n super.dispose();\n }\n isRegisteredLanguageId(languageId) {\n return this._registry.isRegisteredLanguageId(languageId);\n }\n getLanguageIdByLanguageName(languageName) {\n return this._registry.getLanguageIdByLanguageName(languageName);\n }\n getLanguageIdByMimeType(mimeType) {\n return this._registry.getLanguageIdByMimeType(mimeType);\n }\n guessLanguageIdByFilepathOrFirstLine(resource, firstLine) {\n const languageIds = this._registry.guessLanguageIdByFilepathOrFirstLine(resource, firstLine);\n return firstOrDefault(languageIds, null);\n }\n createById(languageId) {\n return new LanguageSelection(this.onDidChange, () => {\n return this._createAndGetLanguageIdentifier(languageId);\n });\n }\n createByFilepathOrFirstLine(resource, firstLine) {\n return new LanguageSelection(this.onDidChange, () => {\n const languageId = this.guessLanguageIdByFilepathOrFirstLine(resource, firstLine);\n return this._createAndGetLanguageIdentifier(languageId);\n });\n }\n _createAndGetLanguageIdentifier(languageId) {\n if (!languageId || !this.isRegisteredLanguageId(languageId)) {\n // Fall back to plain text if language is unknown\n languageId = PLAINTEXT_LANGUAGE_ID;\n }\n if (!this._encounteredLanguages.has(languageId)) {\n this._encounteredLanguages.add(languageId);\n // Ensure tokenizers are created\n TokenizationRegistry.getOrCreate(languageId);\n // Fire event\n this._onDidEncounterLanguage.fire(languageId);\n }\n return languageId;\n }\n}\nLanguageService.instanceCount = 0;\nclass LanguageSelection {\n constructor(_onDidChangeLanguages, _selector) {\n this._onDidChangeLanguages = _onDidChangeLanguages;\n this._selector = _selector;\n this._listener = null;\n this._emitter = null;\n this.languageId = this._selector();\n }\n _dispose() {\n if (this._listener) {\n this._listener.dispose();\n this._listener = null;\n }\n if (this._emitter) {\n this._emitter.dispose();\n this._emitter = null;\n }\n }\n get onDidChange() {\n if (!this._listener) {\n this._listener = this._onDidChangeLanguages(() => this._evaluate());\n }\n if (!this._emitter) {\n this._emitter = new Emitter({\n onLastListenerRemove: () => {\n this._dispose();\n }\n });\n }\n return this._emitter.event;\n }\n _evaluate() {\n var _a;\n const languageId = this._selector();\n if (languageId === this.languageId) {\n // no change\n return;\n }\n this.languageId = languageId;\n (_a = this._emitter) === null || _a === void 0 ? void 0 : _a.fire(this.languageId);\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 *--------------------------------------------------------------------------------------------*/\nimport { isFirefox } from '../../browser.js';\nimport { EventType as TouchEventType, Gesture } from '../../touch.js';\nimport { $, addDisposableListener, append, clearNode, createStyleSheet, Dimension, EventHelper, EventType, getActiveElement, isAncestor, isInShadowDOM } from '../../dom.js';\nimport { StandardKeyboardEvent } from '../../keyboardEvent.js';\nimport { StandardMouseEvent } from '../../mouseEvent.js';\nimport { ActionBar } from '../actionbar/actionbar.js';\nimport { ActionViewItem, BaseActionViewItem } from '../actionbar/actionViewItems.js';\nimport { formatRule } from '../codicons/codiconStyles.js';\nimport { layout } from '../contextview/contextview.js';\nimport { DomScrollableElement } from '../scrollbar/scrollableElement.js';\nimport { EmptySubmenuAction, Separator, SubmenuAction } from '../../../common/actions.js';\nimport { RunOnceScheduler } from '../../../common/async.js';\nimport { Codicon } from '../../../common/codicons.js';\nimport { stripIcons } from '../../../common/iconLabels.js';\nimport { DisposableStore } from '../../../common/lifecycle.js';\nimport { isLinux, isMacintosh } from '../../../common/platform.js';\nimport * as strings from '../../../common/strings.js';\nexport const MENU_MNEMONIC_REGEX = /\\(&([^\\s&])\\)|(^|[^&])&([^\\s&])/;\nexport const MENU_ESCAPED_MNEMONIC_REGEX = /(&)?(&)([^\\s&])/g;\nexport var Direction;\n(function (Direction) {\n Direction[Direction[\"Right\"] = 0] = \"Right\";\n Direction[Direction[\"Left\"] = 1] = \"Left\";\n})(Direction || (Direction = {}));\nexport class Menu extends ActionBar {\n constructor(container, actions, options = {}) {\n container.classList.add('monaco-menu-container');\n container.setAttribute('role', 'presentation');\n const menuElement = document.createElement('div');\n menuElement.classList.add('monaco-menu');\n menuElement.setAttribute('role', 'presentation');\n super(menuElement, {\n orientation: 1 /* ActionsOrientation.VERTICAL */,\n actionViewItemProvider: action => this.doGetActionViewItem(action, options, parentData),\n context: options.context,\n actionRunner: options.actionRunner,\n ariaLabel: options.ariaLabel,\n ariaRole: 'menu',\n focusOnlyEnabledItems: true,\n triggerKeys: { keys: [3 /* KeyCode.Enter */, ...(isMacintosh || isLinux ? [10 /* KeyCode.Space */] : [])], keyDown: true }\n });\n this.menuElement = menuElement;\n this.actionsList.tabIndex = 0;\n this.menuDisposables = this._register(new DisposableStore());\n this.initializeOrUpdateStyleSheet(container, {});\n this._register(Gesture.addTarget(menuElement));\n addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => {\n const event = new StandardKeyboardEvent(e);\n // Stop tab navigation of menus\n if (event.equals(2 /* KeyCode.Tab */)) {\n e.preventDefault();\n }\n });\n if (options.enableMnemonics) {\n this.menuDisposables.add(addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => {\n const key = e.key.toLocaleLowerCase();\n if (this.mnemonics.has(key)) {\n EventHelper.stop(e, true);\n const actions = this.mnemonics.get(key);\n if (actions.length === 1) {\n if (actions[0] instanceof SubmenuMenuActionViewItem && actions[0].container) {\n this.focusItemByElement(actions[0].container);\n }\n actions[0].onClick(e);\n }\n if (actions.length > 1) {\n const action = actions.shift();\n if (action && action.container) {\n this.focusItemByElement(action.container);\n actions.push(action);\n }\n this.mnemonics.set(key, actions);\n }\n }\n }));\n }\n if (isLinux) {\n this._register(addDisposableListener(menuElement, EventType.KEY_DOWN, e => {\n const event = new StandardKeyboardEvent(e);\n if (event.equals(14 /* KeyCode.Home */) || event.equals(11 /* KeyCode.PageUp */)) {\n this.focusedItem = this.viewItems.length - 1;\n this.focusNext();\n EventHelper.stop(e, true);\n }\n else if (event.equals(13 /* KeyCode.End */) || event.equals(12 /* KeyCode.PageDown */)) {\n this.focusedItem = 0;\n this.focusPrevious();\n EventHelper.stop(e, true);\n }\n }));\n }\n this._register(addDisposableListener(this.domNode, EventType.MOUSE_OUT, e => {\n const relatedTarget = e.relatedTarget;\n if (!isAncestor(relatedTarget, this.domNode)) {\n this.focusedItem = undefined;\n this.updateFocus();\n e.stopPropagation();\n }\n }));\n this._register(addDisposableListener(this.actionsList, EventType.MOUSE_OVER, e => {\n let target = e.target;\n if (!target || !isAncestor(target, this.actionsList) || target === this.actionsList) {\n return;\n }\n while (target.parentElement !== this.actionsList && target.parentElement !== null) {\n target = target.parentElement;\n }\n if (target.classList.contains('action-item')) {\n const lastFocusedItem = this.focusedItem;\n this.setFocusedItem(target);\n if (lastFocusedItem !== this.focusedItem) {\n this.updateFocus();\n }\n }\n }));\n // Support touch on actions list to focus items (needed for submenus)\n this._register(Gesture.addTarget(this.actionsList));\n this._register(addDisposableListener(this.actionsList, TouchEventType.Tap, e => {\n let target = e.initialTarget;\n if (!target || !isAncestor(target, this.actionsList) || target === this.actionsList) {\n return;\n }\n while (target.parentElement !== this.actionsList && target.parentElement !== null) {\n target = target.parentElement;\n }\n if (target.classList.contains('action-item')) {\n const lastFocusedItem = this.focusedItem;\n this.setFocusedItem(target);\n if (lastFocusedItem !== this.focusedItem) {\n this.updateFocus();\n }\n }\n }));\n const parentData = {\n parent: this\n };\n this.mnemonics = new Map();\n // Scroll Logic\n this.scrollableElement = this._register(new DomScrollableElement(menuElement, {\n alwaysConsumeMouseWheel: true,\n horizontal: 2 /* ScrollbarVisibility.Hidden */,\n vertical: 3 /* ScrollbarVisibility.Visible */,\n verticalScrollbarSize: 7,\n handleMouseWheel: true,\n useShadows: true\n }));\n const scrollElement = this.scrollableElement.getDomNode();\n scrollElement.style.position = '';\n // Support scroll on menu drag\n this._register(addDisposableListener(menuElement, TouchEventType.Change, e => {\n EventHelper.stop(e, true);\n const scrollTop = this.scrollableElement.getScrollPosition().scrollTop;\n this.scrollableElement.setScrollPosition({ scrollTop: scrollTop - e.translationY });\n }));\n this._register(addDisposableListener(scrollElement, EventType.MOUSE_UP, e => {\n // Absorb clicks in menu dead space https://github.com/microsoft/vscode/issues/63575\n // We do this on the scroll element so the scroll bar doesn't dismiss the menu either\n e.preventDefault();\n }));\n menuElement.style.maxHeight = `${Math.max(10, window.innerHeight - container.getBoundingClientRect().top - 35)}px`;\n actions = actions.filter(a => {\n var _a;\n if ((_a = options.submenuIds) === null || _a === void 0 ? void 0 : _a.has(a.id)) {\n console.warn(`Found submenu cycle: ${a.id}`);\n return false;\n }\n return true;\n });\n this.push(actions, { icon: true, label: true, isMenu: true });\n container.appendChild(this.scrollableElement.getDomNode());\n this.scrollableElement.scanDomNode();\n this.viewItems.filter(item => !(item instanceof MenuSeparatorActionViewItem)).forEach((item, index, array) => {\n item.updatePositionInSet(index + 1, array.length);\n });\n }\n initializeOrUpdateStyleSheet(container, style) {\n if (!this.styleSheet) {\n if (isInShadowDOM(container)) {\n this.styleSheet = createStyleSheet(container);\n }\n else {\n if (!Menu.globalStyleSheet) {\n Menu.globalStyleSheet = createStyleSheet();\n }\n this.styleSheet = Menu.globalStyleSheet;\n }\n }\n this.styleSheet.textContent = getMenuWidgetCSS(style, isInShadowDOM(container));\n }\n style(style) {\n const container = this.getContainer();\n this.initializeOrUpdateStyleSheet(container, style);\n const fgColor = style.foregroundColor ? `${style.foregroundColor}` : '';\n const bgColor = style.backgroundColor ? `${style.backgroundColor}` : '';\n const border = style.borderColor ? `1px solid ${style.borderColor}` : '';\n const borderRadius = '5px';\n const shadow = style.shadowColor ? `0 2px 8px ${style.shadowColor}` : '';\n container.style.outline = border;\n container.style.borderRadius = borderRadius;\n container.style.color = fgColor;\n container.style.backgroundColor = bgColor;\n container.style.boxShadow = shadow;\n if (this.viewItems) {\n this.viewItems.forEach(item => {\n if (item instanceof BaseMenuActionViewItem || item instanceof MenuSeparatorActionViewItem) {\n item.style(style);\n }\n });\n }\n }\n getContainer() {\n return this.scrollableElement.getDomNode();\n }\n get onScroll() {\n return this.scrollableElement.onScroll;\n }\n focusItemByElement(element) {\n const lastFocusedItem = this.focusedItem;\n this.setFocusedItem(element);\n if (lastFocusedItem !== this.focusedItem) {\n this.updateFocus();\n }\n }\n setFocusedItem(element) {\n for (let i = 0; i < this.actionsList.children.length; i++) {\n const elem = this.actionsList.children[i];\n if (element === elem) {\n this.focusedItem = i;\n break;\n }\n }\n }\n updateFocus(fromRight) {\n super.updateFocus(fromRight, true, true);\n if (typeof this.focusedItem !== 'undefined') {\n // Workaround for #80047 caused by an issue in chromium\n // https://bugs.chromium.org/p/chromium/issues/detail?id=414283\n // When that's fixed, just call this.scrollableElement.scanDomNode()\n this.scrollableElement.setScrollPosition({\n scrollTop: Math.round(this.menuElement.scrollTop)\n });\n }\n }\n doGetActionViewItem(action, options, parentData) {\n if (action instanceof Separator) {\n return new MenuSeparatorActionViewItem(options.context, action, { icon: true });\n }\n else if (action instanceof SubmenuAction) {\n const menuActionViewItem = new SubmenuMenuActionViewItem(action, action.actions, parentData, Object.assign(Object.assign({}, options), { submenuIds: new Set([...(options.submenuIds || []), action.id]) }));\n if (options.enableMnemonics) {\n const mnemonic = menuActionViewItem.getMnemonic();\n if (mnemonic && menuActionViewItem.isEnabled()) {\n let actionViewItems = [];\n if (this.mnemonics.has(mnemonic)) {\n actionViewItems = this.mnemonics.get(mnemonic);\n }\n actionViewItems.push(menuActionViewItem);\n this.mnemonics.set(mnemonic, actionViewItems);\n }\n }\n return menuActionViewItem;\n }\n else {\n const menuItemOptions = { enableMnemonics: options.enableMnemonics, useEventAsContext: options.useEventAsContext };\n if (options.getKeyBinding) {\n const keybinding = options.getKeyBinding(action);\n if (keybinding) {\n const keybindingLabel = keybinding.getLabel();\n if (keybindingLabel) {\n menuItemOptions.keybinding = keybindingLabel;\n }\n }\n }\n const menuActionViewItem = new BaseMenuActionViewItem(options.context, action, menuItemOptions);\n if (options.enableMnemonics) {\n const mnemonic = menuActionViewItem.getMnemonic();\n if (mnemonic && menuActionViewItem.isEnabled()) {\n let actionViewItems = [];\n if (this.mnemonics.has(mnemonic)) {\n actionViewItems = this.mnemonics.get(mnemonic);\n }\n actionViewItems.push(menuActionViewItem);\n this.mnemonics.set(mnemonic, actionViewItems);\n }\n }\n return menuActionViewItem;\n }\n }\n}\nclass BaseMenuActionViewItem extends BaseActionViewItem {\n constructor(ctx, action, options = {}) {\n options.isMenu = true;\n super(action, action, options);\n this.options = options;\n this.options.icon = options.icon !== undefined ? options.icon : false;\n this.options.label = options.label !== undefined ? options.label : true;\n this.cssClass = '';\n // Set mnemonic\n if (this.options.label && options.enableMnemonics) {\n const label = this.getAction().label;\n if (label) {\n const matches = MENU_MNEMONIC_REGEX.exec(label);\n if (matches) {\n this.mnemonic = (!!matches[1] ? matches[1] : matches[3]).toLocaleLowerCase();\n }\n }\n }\n // Add mouse up listener later to avoid accidental clicks\n this.runOnceToEnableMouseUp = new RunOnceScheduler(() => {\n if (!this.element) {\n return;\n }\n this._register(addDisposableListener(this.element, EventType.MOUSE_UP, e => {\n // removed default prevention as it conflicts\n // with BaseActionViewItem #101537\n // add back if issues arise and link new issue\n EventHelper.stop(e, true);\n // See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Interact_with_the_clipboard\n // > Writing to the clipboard\n // > You can use the \"cut\" and \"copy\" commands without any special\n // permission if you are using them in a short-lived event handler\n // for a user action (for example, a click handler).\n // => to get the Copy and Paste context menu actions working on Firefox,\n // there should be no timeout here\n if (isFirefox) {\n const mouseEvent = new StandardMouseEvent(e);\n // Allowing right click to trigger the event causes the issue described below,\n // but since the solution below does not work in FF, we must disable right click\n if (mouseEvent.rightButton) {\n return;\n }\n this.onClick(e);\n }\n // In all other cases, set timeout to allow context menu cancellation to trigger\n // otherwise the action will destroy the menu and a second context menu\n // will still trigger for right click.\n else {\n setTimeout(() => {\n this.onClick(e);\n }, 0);\n }\n }));\n this._register(addDisposableListener(this.element, EventType.CONTEXT_MENU, e => {\n EventHelper.stop(e, true);\n }));\n }, 100);\n this._register(this.runOnceToEnableMouseUp);\n }\n render(container) {\n super.render(container);\n if (!this.element) {\n return;\n }\n this.container = container;\n this.item = append(this.element, $('a.action-menu-item'));\n if (this._action.id === Separator.ID) {\n // A separator is a presentation item\n this.item.setAttribute('role', 'presentation');\n }\n else {\n this.item.setAttribute('role', 'menuitem');\n if (this.mnemonic) {\n this.item.setAttribute('aria-keyshortcuts', `${this.mnemonic}`);\n }\n }\n this.check = append(this.item, $('span.menu-item-check' + Codicon.menuSelection.cssSelector));\n this.check.setAttribute('role', 'none');\n this.label = append(this.item, $('span.action-label'));\n if (this.options.label && this.options.keybinding) {\n append(this.item, $('span.keybinding')).textContent = this.options.keybinding;\n }\n // Adds mouse up listener to actually run the action\n this.runOnceToEnableMouseUp.schedule();\n this.updateClass();\n this.updateLabel();\n this.updateTooltip();\n this.updateEnabled();\n this.updateChecked();\n }\n blur() {\n super.blur();\n this.applyStyle();\n }\n focus() {\n super.focus();\n if (this.item) {\n this.item.focus();\n }\n this.applyStyle();\n }\n updatePositionInSet(pos, setSize) {\n if (this.item) {\n this.item.setAttribute('aria-posinset', `${pos}`);\n this.item.setAttribute('aria-setsize', `${setSize}`);\n }\n }\n updateLabel() {\n var _a;\n if (!this.label) {\n return;\n }\n if (this.options.label) {\n clearNode(this.label);\n let label = stripIcons(this.getAction().label);\n if (label) {\n const cleanLabel = cleanMnemonic(label);\n if (!this.options.enableMnemonics) {\n label = cleanLabel;\n }\n this.label.setAttribute('aria-label', cleanLabel.replace(/&&/g, '&'));\n const matches = MENU_MNEMONIC_REGEX.exec(label);\n if (matches) {\n label = strings.escape(label);\n // This is global, reset it\n MENU_ESCAPED_MNEMONIC_REGEX.lastIndex = 0;\n let escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(label);\n // We can't use negative lookbehind so if we match our negative and skip\n while (escMatch && escMatch[1]) {\n escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(label);\n }\n const replaceDoubleEscapes = (str) => str.replace(/&&/g, '&');\n if (escMatch) {\n this.label.append(strings.ltrim(replaceDoubleEscapes(label.substr(0, escMatch.index)), ' '), $('u', { 'aria-hidden': 'true' }, escMatch[3]), strings.rtrim(replaceDoubleEscapes(label.substr(escMatch.index + escMatch[0].length)), ' '));\n }\n else {\n this.label.innerText = replaceDoubleEscapes(label).trim();\n }\n (_a = this.item) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-keyshortcuts', (!!matches[1] ? matches[1] : matches[3]).toLocaleLowerCase());\n }\n else {\n this.label.innerText = label.replace(/&&/g, '&').trim();\n }\n }\n }\n }\n updateTooltip() {\n // menus should function like native menus and they do not have tooltips\n }\n updateClass() {\n if (this.cssClass && this.item) {\n this.item.classList.remove(...this.cssClass.split(' '));\n }\n if (this.options.icon && this.label) {\n this.cssClass = this.getAction().class || '';\n this.label.classList.add('icon');\n if (this.cssClass) {\n this.label.classList.add(...this.cssClass.split(' '));\n }\n this.updateEnabled();\n }\n else if (this.label) {\n this.label.classList.remove('icon');\n }\n }\n updateEnabled() {\n if (this.getAction().enabled) {\n if (this.element) {\n this.element.classList.remove('disabled');\n this.element.removeAttribute('aria-disabled');\n }\n if (this.item) {\n this.item.classList.remove('disabled');\n this.item.removeAttribute('aria-disabled');\n this.item.tabIndex = 0;\n }\n }\n else {\n if (this.element) {\n this.element.classList.add('disabled');\n this.element.setAttribute('aria-disabled', 'true');\n }\n if (this.item) {\n this.item.classList.add('disabled');\n this.item.setAttribute('aria-disabled', 'true');\n }\n }\n }\n updateChecked() {\n if (!this.item) {\n return;\n }\n const checked = this.getAction().checked;\n this.item.classList.toggle('checked', !!checked);\n if (checked !== undefined) {\n this.item.setAttribute('role', 'menuitemcheckbox');\n this.item.setAttribute('aria-checked', checked ? 'true' : 'false');\n }\n else {\n this.item.setAttribute('role', 'menuitem');\n this.item.setAttribute('aria-checked', '');\n }\n }\n getMnemonic() {\n return this.mnemonic;\n }\n applyStyle() {\n if (!this.menuStyle) {\n return;\n }\n const isSelected = this.element && this.element.classList.contains('focused');\n const fgColor = isSelected && this.menuStyle.selectionForegroundColor ? this.menuStyle.selectionForegroundColor : this.menuStyle.foregroundColor;\n const bgColor = isSelected && this.menuStyle.selectionBackgroundColor ? this.menuStyle.selectionBackgroundColor : undefined;\n const outline = isSelected && this.menuStyle.selectionBorderColor ? `1px solid ${this.menuStyle.selectionBorderColor}` : '';\n const outlineOffset = isSelected && this.menuStyle.selectionBorderColor ? `-1px` : '';\n if (this.item) {\n this.item.style.color = fgColor ? fgColor.toString() : '';\n this.item.style.backgroundColor = bgColor ? bgColor.toString() : '';\n this.item.style.outline = outline;\n this.item.style.outlineOffset = outlineOffset;\n }\n if (this.check) {\n this.check.style.color = fgColor ? fgColor.toString() : '';\n }\n }\n style(style) {\n this.menuStyle = style;\n this.applyStyle();\n }\n}\nclass SubmenuMenuActionViewItem extends BaseMenuActionViewItem {\n constructor(action, submenuActions, parentData, submenuOptions) {\n super(action, action, submenuOptions);\n this.submenuActions = submenuActions;\n this.parentData = parentData;\n this.submenuOptions = submenuOptions;\n this.mysubmenu = null;\n this.submenuDisposables = this._register(new DisposableStore());\n this.mouseOver = false;\n this.expandDirection = submenuOptions && submenuOptions.expandDirection !== undefined ? submenuOptions.expandDirection : Direction.Right;\n this.showScheduler = new RunOnceScheduler(() => {\n if (this.mouseOver) {\n this.cleanupExistingSubmenu(false);\n this.createSubmenu(false);\n }\n }, 250);\n this.hideScheduler = new RunOnceScheduler(() => {\n if (this.element && (!isAncestor(getActiveElement(), this.element) && this.parentData.submenu === this.mysubmenu)) {\n this.parentData.parent.focus(false);\n this.cleanupExistingSubmenu(true);\n }\n }, 750);\n }\n render(container) {\n super.render(container);\n if (!this.element) {\n return;\n }\n if (this.item) {\n this.item.classList.add('monaco-submenu-item');\n this.item.tabIndex = 0;\n this.item.setAttribute('aria-haspopup', 'true');\n this.updateAriaExpanded('false');\n this.submenuIndicator = append(this.item, $('span.submenu-indicator' + Codicon.menuSubmenu.cssSelector));\n this.submenuIndicator.setAttribute('aria-hidden', 'true');\n }\n this._register(addDisposableListener(this.element, EventType.KEY_UP, e => {\n const event = new StandardKeyboardEvent(e);\n if (event.equals(17 /* KeyCode.RightArrow */) || event.equals(3 /* KeyCode.Enter */)) {\n EventHelper.stop(e, true);\n this.createSubmenu(true);\n }\n }));\n this._register(addDisposableListener(this.element, EventType.KEY_DOWN, e => {\n const event = new StandardKeyboardEvent(e);\n if (getActiveElement() === this.item) {\n if (event.equals(17 /* KeyCode.RightArrow */) || event.equals(3 /* KeyCode.Enter */)) {\n EventHelper.stop(e, true);\n }\n }\n }));\n this._register(addDisposableListener(this.element, EventType.MOUSE_OVER, e => {\n if (!this.mouseOver) {\n this.mouseOver = true;\n this.showScheduler.schedule();\n }\n }));\n this._register(addDisposableListener(this.element, EventType.MOUSE_LEAVE, e => {\n this.mouseOver = false;\n }));\n this._register(addDisposableListener(this.element, EventType.FOCUS_OUT, e => {\n if (this.element && !isAncestor(getActiveElement(), this.element)) {\n this.hideScheduler.schedule();\n }\n }));\n this._register(this.parentData.parent.onScroll(() => {\n if (this.parentData.submenu === this.mysubmenu) {\n this.parentData.parent.focus(false);\n this.cleanupExistingSubmenu(true);\n }\n }));\n }\n updateEnabled() {\n // override on submenu entry\n // native menus do not observe enablement on sumbenus\n // we mimic that behavior\n }\n onClick(e) {\n // stop clicking from trying to run an action\n EventHelper.stop(e, true);\n this.cleanupExistingSubmenu(false);\n this.createSubmenu(true);\n }\n cleanupExistingSubmenu(force) {\n if (this.parentData.submenu && (force || (this.parentData.submenu !== this.mysubmenu))) {\n // disposal may throw if the submenu has already been removed\n try {\n this.parentData.submenu.dispose();\n }\n catch (_a) { }\n this.parentData.submenu = undefined;\n this.updateAriaExpanded('false');\n if (this.submenuContainer) {\n this.submenuDisposables.clear();\n this.submenuContainer = undefined;\n }\n }\n }\n calculateSubmenuMenuLayout(windowDimensions, submenu, entry, expandDirection) {\n const ret = { top: 0, left: 0 };\n // Start with horizontal\n ret.left = layout(windowDimensions.width, submenu.width, { position: expandDirection === Direction.Right ? 0 /* LayoutAnchorPosition.Before */ : 1 /* LayoutAnchorPosition.After */, offset: entry.left, size: entry.width });\n // We don't have enough room to layout the menu fully, so we are overlapping the menu\n if (ret.left >= entry.left && ret.left < entry.left + entry.width) {\n if (entry.left + 10 + submenu.width <= windowDimensions.width) {\n ret.left = entry.left + 10;\n }\n entry.top += 10;\n entry.height = 0;\n }\n // Now that we have a horizontal position, try layout vertically\n ret.top = layout(windowDimensions.height, submenu.height, { position: 0 /* LayoutAnchorPosition.Before */, offset: entry.top, size: 0 });\n // We didn't have enough room below, but we did above, so we shift down to align the menu\n if (ret.top + submenu.height === entry.top && ret.top + entry.height + submenu.height <= windowDimensions.height) {\n ret.top += entry.height;\n }\n return ret;\n }\n createSubmenu(selectFirstItem = true) {\n if (!this.element) {\n return;\n }\n if (!this.parentData.submenu) {\n this.updateAriaExpanded('true');\n this.submenuContainer = append(this.element, $('div.monaco-submenu'));\n this.submenuContainer.classList.add('menubar-menu-items-holder', 'context-view');\n // Set the top value of the menu container before construction\n // This allows the menu constructor to calculate the proper max height\n const computedStyles = getComputedStyle(this.parentData.parent.domNode);\n const paddingTop = parseFloat(computedStyles.paddingTop || '0') || 0;\n // this.submenuContainer.style.top = `${this.element.offsetTop - this.parentData.parent.scrollOffset - paddingTop}px`;\n this.submenuContainer.style.zIndex = '1';\n this.submenuContainer.style.position = 'fixed';\n this.submenuContainer.style.top = '0';\n this.submenuContainer.style.left = '0';\n this.parentData.submenu = new Menu(this.submenuContainer, this.submenuActions.length ? this.submenuActions : [new EmptySubmenuAction()], this.submenuOptions);\n if (this.menuStyle) {\n this.parentData.submenu.style(this.menuStyle);\n }\n // layout submenu\n const entryBox = this.element.getBoundingClientRect();\n const entryBoxUpdated = {\n top: entryBox.top - paddingTop,\n left: entryBox.left,\n height: entryBox.height + 2 * paddingTop,\n width: entryBox.width\n };\n const viewBox = this.submenuContainer.getBoundingClientRect();\n const { top, left } = this.calculateSubmenuMenuLayout(new Dimension(window.innerWidth, window.innerHeight), Dimension.lift(viewBox), entryBoxUpdated, this.expandDirection);\n // subtract offsets caused by transform parent\n this.submenuContainer.style.left = `${left - viewBox.left}px`;\n this.submenuContainer.style.top = `${top - viewBox.top}px`;\n this.submenuDisposables.add(addDisposableListener(this.submenuContainer, EventType.KEY_UP, e => {\n const event = new StandardKeyboardEvent(e);\n if (event.equals(15 /* KeyCode.LeftArrow */)) {\n EventHelper.stop(e, true);\n this.parentData.parent.focus();\n this.cleanupExistingSubmenu(true);\n }\n }));\n this.submenuDisposables.add(addDisposableListener(this.submenuContainer, EventType.KEY_DOWN, e => {\n const event = new StandardKeyboardEvent(e);\n if (event.equals(15 /* KeyCode.LeftArrow */)) {\n EventHelper.stop(e, true);\n }\n }));\n this.submenuDisposables.add(this.parentData.submenu.onDidCancel(() => {\n this.parentData.parent.focus();\n this.cleanupExistingSubmenu(true);\n }));\n this.parentData.submenu.focus(selectFirstItem);\n this.mysubmenu = this.parentData.submenu;\n }\n else {\n this.parentData.submenu.focus(false);\n }\n }\n updateAriaExpanded(value) {\n var _a;\n if (this.item) {\n (_a = this.item) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-expanded', value);\n }\n }\n applyStyle() {\n var _a;\n super.applyStyle();\n if (!this.menuStyle) {\n return;\n }\n const isSelected = this.element && this.element.classList.contains('focused');\n const fgColor = isSelected && this.menuStyle.selectionForegroundColor ? this.menuStyle.selectionForegroundColor : this.menuStyle.foregroundColor;\n if (this.submenuIndicator) {\n this.submenuIndicator.style.color = fgColor ? `${fgColor}` : '';\n }\n (_a = this.parentData.submenu) === null || _a === void 0 ? void 0 : _a.style(this.menuStyle);\n }\n dispose() {\n super.dispose();\n this.hideScheduler.dispose();\n if (this.mysubmenu) {\n this.mysubmenu.dispose();\n this.mysubmenu = null;\n }\n if (this.submenuContainer) {\n this.submenuContainer = undefined;\n }\n }\n}\nclass MenuSeparatorActionViewItem extends ActionViewItem {\n style(style) {\n if (this.label) {\n this.label.style.borderBottomColor = style.separatorColor ? `${style.separatorColor}` : '';\n }\n }\n}\nexport function cleanMnemonic(label) {\n const regex = MENU_MNEMONIC_REGEX;\n const matches = regex.exec(label);\n if (!matches) {\n return label;\n }\n const mnemonicInText = !matches[1];\n return label.replace(regex, mnemonicInText ? '$2$3' : '').trim();\n}\nfunction getMenuWidgetCSS(style, isForShadowDom) {\n let result = /* css */ `\n.monaco-menu {\n\tfont-size: 13px;\n\tborder-radius: 5px;\n\tmin-width: 160px;\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\tcolor: var(--vscode-disabledForeground);\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 var(--vscode-menu-separatorBackground);\n\tpadding-top: 1px;\n\tpadding: 30px;\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-menu-item:hover .keybinding,\n.monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .keybinding {\n\topacity: unset;\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\twidth: 100%;\n\theight: 0px !important;\n\topacity: 1;\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.hc-black .context-view.monaco-menu-container,\n.hc-light .context-view.monaco-menu-container,\n:host-context(.hc-black) .context-view.monaco-menu-container,\n:host-context(.hc-light) .context-view.monaco-menu-container {\n\tbox-shadow: none;\n}\n\n.hc-black .monaco-menu .monaco-action-bar.vertical .action-item.focused,\n.hc-light .monaco-menu .monaco-action-bar.vertical .action-item.focused,\n:host-context(.hc-black) .monaco-menu .monaco-action-bar.vertical .action-item.focused,\n:host-context(.hc-light) .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: .6em 0;\n}\n\n.monaco-menu .monaco-action-bar.vertical .action-menu-item {\n\theight: 2em;\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\tmargin: 5px 0 !important;\n\tpadding: 0;\n\tborder-radius: 0;\n}\n\n.linux .monaco-menu .monaco-action-bar.vertical .action-label.separator,\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.linux .monaco-menu .monaco-action-bar.vertical .submenu-indicator {\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 if (isForShadowDom) {\n // Only define scrollbar styles when used inside shadow dom,\n // otherwise leave their styling to the global workbench styling.\n result += `\n\t\t\t/* Arrows */\n\t\t\t.monaco-scrollable-element > .scrollbar > .scra {\n\t\t\t\tcursor: pointer;\n\t\t\t\tfont-size: 11px !important;\n\t\t\t}\n\n\t\t\t.monaco-scrollable-element > .visible {\n\t\t\t\topacity: 1;\n\n\t\t\t\t/* Background rule added for IE9 - to allow clicks on dom node */\n\t\t\t\tbackground:rgba(0,0,0,0);\n\n\t\t\t\ttransition: opacity 100ms linear;\n\t\t\t}\n\t\t\t.monaco-scrollable-element > .invisible {\n\t\t\t\topacity: 0;\n\t\t\t\tpointer-events: none;\n\t\t\t}\n\t\t\t.monaco-scrollable-element > .invisible.fade {\n\t\t\t\ttransition: opacity 800ms linear;\n\t\t\t}\n\n\t\t\t/* Scrollable Content Inset Shadow */\n\t\t\t.monaco-scrollable-element > .shadow {\n\t\t\t\tposition: absolute;\n\t\t\t\tdisplay: none;\n\t\t\t}\n\t\t\t.monaco-scrollable-element > .shadow.top {\n\t\t\t\tdisplay: block;\n\t\t\t\ttop: 0;\n\t\t\t\tleft: 3px;\n\t\t\t\theight: 3px;\n\t\t\t\twidth: 100%;\n\t\t\t}\n\t\t\t.monaco-scrollable-element > .shadow.left {\n\t\t\t\tdisplay: block;\n\t\t\t\ttop: 3px;\n\t\t\t\tleft: 0;\n\t\t\t\theight: 100%;\n\t\t\t\twidth: 3px;\n\t\t\t}\n\t\t\t.monaco-scrollable-element > .shadow.top-left-corner {\n\t\t\t\tdisplay: block;\n\t\t\t\ttop: 0;\n\t\t\t\tleft: 0;\n\t\t\t\theight: 3px;\n\t\t\t\twidth: 3px;\n\t\t\t}\n\t\t`;\n // Scrollbars\n const scrollbarShadowColor = style.scrollbarShadow;\n if (scrollbarShadowColor) {\n result += `\n\t\t\t\t.monaco-scrollable-element > .shadow.top {\n\t\t\t\t\tbox-shadow: ${scrollbarShadowColor} 0 6px 6px -6px inset;\n\t\t\t\t}\n\n\t\t\t\t.monaco-scrollable-element > .shadow.left {\n\t\t\t\t\tbox-shadow: ${scrollbarShadowColor} 6px 0 6px -6px inset;\n\t\t\t\t}\n\n\t\t\t\t.monaco-scrollable-element > .shadow.top.left {\n\t\t\t\t\tbox-shadow: ${scrollbarShadowColor} 6px 6px 6px -6px inset;\n\t\t\t\t}\n\t\t\t`;\n }\n const scrollbarSliderBackgroundColor = style.scrollbarSliderBackground;\n if (scrollbarSliderBackgroundColor) {\n result += `\n\t\t\t\t.monaco-scrollable-element > .scrollbar > .slider {\n\t\t\t\t\tbackground: ${scrollbarSliderBackgroundColor};\n\t\t\t\t}\n\t\t\t`;\n }\n const scrollbarSliderHoverBackgroundColor = style.scrollbarSliderHoverBackground;\n if (scrollbarSliderHoverBackgroundColor) {\n result += `\n\t\t\t\t.monaco-scrollable-element > .scrollbar > .slider:hover {\n\t\t\t\t\tbackground: ${scrollbarSliderHoverBackgroundColor};\n\t\t\t\t}\n\t\t\t`;\n }\n const scrollbarSliderActiveBackgroundColor = style.scrollbarSliderActiveBackground;\n if (scrollbarSliderActiveBackgroundColor) {\n result += `\n\t\t\t\t.monaco-scrollable-element > .scrollbar > .slider.active {\n\t\t\t\t\tbackground: ${scrollbarSliderActiveBackgroundColor};\n\t\t\t\t}\n\t\t\t`;\n }\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { $, addDisposableListener, EventType, isHTMLElement } from '../../../base/browser/dom.js';\nimport { StandardMouseEvent } from '../../../base/browser/mouseEvent.js';\nimport { Menu } from '../../../base/browser/ui/menu/menu.js';\nimport { ActionRunner } from '../../../base/common/actions.js';\nimport { isCancellationError } from '../../../base/common/errors.js';\nimport { combinedDisposable, DisposableStore } from '../../../base/common/lifecycle.js';\nimport { attachMenuStyler } from '../../theme/common/styler.js';\nexport class ContextMenuHandler {\n constructor(contextViewService, telemetryService, notificationService, keybindingService, themeService) {\n this.contextViewService = contextViewService;\n this.telemetryService = telemetryService;\n this.notificationService = notificationService;\n this.keybindingService = keybindingService;\n this.themeService = themeService;\n this.focusToReturn = null;\n this.block = null;\n this.options = { blockMouse: true };\n }\n configure(options) {\n this.options = options;\n }\n showContextMenu(delegate) {\n const actions = delegate.getActions();\n if (!actions.length) {\n return; // Don't render an empty context menu\n }\n this.focusToReturn = document.activeElement;\n let menu;\n const shadowRootElement = isHTMLElement(delegate.domForShadowRoot) ? delegate.domForShadowRoot : undefined;\n this.contextViewService.showContextView({\n getAnchor: () => delegate.getAnchor(),\n canRelayout: false,\n anchorAlignment: delegate.anchorAlignment,\n anchorAxisAlignment: delegate.anchorAxisAlignment,\n render: (container) => {\n const className = delegate.getMenuClassName ? delegate.getMenuClassName() : '';\n if (className) {\n container.className += ' ' + className;\n }\n // Render invisible div to block mouse interaction in the rest of the UI\n if (this.options.blockMouse) {\n this.block = container.appendChild($('.context-view-block'));\n this.block.style.position = 'fixed';\n this.block.style.cursor = 'initial';\n this.block.style.left = '0';\n this.block.style.top = '0';\n this.block.style.width = '100%';\n this.block.style.height = '100%';\n this.block.style.zIndex = '-1';\n // TODO@Steven: this is never getting disposed\n addDisposableListener(this.block, EventType.MOUSE_DOWN, e => e.stopPropagation());\n }\n const menuDisposables = new DisposableStore();\n const actionRunner = delegate.actionRunner || new ActionRunner();\n actionRunner.onBeforeRun(this.onActionRun, this, menuDisposables);\n actionRunner.onDidRun(this.onDidActionRun, this, menuDisposables);\n menu = new Menu(container, actions, {\n actionViewItemProvider: delegate.getActionViewItem,\n context: delegate.getActionsContext ? delegate.getActionsContext() : null,\n actionRunner,\n getKeyBinding: delegate.getKeyBinding ? delegate.getKeyBinding : action => this.keybindingService.lookupKeybinding(action.id)\n });\n menuDisposables.add(attachMenuStyler(menu, this.themeService));\n menu.onDidCancel(() => this.contextViewService.hideContextView(true), null, menuDisposables);\n menu.onDidBlur(() => this.contextViewService.hideContextView(true), null, menuDisposables);\n menuDisposables.add(addDisposableListener(window, EventType.BLUR, () => this.contextViewService.hideContextView(true)));\n menuDisposables.add(addDisposableListener(window, EventType.MOUSE_DOWN, (e) => {\n if (e.defaultPrevented) {\n return;\n }\n const event = new StandardMouseEvent(e);\n let element = event.target;\n // Don't do anything as we are likely creating a context menu\n if (event.rightButton) {\n return;\n }\n while (element) {\n if (element === container) {\n return;\n }\n element = element.parentElement;\n }\n this.contextViewService.hideContextView(true);\n }));\n return combinedDisposable(menuDisposables, menu);\n },\n focus: () => {\n menu === null || menu === void 0 ? void 0 : menu.focus(!!delegate.autoSelectFirstItem);\n },\n onHide: (didCancel) => {\n var _a;\n (_a = delegate.onHide) === null || _a === void 0 ? void 0 : _a.call(delegate, !!didCancel);\n if (this.block) {\n this.block.remove();\n this.block = null;\n }\n if (this.focusToReturn) {\n this.focusToReturn.focus();\n }\n }\n }, shadowRootElement, !!shadowRootElement);\n }\n onActionRun(e) {\n this.telemetryService.publicLog2('workbenchActionExecuted', { id: e.action.id, from: 'contextMenu' });\n this.contextViewService.hideContextView(false);\n // Restore focus here\n if (this.focusToReturn) {\n this.focusToReturn.focus();\n }\n }\n onDidActionRun(e) {\n if (e.error && !isCancellationError(e.error)) {\n this.notificationService.error(e.error);\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { ModifierKeyEmitter } from '../../../base/browser/dom.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { IKeybindingService } from '../../keybinding/common/keybinding.js';\nimport { INotificationService } from '../../notification/common/notification.js';\nimport { ITelemetryService } from '../../telemetry/common/telemetry.js';\nimport { IThemeService } from '../../theme/common/themeService.js';\nimport { ContextMenuHandler } from './contextMenuHandler.js';\nimport { IContextViewService } from './contextView.js';\nlet ContextMenuService = class ContextMenuService extends Disposable {\n constructor(telemetryService, notificationService, contextViewService, keybindingService, themeService) {\n super();\n this._onDidShowContextMenu = new Emitter();\n this._onDidHideContextMenu = new Emitter();\n this.contextMenuHandler = new ContextMenuHandler(contextViewService, telemetryService, notificationService, keybindingService, themeService);\n }\n configure(options) {\n this.contextMenuHandler.configure(options);\n }\n // ContextMenu\n showContextMenu(delegate) {\n this.contextMenuHandler.showContextMenu(Object.assign(Object.assign({}, delegate), { onHide: (didCancel) => {\n var _a;\n (_a = delegate.onHide) === null || _a === void 0 ? void 0 : _a.call(delegate, didCancel);\n this._onDidHideContextMenu.fire();\n } }));\n ModifierKeyEmitter.getInstance().resetKeyStatus();\n this._onDidShowContextMenu.fire();\n }\n};\nContextMenuService = __decorate([\n __param(0, ITelemetryService),\n __param(1, INotificationService),\n __param(2, IContextViewService),\n __param(3, IKeybindingService),\n __param(4, IThemeService)\n], ContextMenuService);\nexport { ContextMenuService };\n","export var EditorOpenSource;\n(function (EditorOpenSource) {\n /**\n * Default: the editor is opening via a programmatic call\n * to the editor service API.\n */\n EditorOpenSource[EditorOpenSource[\"API\"] = 0] = \"API\";\n /**\n * Indicates that a user action triggered the opening, e.g.\n * via mouse or keyboard use.\n */\n EditorOpenSource[EditorOpenSource[\"USER\"] = 1] = \"USER\";\n})(EditorOpenSource || (EditorOpenSource = {}));\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport * as dom from '../../../base/browser/dom.js';\nimport { CancellationToken } from '../../../base/common/cancellation.js';\nimport { LinkedList } from '../../../base/common/linkedList.js';\nimport { ResourceMap } from '../../../base/common/map.js';\nimport { parse } from '../../../base/common/marshalling.js';\nimport { Schemas } from '../../../base/common/network.js';\nimport { normalizePath } from '../../../base/common/resources.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { ICodeEditorService } from './codeEditorService.js';\nimport { ICommandService } from '../../../platform/commands/common/commands.js';\nimport { EditorOpenSource } from '../../../platform/editor/common/editor.js';\nimport { extractSelection, matchesScheme, matchesSomeScheme } from '../../../platform/opener/common/opener.js';\nlet CommandOpener = class CommandOpener {\n constructor(_commandService) {\n this._commandService = _commandService;\n }\n open(target, options) {\n return __awaiter(this, void 0, void 0, function* () {\n if (!matchesScheme(target, Schemas.command)) {\n return false;\n }\n if (!(options === null || options === void 0 ? void 0 : options.allowCommands)) {\n // silently ignore commands when command-links are disabled, also\n // surpress other openers by returning TRUE\n return true;\n }\n // run command or bail out if command isn't known\n if (typeof target === 'string') {\n target = URI.parse(target);\n }\n // execute as command\n let args = [];\n try {\n args = parse(decodeURIComponent(target.query));\n }\n catch (_a) {\n // ignore and retry\n try {\n args = parse(target.query);\n }\n catch (_b) {\n // ignore error\n }\n }\n if (!Array.isArray(args)) {\n args = [args];\n }\n yield this._commandService.executeCommand(target.path, ...args);\n return true;\n });\n }\n};\nCommandOpener = __decorate([\n __param(0, ICommandService)\n], CommandOpener);\nlet EditorOpener = class EditorOpener {\n constructor(_editorService) {\n this._editorService = _editorService;\n }\n open(target, options) {\n return __awaiter(this, void 0, void 0, function* () {\n if (typeof target === 'string') {\n target = URI.parse(target);\n }\n const { selection, uri } = extractSelection(target);\n target = uri;\n if (target.scheme === Schemas.file) {\n target = normalizePath(target); // workaround for non-normalized paths (https://github.com/microsoft/vscode/issues/12954)\n }\n yield this._editorService.openCodeEditor({\n resource: target,\n options: Object.assign({ selection, source: (options === null || options === void 0 ? void 0 : options.fromUserGesture) ? EditorOpenSource.USER : EditorOpenSource.API }, options === null || options === void 0 ? void 0 : options.editorOptions)\n }, this._editorService.getFocusedCodeEditor(), options === null || options === void 0 ? void 0 : options.openToSide);\n return true;\n });\n }\n};\nEditorOpener = __decorate([\n __param(0, ICodeEditorService)\n], EditorOpener);\nlet OpenerService = class OpenerService {\n constructor(editorService, commandService) {\n this._openers = new LinkedList();\n this._validators = new LinkedList();\n this._resolvers = new LinkedList();\n this._resolvedUriTargets = new ResourceMap(uri => uri.with({ path: null, fragment: null, query: null }).toString());\n this._externalOpeners = new LinkedList();\n // Default external opener is going through window.open()\n this._defaultExternalOpener = {\n openExternal: (href) => __awaiter(this, void 0, void 0, function* () {\n // ensure to open HTTP/HTTPS links into new windows\n // to not trigger a navigation. Any other link is\n // safe to be set as HREF to prevent a blank window\n // from opening.\n if (matchesSomeScheme(href, Schemas.http, Schemas.https)) {\n dom.windowOpenNoOpener(href);\n }\n else {\n window.location.href = href;\n }\n return true;\n })\n };\n // Default opener: any external, maito, http(s), command, and catch-all-editors\n this._openers.push({\n open: (target, options) => __awaiter(this, void 0, void 0, function* () {\n if ((options === null || options === void 0 ? void 0 : options.openExternal) || matchesSomeScheme(target, Schemas.mailto, Schemas.http, Schemas.https, Schemas.vsls)) {\n // open externally\n yield this._doOpenExternal(target, options);\n return true;\n }\n return false;\n })\n });\n this._openers.push(new CommandOpener(commandService));\n this._openers.push(new EditorOpener(editorService));\n }\n registerOpener(opener) {\n const remove = this._openers.unshift(opener);\n return { dispose: remove };\n }\n registerValidator(validator) {\n const remove = this._validators.push(validator);\n return { dispose: remove };\n }\n registerExternalUriResolver(resolver) {\n const remove = this._resolvers.push(resolver);\n return { dispose: remove };\n }\n setDefaultExternalOpener(externalOpener) {\n this._defaultExternalOpener = externalOpener;\n }\n registerExternalOpener(opener) {\n const remove = this._externalOpeners.push(opener);\n return { dispose: remove };\n }\n open(target, options) {\n var _a;\n return __awaiter(this, void 0, void 0, function* () {\n // check with contributed validators\n const targetURI = typeof target === 'string' ? URI.parse(target) : target;\n // validate against the original URI that this URI resolves to, if one exists\n const validationTarget = (_a = this._resolvedUriTargets.get(targetURI)) !== null && _a !== void 0 ? _a : target;\n for (const validator of this._validators) {\n if (!(yield validator.shouldOpen(validationTarget, options))) {\n return false;\n }\n }\n // check with contributed openers\n for (const opener of this._openers) {\n const handled = yield opener.open(target, options);\n if (handled) {\n return true;\n }\n }\n return false;\n });\n }\n resolveExternalUri(resource, options) {\n return __awaiter(this, void 0, void 0, function* () {\n for (const resolver of this._resolvers) {\n try {\n const result = yield resolver.resolveExternalUri(resource, options);\n if (result) {\n if (!this._resolvedUriTargets.has(result.resolved)) {\n this._resolvedUriTargets.set(result.resolved, resource);\n }\n return result;\n }\n }\n catch (_a) {\n // noop\n }\n }\n throw new Error('Could not resolve external URI: ' + resource.toString());\n });\n }\n _doOpenExternal(resource, options) {\n return __awaiter(this, void 0, void 0, function* () {\n //todo@jrieken IExternalUriResolver should support `uri: URI | string`\n const uri = typeof resource === 'string' ? URI.parse(resource) : resource;\n let externalUri;\n try {\n externalUri = (yield this.resolveExternalUri(uri, options)).resolved;\n }\n catch (_a) {\n externalUri = uri;\n }\n let href;\n if (typeof resource === 'string' && uri.toString() === externalUri.toString()) {\n // open the url-string AS IS\n href = resource;\n }\n else {\n // open URI using the toString(noEncode)+encodeURI-trick\n href = encodeURI(externalUri.toString(true));\n }\n if (options === null || options === void 0 ? void 0 : options.allowContributedOpeners) {\n const preferredOpenerId = typeof (options === null || options === void 0 ? void 0 : options.allowContributedOpeners) === 'string' ? options === null || options === void 0 ? void 0 : options.allowContributedOpeners : undefined;\n for (const opener of this._externalOpeners) {\n const didOpen = yield opener.openExternal(href, {\n sourceUri: uri,\n preferredOpenerId,\n }, CancellationToken.None);\n if (didOpen) {\n return true;\n }\n }\n }\n return this._defaultExternalOpener.openExternal(href, { sourceUri: uri }, CancellationToken.None);\n });\n }\n dispose() {\n this._validators.clear();\n }\n};\nOpenerService = __decorate([\n __param(0, ICodeEditorService),\n __param(1, ICommandService)\n], OpenerService);\nexport { OpenerService };\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { IMarkerService, MarkerSeverity } from '../../../platform/markers/common/markers.js';\nimport { Disposable, toDisposable } from '../../../base/common/lifecycle.js';\nimport { OverviewRulerLane, MinimapPosition } from '../model.js';\nimport { themeColorFromId } from '../../../platform/theme/common/themeService.js';\nimport { overviewRulerWarning, overviewRulerInfo, overviewRulerError } from '../core/editorColorRegistry.js';\nimport { IModelService } from './model.js';\nimport { Range } from '../core/range.js';\nimport { Schemas } from '../../../base/common/network.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { minimapWarning, minimapError } from '../../../platform/theme/common/colorRegistry.js';\nimport { ResourceMap } from '../../../base/common/map.js';\nclass MarkerDecorations extends Disposable {\n constructor(model) {\n super();\n this.model = model;\n this._markersData = new Map();\n this._register(toDisposable(() => {\n this.model.deltaDecorations([...this._markersData.keys()], []);\n this._markersData.clear();\n }));\n }\n update(markers, newDecorations) {\n const oldIds = [...this._markersData.keys()];\n this._markersData.clear();\n const ids = this.model.deltaDecorations(oldIds, newDecorations);\n for (let index = 0; index < ids.length; index++) {\n this._markersData.set(ids[index], markers[index]);\n }\n return oldIds.length !== 0 || ids.length !== 0;\n }\n getMarker(decoration) {\n return this._markersData.get(decoration.id);\n }\n}\nlet MarkerDecorationsService = class MarkerDecorationsService extends Disposable {\n constructor(modelService, _markerService) {\n super();\n this._markerService = _markerService;\n this._onDidChangeMarker = this._register(new Emitter());\n this._markerDecorations = new ResourceMap();\n modelService.getModels().forEach(model => this._onModelAdded(model));\n this._register(modelService.onModelAdded(this._onModelAdded, this));\n this._register(modelService.onModelRemoved(this._onModelRemoved, this));\n this._register(this._markerService.onMarkerChanged(this._handleMarkerChange, this));\n }\n dispose() {\n super.dispose();\n this._markerDecorations.forEach(value => value.dispose());\n this._markerDecorations.clear();\n }\n getMarker(uri, decoration) {\n const markerDecorations = this._markerDecorations.get(uri);\n return markerDecorations ? (markerDecorations.getMarker(decoration) || null) : null;\n }\n _handleMarkerChange(changedResources) {\n changedResources.forEach((resource) => {\n const markerDecorations = this._markerDecorations.get(resource);\n if (markerDecorations) {\n this._updateDecorations(markerDecorations);\n }\n });\n }\n _onModelAdded(model) {\n const markerDecorations = new MarkerDecorations(model);\n this._markerDecorations.set(model.uri, markerDecorations);\n this._updateDecorations(markerDecorations);\n }\n _onModelRemoved(model) {\n var _a;\n const markerDecorations = this._markerDecorations.get(model.uri);\n if (markerDecorations) {\n markerDecorations.dispose();\n this._markerDecorations.delete(model.uri);\n }\n // clean up markers for internal, transient models\n if (model.uri.scheme === Schemas.inMemory\n || model.uri.scheme === Schemas.internal\n || model.uri.scheme === Schemas.vscode) {\n (_a = this._markerService) === null || _a === void 0 ? void 0 : _a.read({ resource: model.uri }).map(marker => marker.owner).forEach(owner => this._markerService.remove(owner, [model.uri]));\n }\n }\n _updateDecorations(markerDecorations) {\n // Limit to the first 500 errors/warnings\n const markers = this._markerService.read({ resource: markerDecorations.model.uri, take: 500 });\n const newModelDecorations = markers.map((marker) => {\n return {\n range: this._createDecorationRange(markerDecorations.model, marker),\n options: this._createDecorationOption(marker)\n };\n });\n if (markerDecorations.update(markers, newModelDecorations)) {\n this._onDidChangeMarker.fire(markerDecorations.model);\n }\n }\n _createDecorationRange(model, rawMarker) {\n let ret = Range.lift(rawMarker);\n if (rawMarker.severity === MarkerSeverity.Hint && !this._hasMarkerTag(rawMarker, 1 /* MarkerTag.Unnecessary */) && !this._hasMarkerTag(rawMarker, 2 /* MarkerTag.Deprecated */)) {\n // * never render hints on multiple lines\n // * make enough space for three dots\n ret = ret.setEndPosition(ret.startLineNumber, ret.startColumn + 2);\n }\n ret = model.validateRange(ret);\n if (ret.isEmpty()) {\n const maxColumn = model.getLineLastNonWhitespaceColumn(ret.startLineNumber) ||\n model.getLineMaxColumn(ret.startLineNumber);\n if (maxColumn === 1 || ret.endColumn >= maxColumn) {\n // empty line or behind eol\n // keep the range as is, it will be rendered 1ch wide\n return ret;\n }\n const word = model.getWordAtPosition(ret.getStartPosition());\n if (word) {\n ret = new Range(ret.startLineNumber, word.startColumn, ret.endLineNumber, word.endColumn);\n }\n }\n else if (rawMarker.endColumn === Number.MAX_VALUE && rawMarker.startColumn === 1 && ret.startLineNumber === ret.endLineNumber) {\n const minColumn = model.getLineFirstNonWhitespaceColumn(rawMarker.startLineNumber);\n if (minColumn < ret.endColumn) {\n ret = new Range(ret.startLineNumber, minColumn, ret.endLineNumber, ret.endColumn);\n rawMarker.startColumn = minColumn;\n }\n }\n return ret;\n }\n _createDecorationOption(marker) {\n let className;\n let color = undefined;\n let zIndex;\n let inlineClassName = undefined;\n let minimap;\n switch (marker.severity) {\n case MarkerSeverity.Hint:\n if (this._hasMarkerTag(marker, 2 /* MarkerTag.Deprecated */)) {\n className = undefined;\n }\n else if (this._hasMarkerTag(marker, 1 /* MarkerTag.Unnecessary */)) {\n className = \"squiggly-unnecessary\" /* ClassName.EditorUnnecessaryDecoration */;\n }\n else {\n className = \"squiggly-hint\" /* ClassName.EditorHintDecoration */;\n }\n zIndex = 0;\n break;\n case MarkerSeverity.Warning:\n className = \"squiggly-warning\" /* ClassName.EditorWarningDecoration */;\n color = themeColorFromId(overviewRulerWarning);\n zIndex = 20;\n minimap = {\n color: themeColorFromId(minimapWarning),\n position: MinimapPosition.Inline\n };\n break;\n case MarkerSeverity.Info:\n className = \"squiggly-info\" /* ClassName.EditorInfoDecoration */;\n color = themeColorFromId(overviewRulerInfo);\n zIndex = 10;\n break;\n case MarkerSeverity.Error:\n default:\n className = \"squiggly-error\" /* ClassName.EditorErrorDecoration */;\n color = themeColorFromId(overviewRulerError);\n zIndex = 30;\n minimap = {\n color: themeColorFromId(minimapError),\n position: MinimapPosition.Inline\n };\n break;\n }\n if (marker.tags) {\n if (marker.tags.indexOf(1 /* MarkerTag.Unnecessary */) !== -1) {\n inlineClassName = \"squiggly-inline-unnecessary\" /* ClassName.EditorUnnecessaryInlineDecoration */;\n }\n if (marker.tags.indexOf(2 /* MarkerTag.Deprecated */) !== -1) {\n inlineClassName = \"squiggly-inline-deprecated\" /* ClassName.EditorDeprecatedInlineDecoration */;\n }\n }\n return {\n description: 'marker-decoration',\n stickiness: 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */,\n className,\n showIfCollapsed: true,\n overviewRuler: {\n color,\n position: OverviewRulerLane.Right\n },\n minimap,\n zIndex,\n inlineClassName,\n };\n }\n _hasMarkerTag(marker, tag) {\n if (marker.tags) {\n return marker.tags.indexOf(tag) >= 0;\n }\n return false;\n }\n};\nMarkerDecorationsService = __decorate([\n __param(0, IModelService),\n __param(1, IMarkerService)\n], MarkerDecorationsService);\nexport { MarkerDecorationsService };\n","import { addDisposableListener, EventHelper, EventType, reset, trackFocus } from '../../dom.js';\nimport { StandardKeyboardEvent } from '../../keyboardEvent.js';\nimport { EventType as TouchEventType, Gesture } from '../../touch.js';\nimport { renderLabelWithIcons } from '../iconLabel/iconLabels.js';\nimport { Color } from '../../../common/color.js';\nimport { Emitter } from '../../../common/event.js';\nimport { Disposable } from '../../../common/lifecycle.js';\nimport { mixin } from '../../../common/objects.js';\nimport './button.css';\nconst defaultOptions = {\n buttonBackground: Color.fromHex('#0E639C'),\n buttonHoverBackground: Color.fromHex('#006BB3'),\n buttonSeparator: Color.white,\n buttonForeground: Color.white\n};\nexport class Button extends Disposable {\n constructor(container, options) {\n super();\n this._onDidClick = this._register(new Emitter());\n this.options = options || Object.create(null);\n mixin(this.options, defaultOptions, false);\n this.buttonForeground = this.options.buttonForeground;\n this.buttonBackground = this.options.buttonBackground;\n this.buttonHoverBackground = this.options.buttonHoverBackground;\n this.buttonSecondaryForeground = this.options.buttonSecondaryForeground;\n this.buttonSecondaryBackground = this.options.buttonSecondaryBackground;\n this.buttonSecondaryHoverBackground = this.options.buttonSecondaryHoverBackground;\n this.buttonBorder = this.options.buttonBorder;\n this._element = document.createElement('a');\n this._element.classList.add('monaco-button');\n this._element.tabIndex = 0;\n this._element.setAttribute('role', 'button');\n container.appendChild(this._element);\n this._register(Gesture.addTarget(this._element));\n [EventType.CLICK, TouchEventType.Tap].forEach(eventType => {\n this._register(addDisposableListener(this._element, eventType, e => {\n if (!this.enabled) {\n EventHelper.stop(e);\n return;\n }\n this._onDidClick.fire(e);\n }));\n });\n this._register(addDisposableListener(this._element, EventType.KEY_DOWN, e => {\n const event = new StandardKeyboardEvent(e);\n let eventHandled = false;\n if (this.enabled && (event.equals(3 /* KeyCode.Enter */) || event.equals(10 /* KeyCode.Space */))) {\n this._onDidClick.fire(e);\n eventHandled = true;\n }\n else if (event.equals(9 /* KeyCode.Escape */)) {\n this._element.blur();\n eventHandled = true;\n }\n if (eventHandled) {\n EventHelper.stop(event, true);\n }\n }));\n this._register(addDisposableListener(this._element, EventType.MOUSE_OVER, e => {\n if (!this._element.classList.contains('disabled')) {\n this.setHoverBackground();\n }\n }));\n this._register(addDisposableListener(this._element, EventType.MOUSE_OUT, e => {\n this.applyStyles(); // restore standard styles\n }));\n // Also set hover background when button is focused for feedback\n this.focusTracker = this._register(trackFocus(this._element));\n this._register(this.focusTracker.onDidFocus(() => { if (this.enabled) {\n this.setHoverBackground();\n } }));\n this._register(this.focusTracker.onDidBlur(() => { if (this.enabled) {\n this.applyStyles();\n } }));\n this.applyStyles();\n }\n get onDidClick() { return this._onDidClick.event; }\n setHoverBackground() {\n let hoverBackground;\n if (this.options.secondary) {\n hoverBackground = this.buttonSecondaryHoverBackground ? this.buttonSecondaryHoverBackground.toString() : null;\n }\n else {\n hoverBackground = this.buttonHoverBackground ? this.buttonHoverBackground.toString() : null;\n }\n if (hoverBackground) {\n this._element.style.backgroundColor = hoverBackground;\n }\n }\n style(styles) {\n this.buttonForeground = styles.buttonForeground;\n this.buttonBackground = styles.buttonBackground;\n this.buttonHoverBackground = styles.buttonHoverBackground;\n this.buttonSecondaryForeground = styles.buttonSecondaryForeground;\n this.buttonSecondaryBackground = styles.buttonSecondaryBackground;\n this.buttonSecondaryHoverBackground = styles.buttonSecondaryHoverBackground;\n this.buttonBorder = styles.buttonBorder;\n this.applyStyles();\n }\n applyStyles() {\n if (this._element) {\n let background, foreground;\n if (this.options.secondary) {\n foreground = this.buttonSecondaryForeground ? this.buttonSecondaryForeground.toString() : '';\n background = this.buttonSecondaryBackground ? this.buttonSecondaryBackground.toString() : '';\n }\n else {\n foreground = this.buttonForeground ? this.buttonForeground.toString() : '';\n background = this.buttonBackground ? this.buttonBackground.toString() : '';\n }\n const border = this.buttonBorder ? this.buttonBorder.toString() : '';\n this._element.style.color = foreground;\n this._element.style.backgroundColor = background;\n this._element.style.borderWidth = border ? '1px' : '';\n this._element.style.borderStyle = border ? 'solid' : '';\n this._element.style.borderColor = border;\n }\n }\n get element() {\n return this._element;\n }\n set label(value) {\n this._element.classList.add('monaco-text-button');\n if (this.options.supportIcons) {\n reset(this._element, ...renderLabelWithIcons(value));\n }\n else {\n this._element.textContent = value;\n }\n if (typeof this.options.title === 'string') {\n this._element.title = this.options.title;\n }\n else if (this.options.title) {\n this._element.title = value;\n }\n }\n set enabled(value) {\n if (value) {\n this._element.classList.remove('disabled');\n this._element.setAttribute('aria-disabled', String(false));\n this._element.tabIndex = 0;\n }\n else {\n this._element.classList.add('disabled');\n this._element.setAttribute('aria-disabled', String(true));\n }\n }\n get enabled() {\n return !this._element.classList.contains('disabled');\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 *--------------------------------------------------------------------------------------------*/\nimport { show } from '../../dom.js';\nimport { RunOnceScheduler } from '../../../common/async.js';\nimport { Color } from '../../../common/color.js';\nimport { Disposable } from '../../../common/lifecycle.js';\nimport { mixin } from '../../../common/objects.js';\nimport './progressbar.css';\nconst CSS_DONE = 'done';\nconst CSS_ACTIVE = 'active';\nconst CSS_INFINITE = 'infinite';\nconst CSS_INFINITE_LONG_RUNNING = 'infinite-long-running';\nconst CSS_DISCRETE = 'discrete';\nconst defaultOpts = {\n progressBarBackground: Color.fromHex('#0E70C0')\n};\n/**\n * A progress bar with support for infinite or discrete progress.\n */\nexport class ProgressBar extends Disposable {\n constructor(container, options) {\n super();\n this.options = options || Object.create(null);\n mixin(this.options, defaultOpts, false);\n this.workedVal = 0;\n this.progressBarBackground = this.options.progressBarBackground;\n this.showDelayedScheduler = this._register(new RunOnceScheduler(() => show(this.element), 0));\n this.longRunningScheduler = this._register(new RunOnceScheduler(() => this.infiniteLongRunning(), ProgressBar.LONG_RUNNING_INFINITE_THRESHOLD));\n this.create(container);\n }\n create(container) {\n this.element = document.createElement('div');\n this.element.classList.add('monaco-progress-container');\n this.element.setAttribute('role', 'progressbar');\n this.element.setAttribute('aria-valuemin', '0');\n container.appendChild(this.element);\n this.bit = document.createElement('div');\n this.bit.classList.add('progress-bit');\n this.element.appendChild(this.bit);\n this.applyStyles();\n }\n off() {\n this.bit.style.width = 'inherit';\n this.bit.style.opacity = '1';\n this.element.classList.remove(CSS_ACTIVE, CSS_INFINITE, CSS_INFINITE_LONG_RUNNING, CSS_DISCRETE);\n this.workedVal = 0;\n this.totalWork = undefined;\n this.longRunningScheduler.cancel();\n }\n /**\n * Stops the progressbar from showing any progress instantly without fading out.\n */\n stop() {\n return this.doDone(false);\n }\n doDone(delayed) {\n this.element.classList.add(CSS_DONE);\n // discrete: let it grow to 100% width and hide afterwards\n if (!this.element.classList.contains(CSS_INFINITE)) {\n this.bit.style.width = 'inherit';\n if (delayed) {\n setTimeout(() => this.off(), 200);\n }\n else {\n this.off();\n }\n }\n // infinite: let it fade out and hide afterwards\n else {\n this.bit.style.opacity = '0';\n if (delayed) {\n setTimeout(() => this.off(), 200);\n }\n else {\n this.off();\n }\n }\n return this;\n }\n /**\n * Use this mode to indicate progress that has no total number of work units.\n */\n infinite() {\n this.bit.style.width = '2%';\n this.bit.style.opacity = '1';\n this.element.classList.remove(CSS_DISCRETE, CSS_DONE, CSS_INFINITE_LONG_RUNNING);\n this.element.classList.add(CSS_ACTIVE, CSS_INFINITE);\n this.longRunningScheduler.schedule();\n return this;\n }\n infiniteLongRunning() {\n this.element.classList.add(CSS_INFINITE_LONG_RUNNING);\n }\n getContainer() {\n return this.element;\n }\n style(styles) {\n this.progressBarBackground = styles.progressBarBackground;\n this.applyStyles();\n }\n applyStyles() {\n if (this.bit) {\n const background = this.progressBarBackground ? this.progressBarBackground.toString() : '';\n this.bit.style.backgroundColor = background;\n }\n }\n}\n/**\n * After a certain time of showing the progress bar, switch\n * to long-running mode and throttle animations to reduce\n * the pressure on the GPU process.\n *\n * https://github.com/microsoft/vscode/issues/97900\n * https://github.com/microsoft/vscode/issues/138396\n */\nProgressBar.LONG_RUNNING_INFINITE_THRESHOLD = 10000;\n","/*---------------------------------------------------------------------------------------------\n * 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 * as dom from '../../../browser/dom.js';\nimport { IdGenerator } from '../../../common/idGenerator.js';\nimport './media/quickInput.css';\nconst iconPathToClass = {};\nconst iconClassGenerator = new IdGenerator('quick-input-button-icon-');\nexport function getIconClass(iconPath) {\n if (!iconPath) {\n return undefined;\n }\n let iconClass;\n const key = iconPath.dark.toString();\n if (iconPathToClass[key]) {\n iconClass = iconPathToClass[key];\n }\n else {\n iconClass = iconClassGenerator.nextId();\n dom.createCSSRule(`.${iconClass}, .hc-light .${iconClass}`, `background-image: ${dom.asCSSUrl(iconPath.light || iconPath.dark)}`);\n dom.createCSSRule(`.vs-dark .${iconClass}, .hc-black .${iconClass}`, `background-image: ${dom.asCSSUrl(iconPath.dark)}`);\n iconPathToClass[key] = iconClass;\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nimport * as dom from '../../../browser/dom.js';\nimport { StandardKeyboardEvent } from '../../../browser/keyboardEvent.js';\nimport { StandardMouseEvent } from '../../../browser/mouseEvent.js';\nimport { InputBox } from '../../../browser/ui/inputbox/inputBox.js';\nimport { Disposable } from '../../../common/lifecycle.js';\nimport Severity from '../../../common/severity.js';\nimport './media/quickInput.css';\nconst $ = dom.$;\nexport class QuickInputBox extends Disposable {\n constructor(parent) {\n super();\n this.parent = parent;\n this.onKeyDown = (handler) => {\n return dom.addDisposableListener(this.inputBox.inputElement, dom.EventType.KEY_DOWN, (e) => {\n handler(new StandardKeyboardEvent(e));\n });\n };\n this.onMouseDown = (handler) => {\n return dom.addDisposableListener(this.inputBox.inputElement, dom.EventType.MOUSE_DOWN, (e) => {\n handler(new StandardMouseEvent(e));\n });\n };\n this.onDidChange = (handler) => {\n return this.inputBox.onDidChange(handler);\n };\n this.container = dom.append(this.parent, $('.quick-input-box'));\n this.inputBox = this._register(new InputBox(this.container, undefined));\n }\n get value() {\n return this.inputBox.value;\n }\n set value(value) {\n this.inputBox.value = value;\n }\n select(range = null) {\n this.inputBox.select(range);\n }\n isSelectionAtEnd() {\n return this.inputBox.isSelectionAtEnd();\n }\n get placeholder() {\n return this.inputBox.inputElement.getAttribute('placeholder') || '';\n }\n set placeholder(placeholder) {\n this.inputBox.setPlaceHolder(placeholder);\n }\n get ariaLabel() {\n return this.inputBox.getAriaLabel();\n }\n set ariaLabel(ariaLabel) {\n this.inputBox.setAriaLabel(ariaLabel);\n }\n get password() {\n return this.inputBox.inputElement.type === 'password';\n }\n set password(password) {\n this.inputBox.inputElement.type = password ? 'password' : 'text';\n }\n setAttribute(name, value) {\n this.inputBox.inputElement.setAttribute(name, value);\n }\n removeAttribute(name) {\n this.inputBox.inputElement.removeAttribute(name);\n }\n showDecoration(decoration) {\n if (decoration === Severity.Ignore) {\n this.inputBox.hideMessage();\n }\n else {\n this.inputBox.showMessage({ type: decoration === Severity.Info ? 1 /* MessageType.INFO */ : decoration === Severity.Warning ? 2 /* MessageType.WARNING */ : 3 /* MessageType.ERROR */, content: '' });\n }\n }\n stylesForType(decoration) {\n return this.inputBox.stylesForType(decoration === Severity.Info ? 1 /* MessageType.INFO */ : decoration === Severity.Warning ? 2 /* MessageType.WARNING */ : 3 /* MessageType.ERROR */);\n }\n setFocus() {\n this.inputBox.focus();\n }\n layout() {\n this.inputBox.layout();\n }\n style(styles) {\n this.inputBox.style(styles);\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 *--------------------------------------------------------------------------------------------*/\nimport * as dom from '../../dom.js';\nimport { UILabelProvider } from '../../../common/keybindingLabels.js';\nimport { equals } from '../../../common/objects.js';\nimport './keybindingLabel.css';\nimport { localize } from '../../../../nls.js';\nconst $ = dom.$;\nexport class KeybindingLabel {\n constructor(container, os, options) {\n this.os = os;\n this.keyElements = new Set();\n this.options = options || Object.create(null);\n this.labelBackground = this.options.keybindingLabelBackground;\n this.labelForeground = this.options.keybindingLabelForeground;\n this.labelBorder = this.options.keybindingLabelBorder;\n this.labelBottomBorder = this.options.keybindingLabelBottomBorder;\n this.labelShadow = this.options.keybindingLabelShadow;\n this.domNode = dom.append(container, $('.monaco-keybinding'));\n this.didEverRender = false;\n container.appendChild(this.domNode);\n }\n get element() {\n return this.domNode;\n }\n set(keybinding, matches) {\n if (this.didEverRender && this.keybinding === keybinding && KeybindingLabel.areSame(this.matches, matches)) {\n return;\n }\n this.keybinding = keybinding;\n this.matches = matches;\n this.render();\n }\n render() {\n this.clear();\n if (this.keybinding) {\n const [firstPart, chordPart] = this.keybinding.getParts();\n if (firstPart) {\n this.renderPart(this.domNode, firstPart, this.matches ? this.matches.firstPart : null);\n }\n if (chordPart) {\n dom.append(this.domNode, $('span.monaco-keybinding-key-chord-separator', undefined, ' '));\n this.renderPart(this.domNode, chordPart, this.matches ? this.matches.chordPart : null);\n }\n this.domNode.title = this.keybinding.getAriaLabel() || '';\n }\n else if (this.options && this.options.renderUnboundKeybindings) {\n this.renderUnbound(this.domNode);\n }\n this.applyStyles();\n this.didEverRender = true;\n }\n clear() {\n dom.clearNode(this.domNode);\n this.keyElements.clear();\n }\n renderPart(parent, part, match) {\n const modifierLabels = UILabelProvider.modifierLabels[this.os];\n if (part.ctrlKey) {\n this.renderKey(parent, modifierLabels.ctrlKey, Boolean(match === null || match === void 0 ? void 0 : match.ctrlKey), modifierLabels.separator);\n }\n if (part.shiftKey) {\n this.renderKey(parent, modifierLabels.shiftKey, Boolean(match === null || match === void 0 ? void 0 : match.shiftKey), modifierLabels.separator);\n }\n if (part.altKey) {\n this.renderKey(parent, modifierLabels.altKey, Boolean(match === null || match === void 0 ? void 0 : match.altKey), modifierLabels.separator);\n }\n if (part.metaKey) {\n this.renderKey(parent, modifierLabels.metaKey, Boolean(match === null || match === void 0 ? void 0 : match.metaKey), modifierLabels.separator);\n }\n const keyLabel = part.keyLabel;\n if (keyLabel) {\n this.renderKey(parent, keyLabel, Boolean(match === null || match === void 0 ? void 0 : match.keyCode), '');\n }\n }\n renderKey(parent, label, highlight, separator) {\n dom.append(parent, this.createKeyElement(label, highlight ? '.highlight' : ''));\n if (separator) {\n dom.append(parent, $('span.monaco-keybinding-key-separator', undefined, separator));\n }\n }\n renderUnbound(parent) {\n dom.append(parent, this.createKeyElement(localize('unbound', \"Unbound\")));\n }\n createKeyElement(label, extraClass = '') {\n const keyElement = $('span.monaco-keybinding-key' + extraClass, undefined, label);\n this.keyElements.add(keyElement);\n return keyElement;\n }\n style(styles) {\n this.labelBackground = styles.keybindingLabelBackground;\n this.labelForeground = styles.keybindingLabelForeground;\n this.labelBorder = styles.keybindingLabelBorder;\n this.labelBottomBorder = styles.keybindingLabelBottomBorder;\n this.labelShadow = styles.keybindingLabelShadow;\n this.applyStyles();\n }\n applyStyles() {\n var _a;\n if (this.element) {\n for (const keyElement of this.keyElements) {\n if (this.labelBackground) {\n keyElement.style.backgroundColor = (_a = this.labelBackground) === null || _a === void 0 ? void 0 : _a.toString();\n }\n if (this.labelBorder) {\n keyElement.style.borderColor = this.labelBorder.toString();\n }\n if (this.labelBottomBorder) {\n keyElement.style.borderBottomColor = this.labelBottomBorder.toString();\n }\n if (this.labelShadow) {\n keyElement.style.boxShadow = `inset 0 -1px 0 ${this.labelShadow}`;\n }\n }\n if (this.labelForeground) {\n this.element.style.color = this.labelForeground.toString();\n }\n }\n }\n static areSame(a, b) {\n if (a === b || (!a && !b)) {\n return true;\n }\n return !!a && !!b && equals(a.firstPart, b.firstPart) && equals(a.chordPart, b.chordPart);\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 *--------------------------------------------------------------------------------------------*/\nimport { IdleValue } from './async.js';\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// A collator with numeric sorting enabled, and no sensitivity to case, accents or diacritics.\nconst intlFileNameCollatorBaseNumeric = new IdleValue(() => {\n const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });\n return {\n collator: collator,\n collatorIsNumeric: collator.resolvedOptions().numeric\n };\n});\n// A collator with numeric sorting enabled.\nconst intlFileNameCollatorNumeric = new IdleValue(() => {\n const collator = new Intl.Collator(undefined, { numeric: true });\n return {\n collator: collator\n };\n});\n// A collator with numeric sorting enabled, and sensitivity to accents and diacritics but not case.\nconst intlFileNameCollatorNumericCaseInsensitive = new IdleValue(() => {\n const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'accent' });\n return {\n collator: collator\n };\n});\n/** Compares filenames without distinguishing the name from the extension. Disambiguates by unicode comparison. */\nexport function compareFileNames(one, other, caseSensitive = false) {\n const a = one || '';\n const b = other || '';\n const result = intlFileNameCollatorBaseNumeric.value.collator.compare(a, b);\n // Using the numeric option will make compare(`foo1`, `foo01`) === 0. Disambiguate.\n if (intlFileNameCollatorBaseNumeric.value.collatorIsNumeric && result === 0 && a !== b) {\n return a < b ? -1 : 1;\n }\n return result;\n}\nexport function compareAnything(one, other, lookFor) {\n const elementAName = one.toLowerCase();\n const elementBName = other.toLowerCase();\n // Sort prefix matches over non prefix matches\n const prefixCompare = compareByPrefix(one, other, lookFor);\n if (prefixCompare) {\n return prefixCompare;\n }\n // Sort suffix matches over non suffix matches\n const elementASuffixMatch = elementAName.endsWith(lookFor);\n const elementBSuffixMatch = elementBName.endsWith(lookFor);\n if (elementASuffixMatch !== elementBSuffixMatch) {\n return elementASuffixMatch ? -1 : 1;\n }\n // Understand file names\n const r = compareFileNames(elementAName, elementBName);\n if (r !== 0) {\n return r;\n }\n // Compare by name\n return elementAName.localeCompare(elementBName);\n}\nexport function compareByPrefix(one, other, lookFor) {\n const elementAName = one.toLowerCase();\n const elementBName = other.toLowerCase();\n // Sort prefix matches over non prefix matches\n const elementAPrefixMatch = elementAName.startsWith(lookFor);\n const elementBPrefixMatch = elementBName.startsWith(lookFor);\n if (elementAPrefixMatch !== elementBPrefixMatch) {\n return elementAPrefixMatch ? -1 : 1;\n }\n // Same prefix: Sort shorter matches to the top to have those on top that match more precisely\n else if (elementAPrefixMatch && elementBPrefixMatch) {\n if (elementAName.length < elementBName.length) {\n return -1;\n }\n if (elementAName.length > elementBName.length) {\n return 1;\n }\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport * as dom from '../../../browser/dom.js';\nimport { StandardKeyboardEvent } from '../../../browser/keyboardEvent.js';\nimport { ActionBar } from '../../../browser/ui/actionbar/actionbar.js';\nimport { IconLabel } from '../../../browser/ui/iconLabel/iconLabel.js';\nimport { KeybindingLabel } from '../../../browser/ui/keybindingLabel/keybindingLabel.js';\nimport { Action } from '../../../common/actions.js';\nimport { range } from '../../../common/arrays.js';\nimport { getCodiconAriaLabel } from '../../../common/codicons.js';\nimport { compareAnything } from '../../../common/comparers.js';\nimport { memoize } from '../../../common/decorators.js';\nimport { Emitter, Event } from '../../../common/event.js';\nimport { matchesFuzzyIconAware, parseLabelWithIcons } from '../../../common/iconLabels.js';\nimport { dispose } from '../../../common/lifecycle.js';\nimport * as platform from '../../../common/platform.js';\nimport { ltrim } from '../../../common/strings.js';\nimport { withNullAsUndefined } from '../../../common/types.js';\nimport { getIconClass } from './quickInputUtils.js';\nimport './media/quickInput.css';\nimport { localize } from '../../../../nls.js';\nconst $ = dom.$;\nclass ListElement {\n constructor(init) {\n this.hidden = false;\n this._onChecked = new Emitter();\n this.onChecked = this._onChecked.event;\n Object.assign(this, init);\n }\n get checked() {\n return !!this._checked;\n }\n set checked(value) {\n if (value !== this._checked) {\n this._checked = value;\n this._onChecked.fire(value);\n }\n }\n dispose() {\n this._onChecked.dispose();\n }\n}\nclass ListElementRenderer {\n get templateId() {\n return ListElementRenderer.ID;\n }\n renderTemplate(container) {\n const data = Object.create(null);\n data.toDisposeElement = [];\n data.toDisposeTemplate = [];\n data.entry = dom.append(container, $('.quick-input-list-entry'));\n // Checkbox\n const label = dom.append(data.entry, $('label.quick-input-list-label'));\n data.toDisposeTemplate.push(dom.addStandardDisposableListener(label, dom.EventType.CLICK, e => {\n if (!data.checkbox.offsetParent) { // If checkbox not visible:\n e.preventDefault(); // Prevent toggle of checkbox when it is immediately shown afterwards. #91740\n }\n }));\n data.checkbox = dom.append(label, $('input.quick-input-list-checkbox'));\n data.checkbox.type = 'checkbox';\n data.toDisposeTemplate.push(dom.addStandardDisposableListener(data.checkbox, dom.EventType.CHANGE, e => {\n data.element.checked = data.checkbox.checked;\n }));\n // Rows\n const rows = dom.append(label, $('.quick-input-list-rows'));\n const row1 = dom.append(rows, $('.quick-input-list-row'));\n const row2 = dom.append(rows, $('.quick-input-list-row'));\n // Label\n data.label = new IconLabel(row1, { supportHighlights: true, supportDescriptionHighlights: true, supportIcons: true });\n // Keybinding\n const keybindingContainer = dom.append(row1, $('.quick-input-list-entry-keybinding'));\n data.keybinding = new KeybindingLabel(keybindingContainer, platform.OS);\n // Detail\n const detailContainer = dom.append(row2, $('.quick-input-list-label-meta'));\n data.detail = new IconLabel(detailContainer, { supportHighlights: true, supportIcons: true });\n // Separator\n data.separator = dom.append(data.entry, $('.quick-input-list-separator'));\n // Actions\n data.actionBar = new ActionBar(data.entry);\n data.actionBar.domNode.classList.add('quick-input-list-entry-action-bar');\n data.toDisposeTemplate.push(data.actionBar);\n return data;\n }\n renderElement(element, index, data) {\n data.toDisposeElement = dispose(data.toDisposeElement);\n data.element = element;\n data.checkbox.checked = element.checked;\n data.toDisposeElement.push(element.onChecked(checked => data.checkbox.checked = checked));\n const { labelHighlights, descriptionHighlights, detailHighlights } = element;\n // Label\n const options = Object.create(null);\n options.matches = labelHighlights || [];\n options.descriptionTitle = element.saneDescription;\n options.descriptionMatches = descriptionHighlights || [];\n options.extraClasses = element.item.iconClasses;\n options.italic = element.item.italic;\n options.strikethrough = element.item.strikethrough;\n data.label.setLabel(element.saneLabel, element.saneDescription, options);\n // Keybinding\n data.keybinding.set(element.item.keybinding);\n // Meta\n if (element.saneDetail) {\n data.detail.setLabel(element.saneDetail, undefined, {\n matches: detailHighlights,\n title: element.saneDetail\n });\n }\n // Separator\n if (element.separator && element.separator.label) {\n data.separator.textContent = element.separator.label;\n data.separator.style.display = '';\n }\n else {\n data.separator.style.display = 'none';\n }\n data.entry.classList.toggle('quick-input-list-separator-border', !!element.separator);\n // Actions\n data.actionBar.clear();\n const buttons = element.item.buttons;\n if (buttons && buttons.length) {\n data.actionBar.push(buttons.map((button, index) => {\n let cssClasses = button.iconClass || (button.iconPath ? getIconClass(button.iconPath) : undefined);\n if (button.alwaysVisible) {\n cssClasses = cssClasses ? `${cssClasses} always-visible` : 'always-visible';\n }\n const action = new Action(`id-${index}`, '', cssClasses, true, () => __awaiter(this, void 0, void 0, function* () {\n element.fireButtonTriggered({\n button,\n item: element.item\n });\n }));\n action.tooltip = button.tooltip || '';\n return action;\n }), { icon: true, label: false });\n data.entry.classList.add('has-actions');\n }\n else {\n data.entry.classList.remove('has-actions');\n }\n }\n disposeElement(element, index, data) {\n data.toDisposeElement = dispose(data.toDisposeElement);\n }\n disposeTemplate(data) {\n data.toDisposeElement = dispose(data.toDisposeElement);\n data.toDisposeTemplate = dispose(data.toDisposeTemplate);\n }\n}\nListElementRenderer.ID = 'listelement';\nclass ListElementDelegate {\n getHeight(element) {\n return element.saneDetail ? 44 : 22;\n }\n getTemplateId(element) {\n return ListElementRenderer.ID;\n }\n}\nexport var QuickInputListFocus;\n(function (QuickInputListFocus) {\n QuickInputListFocus[QuickInputListFocus[\"First\"] = 1] = \"First\";\n QuickInputListFocus[QuickInputListFocus[\"Second\"] = 2] = \"Second\";\n QuickInputListFocus[QuickInputListFocus[\"Last\"] = 3] = \"Last\";\n QuickInputListFocus[QuickInputListFocus[\"Next\"] = 4] = \"Next\";\n QuickInputListFocus[QuickInputListFocus[\"Previous\"] = 5] = \"Previous\";\n QuickInputListFocus[QuickInputListFocus[\"NextPage\"] = 6] = \"NextPage\";\n QuickInputListFocus[QuickInputListFocus[\"PreviousPage\"] = 7] = \"PreviousPage\";\n})(QuickInputListFocus || (QuickInputListFocus = {}));\nexport class QuickInputList {\n constructor(parent, id, options) {\n this.parent = parent;\n this.inputElements = [];\n this.elements = [];\n this.elementsToIndexes = new Map();\n this.matchOnDescription = false;\n this.matchOnDetail = false;\n this.matchOnLabel = true;\n this.matchOnLabelMode = 'fuzzy';\n this.matchOnMeta = true;\n this.sortByLabel = true;\n this._onChangedAllVisibleChecked = new Emitter();\n this.onChangedAllVisibleChecked = this._onChangedAllVisibleChecked.event;\n this._onChangedCheckedCount = new Emitter();\n this.onChangedCheckedCount = this._onChangedCheckedCount.event;\n this._onChangedVisibleCount = new Emitter();\n this.onChangedVisibleCount = this._onChangedVisibleCount.event;\n this._onChangedCheckedElements = new Emitter();\n this.onChangedCheckedElements = this._onChangedCheckedElements.event;\n this._onButtonTriggered = new Emitter();\n this.onButtonTriggered = this._onButtonTriggered.event;\n this._onKeyDown = new Emitter();\n this.onKeyDown = this._onKeyDown.event;\n this._onLeave = new Emitter();\n this.onLeave = this._onLeave.event;\n this._fireCheckedEvents = true;\n this.elementDisposables = [];\n this.disposables = [];\n this.id = id;\n this.container = dom.append(this.parent, $('.quick-input-list'));\n const delegate = new ListElementDelegate();\n const accessibilityProvider = new QuickInputAccessibilityProvider();\n this.list = options.createList('QuickInput', this.container, delegate, [new ListElementRenderer()], {\n identityProvider: { getId: element => element.saneLabel },\n setRowLineHeight: false,\n multipleSelectionSupport: false,\n horizontalScrolling: false,\n accessibilityProvider\n });\n this.list.getHTMLElement().id = id;\n this.disposables.push(this.list);\n this.disposables.push(this.list.onKeyDown(e => {\n const event = new StandardKeyboardEvent(e);\n switch (event.keyCode) {\n case 10 /* KeyCode.Space */:\n this.toggleCheckbox();\n break;\n case 31 /* KeyCode.KeyA */:\n if (platform.isMacintosh ? e.metaKey : e.ctrlKey) {\n this.list.setFocus(range(this.list.length));\n }\n break;\n case 16 /* KeyCode.UpArrow */: {\n const focus1 = this.list.getFocus();\n if (focus1.length === 1 && focus1[0] === 0) {\n this._onLeave.fire();\n }\n break;\n }\n case 18 /* KeyCode.DownArrow */: {\n const focus2 = this.list.getFocus();\n if (focus2.length === 1 && focus2[0] === this.list.length - 1) {\n this._onLeave.fire();\n }\n break;\n }\n }\n this._onKeyDown.fire(event);\n }));\n this.disposables.push(this.list.onMouseDown(e => {\n if (e.browserEvent.button !== 2) {\n // Works around / fixes #64350.\n e.browserEvent.preventDefault();\n }\n }));\n this.disposables.push(dom.addDisposableListener(this.container, dom.EventType.CLICK, e => {\n if (e.x || e.y) { // Avoid 'click' triggered by 'space' on checkbox.\n this._onLeave.fire();\n }\n }));\n this.disposables.push(this.list.onMouseMiddleClick(e => {\n this._onLeave.fire();\n }));\n this.disposables.push(this.list.onContextMenu(e => {\n if (typeof e.index === 'number') {\n e.browserEvent.preventDefault();\n // we want to treat a context menu event as\n // a gesture to open the item at the index\n // since we do not have any context menu\n // this enables for example macOS to Ctrl-\n // click on an item to open it.\n this.list.setSelection([e.index]);\n }\n }));\n this.disposables.push(this._onChangedAllVisibleChecked, this._onChangedCheckedCount, this._onChangedVisibleCount, this._onChangedCheckedElements, this._onButtonTriggered, this._onLeave, this._onKeyDown);\n }\n get onDidChangeFocus() {\n return Event.map(this.list.onDidChangeFocus, e => e.elements.map(e => e.item));\n }\n get onDidChangeSelection() {\n return Event.map(this.list.onDidChangeSelection, e => ({ items: e.elements.map(e => e.item), event: e.browserEvent }));\n }\n get scrollTop() {\n return this.list.scrollTop;\n }\n set scrollTop(scrollTop) {\n this.list.scrollTop = scrollTop;\n }\n getAllVisibleChecked() {\n return this.allVisibleChecked(this.elements, false);\n }\n allVisibleChecked(elements, whenNoneVisible = true) {\n for (let i = 0, n = elements.length; i < n; i++) {\n const element = elements[i];\n if (!element.hidden) {\n if (!element.checked) {\n return false;\n }\n else {\n whenNoneVisible = true;\n }\n }\n }\n return whenNoneVisible;\n }\n getCheckedCount() {\n let count = 0;\n const elements = this.elements;\n for (let i = 0, n = elements.length; i < n; i++) {\n if (elements[i].checked) {\n count++;\n }\n }\n return count;\n }\n getVisibleCount() {\n let count = 0;\n const elements = this.elements;\n for (let i = 0, n = elements.length; i < n; i++) {\n if (!elements[i].hidden) {\n count++;\n }\n }\n return count;\n }\n setAllVisibleChecked(checked) {\n try {\n this._fireCheckedEvents = false;\n this.elements.forEach(element => {\n if (!element.hidden) {\n element.checked = checked;\n }\n });\n }\n finally {\n this._fireCheckedEvents = true;\n this.fireCheckedEvents();\n }\n }\n setElements(inputElements) {\n this.elementDisposables = dispose(this.elementDisposables);\n const fireButtonTriggered = (event) => this.fireButtonTriggered(event);\n this.inputElements = inputElements;\n this.elements = inputElements.reduce((result, item, index) => {\n var _a, _b, _c;\n if (item.type !== 'separator') {\n const previous = index && inputElements[index - 1];\n const saneLabel = item.label && item.label.replace(/\\r?\\n/g, ' ');\n const saneSortLabel = parseLabelWithIcons(saneLabel).text.trim();\n const saneMeta = item.meta && item.meta.replace(/\\r?\\n/g, ' ');\n const saneDescription = item.description && item.description.replace(/\\r?\\n/g, ' ');\n const saneDetail = item.detail && item.detail.replace(/\\r?\\n/g, ' ');\n const saneAriaLabel = item.ariaLabel || [saneLabel, saneDescription, saneDetail]\n .map(s => getCodiconAriaLabel(s))\n .filter(s => !!s)\n .join(', ');\n const hasCheckbox = this.parent.classList.contains('show-checkboxes');\n result.push(new ListElement({\n hasCheckbox,\n index,\n item,\n saneLabel,\n saneSortLabel,\n saneMeta,\n saneAriaLabel,\n saneDescription,\n saneDetail,\n labelHighlights: (_a = item.highlights) === null || _a === void 0 ? void 0 : _a.label,\n descriptionHighlights: (_b = item.highlights) === null || _b === void 0 ? void 0 : _b.description,\n detailHighlights: (_c = item.highlights) === null || _c === void 0 ? void 0 : _c.detail,\n checked: false,\n separator: previous && previous.type === 'separator' ? previous : undefined,\n fireButtonTriggered\n }));\n }\n return result;\n }, []);\n this.elementDisposables.push(...this.elements);\n this.elementDisposables.push(...this.elements.map(element => element.onChecked(() => this.fireCheckedEvents())));\n this.elementsToIndexes = this.elements.reduce((map, element, index) => {\n map.set(element.item, index);\n return map;\n }, new Map());\n this.list.splice(0, this.list.length); // Clear focus and selection first, sending the events when the list is empty.\n this.list.splice(0, this.list.length, this.elements);\n this._onChangedVisibleCount.fire(this.elements.length);\n }\n getFocusedElements() {\n return this.list.getFocusedElements()\n .map(e => e.item);\n }\n setFocusedElements(items) {\n this.list.setFocus(items\n .filter(item => this.elementsToIndexes.has(item))\n .map(item => this.elementsToIndexes.get(item)));\n if (items.length > 0) {\n const focused = this.list.getFocus()[0];\n if (typeof focused === 'number') {\n this.list.reveal(focused);\n }\n }\n }\n getActiveDescendant() {\n return this.list.getHTMLElement().getAttribute('aria-activedescendant');\n }\n setSelectedElements(items) {\n this.list.setSelection(items\n .filter(item => this.elementsToIndexes.has(item))\n .map(item => this.elementsToIndexes.get(item)));\n }\n getCheckedElements() {\n return this.elements.filter(e => e.checked)\n .map(e => e.item);\n }\n setCheckedElements(items) {\n try {\n this._fireCheckedEvents = false;\n const checked = new Set();\n for (const item of items) {\n checked.add(item);\n }\n for (const element of this.elements) {\n element.checked = checked.has(element.item);\n }\n }\n finally {\n this._fireCheckedEvents = true;\n this.fireCheckedEvents();\n }\n }\n set enabled(value) {\n this.list.getHTMLElement().style.pointerEvents = value ? '' : 'none';\n }\n focus(what) {\n if (!this.list.length) {\n return;\n }\n if (what === QuickInputListFocus.Next && this.list.getFocus()[0] === this.list.length - 1) {\n what = QuickInputListFocus.First;\n }\n if (what === QuickInputListFocus.Previous && this.list.getFocus()[0] === 0) {\n what = QuickInputListFocus.Last;\n }\n if (what === QuickInputListFocus.Second && this.list.length < 2) {\n what = QuickInputListFocus.First;\n }\n switch (what) {\n case QuickInputListFocus.First:\n this.list.focusFirst();\n break;\n case QuickInputListFocus.Second:\n this.list.focusNth(1);\n break;\n case QuickInputListFocus.Last:\n this.list.focusLast();\n break;\n case QuickInputListFocus.Next:\n this.list.focusNext();\n break;\n case QuickInputListFocus.Previous:\n this.list.focusPrevious();\n break;\n case QuickInputListFocus.NextPage:\n this.list.focusNextPage();\n break;\n case QuickInputListFocus.PreviousPage:\n this.list.focusPreviousPage();\n break;\n }\n const focused = this.list.getFocus()[0];\n if (typeof focused === 'number') {\n this.list.reveal(focused);\n }\n }\n clearFocus() {\n this.list.setFocus([]);\n }\n domFocus() {\n this.list.domFocus();\n }\n layout(maxHeight) {\n this.list.getHTMLElement().style.maxHeight = maxHeight ? `calc(${Math.floor(maxHeight / 44) * 44}px)` : '';\n this.list.layout();\n }\n filter(query) {\n if (!(this.sortByLabel || this.matchOnLabel || this.matchOnDescription || this.matchOnDetail)) {\n this.list.layout();\n return false;\n }\n const queryWithWhitespace = query;\n query = query.trim();\n // Reset filtering\n if (!query || !(this.matchOnLabel || this.matchOnDescription || this.matchOnDetail)) {\n this.elements.forEach(element => {\n element.labelHighlights = undefined;\n element.descriptionHighlights = undefined;\n element.detailHighlights = undefined;\n element.hidden = false;\n const previous = element.index && this.inputElements[element.index - 1];\n element.separator = previous && previous.type === 'separator' ? previous : undefined;\n });\n }\n // Filter by value (since we support icons in labels, use $(..) aware fuzzy matching)\n else {\n let currentSeparator;\n this.elements.forEach(element => {\n let labelHighlights;\n if (this.matchOnLabelMode === 'fuzzy') {\n labelHighlights = this.matchOnLabel ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneLabel))) : undefined;\n }\n else {\n labelHighlights = this.matchOnLabel ? withNullAsUndefined(matchesContiguousIconAware(queryWithWhitespace, parseLabelWithIcons(element.saneLabel))) : undefined;\n }\n const descriptionHighlights = this.matchOnDescription ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneDescription || ''))) : undefined;\n const detailHighlights = this.matchOnDetail ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneDetail || ''))) : undefined;\n const metaHighlights = this.matchOnMeta ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneMeta || ''))) : undefined;\n if (labelHighlights || descriptionHighlights || detailHighlights || metaHighlights) {\n element.labelHighlights = labelHighlights;\n element.descriptionHighlights = descriptionHighlights;\n element.detailHighlights = detailHighlights;\n element.hidden = false;\n }\n else {\n element.labelHighlights = undefined;\n element.descriptionHighlights = undefined;\n element.detailHighlights = undefined;\n element.hidden = !element.item.alwaysShow;\n }\n element.separator = undefined;\n // we can show the separator unless the list gets sorted by match\n if (!this.sortByLabel) {\n const previous = element.index && this.inputElements[element.index - 1];\n currentSeparator = previous && previous.type === 'separator' ? previous : currentSeparator;\n if (currentSeparator && !element.hidden) {\n element.separator = currentSeparator;\n currentSeparator = undefined;\n }\n }\n });\n }\n const shownElements = this.elements.filter(element => !element.hidden);\n // Sort by value\n if (this.sortByLabel && query) {\n const normalizedSearchValue = query.toLowerCase();\n shownElements.sort((a, b) => {\n return compareEntries(a, b, normalizedSearchValue);\n });\n }\n this.elementsToIndexes = shownElements.reduce((map, element, index) => {\n map.set(element.item, index);\n return map;\n }, new Map());\n this.list.splice(0, this.list.length, shownElements);\n this.list.setFocus([]);\n this.list.layout();\n this._onChangedAllVisibleChecked.fire(this.getAllVisibleChecked());\n this._onChangedVisibleCount.fire(shownElements.length);\n return true;\n }\n toggleCheckbox() {\n try {\n this._fireCheckedEvents = false;\n const elements = this.list.getFocusedElements();\n const allChecked = this.allVisibleChecked(elements);\n for (const element of elements) {\n element.checked = !allChecked;\n }\n }\n finally {\n this._fireCheckedEvents = true;\n this.fireCheckedEvents();\n }\n }\n display(display) {\n this.container.style.display = display ? '' : 'none';\n }\n isDisplayed() {\n return this.container.style.display !== 'none';\n }\n dispose() {\n this.elementDisposables = dispose(this.elementDisposables);\n this.disposables = dispose(this.disposables);\n }\n fireCheckedEvents() {\n if (this._fireCheckedEvents) {\n this._onChangedAllVisibleChecked.fire(this.getAllVisibleChecked());\n this._onChangedCheckedCount.fire(this.getCheckedCount());\n this._onChangedCheckedElements.fire(this.getCheckedElements());\n }\n }\n fireButtonTriggered(event) {\n this._onButtonTriggered.fire(event);\n }\n style(styles) {\n this.list.style(styles);\n }\n}\n__decorate([\n memoize\n], QuickInputList.prototype, \"onDidChangeFocus\", null);\n__decorate([\n memoize\n], QuickInputList.prototype, \"onDidChangeSelection\", null);\nexport function matchesContiguousIconAware(query, target) {\n const { text, iconOffsets } = target;\n // Return early if there are no icon markers in the word to match against\n if (!iconOffsets || iconOffsets.length === 0) {\n return matchesContiguous(query, text);\n }\n // Trim the word to match against because it could have leading\n // whitespace now if the word started with an icon\n const wordToMatchAgainstWithoutIconsTrimmed = ltrim(text, ' ');\n const leadingWhitespaceOffset = text.length - wordToMatchAgainstWithoutIconsTrimmed.length;\n // match on value without icon\n const matches = matchesContiguous(query, wordToMatchAgainstWithoutIconsTrimmed);\n // Map matches back to offsets with icon and trimming\n if (matches) {\n for (const match of matches) {\n const iconOffset = iconOffsets[match.start + leadingWhitespaceOffset] /* icon offsets at index */ + leadingWhitespaceOffset /* overall leading whitespace offset */;\n match.start += iconOffset;\n match.end += iconOffset;\n }\n }\n return matches;\n}\nfunction matchesContiguous(word, wordToMatchAgainst) {\n const matchIndex = wordToMatchAgainst.toLowerCase().indexOf(word.toLowerCase());\n if (matchIndex !== -1) {\n return [{ start: matchIndex, end: matchIndex + word.length }];\n }\n return null;\n}\nfunction compareEntries(elementA, elementB, lookFor) {\n const labelHighlightsA = elementA.labelHighlights || [];\n const labelHighlightsB = elementB.labelHighlights || [];\n if (labelHighlightsA.length && !labelHighlightsB.length) {\n return -1;\n }\n if (!labelHighlightsA.length && labelHighlightsB.length) {\n return 1;\n }\n if (labelHighlightsA.length === 0 && labelHighlightsB.length === 0) {\n return 0;\n }\n return compareAnything(elementA.saneSortLabel, elementB.saneSortLabel, lookFor);\n}\nclass QuickInputAccessibilityProvider {\n getWidgetAriaLabel() {\n return localize('quickInput', \"Quick Input\");\n }\n getAriaLabel(element) {\n var _a;\n return ((_a = element.separator) === null || _a === void 0 ? void 0 : _a.label)\n ? `${element.saneAriaLabel}, ${element.separator.label}`\n : element.saneAriaLabel;\n }\n getWidgetRole() {\n return 'listbox';\n }\n getRole(element) {\n return element.hasCheckbox ? 'checkbox' : 'option';\n }\n isChecked(element) {\n if (!element.hasCheckbox) {\n return undefined;\n }\n return {\n value: element.checked,\n onDidChange: element.onChecked\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 *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport * as dom from '../../../browser/dom.js';\nimport { StandardKeyboardEvent } from '../../../browser/keyboardEvent.js';\nimport { ActionBar } from '../../../browser/ui/actionbar/actionbar.js';\nimport { Button } from '../../../browser/ui/button/button.js';\nimport { CountBadge } from '../../../browser/ui/countBadge/countBadge.js';\nimport { renderLabelWithIcons } from '../../../browser/ui/iconLabel/iconLabels.js';\nimport { ProgressBar } from '../../../browser/ui/progressbar/progressbar.js';\nimport { Action } from '../../../common/actions.js';\nimport { equals } from '../../../common/arrays.js';\nimport { TimeoutTimer } from '../../../common/async.js';\nimport { CancellationToken } from '../../../common/cancellation.js';\nimport { Codicon } from '../../../common/codicons.js';\nimport { Emitter } from '../../../common/event.js';\nimport { Disposable, DisposableStore, dispose } from '../../../common/lifecycle.js';\nimport { isIOS } from '../../../common/platform.js';\nimport Severity from '../../../common/severity.js';\nimport { withNullAsUndefined } from '../../../common/types.js';\nimport { getIconClass } from './quickInputUtils.js';\nimport { ItemActivation, NO_KEY_MODS, QuickInputHideReason } from '../common/quickInput.js';\nimport './media/quickInput.css';\nimport { localize } from '../../../../nls.js';\nimport { QuickInputBox } from './quickInputBox.js';\nimport { QuickInputList, QuickInputListFocus } from './quickInputList.js';\nconst $ = dom.$;\nconst backButton = {\n iconClass: Codicon.quickInputBack.classNames,\n tooltip: localize('quickInput.back', \"Back\"),\n handle: -1 // TODO\n};\nclass QuickInput extends Disposable {\n constructor(ui) {\n super();\n this.ui = ui;\n this.visible = false;\n this._enabled = true;\n this._busy = false;\n this._ignoreFocusOut = false;\n this._buttons = [];\n this.noValidationMessage = QuickInput.noPromptMessage;\n this._severity = Severity.Ignore;\n this.buttonsUpdated = false;\n this.onDidTriggerButtonEmitter = this._register(new Emitter());\n this.onDidHideEmitter = this._register(new Emitter());\n this.onDisposeEmitter = this._register(new Emitter());\n this.visibleDisposables = this._register(new DisposableStore());\n this.onDidHide = this.onDidHideEmitter.event;\n }\n get title() {\n return this._title;\n }\n set title(title) {\n this._title = title;\n this.update();\n }\n get description() {\n return this._description;\n }\n set description(description) {\n this._description = description;\n this.update();\n }\n get step() {\n return this._steps;\n }\n set step(step) {\n this._steps = step;\n this.update();\n }\n get totalSteps() {\n return this._totalSteps;\n }\n set totalSteps(totalSteps) {\n this._totalSteps = totalSteps;\n this.update();\n }\n get enabled() {\n return this._enabled;\n }\n set enabled(enabled) {\n this._enabled = enabled;\n this.update();\n }\n get contextKey() {\n return this._contextKey;\n }\n set contextKey(contextKey) {\n this._contextKey = contextKey;\n this.update();\n }\n get busy() {\n return this._busy;\n }\n set busy(busy) {\n this._busy = busy;\n this.update();\n }\n get ignoreFocusOut() {\n return this._ignoreFocusOut;\n }\n set ignoreFocusOut(ignoreFocusOut) {\n const shouldUpdate = this._ignoreFocusOut !== ignoreFocusOut && !isIOS;\n this._ignoreFocusOut = ignoreFocusOut && !isIOS;\n if (shouldUpdate) {\n this.update();\n }\n }\n get buttons() {\n return this._buttons;\n }\n set buttons(buttons) {\n this._buttons = buttons;\n this.buttonsUpdated = true;\n this.update();\n }\n get validationMessage() {\n return this._validationMessage;\n }\n set validationMessage(validationMessage) {\n this._validationMessage = validationMessage;\n this.update();\n }\n get severity() {\n return this._severity;\n }\n set severity(severity) {\n this._severity = severity;\n this.update();\n }\n show() {\n if (this.visible) {\n return;\n }\n this.visibleDisposables.add(this.ui.onDidTriggerButton(button => {\n if (this.buttons.indexOf(button) !== -1) {\n this.onDidTriggerButtonEmitter.fire(button);\n }\n }));\n this.ui.show(this);\n // update properties in the controller that get reset in the ui.show() call\n this.visible = true;\n // This ensures the message/prompt gets rendered\n this._lastValidationMessage = undefined;\n // This ensures the input box has the right severity applied\n this._lastSeverity = undefined;\n if (this.buttons.length) {\n // if there are buttons, the ui.show() clears them out of the UI so we should\n // rerender them.\n this.buttonsUpdated = true;\n }\n this.update();\n }\n hide() {\n if (!this.visible) {\n return;\n }\n this.ui.hide();\n }\n didHide(reason = QuickInputHideReason.Other) {\n this.visible = false;\n this.visibleDisposables.clear();\n this.onDidHideEmitter.fire({ reason });\n }\n update() {\n if (!this.visible) {\n return;\n }\n const title = this.getTitle();\n if (title && this.ui.title.textContent !== title) {\n this.ui.title.textContent = title;\n }\n else if (!title && this.ui.title.innerHTML !== ' ') {\n this.ui.title.innerText = '\\u00a0';\n }\n const description = this.getDescription();\n if (this.ui.description1.textContent !== description) {\n this.ui.description1.textContent = description;\n }\n if (this.ui.description2.textContent !== description) {\n this.ui.description2.textContent = description;\n }\n if (this.busy && !this.busyDelay) {\n this.busyDelay = new TimeoutTimer();\n this.busyDelay.setIfNotSet(() => {\n if (this.visible) {\n this.ui.progressBar.infinite();\n }\n }, 800);\n }\n if (!this.busy && this.busyDelay) {\n this.ui.progressBar.stop();\n this.busyDelay.cancel();\n this.busyDelay = undefined;\n }\n if (this.buttonsUpdated) {\n this.buttonsUpdated = false;\n this.ui.leftActionBar.clear();\n const leftButtons = this.buttons.filter(button => button === backButton);\n this.ui.leftActionBar.push(leftButtons.map((button, index) => {\n const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => __awaiter(this, void 0, void 0, function* () {\n this.onDidTriggerButtonEmitter.fire(button);\n }));\n action.tooltip = button.tooltip || '';\n return action;\n }), { icon: true, label: false });\n this.ui.rightActionBar.clear();\n const rightButtons = this.buttons.filter(button => button !== backButton);\n this.ui.rightActionBar.push(rightButtons.map((button, index) => {\n const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => __awaiter(this, void 0, void 0, function* () {\n this.onDidTriggerButtonEmitter.fire(button);\n }));\n action.tooltip = button.tooltip || '';\n return action;\n }), { icon: true, label: false });\n }\n this.ui.ignoreFocusOut = this.ignoreFocusOut;\n this.ui.setEnabled(this.enabled);\n this.ui.setContextKey(this.contextKey);\n const validationMessage = this.validationMessage || this.noValidationMessage;\n if (this._lastValidationMessage !== validationMessage) {\n this._lastValidationMessage = validationMessage;\n dom.reset(this.ui.message, ...renderLabelWithIcons(validationMessage));\n }\n if (this._lastSeverity !== this.severity) {\n this._lastSeverity = this.severity;\n this.showMessageDecoration(this.severity);\n }\n }\n getTitle() {\n if (this.title && this.step) {\n return `${this.title} (${this.getSteps()})`;\n }\n if (this.title) {\n return this.title;\n }\n if (this.step) {\n return this.getSteps();\n }\n return '';\n }\n getDescription() {\n return this.description || '';\n }\n getSteps() {\n if (this.step && this.totalSteps) {\n return localize('quickInput.steps', \"{0}/{1}\", this.step, this.totalSteps);\n }\n if (this.step) {\n return String(this.step);\n }\n return '';\n }\n showMessageDecoration(severity) {\n this.ui.inputBox.showDecoration(severity);\n if (severity !== Severity.Ignore) {\n const styles = this.ui.inputBox.stylesForType(severity);\n this.ui.message.style.color = styles.foreground ? `${styles.foreground}` : '';\n this.ui.message.style.backgroundColor = styles.background ? `${styles.background}` : '';\n this.ui.message.style.border = styles.border ? `1px solid ${styles.border}` : '';\n this.ui.message.style.marginBottom = '-2px';\n }\n else {\n this.ui.message.style.color = '';\n this.ui.message.style.backgroundColor = '';\n this.ui.message.style.border = '';\n this.ui.message.style.marginBottom = '';\n }\n }\n dispose() {\n this.hide();\n this.onDisposeEmitter.fire();\n super.dispose();\n }\n}\nQuickInput.noPromptMessage = localize('inputModeEntry', \"Press 'Enter' to confirm your input or 'Escape' to cancel\");\nclass QuickPick extends QuickInput {\n constructor() {\n super(...arguments);\n this._value = '';\n this.onDidChangeValueEmitter = this._register(new Emitter());\n this.onWillAcceptEmitter = this._register(new Emitter());\n this.onDidAcceptEmitter = this._register(new Emitter());\n this.onDidCustomEmitter = this._register(new Emitter());\n this._items = [];\n this.itemsUpdated = false;\n this._canSelectMany = false;\n this._canAcceptInBackground = false;\n this._matchOnDescription = false;\n this._matchOnDetail = false;\n this._matchOnLabel = true;\n this._matchOnLabelMode = 'fuzzy';\n this._sortByLabel = true;\n this._autoFocusOnList = true;\n this._keepScrollPosition = false;\n this._itemActivation = this.ui.isScreenReaderOptimized() ? ItemActivation.NONE /* https://github.com/microsoft/vscode/issues/57501 */ : ItemActivation.FIRST;\n this._activeItems = [];\n this.activeItemsUpdated = false;\n this.activeItemsToConfirm = [];\n this.onDidChangeActiveEmitter = this._register(new Emitter());\n this._selectedItems = [];\n this.selectedItemsUpdated = false;\n this.selectedItemsToConfirm = [];\n this.onDidChangeSelectionEmitter = this._register(new Emitter());\n this.onDidTriggerItemButtonEmitter = this._register(new Emitter());\n this.valueSelectionUpdated = true;\n this._ok = 'default';\n this._customButton = false;\n this.filterValue = (value) => value;\n this.onDidChangeValue = this.onDidChangeValueEmitter.event;\n this.onWillAccept = this.onWillAcceptEmitter.event;\n this.onDidAccept = this.onDidAcceptEmitter.event;\n this.onDidChangeActive = this.onDidChangeActiveEmitter.event;\n this.onDidChangeSelection = this.onDidChangeSelectionEmitter.event;\n this.onDidTriggerItemButton = this.onDidTriggerItemButtonEmitter.event;\n }\n get quickNavigate() {\n return this._quickNavigate;\n }\n set quickNavigate(quickNavigate) {\n this._quickNavigate = quickNavigate;\n this.update();\n }\n get value() {\n return this._value;\n }\n set value(value) {\n this.doSetValue(value);\n }\n doSetValue(value, skipUpdate) {\n if (this._value !== value) {\n this._value = value;\n if (!skipUpdate) {\n this.update();\n }\n if (this.visible) {\n const didFilter = this.ui.list.filter(this.filterValue(this._value));\n if (didFilter) {\n this.trySelectFirst();\n }\n }\n this.onDidChangeValueEmitter.fire(this._value);\n }\n }\n set ariaLabel(ariaLabel) {\n this._ariaLabel = ariaLabel;\n this.update();\n }\n get ariaLabel() {\n return this._ariaLabel;\n }\n get placeholder() {\n return this._placeholder;\n }\n set placeholder(placeholder) {\n this._placeholder = placeholder;\n this.update();\n }\n get items() {\n return this._items;\n }\n get scrollTop() {\n return this.ui.list.scrollTop;\n }\n set scrollTop(scrollTop) {\n this.ui.list.scrollTop = scrollTop;\n }\n set items(items) {\n this._items = items;\n this.itemsUpdated = true;\n this.update();\n }\n get canSelectMany() {\n return this._canSelectMany;\n }\n set canSelectMany(canSelectMany) {\n this._canSelectMany = canSelectMany;\n this.update();\n }\n get canAcceptInBackground() {\n return this._canAcceptInBackground;\n }\n set canAcceptInBackground(canAcceptInBackground) {\n this._canAcceptInBackground = canAcceptInBackground;\n }\n get matchOnDescription() {\n return this._matchOnDescription;\n }\n set matchOnDescription(matchOnDescription) {\n this._matchOnDescription = matchOnDescription;\n this.update();\n }\n get matchOnDetail() {\n return this._matchOnDetail;\n }\n set matchOnDetail(matchOnDetail) {\n this._matchOnDetail = matchOnDetail;\n this.update();\n }\n get matchOnLabel() {\n return this._matchOnLabel;\n }\n set matchOnLabel(matchOnLabel) {\n this._matchOnLabel = matchOnLabel;\n this.update();\n }\n get matchOnLabelMode() {\n return this._matchOnLabelMode;\n }\n set matchOnLabelMode(matchOnLabelMode) {\n this._matchOnLabelMode = matchOnLabelMode;\n this.update();\n }\n get sortByLabel() {\n return this._sortByLabel;\n }\n set sortByLabel(sortByLabel) {\n this._sortByLabel = sortByLabel;\n this.update();\n }\n get autoFocusOnList() {\n return this._autoFocusOnList;\n }\n set autoFocusOnList(autoFocusOnList) {\n this._autoFocusOnList = autoFocusOnList;\n this.update();\n }\n get keepScrollPosition() {\n return this._keepScrollPosition;\n }\n set keepScrollPosition(keepScrollPosition) {\n this._keepScrollPosition = keepScrollPosition;\n }\n get itemActivation() {\n return this._itemActivation;\n }\n set itemActivation(itemActivation) {\n this._itemActivation = itemActivation;\n }\n get activeItems() {\n return this._activeItems;\n }\n set activeItems(activeItems) {\n this._activeItems = activeItems;\n this.activeItemsUpdated = true;\n this.update();\n }\n get selectedItems() {\n return this._selectedItems;\n }\n set selectedItems(selectedItems) {\n this._selectedItems = selectedItems;\n this.selectedItemsUpdated = true;\n this.update();\n }\n get keyMods() {\n if (this._quickNavigate) {\n // Disable keyMods when quick navigate is enabled\n // because in this model the interaction is purely\n // keyboard driven and Ctrl/Alt are typically\n // pressed and hold during this interaction.\n return NO_KEY_MODS;\n }\n return this.ui.keyMods;\n }\n set valueSelection(valueSelection) {\n this._valueSelection = valueSelection;\n this.valueSelectionUpdated = true;\n this.update();\n }\n get customButton() {\n return this._customButton;\n }\n set customButton(showCustomButton) {\n this._customButton = showCustomButton;\n this.update();\n }\n get customLabel() {\n return this._customButtonLabel;\n }\n set customLabel(label) {\n this._customButtonLabel = label;\n this.update();\n }\n get customHover() {\n return this._customButtonHover;\n }\n set customHover(hover) {\n this._customButtonHover = hover;\n this.update();\n }\n get ok() {\n return this._ok;\n }\n set ok(showOkButton) {\n this._ok = showOkButton;\n this.update();\n }\n get hideInput() {\n return !!this._hideInput;\n }\n set hideInput(hideInput) {\n this._hideInput = hideInput;\n this.update();\n }\n trySelectFirst() {\n if (this.autoFocusOnList) {\n if (!this.canSelectMany) {\n this.ui.list.focus(QuickInputListFocus.First);\n }\n }\n }\n show() {\n if (!this.visible) {\n this.visibleDisposables.add(this.ui.inputBox.onDidChange(value => {\n this.doSetValue(value, true /* skip update since this originates from the UI */);\n }));\n this.visibleDisposables.add(this.ui.inputBox.onMouseDown(event => {\n if (!this.autoFocusOnList) {\n this.ui.list.clearFocus();\n }\n }));\n this.visibleDisposables.add((this._hideInput ? this.ui.list : this.ui.inputBox).onKeyDown((event) => {\n switch (event.keyCode) {\n case 18 /* KeyCode.DownArrow */:\n this.ui.list.focus(QuickInputListFocus.Next);\n if (this.canSelectMany) {\n this.ui.list.domFocus();\n }\n dom.EventHelper.stop(event, true);\n break;\n case 16 /* KeyCode.UpArrow */:\n if (this.ui.list.getFocusedElements().length) {\n this.ui.list.focus(QuickInputListFocus.Previous);\n }\n else {\n this.ui.list.focus(QuickInputListFocus.Last);\n }\n if (this.canSelectMany) {\n this.ui.list.domFocus();\n }\n dom.EventHelper.stop(event, true);\n break;\n case 12 /* KeyCode.PageDown */:\n this.ui.list.focus(QuickInputListFocus.NextPage);\n if (this.canSelectMany) {\n this.ui.list.domFocus();\n }\n dom.EventHelper.stop(event, true);\n break;\n case 11 /* KeyCode.PageUp */:\n this.ui.list.focus(QuickInputListFocus.PreviousPage);\n if (this.canSelectMany) {\n this.ui.list.domFocus();\n }\n dom.EventHelper.stop(event, true);\n break;\n case 17 /* KeyCode.RightArrow */:\n if (!this._canAcceptInBackground) {\n return; // needs to be enabled\n }\n if (!this.ui.inputBox.isSelectionAtEnd()) {\n return; // ensure input box selection at end\n }\n if (this.activeItems[0]) {\n this._selectedItems = [this.activeItems[0]];\n this.onDidChangeSelectionEmitter.fire(this.selectedItems);\n this.handleAccept(true);\n }\n break;\n case 14 /* KeyCode.Home */:\n if ((event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey) {\n this.ui.list.focus(QuickInputListFocus.First);\n dom.EventHelper.stop(event, true);\n }\n break;\n case 13 /* KeyCode.End */:\n if ((event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey) {\n this.ui.list.focus(QuickInputListFocus.Last);\n dom.EventHelper.stop(event, true);\n }\n break;\n }\n }));\n this.visibleDisposables.add(this.ui.onDidAccept(() => {\n if (this.canSelectMany) {\n // if there are no checked elements, it means that an onDidChangeSelection never fired to overwrite\n // `_selectedItems`. In that case, we should emit one with an empty array to ensure that\n // `.selectedItems` is up to date.\n if (!this.ui.list.getCheckedElements().length) {\n this._selectedItems = [];\n this.onDidChangeSelectionEmitter.fire(this.selectedItems);\n }\n }\n else if (this.activeItems[0]) {\n // For single-select, we set `selectedItems` to the item that was accepted.\n this._selectedItems = [this.activeItems[0]];\n this.onDidChangeSelectionEmitter.fire(this.selectedItems);\n }\n this.handleAccept(false);\n }));\n this.visibleDisposables.add(this.ui.onDidCustom(() => {\n this.onDidCustomEmitter.fire();\n }));\n this.visibleDisposables.add(this.ui.list.onDidChangeFocus(focusedItems => {\n if (this.activeItemsUpdated) {\n return; // Expect another event.\n }\n if (this.activeItemsToConfirm !== this._activeItems && equals(focusedItems, this._activeItems, (a, b) => a === b)) {\n return;\n }\n this._activeItems = focusedItems;\n this.onDidChangeActiveEmitter.fire(focusedItems);\n }));\n this.visibleDisposables.add(this.ui.list.onDidChangeSelection(({ items: selectedItems, event }) => {\n if (this.canSelectMany) {\n if (selectedItems.length) {\n this.ui.list.setSelectedElements([]);\n }\n return;\n }\n if (this.selectedItemsToConfirm !== this._selectedItems && equals(selectedItems, this._selectedItems, (a, b) => a === b)) {\n return;\n }\n this._selectedItems = selectedItems;\n this.onDidChangeSelectionEmitter.fire(selectedItems);\n if (selectedItems.length) {\n this.handleAccept(event instanceof MouseEvent && event.button === 1 /* mouse middle click */);\n }\n }));\n this.visibleDisposables.add(this.ui.list.onChangedCheckedElements(checkedItems => {\n if (!this.canSelectMany) {\n return;\n }\n if (this.selectedItemsToConfirm !== this._selectedItems && equals(checkedItems, this._selectedItems, (a, b) => a === b)) {\n return;\n }\n this._selectedItems = checkedItems;\n this.onDidChangeSelectionEmitter.fire(checkedItems);\n }));\n this.visibleDisposables.add(this.ui.list.onButtonTriggered(event => this.onDidTriggerItemButtonEmitter.fire(event)));\n this.visibleDisposables.add(this.registerQuickNavigation());\n this.valueSelectionUpdated = true;\n }\n super.show(); // TODO: Why have show() bubble up while update() trickles down? (Could move setComboboxAccessibility() here.)\n }\n handleAccept(inBackground) {\n // Figure out veto via `onWillAccept` event\n let veto = false;\n this.onWillAcceptEmitter.fire({ veto: () => veto = true });\n // Continue with `onDidAccept` if no veto\n if (!veto) {\n this.onDidAcceptEmitter.fire({ inBackground });\n }\n }\n registerQuickNavigation() {\n return dom.addDisposableListener(this.ui.container, dom.EventType.KEY_UP, e => {\n if (this.canSelectMany || !this._quickNavigate) {\n return;\n }\n const keyboardEvent = new StandardKeyboardEvent(e);\n const keyCode = keyboardEvent.keyCode;\n // Select element when keys are pressed that signal it\n const quickNavKeys = this._quickNavigate.keybindings;\n const wasTriggerKeyPressed = quickNavKeys.some(k => {\n const [firstPart, chordPart] = k.getParts();\n if (chordPart) {\n return false;\n }\n if (firstPart.shiftKey && keyCode === 4 /* KeyCode.Shift */) {\n if (keyboardEvent.ctrlKey || keyboardEvent.altKey || keyboardEvent.metaKey) {\n return false; // this is an optimistic check for the shift key being used to navigate back in quick input\n }\n return true;\n }\n if (firstPart.altKey && keyCode === 6 /* KeyCode.Alt */) {\n return true;\n }\n if (firstPart.ctrlKey && keyCode === 5 /* KeyCode.Ctrl */) {\n return true;\n }\n if (firstPart.metaKey && keyCode === 57 /* KeyCode.Meta */) {\n return true;\n }\n return false;\n });\n if (wasTriggerKeyPressed) {\n if (this.activeItems[0]) {\n this._selectedItems = [this.activeItems[0]];\n this.onDidChangeSelectionEmitter.fire(this.selectedItems);\n this.handleAccept(false);\n }\n // Unset quick navigate after press. It is only valid once\n // and should not result in any behaviour change afterwards\n // if the picker remains open because there was no active item\n this._quickNavigate = undefined;\n }\n });\n }\n update() {\n if (!this.visible) {\n return;\n }\n // store the scrollTop before it is reset\n const scrollTopBefore = this.keepScrollPosition ? this.scrollTop : 0;\n const hideInput = !!this._hideInput && this._items.length > 0;\n this.ui.container.classList.toggle('hidden-input', hideInput && !this.description);\n const visibilities = {\n title: !!this.title || !!this.step || !!this.buttons.length,\n description: !!this.description,\n checkAll: this.canSelectMany && !this._hideCheckAll,\n checkBox: this.canSelectMany,\n inputBox: !hideInput,\n progressBar: !hideInput,\n visibleCount: true,\n count: this.canSelectMany,\n ok: this.ok === 'default' ? this.canSelectMany : this.ok,\n list: true,\n message: !!this.validationMessage,\n customButton: this.customButton\n };\n this.ui.setVisibilities(visibilities);\n super.update();\n if (this.ui.inputBox.value !== this.value) {\n this.ui.inputBox.value = this.value;\n }\n if (this.valueSelectionUpdated) {\n this.valueSelectionUpdated = false;\n this.ui.inputBox.select(this._valueSelection && { start: this._valueSelection[0], end: this._valueSelection[1] });\n }\n if (this.ui.inputBox.placeholder !== (this.placeholder || '')) {\n this.ui.inputBox.placeholder = (this.placeholder || '');\n }\n let ariaLabel = this.ariaLabel;\n if (!ariaLabel) {\n ariaLabel = this.placeholder || QuickPick.DEFAULT_ARIA_LABEL;\n // If we have a title, include it in the aria label.\n if (this.title) {\n ariaLabel += ` - ${this.title}`;\n }\n }\n if (this.ui.inputBox.ariaLabel !== ariaLabel) {\n this.ui.inputBox.ariaLabel = ariaLabel;\n }\n this.ui.list.matchOnDescription = this.matchOnDescription;\n this.ui.list.matchOnDetail = this.matchOnDetail;\n this.ui.list.matchOnLabel = this.matchOnLabel;\n this.ui.list.matchOnLabelMode = this.matchOnLabelMode;\n this.ui.list.sortByLabel = this.sortByLabel;\n if (this.itemsUpdated) {\n this.itemsUpdated = false;\n this.ui.list.setElements(this.items);\n this.ui.list.filter(this.filterValue(this.ui.inputBox.value));\n this.ui.checkAll.checked = this.ui.list.getAllVisibleChecked();\n this.ui.visibleCount.setCount(this.ui.list.getVisibleCount());\n this.ui.count.setCount(this.ui.list.getCheckedCount());\n switch (this._itemActivation) {\n case ItemActivation.NONE:\n this._itemActivation = ItemActivation.FIRST; // only valid once, then unset\n break;\n case ItemActivation.SECOND:\n this.ui.list.focus(QuickInputListFocus.Second);\n this._itemActivation = ItemActivation.FIRST; // only valid once, then unset\n break;\n case ItemActivation.LAST:\n this.ui.list.focus(QuickInputListFocus.Last);\n this._itemActivation = ItemActivation.FIRST; // only valid once, then unset\n break;\n default:\n this.trySelectFirst();\n break;\n }\n }\n if (this.ui.container.classList.contains('show-checkboxes') !== !!this.canSelectMany) {\n if (this.canSelectMany) {\n this.ui.list.clearFocus();\n }\n else {\n this.trySelectFirst();\n }\n }\n if (this.activeItemsUpdated) {\n this.activeItemsUpdated = false;\n this.activeItemsToConfirm = this._activeItems;\n this.ui.list.setFocusedElements(this.activeItems);\n if (this.activeItemsToConfirm === this._activeItems) {\n this.activeItemsToConfirm = null;\n }\n }\n if (this.selectedItemsUpdated) {\n this.selectedItemsUpdated = false;\n this.selectedItemsToConfirm = this._selectedItems;\n if (this.canSelectMany) {\n this.ui.list.setCheckedElements(this.selectedItems);\n }\n else {\n this.ui.list.setSelectedElements(this.selectedItems);\n }\n if (this.selectedItemsToConfirm === this._selectedItems) {\n this.selectedItemsToConfirm = null;\n }\n }\n this.ui.customButton.label = this.customLabel || '';\n this.ui.customButton.element.title = this.customHover || '';\n this.ui.setComboboxAccessibility(true);\n if (!visibilities.inputBox) {\n // we need to move focus into the tree to detect keybindings\n // properly when the input box is not visible (quick nav)\n this.ui.list.domFocus();\n // Focus the first element in the list if multiselect is enabled\n if (this.canSelectMany) {\n this.ui.list.focus(QuickInputListFocus.First);\n }\n }\n // Set the scroll position to what it was before updating the items\n if (this.keepScrollPosition) {\n this.scrollTop = scrollTopBefore;\n }\n }\n}\nQuickPick.DEFAULT_ARIA_LABEL = localize('quickInputBox.ariaLabel', \"Type to narrow down results.\");\nexport class QuickInputController extends Disposable {\n constructor(options) {\n super();\n this.options = options;\n this.comboboxAccessibility = false;\n this.enabled = true;\n this.onDidAcceptEmitter = this._register(new Emitter());\n this.onDidCustomEmitter = this._register(new Emitter());\n this.onDidTriggerButtonEmitter = this._register(new Emitter());\n this.keyMods = { ctrlCmd: false, alt: false };\n this.controller = null;\n this.onShowEmitter = this._register(new Emitter());\n this.onShow = this.onShowEmitter.event;\n this.onHideEmitter = this._register(new Emitter());\n this.onHide = this.onHideEmitter.event;\n this.idPrefix = options.idPrefix;\n this.parentElement = options.container;\n this.styles = options.styles;\n this.registerKeyModsListeners();\n }\n registerKeyModsListeners() {\n const listener = (e) => {\n this.keyMods.ctrlCmd = e.ctrlKey || e.metaKey;\n this.keyMods.alt = e.altKey;\n };\n this._register(dom.addDisposableListener(window, dom.EventType.KEY_DOWN, listener, true));\n this._register(dom.addDisposableListener(window, dom.EventType.KEY_UP, listener, true));\n this._register(dom.addDisposableListener(window, dom.EventType.MOUSE_DOWN, listener, true));\n }\n getUI() {\n if (this.ui) {\n return this.ui;\n }\n const container = dom.append(this.parentElement, $('.quick-input-widget.show-file-icons'));\n container.tabIndex = -1;\n container.style.display = 'none';\n const styleSheet = dom.createStyleSheet(container);\n const titleBar = dom.append(container, $('.quick-input-titlebar'));\n const leftActionBar = this._register(new ActionBar(titleBar));\n leftActionBar.domNode.classList.add('quick-input-left-action-bar');\n const title = dom.append(titleBar, $('.quick-input-title'));\n const rightActionBar = this._register(new ActionBar(titleBar));\n rightActionBar.domNode.classList.add('quick-input-right-action-bar');\n const description1 = dom.append(container, $('.quick-input-description'));\n const headerContainer = dom.append(container, $('.quick-input-header'));\n const checkAll = dom.append(headerContainer, $('input.quick-input-check-all'));\n checkAll.type = 'checkbox';\n checkAll.setAttribute('aria-label', localize('quickInput.checkAll', \"Toggle all checkboxes\"));\n this._register(dom.addStandardDisposableListener(checkAll, dom.EventType.CHANGE, e => {\n const checked = checkAll.checked;\n list.setAllVisibleChecked(checked);\n }));\n this._register(dom.addDisposableListener(checkAll, dom.EventType.CLICK, e => {\n if (e.x || e.y) { // Avoid 'click' triggered by 'space'...\n inputBox.setFocus();\n }\n }));\n const description2 = dom.append(headerContainer, $('.quick-input-description'));\n const extraContainer = dom.append(headerContainer, $('.quick-input-and-message'));\n const filterContainer = dom.append(extraContainer, $('.quick-input-filter'));\n const inputBox = this._register(new QuickInputBox(filterContainer));\n inputBox.setAttribute('aria-describedby', `${this.idPrefix}message`);\n const visibleCountContainer = dom.append(filterContainer, $('.quick-input-visible-count'));\n visibleCountContainer.setAttribute('aria-live', 'polite');\n visibleCountContainer.setAttribute('aria-atomic', 'true');\n const 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 const countContainer = dom.append(filterContainer, $('.quick-input-count'));\n countContainer.setAttribute('aria-live', 'polite');\n const 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 const okContainer = dom.append(headerContainer, $('.quick-input-action'));\n const ok = new Button(okContainer);\n ok.label = localize('ok', \"OK\");\n this._register(ok.onDidClick(e => {\n this.onDidAcceptEmitter.fire();\n }));\n const customButtonContainer = dom.append(headerContainer, $('.quick-input-action'));\n const customButton = new Button(customButtonContainer);\n customButton.label = localize('custom', \"Custom\");\n this._register(customButton.onDidClick(e => {\n this.onDidCustomEmitter.fire();\n }));\n const message = dom.append(extraContainer, $(`#${this.idPrefix}message.quick-input-message`));\n const list = this._register(new QuickInputList(container, this.idPrefix + 'list', this.options));\n this._register(list.onChangedAllVisibleChecked(checked => {\n checkAll.checked = checked;\n }));\n this._register(list.onChangedVisibleCount(c => {\n visibleCount.setCount(c);\n }));\n this._register(list.onChangedCheckedCount(c => {\n count.setCount(c);\n }));\n this._register(list.onLeave(() => {\n // Defer to avoid the input field reacting to the triggering key.\n setTimeout(() => {\n inputBox.setFocus();\n if (this.controller instanceof QuickPick && this.controller.canSelectMany) {\n list.clearFocus();\n }\n }, 0);\n }));\n this._register(list.onDidChangeFocus(() => {\n if (this.comboboxAccessibility) {\n this.getUI().inputBox.setAttribute('aria-activedescendant', this.getUI().list.getActiveDescendant() || '');\n }\n }));\n const progressBar = new ProgressBar(container);\n progressBar.getContainer().classList.add('quick-input-progress');\n const focusTracker = dom.trackFocus(container);\n this._register(focusTracker);\n this._register(dom.addDisposableListener(container, dom.EventType.FOCUS, e => {\n this.previousFocusElement = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : undefined;\n }, true));\n this._register(focusTracker.onDidBlur(() => {\n if (!this.getUI().ignoreFocusOut && !this.options.ignoreFocusOut()) {\n this.hide(QuickInputHideReason.Blur);\n }\n this.previousFocusElement = undefined;\n }));\n this._register(dom.addDisposableListener(container, dom.EventType.FOCUS, (e) => {\n inputBox.setFocus();\n }));\n this._register(dom.addDisposableListener(container, dom.EventType.KEY_DOWN, (e) => {\n const event = new StandardKeyboardEvent(e);\n switch (event.keyCode) {\n case 3 /* KeyCode.Enter */:\n dom.EventHelper.stop(e, true);\n this.onDidAcceptEmitter.fire();\n break;\n case 9 /* KeyCode.Escape */:\n dom.EventHelper.stop(e, true);\n this.hide(QuickInputHideReason.Gesture);\n break;\n case 2 /* KeyCode.Tab */:\n if (!event.altKey && !event.ctrlKey && !event.metaKey) {\n const selectors = ['.action-label.codicon'];\n if (container.classList.contains('show-checkboxes')) {\n selectors.push('input');\n }\n else {\n selectors.push('input[type=text]');\n }\n if (this.getUI().list.isDisplayed()) {\n selectors.push('.monaco-list');\n }\n const stops = container.querySelectorAll(selectors.join(', '));\n if (event.shiftKey && event.target === stops[0]) {\n dom.EventHelper.stop(e, true);\n stops[stops.length - 1].focus();\n }\n else if (!event.shiftKey && event.target === stops[stops.length - 1]) {\n dom.EventHelper.stop(e, true);\n stops[0].focus();\n }\n }\n break;\n }\n }));\n this.ui = {\n container,\n styleSheet,\n leftActionBar,\n titleBar,\n title,\n description1,\n description2,\n rightActionBar,\n checkAll,\n filterContainer,\n inputBox,\n visibleCountContainer,\n visibleCount,\n countContainer,\n count,\n okContainer,\n ok,\n message,\n customButtonContainer,\n customButton,\n list,\n progressBar,\n onDidAccept: this.onDidAcceptEmitter.event,\n onDidCustom: this.onDidCustomEmitter.event,\n onDidTriggerButton: this.onDidTriggerButtonEmitter.event,\n ignoreFocusOut: false,\n keyMods: this.keyMods,\n isScreenReaderOptimized: () => this.options.isScreenReaderOptimized(),\n show: controller => this.show(controller),\n hide: () => this.hide(),\n setVisibilities: visibilities => this.setVisibilities(visibilities),\n setComboboxAccessibility: enabled => this.setComboboxAccessibility(enabled),\n setEnabled: enabled => this.setEnabled(enabled),\n setContextKey: contextKey => this.options.setContextKey(contextKey),\n };\n this.updateStyles();\n return this.ui;\n }\n pick(picks, options = {}, token = CancellationToken.None) {\n return new Promise((doResolve, reject) => {\n let resolve = (result) => {\n var _a;\n resolve = doResolve;\n (_a = options.onKeyMods) === null || _a === void 0 ? void 0 : _a.call(options, input.keyMods);\n doResolve(result);\n };\n if (token.isCancellationRequested) {\n resolve(undefined);\n return;\n }\n const input = this.createQuickPick();\n let activeItem;\n const disposables = [\n input,\n input.onDidAccept(() => {\n if (input.canSelectMany) {\n resolve(input.selectedItems.slice());\n input.hide();\n }\n else {\n const result = input.activeItems[0];\n if (result) {\n resolve(result);\n input.hide();\n }\n }\n }),\n input.onDidChangeActive(items => {\n const focused = items[0];\n if (focused && options.onDidFocus) {\n options.onDidFocus(focused);\n }\n }),\n input.onDidChangeSelection(items => {\n if (!input.canSelectMany) {\n const result = items[0];\n if (result) {\n resolve(result);\n input.hide();\n }\n }\n }),\n input.onDidTriggerItemButton(event => options.onDidTriggerItemButton && options.onDidTriggerItemButton(Object.assign(Object.assign({}, event), { removeItem: () => {\n const index = input.items.indexOf(event.item);\n if (index !== -1) {\n const items = input.items.slice();\n const removed = items.splice(index, 1);\n const activeItems = input.activeItems.filter(activeItem => activeItem !== removed[0]);\n const keepScrollPositionBefore = input.keepScrollPosition;\n input.keepScrollPosition = true;\n input.items = items;\n if (activeItems) {\n input.activeItems = activeItems;\n }\n input.keepScrollPosition = keepScrollPositionBefore;\n }\n } }))),\n input.onDidChangeValue(value => {\n if (activeItem && !value && (input.activeItems.length !== 1 || input.activeItems[0] !== activeItem)) {\n input.activeItems = [activeItem];\n }\n }),\n token.onCancellationRequested(() => {\n input.hide();\n }),\n input.onDidHide(() => {\n dispose(disposables);\n resolve(undefined);\n }),\n ];\n input.title = options.title;\n input.canSelectMany = !!options.canPickMany;\n input.placeholder = options.placeHolder;\n input.ignoreFocusOut = !!options.ignoreFocusLost;\n input.matchOnDescription = !!options.matchOnDescription;\n input.matchOnDetail = !!options.matchOnDetail;\n input.matchOnLabel = (options.matchOnLabel === undefined) || options.matchOnLabel; // default to true\n input.autoFocusOnList = (options.autoFocusOnList === undefined) || options.autoFocusOnList; // default to true\n input.quickNavigate = options.quickNavigate;\n input.hideInput = !!options.hideInput;\n input.contextKey = options.contextKey;\n input.busy = true;\n Promise.all([picks, options.activeItem])\n .then(([items, _activeItem]) => {\n activeItem = _activeItem;\n input.busy = false;\n input.items = items;\n if (input.canSelectMany) {\n input.selectedItems = items.filter(item => item.type !== 'separator' && item.picked);\n }\n if (activeItem) {\n input.activeItems = [activeItem];\n }\n });\n input.show();\n Promise.resolve(picks).then(undefined, err => {\n reject(err);\n input.hide();\n });\n });\n }\n createQuickPick() {\n const ui = this.getUI();\n return new QuickPick(ui);\n }\n show(controller) {\n const ui = this.getUI();\n this.onShowEmitter.fire();\n const oldController = this.controller;\n this.controller = controller;\n if (oldController) {\n oldController.didHide();\n }\n this.setEnabled(true);\n ui.leftActionBar.clear();\n ui.title.textContent = '';\n ui.description1.textContent = '';\n ui.description2.textContent = '';\n ui.rightActionBar.clear();\n ui.checkAll.checked = false;\n // ui.inputBox.value = ''; Avoid triggering an event.\n ui.inputBox.placeholder = '';\n ui.inputBox.password = false;\n ui.inputBox.showDecoration(Severity.Ignore);\n ui.visibleCount.setCount(0);\n ui.count.setCount(0);\n dom.reset(ui.message);\n ui.progressBar.stop();\n ui.list.setElements([]);\n ui.list.matchOnDescription = false;\n ui.list.matchOnDetail = false;\n ui.list.matchOnLabel = true;\n ui.list.sortByLabel = true;\n ui.ignoreFocusOut = false;\n this.setComboboxAccessibility(false);\n ui.inputBox.ariaLabel = '';\n const backKeybindingLabel = this.options.backKeybindingLabel();\n backButton.tooltip = backKeybindingLabel ? localize('quickInput.backWithKeybinding', \"Back ({0})\", backKeybindingLabel) : localize('quickInput.back', \"Back\");\n ui.container.style.display = '';\n this.updateLayout();\n ui.inputBox.setFocus();\n }\n setVisibilities(visibilities) {\n const ui = this.getUI();\n ui.title.style.display = visibilities.title ? '' : 'none';\n ui.description1.style.display = visibilities.description && (visibilities.inputBox || visibilities.checkAll) ? '' : 'none';\n ui.description2.style.display = visibilities.description && !(visibilities.inputBox || visibilities.checkAll) ? '' : 'none';\n ui.checkAll.style.display = visibilities.checkAll ? '' : 'none';\n ui.filterContainer.style.display = visibilities.inputBox ? '' : 'none';\n ui.visibleCountContainer.style.display = visibilities.visibleCount ? '' : 'none';\n ui.countContainer.style.display = visibilities.count ? '' : 'none';\n ui.okContainer.style.display = visibilities.ok ? '' : 'none';\n ui.customButtonContainer.style.display = visibilities.customButton ? '' : 'none';\n ui.message.style.display = visibilities.message ? '' : 'none';\n ui.progressBar.getContainer().style.display = visibilities.progressBar ? '' : 'none';\n ui.list.display(!!visibilities.list);\n ui.container.classList[visibilities.checkBox ? 'add' : 'remove']('show-checkboxes');\n this.updateLayout(); // TODO\n }\n setComboboxAccessibility(enabled) {\n if (enabled !== this.comboboxAccessibility) {\n const ui = this.getUI();\n this.comboboxAccessibility = enabled;\n if (this.comboboxAccessibility) {\n ui.inputBox.setAttribute('role', 'combobox');\n ui.inputBox.setAttribute('aria-haspopup', 'true');\n ui.inputBox.setAttribute('aria-autocomplete', 'list');\n ui.inputBox.setAttribute('aria-activedescendant', ui.list.getActiveDescendant() || '');\n }\n else {\n ui.inputBox.removeAttribute('role');\n ui.inputBox.removeAttribute('aria-haspopup');\n ui.inputBox.removeAttribute('aria-autocomplete');\n ui.inputBox.removeAttribute('aria-activedescendant');\n }\n }\n }\n setEnabled(enabled) {\n if (enabled !== this.enabled) {\n this.enabled = enabled;\n for (const item of this.getUI().leftActionBar.viewItems) {\n item.getAction().enabled = enabled;\n }\n for (const item of this.getUI().rightActionBar.viewItems) {\n item.getAction().enabled = enabled;\n }\n this.getUI().checkAll.disabled = !enabled;\n // this.getUI().inputBox.enabled = enabled; Avoid loosing focus.\n this.getUI().ok.enabled = enabled;\n this.getUI().list.enabled = enabled;\n }\n }\n hide(reason) {\n var _a;\n const controller = this.controller;\n if (controller) {\n const focusChanged = !((_a = this.ui) === null || _a === void 0 ? void 0 : _a.container.contains(document.activeElement));\n this.controller = null;\n this.onHideEmitter.fire();\n this.getUI().container.style.display = 'none';\n if (!focusChanged) {\n let currentElement = this.previousFocusElement;\n while (currentElement && !currentElement.offsetParent) {\n currentElement = withNullAsUndefined(currentElement.parentElement);\n }\n if (currentElement === null || currentElement === void 0 ? void 0 : currentElement.offsetParent) {\n currentElement.focus();\n this.previousFocusElement = undefined;\n }\n else {\n this.options.returnFocus();\n }\n }\n controller.didHide(reason);\n }\n }\n layout(dimension, titleBarOffset) {\n this.dimension = dimension;\n this.titleBarOffset = titleBarOffset;\n this.updateLayout();\n }\n updateLayout() {\n if (this.ui) {\n this.ui.container.style.top = `${this.titleBarOffset}px`;\n const style = this.ui.container.style;\n const width = Math.min(this.dimension.width * 0.62 /* golden cut */, QuickInputController.MAX_WIDTH);\n style.width = width + 'px';\n style.marginLeft = '-' + (width / 2) + 'px';\n this.ui.inputBox.layout();\n this.ui.list.layout(this.dimension && this.dimension.height * 0.4);\n }\n }\n applyStyles(styles) {\n this.styles = styles;\n this.updateStyles();\n }\n updateStyles() {\n if (this.ui) {\n const { quickInputTitleBackground, quickInputBackground, quickInputForeground, contrastBorder, widgetShadow, } = this.styles.widget;\n this.ui.titleBar.style.backgroundColor = quickInputTitleBackground ? quickInputTitleBackground.toString() : '';\n this.ui.container.style.backgroundColor = quickInputBackground ? quickInputBackground.toString() : '';\n this.ui.container.style.color = quickInputForeground ? quickInputForeground.toString() : '';\n this.ui.container.style.border = contrastBorder ? `1px solid ${contrastBorder}` : '';\n this.ui.container.style.boxShadow = widgetShadow ? `0 0 8px 2px ${widgetShadow}` : '';\n this.ui.inputBox.style(this.styles.inputBox);\n this.ui.count.style(this.styles.countBadge);\n this.ui.ok.style(this.styles.button);\n this.ui.customButton.style(this.styles.button);\n this.ui.progressBar.style(this.styles.progressBar);\n this.ui.list.style(this.styles.list);\n const content = [];\n if (this.styles.list.pickerGroupBorder) {\n content.push(`.quick-input-list .quick-input-list-entry { border-top-color: ${this.styles.list.pickerGroupBorder}; }`);\n }\n if (this.styles.list.pickerGroupForeground) {\n content.push(`.quick-input-list .quick-input-list-separator { color: ${this.styles.list.pickerGroupForeground}; }`);\n }\n if (this.styles.keybindingLabel.keybindingLabelBackground ||\n this.styles.keybindingLabel.keybindingLabelBorder ||\n this.styles.keybindingLabel.keybindingLabelBottomBorder ||\n this.styles.keybindingLabel.keybindingLabelShadow ||\n this.styles.keybindingLabel.keybindingLabelForeground) {\n content.push('.quick-input-list .monaco-keybinding > .monaco-keybinding-key {');\n if (this.styles.keybindingLabel.keybindingLabelBackground) {\n content.push(`background-color: ${this.styles.keybindingLabel.keybindingLabelBackground};`);\n }\n if (this.styles.keybindingLabel.keybindingLabelBorder) {\n // Order matters here. `border-color` must come before `border-bottom-color`.\n content.push(`border-color: ${this.styles.keybindingLabel.keybindingLabelBorder};`);\n }\n if (this.styles.keybindingLabel.keybindingLabelBottomBorder) {\n content.push(`border-bottom-color: ${this.styles.keybindingLabel.keybindingLabelBottomBorder};`);\n }\n if (this.styles.keybindingLabel.keybindingLabelShadow) {\n content.push(`box-shadow: inset 0 -1px 0 ${this.styles.keybindingLabel.keybindingLabelShadow};`);\n }\n if (this.styles.keybindingLabel.keybindingLabelForeground) {\n content.push(`color: ${this.styles.keybindingLabel.keybindingLabelForeground};`);\n }\n content.push('}');\n }\n const newStyles = content.join('\\n');\n if (newStyles !== this.ui.styleSheet.textContent) {\n this.ui.styleSheet.textContent = newStyles;\n }\n }\n }\n}\nQuickInputController.MAX_WIDTH = 600; // Max total width of quick input widget\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { DeferredPromise } from '../../../base/common/async.js';\nimport { CancellationTokenSource } from '../../../base/common/cancellation.js';\nimport { once } from '../../../base/common/functional.js';\nimport { Disposable, DisposableStore, toDisposable } from '../../../base/common/lifecycle.js';\nimport { IInstantiationService } from '../../instantiation/common/instantiation.js';\nimport { DefaultQuickAccessFilterValue, Extensions } from '../common/quickAccess.js';\nimport { IQuickInputService, ItemActivation } from '../common/quickInput.js';\nimport { Registry } from '../../registry/common/platform.js';\nlet QuickAccessController = class QuickAccessController extends Disposable {\n constructor(quickInputService, instantiationService) {\n super();\n this.quickInputService = quickInputService;\n this.instantiationService = instantiationService;\n this.registry = Registry.as(Extensions.Quickaccess);\n this.mapProviderToDescriptor = new Map();\n this.lastAcceptedPickerValues = new Map();\n this.visibleQuickAccess = undefined;\n }\n show(value = '', options) {\n this.doShowOrPick(value, false, options);\n }\n doShowOrPick(value, pick, options) {\n var _a;\n // Find provider for the value to show\n const [provider, descriptor] = this.getOrInstantiateProvider(value);\n // Return early if quick access is already showing on that same prefix\n const visibleQuickAccess = this.visibleQuickAccess;\n const visibleDescriptor = visibleQuickAccess === null || visibleQuickAccess === void 0 ? void 0 : visibleQuickAccess.descriptor;\n if (visibleQuickAccess && descriptor && visibleDescriptor === descriptor) {\n // Apply value only if it is more specific than the prefix\n // from the provider and we are not instructed to preserve\n if (value !== descriptor.prefix && !(options === null || options === void 0 ? void 0 : options.preserveValue)) {\n visibleQuickAccess.picker.value = value;\n }\n // Always adjust selection\n this.adjustValueSelection(visibleQuickAccess.picker, descriptor, options);\n return;\n }\n // Rewrite the filter value based on certain rules unless disabled\n if (descriptor && !(options === null || options === void 0 ? void 0 : options.preserveValue)) {\n let newValue = undefined;\n // If we have a visible provider with a value, take it's filter value but\n // rewrite to new provider prefix in case they differ\n if (visibleQuickAccess && visibleDescriptor && visibleDescriptor !== descriptor) {\n const newValueCandidateWithoutPrefix = visibleQuickAccess.value.substr(visibleDescriptor.prefix.length);\n if (newValueCandidateWithoutPrefix) {\n newValue = `${descriptor.prefix}${newValueCandidateWithoutPrefix}`;\n }\n }\n // Otherwise, take a default value as instructed\n if (!newValue) {\n const defaultFilterValue = provider === null || provider === void 0 ? void 0 : provider.defaultFilterValue;\n if (defaultFilterValue === DefaultQuickAccessFilterValue.LAST) {\n newValue = this.lastAcceptedPickerValues.get(descriptor);\n }\n else if (typeof defaultFilterValue === 'string') {\n newValue = `${descriptor.prefix}${defaultFilterValue}`;\n }\n }\n if (typeof newValue === 'string') {\n value = newValue;\n }\n }\n // Create a picker for the provider to use with the initial value\n // and adjust the filtering to exclude the prefix from filtering\n const disposables = new DisposableStore();\n const picker = disposables.add(this.quickInputService.createQuickPick());\n picker.value = value;\n this.adjustValueSelection(picker, descriptor, options);\n picker.placeholder = descriptor === null || descriptor === void 0 ? void 0 : descriptor.placeholder;\n picker.quickNavigate = options === null || options === void 0 ? void 0 : options.quickNavigateConfiguration;\n picker.hideInput = !!picker.quickNavigate && !visibleQuickAccess; // only hide input if there was no picker opened already\n if (typeof (options === null || options === void 0 ? void 0 : options.itemActivation) === 'number' || (options === null || options === void 0 ? void 0 : options.quickNavigateConfiguration)) {\n picker.itemActivation = (_a = options === null || options === void 0 ? void 0 : options.itemActivation) !== null && _a !== void 0 ? _a : ItemActivation.SECOND /* quick nav is always second */;\n }\n picker.contextKey = descriptor === null || descriptor === void 0 ? void 0 : descriptor.contextKey;\n picker.filterValue = (value) => value.substring(descriptor ? descriptor.prefix.length : 0);\n if (descriptor === null || descriptor === void 0 ? void 0 : descriptor.placeholder) {\n picker.ariaLabel = descriptor === null || descriptor === void 0 ? void 0 : descriptor.placeholder;\n }\n // Pick mode: setup a promise that can be resolved\n // with the selected items and prevent execution\n let pickPromise = undefined;\n if (pick) {\n pickPromise = new DeferredPromise();\n disposables.add(once(picker.onWillAccept)(e => {\n e.veto();\n picker.hide();\n }));\n }\n // Register listeners\n disposables.add(this.registerPickerListeners(picker, provider, descriptor, value));\n // Ask provider to fill the picker as needed if we have one\n // and pass over a cancellation token that will indicate when\n // the picker is hiding without a pick being made.\n const cts = disposables.add(new CancellationTokenSource());\n if (provider) {\n disposables.add(provider.provide(picker, cts.token));\n }\n // Finally, trigger disposal and cancellation when the picker\n // hides depending on items selected or not.\n once(picker.onDidHide)(() => {\n if (picker.selectedItems.length === 0) {\n cts.cancel();\n }\n // Start to dispose once picker hides\n disposables.dispose();\n // Resolve pick promise with selected items\n pickPromise === null || pickPromise === void 0 ? void 0 : pickPromise.complete(picker.selectedItems.slice(0));\n });\n // Finally, show the picker. This is important because a provider\n // may not call this and then our disposables would leak that rely\n // on the onDidHide event.\n picker.show();\n // Pick mode: return with promise\n if (pick) {\n return pickPromise === null || pickPromise === void 0 ? void 0 : pickPromise.p;\n }\n }\n adjustValueSelection(picker, descriptor, options) {\n var _a;\n let valueSelection;\n // Preserve: just always put the cursor at the end\n if (options === null || options === void 0 ? void 0 : options.preserveValue) {\n valueSelection = [picker.value.length, picker.value.length];\n }\n // Otherwise: select the value up until the prefix\n else {\n valueSelection = [(_a = descriptor === null || descriptor === void 0 ? void 0 : descriptor.prefix.length) !== null && _a !== void 0 ? _a : 0, picker.value.length];\n }\n picker.valueSelection = valueSelection;\n }\n registerPickerListeners(picker, provider, descriptor, value) {\n const disposables = new DisposableStore();\n // Remember as last visible picker and clean up once picker get's disposed\n const visibleQuickAccess = this.visibleQuickAccess = { picker, descriptor, value };\n disposables.add(toDisposable(() => {\n if (visibleQuickAccess === this.visibleQuickAccess) {\n this.visibleQuickAccess = undefined;\n }\n }));\n // Whenever the value changes, check if the provider has\n // changed and if so - re-create the picker from the beginning\n disposables.add(picker.onDidChangeValue(value => {\n const [providerForValue] = this.getOrInstantiateProvider(value);\n if (providerForValue !== provider) {\n this.show(value, { preserveValue: true } /* do not rewrite value from user typing! */);\n }\n else {\n visibleQuickAccess.value = value; // remember the value in our visible one\n }\n }));\n // Remember picker input for future use when accepting\n if (descriptor) {\n disposables.add(picker.onDidAccept(() => {\n this.lastAcceptedPickerValues.set(descriptor, picker.value);\n }));\n }\n return disposables;\n }\n getOrInstantiateProvider(value) {\n const providerDescriptor = this.registry.getQuickAccessProvider(value);\n if (!providerDescriptor) {\n return [undefined, undefined];\n }\n let provider = this.mapProviderToDescriptor.get(providerDescriptor);\n if (!provider) {\n provider = this.instantiationService.createInstance(providerDescriptor.ctor);\n this.mapProviderToDescriptor.set(providerDescriptor, provider);\n }\n return [provider, providerDescriptor];\n }\n};\nQuickAccessController = __decorate([\n __param(0, IQuickInputService),\n __param(1, IInstantiationService)\n], QuickAccessController);\nexport { QuickAccessController };\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { CancellationToken } from '../../../base/common/cancellation.js';\nimport { QuickInputController } from '../../../base/parts/quickinput/browser/quickInput.js';\nimport { IAccessibilityService } from '../../accessibility/common/accessibility.js';\nimport { IContextKeyService, RawContextKey } from '../../contextkey/common/contextkey.js';\nimport { IInstantiationService } from '../../instantiation/common/instantiation.js';\nimport { ILayoutService } from '../../layout/browser/layoutService.js';\nimport { WorkbenchList } from '../../list/browser/listService.js';\nimport { QuickAccessController } from './quickAccess.js';\nimport { activeContrastBorder, badgeBackground, badgeForeground, buttonBackground, buttonForeground, buttonHoverBackground, contrastBorder, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, keybindingLabelBackground, keybindingLabelBorder, keybindingLabelBottomBorder, keybindingLabelForeground, pickerGroupBorder, pickerGroupForeground, progressBarBackground, quickInputBackground, quickInputForeground, quickInputListFocusBackground, quickInputListFocusForeground, quickInputListFocusIconForeground, quickInputTitleBackground, widgetShadow } from '../../theme/common/colorRegistry.js';\nimport { computeStyles } from '../../theme/common/styler.js';\nimport { IThemeService, Themable } from '../../theme/common/themeService.js';\nlet QuickInputService = class QuickInputService extends Themable {\n constructor(instantiationService, contextKeyService, themeService, accessibilityService, layoutService) {\n super(themeService);\n this.instantiationService = instantiationService;\n this.contextKeyService = contextKeyService;\n this.accessibilityService = accessibilityService;\n this.layoutService = layoutService;\n this.contexts = new Map();\n }\n get controller() {\n if (!this._controller) {\n this._controller = this._register(this.createController());\n }\n return this._controller;\n }\n get quickAccess() {\n if (!this._quickAccess) {\n this._quickAccess = this._register(this.instantiationService.createInstance(QuickAccessController));\n }\n return this._quickAccess;\n }\n createController(host = this.layoutService, options) {\n const defaultOptions = {\n idPrefix: 'quickInput_',\n container: host.container,\n ignoreFocusOut: () => false,\n isScreenReaderOptimized: () => this.accessibilityService.isScreenReaderOptimized(),\n backKeybindingLabel: () => undefined,\n setContextKey: (id) => this.setContextKey(id),\n returnFocus: () => host.focus(),\n createList: (user, container, delegate, renderers, options) => this.instantiationService.createInstance(WorkbenchList, user, container, delegate, renderers, options),\n styles: this.computeStyles()\n };\n const controller = this._register(new QuickInputController(Object.assign(Object.assign({}, defaultOptions), options)));\n controller.layout(host.dimension, host.offset.quickPickTop);\n // Layout changes\n this._register(host.onDidLayout(dimension => controller.layout(dimension, host.offset.quickPickTop)));\n // Context keys\n this._register(controller.onShow(() => this.resetContextKeys()));\n this._register(controller.onHide(() => this.resetContextKeys()));\n return controller;\n }\n setContextKey(id) {\n let key;\n if (id) {\n key = this.contexts.get(id);\n if (!key) {\n key = new RawContextKey(id, false)\n .bindTo(this.contextKeyService);\n this.contexts.set(id, key);\n }\n }\n if (key && key.get()) {\n return; // already active context\n }\n this.resetContextKeys();\n key === null || key === void 0 ? void 0 : key.set(true);\n }\n resetContextKeys() {\n this.contexts.forEach(context => {\n if (context.get()) {\n context.reset();\n }\n });\n }\n pick(picks, options = {}, token = CancellationToken.None) {\n return this.controller.pick(picks, options, token);\n }\n createQuickPick() {\n return this.controller.createQuickPick();\n }\n updateStyles() {\n this.controller.applyStyles(this.computeStyles());\n }\n computeStyles() {\n return {\n widget: Object.assign({}, computeStyles(this.theme, {\n quickInputBackground,\n quickInputForeground,\n quickInputTitleBackground,\n contrastBorder,\n widgetShadow\n })),\n inputBox: computeStyles(this.theme, {\n inputForeground,\n inputBackground,\n inputBorder,\n inputValidationInfoBackground,\n inputValidationInfoForeground,\n inputValidationInfoBorder,\n inputValidationWarningBackground,\n inputValidationWarningForeground,\n inputValidationWarningBorder,\n inputValidationErrorBackground,\n inputValidationErrorForeground,\n inputValidationErrorBorder\n }),\n countBadge: computeStyles(this.theme, {\n badgeBackground,\n badgeForeground,\n badgeBorder: contrastBorder\n }),\n button: computeStyles(this.theme, {\n buttonForeground,\n buttonBackground,\n buttonHoverBackground,\n buttonBorder: contrastBorder\n }),\n progressBar: computeStyles(this.theme, {\n progressBarBackground\n }),\n keybindingLabel: computeStyles(this.theme, {\n keybindingLabelBackground,\n keybindingLabelForeground,\n keybindingLabelBorder,\n keybindingLabelBottomBorder,\n keybindingLabelShadow: widgetShadow\n }),\n list: computeStyles(this.theme, {\n listBackground: quickInputBackground,\n // Look like focused when inactive.\n listInactiveFocusForeground: quickInputListFocusForeground,\n listInactiveSelectionIconForeground: quickInputListFocusIconForeground,\n listInactiveFocusBackground: quickInputListFocusBackground,\n listFocusOutline: activeContrastBorder,\n listInactiveFocusOutline: activeContrastBorder,\n pickerGroupBorder,\n pickerGroupForeground\n })\n };\n }\n};\nQuickInputService = __decorate([\n __param(0, IInstantiationService),\n __param(1, IContextKeyService),\n __param(2, IThemeService),\n __param(3, IAccessibilityService),\n __param(4, ILayoutService)\n], QuickInputService);\nexport { QuickInputService };\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport './standaloneQuickInput.css';\nimport { registerEditorContribution } from '../../../browser/editorExtensions.js';\nimport { IThemeService } from '../../../../platform/theme/common/themeService.js';\nimport { CancellationToken } from '../../../../base/common/cancellation.js';\nimport { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';\nimport { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';\nimport { IAccessibilityService } from '../../../../platform/accessibility/common/accessibility.js';\nimport { EditorScopedLayoutService } from '../standaloneLayoutService.js';\nimport { ICodeEditorService } from '../../../browser/services/codeEditorService.js';\nimport { QuickInputService } from '../../../../platform/quickinput/browser/quickInput.js';\nimport { once } from '../../../../base/common/functional.js';\nlet EditorScopedQuickInputService = class EditorScopedQuickInputService extends QuickInputService {\n constructor(editor, instantiationService, contextKeyService, themeService, accessibilityService, codeEditorService) {\n super(instantiationService, contextKeyService, themeService, accessibilityService, new EditorScopedLayoutService(editor.getContainerDomNode(), codeEditorService));\n this.host = undefined;\n // Use the passed in code editor as host for the quick input widget\n const contribution = QuickInputEditorContribution.get(editor);\n if (contribution) {\n const widget = contribution.widget;\n this.host = {\n _serviceBrand: undefined,\n get hasContainer() { return true; },\n get container() { return widget.getDomNode(); },\n get dimension() { return editor.getLayoutInfo(); },\n get onDidLayout() { return editor.onDidLayoutChange; },\n focus: () => editor.focus(),\n offset: { top: 0, quickPickTop: 0 }\n };\n }\n else {\n this.host = undefined;\n }\n }\n createController() {\n return super.createController(this.host);\n }\n};\nEditorScopedQuickInputService = __decorate([\n __param(1, IInstantiationService),\n __param(2, IContextKeyService),\n __param(3, IThemeService),\n __param(4, IAccessibilityService),\n __param(5, ICodeEditorService)\n], EditorScopedQuickInputService);\nexport { EditorScopedQuickInputService };\nlet StandaloneQuickInputService = class StandaloneQuickInputService {\n constructor(instantiationService, codeEditorService) {\n this.instantiationService = instantiationService;\n this.codeEditorService = codeEditorService;\n this.mapEditorToService = new Map();\n }\n get activeService() {\n const editor = this.codeEditorService.getFocusedCodeEditor();\n if (!editor) {\n throw new Error('Quick input service needs a focused editor to work.');\n }\n // Find the quick input implementation for the focused\n // editor or create it lazily if not yet created\n let quickInputService = this.mapEditorToService.get(editor);\n if (!quickInputService) {\n const newQuickInputService = quickInputService = this.instantiationService.createInstance(EditorScopedQuickInputService, editor);\n this.mapEditorToService.set(editor, quickInputService);\n once(editor.onDidDispose)(() => {\n newQuickInputService.dispose();\n this.mapEditorToService.delete(editor);\n });\n }\n return quickInputService;\n }\n get quickAccess() { return this.activeService.quickAccess; }\n pick(picks, options = {}, token = CancellationToken.None) {\n return this.activeService /* TS fail */.pick(picks, options, token);\n }\n createQuickPick() {\n return this.activeService.createQuickPick();\n }\n};\nStandaloneQuickInputService = __decorate([\n __param(0, IInstantiationService),\n __param(1, ICodeEditorService)\n], StandaloneQuickInputService);\nexport { StandaloneQuickInputService };\nexport class QuickInputEditorContribution {\n constructor(editor) {\n this.editor = editor;\n this.widget = new QuickInputEditorWidget(this.editor);\n }\n static get(editor) {\n return editor.getContribution(QuickInputEditorContribution.ID);\n }\n dispose() {\n this.widget.dispose();\n }\n}\nQuickInputEditorContribution.ID = 'editor.controller.quickInput';\nexport class QuickInputEditorWidget {\n constructor(codeEditor) {\n this.codeEditor = codeEditor;\n this.domNode = document.createElement('div');\n this.codeEditor.addOverlayWidget(this);\n }\n getId() {\n return QuickInputEditorWidget.ID;\n }\n getDomNode() {\n return this.domNode;\n }\n getPosition() {\n return { preference: 2 /* OverlayWidgetPositionPreference.TOP_CENTER */ };\n }\n dispose() {\n this.codeEditor.removeOverlayWidget(this);\n }\n}\nQuickInputEditorWidget.ID = 'editor.contrib.quickInputWidget';\nregisterEditorContribution(QuickInputEditorContribution.ID, QuickInputEditorContribution);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { addDisposableListener } from '../../../base/browser/dom.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from '../common/accessibility.js';\nimport { IConfigurationService } from '../../configuration/common/configuration.js';\nimport { IContextKeyService } from '../../contextkey/common/contextkey.js';\nimport { ILayoutService } from '../../layout/browser/layoutService.js';\nlet AccessibilityService = class AccessibilityService extends Disposable {\n constructor(_contextKeyService, _layoutService, _configurationService) {\n super();\n this._contextKeyService = _contextKeyService;\n this._layoutService = _layoutService;\n this._configurationService = _configurationService;\n this._accessibilitySupport = 0 /* AccessibilitySupport.Unknown */;\n this._onDidChangeScreenReaderOptimized = new Emitter();\n this._onDidChangeReducedMotion = new Emitter();\n this._accessibilityModeEnabledContext = CONTEXT_ACCESSIBILITY_MODE_ENABLED.bindTo(this._contextKeyService);\n const updateContextKey = () => this._accessibilityModeEnabledContext.set(this.isScreenReaderOptimized());\n this._register(this._configurationService.onDidChangeConfiguration(e => {\n if (e.affectsConfiguration('editor.accessibilitySupport')) {\n updateContextKey();\n this._onDidChangeScreenReaderOptimized.fire();\n }\n if (e.affectsConfiguration('workbench.reduceMotion')) {\n this._configMotionReduced = this._configurationService.getValue('workbench.reduceMotion');\n this._onDidChangeReducedMotion.fire();\n }\n }));\n updateContextKey();\n this._register(this.onDidChangeScreenReaderOptimized(() => updateContextKey()));\n const reduceMotionMatcher = window.matchMedia(`(prefers-reduced-motion: reduce)`);\n this._systemMotionReduced = reduceMotionMatcher.matches;\n this._configMotionReduced = this._configurationService.getValue('workbench.reduceMotion');\n this.initReducedMotionListeners(reduceMotionMatcher);\n }\n initReducedMotionListeners(reduceMotionMatcher) {\n if (!this._layoutService.hasContainer) {\n // we can't use `ILayoutService.container` because the application\n // doesn't have a single container\n return;\n }\n this._register(addDisposableListener(reduceMotionMatcher, 'change', () => {\n this._systemMotionReduced = reduceMotionMatcher.matches;\n if (this._configMotionReduced === 'auto') {\n this._onDidChangeReducedMotion.fire();\n }\n }));\n const updateRootClasses = () => {\n const reduce = this.isMotionReduced();\n this._layoutService.container.classList.toggle('reduce-motion', reduce);\n this._layoutService.container.classList.toggle('enable-motion', !reduce);\n };\n updateRootClasses();\n this._register(this.onDidChangeReducedMotion(() => updateRootClasses()));\n }\n get onDidChangeScreenReaderOptimized() {\n return this._onDidChangeScreenReaderOptimized.event;\n }\n isScreenReaderOptimized() {\n const config = this._configurationService.getValue('editor.accessibilitySupport');\n return config === 'on' || (config === 'auto' && this._accessibilitySupport === 2 /* AccessibilitySupport.Enabled */);\n }\n get onDidChangeReducedMotion() {\n return this._onDidChangeReducedMotion.event;\n }\n isMotionReduced() {\n const config = this._configMotionReduced;\n return config === 'on' || (config === 'auto' && this._systemMotionReduced);\n }\n getAccessibilitySupport() {\n return this._accessibilitySupport;\n }\n};\nAccessibilityService = __decorate([\n __param(0, IContextKeyService),\n __param(1, ILayoutService),\n __param(2, IConfigurationService)\n], AccessibilityService);\nexport { AccessibilityService };\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { RunOnceScheduler } from '../../../base/common/async.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { DisposableStore } from '../../../base/common/lifecycle.js';\nimport { IMenuService, isIMenuItem, MenuItemAction, MenuRegistry, SubmenuItemAction } from './actions.js';\nimport { ICommandService } from '../../commands/common/commands.js';\nimport { IContextKeyService } from '../../contextkey/common/contextkey.js';\nimport { toAction } from '../../../base/common/actions.js';\nimport { IStorageService } from '../../storage/common/storage.js';\nimport { removeFastWithoutKeepingOrder } from '../../../base/common/arrays.js';\nimport { localize } from '../../../nls.js';\nlet MenuService = class MenuService {\n constructor(_commandService, storageService) {\n this._commandService = _commandService;\n this._hiddenStates = new PersistedMenuHideState(storageService);\n }\n createMenu(id, contextKeyService, options) {\n return new Menu(id, this._hiddenStates, Object.assign({ emitEventsForSubmenuChanges: false, eventDebounceDelay: 50 }, options), this._commandService, contextKeyService, this);\n }\n};\nMenuService = __decorate([\n __param(0, ICommandService),\n __param(1, IStorageService)\n], MenuService);\nexport { MenuService };\nlet PersistedMenuHideState = class PersistedMenuHideState {\n constructor(_storageService) {\n this._storageService = _storageService;\n this._disposables = new DisposableStore();\n this._onDidChange = new Emitter();\n this.onDidChange = this._onDidChange.event;\n this._ignoreChangeEvent = false;\n try {\n const raw = _storageService.get(PersistedMenuHideState._key, 0 /* StorageScope.PROFILE */, '{}');\n this._data = JSON.parse(raw);\n }\n catch (err) {\n this._data = Object.create(null);\n }\n this._disposables.add(_storageService.onDidChangeValue(e => {\n if (e.key !== PersistedMenuHideState._key) {\n return;\n }\n if (!this._ignoreChangeEvent) {\n try {\n const raw = _storageService.get(PersistedMenuHideState._key, 0 /* StorageScope.PROFILE */, '{}');\n this._data = JSON.parse(raw);\n }\n catch (err) {\n console.log('FAILED to read storage after UPDATE', err);\n }\n }\n this._onDidChange.fire();\n }));\n }\n dispose() {\n this._onDidChange.dispose();\n this._disposables.dispose();\n }\n isHidden(menu, commandId) {\n var _a, _b;\n return (_b = (_a = this._data[menu.id]) === null || _a === void 0 ? void 0 : _a.includes(commandId)) !== null && _b !== void 0 ? _b : false;\n }\n updateHidden(menu, commandId, hidden) {\n const entries = this._data[menu.id];\n if (!hidden) {\n // remove and cleanup\n if (entries) {\n const idx = entries.indexOf(commandId);\n if (idx >= 0) {\n removeFastWithoutKeepingOrder(entries, idx);\n }\n if (entries.length === 0) {\n delete this._data[menu.id];\n }\n }\n }\n else {\n // add unless already added\n if (!entries) {\n this._data[menu.id] = [commandId];\n }\n else {\n const idx = entries.indexOf(commandId);\n if (idx < 0) {\n entries.push(commandId);\n }\n }\n }\n this._persist();\n }\n _persist() {\n try {\n this._ignoreChangeEvent = true;\n const raw = JSON.stringify(this._data);\n this._storageService.store(PersistedMenuHideState._key, raw, 0 /* StorageScope.PROFILE */, 0 /* StorageTarget.USER */);\n }\n finally {\n this._ignoreChangeEvent = false;\n }\n }\n};\nPersistedMenuHideState._key = 'menu.hiddenCommands';\nPersistedMenuHideState = __decorate([\n __param(0, IStorageService)\n], PersistedMenuHideState);\nlet Menu = class Menu {\n constructor(_id, _hiddenStates, _options, _commandService, _contextKeyService, _menuService) {\n this._id = _id;\n this._hiddenStates = _hiddenStates;\n this._options = _options;\n this._commandService = _commandService;\n this._contextKeyService = _contextKeyService;\n this._menuService = _menuService;\n this._disposables = new DisposableStore();\n this._menuGroups = [];\n this._contextKeys = new Set();\n this._build();\n // Rebuild this menu whenever the menu registry reports an event for this MenuId.\n // This usually happen while code and extensions are loaded and affects the over\n // structure of the menu\n const rebuildMenuSoon = new RunOnceScheduler(() => {\n this._build();\n this._onDidChange.fire(this);\n }, _options.eventDebounceDelay);\n this._disposables.add(rebuildMenuSoon);\n this._disposables.add(MenuRegistry.onDidChangeMenu(e => {\n if (e.has(_id)) {\n rebuildMenuSoon.schedule();\n }\n }));\n // When context keys or storage state changes we need to check if the menu also has changed. However,\n // we only do that when someone listens on this menu because (1) these events are\n // firing often and (2) menu are often leaked\n const lazyListener = this._disposables.add(new DisposableStore());\n const startLazyListener = () => {\n const fireChangeSoon = new RunOnceScheduler(() => this._onDidChange.fire(this), _options.eventDebounceDelay);\n lazyListener.add(fireChangeSoon);\n lazyListener.add(_contextKeyService.onDidChangeContext(e => {\n if (e.affectsSome(this._contextKeys)) {\n fireChangeSoon.schedule();\n }\n }));\n lazyListener.add(_hiddenStates.onDidChange(() => {\n fireChangeSoon.schedule();\n }));\n };\n this._onDidChange = new Emitter({\n // start/stop context key listener\n onFirstListenerAdd: startLazyListener,\n onLastListenerRemove: lazyListener.clear.bind(lazyListener)\n });\n this.onDidChange = this._onDidChange.event;\n }\n dispose() {\n this._disposables.dispose();\n this._onDidChange.dispose();\n }\n _build() {\n // reset\n this._menuGroups.length = 0;\n this._contextKeys.clear();\n const menuItems = MenuRegistry.getMenuItems(this._id);\n let group;\n menuItems.sort(Menu._compareMenuItems);\n for (const item of menuItems) {\n // group by groupId\n const groupName = item.group || '';\n if (!group || group[0] !== groupName) {\n group = [groupName, []];\n this._menuGroups.push(group);\n }\n group[1].push(item);\n // keep keys for eventing\n this._collectContextKeys(item);\n }\n }\n _collectContextKeys(item) {\n Menu._fillInKbExprKeys(item.when, this._contextKeys);\n if (isIMenuItem(item)) {\n // keep precondition keys for event if applicable\n if (item.command.precondition) {\n Menu._fillInKbExprKeys(item.command.precondition, this._contextKeys);\n }\n // keep toggled keys for event if applicable\n if (item.command.toggled) {\n const toggledExpression = item.command.toggled.condition || item.command.toggled;\n Menu._fillInKbExprKeys(toggledExpression, this._contextKeys);\n }\n }\n else if (this._options.emitEventsForSubmenuChanges) {\n // recursively collect context keys from submenus so that this\n // menu fires events when context key changes affect submenus\n MenuRegistry.getMenuItems(item.submenu).forEach(this._collectContextKeys, this);\n }\n }\n getActions(options) {\n const result = [];\n const allToggleActions = [];\n for (const group of this._menuGroups) {\n const [id, items] = group;\n const toggleActions = [];\n const activeActions = [];\n for (const item of items) {\n if (this._contextKeyService.contextMatchesRules(item.when)) {\n let action;\n const isMenuItem = isIMenuItem(item);\n if (isMenuItem) {\n const menuHide = createMenuHide(this._id, item.command, this._hiddenStates);\n action = new MenuItemAction(item.command, item.alt, options, menuHide, this._contextKeyService, this._commandService);\n }\n else {\n action = new SubmenuItemAction(item, this._menuService, this._contextKeyService, options);\n if (action.actions.length === 0) {\n action.dispose();\n action = undefined;\n }\n }\n if (action) {\n activeActions.push(action);\n }\n }\n }\n if (activeActions.length > 0) {\n result.push([id, activeActions]);\n }\n if (toggleActions.length > 0) {\n allToggleActions.push(toggleActions);\n }\n }\n return result;\n }\n static _fillInKbExprKeys(exp, set) {\n if (exp) {\n for (const key of exp.keys()) {\n set.add(key);\n }\n }\n }\n static _compareMenuItems(a, b) {\n const aGroup = a.group;\n const bGroup = b.group;\n if (aGroup !== bGroup) {\n // Falsy groups come last\n if (!aGroup) {\n return 1;\n }\n else if (!bGroup) {\n return -1;\n }\n // 'navigation' group comes first\n if (aGroup === 'navigation') {\n return -1;\n }\n else if (bGroup === 'navigation') {\n return 1;\n }\n // lexical sort for groups\n const value = aGroup.localeCompare(bGroup);\n if (value !== 0) {\n return value;\n }\n }\n // sort on priority - default is 0\n const aPrio = a.order || 0;\n const bPrio = b.order || 0;\n if (aPrio < bPrio) {\n return -1;\n }\n else if (aPrio > bPrio) {\n return 1;\n }\n // sort on titles\n return Menu._compareTitles(isIMenuItem(a) ? a.command.title : a.title, isIMenuItem(b) ? b.command.title : b.title);\n }\n static _compareTitles(a, b) {\n const aStr = typeof a === 'string' ? a : a.original;\n const bStr = typeof b === 'string' ? b : b.original;\n return aStr.localeCompare(bStr);\n }\n};\nMenu = __decorate([\n __param(3, ICommandService),\n __param(4, IContextKeyService),\n __param(5, IMenuService)\n], Menu);\nfunction createMenuHide(menu, command, states) {\n const id = `${menu.id}/${command.id}`;\n const title = typeof command.title === 'string' ? command.title : command.title.value;\n const hide = toAction({\n id,\n label: localize('hide.label', 'Hide \\'{0}\\'', title),\n run() { states.updateHidden(menu, command.id, true); }\n });\n const toggle = toAction({\n id,\n label: title,\n get checked() { return !states.isHidden(menu, command.id); },\n run() {\n const newValue = !states.isHidden(menu, command.id);\n states.updateHidden(menu, command.id, newValue);\n }\n });\n return {\n hide,\n toggle,\n get isHidden() { return !toggle.checked; },\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { isSafari, isWebkitWebView } from '../../../base/browser/browser.js';\nimport { $, addDisposableListener } from '../../../base/browser/dom.js';\nimport { DeferredPromise } from '../../../base/common/async.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { ILayoutService } from '../../layout/browser/layoutService.js';\nimport { ILogService } from '../../log/common/log.js';\nlet BrowserClipboardService = class BrowserClipboardService extends Disposable {\n constructor(layoutService, logService) {\n super();\n this.layoutService = layoutService;\n this.logService = logService;\n this.mapTextToType = new Map(); // unsupported in web (only in-memory)\n this.findText = ''; // unsupported in web (only in-memory)\n this.resources = [];\n if (isSafari || isWebkitWebView) {\n this.installWebKitWriteTextWorkaround();\n }\n }\n // In Safari, it has the following note:\n //\n // \"The request to write to the clipboard must be triggered during a user gesture.\n // A call to clipboard.write or clipboard.writeText outside the scope of a user\n // gesture(such as \"click\" or \"touch\" event handlers) will result in the immediate\n // rejection of the promise returned by the API call.\"\n // From: https://webkit.org/blog/10855/async-clipboard-api/\n //\n // Since extensions run in a web worker, and handle gestures in an asynchronous way,\n // they are not classified by Safari as \"in response to a user gesture\" and will reject.\n //\n // This function sets up some handlers to work around that behavior.\n installWebKitWriteTextWorkaround() {\n const handler = () => {\n const currentWritePromise = new DeferredPromise();\n // Cancel the previous promise since we just created a new one in response to this new event\n if (this.webKitPendingClipboardWritePromise && !this.webKitPendingClipboardWritePromise.isSettled) {\n this.webKitPendingClipboardWritePromise.cancel();\n }\n this.webKitPendingClipboardWritePromise = currentWritePromise;\n // The ctor of ClipboardItem allows you to pass in a promise that will resolve to a string.\n // This allows us to pass in a Promise that will either be cancelled by another event or\n // resolved with the contents of the first call to this.writeText.\n // see https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem/ClipboardItem#parameters\n navigator.clipboard.write([new ClipboardItem({\n 'text/plain': currentWritePromise.p,\n })]).catch((err) => __awaiter(this, void 0, void 0, function* () {\n if (!(err instanceof Error) || err.name !== 'NotAllowedError' || !currentWritePromise.isRejected) {\n this.logService.error(err);\n }\n }));\n };\n if (this.layoutService.hasContainer) {\n this._register(addDisposableListener(this.layoutService.container, 'click', handler));\n this._register(addDisposableListener(this.layoutService.container, 'keydown', handler));\n }\n }\n writeText(text, type) {\n return __awaiter(this, void 0, void 0, function* () {\n // With type: only in-memory is supported\n if (type) {\n this.mapTextToType.set(type, text);\n return;\n }\n if (this.webKitPendingClipboardWritePromise) {\n // For Safari, we complete this Promise which allows the call to `navigator.clipboard.write()`\n // above to resolve and successfully copy to the clipboard. If we let this continue, Safari\n // would throw an error because this call stack doesn't appear to originate from a user gesture.\n return this.webKitPendingClipboardWritePromise.complete(text);\n }\n // Guard access to navigator.clipboard with try/catch\n // as we have seen DOMExceptions in certain browsers\n // due to security policies.\n try {\n return yield navigator.clipboard.writeText(text);\n }\n catch (error) {\n console.error(error);\n }\n // Fallback to textarea and execCommand solution\n const activeElement = document.activeElement;\n const textArea = document.body.appendChild($('textarea', { 'aria-hidden': true }));\n textArea.style.height = '1px';\n textArea.style.width = '1px';\n textArea.style.position = 'absolute';\n textArea.value = text;\n textArea.focus();\n textArea.select();\n document.execCommand('copy');\n if (activeElement instanceof HTMLElement) {\n activeElement.focus();\n }\n document.body.removeChild(textArea);\n return;\n });\n }\n readText(type) {\n return __awaiter(this, void 0, void 0, function* () {\n // With type: only in-memory is supported\n if (type) {\n return this.mapTextToType.get(type) || '';\n }\n // Guard access to navigator.clipboard with try/catch\n // as we have seen DOMExceptions in certain browsers\n // due to security policies.\n try {\n return yield navigator.clipboard.readText();\n }\n catch (error) {\n console.error(error);\n return '';\n }\n });\n }\n readFindText() {\n return __awaiter(this, void 0, void 0, function* () {\n return this.findText;\n });\n }\n writeFindText(text) {\n return __awaiter(this, void 0, void 0, function* () {\n this.findText = text;\n });\n }\n readResources() {\n return __awaiter(this, void 0, void 0, function* () {\n return this.resources;\n });\n }\n};\nBrowserClipboardService = __decorate([\n __param(0, ILayoutService),\n __param(1, ILogService)\n], BrowserClipboardService);\nexport { BrowserClipboardService };\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { PauseableEmitter } from '../../../base/common/event.js';\nimport { Iterable } from '../../../base/common/iterator.js';\nimport { DisposableStore, MutableDisposable } from '../../../base/common/lifecycle.js';\nimport { TernarySearchTree } from '../../../base/common/map.js';\nimport { cloneAndChange } from '../../../base/common/objects.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { localize } from '../../../nls.js';\nimport { CommandsRegistry } from '../../commands/common/commands.js';\nimport { IConfigurationService } from '../../configuration/common/configuration.js';\nimport { IContextKeyService, RawContextKey, SET_CONTEXT_COMMAND_ID } from '../common/contextkey.js';\nconst KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context';\nexport class Context {\n constructor(id, parent) {\n this._id = id;\n this._parent = parent;\n this._value = Object.create(null);\n this._value['_contextId'] = id;\n }\n get value() {\n return Object.assign({}, this._value);\n }\n setValue(key, value) {\n // console.log('SET ' + key + ' = ' + value + ' ON ' + this._id);\n if (this._value[key] !== value) {\n this._value[key] = value;\n return true;\n }\n return false;\n }\n removeValue(key) {\n // console.log('REMOVE ' + key + ' FROM ' + this._id);\n if (key in this._value) {\n delete this._value[key];\n return true;\n }\n return false;\n }\n getValue(key) {\n const ret = this._value[key];\n if (typeof ret === 'undefined' && this._parent) {\n return this._parent.getValue(key);\n }\n return ret;\n }\n}\nclass NullContext extends Context {\n constructor() {\n super(-1, null);\n }\n setValue(key, value) {\n return false;\n }\n removeValue(key) {\n return false;\n }\n getValue(key) {\n return undefined;\n }\n}\nNullContext.INSTANCE = new NullContext();\nclass ConfigAwareContextValuesContainer extends Context {\n constructor(id, _configurationService, emitter) {\n super(id, null);\n this._configurationService = _configurationService;\n this._values = TernarySearchTree.forConfigKeys();\n this._listener = this._configurationService.onDidChangeConfiguration(event => {\n if (event.source === 7 /* ConfigurationTarget.DEFAULT */) {\n // new setting, reset everything\n const allKeys = Array.from(Iterable.map(this._values, ([k]) => k));\n this._values.clear();\n emitter.fire(new ArrayContextKeyChangeEvent(allKeys));\n }\n else {\n const changedKeys = [];\n for (const configKey of event.affectedKeys) {\n const contextKey = `config.${configKey}`;\n const cachedItems = this._values.findSuperstr(contextKey);\n if (cachedItems !== undefined) {\n changedKeys.push(...Iterable.map(cachedItems, ([key]) => key));\n this._values.deleteSuperstr(contextKey);\n }\n if (this._values.has(contextKey)) {\n changedKeys.push(contextKey);\n this._values.delete(contextKey);\n }\n }\n emitter.fire(new ArrayContextKeyChangeEvent(changedKeys));\n }\n });\n }\n dispose() {\n this._listener.dispose();\n }\n getValue(key) {\n if (key.indexOf(ConfigAwareContextValuesContainer._keyPrefix) !== 0) {\n return super.getValue(key);\n }\n if (this._values.has(key)) {\n return this._values.get(key);\n }\n const configKey = key.substr(ConfigAwareContextValuesContainer._keyPrefix.length);\n const configValue = this._configurationService.getValue(configKey);\n let value = undefined;\n switch (typeof configValue) {\n case 'number':\n case 'boolean':\n case 'string':\n value = configValue;\n break;\n default:\n if (Array.isArray(configValue)) {\n value = JSON.stringify(configValue);\n }\n else {\n value = configValue;\n }\n }\n this._values.set(key, value);\n return value;\n }\n setValue(key, value) {\n return super.setValue(key, value);\n }\n removeValue(key) {\n return super.removeValue(key);\n }\n}\nConfigAwareContextValuesContainer._keyPrefix = 'config.';\nclass ContextKey {\n constructor(service, key, defaultValue) {\n this._service = service;\n this._key = key;\n this._defaultValue = defaultValue;\n this.reset();\n }\n set(value) {\n this._service.setContext(this._key, value);\n }\n reset() {\n if (typeof this._defaultValue === 'undefined') {\n this._service.removeContext(this._key);\n }\n else {\n this._service.setContext(this._key, this._defaultValue);\n }\n }\n get() {\n return this._service.getContextKeyValue(this._key);\n }\n}\nclass SimpleContextKeyChangeEvent {\n constructor(key) {\n this.key = key;\n }\n affectsSome(keys) {\n return keys.has(this.key);\n }\n allKeysContainedIn(keys) {\n return this.affectsSome(keys);\n }\n}\nclass ArrayContextKeyChangeEvent {\n constructor(keys) {\n this.keys = keys;\n }\n affectsSome(keys) {\n for (const key of this.keys) {\n if (keys.has(key)) {\n return true;\n }\n }\n return false;\n }\n allKeysContainedIn(keys) {\n return this.keys.every(key => keys.has(key));\n }\n}\nclass CompositeContextKeyChangeEvent {\n constructor(events) {\n this.events = events;\n }\n affectsSome(keys) {\n for (const e of this.events) {\n if (e.affectsSome(keys)) {\n return true;\n }\n }\n return false;\n }\n allKeysContainedIn(keys) {\n return this.events.every(evt => evt.allKeysContainedIn(keys));\n }\n}\nfunction allEventKeysInContext(event, context) {\n return event.allKeysContainedIn(new Set(Object.keys(context)));\n}\nexport class AbstractContextKeyService {\n constructor(myContextId) {\n this._onDidChangeContext = new PauseableEmitter({ merge: input => new CompositeContextKeyChangeEvent(input) });\n this.onDidChangeContext = this._onDidChangeContext.event;\n this._isDisposed = false;\n this._myContextId = myContextId;\n }\n createKey(key, defaultValue) {\n if (this._isDisposed) {\n throw new Error(`AbstractContextKeyService has been disposed`);\n }\n return new ContextKey(this, key, defaultValue);\n }\n bufferChangeEvents(callback) {\n this._onDidChangeContext.pause();\n try {\n callback();\n }\n finally {\n this._onDidChangeContext.resume();\n }\n }\n createScoped(domNode) {\n if (this._isDisposed) {\n throw new Error(`AbstractContextKeyService has been disposed`);\n }\n return new ScopedContextKeyService(this, domNode);\n }\n contextMatchesRules(rules) {\n if (this._isDisposed) {\n throw new Error(`AbstractContextKeyService has been disposed`);\n }\n const context = this.getContextValuesContainer(this._myContextId);\n const result = (rules ? rules.evaluate(context) : true);\n // console.group(rules.serialize() + ' -> ' + result);\n // rules.keys().forEach(key => { console.log(key, ctx[key]); });\n // console.groupEnd();\n return result;\n }\n getContextKeyValue(key) {\n if (this._isDisposed) {\n return undefined;\n }\n return this.getContextValuesContainer(this._myContextId).getValue(key);\n }\n setContext(key, value) {\n if (this._isDisposed) {\n return;\n }\n const myContext = this.getContextValuesContainer(this._myContextId);\n if (!myContext) {\n return;\n }\n if (myContext.setValue(key, value)) {\n this._onDidChangeContext.fire(new SimpleContextKeyChangeEvent(key));\n }\n }\n removeContext(key) {\n if (this._isDisposed) {\n return;\n }\n if (this.getContextValuesContainer(this._myContextId).removeValue(key)) {\n this._onDidChangeContext.fire(new SimpleContextKeyChangeEvent(key));\n }\n }\n getContext(target) {\n if (this._isDisposed) {\n return NullContext.INSTANCE;\n }\n return this.getContextValuesContainer(findContextAttr(target));\n }\n}\nlet ContextKeyService = class ContextKeyService extends AbstractContextKeyService {\n constructor(configurationService) {\n super(0);\n this._contexts = new Map();\n this._toDispose = new DisposableStore();\n this._lastContextId = 0;\n const myContext = new ConfigAwareContextValuesContainer(this._myContextId, configurationService, this._onDidChangeContext);\n this._contexts.set(this._myContextId, myContext);\n this._toDispose.add(myContext);\n // Uncomment this to see the contexts continuously logged\n // let lastLoggedValue: string | null = null;\n // setInterval(() => {\n // \tlet values = Object.keys(this._contexts).map((key) => this._contexts[key]);\n // \tlet logValue = values.map(v => JSON.stringify(v._value, null, '\\t')).join('\\n');\n // \tif (lastLoggedValue !== logValue) {\n // \t\tlastLoggedValue = logValue;\n // \t\tconsole.log(lastLoggedValue);\n // \t}\n // }, 2000);\n }\n dispose() {\n this._onDidChangeContext.dispose();\n this._isDisposed = true;\n this._toDispose.dispose();\n }\n getContextValuesContainer(contextId) {\n if (this._isDisposed) {\n return NullContext.INSTANCE;\n }\n return this._contexts.get(contextId) || NullContext.INSTANCE;\n }\n createChildContext(parentContextId = this._myContextId) {\n if (this._isDisposed) {\n throw new Error(`ContextKeyService has been disposed`);\n }\n const id = (++this._lastContextId);\n this._contexts.set(id, new Context(id, this.getContextValuesContainer(parentContextId)));\n return id;\n }\n disposeContext(contextId) {\n if (!this._isDisposed) {\n this._contexts.delete(contextId);\n }\n }\n};\nContextKeyService = __decorate([\n __param(0, IConfigurationService)\n], ContextKeyService);\nexport { ContextKeyService };\nclass ScopedContextKeyService extends AbstractContextKeyService {\n constructor(parent, domNode) {\n super(parent.createChildContext());\n this._parentChangeListener = new MutableDisposable();\n this._parent = parent;\n this._updateParentChangeListener();\n this._domNode = domNode;\n if (this._domNode.hasAttribute(KEYBINDING_CONTEXT_ATTR)) {\n let extraInfo = '';\n if (this._domNode.classList) {\n extraInfo = Array.from(this._domNode.classList.values()).join(', ');\n }\n console.error(`Element already has context attribute${extraInfo ? ': ' + extraInfo : ''}`);\n }\n this._domNode.setAttribute(KEYBINDING_CONTEXT_ATTR, String(this._myContextId));\n }\n _updateParentChangeListener() {\n // Forward parent events to this listener. Parent will change.\n this._parentChangeListener.value = this._parent.onDidChangeContext(e => {\n const thisContainer = this._parent.getContextValuesContainer(this._myContextId);\n const thisContextValues = thisContainer.value;\n if (!allEventKeysInContext(e, thisContextValues)) {\n this._onDidChangeContext.fire(e);\n }\n });\n }\n dispose() {\n if (this._isDisposed) {\n return;\n }\n this._onDidChangeContext.dispose();\n this._parent.disposeContext(this._myContextId);\n this._parentChangeListener.dispose();\n this._domNode.removeAttribute(KEYBINDING_CONTEXT_ATTR);\n this._isDisposed = true;\n }\n getContextValuesContainer(contextId) {\n if (this._isDisposed) {\n return NullContext.INSTANCE;\n }\n return this._parent.getContextValuesContainer(contextId);\n }\n createChildContext(parentContextId = this._myContextId) {\n if (this._isDisposed) {\n throw new Error(`ScopedContextKeyService has been disposed`);\n }\n return this._parent.createChildContext(parentContextId);\n }\n disposeContext(contextId) {\n if (this._isDisposed) {\n return;\n }\n this._parent.disposeContext(contextId);\n }\n}\nfunction findContextAttr(domNode) {\n while (domNode) {\n if (domNode.hasAttribute(KEYBINDING_CONTEXT_ATTR)) {\n const attr = domNode.getAttribute(KEYBINDING_CONTEXT_ATTR);\n if (attr) {\n return parseInt(attr, 10);\n }\n return NaN;\n }\n domNode = domNode.parentElement;\n }\n return 0;\n}\nexport function setContext(accessor, contextKey, contextValue) {\n accessor.get(IContextKeyService).createKey(String(contextKey), stringifyURIs(contextValue));\n}\nfunction stringifyURIs(contextValue) {\n return cloneAndChange(contextValue, (obj) => {\n if (typeof obj === 'object' && obj.$mid === 1 /* MarshalledId.Uri */) {\n return URI.revive(obj).toString();\n }\n if (obj instanceof URI) {\n return obj.toString();\n }\n return undefined;\n });\n}\nCommandsRegistry.registerCommand(SET_CONTEXT_COMMAND_ID, setContext);\nCommandsRegistry.registerCommand({\n id: 'getContextKeyInfo',\n handler() {\n return [...RawContextKey.all()].sort((a, b) => a.key.localeCompare(b.key));\n },\n description: {\n description: localize('getContextKeyInfo', \"A command that returns information about context keys\"),\n args: []\n }\n});\nCommandsRegistry.registerCommand('_generateContextKeyInfo', function () {\n const result = [];\n const seen = new Set();\n for (const info of RawContextKey.all()) {\n if (!seen.has(info.key)) {\n seen.add(info.key);\n result.push(info);\n }\n }\n result.sort((a, b) => a.key.localeCompare(b.key));\n console.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 *--------------------------------------------------------------------------------------------*/\nexport class Node {\n constructor(data) {\n this.incoming = new Map();\n this.outgoing = new Map();\n this.data = data;\n }\n}\nexport class Graph {\n constructor(_hashFn) {\n this._hashFn = _hashFn;\n this._nodes = new Map();\n // empty\n }\n roots() {\n const ret = [];\n for (const node of this._nodes.values()) {\n if (node.outgoing.size === 0) {\n ret.push(node);\n }\n }\n return ret;\n }\n insertEdge(from, to) {\n const fromNode = this.lookupOrInsertNode(from);\n const toNode = this.lookupOrInsertNode(to);\n fromNode.outgoing.set(this._hashFn(to), toNode);\n toNode.incoming.set(this._hashFn(from), fromNode);\n }\n removeNode(data) {\n const key = this._hashFn(data);\n this._nodes.delete(key);\n for (const node of this._nodes.values()) {\n node.outgoing.delete(key);\n node.incoming.delete(key);\n }\n }\n lookupOrInsertNode(data) {\n const key = this._hashFn(data);\n let node = this._nodes.get(key);\n if (!node) {\n node = new Node(data);\n this._nodes.set(key, node);\n }\n return node;\n }\n isEmpty() {\n return this._nodes.size === 0;\n }\n toString() {\n const data = [];\n for (const [key, value] of this._nodes) {\n data.push(`${key}, (incoming)[${[...value.incoming.keys()].join(', ')}], (outgoing)[${[...value.outgoing.keys()].join(',')}]`);\n }\n return data.join('\\n');\n }\n /**\n * This is brute force and slow and **only** be used\n * to trouble shoot.\n */\n findCycleSlow() {\n for (const [id, node] of this._nodes) {\n const seen = new Set([id]);\n const res = this._findCycle(node, seen);\n if (res) {\n return res;\n }\n }\n return undefined;\n }\n _findCycle(node, seen) {\n for (const [id, outgoing] of node.outgoing) {\n if (seen.has(id)) {\n return [...seen, id].join(' -> ');\n }\n seen.add(id);\n const value = this._findCycle(outgoing, seen);\n if (value) {\n return value;\n }\n seen.delete(id);\n }\n return undefined;\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 *--------------------------------------------------------------------------------------------*/\nimport { IdleValue } from '../../../base/common/async.js';\nimport { illegalState } from '../../../base/common/errors.js';\nimport { SyncDescriptor } from './descriptors.js';\nimport { Graph } from './graph.js';\nimport { IInstantiationService, _util } from './instantiation.js';\nimport { ServiceCollection } from './serviceCollection.js';\n// TRACING\nconst _enableTracing = false;\nclass CyclicDependencyError extends Error {\n constructor(graph) {\n var _a;\n super('cyclic dependency between services');\n this.message = (_a = graph.findCycleSlow()) !== null && _a !== void 0 ? _a : `UNABLE to detect cycle, dumping graph: \\n${graph.toString()}`;\n }\n}\nexport class InstantiationService {\n constructor(services = new ServiceCollection(), strict = false, parent) {\n this._activeInstantiations = new Set();\n this._services = services;\n this._strict = strict;\n this._parent = parent;\n this._services.set(IInstantiationService, this);\n }\n createChild(services) {\n return new InstantiationService(services, this._strict, this);\n }\n invokeFunction(fn, ...args) {\n const _trace = Trace.traceInvocation(fn);\n let _done = false;\n try {\n const accessor = {\n get: (id) => {\n if (_done) {\n throw illegalState('service accessor is only valid during the invocation of its target method');\n }\n const result = this._getOrCreateServiceInstance(id, _trace);\n if (!result) {\n throw new Error(`[invokeFunction] unknown service '${id}'`);\n }\n return result;\n }\n };\n return fn(accessor, ...args);\n }\n finally {\n _done = true;\n _trace.stop();\n }\n }\n createInstance(ctorOrDescriptor, ...rest) {\n let _trace;\n let result;\n if (ctorOrDescriptor instanceof SyncDescriptor) {\n _trace = Trace.traceCreation(ctorOrDescriptor.ctor);\n result = this._createInstance(ctorOrDescriptor.ctor, ctorOrDescriptor.staticArguments.concat(rest), _trace);\n }\n else {\n _trace = Trace.traceCreation(ctorOrDescriptor);\n result = this._createInstance(ctorOrDescriptor, rest, _trace);\n }\n _trace.stop();\n return result;\n }\n _createInstance(ctor, args = [], _trace) {\n // arguments defined by service decorators\n const serviceDependencies = _util.getServiceDependencies(ctor).sort((a, b) => a.index - b.index);\n const serviceArgs = [];\n for (const dependency of serviceDependencies) {\n const service = this._getOrCreateServiceInstance(dependency.id, _trace);\n if (!service) {\n this._throwIfStrict(`[createInstance] ${ctor.name} depends on UNKNOWN service ${dependency.id}.`, false);\n }\n serviceArgs.push(service);\n }\n const firstServiceArgPos = serviceDependencies.length > 0 ? serviceDependencies[0].index : args.length;\n // check for argument mismatches, adjust static args if needed\n if (args.length !== firstServiceArgPos) {\n console.trace(`[createInstance] First service dependency of ${ctor.name} at position ${firstServiceArgPos + 1} conflicts with ${args.length} static arguments`);\n const delta = firstServiceArgPos - args.length;\n if (delta > 0) {\n args = args.concat(new Array(delta));\n }\n else {\n args = args.slice(0, firstServiceArgPos);\n }\n }\n // now create the instance\n return new ctor(...[...args, ...serviceArgs]);\n }\n _setServiceInstance(id, instance) {\n if (this._services.get(id) instanceof SyncDescriptor) {\n this._services.set(id, instance);\n }\n else if (this._parent) {\n this._parent._setServiceInstance(id, instance);\n }\n else {\n throw new Error('illegalState - setting UNKNOWN service instance');\n }\n }\n _getServiceInstanceOrDescriptor(id) {\n const instanceOrDesc = this._services.get(id);\n if (!instanceOrDesc && this._parent) {\n return this._parent._getServiceInstanceOrDescriptor(id);\n }\n else {\n return instanceOrDesc;\n }\n }\n _getOrCreateServiceInstance(id, _trace) {\n const thing = this._getServiceInstanceOrDescriptor(id);\n if (thing instanceof SyncDescriptor) {\n return this._safeCreateAndCacheServiceInstance(id, thing, _trace.branch(id, true));\n }\n else {\n _trace.branch(id, false);\n return thing;\n }\n }\n _safeCreateAndCacheServiceInstance(id, desc, _trace) {\n if (this._activeInstantiations.has(id)) {\n throw new Error(`illegal state - RECURSIVELY instantiating service '${id}'`);\n }\n this._activeInstantiations.add(id);\n try {\n return this._createAndCacheServiceInstance(id, desc, _trace);\n }\n finally {\n this._activeInstantiations.delete(id);\n }\n }\n _createAndCacheServiceInstance(id, desc, _trace) {\n const graph = new Graph(data => data.id.toString());\n let cycleCount = 0;\n const stack = [{ id, desc, _trace }];\n while (stack.length) {\n const item = stack.pop();\n graph.lookupOrInsertNode(item);\n // a weak but working heuristic for cycle checks\n if (cycleCount++ > 1000) {\n throw new CyclicDependencyError(graph);\n }\n // check all dependencies for existence and if they need to be created first\n for (const dependency of _util.getServiceDependencies(item.desc.ctor)) {\n const instanceOrDesc = this._getServiceInstanceOrDescriptor(dependency.id);\n if (!instanceOrDesc) {\n this._throwIfStrict(`[createInstance] ${id} depends on ${dependency.id} which is NOT registered.`, true);\n }\n if (instanceOrDesc instanceof SyncDescriptor) {\n const d = { id: dependency.id, desc: instanceOrDesc, _trace: item._trace.branch(dependency.id, true) };\n graph.insertEdge(item, d);\n stack.push(d);\n }\n }\n }\n while (true) {\n const roots = graph.roots();\n // if there is no more roots but still\n // nodes in the graph we have a cycle\n if (roots.length === 0) {\n if (!graph.isEmpty()) {\n throw new CyclicDependencyError(graph);\n }\n break;\n }\n for (const { data } of roots) {\n // Repeat the check for this still being a service sync descriptor. That's because\n // instantiating a dependency might have side-effect and recursively trigger instantiation\n // so that some dependencies are now fullfilled already.\n const instanceOrDesc = this._getServiceInstanceOrDescriptor(data.id);\n if (instanceOrDesc instanceof SyncDescriptor) {\n // create instance and overwrite the service collections\n const instance = this._createServiceInstanceWithOwner(data.id, data.desc.ctor, data.desc.staticArguments, data.desc.supportsDelayedInstantiation, data._trace);\n this._setServiceInstance(data.id, instance);\n }\n graph.removeNode(data);\n }\n }\n return this._getServiceInstanceOrDescriptor(id);\n }\n _createServiceInstanceWithOwner(id, ctor, args = [], supportsDelayedInstantiation, _trace) {\n if (this._services.get(id) instanceof SyncDescriptor) {\n return this._createServiceInstance(ctor, args, supportsDelayedInstantiation, _trace);\n }\n else if (this._parent) {\n return this._parent._createServiceInstanceWithOwner(id, ctor, args, supportsDelayedInstantiation, _trace);\n }\n else {\n throw new Error(`illegalState - creating UNKNOWN service instance ${ctor.name}`);\n }\n }\n _createServiceInstance(ctor, args = [], _supportsDelayedInstantiation, _trace) {\n if (!_supportsDelayedInstantiation) {\n // eager instantiation\n return this._createInstance(ctor, args, _trace);\n }\n else {\n // Return a proxy object that's backed by an idle value. That\n // strategy is to instantiate services in our idle time or when actually\n // needed but not when injected into a consumer\n const idle = new IdleValue(() => this._createInstance(ctor, args, _trace));\n return new Proxy(Object.create(null), {\n get(target, key) {\n if (key in target) {\n return target[key];\n }\n const obj = idle.value;\n let prop = obj[key];\n if (typeof prop !== 'function') {\n return prop;\n }\n prop = prop.bind(obj);\n target[key] = prop;\n return prop;\n },\n set(_target, p, value) {\n idle.value[p] = value;\n return true;\n }\n });\n }\n }\n _throwIfStrict(msg, printWarning) {\n if (printWarning) {\n console.warn(msg);\n }\n if (this._strict) {\n throw new Error(msg);\n }\n }\n}\nexport class Trace {\n constructor(type, name) {\n this.type = type;\n this.name = name;\n this._start = Date.now();\n this._dep = [];\n }\n static traceInvocation(ctor) {\n return !_enableTracing ? Trace._None : new Trace(1 /* TraceType.Invocation */, ctor.name || ctor.toString().substring(0, 42).replace(/\\n/g, ''));\n }\n static traceCreation(ctor) {\n return !_enableTracing ? Trace._None : new Trace(0 /* TraceType.Creation */, ctor.name);\n }\n branch(id, first) {\n const child = new Trace(2 /* TraceType.Branch */, id.toString());\n this._dep.push([id, first, child]);\n return child;\n }\n stop() {\n const dur = Date.now() - this._start;\n Trace._totals += dur;\n let causedCreation = false;\n function printChild(n, trace) {\n const res = [];\n const prefix = new Array(n + 1).join('\\t');\n for (const [id, first, child] of trace._dep) {\n if (first && child) {\n causedCreation = true;\n res.push(`${prefix}CREATES -> ${id}`);\n const nested = printChild(n + 1, child);\n if (nested) {\n res.push(nested);\n }\n }\n else {\n res.push(`${prefix}uses -> ${id}`);\n }\n }\n return res.join('\\n');\n }\n const lines = [\n `${this.type === 0 /* TraceType.Creation */ ? 'CREATE' : 'CALL'} ${this.name}`,\n `${printChild(1, this)}`,\n `DONE, took ${dur.toFixed(2)}ms (grand total ${Trace._totals.toFixed(2)}ms)`\n ];\n if (dur > 2 || causedCreation) {\n console.log(lines.join('\\n'));\n }\n }\n}\nTrace._None = new class extends Trace {\n constructor() { super(-1, null); }\n stop() { }\n branch() { return this; }\n};\nTrace._totals = 0;\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 *--------------------------------------------------------------------------------------------*/\nimport { isFalsyOrEmpty, isNonEmptyArray } from '../../../base/common/arrays.js';\nimport { DebounceEmitter } from '../../../base/common/event.js';\nimport { Iterable } from '../../../base/common/iterator.js';\nimport { ResourceMap } from '../../../base/common/map.js';\nimport { Schemas } from '../../../base/common/network.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { MarkerSeverity } from './markers.js';\nclass DoubleResourceMap {\n constructor() {\n this._byResource = new ResourceMap();\n this._byOwner = new Map();\n }\n set(resource, owner, value) {\n let ownerMap = this._byResource.get(resource);\n if (!ownerMap) {\n ownerMap = new Map();\n this._byResource.set(resource, ownerMap);\n }\n ownerMap.set(owner, value);\n let resourceMap = this._byOwner.get(owner);\n if (!resourceMap) {\n resourceMap = new ResourceMap();\n this._byOwner.set(owner, resourceMap);\n }\n resourceMap.set(resource, value);\n }\n get(resource, owner) {\n const ownerMap = this._byResource.get(resource);\n return ownerMap === null || ownerMap === void 0 ? void 0 : ownerMap.get(owner);\n }\n delete(resource, owner) {\n let removedA = false;\n let removedB = false;\n const ownerMap = this._byResource.get(resource);\n if (ownerMap) {\n removedA = ownerMap.delete(owner);\n }\n const resourceMap = this._byOwner.get(owner);\n if (resourceMap) {\n removedB = resourceMap.delete(resource);\n }\n if (removedA !== removedB) {\n throw new Error('illegal state');\n }\n return removedA && removedB;\n }\n values(key) {\n var _a, _b, _c, _d;\n if (typeof key === 'string') {\n return (_b = (_a = this._byOwner.get(key)) === null || _a === void 0 ? void 0 : _a.values()) !== null && _b !== void 0 ? _b : Iterable.empty();\n }\n if (URI.isUri(key)) {\n return (_d = (_c = this._byResource.get(key)) === null || _c === void 0 ? void 0 : _c.values()) !== null && _d !== void 0 ? _d : Iterable.empty();\n }\n return Iterable.map(Iterable.concat(...this._byOwner.values()), map => map[1]);\n }\n}\nclass MarkerStats {\n constructor(service) {\n this.errors = 0;\n this.infos = 0;\n this.warnings = 0;\n this.unknowns = 0;\n this._data = new ResourceMap();\n this._service = service;\n this._subscription = service.onMarkerChanged(this._update, this);\n }\n dispose() {\n this._subscription.dispose();\n }\n _update(resources) {\n for (const resource of resources) {\n const oldStats = this._data.get(resource);\n if (oldStats) {\n this._substract(oldStats);\n }\n const newStats = this._resourceStats(resource);\n this._add(newStats);\n this._data.set(resource, newStats);\n }\n }\n _resourceStats(resource) {\n const result = { errors: 0, warnings: 0, infos: 0, unknowns: 0 };\n // TODO this is a hack\n if (resource.scheme === Schemas.inMemory || resource.scheme === Schemas.walkThrough || resource.scheme === Schemas.walkThroughSnippet || resource.scheme === Schemas.vscodeSourceControl) {\n return result;\n }\n for (const { severity } of this._service.read({ resource })) {\n if (severity === MarkerSeverity.Error) {\n result.errors += 1;\n }\n else if (severity === MarkerSeverity.Warning) {\n result.warnings += 1;\n }\n else if (severity === MarkerSeverity.Info) {\n result.infos += 1;\n }\n else {\n result.unknowns += 1;\n }\n }\n return result;\n }\n _substract(op) {\n this.errors -= op.errors;\n this.warnings -= op.warnings;\n this.infos -= op.infos;\n this.unknowns -= op.unknowns;\n }\n _add(op) {\n this.errors += op.errors;\n this.warnings += op.warnings;\n this.infos += op.infos;\n this.unknowns += op.unknowns;\n }\n}\nexport class MarkerService {\n constructor() {\n this._onMarkerChanged = new DebounceEmitter({\n delay: 0,\n merge: MarkerService._merge\n });\n this.onMarkerChanged = this._onMarkerChanged.event;\n this._data = new DoubleResourceMap();\n this._stats = new MarkerStats(this);\n }\n dispose() {\n this._stats.dispose();\n this._onMarkerChanged.dispose();\n }\n remove(owner, resources) {\n for (const resource of resources || []) {\n this.changeOne(owner, resource, []);\n }\n }\n changeOne(owner, resource, markerData) {\n if (isFalsyOrEmpty(markerData)) {\n // remove marker for this (owner,resource)-tuple\n const removed = this._data.delete(resource, owner);\n if (removed) {\n this._onMarkerChanged.fire([resource]);\n }\n }\n else {\n // insert marker for this (owner,resource)-tuple\n const markers = [];\n for (const data of markerData) {\n const marker = MarkerService._toMarker(owner, resource, data);\n if (marker) {\n markers.push(marker);\n }\n }\n this._data.set(resource, owner, markers);\n this._onMarkerChanged.fire([resource]);\n }\n }\n static _toMarker(owner, resource, data) {\n let { code, severity, message, source, startLineNumber, startColumn, endLineNumber, endColumn, relatedInformation, tags, } = data;\n if (!message) {\n return undefined;\n }\n // santize data\n startLineNumber = startLineNumber > 0 ? startLineNumber : 1;\n startColumn = startColumn > 0 ? startColumn : 1;\n endLineNumber = endLineNumber >= startLineNumber ? endLineNumber : startLineNumber;\n endColumn = endColumn > 0 ? endColumn : startColumn;\n return {\n resource,\n owner,\n code,\n severity,\n message,\n source,\n startLineNumber,\n startColumn,\n endLineNumber,\n endColumn,\n relatedInformation,\n tags,\n };\n }\n changeAll(owner, data) {\n const changes = [];\n // remove old marker\n const existing = this._data.values(owner);\n if (existing) {\n for (const data of existing) {\n const first = Iterable.first(data);\n if (first) {\n changes.push(first.resource);\n this._data.delete(first.resource, owner);\n }\n }\n }\n // add new markers\n if (isNonEmptyArray(data)) {\n // group by resource\n const groups = new ResourceMap();\n for (const { resource, marker: markerData } of data) {\n const marker = MarkerService._toMarker(owner, resource, markerData);\n if (!marker) {\n // filter bad markers\n continue;\n }\n const array = groups.get(resource);\n if (!array) {\n groups.set(resource, [marker]);\n changes.push(resource);\n }\n else {\n array.push(marker);\n }\n }\n // insert all\n for (const [resource, value] of groups) {\n this._data.set(resource, owner, value);\n }\n }\n if (changes.length > 0) {\n this._onMarkerChanged.fire(changes);\n }\n }\n read(filter = Object.create(null)) {\n let { owner, resource, severities, take } = filter;\n if (!take || take < 0) {\n take = -1;\n }\n if (owner && resource) {\n // exactly one owner AND resource\n const data = this._data.get(resource, owner);\n if (!data) {\n return [];\n }\n else {\n const result = [];\n for (const marker of data) {\n if (MarkerService._accept(marker, severities)) {\n const newLen = result.push(marker);\n if (take > 0 && newLen === take) {\n break;\n }\n }\n }\n return result;\n }\n }\n else if (!owner && !resource) {\n // all\n const result = [];\n for (const markers of this._data.values()) {\n for (const data of markers) {\n if (MarkerService._accept(data, severities)) {\n const newLen = result.push(data);\n if (take > 0 && newLen === take) {\n return result;\n }\n }\n }\n }\n return result;\n }\n else {\n // of one resource OR owner\n const iterable = this._data.values(resource !== null && resource !== void 0 ? resource : owner);\n const result = [];\n for (const markers of iterable) {\n for (const data of markers) {\n if (MarkerService._accept(data, severities)) {\n const newLen = result.push(data);\n if (take > 0 && newLen === take) {\n return result;\n }\n }\n }\n }\n return result;\n }\n }\n static _accept(marker, severities) {\n return severities === undefined || (severities & marker.severity) === marker.severity;\n }\n // --- event debounce logic\n static _merge(all) {\n const set = new ResourceMap();\n for (const array of all) {\n for (const item of array) {\n set.set(item, true);\n }\n }\n return Array.from(set.keys());\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 *--------------------------------------------------------------------------------------------*/\nimport { match as matchGlobPattern } from '../../base/common/glob.js';\nimport { normalize } from '../../base/common/path.js';\nexport function score(selector, candidateUri, candidateLanguage, candidateIsSynchronized, candidateNotebookUri, candidateNotebookType) {\n if (Array.isArray(selector)) {\n // array -> take max individual value\n let ret = 0;\n for (const filter of selector) {\n const value = score(filter, candidateUri, candidateLanguage, candidateIsSynchronized, candidateNotebookUri, candidateNotebookType);\n if (value === 10) {\n return value; // already at the highest\n }\n if (value > ret) {\n ret = value;\n }\n }\n return ret;\n }\n else if (typeof selector === 'string') {\n if (!candidateIsSynchronized) {\n return 0;\n }\n // short-hand notion, desugars to\n // 'fooLang' -> { language: 'fooLang'}\n // '*' -> { language: '*' }\n if (selector === '*') {\n return 5;\n }\n else if (selector === candidateLanguage) {\n return 10;\n }\n else {\n return 0;\n }\n }\n else if (selector) {\n // filter -> select accordingly, use defaults for scheme\n const { language, pattern, scheme, hasAccessToAllModels, notebookType } = selector; // TODO: microsoft/TypeScript#42768\n if (!candidateIsSynchronized && !hasAccessToAllModels) {\n return 0;\n }\n // selector targets a notebook -> use the notebook uri instead\n // of the \"normal\" document uri.\n if (notebookType && candidateNotebookUri) {\n candidateUri = candidateNotebookUri;\n }\n let ret = 0;\n if (scheme) {\n if (scheme === candidateUri.scheme) {\n ret = 10;\n }\n else if (scheme === '*') {\n ret = 5;\n }\n else {\n return 0;\n }\n }\n if (language) {\n if (language === candidateLanguage) {\n ret = 10;\n }\n else if (language === '*') {\n ret = Math.max(ret, 5);\n }\n else {\n return 0;\n }\n }\n if (notebookType) {\n if (notebookType === candidateNotebookType) {\n ret = 10;\n }\n else if (notebookType === '*' && candidateNotebookType !== undefined) {\n ret = Math.max(ret, 5);\n }\n else {\n return 0;\n }\n }\n if (pattern) {\n let normalizedPattern;\n if (typeof pattern === 'string') {\n normalizedPattern = pattern;\n }\n else {\n // Since this pattern has a `base` property, we need\n // to normalize this path first before passing it on\n // because we will compare it against `Uri.fsPath`\n // which uses platform specific separators.\n // Refs: https://github.com/microsoft/vscode/issues/99938\n normalizedPattern = Object.assign(Object.assign({}, pattern), { base: normalize(pattern.base) });\n }\n if (normalizedPattern === candidateUri.fsPath || matchGlobPattern(normalizedPattern, candidateUri.fsPath)) {\n ret = 10;\n }\n else {\n return 0;\n }\n }\n return ret;\n }\n else {\n return 0;\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 *--------------------------------------------------------------------------------------------*/\nimport { Emitter } from '../../base/common/event.js';\nimport { toDisposable } from '../../base/common/lifecycle.js';\nimport { shouldSynchronizeModel } from './model.js';\nimport { score } from './languageSelector.js';\nfunction isExclusive(selector) {\n if (typeof selector === 'string') {\n return false;\n }\n else if (Array.isArray(selector)) {\n return selector.every(isExclusive);\n }\n else {\n return !!selector.exclusive; // TODO: microsoft/TypeScript#42768\n }\n}\nclass MatchCandidate {\n constructor(uri, languageId, notebookUri, notebookType) {\n this.uri = uri;\n this.languageId = languageId;\n this.notebookUri = notebookUri;\n this.notebookType = notebookType;\n }\n equals(other) {\n var _a, _b;\n return this.notebookType === other.notebookType\n && this.languageId === other.languageId\n && this.uri.toString() === other.uri.toString()\n && ((_a = this.notebookUri) === null || _a === void 0 ? void 0 : _a.toString()) === ((_b = other.notebookUri) === null || _b === void 0 ? void 0 : _b.toString());\n }\n}\nexport class LanguageFeatureRegistry {\n constructor(_notebookInfoResolver) {\n this._notebookInfoResolver = _notebookInfoResolver;\n this._clock = 0;\n this._entries = [];\n this._onDidChange = new Emitter();\n this.onDidChange = this._onDidChange.event;\n }\n register(selector, provider) {\n let entry = {\n selector,\n provider,\n _score: -1,\n _time: this._clock++\n };\n this._entries.push(entry);\n this._lastCandidate = undefined;\n this._onDidChange.fire(this._entries.length);\n return toDisposable(() => {\n if (entry) {\n const idx = this._entries.indexOf(entry);\n if (idx >= 0) {\n this._entries.splice(idx, 1);\n this._lastCandidate = undefined;\n this._onDidChange.fire(this._entries.length);\n entry = undefined;\n }\n }\n });\n }\n has(model) {\n return this.all(model).length > 0;\n }\n all(model) {\n if (!model) {\n return [];\n }\n this._updateScores(model);\n const result = [];\n // from registry\n for (const entry of this._entries) {\n if (entry._score > 0) {\n result.push(entry.provider);\n }\n }\n return result;\n }\n ordered(model) {\n const result = [];\n this._orderedForEach(model, entry => result.push(entry.provider));\n return result;\n }\n orderedGroups(model) {\n const result = [];\n let lastBucket;\n let lastBucketScore;\n this._orderedForEach(model, entry => {\n if (lastBucket && lastBucketScore === entry._score) {\n lastBucket.push(entry.provider);\n }\n else {\n lastBucketScore = entry._score;\n lastBucket = [entry.provider];\n result.push(lastBucket);\n }\n });\n return result;\n }\n _orderedForEach(model, callback) {\n this._updateScores(model);\n for (const entry of this._entries) {\n if (entry._score > 0) {\n callback(entry);\n }\n }\n }\n _updateScores(model) {\n var _a, _b;\n const notebookInfo = (_a = this._notebookInfoResolver) === null || _a === void 0 ? void 0 : _a.call(this, model.uri);\n // use the uri (scheme, pattern) of the notebook info iff we have one\n // otherwise it's the model's/document's uri\n const candidate = notebookInfo\n ? new MatchCandidate(model.uri, model.getLanguageId(), notebookInfo.uri, notebookInfo.type)\n : new MatchCandidate(model.uri, model.getLanguageId(), undefined, undefined);\n if ((_b = this._lastCandidate) === null || _b === void 0 ? void 0 : _b.equals(candidate)) {\n // nothing has changed\n return;\n }\n this._lastCandidate = candidate;\n for (const entry of this._entries) {\n entry._score = score(entry.selector, candidate.uri, candidate.languageId, shouldSynchronizeModel(model), candidate.notebookUri, candidate.notebookType);\n if (isExclusive(entry.selector) && entry._score > 0) {\n // support for one exclusive selector that overwrites\n // any other selector\n for (const entry of this._entries) {\n entry._score = 0;\n }\n entry._score = 1000;\n break;\n }\n }\n // needs sorting\n this._entries.sort(LanguageFeatureRegistry._compareByScoreAndTime);\n }\n static _compareByScoreAndTime(a, b) {\n if (a._score < b._score) {\n return 1;\n }\n else if (a._score > b._score) {\n return -1;\n }\n else if (a._time < b._time) {\n return 1;\n }\n else if (a._time > b._time) {\n return -1;\n }\n else {\n return 0;\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 *--------------------------------------------------------------------------------------------*/\nimport { LanguageFeatureRegistry } from '../languageFeatureRegistry.js';\nimport { ILanguageFeaturesService } from './languageFeatures.js';\nimport { registerSingleton } from '../../../platform/instantiation/common/extensions.js';\nexport class LanguageFeaturesService {\n constructor() {\n this.referenceProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.renameProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.codeActionProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.definitionProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.typeDefinitionProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.declarationProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.implementationProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.documentSymbolProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.inlayHintsProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.colorProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.codeLensProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.documentFormattingEditProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.documentRangeFormattingEditProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.onTypeFormattingEditProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.signatureHelpProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.hoverProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.documentHighlightProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.selectionRangeProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.foldingRangeProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.linkProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.inlineCompletionsProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.completionProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.linkedEditingRangeProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.documentRangeSemanticTokensProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.documentSemanticTokensProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.documentOnDropEditProvider = new LanguageFeatureRegistry(this._score.bind(this));\n this.documentPasteEditProvider = new LanguageFeatureRegistry(this._score.bind(this));\n }\n _score(uri) {\n var _a;\n return (_a = this._notebookTypeResolver) === null || _a === void 0 ? void 0 : _a.call(this, uri);\n }\n}\nregisterSingleton(ILanguageFeaturesService, LanguageFeaturesService, true);\n","import { addToValueTree, toValuesTree } from './configuration.js';\nimport { ConfigurationModel } from './configurationModels.js';\nimport { Extensions, overrideIdentifiersFromKey, OVERRIDE_PROPERTY_REGEX } from './configurationRegistry.js';\nimport { Registry } from '../../registry/common/platform.js';\nexport class DefaultConfigurationModel extends ConfigurationModel {\n constructor(configurationDefaultsOverrides = {}) {\n const properties = Registry.as(Extensions.Configuration).getConfigurationProperties();\n const keys = Object.keys(properties);\n const contents = Object.create(null);\n const overrides = [];\n for (const key in properties) {\n const defaultOverrideValue = configurationDefaultsOverrides[key];\n const value = defaultOverrideValue !== undefined ? defaultOverrideValue : properties[key].default;\n addToValueTree(contents, key, value, message => console.error(`Conflict in default settings: ${message}`));\n }\n for (const key of Object.keys(contents)) {\n if (OVERRIDE_PROPERTY_REGEX.test(key)) {\n overrides.push({\n identifiers: overrideIdentifiersFromKey(key),\n keys: Object.keys(contents[key]),\n contents: toValuesTree(contents[key], message => console.error(`Conflict in default settings file: ${message}`)),\n });\n }\n }\n super(contents, keys, overrides);\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport '../../common/languages/languageConfigurationRegistry.js';\nimport './standaloneCodeEditorService.js';\nimport './standaloneLayoutService.js';\nimport '../../../platform/undoRedo/common/undoRedoService.js';\nimport '../../common/services/languageFeatureDebounce.js';\nimport * as strings from '../../../base/common/strings.js';\nimport * as dom from '../../../base/browser/dom.js';\nimport { StandardKeyboardEvent } from '../../../base/browser/keyboardEvent.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { SimpleKeybinding, createKeybinding } from '../../../base/common/keybindings.js';\nimport { ImmortalReference, toDisposable, DisposableStore, Disposable } from '../../../base/common/lifecycle.js';\nimport { OS, isLinux, isMacintosh } from '../../../base/common/platform.js';\nimport Severity from '../../../base/common/severity.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { IBulkEditService, ResourceTextEdit } from '../../browser/services/bulkEditService.js';\nimport { isDiffEditorConfigurationKey, isEditorConfigurationKey } from '../../common/config/editorConfigurationSchema.js';\nimport { EditOperation } from '../../common/core/editOperation.js';\nimport { Position as Pos } from '../../common/core/position.js';\nimport { Range } from '../../common/core/range.js';\nimport { IModelService } from '../../common/services/model.js';\nimport { ITextModelService } from '../../common/services/resolverService.js';\nimport { ITextResourceConfigurationService, ITextResourcePropertiesService } from '../../common/services/textResourceConfiguration.js';\nimport { CommandsRegistry, ICommandService } from '../../../platform/commands/common/commands.js';\nimport { IConfigurationService } from '../../../platform/configuration/common/configuration.js';\nimport { Configuration, ConfigurationModel, ConfigurationChangeEvent } from '../../../platform/configuration/common/configurationModels.js';\nimport { IContextKeyService } from '../../../platform/contextkey/common/contextkey.js';\nimport { IDialogService } from '../../../platform/dialogs/common/dialogs.js';\nimport { createDecorator, IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';\nimport { AbstractKeybindingService } from '../../../platform/keybinding/common/abstractKeybindingService.js';\nimport { IKeybindingService } from '../../../platform/keybinding/common/keybinding.js';\nimport { KeybindingResolver } from '../../../platform/keybinding/common/keybindingResolver.js';\nimport { KeybindingsRegistry } from '../../../platform/keybinding/common/keybindingsRegistry.js';\nimport { ResolvedKeybindingItem } from '../../../platform/keybinding/common/resolvedKeybindingItem.js';\nimport { USLayoutResolvedKeybinding } from '../../../platform/keybinding/common/usLayoutResolvedKeybinding.js';\nimport { ILabelService } from '../../../platform/label/common/label.js';\nimport { INotificationService, NoOpNotification } from '../../../platform/notification/common/notification.js';\nimport { IEditorProgressService, IProgressService } from '../../../platform/progress/common/progress.js';\nimport { ITelemetryService } from '../../../platform/telemetry/common/telemetry.js';\nimport { IWorkspaceContextService, WorkspaceFolder } from '../../../platform/workspace/common/workspace.js';\nimport { ILayoutService } from '../../../platform/layout/browser/layoutService.js';\nimport { StandaloneServicesNLS } from '../../common/standaloneStrings.js';\nimport { basename } from '../../../base/common/resources.js';\nimport { ICodeEditorService } from '../../browser/services/codeEditorService.js';\nimport { ConsoleLogger, ILogService, LogService } from '../../../platform/log/common/log.js';\nimport { IWorkspaceTrustManagementService } from '../../../platform/workspace/common/workspaceTrust.js';\nimport { IContextMenuService, IContextViewService } from '../../../platform/contextview/browser/contextView.js';\nimport { ContextViewService } from '../../../platform/contextview/browser/contextViewService.js';\nimport { LanguageService } from '../../common/services/languageService.js';\nimport { ContextMenuService } from '../../../platform/contextview/browser/contextMenuService.js';\nimport { IThemeService } from '../../../platform/theme/common/themeService.js';\nimport { getSingletonServiceDescriptors, registerSingleton } from '../../../platform/instantiation/common/extensions.js';\nimport { OpenerService } from '../../browser/services/openerService.js';\nimport { IEditorWorkerService } from '../../common/services/editorWorker.js';\nimport { EditorWorkerService } from '../../browser/services/editorWorkerService.js';\nimport { ILanguageService } from '../../common/languages/language.js';\nimport { MarkerDecorationsService } from '../../common/services/markerDecorationsService.js';\nimport { IMarkerDecorationsService } from '../../common/services/markerDecorations.js';\nimport { ModelService } from '../../common/services/modelService.js';\nimport { StandaloneQuickInputService } from './quickInput/standaloneQuickInputService.js';\nimport { StandaloneThemeService } from './standaloneThemeService.js';\nimport { IStandaloneThemeService } from '../common/standaloneTheme.js';\nimport { AccessibilityService } from '../../../platform/accessibility/browser/accessibilityService.js';\nimport { IAccessibilityService } from '../../../platform/accessibility/common/accessibility.js';\nimport { IMenuService } from '../../../platform/actions/common/actions.js';\nimport { MenuService } from '../../../platform/actions/common/menuService.js';\nimport { BrowserClipboardService } from '../../../platform/clipboard/browser/clipboardService.js';\nimport { IClipboardService } from '../../../platform/clipboard/common/clipboardService.js';\nimport { ContextKeyService } from '../../../platform/contextkey/browser/contextKeyService.js';\nimport { SyncDescriptor } from '../../../platform/instantiation/common/descriptors.js';\nimport { InstantiationService } from '../../../platform/instantiation/common/instantiationService.js';\nimport { ServiceCollection } from '../../../platform/instantiation/common/serviceCollection.js';\nimport { IListService, ListService } from '../../../platform/list/browser/listService.js';\nimport { IMarkerService } from '../../../platform/markers/common/markers.js';\nimport { MarkerService } from '../../../platform/markers/common/markerService.js';\nimport { IOpenerService } from '../../../platform/opener/common/opener.js';\nimport { IQuickInputService } from '../../../platform/quickinput/common/quickInput.js';\nimport { IStorageService, InMemoryStorageService } from '../../../platform/storage/common/storage.js';\nimport '../../common/services/languageFeaturesService.js';\nimport { DefaultConfigurationModel } from '../../../platform/configuration/common/configurations.js';\nclass SimpleModel {\n constructor(model) {\n this.disposed = false;\n this.model = model;\n this._onWillDispose = new Emitter();\n }\n get textEditorModel() {\n return this.model;\n }\n dispose() {\n this.disposed = true;\n this._onWillDispose.fire();\n }\n}\nlet StandaloneTextModelService = class StandaloneTextModelService {\n constructor(modelService) {\n this.modelService = modelService;\n }\n createModelReference(resource) {\n const model = this.modelService.getModel(resource);\n if (!model) {\n return Promise.reject(new Error(`Model not found`));\n }\n return Promise.resolve(new ImmortalReference(new SimpleModel(model)));\n }\n};\nStandaloneTextModelService = __decorate([\n __param(0, IModelService)\n], StandaloneTextModelService);\nclass StandaloneEditorProgressService {\n show() {\n return StandaloneEditorProgressService.NULL_PROGRESS_RUNNER;\n }\n showWhile(promise, delay) {\n return __awaiter(this, void 0, void 0, function* () {\n yield promise;\n });\n }\n}\nStandaloneEditorProgressService.NULL_PROGRESS_RUNNER = {\n done: () => { },\n total: () => { },\n worked: () => { }\n};\nclass StandaloneProgressService {\n withProgress(_options, task, onDidCancel) {\n return task({\n report: () => { },\n });\n }\n}\nclass StandaloneDialogService {\n confirm(confirmation) {\n return this.doConfirm(confirmation).then(confirmed => {\n return {\n confirmed,\n checkboxChecked: false // unsupported\n };\n });\n }\n doConfirm(confirmation) {\n let messageText = confirmation.message;\n if (confirmation.detail) {\n messageText = messageText + '\\n\\n' + confirmation.detail;\n }\n return Promise.resolve(window.confirm(messageText));\n }\n show(severity, message, buttons, options) {\n return Promise.resolve({ choice: 0 });\n }\n}\nexport class StandaloneNotificationService {\n info(message) {\n return this.notify({ severity: Severity.Info, message });\n }\n warn(message) {\n return this.notify({ severity: Severity.Warning, message });\n }\n error(error) {\n return this.notify({ severity: Severity.Error, message: error });\n }\n notify(notification) {\n switch (notification.severity) {\n case Severity.Error:\n console.error(notification.message);\n break;\n case Severity.Warning:\n console.warn(notification.message);\n break;\n default:\n console.log(notification.message);\n break;\n }\n return StandaloneNotificationService.NO_OP;\n }\n status(message, options) {\n return Disposable.None;\n }\n}\nStandaloneNotificationService.NO_OP = new NoOpNotification();\nlet StandaloneCommandService = class StandaloneCommandService {\n constructor(instantiationService) {\n this._onWillExecuteCommand = new Emitter();\n this._onDidExecuteCommand = new Emitter();\n this.onWillExecuteCommand = this._onWillExecuteCommand.event;\n this.onDidExecuteCommand = this._onDidExecuteCommand.event;\n this._instantiationService = instantiationService;\n }\n executeCommand(id, ...args) {\n const command = CommandsRegistry.getCommand(id);\n if (!command) {\n return Promise.reject(new Error(`command '${id}' not found`));\n }\n try {\n this._onWillExecuteCommand.fire({ commandId: id, args });\n const result = this._instantiationService.invokeFunction.apply(this._instantiationService, [command.handler, ...args]);\n this._onDidExecuteCommand.fire({ commandId: id, args });\n return Promise.resolve(result);\n }\n catch (err) {\n return Promise.reject(err);\n }\n }\n};\nStandaloneCommandService = __decorate([\n __param(0, IInstantiationService)\n], StandaloneCommandService);\nexport { StandaloneCommandService };\nlet StandaloneKeybindingService = class StandaloneKeybindingService extends AbstractKeybindingService {\n constructor(contextKeyService, commandService, telemetryService, notificationService, logService, codeEditorService) {\n super(contextKeyService, commandService, telemetryService, notificationService, logService);\n this._cachedResolver = null;\n this._dynamicKeybindings = [];\n this._domNodeListeners = [];\n const addContainer = (domNode) => {\n const disposables = new DisposableStore();\n // for standard keybindings\n disposables.add(dom.addDisposableListener(domNode, dom.EventType.KEY_DOWN, (e) => {\n const keyEvent = new StandardKeyboardEvent(e);\n const shouldPreventDefault = this._dispatch(keyEvent, keyEvent.target);\n if (shouldPreventDefault) {\n keyEvent.preventDefault();\n keyEvent.stopPropagation();\n }\n }));\n // for single modifier chord keybindings (e.g. shift shift)\n disposables.add(dom.addDisposableListener(domNode, dom.EventType.KEY_UP, (e) => {\n const keyEvent = new StandardKeyboardEvent(e);\n const shouldPreventDefault = this._singleModifierDispatch(keyEvent, keyEvent.target);\n if (shouldPreventDefault) {\n keyEvent.preventDefault();\n }\n }));\n this._domNodeListeners.push(new DomNodeListeners(domNode, disposables));\n };\n const removeContainer = (domNode) => {\n for (let i = 0; i < this._domNodeListeners.length; i++) {\n const domNodeListeners = this._domNodeListeners[i];\n if (domNodeListeners.domNode === domNode) {\n this._domNodeListeners.splice(i, 1);\n domNodeListeners.dispose();\n }\n }\n };\n const addCodeEditor = (codeEditor) => {\n if (codeEditor.getOption(56 /* EditorOption.inDiffEditor */)) {\n return;\n }\n addContainer(codeEditor.getContainerDomNode());\n };\n const removeCodeEditor = (codeEditor) => {\n if (codeEditor.getOption(56 /* EditorOption.inDiffEditor */)) {\n return;\n }\n removeContainer(codeEditor.getContainerDomNode());\n };\n this._register(codeEditorService.onCodeEditorAdd(addCodeEditor));\n this._register(codeEditorService.onCodeEditorRemove(removeCodeEditor));\n codeEditorService.listCodeEditors().forEach(addCodeEditor);\n const addDiffEditor = (diffEditor) => {\n addContainer(diffEditor.getContainerDomNode());\n };\n const removeDiffEditor = (diffEditor) => {\n removeContainer(diffEditor.getContainerDomNode());\n };\n this._register(codeEditorService.onDiffEditorAdd(addDiffEditor));\n this._register(codeEditorService.onDiffEditorRemove(removeDiffEditor));\n codeEditorService.listDiffEditors().forEach(addDiffEditor);\n }\n addDynamicKeybinding(commandId, _keybinding, handler, when) {\n const keybinding = createKeybinding(_keybinding, OS);\n const toDispose = new DisposableStore();\n if (keybinding) {\n this._dynamicKeybindings.push({\n keybinding: keybinding.parts,\n command: commandId,\n when: when,\n weight1: 1000,\n weight2: 0,\n extensionId: null,\n isBuiltinExtension: false\n });\n toDispose.add(toDisposable(() => {\n for (let i = 0; i < this._dynamicKeybindings.length; i++) {\n const kb = this._dynamicKeybindings[i];\n if (kb.command === commandId) {\n this._dynamicKeybindings.splice(i, 1);\n this.updateResolver();\n return;\n }\n }\n }));\n }\n toDispose.add(CommandsRegistry.registerCommand(commandId, handler));\n this.updateResolver();\n return toDispose;\n }\n updateResolver() {\n this._cachedResolver = null;\n this._onDidUpdateKeybindings.fire();\n }\n _getResolver() {\n if (!this._cachedResolver) {\n const defaults = this._toNormalizedKeybindingItems(KeybindingsRegistry.getDefaultKeybindings(), true);\n const overrides = this._toNormalizedKeybindingItems(this._dynamicKeybindings, false);\n this._cachedResolver = new KeybindingResolver(defaults, overrides, (str) => this._log(str));\n }\n return this._cachedResolver;\n }\n _documentHasFocus() {\n return document.hasFocus();\n }\n _toNormalizedKeybindingItems(items, isDefault) {\n const result = [];\n let resultLen = 0;\n for (const item of items) {\n const when = item.when || undefined;\n const keybinding = item.keybinding;\n if (!keybinding) {\n // This might be a removal keybinding item in user settings => accept it\n result[resultLen++] = new ResolvedKeybindingItem(undefined, item.command, item.commandArgs, when, isDefault, null, false);\n }\n else {\n const resolvedKeybindings = USLayoutResolvedKeybinding.resolveUserBinding(keybinding, OS);\n for (const resolvedKeybinding of resolvedKeybindings) {\n result[resultLen++] = new ResolvedKeybindingItem(resolvedKeybinding, item.command, item.commandArgs, when, isDefault, null, false);\n }\n }\n }\n return result;\n }\n resolveKeyboardEvent(keyboardEvent) {\n const keybinding = new SimpleKeybinding(keyboardEvent.ctrlKey, keyboardEvent.shiftKey, keyboardEvent.altKey, keyboardEvent.metaKey, keyboardEvent.keyCode).toChord();\n return new USLayoutResolvedKeybinding(keybinding, OS);\n }\n};\nStandaloneKeybindingService = __decorate([\n __param(0, IContextKeyService),\n __param(1, ICommandService),\n __param(2, ITelemetryService),\n __param(3, INotificationService),\n __param(4, ILogService),\n __param(5, ICodeEditorService)\n], StandaloneKeybindingService);\nexport { StandaloneKeybindingService };\nclass DomNodeListeners extends Disposable {\n constructor(domNode, disposables) {\n super();\n this.domNode = domNode;\n this._register(disposables);\n }\n}\nfunction isConfigurationOverrides(thing) {\n return thing\n && typeof thing === 'object'\n && (!thing.overrideIdentifier || typeof thing.overrideIdentifier === 'string')\n && (!thing.resource || thing.resource instanceof URI);\n}\nexport class StandaloneConfigurationService {\n constructor() {\n this._onDidChangeConfiguration = new Emitter();\n this.onDidChangeConfiguration = this._onDidChangeConfiguration.event;\n this._configuration = new Configuration(new DefaultConfigurationModel(), new ConfigurationModel(), new ConfigurationModel(), new ConfigurationModel());\n }\n getValue(arg1, arg2) {\n const section = typeof arg1 === 'string' ? arg1 : undefined;\n const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : {};\n return this._configuration.getValue(section, overrides, undefined);\n }\n updateValues(values) {\n const previous = { data: this._configuration.toData() };\n const changedKeys = [];\n for (const entry of values) {\n const [key, value] = entry;\n if (this.getValue(key) === value) {\n continue;\n }\n this._configuration.updateValue(key, value);\n changedKeys.push(key);\n }\n if (changedKeys.length > 0) {\n const configurationChangeEvent = new ConfigurationChangeEvent({ keys: changedKeys, overrides: [] }, previous, this._configuration);\n configurationChangeEvent.source = 8 /* ConfigurationTarget.MEMORY */;\n configurationChangeEvent.sourceConfig = null;\n this._onDidChangeConfiguration.fire(configurationChangeEvent);\n }\n return Promise.resolve();\n }\n updateValue(key, value, arg3, arg4) {\n return this.updateValues([[key, value]]);\n }\n inspect(key, options = {}) {\n return this._configuration.inspect(key, options, undefined);\n }\n}\nlet StandaloneResourceConfigurationService = class StandaloneResourceConfigurationService {\n constructor(configurationService) {\n this.configurationService = configurationService;\n this._onDidChangeConfiguration = new Emitter();\n this.configurationService.onDidChangeConfiguration((e) => {\n this._onDidChangeConfiguration.fire({ affectedKeys: e.affectedKeys, affectsConfiguration: (resource, configuration) => e.affectsConfiguration(configuration) });\n });\n }\n getValue(resource, arg2, arg3) {\n const position = Pos.isIPosition(arg2) ? arg2 : null;\n const section = position ? (typeof arg3 === 'string' ? arg3 : undefined) : (typeof arg2 === 'string' ? arg2 : undefined);\n if (typeof section === 'undefined') {\n return this.configurationService.getValue();\n }\n return this.configurationService.getValue(section);\n }\n};\nStandaloneResourceConfigurationService = __decorate([\n __param(0, IConfigurationService)\n], StandaloneResourceConfigurationService);\nlet StandaloneResourcePropertiesService = class StandaloneResourcePropertiesService {\n constructor(configurationService) {\n this.configurationService = configurationService;\n }\n getEOL(resource, language) {\n const eol = this.configurationService.getValue('files.eol', { overrideIdentifier: language, resource });\n if (eol && typeof eol === 'string' && eol !== 'auto') {\n return eol;\n }\n return (isLinux || isMacintosh) ? '\\n' : '\\r\\n';\n }\n};\nStandaloneResourcePropertiesService = __decorate([\n __param(0, IConfigurationService)\n], StandaloneResourcePropertiesService);\nclass StandaloneTelemetryService {\n publicLog(eventName, data) {\n return Promise.resolve(undefined);\n }\n publicLog2(eventName, data) {\n return this.publicLog(eventName, data);\n }\n}\nclass StandaloneWorkspaceContextService {\n constructor() {\n const resource = URI.from({ scheme: StandaloneWorkspaceContextService.SCHEME, authority: 'model', path: '/' });\n this.workspace = { id: '4064f6ec-cb38-4ad0-af64-ee6467e63c82', folders: [new WorkspaceFolder({ uri: resource, name: '', index: 0 })] };\n }\n getWorkspace() {\n return this.workspace;\n }\n getWorkspaceFolder(resource) {\n return resource && resource.scheme === StandaloneWorkspaceContextService.SCHEME ? this.workspace.folders[0] : null;\n }\n}\nStandaloneWorkspaceContextService.SCHEME = 'inmemory';\nexport function updateConfigurationService(configurationService, source, isDiffEditor) {\n if (!source) {\n return;\n }\n if (!(configurationService instanceof StandaloneConfigurationService)) {\n return;\n }\n const toUpdate = [];\n Object.keys(source).forEach((key) => {\n if (isEditorConfigurationKey(key)) {\n toUpdate.push([`editor.${key}`, source[key]]);\n }\n if (isDiffEditor && isDiffEditorConfigurationKey(key)) {\n toUpdate.push([`diffEditor.${key}`, source[key]]);\n }\n });\n if (toUpdate.length > 0) {\n configurationService.updateValues(toUpdate);\n }\n}\nlet StandaloneBulkEditService = class StandaloneBulkEditService {\n constructor(_modelService) {\n this._modelService = _modelService;\n //\n }\n hasPreviewHandler() {\n return false;\n }\n apply(edits, _options) {\n return __awaiter(this, void 0, void 0, function* () {\n const textEdits = new Map();\n for (const edit of edits) {\n if (!(edit instanceof ResourceTextEdit)) {\n throw new Error('bad edit - only text edits are supported');\n }\n const model = this._modelService.getModel(edit.resource);\n if (!model) {\n throw new Error('bad edit - model not found');\n }\n if (typeof edit.versionId === 'number' && model.getVersionId() !== edit.versionId) {\n throw new Error('bad state - model changed in the meantime');\n }\n let array = textEdits.get(model);\n if (!array) {\n array = [];\n textEdits.set(model, array);\n }\n array.push(EditOperation.replaceMove(Range.lift(edit.textEdit.range), edit.textEdit.text));\n }\n let totalEdits = 0;\n let totalFiles = 0;\n for (const [model, edits] of textEdits) {\n model.pushStackElement();\n model.pushEditOperations([], edits, () => []);\n model.pushStackElement();\n totalFiles += 1;\n totalEdits += edits.length;\n }\n return {\n ariaSummary: strings.format(StandaloneServicesNLS.bulkEditServiceSummary, totalEdits, totalFiles)\n };\n });\n }\n};\nStandaloneBulkEditService = __decorate([\n __param(0, IModelService)\n], StandaloneBulkEditService);\nclass StandaloneUriLabelService {\n getUriLabel(resource, options) {\n if (resource.scheme === 'file') {\n return resource.fsPath;\n }\n return resource.path;\n }\n getUriBasenameLabel(resource) {\n return basename(resource);\n }\n}\nlet StandaloneContextViewService = class StandaloneContextViewService extends ContextViewService {\n constructor(layoutService, _codeEditorService) {\n super(layoutService);\n this._codeEditorService = _codeEditorService;\n }\n showContextView(delegate, container, shadowRoot) {\n if (!container) {\n const codeEditor = this._codeEditorService.getFocusedCodeEditor() || this._codeEditorService.getActiveCodeEditor();\n if (codeEditor) {\n container = codeEditor.getContainerDomNode();\n }\n }\n return super.showContextView(delegate, container, shadowRoot);\n }\n};\nStandaloneContextViewService = __decorate([\n __param(0, ILayoutService),\n __param(1, ICodeEditorService)\n], StandaloneContextViewService);\nclass StandaloneWorkspaceTrustManagementService {\n constructor() {\n this._neverEmitter = new Emitter();\n this.onDidChangeTrust = this._neverEmitter.event;\n }\n isWorkspaceTrusted() {\n return true;\n }\n}\nclass StandaloneLanguageService extends LanguageService {\n constructor() {\n super();\n }\n}\nclass StandaloneLogService extends LogService {\n constructor() {\n super(new ConsoleLogger());\n }\n}\nlet StandaloneContextMenuService = class StandaloneContextMenuService extends ContextMenuService {\n constructor(telemetryService, notificationService, contextViewService, keybindingService, themeService) {\n super(telemetryService, notificationService, contextViewService, keybindingService, themeService);\n this.configure({ blockMouse: false }); // we do not want that in the standalone editor\n }\n};\nStandaloneContextMenuService = __decorate([\n __param(0, ITelemetryService),\n __param(1, INotificationService),\n __param(2, IContextViewService),\n __param(3, IKeybindingService),\n __param(4, IThemeService)\n], StandaloneContextMenuService);\nregisterSingleton(IConfigurationService, StandaloneConfigurationService);\nregisterSingleton(ITextResourceConfigurationService, StandaloneResourceConfigurationService);\nregisterSingleton(ITextResourcePropertiesService, StandaloneResourcePropertiesService);\nregisterSingleton(IWorkspaceContextService, StandaloneWorkspaceContextService);\nregisterSingleton(ILabelService, StandaloneUriLabelService);\nregisterSingleton(ITelemetryService, StandaloneTelemetryService);\nregisterSingleton(IDialogService, StandaloneDialogService);\nregisterSingleton(INotificationService, StandaloneNotificationService);\nregisterSingleton(IMarkerService, MarkerService);\nregisterSingleton(ILanguageService, StandaloneLanguageService);\nregisterSingleton(IStandaloneThemeService, StandaloneThemeService);\nregisterSingleton(ILogService, StandaloneLogService);\nregisterSingleton(IModelService, ModelService);\nregisterSingleton(IMarkerDecorationsService, MarkerDecorationsService);\nregisterSingleton(IContextKeyService, ContextKeyService);\nregisterSingleton(IProgressService, StandaloneProgressService);\nregisterSingleton(IEditorProgressService, StandaloneEditorProgressService);\nregisterSingleton(IStorageService, InMemoryStorageService);\nregisterSingleton(IEditorWorkerService, EditorWorkerService);\nregisterSingleton(IBulkEditService, StandaloneBulkEditService);\nregisterSingleton(IWorkspaceTrustManagementService, StandaloneWorkspaceTrustManagementService);\nregisterSingleton(ITextModelService, StandaloneTextModelService);\nregisterSingleton(IAccessibilityService, AccessibilityService);\nregisterSingleton(IListService, ListService);\nregisterSingleton(ICommandService, StandaloneCommandService);\nregisterSingleton(IKeybindingService, StandaloneKeybindingService);\nregisterSingleton(IQuickInputService, StandaloneQuickInputService);\nregisterSingleton(IContextViewService, StandaloneContextViewService);\nregisterSingleton(IOpenerService, OpenerService);\nregisterSingleton(IClipboardService, BrowserClipboardService);\nregisterSingleton(IContextMenuService, StandaloneContextMenuService);\nregisterSingleton(IMenuService, MenuService);\n/**\n * We don't want to eagerly instantiate services because embedders get a one time chance\n * to override services when they create the first editor.\n */\nexport var StandaloneServices;\n(function (StandaloneServices) {\n const serviceCollection = new ServiceCollection();\n for (const [id, descriptor] of getSingletonServiceDescriptors()) {\n serviceCollection.set(id, descriptor);\n }\n const instantiationService = new InstantiationService(serviceCollection, true);\n serviceCollection.set(IInstantiationService, instantiationService);\n function get(serviceId) {\n const r = serviceCollection.get(serviceId);\n if (!r) {\n throw new Error('Missing service ' + serviceId);\n }\n if (r instanceof SyncDescriptor) {\n return instantiationService.invokeFunction((accessor) => accessor.get(serviceId));\n }\n else {\n return r;\n }\n }\n StandaloneServices.get = get;\n let initialized = false;\n function initialize(overrides) {\n if (initialized) {\n return instantiationService;\n }\n initialized = true;\n // Add singletons that were registered after this module loaded\n for (const [id, descriptor] of getSingletonServiceDescriptors()) {\n if (!serviceCollection.get(id)) {\n serviceCollection.set(id, descriptor);\n }\n }\n // Initialize the service collection with the overrides, but only if the\n // service was not instantiated in the meantime.\n for (const serviceId in overrides) {\n if (overrides.hasOwnProperty(serviceId)) {\n const serviceIdentifier = createDecorator(serviceId);\n const r = serviceCollection.get(serviceIdentifier);\n if (r instanceof SyncDescriptor) {\n serviceCollection.set(serviceIdentifier, overrides[serviceId]);\n }\n }\n }\n return instantiationService;\n }\n StandaloneServices.initialize = initialize;\n})(StandaloneServices || (StandaloneServices = {}));\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport * as aria from '../../../base/browser/ui/aria/aria.js';\nimport { Disposable, toDisposable, DisposableStore } from '../../../base/common/lifecycle.js';\nimport { ICodeEditorService } from '../../browser/services/codeEditorService.js';\nimport { CodeEditorWidget } from '../../browser/widget/codeEditorWidget.js';\nimport { DiffEditorWidget } from '../../browser/widget/diffEditorWidget.js';\nimport { InternalEditorAction } from '../../common/editorAction.js';\nimport { IEditorWorkerService } from '../../common/services/editorWorker.js';\nimport { StandaloneKeybindingService, updateConfigurationService } from './standaloneServices.js';\nimport { IStandaloneThemeService } from '../common/standaloneTheme.js';\nimport { MenuId, MenuRegistry } from '../../../platform/actions/common/actions.js';\nimport { CommandsRegistry, ICommandService } from '../../../platform/commands/common/commands.js';\nimport { IConfigurationService } from '../../../platform/configuration/common/configuration.js';\nimport { ContextKeyExpr, IContextKeyService } from '../../../platform/contextkey/common/contextkey.js';\nimport { IContextMenuService } from '../../../platform/contextview/browser/contextView.js';\nimport { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';\nimport { IKeybindingService } from '../../../platform/keybinding/common/keybinding.js';\nimport { INotificationService } from '../../../platform/notification/common/notification.js';\nimport { IThemeService } from '../../../platform/theme/common/themeService.js';\nimport { IAccessibilityService } from '../../../platform/accessibility/common/accessibility.js';\nimport { StandaloneCodeEditorNLS } from '../../common/standaloneStrings.js';\nimport { IClipboardService } from '../../../platform/clipboard/common/clipboardService.js';\nimport { IEditorProgressService } from '../../../platform/progress/common/progress.js';\nimport { IModelService } from '../../common/services/model.js';\nimport { ILanguageService } from '../../common/languages/language.js';\nimport { StandaloneCodeEditorService } from './standaloneCodeEditorService.js';\nimport { PLAINTEXT_LANGUAGE_ID } from '../../common/languages/modesRegistry.js';\nimport { ILanguageConfigurationService } from '../../common/languages/languageConfigurationRegistry.js';\nimport { ILanguageFeaturesService } from '../../common/services/languageFeatures.js';\nlet LAST_GENERATED_COMMAND_ID = 0;\nlet ariaDomNodeCreated = false;\n/**\n * Create ARIA dom node inside parent,\n * or only for the first editor instantiation inside document.body.\n * @param parent container element for ARIA dom node\n */\nfunction createAriaDomNode(parent) {\n if (!parent) {\n if (ariaDomNodeCreated) {\n return;\n }\n ariaDomNodeCreated = true;\n }\n aria.setARIAContainer(parent || document.body);\n}\n/**\n * A code editor to be used both by the standalone editor and the standalone diff editor.\n */\nlet StandaloneCodeEditor = class StandaloneCodeEditor extends CodeEditorWidget {\n constructor(domElement, _options, instantiationService, codeEditorService, commandService, contextKeyService, keybindingService, themeService, notificationService, accessibilityService, languageConfigurationService, languageFeaturesService) {\n const options = Object.assign({}, _options);\n options.ariaLabel = options.ariaLabel || StandaloneCodeEditorNLS.editorViewAccessibleLabel;\n options.ariaLabel = options.ariaLabel + ';' + (StandaloneCodeEditorNLS.accessibilityHelpMessage);\n super(domElement, options, {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService, languageFeaturesService);\n if (keybindingService instanceof StandaloneKeybindingService) {\n this._standaloneKeybindingService = keybindingService;\n }\n else {\n this._standaloneKeybindingService = null;\n }\n createAriaDomNode(options.ariaContainerElement);\n }\n addCommand(keybinding, handler, context) {\n if (!this._standaloneKeybindingService) {\n console.warn('Cannot add command because the editor is configured with an unrecognized KeybindingService');\n return null;\n }\n const commandId = 'DYNAMIC_' + (++LAST_GENERATED_COMMAND_ID);\n const whenExpression = ContextKeyExpr.deserialize(context);\n this._standaloneKeybindingService.addDynamicKeybinding(commandId, keybinding, handler, whenExpression);\n return commandId;\n }\n createContextKey(key, defaultValue) {\n return this._contextKeyService.createKey(key, defaultValue);\n }\n addAction(_descriptor) {\n if ((typeof _descriptor.id !== 'string') || (typeof _descriptor.label !== 'string') || (typeof _descriptor.run !== 'function')) {\n throw new Error('Invalid action descriptor, `id`, `label` and `run` are required properties!');\n }\n if (!this._standaloneKeybindingService) {\n console.warn('Cannot add keybinding because the editor is configured with an unrecognized KeybindingService');\n return Disposable.None;\n }\n // Read descriptor options\n const id = _descriptor.id;\n const label = _descriptor.label;\n const precondition = ContextKeyExpr.and(ContextKeyExpr.equals('editorId', this.getId()), ContextKeyExpr.deserialize(_descriptor.precondition));\n const keybindings = _descriptor.keybindings;\n const keybindingsWhen = ContextKeyExpr.and(precondition, ContextKeyExpr.deserialize(_descriptor.keybindingContext));\n const contextMenuGroupId = _descriptor.contextMenuGroupId || null;\n const contextMenuOrder = _descriptor.contextMenuOrder || 0;\n const run = (accessor, ...args) => {\n return Promise.resolve(_descriptor.run(this, ...args));\n };\n const toDispose = new DisposableStore();\n // Generate a unique id to allow the same descriptor.id across multiple editor instances\n const uniqueId = this.getId() + ':' + id;\n // Register the command\n toDispose.add(CommandsRegistry.registerCommand(uniqueId, run));\n // Register the context menu item\n if (contextMenuGroupId) {\n const menuItem = {\n command: {\n id: uniqueId,\n title: label\n },\n when: precondition,\n group: contextMenuGroupId,\n order: contextMenuOrder\n };\n toDispose.add(MenuRegistry.appendMenuItem(MenuId.EditorContext, menuItem));\n }\n // Register the keybindings\n if (Array.isArray(keybindings)) {\n for (const kb of keybindings) {\n toDispose.add(this._standaloneKeybindingService.addDynamicKeybinding(uniqueId, kb, run, keybindingsWhen));\n }\n }\n // Finally, register an internal editor action\n const internalAction = new InternalEditorAction(uniqueId, label, label, precondition, run, this._contextKeyService);\n // Store it under the original id, such that trigger with the original id will work\n this._actions[id] = internalAction;\n toDispose.add(toDisposable(() => {\n delete this._actions[id];\n }));\n return toDispose;\n }\n _triggerCommand(handlerId, payload) {\n if (this._codeEditorService instanceof StandaloneCodeEditorService) {\n // Help commands find this editor as the active editor\n try {\n this._codeEditorService.setActiveCodeEditor(this);\n super._triggerCommand(handlerId, payload);\n }\n finally {\n this._codeEditorService.setActiveCodeEditor(null);\n }\n }\n else {\n super._triggerCommand(handlerId, payload);\n }\n }\n};\nStandaloneCodeEditor = __decorate([\n __param(2, IInstantiationService),\n __param(3, ICodeEditorService),\n __param(4, ICommandService),\n __param(5, IContextKeyService),\n __param(6, IKeybindingService),\n __param(7, IThemeService),\n __param(8, INotificationService),\n __param(9, IAccessibilityService),\n __param(10, ILanguageConfigurationService),\n __param(11, ILanguageFeaturesService)\n], StandaloneCodeEditor);\nexport { StandaloneCodeEditor };\nlet StandaloneEditor = class StandaloneEditor extends StandaloneCodeEditor {\n constructor(domElement, _options, instantiationService, codeEditorService, commandService, contextKeyService, keybindingService, themeService, notificationService, configurationService, accessibilityService, modelService, languageService, languageConfigurationService, languageFeaturesService) {\n const options = Object.assign({}, _options);\n updateConfigurationService(configurationService, options, false);\n const themeDomRegistration = themeService.registerEditorContainer(domElement);\n if (typeof options.theme === 'string') {\n themeService.setTheme(options.theme);\n }\n if (typeof options.autoDetectHighContrast !== 'undefined') {\n themeService.setAutoDetectHighContrast(Boolean(options.autoDetectHighContrast));\n }\n const _model = options.model;\n delete options.model;\n super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, keybindingService, themeService, notificationService, accessibilityService, languageConfigurationService, languageFeaturesService);\n this._configurationService = configurationService;\n this._standaloneThemeService = themeService;\n this._register(themeDomRegistration);\n let model;\n if (typeof _model === 'undefined') {\n const languageId = languageService.getLanguageIdByMimeType(options.language) || options.language || PLAINTEXT_LANGUAGE_ID;\n model = createTextModel(modelService, languageService, options.value || '', languageId, undefined);\n this._ownsModel = true;\n }\n else {\n model = _model;\n this._ownsModel = false;\n }\n this._attachModel(model);\n if (model) {\n const e = {\n oldModelUrl: null,\n newModelUrl: model.uri\n };\n this._onDidChangeModel.fire(e);\n }\n }\n dispose() {\n super.dispose();\n }\n updateOptions(newOptions) {\n updateConfigurationService(this._configurationService, newOptions, false);\n if (typeof newOptions.theme === 'string') {\n this._standaloneThemeService.setTheme(newOptions.theme);\n }\n if (typeof newOptions.autoDetectHighContrast !== 'undefined') {\n this._standaloneThemeService.setAutoDetectHighContrast(Boolean(newOptions.autoDetectHighContrast));\n }\n super.updateOptions(newOptions);\n }\n _postDetachModelCleanup(detachedModel) {\n super._postDetachModelCleanup(detachedModel);\n if (detachedModel && this._ownsModel) {\n detachedModel.dispose();\n this._ownsModel = false;\n }\n }\n};\nStandaloneEditor = __decorate([\n __param(2, IInstantiationService),\n __param(3, ICodeEditorService),\n __param(4, ICommandService),\n __param(5, IContextKeyService),\n __param(6, IKeybindingService),\n __param(7, IStandaloneThemeService),\n __param(8, INotificationService),\n __param(9, IConfigurationService),\n __param(10, IAccessibilityService),\n __param(11, IModelService),\n __param(12, ILanguageService),\n __param(13, ILanguageConfigurationService),\n __param(14, ILanguageFeaturesService)\n], StandaloneEditor);\nexport { StandaloneEditor };\nlet StandaloneDiffEditor = class StandaloneDiffEditor extends DiffEditorWidget {\n constructor(domElement, _options, instantiationService, contextKeyService, editorWorkerService, codeEditorService, themeService, notificationService, configurationService, contextMenuService, editorProgressService, clipboardService) {\n const options = Object.assign({}, _options);\n updateConfigurationService(configurationService, options, true);\n const themeDomRegistration = themeService.registerEditorContainer(domElement);\n if (typeof options.theme === 'string') {\n themeService.setTheme(options.theme);\n }\n if (typeof options.autoDetectHighContrast !== 'undefined') {\n themeService.setAutoDetectHighContrast(Boolean(options.autoDetectHighContrast));\n }\n super(domElement, options, {}, clipboardService, editorWorkerService, contextKeyService, instantiationService, codeEditorService, themeService, notificationService, contextMenuService, editorProgressService);\n this._configurationService = configurationService;\n this._standaloneThemeService = themeService;\n this._register(themeDomRegistration);\n }\n dispose() {\n super.dispose();\n }\n updateOptions(newOptions) {\n updateConfigurationService(this._configurationService, newOptions, true);\n if (typeof newOptions.theme === 'string') {\n this._standaloneThemeService.setTheme(newOptions.theme);\n }\n if (typeof newOptions.autoDetectHighContrast !== 'undefined') {\n this._standaloneThemeService.setAutoDetectHighContrast(Boolean(newOptions.autoDetectHighContrast));\n }\n super.updateOptions(newOptions);\n }\n _createInnerEditor(instantiationService, container, options) {\n return instantiationService.createInstance(StandaloneCodeEditor, container, options);\n }\n getOriginalEditor() {\n return super.getOriginalEditor();\n }\n getModifiedEditor() {\n return super.getModifiedEditor();\n }\n addCommand(keybinding, handler, context) {\n return this.getModifiedEditor().addCommand(keybinding, handler, context);\n }\n createContextKey(key, defaultValue) {\n return this.getModifiedEditor().createContextKey(key, defaultValue);\n }\n addAction(descriptor) {\n return this.getModifiedEditor().addAction(descriptor);\n }\n};\nStandaloneDiffEditor = __decorate([\n __param(2, IInstantiationService),\n __param(3, IContextKeyService),\n __param(4, IEditorWorkerService),\n __param(5, ICodeEditorService),\n __param(6, IStandaloneThemeService),\n __param(7, INotificationService),\n __param(8, IConfigurationService),\n __param(9, IContextMenuService),\n __param(10, IEditorProgressService),\n __param(11, IClipboardService)\n], StandaloneDiffEditor);\nexport { StandaloneDiffEditor };\n/**\n * @internal\n */\nexport function createTextModel(modelService, languageService, value, languageId, uri) {\n value = value || '';\n if (!languageId) {\n const firstLF = value.indexOf('\\n');\n let firstLine = value;\n if (firstLF !== -1) {\n firstLine = value.substring(0, firstLF);\n }\n return doCreateModel(modelService, value, languageService.createByFilepathOrFirstLine(uri || null, firstLine), uri);\n }\n return doCreateModel(modelService, value, languageService.createById(languageId), uri);\n}\n/**\n * @internal\n */\nfunction doCreateModel(modelService, value, languageSelection, uri) {\n return modelService.createModel(value, languageSelection, uri);\n}\n","/*---------------------------------------------------------------------------------------------\n * 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 './standalone-tokens.css';\nimport { splitLines } from '../../../base/common/strings.js';\nimport { FontMeasurements } from '../../browser/config/fontMeasurements.js';\nimport { ICodeEditorService } from '../../browser/services/codeEditorService.js';\nimport { DiffNavigator } from '../../browser/widget/diffNavigator.js';\nimport { ApplyUpdateResult, ConfigurationChangedEvent, EditorOptions } from '../../common/config/editorOptions.js';\nimport { BareFontInfo, FontInfo } from '../../common/config/fontInfo.js';\nimport { EditorType } from '../../common/editorCommon.js';\nimport { FindMatch, TextModelResolvedOptions } from '../../common/model.js';\nimport * as languages from '../../common/languages.js';\nimport { ILanguageConfigurationService } from '../../common/languages/languageConfigurationRegistry.js';\nimport { NullState, nullTokenize } from '../../common/languages/nullTokenize.js';\nimport { ILanguageService } from '../../common/languages/language.js';\nimport { IModelService } from '../../common/services/model.js';\nimport { createWebWorker as actualCreateWebWorker } from '../../browser/services/webWorker.js';\nimport * as standaloneEnums from '../../common/standalone/standaloneEnums.js';\nimport { Colorizer } from './colorizer.js';\nimport { createTextModel, StandaloneDiffEditor, StandaloneEditor } from './standaloneCodeEditor.js';\nimport { StandaloneServices } from './standaloneServices.js';\nimport { IStandaloneThemeService } from '../common/standaloneTheme.js';\nimport { CommandsRegistry } from '../../../platform/commands/common/commands.js';\nimport { IMarkerService } from '../../../platform/markers/common/markers.js';\n/**\n * Create a new editor under `domElement`.\n * `domElement` should be empty (not contain other dom nodes).\n * The editor will read the size of `domElement`.\n */\nexport function create(domElement, options, override) {\n const instantiationService = StandaloneServices.initialize(override || {});\n return instantiationService.createInstance(StandaloneEditor, domElement, options);\n}\n/**\n * Emitted when an editor is created.\n * Creating a diff editor might cause this listener to be invoked with the two editors.\n * @event\n */\nexport function onDidCreateEditor(listener) {\n const codeEditorService = StandaloneServices.get(ICodeEditorService);\n return codeEditorService.onCodeEditorAdd((editor) => {\n listener(editor);\n });\n}\n/**\n * Emitted when an diff editor is created.\n * @event\n */\nexport function onDidCreateDiffEditor(listener) {\n const codeEditorService = StandaloneServices.get(ICodeEditorService);\n return codeEditorService.onDiffEditorAdd((editor) => {\n listener(editor);\n });\n}\n/**\n * Get all the created editors.\n */\nexport function getEditors() {\n const codeEditorService = StandaloneServices.get(ICodeEditorService);\n return codeEditorService.listCodeEditors();\n}\n/**\n * Get all the created diff editors.\n */\nexport function getDiffEditors() {\n const codeEditorService = StandaloneServices.get(ICodeEditorService);\n return codeEditorService.listDiffEditors();\n}\n/**\n * Create a new diff editor under `domElement`.\n * `domElement` should be empty (not contain other dom nodes).\n * The editor will read the size of `domElement`.\n */\nexport function createDiffEditor(domElement, options, override) {\n const instantiationService = StandaloneServices.initialize(override || {});\n return instantiationService.createInstance(StandaloneDiffEditor, domElement, options);\n}\nexport function createDiffNavigator(diffEditor, opts) {\n return new DiffNavigator(diffEditor, opts);\n}\n/**\n * Create a new editor model.\n * You can specify the language that should be set for this model or let the language be inferred from the `uri`.\n */\nexport function createModel(value, language, uri) {\n const languageService = StandaloneServices.get(ILanguageService);\n const languageId = languageService.getLanguageIdByMimeType(language) || language;\n return createTextModel(StandaloneServices.get(IModelService), languageService, value, languageId, uri);\n}\n/**\n * Change the language for a model.\n */\nexport function setModelLanguage(model, languageId) {\n const languageService = StandaloneServices.get(ILanguageService);\n const modelService = StandaloneServices.get(IModelService);\n modelService.setMode(model, languageService.createById(languageId));\n}\n/**\n * Set the markers for a model.\n */\nexport function setModelMarkers(model, owner, markers) {\n if (model) {\n const markerService = StandaloneServices.get(IMarkerService);\n markerService.changeOne(owner, model.uri, markers);\n }\n}\n/**\n * Remove all markers of an owner.\n */\nexport function removeAllMarkers(owner) {\n const markerService = StandaloneServices.get(IMarkerService);\n markerService.changeAll(owner, []);\n}\n/**\n * Get markers for owner and/or resource\n *\n * @returns list of markers\n */\nexport function getModelMarkers(filter) {\n const markerService = StandaloneServices.get(IMarkerService);\n return markerService.read(filter);\n}\n/**\n * Emitted when markers change for a model.\n * @event\n */\nexport function onDidChangeMarkers(listener) {\n const markerService = StandaloneServices.get(IMarkerService);\n return markerService.onMarkerChanged(listener);\n}\n/**\n * Get the model that has `uri` if it exists.\n */\nexport function getModel(uri) {\n const modelService = StandaloneServices.get(IModelService);\n return modelService.getModel(uri);\n}\n/**\n * Get all the created models.\n */\nexport function getModels() {\n const modelService = StandaloneServices.get(IModelService);\n return modelService.getModels();\n}\n/**\n * Emitted when a model is created.\n * @event\n */\nexport function onDidCreateModel(listener) {\n const modelService = StandaloneServices.get(IModelService);\n return modelService.onModelAdded(listener);\n}\n/**\n * Emitted right before a model is disposed.\n * @event\n */\nexport function onWillDisposeModel(listener) {\n const modelService = StandaloneServices.get(IModelService);\n return modelService.onModelRemoved(listener);\n}\n/**\n * Emitted when a different language is set to a model.\n * @event\n */\nexport function onDidChangeModelLanguage(listener) {\n const modelService = StandaloneServices.get(IModelService);\n return modelService.onModelLanguageChanged((e) => {\n listener({\n model: e.model,\n oldLanguage: e.oldLanguageId\n });\n });\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(opts) {\n return actualCreateWebWorker(StandaloneServices.get(IModelService), StandaloneServices.get(ILanguageConfigurationService), opts);\n}\n/**\n * Colorize the contents of `domNode` using attribute `data-lang`.\n */\nexport function colorizeElement(domNode, options) {\n const languageService = StandaloneServices.get(ILanguageService);\n const themeService = StandaloneServices.get(IStandaloneThemeService);\n themeService.registerEditorContainer(domNode);\n return Colorizer.colorizeElement(themeService, languageService, domNode, options);\n}\n/**\n * Colorize `text` using language `languageId`.\n */\nexport function colorize(text, languageId, options) {\n const languageService = StandaloneServices.get(ILanguageService);\n const themeService = StandaloneServices.get(IStandaloneThemeService);\n themeService.registerEditorContainer(document.body);\n return Colorizer.colorize(languageService, text, languageId, options);\n}\n/**\n * Colorize a line in a model.\n */\nexport function colorizeModelLine(model, lineNumber, tabSize = 4) {\n const themeService = StandaloneServices.get(IStandaloneThemeService);\n themeService.registerEditorContainer(document.body);\n return Colorizer.colorizeModelLine(model, lineNumber, tabSize);\n}\n/**\n * @internal\n */\nfunction getSafeTokenizationSupport(language) {\n const tokenizationSupport = languages.TokenizationRegistry.get(language);\n if (tokenizationSupport) {\n return tokenizationSupport;\n }\n return {\n getInitialState: () => NullState,\n tokenize: (line, hasEOL, state) => nullTokenize(language, state)\n };\n}\n/**\n * Tokenize `text` using language `languageId`\n */\nexport function tokenize(text, languageId) {\n // Needed in order to get the mode registered for subsequent look-ups\n languages.TokenizationRegistry.getOrCreate(languageId);\n const tokenizationSupport = getSafeTokenizationSupport(languageId);\n const lines = splitLines(text);\n const result = [];\n let state = tokenizationSupport.getInitialState();\n for (let i = 0, len = lines.length; i < len; i++) {\n const line = lines[i];\n const tokenizationResult = tokenizationSupport.tokenize(line, true, state);\n result[i] = tokenizationResult.tokens;\n state = tokenizationResult.endState;\n }\n return result;\n}\n/**\n * Define a new theme or update an existing theme.\n */\nexport function defineTheme(themeName, themeData) {\n const standaloneThemeService = StandaloneServices.get(IStandaloneThemeService);\n standaloneThemeService.defineTheme(themeName, themeData);\n}\n/**\n * Switches to a theme.\n */\nexport function setTheme(themeName) {\n const standaloneThemeService = StandaloneServices.get(IStandaloneThemeService);\n standaloneThemeService.setTheme(themeName);\n}\n/**\n * Clears all cached font measurements and triggers re-measurement.\n */\nexport function remeasureFonts() {\n FontMeasurements.clearAllFontInfos();\n}\n/**\n * Register a command.\n */\nexport function registerCommand(id, handler) {\n return CommandsRegistry.registerCommand({ id, handler });\n}\n/**\n * @internal\n */\nexport function createMonacoEditorAPI() {\n return {\n // methods\n create: create,\n getEditors: getEditors,\n getDiffEditors: getDiffEditors,\n onDidCreateEditor: onDidCreateEditor,\n onDidCreateDiffEditor: onDidCreateDiffEditor,\n createDiffEditor: createDiffEditor,\n createDiffNavigator: createDiffNavigator,\n createModel: createModel,\n setModelLanguage: setModelLanguage,\n setModelMarkers: setModelMarkers,\n getModelMarkers: getModelMarkers,\n removeAllMarkers: removeAllMarkers,\n onDidChangeMarkers: onDidChangeMarkers,\n getModels: getModels,\n getModel: getModel,\n onDidCreateModel: onDidCreateModel,\n onWillDisposeModel: onWillDisposeModel,\n onDidChangeModelLanguage: onDidChangeModelLanguage,\n createWebWorker: createWebWorker,\n colorizeElement: colorizeElement,\n colorize: colorize,\n colorizeModelLine: colorizeModelLine,\n tokenize: tokenize,\n defineTheme: defineTheme,\n setTheme: setTheme,\n remeasureFonts: remeasureFonts,\n registerCommand: registerCommand,\n // enums\n AccessibilitySupport: standaloneEnums.AccessibilitySupport,\n ContentWidgetPositionPreference: standaloneEnums.ContentWidgetPositionPreference,\n CursorChangeReason: standaloneEnums.CursorChangeReason,\n DefaultEndOfLine: standaloneEnums.DefaultEndOfLine,\n EditorAutoIndentStrategy: standaloneEnums.EditorAutoIndentStrategy,\n EditorOption: standaloneEnums.EditorOption,\n EndOfLinePreference: standaloneEnums.EndOfLinePreference,\n EndOfLineSequence: standaloneEnums.EndOfLineSequence,\n MinimapPosition: standaloneEnums.MinimapPosition,\n MouseTargetType: standaloneEnums.MouseTargetType,\n OverlayWidgetPositionPreference: standaloneEnums.OverlayWidgetPositionPreference,\n OverviewRulerLane: standaloneEnums.OverviewRulerLane,\n RenderLineNumbersType: standaloneEnums.RenderLineNumbersType,\n RenderMinimap: standaloneEnums.RenderMinimap,\n ScrollbarVisibility: standaloneEnums.ScrollbarVisibility,\n ScrollType: standaloneEnums.ScrollType,\n TextEditorCursorBlinkingStyle: standaloneEnums.TextEditorCursorBlinkingStyle,\n TextEditorCursorStyle: standaloneEnums.TextEditorCursorStyle,\n TrackedRangeStickiness: standaloneEnums.TrackedRangeStickiness,\n WrappingIndent: standaloneEnums.WrappingIndent,\n InjectedTextCursorStops: standaloneEnums.InjectedTextCursorStops,\n PositionAffinity: standaloneEnums.PositionAffinity,\n // classes\n ConfigurationChangedEvent: ConfigurationChangedEvent,\n BareFontInfo: BareFontInfo,\n FontInfo: FontInfo,\n TextModelResolvedOptions: TextModelResolvedOptions,\n FindMatch: FindMatch,\n ApplyUpdateResult: ApplyUpdateResult,\n // vars\n EditorType: EditorType,\n EditorOptions: EditorOptions\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/*\n * This module only exports 'compile' which compiles a JSON language definition\n * into a typed and checked ILexer definition.\n */\nimport * as monarchCommon from './monarchCommon.js';\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 */\nfunction isArrayOf(elemType, obj) {\n if (!obj) {\n return false;\n }\n if (!(Array.isArray(obj))) {\n return false;\n }\n for (const el of obj) {\n if (!(elemType(el))) {\n return false;\n }\n }\n return true;\n}\nfunction bool(prop, defValue) {\n if (typeof prop === 'boolean') {\n return prop;\n }\n return defValue;\n}\nfunction string(prop, defValue) {\n if (typeof (prop) === 'string') {\n return prop;\n }\n return defValue;\n}\nfunction arrayToHash(array) {\n const result = {};\n for (const e of array) {\n result[e] = true;\n }\n return result;\n}\nfunction createKeywordMatcher(arr, caseInsensitive = false) {\n if (caseInsensitive) {\n arr = arr.map(function (x) { return x.toLowerCase(); });\n }\n const hash = arrayToHash(arr);\n if (caseInsensitive) {\n return function (word) {\n return hash[word.toLowerCase()] !== undefined && hash.hasOwnProperty(word.toLowerCase());\n };\n }\n else {\n return function (word) {\n return hash[word] !== undefined && hash.hasOwnProperty(word);\n };\n }\n}\n// Lexer helpers\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, str) {\n // @@ must be interpreted as a literal @, so we replace all occurences of @@ with a placeholder character\n str = str.replace(/@@/g, `\\x01`);\n let n = 0;\n let hadExpansion;\n do {\n hadExpansion = false;\n str = str.replace(/@(\\w+)/g, function (s, attr) {\n hadExpansion = true;\n let sub = '';\n if (typeof (lexer[attr]) === 'string') {\n sub = lexer[attr];\n }\n else if (lexer[attr] && lexer[attr] instanceof RegExp) {\n sub = lexer[attr].source;\n }\n else {\n if (lexer[attr] === undefined) {\n throw monarchCommon.createError(lexer, 'language definition does not contain attribute \\'' + attr + '\\', used at: ' + str);\n }\n else {\n throw monarchCommon.createError(lexer, 'attribute reference \\'' + attr + '\\' must be a string, used at: ' + str);\n }\n }\n return (monarchCommon.empty(sub) ? '' : '(?:' + sub + ')');\n });\n n++;\n } while (hadExpansion && n < 5);\n // handle escaped @@\n str = str.replace(/\\x01/g, '@');\n const flags = (lexer.ignoreCase ? 'i' : '') + (lexer.unicode ? 'u' : '');\n return new RegExp(str, flags);\n}\n/**\n * Compiles guard functions for case matches.\n * This compiles 'cases' attributes into efficient match functions.\n *\n */\nfunction selectScrutinee(id, matches, state, num) {\n if (num < 0) {\n return id;\n }\n if (num < matches.length) {\n return matches[num];\n }\n if (num >= 100) {\n num = num - 100;\n const parts = state.split('.');\n parts.unshift(state);\n if (num < parts.length) {\n return parts[num];\n }\n }\n return null;\n}\nfunction createGuard(lexer, ruleName, tkey, val) {\n // get the scrutinee and pattern\n let scrut = -1; // -1: $!, 0-99: $n, 100+n: $Sn\n let oppat = tkey;\n let matches = tkey.match(/^\\$(([sS]?)(\\d\\d?)|#)(.*)$/);\n if (matches) {\n if (matches[3]) { // if digits\n scrut = parseInt(matches[3]);\n if (matches[2]) {\n scrut = scrut + 100; // if [sS] present\n }\n }\n oppat = matches[4];\n }\n // get operator\n let op = '~';\n let pat = oppat;\n if (!oppat || oppat.length === 0) {\n op = '!=';\n pat = '';\n }\n else if (/^\\w*$/.test(pat)) { // just a word\n op = '==';\n }\n else {\n matches = oppat.match(/^(@|!@|~|!~|==|!=)(.*)$/);\n if (matches) {\n op = matches[1];\n pat = matches[2];\n }\n }\n // set the tester function\n let tester;\n // special case a regexp that matches just words\n if ((op === '~' || op === '!~') && /^(\\w|\\|)*$/.test(pat)) {\n const inWords = createKeywordMatcher(pat.split('|'), lexer.ignoreCase);\n tester = function (s) { return (op === '~' ? inWords(s) : !inWords(s)); };\n }\n else if (op === '@' || op === '!@') {\n const words = lexer[pat];\n if (!words) {\n throw monarchCommon.createError(lexer, 'the @ match target \\'' + pat + '\\' is not defined, in rule: ' + ruleName);\n }\n if (!(isArrayOf(function (elem) { return (typeof (elem) === 'string'); }, words))) {\n throw monarchCommon.createError(lexer, 'the @ match target \\'' + pat + '\\' must be an array of strings, in rule: ' + ruleName);\n }\n const inWords = createKeywordMatcher(words, lexer.ignoreCase);\n tester = function (s) { return (op === '@' ? inWords(s) : !inWords(s)); };\n }\n else if (op === '~' || op === '!~') {\n if (pat.indexOf('$') < 0) {\n // precompile regular expression\n const re = compileRegExp(lexer, '^' + pat + '$');\n tester = function (s) { return (op === '~' ? re.test(s) : !re.test(s)); };\n }\n else {\n tester = function (s, id, matches, state) {\n const re = compileRegExp(lexer, '^' + monarchCommon.substituteMatches(lexer, pat, id, matches, state) + '$');\n return re.test(s);\n };\n }\n }\n else { // if (op==='==' || op==='!=') {\n if (pat.indexOf('$') < 0) {\n const patx = monarchCommon.fixCase(lexer, pat);\n tester = function (s) { return (op === '==' ? s === patx : s !== patx); };\n }\n else {\n const patx = monarchCommon.fixCase(lexer, pat);\n tester = function (s, id, matches, state, eos) {\n const patexp = monarchCommon.substituteMatches(lexer, patx, id, matches, state);\n return (op === '==' ? s === patexp : s !== patexp);\n };\n }\n }\n // return the branch object\n if (scrut === -1) {\n return {\n name: tkey, value: val, test: function (id, matches, state, eos) {\n return tester(id, id, matches, state, eos);\n }\n };\n }\n else {\n return {\n name: tkey, value: val, test: function (id, matches, state, eos) {\n const scrutinee = selectScrutinee(id, matches, state, scrut);\n return tester(!scrutinee ? '' : scrutinee, id, matches, state, eos);\n }\n };\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, ruleName, action) {\n if (!action) {\n return { token: '' };\n }\n else if (typeof (action) === 'string') {\n return action; // { token: action };\n }\n else if (action.token || action.token === '') {\n if (typeof (action.token) !== 'string') {\n throw monarchCommon.createError(lexer, 'a \\'token\\' attribute must be of type string, in rule: ' + ruleName);\n }\n else {\n // only copy specific typed fields (only happens once during compile Lexer)\n const newAction = { token: action.token };\n if (action.token.indexOf('$') >= 0) {\n newAction.tokenSubst = true;\n }\n if (typeof (action.bracket) === 'string') {\n if (action.bracket === '@open') {\n newAction.bracket = 1 /* monarchCommon.MonarchBracket.Open */;\n }\n else if (action.bracket === '@close') {\n newAction.bracket = -1 /* monarchCommon.MonarchBracket.Close */;\n }\n else {\n throw monarchCommon.createError(lexer, 'a \\'bracket\\' attribute must be either \\'@open\\' or \\'@close\\', in rule: ' + ruleName);\n }\n }\n if (action.next) {\n if (typeof (action.next) !== 'string') {\n throw monarchCommon.createError(lexer, 'the next state must be a string value in rule: ' + ruleName);\n }\n else {\n let next = action.next;\n if (!/^(@pop|@push|@popall)$/.test(next)) {\n if (next[0] === '@') {\n next = next.substr(1); // peel off starting @ sign\n }\n if (next.indexOf('$') < 0) { // no dollar substitution, we can check if the state exists\n if (!monarchCommon.stateExists(lexer, monarchCommon.substituteMatches(lexer, next, '', [], ''))) {\n throw monarchCommon.createError(lexer, 'the next state \\'' + action.next + '\\' is not defined in rule: ' + ruleName);\n }\n }\n }\n newAction.next = next;\n }\n }\n if (typeof (action.goBack) === 'number') {\n newAction.goBack = action.goBack;\n }\n if (typeof (action.switchTo) === 'string') {\n newAction.switchTo = action.switchTo;\n }\n if (typeof (action.log) === 'string') {\n newAction.log = action.log;\n }\n if (typeof (action.nextEmbedded) === 'string') {\n newAction.nextEmbedded = action.nextEmbedded;\n lexer.usesEmbedded = true;\n }\n return newAction;\n }\n }\n else if (Array.isArray(action)) {\n const results = [];\n for (let i = 0, len = action.length; i < len; i++) {\n results[i] = compileAction(lexer, ruleName, action[i]);\n }\n return { group: results };\n }\n else if (action.cases) {\n // build an array of test cases\n const cases = [];\n // for each case, push a test function and result value\n for (const tkey in action.cases) {\n if (action.cases.hasOwnProperty(tkey)) {\n const val = compileAction(lexer, ruleName, action.cases[tkey]);\n // what kind of case\n if (tkey === '@default' || tkey === '@' || tkey === '') {\n cases.push({ test: undefined, value: val, name: tkey });\n }\n else if (tkey === '@eos') {\n cases.push({ test: function (id, matches, state, eos) { return eos; }, value: val, name: tkey });\n }\n else {\n cases.push(createGuard(lexer, ruleName, tkey, val)); // call separate function to avoid local variable capture\n }\n }\n }\n // create a matching function\n const def = lexer.defaultToken;\n return {\n test: function (id, matches, state, eos) {\n for (const _case of cases) {\n const didmatch = (!_case.test || _case.test(id, matches, state, eos));\n if (didmatch) {\n return _case.value;\n }\n }\n return def;\n }\n };\n }\n else {\n throw 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 }\n}\n/**\n * Helper class for creating matching rules\n */\nclass Rule {\n constructor(name) {\n this.regex = new RegExp('');\n this.action = { token: '' };\n this.matchOnlyAtLineStart = false;\n this.name = '';\n this.name = name;\n }\n setRegex(lexer, re) {\n let sregex;\n if (typeof (re) === 'string') {\n sregex = re;\n }\n else if (re instanceof RegExp) {\n sregex = re.source;\n }\n else {\n throw monarchCommon.createError(lexer, 'rules must start with a match string or regular expression: ' + this.name);\n }\n this.matchOnlyAtLineStart = (sregex.length > 0 && sregex[0] === '^');\n this.name = this.name + ': ' + sregex;\n this.regex = compileRegExp(lexer, '^(?:' + (this.matchOnlyAtLineStart ? sregex.substr(1) : sregex) + ')');\n }\n setAction(lexer, act) {\n this.action = compileAction(lexer, this.name, act);\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, json) {\n if (!json || typeof (json) !== 'object') {\n throw new Error('Monarch: expecting a language definition object');\n }\n // Create our lexer\n const lexer = {};\n lexer.languageId = languageId;\n lexer.includeLF = bool(json.includeLF, false);\n lexer.noThrow = false; // raise exceptions during compilation\n lexer.maxStack = 100;\n // Set standard fields: be defensive about types\n lexer.start = (typeof json.start === 'string' ? json.start : null);\n lexer.ignoreCase = bool(json.ignoreCase, false);\n lexer.unicode = bool(json.unicode, false);\n lexer.tokenPostfix = string(json.tokenPostfix, '.' + lexer.languageId);\n lexer.defaultToken = string(json.defaultToken, 'source');\n lexer.usesEmbedded = false; // becomes true if we find a nextEmbedded action\n // For calling compileAction later on\n const lexerMin = json;\n lexerMin.languageId = languageId;\n lexerMin.includeLF = lexer.includeLF;\n lexerMin.ignoreCase = lexer.ignoreCase;\n lexerMin.unicode = lexer.unicode;\n lexerMin.noThrow = lexer.noThrow;\n lexerMin.usesEmbedded = lexer.usesEmbedded;\n lexerMin.stateNames = json.tokenizer;\n lexerMin.defaultToken = lexer.defaultToken;\n // Compile an array of rules into newrules where RegExp objects are created.\n function addRules(state, newrules, rules) {\n for (const rule of rules) {\n let include = rule.include;\n if (include) {\n if (typeof (include) !== 'string') {\n throw monarchCommon.createError(lexer, 'an \\'include\\' attribute must be a string at: ' + state);\n }\n if (include[0] === '@') {\n include = include.substr(1); // peel off starting @\n }\n if (!json.tokenizer[include]) {\n throw monarchCommon.createError(lexer, 'include target \\'' + include + '\\' is not defined at: ' + state);\n }\n addRules(state + '.' + include, newrules, json.tokenizer[include]);\n }\n else {\n const newrule = new Rule(state);\n // Set up new rule attributes\n if (Array.isArray(rule) && rule.length >= 1 && rule.length <= 3) {\n newrule.setRegex(lexerMin, rule[0]);\n if (rule.length >= 3) {\n if (typeof (rule[1]) === 'string') {\n newrule.setAction(lexerMin, { token: rule[1], next: rule[2] });\n }\n else if (typeof (rule[1]) === 'object') {\n const rule1 = rule[1];\n rule1.next = rule[2];\n newrule.setAction(lexerMin, rule1);\n }\n else {\n throw 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 }\n }\n else {\n newrule.setAction(lexerMin, rule[1]);\n }\n }\n else {\n if (!rule.regex) {\n throw monarchCommon.createError(lexer, 'a rule must either be an array, or an object with a \\'regex\\' or \\'include\\' field at: ' + state);\n }\n if (rule.name) {\n if (typeof rule.name === 'string') {\n newrule.name = rule.name;\n }\n }\n if (rule.matchOnlyAtStart) {\n newrule.matchOnlyAtLineStart = bool(rule.matchOnlyAtLineStart, false);\n }\n newrule.setRegex(lexerMin, rule.regex);\n newrule.setAction(lexerMin, rule.action);\n }\n newrules.push(newrule);\n }\n }\n }\n // compile the tokenizer rules\n if (!json.tokenizer || typeof (json.tokenizer) !== 'object') {\n throw monarchCommon.createError(lexer, 'a language definition must define the \\'tokenizer\\' attribute as an object');\n }\n lexer.tokenizer = [];\n for (const key in json.tokenizer) {\n if (json.tokenizer.hasOwnProperty(key)) {\n if (!lexer.start) {\n lexer.start = key;\n }\n const rules = json.tokenizer[key];\n lexer.tokenizer[key] = new Array();\n addRules('tokenizer.' + key, lexer.tokenizer[key], rules);\n }\n }\n lexer.usesEmbedded = lexerMin.usesEmbedded; // can be set during compileAction\n // Set simple brackets\n if (json.brackets) {\n if (!(Array.isArray(json.brackets))) {\n throw monarchCommon.createError(lexer, 'the \\'brackets\\' attribute must be defined as an array');\n }\n }\n else {\n json.brackets = [\n { open: '{', close: '}', token: 'delimiter.curly' },\n { open: '[', close: ']', token: 'delimiter.square' },\n { open: '(', close: ')', token: 'delimiter.parenthesis' },\n { open: '<', close: '>', token: 'delimiter.angle' }\n ];\n }\n const brackets = [];\n for (const el of json.brackets) {\n let desc = el;\n if (desc && Array.isArray(desc) && desc.length === 3) {\n desc = { token: desc[2], open: desc[0], close: desc[1] };\n }\n if (desc.open === desc.close) {\n throw monarchCommon.createError(lexer, 'open and close brackets in a \\'brackets\\' attribute must be different: ' + desc.open +\n '\\n hint: use the \\'bracket\\' attribute if matching on equal brackets is required.');\n }\n if (typeof desc.open === 'string' && typeof desc.token === 'string' && typeof desc.close === 'string') {\n brackets.push({\n token: desc.token + lexer.tokenPostfix,\n open: monarchCommon.fixCase(lexer, desc.open),\n close: monarchCommon.fixCase(lexer, desc.close)\n });\n }\n else {\n throw monarchCommon.createError(lexer, 'every element in the \\'brackets\\' array must be a \\'{open,close,token}\\' object or array');\n }\n }\n lexer.brackets = brackets;\n // Disable throw so the syntax highlighter goes, no matter what\n lexer.noThrow = true;\n return 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 *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { Color } from '../../../base/common/color.js';\nimport { Range } from '../../common/core/range.js';\nimport * as languages from '../../common/languages.js';\nimport { ILanguageConfigurationService } from '../../common/languages/languageConfigurationRegistry.js';\nimport { ModesRegistry } from '../../common/languages/modesRegistry.js';\nimport { ILanguageService } from '../../common/languages/language.js';\nimport * as standaloneEnums from '../../common/standalone/standaloneEnums.js';\nimport { StandaloneServices } from './standaloneServices.js';\nimport { compile } from '../common/monarch/monarchCompile.js';\nimport { MonarchTokenizer } from '../common/monarch/monarchLexer.js';\nimport { IStandaloneThemeService } from '../common/standaloneTheme.js';\nimport { IMarkerService } from '../../../platform/markers/common/markers.js';\nimport { ILanguageFeaturesService } from '../../common/services/languageFeatures.js';\nimport { IConfigurationService } from '../../../platform/configuration/common/configuration.js';\n/**\n * Register information about a new language.\n */\nexport function register(language) {\n // Intentionally using the `ModesRegistry` here to avoid\n // instantiating services too quickly in the standalone editor.\n ModesRegistry.registerLanguage(language);\n}\n/**\n * Get the information of all the registered languages.\n */\nexport function getLanguages() {\n let result = [];\n result = result.concat(ModesRegistry.getLanguages());\n return result;\n}\nexport function getEncodedLanguageId(languageId) {\n const languageService = StandaloneServices.get(ILanguageService);\n return languageService.languageIdCodec.encodeLanguageId(languageId);\n}\n/**\n * An event emitted when a language is needed for the first time (e.g. a model has it set).\n * @event\n */\nexport function onLanguage(languageId, callback) {\n const languageService = StandaloneServices.get(ILanguageService);\n const disposable = languageService.onDidEncounterLanguage((encounteredLanguageId) => {\n if (encounteredLanguageId === languageId) {\n // stop listening\n disposable.dispose();\n // invoke actual listener\n callback();\n }\n });\n return disposable;\n}\n/**\n * Set the editing configuration for a language.\n */\nexport function setLanguageConfiguration(languageId, configuration) {\n const languageService = StandaloneServices.get(ILanguageService);\n if (!languageService.isRegisteredLanguageId(languageId)) {\n throw new Error(`Cannot set configuration for unknown language ${languageId}`);\n }\n const languageConfigurationService = StandaloneServices.get(ILanguageConfigurationService);\n return languageConfigurationService.register(languageId, configuration, 100);\n}\n/**\n * @internal\n */\nexport class EncodedTokenizationSupportAdapter {\n constructor(languageId, actual) {\n this._languageId = languageId;\n this._actual = actual;\n }\n getInitialState() {\n return this._actual.getInitialState();\n }\n tokenize(line, hasEOL, state) {\n if (typeof this._actual.tokenize === 'function') {\n return TokenizationSupportAdapter.adaptTokenize(this._languageId, this._actual, line, state);\n }\n throw new Error('Not supported!');\n }\n tokenizeEncoded(line, hasEOL, state) {\n const result = this._actual.tokenizeEncoded(line, state);\n return new languages.EncodedTokenizationResult(result.tokens, result.endState);\n }\n}\n/**\n * @internal\n */\nexport class TokenizationSupportAdapter {\n constructor(_languageId, _actual, _languageService, _standaloneThemeService) {\n this._languageId = _languageId;\n this._actual = _actual;\n this._languageService = _languageService;\n this._standaloneThemeService = _standaloneThemeService;\n }\n getInitialState() {\n return this._actual.getInitialState();\n }\n static _toClassicTokens(tokens, language) {\n const result = [];\n let previousStartIndex = 0;\n for (let i = 0, len = tokens.length; i < len; i++) {\n const t = tokens[i];\n let startIndex = t.startIndex;\n // Prevent issues stemming from a buggy external tokenizer.\n if (i === 0) {\n // Force first token to start at first index!\n startIndex = 0;\n }\n else if (startIndex < previousStartIndex) {\n // Force tokens to be after one another!\n startIndex = previousStartIndex;\n }\n result[i] = new languages.Token(startIndex, t.scopes, language);\n previousStartIndex = startIndex;\n }\n return result;\n }\n static adaptTokenize(language, actual, line, state) {\n const actualResult = actual.tokenize(line, state);\n const tokens = TokenizationSupportAdapter._toClassicTokens(actualResult.tokens, language);\n let endState;\n // try to save an object if possible\n if (actualResult.endState.equals(state)) {\n endState = state;\n }\n else {\n endState = actualResult.endState;\n }\n return new languages.TokenizationResult(tokens, endState);\n }\n tokenize(line, hasEOL, state) {\n return TokenizationSupportAdapter.adaptTokenize(this._languageId, this._actual, line, state);\n }\n _toBinaryTokens(languageIdCodec, tokens) {\n const languageId = languageIdCodec.encodeLanguageId(this._languageId);\n const tokenTheme = this._standaloneThemeService.getColorTheme().tokenTheme;\n const result = [];\n let resultLen = 0;\n let previousStartIndex = 0;\n for (let i = 0, len = tokens.length; i < len; i++) {\n const t = tokens[i];\n const metadata = tokenTheme.match(languageId, t.scopes);\n if (resultLen > 0 && result[resultLen - 1] === metadata) {\n // same metadata\n continue;\n }\n let startIndex = t.startIndex;\n // Prevent issues stemming from a buggy external tokenizer.\n if (i === 0) {\n // Force first token to start at first index!\n startIndex = 0;\n }\n else if (startIndex < previousStartIndex) {\n // Force tokens to be after one another!\n startIndex = previousStartIndex;\n }\n result[resultLen++] = startIndex;\n result[resultLen++] = metadata;\n previousStartIndex = startIndex;\n }\n const actualResult = new Uint32Array(resultLen);\n for (let i = 0; i < resultLen; i++) {\n actualResult[i] = result[i];\n }\n return actualResult;\n }\n tokenizeEncoded(line, hasEOL, state) {\n const actualResult = this._actual.tokenize(line, state);\n const tokens = this._toBinaryTokens(this._languageService.languageIdCodec, actualResult.tokens);\n let endState;\n // try to save an object if possible\n if (actualResult.endState.equals(state)) {\n endState = state;\n }\n else {\n endState = actualResult.endState;\n }\n return new languages.EncodedTokenizationResult(tokens, endState);\n }\n}\nfunction isATokensProvider(provider) {\n return (typeof provider.getInitialState === 'function');\n}\nfunction isEncodedTokensProvider(provider) {\n return 'tokenizeEncoded' in provider;\n}\nfunction isThenable(obj) {\n return obj && typeof obj.then === 'function';\n}\n/**\n * Change the color map that is used for token colors.\n * Supported formats (hex): #RRGGBB, $RRGGBBAA, #RGB, #RGBA\n */\nexport function setColorMap(colorMap) {\n const standaloneThemeService = StandaloneServices.get(IStandaloneThemeService);\n if (colorMap) {\n const result = [null];\n for (let i = 1, len = colorMap.length; i < len; i++) {\n result[i] = Color.fromHex(colorMap[i]);\n }\n standaloneThemeService.setColorMapOverride(result);\n }\n else {\n standaloneThemeService.setColorMapOverride(null);\n }\n}\n/**\n * @internal\n */\nfunction createTokenizationSupportAdapter(languageId, provider) {\n if (isEncodedTokensProvider(provider)) {\n return new EncodedTokenizationSupportAdapter(languageId, provider);\n }\n else {\n return new TokenizationSupportAdapter(languageId, provider, StandaloneServices.get(ILanguageService), StandaloneServices.get(IStandaloneThemeService));\n }\n}\n/**\n * Register a tokens provider factory for a language. This tokenizer will be exclusive with a tokenizer\n * set using `setTokensProvider` or one created using `setMonarchTokensProvider`, but will work together\n * with a tokens provider set using `registerDocumentSemanticTokensProvider` or `registerDocumentRangeSemanticTokensProvider`.\n */\nexport function registerTokensProviderFactory(languageId, factory) {\n const adaptedFactory = {\n createTokenizationSupport: () => __awaiter(this, void 0, void 0, function* () {\n const result = yield Promise.resolve(factory.create());\n if (!result) {\n return null;\n }\n if (isATokensProvider(result)) {\n return createTokenizationSupportAdapter(languageId, result);\n }\n return new MonarchTokenizer(StandaloneServices.get(ILanguageService), StandaloneServices.get(IStandaloneThemeService), languageId, compile(languageId, result), StandaloneServices.get(IConfigurationService));\n })\n };\n return languages.TokenizationRegistry.registerFactory(languageId, adaptedFactory);\n}\n/**\n * Set the tokens provider for a language (manual implementation). This tokenizer will be exclusive\n * with a tokenizer created using `setMonarchTokensProvider`, or with `registerTokensProviderFactory`,\n * but will work together with a tokens provider set using `registerDocumentSemanticTokensProvider`\n * or `registerDocumentRangeSemanticTokensProvider`.\n */\nexport function setTokensProvider(languageId, provider) {\n const languageService = StandaloneServices.get(ILanguageService);\n if (!languageService.isRegisteredLanguageId(languageId)) {\n throw new Error(`Cannot set tokens provider for unknown language ${languageId}`);\n }\n if (isThenable(provider)) {\n return registerTokensProviderFactory(languageId, { create: () => provider });\n }\n return languages.TokenizationRegistry.register(languageId, createTokenizationSupportAdapter(languageId, provider));\n}\n/**\n * Set the tokens provider for a language (monarch implementation). This tokenizer will be exclusive\n * with a tokenizer set using `setTokensProvider`, or with `registerTokensProviderFactory`, but will\n * work together with a tokens provider set using `registerDocumentSemanticTokensProvider` or\n * `registerDocumentRangeSemanticTokensProvider`.\n */\nexport function setMonarchTokensProvider(languageId, languageDef) {\n const create = (languageDef) => {\n return new MonarchTokenizer(StandaloneServices.get(ILanguageService), StandaloneServices.get(IStandaloneThemeService), languageId, compile(languageId, languageDef), StandaloneServices.get(IConfigurationService));\n };\n if (isThenable(languageDef)) {\n return registerTokensProviderFactory(languageId, { create: () => languageDef });\n }\n return languages.TokenizationRegistry.register(languageId, create(languageDef));\n}\n/**\n * Register a reference provider (used by e.g. reference search).\n */\nexport function registerReferenceProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.referenceProvider.register(languageSelector, provider);\n}\n/**\n * Register a rename provider (used by e.g. rename symbol).\n */\nexport function registerRenameProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.renameProvider.register(languageSelector, provider);\n}\n/**\n * Register a signature help provider (used by e.g. parameter hints).\n */\nexport function registerSignatureHelpProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.signatureHelpProvider.register(languageSelector, provider);\n}\n/**\n * Register a hover provider (used by e.g. editor hover).\n */\nexport function registerHoverProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.hoverProvider.register(languageSelector, {\n provideHover: (model, position, token) => {\n const word = model.getWordAtPosition(position);\n return Promise.resolve(provider.provideHover(model, position, token)).then((value) => {\n if (!value) {\n return undefined;\n }\n if (!value.range && word) {\n value.range = new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn);\n }\n if (!value.range) {\n value.range = new Range(position.lineNumber, position.column, position.lineNumber, position.column);\n }\n return value;\n });\n }\n });\n}\n/**\n * Register a document symbol provider (used by e.g. outline).\n */\nexport function registerDocumentSymbolProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.documentSymbolProvider.register(languageSelector, provider);\n}\n/**\n * Register a document highlight provider (used by e.g. highlight occurrences).\n */\nexport function registerDocumentHighlightProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.documentHighlightProvider.register(languageSelector, provider);\n}\n/**\n * Register an linked editing range provider.\n */\nexport function registerLinkedEditingRangeProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.linkedEditingRangeProvider.register(languageSelector, provider);\n}\n/**\n * Register a definition provider (used by e.g. go to definition).\n */\nexport function registerDefinitionProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.definitionProvider.register(languageSelector, provider);\n}\n/**\n * Register a implementation provider (used by e.g. go to implementation).\n */\nexport function registerImplementationProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.implementationProvider.register(languageSelector, provider);\n}\n/**\n * Register a type definition provider (used by e.g. go to type definition).\n */\nexport function registerTypeDefinitionProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.typeDefinitionProvider.register(languageSelector, provider);\n}\n/**\n * Register a code lens provider (used by e.g. inline code lenses).\n */\nexport function registerCodeLensProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.codeLensProvider.register(languageSelector, provider);\n}\n/**\n * Register a code action provider (used by e.g. quick fix).\n */\nexport function registerCodeActionProvider(languageSelector, provider, metadata) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.codeActionProvider.register(languageSelector, {\n providedCodeActionKinds: metadata === null || metadata === void 0 ? void 0 : metadata.providedCodeActionKinds,\n documentation: metadata === null || metadata === void 0 ? void 0 : metadata.documentation,\n provideCodeActions: (model, range, context, token) => {\n const markerService = StandaloneServices.get(IMarkerService);\n const markers = markerService.read({ resource: model.uri }).filter(m => {\n return Range.areIntersectingOrTouching(m, range);\n });\n return provider.provideCodeActions(model, range, { markers, only: context.only, trigger: context.trigger }, token);\n },\n resolveCodeAction: provider.resolveCodeAction\n });\n}\n/**\n * Register a formatter that can handle only entire models.\n */\nexport function registerDocumentFormattingEditProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.documentFormattingEditProvider.register(languageSelector, provider);\n}\n/**\n * Register a formatter that can handle a range inside a model.\n */\nexport function registerDocumentRangeFormattingEditProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.documentRangeFormattingEditProvider.register(languageSelector, provider);\n}\n/**\n * Register a formatter than can do formatting as the user types.\n */\nexport function registerOnTypeFormattingEditProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.onTypeFormattingEditProvider.register(languageSelector, provider);\n}\n/**\n * Register a link provider that can find links in text.\n */\nexport function registerLinkProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.linkProvider.register(languageSelector, provider);\n}\n/**\n * Register a completion item provider (use by e.g. suggestions).\n */\nexport function registerCompletionItemProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.completionProvider.register(languageSelector, provider);\n}\n/**\n * Register a document color provider (used by Color Picker, Color Decorator).\n */\nexport function registerColorProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.colorProvider.register(languageSelector, provider);\n}\n/**\n * Register a folding range provider\n */\nexport function registerFoldingRangeProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.foldingRangeProvider.register(languageSelector, provider);\n}\n/**\n * Register a declaration provider\n */\nexport function registerDeclarationProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.declarationProvider.register(languageSelector, provider);\n}\n/**\n * Register a selection range provider\n */\nexport function registerSelectionRangeProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.selectionRangeProvider.register(languageSelector, provider);\n}\n/**\n * Register a document semantic tokens provider. A semantic tokens provider will complement and enhance a\n * simple top-down tokenizer. Simple top-down tokenizers can be set either via `setMonarchTokensProvider`\n * or `setTokensProvider`.\n *\n * For the best user experience, register both a semantic tokens provider and a top-down tokenizer.\n */\nexport function registerDocumentSemanticTokensProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.documentSemanticTokensProvider.register(languageSelector, provider);\n}\n/**\n * Register a document range semantic tokens provider. A semantic tokens provider will complement and enhance a\n * simple top-down tokenizer. Simple top-down tokenizers can be set either via `setMonarchTokensProvider`\n * or `setTokensProvider`.\n *\n * For the best user experience, register both a semantic tokens provider and a top-down tokenizer.\n */\nexport function registerDocumentRangeSemanticTokensProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.documentRangeSemanticTokensProvider.register(languageSelector, provider);\n}\n/**\n * Register an inline completions provider.\n */\nexport function registerInlineCompletionsProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.inlineCompletionsProvider.register(languageSelector, provider);\n}\n/**\n * Register an inlay hints provider.\n */\nexport function registerInlayHintsProvider(languageSelector, provider) {\n const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);\n return languageFeaturesService.inlayHintsProvider.register(languageSelector, provider);\n}\n/**\n * @internal\n */\nexport function createMonacoLanguagesAPI() {\n return {\n register: register,\n getLanguages: getLanguages,\n onLanguage: onLanguage,\n getEncodedLanguageId: getEncodedLanguageId,\n // provider methods\n setLanguageConfiguration: setLanguageConfiguration,\n setColorMap: setColorMap,\n registerTokensProviderFactory: registerTokensProviderFactory,\n setTokensProvider: setTokensProvider,\n setMonarchTokensProvider: setMonarchTokensProvider,\n registerReferenceProvider: registerReferenceProvider,\n registerRenameProvider: registerRenameProvider,\n registerCompletionItemProvider: registerCompletionItemProvider,\n registerSignatureHelpProvider: registerSignatureHelpProvider,\n registerHoverProvider: registerHoverProvider,\n registerDocumentSymbolProvider: registerDocumentSymbolProvider,\n registerDocumentHighlightProvider: registerDocumentHighlightProvider,\n registerLinkedEditingRangeProvider: registerLinkedEditingRangeProvider,\n registerDefinitionProvider: registerDefinitionProvider,\n registerImplementationProvider: registerImplementationProvider,\n registerTypeDefinitionProvider: registerTypeDefinitionProvider,\n registerCodeLensProvider: registerCodeLensProvider,\n registerCodeActionProvider: registerCodeActionProvider,\n registerDocumentFormattingEditProvider: registerDocumentFormattingEditProvider,\n registerDocumentRangeFormattingEditProvider: registerDocumentRangeFormattingEditProvider,\n registerOnTypeFormattingEditProvider: registerOnTypeFormattingEditProvider,\n registerLinkProvider: registerLinkProvider,\n registerColorProvider: registerColorProvider,\n registerFoldingRangeProvider: registerFoldingRangeProvider,\n registerDeclarationProvider: registerDeclarationProvider,\n registerSelectionRangeProvider: registerSelectionRangeProvider,\n registerDocumentSemanticTokensProvider: registerDocumentSemanticTokensProvider,\n registerDocumentRangeSemanticTokensProvider: registerDocumentRangeSemanticTokensProvider,\n registerInlineCompletionsProvider: registerInlineCompletionsProvider,\n registerInlayHintsProvider: registerInlayHintsProvider,\n // enums\n DocumentHighlightKind: standaloneEnums.DocumentHighlightKind,\n CompletionItemKind: standaloneEnums.CompletionItemKind,\n CompletionItemTag: standaloneEnums.CompletionItemTag,\n CompletionItemInsertTextRule: standaloneEnums.CompletionItemInsertTextRule,\n SymbolKind: standaloneEnums.SymbolKind,\n SymbolTag: standaloneEnums.SymbolTag,\n IndentAction: standaloneEnums.IndentAction,\n CompletionTriggerKind: standaloneEnums.CompletionTriggerKind,\n SignatureHelpTriggerKind: standaloneEnums.SignatureHelpTriggerKind,\n InlayHintKind: standaloneEnums.InlayHintKind,\n InlineCompletionTriggerKind: standaloneEnums.InlineCompletionTriggerKind,\n CodeActionTriggerType: standaloneEnums.CodeActionTriggerType,\n // classes\n FoldingRangeKind: languages.FoldingRangeKind,\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 *--------------------------------------------------------------------------------------------*/\nvar _a;\nimport { EditorOptions } from './common/config/editorOptions.js';\nimport { createMonacoBaseAPI } from './common/services/editorBaseApi.js';\nimport { createMonacoEditorAPI } from './standalone/browser/standaloneEditor.js';\nimport { createMonacoLanguagesAPI } from './standalone/browser/standaloneLanguages.js';\nimport { globals } from '../base/common/platform.js';\nimport { FormattingConflicts } from './contrib/format/browser/format.js';\n// Set defaults for standalone editor\nEditorOptions.wrappingIndent.defaultValue = 0 /* WrappingIndent.None */;\nEditorOptions.glyphMargin.defaultValue = false;\nEditorOptions.autoIndent.defaultValue = 3 /* EditorAutoIndentStrategy.Advanced */;\nEditorOptions.overviewRulerLanes.defaultValue = 2;\n// We need to register a formatter selector which simply picks the first available formatter.\n// See https://github.com/microsoft/monaco-editor/issues/2327\nFormattingConflicts.setFormatterSelector((formatter, document, mode) => Promise.resolve(formatter[0]));\nconst api = createMonacoBaseAPI();\napi.editor = createMonacoEditorAPI();\napi.languages = createMonacoLanguagesAPI();\nexport const CancellationTokenSource = api.CancellationTokenSource;\nexport const Emitter = api.Emitter;\nexport const KeyCode = api.KeyCode;\nexport const KeyMod = api.KeyMod;\nexport const Position = api.Position;\nexport const Range = api.Range;\nexport const Selection = api.Selection;\nexport const SelectionDirection = api.SelectionDirection;\nexport const MarkerSeverity = api.MarkerSeverity;\nexport const MarkerTag = api.MarkerTag;\nexport const Uri = api.Uri;\nexport const Token = api.Token;\nexport const editor = api.editor;\nexport const languages = api.languages;\nif (((_a = globals.MonacoEnvironment) === null || _a === void 0 ? void 0 : _a.globalAPI) || (typeof define === 'function' && define.amd)) {\n self.monaco = api;\n}\nif (typeof self.require !== 'undefined' && typeof self.require.config === 'function') {\n self.require.config({\n ignoreDuplicateModules: [\n 'vscode-languageserver-types',\n 'vscode-languageserver-types/main',\n 'vscode-languageserver-textdocument',\n 'vscode-languageserver-textdocument/main',\n 'vscode-nls',\n 'vscode-nls/vscode-nls',\n 'jsonc-parser',\n 'jsonc-parser/main',\n 'vscode-uri',\n 'vscode-uri/index',\n 'vs/basic-languages/typescript/typescript'\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 *--------------------------------------------------------------------------------------------*/\nimport { Color } from '../../../../base/common/color.js';\nexport class ParsedTokenThemeRule {\n constructor(token, index, fontStyle, foreground, background) {\n this._parsedThemeRuleBrand = undefined;\n this.token = token;\n this.index = index;\n this.fontStyle = fontStyle;\n this.foreground = foreground;\n this.background = background;\n }\n}\n/**\n * Parse a raw theme into rules.\n */\nexport function parseTokenTheme(source) {\n if (!source || !Array.isArray(source)) {\n return [];\n }\n const result = [];\n let resultLen = 0;\n for (let i = 0, len = source.length; i < len; i++) {\n const entry = source[i];\n let fontStyle = -1 /* FontStyle.NotSet */;\n if (typeof entry.fontStyle === 'string') {\n fontStyle = 0 /* FontStyle.None */;\n const segments = entry.fontStyle.split(' ');\n for (let j = 0, lenJ = segments.length; j < lenJ; j++) {\n const segment = segments[j];\n switch (segment) {\n case 'italic':\n fontStyle = fontStyle | 1 /* FontStyle.Italic */;\n break;\n case 'bold':\n fontStyle = fontStyle | 2 /* FontStyle.Bold */;\n break;\n case 'underline':\n fontStyle = fontStyle | 4 /* FontStyle.Underline */;\n break;\n case 'strikethrough':\n fontStyle = fontStyle | 8 /* FontStyle.Strikethrough */;\n break;\n }\n }\n }\n let foreground = null;\n if (typeof entry.foreground === 'string') {\n foreground = entry.foreground;\n }\n let background = null;\n if (typeof entry.background === 'string') {\n background = entry.background;\n }\n result[resultLen++] = new ParsedTokenThemeRule(entry.token || '', i, fontStyle, foreground, background);\n }\n return result;\n}\n/**\n * Resolve rules (i.e. inheritance).\n */\nfunction resolveParsedTokenThemeRules(parsedThemeRules, customTokenColors) {\n // Sort rules lexicographically, and then by index if necessary\n parsedThemeRules.sort((a, b) => {\n const r = strcmp(a.token, b.token);\n if (r !== 0) {\n return r;\n }\n return a.index - b.index;\n });\n // Determine defaults\n let defaultFontStyle = 0 /* FontStyle.None */;\n let defaultForeground = '000000';\n let defaultBackground = 'ffffff';\n while (parsedThemeRules.length >= 1 && parsedThemeRules[0].token === '') {\n const incomingDefaults = parsedThemeRules.shift();\n if (incomingDefaults.fontStyle !== -1 /* FontStyle.NotSet */) {\n defaultFontStyle = incomingDefaults.fontStyle;\n }\n if (incomingDefaults.foreground !== null) {\n defaultForeground = incomingDefaults.foreground;\n }\n if (incomingDefaults.background !== null) {\n defaultBackground = incomingDefaults.background;\n }\n }\n const colorMap = new ColorMap();\n // start with token colors from custom token themes\n for (const color of customTokenColors) {\n colorMap.getId(color);\n }\n const foregroundColorId = colorMap.getId(defaultForeground);\n const backgroundColorId = colorMap.getId(defaultBackground);\n const defaults = new ThemeTrieElementRule(defaultFontStyle, foregroundColorId, backgroundColorId);\n const root = new ThemeTrieElement(defaults);\n for (let i = 0, len = parsedThemeRules.length; i < len; i++) {\n const rule = parsedThemeRules[i];\n root.insert(rule.token, rule.fontStyle, colorMap.getId(rule.foreground), colorMap.getId(rule.background));\n }\n return new TokenTheme(colorMap, root);\n}\nconst colorRegExp = /^#?([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$/;\nexport class ColorMap {\n constructor() {\n this._lastColorId = 0;\n this._id2color = [];\n this._color2id = new Map();\n }\n getId(color) {\n if (color === null) {\n return 0;\n }\n const match = color.match(colorRegExp);\n if (!match) {\n throw new Error('Illegal value for token color: ' + color);\n }\n color = match[1].toUpperCase();\n let value = this._color2id.get(color);\n if (value) {\n return value;\n }\n value = ++this._lastColorId;\n this._color2id.set(color, value);\n this._id2color[value] = Color.fromHex('#' + color);\n return value;\n }\n getColorMap() {\n return this._id2color.slice(0);\n }\n}\nexport class TokenTheme {\n constructor(colorMap, root) {\n this._colorMap = colorMap;\n this._root = root;\n this._cache = new Map();\n }\n static createFromRawTokenTheme(source, customTokenColors) {\n return this.createFromParsedTokenTheme(parseTokenTheme(source), customTokenColors);\n }\n static createFromParsedTokenTheme(source, customTokenColors) {\n return resolveParsedTokenThemeRules(source, customTokenColors);\n }\n getColorMap() {\n return this._colorMap.getColorMap();\n }\n _match(token) {\n return this._root.match(token);\n }\n match(languageId, token) {\n // The cache contains the metadata without the language bits set.\n let result = this._cache.get(token);\n if (typeof result === 'undefined') {\n const rule = this._match(token);\n const standardToken = toStandardTokenType(token);\n result = (rule.metadata\n | (standardToken << 8 /* MetadataConsts.TOKEN_TYPE_OFFSET */)) >>> 0;\n this._cache.set(token, result);\n }\n return (result\n | (languageId << 0 /* MetadataConsts.LANGUAGEID_OFFSET */)) >>> 0;\n }\n}\nconst STANDARD_TOKEN_TYPE_REGEXP = /\\b(comment|string|regex|regexp)\\b/;\nexport function toStandardTokenType(tokenType) {\n const m = tokenType.match(STANDARD_TOKEN_TYPE_REGEXP);\n if (!m) {\n return 0 /* StandardTokenType.Other */;\n }\n switch (m[1]) {\n case 'comment':\n return 1 /* StandardTokenType.Comment */;\n case 'string':\n return 2 /* StandardTokenType.String */;\n case 'regex':\n return 3 /* StandardTokenType.RegEx */;\n case 'regexp':\n return 3 /* StandardTokenType.RegEx */;\n }\n throw new Error('Unexpected match for standard token type!');\n}\nexport function strcmp(a, b) {\n if (a < b) {\n return -1;\n }\n if (a > b) {\n return 1;\n }\n return 0;\n}\nexport class ThemeTrieElementRule {\n constructor(fontStyle, foreground, background) {\n this._themeTrieElementRuleBrand = undefined;\n this._fontStyle = fontStyle;\n this._foreground = foreground;\n this._background = background;\n this.metadata = ((this._fontStyle << 11 /* MetadataConsts.FONT_STYLE_OFFSET */)\n | (this._foreground << 15 /* MetadataConsts.FOREGROUND_OFFSET */)\n | (this._background << 24 /* MetadataConsts.BACKGROUND_OFFSET */)) >>> 0;\n }\n clone() {\n return new ThemeTrieElementRule(this._fontStyle, this._foreground, this._background);\n }\n acceptOverwrite(fontStyle, foreground, background) {\n if (fontStyle !== -1 /* FontStyle.NotSet */) {\n this._fontStyle = fontStyle;\n }\n if (foreground !== 0 /* ColorId.None */) {\n this._foreground = foreground;\n }\n if (background !== 0 /* ColorId.None */) {\n this._background = background;\n }\n this.metadata = ((this._fontStyle << 11 /* MetadataConsts.FONT_STYLE_OFFSET */)\n | (this._foreground << 15 /* MetadataConsts.FOREGROUND_OFFSET */)\n | (this._background << 24 /* MetadataConsts.BACKGROUND_OFFSET */)) >>> 0;\n }\n}\nexport class ThemeTrieElement {\n constructor(mainRule) {\n this._themeTrieElementBrand = undefined;\n this._mainRule = mainRule;\n this._children = new Map();\n }\n match(token) {\n if (token === '') {\n return this._mainRule;\n }\n const dotIndex = token.indexOf('.');\n let head;\n let tail;\n if (dotIndex === -1) {\n head = token;\n tail = '';\n }\n else {\n head = token.substring(0, dotIndex);\n tail = token.substring(dotIndex + 1);\n }\n const child = this._children.get(head);\n if (typeof child !== 'undefined') {\n return child.match(tail);\n }\n return this._mainRule;\n }\n insert(token, fontStyle, foreground, background) {\n if (token === '') {\n // Merge into the main rule\n this._mainRule.acceptOverwrite(fontStyle, foreground, background);\n return;\n }\n const dotIndex = token.indexOf('.');\n let head;\n let tail;\n if (dotIndex === -1) {\n head = token;\n tail = '';\n }\n else {\n head = token.substring(0, dotIndex);\n tail = token.substring(dotIndex + 1);\n }\n let child = this._children.get(head);\n if (typeof child === 'undefined') {\n child = new ThemeTrieElement(this._mainRule.clone());\n this._children.set(head, child);\n }\n child.insert(tail, fontStyle, foreground, background);\n }\n}\nexport function generateTokensCSSForColorMap(colorMap) {\n const rules = [];\n for (let i = 1, len = colorMap.length; i < len; i++) {\n const color = colorMap[i];\n rules[i] = `.mtk${i} { color: ${color}; }`;\n }\n rules.push('.mtki { font-style: italic; }');\n rules.push('.mtkb { font-weight: bold; }');\n rules.push('.mtku { text-decoration: underline; text-underline-position: under; }');\n rules.push('.mtks { text-decoration: line-through; }');\n rules.push('.mtks.mtku { text-decoration: underline line-through; text-underline-position: under; }');\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { editorActiveIndentGuides, editorIndentGuides } from '../../common/core/editorColorRegistry.js';\nimport { editorBackground, editorForeground, editorInactiveSelection, editorSelectionHighlight } from '../../../platform/theme/common/colorRegistry.js';\n/* -------------------------------- Begin vs theme -------------------------------- */\nexport const vs = {\n base: 'vs',\n inherit: false,\n rules: [\n { token: '', foreground: '000000', background: 'fffffe' },\n { token: 'invalid', foreground: 'cd3131' },\n { token: 'emphasis', fontStyle: 'italic' },\n { token: 'strong', fontStyle: 'bold' },\n { token: 'variable', foreground: '001188' },\n { token: 'variable.predefined', foreground: '4864AA' },\n { token: 'constant', foreground: 'dd0000' },\n { token: 'comment', foreground: '008000' },\n { token: 'number', foreground: '098658' },\n { token: 'number.hex', foreground: '3030c0' },\n { token: 'regexp', foreground: '800000' },\n { token: 'annotation', foreground: '808080' },\n { token: 'type', foreground: '008080' },\n { token: 'delimiter', foreground: '000000' },\n { token: 'delimiter.html', foreground: '383838' },\n { token: 'delimiter.xml', foreground: '0000FF' },\n { token: 'tag', foreground: '800000' },\n { token: 'tag.id.pug', foreground: '4F76AC' },\n { token: 'tag.class.pug', foreground: '4F76AC' },\n { token: 'meta.scss', foreground: '800000' },\n { token: 'metatag', foreground: 'e00000' },\n { token: 'metatag.content.html', foreground: 'FF0000' },\n { token: 'metatag.html', foreground: '808080' },\n { token: 'metatag.xml', foreground: '808080' },\n { token: 'metatag.php', fontStyle: 'bold' },\n { token: 'key', foreground: '863B00' },\n { token: 'string.key.json', foreground: 'A31515' },\n { token: 'string.value.json', foreground: '0451A5' },\n { token: 'attribute.name', foreground: 'FF0000' },\n { token: 'attribute.value', foreground: '0451A5' },\n { token: 'attribute.value.number', foreground: '098658' },\n { token: 'attribute.value.unit', foreground: '098658' },\n { token: 'attribute.value.html', foreground: '0000FF' },\n { token: 'attribute.value.xml', foreground: '0000FF' },\n { token: 'string', foreground: 'A31515' },\n { token: 'string.html', foreground: '0000FF' },\n { token: 'string.sql', foreground: 'FF0000' },\n { token: 'string.yaml', foreground: '0451A5' },\n { token: 'keyword', foreground: '0000FF' },\n { token: 'keyword.json', foreground: '0451A5' },\n { token: 'keyword.flow', foreground: 'AF00DB' },\n { token: 'keyword.flow.scss', foreground: '0000FF' },\n { token: 'operator.scss', foreground: '666666' },\n { token: 'operator.sql', foreground: '778899' },\n { token: 'operator.swift', foreground: '666666' },\n { token: 'predefined.sql', foreground: 'C700C7' },\n ],\n colors: {\n [editorBackground]: '#FFFFFE',\n [editorForeground]: '#000000',\n [editorInactiveSelection]: '#E5EBF1',\n [editorIndentGuides]: '#D3D3D3',\n [editorActiveIndentGuides]: '#939393',\n [editorSelectionHighlight]: '#ADD6FF4D'\n }\n};\n/* -------------------------------- End vs theme -------------------------------- */\n/* -------------------------------- Begin vs-dark theme -------------------------------- */\nexport const vs_dark = {\n base: 'vs-dark',\n inherit: false,\n rules: [\n { token: '', foreground: 'D4D4D4', background: '1E1E1E' },\n { token: 'invalid', foreground: 'f44747' },\n { token: 'emphasis', fontStyle: 'italic' },\n { token: 'strong', fontStyle: 'bold' },\n { token: 'variable', foreground: '74B0DF' },\n { token: 'variable.predefined', foreground: '4864AA' },\n { token: 'variable.parameter', foreground: '9CDCFE' },\n { token: 'constant', foreground: '569CD6' },\n { token: 'comment', foreground: '608B4E' },\n { token: 'number', foreground: 'B5CEA8' },\n { token: 'number.hex', foreground: '5BB498' },\n { token: 'regexp', foreground: 'B46695' },\n { token: 'annotation', foreground: 'cc6666' },\n { token: 'type', foreground: '3DC9B0' },\n { token: 'delimiter', foreground: 'DCDCDC' },\n { token: 'delimiter.html', foreground: '808080' },\n { token: 'delimiter.xml', foreground: '808080' },\n { token: 'tag', foreground: '569CD6' },\n { token: 'tag.id.pug', foreground: '4F76AC' },\n { token: 'tag.class.pug', foreground: '4F76AC' },\n { token: 'meta.scss', foreground: 'A79873' },\n { token: 'meta.tag', foreground: 'CE9178' },\n { token: 'metatag', foreground: 'DD6A6F' },\n { token: 'metatag.content.html', foreground: '9CDCFE' },\n { token: 'metatag.html', foreground: '569CD6' },\n { token: 'metatag.xml', foreground: '569CD6' },\n { token: 'metatag.php', fontStyle: 'bold' },\n { token: 'key', foreground: '9CDCFE' },\n { token: 'string.key.json', foreground: '9CDCFE' },\n { token: 'string.value.json', foreground: 'CE9178' },\n { token: 'attribute.name', foreground: '9CDCFE' },\n { token: 'attribute.value', foreground: 'CE9178' },\n { token: 'attribute.value.number.css', foreground: 'B5CEA8' },\n { token: 'attribute.value.unit.css', foreground: 'B5CEA8' },\n { token: 'attribute.value.hex.css', foreground: 'D4D4D4' },\n { token: 'string', foreground: 'CE9178' },\n { token: 'string.sql', foreground: 'FF0000' },\n { token: 'keyword', foreground: '569CD6' },\n { token: 'keyword.flow', foreground: 'C586C0' },\n { token: 'keyword.json', foreground: 'CE9178' },\n { token: 'keyword.flow.scss', foreground: '569CD6' },\n { token: 'operator.scss', foreground: '909090' },\n { token: 'operator.sql', foreground: '778899' },\n { token: 'operator.swift', foreground: '909090' },\n { token: 'predefined.sql', foreground: 'FF00FF' },\n ],\n colors: {\n [editorBackground]: '#1E1E1E',\n [editorForeground]: '#D4D4D4',\n [editorInactiveSelection]: '#3A3D41',\n [editorIndentGuides]: '#404040',\n [editorActiveIndentGuides]: '#707070',\n [editorSelectionHighlight]: '#ADD6FF26'\n }\n};\n/* -------------------------------- End vs-dark theme -------------------------------- */\n/* -------------------------------- Begin hc-black theme -------------------------------- */\nexport const hc_black = {\n base: 'hc-black',\n inherit: false,\n rules: [\n { token: '', foreground: 'FFFFFF', background: '000000' },\n { token: 'invalid', foreground: 'f44747' },\n { token: 'emphasis', fontStyle: 'italic' },\n { token: 'strong', fontStyle: 'bold' },\n { token: 'variable', foreground: '1AEBFF' },\n { token: 'variable.parameter', foreground: '9CDCFE' },\n { token: 'constant', foreground: '569CD6' },\n { token: 'comment', foreground: '608B4E' },\n { token: 'number', foreground: 'FFFFFF' },\n { token: 'regexp', foreground: 'C0C0C0' },\n { token: 'annotation', foreground: '569CD6' },\n { token: 'type', foreground: '3DC9B0' },\n { token: 'delimiter', foreground: 'FFFF00' },\n { token: 'delimiter.html', foreground: 'FFFF00' },\n { token: 'tag', foreground: '569CD6' },\n { token: 'tag.id.pug', foreground: '4F76AC' },\n { token: 'tag.class.pug', foreground: '4F76AC' },\n { token: 'meta', foreground: 'D4D4D4' },\n { token: 'meta.tag', foreground: 'CE9178' },\n { token: 'metatag', foreground: '569CD6' },\n { token: 'metatag.content.html', foreground: '1AEBFF' },\n { token: 'metatag.html', foreground: '569CD6' },\n { token: 'metatag.xml', foreground: '569CD6' },\n { token: 'metatag.php', fontStyle: 'bold' },\n { token: 'key', foreground: '9CDCFE' },\n { token: 'string.key', foreground: '9CDCFE' },\n { token: 'string.value', foreground: 'CE9178' },\n { token: 'attribute.name', foreground: '569CD6' },\n { token: 'attribute.value', foreground: '3FF23F' },\n { token: 'string', foreground: 'CE9178' },\n { token: 'string.sql', foreground: 'FF0000' },\n { token: 'keyword', foreground: '569CD6' },\n { token: 'keyword.flow', foreground: 'C586C0' },\n { token: 'operator.sql', foreground: '778899' },\n { token: 'operator.swift', foreground: '909090' },\n { token: 'predefined.sql', foreground: 'FF00FF' },\n ],\n colors: {\n [editorBackground]: '#000000',\n [editorForeground]: '#FFFFFF',\n [editorIndentGuides]: '#FFFFFF',\n [editorActiveIndentGuides]: '#FFFFFF',\n }\n};\n/* -------------------------------- End hc-black theme -------------------------------- */\n/* -------------------------------- Begin hc-light theme -------------------------------- */\nexport const hc_light = {\n base: 'hc-light',\n inherit: false,\n rules: [\n { token: '', foreground: '292929', background: 'FFFFFF' },\n { token: 'invalid', foreground: 'B5200D' },\n { token: 'emphasis', fontStyle: 'italic' },\n { token: 'strong', fontStyle: 'bold' },\n { token: 'variable', foreground: '264F70' },\n { token: 'variable.predefined', foreground: '4864AA' },\n { token: 'constant', foreground: 'dd0000' },\n { token: 'comment', foreground: '008000' },\n { token: 'number', foreground: '098658' },\n { token: 'number.hex', foreground: '3030c0' },\n { token: 'regexp', foreground: '800000' },\n { token: 'annotation', foreground: '808080' },\n { token: 'type', foreground: '008080' },\n { token: 'delimiter', foreground: '000000' },\n { token: 'delimiter.html', foreground: '383838' },\n { token: 'tag', foreground: '800000' },\n { token: 'tag.id.pug', foreground: '4F76AC' },\n { token: 'tag.class.pug', foreground: '4F76AC' },\n { token: 'meta.scss', foreground: '800000' },\n { token: 'metatag', foreground: 'e00000' },\n { token: 'metatag.content.html', foreground: 'B5200D' },\n { token: 'metatag.html', foreground: '808080' },\n { token: 'metatag.xml', foreground: '808080' },\n { token: 'metatag.php', fontStyle: 'bold' },\n { token: 'key', foreground: '863B00' },\n { token: 'string.key.json', foreground: 'A31515' },\n { token: 'string.value.json', foreground: '0451A5' },\n { token: 'attribute.name', foreground: '264F78' },\n { token: 'attribute.value', foreground: '0451A5' },\n { token: 'string', foreground: 'A31515' },\n { token: 'string.sql', foreground: 'B5200D' },\n { token: 'keyword', foreground: '0000FF' },\n { token: 'keyword.flow', foreground: 'AF00DB' },\n { token: 'operator.sql', foreground: '778899' },\n { token: 'operator.swift', foreground: '666666' },\n { token: 'predefined.sql', foreground: 'C700C7' },\n ],\n colors: {\n [editorBackground]: '#FFFFFF',\n [editorForeground]: '#292929',\n [editorIndentGuides]: '#292929',\n [editorActiveIndentGuides]: '#292929',\n }\n};\n/* -------------------------------- End hc-light theme -------------------------------- */\n","/*---------------------------------------------------------------------------------------------\n * 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 { asCSSPropertyValue, asCSSUrl } from '../../../base/browser/dom.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { getIconRegistry } from '../common/iconRegistry.js';\nimport { ThemeIcon } from '../common/themeService.js';\nexport function getIconsStyleSheet(themeService) {\n const onDidChangeEmmiter = new Emitter();\n const iconRegistry = getIconRegistry();\n iconRegistry.onDidChange(() => onDidChangeEmmiter.fire());\n themeService === null || themeService === void 0 ? void 0 : themeService.onDidProductIconThemeChange(() => onDidChangeEmmiter.fire());\n return {\n onDidChange: onDidChangeEmmiter.event,\n getCSS() {\n const productIconTheme = themeService ? themeService.getProductIconTheme() : new UnthemedProductIconTheme();\n const usedFontIds = {};\n const formatIconRule = (contribution) => {\n const definition = productIconTheme.getIcon(contribution);\n if (!definition) {\n return undefined;\n }\n const fontContribution = definition.font;\n if (fontContribution) {\n usedFontIds[fontContribution.id] = fontContribution.definition;\n return `.codicon-${contribution.id}:before { content: '${definition.fontCharacter}'; font-family: ${asCSSPropertyValue(fontContribution.id)}; }`;\n }\n // default font (codicon)\n return `.codicon-${contribution.id}:before { content: '${definition.fontCharacter}'; }`;\n };\n const rules = [];\n for (const contribution of iconRegistry.getIcons()) {\n const rule = formatIconRule(contribution);\n if (rule) {\n rules.push(rule);\n }\n }\n for (const id in usedFontIds) {\n const definition = usedFontIds[id];\n const fontWeight = definition.weight ? `font-weight: ${definition.weight};` : '';\n const fontStyle = definition.style ? `font-style: ${definition.style};` : '';\n const src = definition.src.map(l => `${asCSSUrl(l.location)} format('${l.format}')`).join(', ');\n rules.push(`@font-face { src: ${src}; font-family: ${asCSSPropertyValue(id)};${fontWeight}${fontStyle} font-display: block; }`);\n }\n return rules.join('\\n');\n }\n };\n}\nexport class UnthemedProductIconTheme {\n getIcon(contribution) {\n const iconRegistry = getIconRegistry();\n let definition = contribution.defaults;\n while (ThemeIcon.isThemeIcon(definition)) {\n const c = iconRegistry.getIcon(definition.id);\n if (!c) {\n return undefined;\n }\n definition = c.defaults;\n }\n return definition;\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 *--------------------------------------------------------------------------------------------*/\nimport * as dom from '../../../base/browser/dom.js';\nimport { addMatchMediaChangeListener } from '../../../base/browser/browser.js';\nimport { Color } from '../../../base/common/color.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { TokenizationRegistry } from '../../common/languages.js';\nimport { TokenMetadata } from '../../common/encodedTokenAttributes.js';\nimport { TokenTheme, generateTokensCSSForColorMap } from '../../common/languages/supports/tokenization.js';\nimport { hc_black, hc_light, vs, vs_dark } from '../common/themes.js';\nimport { Registry } from '../../../platform/registry/common/platform.js';\nimport { asCssVariableName, Extensions } from '../../../platform/theme/common/colorRegistry.js';\nimport { Extensions as ThemingExtensions } from '../../../platform/theme/common/themeService.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { ColorScheme, isDark, isHighContrast } from '../../../platform/theme/common/theme.js';\nimport { getIconsStyleSheet, UnthemedProductIconTheme } from '../../../platform/theme/browser/iconsStyleSheet.js';\nexport const VS_LIGHT_THEME_NAME = 'vs';\nexport const VS_DARK_THEME_NAME = 'vs-dark';\nexport const HC_BLACK_THEME_NAME = 'hc-black';\nexport const HC_LIGHT_THEME_NAME = 'hc-light';\nconst colorRegistry = Registry.as(Extensions.ColorContribution);\nconst themingRegistry = Registry.as(ThemingExtensions.ThemingContribution);\nclass StandaloneTheme {\n constructor(name, standaloneThemeData) {\n this.semanticHighlighting = false;\n this.themeData = standaloneThemeData;\n const base = standaloneThemeData.base;\n if (name.length > 0) {\n if (isBuiltinTheme(name)) {\n this.id = name;\n }\n else {\n this.id = base + ' ' + name;\n }\n this.themeName = name;\n }\n else {\n this.id = base;\n this.themeName = base;\n }\n this.colors = null;\n this.defaultColors = Object.create(null);\n this._tokenTheme = null;\n }\n get base() {\n return this.themeData.base;\n }\n notifyBaseUpdated() {\n if (this.themeData.inherit) {\n this.colors = null;\n this._tokenTheme = null;\n }\n }\n getColors() {\n if (!this.colors) {\n const colors = new Map();\n for (const id in this.themeData.colors) {\n colors.set(id, Color.fromHex(this.themeData.colors[id]));\n }\n if (this.themeData.inherit) {\n const baseData = getBuiltinRules(this.themeData.base);\n for (const id in baseData.colors) {\n if (!colors.has(id)) {\n colors.set(id, Color.fromHex(baseData.colors[id]));\n }\n }\n }\n this.colors = colors;\n }\n return this.colors;\n }\n getColor(colorId, useDefault) {\n const color = this.getColors().get(colorId);\n if (color) {\n return color;\n }\n if (useDefault !== false) {\n return this.getDefault(colorId);\n }\n return undefined;\n }\n getDefault(colorId) {\n let color = this.defaultColors[colorId];\n if (color) {\n return color;\n }\n color = colorRegistry.resolveDefaultColor(colorId, this);\n this.defaultColors[colorId] = color;\n return color;\n }\n defines(colorId) {\n return Object.prototype.hasOwnProperty.call(this.getColors(), colorId);\n }\n get type() {\n switch (this.base) {\n case VS_LIGHT_THEME_NAME: return ColorScheme.LIGHT;\n case HC_BLACK_THEME_NAME: return ColorScheme.HIGH_CONTRAST_DARK;\n case HC_LIGHT_THEME_NAME: return ColorScheme.HIGH_CONTRAST_LIGHT;\n default: return ColorScheme.DARK;\n }\n }\n get tokenTheme() {\n if (!this._tokenTheme) {\n let rules = [];\n let encodedTokensColors = [];\n if (this.themeData.inherit) {\n const baseData = getBuiltinRules(this.themeData.base);\n rules = baseData.rules;\n if (baseData.encodedTokensColors) {\n encodedTokensColors = baseData.encodedTokensColors;\n }\n }\n // Pick up default colors from `editor.foreground` and `editor.background` if available\n const editorForeground = this.themeData.colors['editor.foreground'];\n const editorBackground = this.themeData.colors['editor.background'];\n if (editorForeground || editorBackground) {\n const rule = { token: '' };\n if (editorForeground) {\n rule.foreground = editorForeground;\n }\n if (editorBackground) {\n rule.background = editorBackground;\n }\n rules.push(rule);\n }\n rules = rules.concat(this.themeData.rules);\n if (this.themeData.encodedTokensColors) {\n encodedTokensColors = this.themeData.encodedTokensColors;\n }\n this._tokenTheme = TokenTheme.createFromRawTokenTheme(rules, encodedTokensColors);\n }\n return this._tokenTheme;\n }\n getTokenStyleMetadata(type, modifiers, modelLanguage) {\n // use theme rules match\n const style = this.tokenTheme._match([type].concat(modifiers).join('.'));\n const metadata = style.metadata;\n const foreground = TokenMetadata.getForeground(metadata);\n const fontStyle = TokenMetadata.getFontStyle(metadata);\n return {\n foreground: foreground,\n italic: Boolean(fontStyle & 1 /* FontStyle.Italic */),\n bold: Boolean(fontStyle & 2 /* FontStyle.Bold */),\n underline: Boolean(fontStyle & 4 /* FontStyle.Underline */),\n strikethrough: Boolean(fontStyle & 8 /* FontStyle.Strikethrough */)\n };\n }\n}\nfunction isBuiltinTheme(themeName) {\n return (themeName === VS_LIGHT_THEME_NAME\n || themeName === VS_DARK_THEME_NAME\n || themeName === HC_BLACK_THEME_NAME\n || themeName === HC_LIGHT_THEME_NAME);\n}\nfunction getBuiltinRules(builtinTheme) {\n switch (builtinTheme) {\n case VS_LIGHT_THEME_NAME:\n return vs;\n case VS_DARK_THEME_NAME:\n return vs_dark;\n case HC_BLACK_THEME_NAME:\n return hc_black;\n case HC_LIGHT_THEME_NAME:\n return hc_light;\n }\n}\nfunction newBuiltInTheme(builtinTheme) {\n const themeData = getBuiltinRules(builtinTheme);\n return new StandaloneTheme(builtinTheme, themeData);\n}\nexport class StandaloneThemeService extends Disposable {\n constructor() {\n super();\n this._onColorThemeChange = this._register(new Emitter());\n this.onDidColorThemeChange = this._onColorThemeChange.event;\n this._onProductIconThemeChange = this._register(new Emitter());\n this.onDidProductIconThemeChange = this._onProductIconThemeChange.event;\n this._environment = Object.create(null);\n this._builtInProductIconTheme = new UnthemedProductIconTheme();\n this._autoDetectHighContrast = true;\n this._knownThemes = new Map();\n this._knownThemes.set(VS_LIGHT_THEME_NAME, newBuiltInTheme(VS_LIGHT_THEME_NAME));\n this._knownThemes.set(VS_DARK_THEME_NAME, newBuiltInTheme(VS_DARK_THEME_NAME));\n this._knownThemes.set(HC_BLACK_THEME_NAME, newBuiltInTheme(HC_BLACK_THEME_NAME));\n this._knownThemes.set(HC_LIGHT_THEME_NAME, newBuiltInTheme(HC_LIGHT_THEME_NAME));\n const iconsStyleSheet = getIconsStyleSheet(this);\n this._codiconCSS = iconsStyleSheet.getCSS();\n this._themeCSS = '';\n this._allCSS = `${this._codiconCSS}\\n${this._themeCSS}`;\n this._globalStyleElement = null;\n this._styleElements = [];\n this._colorMapOverride = null;\n this.setTheme(VS_LIGHT_THEME_NAME);\n this._onOSSchemeChanged();\n iconsStyleSheet.onDidChange(() => {\n this._codiconCSS = iconsStyleSheet.getCSS();\n this._updateCSS();\n });\n addMatchMediaChangeListener('(forced-colors: active)', () => {\n this._onOSSchemeChanged();\n });\n }\n registerEditorContainer(domNode) {\n if (dom.isInShadowDOM(domNode)) {\n return this._registerShadowDomContainer(domNode);\n }\n return this._registerRegularEditorContainer();\n }\n _registerRegularEditorContainer() {\n if (!this._globalStyleElement) {\n this._globalStyleElement = dom.createStyleSheet();\n this._globalStyleElement.className = 'monaco-colors';\n this._globalStyleElement.textContent = this._allCSS;\n this._styleElements.push(this._globalStyleElement);\n }\n return Disposable.None;\n }\n _registerShadowDomContainer(domNode) {\n const styleElement = dom.createStyleSheet(domNode);\n styleElement.className = 'monaco-colors';\n styleElement.textContent = this._allCSS;\n this._styleElements.push(styleElement);\n return {\n dispose: () => {\n for (let i = 0; i < this._styleElements.length; i++) {\n if (this._styleElements[i] === styleElement) {\n this._styleElements.splice(i, 1);\n return;\n }\n }\n }\n };\n }\n defineTheme(themeName, themeData) {\n if (!/^[a-z0-9\\-]+$/i.test(themeName)) {\n throw new Error('Illegal theme name!');\n }\n if (!isBuiltinTheme(themeData.base) && !isBuiltinTheme(themeName)) {\n throw new Error('Illegal theme base!');\n }\n // set or replace theme\n this._knownThemes.set(themeName, new StandaloneTheme(themeName, themeData));\n if (isBuiltinTheme(themeName)) {\n this._knownThemes.forEach(theme => {\n if (theme.base === themeName) {\n theme.notifyBaseUpdated();\n }\n });\n }\n if (this._theme.themeName === themeName) {\n this.setTheme(themeName); // refresh theme\n }\n }\n getColorTheme() {\n return this._theme;\n }\n setColorMapOverride(colorMapOverride) {\n this._colorMapOverride = colorMapOverride;\n this._updateThemeOrColorMap();\n }\n setTheme(themeName) {\n let theme;\n if (this._knownThemes.has(themeName)) {\n theme = this._knownThemes.get(themeName);\n }\n else {\n theme = this._knownThemes.get(VS_LIGHT_THEME_NAME);\n }\n this._updateActualTheme(theme);\n }\n _updateActualTheme(desiredTheme) {\n if (!desiredTheme || this._theme === desiredTheme) {\n // Nothing to do\n return;\n }\n this._theme = desiredTheme;\n this._updateThemeOrColorMap();\n }\n _onOSSchemeChanged() {\n if (this._autoDetectHighContrast) {\n const wantsHighContrast = window.matchMedia(`(forced-colors: active)`).matches;\n if (wantsHighContrast !== isHighContrast(this._theme.type)) {\n // switch to high contrast or non-high contrast but stick to dark or light\n let newThemeName;\n if (isDark(this._theme.type)) {\n newThemeName = wantsHighContrast ? HC_BLACK_THEME_NAME : VS_DARK_THEME_NAME;\n }\n else {\n newThemeName = wantsHighContrast ? HC_LIGHT_THEME_NAME : VS_LIGHT_THEME_NAME;\n }\n this._updateActualTheme(this._knownThemes.get(newThemeName));\n }\n }\n }\n setAutoDetectHighContrast(autoDetectHighContrast) {\n this._autoDetectHighContrast = autoDetectHighContrast;\n this._onOSSchemeChanged();\n }\n _updateThemeOrColorMap() {\n const cssRules = [];\n const hasRule = {};\n const ruleCollector = {\n addRule: (rule) => {\n if (!hasRule[rule]) {\n cssRules.push(rule);\n hasRule[rule] = true;\n }\n }\n };\n themingRegistry.getThemingParticipants().forEach(p => p(this._theme, ruleCollector, this._environment));\n const colorVariables = [];\n for (const item of colorRegistry.getColors()) {\n const color = this._theme.getColor(item.id, true);\n if (color) {\n colorVariables.push(`${asCssVariableName(item.id)}: ${color.toString()};`);\n }\n }\n ruleCollector.addRule(`.monaco-editor { ${colorVariables.join('\\n')} }`);\n const colorMap = this._colorMapOverride || this._theme.tokenTheme.getColorMap();\n ruleCollector.addRule(generateTokensCSSForColorMap(colorMap));\n this._themeCSS = cssRules.join('\\n');\n this._updateCSS();\n TokenizationRegistry.setColorMap(colorMap);\n this._onColorThemeChange.fire(this._theme);\n }\n _updateCSS() {\n this._allCSS = `${this._codiconCSS}\\n${this._themeCSS}`;\n this._styleElements.forEach(styleElement => styleElement.textContent = this._allCSS);\n }\n getFileIconTheme() {\n return {\n hasFileIcons: false,\n hasFolderIcons: false,\n hidesExplorerArrows: false\n };\n }\n getProductIconTheme() {\n return this._builtInProductIconTheme;\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 *--------------------------------------------------------------------------------------------*/\nimport { createDecorator } from '../../../platform/instantiation/common/instantiation.js';\nexport const IStandaloneThemeService = createDecorator('themeService');\n","import '../../editor/editor.api.js';\n/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, \"default\"), secondTarget && __copyProps(secondTarget, mod, \"default\"));\n\n// src/language/typescript/lib/typescriptServicesMetadata.ts\nvar typescriptVersion = \"4.5.5\";\n\n// src/fillers/monaco-editor-core.ts\nvar monaco_editor_core_exports = {};\n__reExport(monaco_editor_core_exports, monaco_editor_core_star);\nimport * as monaco_editor_core_star from \"../../editor/editor.api.js\";\n\n// src/language/typescript/monaco.contribution.ts\nvar ModuleKind = /* @__PURE__ */ ((ModuleKind2) => {\n ModuleKind2[ModuleKind2[\"None\"] = 0] = \"None\";\n ModuleKind2[ModuleKind2[\"CommonJS\"] = 1] = \"CommonJS\";\n ModuleKind2[ModuleKind2[\"AMD\"] = 2] = \"AMD\";\n ModuleKind2[ModuleKind2[\"UMD\"] = 3] = \"UMD\";\n ModuleKind2[ModuleKind2[\"System\"] = 4] = \"System\";\n ModuleKind2[ModuleKind2[\"ES2015\"] = 5] = \"ES2015\";\n ModuleKind2[ModuleKind2[\"ESNext\"] = 99] = \"ESNext\";\n return ModuleKind2;\n})(ModuleKind || {});\nvar JsxEmit = /* @__PURE__ */ ((JsxEmit2) => {\n JsxEmit2[JsxEmit2[\"None\"] = 0] = \"None\";\n JsxEmit2[JsxEmit2[\"Preserve\"] = 1] = \"Preserve\";\n JsxEmit2[JsxEmit2[\"React\"] = 2] = \"React\";\n JsxEmit2[JsxEmit2[\"ReactNative\"] = 3] = \"ReactNative\";\n JsxEmit2[JsxEmit2[\"ReactJSX\"] = 4] = \"ReactJSX\";\n JsxEmit2[JsxEmit2[\"ReactJSXDev\"] = 5] = \"ReactJSXDev\";\n return JsxEmit2;\n})(JsxEmit || {});\nvar NewLineKind = /* @__PURE__ */ ((NewLineKind2) => {\n NewLineKind2[NewLineKind2[\"CarriageReturnLineFeed\"] = 0] = \"CarriageReturnLineFeed\";\n NewLineKind2[NewLineKind2[\"LineFeed\"] = 1] = \"LineFeed\";\n return NewLineKind2;\n})(NewLineKind || {});\nvar ScriptTarget = /* @__PURE__ */ ((ScriptTarget2) => {\n ScriptTarget2[ScriptTarget2[\"ES3\"] = 0] = \"ES3\";\n ScriptTarget2[ScriptTarget2[\"ES5\"] = 1] = \"ES5\";\n ScriptTarget2[ScriptTarget2[\"ES2015\"] = 2] = \"ES2015\";\n ScriptTarget2[ScriptTarget2[\"ES2016\"] = 3] = \"ES2016\";\n ScriptTarget2[ScriptTarget2[\"ES2017\"] = 4] = \"ES2017\";\n ScriptTarget2[ScriptTarget2[\"ES2018\"] = 5] = \"ES2018\";\n ScriptTarget2[ScriptTarget2[\"ES2019\"] = 6] = \"ES2019\";\n ScriptTarget2[ScriptTarget2[\"ES2020\"] = 7] = \"ES2020\";\n ScriptTarget2[ScriptTarget2[\"ESNext\"] = 99] = \"ESNext\";\n ScriptTarget2[ScriptTarget2[\"JSON\"] = 100] = \"JSON\";\n ScriptTarget2[ScriptTarget2[\"Latest\"] = 99 /* ESNext */] = \"Latest\";\n return ScriptTarget2;\n})(ScriptTarget || {});\nvar ModuleResolutionKind = /* @__PURE__ */ ((ModuleResolutionKind2) => {\n ModuleResolutionKind2[ModuleResolutionKind2[\"Classic\"] = 1] = \"Classic\";\n ModuleResolutionKind2[ModuleResolutionKind2[\"NodeJs\"] = 2] = \"NodeJs\";\n return ModuleResolutionKind2;\n})(ModuleResolutionKind || {});\nvar LanguageServiceDefaultsImpl = class {\n _onDidChange = new monaco_editor_core_exports.Emitter();\n _onDidExtraLibsChange = new monaco_editor_core_exports.Emitter();\n _extraLibs;\n _removedExtraLibs;\n _eagerModelSync;\n _compilerOptions;\n _diagnosticsOptions;\n _workerOptions;\n _onDidExtraLibsChangeTimeout;\n _inlayHintsOptions;\n constructor(compilerOptions, diagnosticsOptions, workerOptions, inlayHintsOptions) {\n this._extraLibs = /* @__PURE__ */ Object.create(null);\n this._removedExtraLibs = /* @__PURE__ */ Object.create(null);\n this._eagerModelSync = false;\n this.setCompilerOptions(compilerOptions);\n this.setDiagnosticsOptions(diagnosticsOptions);\n this.setWorkerOptions(workerOptions);\n this.setInlayHintsOptions(inlayHintsOptions);\n this._onDidExtraLibsChangeTimeout = -1;\n }\n get onDidChange() {\n return this._onDidChange.event;\n }\n get onDidExtraLibsChange() {\n return this._onDidExtraLibsChange.event;\n }\n get workerOptions() {\n return this._workerOptions;\n }\n get inlayHintsOptions() {\n return this._inlayHintsOptions;\n }\n getExtraLibs() {\n return this._extraLibs;\n }\n addExtraLib(content, _filePath) {\n let filePath;\n if (typeof _filePath === \"undefined\") {\n filePath = `ts:extralib-${Math.random().toString(36).substring(2, 15)}`;\n } else {\n filePath = _filePath;\n }\n if (this._extraLibs[filePath] && this._extraLibs[filePath].content === content) {\n return {\n dispose: () => {\n }\n };\n }\n let myVersion = 1;\n if (this._removedExtraLibs[filePath]) {\n myVersion = this._removedExtraLibs[filePath] + 1;\n }\n if (this._extraLibs[filePath]) {\n myVersion = this._extraLibs[filePath].version + 1;\n }\n this._extraLibs[filePath] = {\n content,\n version: myVersion\n };\n this._fireOnDidExtraLibsChangeSoon();\n return {\n dispose: () => {\n let extraLib = this._extraLibs[filePath];\n if (!extraLib) {\n return;\n }\n if (extraLib.version !== myVersion) {\n return;\n }\n delete this._extraLibs[filePath];\n this._removedExtraLibs[filePath] = myVersion;\n this._fireOnDidExtraLibsChangeSoon();\n }\n };\n }\n setExtraLibs(libs) {\n for (const filePath in this._extraLibs) {\n this._removedExtraLibs[filePath] = this._extraLibs[filePath].version;\n }\n this._extraLibs = /* @__PURE__ */ Object.create(null);\n if (libs && libs.length > 0) {\n for (const lib of libs) {\n const filePath = lib.filePath || `ts:extralib-${Math.random().toString(36).substring(2, 15)}`;\n const content = lib.content;\n let myVersion = 1;\n if (this._removedExtraLibs[filePath]) {\n myVersion = this._removedExtraLibs[filePath] + 1;\n }\n this._extraLibs[filePath] = {\n content,\n version: myVersion\n };\n }\n }\n this._fireOnDidExtraLibsChangeSoon();\n }\n _fireOnDidExtraLibsChangeSoon() {\n if (this._onDidExtraLibsChangeTimeout !== -1) {\n return;\n }\n this._onDidExtraLibsChangeTimeout = window.setTimeout(() => {\n this._onDidExtraLibsChangeTimeout = -1;\n this._onDidExtraLibsChange.fire(void 0);\n }, 0);\n }\n getCompilerOptions() {\n return this._compilerOptions;\n }\n setCompilerOptions(options) {\n this._compilerOptions = options || /* @__PURE__ */ Object.create(null);\n this._onDidChange.fire(void 0);\n }\n getDiagnosticsOptions() {\n return this._diagnosticsOptions;\n }\n setDiagnosticsOptions(options) {\n this._diagnosticsOptions = options || /* @__PURE__ */ Object.create(null);\n this._onDidChange.fire(void 0);\n }\n setWorkerOptions(options) {\n this._workerOptions = options || /* @__PURE__ */ Object.create(null);\n this._onDidChange.fire(void 0);\n }\n setInlayHintsOptions(options) {\n this._inlayHintsOptions = options || /* @__PURE__ */ Object.create(null);\n this._onDidChange.fire(void 0);\n }\n setMaximumWorkerIdleTime(value) {\n }\n setEagerModelSync(value) {\n this._eagerModelSync = value;\n }\n getEagerModelSync() {\n return this._eagerModelSync;\n }\n};\nvar typescriptVersion2 = typescriptVersion;\nvar typescriptDefaults = new LanguageServiceDefaultsImpl({ allowNonTsExtensions: true, target: 99 /* Latest */ }, { noSemanticValidation: false, noSyntaxValidation: false, onlyVisible: false }, {}, {});\nvar javascriptDefaults = new LanguageServiceDefaultsImpl({ allowNonTsExtensions: true, allowJs: true, target: 99 /* Latest */ }, { noSemanticValidation: true, noSyntaxValidation: false, onlyVisible: false }, {}, {});\nvar getTypeScriptWorker = () => {\n return getMode().then((mode) => mode.getTypeScriptWorker());\n};\nvar getJavaScriptWorker = () => {\n return getMode().then((mode) => mode.getJavaScriptWorker());\n};\nmonaco_editor_core_exports.languages.typescript = {\n ModuleKind,\n JsxEmit,\n NewLineKind,\n ScriptTarget,\n ModuleResolutionKind,\n typescriptVersion: typescriptVersion2,\n typescriptDefaults,\n javascriptDefaults,\n getTypeScriptWorker,\n getJavaScriptWorker\n};\nfunction getMode() {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/language/typescript/tsMode\"], resolve, reject);\n });\n } else {\n return import(\"./tsMode\");\n }\n}\nmonaco_editor_core_exports.languages.onLanguage(\"typescript\", () => {\n return getMode().then((mode) => mode.setupTypeScript(typescriptDefaults));\n});\nmonaco_editor_core_exports.languages.onLanguage(\"javascript\", () => {\n return getMode().then((mode) => mode.setupJavaScript(javascriptDefaults));\n});\nexport {\n JsxEmit,\n ModuleKind,\n ModuleResolutionKind,\n NewLineKind,\n ScriptTarget,\n getJavaScriptWorker,\n getTypeScriptWorker,\n javascriptDefaults,\n typescriptDefaults,\n typescriptVersion2 as typescriptVersion\n};\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nlet isPseudo = (typeof document !== 'undefined' && document.location && document.location.hash.indexOf('pseudo=true') >= 0);\nconst DEFAULT_TAG = 'i-default';\nfunction _format(message, args) {\n let result;\n if (args.length === 0) {\n result = message;\n }\n else {\n result = message.replace(/\\{(\\d+)\\}/g, (match, rest) => {\n const index = rest[0];\n const arg = args[index];\n let 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 (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}\nfunction findLanguageForModule(config, name) {\n let result = config[name];\n if (result) {\n return result;\n }\n result = config['*'];\n if (result) {\n return result;\n }\n return null;\n}\nfunction endWithSlash(path) {\n if (path.charAt(path.length - 1) === '/') {\n return path;\n }\n return path + '/';\n}\nfunction getMessagesFromTranslationsService(translationServiceUrl, language, name) {\n return __awaiter(this, void 0, void 0, function* () {\n const url = endWithSlash(translationServiceUrl) + endWithSlash(language) + 'vscode/' + endWithSlash(name);\n const res = yield fetch(url);\n if (res.ok) {\n const messages = yield res.json();\n return messages;\n }\n throw new Error(`${res.status} - ${res.statusText}`);\n });\n}\nfunction createScopedLocalize(scope) {\n return function (idx, defaultValue) {\n const restArgs = Array.prototype.slice.call(arguments, 2);\n return _format(scope[idx], restArgs);\n };\n}\nexport function localize(data, message, ...args) {\n return _format(message, args);\n}\nexport function getConfiguredDefaultLocale(_) {\n // This returns undefined because this implementation isn't used and is overwritten by the loader\n // when loaded.\n return undefined;\n}\nexport function setPseudoTranslation(value) {\n isPseudo = value;\n}\n/**\n * Invoked in a built product at run-time\n */\nexport function create(key, data) {\n var _a;\n return {\n localize: createScopedLocalize(data[key]),\n getConfiguredDefaultLocale: (_a = data.getConfiguredDefaultLocale) !== null && _a !== void 0 ? _a : ((_) => undefined)\n };\n}\n/**\n * Invoked by the loader at run-time\n */\nexport function load(name, req, load, config) {\n var _a;\n const pluginConfig = (_a = config['vs/nls']) !== null && _a !== void 0 ? _a : {};\n if (!name || name.length === 0) {\n return load({\n localize: localize,\n getConfiguredDefaultLocale: () => { var _a; return (_a = pluginConfig.availableLanguages) === null || _a === void 0 ? void 0 : _a['*']; }\n });\n }\n const language = pluginConfig.availableLanguages ? findLanguageForModule(pluginConfig.availableLanguages, name) : null;\n const useDefaultLanguage = language === null || language === DEFAULT_TAG;\n let suffix = '.nls';\n if (!useDefaultLanguage) {\n suffix = suffix + '.' + language;\n }\n const messagesLoaded = (messages) => {\n if (Array.isArray(messages)) {\n messages.localize = createScopedLocalize(messages);\n }\n else {\n messages.localize = createScopedLocalize(messages[name]);\n }\n messages.getConfiguredDefaultLocale = () => { var _a; return (_a = pluginConfig.availableLanguages) === null || _a === void 0 ? void 0 : _a['*']; };\n load(messages);\n };\n if (typeof pluginConfig.loadBundle === 'function') {\n pluginConfig.loadBundle(name, language, (err, messages) => {\n // We have an error. Load the English default strings to not fail\n if (err) {\n req([name + '.nls'], messagesLoaded);\n }\n else {\n messagesLoaded(messages);\n }\n });\n }\n else if (pluginConfig.translationServiceUrl && !useDefaultLanguage) {\n (() => __awaiter(this, void 0, void 0, function* () {\n var _b;\n try {\n const messages = yield getMessagesFromTranslationsService(pluginConfig.translationServiceUrl, language, name);\n return messagesLoaded(messages);\n }\n catch (err) {\n // Language is already as generic as it gets, so require default messages\n if (!language.includes('-')) {\n console.error(err);\n return req([name + '.nls'], messagesLoaded);\n }\n try {\n // Since there is a dash, the language configured is a specific sub-language of the same generic language.\n // Since we were unable to load the specific language, try to load the generic language. Ex. we failed to find a\n // Swiss German (de-CH), so try to load the generic German (de) messages instead.\n const genericLanguage = language.split('-')[0];\n const messages = yield getMessagesFromTranslationsService(pluginConfig.translationServiceUrl, genericLanguage, name);\n // We got some messages, so we configure the configuration to use the generic language for this session.\n (_b = pluginConfig.availableLanguages) !== null && _b !== void 0 ? _b : (pluginConfig.availableLanguages = {});\n pluginConfig.availableLanguages['*'] = genericLanguage;\n return messagesLoaded(messages);\n }\n catch (err) {\n console.error(err);\n return req([name + '.nls'], messagesLoaded);\n }\n }\n }))();\n }\n else {\n req([name + suffix], messagesLoaded, (err) => {\n if (suffix === '.nls') {\n console.error('Failed trying to load default language strings', err);\n return;\n }\n console.error(`Failed to load message bundle for language ${language}. Falling back to the default language:`, err);\n req([name + '.nls'], messagesLoaded);\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 *--------------------------------------------------------------------------------------------*/\nimport { RawContextKey } from '../../contextkey/common/contextkey.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const IAccessibilityService = createDecorator('accessibilityService');\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { Separator, SubmenuAction } from '../../../base/common/actions.js';\nimport { CSSIcon } from '../../../base/common/codicons.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { Iterable } from '../../../base/common/iterator.js';\nimport { toDisposable } from '../../../base/common/lifecycle.js';\nimport { LinkedList } from '../../../base/common/linkedList.js';\nimport { ICommandService } from '../../commands/common/commands.js';\nimport { IContextKeyService } from '../../contextkey/common/contextkey.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nimport { ThemeIcon } from '../../theme/common/themeService.js';\nexport function isIMenuItem(item) {\n return item.command !== undefined;\n}\nexport class MenuId {\n /**\n * Create a new `MenuId` with the unique identifier. Will throw if a menu\n * with the identifier already exists, use `MenuId.for(ident)` or a unique\n * identifier\n */\n constructor(identifier) {\n if (MenuId._instances.has(identifier)) {\n throw new TypeError(`MenuId with identifier '${identifier}' already exists. Use MenuId.for(ident) or a unique identifier`);\n }\n MenuId._instances.set(identifier, this);\n this.id = identifier;\n }\n}\nMenuId._instances = new Map();\nMenuId.CommandPalette = new MenuId('CommandPalette');\nMenuId.DebugBreakpointsContext = new MenuId('DebugBreakpointsContext');\nMenuId.DebugCallStackContext = new MenuId('DebugCallStackContext');\nMenuId.DebugConsoleContext = new MenuId('DebugConsoleContext');\nMenuId.DebugVariablesContext = new MenuId('DebugVariablesContext');\nMenuId.DebugWatchContext = new MenuId('DebugWatchContext');\nMenuId.DebugToolBar = new MenuId('DebugToolBar');\nMenuId.DebugToolBarStop = new MenuId('DebugToolBarStop');\nMenuId.EditorContext = new MenuId('EditorContext');\nMenuId.SimpleEditorContext = new MenuId('SimpleEditorContext');\nMenuId.EditorContextCopy = new MenuId('EditorContextCopy');\nMenuId.EditorContextPeek = new MenuId('EditorContextPeek');\nMenuId.EditorContextShare = new MenuId('EditorContextShare');\nMenuId.EditorTitle = new MenuId('EditorTitle');\nMenuId.EditorTitleRun = new MenuId('EditorTitleRun');\nMenuId.EditorTitleContext = new MenuId('EditorTitleContext');\nMenuId.EmptyEditorGroup = new MenuId('EmptyEditorGroup');\nMenuId.EmptyEditorGroupContext = new MenuId('EmptyEditorGroupContext');\nMenuId.ExplorerContext = new MenuId('ExplorerContext');\nMenuId.ExtensionContext = new MenuId('ExtensionContext');\nMenuId.GlobalActivity = new MenuId('GlobalActivity');\nMenuId.CommandCenter = new MenuId('CommandCenter');\nMenuId.LayoutControlMenuSubmenu = new MenuId('LayoutControlMenuSubmenu');\nMenuId.LayoutControlMenu = new MenuId('LayoutControlMenu');\nMenuId.MenubarMainMenu = new MenuId('MenubarMainMenu');\nMenuId.MenubarAppearanceMenu = new MenuId('MenubarAppearanceMenu');\nMenuId.MenubarDebugMenu = new MenuId('MenubarDebugMenu');\nMenuId.MenubarEditMenu = new MenuId('MenubarEditMenu');\nMenuId.MenubarCopy = new MenuId('MenubarCopy');\nMenuId.MenubarFileMenu = new MenuId('MenubarFileMenu');\nMenuId.MenubarGoMenu = new MenuId('MenubarGoMenu');\nMenuId.MenubarHelpMenu = new MenuId('MenubarHelpMenu');\nMenuId.MenubarLayoutMenu = new MenuId('MenubarLayoutMenu');\nMenuId.MenubarNewBreakpointMenu = new MenuId('MenubarNewBreakpointMenu');\nMenuId.MenubarPanelAlignmentMenu = new MenuId('MenubarPanelAlignmentMenu');\nMenuId.MenubarPanelPositionMenu = new MenuId('MenubarPanelPositionMenu');\nMenuId.MenubarPreferencesMenu = new MenuId('MenubarPreferencesMenu');\nMenuId.MenubarRecentMenu = new MenuId('MenubarRecentMenu');\nMenuId.MenubarSelectionMenu = new MenuId('MenubarSelectionMenu');\nMenuId.MenubarShare = new MenuId('MenubarShare');\nMenuId.MenubarSwitchEditorMenu = new MenuId('MenubarSwitchEditorMenu');\nMenuId.MenubarSwitchGroupMenu = new MenuId('MenubarSwitchGroupMenu');\nMenuId.MenubarTerminalMenu = new MenuId('MenubarTerminalMenu');\nMenuId.MenubarViewMenu = new MenuId('MenubarViewMenu');\nMenuId.MenubarHomeMenu = new MenuId('MenubarHomeMenu');\nMenuId.OpenEditorsContext = new MenuId('OpenEditorsContext');\nMenuId.ProblemsPanelContext = new MenuId('ProblemsPanelContext');\nMenuId.SCMChangeContext = new MenuId('SCMChangeContext');\nMenuId.SCMResourceContext = new MenuId('SCMResourceContext');\nMenuId.SCMResourceFolderContext = new MenuId('SCMResourceFolderContext');\nMenuId.SCMResourceGroupContext = new MenuId('SCMResourceGroupContext');\nMenuId.SCMSourceControl = new MenuId('SCMSourceControl');\nMenuId.SCMTitle = new MenuId('SCMTitle');\nMenuId.SearchContext = new MenuId('SearchContext');\nMenuId.StatusBarWindowIndicatorMenu = new MenuId('StatusBarWindowIndicatorMenu');\nMenuId.StatusBarRemoteIndicatorMenu = new MenuId('StatusBarRemoteIndicatorMenu');\nMenuId.TestItem = new MenuId('TestItem');\nMenuId.TestItemGutter = new MenuId('TestItemGutter');\nMenuId.TestPeekElement = new MenuId('TestPeekElement');\nMenuId.TestPeekTitle = new MenuId('TestPeekTitle');\nMenuId.TouchBarContext = new MenuId('TouchBarContext');\nMenuId.TitleBarContext = new MenuId('TitleBarContext');\nMenuId.TitleBarTitleContext = new MenuId('TitleBarTitleContext');\nMenuId.TunnelContext = new MenuId('TunnelContext');\nMenuId.TunnelPrivacy = new MenuId('TunnelPrivacy');\nMenuId.TunnelProtocol = new MenuId('TunnelProtocol');\nMenuId.TunnelPortInline = new MenuId('TunnelInline');\nMenuId.TunnelTitle = new MenuId('TunnelTitle');\nMenuId.TunnelLocalAddressInline = new MenuId('TunnelLocalAddressInline');\nMenuId.TunnelOriginInline = new MenuId('TunnelOriginInline');\nMenuId.ViewItemContext = new MenuId('ViewItemContext');\nMenuId.ViewContainerTitle = new MenuId('ViewContainerTitle');\nMenuId.ViewContainerTitleContext = new MenuId('ViewContainerTitleContext');\nMenuId.ViewTitle = new MenuId('ViewTitle');\nMenuId.ViewTitleContext = new MenuId('ViewTitleContext');\nMenuId.CommentThreadTitle = new MenuId('CommentThreadTitle');\nMenuId.CommentThreadActions = new MenuId('CommentThreadActions');\nMenuId.CommentTitle = new MenuId('CommentTitle');\nMenuId.CommentActions = new MenuId('CommentActions');\nMenuId.InteractiveToolbar = new MenuId('InteractiveToolbar');\nMenuId.InteractiveCellTitle = new MenuId('InteractiveCellTitle');\nMenuId.InteractiveCellDelete = new MenuId('InteractiveCellDelete');\nMenuId.InteractiveCellExecute = new MenuId('InteractiveCellExecute');\nMenuId.InteractiveInputExecute = new MenuId('InteractiveInputExecute');\nMenuId.NotebookToolbar = new MenuId('NotebookToolbar');\nMenuId.NotebookCellTitle = new MenuId('NotebookCellTitle');\nMenuId.NotebookCellDelete = new MenuId('NotebookCellDelete');\nMenuId.NotebookCellInsert = new MenuId('NotebookCellInsert');\nMenuId.NotebookCellBetween = new MenuId('NotebookCellBetween');\nMenuId.NotebookCellListTop = new MenuId('NotebookCellTop');\nMenuId.NotebookCellExecute = new MenuId('NotebookCellExecute');\nMenuId.NotebookCellExecutePrimary = new MenuId('NotebookCellExecutePrimary');\nMenuId.NotebookDiffCellInputTitle = new MenuId('NotebookDiffCellInputTitle');\nMenuId.NotebookDiffCellMetadataTitle = new MenuId('NotebookDiffCellMetadataTitle');\nMenuId.NotebookDiffCellOutputsTitle = new MenuId('NotebookDiffCellOutputsTitle');\nMenuId.NotebookOutputToolbar = new MenuId('NotebookOutputToolbar');\nMenuId.NotebookEditorLayoutConfigure = new MenuId('NotebookEditorLayoutConfigure');\nMenuId.NotebookKernelSource = new MenuId('NotebookKernelSource');\nMenuId.BulkEditTitle = new MenuId('BulkEditTitle');\nMenuId.BulkEditContext = new MenuId('BulkEditContext');\nMenuId.TimelineItemContext = new MenuId('TimelineItemContext');\nMenuId.TimelineTitle = new MenuId('TimelineTitle');\nMenuId.TimelineTitleContext = new MenuId('TimelineTitleContext');\nMenuId.TimelineFilterSubMenu = new MenuId('TimelineFilterSubMenu');\nMenuId.AccountsContext = new MenuId('AccountsContext');\nMenuId.PanelTitle = new MenuId('PanelTitle');\nMenuId.AuxiliaryBarTitle = new MenuId('AuxiliaryBarTitle');\nMenuId.TerminalInstanceContext = new MenuId('TerminalInstanceContext');\nMenuId.TerminalEditorInstanceContext = new MenuId('TerminalEditorInstanceContext');\nMenuId.TerminalNewDropdownContext = new MenuId('TerminalNewDropdownContext');\nMenuId.TerminalTabContext = new MenuId('TerminalTabContext');\nMenuId.TerminalTabEmptyAreaContext = new MenuId('TerminalTabEmptyAreaContext');\nMenuId.TerminalInlineTabContext = new MenuId('TerminalInlineTabContext');\nMenuId.WebviewContext = new MenuId('WebviewContext');\nMenuId.InlineCompletionsActions = new MenuId('InlineCompletionsActions');\nMenuId.NewFile = new MenuId('NewFile');\nMenuId.MergeToolbar = new MenuId('MergeToolbar');\nMenuId.MergeInput1Toolbar = new MenuId('MergeToolbar1Toolbar');\nMenuId.MergeInput2Toolbar = new MenuId('MergeToolbar2Toolbar');\nexport const IMenuService = createDecorator('menuService');\nexport const MenuRegistry = new class {\n constructor() {\n this._commands = new Map();\n this._menuItems = new Map();\n this._onDidChangeMenu = new Emitter();\n this.onDidChangeMenu = this._onDidChangeMenu.event;\n this._commandPaletteChangeEvent = {\n has: id => id === MenuId.CommandPalette\n };\n }\n addCommand(command) {\n return this.addCommands(Iterable.single(command));\n }\n addCommands(commands) {\n for (const command of commands) {\n this._commands.set(command.id, command);\n }\n this._onDidChangeMenu.fire(this._commandPaletteChangeEvent);\n return toDisposable(() => {\n let didChange = false;\n for (const command of commands) {\n didChange = this._commands.delete(command.id) || didChange;\n }\n if (didChange) {\n this._onDidChangeMenu.fire(this._commandPaletteChangeEvent);\n }\n });\n }\n getCommand(id) {\n return this._commands.get(id);\n }\n getCommands() {\n const map = new Map();\n this._commands.forEach((value, key) => map.set(key, value));\n return map;\n }\n appendMenuItem(id, item) {\n return this.appendMenuItems(Iterable.single({ id, item }));\n }\n appendMenuItems(items) {\n const changedIds = new Set();\n const toRemove = new LinkedList();\n for (const { id, item } of items) {\n let list = this._menuItems.get(id);\n if (!list) {\n list = new LinkedList();\n this._menuItems.set(id, list);\n }\n toRemove.push(list.push(item));\n changedIds.add(id);\n }\n this._onDidChangeMenu.fire(changedIds);\n return toDisposable(() => {\n if (toRemove.size > 0) {\n for (const fn of toRemove) {\n fn();\n }\n this._onDidChangeMenu.fire(changedIds);\n toRemove.clear();\n }\n });\n }\n getMenuItems(id) {\n let result;\n if (this._menuItems.has(id)) {\n result = [...this._menuItems.get(id)];\n }\n else {\n result = [];\n }\n if (id === MenuId.CommandPalette) {\n // CommandPalette is special because it shows\n // all commands by default\n this._appendImplicitItems(result);\n }\n return result;\n }\n _appendImplicitItems(result) {\n const set = new Set();\n for (const item of result) {\n if (isIMenuItem(item)) {\n set.add(item.command.id);\n if (item.alt) {\n set.add(item.alt.id);\n }\n }\n }\n this._commands.forEach((command, id) => {\n if (!set.has(id)) {\n result.push({ command });\n }\n });\n }\n};\nexport class SubmenuItemAction extends SubmenuAction {\n constructor(item, _menuService, _contextKeyService, _options) {\n super(`submenuitem.${item.submenu.id}`, typeof item.title === 'string' ? item.title : item.title.value, [], 'submenu');\n this.item = item;\n this._menuService = _menuService;\n this._contextKeyService = _contextKeyService;\n this._options = _options;\n }\n get actions() {\n const result = [];\n const menu = this._menuService.createMenu(this.item.submenu, this._contextKeyService);\n const groups = menu.getActions(this._options);\n menu.dispose();\n for (const [, actions] of groups) {\n if (actions.length > 0) {\n result.push(...actions);\n result.push(new Separator());\n }\n }\n if (result.length) {\n result.pop(); // remove last separator\n }\n return result;\n }\n}\n// implements IAction, does NOT extend Action, so that no one\n// subscribes to events of Action or modified properties\nlet MenuItemAction = class MenuItemAction {\n constructor(item, alt, options, hideActions, contextKeyService, _commandService) {\n var _a, _b;\n this.hideActions = hideActions;\n this._commandService = _commandService;\n this.id = item.id;\n this.label = (options === null || options === void 0 ? void 0 : options.renderShortTitle) && item.shortTitle\n ? (typeof item.shortTitle === 'string' ? item.shortTitle : item.shortTitle.value)\n : (typeof item.title === 'string' ? item.title : item.title.value);\n this.tooltip = (_b = (typeof item.tooltip === 'string' ? item.tooltip : (_a = item.tooltip) === null || _a === void 0 ? void 0 : _a.value)) !== null && _b !== void 0 ? _b : '';\n this.enabled = !item.precondition || contextKeyService.contextMatchesRules(item.precondition);\n this.checked = undefined;\n if (item.toggled) {\n const toggled = (item.toggled.condition ? item.toggled : { condition: item.toggled });\n this.checked = contextKeyService.contextMatchesRules(toggled.condition);\n if (this.checked && toggled.tooltip) {\n this.tooltip = typeof toggled.tooltip === 'string' ? toggled.tooltip : toggled.tooltip.value;\n }\n if (toggled.title) {\n this.label = typeof toggled.title === 'string' ? toggled.title : toggled.title.value;\n }\n }\n this.item = item;\n this.alt = alt ? new MenuItemAction(alt, undefined, options, hideActions, contextKeyService, _commandService) : undefined;\n this._options = options;\n if (ThemeIcon.isThemeIcon(item.icon)) {\n this.class = CSSIcon.asClassName(item.icon);\n }\n }\n dispose() {\n // there is NOTHING to dispose and the MenuItemAction should\n // never have anything to dispose as it is a convenience type\n // to bridge into the rendering world.\n }\n run(...args) {\n var _a, _b;\n let runArgs = [];\n if ((_a = this._options) === null || _a === void 0 ? void 0 : _a.arg) {\n runArgs = [...runArgs, this._options.arg];\n }\n if ((_b = this._options) === null || _b === void 0 ? void 0 : _b.shouldForwardArgs) {\n runArgs = [...runArgs, ...args];\n }\n return this._commandService.executeCommand(this.id, ...runArgs);\n }\n};\nMenuItemAction = __decorate([\n __param(4, IContextKeyService),\n __param(5, ICommandService)\n], MenuItemAction);\nexport { MenuItemAction };\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 *--------------------------------------------------------------------------------------------*/\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const IClipboardService = createDecorator('clipboardService');\n","/*---------------------------------------------------------------------------------------------\n * 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 { Emitter } from '../../../base/common/event.js';\nimport { Iterable } from '../../../base/common/iterator.js';\nimport { Disposable, toDisposable } from '../../../base/common/lifecycle.js';\nimport { LinkedList } from '../../../base/common/linkedList.js';\nimport { validateConstraints } from '../../../base/common/types.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const ICommandService = createDecorator('commandService');\nexport const CommandsRegistry = new class {\n constructor() {\n this._commands = new Map();\n this._onDidRegisterCommand = new Emitter();\n this.onDidRegisterCommand = this._onDidRegisterCommand.event;\n }\n registerCommand(idOrCommand, handler) {\n if (!idOrCommand) {\n throw new Error(`invalid command`);\n }\n if (typeof idOrCommand === 'string') {\n if (!handler) {\n throw new Error(`invalid command`);\n }\n return this.registerCommand({ id: idOrCommand, handler });\n }\n // add argument validation if rich command metadata is provided\n if (idOrCommand.description) {\n const constraints = [];\n for (const arg of idOrCommand.description.args) {\n constraints.push(arg.constraint);\n }\n const actualHandler = idOrCommand.handler;\n idOrCommand.handler = function (accessor, ...args) {\n validateConstraints(args, constraints);\n return actualHandler(accessor, ...args);\n };\n }\n // find a place to store the command\n const { id } = idOrCommand;\n let commands = this._commands.get(id);\n if (!commands) {\n commands = new LinkedList();\n this._commands.set(id, commands);\n }\n const removeFn = commands.unshift(idOrCommand);\n const ret = toDisposable(() => {\n removeFn();\n const command = this._commands.get(id);\n if (command === null || command === void 0 ? void 0 : command.isEmpty()) {\n this._commands.delete(id);\n }\n });\n // tell the world about this command\n this._onDidRegisterCommand.fire(id);\n return ret;\n }\n registerCommandAlias(oldId, newId) {\n return CommandsRegistry.registerCommand(oldId, (accessor, ...args) => accessor.get(ICommandService).executeCommand(newId, ...args));\n }\n getCommand(id) {\n const list = this._commands.get(id);\n if (!list || list.isEmpty()) {\n return undefined;\n }\n return Iterable.first(list);\n }\n getCommands() {\n const result = new Map();\n for (const key of this._commands.keys()) {\n const command = this.getCommand(key);\n if (command) {\n result.set(key, command);\n }\n }\n return result;\n }\n};\nexport const NullCommandService = {\n _serviceBrand: undefined,\n onWillExecuteCommand: () => Disposable.None,\n onDidExecuteCommand: () => Disposable.None,\n executeCommand() {\n return Promise.resolve(undefined);\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 *--------------------------------------------------------------------------------------------*/\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const IConfigurationService = createDecorator('configurationService');\nexport function toValuesTree(properties, conflictReporter) {\n const root = Object.create(null);\n for (const key in properties) {\n addToValueTree(root, key, properties[key], conflictReporter);\n }\n return root;\n}\nexport function addToValueTree(settingsTreeRoot, key, value, conflictReporter) {\n const segments = key.split('.');\n const last = segments.pop();\n let curr = settingsTreeRoot;\n for (let i = 0; i < segments.length; i++) {\n const s = segments[i];\n let obj = curr[s];\n switch (typeof obj) {\n case 'undefined':\n obj = curr[s] = Object.create(null);\n break;\n case 'object':\n break;\n default:\n conflictReporter(`Ignoring ${key} as ${segments.slice(0, i + 1).join('.')} is ${JSON.stringify(obj)}`);\n return;\n }\n curr = obj;\n }\n if (typeof curr === 'object' && curr !== null) {\n try {\n curr[last] = value; // workaround https://github.com/microsoft/vscode/issues/13606\n }\n catch (e) {\n conflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`);\n }\n }\n else {\n conflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`);\n }\n}\nexport function removeFromValueTree(valueTree, key) {\n const segments = key.split('.');\n doRemoveFromValueTree(valueTree, segments);\n}\nfunction doRemoveFromValueTree(valueTree, segments) {\n const first = segments.shift();\n if (segments.length === 0) {\n // Reached last segment\n delete valueTree[first];\n return;\n }\n if (Object.keys(valueTree).indexOf(first) !== -1) {\n const value = valueTree[first];\n if (typeof value === 'object' && !Array.isArray(value)) {\n doRemoveFromValueTree(value, segments);\n if (Object.keys(value).length === 0) {\n delete valueTree[first];\n }\n }\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, settingPath, defaultValue) {\n function accessSetting(config, path) {\n let current = config;\n for (const component of path) {\n if (typeof current !== 'object' || current === null) {\n return undefined;\n }\n current = current[component];\n }\n return current;\n }\n const path = settingPath.split('.');\n const result = accessSetting(config, path);\n return typeof result === 'undefined' ? defaultValue : result;\n}\nexport function getLanguageTagSettingPlainKey(settingKey) {\n return settingKey.replace(/[\\[\\]]/g, '');\n}\n","/*---------------------------------------------------------------------------------------------\n * 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 { distinct } from '../../../base/common/arrays.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport * as types from '../../../base/common/types.js';\nimport * as nls from '../../../nls.js';\nimport { getLanguageTagSettingPlainKey } from './configuration.js';\nimport { Extensions as JSONExtensions } from '../../jsonschemas/common/jsonContributionRegistry.js';\nimport { Registry } from '../../registry/common/platform.js';\nexport const Extensions = {\n Configuration: 'base.contributions.configuration'\n};\nexport const allSettings = { properties: {}, patternProperties: {} };\nexport const applicationSettings = { properties: {}, patternProperties: {} };\nexport const machineSettings = { properties: {}, patternProperties: {} };\nexport const machineOverridableSettings = { properties: {}, patternProperties: {} };\nexport const windowSettings = { properties: {}, patternProperties: {} };\nexport const resourceSettings = { properties: {}, patternProperties: {} };\nexport const resourceLanguageSettingsSchemaId = 'vscode://schemas/settings/resourceLanguage';\nconst contributionRegistry = Registry.as(JSONExtensions.JSONContribution);\nclass ConfigurationRegistry {\n constructor() {\n this.overrideIdentifiers = new Set();\n this._onDidSchemaChange = new Emitter();\n this._onDidUpdateConfiguration = new Emitter();\n this.configurationDefaultsOverrides = new Map();\n this.defaultLanguageConfigurationOverridesNode = {\n id: 'defaultOverrides',\n title: nls.localize('defaultLanguageConfigurationOverrides.title', \"Default Language Configuration Overrides\"),\n properties: {}\n };\n this.configurationContributors = [this.defaultLanguageConfigurationOverridesNode];\n this.resourceLanguageSettingsSchema = { properties: {}, patternProperties: {}, additionalProperties: false, errorMessage: 'Unknown editor configuration setting', allowTrailingCommas: true, allowComments: true };\n this.configurationProperties = {};\n this.policyConfigurations = new Map();\n this.excludedConfigurationProperties = {};\n contributionRegistry.registerSchema(resourceLanguageSettingsSchemaId, this.resourceLanguageSettingsSchema);\n this.registerOverridePropertyPatternKey();\n }\n registerConfiguration(configuration, validate = true) {\n this.registerConfigurations([configuration], validate);\n }\n registerConfigurations(configurations, validate = true) {\n const properties = this.doRegisterConfigurations(configurations, validate);\n contributionRegistry.registerSchema(resourceLanguageSettingsSchemaId, this.resourceLanguageSettingsSchema);\n this._onDidSchemaChange.fire();\n this._onDidUpdateConfiguration.fire({ properties });\n }\n registerDefaultConfigurations(configurationDefaults) {\n var _a;\n const properties = [];\n const overrideIdentifiers = [];\n for (const { overrides, source } of configurationDefaults) {\n for (const key in overrides) {\n properties.push(key);\n if (OVERRIDE_PROPERTY_REGEX.test(key)) {\n const configurationDefaultOverride = this.configurationDefaultsOverrides.get(key);\n const valuesSources = (_a = configurationDefaultOverride === null || configurationDefaultOverride === void 0 ? void 0 : configurationDefaultOverride.valuesSources) !== null && _a !== void 0 ? _a : new Map();\n if (source) {\n for (const configuration of Object.keys(overrides[key])) {\n valuesSources.set(configuration, source);\n }\n }\n const defaultValue = Object.assign(Object.assign({}, ((configurationDefaultOverride === null || configurationDefaultOverride === void 0 ? void 0 : configurationDefaultOverride.value) || {})), overrides[key]);\n this.configurationDefaultsOverrides.set(key, { source, value: defaultValue, valuesSources });\n const plainKey = getLanguageTagSettingPlainKey(key);\n const property = {\n type: 'object',\n default: defaultValue,\n description: nls.localize('defaultLanguageConfiguration.description', \"Configure settings to be overridden for the {0} language.\", plainKey),\n $ref: resourceLanguageSettingsSchemaId,\n defaultDefaultValue: defaultValue,\n source: types.isString(source) ? undefined : source,\n defaultValueSource: source\n };\n overrideIdentifiers.push(...overrideIdentifiersFromKey(key));\n this.configurationProperties[key] = property;\n this.defaultLanguageConfigurationOverridesNode.properties[key] = property;\n }\n else {\n this.configurationDefaultsOverrides.set(key, { value: overrides[key], source });\n const property = this.configurationProperties[key];\n if (property) {\n this.updatePropertyDefaultValue(key, property);\n this.updateSchema(key, property);\n }\n }\n }\n }\n this.registerOverrideIdentifiers(overrideIdentifiers);\n this._onDidSchemaChange.fire();\n this._onDidUpdateConfiguration.fire({ properties, defaultsOverrides: true });\n }\n registerOverrideIdentifiers(overrideIdentifiers) {\n for (const overrideIdentifier of overrideIdentifiers) {\n this.overrideIdentifiers.add(overrideIdentifier);\n }\n this.updateOverridePropertyPatternKey();\n }\n doRegisterConfigurations(configurations, validate) {\n const properties = [];\n configurations.forEach(configuration => {\n properties.push(...this.validateAndRegisterProperties(configuration, validate, configuration.extensionInfo, configuration.restrictedProperties)); // fills in defaults\n this.configurationContributors.push(configuration);\n this.registerJSONConfiguration(configuration);\n });\n return properties;\n }\n validateAndRegisterProperties(configuration, validate = true, extensionInfo, restrictedProperties, scope = 3 /* ConfigurationScope.WINDOW */) {\n var _a;\n scope = types.isUndefinedOrNull(configuration.scope) ? scope : configuration.scope;\n const propertyKeys = [];\n const properties = configuration.properties;\n if (properties) {\n for (const key in properties) {\n const property = properties[key];\n if (validate && validateProperty(key, property)) {\n delete properties[key];\n continue;\n }\n property.source = extensionInfo;\n // update default value\n property.defaultDefaultValue = properties[key].default;\n this.updatePropertyDefaultValue(key, property);\n // update scope\n if (OVERRIDE_PROPERTY_REGEX.test(key)) {\n property.scope = undefined; // No scope for overridable properties `[${identifier}]`\n }\n else {\n property.scope = types.isUndefinedOrNull(property.scope) ? scope : property.scope;\n property.restricted = types.isUndefinedOrNull(property.restricted) ? !!(restrictedProperties === null || restrictedProperties === void 0 ? void 0 : restrictedProperties.includes(key)) : property.restricted;\n }\n // Add to properties maps\n // Property is included by default if 'included' is unspecified\n if (properties[key].hasOwnProperty('included') && !properties[key].included) {\n this.excludedConfigurationProperties[key] = properties[key];\n delete properties[key];\n continue;\n }\n else {\n this.configurationProperties[key] = properties[key];\n if ((_a = properties[key].policy) === null || _a === void 0 ? void 0 : _a.name) {\n this.policyConfigurations.set(properties[key].policy.name, key);\n }\n }\n if (!properties[key].deprecationMessage && properties[key].markdownDeprecationMessage) {\n // If not set, default deprecationMessage to the markdown source\n properties[key].deprecationMessage = properties[key].markdownDeprecationMessage;\n }\n propertyKeys.push(key);\n }\n }\n const subNodes = configuration.allOf;\n if (subNodes) {\n for (const node of subNodes) {\n propertyKeys.push(...this.validateAndRegisterProperties(node, validate, extensionInfo, restrictedProperties, scope));\n }\n }\n return propertyKeys;\n }\n getConfigurationProperties() {\n return this.configurationProperties;\n }\n getPolicyConfigurations() {\n return this.policyConfigurations;\n }\n registerJSONConfiguration(configuration) {\n const register = (configuration) => {\n const properties = configuration.properties;\n if (properties) {\n for (const key in properties) {\n this.updateSchema(key, properties[key]);\n }\n }\n const subNodes = configuration.allOf;\n subNodes === null || subNodes === void 0 ? void 0 : subNodes.forEach(register);\n };\n register(configuration);\n }\n updateSchema(key, property) {\n allSettings.properties[key] = property;\n switch (property.scope) {\n case 1 /* ConfigurationScope.APPLICATION */:\n applicationSettings.properties[key] = property;\n break;\n case 2 /* ConfigurationScope.MACHINE */:\n machineSettings.properties[key] = property;\n break;\n case 6 /* ConfigurationScope.MACHINE_OVERRIDABLE */:\n machineOverridableSettings.properties[key] = property;\n break;\n case 3 /* ConfigurationScope.WINDOW */:\n windowSettings.properties[key] = property;\n break;\n case 4 /* ConfigurationScope.RESOURCE */:\n resourceSettings.properties[key] = property;\n break;\n case 5 /* ConfigurationScope.LANGUAGE_OVERRIDABLE */:\n resourceSettings.properties[key] = property;\n this.resourceLanguageSettingsSchema.properties[key] = property;\n break;\n }\n }\n updateOverridePropertyPatternKey() {\n for (const overrideIdentifier of this.overrideIdentifiers.values()) {\n const overrideIdentifierProperty = `[${overrideIdentifier}]`;\n const resourceLanguagePropertiesSchema = {\n type: 'object',\n description: nls.localize('overrideSettings.defaultDescription', \"Configure editor settings to be overridden for a language.\"),\n errorMessage: nls.localize('overrideSettings.errorMessage', \"This setting does not support per-language configuration.\"),\n $ref: resourceLanguageSettingsSchemaId,\n };\n this.updatePropertyDefaultValue(overrideIdentifierProperty, resourceLanguagePropertiesSchema);\n allSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n applicationSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n machineSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n machineOverridableSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n windowSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n resourceSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;\n }\n this._onDidSchemaChange.fire();\n }\n registerOverridePropertyPatternKey() {\n const resourceLanguagePropertiesSchema = {\n type: 'object',\n description: nls.localize('overrideSettings.defaultDescription', \"Configure editor settings to be overridden for a language.\"),\n errorMessage: nls.localize('overrideSettings.errorMessage', \"This setting does not support per-language configuration.\"),\n $ref: resourceLanguageSettingsSchemaId,\n };\n allSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n applicationSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n machineSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n machineOverridableSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n windowSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n resourceSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;\n this._onDidSchemaChange.fire();\n }\n updatePropertyDefaultValue(key, property) {\n const configurationdefaultOverride = this.configurationDefaultsOverrides.get(key);\n let defaultValue = configurationdefaultOverride === null || configurationdefaultOverride === void 0 ? void 0 : configurationdefaultOverride.value;\n let defaultSource = configurationdefaultOverride === null || configurationdefaultOverride === void 0 ? void 0 : configurationdefaultOverride.source;\n if (types.isUndefined(defaultValue)) {\n defaultValue = property.defaultDefaultValue;\n defaultSource = undefined;\n }\n if (types.isUndefined(defaultValue)) {\n defaultValue = getDefaultValue(property.type);\n }\n property.default = defaultValue;\n property.defaultValueSource = defaultSource;\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);\nexport function overrideIdentifiersFromKey(key) {\n const identifiers = [];\n if (OVERRIDE_PROPERTY_REGEX.test(key)) {\n let matches = OVERRIDE_IDENTIFIER_REGEX.exec(key);\n while (matches === null || matches === void 0 ? void 0 : matches.length) {\n const identifier = matches[1].trim();\n if (identifier) {\n identifiers.push(identifier);\n }\n matches = OVERRIDE_IDENTIFIER_REGEX.exec(key);\n }\n }\n return distinct(identifiers);\n}\nexport function getDefaultValue(type) {\n const t = Array.isArray(type) ? type[0] : type;\n switch (t) {\n case 'boolean':\n return false;\n case 'integer':\n case 'number':\n return 0;\n case 'string':\n return '';\n case 'array':\n return [];\n case 'object':\n return {};\n default:\n return null;\n }\n}\nconst configurationRegistry = new ConfigurationRegistry();\nRegistry.add(Extensions.Configuration, configurationRegistry);\nexport function validateProperty(property, schema) {\n var _a, _b, _c, _d;\n if (!property.trim()) {\n return nls.localize('config.property.empty', \"Cannot register an empty property\");\n }\n if (OVERRIDE_PROPERTY_REGEX.test(property)) {\n return nls.localize('config.property.languageDefault', \"Cannot register '{0}'. This matches property pattern '\\\\\\\\[.*\\\\\\\\]$' for describing language specific editor settings. Use 'configurationDefaults' contribution.\", property);\n }\n if (configurationRegistry.getConfigurationProperties()[property] !== undefined) {\n return nls.localize('config.property.duplicate', \"Cannot register '{0}'. This property is already registered.\", property);\n }\n if (((_a = schema.policy) === null || _a === void 0 ? void 0 : _a.name) && configurationRegistry.getPolicyConfigurations().get((_b = schema.policy) === null || _b === void 0 ? void 0 : _b.name) !== undefined) {\n return nls.localize('config.policy.duplicate', \"Cannot register '{0}'. The associated policy {1} is already registered with {2}.\", property, (_c = schema.policy) === null || _c === void 0 ? void 0 : _c.name, configurationRegistry.getPolicyConfigurations().get((_d = schema.policy) === null || _d === void 0 ? void 0 : _d.name));\n }\n return 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 *--------------------------------------------------------------------------------------------*/\nimport { isChrome, isEdge, isFirefox, isLinux, isMacintosh, isSafari, isWeb, isWindows } from '../../../base/common/platform.js';\nimport { isFalsyOrWhitespace } from '../../../base/common/strings.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\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);\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nexport class ContextKeyExpr {\n static has(key) {\n return ContextKeyDefinedExpr.create(key);\n }\n static equals(key, value) {\n return ContextKeyEqualsExpr.create(key, value);\n }\n static regex(key, value) {\n return ContextKeyRegexExpr.create(key, value);\n }\n static not(key) {\n return ContextKeyNotExpr.create(key);\n }\n static and(...expr) {\n return ContextKeyAndExpr.create(expr, null);\n }\n static or(...expr) {\n return ContextKeyOrExpr.create(expr, null, true);\n }\n static deserialize(serialized, strict = false) {\n if (!serialized) {\n return undefined;\n }\n return this._deserializeOrExpression(serialized, strict);\n }\n static _deserializeOrExpression(serialized, strict) {\n const pieces = serialized.split('||');\n return ContextKeyOrExpr.create(pieces.map(p => this._deserializeAndExpression(p, strict)), null, true);\n }\n static _deserializeAndExpression(serialized, strict) {\n const pieces = serialized.split('&&');\n return ContextKeyAndExpr.create(pieces.map(p => this._deserializeOne(p, strict)), null);\n }\n static _deserializeOne(serializedOne, strict) {\n serializedOne = serializedOne.trim();\n if (serializedOne.indexOf('!=') >= 0) {\n const pieces = serializedOne.split('!=');\n return ContextKeyNotEqualsExpr.create(pieces[0].trim(), this._deserializeValue(pieces[1], strict));\n }\n if (serializedOne.indexOf('==') >= 0) {\n const pieces = serializedOne.split('==');\n return ContextKeyEqualsExpr.create(pieces[0].trim(), this._deserializeValue(pieces[1], strict));\n }\n if (serializedOne.indexOf('=~') >= 0) {\n const pieces = serializedOne.split('=~');\n return ContextKeyRegexExpr.create(pieces[0].trim(), this._deserializeRegexValue(pieces[1], strict));\n }\n if (serializedOne.indexOf(' not in ') >= 0) {\n const pieces = serializedOne.split(' not in ');\n return ContextKeyNotInExpr.create(pieces[0].trim(), pieces[1].trim());\n }\n if (serializedOne.indexOf(' in ') >= 0) {\n const pieces = serializedOne.split(' in ');\n return ContextKeyInExpr.create(pieces[0].trim(), pieces[1].trim());\n }\n if (/^[^<=>]+>=[^<=>]+$/.test(serializedOne)) {\n const pieces = serializedOne.split('>=');\n return ContextKeyGreaterEqualsExpr.create(pieces[0].trim(), pieces[1].trim());\n }\n if (/^[^<=>]+>[^<=>]+$/.test(serializedOne)) {\n const pieces = serializedOne.split('>');\n return ContextKeyGreaterExpr.create(pieces[0].trim(), pieces[1].trim());\n }\n if (/^[^<=>]+<=[^<=>]+$/.test(serializedOne)) {\n const pieces = serializedOne.split('<=');\n return ContextKeySmallerEqualsExpr.create(pieces[0].trim(), pieces[1].trim());\n }\n if (/^[^<=>]+<[^<=>]+$/.test(serializedOne)) {\n const pieces = serializedOne.split('<');\n return ContextKeySmallerExpr.create(pieces[0].trim(), pieces[1].trim());\n }\n if (/^\\!\\s*/.test(serializedOne)) {\n return ContextKeyNotExpr.create(serializedOne.substr(1).trim());\n }\n return ContextKeyDefinedExpr.create(serializedOne);\n }\n static _deserializeValue(serializedValue, strict) {\n serializedValue = serializedValue.trim();\n if (serializedValue === 'true') {\n return true;\n }\n if (serializedValue === 'false') {\n return false;\n }\n const m = /^'([^']*)'$/.exec(serializedValue);\n if (m) {\n return m[1].trim();\n }\n return serializedValue;\n }\n static _deserializeRegexValue(serializedValue, strict) {\n if (isFalsyOrWhitespace(serializedValue)) {\n if (strict) {\n throw new Error('missing regexp-value for =~-expression');\n }\n else {\n console.warn('missing regexp-value for =~-expression');\n }\n return null;\n }\n const start = serializedValue.indexOf('/');\n const end = serializedValue.lastIndexOf('/');\n if (start === end || start < 0 /* || to < 0 */) {\n if (strict) {\n throw new Error(`bad regexp-value '${serializedValue}', missing /-enclosure`);\n }\n else {\n console.warn(`bad regexp-value '${serializedValue}', missing /-enclosure`);\n }\n return null;\n }\n const value = serializedValue.slice(start + 1, end);\n const caseIgnoreFlag = serializedValue[end + 1] === 'i' ? 'i' : '';\n try {\n return new RegExp(value, caseIgnoreFlag);\n }\n catch (e) {\n if (strict) {\n throw new Error(`bad regexp-value '${serializedValue}', parse error: ${e}`);\n }\n else {\n console.warn(`bad regexp-value '${serializedValue}', parse error: ${e}`);\n }\n return null;\n }\n }\n}\nexport function expressionsAreEqualWithConstantSubstitution(a, b) {\n const aExpr = a ? a.substituteConstants() : undefined;\n const bExpr = b ? b.substituteConstants() : undefined;\n if (!aExpr && !bExpr) {\n return true;\n }\n if (!aExpr || !bExpr) {\n return false;\n }\n return aExpr.equals(bExpr);\n}\nfunction cmp(a, b) {\n return a.cmp(b);\n}\nexport class ContextKeyFalseExpr {\n constructor() {\n this.type = 0 /* ContextKeyExprType.False */;\n }\n cmp(other) {\n return this.type - other.type;\n }\n equals(other) {\n return (other.type === this.type);\n }\n substituteConstants() {\n return this;\n }\n evaluate(context) {\n return false;\n }\n serialize() {\n return 'false';\n }\n keys() {\n return [];\n }\n negate() {\n return ContextKeyTrueExpr.INSTANCE;\n }\n}\nContextKeyFalseExpr.INSTANCE = new ContextKeyFalseExpr();\nexport class ContextKeyTrueExpr {\n constructor() {\n this.type = 1 /* ContextKeyExprType.True */;\n }\n cmp(other) {\n return this.type - other.type;\n }\n equals(other) {\n return (other.type === this.type);\n }\n substituteConstants() {\n return this;\n }\n evaluate(context) {\n return true;\n }\n serialize() {\n return 'true';\n }\n keys() {\n return [];\n }\n negate() {\n return ContextKeyFalseExpr.INSTANCE;\n }\n}\nContextKeyTrueExpr.INSTANCE = new ContextKeyTrueExpr();\nexport class ContextKeyDefinedExpr {\n constructor(key, negated) {\n this.key = key;\n this.negated = negated;\n this.type = 2 /* ContextKeyExprType.Defined */;\n }\n static create(key, negated = null) {\n const constantValue = CONSTANT_VALUES.get(key);\n if (typeof constantValue === 'boolean') {\n return constantValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE;\n }\n return new ContextKeyDefinedExpr(key, negated);\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n return cmp1(this.key, other.key);\n }\n equals(other) {\n if (other.type === this.type) {\n return (this.key === other.key);\n }\n return false;\n }\n substituteConstants() {\n const constantValue = CONSTANT_VALUES.get(this.key);\n if (typeof constantValue === 'boolean') {\n return constantValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE;\n }\n return this;\n }\n evaluate(context) {\n return (!!context.getValue(this.key));\n }\n serialize() {\n return this.key;\n }\n keys() {\n return [this.key];\n }\n negate() {\n if (!this.negated) {\n this.negated = ContextKeyNotExpr.create(this.key, this);\n }\n return this.negated;\n }\n}\nexport class ContextKeyEqualsExpr {\n constructor(key, value, negated) {\n this.key = key;\n this.value = value;\n this.negated = negated;\n this.type = 4 /* ContextKeyExprType.Equals */;\n }\n static create(key, value, negated = null) {\n if (typeof value === 'boolean') {\n return (value ? ContextKeyDefinedExpr.create(key, negated) : ContextKeyNotExpr.create(key, negated));\n }\n const constantValue = CONSTANT_VALUES.get(key);\n if (typeof constantValue === 'boolean') {\n const trueValue = constantValue ? 'true' : 'false';\n return (value === trueValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE);\n }\n return new ContextKeyEqualsExpr(key, value, negated);\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n return cmp2(this.key, this.value, other.key, other.value);\n }\n equals(other) {\n if (other.type === this.type) {\n return (this.key === other.key && this.value === other.value);\n }\n return false;\n }\n substituteConstants() {\n const constantValue = CONSTANT_VALUES.get(this.key);\n if (typeof constantValue === 'boolean') {\n const trueValue = constantValue ? 'true' : 'false';\n return (this.value === trueValue ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE);\n }\n return this;\n }\n evaluate(context) {\n // Intentional ==\n // eslint-disable-next-line eqeqeq\n return (context.getValue(this.key) == this.value);\n }\n serialize() {\n return `${this.key} == '${this.value}'`;\n }\n keys() {\n return [this.key];\n }\n negate() {\n if (!this.negated) {\n this.negated = ContextKeyNotEqualsExpr.create(this.key, this.value, this);\n }\n return this.negated;\n }\n}\nexport class ContextKeyInExpr {\n constructor(key, valueKey) {\n this.key = key;\n this.valueKey = valueKey;\n this.type = 10 /* ContextKeyExprType.In */;\n this.negated = null;\n }\n static create(key, valueKey) {\n return new ContextKeyInExpr(key, valueKey);\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n return cmp2(this.key, this.valueKey, other.key, other.valueKey);\n }\n equals(other) {\n if (other.type === this.type) {\n return (this.key === other.key && this.valueKey === other.valueKey);\n }\n return false;\n }\n substituteConstants() {\n return this;\n }\n evaluate(context) {\n const source = context.getValue(this.valueKey);\n const item = context.getValue(this.key);\n if (Array.isArray(source)) {\n return source.includes(item);\n }\n if (typeof item === 'string' && typeof source === 'object' && source !== null) {\n return hasOwnProperty.call(source, item);\n }\n return false;\n }\n serialize() {\n return `${this.key} in '${this.valueKey}'`;\n }\n keys() {\n return [this.key, this.valueKey];\n }\n negate() {\n if (!this.negated) {\n this.negated = ContextKeyNotInExpr.create(this.key, this.valueKey);\n }\n return this.negated;\n }\n}\nexport class ContextKeyNotInExpr {\n constructor(key, valueKey) {\n this.key = key;\n this.valueKey = valueKey;\n this.type = 11 /* ContextKeyExprType.NotIn */;\n this._negated = ContextKeyInExpr.create(key, valueKey);\n }\n static create(key, valueKey) {\n return new ContextKeyNotInExpr(key, valueKey);\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n return this._negated.cmp(other._negated);\n }\n equals(other) {\n if (other.type === this.type) {\n return this._negated.equals(other._negated);\n }\n return false;\n }\n substituteConstants() {\n return this;\n }\n evaluate(context) {\n return !this._negated.evaluate(context);\n }\n serialize() {\n return `${this.key} not in '${this.valueKey}'`;\n }\n keys() {\n return this._negated.keys();\n }\n negate() {\n return this._negated;\n }\n}\nexport class ContextKeyNotEqualsExpr {\n constructor(key, value, negated) {\n this.key = key;\n this.value = value;\n this.negated = negated;\n this.type = 5 /* ContextKeyExprType.NotEquals */;\n }\n static create(key, value, negated = null) {\n if (typeof value === 'boolean') {\n if (value) {\n return ContextKeyNotExpr.create(key, negated);\n }\n return ContextKeyDefinedExpr.create(key, negated);\n }\n const constantValue = CONSTANT_VALUES.get(key);\n if (typeof constantValue === 'boolean') {\n const falseValue = constantValue ? 'true' : 'false';\n return (value === falseValue ? ContextKeyFalseExpr.INSTANCE : ContextKeyTrueExpr.INSTANCE);\n }\n return new ContextKeyNotEqualsExpr(key, value, negated);\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n return cmp2(this.key, this.value, other.key, other.value);\n }\n equals(other) {\n if (other.type === this.type) {\n return (this.key === other.key && this.value === other.value);\n }\n return false;\n }\n substituteConstants() {\n const constantValue = CONSTANT_VALUES.get(this.key);\n if (typeof constantValue === 'boolean') {\n const falseValue = constantValue ? 'true' : 'false';\n return (this.value === falseValue ? ContextKeyFalseExpr.INSTANCE : ContextKeyTrueExpr.INSTANCE);\n }\n return this;\n }\n evaluate(context) {\n // Intentional !=\n // eslint-disable-next-line eqeqeq\n return (context.getValue(this.key) != this.value);\n }\n serialize() {\n return `${this.key} != '${this.value}'`;\n }\n keys() {\n return [this.key];\n }\n negate() {\n if (!this.negated) {\n this.negated = ContextKeyEqualsExpr.create(this.key, this.value, this);\n }\n return this.negated;\n }\n}\nexport class ContextKeyNotExpr {\n constructor(key, negated) {\n this.key = key;\n this.negated = negated;\n this.type = 3 /* ContextKeyExprType.Not */;\n }\n static create(key, negated = null) {\n const constantValue = CONSTANT_VALUES.get(key);\n if (typeof constantValue === 'boolean') {\n return (constantValue ? ContextKeyFalseExpr.INSTANCE : ContextKeyTrueExpr.INSTANCE);\n }\n return new ContextKeyNotExpr(key, negated);\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n return cmp1(this.key, other.key);\n }\n equals(other) {\n if (other.type === this.type) {\n return (this.key === other.key);\n }\n return false;\n }\n substituteConstants() {\n const constantValue = CONSTANT_VALUES.get(this.key);\n if (typeof constantValue === 'boolean') {\n return (constantValue ? ContextKeyFalseExpr.INSTANCE : ContextKeyTrueExpr.INSTANCE);\n }\n return this;\n }\n evaluate(context) {\n return (!context.getValue(this.key));\n }\n serialize() {\n return `!${this.key}`;\n }\n keys() {\n return [this.key];\n }\n negate() {\n if (!this.negated) {\n this.negated = ContextKeyDefinedExpr.create(this.key, this);\n }\n return this.negated;\n }\n}\nfunction withFloatOrStr(value, callback) {\n if (typeof value === 'string') {\n const n = parseFloat(value);\n if (!isNaN(n)) {\n value = n;\n }\n }\n if (typeof value === 'string' || typeof value === 'number') {\n return callback(value);\n }\n return ContextKeyFalseExpr.INSTANCE;\n}\nexport class ContextKeyGreaterExpr {\n constructor(key, value, negated) {\n this.key = key;\n this.value = value;\n this.negated = negated;\n this.type = 12 /* ContextKeyExprType.Greater */;\n }\n static create(key, _value, negated = null) {\n return withFloatOrStr(_value, (value) => new ContextKeyGreaterExpr(key, value, negated));\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n return cmp2(this.key, this.value, other.key, other.value);\n }\n equals(other) {\n if (other.type === this.type) {\n return (this.key === other.key && this.value === other.value);\n }\n return false;\n }\n substituteConstants() {\n return this;\n }\n evaluate(context) {\n if (typeof this.value === 'string') {\n return false;\n }\n return (parseFloat(context.getValue(this.key)) > this.value);\n }\n serialize() {\n return `${this.key} > ${this.value}`;\n }\n keys() {\n return [this.key];\n }\n negate() {\n if (!this.negated) {\n this.negated = ContextKeySmallerEqualsExpr.create(this.key, this.value, this);\n }\n return this.negated;\n }\n}\nexport class ContextKeyGreaterEqualsExpr {\n constructor(key, value, negated) {\n this.key = key;\n this.value = value;\n this.negated = negated;\n this.type = 13 /* ContextKeyExprType.GreaterEquals */;\n }\n static create(key, _value, negated = null) {\n return withFloatOrStr(_value, (value) => new ContextKeyGreaterEqualsExpr(key, value, negated));\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n return cmp2(this.key, this.value, other.key, other.value);\n }\n equals(other) {\n if (other.type === this.type) {\n return (this.key === other.key && this.value === other.value);\n }\n return false;\n }\n substituteConstants() {\n return this;\n }\n evaluate(context) {\n if (typeof this.value === 'string') {\n return false;\n }\n return (parseFloat(context.getValue(this.key)) >= this.value);\n }\n serialize() {\n return `${this.key} >= ${this.value}`;\n }\n keys() {\n return [this.key];\n }\n negate() {\n if (!this.negated) {\n this.negated = ContextKeySmallerExpr.create(this.key, this.value, this);\n }\n return this.negated;\n }\n}\nexport class ContextKeySmallerExpr {\n constructor(key, value, negated) {\n this.key = key;\n this.value = value;\n this.negated = negated;\n this.type = 14 /* ContextKeyExprType.Smaller */;\n }\n static create(key, _value, negated = null) {\n return withFloatOrStr(_value, (value) => new ContextKeySmallerExpr(key, value, negated));\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n return cmp2(this.key, this.value, other.key, other.value);\n }\n equals(other) {\n if (other.type === this.type) {\n return (this.key === other.key && this.value === other.value);\n }\n return false;\n }\n substituteConstants() {\n return this;\n }\n evaluate(context) {\n if (typeof this.value === 'string') {\n return false;\n }\n return (parseFloat(context.getValue(this.key)) < this.value);\n }\n serialize() {\n return `${this.key} < ${this.value}`;\n }\n keys() {\n return [this.key];\n }\n negate() {\n if (!this.negated) {\n this.negated = ContextKeyGreaterEqualsExpr.create(this.key, this.value, this);\n }\n return this.negated;\n }\n}\nexport class ContextKeySmallerEqualsExpr {\n constructor(key, value, negated) {\n this.key = key;\n this.value = value;\n this.negated = negated;\n this.type = 15 /* ContextKeyExprType.SmallerEquals */;\n }\n static create(key, _value, negated = null) {\n return withFloatOrStr(_value, (value) => new ContextKeySmallerEqualsExpr(key, value, negated));\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n return cmp2(this.key, this.value, other.key, other.value);\n }\n equals(other) {\n if (other.type === this.type) {\n return (this.key === other.key && this.value === other.value);\n }\n return false;\n }\n substituteConstants() {\n return this;\n }\n evaluate(context) {\n if (typeof this.value === 'string') {\n return false;\n }\n return (parseFloat(context.getValue(this.key)) <= this.value);\n }\n serialize() {\n return `${this.key} <= ${this.value}`;\n }\n keys() {\n return [this.key];\n }\n negate() {\n if (!this.negated) {\n this.negated = ContextKeyGreaterExpr.create(this.key, this.value, this);\n }\n return this.negated;\n }\n}\nexport class ContextKeyRegexExpr {\n constructor(key, regexp) {\n this.key = key;\n this.regexp = regexp;\n this.type = 7 /* ContextKeyExprType.Regex */;\n this.negated = null;\n //\n }\n static create(key, regexp) {\n return new ContextKeyRegexExpr(key, regexp);\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n if (this.key < other.key) {\n return -1;\n }\n if (this.key > other.key) {\n return 1;\n }\n const thisSource = this.regexp ? this.regexp.source : '';\n const otherSource = other.regexp ? other.regexp.source : '';\n if (thisSource < otherSource) {\n return -1;\n }\n if (thisSource > otherSource) {\n return 1;\n }\n return 0;\n }\n equals(other) {\n if (other.type === this.type) {\n const thisSource = this.regexp ? this.regexp.source : '';\n const otherSource = other.regexp ? other.regexp.source : '';\n return (this.key === other.key && thisSource === otherSource);\n }\n return false;\n }\n substituteConstants() {\n return this;\n }\n evaluate(context) {\n const value = context.getValue(this.key);\n return this.regexp ? this.regexp.test(value) : false;\n }\n serialize() {\n const value = this.regexp\n ? `/${this.regexp.source}/${this.regexp.ignoreCase ? 'i' : ''}`\n : '/invalid/';\n return `${this.key} =~ ${value}`;\n }\n keys() {\n return [this.key];\n }\n negate() {\n if (!this.negated) {\n this.negated = ContextKeyNotRegexExpr.create(this);\n }\n return this.negated;\n }\n}\nexport class ContextKeyNotRegexExpr {\n constructor(_actual) {\n this._actual = _actual;\n this.type = 8 /* ContextKeyExprType.NotRegex */;\n //\n }\n static create(actual) {\n return new ContextKeyNotRegexExpr(actual);\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n return this._actual.cmp(other._actual);\n }\n equals(other) {\n if (other.type === this.type) {\n return this._actual.equals(other._actual);\n }\n return false;\n }\n substituteConstants() {\n return this;\n }\n evaluate(context) {\n return !this._actual.evaluate(context);\n }\n serialize() {\n throw new Error('Method not implemented.');\n }\n keys() {\n return this._actual.keys();\n }\n negate() {\n return this._actual;\n }\n}\n/**\n * @returns the same instance if nothing changed.\n */\nfunction eliminateConstantsInArray(arr) {\n // Allocate array only if there is a difference\n let newArr = null;\n for (let i = 0, len = arr.length; i < len; i++) {\n const newExpr = arr[i].substituteConstants();\n if (arr[i] !== newExpr) {\n // something has changed!\n // allocate array on first difference\n if (newArr === null) {\n newArr = [];\n for (let j = 0; j < i; j++) {\n newArr[j] = arr[j];\n }\n }\n }\n if (newArr !== null) {\n newArr[i] = newExpr;\n }\n }\n if (newArr === null) {\n return arr;\n }\n return newArr;\n}\nclass ContextKeyAndExpr {\n constructor(expr, negated) {\n this.expr = expr;\n this.negated = negated;\n this.type = 6 /* ContextKeyExprType.And */;\n }\n static create(_expr, negated) {\n return ContextKeyAndExpr._normalizeArr(_expr, negated);\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n if (this.expr.length < other.expr.length) {\n return -1;\n }\n if (this.expr.length > other.expr.length) {\n return 1;\n }\n for (let i = 0, len = this.expr.length; i < len; i++) {\n const r = cmp(this.expr[i], other.expr[i]);\n if (r !== 0) {\n return r;\n }\n }\n return 0;\n }\n equals(other) {\n if (other.type === this.type) {\n if (this.expr.length !== other.expr.length) {\n return false;\n }\n for (let i = 0, len = this.expr.length; i < len; i++) {\n if (!this.expr[i].equals(other.expr[i])) {\n return false;\n }\n }\n return true;\n }\n return false;\n }\n substituteConstants() {\n const exprArr = eliminateConstantsInArray(this.expr);\n if (exprArr === this.expr) {\n // no change\n return this;\n }\n return ContextKeyAndExpr.create(exprArr, this.negated);\n }\n evaluate(context) {\n for (let i = 0, len = this.expr.length; i < len; i++) {\n if (!this.expr[i].evaluate(context)) {\n return false;\n }\n }\n return true;\n }\n static _normalizeArr(arr, negated) {\n const expr = [];\n let hasTrue = false;\n for (const e of arr) {\n if (!e) {\n continue;\n }\n if (e.type === 1 /* ContextKeyExprType.True */) {\n // anything && true ==> anything\n hasTrue = true;\n continue;\n }\n if (e.type === 0 /* ContextKeyExprType.False */) {\n // anything && false ==> false\n return ContextKeyFalseExpr.INSTANCE;\n }\n if (e.type === 6 /* ContextKeyExprType.And */) {\n expr.push(...e.expr);\n continue;\n }\n expr.push(e);\n }\n if (expr.length === 0 && hasTrue) {\n return ContextKeyTrueExpr.INSTANCE;\n }\n if (expr.length === 0) {\n return undefined;\n }\n if (expr.length === 1) {\n return expr[0];\n }\n expr.sort(cmp);\n // eliminate duplicate terms\n for (let i = 1; i < expr.length; i++) {\n if (expr[i - 1].equals(expr[i])) {\n expr.splice(i, 1);\n i--;\n }\n }\n if (expr.length === 1) {\n return expr[0];\n }\n // We must distribute any OR expression because we don't support parens\n // OR extensions will be at the end (due to sorting rules)\n while (expr.length > 1) {\n const lastElement = expr[expr.length - 1];\n if (lastElement.type !== 9 /* ContextKeyExprType.Or */) {\n break;\n }\n // pop the last element\n expr.pop();\n // pop the second to last element\n const secondToLastElement = expr.pop();\n const isFinished = (expr.length === 0);\n // distribute `lastElement` over `secondToLastElement`\n const resultElement = ContextKeyOrExpr.create(lastElement.expr.map(el => ContextKeyAndExpr.create([el, secondToLastElement], null)), null, isFinished);\n if (resultElement) {\n expr.push(resultElement);\n expr.sort(cmp);\n }\n }\n if (expr.length === 1) {\n return expr[0];\n }\n return new ContextKeyAndExpr(expr, negated);\n }\n serialize() {\n return this.expr.map(e => e.serialize()).join(' && ');\n }\n keys() {\n const result = [];\n for (const expr of this.expr) {\n result.push(...expr.keys());\n }\n return result;\n }\n negate() {\n if (!this.negated) {\n const result = [];\n for (const expr of this.expr) {\n result.push(expr.negate());\n }\n this.negated = ContextKeyOrExpr.create(result, this, true);\n }\n return this.negated;\n }\n}\nclass ContextKeyOrExpr {\n constructor(expr, negated) {\n this.expr = expr;\n this.negated = negated;\n this.type = 9 /* ContextKeyExprType.Or */;\n }\n static create(_expr, negated, extraRedundantCheck) {\n return ContextKeyOrExpr._normalizeArr(_expr, negated, extraRedundantCheck);\n }\n cmp(other) {\n if (other.type !== this.type) {\n return this.type - other.type;\n }\n if (this.expr.length < other.expr.length) {\n return -1;\n }\n if (this.expr.length > other.expr.length) {\n return 1;\n }\n for (let i = 0, len = this.expr.length; i < len; i++) {\n const r = cmp(this.expr[i], other.expr[i]);\n if (r !== 0) {\n return r;\n }\n }\n return 0;\n }\n equals(other) {\n if (other.type === this.type) {\n if (this.expr.length !== other.expr.length) {\n return false;\n }\n for (let i = 0, len = this.expr.length; i < len; i++) {\n if (!this.expr[i].equals(other.expr[i])) {\n return false;\n }\n }\n return true;\n }\n return false;\n }\n substituteConstants() {\n const exprArr = eliminateConstantsInArray(this.expr);\n if (exprArr === this.expr) {\n // no change\n return this;\n }\n return ContextKeyOrExpr.create(exprArr, this.negated, false);\n }\n evaluate(context) {\n for (let i = 0, len = this.expr.length; i < len; i++) {\n if (this.expr[i].evaluate(context)) {\n return true;\n }\n }\n return false;\n }\n static _normalizeArr(arr, negated, extraRedundantCheck) {\n let expr = [];\n let hasFalse = false;\n if (arr) {\n for (let i = 0, len = arr.length; i < len; i++) {\n const e = arr[i];\n if (!e) {\n continue;\n }\n if (e.type === 0 /* ContextKeyExprType.False */) {\n // anything || false ==> anything\n hasFalse = true;\n continue;\n }\n if (e.type === 1 /* ContextKeyExprType.True */) {\n // anything || true ==> true\n return ContextKeyTrueExpr.INSTANCE;\n }\n if (e.type === 9 /* ContextKeyExprType.Or */) {\n expr = expr.concat(e.expr);\n continue;\n }\n expr.push(e);\n }\n if (expr.length === 0 && hasFalse) {\n return ContextKeyFalseExpr.INSTANCE;\n }\n expr.sort(cmp);\n }\n if (expr.length === 0) {\n return undefined;\n }\n if (expr.length === 1) {\n return expr[0];\n }\n // eliminate duplicate terms\n for (let i = 1; i < expr.length; i++) {\n if (expr[i - 1].equals(expr[i])) {\n expr.splice(i, 1);\n i--;\n }\n }\n if (expr.length === 1) {\n return expr[0];\n }\n // eliminate redundant terms\n if (extraRedundantCheck) {\n for (let i = 0; i < expr.length; i++) {\n for (let j = i + 1; j < expr.length; j++) {\n if (implies(expr[i], expr[j])) {\n expr.splice(j, 1);\n j--;\n }\n }\n }\n if (expr.length === 1) {\n return expr[0];\n }\n }\n return new ContextKeyOrExpr(expr, negated);\n }\n serialize() {\n return this.expr.map(e => e.serialize()).join(' || ');\n }\n keys() {\n const result = [];\n for (const expr of this.expr) {\n result.push(...expr.keys());\n }\n return result;\n }\n negate() {\n if (!this.negated) {\n const result = [];\n for (const expr of this.expr) {\n result.push(expr.negate());\n }\n // We don't support parens, so here we distribute the AND over the OR terminals\n // We always take the first 2 AND pairs and distribute them\n while (result.length > 1) {\n const LEFT = result.shift();\n const RIGHT = result.shift();\n const all = [];\n for (const left of getTerminals(LEFT)) {\n for (const right of getTerminals(RIGHT)) {\n all.push(ContextKeyAndExpr.create([left, right], null));\n }\n }\n const isFinished = (result.length === 0);\n result.unshift(ContextKeyOrExpr.create(all, null, isFinished));\n }\n this.negated = result[0];\n }\n return this.negated;\n }\n}\nexport class RawContextKey extends ContextKeyDefinedExpr {\n constructor(key, defaultValue, metaOrHide) {\n super(key, null);\n this._defaultValue = defaultValue;\n // collect all context keys into a central place\n if (typeof metaOrHide === 'object') {\n RawContextKey._info.push(Object.assign(Object.assign({}, metaOrHide), { key }));\n }\n else if (metaOrHide !== true) {\n RawContextKey._info.push({ key, description: metaOrHide, type: defaultValue !== null && defaultValue !== undefined ? typeof defaultValue : undefined });\n }\n }\n static all() {\n return RawContextKey._info.values();\n }\n bindTo(target) {\n return target.createKey(this.key, this._defaultValue);\n }\n getValue(target) {\n return target.getContextKeyValue(this.key);\n }\n toNegated() {\n return this.negate();\n }\n isEqualTo(value) {\n return ContextKeyEqualsExpr.create(this.key, value);\n }\n}\nRawContextKey._info = [];\nexport const IContextKeyService = createDecorator('contextKeyService');\nexport const SET_CONTEXT_COMMAND_ID = 'setContext';\nfunction cmp1(key1, key2) {\n if (key1 < key2) {\n return -1;\n }\n if (key1 > key2) {\n return 1;\n }\n return 0;\n}\nfunction cmp2(key1, value1, key2, value2) {\n if (key1 < key2) {\n return -1;\n }\n if (key1 > key2) {\n return 1;\n }\n if (value1 < value2) {\n return -1;\n }\n if (value1 > value2) {\n return 1;\n }\n return 0;\n}\n/**\n * Returns true if it is provable `p` implies `q`.\n */\nexport function implies(p, q) {\n if (q.type === 6 /* ContextKeyExprType.And */ && (p.type !== 9 /* ContextKeyExprType.Or */ && p.type !== 6 /* ContextKeyExprType.And */)) {\n // covers the case: A implies A && B\n for (const qTerm of q.expr) {\n if (p.equals(qTerm)) {\n return true;\n }\n }\n }\n const notP = p.negate();\n const expr = getTerminals(notP).concat(getTerminals(q));\n expr.sort(cmp);\n for (let i = 0; i < expr.length; i++) {\n const a = expr[i];\n const notA = a.negate();\n for (let j = i + 1; j < expr.length; j++) {\n const b = expr[j];\n if (notA.equals(b)) {\n return true;\n }\n }\n }\n return false;\n}\nfunction getTerminals(node) {\n if (node.type === 9 /* ContextKeyExprType.Or */) {\n return node.expr;\n }\n return [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 *--------------------------------------------------------------------------------------------*/\nimport { isIOS, isLinux, isMacintosh, isWeb, isWindows } from '../../../base/common/platform.js';\nimport { localize } from '../../../nls.js';\nimport { RawContextKey } from './contextkey.js';\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\"));\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\"));\nexport const IsDevelopmentContext = new RawContextKey('isDevelopment', false, true);\nexport const ProductQualityContext = new RawContextKey('productQualityType', '', localize('productQualityType', \"Quality type of VS Code\"));\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 *--------------------------------------------------------------------------------------------*/\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const IContextViewService = createDecorator('contextViewService');\nexport const IContextMenuService = createDecorator('contextMenuService');\n","import { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const IDialogService = createDecorator('dialogService');\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nexport class SyncDescriptor {\n constructor(ctor, staticArguments = [], supportsDelayedInstantiation = false) {\n this.ctor = ctor;\n this.staticArguments = staticArguments;\n this.supportsDelayedInstantiation = supportsDelayedInstantiation;\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 *--------------------------------------------------------------------------------------------*/\nimport { SyncDescriptor } from './descriptors.js';\nconst _registry = [];\nexport function registerSingleton(id, ctorOrDescriptor, supportsDelayedInstantiation) {\n if (!(ctorOrDescriptor instanceof SyncDescriptor)) {\n ctorOrDescriptor = new SyncDescriptor(ctorOrDescriptor, [], supportsDelayedInstantiation);\n }\n _registry.push([id, ctorOrDescriptor]);\n}\nexport function getSingletonServiceDescriptors() {\n return _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// ------ internal util\nexport var _util;\n(function (_util) {\n _util.serviceIds = new Map();\n _util.DI_TARGET = '$di$target';\n _util.DI_DEPENDENCIES = '$di$dependencies';\n function getServiceDependencies(ctor) {\n return ctor[_util.DI_DEPENDENCIES] || [];\n }\n _util.getServiceDependencies = getServiceDependencies;\n})(_util || (_util = {}));\nexport const IInstantiationService = createDecorator('instantiationService');\nfunction storeServiceDependency(id, target, index) {\n if (target[_util.DI_TARGET] === target) {\n target[_util.DI_DEPENDENCIES].push({ id, index });\n }\n else {\n target[_util.DI_DEPENDENCIES] = [{ id, index }];\n target[_util.DI_TARGET] = target;\n }\n}\n/**\n * The *only* valid way to create a {{ServiceIdentifier}}.\n */\nexport function createDecorator(serviceId) {\n if (_util.serviceIds.has(serviceId)) {\n return _util.serviceIds.get(serviceId);\n }\n const id = function (target, key, index) {\n if (arguments.length !== 3) {\n throw new Error('@IServiceName-decorator can only be used to decorate a parameter');\n }\n storeServiceDependency(id, target, index);\n };\n id.toString = () => serviceId;\n _util.serviceIds.set(serviceId, id);\n return 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 *--------------------------------------------------------------------------------------------*/\nexport class ServiceCollection {\n constructor(...entries) {\n this._entries = new Map();\n for (const [id, service] of entries) {\n this.set(id, service);\n }\n }\n set(id, instanceOrDescriptor) {\n const result = this._entries.get(id);\n this._entries.set(id, instanceOrDescriptor);\n return result;\n }\n get(id) {\n return this._entries.get(id);\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 *--------------------------------------------------------------------------------------------*/\nimport { Emitter } from '../../../base/common/event.js';\nimport * as platform from '../../registry/common/platform.js';\nexport const Extensions = {\n JSONContribution: 'base.contributions.json'\n};\nfunction normalizeId(id) {\n if (id.length > 0 && id.charAt(id.length - 1) === '#') {\n return id.substring(0, id.length - 1);\n }\n return id;\n}\nclass JSONContributionRegistry {\n constructor() {\n this._onDidChangeSchema = new Emitter();\n this.schemasById = {};\n }\n registerSchema(uri, unresolvedSchemaContent) {\n this.schemasById[normalizeId(uri)] = unresolvedSchemaContent;\n this._onDidChangeSchema.fire(uri);\n }\n notifySchemaChanged(uri) {\n this._onDidChangeSchema.fire(uri);\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 *--------------------------------------------------------------------------------------------*/\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const IKeybindingService = createDecorator('keybindingService');\n","/*---------------------------------------------------------------------------------------------\n * 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 { createKeybinding } from '../../../base/common/keybindings.js';\nimport { OS } from '../../../base/common/platform.js';\nimport { CommandsRegistry } from '../../commands/common/commands.js';\nimport { Registry } from '../../registry/common/platform.js';\nclass KeybindingsRegistryImpl {\n constructor() {\n this._coreKeybindings = [];\n this._extensionKeybindings = [];\n this._cachedMergedKeybindings = null;\n }\n /**\n * Take current platform into account and reduce to primary & secondary.\n */\n static bindToCurrentPlatform(kb) {\n if (OS === 1 /* OperatingSystem.Windows */) {\n if (kb && kb.win) {\n return kb.win;\n }\n }\n else if (OS === 2 /* OperatingSystem.Macintosh */) {\n if (kb && kb.mac) {\n return kb.mac;\n }\n }\n else {\n if (kb && kb.linux) {\n return kb.linux;\n }\n }\n return kb;\n }\n registerKeybindingRule(rule) {\n const actualKb = KeybindingsRegistryImpl.bindToCurrentPlatform(rule);\n if (actualKb && actualKb.primary) {\n const kk = createKeybinding(actualKb.primary, OS);\n if (kk) {\n this._registerDefaultKeybinding(kk, rule.id, rule.args, rule.weight, 0, rule.when);\n }\n }\n if (actualKb && Array.isArray(actualKb.secondary)) {\n for (let i = 0, len = actualKb.secondary.length; i < len; i++) {\n const k = actualKb.secondary[i];\n const kk = createKeybinding(k, OS);\n if (kk) {\n this._registerDefaultKeybinding(kk, rule.id, rule.args, rule.weight, -i - 1, rule.when);\n }\n }\n }\n }\n registerCommandAndKeybindingRule(desc) {\n this.registerKeybindingRule(desc);\n CommandsRegistry.registerCommand(desc);\n }\n static _mightProduceChar(keyCode) {\n if (keyCode >= 21 /* KeyCode.Digit0 */ && keyCode <= 30 /* KeyCode.Digit9 */) {\n return true;\n }\n if (keyCode >= 31 /* KeyCode.KeyA */ && keyCode <= 56 /* KeyCode.KeyZ */) {\n return true;\n }\n return (keyCode === 80 /* KeyCode.Semicolon */\n || keyCode === 81 /* KeyCode.Equal */\n || keyCode === 82 /* KeyCode.Comma */\n || keyCode === 83 /* KeyCode.Minus */\n || keyCode === 84 /* KeyCode.Period */\n || keyCode === 85 /* KeyCode.Slash */\n || keyCode === 86 /* KeyCode.Backquote */\n || keyCode === 110 /* KeyCode.ABNT_C1 */\n || keyCode === 111 /* KeyCode.ABNT_C2 */\n || keyCode === 87 /* KeyCode.BracketLeft */\n || keyCode === 88 /* KeyCode.Backslash */\n || keyCode === 89 /* KeyCode.BracketRight */\n || keyCode === 90 /* KeyCode.Quote */\n || keyCode === 91 /* KeyCode.OEM_8 */\n || keyCode === 92 /* KeyCode.IntlBackslash */);\n }\n _assertNoCtrlAlt(keybinding, commandId) {\n if (keybinding.ctrlKey && keybinding.altKey && !keybinding.metaKey) {\n if (KeybindingsRegistryImpl._mightProduceChar(keybinding.keyCode)) {\n console.warn('Ctrl+Alt+ keybindings should not be used by default under Windows. Offender: ', keybinding, ' for ', commandId);\n }\n }\n }\n _registerDefaultKeybinding(keybinding, commandId, commandArgs, weight1, weight2, when) {\n if (OS === 1 /* OperatingSystem.Windows */) {\n this._assertNoCtrlAlt(keybinding.parts[0], commandId);\n }\n this._coreKeybindings.push({\n keybinding: keybinding.parts,\n command: commandId,\n commandArgs: commandArgs,\n when: when,\n weight1: weight1,\n weight2: weight2,\n extensionId: null,\n isBuiltinExtension: false\n });\n this._cachedMergedKeybindings = null;\n }\n getDefaultKeybindings() {\n if (!this._cachedMergedKeybindings) {\n this._cachedMergedKeybindings = [].concat(this._coreKeybindings).concat(this._extensionKeybindings);\n this._cachedMergedKeybindings.sort(sorter);\n }\n return this._cachedMergedKeybindings.slice(0);\n }\n}\nexport const KeybindingsRegistry = new KeybindingsRegistryImpl();\n// Define extension point ids\nexport const Extensions = {\n EditorModes: 'platform.keybindingsRegistry'\n};\nRegistry.add(Extensions.EditorModes, KeybindingsRegistry);\nfunction sorter(a, b) {\n if (a.weight1 !== b.weight1) {\n return a.weight1 - b.weight1;\n }\n if (a.command < b.command) {\n return -1;\n }\n if (a.command > b.command) {\n return 1;\n }\n return a.weight2 - b.weight2;\n}\n","import { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const ILabelService = createDecorator('labelService');\n","/*---------------------------------------------------------------------------------------------\n * 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 { range } from '../../../common/arrays.js';\nimport { CancellationTokenSource } from '../../../common/cancellation.js';\nimport { Event } from '../../../common/event.js';\nimport { Disposable } from '../../../common/lifecycle.js';\nimport './list.css';\nimport { List } from './listWidget.js';\nclass PagedRenderer {\n constructor(renderer, modelProvider) {\n this.renderer = renderer;\n this.modelProvider = modelProvider;\n }\n get templateId() { return this.renderer.templateId; }\n renderTemplate(container) {\n const data = this.renderer.renderTemplate(container);\n return { data, disposable: Disposable.None };\n }\n renderElement(index, _, data, height) {\n if (data.disposable) {\n data.disposable.dispose();\n }\n if (!data.data) {\n return;\n }\n const model = this.modelProvider();\n if (model.isResolved(index)) {\n return this.renderer.renderElement(model.get(index), index, data.data, height);\n }\n const cts = new CancellationTokenSource();\n const promise = model.resolve(index, cts.token);\n data.disposable = { dispose: () => cts.cancel() };\n this.renderer.renderPlaceholder(index, data.data);\n promise.then(entry => this.renderer.renderElement(entry, index, data.data, height));\n }\n disposeTemplate(data) {\n if (data.disposable) {\n data.disposable.dispose();\n data.disposable = undefined;\n }\n if (data.data) {\n this.renderer.disposeTemplate(data.data);\n data.data = undefined;\n }\n }\n}\nclass PagedAccessibilityProvider {\n constructor(modelProvider, accessibilityProvider) {\n this.modelProvider = modelProvider;\n this.accessibilityProvider = accessibilityProvider;\n }\n getWidgetAriaLabel() {\n return this.accessibilityProvider.getWidgetAriaLabel();\n }\n getAriaLabel(index) {\n const model = this.modelProvider();\n if (!model.isResolved(index)) {\n return null;\n }\n return this.accessibilityProvider.getAriaLabel(model.get(index));\n }\n}\nfunction fromPagedListOptions(modelProvider, options) {\n return Object.assign(Object.assign({}, options), { accessibilityProvider: options.accessibilityProvider && new PagedAccessibilityProvider(modelProvider, options.accessibilityProvider) });\n}\nexport class PagedList {\n constructor(user, container, virtualDelegate, renderers, options = {}) {\n const modelProvider = () => this.model;\n const pagedRenderers = renderers.map(r => new PagedRenderer(r, modelProvider));\n this.list = new List(user, container, virtualDelegate, pagedRenderers, fromPagedListOptions(modelProvider, options));\n }\n updateOptions(options) {\n this.list.updateOptions(options);\n }\n getHTMLElement() {\n return this.list.getHTMLElement();\n }\n get onDidFocus() {\n return this.list.onDidFocus;\n }\n get onDidDispose() {\n return this.list.onDidDispose;\n }\n get onMouseDblClick() {\n return Event.map(this.list.onMouseDblClick, ({ element, index, browserEvent }) => ({ element: element === undefined ? undefined : this._model.get(element), index, browserEvent }));\n }\n get onPointer() {\n return Event.map(this.list.onPointer, ({ element, index, browserEvent }) => ({ element: element === undefined ? undefined : this._model.get(element), index, browserEvent }));\n }\n get onDidChangeSelection() {\n return Event.map(this.list.onDidChangeSelection, ({ elements, indexes, browserEvent }) => ({ elements: elements.map(e => this._model.get(e)), indexes, browserEvent }));\n }\n get model() {\n return this._model;\n }\n set model(model) {\n this._model = model;\n this.list.splice(0, this.list.length, range(model.length));\n }\n getFocus() {\n return this.list.getFocus();\n }\n getSelection() {\n return this.list.getSelection();\n }\n getSelectedElements() {\n return this.getSelection().map(i => this.model.get(i));\n }\n style(styles) {\n this.list.style(styles);\n }\n dispose() {\n this.list.dispose();\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 *--------------------------------------------------------------------------------------------*/\nimport { $, append, clearNode, createStyleSheet } from '../../dom.js';\nimport { List } from '../list/listWidget.js';\nimport { SplitView } from '../splitview/splitview.js';\nimport { Emitter, Event } from '../../../common/event.js';\nimport { DisposableStore } from '../../../common/lifecycle.js';\nimport './table.css';\nclass TableListRenderer {\n constructor(columns, renderers, getColumnSize) {\n this.columns = columns;\n this.getColumnSize = getColumnSize;\n this.templateId = TableListRenderer.TemplateId;\n this.renderedTemplates = new Set();\n const rendererMap = new Map(renderers.map(r => [r.templateId, r]));\n this.renderers = [];\n for (const column of columns) {\n const renderer = rendererMap.get(column.templateId);\n if (!renderer) {\n throw new Error(`Table cell renderer for template id ${column.templateId} not found.`);\n }\n this.renderers.push(renderer);\n }\n }\n renderTemplate(container) {\n const rowContainer = append(container, $('.monaco-table-tr'));\n const cellContainers = [];\n const cellTemplateData = [];\n for (let i = 0; i < this.columns.length; i++) {\n const renderer = this.renderers[i];\n const cellContainer = append(rowContainer, $('.monaco-table-td', { 'data-col-index': i }));\n cellContainer.style.width = `${this.getColumnSize(i)}px`;\n cellContainers.push(cellContainer);\n cellTemplateData.push(renderer.renderTemplate(cellContainer));\n }\n const result = { container, cellContainers, cellTemplateData };\n this.renderedTemplates.add(result);\n return result;\n }\n renderElement(element, index, templateData, height) {\n for (let i = 0; i < this.columns.length; i++) {\n const column = this.columns[i];\n const cell = column.project(element);\n const renderer = this.renderers[i];\n renderer.renderElement(cell, index, templateData.cellTemplateData[i], height);\n }\n }\n disposeElement(element, index, templateData, height) {\n for (let i = 0; i < this.columns.length; i++) {\n const renderer = this.renderers[i];\n if (renderer.disposeElement) {\n const column = this.columns[i];\n const cell = column.project(element);\n renderer.disposeElement(cell, index, templateData.cellTemplateData[i], height);\n }\n }\n }\n disposeTemplate(templateData) {\n for (let i = 0; i < this.columns.length; i++) {\n const renderer = this.renderers[i];\n renderer.disposeTemplate(templateData.cellTemplateData[i]);\n }\n clearNode(templateData.container);\n this.renderedTemplates.delete(templateData);\n }\n layoutColumn(index, size) {\n for (const { cellContainers } of this.renderedTemplates) {\n cellContainers[index].style.width = `${size}px`;\n }\n }\n}\nTableListRenderer.TemplateId = 'row';\nfunction asListVirtualDelegate(delegate) {\n return {\n getHeight(row) { return delegate.getHeight(row); },\n getTemplateId() { return TableListRenderer.TemplateId; },\n };\n}\nclass ColumnHeader {\n constructor(column, index) {\n this.column = column;\n this.index = index;\n this._onDidLayout = new Emitter();\n this.onDidLayout = this._onDidLayout.event;\n this.element = $('.monaco-table-th', { 'data-col-index': index, title: column.tooltip }, column.label);\n }\n get minimumSize() { var _a; return (_a = this.column.minimumWidth) !== null && _a !== void 0 ? _a : 120; }\n get maximumSize() { var _a; return (_a = this.column.maximumWidth) !== null && _a !== void 0 ? _a : Number.POSITIVE_INFINITY; }\n get onDidChange() { var _a; return (_a = this.column.onDidChangeWidthConstraints) !== null && _a !== void 0 ? _a : Event.None; }\n layout(size) {\n this._onDidLayout.fire([this.index, size]);\n }\n}\nexport class Table {\n constructor(user, container, virtualDelegate, columns, renderers, _options) {\n this.virtualDelegate = virtualDelegate;\n this.domId = `table_id_${++Table.InstanceCount}`;\n this.disposables = new DisposableStore();\n this.cachedWidth = 0;\n this.cachedHeight = 0;\n this.domNode = append(container, $(`.monaco-table.${this.domId}`));\n const headers = columns.map((c, i) => new ColumnHeader(c, i));\n const descriptor = {\n size: headers.reduce((a, b) => a + b.column.weight, 0),\n views: headers.map(view => ({ size: view.column.weight, view }))\n };\n this.splitview = this.disposables.add(new SplitView(this.domNode, {\n orientation: 1 /* Orientation.HORIZONTAL */,\n scrollbarVisibility: 2 /* ScrollbarVisibility.Hidden */,\n getSashOrthogonalSize: () => this.cachedHeight,\n descriptor\n }));\n this.splitview.el.style.height = `${virtualDelegate.headerRowHeight}px`;\n this.splitview.el.style.lineHeight = `${virtualDelegate.headerRowHeight}px`;\n const renderer = new TableListRenderer(columns, renderers, i => this.splitview.getViewSize(i));\n this.list = this.disposables.add(new List(user, this.domNode, asListVirtualDelegate(virtualDelegate), [renderer], _options));\n Event.any(...headers.map(h => h.onDidLayout))(([index, size]) => renderer.layoutColumn(index, size), null, this.disposables);\n this.splitview.onDidSashReset(index => {\n const totalWeight = columns.reduce((r, c) => r + c.weight, 0);\n const size = columns[index].weight / totalWeight * this.cachedWidth;\n this.splitview.resizeView(index, size);\n }, null, this.disposables);\n this.styleElement = createStyleSheet(this.domNode);\n this.style({});\n }\n get onDidChangeFocus() { return this.list.onDidChangeFocus; }\n get onDidChangeSelection() { return this.list.onDidChangeSelection; }\n get onMouseDblClick() { return this.list.onMouseDblClick; }\n get onPointer() { return this.list.onPointer; }\n get onDidFocus() { return this.list.onDidFocus; }\n get onDidDispose() { return this.list.onDidDispose; }\n updateOptions(options) {\n this.list.updateOptions(options);\n }\n splice(start, deleteCount, elements = []) {\n this.list.splice(start, deleteCount, elements);\n }\n getHTMLElement() {\n return this.domNode;\n }\n style(styles) {\n const content = [];\n content.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 this.styleElement.textContent = content.join('\\n');\n this.list.style(styles);\n }\n getSelectedElements() {\n return this.list.getSelectedElements();\n }\n getSelection() {\n return this.list.getSelection();\n }\n getFocus() {\n return this.list.getFocus();\n }\n dispose() {\n this.disposables.dispose();\n }\n}\nTable.InstanceCount = 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 *--------------------------------------------------------------------------------------------*/\nexport var TreeMouseEventTarget;\n(function (TreeMouseEventTarget) {\n TreeMouseEventTarget[TreeMouseEventTarget[\"Unknown\"] = 0] = \"Unknown\";\n TreeMouseEventTarget[TreeMouseEventTarget[\"Twistie\"] = 1] = \"Twistie\";\n TreeMouseEventTarget[TreeMouseEventTarget[\"Element\"] = 2] = \"Element\";\n TreeMouseEventTarget[TreeMouseEventTarget[\"Filter\"] = 3] = \"Filter\";\n})(TreeMouseEventTarget || (TreeMouseEventTarget = {}));\nexport class TreeError extends Error {\n constructor(user, message) {\n super(`TreeError [${user}] ${message}`);\n }\n}\nexport class WeakMapper {\n constructor(fn) {\n this.fn = fn;\n this._map = new WeakMap();\n }\n map(key) {\n let result = this._map.get(key);\n if (!result) {\n result = this.fn(key);\n this._map.set(key, result);\n }\n return result;\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 *--------------------------------------------------------------------------------------------*/\nimport { TreeError } from './tree.js';\nimport { splice, tail2 } from '../../../common/arrays.js';\nimport { Delayer, MicrotaskDelay } from '../../../common/async.js';\nimport { LcsDiff } from '../../../common/diff/diff.js';\nimport { Emitter, EventBufferer } from '../../../common/event.js';\nimport { Iterable } from '../../../common/iterator.js';\nexport function isFilterResult(obj) {\n return typeof obj === 'object' && 'visibility' in obj && 'data' in obj;\n}\nexport function getVisibleState(visibility) {\n switch (visibility) {\n case true: return 1 /* TreeVisibility.Visible */;\n case false: return 0 /* TreeVisibility.Hidden */;\n default: return visibility;\n }\n}\nfunction isCollapsibleStateUpdate(update) {\n return typeof update.collapsible === 'boolean';\n}\nexport class IndexTreeModel {\n constructor(user, list, rootElement, options = {}) {\n this.user = user;\n this.list = list;\n this.rootRef = [];\n this.eventBufferer = new EventBufferer();\n this._onDidChangeCollapseState = new Emitter();\n this.onDidChangeCollapseState = this.eventBufferer.wrapEvent(this._onDidChangeCollapseState.event);\n this._onDidChangeRenderNodeCount = new Emitter();\n this.onDidChangeRenderNodeCount = this.eventBufferer.wrapEvent(this._onDidChangeRenderNodeCount.event);\n this._onDidSplice = new Emitter();\n this.onDidSplice = this._onDidSplice.event;\n this.refilterDelayer = new Delayer(MicrotaskDelay);\n this.collapseByDefault = typeof options.collapseByDefault === 'undefined' ? false : options.collapseByDefault;\n this.filter = options.filter;\n this.autoExpandSingleChildren = typeof options.autoExpandSingleChildren === 'undefined' ? false : options.autoExpandSingleChildren;\n this.root = {\n parent: undefined,\n element: rootElement,\n children: [],\n depth: 0,\n visibleChildrenCount: 0,\n visibleChildIndex: -1,\n collapsible: false,\n collapsed: false,\n renderNodeCount: 0,\n visibility: 1 /* TreeVisibility.Visible */,\n visible: true,\n filterData: undefined\n };\n }\n splice(location, deleteCount, toInsert = Iterable.empty(), options = {}) {\n if (location.length === 0) {\n throw new TreeError(this.user, 'Invalid tree location');\n }\n if (options.diffIdentityProvider) {\n this.spliceSmart(options.diffIdentityProvider, location, deleteCount, toInsert, options);\n }\n else {\n this.spliceSimple(location, deleteCount, toInsert, options);\n }\n }\n spliceSmart(identity, location, deleteCount, toInsertIterable, options, recurseLevels) {\n var _a;\n if (toInsertIterable === void 0) { toInsertIterable = Iterable.empty(); }\n if (recurseLevels === void 0) { recurseLevels = (_a = options.diffDepth) !== null && _a !== void 0 ? _a : 0; }\n const { parentNode } = this.getParentNodeWithListIndex(location);\n if (!parentNode.lastDiffIds) {\n return this.spliceSimple(location, deleteCount, toInsertIterable, options);\n }\n const toInsert = [...toInsertIterable];\n const index = location[location.length - 1];\n const diff = new LcsDiff({ getElements: () => parentNode.lastDiffIds }, {\n getElements: () => [\n ...parentNode.children.slice(0, index),\n ...toInsert,\n ...parentNode.children.slice(index + deleteCount),\n ].map(e => identity.getId(e.element).toString())\n }).ComputeDiff(false);\n // if we were given a 'best effort' diff, use default behavior\n if (diff.quitEarly) {\n parentNode.lastDiffIds = undefined;\n return this.spliceSimple(location, deleteCount, toInsert, options);\n }\n const locationPrefix = location.slice(0, -1);\n const recurseSplice = (fromOriginal, fromModified, count) => {\n if (recurseLevels > 0) {\n for (let i = 0; i < count; i++) {\n fromOriginal--;\n fromModified--;\n this.spliceSmart(identity, [...locationPrefix, fromOriginal, 0], Number.MAX_SAFE_INTEGER, toInsert[fromModified].children, options, recurseLevels - 1);\n }\n }\n };\n let lastStartO = Math.min(parentNode.children.length, index + deleteCount);\n let lastStartM = toInsert.length;\n for (const change of diff.changes.sort((a, b) => b.originalStart - a.originalStart)) {\n recurseSplice(lastStartO, lastStartM, lastStartO - (change.originalStart + change.originalLength));\n lastStartO = change.originalStart;\n lastStartM = change.modifiedStart - index;\n this.spliceSimple([...locationPrefix, lastStartO], change.originalLength, Iterable.slice(toInsert, lastStartM, lastStartM + change.modifiedLength), options);\n }\n // at this point, startO === startM === count since any remaining prefix should match\n recurseSplice(lastStartO, lastStartM, lastStartO);\n }\n spliceSimple(location, deleteCount, toInsert = Iterable.empty(), { onDidCreateNode, onDidDeleteNode, diffIdentityProvider }) {\n const { parentNode, listIndex, revealed, visible } = this.getParentNodeWithListIndex(location);\n const treeListElementsToInsert = [];\n const nodesToInsertIterator = Iterable.map(toInsert, el => this.createTreeNode(el, parentNode, parentNode.visible ? 1 /* TreeVisibility.Visible */ : 0 /* TreeVisibility.Hidden */, revealed, treeListElementsToInsert, onDidCreateNode));\n const lastIndex = location[location.length - 1];\n const lastHadChildren = parentNode.children.length > 0;\n // figure out what's the visible child start index right before the\n // splice point\n let visibleChildStartIndex = 0;\n for (let i = lastIndex; i >= 0 && i < parentNode.children.length; i--) {\n const child = parentNode.children[i];\n if (child.visible) {\n visibleChildStartIndex = child.visibleChildIndex;\n break;\n }\n }\n const nodesToInsert = [];\n let insertedVisibleChildrenCount = 0;\n let renderNodeCount = 0;\n for (const child of nodesToInsertIterator) {\n nodesToInsert.push(child);\n renderNodeCount += child.renderNodeCount;\n if (child.visible) {\n child.visibleChildIndex = visibleChildStartIndex + insertedVisibleChildrenCount++;\n }\n }\n const deletedNodes = splice(parentNode.children, lastIndex, deleteCount, nodesToInsert);\n if (!diffIdentityProvider) {\n parentNode.lastDiffIds = undefined;\n }\n else if (parentNode.lastDiffIds) {\n splice(parentNode.lastDiffIds, lastIndex, deleteCount, nodesToInsert.map(n => diffIdentityProvider.getId(n.element).toString()));\n }\n else {\n parentNode.lastDiffIds = parentNode.children.map(n => diffIdentityProvider.getId(n.element).toString());\n }\n // figure out what is the count of deleted visible children\n let deletedVisibleChildrenCount = 0;\n for (const child of deletedNodes) {\n if (child.visible) {\n deletedVisibleChildrenCount++;\n }\n }\n // and adjust for all visible children after the splice point\n if (deletedVisibleChildrenCount !== 0) {\n for (let i = lastIndex + nodesToInsert.length; i < parentNode.children.length; i++) {\n const child = parentNode.children[i];\n if (child.visible) {\n child.visibleChildIndex -= deletedVisibleChildrenCount;\n }\n }\n }\n // update parent's visible children count\n parentNode.visibleChildrenCount += insertedVisibleChildrenCount - deletedVisibleChildrenCount;\n if (revealed && visible) {\n const visibleDeleteCount = deletedNodes.reduce((r, node) => r + (node.visible ? node.renderNodeCount : 0), 0);\n this._updateAncestorsRenderNodeCount(parentNode, renderNodeCount - visibleDeleteCount);\n this.list.splice(listIndex, visibleDeleteCount, treeListElementsToInsert);\n }\n if (deletedNodes.length > 0 && onDidDeleteNode) {\n const visit = (node) => {\n onDidDeleteNode(node);\n node.children.forEach(visit);\n };\n deletedNodes.forEach(visit);\n }\n this._onDidSplice.fire({ insertedNodes: nodesToInsert, deletedNodes });\n const currentlyHasChildren = parentNode.children.length > 0;\n if (lastHadChildren !== currentlyHasChildren) {\n this.setCollapsible(location.slice(0, -1), currentlyHasChildren);\n }\n let node = parentNode;\n while (node) {\n if (node.visibility === 2 /* TreeVisibility.Recurse */) {\n // delayed to avoid excessive refiltering, see #135941\n this.refilterDelayer.trigger(() => this.refilter());\n break;\n }\n node = node.parent;\n }\n }\n rerender(location) {\n if (location.length === 0) {\n throw new TreeError(this.user, 'Invalid tree location');\n }\n const { node, listIndex, revealed } = this.getTreeNodeWithListIndex(location);\n if (node.visible && revealed) {\n this.list.splice(listIndex, 1, [node]);\n }\n }\n has(location) {\n return this.hasTreeNode(location);\n }\n getListIndex(location) {\n const { listIndex, visible, revealed } = this.getTreeNodeWithListIndex(location);\n return visible && revealed ? listIndex : -1;\n }\n getListRenderCount(location) {\n return this.getTreeNode(location).renderNodeCount;\n }\n isCollapsible(location) {\n return this.getTreeNode(location).collapsible;\n }\n setCollapsible(location, collapsible) {\n const node = this.getTreeNode(location);\n if (typeof collapsible === 'undefined') {\n collapsible = !node.collapsible;\n }\n const update = { collapsible };\n return this.eventBufferer.bufferEvents(() => this._setCollapseState(location, update));\n }\n isCollapsed(location) {\n return this.getTreeNode(location).collapsed;\n }\n setCollapsed(location, collapsed, recursive) {\n const node = this.getTreeNode(location);\n if (typeof collapsed === 'undefined') {\n collapsed = !node.collapsed;\n }\n const update = { collapsed, recursive: recursive || false };\n return this.eventBufferer.bufferEvents(() => this._setCollapseState(location, update));\n }\n _setCollapseState(location, update) {\n const { node, listIndex, revealed } = this.getTreeNodeWithListIndex(location);\n const result = this._setListNodeCollapseState(node, listIndex, revealed, update);\n if (node !== this.root && this.autoExpandSingleChildren && result && !isCollapsibleStateUpdate(update) && node.collapsible && !node.collapsed && !update.recursive) {\n let onlyVisibleChildIndex = -1;\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n if (child.visible) {\n if (onlyVisibleChildIndex > -1) {\n onlyVisibleChildIndex = -1;\n break;\n }\n else {\n onlyVisibleChildIndex = i;\n }\n }\n }\n if (onlyVisibleChildIndex > -1) {\n this._setCollapseState([...location, onlyVisibleChildIndex], update);\n }\n }\n return result;\n }\n _setListNodeCollapseState(node, listIndex, revealed, update) {\n const result = this._setNodeCollapseState(node, update, false);\n if (!revealed || !node.visible || !result) {\n return result;\n }\n const previousRenderNodeCount = node.renderNodeCount;\n const toInsert = this.updateNodeAfterCollapseChange(node);\n const deleteCount = previousRenderNodeCount - (listIndex === -1 ? 0 : 1);\n this.list.splice(listIndex + 1, deleteCount, toInsert.slice(1));\n return result;\n }\n _setNodeCollapseState(node, update, deep) {\n let result;\n if (node === this.root) {\n result = false;\n }\n else {\n if (isCollapsibleStateUpdate(update)) {\n result = node.collapsible !== update.collapsible;\n node.collapsible = update.collapsible;\n }\n else if (!node.collapsible) {\n result = false;\n }\n else {\n result = node.collapsed !== update.collapsed;\n node.collapsed = update.collapsed;\n }\n if (result) {\n this._onDidChangeCollapseState.fire({ node, deep });\n }\n }\n if (!isCollapsibleStateUpdate(update) && update.recursive) {\n for (const child of node.children) {\n result = this._setNodeCollapseState(child, update, true) || result;\n }\n }\n return result;\n }\n expandTo(location) {\n this.eventBufferer.bufferEvents(() => {\n let node = this.getTreeNode(location);\n while (node.parent) {\n node = node.parent;\n location = location.slice(0, location.length - 1);\n if (node.collapsed) {\n this._setCollapseState(location, { collapsed: false, recursive: false });\n }\n }\n });\n }\n refilter() {\n const previousRenderNodeCount = this.root.renderNodeCount;\n const toInsert = this.updateNodeAfterFilterChange(this.root);\n this.list.splice(0, previousRenderNodeCount, toInsert);\n this.refilterDelayer.cancel();\n }\n createTreeNode(treeElement, parent, parentVisibility, revealed, treeListElements, onDidCreateNode) {\n const node = {\n parent,\n element: treeElement.element,\n children: [],\n depth: parent.depth + 1,\n visibleChildrenCount: 0,\n visibleChildIndex: -1,\n collapsible: typeof treeElement.collapsible === 'boolean' ? treeElement.collapsible : (typeof treeElement.collapsed !== 'undefined'),\n collapsed: typeof treeElement.collapsed === 'undefined' ? this.collapseByDefault : treeElement.collapsed,\n renderNodeCount: 1,\n visibility: 1 /* TreeVisibility.Visible */,\n visible: true,\n filterData: undefined\n };\n const visibility = this._filterNode(node, parentVisibility);\n node.visibility = visibility;\n if (revealed) {\n treeListElements.push(node);\n }\n const childElements = treeElement.children || Iterable.empty();\n const childRevealed = revealed && visibility !== 0 /* TreeVisibility.Hidden */ && !node.collapsed;\n const childNodes = Iterable.map(childElements, el => this.createTreeNode(el, node, visibility, childRevealed, treeListElements, onDidCreateNode));\n let visibleChildrenCount = 0;\n let renderNodeCount = 1;\n for (const child of childNodes) {\n node.children.push(child);\n renderNodeCount += child.renderNodeCount;\n if (child.visible) {\n child.visibleChildIndex = visibleChildrenCount++;\n }\n }\n node.collapsible = node.collapsible || node.children.length > 0;\n node.visibleChildrenCount = visibleChildrenCount;\n node.visible = visibility === 2 /* TreeVisibility.Recurse */ ? visibleChildrenCount > 0 : (visibility === 1 /* TreeVisibility.Visible */);\n if (!node.visible) {\n node.renderNodeCount = 0;\n if (revealed) {\n treeListElements.pop();\n }\n }\n else if (!node.collapsed) {\n node.renderNodeCount = renderNodeCount;\n }\n onDidCreateNode === null || onDidCreateNode === void 0 ? void 0 : onDidCreateNode(node);\n return node;\n }\n updateNodeAfterCollapseChange(node) {\n const previousRenderNodeCount = node.renderNodeCount;\n const result = [];\n this._updateNodeAfterCollapseChange(node, result);\n this._updateAncestorsRenderNodeCount(node.parent, result.length - previousRenderNodeCount);\n return result;\n }\n _updateNodeAfterCollapseChange(node, result) {\n if (node.visible === false) {\n return 0;\n }\n result.push(node);\n node.renderNodeCount = 1;\n if (!node.collapsed) {\n for (const child of node.children) {\n node.renderNodeCount += this._updateNodeAfterCollapseChange(child, result);\n }\n }\n this._onDidChangeRenderNodeCount.fire(node);\n return node.renderNodeCount;\n }\n updateNodeAfterFilterChange(node) {\n const previousRenderNodeCount = node.renderNodeCount;\n const result = [];\n this._updateNodeAfterFilterChange(node, node.visible ? 1 /* TreeVisibility.Visible */ : 0 /* TreeVisibility.Hidden */, result);\n this._updateAncestorsRenderNodeCount(node.parent, result.length - previousRenderNodeCount);\n return result;\n }\n _updateNodeAfterFilterChange(node, parentVisibility, result, revealed = true) {\n let visibility;\n if (node !== this.root) {\n visibility = this._filterNode(node, parentVisibility);\n if (visibility === 0 /* TreeVisibility.Hidden */) {\n node.visible = false;\n node.renderNodeCount = 0;\n return false;\n }\n if (revealed) {\n result.push(node);\n }\n }\n const resultStartLength = result.length;\n node.renderNodeCount = node === this.root ? 0 : 1;\n let hasVisibleDescendants = false;\n if (!node.collapsed || visibility !== 0 /* TreeVisibility.Hidden */) {\n let visibleChildIndex = 0;\n for (const child of node.children) {\n hasVisibleDescendants = this._updateNodeAfterFilterChange(child, visibility, result, revealed && !node.collapsed) || hasVisibleDescendants;\n if (child.visible) {\n child.visibleChildIndex = visibleChildIndex++;\n }\n }\n node.visibleChildrenCount = visibleChildIndex;\n }\n else {\n node.visibleChildrenCount = 0;\n }\n if (node !== this.root) {\n node.visible = visibility === 2 /* TreeVisibility.Recurse */ ? hasVisibleDescendants : (visibility === 1 /* TreeVisibility.Visible */);\n node.visibility = visibility;\n }\n if (!node.visible) {\n node.renderNodeCount = 0;\n if (revealed) {\n result.pop();\n }\n }\n else if (!node.collapsed) {\n node.renderNodeCount += result.length - resultStartLength;\n }\n this._onDidChangeRenderNodeCount.fire(node);\n return node.visible;\n }\n _updateAncestorsRenderNodeCount(node, diff) {\n if (diff === 0) {\n return;\n }\n while (node) {\n node.renderNodeCount += diff;\n this._onDidChangeRenderNodeCount.fire(node);\n node = node.parent;\n }\n }\n _filterNode(node, parentVisibility) {\n const result = this.filter ? this.filter.filter(node.element, parentVisibility) : 1 /* TreeVisibility.Visible */;\n if (typeof result === 'boolean') {\n node.filterData = undefined;\n return result ? 1 /* TreeVisibility.Visible */ : 0 /* TreeVisibility.Hidden */;\n }\n else if (isFilterResult(result)) {\n node.filterData = result.data;\n return getVisibleState(result.visibility);\n }\n else {\n node.filterData = undefined;\n return getVisibleState(result);\n }\n }\n // cheap\n hasTreeNode(location, node = this.root) {\n if (!location || location.length === 0) {\n return true;\n }\n const [index, ...rest] = location;\n if (index < 0 || index > node.children.length) {\n return false;\n }\n return this.hasTreeNode(rest, node.children[index]);\n }\n // cheap\n getTreeNode(location, node = this.root) {\n if (!location || location.length === 0) {\n return node;\n }\n const [index, ...rest] = location;\n if (index < 0 || index > node.children.length) {\n throw new TreeError(this.user, 'Invalid tree location');\n }\n return this.getTreeNode(rest, node.children[index]);\n }\n // expensive\n getTreeNodeWithListIndex(location) {\n if (location.length === 0) {\n return { node: this.root, listIndex: -1, revealed: true, visible: false };\n }\n const { parentNode, listIndex, revealed, visible } = this.getParentNodeWithListIndex(location);\n const index = location[location.length - 1];\n if (index < 0 || index > parentNode.children.length) {\n throw new TreeError(this.user, 'Invalid tree location');\n }\n const node = parentNode.children[index];\n return { node, listIndex, revealed, visible: visible && node.visible };\n }\n getParentNodeWithListIndex(location, node = this.root, listIndex = 0, revealed = true, visible = true) {\n const [index, ...rest] = location;\n if (index < 0 || index > node.children.length) {\n throw new TreeError(this.user, 'Invalid tree location');\n }\n // TODO@joao perf!\n for (let i = 0; i < index; i++) {\n listIndex += node.children[i].renderNodeCount;\n }\n revealed = revealed && !node.collapsed;\n visible = visible && node.visible;\n if (rest.length === 0) {\n return { parentNode: node, listIndex, revealed, visible };\n }\n return this.getParentNodeWithListIndex(rest, node.children[index], listIndex + 1, revealed, visible);\n }\n getNode(location = []) {\n return this.getTreeNode(location);\n }\n // TODO@joao perf!\n getNodeLocation(node) {\n const location = [];\n let indexTreeNode = node; // typing woes\n while (indexTreeNode.parent) {\n location.push(indexTreeNode.parent.children.indexOf(indexTreeNode));\n indexTreeNode = indexTreeNode.parent;\n }\n return location.reverse();\n }\n getParentNodeLocation(location) {\n if (location.length === 0) {\n return undefined;\n }\n else if (location.length === 1) {\n return [];\n }\n else {\n return tail2(location)[0];\n }\n }\n getFirstElementChild(location) {\n const node = this.getTreeNode(location);\n if (node.children.length === 0) {\n return undefined;\n }\n return node.children[0].element;\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 *--------------------------------------------------------------------------------------------*/\nexport class SetMap {\n constructor() {\n this.map = new Map();\n }\n add(key, value) {\n let values = this.map.get(key);\n if (!values) {\n values = new Set();\n this.map.set(key, values);\n }\n values.add(value);\n }\n delete(key, value) {\n const values = this.map.get(key);\n if (!values) {\n return;\n }\n values.delete(value);\n if (values.size === 0) {\n this.map.delete(key);\n }\n }\n forEach(key, fn) {\n const values = this.map.get(key);\n if (!values) {\n return;\n }\n values.forEach(fn);\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 *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { $, append, clearNode, createStyleSheet, h, hasParentWithClass } from '../../dom.js';\nimport { DomEmitter } from '../../event.js';\nimport { StandardKeyboardEvent } from '../../keyboardEvent.js';\nimport { ActionBar } from '../actionbar/actionbar.js';\nimport { FindInput } from '../findinput/findInput.js';\nimport { ElementsDragAndDropData } from '../list/listView.js';\nimport { isButton, isInputElement, isMonacoEditor, List, MouseController } from '../list/listWidget.js';\nimport { Toggle } from '../toggle/toggle.js';\nimport { getVisibleState, isFilterResult } from './indexTreeModel.js';\nimport { TreeMouseEventTarget } from './tree.js';\nimport { Action } from '../../../common/actions.js';\nimport { distinct, equals, range } from '../../../common/arrays.js';\nimport { disposableTimeout, timeout } from '../../../common/async.js';\nimport { Codicon } from '../../../common/codicons.js';\nimport { SetMap } from '../../../common/collections.js';\nimport { Emitter, Event, EventBufferer, Relay } from '../../../common/event.js';\nimport { fuzzyScore, FuzzyScore } from '../../../common/filters.js';\nimport { Disposable, DisposableStore, dispose, toDisposable } from '../../../common/lifecycle.js';\nimport { clamp } from '../../../common/numbers.js';\nimport { isNumber } from '../../../common/types.js';\nimport './media/tree.css';\nimport { localize } from '../../../../nls.js';\nclass TreeElementsDragAndDropData extends ElementsDragAndDropData {\n constructor(data) {\n super(data.elements.map(node => node.element));\n this.data = data;\n }\n}\nfunction asTreeDragAndDropData(data) {\n if (data instanceof ElementsDragAndDropData) {\n return new TreeElementsDragAndDropData(data);\n }\n return data;\n}\nclass TreeNodeListDragAndDrop {\n constructor(modelProvider, dnd) {\n this.modelProvider = modelProvider;\n this.dnd = dnd;\n this.autoExpandDisposable = Disposable.None;\n }\n getDragURI(node) {\n return this.dnd.getDragURI(node.element);\n }\n getDragLabel(nodes, originalEvent) {\n if (this.dnd.getDragLabel) {\n return this.dnd.getDragLabel(nodes.map(node => node.element), originalEvent);\n }\n return undefined;\n }\n onDragStart(data, originalEvent) {\n var _a, _b;\n (_b = (_a = this.dnd).onDragStart) === null || _b === void 0 ? void 0 : _b.call(_a, asTreeDragAndDropData(data), originalEvent);\n }\n onDragOver(data, targetNode, targetIndex, originalEvent, raw = true) {\n const result = this.dnd.onDragOver(asTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);\n const didChangeAutoExpandNode = this.autoExpandNode !== targetNode;\n if (didChangeAutoExpandNode) {\n this.autoExpandDisposable.dispose();\n this.autoExpandNode = targetNode;\n }\n if (typeof targetNode === 'undefined') {\n return result;\n }\n if (didChangeAutoExpandNode && typeof result !== 'boolean' && result.autoExpand) {\n this.autoExpandDisposable = disposableTimeout(() => {\n const model = this.modelProvider();\n const ref = model.getNodeLocation(targetNode);\n if (model.isCollapsed(ref)) {\n model.setCollapsed(ref, false);\n }\n this.autoExpandNode = undefined;\n }, 500);\n }\n if (typeof result === 'boolean' || !result.accept || typeof result.bubble === 'undefined' || result.feedback) {\n if (!raw) {\n const accept = typeof result === 'boolean' ? result : result.accept;\n const effect = typeof result === 'boolean' ? undefined : result.effect;\n return { accept, effect, feedback: [targetIndex] };\n }\n return result;\n }\n if (result.bubble === 1 /* TreeDragOverBubble.Up */) {\n const model = this.modelProvider();\n const ref = model.getNodeLocation(targetNode);\n const parentRef = model.getParentNodeLocation(ref);\n const parentNode = model.getNode(parentRef);\n const parentIndex = parentRef && model.getListIndex(parentRef);\n return this.onDragOver(data, parentNode, parentIndex, originalEvent, false);\n }\n const model = this.modelProvider();\n const ref = model.getNodeLocation(targetNode);\n const start = model.getListIndex(ref);\n const length = model.getListRenderCount(ref);\n return Object.assign(Object.assign({}, result), { feedback: range(start, start + length) });\n }\n drop(data, targetNode, targetIndex, originalEvent) {\n this.autoExpandDisposable.dispose();\n this.autoExpandNode = undefined;\n this.dnd.drop(asTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);\n }\n onDragEnd(originalEvent) {\n var _a, _b;\n (_b = (_a = this.dnd).onDragEnd) === null || _b === void 0 ? void 0 : _b.call(_a, originalEvent);\n }\n}\nfunction asListOptions(modelProvider, options) {\n return options && Object.assign(Object.assign({}, options), { identityProvider: options.identityProvider && {\n getId(el) {\n return options.identityProvider.getId(el.element);\n }\n }, dnd: options.dnd && new TreeNodeListDragAndDrop(modelProvider, options.dnd), multipleSelectionController: options.multipleSelectionController && {\n isSelectionSingleChangeEvent(e) {\n return options.multipleSelectionController.isSelectionSingleChangeEvent(Object.assign(Object.assign({}, e), { element: e.element }));\n },\n isSelectionRangeChangeEvent(e) {\n return options.multipleSelectionController.isSelectionRangeChangeEvent(Object.assign(Object.assign({}, e), { element: e.element }));\n }\n }, accessibilityProvider: options.accessibilityProvider && Object.assign(Object.assign({}, options.accessibilityProvider), { getSetSize(node) {\n const model = modelProvider();\n const ref = model.getNodeLocation(node);\n const parentRef = model.getParentNodeLocation(ref);\n const parentNode = model.getNode(parentRef);\n return parentNode.visibleChildrenCount;\n },\n getPosInSet(node) {\n return node.visibleChildIndex + 1;\n }, isChecked: options.accessibilityProvider && options.accessibilityProvider.isChecked ? (node) => {\n return options.accessibilityProvider.isChecked(node.element);\n } : undefined, getRole: options.accessibilityProvider && options.accessibilityProvider.getRole ? (node) => {\n return options.accessibilityProvider.getRole(node.element);\n } : () => 'treeitem', getAriaLabel(e) {\n return options.accessibilityProvider.getAriaLabel(e.element);\n },\n getWidgetAriaLabel() {\n return options.accessibilityProvider.getWidgetAriaLabel();\n }, getWidgetRole: options.accessibilityProvider && options.accessibilityProvider.getWidgetRole ? () => options.accessibilityProvider.getWidgetRole() : () => 'tree', getAriaLevel: options.accessibilityProvider && options.accessibilityProvider.getAriaLevel ? (node) => options.accessibilityProvider.getAriaLevel(node.element) : (node) => {\n return node.depth;\n }, getActiveDescendantId: options.accessibilityProvider.getActiveDescendantId && (node => {\n return options.accessibilityProvider.getActiveDescendantId(node.element);\n }) }), keyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && Object.assign(Object.assign({}, options.keyboardNavigationLabelProvider), { getKeyboardNavigationLabel(node) {\n return options.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(node.element);\n } }) });\n}\nexport class ComposedTreeDelegate {\n constructor(delegate) {\n this.delegate = delegate;\n }\n getHeight(element) {\n return this.delegate.getHeight(element.element);\n }\n getTemplateId(element) {\n return this.delegate.getTemplateId(element.element);\n }\n hasDynamicHeight(element) {\n return !!this.delegate.hasDynamicHeight && this.delegate.hasDynamicHeight(element.element);\n }\n setDynamicHeight(element, height) {\n var _a, _b;\n (_b = (_a = this.delegate).setDynamicHeight) === null || _b === void 0 ? void 0 : _b.call(_a, element.element, height);\n }\n}\nexport var RenderIndentGuides;\n(function (RenderIndentGuides) {\n RenderIndentGuides[\"None\"] = \"none\";\n RenderIndentGuides[\"OnHover\"] = \"onHover\";\n RenderIndentGuides[\"Always\"] = \"always\";\n})(RenderIndentGuides || (RenderIndentGuides = {}));\nclass EventCollection {\n constructor(onDidChange, _elements = []) {\n this._elements = _elements;\n this.disposables = new DisposableStore();\n this.onDidChange = Event.forEach(onDidChange, elements => this._elements = elements, this.disposables);\n }\n get elements() {\n return this._elements;\n }\n dispose() {\n this.disposables.dispose();\n }\n}\nclass TreeRenderer {\n constructor(renderer, modelProvider, onDidChangeCollapseState, activeNodes, options = {}) {\n var _a;\n this.renderer = renderer;\n this.modelProvider = modelProvider;\n this.activeNodes = activeNodes;\n this.renderedElements = new Map();\n this.renderedNodes = new Map();\n this.indent = TreeRenderer.DefaultIndent;\n this.hideTwistiesOfChildlessElements = false;\n this.shouldRenderIndentGuides = false;\n this.renderedIndentGuides = new SetMap();\n this.activeIndentNodes = new Set();\n this.indentGuidesDisposable = Disposable.None;\n this.disposables = new DisposableStore();\n this.templateId = renderer.templateId;\n this.updateOptions(options);\n Event.map(onDidChangeCollapseState, e => e.node)(this.onDidChangeNodeTwistieState, this, this.disposables);\n (_a = renderer.onDidChangeTwistieState) === null || _a === void 0 ? void 0 : _a.call(renderer, this.onDidChangeTwistieState, this, this.disposables);\n }\n updateOptions(options = {}) {\n if (typeof options.indent !== 'undefined') {\n this.indent = clamp(options.indent, 0, 40);\n }\n if (typeof options.renderIndentGuides !== 'undefined') {\n const shouldRenderIndentGuides = options.renderIndentGuides !== RenderIndentGuides.None;\n if (shouldRenderIndentGuides !== this.shouldRenderIndentGuides) {\n this.shouldRenderIndentGuides = shouldRenderIndentGuides;\n this.indentGuidesDisposable.dispose();\n if (shouldRenderIndentGuides) {\n const disposables = new DisposableStore();\n this.activeNodes.onDidChange(this._onDidChangeActiveNodes, this, disposables);\n this.indentGuidesDisposable = disposables;\n this._onDidChangeActiveNodes(this.activeNodes.elements);\n }\n }\n }\n if (typeof options.hideTwistiesOfChildlessElements !== 'undefined') {\n this.hideTwistiesOfChildlessElements = options.hideTwistiesOfChildlessElements;\n }\n }\n renderTemplate(container) {\n const el = append(container, $('.monaco-tl-row'));\n const indent = append(el, $('.monaco-tl-indent'));\n const twistie = append(el, $('.monaco-tl-twistie'));\n const contents = append(el, $('.monaco-tl-contents'));\n const templateData = this.renderer.renderTemplate(contents);\n return { container, indent, twistie, indentGuidesDisposable: Disposable.None, templateData };\n }\n renderElement(node, index, templateData, height) {\n if (typeof height === 'number') {\n this.renderedNodes.set(node, { templateData, height });\n this.renderedElements.set(node.element, node);\n }\n const indent = TreeRenderer.DefaultIndent + (node.depth - 1) * this.indent;\n templateData.twistie.style.paddingLeft = `${indent}px`;\n templateData.indent.style.width = `${indent + this.indent - 16}px`;\n this.renderTwistie(node, templateData);\n if (typeof height === 'number') {\n this.renderIndentGuides(node, templateData);\n }\n this.renderer.renderElement(node, index, templateData.templateData, height);\n }\n disposeElement(node, index, templateData, height) {\n var _a, _b;\n templateData.indentGuidesDisposable.dispose();\n (_b = (_a = this.renderer).disposeElement) === null || _b === void 0 ? void 0 : _b.call(_a, node, index, templateData.templateData, height);\n if (typeof height === 'number') {\n this.renderedNodes.delete(node);\n this.renderedElements.delete(node.element);\n }\n }\n disposeTemplate(templateData) {\n this.renderer.disposeTemplate(templateData.templateData);\n }\n onDidChangeTwistieState(element) {\n const node = this.renderedElements.get(element);\n if (!node) {\n return;\n }\n this.onDidChangeNodeTwistieState(node);\n }\n onDidChangeNodeTwistieState(node) {\n const data = this.renderedNodes.get(node);\n if (!data) {\n return;\n }\n this.renderTwistie(node, data.templateData);\n this._onDidChangeActiveNodes(this.activeNodes.elements);\n this.renderIndentGuides(node, data.templateData);\n }\n renderTwistie(node, templateData) {\n templateData.twistie.classList.remove(...Codicon.treeItemExpanded.classNamesArray);\n let twistieRendered = false;\n if (this.renderer.renderTwistie) {\n twistieRendered = this.renderer.renderTwistie(node.element, templateData.twistie);\n }\n if (node.collapsible && (!this.hideTwistiesOfChildlessElements || node.visibleChildrenCount > 0)) {\n if (!twistieRendered) {\n templateData.twistie.classList.add(...Codicon.treeItemExpanded.classNamesArray);\n }\n templateData.twistie.classList.add('collapsible');\n templateData.twistie.classList.toggle('collapsed', node.collapsed);\n }\n else {\n templateData.twistie.classList.remove('collapsible', 'collapsed');\n }\n if (node.collapsible) {\n templateData.container.setAttribute('aria-expanded', String(!node.collapsed));\n }\n else {\n templateData.container.removeAttribute('aria-expanded');\n }\n }\n renderIndentGuides(target, templateData) {\n clearNode(templateData.indent);\n templateData.indentGuidesDisposable.dispose();\n if (!this.shouldRenderIndentGuides) {\n return;\n }\n const disposableStore = new DisposableStore();\n const model = this.modelProvider();\n let node = target;\n while (true) {\n const ref = model.getNodeLocation(node);\n const parentRef = model.getParentNodeLocation(ref);\n if (!parentRef) {\n break;\n }\n const parent = model.getNode(parentRef);\n const guide = $('.indent-guide', { style: `width: ${this.indent}px` });\n if (this.activeIndentNodes.has(parent)) {\n guide.classList.add('active');\n }\n if (templateData.indent.childElementCount === 0) {\n templateData.indent.appendChild(guide);\n }\n else {\n templateData.indent.insertBefore(guide, templateData.indent.firstElementChild);\n }\n this.renderedIndentGuides.add(parent, guide);\n disposableStore.add(toDisposable(() => this.renderedIndentGuides.delete(parent, guide)));\n node = parent;\n }\n templateData.indentGuidesDisposable = disposableStore;\n }\n _onDidChangeActiveNodes(nodes) {\n if (!this.shouldRenderIndentGuides) {\n return;\n }\n const set = new Set();\n const model = this.modelProvider();\n nodes.forEach(node => {\n const ref = model.getNodeLocation(node);\n try {\n const parentRef = model.getParentNodeLocation(ref);\n if (node.collapsible && node.children.length > 0 && !node.collapsed) {\n set.add(node);\n }\n else if (parentRef) {\n set.add(model.getNode(parentRef));\n }\n }\n catch (_a) {\n // noop\n }\n });\n this.activeIndentNodes.forEach(node => {\n if (!set.has(node)) {\n this.renderedIndentGuides.forEach(node, line => line.classList.remove('active'));\n }\n });\n set.forEach(node => {\n if (!this.activeIndentNodes.has(node)) {\n this.renderedIndentGuides.forEach(node, line => line.classList.add('active'));\n }\n });\n this.activeIndentNodes = set;\n }\n dispose() {\n this.renderedNodes.clear();\n this.renderedElements.clear();\n this.indentGuidesDisposable.dispose();\n dispose(this.disposables);\n }\n}\nTreeRenderer.DefaultIndent = 8;\nclass FindFilter {\n constructor(tree, keyboardNavigationLabelProvider, _filter) {\n this.tree = tree;\n this.keyboardNavigationLabelProvider = keyboardNavigationLabelProvider;\n this._filter = _filter;\n this._totalCount = 0;\n this._matchCount = 0;\n this._pattern = '';\n this._lowercasePattern = '';\n this.disposables = new DisposableStore();\n tree.onWillRefilter(this.reset, this, this.disposables);\n }\n get totalCount() { return this._totalCount; }\n get matchCount() { return this._matchCount; }\n filter(element, parentVisibility) {\n let visibility = 1 /* TreeVisibility.Visible */;\n if (this._filter) {\n const result = this._filter.filter(element, parentVisibility);\n if (typeof result === 'boolean') {\n visibility = result ? 1 /* TreeVisibility.Visible */ : 0 /* TreeVisibility.Hidden */;\n }\n else if (isFilterResult(result)) {\n visibility = getVisibleState(result.visibility);\n }\n else {\n visibility = result;\n }\n if (visibility === 0 /* TreeVisibility.Hidden */) {\n return false;\n }\n }\n this._totalCount++;\n if (!this._pattern) {\n this._matchCount++;\n return { data: FuzzyScore.Default, visibility };\n }\n const label = this.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(element);\n const labels = Array.isArray(label) ? label : [label];\n for (const l of labels) {\n const labelStr = l && l.toString();\n if (typeof labelStr === 'undefined') {\n return { data: FuzzyScore.Default, visibility };\n }\n const score = fuzzyScore(this._pattern, this._lowercasePattern, 0, labelStr, labelStr.toLowerCase(), 0, { firstMatchCanBeWeak: true, boostFullMatch: true });\n if (score) {\n this._matchCount++;\n return labels.length === 1 ?\n { data: score, visibility } :\n { data: { label: labelStr, score: score }, visibility };\n }\n }\n if (this.tree.findMode === TreeFindMode.Filter) {\n return 2 /* TreeVisibility.Recurse */;\n }\n else {\n return { data: FuzzyScore.Default, visibility };\n }\n }\n reset() {\n this._totalCount = 0;\n this._matchCount = 0;\n }\n dispose() {\n dispose(this.disposables);\n }\n}\nexport class ModeToggle extends Toggle {\n constructor(opts) {\n var _a;\n super({\n icon: Codicon.filter,\n title: localize('filter', \"Filter\"),\n isChecked: (_a = opts === null || opts === void 0 ? void 0 : opts.isChecked) !== null && _a !== void 0 ? _a : false,\n inputActiveOptionBorder: opts === null || opts === void 0 ? void 0 : opts.inputActiveOptionBorder,\n inputActiveOptionForeground: opts === null || opts === void 0 ? void 0 : opts.inputActiveOptionForeground,\n inputActiveOptionBackground: opts === null || opts === void 0 ? void 0 : opts.inputActiveOptionBackground\n });\n }\n}\nexport var TreeFindMode;\n(function (TreeFindMode) {\n TreeFindMode[TreeFindMode[\"Highlight\"] = 0] = \"Highlight\";\n TreeFindMode[TreeFindMode[\"Filter\"] = 1] = \"Filter\";\n})(TreeFindMode || (TreeFindMode = {}));\nclass FindWidget extends Disposable {\n constructor(container, tree, contextViewProvider, mode, options) {\n super();\n this.tree = tree;\n this.elements = h('.monaco-tree-type-filter', [\n h('.monaco-tree-type-filter-grab.codicon.codicon-debug-gripper@grab', { tabIndex: 0 }),\n h('.monaco-tree-type-filter-input@findInput'),\n h('.monaco-tree-type-filter-actionbar@actionbar'),\n ]);\n this.width = 0;\n this.right = 0;\n this._onDidDisable = new Emitter();\n container.appendChild(this.elements.root);\n this._register(toDisposable(() => container.removeChild(this.elements.root)));\n this.modeToggle = this._register(new ModeToggle(Object.assign(Object.assign({}, options), { isChecked: mode === TreeFindMode.Filter })));\n this.onDidChangeMode = Event.map(this.modeToggle.onChange, () => this.modeToggle.checked ? TreeFindMode.Filter : TreeFindMode.Highlight, this._store);\n this.findInput = this._register(new FindInput(this.elements.findInput, contextViewProvider, false, {\n label: localize('type to search', \"Type to search\"),\n additionalToggles: [this.modeToggle]\n }));\n this.actionbar = this._register(new ActionBar(this.elements.actionbar));\n this.mode = mode;\n const emitter = this._register(new DomEmitter(this.findInput.inputBox.inputElement, 'keydown'));\n const onKeyDown = this._register(Event.chain(emitter.event))\n .map(e => new StandardKeyboardEvent(e))\n .event;\n this._register(onKeyDown((e) => {\n switch (e.keyCode) {\n case 18 /* KeyCode.DownArrow */:\n e.preventDefault();\n e.stopPropagation();\n this.tree.domFocus();\n return;\n }\n }));\n const closeAction = this._register(new Action('close', localize('close', \"Close\"), 'codicon codicon-close', true, () => this.dispose()));\n this.actionbar.push(closeAction, { icon: true, label: false });\n const onGrabMouseDown = this._register(new DomEmitter(this.elements.grab, 'mousedown'));\n this._register(onGrabMouseDown.event(e => {\n const disposables = new DisposableStore();\n const onWindowMouseMove = disposables.add(new DomEmitter(window, 'mousemove'));\n const onWindowMouseUp = disposables.add(new DomEmitter(window, 'mouseup'));\n const startRight = this.right;\n const startX = e.pageX;\n this.elements.grab.classList.add('grabbing');\n const update = (e) => {\n const deltaX = e.pageX - startX;\n this.right = startRight - deltaX;\n this.layout();\n };\n disposables.add(onWindowMouseMove.event(update));\n disposables.add(onWindowMouseUp.event(e => {\n update(e);\n this.elements.grab.classList.remove('grabbing');\n disposables.dispose();\n }));\n }));\n const onGrabKeyDown = this._register(Event.chain(this._register(new DomEmitter(this.elements.grab, 'keydown')).event))\n .map(e => new StandardKeyboardEvent(e))\n .event;\n this._register(onGrabKeyDown((e) => {\n let right;\n if (e.keyCode === 15 /* KeyCode.LeftArrow */) {\n right = Number.POSITIVE_INFINITY;\n }\n else if (e.keyCode === 17 /* KeyCode.RightArrow */) {\n right = 0;\n }\n else if (e.keyCode === 10 /* KeyCode.Space */) {\n right = this.right === 0 ? Number.POSITIVE_INFINITY : 0;\n }\n if (right !== undefined) {\n e.preventDefault();\n e.stopPropagation();\n this.right = right;\n this.layout();\n }\n }));\n this.onDidChangeValue = this.findInput.onDidChange;\n this.style(options !== null && options !== void 0 ? options : {});\n }\n set mode(mode) {\n this.modeToggle.checked = mode === TreeFindMode.Filter;\n this.findInput.inputBox.setPlaceHolder(mode === TreeFindMode.Filter ? localize('type to filter', \"Type to filter\") : localize('type to search', \"Type to search\"));\n }\n style(styles) {\n this.findInput.style(styles);\n if (styles.listFilterWidgetBackground) {\n this.elements.root.style.backgroundColor = styles.listFilterWidgetBackground.toString();\n }\n if (styles.listFilterWidgetShadow) {\n this.elements.root.style.boxShadow = `0 0 8px 2px ${styles.listFilterWidgetShadow}`;\n }\n }\n layout(width = this.width) {\n this.width = width;\n this.right = clamp(this.right, 0, Math.max(0, width - 212));\n this.elements.root.style.right = `${this.right}px`;\n }\n showMessage(message) {\n this.findInput.showMessage(message);\n }\n clearMessage() {\n this.findInput.clearMessage();\n }\n dispose() {\n const _super = Object.create(null, {\n dispose: { get: () => super.dispose }\n });\n return __awaiter(this, void 0, void 0, function* () {\n this._onDidDisable.fire();\n this.elements.root.classList.add('disabled');\n yield timeout(300);\n _super.dispose.call(this);\n });\n }\n}\nclass FindController {\n constructor(tree, model, view, filter, contextViewProvider) {\n var _a;\n this.tree = tree;\n this.view = view;\n this.filter = filter;\n this.contextViewProvider = contextViewProvider;\n this._pattern = '';\n this.width = 0;\n this._onDidChangeMode = new Emitter();\n this.onDidChangeMode = this._onDidChangeMode.event;\n this._onDidChangePattern = new Emitter();\n this._onDidChangeOpenState = new Emitter();\n this.onDidChangeOpenState = this._onDidChangeOpenState.event;\n this.enabledDisposables = new DisposableStore();\n this.disposables = new DisposableStore();\n this._mode = (_a = tree.options.defaultFindMode) !== null && _a !== void 0 ? _a : TreeFindMode.Highlight;\n model.onDidSplice(this.onDidSpliceModel, this, this.disposables);\n }\n get pattern() { return this._pattern; }\n get mode() { return this._mode; }\n set mode(mode) {\n if (mode === this._mode) {\n return;\n }\n this._mode = mode;\n if (this.widget) {\n this.widget.mode = this._mode;\n }\n this.tree.refilter();\n this.render();\n this._onDidChangeMode.fire(mode);\n }\n onDidSpliceModel() {\n if (!this.widget || this.pattern.length === 0) {\n return;\n }\n this.tree.refilter();\n this.render();\n }\n render() {\n var _a, _b;\n const noMatches = this.filter.totalCount > 0 && this.filter.matchCount === 0;\n if (this.pattern && noMatches) {\n (_a = this.widget) === null || _a === void 0 ? void 0 : _a.showMessage({ type: 2 /* MessageType.WARNING */, content: localize('not found', \"No elements found.\") });\n }\n else {\n (_b = this.widget) === null || _b === void 0 ? void 0 : _b.clearMessage();\n }\n }\n shouldAllowFocus(node) {\n if (!this.widget || !this.pattern || this._mode === TreeFindMode.Filter) {\n return true;\n }\n if (this.filter.totalCount > 0 && this.filter.matchCount <= 1) {\n return true;\n }\n return !FuzzyScore.isDefault(node.filterData);\n }\n style(styles) {\n var _a;\n this.styles = styles;\n (_a = this.widget) === null || _a === void 0 ? void 0 : _a.style(styles);\n }\n layout(width) {\n var _a;\n this.width = width;\n (_a = this.widget) === null || _a === void 0 ? void 0 : _a.layout(width);\n }\n dispose() {\n this._onDidChangePattern.dispose();\n this.enabledDisposables.dispose();\n this.disposables.dispose();\n }\n}\nfunction asTreeMouseEvent(event) {\n let target = TreeMouseEventTarget.Unknown;\n if (hasParentWithClass(event.browserEvent.target, 'monaco-tl-twistie', 'monaco-tl-row')) {\n target = TreeMouseEventTarget.Twistie;\n }\n else if (hasParentWithClass(event.browserEvent.target, 'monaco-tl-contents', 'monaco-tl-row')) {\n target = TreeMouseEventTarget.Element;\n }\n else if (hasParentWithClass(event.browserEvent.target, 'monaco-tree-type-filter', 'monaco-list')) {\n target = TreeMouseEventTarget.Filter;\n }\n return {\n browserEvent: event.browserEvent,\n element: event.element ? event.element.element : null,\n target\n };\n}\nfunction dfs(node, fn) {\n fn(node);\n node.children.forEach(child => dfs(child, fn));\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 constructor(getFirstViewElementWithTrait, identityProvider) {\n this.getFirstViewElementWithTrait = getFirstViewElementWithTrait;\n this.identityProvider = identityProvider;\n this.nodes = [];\n this._onDidChange = new Emitter();\n this.onDidChange = this._onDidChange.event;\n }\n get nodeSet() {\n if (!this._nodeSet) {\n this._nodeSet = this.createNodeSet();\n }\n return this._nodeSet;\n }\n set(nodes, browserEvent) {\n if (!(browserEvent === null || browserEvent === void 0 ? void 0 : browserEvent.__forceEvent) && equals(this.nodes, nodes)) {\n return;\n }\n this._set(nodes, false, browserEvent);\n }\n _set(nodes, silent, browserEvent) {\n this.nodes = [...nodes];\n this.elements = undefined;\n this._nodeSet = undefined;\n if (!silent) {\n const that = this;\n this._onDidChange.fire({ get elements() { return that.get(); }, browserEvent });\n }\n }\n get() {\n if (!this.elements) {\n this.elements = this.nodes.map(node => node.element);\n }\n return [...this.elements];\n }\n getNodes() {\n return this.nodes;\n }\n has(node) {\n return this.nodeSet.has(node);\n }\n onDidModelSplice({ insertedNodes, deletedNodes }) {\n if (!this.identityProvider) {\n const set = this.createNodeSet();\n const visit = (node) => set.delete(node);\n deletedNodes.forEach(node => dfs(node, visit));\n this.set([...set.values()]);\n return;\n }\n const deletedNodesIdSet = new Set();\n const deletedNodesVisitor = (node) => deletedNodesIdSet.add(this.identityProvider.getId(node.element).toString());\n deletedNodes.forEach(node => dfs(node, deletedNodesVisitor));\n const insertedNodesMap = new Map();\n const insertedNodesVisitor = (node) => insertedNodesMap.set(this.identityProvider.getId(node.element).toString(), node);\n insertedNodes.forEach(node => dfs(node, insertedNodesVisitor));\n const nodes = [];\n for (const node of this.nodes) {\n const id = this.identityProvider.getId(node.element).toString();\n const wasDeleted = deletedNodesIdSet.has(id);\n if (!wasDeleted) {\n nodes.push(node);\n }\n else {\n const insertedNode = insertedNodesMap.get(id);\n if (insertedNode) {\n nodes.push(insertedNode);\n }\n }\n }\n if (this.nodes.length > 0 && nodes.length === 0) {\n const node = this.getFirstViewElementWithTrait();\n if (node) {\n nodes.push(node);\n }\n }\n this._set(nodes, true);\n }\n createNodeSet() {\n const set = new Set();\n for (const node of this.nodes) {\n set.add(node);\n }\n return set;\n }\n}\nclass TreeNodeListMouseController extends MouseController {\n constructor(list, tree) {\n super(list);\n this.tree = tree;\n }\n onViewPointer(e) {\n if (isButton(e.browserEvent.target) ||\n isInputElement(e.browserEvent.target) ||\n isMonacoEditor(e.browserEvent.target)) {\n return;\n }\n const node = e.element;\n if (!node) {\n return super.onViewPointer(e);\n }\n if (this.isSelectionRangeChangeEvent(e) || this.isSelectionSingleChangeEvent(e)) {\n return super.onViewPointer(e);\n }\n const target = e.browserEvent.target;\n const onTwistie = target.classList.contains('monaco-tl-twistie')\n || (target.classList.contains('monaco-icon-label') && target.classList.contains('folder-icon') && e.browserEvent.offsetX < 16);\n let expandOnlyOnTwistieClick = false;\n if (typeof this.tree.expandOnlyOnTwistieClick === 'function') {\n expandOnlyOnTwistieClick = this.tree.expandOnlyOnTwistieClick(node.element);\n }\n else {\n expandOnlyOnTwistieClick = !!this.tree.expandOnlyOnTwistieClick;\n }\n if (expandOnlyOnTwistieClick && !onTwistie && e.browserEvent.detail !== 2) {\n return super.onViewPointer(e);\n }\n if (!this.tree.expandOnDoubleClick && e.browserEvent.detail === 2) {\n return super.onViewPointer(e);\n }\n if (node.collapsible) {\n const model = this.tree.model; // internal\n const location = model.getNodeLocation(node);\n const recursive = e.browserEvent.altKey;\n this.tree.setFocus([location]);\n model.setCollapsed(location, undefined, recursive);\n if (expandOnlyOnTwistieClick && onTwistie) {\n return;\n }\n }\n super.onViewPointer(e);\n }\n onDoubleClick(e) {\n const onTwistie = e.browserEvent.target.classList.contains('monaco-tl-twistie');\n if (onTwistie || !this.tree.expandOnDoubleClick) {\n return;\n }\n super.onDoubleClick(e);\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 constructor(user, container, virtualDelegate, renderers, focusTrait, selectionTrait, anchorTrait, options) {\n super(user, container, virtualDelegate, renderers, options);\n this.focusTrait = focusTrait;\n this.selectionTrait = selectionTrait;\n this.anchorTrait = anchorTrait;\n }\n createMouseController(options) {\n return new TreeNodeListMouseController(this, options.tree);\n }\n splice(start, deleteCount, elements = []) {\n super.splice(start, deleteCount, elements);\n if (elements.length === 0) {\n return;\n }\n const additionalFocus = [];\n const additionalSelection = [];\n let anchor;\n elements.forEach((node, index) => {\n if (this.focusTrait.has(node)) {\n additionalFocus.push(start + index);\n }\n if (this.selectionTrait.has(node)) {\n additionalSelection.push(start + index);\n }\n if (this.anchorTrait.has(node)) {\n anchor = start + index;\n }\n });\n if (additionalFocus.length > 0) {\n super.setFocus(distinct([...super.getFocus(), ...additionalFocus]));\n }\n if (additionalSelection.length > 0) {\n super.setSelection(distinct([...super.getSelection(), ...additionalSelection]));\n }\n if (typeof anchor === 'number') {\n super.setAnchor(anchor);\n }\n }\n setFocus(indexes, browserEvent, fromAPI = false) {\n super.setFocus(indexes, browserEvent);\n if (!fromAPI) {\n this.focusTrait.set(indexes.map(i => this.element(i)), browserEvent);\n }\n }\n setSelection(indexes, browserEvent, fromAPI = false) {\n super.setSelection(indexes, browserEvent);\n if (!fromAPI) {\n this.selectionTrait.set(indexes.map(i => this.element(i)), browserEvent);\n }\n }\n setAnchor(index, fromAPI = false) {\n super.setAnchor(index);\n if (!fromAPI) {\n if (typeof index === 'undefined') {\n this.anchorTrait.set([]);\n }\n else {\n this.anchorTrait.set([this.element(index)]);\n }\n }\n }\n}\nexport class AbstractTree {\n constructor(_user, container, delegate, renderers, _options = {}) {\n var _a;\n this._user = _user;\n this._options = _options;\n this.eventBufferer = new EventBufferer();\n this.onDidChangeFindOpenState = Event.None;\n this.disposables = new DisposableStore();\n this._onWillRefilter = new Emitter();\n this.onWillRefilter = this._onWillRefilter.event;\n this._onDidUpdateOptions = new Emitter();\n const treeDelegate = new ComposedTreeDelegate(delegate);\n const onDidChangeCollapseStateRelay = new Relay();\n const onDidChangeActiveNodes = new Relay();\n const activeNodes = this.disposables.add(new EventCollection(onDidChangeActiveNodes.event));\n this.renderers = renderers.map(r => new TreeRenderer(r, () => this.model, onDidChangeCollapseStateRelay.event, activeNodes, _options));\n for (const r of this.renderers) {\n this.disposables.add(r);\n }\n let filter;\n if (_options.keyboardNavigationLabelProvider) {\n filter = new FindFilter(this, _options.keyboardNavigationLabelProvider, _options.filter);\n _options = Object.assign(Object.assign({}, _options), { filter: filter }); // TODO need typescript help here\n this.disposables.add(filter);\n }\n this.focus = new Trait(() => this.view.getFocusedElements()[0], _options.identityProvider);\n this.selection = new Trait(() => this.view.getSelectedElements()[0], _options.identityProvider);\n this.anchor = new Trait(() => this.view.getAnchorElement(), _options.identityProvider);\n this.view = new TreeNodeList(_user, container, treeDelegate, this.renderers, this.focus, this.selection, this.anchor, Object.assign(Object.assign({}, asListOptions(() => this.model, _options)), { tree: this }));\n this.model = this.createModel(_user, this.view, _options);\n onDidChangeCollapseStateRelay.input = this.model.onDidChangeCollapseState;\n const onDidModelSplice = Event.forEach(this.model.onDidSplice, e => {\n this.eventBufferer.bufferEvents(() => {\n this.focus.onDidModelSplice(e);\n this.selection.onDidModelSplice(e);\n });\n }, this.disposables);\n // Make sure the `forEach` always runs\n onDidModelSplice(() => null, null, this.disposables);\n // Active nodes can change when the model changes or when focus or selection change.\n // We debounce it with 0 delay since these events may fire in the same stack and we only\n // want to run this once. It also doesn't matter if it runs on the next tick since it's only\n // a nice to have UI feature.\n onDidChangeActiveNodes.input = Event.chain(Event.any(onDidModelSplice, this.focus.onDidChange, this.selection.onDidChange))\n .debounce(() => null, 0)\n .map(() => {\n const set = new Set();\n for (const node of this.focus.getNodes()) {\n set.add(node);\n }\n for (const node of this.selection.getNodes()) {\n set.add(node);\n }\n return [...set.values()];\n }).event;\n if (_options.keyboardSupport !== false) {\n const onKeyDown = Event.chain(this.view.onKeyDown)\n .filter(e => !isInputElement(e.target))\n .map(e => new StandardKeyboardEvent(e));\n onKeyDown.filter(e => e.keyCode === 15 /* KeyCode.LeftArrow */).on(this.onLeftArrow, this, this.disposables);\n onKeyDown.filter(e => e.keyCode === 17 /* KeyCode.RightArrow */).on(this.onRightArrow, this, this.disposables);\n onKeyDown.filter(e => e.keyCode === 10 /* KeyCode.Space */).on(this.onSpace, this, this.disposables);\n }\n if (((_a = _options.findWidgetEnabled) !== null && _a !== void 0 ? _a : true) && _options.keyboardNavigationLabelProvider && _options.contextViewProvider) {\n this.findController = new FindController(this, this.model, this.view, filter, _options.contextViewProvider);\n this.focusNavigationFilter = node => this.findController.shouldAllowFocus(node);\n this.onDidChangeFindOpenState = this.findController.onDidChangeOpenState;\n this.disposables.add(this.findController);\n this.onDidChangeFindMode = this.findController.onDidChangeMode;\n }\n else {\n this.onDidChangeFindMode = Event.None;\n }\n this.styleElement = createStyleSheet(this.view.getHTMLElement());\n this.getHTMLElement().classList.toggle('always', this._options.renderIndentGuides === RenderIndentGuides.Always);\n }\n get onDidChangeFocus() { return this.eventBufferer.wrapEvent(this.focus.onDidChange); }\n get onDidChangeSelection() { return this.eventBufferer.wrapEvent(this.selection.onDidChange); }\n get onMouseDblClick() { return Event.filter(Event.map(this.view.onMouseDblClick, asTreeMouseEvent), e => e.target !== TreeMouseEventTarget.Filter); }\n get onPointer() { return Event.map(this.view.onPointer, asTreeMouseEvent); }\n get onDidFocus() { return this.view.onDidFocus; }\n get onDidChangeModel() { return Event.signal(this.model.onDidSplice); }\n get onDidChangeCollapseState() { return this.model.onDidChangeCollapseState; }\n get findMode() { var _a, _b; return (_b = (_a = this.findController) === null || _a === void 0 ? void 0 : _a.mode) !== null && _b !== void 0 ? _b : TreeFindMode.Highlight; }\n set findMode(findMode) { if (this.findController) {\n this.findController.mode = findMode;\n } }\n get expandOnDoubleClick() { return typeof this._options.expandOnDoubleClick === 'undefined' ? true : this._options.expandOnDoubleClick; }\n get expandOnlyOnTwistieClick() { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? true : this._options.expandOnlyOnTwistieClick; }\n get onDidDispose() { return this.view.onDidDispose; }\n updateOptions(optionsUpdate = {}) {\n this._options = Object.assign(Object.assign({}, this._options), optionsUpdate);\n for (const renderer of this.renderers) {\n renderer.updateOptions(optionsUpdate);\n }\n this.view.updateOptions(this._options);\n this._onDidUpdateOptions.fire(this._options);\n this.getHTMLElement().classList.toggle('always', this._options.renderIndentGuides === RenderIndentGuides.Always);\n }\n get options() {\n return this._options;\n }\n // Widget\n getHTMLElement() {\n return this.view.getHTMLElement();\n }\n get scrollTop() {\n return this.view.scrollTop;\n }\n set scrollTop(scrollTop) {\n this.view.scrollTop = scrollTop;\n }\n domFocus() {\n this.view.domFocus();\n }\n layout(height, width) {\n var _a;\n this.view.layout(height, width);\n if (isNumber(width)) {\n (_a = this.findController) === null || _a === void 0 ? void 0 : _a.layout(width);\n }\n }\n style(styles) {\n var _a;\n const suffix = `.${this.view.domId}`;\n const content = [];\n if (styles.treeIndentGuidesStroke) {\n content.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 content.push(`.monaco-list${suffix} .monaco-tl-indent > .indent-guide.active { border-color: ${styles.treeIndentGuidesStroke}; }`);\n }\n this.styleElement.textContent = content.join('\\n');\n (_a = this.findController) === null || _a === void 0 ? void 0 : _a.style(styles);\n this.view.style(styles);\n }\n // Tree navigation\n getParentElement(location) {\n const parentRef = this.model.getParentNodeLocation(location);\n const parentNode = this.model.getNode(parentRef);\n return parentNode.element;\n }\n getFirstElementChild(location) {\n return this.model.getFirstElementChild(location);\n }\n // Tree\n getNode(location) {\n return this.model.getNode(location);\n }\n collapse(location, recursive = false) {\n return this.model.setCollapsed(location, true, recursive);\n }\n expand(location, recursive = false) {\n return this.model.setCollapsed(location, false, recursive);\n }\n isCollapsible(location) {\n return this.model.isCollapsible(location);\n }\n setCollapsible(location, collapsible) {\n return this.model.setCollapsible(location, collapsible);\n }\n isCollapsed(location) {\n return this.model.isCollapsed(location);\n }\n refilter() {\n this._onWillRefilter.fire(undefined);\n this.model.refilter();\n }\n setSelection(elements, browserEvent) {\n const nodes = elements.map(e => this.model.getNode(e));\n this.selection.set(nodes, browserEvent);\n const indexes = elements.map(e => this.model.getListIndex(e)).filter(i => i > -1);\n this.view.setSelection(indexes, browserEvent, true);\n }\n getSelection() {\n return this.selection.get();\n }\n setFocus(elements, browserEvent) {\n const nodes = elements.map(e => this.model.getNode(e));\n this.focus.set(nodes, browserEvent);\n const indexes = elements.map(e => this.model.getListIndex(e)).filter(i => i > -1);\n this.view.setFocus(indexes, browserEvent, true);\n }\n getFocus() {\n return this.focus.get();\n }\n reveal(location, relativeTop) {\n this.model.expandTo(location);\n const index = this.model.getListIndex(location);\n if (index === -1) {\n return;\n }\n this.view.reveal(index, relativeTop);\n }\n // List\n onLeftArrow(e) {\n e.preventDefault();\n e.stopPropagation();\n const nodes = this.view.getFocusedElements();\n if (nodes.length === 0) {\n return;\n }\n const node = nodes[0];\n const location = this.model.getNodeLocation(node);\n const didChange = this.model.setCollapsed(location, true);\n if (!didChange) {\n const parentLocation = this.model.getParentNodeLocation(location);\n if (!parentLocation) {\n return;\n }\n const parentListIndex = this.model.getListIndex(parentLocation);\n this.view.reveal(parentListIndex);\n this.view.setFocus([parentListIndex]);\n }\n }\n onRightArrow(e) {\n e.preventDefault();\n e.stopPropagation();\n const nodes = this.view.getFocusedElements();\n if (nodes.length === 0) {\n return;\n }\n const node = nodes[0];\n const location = this.model.getNodeLocation(node);\n const didChange = this.model.setCollapsed(location, false);\n if (!didChange) {\n if (!node.children.some(child => child.visible)) {\n return;\n }\n const [focusedIndex] = this.view.getFocus();\n const firstChildIndex = focusedIndex + 1;\n this.view.reveal(firstChildIndex);\n this.view.setFocus([firstChildIndex]);\n }\n }\n onSpace(e) {\n e.preventDefault();\n e.stopPropagation();\n const nodes = this.view.getFocusedElements();\n if (nodes.length === 0) {\n return;\n }\n const node = nodes[0];\n const location = this.model.getNodeLocation(node);\n const recursive = e.browserEvent.altKey;\n this.model.setCollapsed(location, undefined, recursive);\n }\n dispose() {\n dispose(this.disposables);\n this.view.dispose();\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 *--------------------------------------------------------------------------------------------*/\nimport { IndexTreeModel } from './indexTreeModel.js';\nimport { TreeError } from './tree.js';\nimport { Iterable } from '../../../common/iterator.js';\nexport class ObjectTreeModel {\n constructor(user, list, options = {}) {\n this.user = user;\n this.rootRef = null;\n this.nodes = new Map();\n this.nodesByIdentity = new Map();\n this.model = new IndexTreeModel(user, list, null, options);\n this.onDidSplice = this.model.onDidSplice;\n this.onDidChangeCollapseState = this.model.onDidChangeCollapseState;\n this.onDidChangeRenderNodeCount = this.model.onDidChangeRenderNodeCount;\n if (options.sorter) {\n this.sorter = {\n compare(a, b) {\n return options.sorter.compare(a.element, b.element);\n }\n };\n }\n this.identityProvider = options.identityProvider;\n }\n setChildren(element, children = Iterable.empty(), options = {}) {\n const location = this.getElementLocation(element);\n this._setChildren(location, this.preserveCollapseState(children), options);\n }\n _setChildren(location, children = Iterable.empty(), options) {\n const insertedElements = new Set();\n const insertedElementIds = new Set();\n const onDidCreateNode = (node) => {\n var _a;\n if (node.element === null) {\n return;\n }\n const tnode = node;\n insertedElements.add(tnode.element);\n this.nodes.set(tnode.element, tnode);\n if (this.identityProvider) {\n const id = this.identityProvider.getId(tnode.element).toString();\n insertedElementIds.add(id);\n this.nodesByIdentity.set(id, tnode);\n }\n (_a = options.onDidCreateNode) === null || _a === void 0 ? void 0 : _a.call(options, tnode);\n };\n const onDidDeleteNode = (node) => {\n var _a;\n if (node.element === null) {\n return;\n }\n const tnode = node;\n if (!insertedElements.has(tnode.element)) {\n this.nodes.delete(tnode.element);\n }\n if (this.identityProvider) {\n const id = this.identityProvider.getId(tnode.element).toString();\n if (!insertedElementIds.has(id)) {\n this.nodesByIdentity.delete(id);\n }\n }\n (_a = options.onDidDeleteNode) === null || _a === void 0 ? void 0 : _a.call(options, tnode);\n };\n this.model.splice([...location, 0], Number.MAX_VALUE, children, Object.assign(Object.assign({}, options), { onDidCreateNode, onDidDeleteNode }));\n }\n preserveCollapseState(elements = Iterable.empty()) {\n if (this.sorter) {\n elements = [...elements].sort(this.sorter.compare.bind(this.sorter));\n }\n return Iterable.map(elements, treeElement => {\n let node = this.nodes.get(treeElement.element);\n if (!node && this.identityProvider) {\n const id = this.identityProvider.getId(treeElement.element).toString();\n node = this.nodesByIdentity.get(id);\n }\n if (!node) {\n return Object.assign(Object.assign({}, treeElement), { children: this.preserveCollapseState(treeElement.children) });\n }\n const collapsible = typeof treeElement.collapsible === 'boolean' ? treeElement.collapsible : node.collapsible;\n const collapsed = typeof treeElement.collapsed !== 'undefined' ? treeElement.collapsed : node.collapsed;\n return Object.assign(Object.assign({}, treeElement), { collapsible,\n collapsed, children: this.preserveCollapseState(treeElement.children) });\n });\n }\n rerender(element) {\n const location = this.getElementLocation(element);\n this.model.rerender(location);\n }\n getFirstElementChild(ref = null) {\n const location = this.getElementLocation(ref);\n return this.model.getFirstElementChild(location);\n }\n has(element) {\n return this.nodes.has(element);\n }\n getListIndex(element) {\n const location = this.getElementLocation(element);\n return this.model.getListIndex(location);\n }\n getListRenderCount(element) {\n const location = this.getElementLocation(element);\n return this.model.getListRenderCount(location);\n }\n isCollapsible(element) {\n const location = this.getElementLocation(element);\n return this.model.isCollapsible(location);\n }\n setCollapsible(element, collapsible) {\n const location = this.getElementLocation(element);\n return this.model.setCollapsible(location, collapsible);\n }\n isCollapsed(element) {\n const location = this.getElementLocation(element);\n return this.model.isCollapsed(location);\n }\n setCollapsed(element, collapsed, recursive) {\n const location = this.getElementLocation(element);\n return this.model.setCollapsed(location, collapsed, recursive);\n }\n expandTo(element) {\n const location = this.getElementLocation(element);\n this.model.expandTo(location);\n }\n refilter() {\n this.model.refilter();\n }\n getNode(element = null) {\n if (element === null) {\n return this.model.getNode(this.model.rootRef);\n }\n const node = this.nodes.get(element);\n if (!node) {\n throw new TreeError(this.user, `Tree element not found: ${element}`);\n }\n return node;\n }\n getNodeLocation(node) {\n return node.element;\n }\n getParentNodeLocation(element) {\n if (element === null) {\n throw new TreeError(this.user, `Invalid getParentNodeLocation call`);\n }\n const node = this.nodes.get(element);\n if (!node) {\n throw new TreeError(this.user, `Tree element not found: ${element}`);\n }\n const location = this.model.getNodeLocation(node);\n const parentLocation = this.model.getParentNodeLocation(location);\n const parent = this.model.getNode(parentLocation);\n return parent.element;\n }\n getElementLocation(element) {\n if (element === null) {\n return [];\n }\n const node = this.nodes.get(element);\n if (!node) {\n throw new TreeError(this.user, `Tree element not found: ${element}`);\n }\n return this.model.getNodeLocation(node);\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 *--------------------------------------------------------------------------------------------*/\nimport { ObjectTreeModel } from './objectTreeModel.js';\nimport { TreeError, WeakMapper } from './tree.js';\nimport { Event } from '../../../common/event.js';\nimport { Iterable } from '../../../common/iterator.js';\nfunction noCompress(element) {\n const elements = [element.element];\n const incompressible = element.incompressible || false;\n return {\n element: { elements, incompressible },\n children: Iterable.map(Iterable.from(element.children), noCompress),\n collapsible: element.collapsible,\n collapsed: element.collapsed\n };\n}\n// Exported only for test reasons, do not use directly\nexport function compress(element) {\n const elements = [element.element];\n const incompressible = element.incompressible || false;\n let childrenIterator;\n let children;\n while (true) {\n [children, childrenIterator] = Iterable.consume(Iterable.from(element.children), 2);\n if (children.length !== 1) {\n break;\n }\n if (children[0].incompressible) {\n break;\n }\n element = children[0];\n elements.push(element.element);\n }\n return {\n element: { elements, incompressible },\n children: Iterable.map(Iterable.concat(children, childrenIterator), compress),\n collapsible: element.collapsible,\n collapsed: element.collapsed\n };\n}\nfunction _decompress(element, index = 0) {\n let children;\n if (index < element.element.elements.length - 1) {\n children = [_decompress(element, index + 1)];\n }\n else {\n children = Iterable.map(Iterable.from(element.children), el => _decompress(el, 0));\n }\n if (index === 0 && element.element.incompressible) {\n return {\n element: element.element.elements[index],\n children,\n incompressible: true,\n collapsible: element.collapsible,\n collapsed: element.collapsed\n };\n }\n return {\n element: element.element.elements[index],\n children,\n collapsible: element.collapsible,\n collapsed: element.collapsed\n };\n}\n// Exported only for test reasons, do not use directly\nexport function decompress(element) {\n return _decompress(element, 0);\n}\nfunction splice(treeElement, element, children) {\n if (treeElement.element === element) {\n return Object.assign(Object.assign({}, treeElement), { children });\n }\n return Object.assign(Object.assign({}, treeElement), { children: Iterable.map(Iterable.from(treeElement.children), e => splice(e, element, children)) });\n}\nconst wrapIdentityProvider = (base) => ({\n getId(node) {\n return node.elements.map(e => base.getId(e).toString()).join('\\0');\n }\n});\n// Exported only for test reasons, do not use directly\nexport class CompressedObjectTreeModel {\n constructor(user, list, options = {}) {\n this.user = user;\n this.rootRef = null;\n this.nodes = new Map();\n this.model = new ObjectTreeModel(user, list, options);\n this.enabled = typeof options.compressionEnabled === 'undefined' ? true : options.compressionEnabled;\n this.identityProvider = options.identityProvider;\n }\n get onDidSplice() { return this.model.onDidSplice; }\n get onDidChangeCollapseState() { return this.model.onDidChangeCollapseState; }\n get onDidChangeRenderNodeCount() { return this.model.onDidChangeRenderNodeCount; }\n setChildren(element, children = Iterable.empty(), options) {\n // Diffs must be deem, since the compression can affect nested elements.\n // @see https://github.com/microsoft/vscode/pull/114237#issuecomment-759425034\n const diffIdentityProvider = options.diffIdentityProvider && wrapIdentityProvider(options.diffIdentityProvider);\n if (element === null) {\n const compressedChildren = Iterable.map(children, this.enabled ? compress : noCompress);\n this._setChildren(null, compressedChildren, { diffIdentityProvider, diffDepth: Infinity });\n return;\n }\n const compressedNode = this.nodes.get(element);\n if (!compressedNode) {\n throw new Error('Unknown compressed tree node');\n }\n const node = this.model.getNode(compressedNode);\n const compressedParentNode = this.model.getParentNodeLocation(compressedNode);\n const parent = this.model.getNode(compressedParentNode);\n const decompressedElement = decompress(node);\n const splicedElement = splice(decompressedElement, element, children);\n const recompressedElement = (this.enabled ? compress : noCompress)(splicedElement);\n const parentChildren = parent.children\n .map(child => child === node ? recompressedElement : child);\n this._setChildren(parent.element, parentChildren, {\n diffIdentityProvider,\n diffDepth: node.depth - parent.depth,\n });\n }\n setCompressionEnabled(enabled) {\n if (enabled === this.enabled) {\n return;\n }\n this.enabled = enabled;\n const root = this.model.getNode();\n const rootChildren = root.children;\n const decompressedRootChildren = Iterable.map(rootChildren, decompress);\n const recompressedRootChildren = Iterable.map(decompressedRootChildren, enabled ? compress : noCompress);\n // it should be safe to always use deep diff mode here if an identity\n // provider is available, since we know the raw nodes are unchanged.\n this._setChildren(null, recompressedRootChildren, {\n diffIdentityProvider: this.identityProvider,\n diffDepth: Infinity,\n });\n }\n _setChildren(node, children, options) {\n const insertedElements = new Set();\n const onDidCreateNode = (node) => {\n for (const element of node.element.elements) {\n insertedElements.add(element);\n this.nodes.set(element, node.element);\n }\n };\n const onDidDeleteNode = (node) => {\n for (const element of node.element.elements) {\n if (!insertedElements.has(element)) {\n this.nodes.delete(element);\n }\n }\n };\n this.model.setChildren(node, children, Object.assign(Object.assign({}, options), { onDidCreateNode, onDidDeleteNode }));\n }\n has(element) {\n return this.nodes.has(element);\n }\n getListIndex(location) {\n const node = this.getCompressedNode(location);\n return this.model.getListIndex(node);\n }\n getListRenderCount(location) {\n const node = this.getCompressedNode(location);\n return this.model.getListRenderCount(node);\n }\n getNode(location) {\n if (typeof location === 'undefined') {\n return this.model.getNode();\n }\n const node = this.getCompressedNode(location);\n return this.model.getNode(node);\n }\n // TODO: review this\n getNodeLocation(node) {\n const compressedNode = this.model.getNodeLocation(node);\n if (compressedNode === null) {\n return null;\n }\n return compressedNode.elements[compressedNode.elements.length - 1];\n }\n // TODO: review this\n getParentNodeLocation(location) {\n const compressedNode = this.getCompressedNode(location);\n const parentNode = this.model.getParentNodeLocation(compressedNode);\n if (parentNode === null) {\n return null;\n }\n return parentNode.elements[parentNode.elements.length - 1];\n }\n getFirstElementChild(location) {\n const compressedNode = this.getCompressedNode(location);\n return this.model.getFirstElementChild(compressedNode);\n }\n isCollapsible(location) {\n const compressedNode = this.getCompressedNode(location);\n return this.model.isCollapsible(compressedNode);\n }\n setCollapsible(location, collapsible) {\n const compressedNode = this.getCompressedNode(location);\n return this.model.setCollapsible(compressedNode, collapsible);\n }\n isCollapsed(location) {\n const compressedNode = this.getCompressedNode(location);\n return this.model.isCollapsed(compressedNode);\n }\n setCollapsed(location, collapsed, recursive) {\n const compressedNode = this.getCompressedNode(location);\n return this.model.setCollapsed(compressedNode, collapsed, recursive);\n }\n expandTo(location) {\n const compressedNode = this.getCompressedNode(location);\n this.model.expandTo(compressedNode);\n }\n rerender(location) {\n const compressedNode = this.getCompressedNode(location);\n this.model.rerender(compressedNode);\n }\n refilter() {\n this.model.refilter();\n }\n getCompressedNode(element) {\n if (element === null) {\n return null;\n }\n const node = this.nodes.get(element);\n if (!node) {\n throw new TreeError(this.user, `Tree element not found: ${element}`);\n }\n return node;\n }\n}\nexport const DefaultElementMapper = elements => elements[elements.length - 1];\nclass CompressedTreeNodeWrapper {\n constructor(unwrapper, node) {\n this.unwrapper = unwrapper;\n this.node = node;\n }\n get element() { return this.node.element === null ? null : this.unwrapper(this.node.element); }\n get children() { return this.node.children.map(node => new CompressedTreeNodeWrapper(this.unwrapper, node)); }\n get depth() { return this.node.depth; }\n get visibleChildrenCount() { return this.node.visibleChildrenCount; }\n get visibleChildIndex() { return this.node.visibleChildIndex; }\n get collapsible() { return this.node.collapsible; }\n get collapsed() { return this.node.collapsed; }\n get visible() { return this.node.visible; }\n get filterData() { return this.node.filterData; }\n}\nfunction mapList(nodeMapper, list) {\n return {\n splice(start, deleteCount, toInsert) {\n list.splice(start, deleteCount, toInsert.map(node => nodeMapper.map(node)));\n },\n updateElementHeight(index, height) {\n list.updateElementHeight(index, height);\n }\n };\n}\nfunction mapOptions(compressedNodeUnwrapper, options) {\n return Object.assign(Object.assign({}, options), { identityProvider: options.identityProvider && {\n getId(node) {\n return options.identityProvider.getId(compressedNodeUnwrapper(node));\n }\n }, sorter: options.sorter && {\n compare(node, otherNode) {\n return options.sorter.compare(node.elements[0], otherNode.elements[0]);\n }\n }, filter: options.filter && {\n filter(node, parentVisibility) {\n return options.filter.filter(compressedNodeUnwrapper(node), parentVisibility);\n }\n } });\n}\nexport class CompressibleObjectTreeModel {\n constructor(user, list, options = {}) {\n this.rootRef = null;\n this.elementMapper = options.elementMapper || DefaultElementMapper;\n const compressedNodeUnwrapper = node => this.elementMapper(node.elements);\n this.nodeMapper = new WeakMapper(node => new CompressedTreeNodeWrapper(compressedNodeUnwrapper, node));\n this.model = new CompressedObjectTreeModel(user, mapList(this.nodeMapper, list), mapOptions(compressedNodeUnwrapper, options));\n }\n get onDidSplice() {\n return Event.map(this.model.onDidSplice, ({ insertedNodes, deletedNodes }) => ({\n insertedNodes: insertedNodes.map(node => this.nodeMapper.map(node)),\n deletedNodes: deletedNodes.map(node => this.nodeMapper.map(node)),\n }));\n }\n get onDidChangeCollapseState() {\n return Event.map(this.model.onDidChangeCollapseState, ({ node, deep }) => ({\n node: this.nodeMapper.map(node),\n deep\n }));\n }\n get onDidChangeRenderNodeCount() {\n return Event.map(this.model.onDidChangeRenderNodeCount, node => this.nodeMapper.map(node));\n }\n setChildren(element, children = Iterable.empty(), options = {}) {\n this.model.setChildren(element, children, options);\n }\n setCompressionEnabled(enabled) {\n this.model.setCompressionEnabled(enabled);\n }\n has(location) {\n return this.model.has(location);\n }\n getListIndex(location) {\n return this.model.getListIndex(location);\n }\n getListRenderCount(location) {\n return this.model.getListRenderCount(location);\n }\n getNode(location) {\n return this.nodeMapper.map(this.model.getNode(location));\n }\n getNodeLocation(node) {\n return node.element;\n }\n getParentNodeLocation(location) {\n return this.model.getParentNodeLocation(location);\n }\n getFirstElementChild(location) {\n const result = this.model.getFirstElementChild(location);\n if (result === null || typeof result === 'undefined') {\n return result;\n }\n return this.elementMapper(result.elements);\n }\n isCollapsible(location) {\n return this.model.isCollapsible(location);\n }\n setCollapsible(location, collapsed) {\n return this.model.setCollapsible(location, collapsed);\n }\n isCollapsed(location) {\n return this.model.isCollapsed(location);\n }\n setCollapsed(location, collapsed, recursive) {\n return this.model.setCollapsed(location, collapsed, recursive);\n }\n expandTo(location) {\n return this.model.expandTo(location);\n }\n rerender(location) {\n return this.model.rerender(location);\n }\n refilter() {\n return this.model.refilter();\n }\n getCompressedTreeNode(location = null) {\n return this.model.getNode(location);\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nimport { AbstractTree } from './abstractTree.js';\nimport { CompressibleObjectTreeModel } from './compressedObjectTreeModel.js';\nimport { ObjectTreeModel } from './objectTreeModel.js';\nimport { memoize } from '../../../common/decorators.js';\nimport { Iterable } from '../../../common/iterator.js';\nexport class ObjectTree extends AbstractTree {\n constructor(user, container, delegate, renderers, options = {}) {\n super(user, container, delegate, renderers, options);\n this.user = user;\n }\n get onDidChangeCollapseState() { return this.model.onDidChangeCollapseState; }\n setChildren(element, children = Iterable.empty(), options) {\n this.model.setChildren(element, children, options);\n }\n rerender(element) {\n if (element === undefined) {\n this.view.rerender();\n return;\n }\n this.model.rerender(element);\n }\n hasElement(element) {\n return this.model.has(element);\n }\n createModel(user, view, options) {\n return new ObjectTreeModel(user, view, options);\n }\n}\nclass CompressibleRenderer {\n constructor(_compressedTreeNodeProvider, renderer) {\n this._compressedTreeNodeProvider = _compressedTreeNodeProvider;\n this.renderer = renderer;\n this.templateId = renderer.templateId;\n if (renderer.onDidChangeTwistieState) {\n this.onDidChangeTwistieState = renderer.onDidChangeTwistieState;\n }\n }\n get compressedTreeNodeProvider() {\n return this._compressedTreeNodeProvider();\n }\n renderTemplate(container) {\n const data = this.renderer.renderTemplate(container);\n return { compressedTreeNode: undefined, data };\n }\n renderElement(node, index, templateData, height) {\n const compressedTreeNode = this.compressedTreeNodeProvider.getCompressedTreeNode(node.element);\n if (compressedTreeNode.element.elements.length === 1) {\n templateData.compressedTreeNode = undefined;\n this.renderer.renderElement(node, index, templateData.data, height);\n }\n else {\n templateData.compressedTreeNode = compressedTreeNode;\n this.renderer.renderCompressedElements(compressedTreeNode, index, templateData.data, height);\n }\n }\n disposeElement(node, index, templateData, height) {\n var _a, _b, _c, _d;\n if (templateData.compressedTreeNode) {\n (_b = (_a = this.renderer).disposeCompressedElements) === null || _b === void 0 ? void 0 : _b.call(_a, templateData.compressedTreeNode, index, templateData.data, height);\n }\n else {\n (_d = (_c = this.renderer).disposeElement) === null || _d === void 0 ? void 0 : _d.call(_c, node, index, templateData.data, height);\n }\n }\n disposeTemplate(templateData) {\n this.renderer.disposeTemplate(templateData.data);\n }\n renderTwistie(element, twistieElement) {\n if (this.renderer.renderTwistie) {\n return this.renderer.renderTwistie(element, twistieElement);\n }\n return false;\n }\n}\n__decorate([\n memoize\n], CompressibleRenderer.prototype, \"compressedTreeNodeProvider\", null);\nfunction asObjectTreeOptions(compressedTreeNodeProvider, options) {\n return options && Object.assign(Object.assign({}, options), { keyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && {\n getKeyboardNavigationLabel(e) {\n let compressedTreeNode;\n try {\n compressedTreeNode = compressedTreeNodeProvider().getCompressedTreeNode(e);\n }\n catch (_a) {\n return options.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(e);\n }\n if (compressedTreeNode.element.elements.length === 1) {\n return options.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(e);\n }\n else {\n return options.keyboardNavigationLabelProvider.getCompressedNodeKeyboardNavigationLabel(compressedTreeNode.element.elements);\n }\n }\n } });\n}\nexport class CompressibleObjectTree extends ObjectTree {\n constructor(user, container, delegate, renderers, options = {}) {\n const compressedTreeNodeProvider = () => this;\n const compressibleRenderers = renderers.map(r => new CompressibleRenderer(compressedTreeNodeProvider, r));\n super(user, container, delegate, compressibleRenderers, asObjectTreeOptions(compressedTreeNodeProvider, options));\n }\n setChildren(element, children = Iterable.empty(), options) {\n this.model.setChildren(element, children, options);\n }\n createModel(user, view, options) {\n return new CompressibleObjectTreeModel(user, view, options);\n }\n updateOptions(optionsUpdate = {}) {\n super.updateOptions(optionsUpdate);\n if (typeof optionsUpdate.compressionEnabled !== 'undefined') {\n this.model.setCompressionEnabled(optionsUpdate.compressionEnabled);\n }\n }\n getCompressedTreeNode(element = null) {\n return this.model.getCompressedTreeNode(element);\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 *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { ElementsDragAndDropData } from '../list/listView.js';\nimport { ComposedTreeDelegate } from './abstractTree.js';\nimport { getVisibleState, isFilterResult } from './indexTreeModel.js';\nimport { CompressibleObjectTree, ObjectTree } from './objectTree.js';\nimport { TreeError, WeakMapper } from './tree.js';\nimport { createCancelablePromise, Promises, timeout } from '../../../common/async.js';\nimport { Codicon } from '../../../common/codicons.js';\nimport { isCancellationError, onUnexpectedError } from '../../../common/errors.js';\nimport { Emitter, Event } from '../../../common/event.js';\nimport { Iterable } from '../../../common/iterator.js';\nimport { DisposableStore, dispose } from '../../../common/lifecycle.js';\nimport { isIterable } from '../../../common/types.js';\nfunction createAsyncDataTreeNode(props) {\n return Object.assign(Object.assign({}, props), { children: [], refreshPromise: undefined, stale: true, slow: false, collapsedByDefault: undefined });\n}\nfunction isAncestor(ancestor, descendant) {\n if (!descendant.parent) {\n return false;\n }\n else if (descendant.parent === ancestor) {\n return true;\n }\n else {\n return isAncestor(ancestor, descendant.parent);\n }\n}\nfunction intersects(node, other) {\n return node === other || isAncestor(node, other) || isAncestor(other, node);\n}\nclass AsyncDataTreeNodeWrapper {\n constructor(node) {\n this.node = node;\n }\n get element() { return this.node.element.element; }\n get children() { return this.node.children.map(node => new AsyncDataTreeNodeWrapper(node)); }\n get depth() { return this.node.depth; }\n get visibleChildrenCount() { return this.node.visibleChildrenCount; }\n get visibleChildIndex() { return this.node.visibleChildIndex; }\n get collapsible() { return this.node.collapsible; }\n get collapsed() { return this.node.collapsed; }\n get visible() { return this.node.visible; }\n get filterData() { return this.node.filterData; }\n}\nclass AsyncDataTreeRenderer {\n constructor(renderer, nodeMapper, onDidChangeTwistieState) {\n this.renderer = renderer;\n this.nodeMapper = nodeMapper;\n this.onDidChangeTwistieState = onDidChangeTwistieState;\n this.renderedNodes = new Map();\n this.templateId = renderer.templateId;\n }\n renderTemplate(container) {\n const templateData = this.renderer.renderTemplate(container);\n return { templateData };\n }\n renderElement(node, index, templateData, height) {\n this.renderer.renderElement(this.nodeMapper.map(node), index, templateData.templateData, height);\n }\n renderTwistie(element, twistieElement) {\n if (element.slow) {\n twistieElement.classList.add(...Codicon.treeItemLoading.classNamesArray);\n return true;\n }\n else {\n twistieElement.classList.remove(...Codicon.treeItemLoading.classNamesArray);\n return false;\n }\n }\n disposeElement(node, index, templateData, height) {\n var _a, _b;\n (_b = (_a = this.renderer).disposeElement) === null || _b === void 0 ? void 0 : _b.call(_a, this.nodeMapper.map(node), index, templateData.templateData, height);\n }\n disposeTemplate(templateData) {\n this.renderer.disposeTemplate(templateData.templateData);\n }\n dispose() {\n this.renderedNodes.clear();\n }\n}\nfunction asTreeEvent(e) {\n return {\n browserEvent: e.browserEvent,\n elements: e.elements.map(e => e.element)\n };\n}\nfunction asTreeMouseEvent(e) {\n return {\n browserEvent: e.browserEvent,\n element: e.element && e.element.element,\n target: e.target\n };\n}\nclass AsyncDataTreeElementsDragAndDropData extends ElementsDragAndDropData {\n constructor(data) {\n super(data.elements.map(node => node.element));\n this.data = data;\n }\n}\nfunction asAsyncDataTreeDragAndDropData(data) {\n if (data instanceof ElementsDragAndDropData) {\n return new AsyncDataTreeElementsDragAndDropData(data);\n }\n return data;\n}\nclass AsyncDataTreeNodeListDragAndDrop {\n constructor(dnd) {\n this.dnd = dnd;\n }\n getDragURI(node) {\n return this.dnd.getDragURI(node.element);\n }\n getDragLabel(nodes, originalEvent) {\n if (this.dnd.getDragLabel) {\n return this.dnd.getDragLabel(nodes.map(node => node.element), originalEvent);\n }\n return undefined;\n }\n onDragStart(data, originalEvent) {\n var _a, _b;\n (_b = (_a = this.dnd).onDragStart) === null || _b === void 0 ? void 0 : _b.call(_a, asAsyncDataTreeDragAndDropData(data), originalEvent);\n }\n onDragOver(data, targetNode, targetIndex, originalEvent, raw = true) {\n return this.dnd.onDragOver(asAsyncDataTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);\n }\n drop(data, targetNode, targetIndex, originalEvent) {\n this.dnd.drop(asAsyncDataTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);\n }\n onDragEnd(originalEvent) {\n var _a, _b;\n (_b = (_a = this.dnd).onDragEnd) === null || _b === void 0 ? void 0 : _b.call(_a, originalEvent);\n }\n}\nfunction asObjectTreeOptions(options) {\n return options && Object.assign(Object.assign({}, options), { collapseByDefault: true, identityProvider: options.identityProvider && {\n getId(el) {\n return options.identityProvider.getId(el.element);\n }\n }, dnd: options.dnd && new AsyncDataTreeNodeListDragAndDrop(options.dnd), multipleSelectionController: options.multipleSelectionController && {\n isSelectionSingleChangeEvent(e) {\n return options.multipleSelectionController.isSelectionSingleChangeEvent(Object.assign(Object.assign({}, e), { element: e.element }));\n },\n isSelectionRangeChangeEvent(e) {\n return options.multipleSelectionController.isSelectionRangeChangeEvent(Object.assign(Object.assign({}, e), { element: e.element }));\n }\n }, accessibilityProvider: options.accessibilityProvider && Object.assign(Object.assign({}, options.accessibilityProvider), { getPosInSet: undefined, getSetSize: undefined, getRole: options.accessibilityProvider.getRole ? (el) => {\n return options.accessibilityProvider.getRole(el.element);\n } : () => 'treeitem', isChecked: options.accessibilityProvider.isChecked ? (e) => {\n var _a;\n return !!((_a = options.accessibilityProvider) === null || _a === void 0 ? void 0 : _a.isChecked(e.element));\n } : undefined, getAriaLabel(e) {\n return options.accessibilityProvider.getAriaLabel(e.element);\n },\n getWidgetAriaLabel() {\n return options.accessibilityProvider.getWidgetAriaLabel();\n }, getWidgetRole: options.accessibilityProvider.getWidgetRole ? () => options.accessibilityProvider.getWidgetRole() : () => 'tree', getAriaLevel: options.accessibilityProvider.getAriaLevel && (node => {\n return options.accessibilityProvider.getAriaLevel(node.element);\n }), getActiveDescendantId: options.accessibilityProvider.getActiveDescendantId && (node => {\n return options.accessibilityProvider.getActiveDescendantId(node.element);\n }) }), filter: options.filter && {\n filter(e, parentVisibility) {\n return options.filter.filter(e.element, parentVisibility);\n }\n }, keyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && Object.assign(Object.assign({}, options.keyboardNavigationLabelProvider), { getKeyboardNavigationLabel(e) {\n return options.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(e.element);\n } }), sorter: undefined, expandOnlyOnTwistieClick: typeof options.expandOnlyOnTwistieClick === 'undefined' ? undefined : (typeof options.expandOnlyOnTwistieClick !== 'function' ? options.expandOnlyOnTwistieClick : (e => options.expandOnlyOnTwistieClick(e.element))), additionalScrollHeight: options.additionalScrollHeight });\n}\nfunction dfs(node, fn) {\n fn(node);\n node.children.forEach(child => dfs(child, fn));\n}\nexport class AsyncDataTree {\n constructor(user, container, delegate, renderers, dataSource, options = {}) {\n this.user = user;\n this.dataSource = dataSource;\n this.nodes = new Map();\n this.subTreeRefreshPromises = new Map();\n this.refreshPromises = new Map();\n this._onDidRender = new Emitter();\n this._onDidChangeNodeSlowState = new Emitter();\n this.nodeMapper = new WeakMapper(node => new AsyncDataTreeNodeWrapper(node));\n this.disposables = new DisposableStore();\n this.identityProvider = options.identityProvider;\n this.autoExpandSingleChildren = typeof options.autoExpandSingleChildren === 'undefined' ? false : options.autoExpandSingleChildren;\n this.sorter = options.sorter;\n this.collapseByDefault = options.collapseByDefault;\n this.tree = this.createTree(user, container, delegate, renderers, options);\n this.onDidChangeFindMode = this.tree.onDidChangeFindMode;\n this.root = createAsyncDataTreeNode({\n element: undefined,\n parent: null,\n hasChildren: true\n });\n if (this.identityProvider) {\n this.root = Object.assign(Object.assign({}, this.root), { id: null });\n }\n this.nodes.set(null, this.root);\n this.tree.onDidChangeCollapseState(this._onDidChangeCollapseState, this, this.disposables);\n }\n get onDidChangeFocus() { return Event.map(this.tree.onDidChangeFocus, asTreeEvent); }\n get onDidChangeSelection() { return Event.map(this.tree.onDidChangeSelection, asTreeEvent); }\n get onMouseDblClick() { return Event.map(this.tree.onMouseDblClick, asTreeMouseEvent); }\n get onPointer() { return Event.map(this.tree.onPointer, asTreeMouseEvent); }\n get onDidFocus() { return this.tree.onDidFocus; }\n get onDidChangeModel() { return this.tree.onDidChangeModel; }\n get onDidChangeCollapseState() { return this.tree.onDidChangeCollapseState; }\n get onDidChangeFindOpenState() { return this.tree.onDidChangeFindOpenState; }\n get onDidDispose() { return this.tree.onDidDispose; }\n createTree(user, container, delegate, renderers, options) {\n const objectTreeDelegate = new ComposedTreeDelegate(delegate);\n const objectTreeRenderers = renderers.map(r => new AsyncDataTreeRenderer(r, this.nodeMapper, this._onDidChangeNodeSlowState.event));\n const objectTreeOptions = asObjectTreeOptions(options) || {};\n return new ObjectTree(user, container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions);\n }\n updateOptions(options = {}) {\n this.tree.updateOptions(options);\n }\n // Widget\n getHTMLElement() {\n return this.tree.getHTMLElement();\n }\n get scrollTop() {\n return this.tree.scrollTop;\n }\n set scrollTop(scrollTop) {\n this.tree.scrollTop = scrollTop;\n }\n domFocus() {\n this.tree.domFocus();\n }\n layout(height, width) {\n this.tree.layout(height, width);\n }\n style(styles) {\n this.tree.style(styles);\n }\n // Model\n getInput() {\n return this.root.element;\n }\n setInput(input, viewState) {\n return __awaiter(this, void 0, void 0, function* () {\n this.refreshPromises.forEach(promise => promise.cancel());\n this.refreshPromises.clear();\n this.root.element = input;\n const viewStateContext = viewState && { viewState, focus: [], selection: [] };\n yield this._updateChildren(input, true, false, viewStateContext);\n if (viewStateContext) {\n this.tree.setFocus(viewStateContext.focus);\n this.tree.setSelection(viewStateContext.selection);\n }\n if (viewState && typeof viewState.scrollTop === 'number') {\n this.scrollTop = viewState.scrollTop;\n }\n });\n }\n _updateChildren(element = this.root.element, recursive = true, rerender = false, viewStateContext, options) {\n return __awaiter(this, void 0, void 0, function* () {\n if (typeof this.root.element === 'undefined') {\n throw new TreeError(this.user, 'Tree input not set');\n }\n if (this.root.refreshPromise) {\n yield this.root.refreshPromise;\n yield Event.toPromise(this._onDidRender.event);\n }\n const node = this.getDataNode(element);\n yield this.refreshAndRenderNode(node, recursive, viewStateContext, options);\n if (rerender) {\n try {\n this.tree.rerender(node);\n }\n catch (_a) {\n // missing nodes are fine, this could've resulted from\n // parallel refresh calls, removing `node` altogether\n }\n }\n });\n }\n // View\n rerender(element) {\n if (element === undefined || element === this.root.element) {\n this.tree.rerender();\n return;\n }\n const node = this.getDataNode(element);\n this.tree.rerender(node);\n }\n // Tree\n getNode(element = this.root.element) {\n const dataNode = this.getDataNode(element);\n const node = this.tree.getNode(dataNode === this.root ? null : dataNode);\n return this.nodeMapper.map(node);\n }\n collapse(element, recursive = false) {\n const node = this.getDataNode(element);\n return this.tree.collapse(node === this.root ? null : node, recursive);\n }\n expand(element, recursive = false) {\n return __awaiter(this, void 0, void 0, function* () {\n if (typeof this.root.element === 'undefined') {\n throw new TreeError(this.user, 'Tree input not set');\n }\n if (this.root.refreshPromise) {\n yield this.root.refreshPromise;\n yield Event.toPromise(this._onDidRender.event);\n }\n const node = this.getDataNode(element);\n if (this.tree.hasElement(node) && !this.tree.isCollapsible(node)) {\n return false;\n }\n if (node.refreshPromise) {\n yield this.root.refreshPromise;\n yield Event.toPromise(this._onDidRender.event);\n }\n if (node !== this.root && !node.refreshPromise && !this.tree.isCollapsed(node)) {\n return false;\n }\n const result = this.tree.expand(node === this.root ? null : node, recursive);\n if (node.refreshPromise) {\n yield this.root.refreshPromise;\n yield Event.toPromise(this._onDidRender.event);\n }\n return result;\n });\n }\n setSelection(elements, browserEvent) {\n const nodes = elements.map(e => this.getDataNode(e));\n this.tree.setSelection(nodes, browserEvent);\n }\n getSelection() {\n const nodes = this.tree.getSelection();\n return nodes.map(n => n.element);\n }\n setFocus(elements, browserEvent) {\n const nodes = elements.map(e => this.getDataNode(e));\n this.tree.setFocus(nodes, browserEvent);\n }\n getFocus() {\n const nodes = this.tree.getFocus();\n return nodes.map(n => n.element);\n }\n reveal(element, relativeTop) {\n this.tree.reveal(this.getDataNode(element), relativeTop);\n }\n // Tree navigation\n getParentElement(element) {\n const node = this.tree.getParentElement(this.getDataNode(element));\n return (node && node.element);\n }\n getFirstElementChild(element = this.root.element) {\n const dataNode = this.getDataNode(element);\n const node = this.tree.getFirstElementChild(dataNode === this.root ? null : dataNode);\n return (node && node.element);\n }\n // Implementation\n getDataNode(element) {\n const node = this.nodes.get((element === this.root.element ? null : element));\n if (!node) {\n throw new TreeError(this.user, `Data tree node not found: ${element}`);\n }\n return node;\n }\n refreshAndRenderNode(node, recursive, viewStateContext, options) {\n return __awaiter(this, void 0, void 0, function* () {\n yield this.refreshNode(node, recursive, viewStateContext);\n this.render(node, viewStateContext, options);\n });\n }\n refreshNode(node, recursive, viewStateContext) {\n return __awaiter(this, void 0, void 0, function* () {\n let result;\n this.subTreeRefreshPromises.forEach((refreshPromise, refreshNode) => {\n if (!result && intersects(refreshNode, node)) {\n result = refreshPromise.then(() => this.refreshNode(node, recursive, viewStateContext));\n }\n });\n if (result) {\n return result;\n }\n if (node !== this.root) {\n const treeNode = this.tree.getNode(node);\n if (treeNode.collapsed) {\n node.hasChildren = !!this.dataSource.hasChildren(node.element);\n node.stale = true;\n return;\n }\n }\n return this.doRefreshSubTree(node, recursive, viewStateContext);\n });\n }\n doRefreshSubTree(node, recursive, viewStateContext) {\n return __awaiter(this, void 0, void 0, function* () {\n let done;\n node.refreshPromise = new Promise(c => done = c);\n this.subTreeRefreshPromises.set(node, node.refreshPromise);\n node.refreshPromise.finally(() => {\n node.refreshPromise = undefined;\n this.subTreeRefreshPromises.delete(node);\n });\n try {\n const childrenToRefresh = yield this.doRefreshNode(node, recursive, viewStateContext);\n node.stale = false;\n yield Promises.settled(childrenToRefresh.map(child => this.doRefreshSubTree(child, recursive, viewStateContext)));\n }\n finally {\n done();\n }\n });\n }\n doRefreshNode(node, recursive, viewStateContext) {\n return __awaiter(this, void 0, void 0, function* () {\n node.hasChildren = !!this.dataSource.hasChildren(node.element);\n let childrenPromise;\n if (!node.hasChildren) {\n childrenPromise = Promise.resolve(Iterable.empty());\n }\n else {\n const children = this.doGetChildren(node);\n if (isIterable(children)) {\n childrenPromise = Promise.resolve(children);\n }\n else {\n const slowTimeout = timeout(800);\n slowTimeout.then(() => {\n node.slow = true;\n this._onDidChangeNodeSlowState.fire(node);\n }, _ => null);\n childrenPromise = children.finally(() => slowTimeout.cancel());\n }\n }\n try {\n const children = yield childrenPromise;\n return this.setChildren(node, children, recursive, viewStateContext);\n }\n catch (err) {\n if (node !== this.root && this.tree.hasElement(node)) {\n this.tree.collapse(node);\n }\n if (isCancellationError(err)) {\n return [];\n }\n throw err;\n }\n finally {\n if (node.slow) {\n node.slow = false;\n this._onDidChangeNodeSlowState.fire(node);\n }\n }\n });\n }\n doGetChildren(node) {\n let result = this.refreshPromises.get(node);\n if (result) {\n return result;\n }\n const children = this.dataSource.getChildren(node.element);\n if (isIterable(children)) {\n return this.processChildren(children);\n }\n else {\n result = createCancelablePromise(() => __awaiter(this, void 0, void 0, function* () { return this.processChildren(yield children); }));\n this.refreshPromises.set(node, result);\n return result.finally(() => { this.refreshPromises.delete(node); });\n }\n }\n _onDidChangeCollapseState({ node, deep }) {\n if (node.element === null) {\n return;\n }\n if (!node.collapsed && node.element.stale) {\n if (deep) {\n this.collapse(node.element.element);\n }\n else {\n this.refreshAndRenderNode(node.element, false)\n .catch(onUnexpectedError);\n }\n }\n }\n setChildren(node, childrenElementsIterable, recursive, viewStateContext) {\n const childrenElements = [...childrenElementsIterable];\n // perf: if the node was and still is a leaf, avoid all this hassle\n if (node.children.length === 0 && childrenElements.length === 0) {\n return [];\n }\n const nodesToForget = new Map();\n const childrenTreeNodesById = new Map();\n for (const child of node.children) {\n nodesToForget.set(child.element, child);\n if (this.identityProvider) {\n const collapsed = this.tree.isCollapsed(child);\n childrenTreeNodesById.set(child.id, { node: child, collapsed });\n }\n }\n const childrenToRefresh = [];\n const children = childrenElements.map(element => {\n const hasChildren = !!this.dataSource.hasChildren(element);\n if (!this.identityProvider) {\n const asyncDataTreeNode = createAsyncDataTreeNode({ element, parent: node, hasChildren });\n if (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) {\n asyncDataTreeNode.collapsedByDefault = false;\n childrenToRefresh.push(asyncDataTreeNode);\n }\n return asyncDataTreeNode;\n }\n const id = this.identityProvider.getId(element).toString();\n const result = childrenTreeNodesById.get(id);\n if (result) {\n const asyncDataTreeNode = result.node;\n nodesToForget.delete(asyncDataTreeNode.element);\n this.nodes.delete(asyncDataTreeNode.element);\n this.nodes.set(element, asyncDataTreeNode);\n asyncDataTreeNode.element = element;\n asyncDataTreeNode.hasChildren = hasChildren;\n if (recursive) {\n if (result.collapsed) {\n asyncDataTreeNode.children.forEach(node => dfs(node, node => this.nodes.delete(node.element)));\n asyncDataTreeNode.children.splice(0, asyncDataTreeNode.children.length);\n asyncDataTreeNode.stale = true;\n }\n else {\n childrenToRefresh.push(asyncDataTreeNode);\n }\n }\n else if (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) {\n asyncDataTreeNode.collapsedByDefault = false;\n childrenToRefresh.push(asyncDataTreeNode);\n }\n return asyncDataTreeNode;\n }\n const childAsyncDataTreeNode = createAsyncDataTreeNode({ element, parent: node, id, hasChildren });\n if (viewStateContext && viewStateContext.viewState.focus && viewStateContext.viewState.focus.indexOf(id) > -1) {\n viewStateContext.focus.push(childAsyncDataTreeNode);\n }\n if (viewStateContext && viewStateContext.viewState.selection && viewStateContext.viewState.selection.indexOf(id) > -1) {\n viewStateContext.selection.push(childAsyncDataTreeNode);\n }\n if (viewStateContext && viewStateContext.viewState.expanded && viewStateContext.viewState.expanded.indexOf(id) > -1) {\n childrenToRefresh.push(childAsyncDataTreeNode);\n }\n else if (hasChildren && this.collapseByDefault && !this.collapseByDefault(element)) {\n childAsyncDataTreeNode.collapsedByDefault = false;\n childrenToRefresh.push(childAsyncDataTreeNode);\n }\n return childAsyncDataTreeNode;\n });\n for (const node of nodesToForget.values()) {\n dfs(node, node => this.nodes.delete(node.element));\n }\n for (const child of children) {\n this.nodes.set(child.element, child);\n }\n node.children.splice(0, node.children.length, ...children);\n // TODO@joao this doesn't take filter into account\n if (node !== this.root && this.autoExpandSingleChildren && children.length === 1 && childrenToRefresh.length === 0) {\n children[0].collapsedByDefault = false;\n childrenToRefresh.push(children[0]);\n }\n return childrenToRefresh;\n }\n render(node, viewStateContext, options) {\n const children = node.children.map(node => this.asTreeElement(node, viewStateContext));\n const objectTreeOptions = options && Object.assign(Object.assign({}, options), { diffIdentityProvider: options.diffIdentityProvider && {\n getId(node) {\n return options.diffIdentityProvider.getId(node.element);\n }\n } });\n this.tree.setChildren(node === this.root ? null : node, children, objectTreeOptions);\n if (node !== this.root) {\n this.tree.setCollapsible(node, node.hasChildren);\n }\n this._onDidRender.fire();\n }\n asTreeElement(node, viewStateContext) {\n if (node.stale) {\n return {\n element: node,\n collapsible: node.hasChildren,\n collapsed: true\n };\n }\n let collapsed;\n if (viewStateContext && viewStateContext.viewState.expanded && node.id && viewStateContext.viewState.expanded.indexOf(node.id) > -1) {\n collapsed = false;\n }\n else {\n collapsed = node.collapsedByDefault;\n }\n node.collapsedByDefault = undefined;\n return {\n element: node,\n children: node.hasChildren ? Iterable.map(node.children, child => this.asTreeElement(child, viewStateContext)) : [],\n collapsible: node.hasChildren,\n collapsed\n };\n }\n processChildren(children) {\n if (this.sorter) {\n children = [...children].sort(this.sorter.compare.bind(this.sorter));\n }\n return children;\n }\n dispose() {\n this.disposables.dispose();\n }\n}\nclass CompressibleAsyncDataTreeNodeWrapper {\n constructor(node) {\n this.node = node;\n }\n get element() {\n return {\n elements: this.node.element.elements.map(e => e.element),\n incompressible: this.node.element.incompressible\n };\n }\n get children() { return this.node.children.map(node => new CompressibleAsyncDataTreeNodeWrapper(node)); }\n get depth() { return this.node.depth; }\n get visibleChildrenCount() { return this.node.visibleChildrenCount; }\n get visibleChildIndex() { return this.node.visibleChildIndex; }\n get collapsible() { return this.node.collapsible; }\n get collapsed() { return this.node.collapsed; }\n get visible() { return this.node.visible; }\n get filterData() { return this.node.filterData; }\n}\nclass CompressibleAsyncDataTreeRenderer {\n constructor(renderer, nodeMapper, compressibleNodeMapperProvider, onDidChangeTwistieState) {\n this.renderer = renderer;\n this.nodeMapper = nodeMapper;\n this.compressibleNodeMapperProvider = compressibleNodeMapperProvider;\n this.onDidChangeTwistieState = onDidChangeTwistieState;\n this.renderedNodes = new Map();\n this.disposables = [];\n this.templateId = renderer.templateId;\n }\n renderTemplate(container) {\n const templateData = this.renderer.renderTemplate(container);\n return { templateData };\n }\n renderElement(node, index, templateData, height) {\n this.renderer.renderElement(this.nodeMapper.map(node), index, templateData.templateData, height);\n }\n renderCompressedElements(node, index, templateData, height) {\n this.renderer.renderCompressedElements(this.compressibleNodeMapperProvider().map(node), index, templateData.templateData, height);\n }\n renderTwistie(element, twistieElement) {\n if (element.slow) {\n twistieElement.classList.add(...Codicon.treeItemLoading.classNamesArray);\n return true;\n }\n else {\n twistieElement.classList.remove(...Codicon.treeItemLoading.classNamesArray);\n return false;\n }\n }\n disposeElement(node, index, templateData, height) {\n var _a, _b;\n (_b = (_a = this.renderer).disposeElement) === null || _b === void 0 ? void 0 : _b.call(_a, this.nodeMapper.map(node), index, templateData.templateData, height);\n }\n disposeCompressedElements(node, index, templateData, height) {\n var _a, _b;\n (_b = (_a = this.renderer).disposeCompressedElements) === null || _b === void 0 ? void 0 : _b.call(_a, this.compressibleNodeMapperProvider().map(node), index, templateData.templateData, height);\n }\n disposeTemplate(templateData) {\n this.renderer.disposeTemplate(templateData.templateData);\n }\n dispose() {\n this.renderedNodes.clear();\n this.disposables = dispose(this.disposables);\n }\n}\nfunction asCompressibleObjectTreeOptions(options) {\n const objectTreeOptions = options && asObjectTreeOptions(options);\n return objectTreeOptions && Object.assign(Object.assign({}, objectTreeOptions), { keyboardNavigationLabelProvider: objectTreeOptions.keyboardNavigationLabelProvider && Object.assign(Object.assign({}, objectTreeOptions.keyboardNavigationLabelProvider), { getCompressedNodeKeyboardNavigationLabel(els) {\n return options.keyboardNavigationLabelProvider.getCompressedNodeKeyboardNavigationLabel(els.map(e => e.element));\n } }) });\n}\nexport class CompressibleAsyncDataTree extends AsyncDataTree {\n constructor(user, container, virtualDelegate, compressionDelegate, renderers, dataSource, options = {}) {\n super(user, container, virtualDelegate, renderers, dataSource, options);\n this.compressionDelegate = compressionDelegate;\n this.compressibleNodeMapper = new WeakMapper(node => new CompressibleAsyncDataTreeNodeWrapper(node));\n this.filter = options.filter;\n }\n createTree(user, container, delegate, renderers, options) {\n const objectTreeDelegate = new ComposedTreeDelegate(delegate);\n const objectTreeRenderers = renderers.map(r => new CompressibleAsyncDataTreeRenderer(r, this.nodeMapper, () => this.compressibleNodeMapper, this._onDidChangeNodeSlowState.event));\n const objectTreeOptions = asCompressibleObjectTreeOptions(options) || {};\n return new CompressibleObjectTree(user, container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions);\n }\n asTreeElement(node, viewStateContext) {\n return Object.assign({ incompressible: this.compressionDelegate.isIncompressible(node.element) }, super.asTreeElement(node, viewStateContext));\n }\n updateOptions(options = {}) {\n this.tree.updateOptions(options);\n }\n render(node, viewStateContext) {\n if (!this.identityProvider) {\n return super.render(node, viewStateContext);\n }\n // Preserve traits across compressions. Hacky but does the trick.\n // This is hard to fix properly since it requires rewriting the traits\n // across trees and lists. Let's just keep it this way for now.\n const getId = (element) => this.identityProvider.getId(element).toString();\n const getUncompressedIds = (nodes) => {\n const result = new Set();\n for (const node of nodes) {\n const compressedNode = this.tree.getCompressedTreeNode(node === this.root ? null : node);\n if (!compressedNode.element) {\n continue;\n }\n for (const node of compressedNode.element.elements) {\n result.add(getId(node.element));\n }\n }\n return result;\n };\n const oldSelection = getUncompressedIds(this.tree.getSelection());\n const oldFocus = getUncompressedIds(this.tree.getFocus());\n super.render(node, viewStateContext);\n const selection = this.getSelection();\n let didChangeSelection = false;\n const focus = this.getFocus();\n let didChangeFocus = false;\n const visit = (node) => {\n const compressedNode = node.element;\n if (compressedNode) {\n for (let i = 0; i < compressedNode.elements.length; i++) {\n const id = getId(compressedNode.elements[i].element);\n const element = compressedNode.elements[compressedNode.elements.length - 1].element;\n // github.com/microsoft/vscode/issues/85938\n if (oldSelection.has(id) && selection.indexOf(element) === -1) {\n selection.push(element);\n didChangeSelection = true;\n }\n if (oldFocus.has(id) && focus.indexOf(element) === -1) {\n focus.push(element);\n didChangeFocus = true;\n }\n }\n }\n node.children.forEach(visit);\n };\n visit(this.tree.getCompressedTreeNode(node === this.root ? null : node));\n if (didChangeSelection) {\n this.setSelection(selection);\n }\n if (didChangeFocus) {\n this.setFocus(focus);\n }\n }\n // For compressed async data trees, `TreeVisibility.Recurse` doesn't currently work\n // and we have to filter everything beforehand\n // Related to #85193 and #85835\n processChildren(children) {\n if (this.filter) {\n children = Iterable.filter(children, e => {\n const result = this.filter.filter(e, 1 /* TreeVisibility.Visible */);\n const visibility = getVisibility(result);\n if (visibility === 2 /* TreeVisibility.Recurse */) {\n throw new Error('Recursive tree visibility not supported in async data compressed trees');\n }\n return visibility === 1 /* TreeVisibility.Visible */;\n });\n }\n return super.processChildren(children);\n }\n}\nfunction getVisibility(filterResult) {\n if (typeof filterResult === 'boolean') {\n return filterResult ? 1 /* TreeVisibility.Visible */ : 0 /* TreeVisibility.Hidden */;\n }\n else if (isFilterResult(filterResult)) {\n return getVisibleState(filterResult.visibility);\n }\n else {\n return getVisibleState(filterResult);\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 *--------------------------------------------------------------------------------------------*/\nimport { AbstractTree } from './abstractTree.js';\nimport { ObjectTreeModel } from './objectTreeModel.js';\nexport class DataTree extends AbstractTree {\n constructor(user, container, delegate, renderers, dataSource, options = {}) {\n super(user, container, delegate, renderers, options);\n this.user = user;\n this.dataSource = dataSource;\n this.identityProvider = options.identityProvider;\n }\n createModel(user, view, options) {\n return new ObjectTreeModel(user, view, options);\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 *--------------------------------------------------------------------------------------------*/\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nimport { createStyleSheet } from '../../../base/browser/dom.js';\nimport { PagedList } from '../../../base/browser/ui/list/listPaging.js';\nimport { DefaultStyleController, isSelectionRangeChangeEvent, isSelectionSingleChangeEvent, List, TypeNavigationMode } from '../../../base/browser/ui/list/listWidget.js';\nimport { Table } from '../../../base/browser/ui/table/tableWidget.js';\nimport { TreeFindMode } from '../../../base/browser/ui/tree/abstractTree.js';\nimport { AsyncDataTree, CompressibleAsyncDataTree } from '../../../base/browser/ui/tree/asyncDataTree.js';\nimport { DataTree } from '../../../base/browser/ui/tree/dataTree.js';\nimport { CompressibleObjectTree, ObjectTree } from '../../../base/browser/ui/tree/objectTree.js';\nimport { Emitter, Event } from '../../../base/common/event.js';\nimport { combinedDisposable, Disposable, DisposableStore, dispose, toDisposable } from '../../../base/common/lifecycle.js';\nimport { localize } from '../../../nls.js';\nimport { IConfigurationService } from '../../configuration/common/configuration.js';\nimport { Extensions as ConfigurationExtensions } from '../../configuration/common/configurationRegistry.js';\nimport { ContextKeyExpr, IContextKeyService, RawContextKey } from '../../contextkey/common/contextkey.js';\nimport { InputFocusedContextKey } from '../../contextkey/common/contextkeys.js';\nimport { IContextViewService } from '../../contextview/browser/contextView.js';\nimport { createDecorator, IInstantiationService } from '../../instantiation/common/instantiation.js';\nimport { IKeybindingService } from '../../keybinding/common/keybinding.js';\nimport { Registry } from '../../registry/common/platform.js';\nimport { attachListStyler, computeStyles, defaultListStyles } from '../../theme/common/styler.js';\nimport { IThemeService } from '../../theme/common/themeService.js';\nexport const IListService = createDecorator('listService');\nlet ListService = class ListService {\n constructor(_themeService) {\n this._themeService = _themeService;\n this.disposables = new DisposableStore();\n this.lists = [];\n this._lastFocusedWidget = undefined;\n this._hasCreatedStyleController = false;\n }\n get lastFocusedList() {\n return this._lastFocusedWidget;\n }\n setLastFocusedList(widget) {\n var _a, _b;\n if (widget === this._lastFocusedWidget) {\n return;\n }\n (_a = this._lastFocusedWidget) === null || _a === void 0 ? void 0 : _a.getHTMLElement().classList.remove('last-focused');\n this._lastFocusedWidget = widget;\n (_b = this._lastFocusedWidget) === null || _b === void 0 ? void 0 : _b.getHTMLElement().classList.add('last-focused');\n }\n register(widget, extraContextKeys) {\n if (!this._hasCreatedStyleController) {\n this._hasCreatedStyleController = true;\n // create a shared default tree style sheet for performance reasons\n const styleController = new DefaultStyleController(createStyleSheet(), '');\n this.disposables.add(attachListStyler(styleController, this._themeService));\n }\n if (this.lists.some(l => l.widget === widget)) {\n throw new Error('Cannot register the same widget multiple times');\n }\n // Keep in our lists list\n const registeredList = { widget, extraContextKeys };\n this.lists.push(registeredList);\n // Check for currently being focused\n if (widget.getHTMLElement() === document.activeElement) {\n this.setLastFocusedList(widget);\n }\n return combinedDisposable(widget.onDidFocus(() => this.setLastFocusedList(widget)), toDisposable(() => this.lists.splice(this.lists.indexOf(registeredList), 1)), widget.onDidDispose(() => {\n this.lists = this.lists.filter(l => l !== registeredList);\n if (this._lastFocusedWidget === widget) {\n this.setLastFocusedList(undefined);\n }\n }));\n }\n dispose() {\n this.disposables.dispose();\n }\n};\nListService = __decorate([\n __param(0, IThemeService)\n], ListService);\nexport { ListService };\nexport const RawWorkbenchListFocusContextKey = new RawContextKey('listFocus', true);\nexport const WorkbenchListSupportsMultiSelectContextKey = new RawContextKey('listSupportsMultiselect', true);\nexport const WorkbenchListFocusContextKey = ContextKeyExpr.and(RawWorkbenchListFocusContextKey, ContextKeyExpr.not(InputFocusedContextKey));\nexport const WorkbenchListHasSelectionOrFocus = new RawContextKey('listHasSelectionOrFocus', false);\nexport const WorkbenchListDoubleSelection = new RawContextKey('listDoubleSelection', false);\nexport const WorkbenchListMultiSelection = new RawContextKey('listMultiSelection', false);\nexport const WorkbenchListSelectionNavigation = new RawContextKey('listSelectionNavigation', false);\nexport const WorkbenchListSupportsFind = new RawContextKey('listSupportsFind', true);\nexport const WorkbenchTreeElementCanCollapse = new RawContextKey('treeElementCanCollapse', false);\nexport const WorkbenchTreeElementHasParent = new RawContextKey('treeElementHasParent', false);\nexport const WorkbenchTreeElementCanExpand = new RawContextKey('treeElementCanExpand', false);\nexport const WorkbenchTreeElementHasChild = new RawContextKey('treeElementHasChild', false);\nexport const WorkbenchTreeFindOpen = new RawContextKey('treeFindOpen', false);\nconst WorkbenchListTypeNavigationModeKey = 'listTypeNavigationMode';\n/**\n * @deprecated in favor of WorkbenchListTypeNavigationModeKey\n */\nconst WorkbenchListAutomaticKeyboardNavigationLegacyKey = 'listAutomaticKeyboardNavigation';\nfunction createScopedContextKeyService(contextKeyService, widget) {\n const result = contextKeyService.createScoped(widget.getHTMLElement());\n RawWorkbenchListFocusContextKey.bindTo(result);\n return result;\n}\nconst multiSelectModifierSettingKey = 'workbench.list.multiSelectModifier';\nconst openModeSettingKey = 'workbench.list.openMode';\nconst horizontalScrollingKey = 'workbench.list.horizontalScrolling';\nconst defaultFindModeSettingKey = 'workbench.list.defaultFindMode';\n/** @deprecated in favor of workbench.list.defaultFindMode */\nconst keyboardNavigationSettingKey = 'workbench.list.keyboardNavigation';\nconst treeIndentKey = 'workbench.tree.indent';\nconst treeRenderIndentGuidesKey = 'workbench.tree.renderIndentGuides';\nconst listSmoothScrolling = 'workbench.list.smoothScrolling';\nconst mouseWheelScrollSensitivityKey = 'workbench.list.mouseWheelScrollSensitivity';\nconst fastScrollSensitivityKey = 'workbench.list.fastScrollSensitivity';\nconst treeExpandMode = 'workbench.tree.expandMode';\nfunction useAltAsMultipleSelectionModifier(configurationService) {\n return configurationService.getValue(multiSelectModifierSettingKey) === 'alt';\n}\nclass MultipleSelectionController extends Disposable {\n constructor(configurationService) {\n super();\n this.configurationService = configurationService;\n this.useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);\n this.registerListeners();\n }\n registerListeners() {\n this._register(this.configurationService.onDidChangeConfiguration(e => {\n if (e.affectsConfiguration(multiSelectModifierSettingKey)) {\n this.useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(this.configurationService);\n }\n }));\n }\n isSelectionSingleChangeEvent(event) {\n if (this.useAltAsMultipleSelectionModifier) {\n return event.browserEvent.altKey;\n }\n return isSelectionSingleChangeEvent(event);\n }\n isSelectionRangeChangeEvent(event) {\n return isSelectionRangeChangeEvent(event);\n }\n}\nfunction toWorkbenchListOptions(accessor, options) {\n var _a;\n const configurationService = accessor.get(IConfigurationService);\n const keybindingService = accessor.get(IKeybindingService);\n const disposables = new DisposableStore();\n const result = Object.assign(Object.assign({}, options), { keyboardNavigationDelegate: { mightProducePrintableCharacter(e) { return keybindingService.mightProducePrintableCharacter(e); } }, smoothScrolling: Boolean(configurationService.getValue(listSmoothScrolling)), mouseWheelScrollSensitivity: configurationService.getValue(mouseWheelScrollSensitivityKey), fastScrollSensitivity: configurationService.getValue(fastScrollSensitivityKey), multipleSelectionController: (_a = options.multipleSelectionController) !== null && _a !== void 0 ? _a : disposables.add(new MultipleSelectionController(configurationService)), keyboardNavigationEventFilter: createKeyboardNavigationEventFilter(keybindingService) });\n return [result, disposables];\n}\nlet WorkbenchList = class WorkbenchList extends List {\n constructor(user, container, delegate, renderers, options, contextKeyService, listService, themeService, configurationService, instantiationService) {\n const horizontalScrolling = typeof options.horizontalScrolling !== 'undefined' ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));\n const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);\n super(user, container, delegate, renderers, Object.assign(Object.assign(Object.assign({ keyboardSupport: false }, computeStyles(themeService.getColorTheme(), defaultListStyles)), workbenchListOptions), { horizontalScrolling }));\n this.disposables.add(workbenchListOptionsDisposable);\n this.contextKeyService = createScopedContextKeyService(contextKeyService, this);\n this.themeService = themeService;\n this.listSupportsMultiSelect = WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService);\n this.listSupportsMultiSelect.set(options.multipleSelectionSupport !== false);\n const listSelectionNavigation = WorkbenchListSelectionNavigation.bindTo(this.contextKeyService);\n listSelectionNavigation.set(Boolean(options.selectionNavigation));\n this.listHasSelectionOrFocus = WorkbenchListHasSelectionOrFocus.bindTo(this.contextKeyService);\n this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService);\n this.listMultiSelection = WorkbenchListMultiSelection.bindTo(this.contextKeyService);\n this.horizontalScrolling = options.horizontalScrolling;\n this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);\n this.disposables.add(this.contextKeyService);\n this.disposables.add(listService.register(this));\n if (options.overrideStyles) {\n this.updateStyles(options.overrideStyles);\n }\n this.disposables.add(this.onDidChangeSelection(() => {\n const selection = this.getSelection();\n const focus = this.getFocus();\n this.contextKeyService.bufferChangeEvents(() => {\n this.listHasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);\n this.listMultiSelection.set(selection.length > 1);\n this.listDoubleSelection.set(selection.length === 2);\n });\n }));\n this.disposables.add(this.onDidChangeFocus(() => {\n const selection = this.getSelection();\n const focus = this.getFocus();\n this.listHasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);\n }));\n this.disposables.add(configurationService.onDidChangeConfiguration(e => {\n if (e.affectsConfiguration(multiSelectModifierSettingKey)) {\n this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);\n }\n let options = {};\n if (e.affectsConfiguration(horizontalScrollingKey) && this.horizontalScrolling === undefined) {\n const horizontalScrolling = Boolean(configurationService.getValue(horizontalScrollingKey));\n options = Object.assign(Object.assign({}, options), { horizontalScrolling });\n }\n if (e.affectsConfiguration(listSmoothScrolling)) {\n const smoothScrolling = Boolean(configurationService.getValue(listSmoothScrolling));\n options = Object.assign(Object.assign({}, options), { smoothScrolling });\n }\n if (e.affectsConfiguration(mouseWheelScrollSensitivityKey)) {\n const mouseWheelScrollSensitivity = configurationService.getValue(mouseWheelScrollSensitivityKey);\n options = Object.assign(Object.assign({}, options), { mouseWheelScrollSensitivity });\n }\n if (e.affectsConfiguration(fastScrollSensitivityKey)) {\n const fastScrollSensitivity = configurationService.getValue(fastScrollSensitivityKey);\n options = Object.assign(Object.assign({}, options), { fastScrollSensitivity });\n }\n if (Object.keys(options).length > 0) {\n this.updateOptions(options);\n }\n }));\n this.navigator = new ListResourceNavigator(this, Object.assign({ configurationService }, options));\n this.disposables.add(this.navigator);\n }\n updateOptions(options) {\n super.updateOptions(options);\n if (options.overrideStyles) {\n this.updateStyles(options.overrideStyles);\n }\n if (options.multipleSelectionSupport !== undefined) {\n this.listSupportsMultiSelect.set(!!options.multipleSelectionSupport);\n }\n }\n updateStyles(styles) {\n var _a;\n (_a = this._styler) === null || _a === void 0 ? void 0 : _a.dispose();\n this._styler = attachListStyler(this, this.themeService, styles);\n }\n dispose() {\n var _a;\n (_a = this._styler) === null || _a === void 0 ? void 0 : _a.dispose();\n super.dispose();\n }\n};\nWorkbenchList = __decorate([\n __param(5, IContextKeyService),\n __param(6, IListService),\n __param(7, IThemeService),\n __param(8, IConfigurationService),\n __param(9, IInstantiationService)\n], WorkbenchList);\nexport { WorkbenchList };\nlet WorkbenchPagedList = class WorkbenchPagedList extends PagedList {\n constructor(user, container, delegate, renderers, options, contextKeyService, listService, themeService, configurationService, instantiationService) {\n const horizontalScrolling = typeof options.horizontalScrolling !== 'undefined' ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));\n const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);\n super(user, container, delegate, renderers, Object.assign(Object.assign(Object.assign({ keyboardSupport: false }, computeStyles(themeService.getColorTheme(), defaultListStyles)), workbenchListOptions), { horizontalScrolling }));\n this.disposables = new DisposableStore();\n this.disposables.add(workbenchListOptionsDisposable);\n this.contextKeyService = createScopedContextKeyService(contextKeyService, this);\n this.themeService = themeService;\n this.horizontalScrolling = options.horizontalScrolling;\n this.listSupportsMultiSelect = WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService);\n this.listSupportsMultiSelect.set(options.multipleSelectionSupport !== false);\n const listSelectionNavigation = WorkbenchListSelectionNavigation.bindTo(this.contextKeyService);\n listSelectionNavigation.set(Boolean(options.selectionNavigation));\n this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);\n this.disposables.add(this.contextKeyService);\n this.disposables.add(listService.register(this));\n if (options.overrideStyles) {\n this.updateStyles(options.overrideStyles);\n }\n if (options.overrideStyles) {\n this.disposables.add(attachListStyler(this, themeService, options.overrideStyles));\n }\n this.disposables.add(configurationService.onDidChangeConfiguration(e => {\n if (e.affectsConfiguration(multiSelectModifierSettingKey)) {\n this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);\n }\n let options = {};\n if (e.affectsConfiguration(horizontalScrollingKey) && this.horizontalScrolling === undefined) {\n const horizontalScrolling = Boolean(configurationService.getValue(horizontalScrollingKey));\n options = Object.assign(Object.assign({}, options), { horizontalScrolling });\n }\n if (e.affectsConfiguration(listSmoothScrolling)) {\n const smoothScrolling = Boolean(configurationService.getValue(listSmoothScrolling));\n options = Object.assign(Object.assign({}, options), { smoothScrolling });\n }\n if (e.affectsConfiguration(mouseWheelScrollSensitivityKey)) {\n const mouseWheelScrollSensitivity = configurationService.getValue(mouseWheelScrollSensitivityKey);\n options = Object.assign(Object.assign({}, options), { mouseWheelScrollSensitivity });\n }\n if (e.affectsConfiguration(fastScrollSensitivityKey)) {\n const fastScrollSensitivity = configurationService.getValue(fastScrollSensitivityKey);\n options = Object.assign(Object.assign({}, options), { fastScrollSensitivity });\n }\n if (Object.keys(options).length > 0) {\n this.updateOptions(options);\n }\n }));\n this.navigator = new ListResourceNavigator(this, Object.assign({ configurationService }, options));\n this.disposables.add(this.navigator);\n }\n updateOptions(options) {\n super.updateOptions(options);\n if (options.overrideStyles) {\n this.updateStyles(options.overrideStyles);\n }\n if (options.multipleSelectionSupport !== undefined) {\n this.listSupportsMultiSelect.set(!!options.multipleSelectionSupport);\n }\n }\n updateStyles(styles) {\n var _a;\n (_a = this._styler) === null || _a === void 0 ? void 0 : _a.dispose();\n this._styler = attachListStyler(this, this.themeService, styles);\n }\n dispose() {\n var _a;\n (_a = this._styler) === null || _a === void 0 ? void 0 : _a.dispose();\n this.disposables.dispose();\n super.dispose();\n }\n};\nWorkbenchPagedList = __decorate([\n __param(5, IContextKeyService),\n __param(6, IListService),\n __param(7, IThemeService),\n __param(8, IConfigurationService),\n __param(9, IInstantiationService)\n], WorkbenchPagedList);\nexport { WorkbenchPagedList };\nlet WorkbenchTable = class WorkbenchTable extends Table {\n constructor(user, container, delegate, columns, renderers, options, contextKeyService, listService, themeService, configurationService, instantiationService) {\n const horizontalScrolling = typeof options.horizontalScrolling !== 'undefined' ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));\n const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);\n super(user, container, delegate, columns, renderers, Object.assign(Object.assign(Object.assign({ keyboardSupport: false }, computeStyles(themeService.getColorTheme(), defaultListStyles)), workbenchListOptions), { horizontalScrolling }));\n this.disposables.add(workbenchListOptionsDisposable);\n this.contextKeyService = createScopedContextKeyService(contextKeyService, this);\n this.themeService = themeService;\n this.listSupportsMultiSelect = WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService);\n this.listSupportsMultiSelect.set(options.multipleSelectionSupport !== false);\n const listSelectionNavigation = WorkbenchListSelectionNavigation.bindTo(this.contextKeyService);\n listSelectionNavigation.set(Boolean(options.selectionNavigation));\n this.listHasSelectionOrFocus = WorkbenchListHasSelectionOrFocus.bindTo(this.contextKeyService);\n this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService);\n this.listMultiSelection = WorkbenchListMultiSelection.bindTo(this.contextKeyService);\n this.horizontalScrolling = options.horizontalScrolling;\n this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);\n this.disposables.add(this.contextKeyService);\n this.disposables.add(listService.register(this));\n if (options.overrideStyles) {\n this.updateStyles(options.overrideStyles);\n }\n this.disposables.add(this.onDidChangeSelection(() => {\n const selection = this.getSelection();\n const focus = this.getFocus();\n this.contextKeyService.bufferChangeEvents(() => {\n this.listHasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);\n this.listMultiSelection.set(selection.length > 1);\n this.listDoubleSelection.set(selection.length === 2);\n });\n }));\n this.disposables.add(this.onDidChangeFocus(() => {\n const selection = this.getSelection();\n const focus = this.getFocus();\n this.listHasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);\n }));\n this.disposables.add(configurationService.onDidChangeConfiguration(e => {\n if (e.affectsConfiguration(multiSelectModifierSettingKey)) {\n this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);\n }\n let options = {};\n if (e.affectsConfiguration(horizontalScrollingKey) && this.horizontalScrolling === undefined) {\n const horizontalScrolling = Boolean(configurationService.getValue(horizontalScrollingKey));\n options = Object.assign(Object.assign({}, options), { horizontalScrolling });\n }\n if (e.affectsConfiguration(listSmoothScrolling)) {\n const smoothScrolling = Boolean(configurationService.getValue(listSmoothScrolling));\n options = Object.assign(Object.assign({}, options), { smoothScrolling });\n }\n if (e.affectsConfiguration(mouseWheelScrollSensitivityKey)) {\n const mouseWheelScrollSensitivity = configurationService.getValue(mouseWheelScrollSensitivityKey);\n options = Object.assign(Object.assign({}, options), { mouseWheelScrollSensitivity });\n }\n if (e.affectsConfiguration(fastScrollSensitivityKey)) {\n const fastScrollSensitivity = configurationService.getValue(fastScrollSensitivityKey);\n options = Object.assign(Object.assign({}, options), { fastScrollSensitivity });\n }\n if (Object.keys(options).length > 0) {\n this.updateOptions(options);\n }\n }));\n this.navigator = new TableResourceNavigator(this, Object.assign({ configurationService }, options));\n this.disposables.add(this.navigator);\n }\n updateOptions(options) {\n super.updateOptions(options);\n if (options.overrideStyles) {\n this.updateStyles(options.overrideStyles);\n }\n if (options.multipleSelectionSupport !== undefined) {\n this.listSupportsMultiSelect.set(!!options.multipleSelectionSupport);\n }\n }\n updateStyles(styles) {\n var _a;\n (_a = this._styler) === null || _a === void 0 ? void 0 : _a.dispose();\n this._styler = attachListStyler(this, this.themeService, styles);\n }\n dispose() {\n var _a;\n (_a = this._styler) === null || _a === void 0 ? void 0 : _a.dispose();\n this.disposables.dispose();\n super.dispose();\n }\n};\nWorkbenchTable = __decorate([\n __param(6, IContextKeyService),\n __param(7, IListService),\n __param(8, IThemeService),\n __param(9, IConfigurationService),\n __param(10, IInstantiationService)\n], WorkbenchTable);\nexport { WorkbenchTable };\nclass ResourceNavigator extends Disposable {\n constructor(widget, options) {\n var _a;\n super();\n this.widget = widget;\n this._onDidOpen = this._register(new Emitter());\n this.onDidOpen = this._onDidOpen.event;\n this._register(Event.filter(this.widget.onDidChangeSelection, e => e.browserEvent instanceof KeyboardEvent)(e => this.onSelectionFromKeyboard(e)));\n this._register(this.widget.onPointer((e) => this.onPointer(e.element, e.browserEvent)));\n this._register(this.widget.onMouseDblClick((e) => this.onMouseDblClick(e.element, e.browserEvent)));\n if (typeof (options === null || options === void 0 ? void 0 : options.openOnSingleClick) !== 'boolean' && (options === null || options === void 0 ? void 0 : options.configurationService)) {\n this.openOnSingleClick = (options === null || options === void 0 ? void 0 : options.configurationService.getValue(openModeSettingKey)) !== 'doubleClick';\n this._register(options === null || options === void 0 ? void 0 : options.configurationService.onDidChangeConfiguration(() => {\n this.openOnSingleClick = (options === null || options === void 0 ? void 0 : options.configurationService.getValue(openModeSettingKey)) !== 'doubleClick';\n }));\n }\n else {\n this.openOnSingleClick = (_a = options === null || options === void 0 ? void 0 : options.openOnSingleClick) !== null && _a !== void 0 ? _a : true;\n }\n }\n onSelectionFromKeyboard(event) {\n if (event.elements.length !== 1) {\n return;\n }\n const selectionKeyboardEvent = event.browserEvent;\n const preserveFocus = typeof selectionKeyboardEvent.preserveFocus === 'boolean' ? selectionKeyboardEvent.preserveFocus : true;\n const pinned = typeof selectionKeyboardEvent.pinned === 'boolean' ? selectionKeyboardEvent.pinned : !preserveFocus;\n const sideBySide = false;\n this._open(this.getSelectedElement(), preserveFocus, pinned, sideBySide, event.browserEvent);\n }\n onPointer(element, browserEvent) {\n if (!this.openOnSingleClick) {\n return;\n }\n const isDoubleClick = browserEvent.detail === 2;\n if (isDoubleClick) {\n return;\n }\n const isMiddleClick = browserEvent.button === 1;\n const preserveFocus = true;\n const pinned = isMiddleClick;\n const sideBySide = browserEvent.ctrlKey || browserEvent.metaKey || browserEvent.altKey;\n this._open(element, preserveFocus, pinned, sideBySide, browserEvent);\n }\n onMouseDblClick(element, browserEvent) {\n if (!browserEvent) {\n return;\n }\n // copied from AbstractTree\n const target = browserEvent.target;\n const onTwistie = target.classList.contains('monaco-tl-twistie')\n || (target.classList.contains('monaco-icon-label') && target.classList.contains('folder-icon') && browserEvent.offsetX < 16);\n if (onTwistie) {\n return;\n }\n const preserveFocus = false;\n const pinned = true;\n const sideBySide = (browserEvent.ctrlKey || browserEvent.metaKey || browserEvent.altKey);\n this._open(element, preserveFocus, pinned, sideBySide, browserEvent);\n }\n _open(element, preserveFocus, pinned, sideBySide, browserEvent) {\n if (!element) {\n return;\n }\n this._onDidOpen.fire({\n editorOptions: {\n preserveFocus,\n pinned,\n revealIfVisible: true\n },\n sideBySide,\n element,\n browserEvent\n });\n }\n}\nclass ListResourceNavigator extends ResourceNavigator {\n constructor(widget, options) {\n super(widget, options);\n this.widget = widget;\n }\n getSelectedElement() {\n return this.widget.getSelectedElements()[0];\n }\n}\nclass TableResourceNavigator extends ResourceNavigator {\n constructor(widget, options) {\n super(widget, options);\n }\n getSelectedElement() {\n return this.widget.getSelectedElements()[0];\n }\n}\nclass TreeResourceNavigator extends ResourceNavigator {\n constructor(widget, options) {\n super(widget, options);\n }\n getSelectedElement() {\n var _a;\n return (_a = this.widget.getSelection()[0]) !== null && _a !== void 0 ? _a : undefined;\n }\n}\nfunction createKeyboardNavigationEventFilter(keybindingService) {\n let inChord = false;\n return event => {\n if (event.toKeybinding().isModifierKey()) {\n return false;\n }\n if (inChord) {\n inChord = false;\n return false;\n }\n const result = keybindingService.softDispatch(event, event.target);\n if (result === null || result === void 0 ? void 0 : result.enterChord) {\n inChord = true;\n return false;\n }\n inChord = false;\n return !result;\n };\n}\nlet WorkbenchObjectTree = class WorkbenchObjectTree extends ObjectTree {\n constructor(user, container, delegate, renderers, options, instantiationService, contextKeyService, listService, themeService, configurationService) {\n const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options);\n super(user, container, delegate, renderers, treeOptions);\n this.disposables.add(disposable);\n this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, themeService, configurationService);\n this.disposables.add(this.internals);\n }\n updateOptions(options) {\n super.updateOptions(options);\n this.internals.updateOptions(options);\n }\n};\nWorkbenchObjectTree = __decorate([\n __param(5, IInstantiationService),\n __param(6, IContextKeyService),\n __param(7, IListService),\n __param(8, IThemeService),\n __param(9, IConfigurationService)\n], WorkbenchObjectTree);\nexport { WorkbenchObjectTree };\nlet WorkbenchCompressibleObjectTree = class WorkbenchCompressibleObjectTree extends CompressibleObjectTree {\n constructor(user, container, delegate, renderers, options, instantiationService, contextKeyService, listService, themeService, configurationService) {\n const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options);\n super(user, container, delegate, renderers, treeOptions);\n this.disposables.add(disposable);\n this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, themeService, configurationService);\n this.disposables.add(this.internals);\n }\n updateOptions(options = {}) {\n super.updateOptions(options);\n if (options.overrideStyles) {\n this.internals.updateStyleOverrides(options.overrideStyles);\n }\n this.internals.updateOptions(options);\n }\n};\nWorkbenchCompressibleObjectTree = __decorate([\n __param(5, IInstantiationService),\n __param(6, IContextKeyService),\n __param(7, IListService),\n __param(8, IThemeService),\n __param(9, IConfigurationService)\n], WorkbenchCompressibleObjectTree);\nexport { WorkbenchCompressibleObjectTree };\nlet WorkbenchDataTree = class WorkbenchDataTree extends DataTree {\n constructor(user, container, delegate, renderers, dataSource, options, instantiationService, contextKeyService, listService, themeService, configurationService) {\n const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options);\n super(user, container, delegate, renderers, dataSource, treeOptions);\n this.disposables.add(disposable);\n this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, themeService, configurationService);\n this.disposables.add(this.internals);\n }\n updateOptions(options = {}) {\n super.updateOptions(options);\n if (options.overrideStyles) {\n this.internals.updateStyleOverrides(options.overrideStyles);\n }\n this.internals.updateOptions(options);\n }\n};\nWorkbenchDataTree = __decorate([\n __param(6, IInstantiationService),\n __param(7, IContextKeyService),\n __param(8, IListService),\n __param(9, IThemeService),\n __param(10, IConfigurationService)\n], WorkbenchDataTree);\nexport { WorkbenchDataTree };\nlet WorkbenchAsyncDataTree = class WorkbenchAsyncDataTree extends AsyncDataTree {\n constructor(user, container, delegate, renderers, dataSource, options, instantiationService, contextKeyService, listService, themeService, configurationService) {\n const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options);\n super(user, container, delegate, renderers, dataSource, treeOptions);\n this.disposables.add(disposable);\n this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, themeService, configurationService);\n this.disposables.add(this.internals);\n }\n get onDidOpen() { return this.internals.onDidOpen; }\n updateOptions(options = {}) {\n super.updateOptions(options);\n if (options.overrideStyles) {\n this.internals.updateStyleOverrides(options.overrideStyles);\n }\n this.internals.updateOptions(options);\n }\n};\nWorkbenchAsyncDataTree = __decorate([\n __param(6, IInstantiationService),\n __param(7, IContextKeyService),\n __param(8, IListService),\n __param(9, IThemeService),\n __param(10, IConfigurationService)\n], WorkbenchAsyncDataTree);\nexport { WorkbenchAsyncDataTree };\nlet WorkbenchCompressibleAsyncDataTree = class WorkbenchCompressibleAsyncDataTree extends CompressibleAsyncDataTree {\n constructor(user, container, virtualDelegate, compressionDelegate, renderers, dataSource, options, instantiationService, contextKeyService, listService, themeService, configurationService) {\n const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options);\n super(user, container, virtualDelegate, compressionDelegate, renderers, dataSource, treeOptions);\n this.disposables.add(disposable);\n this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, themeService, configurationService);\n this.disposables.add(this.internals);\n }\n updateOptions(options) {\n super.updateOptions(options);\n this.internals.updateOptions(options);\n }\n};\nWorkbenchCompressibleAsyncDataTree = __decorate([\n __param(7, IInstantiationService),\n __param(8, IContextKeyService),\n __param(9, IListService),\n __param(10, IThemeService),\n __param(11, IConfigurationService)\n], WorkbenchCompressibleAsyncDataTree);\nexport { WorkbenchCompressibleAsyncDataTree };\nfunction getDefaultTreeFindMode(configurationService) {\n const value = configurationService.getValue(defaultFindModeSettingKey);\n if (value === 'highlight') {\n return TreeFindMode.Highlight;\n }\n else if (value === 'filter') {\n return TreeFindMode.Filter;\n }\n const deprecatedValue = configurationService.getValue(keyboardNavigationSettingKey);\n if (deprecatedValue === 'simple' || deprecatedValue === 'highlight') {\n return TreeFindMode.Highlight;\n }\n else if (deprecatedValue === 'filter') {\n return TreeFindMode.Filter;\n }\n return undefined;\n}\nfunction workbenchTreeDataPreamble(accessor, options) {\n var _a;\n const configurationService = accessor.get(IConfigurationService);\n const contextViewService = accessor.get(IContextViewService);\n const contextKeyService = accessor.get(IContextKeyService);\n const instantiationService = accessor.get(IInstantiationService);\n const getTypeNavigationMode = () => {\n // give priority to the context key value to specify a value\n const modeString = contextKeyService.getContextKeyValue(WorkbenchListTypeNavigationModeKey);\n if (modeString === 'automatic') {\n return TypeNavigationMode.Automatic;\n }\n else if (modeString === 'trigger') {\n return TypeNavigationMode.Trigger;\n }\n // also check the deprecated context key to set the mode to 'trigger'\n const modeBoolean = contextKeyService.getContextKeyValue(WorkbenchListAutomaticKeyboardNavigationLegacyKey);\n if (modeBoolean === false) {\n return TypeNavigationMode.Trigger;\n }\n return undefined;\n };\n const horizontalScrolling = options.horizontalScrolling !== undefined ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));\n const [workbenchListOptions, disposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);\n const additionalScrollHeight = options.additionalScrollHeight;\n return {\n getTypeNavigationMode,\n disposable,\n options: Object.assign(Object.assign({ \n // ...options, // TODO@Joao why is this not splatted here?\n keyboardSupport: false }, workbenchListOptions), { indent: typeof configurationService.getValue(treeIndentKey) === 'number' ? configurationService.getValue(treeIndentKey) : undefined, renderIndentGuides: configurationService.getValue(treeRenderIndentGuidesKey), smoothScrolling: Boolean(configurationService.getValue(listSmoothScrolling)), defaultFindMode: getDefaultTreeFindMode(configurationService), horizontalScrolling,\n additionalScrollHeight, hideTwistiesOfChildlessElements: options.hideTwistiesOfChildlessElements, expandOnlyOnTwistieClick: (_a = options.expandOnlyOnTwistieClick) !== null && _a !== void 0 ? _a : (configurationService.getValue(treeExpandMode) === 'doubleClick'), contextViewProvider: contextViewService })\n };\n}\nlet WorkbenchTreeInternals = class WorkbenchTreeInternals {\n constructor(tree, options, getTypeNavigationMode, overrideStyles, contextKeyService, listService, themeService, configurationService) {\n var _a;\n this.tree = tree;\n this.themeService = themeService;\n this.disposables = [];\n this.contextKeyService = createScopedContextKeyService(contextKeyService, tree);\n this.listSupportsMultiSelect = WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService);\n this.listSupportsMultiSelect.set(options.multipleSelectionSupport !== false);\n const listSelectionNavigation = WorkbenchListSelectionNavigation.bindTo(this.contextKeyService);\n listSelectionNavigation.set(Boolean(options.selectionNavigation));\n this.listSupportFindWidget = WorkbenchListSupportsFind.bindTo(this.contextKeyService);\n this.listSupportFindWidget.set((_a = options.findWidgetEnabled) !== null && _a !== void 0 ? _a : true);\n this.hasSelectionOrFocus = WorkbenchListHasSelectionOrFocus.bindTo(this.contextKeyService);\n this.hasDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService);\n this.hasMultiSelection = WorkbenchListMultiSelection.bindTo(this.contextKeyService);\n this.treeElementCanCollapse = WorkbenchTreeElementCanCollapse.bindTo(this.contextKeyService);\n this.treeElementHasParent = WorkbenchTreeElementHasParent.bindTo(this.contextKeyService);\n this.treeElementCanExpand = WorkbenchTreeElementCanExpand.bindTo(this.contextKeyService);\n this.treeElementHasChild = WorkbenchTreeElementHasChild.bindTo(this.contextKeyService);\n this.treeFindOpen = WorkbenchTreeFindOpen.bindTo(this.contextKeyService);\n this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);\n this.updateStyleOverrides(overrideStyles);\n const updateCollapseContextKeys = () => {\n const focus = tree.getFocus()[0];\n if (!focus) {\n return;\n }\n const node = tree.getNode(focus);\n this.treeElementCanCollapse.set(node.collapsible && !node.collapsed);\n this.treeElementHasParent.set(!!tree.getParentElement(focus));\n this.treeElementCanExpand.set(node.collapsible && node.collapsed);\n this.treeElementHasChild.set(!!tree.getFirstElementChild(focus));\n };\n const interestingContextKeys = new Set();\n interestingContextKeys.add(WorkbenchListTypeNavigationModeKey);\n interestingContextKeys.add(WorkbenchListAutomaticKeyboardNavigationLegacyKey);\n this.disposables.push(this.contextKeyService, listService.register(tree), tree.onDidChangeSelection(() => {\n const selection = tree.getSelection();\n const focus = tree.getFocus();\n this.contextKeyService.bufferChangeEvents(() => {\n this.hasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);\n this.hasMultiSelection.set(selection.length > 1);\n this.hasDoubleSelection.set(selection.length === 2);\n });\n }), tree.onDidChangeFocus(() => {\n const selection = tree.getSelection();\n const focus = tree.getFocus();\n this.hasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);\n updateCollapseContextKeys();\n }), tree.onDidChangeCollapseState(updateCollapseContextKeys), tree.onDidChangeModel(updateCollapseContextKeys), tree.onDidChangeFindOpenState(enabled => this.treeFindOpen.set(enabled)), configurationService.onDidChangeConfiguration(e => {\n let newOptions = {};\n if (e.affectsConfiguration(multiSelectModifierSettingKey)) {\n this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);\n }\n if (e.affectsConfiguration(treeIndentKey)) {\n const indent = configurationService.getValue(treeIndentKey);\n newOptions = Object.assign(Object.assign({}, newOptions), { indent });\n }\n if (e.affectsConfiguration(treeRenderIndentGuidesKey)) {\n const renderIndentGuides = configurationService.getValue(treeRenderIndentGuidesKey);\n newOptions = Object.assign(Object.assign({}, newOptions), { renderIndentGuides });\n }\n if (e.affectsConfiguration(listSmoothScrolling)) {\n const smoothScrolling = Boolean(configurationService.getValue(listSmoothScrolling));\n newOptions = Object.assign(Object.assign({}, newOptions), { smoothScrolling });\n }\n if (e.affectsConfiguration(defaultFindModeSettingKey) || e.affectsConfiguration(keyboardNavigationSettingKey)) {\n tree.updateOptions({ defaultFindMode: getDefaultTreeFindMode(configurationService) });\n }\n if (e.affectsConfiguration(horizontalScrollingKey) && options.horizontalScrolling === undefined) {\n const horizontalScrolling = Boolean(configurationService.getValue(horizontalScrollingKey));\n newOptions = Object.assign(Object.assign({}, newOptions), { horizontalScrolling });\n }\n if (e.affectsConfiguration(treeExpandMode) && options.expandOnlyOnTwistieClick === undefined) {\n newOptions = Object.assign(Object.assign({}, newOptions), { expandOnlyOnTwistieClick: configurationService.getValue(treeExpandMode) === 'doubleClick' });\n }\n if (e.affectsConfiguration(mouseWheelScrollSensitivityKey)) {\n const mouseWheelScrollSensitivity = configurationService.getValue(mouseWheelScrollSensitivityKey);\n newOptions = Object.assign(Object.assign({}, newOptions), { mouseWheelScrollSensitivity });\n }\n if (e.affectsConfiguration(fastScrollSensitivityKey)) {\n const fastScrollSensitivity = configurationService.getValue(fastScrollSensitivityKey);\n newOptions = Object.assign(Object.assign({}, newOptions), { fastScrollSensitivity });\n }\n if (Object.keys(newOptions).length > 0) {\n tree.updateOptions(newOptions);\n }\n }), this.contextKeyService.onDidChangeContext(e => {\n if (e.affectsSome(interestingContextKeys)) {\n tree.updateOptions({ typeNavigationMode: getTypeNavigationMode() });\n }\n }));\n this.navigator = new TreeResourceNavigator(tree, Object.assign({ configurationService }, options));\n this.disposables.push(this.navigator);\n }\n get onDidOpen() { return this.navigator.onDidOpen; }\n updateOptions(options) {\n if (options.multipleSelectionSupport !== undefined) {\n this.listSupportsMultiSelect.set(!!options.multipleSelectionSupport);\n }\n }\n updateStyleOverrides(overrideStyles) {\n dispose(this.styler);\n this.styler = overrideStyles ? attachListStyler(this.tree, this.themeService, overrideStyles) : Disposable.None;\n }\n dispose() {\n this.disposables = dispose(this.disposables);\n dispose(this.styler);\n this.styler = undefined;\n }\n};\nWorkbenchTreeInternals = __decorate([\n __param(4, IContextKeyService),\n __param(5, IListService),\n __param(6, IThemeService),\n __param(7, IConfigurationService)\n], WorkbenchTreeInternals);\nconst configurationRegistry = Registry.as(ConfigurationExtensions.Configuration);\nconfigurationRegistry.registerConfiguration({\n id: 'workbench',\n order: 7,\n title: localize('workbenchConfigurationTitle', \"Workbench\"),\n type: 'object',\n properties: {\n [multiSelectModifierSettingKey]: {\n type: 'string',\n enum: ['ctrlCmd', 'alt'],\n markdownEnumDescriptions: [\n localize('multiSelectModifier.ctrlCmd', \"Maps to `Control` on Windows and Linux and to `Command` on macOS.\"),\n localize('multiSelectModifier.alt', \"Maps to `Alt` on Windows and Linux and to `Option` on macOS.\")\n ],\n default: 'ctrlCmd',\n description: localize({\n key: 'multiSelectModifier',\n comment: [\n '- `ctrlCmd` refers to a value the setting can take and should not be localized.',\n '- `Control` and `Command` refer to the modifier keys Ctrl or Cmd on the keyboard and can be localized.'\n ]\n }, \"The modifier to be used to add an item in trees and lists to a multi-selection with the mouse (for example in the explorer, open editors and scm view). The 'Open to Side' mouse gestures - if supported - will adapt such that they do not conflict with the multiselect modifier.\")\n },\n [openModeSettingKey]: {\n type: 'string',\n enum: ['singleClick', 'doubleClick'],\n default: 'singleClick',\n description: localize({\n key: 'openModeModifier',\n comment: ['`singleClick` and `doubleClick` refers to a value the setting can take and should not be localized.']\n }, \"Controls how to open items in trees and lists using the mouse (if supported). Note that some trees and lists might choose to ignore this setting if it is not applicable.\")\n },\n [horizontalScrollingKey]: {\n type: 'boolean',\n default: false,\n description: localize('horizontalScrolling setting', \"Controls whether lists and trees support horizontal scrolling in the workbench. Warning: turning on this setting has a performance implication.\")\n },\n [treeIndentKey]: {\n type: 'number',\n default: 8,\n minimum: 4,\n maximum: 40,\n description: localize('tree indent setting', \"Controls tree indentation in pixels.\")\n },\n [treeRenderIndentGuidesKey]: {\n type: 'string',\n enum: ['none', 'onHover', 'always'],\n default: 'onHover',\n description: localize('render tree indent guides', \"Controls whether the tree should render indent guides.\")\n },\n [listSmoothScrolling]: {\n type: 'boolean',\n default: false,\n description: localize('list smoothScrolling setting', \"Controls whether lists and trees have smooth scrolling.\"),\n },\n [mouseWheelScrollSensitivityKey]: {\n type: 'number',\n default: 1,\n markdownDescription: localize('Mouse Wheel Scroll Sensitivity', \"A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.\")\n },\n [fastScrollSensitivityKey]: {\n type: 'number',\n default: 5,\n description: localize('Fast Scroll Sensitivity', \"Scrolling speed multiplier when pressing `Alt`.\")\n },\n [defaultFindModeSettingKey]: {\n type: 'string',\n enum: ['highlight', 'filter'],\n enumDescriptions: [\n localize('defaultFindModeSettingKey.highlight', \"Highlight elements when searching. Further up and down navigation will traverse only the highlighted elements.\"),\n localize('defaultFindModeSettingKey.filter', \"Filter elements when searching.\")\n ],\n default: 'highlight',\n description: localize('defaultFindModeSettingKey', \"Controls the default find mode for lists and trees in the workbench.\")\n },\n [keyboardNavigationSettingKey]: {\n type: 'string',\n enum: ['simple', 'highlight', 'filter'],\n enumDescriptions: [\n localize('keyboardNavigationSettingKey.simple', \"Simple keyboard navigation focuses elements which match the keyboard input. Matching is done only on prefixes.\"),\n localize('keyboardNavigationSettingKey.highlight', \"Highlight keyboard navigation highlights elements which match the keyboard input. Further up and down navigation will traverse only the highlighted elements.\"),\n localize('keyboardNavigationSettingKey.filter', \"Filter keyboard navigation will filter out and hide all the elements which do not match the keyboard input.\")\n ],\n default: 'highlight',\n description: localize('keyboardNavigationSettingKey', \"Controls the keyboard navigation style for lists and trees in the workbench. Can be simple, highlight and filter.\"),\n deprecated: true,\n deprecationMessage: localize('keyboardNavigationSettingKeyDeprecated', \"Please use 'workbench.list.defaultFindMode' instead.\")\n },\n [treeExpandMode]: {\n type: 'string',\n enum: ['singleClick', 'doubleClick'],\n default: 'singleClick',\n description: localize('expand mode', \"Controls how tree folders are expanded when clicking the folder names. Note that some trees and lists might choose to ignore this setting if it is not applicable.\"),\n }\n }\n});\n","import { Emitter } from '../../../base/common/event.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const ILogService = createDecorator('logService');\nexport var LogLevel;\n(function (LogLevel) {\n LogLevel[LogLevel[\"Trace\"] = 0] = \"Trace\";\n LogLevel[LogLevel[\"Debug\"] = 1] = \"Debug\";\n LogLevel[LogLevel[\"Info\"] = 2] = \"Info\";\n LogLevel[LogLevel[\"Warning\"] = 3] = \"Warning\";\n LogLevel[LogLevel[\"Error\"] = 4] = \"Error\";\n LogLevel[LogLevel[\"Critical\"] = 5] = \"Critical\";\n LogLevel[LogLevel[\"Off\"] = 6] = \"Off\";\n})(LogLevel || (LogLevel = {}));\nexport const DEFAULT_LOG_LEVEL = LogLevel.Info;\nexport class AbstractLogger extends Disposable {\n constructor() {\n super(...arguments);\n this.level = DEFAULT_LOG_LEVEL;\n this._onDidChangeLogLevel = this._register(new Emitter());\n }\n setLevel(level) {\n if (this.level !== level) {\n this.level = level;\n this._onDidChangeLogLevel.fire(this.level);\n }\n }\n getLevel() {\n return this.level;\n }\n}\nexport class ConsoleLogger extends AbstractLogger {\n constructor(logLevel = DEFAULT_LOG_LEVEL) {\n super();\n this.setLevel(logLevel);\n }\n trace(message, ...args) {\n if (this.getLevel() <= LogLevel.Trace) {\n console.log('%cTRACE', 'color: #888', message, ...args);\n }\n }\n debug(message, ...args) {\n if (this.getLevel() <= LogLevel.Debug) {\n console.log('%cDEBUG', 'background: #eee; color: #888', message, ...args);\n }\n }\n info(message, ...args) {\n if (this.getLevel() <= LogLevel.Info) {\n console.log('%c INFO', 'color: #33f', message, ...args);\n }\n }\n error(message, ...args) {\n if (this.getLevel() <= LogLevel.Error) {\n console.log('%c ERR', 'color: #f33', message, ...args);\n }\n }\n dispose() {\n // noop\n }\n}\nexport class LogService extends Disposable {\n constructor(logger) {\n super();\n this.logger = logger;\n this._register(logger);\n }\n getLevel() {\n return this.logger.getLevel();\n }\n trace(message, ...args) {\n this.logger.trace(message, ...args);\n }\n debug(message, ...args) {\n this.logger.debug(message, ...args);\n }\n info(message, ...args) {\n this.logger.info(message, ...args);\n }\n error(message, ...args) {\n this.logger.error(message, ...args);\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 *--------------------------------------------------------------------------------------------*/\nimport Severity from '../../../base/common/severity.js';\nimport { localize } from '../../../nls.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport var MarkerSeverity;\n(function (MarkerSeverity) {\n MarkerSeverity[MarkerSeverity[\"Hint\"] = 1] = \"Hint\";\n MarkerSeverity[MarkerSeverity[\"Info\"] = 2] = \"Info\";\n MarkerSeverity[MarkerSeverity[\"Warning\"] = 4] = \"Warning\";\n MarkerSeverity[MarkerSeverity[\"Error\"] = 8] = \"Error\";\n})(MarkerSeverity || (MarkerSeverity = {}));\n(function (MarkerSeverity) {\n function compare(a, b) {\n return b - a;\n }\n MarkerSeverity.compare = compare;\n const _displayStrings = Object.create(null);\n _displayStrings[MarkerSeverity.Error] = localize('sev.error', \"Error\");\n _displayStrings[MarkerSeverity.Warning] = localize('sev.warning', \"Warning\");\n _displayStrings[MarkerSeverity.Info] = localize('sev.info', \"Info\");\n function toString(a) {\n return _displayStrings[a] || '';\n }\n MarkerSeverity.toString = toString;\n function fromSeverity(severity) {\n switch (severity) {\n case Severity.Error: return MarkerSeverity.Error;\n case Severity.Warning: return MarkerSeverity.Warning;\n case Severity.Info: return MarkerSeverity.Info;\n case Severity.Ignore: return MarkerSeverity.Hint;\n }\n }\n MarkerSeverity.fromSeverity = fromSeverity;\n function toSeverity(severity) {\n switch (severity) {\n case MarkerSeverity.Error: return Severity.Error;\n case MarkerSeverity.Warning: return Severity.Warning;\n case MarkerSeverity.Info: return Severity.Info;\n case MarkerSeverity.Hint: return Severity.Ignore;\n }\n }\n MarkerSeverity.toSeverity = toSeverity;\n})(MarkerSeverity || (MarkerSeverity = {}));\nexport var IMarkerData;\n(function (IMarkerData) {\n const emptyString = '';\n function makeKey(markerData) {\n return makeKeyOptionalMessage(markerData, true);\n }\n IMarkerData.makeKey = makeKey;\n function makeKeyOptionalMessage(markerData, useMessage) {\n const result = [emptyString];\n if (markerData.source) {\n result.push(markerData.source.replace('¦', '\\\\¦'));\n }\n else {\n result.push(emptyString);\n }\n if (markerData.code) {\n if (typeof markerData.code === 'string') {\n result.push(markerData.code.replace('¦', '\\\\¦'));\n }\n else {\n result.push(markerData.code.value.replace('¦', '\\\\¦'));\n }\n }\n else {\n result.push(emptyString);\n }\n if (markerData.severity !== undefined && markerData.severity !== null) {\n result.push(MarkerSeverity.toString(markerData.severity));\n }\n else {\n result.push(emptyString);\n }\n // Modifed to not include the message as part of the marker key to work around\n // https://github.com/microsoft/vscode/issues/77475\n if (markerData.message && useMessage) {\n result.push(markerData.message.replace('¦', '\\\\¦'));\n }\n else {\n result.push(emptyString);\n }\n if (markerData.startLineNumber !== undefined && markerData.startLineNumber !== null) {\n result.push(markerData.startLineNumber.toString());\n }\n else {\n result.push(emptyString);\n }\n if (markerData.startColumn !== undefined && markerData.startColumn !== null) {\n result.push(markerData.startColumn.toString());\n }\n else {\n result.push(emptyString);\n }\n if (markerData.endLineNumber !== undefined && markerData.endLineNumber !== null) {\n result.push(markerData.endLineNumber.toString());\n }\n else {\n result.push(emptyString);\n }\n if (markerData.endColumn !== undefined && markerData.endColumn !== null) {\n result.push(markerData.endColumn.toString());\n }\n else {\n result.push(emptyString);\n }\n result.push(emptyString);\n return result.join('¦');\n }\n IMarkerData.makeKeyOptionalMessage = makeKeyOptionalMessage;\n})(IMarkerData || (IMarkerData = {}));\nexport const IMarkerService = createDecorator('markerService');\n","import BaseSeverity from '../../../base/common/severity.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport var Severity = BaseSeverity;\nexport const INotificationService = createDecorator('notificationService');\nexport class NoOpNotification {\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { equalsIgnoreCase, startsWithIgnoreCase } from '../../../base/common/strings.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const IOpenerService = createDecorator('openerService');\nexport const NullOpenerService = Object.freeze({\n _serviceBrand: undefined,\n registerOpener() { return Disposable.None; },\n registerValidator() { return Disposable.None; },\n registerExternalUriResolver() { return Disposable.None; },\n setDefaultExternalOpener() { },\n registerExternalOpener() { return Disposable.None; },\n open() {\n return __awaiter(this, void 0, void 0, function* () { return false; });\n },\n resolveExternalUri(uri) {\n return __awaiter(this, void 0, void 0, function* () { return { resolved: uri, dispose() { } }; });\n },\n});\nexport function matchesScheme(target, scheme) {\n if (URI.isUri(target)) {\n return equalsIgnoreCase(target.scheme, scheme);\n }\n else {\n return startsWithIgnoreCase(target, scheme + ':');\n }\n}\nexport function matchesSomeScheme(target, ...schemes) {\n return schemes.some(scheme => matchesScheme(target, scheme));\n}\n/**\n * file:///some/file.js#73\n * file:///some/file.js#L73\n * file:///some/file.js#73,84\n * file:///some/file.js#L73,84\n * file:///some/file.js#73-83\n * file:///some/file.js#L73-L83\n * file:///some/file.js#73,84-83,52\n * file:///some/file.js#L73,84-L83,52\n */\nexport function extractSelection(uri) {\n let selection = undefined;\n const match = /^L?(\\d+)(?:,(\\d+))?(-L?(\\d+)(?:,(\\d+))?)?/.exec(uri.fragment);\n if (match) {\n selection = {\n startLineNumber: parseInt(match[1]),\n startColumn: match[2] ? parseInt(match[2]) : 1,\n endLineNumber: match[4] ? parseInt(match[4]) : undefined,\n endColumn: match[4] ? (match[5] ? parseInt(match[5]) : 1) : undefined\n };\n uri = uri.with({ fragment: '' });\n }\n return { selection, uri };\n}\n","import { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const IProgressService = createDecorator('progressService');\nexport const emptyProgressRunner = Object.freeze({\n total() { },\n worked() { },\n done() { }\n});\nexport class Progress {\n constructor(callback) {\n this.callback = callback;\n }\n report(item) {\n this._value = item;\n this.callback(this._value);\n }\n}\nProgress.None = Object.freeze({ report() { } });\nexport const IEditorProgressService = createDecorator('editorProgressService');\n","/*---------------------------------------------------------------------------------------------\n * 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 { coalesce } from '../../../base/common/arrays.js';\nimport { toDisposable } from '../../../base/common/lifecycle.js';\nimport { Registry } from '../../registry/common/platform.js';\nexport var DefaultQuickAccessFilterValue;\n(function (DefaultQuickAccessFilterValue) {\n /**\n * Keep the value as it is given to quick access.\n */\n DefaultQuickAccessFilterValue[DefaultQuickAccessFilterValue[\"PRESERVE\"] = 0] = \"PRESERVE\";\n /**\n * Use the value that was used last time something was accepted from the picker.\n */\n DefaultQuickAccessFilterValue[DefaultQuickAccessFilterValue[\"LAST\"] = 1] = \"LAST\";\n})(DefaultQuickAccessFilterValue || (DefaultQuickAccessFilterValue = {}));\nexport const Extensions = {\n Quickaccess: 'workbench.contributions.quickaccess'\n};\nexport class QuickAccessRegistry {\n constructor() {\n this.providers = [];\n this.defaultProvider = undefined;\n }\n registerQuickAccessProvider(provider) {\n // Extract the default provider when no prefix is present\n if (provider.prefix.length === 0) {\n this.defaultProvider = provider;\n }\n else {\n this.providers.push(provider);\n }\n // sort the providers by decreasing prefix length, such that longer\n // prefixes take priority: 'ext' vs 'ext install' - the latter should win\n this.providers.sort((providerA, providerB) => providerB.prefix.length - providerA.prefix.length);\n return toDisposable(() => {\n this.providers.splice(this.providers.indexOf(provider), 1);\n if (this.defaultProvider === provider) {\n this.defaultProvider = undefined;\n }\n });\n }\n getQuickAccessProviders() {\n return coalesce([this.defaultProvider, ...this.providers]);\n }\n getQuickAccessProvider(prefix) {\n const result = prefix ? (this.providers.find(provider => prefix.startsWith(provider.prefix)) || undefined) : undefined;\n return result || this.defaultProvider;\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 *--------------------------------------------------------------------------------------------*/\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport * from '../../../base/parts/quickinput/common/quickInput.js';\nexport const IQuickInputService = createDecorator('quickInputService');\n","/*---------------------------------------------------------------------------------------------\n * 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 * as Assert from '../../../base/common/assert.js';\nimport * as Types from '../../../base/common/types.js';\nclass RegistryImpl {\n constructor() {\n this.data = new Map();\n }\n add(id, data) {\n Assert.ok(Types.isString(id));\n Assert.ok(Types.isObject(data));\n Assert.ok(!this.data.has(id), 'There is already an extension with this id');\n this.data.set(id, data);\n }\n as(id) {\n return this.data.get(id) || null;\n }\n}\nexport const Registry = 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 *--------------------------------------------------------------------------------------------*/\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nimport { ThrottledDelayer } from '../../../common/async.js';\nimport { Emitter, Event } from '../../../common/event.js';\nimport { Disposable } from '../../../common/lifecycle.js';\nimport { isUndefinedOrNull } from '../../../common/types.js';\nexport var StorageState;\n(function (StorageState) {\n StorageState[StorageState[\"None\"] = 0] = \"None\";\n StorageState[StorageState[\"Initialized\"] = 1] = \"Initialized\";\n StorageState[StorageState[\"Closed\"] = 2] = \"Closed\";\n})(StorageState || (StorageState = {}));\nexport class Storage extends Disposable {\n constructor(database, options = Object.create(null)) {\n super();\n this.database = database;\n this.options = options;\n this._onDidChangeStorage = this._register(new Emitter());\n this.onDidChangeStorage = this._onDidChangeStorage.event;\n this.state = StorageState.None;\n this.cache = new Map();\n this.flushDelayer = new ThrottledDelayer(Storage.DEFAULT_FLUSH_DELAY);\n this.pendingDeletes = new Set();\n this.pendingInserts = new Map();\n this.whenFlushedCallbacks = [];\n this.registerListeners();\n }\n registerListeners() {\n this._register(this.database.onDidChangeItemsExternal(e => this.onDidChangeItemsExternal(e)));\n }\n onDidChangeItemsExternal(e) {\n var _a, _b;\n // items that change external require us to update our\n // caches with the values. we just accept the value and\n // emit an event if there is a change.\n (_a = e.changed) === null || _a === void 0 ? void 0 : _a.forEach((value, key) => this.accept(key, value));\n (_b = e.deleted) === null || _b === void 0 ? void 0 : _b.forEach(key => this.accept(key, undefined));\n }\n accept(key, value) {\n if (this.state === StorageState.Closed) {\n return; // Return early if we are already closed\n }\n let changed = false;\n // Item got removed, check for deletion\n if (isUndefinedOrNull(value)) {\n changed = this.cache.delete(key);\n }\n // Item got updated, check for change\n else {\n const currentValue = this.cache.get(key);\n if (currentValue !== value) {\n this.cache.set(key, value);\n changed = true;\n }\n }\n // Signal to outside listeners\n if (changed) {\n this._onDidChangeStorage.fire(key);\n }\n }\n get(key, fallbackValue) {\n const value = this.cache.get(key);\n if (isUndefinedOrNull(value)) {\n return fallbackValue;\n }\n return value;\n }\n getBoolean(key, fallbackValue) {\n const value = this.get(key);\n if (isUndefinedOrNull(value)) {\n return fallbackValue;\n }\n return value === 'true';\n }\n getNumber(key, fallbackValue) {\n const value = this.get(key);\n if (isUndefinedOrNull(value)) {\n return fallbackValue;\n }\n return parseInt(value, 10);\n }\n set(key, value) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this.state === StorageState.Closed) {\n return; // Return early if we are already closed\n }\n // We remove the key for undefined/null values\n if (isUndefinedOrNull(value)) {\n return this.delete(key);\n }\n // Otherwise, convert to String and store\n const valueStr = String(value);\n // Return early if value already set\n const currentValue = this.cache.get(key);\n if (currentValue === valueStr) {\n return;\n }\n // Update in cache and pending\n this.cache.set(key, valueStr);\n this.pendingInserts.set(key, valueStr);\n this.pendingDeletes.delete(key);\n // Event\n this._onDidChangeStorage.fire(key);\n // Accumulate work by scheduling after timeout\n return this.doFlush();\n });\n }\n delete(key) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this.state === StorageState.Closed) {\n return; // Return early if we are already closed\n }\n // Remove from cache and add to pending\n const wasDeleted = this.cache.delete(key);\n if (!wasDeleted) {\n return; // Return early if value already deleted\n }\n if (!this.pendingDeletes.has(key)) {\n this.pendingDeletes.add(key);\n }\n this.pendingInserts.delete(key);\n // Event\n this._onDidChangeStorage.fire(key);\n // Accumulate work by scheduling after timeout\n return this.doFlush();\n });\n }\n get hasPending() {\n return this.pendingInserts.size > 0 || this.pendingDeletes.size > 0;\n }\n flushPending() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.hasPending) {\n return; // return early if nothing to do\n }\n // Get pending data\n const updateRequest = { insert: this.pendingInserts, delete: this.pendingDeletes };\n // Reset pending data for next run\n this.pendingDeletes = new Set();\n this.pendingInserts = new Map();\n // Update in storage and release any\n // waiters we have once done\n return this.database.updateItems(updateRequest).finally(() => {\n var _a;\n if (!this.hasPending) {\n while (this.whenFlushedCallbacks.length) {\n (_a = this.whenFlushedCallbacks.pop()) === null || _a === void 0 ? void 0 : _a();\n }\n }\n });\n });\n }\n doFlush(delay) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.flushDelayer.trigger(() => this.flushPending(), delay);\n });\n }\n dispose() {\n this.flushDelayer.dispose();\n super.dispose();\n }\n}\nStorage.DEFAULT_FLUSH_DELAY = 100;\nexport class InMemoryStorageDatabase {\n constructor() {\n this.onDidChangeItemsExternal = Event.None;\n this.items = new Map();\n }\n updateItems(request) {\n var _a, _b;\n return __awaiter(this, void 0, void 0, function* () {\n (_a = request.insert) === null || _a === void 0 ? void 0 : _a.forEach((value, key) => this.items.set(key, value));\n (_b = request.delete) === null || _b === void 0 ? void 0 : _b.forEach(key => this.items.delete(key));\n });\n }\n}\n","import { Emitter, PauseableEmitter } from '../../../base/common/event.js';\nimport { Disposable } from '../../../base/common/lifecycle.js';\nimport { isUndefinedOrNull } from '../../../base/common/types.js';\nimport { InMemoryStorageDatabase, Storage } from '../../../base/parts/storage/common/storage.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nconst TARGET_KEY = '__$__targetStorageMarker';\nexport const IStorageService = createDecorator('storageService');\nexport var WillSaveStateReason;\n(function (WillSaveStateReason) {\n /**\n * No specific reason to save state.\n */\n WillSaveStateReason[WillSaveStateReason[\"NONE\"] = 0] = \"NONE\";\n /**\n * A hint that the workbench is about to shutdown.\n */\n WillSaveStateReason[WillSaveStateReason[\"SHUTDOWN\"] = 1] = \"SHUTDOWN\";\n})(WillSaveStateReason || (WillSaveStateReason = {}));\nexport class AbstractStorageService extends Disposable {\n constructor(options = { flushInterval: AbstractStorageService.DEFAULT_FLUSH_INTERVAL }) {\n super();\n this.options = options;\n this._onDidChangeValue = this._register(new PauseableEmitter());\n this.onDidChangeValue = this._onDidChangeValue.event;\n this._onDidChangeTarget = this._register(new PauseableEmitter());\n this._onWillSaveState = this._register(new Emitter());\n this.onWillSaveState = this._onWillSaveState.event;\n this._workspaceKeyTargets = undefined;\n this._profileKeyTargets = undefined;\n this._applicationKeyTargets = undefined;\n }\n emitDidChangeValue(scope, key) {\n // Specially handle `TARGET_KEY`\n if (key === TARGET_KEY) {\n // Clear our cached version which is now out of date\n switch (scope) {\n case -1 /* StorageScope.APPLICATION */:\n this._applicationKeyTargets = undefined;\n break;\n case 0 /* StorageScope.PROFILE */:\n this._profileKeyTargets = undefined;\n break;\n case 1 /* StorageScope.WORKSPACE */:\n this._workspaceKeyTargets = undefined;\n break;\n }\n // Emit as `didChangeTarget` event\n this._onDidChangeTarget.fire({ scope });\n }\n // Emit any other key to outside\n else {\n this._onDidChangeValue.fire({ scope, key, target: this.getKeyTargets(scope)[key] });\n }\n }\n get(key, scope, fallbackValue) {\n var _a;\n return (_a = this.getStorage(scope)) === null || _a === void 0 ? void 0 : _a.get(key, fallbackValue);\n }\n getBoolean(key, scope, fallbackValue) {\n var _a;\n return (_a = this.getStorage(scope)) === null || _a === void 0 ? void 0 : _a.getBoolean(key, fallbackValue);\n }\n getNumber(key, scope, fallbackValue) {\n var _a;\n return (_a = this.getStorage(scope)) === null || _a === void 0 ? void 0 : _a.getNumber(key, fallbackValue);\n }\n store(key, value, scope, target) {\n // We remove the key for undefined/null values\n if (isUndefinedOrNull(value)) {\n this.remove(key, scope);\n return;\n }\n // Update our datastructures but send events only after\n this.withPausedEmitters(() => {\n var _a;\n // Update key-target map\n this.updateKeyTarget(key, scope, target);\n // Store actual value\n (_a = this.getStorage(scope)) === null || _a === void 0 ? void 0 : _a.set(key, value);\n });\n }\n remove(key, scope) {\n // Update our datastructures but send events only after\n this.withPausedEmitters(() => {\n var _a;\n // Update key-target map\n this.updateKeyTarget(key, scope, undefined);\n // Remove actual key\n (_a = this.getStorage(scope)) === null || _a === void 0 ? void 0 : _a.delete(key);\n });\n }\n withPausedEmitters(fn) {\n // Pause emitters\n this._onDidChangeValue.pause();\n this._onDidChangeTarget.pause();\n try {\n fn();\n }\n finally {\n // Resume emitters\n this._onDidChangeValue.resume();\n this._onDidChangeTarget.resume();\n }\n }\n updateKeyTarget(key, scope, target) {\n var _a, _b;\n // Add\n const keyTargets = this.getKeyTargets(scope);\n if (typeof target === 'number') {\n if (keyTargets[key] !== target) {\n keyTargets[key] = target;\n (_a = this.getStorage(scope)) === null || _a === void 0 ? void 0 : _a.set(TARGET_KEY, JSON.stringify(keyTargets));\n }\n }\n // Remove\n else {\n if (typeof keyTargets[key] === 'number') {\n delete keyTargets[key];\n (_b = this.getStorage(scope)) === null || _b === void 0 ? void 0 : _b.set(TARGET_KEY, JSON.stringify(keyTargets));\n }\n }\n }\n get workspaceKeyTargets() {\n if (!this._workspaceKeyTargets) {\n this._workspaceKeyTargets = this.loadKeyTargets(1 /* StorageScope.WORKSPACE */);\n }\n return this._workspaceKeyTargets;\n }\n get profileKeyTargets() {\n if (!this._profileKeyTargets) {\n this._profileKeyTargets = this.loadKeyTargets(0 /* StorageScope.PROFILE */);\n }\n return this._profileKeyTargets;\n }\n get applicationKeyTargets() {\n if (!this._applicationKeyTargets) {\n this._applicationKeyTargets = this.loadKeyTargets(-1 /* StorageScope.APPLICATION */);\n }\n return this._applicationKeyTargets;\n }\n getKeyTargets(scope) {\n switch (scope) {\n case -1 /* StorageScope.APPLICATION */:\n return this.applicationKeyTargets;\n case 0 /* StorageScope.PROFILE */:\n return this.profileKeyTargets;\n default:\n return this.workspaceKeyTargets;\n }\n }\n loadKeyTargets(scope) {\n const keysRaw = this.get(TARGET_KEY, scope);\n if (keysRaw) {\n try {\n return JSON.parse(keysRaw);\n }\n catch (error) {\n // Fail gracefully\n }\n }\n return Object.create(null);\n }\n}\nAbstractStorageService.DEFAULT_FLUSH_INTERVAL = 60 * 1000; // every minute\nexport class InMemoryStorageService extends AbstractStorageService {\n constructor() {\n super();\n this.applicationStorage = this._register(new Storage(new InMemoryStorageDatabase()));\n this.profileStorage = this._register(new Storage(new InMemoryStorageDatabase()));\n this.workspaceStorage = this._register(new Storage(new InMemoryStorageDatabase()));\n this._register(this.workspaceStorage.onDidChangeStorage(key => this.emitDidChangeValue(1 /* StorageScope.WORKSPACE */, key)));\n this._register(this.profileStorage.onDidChangeStorage(key => this.emitDidChangeValue(0 /* StorageScope.PROFILE */, key)));\n this._register(this.applicationStorage.onDidChangeStorage(key => this.emitDidChangeValue(-1 /* StorageScope.APPLICATION */, key)));\n }\n getStorage(scope) {\n switch (scope) {\n case -1 /* StorageScope.APPLICATION */:\n return this.applicationStorage;\n case 0 /* StorageScope.PROFILE */:\n return this.profileStorage;\n default:\n return this.workspaceStorage;\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 *--------------------------------------------------------------------------------------------*/\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const ITelemetryService = createDecorator('telemetryService');\n","/*---------------------------------------------------------------------------------------------\n * 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 { RunOnceScheduler } from '../../../base/common/async.js';\nimport { Color, RGBA } from '../../../base/common/color.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { assertNever } from '../../../base/common/types.js';\nimport * as nls from '../../../nls.js';\nimport { Extensions as JSONExtensions } from '../../jsonschemas/common/jsonContributionRegistry.js';\nimport * as platform from '../../registry/common/platform.js';\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) {\n return `--vscode-${colorIdent.replace(/\\./g, '-')}`;\n}\n// color registry\nexport const Extensions = {\n ColorContribution: 'base.contributions.colors'\n};\nclass ColorRegistry {\n constructor() {\n this._onDidChangeSchema = new Emitter();\n this.onDidChangeSchema = this._onDidChangeSchema.event;\n this.colorSchema = { type: 'object', properties: {} };\n this.colorReferenceSchema = { type: 'string', enum: [], enumDescriptions: [] };\n this.colorsById = {};\n }\n registerColor(id, defaults, description, needsTransparency = false, deprecationMessage) {\n const colorContribution = { id, description, defaults, needsTransparency, deprecationMessage };\n this.colorsById[id] = colorContribution;\n const propertySchema = { type: 'string', description, format: 'color-hex', defaultSnippets: [{ body: '${1:#ff0000}' }] };\n if (deprecationMessage) {\n propertySchema.deprecationMessage = deprecationMessage;\n }\n this.colorSchema.properties[id] = propertySchema;\n this.colorReferenceSchema.enum.push(id);\n this.colorReferenceSchema.enumDescriptions.push(description);\n this._onDidChangeSchema.fire();\n return id;\n }\n getColors() {\n return Object.keys(this.colorsById).map(id => this.colorsById[id]);\n }\n resolveDefaultColor(id, theme) {\n const colorDesc = this.colorsById[id];\n if (colorDesc && colorDesc.defaults) {\n const colorValue = colorDesc.defaults[theme.type];\n return resolveColorValue(colorValue, theme);\n }\n return undefined;\n }\n getColorSchema() {\n return this.colorSchema;\n }\n toString() {\n const sorter = (a, b) => {\n const cat1 = a.indexOf('.') === -1 ? 0 : 1;\n const cat2 = b.indexOf('.') === -1 ? 0 : 1;\n if (cat1 !== cat2) {\n return cat1 - cat2;\n }\n return a.localeCompare(b);\n };\n return Object.keys(this.colorsById).sort(sorter).map(k => `- \\`${k}\\`: ${this.colorsById[k].description}`).join('\\n');\n }\n}\nconst colorRegistry = new ColorRegistry();\nplatform.Registry.add(Extensions.ColorContribution, colorRegistry);\nfunction migrateColorDefaults(o) {\n if (o === null) {\n return o;\n }\n if (typeof o.hcLight === 'undefined') {\n if (o.hcDark === null || typeof o.hcDark === 'string') {\n o.hcLight = o.hcDark;\n }\n else {\n o.hcLight = o.light;\n }\n }\n return o;\n}\nexport function registerColor(id, defaults, description, needsTransparency, deprecationMessage) {\n return colorRegistry.registerColor(id, migrateColorDefaults(defaults), description, needsTransparency, deprecationMessage);\n}\n// ----- base colors\nexport const foreground = registerColor('foreground', { dark: '#CCCCCC', light: '#616161', hcDark: '#FFFFFF', hcLight: '#292929' }, nls.localize('foreground', \"Overall foreground color. This color is only used if not overridden by a component.\"));\nexport const disabledForeground = registerColor('disabledForeground', { dark: '#CCCCCC80', light: '#61616180', hcDark: '#A5A5A5', hcLight: '#7F7F7F' }, nls.localize('disabledForeground', \"Overall foreground for disabled elements. This color is only used if not overridden by a component.\"));\nexport const errorForeground = registerColor('errorForeground', { dark: '#F48771', light: '#A1260D', hcDark: '#F48771', hcLight: '#B5200D' }, 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), hcDark: transparent(foreground, 0.7), hcLight: 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', hcDark: '#FFFFFF', hcLight: '#292929' }, nls.localize('iconForeground', \"The default color for icons in the workbench.\"));\nexport const focusBorder = registerColor('focusBorder', { dark: '#007FD4', light: '#0090F1', hcDark: '#F38518', hcLight: '#0F4A85' }, nls.localize('focusBorder', \"Overall border color for focused elements. This color is only used if not overridden by a component.\"));\nexport const contrastBorder = registerColor('contrastBorder', { light: null, dark: null, hcDark: '#6FC3DF', hcLight: '#0F4A85' }, 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, hcDark: focusBorder, hcLight: focusBorder }, nls.localize('activeContrastBorder', \"An extra border around active elements to separate them from others for greater contrast.\"));\nexport const selectionBackground = registerColor('selection.background', { light: null, dark: null, hcDark: null, hcLight: 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// ------ text colors\nexport const textSeparatorForeground = registerColor('textSeparator.foreground', { light: '#0000002e', dark: '#ffffff2e', hcDark: Color.black, hcLight: '#292929' }, nls.localize('textSeparatorForeground', \"Color for text separators.\"));\nexport const textLinkForeground = registerColor('textLink.foreground', { light: '#006AB1', dark: '#3794FF', hcDark: '#3794FF', hcLight: '#0F4A85' }, nls.localize('textLinkForeground', \"Foreground color for links in text.\"));\nexport const textLinkActiveForeground = registerColor('textLink.activeForeground', { light: '#006AB1', dark: '#3794FF', hcDark: '#3794FF', hcLight: '#0F4A85' }, 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', hcDark: '#D7BA7D', hcLight: '#292929' }, nls.localize('textPreformatForeground', \"Foreground color for preformatted text segments.\"));\nexport const textBlockQuoteBackground = registerColor('textBlockQuote.background', { light: '#7f7f7f1a', dark: '#7f7f7f1a', hcDark: null, hcLight: '#F2F2F2' }, nls.localize('textBlockQuoteBackground', \"Background color for block quotes in text.\"));\nexport const textBlockQuoteBorder = registerColor('textBlockQuote.border', { light: '#007acc80', dark: '#007acc80', hcDark: Color.white, hcLight: '#292929' }, nls.localize('textBlockQuoteBorder', \"Border color for block quotes in text.\"));\nexport const textCodeBlockBackground = registerColor('textCodeBlock.background', { light: '#dcdcdc66', dark: '#0a0a0a66', hcDark: Color.black, hcLight: '#F2F2F2' }, nls.localize('textCodeBlockBackground', \"Background color for code blocks in text.\"));\n// ----- widgets\nexport const widgetShadow = registerColor('widget.shadow', { dark: transparent(Color.black, .36), light: transparent(Color.black, .16), hcDark: null, hcLight: null }, nls.localize('widgetShadow', 'Shadow color of widgets such as find/replace inside the editor.'));\nexport const inputBackground = registerColor('input.background', { dark: '#3C3C3C', light: Color.white, hcDark: Color.black, hcLight: Color.white }, nls.localize('inputBoxBackground', \"Input box background.\"));\nexport const inputForeground = registerColor('input.foreground', { dark: foreground, light: foreground, hcDark: foreground, hcLight: foreground }, nls.localize('inputBoxForeground', \"Input box foreground.\"));\nexport const inputBorder = registerColor('input.border', { dark: null, light: null, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('inputBoxBorder', \"Input box border.\"));\nexport const inputActiveOptionBorder = registerColor('inputOption.activeBorder', { dark: '#007ACC00', light: '#007ACC00', hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('inputBoxActiveOptionBorder', \"Border color of activated options in input fields.\"));\nexport const inputActiveOptionHoverBackground = registerColor('inputOption.hoverBackground', { dark: '#5a5d5e80', light: '#b8b8b850', hcDark: null, hcLight: 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), hcDark: Color.transparent, hcLight: 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, hcDark: null, hcLight: foreground }, 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), hcDark: transparent(foreground, 0.7), hcLight: transparent(foreground, 0.7) }, nls.localize('inputPlaceholderForeground', \"Input box foreground color for placeholder text.\"));\nexport const inputValidationInfoBackground = registerColor('inputValidation.infoBackground', { dark: '#063B49', light: '#D6ECF2', hcDark: Color.black, hcLight: Color.white }, nls.localize('inputValidationInfoBackground', \"Input validation background color for information severity.\"));\nexport const inputValidationInfoForeground = registerColor('inputValidation.infoForeground', { dark: null, light: null, hcDark: null, hcLight: foreground }, nls.localize('inputValidationInfoForeground', \"Input validation foreground color for information severity.\"));\nexport const inputValidationInfoBorder = registerColor('inputValidation.infoBorder', { dark: '#007acc', light: '#007acc', hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('inputValidationInfoBorder', \"Input validation border color for information severity.\"));\nexport const inputValidationWarningBackground = registerColor('inputValidation.warningBackground', { dark: '#352A05', light: '#F6F5D2', hcDark: Color.black, hcLight: Color.white }, nls.localize('inputValidationWarningBackground', \"Input validation background color for warning severity.\"));\nexport const inputValidationWarningForeground = registerColor('inputValidation.warningForeground', { dark: null, light: null, hcDark: null, hcLight: foreground }, nls.localize('inputValidationWarningForeground', \"Input validation foreground color for warning severity.\"));\nexport const inputValidationWarningBorder = registerColor('inputValidation.warningBorder', { dark: '#B89500', light: '#B89500', hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('inputValidationWarningBorder', \"Input validation border color for warning severity.\"));\nexport const inputValidationErrorBackground = registerColor('inputValidation.errorBackground', { dark: '#5A1D1D', light: '#F2DEDE', hcDark: Color.black, hcLight: Color.white }, nls.localize('inputValidationErrorBackground', \"Input validation background color for error severity.\"));\nexport const inputValidationErrorForeground = registerColor('inputValidation.errorForeground', { dark: null, light: null, hcDark: null, hcLight: foreground }, nls.localize('inputValidationErrorForeground', \"Input validation foreground color for error severity.\"));\nexport const inputValidationErrorBorder = registerColor('inputValidation.errorBorder', { dark: '#BE1100', light: '#BE1100', hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('inputValidationErrorBorder', \"Input validation border color for error severity.\"));\nexport const selectBackground = registerColor('dropdown.background', { dark: '#3C3C3C', light: Color.white, hcDark: Color.black, hcLight: Color.white }, nls.localize('dropdownBackground', \"Dropdown background.\"));\nexport const selectListBackground = registerColor('dropdown.listBackground', { dark: null, light: null, hcDark: Color.black, hcLight: Color.white }, nls.localize('dropdownListBackground', \"Dropdown list background.\"));\nexport const selectForeground = registerColor('dropdown.foreground', { dark: '#F0F0F0', light: null, hcDark: Color.white, hcLight: foreground }, nls.localize('dropdownForeground', \"Dropdown foreground.\"));\nexport const selectBorder = registerColor('dropdown.border', { dark: selectBackground, light: '#CECECE', hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('dropdownBorder', \"Dropdown border.\"));\nexport const checkboxBackground = registerColor('checkbox.background', { dark: selectBackground, light: selectBackground, hcDark: selectBackground, hcLight: selectBackground }, nls.localize('checkbox.background', \"Background color of checkbox widget.\"));\nexport const checkboxForeground = registerColor('checkbox.foreground', { dark: selectForeground, light: selectForeground, hcDark: selectForeground, hcLight: selectForeground }, nls.localize('checkbox.foreground', \"Foreground color of checkbox widget.\"));\nexport const checkboxBorder = registerColor('checkbox.border', { dark: selectBorder, light: selectBorder, hcDark: selectBorder, hcLight: selectBorder }, nls.localize('checkbox.border', \"Border color of checkbox widget.\"));\nexport const buttonForeground = registerColor('button.foreground', { dark: Color.white, light: Color.white, hcDark: Color.white, hcLight: Color.white }, nls.localize('buttonForeground', \"Button foreground color.\"));\nexport const buttonSeparator = registerColor('button.separator', { dark: transparent(buttonForeground, .4), light: transparent(buttonForeground, .4), hcDark: transparent(buttonForeground, .4), hcLight: transparent(buttonForeground, .4) }, nls.localize('buttonSeparator', \"Button separator color.\"));\nexport const buttonBackground = registerColor('button.background', { dark: '#0E639C', light: '#007ACC', hcDark: null, hcLight: '#0F4A85' }, nls.localize('buttonBackground', \"Button background color.\"));\nexport const buttonHoverBackground = registerColor('button.hoverBackground', { dark: lighten(buttonBackground, 0.2), light: darken(buttonBackground, 0.2), hcDark: null, hcLight: null }, nls.localize('buttonHoverBackground', \"Button background color when hovering.\"));\nexport const buttonBorder = registerColor('button.border', { dark: contrastBorder, light: contrastBorder, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('buttonBorder', \"Button border color.\"));\nexport const buttonSecondaryForeground = registerColor('button.secondaryForeground', { dark: Color.white, light: Color.white, hcDark: Color.white, hcLight: foreground }, nls.localize('buttonSecondaryForeground', \"Secondary button foreground color.\"));\nexport const buttonSecondaryBackground = registerColor('button.secondaryBackground', { dark: '#3A3D41', light: '#5F6A79', hcDark: null, hcLight: Color.white }, nls.localize('buttonSecondaryBackground', \"Secondary button background color.\"));\nexport const buttonSecondaryHoverBackground = registerColor('button.secondaryHoverBackground', { dark: lighten(buttonSecondaryBackground, 0.2), light: darken(buttonSecondaryBackground, 0.2), hcDark: null, hcLight: null }, nls.localize('buttonSecondaryHoverBackground', \"Secondary button background color when hovering.\"));\nexport const badgeBackground = registerColor('badge.background', { dark: '#4D4D4D', light: '#C4C4C4', hcDark: Color.black, hcLight: '#0F4A85' }, 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', hcDark: Color.white, hcLight: Color.white }, nls.localize('badgeForeground', \"Badge foreground color. Badges are small information labels, e.g. for search results count.\"));\nexport const scrollbarShadow = registerColor('scrollbar.shadow', { dark: '#000000', light: '#DDDDDD', hcDark: null, hcLight: 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), hcDark: transparent(contrastBorder, 0.6), hcLight: transparent(contrastBorder, 0.4) }, 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), hcDark: transparent(contrastBorder, 0.8), hcLight: 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), hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('scrollbarSliderActiveBackground', \"Scrollbar slider background color when clicked on.\"));\nexport const progressBarBackground = registerColor('progressBar.background', { dark: Color.fromHex('#0E70C0'), light: Color.fromHex('#0E70C0'), hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('progressBarBackground', \"Background color of the progress bar that can show for long running operations.\"));\nexport const editorErrorBackground = registerColor('editorError.background', { dark: null, light: null, hcDark: null, hcLight: 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', hcDark: '#F48771', hcLight: '#B5200D' }, nls.localize('editorError.foreground', 'Foreground color of error squigglies in the editor.'));\nexport const editorErrorBorder = registerColor('editorError.border', { dark: null, light: null, hcDark: Color.fromHex('#E47777').transparent(0.8), hcLight: '#B5200D' }, nls.localize('errorBorder', 'Border color of error boxes in the editor.'));\nexport const editorWarningBackground = registerColor('editorWarning.background', { dark: null, light: null, hcDark: null, hcLight: 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', hcDark: '#FFD37', hcLight: '#895503' }, nls.localize('editorWarning.foreground', 'Foreground color of warning squigglies in the editor.'));\nexport const editorWarningBorder = registerColor('editorWarning.border', { dark: null, light: null, hcDark: Color.fromHex('#FFCC00').transparent(0.8), hcLight: '#' }, nls.localize('warningBorder', 'Border color of warning boxes in the editor.'));\nexport const editorInfoBackground = registerColor('editorInfo.background', { dark: null, light: null, hcDark: null, hcLight: 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', hcDark: '#3794FF', hcLight: '#1a85ff' }, nls.localize('editorInfo.foreground', 'Foreground color of info squigglies in the editor.'));\nexport const editorInfoBorder = registerColor('editorInfo.border', { dark: null, light: null, hcDark: Color.fromHex('#3794FF').transparent(0.8), hcLight: '#292929' }, nls.localize('infoBorder', 'Border color of info boxes in the editor.'));\nexport const editorHintForeground = registerColor('editorHint.foreground', { dark: Color.fromHex('#eeeeee').transparent(0.7), light: '#6c6c6c', hcDark: null, hcLight: null }, nls.localize('editorHint.foreground', 'Foreground color of hint squigglies in the editor.'));\nexport const editorHintBorder = registerColor('editorHint.border', { dark: null, light: null, hcDark: Color.fromHex('#eeeeee').transparent(0.8), hcLight: '#292929' }, nls.localize('hintBorder', 'Border color of hint boxes in the editor.'));\nexport const sashHoverBorder = registerColor('sash.hoverBorder', { dark: focusBorder, light: focusBorder, hcDark: focusBorder, hcLight: focusBorder }, nls.localize('sashActiveBorder', \"Border color of active sashes.\"));\n/**\n * Editor background color.\n */\nexport const editorBackground = registerColor('editor.background', { light: '#ffffff', dark: '#1E1E1E', hcDark: Color.black, hcLight: Color.white }, nls.localize('editorBackground', \"Editor background color.\"));\n/**\n * Editor foreground color.\n */\nexport const editorForeground = registerColor('editor.foreground', { light: '#333333', dark: '#BBBBBB', hcDark: Color.white, hcLight: foreground }, nls.localize('editorForeground', \"Editor default foreground color.\"));\n/**\n * Sticky scroll\n */\nexport const editorStickyScrollBackground = registerColor('editorStickyScroll.background', { light: editorBackground, dark: editorBackground, hcDark: editorBackground, hcLight: editorBackground }, nls.localize('editorStickyScrollBackground', \"Sticky scroll background color for the editor\"));\nexport const editorStickyScrollHoverBackground = registerColor('editorStickyScrollHover.background', { dark: '#2A2D2E', light: '#F0F0F0', hcDark: null, hcLight: Color.fromHex('#0F4A85').transparent(0.1) }, nls.localize('editorStickyScrollHoverBackground', \"Sticky scroll on hover background color for the editor\"));\n/**\n * Editor widgets\n */\nexport const editorWidgetBackground = registerColor('editorWidget.background', { dark: '#252526', light: '#F3F3F3', hcDark: '#0C141F', hcLight: Color.white }, nls.localize('editorWidgetBackground', 'Background color of editor widgets, such as find/replace.'));\nexport const editorWidgetForeground = registerColor('editorWidget.foreground', { dark: foreground, light: foreground, hcDark: foreground, hcLight: foreground }, nls.localize('editorWidgetForeground', 'Foreground color of editor widgets, such as find/replace.'));\nexport const editorWidgetBorder = registerColor('editorWidget.border', { dark: '#454545', light: '#C8C8C8', hcDark: contrastBorder, hcLight: 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.'));\nexport const editorWidgetResizeBorder = registerColor('editorWidget.resizeBorder', { light: null, dark: null, hcDark: null, hcLight: 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 * Quick pick widget\n */\nexport const quickInputBackground = registerColor('quickInput.background', { dark: editorWidgetBackground, light: editorWidgetBackground, hcDark: editorWidgetBackground, hcLight: 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, hcDark: editorWidgetForeground, hcLight: 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)), hcDark: '#000000', hcLight: Color.white }, 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', hcDark: Color.white, hcLight: '#0F4A85' }, nls.localize('pickerGroupForeground', \"Quick picker color for grouping labels.\"));\nexport const pickerGroupBorder = registerColor('pickerGroup.border', { dark: '#3F3F46', light: '#CCCEDB', hcDark: Color.white, hcLight: '#0F4A85' }, nls.localize('pickerGroupBorder', \"Quick picker color for grouping borders.\"));\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)), hcDark: Color.transparent, hcLight: 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'), hcDark: Color.white, hcLight: foreground }, 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)), hcDark: new Color(new RGBA(111, 195, 223)), hcLight: contrastBorder }, 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)), hcDark: new Color(new RGBA(111, 195, 223)), hcLight: foreground }, nls.localize('keybindingLabelBottomBorder', \"Keybinding label border bottom color. The keybinding label is used to represent a keyboard shortcut.\"));\n/**\n * Editor selection colors.\n */\nexport const editorSelectionBackground = registerColor('editor.selectionBackground', { light: '#ADD6FF', dark: '#264F78', hcDark: '#f3f518', hcLight: '#0F4A85' }, nls.localize('editorSelectionBackground', \"Color of the editor selection.\"));\nexport const editorSelectionForeground = registerColor('editor.selectionForeground', { light: null, dark: null, hcDark: '#000000', hcLight: Color.white }, 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), hcDark: transparent(editorSelectionBackground, 0.7), hcLight: 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), hcDark: null, hcLight: 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, hcDark: activeContrastBorder, hcLight: activeContrastBorder }, nls.localize('editorSelectionHighlightBorder', \"Border color for regions with the same content as the selection.\"));\n/**\n * Editor find match colors.\n */\nexport const editorFindMatch = registerColor('editor.findMatchBackground', { light: '#A8AC94', dark: '#515C6A', hcDark: null, hcLight: null }, nls.localize('editorFindMatch', \"Color of the current search match.\"));\nexport const editorFindMatchHighlight = registerColor('editor.findMatchHighlightBackground', { light: '#EA5C0055', dark: '#EA5C0055', hcDark: null, hcLight: 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', hcDark: null, hcLight: 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, hcDark: activeContrastBorder, hcLight: activeContrastBorder }, nls.localize('editorFindMatchBorder', \"Border color of the current search match.\"));\nexport const editorFindMatchHighlightBorder = registerColor('editor.findMatchHighlightBorder', { light: null, dark: null, hcDark: activeContrastBorder, hcLight: activeContrastBorder }, nls.localize('findMatchHighlightBorder', \"Border color of the other search matches.\"));\nexport const editorFindRangeHighlightBorder = registerColor('editor.findRangeHighlightBorder', { dark: null, light: null, hcDark: transparent(activeContrastBorder, 0.4), hcLight: 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 * 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), hcDark: editorFindMatchHighlight, hcLight: 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), hcDark: editorFindMatchHighlightBorder, hcLight: editorFindMatchHighlightBorder }, nls.localize('searchEditor.editorFindMatchBorder', \"Border color of the Search Editor query matches.\"));\n/**\n * Editor hover\n */\nexport const editorHoverHighlight = registerColor('editor.hoverHighlightBackground', { light: '#ADD6FF26', dark: '#264f7840', hcDark: '#ADD6FF26', hcLight: null }, 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, hcDark: editorWidgetBackground, hcLight: editorWidgetBackground }, nls.localize('hoverBackground', 'Background color of the editor hover.'));\nexport const editorHoverForeground = registerColor('editorHoverWidget.foreground', { light: editorWidgetForeground, dark: editorWidgetForeground, hcDark: editorWidgetForeground, hcLight: editorWidgetForeground }, nls.localize('hoverForeground', 'Foreground color of the editor hover.'));\nexport const editorHoverBorder = registerColor('editorHoverWidget.border', { light: editorWidgetBorder, dark: editorWidgetBorder, hcDark: editorWidgetBorder, hcLight: 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), hcDark: editorWidgetBackground, hcLight: 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, hcDark: Color.cyan, hcLight: '#292929' }, nls.localize('activeLinkForeground', 'Color of active links.'));\n/**\n * Inline hints\n */\nexport const editorInlayHintForeground = registerColor('editorInlayHint.foreground', { dark: transparent(badgeForeground, .8), light: transparent(badgeForeground, .8), hcDark: badgeForeground, hcLight: badgeForeground }, nls.localize('editorInlayHintForeground', 'Foreground color of inline hints'));\nexport const editorInlayHintBackground = registerColor('editorInlayHint.background', { dark: transparent(badgeBackground, .6), light: transparent(badgeBackground, .3), hcDark: badgeBackground, hcLight: badgeBackground }, nls.localize('editorInlayHintBackground', 'Background color of inline hints'));\nexport const editorInlayHintTypeForeground = registerColor('editorInlayHint.typeForeground', { dark: editorInlayHintForeground, light: editorInlayHintForeground, hcDark: editorInlayHintForeground, hcLight: editorInlayHintForeground }, nls.localize('editorInlayHintForegroundTypes', 'Foreground color of inline hints for types'));\nexport const editorInlayHintTypeBackground = registerColor('editorInlayHint.typeBackground', { dark: editorInlayHintBackground, light: editorInlayHintBackground, hcDark: editorInlayHintBackground, hcLight: editorInlayHintBackground }, nls.localize('editorInlayHintBackgroundTypes', 'Background color of inline hints for types'));\nexport const editorInlayHintParameterForeground = registerColor('editorInlayHint.parameterForeground', { dark: editorInlayHintForeground, light: editorInlayHintForeground, hcDark: editorInlayHintForeground, hcLight: editorInlayHintForeground }, nls.localize('editorInlayHintForegroundParameter', 'Foreground color of inline hints for parameters'));\nexport const editorInlayHintParameterBackground = registerColor('editorInlayHint.parameterBackground', { dark: editorInlayHintBackground, light: editorInlayHintBackground, hcDark: editorInlayHintBackground, hcLight: editorInlayHintBackground }, nls.localize('editorInlayHintBackgroundParameter', 'Background color of inline hints for parameters'));\n/**\n * Editor lighbulb icon colors\n */\nexport const editorLightBulbForeground = registerColor('editorLightBulb.foreground', { dark: '#FFCC00', light: '#DDB100', hcDark: '#FFCC00', hcLight: '#007ACC' }, nls.localize('editorLightBulbForeground', \"The color used for the lightbulb actions icon.\"));\nexport const editorLightBulbAutoFixForeground = registerColor('editorLightBulbAutoFix.foreground', { dark: '#75BEFF', light: '#007ACC', hcDark: '#75BEFF', hcLight: '#007ACC' }, nls.localize('editorLightBulbAutoFixForeground', \"The color used for the lightbulb auto fix actions icon.\"));\n/**\n * Diff Editor Colors\n */\nexport const defaultInsertColor = new Color(new RGBA(155, 185, 85, .2));\nexport const defaultRemoveColor = new Color(new RGBA(255, 0, 0, .2));\nexport const diffInserted = registerColor('diffEditor.insertedTextBackground', { dark: '#9ccc2c33', light: '#9ccc2c66', hcDark: null, hcLight: 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: '#ff000066', light: '#ff00004d', hcDark: null, hcLight: 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);\nexport const diffInsertedLine = registerColor('diffEditor.insertedLineBackground', { dark: defaultInsertColor, light: defaultInsertColor, hcDark: null, hcLight: null }, nls.localize('diffEditorInsertedLines', 'Background color for lines that got inserted. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const diffRemovedLine = registerColor('diffEditor.removedLineBackground', { dark: defaultRemoveColor, light: defaultRemoveColor, hcDark: null, hcLight: null }, nls.localize('diffEditorRemovedLines', 'Background color for lines that got removed. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const diffInsertedLineGutter = registerColor('diffEditorGutter.insertedLineBackground', { dark: null, light: null, hcDark: null, hcLight: null }, nls.localize('diffEditorInsertedLineGutter', 'Background color for the margin where lines got inserted.'));\nexport const diffRemovedLineGutter = registerColor('diffEditorGutter.removedLineBackground', { dark: null, light: null, hcDark: null, hcLight: null }, nls.localize('diffEditorRemovedLineGutter', 'Background color for the margin where lines got removed.'));\nexport const diffOverviewRulerInserted = registerColor('diffEditorOverview.insertedForeground', { dark: null, light: null, hcDark: null, hcLight: null }, nls.localize('diffEditorOverviewInserted', 'Diff overview ruler foreground for inserted content.'));\nexport const diffOverviewRulerRemoved = registerColor('diffEditorOverview.removedForeground', { dark: null, light: null, hcDark: null, hcLight: null }, nls.localize('diffEditorOverviewRemoved', 'Diff overview ruler foreground for removed content.'));\nexport const diffInsertedOutline = registerColor('diffEditor.insertedTextBorder', { dark: null, light: null, hcDark: '#33ff2eff', hcLight: '#374E06' }, nls.localize('diffEditorInsertedOutline', 'Outline color for the text that got inserted.'));\nexport const diffRemovedOutline = registerColor('diffEditor.removedTextBorder', { dark: null, light: null, hcDark: '#FF008F', hcLight: '#AD0707' }, nls.localize('diffEditorRemovedOutline', 'Outline color for text that got removed.'));\nexport const diffBorder = registerColor('diffEditor.border', { dark: null, light: null, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('diffEditorBorder', 'Border color between the two text editors.'));\nexport const diffDiagonalFill = registerColor('diffEditor.diagonalFill', { dark: '#cccccc33', light: '#22222233', hcDark: null, hcLight: 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 * List and tree colors\n */\nexport const listFocusBackground = registerColor('list.focusBackground', { dark: null, light: null, hcDark: null, hcLight: 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, hcDark: null, hcLight: 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, hcDark: activeContrastBorder, hcLight: 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 listFocusAndSelectionOutline = registerColor('list.focusAndSelectionOutline', { dark: null, light: null, hcDark: null, hcLight: null }, nls.localize('listFocusAndSelectionOutline', \"List/Tree outline color for the focused item when the list/tree is active and selected. An active list/tree has keyboard focus, an inactive does not.\"));\nexport const listActiveSelectionBackground = registerColor('list.activeSelectionBackground', { dark: '#04395E', light: '#0060C0', hcDark: null, hcLight: Color.fromHex('#0F4A85').transparent(0.1) }, 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, hcDark: null, hcLight: 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, hcDark: null, hcLight: 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', hcDark: null, hcLight: Color.fromHex('#0F4A85').transparent(0.1) }, 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, hcDark: null, hcLight: 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, hcDark: null, hcLight: 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, hcDark: null, hcLight: 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, hcDark: null, hcLight: 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', hcDark: null, hcLight: Color.fromHex('#0F4A85').transparent(0.1) }, nls.localize('listHoverBackground', \"List/Tree background when hovering over items using the mouse.\"));\nexport const listHoverForeground = registerColor('list.hoverForeground', { dark: null, light: null, hcDark: null, hcLight: null }, nls.localize('listHoverForeground', \"List/Tree foreground when hovering over items using the mouse.\"));\nexport const listDropBackground = registerColor('list.dropBackground', { dark: '#062F4A', light: '#D6EBFF', hcDark: null, hcLight: null }, nls.localize('listDropBackground', \"List/Tree drag and drop background when moving items around using the mouse.\"));\nexport const listHighlightForeground = registerColor('list.highlightForeground', { dark: '#2AAAFF', light: '#0066BF', hcDark: focusBorder, hcLight: 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, '#BBE7FF'), hcDark: listHighlightForeground, hcLight: 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', hcDark: '#B89500', hcLight: '#B5200D' }, 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', hcDark: null, hcLight: null }, nls.localize('listErrorForeground', 'Foreground color of list items containing errors.'));\nexport const listWarningForeground = registerColor('list.warningForeground', { dark: '#CCA700', light: '#855F00', hcDark: null, hcLight: null }, nls.localize('listWarningForeground', 'Foreground color of list items containing warnings.'));\nexport const listFilterWidgetBackground = registerColor('listFilterWidget.background', { light: darken(editorWidgetBackground, 0), dark: lighten(editorWidgetBackground, 0), hcDark: editorWidgetBackground, hcLight: editorWidgetBackground }, 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, hcDark: '#f38518', hcLight: '#007ACC' }, nls.localize('listFilterWidgetOutline', 'Outline color of the type filter widget in lists and trees.'));\nexport const listFilterWidgetNoMatchesOutline = registerColor('listFilterWidget.noMatchesOutline', { dark: '#BE1100', light: '#BE1100', hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('listFilterWidgetNoMatchesOutline', 'Outline color of the type filter widget in lists and trees, when there are no matches.'));\nexport const listFilterWidgetShadow = registerColor('listFilterWidget.shadow', { dark: widgetShadow, light: widgetShadow, hcDark: widgetShadow, hcLight: widgetShadow }, nls.localize('listFilterWidgetShadow', 'Shadown color of the type filter widget in lists and trees.'));\nexport const listFilterMatchHighlight = registerColor('list.filterMatchBackground', { dark: editorFindMatchHighlight, light: editorFindMatchHighlight, hcDark: null, hcLight: null }, nls.localize('listFilterMatchHighlight', 'Background color of the filtered match.'));\nexport const listFilterMatchHighlightBorder = registerColor('list.filterMatchBorder', { dark: editorFindMatchHighlightBorder, light: editorFindMatchHighlightBorder, hcDark: contrastBorder, hcLight: activeContrastBorder }, nls.localize('listFilterMatchHighlightBorder', 'Border color of the filtered match.'));\nexport const treeIndentGuidesStroke = registerColor('tree.indentGuidesStroke', { dark: '#585858', light: '#a9a9a9', hcDark: '#a9a9a9', hcLight: '#a5a5a5' }, nls.localize('treeIndentGuidesStroke', \"Tree stroke color for the indentation guides.\"));\nexport const tableColumnsBorder = registerColor('tree.tableColumnsBorder', { dark: '#CCCCCC20', light: '#61616120', hcDark: null, hcLight: 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), hcDark: null, hcLight: null }, nls.localize('tableOddRowsBackgroundColor', \"Background color for odd table rows.\"));\nexport const listDeemphasizedForeground = registerColor('list.deemphasizedForeground', { dark: '#8C8C8C', light: '#8E8E90', hcDark: '#A7A8A9', hcLight: '#666666' }, nls.localize('listDeemphasizedForeground', \"List/Tree foreground color for items that are deemphasized. \"));\n/**\n * Quick pick widget (dependent on List and tree colors)\n */\nexport const _deprecatedQuickInputListFocusBackground = registerColor('quickInput.list.focusBackground', { dark: null, light: null, hcDark: null, hcLight: null }, '', undefined, nls.localize('quickInput.list.focusBackground deprecation', \"Please use quickInputList.focusBackground instead\"));\nexport const quickInputListFocusForeground = registerColor('quickInputList.focusForeground', { dark: listActiveSelectionForeground, light: listActiveSelectionForeground, hcDark: listActiveSelectionForeground, hcLight: listActiveSelectionForeground }, nls.localize('quickInput.listFocusForeground', \"Quick picker foreground color for the focused item.\"));\nexport const quickInputListFocusIconForeground = registerColor('quickInputList.focusIconForeground', { dark: listActiveSelectionIconForeground, light: listActiveSelectionIconForeground, hcDark: listActiveSelectionIconForeground, hcLight: 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), hcDark: null, hcLight: null }, nls.localize('quickInput.listFocusBackground', \"Quick picker background color for the focused item.\"));\n/**\n * Menu colors\n */\nexport const menuBorder = registerColor('menu.border', { dark: null, light: null, hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('menuBorder', \"Border color of menus.\"));\nexport const menuForeground = registerColor('menu.foreground', { dark: selectForeground, light: foreground, hcDark: selectForeground, hcLight: selectForeground }, nls.localize('menuForeground', \"Foreground color of menu items.\"));\nexport const menuBackground = registerColor('menu.background', { dark: selectBackground, light: selectBackground, hcDark: selectBackground, hcLight: selectBackground }, nls.localize('menuBackground', \"Background color of menu items.\"));\nexport const menuSelectionForeground = registerColor('menu.selectionForeground', { dark: listActiveSelectionForeground, light: listActiveSelectionForeground, hcDark: listActiveSelectionForeground, hcLight: listActiveSelectionForeground }, nls.localize('menuSelectionForeground', \"Foreground color of the selected menu item in menus.\"));\nexport const menuSelectionBackground = registerColor('menu.selectionBackground', { dark: listActiveSelectionBackground, light: listActiveSelectionBackground, hcDark: listActiveSelectionBackground, hcLight: listActiveSelectionBackground }, nls.localize('menuSelectionBackground', \"Background color of the selected menu item in menus.\"));\nexport const menuSelectionBorder = registerColor('menu.selectionBorder', { dark: null, light: null, hcDark: activeContrastBorder, hcLight: activeContrastBorder }, nls.localize('menuSelectionBorder', \"Border color of the selected menu item in menus.\"));\nexport const menuSeparatorBackground = registerColor('menu.separatorBackground', { dark: '#606060', light: '#D4D4D4', hcDark: contrastBorder, hcLight: contrastBorder }, nls.localize('menuSeparatorBackground', \"Color of a separator menu item in menus.\"));\n/**\n * Toolbar colors\n */\nexport const toolbarHoverBackground = registerColor('toolbar.hoverBackground', { dark: '#5a5d5e50', light: '#b8b8b850', hcDark: null, hcLight: null }, nls.localize('toolbarHoverBackground', \"Toolbar background when hovering over actions using the mouse\"));\nexport const toolbarHoverOutline = registerColor('toolbar.hoverOutline', { dark: null, light: null, hcDark: activeContrastBorder, hcLight: 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), hcDark: null, hcLight: null }, nls.localize('toolbarActiveBackground', \"Toolbar background when holding the mouse over actions\"));\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)), hcDark: new Color(new RGBA(124, 124, 124, 0.3)), hcLight: new Color(new RGBA(10, 50, 100, 0.2)) }, nls.localize('snippetTabstopHighlightBackground', \"Highlight background color of a snippet tabstop.\"));\nexport const snippetTabstopHighlightBorder = registerColor('editor.snippetTabstopHighlightBorder', { dark: null, light: null, hcDark: null, hcLight: null }, nls.localize('snippetTabstopHighlightBorder', \"Highlight border color of a snippet tabstop.\"));\nexport const snippetFinalTabstopHighlightBackground = registerColor('editor.snippetFinalTabstopHighlightBackground', { dark: null, light: null, hcDark: null, hcLight: 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)), hcDark: '#525252', hcLight: '#292929' }, nls.localize('snippetFinalTabstopHighlightBorder', \"Highlight border color of the final tabstop of a snippet.\"));\n/**\n * Breadcrumb colors\n */\nexport const breadcrumbsForeground = registerColor('breadcrumb.foreground', { light: transparent(foreground, 0.8), dark: transparent(foreground, 0.8), hcDark: transparent(foreground, 0.8), hcLight: transparent(foreground, 0.8) }, nls.localize('breadcrumbsFocusForeground', \"Color of focused breadcrumb items.\"));\nexport const breadcrumbsBackground = registerColor('breadcrumb.background', { light: editorBackground, dark: editorBackground, hcDark: editorBackground, hcLight: 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), hcDark: lighten(foreground, 0.1), hcLight: 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), hcDark: lighten(foreground, 0.1), hcLight: lighten(foreground, 0.1) }, nls.localize('breadcrumbsSelectedForeground', \"Color of selected breadcrumb items.\"));\nexport const breadcrumbsPickerBackground = registerColor('breadcrumbPicker.background', { light: editorWidgetBackground, dark: editorWidgetBackground, hcDark: editorWidgetBackground, hcLight: editorWidgetBackground }, nls.localize('breadcrumbsSelectedBackground', \"Background color of breadcrumb item picker.\"));\n/**\n * Merge-conflict colors\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;\nexport const mergeCurrentHeaderBackground = registerColor('merge.currentHeaderBackground', { dark: currentBaseColor, light: currentBaseColor, hcDark: null, hcLight: 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), hcDark: transparent(mergeCurrentHeaderBackground, contentTransparency), hcLight: 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, hcDark: null, hcLight: 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), hcDark: transparent(mergeIncomingHeaderBackground, contentTransparency), hcLight: 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, hcDark: null, hcLight: 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), hcDark: transparent(mergeCommonHeaderBackground, contentTransparency), hcLight: 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);\nexport const mergeBorder = registerColor('merge.border', { dark: null, light: null, hcDark: '#C3DF6F', hcLight: '#007ACC' }, nls.localize('mergeBorder', 'Border color on headers and the splitter in inline merge-conflicts.'));\nexport const overviewRulerCurrentContentForeground = registerColor('editorOverviewRuler.currentContentForeground', { dark: transparent(mergeCurrentHeaderBackground, rulerTransparency), light: transparent(mergeCurrentHeaderBackground, rulerTransparency), hcDark: mergeBorder, hcLight: 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), hcDark: mergeBorder, hcLight: 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), hcDark: mergeBorder, hcLight: mergeBorder }, nls.localize('overviewRulerCommonContentForeground', 'Common ancestor overview ruler foreground for inline merge-conflicts.'));\nexport const overviewRulerFindMatchForeground = registerColor('editorOverviewRuler.findMatchForeground', { dark: '#d186167e', light: '#d186167e', hcDark: '#AB5A00', hcLight: '' }, nls.localize('overviewRulerFindMatchForeground', 'Overview ruler marker color for find matches. The color must not be opaque so as not to hide underlying decorations.'), true);\nexport const overviewRulerSelectionHighlightForeground = registerColor('editorOverviewRuler.selectionHighlightForeground', { dark: '#A0A0A0CC', light: '#A0A0A0CC', hcDark: '#A0A0A0CC', hcLight: '#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);\nexport const minimapFindMatch = registerColor('minimap.findMatchHighlight', { light: '#d18616', dark: '#d18616', hcDark: '#AB5A00', hcLight: '#0F4A85' }, nls.localize('minimapFindMatchHighlight', 'Minimap marker color for find matches.'), true);\nexport const minimapSelectionOccurrenceHighlight = registerColor('minimap.selectionOccurrenceHighlight', { light: '#c9c9c9', dark: '#676767', hcDark: '#ffffff', hcLight: '#0F4A85' }, nls.localize('minimapSelectionOccurrenceHighlight', 'Minimap marker color for repeating editor selections.'), true);\nexport const minimapSelection = registerColor('minimap.selectionHighlight', { light: '#ADD6FF', dark: '#264F78', hcDark: '#ffffff', hcLight: '#0F4A85' }, 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)), hcDark: new Color(new RGBA(255, 50, 50, 1)), hcLight: '#B5200D' }, nls.localize('minimapError', 'Minimap marker color for errors.'));\nexport const minimapWarning = registerColor('minimap.warningHighlight', { dark: editorWarningForeground, light: editorWarningForeground, hcDark: editorWarningBorder, hcLight: editorWarningBorder }, nls.localize('overviewRuleWarning', 'Minimap marker color for warnings.'));\nexport const minimapBackground = registerColor('minimap.background', { dark: null, light: null, hcDark: null, hcLight: null }, nls.localize('minimapBackground', \"Minimap background color.\"));\nexport const minimapForegroundOpacity = registerColor('minimap.foregroundOpacity', { dark: Color.fromHex('#000f'), light: Color.fromHex('#000f'), hcDark: Color.fromHex('#000f'), hcLight: Color.fromHex('#000f') }, nls.localize('minimapForegroundOpacity', 'Opacity of foreground elements rendered in the minimap. For example, \"#000000c0\" will render the elements with 75% opacity.'));\nexport const minimapSliderBackground = registerColor('minimapSlider.background', { light: transparent(scrollbarSliderBackground, 0.5), dark: transparent(scrollbarSliderBackground, 0.5), hcDark: transparent(scrollbarSliderBackground, 0.5), hcLight: 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), hcDark: transparent(scrollbarSliderHoverBackground, 0.5), hcLight: 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), hcDark: transparent(scrollbarSliderActiveBackground, 0.5), hcLight: transparent(scrollbarSliderActiveBackground, 0.5) }, nls.localize('minimapSliderActiveBackground', \"Minimap slider background color when clicked on.\"));\nexport const problemsErrorIconForeground = registerColor('problemsErrorIcon.foreground', { dark: editorErrorForeground, light: editorErrorForeground, hcDark: editorErrorForeground, hcLight: editorErrorForeground }, nls.localize('problemsErrorIconForeground', \"The color used for the problems error icon.\"));\nexport const problemsWarningIconForeground = registerColor('problemsWarningIcon.foreground', { dark: editorWarningForeground, light: editorWarningForeground, hcDark: editorWarningForeground, hcLight: editorWarningForeground }, nls.localize('problemsWarningIconForeground', \"The color used for the problems warning icon.\"));\nexport const problemsInfoIconForeground = registerColor('problemsInfoIcon.foreground', { dark: editorInfoForeground, light: editorInfoForeground, hcDark: editorInfoForeground, hcLight: editorInfoForeground }, nls.localize('problemsInfoIconForeground', \"The color used for the problems info icon.\"));\n/**\n * Chart colors\n */\nexport const chartsForeground = registerColor('charts.foreground', { dark: foreground, light: foreground, hcDark: foreground, hcLight: foreground }, nls.localize('chartsForeground', \"The foreground color used in charts.\"));\nexport const chartsLines = registerColor('charts.lines', { dark: transparent(foreground, .5), light: transparent(foreground, .5), hcDark: transparent(foreground, .5), hcLight: transparent(foreground, .5) }, nls.localize('chartsLines', \"The color used for horizontal lines in charts.\"));\nexport const chartsRed = registerColor('charts.red', { dark: editorErrorForeground, light: editorErrorForeground, hcDark: editorErrorForeground, hcLight: editorErrorForeground }, nls.localize('chartsRed', \"The red color used in chart visualizations.\"));\nexport const chartsBlue = registerColor('charts.blue', { dark: editorInfoForeground, light: editorInfoForeground, hcDark: editorInfoForeground, hcLight: editorInfoForeground }, nls.localize('chartsBlue', \"The blue color used in chart visualizations.\"));\nexport const chartsYellow = registerColor('charts.yellow', { dark: editorWarningForeground, light: editorWarningForeground, hcDark: editorWarningForeground, hcLight: editorWarningForeground }, nls.localize('chartsYellow', \"The yellow color used in chart visualizations.\"));\nexport const chartsOrange = registerColor('charts.orange', { dark: minimapFindMatch, light: minimapFindMatch, hcDark: minimapFindMatch, hcLight: minimapFindMatch }, nls.localize('chartsOrange', \"The orange color used in chart visualizations.\"));\nexport const chartsGreen = registerColor('charts.green', { dark: '#89D185', light: '#388A34', hcDark: '#89D185', hcLight: '#374e06' }, nls.localize('chartsGreen', \"The green color used in chart visualizations.\"));\nexport const chartsPurple = registerColor('charts.purple', { dark: '#B180D7', light: '#652D90', hcDark: '#B180D7', hcLight: '#652D90' }, nls.localize('chartsPurple', \"The purple color used in chart visualizations.\"));\n// ----- color functions\nexport function executeTransform(transform, theme) {\n var _a, _b, _c;\n switch (transform.op) {\n case 0 /* ColorTransformType.Darken */:\n return (_a = resolveColorValue(transform.value, theme)) === null || _a === void 0 ? void 0 : _a.darken(transform.factor);\n case 1 /* ColorTransformType.Lighten */:\n return (_b = resolveColorValue(transform.value, theme)) === null || _b === void 0 ? void 0 : _b.lighten(transform.factor);\n case 2 /* ColorTransformType.Transparent */:\n return (_c = resolveColorValue(transform.value, theme)) === null || _c === void 0 ? void 0 : _c.transparent(transform.factor);\n case 3 /* ColorTransformType.OneOf */:\n for (const candidate of transform.values) {\n const color = resolveColorValue(candidate, theme);\n if (color) {\n return color;\n }\n }\n return undefined;\n case 5 /* ColorTransformType.IfDefinedThenElse */:\n return resolveColorValue(theme.defines(transform.if) ? transform.then : transform.else, theme);\n case 4 /* ColorTransformType.LessProminent */: {\n const from = resolveColorValue(transform.value, theme);\n if (!from) {\n return undefined;\n }\n const backgroundColor = resolveColorValue(transform.background, theme);\n if (!backgroundColor) {\n return from.transparent(transform.factor * transform.transparency);\n }\n return from.isDarkerThan(backgroundColor)\n ? Color.getLighterColor(from, backgroundColor, transform.factor).transparent(transform.transparency)\n : Color.getDarkerColor(from, backgroundColor, transform.factor).transparent(transform.transparency);\n }\n default:\n throw assertNever(transform);\n }\n}\nexport function darken(colorValue, factor) {\n return { op: 0 /* ColorTransformType.Darken */, value: colorValue, factor };\n}\nexport function lighten(colorValue, factor) {\n return { op: 1 /* ColorTransformType.Lighten */, value: colorValue, factor };\n}\nexport function transparent(colorValue, factor) {\n return { op: 2 /* ColorTransformType.Transparent */, value: colorValue, factor };\n}\nexport function oneOf(...colorValues) {\n return { op: 3 /* ColorTransformType.OneOf */, values: colorValues };\n}\nexport function ifDefinedThenElse(ifArg, thenArg, elseArg) {\n return { op: 5 /* ColorTransformType.IfDefinedThenElse */, if: ifArg, then: thenArg, else: elseArg };\n}\nfunction lessProminent(colorValue, backgroundColorValue, factor, transparency) {\n return { op: 4 /* ColorTransformType.LessProminent */, value: colorValue, background: backgroundColorValue, factor, transparency };\n}\n// ----- implementation\n/**\n * @param colorValue Resolve a color value in the context of a theme\n */\nexport function resolveColorValue(colorValue, theme) {\n if (colorValue === null) {\n return undefined;\n }\n else if (typeof colorValue === 'string') {\n if (colorValue[0] === '#') {\n return Color.fromHex(colorValue);\n }\n return theme.getColor(colorValue);\n }\n else if (colorValue instanceof Color) {\n return colorValue;\n }\n else if (typeof colorValue === 'object') {\n return executeTransform(colorValue, theme);\n }\n return undefined;\n}\nexport const workbenchColorsSchemaId = 'vscode://schemas/workbench-colors';\nconst schemaRegistry = platform.Registry.as(JSONExtensions.JSONContribution);\nschemaRegistry.registerSchema(workbenchColorsSchemaId, colorRegistry.getColorSchema());\nconst delayer = new RunOnceScheduler(() => schemaRegistry.notifySchemaChanged(workbenchColorsSchemaId), 200);\ncolorRegistry.onDidChangeSchema(() => {\n if (!delayer.isScheduled()) {\n delayer.schedule();\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 *--------------------------------------------------------------------------------------------*/\nimport { RunOnceScheduler } from '../../../base/common/async.js';\nimport { Codicon, CSSIcon } from '../../../base/common/codicons.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { isString } from '../../../base/common/types.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { localize } from '../../../nls.js';\nimport { Extensions as JSONExtensions } from '../../jsonschemas/common/jsonContributionRegistry.js';\nimport * as platform from '../../registry/common/platform.js';\nimport { ThemeIcon } from './themeService.js';\n// icon registry\nexport const Extensions = {\n IconContribution: 'base.contributions.icons'\n};\nexport var IconContribution;\n(function (IconContribution) {\n function getDefinition(contribution, registry) {\n let definition = contribution.defaults;\n while (ThemeIcon.isThemeIcon(definition)) {\n const c = iconRegistry.getIcon(definition.id);\n if (!c) {\n return undefined;\n }\n definition = c.defaults;\n }\n return definition;\n }\n IconContribution.getDefinition = getDefinition;\n})(IconContribution || (IconContribution = {}));\nexport var IconFontDefinition;\n(function (IconFontDefinition) {\n function toJSONObject(iconFont) {\n return {\n weight: iconFont.weight,\n style: iconFont.style,\n src: iconFont.src.map(s => ({ format: s.format, location: s.location.toString() }))\n };\n }\n IconFontDefinition.toJSONObject = toJSONObject;\n function fromJSONObject(json) {\n const stringOrUndef = (s) => isString(s) ? s : undefined;\n if (json && Array.isArray(json.src) && json.src.every((s) => isString(s.format) && isString(s.location))) {\n return {\n weight: stringOrUndef(json.weight),\n style: stringOrUndef(json.style),\n src: json.src.map((s) => ({ format: s.format, location: URI.parse(s.location) }))\n };\n }\n return undefined;\n }\n IconFontDefinition.fromJSONObject = fromJSONObject;\n})(IconFontDefinition || (IconFontDefinition = {}));\nclass IconRegistry {\n constructor() {\n this._onDidChange = new Emitter();\n this.onDidChange = this._onDidChange.event;\n this.iconSchema = {\n definitions: {\n icons: {\n type: 'object',\n properties: {\n fontId: { type: 'string', description: localize('iconDefinition.fontId', 'The id of the font to use. If not set, the font that is defined first is used.') },\n fontCharacter: { type: 'string', description: localize('iconDefinition.fontCharacter', 'The font character associated with the icon definition.') }\n },\n additionalProperties: false,\n defaultSnippets: [{ body: { fontCharacter: '\\\\\\\\e030' } }]\n }\n },\n type: 'object',\n properties: {}\n };\n this.iconReferenceSchema = { type: 'string', pattern: `^${CSSIcon.iconNameExpression}$`, enum: [], enumDescriptions: [] };\n this.iconsById = {};\n this.iconFontsById = {};\n }\n registerIcon(id, defaults, description, deprecationMessage) {\n const existing = this.iconsById[id];\n if (existing) {\n if (description && !existing.description) {\n existing.description = description;\n this.iconSchema.properties[id].markdownDescription = `${description} $(${id})`;\n const enumIndex = this.iconReferenceSchema.enum.indexOf(id);\n if (enumIndex !== -1) {\n this.iconReferenceSchema.enumDescriptions[enumIndex] = description;\n }\n this._onDidChange.fire();\n }\n return existing;\n }\n const iconContribution = { id, description, defaults, deprecationMessage };\n this.iconsById[id] = iconContribution;\n const propertySchema = { $ref: '#/definitions/icons' };\n if (deprecationMessage) {\n propertySchema.deprecationMessage = deprecationMessage;\n }\n if (description) {\n propertySchema.markdownDescription = `${description}: $(${id})`;\n }\n this.iconSchema.properties[id] = propertySchema;\n this.iconReferenceSchema.enum.push(id);\n this.iconReferenceSchema.enumDescriptions.push(description || '');\n this._onDidChange.fire();\n return { id };\n }\n getIcons() {\n return Object.keys(this.iconsById).map(id => this.iconsById[id]);\n }\n getIcon(id) {\n return this.iconsById[id];\n }\n getIconSchema() {\n return this.iconSchema;\n }\n toString() {\n const sorter = (i1, i2) => {\n return i1.id.localeCompare(i2.id);\n };\n const classNames = (i) => {\n while (ThemeIcon.isThemeIcon(i.defaults)) {\n i = this.iconsById[i.defaults.id];\n }\n return `codicon codicon-${i ? i.id : ''}`;\n };\n const reference = [];\n reference.push(`| preview | identifier | default codicon ID | description`);\n reference.push(`| ----------- | --------------------------------- | --------------------------------- | --------------------------------- |`);\n const contributions = Object.keys(this.iconsById).map(key => this.iconsById[key]);\n for (const i of contributions.filter(i => !!i.description).sort(sorter)) {\n reference.push(`||${i.id}|${ThemeIcon.isThemeIcon(i.defaults) ? i.defaults.id : i.id}|${i.description || ''}|`);\n }\n reference.push(`| preview | identifier `);\n reference.push(`| ----------- | --------------------------------- |`);\n for (const i of contributions.filter(i => !ThemeIcon.isThemeIcon(i.defaults)).sort(sorter)) {\n reference.push(`||${i.id}|`);\n }\n return reference.join('\\n');\n }\n}\nconst iconRegistry = new IconRegistry();\nplatform.Registry.add(Extensions.IconContribution, iconRegistry);\nexport function registerIcon(id, defaults, description, deprecationMessage) {\n return iconRegistry.registerIcon(id, defaults, description, deprecationMessage);\n}\nexport function getIconRegistry() {\n return iconRegistry;\n}\nfunction initialize() {\n for (const icon of Codicon.getAll()) {\n iconRegistry.registerIcon(icon.id, icon.definition, icon.description);\n }\n}\ninitialize();\nexport const iconsSchemaId = 'vscode://schemas/icons';\nconst schemaRegistry = platform.Registry.as(JSONExtensions.JSONContribution);\nschemaRegistry.registerSchema(iconsSchemaId, iconRegistry.getIconSchema());\nconst delayer = new RunOnceScheduler(() => schemaRegistry.notifySchemaChanged(iconsSchemaId), 200);\niconRegistry.onDidChange(() => {\n if (!delayer.isScheduled()) {\n delayer.schedule();\n }\n});\n//setTimeout(_ => console.log(iconRegistry.toString()), 5000);\n// common icons\nexport const widgetClose = registerIcon('widget-close', Codicon.close, localize('widgetClose', 'Icon for the close action in widgets.'));\nexport const gotoPreviousLocation = registerIcon('goto-previous-location', Codicon.arrowUp, localize('previousChangeIcon', 'Icon for goto previous editor location.'));\nexport const gotoNextLocation = registerIcon('goto-next-location', Codicon.arrowDown, localize('nextChangeIcon', 'Icon for goto next editor location.'));\nexport const syncing = ThemeIcon.modify(Codicon.sync, 'spin');\nexport const spinningLoading = ThemeIcon.modify(Codicon.loading, 'spin');\n","/*---------------------------------------------------------------------------------------------\n * 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 { activeContrastBorder, badgeBackground, badgeForeground, contrastBorder, inputActiveOptionBackground, inputActiveOptionBorder, inputActiveOptionForeground, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, 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, listFocusAndSelectionOutline, listFilterWidgetShadow } from './colorRegistry.js';\nexport function computeStyles(theme, styleMap) {\n const styles = Object.create(null);\n for (const key in styleMap) {\n const value = styleMap[key];\n if (value) {\n styles[key] = resolveColorValue(value, theme);\n }\n }\n return styles;\n}\nexport function attachStyler(themeService, styleMap, widgetOrCallback) {\n function applyStyles() {\n const styles = computeStyles(themeService.getColorTheme(), styleMap);\n if (typeof widgetOrCallback === 'function') {\n widgetOrCallback(styles);\n }\n else {\n widgetOrCallback.style(styles);\n }\n }\n applyStyles();\n return themeService.onDidColorThemeChange(applyStyles);\n}\nexport function attachBadgeStyler(widget, themeService, style) {\n return attachStyler(themeService, {\n badgeBackground: (style === null || style === void 0 ? void 0 : style.badgeBackground) || badgeBackground,\n badgeForeground: (style === null || style === void 0 ? void 0 : style.badgeForeground) || badgeForeground,\n badgeBorder: contrastBorder\n }, widget);\n}\nexport function attachListStyler(widget, themeService, overrides) {\n return attachStyler(themeService, Object.assign(Object.assign({}, defaultListStyles), (overrides || {})), widget);\n}\nexport const defaultListStyles = {\n listFocusBackground,\n listFocusForeground,\n listFocusOutline,\n listActiveSelectionBackground,\n listActiveSelectionForeground,\n listActiveSelectionIconForeground,\n listFocusAndSelectionOutline,\n listFocusAndSelectionBackground: listActiveSelectionBackground,\n listFocusAndSelectionForeground: listActiveSelectionForeground,\n listInactiveSelectionBackground,\n listInactiveSelectionIconForeground,\n listInactiveSelectionForeground,\n listInactiveFocusBackground,\n listInactiveFocusOutline,\n listHoverBackground,\n listHoverForeground,\n listDropBackground,\n listSelectionOutline: activeContrastBorder,\n listHoverOutline: activeContrastBorder,\n listFilterWidgetBackground,\n listFilterWidgetOutline,\n listFilterWidgetNoMatchesOutline,\n listFilterWidgetShadow,\n treeIndentGuidesStroke,\n tableColumnsBorder,\n tableOddRowsBackgroundColor,\n inputActiveOptionBorder,\n inputActiveOptionForeground,\n inputActiveOptionBackground,\n inputBackground,\n inputForeground,\n inputBorder,\n inputValidationInfoBackground,\n inputValidationInfoForeground,\n inputValidationInfoBorder,\n inputValidationWarningBackground,\n inputValidationWarningForeground,\n inputValidationWarningBorder,\n inputValidationErrorBackground,\n inputValidationErrorForeground,\n inputValidationErrorBorder,\n};\nexport const defaultMenuStyles = {\n shadowColor: widgetShadow,\n borderColor: menuBorder,\n foregroundColor: menuForeground,\n backgroundColor: menuBackground,\n selectionForegroundColor: menuSelectionForeground,\n selectionBackgroundColor: menuSelectionBackground,\n selectionBorderColor: menuSelectionBorder,\n separatorColor: menuSeparatorBackground,\n scrollbarShadow: scrollbarShadow,\n scrollbarSliderBackground: scrollbarSliderBackground,\n scrollbarSliderHoverBackground: scrollbarSliderHoverBackground,\n scrollbarSliderActiveBackground: scrollbarSliderActiveBackground\n};\nexport function attachMenuStyler(widget, themeService, style) {\n return attachStyler(themeService, Object.assign(Object.assign({}, 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/**\n * Color scheme used by the OS and by color themes.\n */\nexport var ColorScheme;\n(function (ColorScheme) {\n ColorScheme[\"DARK\"] = \"dark\";\n ColorScheme[\"LIGHT\"] = \"light\";\n ColorScheme[\"HIGH_CONTRAST_DARK\"] = \"hcDark\";\n ColorScheme[\"HIGH_CONTRAST_LIGHT\"] = \"hcLight\";\n})(ColorScheme || (ColorScheme = {}));\nexport function isHighContrast(scheme) {\n return scheme === ColorScheme.HIGH_CONTRAST_DARK || scheme === ColorScheme.HIGH_CONTRAST_LIGHT;\n}\nexport function isDark(scheme) {\n return scheme === ColorScheme.DARK || scheme === ColorScheme.HIGH_CONTRAST_DARK;\n}\n","/*---------------------------------------------------------------------------------------------\n * 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 { CSSIcon } from '../../../base/common/codicons.js';\nimport { Emitter } from '../../../base/common/event.js';\nimport { Disposable, toDisposable } from '../../../base/common/lifecycle.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nimport * as platform from '../../registry/common/platform.js';\nimport { ColorScheme } from './theme.js';\nexport const IThemeService = createDecorator('themeService');\nexport var ThemeColor;\n(function (ThemeColor) {\n function isThemeColor(obj) {\n return obj && typeof obj === 'object' && typeof obj.id === 'string';\n }\n ThemeColor.isThemeColor = isThemeColor;\n})(ThemeColor || (ThemeColor = {}));\nexport function themeColorFromId(id) {\n return { id };\n}\nexport var ThemeIcon;\n(function (ThemeIcon) {\n function isThemeIcon(obj) {\n return obj && typeof obj === 'object' && typeof obj.id === 'string' && (typeof obj.color === 'undefined' || ThemeColor.isThemeColor(obj.color));\n }\n ThemeIcon.isThemeIcon = isThemeIcon;\n const _regexFromString = new RegExp(`^\\\\$\\\\((${CSSIcon.iconNameExpression}(?:${CSSIcon.iconModifierExpression})?)\\\\)$`);\n function fromString(str) {\n const match = _regexFromString.exec(str);\n if (!match) {\n return undefined;\n }\n const [, name] = match;\n return { id: name };\n }\n ThemeIcon.fromString = fromString;\n function fromId(id) {\n return { id };\n }\n ThemeIcon.fromId = fromId;\n function modify(icon, modifier) {\n let id = icon.id;\n const tildeIndex = id.lastIndexOf('~');\n if (tildeIndex !== -1) {\n id = id.substring(0, tildeIndex);\n }\n if (modifier) {\n id = `${id}~${modifier}`;\n }\n return { id };\n }\n ThemeIcon.modify = modify;\n function getModifier(icon) {\n const tildeIndex = icon.id.lastIndexOf('~');\n if (tildeIndex !== -1) {\n return icon.id.substring(tildeIndex + 1);\n }\n return undefined;\n }\n ThemeIcon.getModifier = getModifier;\n function isEqual(ti1, ti2) {\n var _a, _b;\n return ti1.id === ti2.id && ((_a = ti1.color) === null || _a === void 0 ? void 0 : _a.id) === ((_b = ti2.color) === null || _b === void 0 ? void 0 : _b.id);\n }\n ThemeIcon.isEqual = isEqual;\n function asThemeIcon(codicon, color) {\n return { id: codicon.id, color: color ? themeColorFromId(color) : undefined };\n }\n ThemeIcon.asThemeIcon = asThemeIcon;\n ThemeIcon.asClassNameArray = CSSIcon.asClassNameArray;\n ThemeIcon.asClassName = CSSIcon.asClassName;\n ThemeIcon.asCSSSelector = CSSIcon.asCSSSelector;\n})(ThemeIcon || (ThemeIcon = {}));\nexport function getThemeTypeSelector(type) {\n switch (type) {\n case ColorScheme.DARK: return 'vs-dark';\n case ColorScheme.HIGH_CONTRAST_DARK: return 'hc-black';\n case ColorScheme.HIGH_CONTRAST_LIGHT: return 'hc-light';\n default: return 'vs';\n }\n}\n// static theming participant\nexport const Extensions = {\n ThemingContribution: 'base.contributions.theming'\n};\nclass ThemingRegistry {\n constructor() {\n this.themingParticipants = [];\n this.themingParticipants = [];\n this.onThemingParticipantAddedEmitter = new Emitter();\n }\n onColorThemeChange(participant) {\n this.themingParticipants.push(participant);\n this.onThemingParticipantAddedEmitter.fire(participant);\n return toDisposable(() => {\n const idx = this.themingParticipants.indexOf(participant);\n this.themingParticipants.splice(idx, 1);\n });\n }\n getThemingParticipants() {\n return this.themingParticipants;\n }\n}\nconst themingRegistry = new ThemingRegistry();\nplatform.Registry.add(Extensions.ThemingContribution, themingRegistry);\nexport function registerThemingParticipant(participant) {\n return themingRegistry.onColorThemeChange(participant);\n}\n/**\n * Utility base class for all themable components.\n */\nexport class Themable extends Disposable {\n constructor(themeService) {\n super();\n this.themeService = themeService;\n this.theme = themeService.getColorTheme();\n // Hook up to theme changes\n this._register(this.themeService.onDidColorThemeChange(theme => this.onThemeChange(theme)));\n }\n onThemeChange(theme) {\n this.theme = theme;\n this.updateStyles();\n }\n updateStyles() {\n // Subclasses to override\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 *--------------------------------------------------------------------------------------------*/\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const IUndoRedoService = createDecorator('undoRedoService');\nexport class ResourceEditStackSnapshot {\n constructor(resource, elements) {\n this.resource = resource;\n this.elements = elements;\n }\n}\nexport class UndoRedoGroup {\n constructor() {\n this.id = UndoRedoGroup._ID++;\n this.order = 1;\n }\n nextOrder() {\n if (this.id === 0) {\n return 0;\n }\n return this.order++;\n }\n}\nUndoRedoGroup._ID = 0;\nUndoRedoGroup.None = new UndoRedoGroup();\nexport class UndoRedoSource {\n constructor() {\n this.id = UndoRedoSource._ID++;\n this.order = 1;\n }\n nextOrder() {\n if (this.id === 0) {\n return 0;\n }\n return this.order++;\n }\n}\nUndoRedoSource._ID = 0;\nUndoRedoSource.None = new UndoRedoSource();\n","/*---------------------------------------------------------------------------------------------\n * 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 { localize } from '../../../nls.js';\nimport { TernarySearchTree } from '../../../base/common/map.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const IWorkspaceContextService = createDecorator('contextService');\nexport function isSingleFolderWorkspaceIdentifier(obj) {\n const singleFolderIdentifier = obj;\n return typeof (singleFolderIdentifier === null || singleFolderIdentifier === void 0 ? void 0 : singleFolderIdentifier.id) === 'string' && URI.isUri(singleFolderIdentifier.uri);\n}\nexport function toWorkspaceIdentifier(workspace) {\n // Multi root\n if (workspace.configuration) {\n return {\n id: workspace.id,\n configPath: workspace.configuration\n };\n }\n // Single folder\n if (workspace.folders.length === 1) {\n return {\n id: workspace.id,\n uri: workspace.folders[0].uri\n };\n }\n // Empty workspace\n return undefined;\n}\nexport class Workspace {\n constructor(_id, folders, _transient, _configuration, _ignorePathCasing) {\n this._id = _id;\n this._transient = _transient;\n this._configuration = _configuration;\n this._ignorePathCasing = _ignorePathCasing;\n this._foldersMap = TernarySearchTree.forUris(this._ignorePathCasing, () => true);\n this.folders = folders;\n }\n get folders() {\n return this._folders;\n }\n set folders(folders) {\n this._folders = folders;\n this.updateFoldersMap();\n }\n get id() {\n return this._id;\n }\n get transient() {\n return this._transient;\n }\n get configuration() {\n return this._configuration;\n }\n set configuration(configuration) {\n this._configuration = configuration;\n }\n getFolder(resource) {\n if (!resource) {\n return null;\n }\n return this._foldersMap.findSubstr(resource) || null;\n }\n updateFoldersMap() {\n this._foldersMap = TernarySearchTree.forUris(this._ignorePathCasing, () => true);\n for (const folder of this.folders) {\n this._foldersMap.set(folder.uri, folder);\n }\n }\n toJSON() {\n return { id: this.id, folders: this.folders, transient: this.transient, configuration: this.configuration };\n }\n}\nexport class WorkspaceFolder {\n constructor(data, \n /**\n * Provides access to the original metadata for this workspace\n * folder. This can be different from the metadata provided in\n * this class:\n * - raw paths can be relative\n * - raw paths are not normalized\n */\n raw) {\n this.raw = raw;\n this.uri = data.uri;\n this.index = data.index;\n this.name = data.name;\n }\n toJSON() {\n return { uri: this.uri, name: this.name, index: this.index };\n }\n}\nexport const WORKSPACE_EXTENSION = 'code-workspace';\nexport const WORKSPACE_FILTER = [{ name: localize('codeWorkspace', \"Code Workspace\"), extensions: [WORKSPACE_EXTENSION] }];\n","/*---------------------------------------------------------------------------------------------\n * 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 { createDecorator } from '../../instantiation/common/instantiation.js';\nexport const IWorkspaceTrustManagementService = createDecorator('workspaceTrustManagementService');\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, \"default\"), secondTarget && __copyProps(secondTarget, mod, \"default\"));\n\n// src/fillers/monaco-editor-core.ts\nvar monaco_editor_core_exports = {};\n__reExport(monaco_editor_core_exports, monaco_editor_core_star);\nimport * as monaco_editor_core_star from \"../editor/editor.api.js\";\n\n// src/basic-languages/_.contribution.ts\nvar languageDefinitions = {};\nvar lazyLanguageLoaders = {};\nvar LazyLanguageLoader = class {\n static getOrCreate(languageId) {\n if (!lazyLanguageLoaders[languageId]) {\n lazyLanguageLoaders[languageId] = new LazyLanguageLoader(languageId);\n }\n return lazyLanguageLoaders[languageId];\n }\n _languageId;\n _loadingTriggered;\n _lazyLoadPromise;\n _lazyLoadPromiseResolve;\n _lazyLoadPromiseReject;\n constructor(languageId) {\n this._languageId = languageId;\n this._loadingTriggered = false;\n this._lazyLoadPromise = new Promise((resolve, reject) => {\n this._lazyLoadPromiseResolve = resolve;\n this._lazyLoadPromiseReject = reject;\n });\n }\n load() {\n if (!this._loadingTriggered) {\n this._loadingTriggered = true;\n languageDefinitions[this._languageId].loader().then((mod) => this._lazyLoadPromiseResolve(mod), (err) => this._lazyLoadPromiseReject(err));\n }\n return this._lazyLoadPromise;\n }\n};\nasync function loadLanguage(languageId) {\n await LazyLanguageLoader.getOrCreate(languageId).load();\n const model = monaco_editor_core_exports.editor.createModel(\"\", languageId);\n model.dispose();\n}\nfunction registerLanguage(def) {\n const languageId = def.id;\n languageDefinitions[languageId] = def;\n monaco_editor_core_exports.languages.register(def);\n const lazyLanguageLoader = LazyLanguageLoader.getOrCreate(languageId);\n monaco_editor_core_exports.languages.registerTokensProviderFactory(languageId, {\n create: async () => {\n const mod = await lazyLanguageLoader.load();\n return mod.language;\n }\n });\n monaco_editor_core_exports.languages.onLanguage(languageId, async () => {\n const mod = await lazyLanguageLoader.load();\n monaco_editor_core_exports.languages.setLanguageConfiguration(languageId, mod.conf);\n });\n}\nexport {\n loadLanguage,\n registerLanguage\n};\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/abap/abap.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"abap\",\n extensions: [\".abap\"],\n aliases: [\"abap\", \"ABAP\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/abap/abap\"], resolve, reject);\n });\n } else {\n return import(\"./abap.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/apex/apex.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"apex\",\n extensions: [\".cls\"],\n aliases: [\"Apex\", \"apex\"],\n mimetypes: [\"text/x-apex-source\", \"text/x-apex\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/apex/apex\"], resolve, reject);\n });\n } else {\n return import(\"./apex.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/azcli/azcli.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"azcli\",\n extensions: [\".azcli\"],\n aliases: [\"Azure CLI\", \"azcli\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/azcli/azcli\"], resolve, reject);\n });\n } else {\n return import(\"./azcli.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/bat/bat.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"bat\",\n extensions: [\".bat\", \".cmd\"],\n aliases: [\"Batch\", \"bat\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/bat/bat\"], resolve, reject);\n });\n } else {\n return import(\"./bat.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/bicep/bicep.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"bicep\",\n extensions: [\".bicep\"],\n aliases: [\"Bicep\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/bicep/bicep\"], resolve, reject);\n });\n } else {\n return import(\"./bicep.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/cameligo/cameligo.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"cameligo\",\n extensions: [\".mligo\"],\n aliases: [\"Cameligo\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/cameligo/cameligo\"], resolve, reject);\n });\n } else {\n return import(\"./cameligo.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/clojure/clojure.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"clojure\",\n extensions: [\".clj\", \".cljs\", \".cljc\", \".edn\"],\n aliases: [\"clojure\", \"Clojure\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/clojure/clojure\"], resolve, reject);\n });\n } else {\n return import(\"./clojure.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/coffee/coffee.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"coffeescript\",\n extensions: [\".coffee\"],\n aliases: [\"CoffeeScript\", \"coffeescript\", \"coffee\"],\n mimetypes: [\"text/x-coffeescript\", \"text/coffeescript\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/coffee/coffee\"], resolve, reject);\n });\n } else {\n return import(\"./coffee.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/cpp/cpp.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"c\",\n extensions: [\".c\", \".h\"],\n aliases: [\"C\", \"c\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/cpp/cpp\"], resolve, reject);\n });\n } else {\n return import(\"./cpp.js\");\n }\n }\n});\nregisterLanguage({\n id: \"cpp\",\n extensions: [\".cpp\", \".cc\", \".cxx\", \".hpp\", \".hh\", \".hxx\"],\n aliases: [\"C++\", \"Cpp\", \"cpp\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/cpp/cpp\"], resolve, reject);\n });\n } else {\n return import(\"./cpp.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/csharp/csharp.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"csharp\",\n extensions: [\".cs\", \".csx\", \".cake\"],\n aliases: [\"C#\", \"csharp\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/csharp/csharp\"], resolve, reject);\n });\n } else {\n return import(\"./csharp.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/csp/csp.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"csp\",\n extensions: [],\n aliases: [\"CSP\", \"csp\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/csp/csp\"], resolve, reject);\n });\n } else {\n return import(\"./csp.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/css/css.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"css\",\n extensions: [\".css\"],\n aliases: [\"CSS\", \"css\"],\n mimetypes: [\"text/css\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/css/css\"], resolve, reject);\n });\n } else {\n return import(\"./css.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/cypher/cypher.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"cypher\",\n extensions: [\".cypher\", \".cyp\"],\n aliases: [\"Cypher\", \"OpenCypher\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/cypher/cypher\"], resolve, reject);\n });\n } else {\n return import(\"./cypher.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/dart/dart.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"dart\",\n extensions: [\".dart\"],\n aliases: [\"Dart\", \"dart\"],\n mimetypes: [\"text/x-dart-source\", \"text/x-dart\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/dart/dart\"], resolve, reject);\n });\n } else {\n return import(\"./dart.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/dockerfile/dockerfile.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"dockerfile\",\n extensions: [\".dockerfile\"],\n filenames: [\"Dockerfile\"],\n aliases: [\"Dockerfile\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/dockerfile/dockerfile\"], resolve, reject);\n });\n } else {\n return import(\"./dockerfile.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/ecl/ecl.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"ecl\",\n extensions: [\".ecl\"],\n aliases: [\"ECL\", \"Ecl\", \"ecl\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/ecl/ecl\"], resolve, reject);\n });\n } else {\n return import(\"./ecl.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/elixir/elixir.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"elixir\",\n extensions: [\".ex\", \".exs\"],\n aliases: [\"Elixir\", \"elixir\", \"ex\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/elixir/elixir\"], resolve, reject);\n });\n } else {\n return import(\"./elixir.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/flow9/flow9.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"flow9\",\n extensions: [\".flow\"],\n aliases: [\"Flow9\", \"Flow\", \"flow9\", \"flow\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/flow9/flow9\"], resolve, reject);\n });\n } else {\n return import(\"./flow9.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/fsharp/fsharp.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"fsharp\",\n extensions: [\".fs\", \".fsi\", \".ml\", \".mli\", \".fsx\", \".fsscript\"],\n aliases: [\"F#\", \"FSharp\", \"fsharp\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/fsharp/fsharp\"], resolve, reject);\n });\n } else {\n return import(\"./fsharp.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/freemarker2/freemarker2.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"freemarker2\",\n extensions: [\".ftl\", \".ftlh\", \".ftlx\"],\n aliases: [\"FreeMarker2\", \"Apache FreeMarker2\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/freemarker2/freemarker2\"], resolve, reject);\n }).then((m) => m.TagAngleInterpolationDollar);\n } else {\n return import(\"./freemarker2.js\").then((m) => m.TagAutoInterpolationDollar);\n }\n }\n});\nregisterLanguage({\n id: \"freemarker2.tag-angle.interpolation-dollar\",\n aliases: [\"FreeMarker2 (Angle/Dollar)\", \"Apache FreeMarker2 (Angle/Dollar)\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/freemarker2/freemarker2\"], resolve, reject);\n }).then((m) => m.TagAngleInterpolationDollar);\n } else {\n return import(\"./freemarker2.js\").then((m) => m.TagAngleInterpolationDollar);\n }\n }\n});\nregisterLanguage({\n id: \"freemarker2.tag-bracket.interpolation-dollar\",\n aliases: [\"FreeMarker2 (Bracket/Dollar)\", \"Apache FreeMarker2 (Bracket/Dollar)\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/freemarker2/freemarker2\"], resolve, reject);\n }).then((m) => m.TagBracketInterpolationDollar);\n } else {\n return import(\"./freemarker2.js\").then((m) => m.TagBracketInterpolationDollar);\n }\n }\n});\nregisterLanguage({\n id: \"freemarker2.tag-angle.interpolation-bracket\",\n aliases: [\"FreeMarker2 (Angle/Bracket)\", \"Apache FreeMarker2 (Angle/Bracket)\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/freemarker2/freemarker2\"], resolve, reject);\n }).then((m) => m.TagAngleInterpolationBracket);\n } else {\n return import(\"./freemarker2.js\").then((m) => m.TagAngleInterpolationBracket);\n }\n }\n});\nregisterLanguage({\n id: \"freemarker2.tag-bracket.interpolation-bracket\",\n aliases: [\"FreeMarker2 (Bracket/Bracket)\", \"Apache FreeMarker2 (Bracket/Bracket)\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/freemarker2/freemarker2\"], resolve, reject);\n }).then((m) => m.TagBracketInterpolationBracket);\n } else {\n return import(\"./freemarker2.js\").then((m) => m.TagBracketInterpolationBracket);\n }\n }\n});\nregisterLanguage({\n id: \"freemarker2.tag-auto.interpolation-dollar\",\n aliases: [\"FreeMarker2 (Auto/Dollar)\", \"Apache FreeMarker2 (Auto/Dollar)\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/freemarker2/freemarker2\"], resolve, reject);\n }).then((m) => m.TagAutoInterpolationDollar);\n } else {\n return import(\"./freemarker2.js\").then((m) => m.TagAutoInterpolationDollar);\n }\n }\n});\nregisterLanguage({\n id: \"freemarker2.tag-auto.interpolation-bracket\",\n aliases: [\"FreeMarker2 (Auto/Bracket)\", \"Apache FreeMarker2 (Auto/Bracket)\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/freemarker2/freemarker2\"], resolve, reject);\n }).then((m) => m.TagAutoInterpolationBracket);\n } else {\n return import(\"./freemarker2.js\").then((m) => m.TagAutoInterpolationBracket);\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/go/go.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"go\",\n extensions: [\".go\"],\n aliases: [\"Go\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/go/go\"], resolve, reject);\n });\n } else {\n return import(\"./go.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/graphql/graphql.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"graphql\",\n extensions: [\".graphql\", \".gql\"],\n aliases: [\"GraphQL\", \"graphql\", \"gql\"],\n mimetypes: [\"application/graphql\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/graphql/graphql\"], resolve, reject);\n });\n } else {\n return import(\"./graphql.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/handlebars/handlebars.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"handlebars\",\n extensions: [\".handlebars\", \".hbs\"],\n aliases: [\"Handlebars\", \"handlebars\", \"hbs\"],\n mimetypes: [\"text/x-handlebars-template\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/handlebars/handlebars\"], resolve, reject);\n });\n } else {\n return import(\"./handlebars.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/hcl/hcl.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"hcl\",\n extensions: [\".tf\", \".tfvars\", \".hcl\"],\n aliases: [\"Terraform\", \"tf\", \"HCL\", \"hcl\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/hcl/hcl\"], resolve, reject);\n });\n } else {\n return import(\"./hcl.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/html/html.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"html\",\n extensions: [\".html\", \".htm\", \".shtml\", \".xhtml\", \".mdoc\", \".jsp\", \".asp\", \".aspx\", \".jshtm\"],\n aliases: [\"HTML\", \"htm\", \"html\", \"xhtml\"],\n mimetypes: [\"text/html\", \"text/x-jshtm\", \"text/template\", \"text/ng-template\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/html/html\"], resolve, reject);\n });\n } else {\n return import(\"./html.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/ini/ini.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"ini\",\n extensions: [\".ini\", \".properties\", \".gitconfig\"],\n filenames: [\"config\", \".gitattributes\", \".gitconfig\", \".editorconfig\"],\n aliases: [\"Ini\", \"ini\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/ini/ini\"], resolve, reject);\n });\n } else {\n return import(\"./ini.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/java/java.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"java\",\n extensions: [\".java\", \".jav\"],\n aliases: [\"Java\", \"java\"],\n mimetypes: [\"text/x-java-source\", \"text/x-java\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/java/java\"], resolve, reject);\n });\n } else {\n return import(\"./java.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/javascript/javascript.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"javascript\",\n extensions: [\".js\", \".es6\", \".jsx\", \".mjs\", \".cjs\"],\n firstLine: \"^#!.*\\\\bnode\",\n filenames: [\"jakefile\"],\n aliases: [\"JavaScript\", \"javascript\", \"js\"],\n mimetypes: [\"text/javascript\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/javascript/javascript\"], resolve, reject);\n });\n } else {\n return import(\"./javascript.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/julia/julia.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"julia\",\n extensions: [\".jl\"],\n aliases: [\"julia\", \"Julia\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/julia/julia\"], resolve, reject);\n });\n } else {\n return import(\"./julia.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/kotlin/kotlin.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"kotlin\",\n extensions: [\".kt\"],\n aliases: [\"Kotlin\", \"kotlin\"],\n mimetypes: [\"text/x-kotlin-source\", \"text/x-kotlin\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/kotlin/kotlin\"], resolve, reject);\n });\n } else {\n return import(\"./kotlin.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/less/less.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"less\",\n extensions: [\".less\"],\n aliases: [\"Less\", \"less\"],\n mimetypes: [\"text/x-less\", \"text/less\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/less/less\"], resolve, reject);\n });\n } else {\n return import(\"./less.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/lexon/lexon.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"lexon\",\n extensions: [\".lex\"],\n aliases: [\"Lexon\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/lexon/lexon\"], resolve, reject);\n });\n } else {\n return import(\"./lexon.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/lua/lua.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"lua\",\n extensions: [\".lua\"],\n aliases: [\"Lua\", \"lua\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/lua/lua\"], resolve, reject);\n });\n } else {\n return import(\"./lua.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/liquid/liquid.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"liquid\",\n extensions: [\".liquid\", \".html.liquid\"],\n aliases: [\"Liquid\", \"liquid\"],\n mimetypes: [\"application/liquid\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/liquid/liquid\"], resolve, reject);\n });\n } else {\n return import(\"./liquid.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/m3/m3.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"m3\",\n extensions: [\".m3\", \".i3\", \".mg\", \".ig\"],\n aliases: [\"Modula-3\", \"Modula3\", \"modula3\", \"m3\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/m3/m3\"], resolve, reject);\n });\n } else {\n return import(\"./m3.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/markdown/markdown.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"markdown\",\n extensions: [\".md\", \".markdown\", \".mdown\", \".mkdn\", \".mkd\", \".mdwn\", \".mdtxt\", \".mdtext\"],\n aliases: [\"Markdown\", \"markdown\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/markdown/markdown\"], resolve, reject);\n });\n } else {\n return import(\"./markdown.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/mips/mips.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"mips\",\n extensions: [\".s\"],\n aliases: [\"MIPS\", \"MIPS-V\"],\n mimetypes: [\"text/x-mips\", \"text/mips\", \"text/plaintext\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/mips/mips\"], resolve, reject);\n });\n } else {\n return import(\"./mips.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/msdax/msdax.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"msdax\",\n extensions: [\".dax\", \".msdax\"],\n aliases: [\"DAX\", \"MSDAX\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/msdax/msdax\"], resolve, reject);\n });\n } else {\n return import(\"./msdax.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/mysql/mysql.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"mysql\",\n extensions: [],\n aliases: [\"MySQL\", \"mysql\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/mysql/mysql\"], resolve, reject);\n });\n } else {\n return import(\"./mysql.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/objective-c/objective-c.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"objective-c\",\n extensions: [\".m\"],\n aliases: [\"Objective-C\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/objective-c/objective-c\"], resolve, reject);\n });\n } else {\n return import(\"./objective-c.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/pascal/pascal.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"pascal\",\n extensions: [\".pas\", \".p\", \".pp\"],\n aliases: [\"Pascal\", \"pas\"],\n mimetypes: [\"text/x-pascal-source\", \"text/x-pascal\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/pascal/pascal\"], resolve, reject);\n });\n } else {\n return import(\"./pascal.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/pascaligo/pascaligo.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"pascaligo\",\n extensions: [\".ligo\"],\n aliases: [\"Pascaligo\", \"ligo\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/pascaligo/pascaligo\"], resolve, reject);\n });\n } else {\n return import(\"./pascaligo.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/perl/perl.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"perl\",\n extensions: [\".pl\"],\n aliases: [\"Perl\", \"pl\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/perl/perl\"], resolve, reject);\n });\n } else {\n return import(\"./perl.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/pgsql/pgsql.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"pgsql\",\n extensions: [],\n aliases: [\"PostgreSQL\", \"postgres\", \"pg\", \"postgre\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/pgsql/pgsql\"], resolve, reject);\n });\n } else {\n return import(\"./pgsql.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/php/php.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"php\",\n extensions: [\".php\", \".php4\", \".php5\", \".phtml\", \".ctp\"],\n aliases: [\"PHP\", \"php\"],\n mimetypes: [\"application/x-php\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/php/php\"], resolve, reject);\n });\n } else {\n return import(\"./php.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/pla/pla.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"pla\",\n extensions: [\".pla\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/pla/pla\"], resolve, reject);\n });\n } else {\n return import(\"./pla.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/postiats/postiats.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"postiats\",\n extensions: [\".dats\", \".sats\", \".hats\"],\n aliases: [\"ATS\", \"ATS/Postiats\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/postiats/postiats\"], resolve, reject);\n });\n } else {\n return import(\"./postiats.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/powerquery/powerquery.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"powerquery\",\n extensions: [\".pq\", \".pqm\"],\n aliases: [\"PQ\", \"M\", \"Power Query\", \"Power Query M\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/powerquery/powerquery\"], resolve, reject);\n });\n } else {\n return import(\"./powerquery.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/powershell/powershell.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"powershell\",\n extensions: [\".ps1\", \".psm1\", \".psd1\"],\n aliases: [\"PowerShell\", \"powershell\", \"ps\", \"ps1\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/powershell/powershell\"], resolve, reject);\n });\n } else {\n return import(\"./powershell.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/protobuf/protobuf.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"proto\",\n extensions: [\".proto\"],\n aliases: [\"protobuf\", \"Protocol Buffers\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/protobuf/protobuf\"], resolve, reject);\n });\n } else {\n return import(\"./protobuf.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/pug/pug.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"pug\",\n extensions: [\".jade\", \".pug\"],\n aliases: [\"Pug\", \"Jade\", \"jade\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/pug/pug\"], resolve, reject);\n });\n } else {\n return import(\"./pug.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/python/python.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"python\",\n extensions: [\".py\", \".rpy\", \".pyw\", \".cpy\", \".gyp\", \".gypi\"],\n aliases: [\"Python\", \"py\"],\n firstLine: \"^#!/.*\\\\bpython[0-9.-]*\\\\b\",\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/python/python\"], resolve, reject);\n });\n } else {\n return import(\"./python.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/qsharp/qsharp.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"qsharp\",\n extensions: [\".qs\"],\n aliases: [\"Q#\", \"qsharp\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/qsharp/qsharp\"], resolve, reject);\n });\n } else {\n return import(\"./qsharp.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/r/r.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"r\",\n extensions: [\".r\", \".rhistory\", \".rmd\", \".rprofile\", \".rt\"],\n aliases: [\"R\", \"r\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/r/r\"], resolve, reject);\n });\n } else {\n return import(\"./r.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/razor/razor.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"razor\",\n extensions: [\".cshtml\"],\n aliases: [\"Razor\", \"razor\"],\n mimetypes: [\"text/x-cshtml\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/razor/razor\"], resolve, reject);\n });\n } else {\n return import(\"./razor.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/redis/redis.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"redis\",\n extensions: [\".redis\"],\n aliases: [\"redis\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/redis/redis\"], resolve, reject);\n });\n } else {\n return import(\"./redis.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/redshift/redshift.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"redshift\",\n extensions: [],\n aliases: [\"Redshift\", \"redshift\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/redshift/redshift\"], resolve, reject);\n });\n } else {\n return import(\"./redshift.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/restructuredtext/restructuredtext.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"restructuredtext\",\n extensions: [\".rst\"],\n aliases: [\"reStructuredText\", \"restructuredtext\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/restructuredtext/restructuredtext\"], resolve, reject);\n });\n } else {\n return import(\"./restructuredtext.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/ruby/ruby.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"ruby\",\n extensions: [\".rb\", \".rbx\", \".rjs\", \".gemspec\", \".pp\"],\n filenames: [\"rakefile\", \"Gemfile\"],\n aliases: [\"Ruby\", \"rb\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/ruby/ruby\"], resolve, reject);\n });\n } else {\n return import(\"./ruby.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/rust/rust.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"rust\",\n extensions: [\".rs\", \".rlib\"],\n aliases: [\"Rust\", \"rust\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/rust/rust\"], resolve, reject);\n });\n } else {\n return import(\"./rust.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/sb/sb.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"sb\",\n extensions: [\".sb\"],\n aliases: [\"Small Basic\", \"sb\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/sb/sb\"], resolve, reject);\n });\n } else {\n return import(\"./sb.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/scala/scala.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"scala\",\n extensions: [\".scala\", \".sc\", \".sbt\"],\n aliases: [\"Scala\", \"scala\", \"SBT\", \"Sbt\", \"sbt\", \"Dotty\", \"dotty\"],\n mimetypes: [\"text/x-scala-source\", \"text/x-scala\", \"text/x-sbt\", \"text/x-dotty\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/scala/scala\"], resolve, reject);\n });\n } else {\n return import(\"./scala.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/scheme/scheme.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"scheme\",\n extensions: [\".scm\", \".ss\", \".sch\", \".rkt\"],\n aliases: [\"scheme\", \"Scheme\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/scheme/scheme\"], resolve, reject);\n });\n } else {\n return import(\"./scheme.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/scss/scss.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"scss\",\n extensions: [\".scss\"],\n aliases: [\"Sass\", \"sass\", \"scss\"],\n mimetypes: [\"text/x-scss\", \"text/scss\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/scss/scss\"], resolve, reject);\n });\n } else {\n return import(\"./scss.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/shell/shell.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"shell\",\n extensions: [\".sh\", \".bash\"],\n aliases: [\"Shell\", \"sh\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/shell/shell\"], resolve, reject);\n });\n } else {\n return import(\"./shell.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/solidity/solidity.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"sol\",\n extensions: [\".sol\"],\n aliases: [\"sol\", \"solidity\", \"Solidity\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/solidity/solidity\"], resolve, reject);\n });\n } else {\n return import(\"./solidity.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/sophia/sophia.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"aes\",\n extensions: [\".aes\"],\n aliases: [\"aes\", \"sophia\", \"Sophia\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/sophia/sophia\"], resolve, reject);\n });\n } else {\n return import(\"./sophia.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/sparql/sparql.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"sparql\",\n extensions: [\".rq\"],\n aliases: [\"sparql\", \"SPARQL\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/sparql/sparql\"], resolve, reject);\n });\n } else {\n return import(\"./sparql.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/sql/sql.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"sql\",\n extensions: [\".sql\"],\n aliases: [\"SQL\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/sql/sql\"], resolve, reject);\n });\n } else {\n return import(\"./sql.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/st/st.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"st\",\n extensions: [\".st\", \".iecst\", \".iecplc\", \".lc3lib\"],\n aliases: [\"StructuredText\", \"scl\", \"stl\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/st/st\"], resolve, reject);\n });\n } else {\n return import(\"./st.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/swift/swift.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"swift\",\n aliases: [\"Swift\", \"swift\"],\n extensions: [\".swift\"],\n mimetypes: [\"text/swift\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/swift/swift\"], resolve, reject);\n });\n } else {\n return import(\"./swift.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/systemverilog/systemverilog.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"systemverilog\",\n extensions: [\".sv\", \".svh\"],\n aliases: [\"SV\", \"sv\", \"SystemVerilog\", \"systemverilog\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/systemverilog/systemverilog\"], resolve, reject);\n });\n } else {\n return import(\"./systemverilog.js\");\n }\n }\n});\nregisterLanguage({\n id: \"verilog\",\n extensions: [\".v\", \".vh\"],\n aliases: [\"V\", \"v\", \"Verilog\", \"verilog\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/systemverilog/systemverilog\"], resolve, reject);\n });\n } else {\n return import(\"./systemverilog.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/tcl/tcl.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"tcl\",\n extensions: [\".tcl\"],\n aliases: [\"tcl\", \"Tcl\", \"tcltk\", \"TclTk\", \"tcl/tk\", \"Tcl/Tk\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/tcl/tcl\"], resolve, reject);\n });\n } else {\n return import(\"./tcl.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/twig/twig.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"twig\",\n extensions: [\".twig\"],\n aliases: [\"Twig\", \"twig\"],\n mimetypes: [\"text/x-twig\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/twig/twig\"], resolve, reject);\n });\n } else {\n return import(\"./twig.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/typescript/typescript.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"typescript\",\n extensions: [\".ts\", \".tsx\"],\n aliases: [\"TypeScript\", \"ts\", \"typescript\"],\n mimetypes: [\"text/typescript\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/typescript/typescript\"], resolve, reject);\n });\n } else {\n return import(\"./typescript.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/vb/vb.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"vb\",\n extensions: [\".vb\"],\n aliases: [\"Visual Basic\", \"vb\"],\n loader: () => {\n if (false) {\n return new Promise((resolve, reject) => {\n __require([\"vs/basic-languages/vb/vb\"], resolve, reject);\n });\n } else {\n return import(\"./vb.js\");\n }\n }\n});\n","/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.34.0(9d278685b078158491964f8fd7ac9628fffa0f30)\n * Released under the MIT license\n * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt\n *-----------------------------------------------------------------------------*/\n\n// src/basic-languages/xml/xml.contribution.ts\nimport { registerLanguage } from \"../_.contribution.js\";\nregisterLanguage({\n id: \"xml\",\n extensions: [\n \".xml\",\n \".dtd\",\n \".ascx\",\n \".csproj\",\n \".config\",\n \".wxi\",\n \".wxl\",\n \".wxs\",\n \".xaml\",\n \".svg\",\n \".svgz\",\n \".opf\",\n \".xsl\"\n ],\n firstLine: \"(\\\\<\\\\?xml.*)|(\\\\