Repository: vscode
Issue: Merge Editor Jumps
Labels: bug,merge-editor



![Image](https://github.com/microsoft/vscode/assets/2931520/7ac56531-9c8e-4d53-9cdb-06155e7e1cf8)

(Pressing Space)

```json
{
    "languageId": "typescript",
    "base": "\t\tthis._register(applyObservableDecorations(this._editors.original, derived(reader => {\n\t\t\t/** @description decorations */\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\n\t\t\tconst result = curUnchangedRegions.map<IModelDeltaDecoration>(r => ({\n\t\t\t\trange: r.originalRange.toInclusiveRange()!,\n\t\t\t\toptions: unchangedLinesDecoration,\n\t\t\t}));\n\t\t\tfor (const r of curUnchangedRegions) {\n\t\t\t\tif (r.shouldHideControls(reader)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trange: Range.fromPositions(new Position(r.originalLineNumber, 1)),\n\t\t\t\t\t\toptions: unchangedLinesDecorationShow\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t})));\n\n\t\tthis._register(applyObservableDecorations(this._editors.modified, derived(reader => {\n\t\t\t/** @description decorations */\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\n\t\t\tconst result = curUnchangedRegions.map<IModelDeltaDecoration>(r => ({\n\t\t\t\trange: r.modifiedRange.toInclusiveRange()!,\n\t\t\t\toptions: unchangedLinesDecoration,\n\t\t\t}));\n\t\t\tfor (const r of curUnchangedRegions) {\n\t\t\t\tif (r.shouldHideControls(reader)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trange: LineRange.ofLength(r.modifiedLineNumber, 1).toInclusiveRange()!,\n\t\t\t\t\t\toptions: unchangedLinesDecorationShow\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t})));\n\n\t\tthis._register(applyViewZones(this._editors.original, viewZones.map(v => v.origViewZones), v => this._isUpdatingViewZones = v));\n\t\tthis._register(applyViewZones(this._editors.modified, viewZones.map(v => v.modViewZones), v => this._isUpdatingViewZones = v));\n\n\t\tthis._register(autorun((reader) => {\n\t\t\t/** @description update folded unchanged regions */\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\n\t\t\tthis._editors.original.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenOriginalRange(reader).toInclusiveRange()).filter(isDefined));\n\t\t\tthis._editors.modified.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenModifiedRange(reader).toInclusiveRange()).filter(isDefined));\n\t\t}));\n\n\t\tthis._register(this._editors.modified.onMouseUp(event => {\n\t\t\tif (!event.event.rightButton && event.target.position && event.target.element?.className.includes('fold-unchanged')) {\n\t\t\t\tconst lineNumber = event.target.position.lineNumber;\n\t\t\t\tconst model = this._diffModel.get();\n\t\t\t\tif (!model) { return; }\n\t\t\t\tconst region = model.unchangedRegions.get().find(r => r.modifiedRange.includes(lineNumber));\n\t\t\t\tif (!region) { return; }\n\t\t\t\tregion.setState(0, 0, undefined);\n\t\t\t\tevent.event.stopPropagation();\n\t\t\t\tevent.event.preventDefault();\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(this._editors.original.onMouseUp(event => {\n\t\t\tif (!event.event.rightButton && event.target.position && event.target.element?.className.includes('fold-unchanged')) {\n\t\t\t\tconst lineNumber = event.target.position.lineNumber;\n\t\t\t\tconst model = this._diffModel.get();\n\t\t\t\tif (!model) { return; }\n\t\t\t\tconst region = model.unchangedRegions.get().find(r => r.originalRange.includes(lineNumber));\n\t\t\t\tif (!region) { return; }\n\t\t\t\tregion.setState(0, 0, undefined);\n\t\t\t\tevent.event.stopPropagation();\n\t\t\t\tevent.event.preventDefault();\n\t\t\t}\n\t\t}));\n\t}\n}\n\nclass CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget {\n\tprivate readonly _nodes = h('div.diff-hidden-lines', [\n\t\th('div.top@top', { title: localize('diff.hiddenLines.top', 'Click or drag to show more above') }),\n\t\th('div.center@content', { style: { display: 'flex' } }, [\n\t\t\th('div@first', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } },\n\t\t\t\t[$('a', { title: localize('showAll', 'Show all'), role: 'button', onclick: () => { this._unchangedRegion.showAll(undefined); } }, ...renderLabelWithIcons('$(unfold)'))]\n\t\t\t),\n\t\t\th('div@others', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } }),\n\t\t]),\n\t\th('div.bottom@bottom', { title: localize('diff.bottom', 'Click or drag to show more below'), role: 'button' }),\n\t]);\n\n\tconstructor(\n\t\tprivate readonly _editor: ICodeEditor,\n\t\t_viewZone: PlaceholderViewZone,\n\t\tprivate readonly _unchangedRegion: UnchangedRegion,\n\t\tprivate readonly hide: boolean,\n\t) {\n\t\tconst root = h('div.diff-hidden-lines-widget');\n\t\tsuper(_editor, _viewZone, root.root);\n\t\troot.root.appendChild(this._nodes.root);\n\n\t\tconst layoutInfo = observableFromEvent(this._editor.onDidLayoutChange, () =>\n\t\t\tthis._editor.getLayoutInfo()\n\t\t);\n\n\t\tif (!this.hide) {\n\t\t\tthis._register(applyStyle(this._nodes.first, { width: layoutInfo.map((l) => l.contentLeft) }));\n\t\t} else {\n\t\t\treset(this._nodes.first);\n\t\t}\n\n\t\tconst editor = this._editor;\n\n\t\tthis._register(addDisposableListener(this._nodes.top, 'mousedown', e => {\n\t\t\tif (e.button !== 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._nodes.top.classList.toggle('dragging', true);\n\t\t\tthis._nodes.root.classList.toggle('dragging', true);\n\t\t\te.preventDefault();\n\t\t\tconst startTop = e.clientY;\n\t\t\tlet didMove = false;\n\t\t\tconst cur = this._unchangedRegion.visibleLineCountTop.get();\n\t\t\tthis._unchangedRegion.isDragged.set(true, undefined);\n\n\n\t\t\tconst mouseMoveListener = addDisposableListener(window, 'mousemove', e => {\n\t\t\t\tconst currentTop = e.clientY;\n\t\t\t\tconst delta = currentTop - startTop;\n\t\t\t\tdidMove = didMove || Math.abs(delta) > 2;\n\t\t\t\tconst lineDelta = Math.round(delta / editor.getOption(EditorOption.lineHeight));\n\t\t\t\tconst newVal = Math.max(0, Math.min(cur + lineDelta, this._unchangedRegion.getMaxVisibleLineCountTop()));\n\t\t\t\tthis._unchangedRegion.visibleLineCountTop.set(newVal, undefined);\n\t\t\t});\n\n\t\t\tconst mouseUpListener = addDisposableListener(window, 'mouseup', e => {\n\t\t\t\tif (!didMove) {\n\t\t\t\t\tthis._unchangedRegion.showMoreAbove(20, undefined);\n\t\t\t\t}\n\t\t\t\tthis._nodes.top.classList.toggle('dragging', false);\n\t\t\t\tthis._nodes.root.classList.toggle('dragging', false);\n\t\t\t\tthis._unchangedRegion.isDragged.set(false, undefined);\n\t\t\t\tmouseMoveListener.dispose();\n\t\t\t\tmouseUpListener.dispose();\n\t\t\t});\n\t\t}));\n\n\t\tthis._register(addDisposableListener(this._nodes.bottom, 'mousedown', e => {\n\t\t\tif (e.button !== 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._nodes.bottom.classList.toggle('dragging', true);\n\t\t\tthis._nodes.root.classList.toggle('dragging', true);\n\t\t\te.preventDefault();\n\t\t\tconst startTop = e.clientY;\n\t\t\tlet didMove = false;\n\t\t\tconst cur = this._unchangedRegion.visibleLineCountBottom.get();\n\t\t\tthis._unchangedRegion.isDragged.set(true, undefined);\n\n\t\t\tconst mouseMoveListener = addDisposableListener(window, 'mousemove', e => {\n\t\t\t\tconst currentTop = e.clientY;\n\t\t\t\tconst delta = currentTop - startTop;\n\t\t\t\tdidMove = didMove || Math.abs(delta) > 2;\n\t\t\t\tconst lineDelta = Math.round(delta / editor.getOption(EditorOption.lineHeight));\n\t\t\t\tconst newVal = Math.max(0, Math.min(cur - lineDelta, this._unchangedRegion.getMaxVisibleLineCountBottom()));\n\t\t\t\tconst top = editor.getTopForLineNumber(this._unchangedRegion.originalRange.endLineNumberExclusive);\n\t\t\t\tthis._unchangedRegion.visibleLineCountBottom.set(newVal, undefined);\n\t\t\t\tconst top2 = editor.getTopForLineNumber(this._unchangedRegion.originalRange.endLineNumberExclusive);\n\t\t\t\teditor.setScrollTop(editor.getScrollTop() + (top2 - top));\n\t\t\t});\n\n\t\t\tconst mouseUpListener = addDisposableListener(window, 'mouseup', e => {\n\t\t\t\tthis._unchangedRegion.isDragged.set(false, undefined);\n\n\t\t\t\tif (!didMove) {\n\t\t\t\t\tconst top = editor.getTopForLineNumber(this._unchangedRegion.originalRange.endLineNumberExclusive);\n\n\t\t\t\t\tthis._unchangedRegion.showMoreBelow(20, undefined);\n\t\t\t\t\tconst top2 = editor.getTopForLineNumber(this._unchangedRegion.originalRange.endLineNumberExclusive);\n\t\t\t\t\teditor.setScrollTop(editor.getScrollTop() + (top2 - top));\n\t\t\t\t}\n\t\t\t\tthis._nodes.bottom.classList.toggle('dragging', false);\n\t\t\t\tthis._nodes.root.classList.toggle('dragging', false);\n\t\t\t\tmouseMoveListener.dispose();\n\t\t\t\tmouseUpListener.dispose();\n\t\t\t});\n\t\t}));\n\n\t\tthis._register(autorun(reader => {\n\t\t\t/** @description update labels */\n\n\t\t\tconst children: HTMLElement[] = [];\n\t\t\tif (!this.hide && true) {\n\t\t\t\tconst lineCount = _unchangedRegion.getHiddenModifiedRange(reader).length;\n\t\t\t\tconst linesHiddenText = localize('hiddenLines', '{0} Hidden Lines', lineCount);\n\t\t\t\tchildren.push($('span', { title: linesHiddenText }, linesHiddenText));\n\t\t\t}\n\n\t\t\t// TODO@hediet implement breadcrumbs for collapsed regions\n\t\t\t/*\n\t\t\tif (_unchangedRegion.originalLineNumber === 48) {\n\t\t\t\tchildren.push($('span', undefined, '\\u00a0|\\u00a0'));\n\t\t\t\tchildren.push($('span', { title: 'test' }, ...renderLabelWithIcons('$(symbol-class) DiffEditorWidget2')));\n\t\t\t} else if (_unchangedRegion.originalLineNumber === 88) {\n\t\t\t\tchildren.push($('span', undefined, '\\u00a0|\\u00a0'));\n\t\t\t\tchildren.push($('span', { title: 'test' }, ...renderLabelWithIcons('$(symbol-constructor) constructor')));\n\t\t\t}\n\t\t\t*/\n\n\t\t\treset(this._nodes.others, ...children);\n\n\t\t}));\n\t}\n}\n",
    "input1": "\t\tthis._register(applyObservableDecorations(this._editors.original, derived(reader => {\n\t\t\t/** @description decorations */\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\n\t\t\tconst result = curUnchangedRegions.map<IModelDeltaDecoration>(r => ({\n\t\t\t\trange: r.originalRange.toInclusiveRange()!,\n\t\t\t\toptions: unchangedLinesDecoration,\n\t\t\t}));\n\t\t\tfor (const r of curUnchangedRegions) {\n\t\t\t\tif (r.shouldHideControls(reader)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trange: Range.fromPositions(new Position(r.originalLineNumber, 1)),\n\t\t\t\t\t\toptions: unchangedLinesDecorationShow\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t})));\n\n\t\tthis._register(applyObservableDecorations(this._editors.modified, derived(reader => {\n\t\t\t/** @description decorations */\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\n\t\t\tconst result = curUnchangedRegions.map<IModelDeltaDecoration>(r => ({\n\t\t\t\trange: r.modifiedRange.toInclusiveRange()!,\n\t\t\t\toptions: unchangedLinesDecoration,\n\t\t\t}));\n\t\t\tfor (const r of curUnchangedRegions) {\n\t\t\t\tif (r.shouldHideControls(reader)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trange: LineRange.ofLength(r.modifiedLineNumber, 1).toInclusiveRange()!,\n\t\t\t\t\t\toptions: unchangedLinesDecorationShow\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t})));\n\n\t\tthis._register(applyViewZones(this._editors.original, viewZones.map(v => v.origViewZones), v => this._isUpdatingViewZones = v));\n\t\tthis._register(applyViewZones(this._editors.modified, viewZones.map(v => v.modViewZones), v => this._isUpdatingViewZones = v));\n\n\t\tthis._register(autorun((reader) => {\n\t\t\t/** @description update folded unchanged regions */\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\n\t\t\tthis._editors.original.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenOriginalRange(reader).toInclusiveRange()).filter(isDefined));\n\t\t\tthis._editors.modified.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenModifiedRange(reader).toInclusiveRange()).filter(isDefined));\n\t\t}));\n\n\t\tthis._register(this._editors.modified.onMouseUp(event => {\n\t\t\tif (!event.event.rightButton && event.target.position && event.target.element?.className.includes('fold-unchanged')) {\n\t\t\t\tconst lineNumber = event.target.position.lineNumber;\n\t\t\t\tconst model = this._diffModel.get();\n\t\t\t\tif (!model) { return; }\n\t\t\t\tconst region = model.unchangedRegions.get().find(r => r.modifiedRange.includes(lineNumber));\n\t\t\t\tif (!region) { return; }\n\t\t\t\tregion.setState(0, 0, undefined);\n\t\t\t\tevent.event.stopPropagation();\n\t\t\t\tevent.event.preventDefault();\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(this._editors.original.onMouseUp(event => {\n\t\t\tif (!event.event.rightButton && event.target.position && event.target.element?.className.includes('fold-unchanged')) {\n\t\t\t\tconst lineNumber = event.target.position.lineNumber;\n\t\t\t\tconst model = this._diffModel.get();\n\t\t\t\tif (!model) { return; }\n\t\t\t\tconst region = model.unchangedRegions.get().find(r => r.originalRange.includes(lineNumber));\n\t\t\t\tif (!region) { return; }\n\t\t\t\tregion.setState(0, 0, undefined);\n\t\t\t\tevent.event.stopPropagation();\n\t\t\t\tevent.event.preventDefault();\n\t\t\t}\n\t\t}));\n\t}\n}\n\nclass DisposableCancellationTokenSource extends CancellationTokenSource {\n\tpublic override dispose() {\n\t\tsuper.dispose(true);\n\t}\n}\n\nclass OutlineSource extends Disposable {\n\tprivate readonly _currentModel = observableValue<OutlineModel | undefined>('current model', undefined);\n\n\tconstructor(\n\t\t@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,\n\t\tprivate readonly _textModel: ITextModel,\n\t) {\n\t\tsuper();\n\n\t\tconst documentSymbolProviderChanged = observableSignalFromEvent(\n\t\t\t'documentSymbolProvider.onDidChange',\n\t\t\tthis._languageFeaturesService.documentSymbolProvider.onDidChange\n\t\t);\n\n\t\tconst textModelChanged = observableSignalFromEvent(\n\t\t\t'_textModel.onDidChangeContent',\n\t\t\tEvent.debounce<any>(e => this._textModel.onDidChangeContent(e), () => undefined, 100)\n\t\t);\n\n\t\tthis._register(autorunWithStore(async (reader, store) => {\n\t\t\tdocumentSymbolProviderChanged.read(reader);\n\t\t\ttextModelChanged.read(reader);\n\n\t\t\tconst src = store.add(new DisposableCancellationTokenSource());\n\t\t\tconst model = await OutlineModel.create(\n\t\t\t\tthis._languageFeaturesService.documentSymbolProvider,\n\t\t\t\tthis._textModel,\n\t\t\t\tsrc.token,\n\t\t\t);\n\t\t\tif (store.isDisposed) { return; }\n\n\t\t\tthis._currentModel.set(model, undefined);\n\t\t}));\n\t}\n\n\tpublic getBreadcrumbItems(startRange: LineRange, reader: IReader): { name: string; kind: SymbolKind }[] {\n\t\tconst m = this._currentModel.read(reader);\n\t\tif (!m) { return []; }\n\t\tconst symbols = m.asListOfDocumentSymbols()\n\t\t\t.filter(s => startRange.contains(s.range.startLineNumber) && !startRange.contains(s.range.endLineNumber));\n\t\tsymbols.sort(reverseOrder(compareBy(s => s.range.endLineNumber - s.range.startLineNumber, numberComparator)));\n\t\treturn symbols.map(s => ({ name: s.name, kind: s.kind }));\n\t}\n}\n\nclass CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget {\n\tprivate readonly _nodes = h('div.diff-hidden-lines', [\n\t\th('div.top@top', { title: localize('diff.hiddenLines.top', 'Click or drag to show more above') }),\n\t\th('div.center@content', { style: { display: 'flex' } }, [\n\t\t\th('div@first', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } },\n\t\t\t\t[$('a', { title: localize('showAll', 'Show all'), role: 'button', onclick: () => { this._unchangedRegion.showAll(undefined); } }, ...renderLabelWithIcons('$(unfold)'))]\n\t\t\t),\n\t\t\th('div@others', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } }),\n\t\t]),\n\t\th('div.bottom@bottom', { title: localize('diff.bottom', 'Click or drag to show more below'), role: 'button' }),\n\t]);\n\n\tconstructor(\n\t\tprivate readonly _editor: ICodeEditor,\n\t\t_viewZone: PlaceholderViewZone,\n\t\tprivate readonly _unchangedRegion: UnchangedRegion,\n\t\tprivate readonly _unchangedRegionRange: LineRange,\n\t\tprivate readonly hide: boolean,\n\t\tprivate readonly _modifiedOutlineSource: OutlineSource,\n\t) {\n\t\tconst root = h('div.diff-hidden-lines-widget');\n\t\tsuper(_editor, _viewZone, root.root);\n\t\troot.root.appendChild(this._nodes.root);\n\n\t\tconst layoutInfo = observableFromEvent(this._editor.onDidLayoutChange, () =>\n\t\t\tthis._editor.getLayoutInfo()\n\t\t);\n\n\t\tif (!this.hide) {\n\t\t\tthis._register(applyStyle(this._nodes.first, { width: layoutInfo.map((l) => l.contentLeft) }));\n\t\t} else {\n\t\t\treset(this._nodes.first);\n\t\t}\n\n\t\tconst editor = this._editor;\n\n\t\tthis._register(addDisposableListener(this._nodes.top, 'mousedown', e => {\n\t\t\tif (e.button !== 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._nodes.top.classList.toggle('dragging', true);\n\t\t\tthis._nodes.root.classList.toggle('dragging', true);\n\t\t\te.preventDefault();\n\t\t\tconst startTop = e.clientY;\n\t\t\tlet didMove = false;\n\t\t\tconst cur = this._unchangedRegion.visibleLineCountTop.get();\n\t\t\tthis._unchangedRegion.isDragged.set(true, undefined);\n\n\n\t\t\tconst mouseMoveListener = addDisposableListener(window, 'mousemove', e => {\n\t\t\t\tconst currentTop = e.clientY;\n\t\t\t\tconst delta = currentTop - startTop;\n\t\t\t\tdidMove = didMove || Math.abs(delta) > 2;\n\t\t\t\tconst lineDelta = Math.round(delta / editor.getOption(EditorOption.lineHeight));\n\t\t\t\tconst newVal = Math.max(0, Math.min(cur + lineDelta, this._unchangedRegion.getMaxVisibleLineCountTop()));\n\t\t\t\tthis._unchangedRegion.visibleLineCountTop.set(newVal, undefined);\n\t\t\t});\n\n\t\t\tconst mouseUpListener = addDisposableListener(window, 'mouseup', e => {\n\t\t\t\tif (!didMove) {\n\t\t\t\t\tthis._unchangedRegion.showMoreAbove(20, undefined);\n\t\t\t\t}\n\t\t\t\tthis._nodes.top.classList.toggle('dragging', false);\n\t\t\t\tthis._nodes.root.classList.toggle('dragging', false);\n\t\t\t\tthis._unchangedRegion.isDragged.set(false, undefined);\n\t\t\t\tmouseMoveListener.dispose();\n\t\t\t\tmouseUpListener.dispose();\n\t\t\t});\n\t\t}));\n\n\t\tthis._register(addDisposableListener(this._nodes.bottom, 'mousedown', e => {\n\t\t\tif (e.button !== 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._nodes.bottom.classList.toggle('dragging', true);\n\t\t\tthis._nodes.root.classList.toggle('dragging', true);\n\t\t\te.preventDefault();\n\t\t\tconst startTop = e.clientY;\n\t\t\tlet didMove = false;\n\t\t\tconst cur = this._unchangedRegion.visibleLineCountBottom.get();\n\t\t\tthis._unchangedRegion.isDragged.set(true, undefined);\n\n\t\t\tconst mouseMoveListener = addDisposableListener(window, 'mousemove', e => {\n\t\t\t\tconst currentTop = e.clientY;\n\t\t\t\tconst delta = currentTop - startTop;\n\t\t\t\tdidMove = didMove || Math.abs(delta) > 2;\n\t\t\t\tconst lineDelta = Math.round(delta / editor.getOption(EditorOption.lineHeight));\n\t\t\t\tconst newVal = Math.max(0, Math.min(cur - lineDelta, this._unchangedRegion.getMaxVisibleLineCountBottom()));\n\t\t\t\tconst top = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\n\t\t\t\tthis._unchangedRegion.visibleLineCountBottom.set(newVal, undefined);\n\t\t\t\tconst top2 = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\n\t\t\t\teditor.setScrollTop(editor.getScrollTop() + (top2 - top));\n\t\t\t});\n\n\t\t\tconst mouseUpListener = addDisposableListener(window, 'mouseup', e => {\n\t\t\t\tthis._unchangedRegion.isDragged.set(false, undefined);\n\n\t\t\t\tif (!didMove) {\n\t\t\t\t\tconst top = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\n\n\t\t\t\t\tthis._unchangedRegion.showMoreBelow(20, undefined);\n\t\t\t\t\tconst top2 = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\n\t\t\t\t\teditor.setScrollTop(editor.getScrollTop() + (top2 - top));\n\t\t\t\t}\n\t\t\t\tthis._nodes.bottom.classList.toggle('dragging', false);\n\t\t\t\tthis._nodes.root.classList.toggle('dragging', false);\n\t\t\t\tmouseMoveListener.dispose();\n\t\t\t\tmouseUpListener.dispose();\n\t\t\t});\n\t\t}));\n\n\t\tthis._register(autorun(reader => {\n\t\t\t/** @description update labels */\n\n\t\t\tconst children: HTMLElement[] = [];\n\t\t\tif (!this.hide) {\n\t\t\t\tconst lineCount = _unchangedRegion.getHiddenModifiedRange(reader).length;\n\t\t\t\tconst linesHiddenText = localize('hiddenLines', '{0} Hidden Lines', lineCount);\n\t\t\t\tchildren.push($('span', { title: linesHiddenText }, linesHiddenText));\n\n\t\t\t\tconst range = this._unchangedRegion.getHiddenModifiedRange(reader);\n\t\t\t\tconst items = this._modifiedOutlineSource.getBreadcrumbItems(range, reader);\n\n\t\t\t\tif (items.length > 0) {\n\t\t\t\t\tchildren.push($('span', undefined, '\\u00a0|\\u00a0'));\n\n\t\t\t\t\tlet isFirst = true;\n\t\t\t\t\tfor (const item of items) {\n\t\t\t\t\t\tif (!isFirst) {\n\t\t\t\t\t\t\tchildren.push($('span', {}, ' ', renderIcon(Codicon.chevronRight), ' '));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst icon = SymbolKinds.toIcon(item.kind);\n\t\t\t\t\t\tchildren.push($('span', {}, renderIcon(icon), ' ', item.name));\n\t\t\t\t\t\tisFirst = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treset(this._nodes.others, ...children);\n\t\t}));\n\t}\n}\n",
    "input2": "\t\tthis._register(applyObservableDecorations(this._editors.original, derived(reader => {\n\t\t\t/** @description decorations */\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\n\t\t\tconst result = curUnchangedRegions.map<IModelDeltaDecoration>(r => ({\n\t\t\t\trange: r.originalRange.toInclusiveRange()!,\n\t\t\t\toptions: unchangedLinesDecoration,\n\t\t\t}));\n\t\t\tfor (const r of curUnchangedRegions) {\n\t\t\t\tif (r.shouldHideControls(reader)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trange: Range.fromPositions(new Position(r.originalLineNumber, 1)),\n\t\t\t\t\t\toptions: unchangedLinesDecorationShow\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t})));\n\n\t\tthis._register(applyObservableDecorations(this._editors.modified, derived(reader => {\n\t\t\t/** @description decorations */\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\n\t\t\tconst result = curUnchangedRegions.map<IModelDeltaDecoration>(r => ({\n\t\t\t\trange: r.modifiedRange.toInclusiveRange()!,\n\t\t\t\toptions: unchangedLinesDecoration,\n\t\t\t}));\n\t\t\tfor (const r of curUnchangedRegions) {\n\t\t\t\tif (r.shouldHideControls(reader)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trange: LineRange.ofLength(r.modifiedLineNumber, 1).toInclusiveRange()!,\n\t\t\t\t\t\toptions: unchangedLinesDecorationShow\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t})));\n\n\t\tthis._register(applyViewZones(this._editors.original, viewZones.map(v => v.origViewZones), v => this._isUpdatingViewZones = v));\n\t\tthis._register(applyViewZones(this._editors.modified, viewZones.map(v => v.modViewZones), v => this._isUpdatingViewZones = v));\n\n\t\tthis._register(autorun((reader) => {\n\t\t\t/** @description update folded unchanged regions */\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\n\t\t\tthis._editors.original.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenOriginalRange(reader).toInclusiveRange()).filter(isDefined));\n\t\t\tthis._editors.modified.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenModifiedRange(reader).toInclusiveRange()).filter(isDefined));\n\t\t}));\n\n\t\tthis._register(this._editors.modified.onMouseUp(event => {\n\t\t\tif (!event.event.rightButton && event.target.position && event.target.element?.className.includes('fold-unchanged')) {\n\t\t\t\tconst lineNumber = event.target.position.lineNumber;\n\t\t\t\tconst model = this._diffModel.get();\n\t\t\t\tif (!model) { return; }\n\t\t\t\tconst region = model.unchangedRegions.get().find(r => r.modifiedRange.includes(lineNumber));\n\t\t\t\tif (!region) { return; }\n\t\t\t\tregion.setState(0, 0, undefined);\n\t\t\t\tevent.event.stopPropagation();\n\t\t\t\tevent.event.preventDefault();\n\t\t\t}\n\t\t}));\n\n\t\tthis._register(this._editors.original.onMouseUp(event => {\n\t\t\tif (!event.event.rightButton && event.target.position && event.target.element?.className.includes('fold-unchanged')) {\n\t\t\t\tconst lineNumber = event.target.position.lineNumber;\n\t\t\t\tconst model = this._diffModel.get();\n\t\t\t\tif (!model) { return; }\n\t\t\t\tconst region = model.unchangedRegions.get().find(r => r.originalRange.includes(lineNumber));\n\t\t\t\tif (!region) { return; }\n\t\t\t\tregion.setState(0, 0, undefined);\n\t\t\t\tevent.event.stopPropagation();\n\t\t\t\tevent.event.preventDefault();\n\t\t\t}\n\t\t}));\n\t}\n}\n\nclass CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget {\n\tprivate readonly _nodes = h('div.diff-hidden-lines', [\n\t\th('div.top@top', { title: localize('diff.hiddenLines.top', 'Click or drag to show more above') }),\n\t\th('div.center@content', { style: { display: 'flex' } }, [\n\t\t\th('div@first', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } },\n\t\t\t\t[$('a', { title: localize('showAll', 'Show all'), role: 'button', onclick: () => { this.showAll(); } }, ...renderLabelWithIcons('$(unfold)'))]\n\t\t\t),\n\t\t\th('div@others', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } }),\n\t\t]),\n\t\th('div.bottom@bottom', { title: localize('diff.bottom', 'Click or drag to show more below'), role: 'button' }),\n\t]);\n\n\tconstructor(\n\t\tprivate readonly _editor: ICodeEditor,\n\t\t_viewZone: PlaceholderViewZone,\n\t\tprivate readonly _unchangedRegion: UnchangedRegion,\n\t\tprivate readonly hide: boolean,\n\t) {\n\t\tconst root = h('div.diff-hidden-lines-widget');\n\t\tsuper(_editor, _viewZone, root.root);\n\t\troot.root.appendChild(this._nodes.root);\n\n\t\tconst layoutInfo = observableFromEvent(this._editor.onDidLayoutChange, () =>\n\t\t\tthis._editor.getLayoutInfo()\n\t\t);\n\n\t\tif (!this.hide) {\n\t\t\tthis._register(applyStyle(this._nodes.first, { width: layoutInfo.map((l) => l.contentLeft) }));\n\t\t} else {\n\t\t\treset(this._nodes.first);\n\t\t}\n\n\t\tconst editor = this._editor;\n\n\t\tthis._register(addDisposableListener(this._nodes.top, 'mousedown', e => {\n\t\t\tif (e.button !== 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._nodes.top.classList.toggle('dragging', true);\n\t\t\tthis._nodes.root.classList.toggle('dragging', true);\n\t\t\te.preventDefault();\n\t\t\tconst startTop = e.clientY;\n\t\t\tlet didMove = false;\n\t\t\tconst cur = this._unchangedRegion.visibleLineCountTop.get();\n\t\t\tthis._unchangedRegion.isDragged.set(true, undefined);\n\n\n\t\t\tconst mouseMoveListener = addDisposableListener(window, 'mousemove', e => {\n\t\t\t\tconst currentTop = e.clientY;\n\t\t\t\tconst delta = currentTop - startTop;\n\t\t\t\tdidMove = didMove || Math.abs(delta) > 2;\n\t\t\t\tconst lineDelta = Math.round(delta / editor.getOption(EditorOption.lineHeight));\n\t\t\t\tconst newVal = Math.max(0, Math.min(cur + lineDelta, this._unchangedRegion.getMaxVisibleLineCountTop()));\n\t\t\t\tthis._unchangedRegion.visibleLineCountTop.set(newVal, undefined);\n\t\t\t});\n\n\t\t\tconst mouseUpListener = addDisposableListener(window, 'mouseup', e => {\n\t\t\t\tif (!didMove) {\n\t\t\t\t\tthis._unchangedRegion.showMoreAbove(20, undefined);\n\t\t\t\t}\n\t\t\t\tthis._nodes.top.classList.toggle('dragging', false);\n\t\t\t\tthis._nodes.root.classList.toggle('dragging', false);\n\t\t\t\tthis._unchangedRegion.isDragged.set(false, undefined);\n\t\t\t\tmouseMoveListener.dispose();\n\t\t\t\tmouseUpListener.dispose();\n\t\t\t});\n\t\t}));\n\n\t\tthis._register(addDisposableListener(this._nodes.bottom, 'mousedown', e => {\n\t\t\tif (e.button !== 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis._nodes.bottom.classList.toggle('dragging', true);\n\t\t\tthis._nodes.root.classList.toggle('dragging', true);\n\t\t\te.preventDefault();\n\t\t\tconst startTop = e.clientY;\n\t\t\tlet didMove = false;\n\t\t\tconst cur = this._unchangedRegion.visibleLineCountBottom.get();\n\t\t\tthis._unchangedRegion.isDragged.set(true, undefined);\n\n\t\t\tconst mouseMoveListener = addDisposableListener(window, 'mousemove', e => {\n\t\t\t\tconst currentTop = e.clientY;\n\t\t\t\tconst delta = currentTop - startTop;\n\t\t\t\tdidMove = didMove || Math.abs(delta) > 2;\n\t\t\t\tconst lineDelta = Math.round(delta / editor.getOption(EditorOption.lineHeight));\n\t\t\t\tconst newVal = Math.max(0, Math.min(cur - lineDelta, this._unchangedRegion.getMaxVisibleLineCountBottom()));\n\t\t\t\tconst top = editor.getTopForLineNumber(this._unchangedRegion.originalRange.endLineNumberExclusive);\n\t\t\t\tthis._unchangedRegion.visibleLineCountBottom.set(newVal, undefined);\n\t\t\t\tconst top2 = editor.getTopForLineNumber(this._unchangedRegion.originalRange.endLineNumberExclusive);\n\t\t\t\teditor.setScrollTop(editor.getScrollTop() + (top2 - top));\n\t\t\t});\n\n\t\t\tconst mouseUpListener = addDisposableListener(window, 'mouseup', e => {\n\t\t\t\tthis._unchangedRegion.isDragged.set(false, undefined);\n\n\t\t\t\tif (!didMove) {\n\t\t\t\t\tconst top = editor.getTopForLineNumber(this._unchangedRegion.originalRange.endLineNumberExclusive);\n\n\t\t\t\t\tthis._unchangedRegion.showMoreBelow(20, undefined);\n\t\t\t\t\tconst top2 = editor.getTopForLineNumber(this._unchangedRegion.originalRange.endLineNumberExclusive);\n\t\t\t\t\teditor.setScrollTop(editor.getScrollTop() + (top2 - top));\n\t\t\t\t}\n\t\t\t\tthis._nodes.bottom.classList.toggle('dragging', false);\n\t\t\t\tthis._nodes.root.classList.toggle('dragging', false);\n\t\t\t\tmouseMoveListener.dispose();\n\t\t\t\tmouseUpListener.dispose();\n\t\t\t});\n\t\t}));\n\n\t\tthis._register(autorun(reader => {\n\t\t\t/** @description update labels */\n\n\t\t\tconst children: HTMLElement[] = [];\n\t\t\tif (!this.hide && true) {\n\t\t\t\tconst lineCount = _unchangedRegion.getHiddenModifiedRange(reader).length;\n\t\t\t\tconst linesHiddenText = localize('hiddenLines', '{0} Hidden Lines', lineCount);\n\t\t\t\tconst span = $('span', { title: localize('diff.hiddenLines.expandAll', 'Double click to show all unchanged region') }, linesHiddenText);\n\t\t\t\tspan.addEventListener('dblclick', e => {\n\t\t\t\t\tif (e.button !== 0) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tthis.showAll();\n\t\t\t\t});\n\t\t\t\tchildren.push(span);\n\t\t\t}\n\n\t\t\t// TODO@hediet implement breadcrumbs for collapsed regions\n\t\t\t/*\n\t\t\tif (_unchangedRegion.originalLineNumber === 48) {\n\t\t\t\tchildren.push($('span', undefined, '\\u00a0|\\u00a0'));\n\t\t\t\tchildren.push($('span', { title: 'test' }, ...renderLabelWithIcons('$(symbol-class) DiffEditorWidget2')));\n\t\t\t} else if (_unchangedRegion.originalLineNumber === 88) {\n\t\t\t\tchildren.push($('span', undefined, '\\u00a0|\\u00a0'));\n\t\t\t\tchildren.push($('span', { title: 'test' }, ...renderLabelWithIcons('$(symbol-constructor) constructor')));\n\t\t\t}\n\t\t\t*/\n\n\t\t\treset(this._nodes.others, ...children);\n\n\t\t}));\n\t}\n\n\tprivate showAll() { this._unchangedRegion.showAll(undefined); }\n\n}\n",
    "result": "\t\tthis._register(applyObservableDecorations(this._editors.original, derived(reader => {\r\n\t\t\t/** @description decorations */\r\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\r\n\t\t\tconst result = curUnchangedRegions.map<IModelDeltaDecoration>(r => ({\r\n\t\t\t\trange: r.originalRange.toInclusiveRange()!,\r\n\t\t\t\toptions: unchangedLinesDecoration,\r\n\t\t\t}));\r\n\t\t\tfor (const r of curUnchangedRegions) {\r\n\t\t\t\tif (r.shouldHideControls(reader)) {\r\n\t\t\t\t\tresult.push({\r\n\t\t\t\t\t\trange: Range.fromPositions(new Position(r.originalLineNumber, 1)),\r\n\t\t\t\t\t\toptions: unchangedLinesDecorationShow\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn result;\r\n\t\t})));\r\n\r\n\t\tthis._register(applyObservableDecorations(this._editors.modified, derived(reader => {\r\n\t\t\t/** @description decorations */\r\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\r\n\t\t\tconst result = curUnchangedRegions.map<IModelDeltaDecoration>(r => ({\r\n\t\t\t\trange: r.modifiedRange.toInclusiveRange()!,\r\n\t\t\t\toptions: unchangedLinesDecoration,\r\n\t\t\t}));\r\n\t\t\tfor (const r of curUnchangedRegions) {\r\n\t\t\t\tif (r.shouldHideControls(reader)) {\r\n\t\t\t\t\tresult.push({\r\n\t\t\t\t\t\trange: LineRange.ofLength(r.modifiedLineNumber, 1).toInclusiveRange()!,\r\n\t\t\t\t\t\toptions: unchangedLinesDecorationShow\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn result;\r\n\t\t})));\r\n\r\n\t\tthis._register(applyViewZones(this._editors.original, viewZones.map(v => v.origViewZones), v => this._isUpdatingViewZones = v));\r\n\t\tthis._register(applyViewZones(this._editors.modified, viewZones.map(v => v.modViewZones), v => this._isUpdatingViewZones = v));\r\n\r\n\t\tthis._register(autorun((reader) => {\r\n\t\t\t/** @description update folded unchanged regions */\r\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\r\n\t\t\tthis._editors.original.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenOriginalRange(reader).toInclusiveRange()).filter(isDefined));\r\n\t\t\tthis._editors.modified.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenModifiedRange(reader).toInclusiveRange()).filter(isDefined));\r\n\t\t}));\r\n\r\n\t\tthis._register(this._editors.modified.onMouseUp(event => {\r\n\t\t\tif (!event.event.rightButton && event.target.position && event.target.element?.className.includes('fold-unchanged')) {\r\n\t\t\t\tconst lineNumber = event.target.position.lineNumber;\r\n\t\t\t\tconst model = this._diffModel.get();\r\n\t\t\t\tif (!model) { return; }\r\n\t\t\t\tconst region = model.unchangedRegions.get().find(r => r.modifiedRange.includes(lineNumber));\r\n\t\t\t\tif (!region) { return; }\r\n\t\t\t\tregion.setState(0, 0, undefined);\r\n\t\t\t\tevent.event.stopPropagation();\r\n\t\t\t\tevent.event.preventDefault();\r\n\t\t\t}\r\n\t\t}));\r\n\r\n\t\tthis._register(this._editors.original.onMouseUp(event => {\r\n\t\t\tif (!event.event.rightButton && event.target.position && event.target.element?.className.includes('fold-unchanged')) {\r\n\t\t\t\tconst lineNumber = event.target.position.lineNumber;\r\n\t\t\t\tconst model = this._diffModel.get();\r\n\t\t\t\tif (!model) { return; }\r\n\t\t\t\tconst region = model.unchangedRegions.get().find(r => r.originalRange.includes(lineNumber));\r\n\t\t\t\tif (!region) { return; }\r\n\t\t\t\tregion.setState(0, 0, undefined);\r\n\t\t\t\tevent.event.stopPropagation();\r\n\t\t\t\tevent.event.preventDefault();\r\n\t\t\t}\r\n\t\t}));\r\n\t}\r\n}\r\n\r\nclass DisposableCancellationTokenSource extends CancellationTokenSource {\r\n\tpublic override dispose() {\r\n\t\tsuper.dispose(true);\r\n\t}\r\n}\r\n\r\nclass OutlineSource extends Disposable {\r\n\tprivate readonly _currentModel = observableValue<OutlineModel | undefined>('current model', undefined);\r\n\r\n\tconstructor(\r\n\t\t@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,\r\n\t\tprivate readonly _textModel: ITextModel,\r\n\t) {\r\n\t\tsuper();\r\n\r\n\t\tconst documentSymbolProviderChanged = observableSignalFromEvent(\r\n\t\t\t'documentSymbolProvider.onDidChange',\r\n\t\t\tthis._languageFeaturesService.documentSymbolProvider.onDidChange\r\n\t\t);\r\n\r\n\t\tconst textModelChanged = observableSignalFromEvent(\r\n\t\t\t'_textModel.onDidChangeContent',\r\n\t\t\tEvent.debounce<any>(e => this._textModel.onDidChangeContent(e), () => undefined, 100)\r\n\t\t);\r\n\r\n\t\tthis._register(autorunWithStore(async (reader, store) => {\r\n\t\t\tdocumentSymbolProviderChanged.read(reader);\r\n\t\t\ttextModelChanged.read(reader);\r\n\r\n\t\t\tconst src = store.add(new DisposableCancellationTokenSource());\r\n\t\t\tconst model = await OutlineModel.create(\r\n\t\t\t\tthis._languageFeaturesService.documentSymbolProvider,\r\n\t\t\t\tthis._textModel,\r\n\t\t\t\tsrc.token,\r\n\t\t\t);\r\n\t\t\tif (store.isDisposed) { return; }\r\n\r\n\t\t\tthis._currentModel.set(model, undefined);\r\n\t\t}));\r\n\t}\r\n\r\n\tpublic getBreadcrumbItems(startRange: LineRange, reader: IReader): { name: string; kind: SymbolKind }[] {\r\n\t\tconst m = this._currentModel.read(reader);\r\n\t\tif (!m) { return []; }\r\n\t\tconst symbols = m.asListOfDocumentSymbols()\r\n\t\t\t.filter(s => startRange.contains(s.range.startLineNumber) && !startRange.contains(s.range.endLineNumber));\r\n\t\tsymbols.sort(reverseOrder(compareBy(s => s.range.endLineNumber - s.range.startLineNumber, numberComparator)));\r\n\t\treturn symbols.map(s => ({ name: s.name, kind: s.kind }));\r\n\t}\r\n}\r\n\r\nclass CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget {\r\n\tprivate readonly _nodes = h('div.diff-hidden-lines', [\r\n\t\th('div.top@top', { title: localize('diff.hiddenLines.top', 'Click or drag to show more above') }),\r\n\t\th('div.center@content', { style: { display: 'flex' } }, [\r\n\t\t\th('div@first', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } },\r\n\t\t\t\t[$('a', { title: localize('showAll', 'Show all'), role: 'button', onclick: () => { this.showAll(); } }, ...renderLabelWithIcons('$(unfold)'))]\r\n\t\t\t),\r\n\t\t\th('div@others', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } }),\r\n\t\t]),\r\n\t\th('div.bottom@bottom', { title: localize('diff.bottom', 'Click or drag to show more below'), role: 'button' }),\r\n\t]);\r\n\r\n\tconstructor(\r\n\t\tprivate readonly _editor: ICodeEditor,\r\n\t\t_viewZone: PlaceholderViewZone,\r\n\t\tprivate readonly _unchangedRegion: UnchangedRegion,\r\n\t\tprivate readonly _unchangedRegionRange: LineRange,\r\n\t\tprivate readonly hide: boolean,\r\n\t\tprivate readonly _modifiedOutlineSource: OutlineSource,\r\n\t) {\r\n\t\tconst root = h('div.diff-hidden-lines-widget');\r\n\t\tsuper(_editor, _viewZone, root.root);\r\n\t\troot.root.appendChild(this._nodes.root);\r\n\r\n\t\tconst layoutInfo = observableFromEvent(this._editor.onDidLayoutChange, () =>\r\n\t\t\tthis._editor.getLayoutInfo()\r\n\t\t);\r\n\r\n\t\tif (!this.hide) {\r\n\t\t\tthis._register(applyStyle(this._nodes.first, { width: layoutInfo.map((l) => l.contentLeft) }));\r\n\t\t} else {\r\n\t\t\treset(this._nodes.first);\r\n\t\t}\r\n\r\n\t\tconst editor = this._editor;\r\n\r\n\t\tthis._register(addDisposableListener(this._nodes.top, 'mousedown', e => {\r\n\t\t\tif (e.button !== 0) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis._nodes.top.classList.toggle('dragging', true);\r\n\t\t\tthis._nodes.root.classList.toggle('dragging', true);\r\n\t\t\te.preventDefault();\r\n\t\t\tconst startTop = e.clientY;\r\n\t\t\tlet didMove = false;\r\n\t\t\tconst cur = this._unchangedRegion.visibleLineCountTop.get();\r\n\t\t\tthis._unchangedRegion.isDragged.set(true, undefined);\r\n\r\n\r\n\t\t\tconst mouseMoveListener = addDisposableListener(window, 'mousemove', e => {\r\n\t\t\t\tconst currentTop = e.clientY;\r\n\t\t\t\tconst delta = currentTop - startTop;\r\n\t\t\t\tdidMove = didMove || Math.abs(delta) > 2;\r\n\t\t\t\tconst lineDelta = Math.round(delta / editor.getOption(EditorOption.lineHeight));\r\n\t\t\t\tconst newVal = Math.max(0, Math.min(cur + lineDelta, this._unchangedRegion.getMaxVisibleLineCountTop()));\r\n\t\t\t\tthis._unchangedRegion.visibleLineCountTop.set(newVal, undefined);\r\n\t\t\t});\r\n\r\n\t\t\tconst mouseUpListener = addDisposableListener(window, 'mouseup', e => {\r\n\t\t\t\tif (!didMove) {\r\n\t\t\t\t\tthis._unchangedRegion.showMoreAbove(20, undefined);\r\n\t\t\t\t}\r\n\t\t\t\tthis._nodes.top.classList.toggle('dragging', false);\r\n\t\t\t\tthis._nodes.root.classList.toggle('dragging', false);\r\n\t\t\t\tthis._unchangedRegion.isDragged.set(false, undefined);\r\n\t\t\t\tmouseMoveListener.dispose();\r\n\t\t\t\tmouseUpListener.dispose();\r\n\t\t\t});\r\n\t\t}));\r\n\r\n\t\tthis._register(addDisposableListener(this._nodes.bottom, 'mousedown', e => {\r\n\t\t\tif (e.button !== 0) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis._nodes.bottom.classList.toggle('dragging', true);\r\n\t\t\tthis._nodes.root.classList.toggle('dragging', true);\r\n\t\t\te.preventDefault();\r\n\t\t\tconst startTop = e.clientY;\r\n\t\t\tlet didMove = false;\r\n\t\t\tconst cur = this._unchangedRegion.visibleLineCountBottom.get();\r\n\t\t\tthis._unchangedRegion.isDragged.set(true, undefined);\r\n\r\n\t\t\tconst mouseMoveListener = addDisposableListener(window, 'mousemove', e => {\r\n\t\t\t\tconst currentTop = e.clientY;\r\n\t\t\t\tconst delta = currentTop - startTop;\r\n\t\t\t\tdidMove = didMove || Math.abs(delta) > 2;\r\n\t\t\t\tconst lineDelta = Math.round(delta / editor.getOption(EditorOption.lineHeight));\r\n\t\t\t\tconst newVal = Math.max(0, Math.min(cur - lineDelta, this._unchangedRegion.getMaxVisibleLineCountBottom()));\r\n\t\t\t\tconst top = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\r\n\t\t\t\tthis._unchangedRegion.visibleLineCountBottom.set(newVal, undefined);\r\n\t\t\t\tconst top2 = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\r\n\t\t\t\teditor.setScrollTop(editor.getScrollTop() + (top2 - top));\r\n\t\t\t});\r\n\r\n\t\t\tconst mouseUpListener = addDisposableListener(window, 'mouseup', e => {\r\n\t\t\t\tthis._unchangedRegion.isDragged.set(false, undefined);\r\n\r\n\t\t\t\tif (!didMove) {\r\n\t\t\t\t\tconst top = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\r\n\r\n\t\t\t\t\tthis._unchangedRegion.showMoreBelow(20, undefined);\r\n\t\t\t\t\tconst top2 = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\r\n\t\t\t\t\teditor.setScrollTop(editor.getScrollTop() + (top2 - top));\r\n\t\t\t\t}\r\n\t\t\t\tthis._nodes.bottom.classList.toggle('dragging', false);\r\n\t\t\t\tthis._nodes.root.classList.toggle('dragging', false);\r\n\t\t\t\tmouseMoveListener.dispose();\r\n\t\t\t\tmouseUpListener.dispose();\r\n\t\t\t});\r\n\t\t}));\r\n\r\n\t\tthis._register(autorun(reader => {\r\n\t\t\t/** @description update labels */\r\n\r\n\t\t\tconst children: HTMLElement[] = [];\r\n\t\t\tif (!this.hide) {\r\n\t\t\t\tconst lineCount = _unchangedRegion.getHiddenModifiedRange(reader).length;\r\n\t\t\t\tconst linesHiddenText = localize('hiddenLines', '{0} Hidden Lines', lineCount);\r\n\t\t\t\tconst span = $('span', { title: localize('diff.hiddenLines.expandAll', 'Double click to show all unchanged region') }, linesHiddenText);\r\n\t\t\t\tspan.addEventListener('dblclick', e => {\r\n\t\t\t\t\tif (e.button !== 0) { return; }\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tthis.showAll();\r\n\t\t\t\t});\r\n\t\t\t\tchildren.push(span);\r\n\r\n\t\t\t\tconst range = this._unchangedRegion.getHiddenModifiedRange(reader);\r\n\t\t\t\tconst items = this._modifiedOutlineSource.getBreadcrumbItems(range, reader);\r\n\r\n\t\t\t\tif (items.length > 0) {\r\n\t\t\t\t\tchildren.push($('span', undefined, '\\u00a0|\\u00a0'));\r\n\r\n\t\t\t\t\tlet isFirst = true;\r\n\t\t\t\t\tfor (const item of items) {\r\n\t\t\t\t\t\tif (!isFirst) {\r\n\t\t\t\t\t\t\tchildren.push($('span', {}, ' ', renderIcon(Codicon.chevronRight), ' '));\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tconst icon = SymbolKinds.toIcon(item.kind);\r\n\t\t\t\t\t\tchildren.push($('span', {}, renderIcon(icon), ' ', item.name));\r\n\t\t\t\t\t\tisFirst = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treset(this._nodes.others, ...children);\r\n\t\t}));\r\n\t}\r\n\r\n\tprivate showAll() { this._unchangedRegion.showAll(undefined); }\r\n\r\n}\r\n",
    "initialResult": "\t\tthis._register(applyObservableDecorations(this._editors.original, derived(reader => {\r\n\t\t\t/** @description decorations */\r\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\r\n\t\t\tconst result = curUnchangedRegions.map<IModelDeltaDecoration>(r => ({\r\n\t\t\t\trange: r.originalRange.toInclusiveRange()!,\r\n\t\t\t\toptions: unchangedLinesDecoration,\r\n\t\t\t}));\r\n\t\t\tfor (const r of curUnchangedRegions) {\r\n\t\t\t\tif (r.shouldHideControls(reader)) {\r\n\t\t\t\t\tresult.push({\r\n\t\t\t\t\t\trange: Range.fromPositions(new Position(r.originalLineNumber, 1)),\r\n\t\t\t\t\t\toptions: unchangedLinesDecorationShow\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn result;\r\n\t\t})));\r\n\r\n\t\tthis._register(applyObservableDecorations(this._editors.modified, derived(reader => {\r\n\t\t\t/** @description decorations */\r\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\r\n\t\t\tconst result = curUnchangedRegions.map<IModelDeltaDecoration>(r => ({\r\n\t\t\t\trange: r.modifiedRange.toInclusiveRange()!,\r\n\t\t\t\toptions: unchangedLinesDecoration,\r\n\t\t\t}));\r\n\t\t\tfor (const r of curUnchangedRegions) {\r\n\t\t\t\tif (r.shouldHideControls(reader)) {\r\n\t\t\t\t\tresult.push({\r\n\t\t\t\t\t\trange: LineRange.ofLength(r.modifiedLineNumber, 1).toInclusiveRange()!,\r\n\t\t\t\t\t\toptions: unchangedLinesDecorationShow\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn result;\r\n\t\t})));\r\n\r\n\t\tthis._register(applyViewZones(this._editors.original, viewZones.map(v => v.origViewZones), v => this._isUpdatingViewZones = v));\r\n\t\tthis._register(applyViewZones(this._editors.modified, viewZones.map(v => v.modViewZones), v => this._isUpdatingViewZones = v));\r\n\r\n\t\tthis._register(autorun((reader) => {\r\n\t\t\t/** @description update folded unchanged regions */\r\n\t\t\tconst curUnchangedRegions = unchangedRegions.read(reader);\r\n\t\t\tthis._editors.original.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenOriginalRange(reader).toInclusiveRange()).filter(isDefined));\r\n\t\t\tthis._editors.modified.setHiddenAreas(curUnchangedRegions.map(r => r.getHiddenModifiedRange(reader).toInclusiveRange()).filter(isDefined));\r\n\t\t}));\r\n\r\n\t\tthis._register(this._editors.modified.onMouseUp(event => {\r\n\t\t\tif (!event.event.rightButton && event.target.position && event.target.element?.className.includes('fold-unchanged')) {\r\n\t\t\t\tconst lineNumber = event.target.position.lineNumber;\r\n\t\t\t\tconst model = this._diffModel.get();\r\n\t\t\t\tif (!model) { return; }\r\n\t\t\t\tconst region = model.unchangedRegions.get().find(r => r.modifiedRange.includes(lineNumber));\r\n\t\t\t\tif (!region) { return; }\r\n\t\t\t\tregion.setState(0, 0, undefined);\r\n\t\t\t\tevent.event.stopPropagation();\r\n\t\t\t\tevent.event.preventDefault();\r\n\t\t\t}\r\n\t\t}));\r\n\r\n\t\tthis._register(this._editors.original.onMouseUp(event => {\r\n\t\t\tif (!event.event.rightButton && event.target.position && event.target.element?.className.includes('fold-unchanged')) {\r\n\t\t\t\tconst lineNumber = event.target.position.lineNumber;\r\n\t\t\t\tconst model = this._diffModel.get();\r\n\t\t\t\tif (!model) { return; }\r\n\t\t\t\tconst region = model.unchangedRegions.get().find(r => r.originalRange.includes(lineNumber));\r\n\t\t\t\tif (!region) { return; }\r\n\t\t\t\tregion.setState(0, 0, undefined);\r\n\t\t\t\tevent.event.stopPropagation();\r\n\t\t\t\tevent.event.preventDefault();\r\n\t\t\t}\r\n\t\t}));\r\n\t}\r\n}\r\n\r\nclass DisposableCancellationTokenSource extends CancellationTokenSource {\r\n\tpublic override dispose() {\r\n\t\tsuper.dispose(true);\r\n\t}\r\n}\r\n\r\nclass OutlineSource extends Disposable {\r\n\tprivate readonly _currentModel = observableValue<OutlineModel | undefined>('current model', undefined);\r\n\r\n\tconstructor(\r\n\t\t@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,\r\n\t\tprivate readonly _textModel: ITextModel,\r\n\t) {\r\n\t\tsuper();\r\n\r\n\t\tconst documentSymbolProviderChanged = observableSignalFromEvent(\r\n\t\t\t'documentSymbolProvider.onDidChange',\r\n\t\t\tthis._languageFeaturesService.documentSymbolProvider.onDidChange\r\n\t\t);\r\n\r\n\t\tconst textModelChanged = observableSignalFromEvent(\r\n\t\t\t'_textModel.onDidChangeContent',\r\n\t\t\tEvent.debounce<any>(e => this._textModel.onDidChangeContent(e), () => undefined, 100)\r\n\t\t);\r\n\r\n\t\tthis._register(autorunWithStore(async (reader, store) => {\r\n\t\t\tdocumentSymbolProviderChanged.read(reader);\r\n\t\t\ttextModelChanged.read(reader);\r\n\r\n\t\t\tconst src = store.add(new DisposableCancellationTokenSource());\r\n\t\t\tconst model = await OutlineModel.create(\r\n\t\t\t\tthis._languageFeaturesService.documentSymbolProvider,\r\n\t\t\t\tthis._textModel,\r\n\t\t\t\tsrc.token,\r\n\t\t\t);\r\n\t\t\tif (store.isDisposed) { return; }\r\n\r\n\t\t\tthis._currentModel.set(model, undefined);\r\n\t\t}));\r\n\t}\r\n\r\n\tpublic getBreadcrumbItems(startRange: LineRange, reader: IReader): { name: string; kind: SymbolKind }[] {\r\n\t\tconst m = this._currentModel.read(reader);\r\n\t\tif (!m) { return []; }\r\n\t\tconst symbols = m.asListOfDocumentSymbols()\r\n\t\t\t.filter(s => startRange.contains(s.range.startLineNumber) && !startRange.contains(s.range.endLineNumber));\r\n\t\tsymbols.sort(reverseOrder(compareBy(s => s.range.endLineNumber - s.range.startLineNumber, numberComparator)));\r\n\t\treturn symbols.map(s => ({ name: s.name, kind: s.kind }));\r\n\t}\r\n}\r\n\r\nclass CollapsedCodeOverlayWidget extends ViewZoneOverlayWidget {\r\n\tprivate readonly _nodes = h('div.diff-hidden-lines', [\r\n\t\th('div.top@top', { title: localize('diff.hiddenLines.top', 'Click or drag to show more above') }),\r\n\t\th('div.center@content', { style: { display: 'flex' } }, [\r\n\t\t\th('div@first', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } },\r\n\t\t\t\t[$('a', { title: localize('showAll', 'Show all'), role: 'button', onclick: () => { this.showAll(); } }, ...renderLabelWithIcons('$(unfold)'))]\r\n\t\t\t),\r\n\t\t\th('div@others', { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' } }),\r\n\t\t]),\r\n\t\th('div.bottom@bottom', { title: localize('diff.bottom', 'Click or drag to show more below'), role: 'button' }),\r\n\t]);\r\n\r\n\tconstructor(\r\n\t\tprivate readonly _editor: ICodeEditor,\r\n\t\t_viewZone: PlaceholderViewZone,\r\n\t\tprivate readonly _unchangedRegion: UnchangedRegion,\r\n\t\tprivate readonly _unchangedRegionRange: LineRange,\r\n\t\tprivate readonly hide: boolean,\r\n\t\tprivate readonly _modifiedOutlineSource: OutlineSource,\r\n\t) {\r\n\t\tconst root = h('div.diff-hidden-lines-widget');\r\n\t\tsuper(_editor, _viewZone, root.root);\r\n\t\troot.root.appendChild(this._nodes.root);\r\n\r\n\t\tconst layoutInfo = observableFromEvent(this._editor.onDidLayoutChange, () =>\r\n\t\t\tthis._editor.getLayoutInfo()\r\n\t\t);\r\n\r\n\t\tif (!this.hide) {\r\n\t\t\tthis._register(applyStyle(this._nodes.first, { width: layoutInfo.map((l) => l.contentLeft) }));\r\n\t\t} else {\r\n\t\t\treset(this._nodes.first);\r\n\t\t}\r\n\r\n\t\tconst editor = this._editor;\r\n\r\n\t\tthis._register(addDisposableListener(this._nodes.top, 'mousedown', e => {\r\n\t\t\tif (e.button !== 0) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis._nodes.top.classList.toggle('dragging', true);\r\n\t\t\tthis._nodes.root.classList.toggle('dragging', true);\r\n\t\t\te.preventDefault();\r\n\t\t\tconst startTop = e.clientY;\r\n\t\t\tlet didMove = false;\r\n\t\t\tconst cur = this._unchangedRegion.visibleLineCountTop.get();\r\n\t\t\tthis._unchangedRegion.isDragged.set(true, undefined);\r\n\r\n\r\n\t\t\tconst mouseMoveListener = addDisposableListener(window, 'mousemove', e => {\r\n\t\t\t\tconst currentTop = e.clientY;\r\n\t\t\t\tconst delta = currentTop - startTop;\r\n\t\t\t\tdidMove = didMove || Math.abs(delta) > 2;\r\n\t\t\t\tconst lineDelta = Math.round(delta / editor.getOption(EditorOption.lineHeight));\r\n\t\t\t\tconst newVal = Math.max(0, Math.min(cur + lineDelta, this._unchangedRegion.getMaxVisibleLineCountTop()));\r\n\t\t\t\tthis._unchangedRegion.visibleLineCountTop.set(newVal, undefined);\r\n\t\t\t});\r\n\r\n\t\t\tconst mouseUpListener = addDisposableListener(window, 'mouseup', e => {\r\n\t\t\t\tif (!didMove) {\r\n\t\t\t\t\tthis._unchangedRegion.showMoreAbove(20, undefined);\r\n\t\t\t\t}\r\n\t\t\t\tthis._nodes.top.classList.toggle('dragging', false);\r\n\t\t\t\tthis._nodes.root.classList.toggle('dragging', false);\r\n\t\t\t\tthis._unchangedRegion.isDragged.set(false, undefined);\r\n\t\t\t\tmouseMoveListener.dispose();\r\n\t\t\t\tmouseUpListener.dispose();\r\n\t\t\t});\r\n\t\t}));\r\n\r\n\t\tthis._register(addDisposableListener(this._nodes.bottom, 'mousedown', e => {\r\n\t\t\tif (e.button !== 0) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis._nodes.bottom.classList.toggle('dragging', true);\r\n\t\t\tthis._nodes.root.classList.toggle('dragging', true);\r\n\t\t\te.preventDefault();\r\n\t\t\tconst startTop = e.clientY;\r\n\t\t\tlet didMove = false;\r\n\t\t\tconst cur = this._unchangedRegion.visibleLineCountBottom.get();\r\n\t\t\tthis._unchangedRegion.isDragged.set(true, undefined);\r\n\r\n\t\t\tconst mouseMoveListener = addDisposableListener(window, 'mousemove', e => {\r\n\t\t\t\tconst currentTop = e.clientY;\r\n\t\t\t\tconst delta = currentTop - startTop;\r\n\t\t\t\tdidMove = didMove || Math.abs(delta) > 2;\r\n\t\t\t\tconst lineDelta = Math.round(delta / editor.getOption(EditorOption.lineHeight));\r\n\t\t\t\tconst newVal = Math.max(0, Math.min(cur - lineDelta, this._unchangedRegion.getMaxVisibleLineCountBottom()));\r\n\t\t\t\tconst top = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\r\n\t\t\t\tthis._unchangedRegion.visibleLineCountBottom.set(newVal, undefined);\r\n\t\t\t\tconst top2 = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\r\n\t\t\t\teditor.setScrollTop(editor.getScrollTop() + (top2 - top));\r\n\t\t\t});\r\n\r\n\t\t\tconst mouseUpListener = addDisposableListener(window, 'mouseup', e => {\r\n\t\t\t\tthis._unchangedRegion.isDragged.set(false, undefined);\r\n\r\n\t\t\t\tif (!didMove) {\r\n\t\t\t\t\tconst top = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\r\n\r\n\t\t\t\t\tthis._unchangedRegion.showMoreBelow(20, undefined);\r\n\t\t\t\t\tconst top2 = editor.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);\r\n\t\t\t\t\teditor.setScrollTop(editor.getScrollTop() + (top2 - top));\r\n\t\t\t\t}\r\n\t\t\t\tthis._nodes.bottom.classList.toggle('dragging', false);\r\n\t\t\t\tthis._nodes.root.classList.toggle('dragging', false);\r\n\t\t\t\tmouseMoveListener.dispose();\r\n\t\t\t\tmouseUpListener.dispose();\r\n\t\t\t});\r\n\t\t}));\r\n\r\n\t\tthis._register(autorun(reader => {\r\n\t\t\t/** @description update labels */\r\n\r\n\t\t\tconst children: HTMLElement[] = [];\r\n\t\t\tif (!this.hide) {\r\n\t\t\t\tconst lineCount = _unchangedRegion.getHiddenModifiedRange(reader).length;\r\n\t\t\t\tconst linesHiddenText = localize('hiddenLines', '{0} Hidden Lines', lineCount);\r\n\t\t\t\tconst span = $('span', { title: localize('diff.hiddenLines.expandAll', 'Double click to show all unchanged region') }, linesHiddenText);\r\n\t\t\t\tspan.addEventListener('dblclick', e => {\r\n\t\t\t\t\tif (e.button !== 0) { return; }\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tthis.showAll();\r\n\t\t\t\t});\r\n\t\t\t\tchildren.push(span);\r\n\r\n\t\t\t\tconst range = this._unchangedRegion.getHiddenModifiedRange(reader);\r\n\t\t\t\tconst items = this._modifiedOutlineSource.getBreadcrumbItems(range, reader);\r\n\r\n\t\t\t\tif (items.length > 0) {\r\n\t\t\t\t\tchildren.push($('span', undefined, '\\u00a0|\\u00a0'));\r\n\r\n\t\t\t\t\tlet isFirst = true;\r\n\t\t\t\t\tfor (const item of items) {\r\n\t\t\t\t\t\tif (!isFirst) {\r\n\t\t\t\t\t\t\tchildren.push($('span', {}, ' ', renderIcon(Codicon.chevronRight), ' '));\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tconst icon = SymbolKinds.toIcon(item.kind);\r\n\t\t\t\t\t\tchildren.push($('span', {}, renderIcon(icon), ' ', item.name));\r\n\t\t\t\t\t\tisFirst = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treset(this._nodes.others, ...children);\r\n\t\t}));\r\n\t}\r\n\r\n\tprivate showAll() { this._unchangedRegion.showAll(undefined); }\r\n\r\n}\r\n"
}
```