Merge branch 'main' into joh/corporate-canid

This commit is contained in:
Johannes Rieken 2023-09-05 13:50:57 +02:00 committed by GitHub
commit 137b724984
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 320 additions and 4555 deletions

View file

@ -151,5 +151,4 @@
"application.experimental.rendererProfiling": true,
"editor.experimental.asyncTokenization": true,
"editor.experimental.asyncTokenizationVerification": true,
"diffEditor.experimental.useVersion2": true,
}

View file

@ -89,7 +89,6 @@ declare namespace monaco {
}
declare namespace monaco.editor {
#include(vs/editor/browser/widget/diffNavigator): IDiffNavigator
#includeAll(vs/editor/standalone/browser/standaloneEditor;languages.Token=>Token):
#include(vs/editor/standalone/common/standaloneTheme): BuiltinTheme, IStandaloneThemeData, IColors
#include(vs/editor/common/languages/supports/tokenization): ITokenThemeRule
@ -108,10 +107,6 @@ export interface ICommandHandler {
#include(vs/editor/common/core/wordHelper): IWordAtPosition
#includeAll(vs/editor/common/model): IScrollEvent
#include(vs/editor/common/diff/legacyLinesDiffComputer): IChange, ICharChange, ILineChange
#include(vs/editor/common/diff/documentDiffProvider): IDocumentDiffProvider, IDocumentDiffProviderOptions, IDocumentDiff
#include(vs/editor/common/core/lineRange): LineRange
#include(vs/editor/common/diff/linesDiffComputer): MovedText
#include(vs/editor/common/diff/rangeMapping): DetailedLineRangeMapping, RangeMapping, LineRangeMapping
#include(vs/editor/common/core/dimension): IDimension
#includeAll(vs/editor/common/editorCommon): IScrollEvent
#includeAll(vs/editor/common/textModelEvents):

View file

@ -122,7 +122,7 @@ suite('git smoke test', function () {
repository.state.workingTreeChanges.some(r => r.uri.path === newfile.path && r.status === Status.UNTRACKED);
assert.strictEqual(repository.state.indexChanges.length, 0);
await commands.executeCommand('git.stageAll');
await commands.executeCommand('git.stageAll', appjs);
await repository.commit('third commit');
assert.strictEqual(repository.state.workingTreeChanges.length, 0);
assert.strictEqual(repository.state.indexChanges.length, 0);

View file

@ -6,6 +6,7 @@
import { CancellationToken } from 'vs/base/common/cancellation';
import { CancellationError } from 'vs/base/common/errors';
import { ISplice } from 'vs/base/common/sequence';
import { findFirstIdxMonotonousOrArrLen } from './arraysFind';
/**
* Returns the last element of an array.
@ -106,27 +107,6 @@ export function binarySearch2(length: number, compareToKey: (index: number) => n
return -(low + 1);
}
/**
* Takes a sorted array and a function p. The array is sorted in such a way that all elements where p(x) is false
* are located before all elements where p(x) is true.
* @returns the least x for which p(x) is true or array.length if no element fullfills the given function.
*/
export function findFirstInSorted<T>(array: ReadonlyArray<T>, p: (x: T) => boolean): number {
let low = 0, high = array.length;
if (high === 0) {
return 0; // no children
}
while (low < high) {
const mid = Math.floor((low + high) / 2);
if (p(array[mid])) {
high = mid;
} else {
low = mid + 1;
}
}
return low;
}
type Compare<T> = (a: T, b: T) => number;
@ -345,7 +325,7 @@ function topStep<T>(array: ReadonlyArray<T>, compare: (a: T, b: T) => number, re
const element = array[i];
if (compare(element, result[n - 1]) < 0) {
result.pop();
const j = findFirstInSorted(result, e => compare(element, e) < 0);
const j = findFirstIdxMonotonousOrArrLen(result, e => compare(element, e) < 0);
result.splice(j, 0, element);
}
}
@ -427,26 +407,6 @@ export function uniqueFilter<T, R>(keyFn: (t: T) => R): (t: T) => boolean {
};
}
export function findLast<T>(arr: readonly T[], predicate: (item: T) => boolean): T | undefined {
const idx = findLastIndex(arr, predicate);
if (idx === -1) {
return undefined;
}
return arr[idx];
}
export function findLastIndex<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean): number {
for (let i = array.length - 1; i >= 0; i--) {
const element = array[i];
if (fn(element)) {
return i;
}
}
return -1;
}
export function firstOrDefault<T, NotFound = T>(array: ReadonlyArray<T>, notFoundValue: NotFound): T | NotFound;
export function firstOrDefault<T>(array: ReadonlyArray<T>): T | undefined;
export function firstOrDefault<T, NotFound = T>(array: ReadonlyArray<T>, notFoundValue?: NotFound): T | NotFound | undefined {
@ -622,20 +582,6 @@ export function getRandomElement<T>(arr: T[]): T | undefined {
return arr[Math.floor(Math.random() * arr.length)];
}
/**
* Returns the first mapped value of the array which is not undefined.
*/
export function mapFind<T, R>(array: Iterable<T>, mapFn: (value: T) => R | undefined): R | undefined {
for (const value of array) {
const mapped = mapFn(value);
if (mapped !== undefined) {
return mapped;
}
}
return undefined;
}
/**
* Insert the new items in the array.
* @param array The original array.
@ -751,64 +697,6 @@ export function reverseOrder<TItem>(comparator: Comparator<TItem>): Comparator<T
return (a, b) => -comparator(a, b);
}
/**
* Returns the first item that is equal to or greater than every other item.
*/
export function findMaxBy<T>(items: readonly T[], comparator: Comparator<T>): T | undefined {
if (items.length === 0) {
return undefined;
}
let max = items[0];
for (let i = 1; i < items.length; i++) {
const item = items[i];
if (comparator(item, max) > 0) {
max = item;
}
}
return max;
}
/**
* Returns the last item that is equal to or greater than every other item.
*/
export function findLastMaxBy<T>(items: readonly T[], comparator: Comparator<T>): T | undefined {
if (items.length === 0) {
return undefined;
}
let max = items[0];
for (let i = 1; i < items.length; i++) {
const item = items[i];
if (comparator(item, max) >= 0) {
max = item;
}
}
return max;
}
/**
* Returns the first item that is equal to or less than every other item.
*/
export function findMinBy<T>(items: readonly T[], comparator: Comparator<T>): T | undefined {
return findMaxBy(items, (a, b) => -comparator(a, b));
}
export function findMaxIdxBy<T>(items: readonly T[], comparator: Comparator<T>): number {
if (items.length === 0) {
return -1;
}
let maxIdx = 0;
for (let i = 1; i < items.length; i++) {
const item = items[i];
if (comparator(item, items[maxIdx]) > 0) {
maxIdx = i;
}
}
return maxIdx;
}
export class ArrayQueue<T> {
private firstIdx = 0;
private lastIdx = this.items.length - 1;

View file

@ -3,15 +3,37 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Comparator } from './arrays';
export function findLast<T>(array: readonly T[], predicate: (item: T) => boolean): T | undefined {
const idx = findLastIdx(array, predicate);
if (idx === -1) {
return undefined;
}
return array[idx];
}
export function findLastIdx<T>(array: readonly T[], predicate: (item: T) => boolean): number {
for (let i = array.length - 1; i >= 0; i--) {
const element = array[i];
if (predicate(element)) {
return i;
}
}
return -1;
}
/**
* Finds the last item where predicate is true using binary search.
* `predicate` must be monotonous, i.e. `arr.map(predicate)` must be like `[true, ..., true, false, ..., false]`!
*
* @returns `undefined` if no item matches, otherwise the last item that matches the predicate.
*/
export function findLastMonotonous<T>(arr: T[], predicate: (item: T) => boolean): T | undefined {
const idx = findLastIdxMonotonous(arr, predicate);
return idx === -1 ? undefined : arr[idx];
export function findLastMonotonous<T>(array: readonly T[], predicate: (item: T) => boolean): T | undefined {
const idx = findLastIdxMonotonous(array, predicate);
return idx === -1 ? undefined : array[idx];
}
/**
@ -20,12 +42,12 @@ export function findLastMonotonous<T>(arr: T[], predicate: (item: T) => boolean)
*
* @returns `startIdx - 1` if predicate is false for all items, otherwise the index of the last item that matches the predicate.
*/
export function findLastIdxMonotonous<T>(arr: T[], predicate: (item: T) => boolean, startIdx = 0, endIdxEx = arr.length): number {
export function findLastIdxMonotonous<T>(array: readonly T[], predicate: (item: T) => boolean, startIdx = 0, endIdxEx = array.length): number {
let i = startIdx;
let j = endIdxEx;
while (i < j) {
const k = Math.floor((i + j) / 2);
if (predicate(arr[k])) {
if (predicate(array[k])) {
i = k + 1;
} else {
j = k;
@ -34,16 +56,15 @@ export function findLastIdxMonotonous<T>(arr: T[], predicate: (item: T) => boole
return i - 1;
}
/**
* Finds the first item where predicate is true using binary search.
* `predicate` must be monotonous, i.e. `arr.map(predicate)` must be like `[false, ..., false, true, ..., true]`!
*
* @returns `undefined` if no item matches, otherwise the first item that matches the predicate.
*/
export function findFirstMonotonous<T>(arr: T[], predicate: (item: T) => boolean): T | undefined {
const idx = findFirstIdxMonotonousOrArrLen(arr, predicate);
return idx === arr.length ? undefined : arr[idx];
export function findFirstMonotonous<T>(array: readonly T[], predicate: (item: T) => boolean): T | undefined {
const idx = findFirstIdxMonotonousOrArrLen(array, predicate);
return idx === array.length ? undefined : array[idx];
}
/**
@ -52,12 +73,12 @@ export function findFirstMonotonous<T>(arr: T[], predicate: (item: T) => boolean
*
* @returns `endIdxEx` if predicate is false for all items, otherwise the index of the first item that matches the predicate.
*/
export function findFirstIdxMonotonousOrArrLen<T>(arr: T[], predicate: (item: T) => boolean, startIdx = 0, endIdxEx = arr.length): number {
export function findFirstIdxMonotonousOrArrLen<T>(array: readonly T[], predicate: (item: T) => boolean, startIdx = 0, endIdxEx = array.length): number {
let i = startIdx;
let j = endIdxEx;
while (i < j) {
const k = Math.floor((i + j) / 2);
if (predicate(arr[k])) {
if (predicate(array[k])) {
j = k;
} else {
i = k + 1;
@ -66,9 +87,9 @@ export function findFirstIdxMonotonousOrArrLen<T>(arr: T[], predicate: (item: T)
return i;
}
export function findFirstIdxMonotonous<T>(arr: T[], predicate: (item: T) => boolean, startIdx = 0, endIdxEx = arr.length): number {
const idx = findFirstIdxMonotonousOrArrLen(arr, predicate, startIdx, endIdxEx);
return idx === arr.length ? -1 : idx;
export function findFirstIdxMonotonous<T>(array: readonly T[], predicate: (item: T) => boolean, startIdx = 0, endIdxEx = array.length): number {
const idx = findFirstIdxMonotonousOrArrLen(array, predicate, startIdx, endIdxEx);
return idx === array.length ? -1 : idx;
}
/**
@ -83,7 +104,7 @@ export class MonotonousArray<T> {
private _findLastMonotonousLastIdx = 0;
private _prevFindLastPredicate: ((item: T) => boolean) | undefined;
constructor(private readonly _items: T[]) {
constructor(private readonly _array: readonly T[]) {
}
/**
@ -93,7 +114,7 @@ export class MonotonousArray<T> {
findLastMonotonous(predicate: (item: T) => boolean): T | undefined {
if (MonotonousArray.assertInvariants) {
if (this._prevFindLastPredicate) {
for (const item of this._items) {
for (const item of this._array) {
if (this._prevFindLastPredicate(item) && !predicate(item)) {
throw new Error('MonotonousArray: current predicate must be weaker than (or equal to) the previous predicate.');
}
@ -102,8 +123,80 @@ export class MonotonousArray<T> {
this._prevFindLastPredicate = predicate;
}
const idx = findLastIdxMonotonous(this._items, predicate, this._findLastMonotonousLastIdx);
const idx = findLastIdxMonotonous(this._array, predicate, this._findLastMonotonousLastIdx);
this._findLastMonotonousLastIdx = idx + 1;
return idx === -1 ? undefined : this._items[idx];
return idx === -1 ? undefined : this._array[idx];
}
}
/**
* Returns the first item that is equal to or greater than every other item.
*/
export function findFirstMaxBy<T>(array: readonly T[], comparator: Comparator<T>): T | undefined {
if (array.length === 0) {
return undefined;
}
let max = array[0];
for (let i = 1; i < array.length; i++) {
const item = array[i];
if (comparator(item, max) > 0) {
max = item;
}
}
return max;
}
/**
* Returns the last item that is equal to or greater than every other item.
*/
export function findLastMaxBy<T>(array: readonly T[], comparator: Comparator<T>): T | undefined {
if (array.length === 0) {
return undefined;
}
let max = array[0];
for (let i = 1; i < array.length; i++) {
const item = array[i];
if (comparator(item, max) >= 0) {
max = item;
}
}
return max;
}
/**
* Returns the first item that is equal to or less than every other item.
*/
export function findFirstMinBy<T>(array: readonly T[], comparator: Comparator<T>): T | undefined {
return findFirstMaxBy(array, (a, b) => -comparator(a, b));
}
export function findMaxIdxBy<T>(array: readonly T[], comparator: Comparator<T>): number {
if (array.length === 0) {
return -1;
}
let maxIdx = 0;
for (let i = 1; i < array.length; i++) {
const item = array[i];
if (comparator(item, array[maxIdx]) > 0) {
maxIdx = i;
}
}
return maxIdx;
}
/**
* Returns the first mapped value of the array which is not undefined.
*/
export function mapFindFirst<T, R>(items: Iterable<T>, mapFn: (value: T) => R | undefined): R | undefined {
for (const value of items) {
const mapped = mapFn(value);
if (mapped !== undefined) {
return mapped;
}
}
return undefined;
}

View file

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as arrays from 'vs/base/common/arrays';
import * as arraysFind from 'vs/base/common/arraysFind';
suite('Arrays', () => {
@ -22,25 +23,25 @@ suite('Arrays', () => {
test('findFirst', () => {
const array = [1, 4, 5, 7, 55, 59, 60, 61, 64, 69];
let idx = arrays.findFirstInSorted(array, e => e >= 0);
let idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e >= 0);
assert.strictEqual(array[idx], 1);
idx = arrays.findFirstInSorted(array, e => e > 1);
idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e > 1);
assert.strictEqual(array[idx], 4);
idx = arrays.findFirstInSorted(array, e => e >= 8);
idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e >= 8);
assert.strictEqual(array[idx], 55);
idx = arrays.findFirstInSorted(array, e => e >= 61);
idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e >= 61);
assert.strictEqual(array[idx], 61);
idx = arrays.findFirstInSorted(array, e => e >= 69);
idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e >= 69);
assert.strictEqual(array[idx], 69);
idx = arrays.findFirstInSorted(array, e => e >= 70);
idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e >= 70);
assert.strictEqual(idx, array.length);
idx = arrays.findFirstInSorted([], e => e >= 0);
idx = arraysFind.findFirstIdxMonotonousOrArrLen([], e => e >= 0);
assert.strictEqual(array[idx], 1);
});
@ -372,7 +373,7 @@ suite('Arrays', () => {
const array = [{ v: 3 }, { v: 5 }, { v: 2 }, { v: 2 }, { v: 2 }, { v: 5 }];
assert.strictEqual(
array.indexOf(arrays.findMaxBy(array, arrays.compareBy(v => v.v, arrays.numberComparator))!),
array.indexOf(arraysFind.findFirstMaxBy(array, arrays.compareBy(v => v.v, arrays.numberComparator))!),
1
);
});
@ -381,7 +382,7 @@ suite('Arrays', () => {
const array = [{ v: 3 }, { v: 5 }, { v: 2 }, { v: 2 }, { v: 2 }, { v: 5 }];
assert.strictEqual(
array.indexOf(arrays.findLastMaxBy(array, arrays.compareBy(v => v.v, arrays.numberComparator))!),
array.indexOf(arraysFind.findLastMaxBy(array, arrays.compareBy(v => v.v, arrays.numberComparator))!),
5
);
});
@ -390,7 +391,7 @@ suite('Arrays', () => {
const array = [{ v: 3 }, { v: 5 }, { v: 2 }, { v: 2 }, { v: 2 }, { v: 5 }];
assert.strictEqual(
array.indexOf(arrays.findMinBy(array, arrays.compareBy(v => v.v, arrays.numberComparator))!),
array.indexOf(arraysFind.findFirstMinBy(array, arrays.compareBy(v => v.v, arrays.numberComparator))!),
2
);
});

File diff suppressed because it is too large Load diff

View file

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { addDisposableListener, addStandardDisposableListener, reset } from 'vs/base/browser/dom';
import { createTrustedTypesPolicy } from 'vs/base/browser/trustedTypes';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { Action } from 'vs/base/common/actions';
@ -16,7 +17,6 @@ import { ThemeIcon } from 'vs/base/common/themables';
import { applyFontInfo } from 'vs/editor/browser/config/domFontInfo';
import { DiffEditorEditors } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorEditors';
import { applyStyle } from 'vs/editor/browser/widget/diffEditorWidget2/utils';
import { DiffReview } from 'vs/editor/browser/widget/diffReview';
import { EditorFontLigatures, EditorOption, IComputedEditorOptions } from 'vs/editor/common/config/editorOptions';
import { LineRange } from 'vs/editor/common/core/lineRange';
import { OffsetRange } from 'vs/editor/common/core/offsetRange';
@ -39,6 +39,8 @@ const accessibleDiffViewerRemoveIcon = registerIcon('diff-review-remove', Codico
const accessibleDiffViewerCloseIcon = registerIcon('diff-review-close', Codicon.close, localize('accessibleDiffViewerCloseIcon', 'Icon for \'Close\' in accessible diff viewer.'));
export class AccessibleDiffViewer extends Disposable {
public static _ttPolicy = createTrustedTypesPolicy('diffReview', { createHTML: value => value });
constructor(
private readonly _parentNode: HTMLElement,
private readonly _visible: IObservable<boolean>,
@ -590,15 +592,15 @@ class View extends Disposable {
let lineContent: string;
if (item.modifiedLineNumber !== undefined) {
let html: string | TrustedHTML = this._getLineHtml(modifiedModel, modifiedOptions, modifiedModelOpts.tabSize, item.modifiedLineNumber, this._languageService.languageIdCodec);
if (DiffReview._ttPolicy) {
html = DiffReview._ttPolicy.createHTML(html as string);
if (AccessibleDiffViewer._ttPolicy) {
html = AccessibleDiffViewer._ttPolicy.createHTML(html as string);
}
cell.insertAdjacentHTML('beforeend', html as string);
lineContent = modifiedModel.getLineContent(item.modifiedLineNumber);
} else {
let html: string | TrustedHTML = this._getLineHtml(originalModel, originalOptions, originalModelOpts.tabSize, item.originalLineNumber, this._languageService.languageIdCodec);
if (DiffReview._ttPolicy) {
html = DiffReview._ttPolicy.createHTML(html as string);
if (AccessibleDiffViewer._ttPolicy) {
html = AccessibleDiffViewer._ttPolicy.createHTML(html as string);
}
cell.insertAdjacentHTML('beforeend', html as string);
lineContent = originalModel.getLineContent(item.originalLineNumber);

View file

@ -8,7 +8,6 @@ import { IObservable, IReader, autorunHandleChanges, observableFromEvent } from
import { IEditorConstructionOptions } from 'vs/editor/browser/config/editorConfiguration';
import { IDiffEditorConstructionOptions } from 'vs/editor/browser/editorBrowser';
import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget';
import { IDiffCodeEditorWidgetOptions } from 'vs/editor/browser/widget/diffEditorWidget';
import { OverviewRulerPart } from 'vs/editor/browser/widget/diffEditorWidget2/overviewRulerPart';
import { EditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IContentSizeChangedEvent } from 'vs/editor/common/editorCommon';
@ -17,6 +16,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { DiffEditorOptions } from './diffEditorOptions';
import { ITextModel } from 'vs/editor/common/model';
import { IDiffCodeEditorWidgetOptions } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';
export class DiffEditorEditors extends Disposable {
public readonly modified: CodeEditorWidget;

View file

@ -7,10 +7,12 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IObservable, IReader, ISettableObservable, ITransaction, autorunWithStore, derived, observableSignal, observableSignalFromEvent, observableValue, transaction, waitForState } from 'vs/base/common/observable';
import { IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { IDiffProviderFactoryService } from 'vs/editor/browser/widget/diffEditorWidget2/diffProviderFactoryService';
import { readHotReloadableExport } from 'vs/editor/browser/widget/diffEditorWidget2/utils';
import { ISerializedLineRange, LineRange } from 'vs/editor/common/core/lineRange';
import { DefaultLinesDiffComputer } from 'vs/editor/common/diff/defaultLinesDiffComputer/defaultLinesDiffComputer';
import { IDocumentDiff, IDocumentDiffProvider } from 'vs/editor/common/diff/documentDiffProvider';
import { IDocumentDiff } from 'vs/editor/common/diff/documentDiffProvider';
import { MovedText } from 'vs/editor/common/diff/linesDiffComputer';
import { DetailedLineRangeMapping } from 'vs/editor/common/diff/rangeMapping';
import { IDiffEditorModel, IDiffEditorViewModel } from 'vs/editor/common/editorCommon';
@ -64,10 +66,22 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo
private readonly _cancellationTokenSource = new CancellationTokenSource();
private readonly _diffProvider = derived(this, reader => {
const diffProvider = this._diffProviderFactoryService.createDiffProvider(this._editor, {
diffAlgorithm: this._options.diffAlgorithm.read(reader)
});
const onChangeSignal = observableSignalFromEvent('onDidChange', diffProvider.onDidChange);
return {
diffProvider,
onChangeSignal,
};
});
constructor(
public readonly model: IDiffEditorModel,
private readonly _options: DiffEditorOptions,
documentDiffProvider: IDocumentDiffProvider,
private readonly _editor: IDiffEditor,
@IDiffProviderFactoryService private readonly _diffProviderFactoryService: IDiffProviderFactoryService,
) {
super();
@ -162,8 +176,6 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo
debouncer.schedule();
}));
const documentDiffProviderOptionChanged = observableSignalFromEvent('documentDiffProviderOptionChanged', documentDiffProvider.onDidChange);
this._register(autorunWithStore(async (reader, store) => {
/** @description compute diff */
@ -173,7 +185,9 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo
debouncer.cancel();
contentChangedSignal.read(reader);
documentDiffProviderOptionChanged.read(reader);
const documentDiffProvider = this._diffProvider.read(reader);
documentDiffProvider.onChangeSignal.read(reader);
readHotReloadableExport(DefaultLinesDiffComputer, reader);
this._isDiffUpToDate.set(false, undefined);
@ -190,7 +204,7 @@ export class DiffEditorViewModel extends Disposable implements IDiffEditorViewMo
modifiedTextEditInfos = combineTextEditInfos(modifiedTextEditInfos, edits);
}));
let result = await documentDiffProvider.computeDiff(model.original, model.modified, {
let result = await documentDiffProvider.diffProvider.computeDiff(model.original, model.modified, {
ignoreTrimWhitespace: this._options.ignoreTrimWhitespace.read(reader),
maxComputationTimeMs: this._options.maxComputationTimeMs.read(reader),
computeMoves: this._options.showMoves.read(reader),

View file

@ -4,9 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import { $, h } from 'vs/base/browser/dom';
import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash';
import { findLast } from 'vs/base/common/arrays';
import { findLast } from 'vs/base/common/arraysFind';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Event } from 'vs/base/common/event';
import { toDisposable } from 'vs/base/common/lifecycle';
import { IObservable, autorun, autorunWithStore, derived, derivedWithStore, disposableObservableValue, recomputeInitiallyAndOnChange, observableValue, transaction } from 'vs/base/common/observable';
import 'vs/css!./style';
import { IEditorConstructionOptions } from 'vs/editor/browser/config/editorConfiguration';
@ -14,23 +15,21 @@ import { ICodeEditor, IDiffEditor, IDiffEditorConstructionOptions, IMouseTargetV
import { EditorExtensionsRegistry, IDiffEditorContributionDescription } from 'vs/editor/browser/editorExtensions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget';
import { IDiffCodeEditorWidgetOptions } from 'vs/editor/browser/widget/diffEditorWidget';
import { AccessibleDiffViewer } from 'vs/editor/browser/widget/diffEditorWidget2/accessibleDiffViewer';
import { DiffEditorDecorations } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorDecorations';
import { DiffEditorSash } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorSash';
import { HideUnchangedRegionsFeature } from 'vs/editor/browser/widget/diffEditorWidget2/hideUnchangedRegionsFeature';
import { ViewZoneManager } from 'vs/editor/browser/widget/diffEditorWidget2/lineAlignment';
import { MovedBlocksLinesPart } from 'vs/editor/browser/widget/diffEditorWidget2/movedBlocksLines';
import { OverviewRulerPart } from 'vs/editor/browser/widget/diffEditorWidget2/overviewRulerPart';
import { HideUnchangedRegionsFeature } from 'vs/editor/browser/widget/diffEditorWidget2/hideUnchangedRegionsFeature';
import { CSSStyle, ObservableElementSizeObserver, applyStyle, readHotReloadableExport } from 'vs/editor/browser/widget/diffEditorWidget2/utils';
import { WorkerBasedDocumentDiffProvider } from 'vs/editor/browser/widget/workerBasedDocumentDiffProvider';
import { IDiffEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IDimension } from 'vs/editor/common/core/dimension';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { CursorChangeReason } from 'vs/editor/common/cursorEvents';
import { DetailedLineRangeMapping } from 'vs/editor/common/diff/rangeMapping';
import { IDiffComputationResult, ILineChange } from 'vs/editor/common/diff/legacyLinesDiffComputer';
import { DetailedLineRangeMapping } from 'vs/editor/common/diff/rangeMapping';
import { EditorType, IDiffEditorModel, IDiffEditorViewModel, IDiffEditorViewState } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
@ -39,15 +38,21 @@ import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioC
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
import './colors';
import { DelegatingEditor } from './delegatingEditorImpl';
import { DiffEditorEditors } from './diffEditorEditors';
import { DiffEditorOptions } from './diffEditorOptions';
import { DiffEditorViewModel, DiffMapping, DiffState } from './diffEditorViewModel';
import { toDisposable } from 'vs/base/common/lifecycle';
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
export interface IDiffCodeEditorWidgetOptions {
originalEditor?: ICodeEditorWidgetOptions;
modifiedEditor?: ICodeEditorWidgetOptions;
}
export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor {
public static ENTIRE_DIFF_OVERVIEW_WIDTH = OverviewRulerPart.ENTIRE_DIFF_OVERVIEW_WIDTH;
private readonly elements = h('div.monaco-diff-editor.side-by-side', { style: { position: 'relative', height: '100%' } }, [
h('div.noModificationsOverlay@overlay', { style: { position: 'absolute', height: '100%', visibility: 'hidden', } }, [$('span', {}, 'No Changes')]),
h('div.editor.original@original', { style: { position: 'absolute', height: '100%' } }),
@ -280,6 +285,10 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor {
}));
}
public getViewWidth(): number {
return this._rootSizeObserver.width.get();
}
public getContentHeight() {
return this._editors.modified.getContentHeight();
}
@ -366,12 +375,7 @@ export class DiffEditorWidget2 extends DelegatingEditor implements IDiffEditor {
}
public createViewModel(model: IDiffEditorModel): IDiffEditorViewModel {
return new DiffEditorViewModel(
model,
this._options,
// TODO@hediet make diffAlgorithm observable
this._instantiationService.createInstance(WorkerBasedDocumentDiffProvider, { diffAlgorithm: this._options.diffAlgorithm.get() })
);
return this._instantiationService.createInstance(DiffEditorViewModel, model, this._options, this);
}
override getModel(): IDiffEditorModel | null { return this._diffModel.get()?.model ?? null; }

View file

@ -0,0 +1,35 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { WorkerBasedDocumentDiffProvider } from 'vs/editor/browser/widget/workerBasedDocumentDiffProvider';
import { IDocumentDiffProvider } from 'vs/editor/common/diff/documentDiffProvider';
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const IDiffProviderFactoryService = createDecorator<IDiffProviderFactoryService>('diffProviderFactoryService');
export interface IDocumentDiffProviderOptions {
readonly diffAlgorithm?: 'legacy' | 'advanced';
}
export interface IDiffProviderFactoryService {
readonly _serviceBrand: undefined;
createDiffProvider(editor: IDiffEditor, options: IDocumentDiffProviderOptions): IDocumentDiffProvider;
}
export class DiffProviderFactoryService implements IDiffProviderFactoryService {
readonly _serviceBrand: undefined;
constructor(
@IInstantiationService private readonly instantiationService: IInstantiationService,
) { }
createDiffProvider(editor: IDiffEditor, options: IDocumentDiffProviderOptions): IDocumentDiffProvider {
return this.instantiationService.createInstance(WorkerBasedDocumentDiffProvider, options);
}
}
registerSingleton(IDiffProviderFactoryService, DiffProviderFactoryService, InstantiationType.Delayed);

View file

@ -6,7 +6,8 @@
import { h } from 'vs/base/browser/dom';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { Action } from 'vs/base/common/actions';
import { booleanComparator, compareBy, findMaxIdxBy, numberComparator, tieBreakComparators } from 'vs/base/common/arrays';
import { booleanComparator, compareBy, numberComparator, tieBreakComparators } from 'vs/base/common/arrays';
import { findMaxIdxBy } from 'vs/base/common/arraysFind';
import { Codicon } from 'vs/base/common/codicons';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IObservable, autorun, autorunHandleChanges, autorunWithStore, constObservable, derived, derivedWithStore, observableFromEvent, observableSignalFromEvent, observableValue, recomputeInitiallyAndOnChange } from 'vs/base/common/observable';

View file

@ -3,9 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createTrustedTypesPolicy } from 'vs/base/browser/trustedTypes';
import { applyFontInfo } from 'vs/editor/browser/config/domFontInfo';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { diffEditorWidgetTtPolicy } from 'vs/editor/browser/widget/diffEditorWidget';
import { EditorFontLigatures, EditorOption, FindComputedEditorOptionValueById } from 'vs/editor/common/config/editorOptions';
import { FontInfo } from 'vs/editor/common/config/fontInfo';
import { StringBuilder } from 'vs/editor/common/core/stringBuilder';
@ -15,7 +15,7 @@ import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';
import { RenderLineInput, renderViewLine } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { InlineDecoration, ViewLineRenderingData } from 'vs/editor/common/viewModel';
const ttPolicy = diffEditorWidgetTtPolicy;
const ttPolicy = createTrustedTypesPolicy('diffEditorWidget', { createHTML: value => value });
export function renderLines(source: LineSource, options: RenderOptions, decorations: InlineDecoration[], domNode: HTMLElement): RenderLinesResult {
applyFontInfo(domNode, options.fontInfo);

View file

@ -1,278 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'vs/base/common/assert';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import * as objects from 'vs/base/common/objects';
import { IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { ICursorPositionChangedEvent } from 'vs/editor/common/cursorEvents';
import { Range } from 'vs/editor/common/core/range';
import { ILineChange } from 'vs/editor/common/diff/legacyLinesDiffComputer';
import { ScrollType } from 'vs/editor/common/editorCommon';
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
interface IDiffRange {
rhs: boolean;
range: Range;
}
export interface Options {
followsCaret?: boolean;
ignoreCharChanges?: boolean;
alwaysRevealFirst?: boolean;
findResultLoop?: boolean;
}
const defaultOptions: Options = {
followsCaret: true,
ignoreCharChanges: true,
alwaysRevealFirst: true,
findResultLoop: true
};
export interface IDiffNavigator {
canNavigate(): boolean;
next(): void;
previous(): void;
dispose(): void;
}
/**
* Create a new diff navigator for the provided diff editor.
*/
export class DiffNavigator extends Disposable implements IDiffNavigator {
private readonly _editor: IDiffEditor;
private readonly _options: Options;
private readonly _onDidUpdate = this._register(new Emitter<this>());
readonly onDidUpdate: Event<this> = this._onDidUpdate.event;
private disposed: boolean;
public revealFirst: boolean;
private nextIdx: number;
private ranges: IDiffRange[];
private ignoreSelectionChange: boolean;
constructor(
editor: IDiffEditor,
options: Options = {},
@IAudioCueService private readonly _audioCueService: IAudioCueService,
@ICodeEditorService private readonly _codeEditorService: ICodeEditorService,
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService
) {
super();
this._editor = editor;
this._options = objects.mixin(options, defaultOptions, false);
this.disposed = false;
this.nextIdx = -1;
this.ranges = [];
this.ignoreSelectionChange = false;
this.revealFirst = Boolean(this._options.alwaysRevealFirst);
this._register(this._editor.onDidUpdateDiff(() => this._onDiffUpdated()));
if (this._options.followsCaret) {
this._register(this._editor.getModifiedEditor().onDidChangeCursorPosition((e: ICursorPositionChangedEvent) => {
if (this.ignoreSelectionChange) {
return;
}
this._updateAccessibilityState(e.position.lineNumber);
this.nextIdx = -1;
}));
}
// init things
this._init();
}
private _init(): void {
const changes = this._editor.getLineChanges();
if (!changes) {
return;
}
}
private _onDiffUpdated(): void {
this._init();
this._compute(this._editor.getLineChanges());
if (this.revealFirst) {
// Only reveal first on first non-null changes
if (this._editor.getLineChanges() !== null) {
this.revealFirst = false;
this.nextIdx = -1;
this.next(ScrollType.Immediate);
}
}
}
private _compute(lineChanges: ILineChange[] | null): void {
// new ranges
this.ranges = [];
if (lineChanges) {
// create ranges from changes
lineChanges.forEach((lineChange) => {
if (!this._options.ignoreCharChanges && lineChange.charChanges) {
lineChange.charChanges.forEach((charChange) => {
this.ranges.push({
rhs: true,
range: new Range(
charChange.modifiedStartLineNumber,
charChange.modifiedStartColumn,
charChange.modifiedEndLineNumber,
charChange.modifiedEndColumn)
});
});
} else {
if (lineChange.modifiedEndLineNumber === 0) {
// a deletion
this.ranges.push({
rhs: true,
range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedStartLineNumber + 1, 1)
});
} else {
// an insertion or modification
this.ranges.push({
rhs: true,
range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber + 1, 1)
});
}
}
});
}
// sort
this.ranges.sort((left, right) => Range.compareRangesUsingStarts(left.range, right.range));
this._onDidUpdate.fire(this);
}
private _initIdx(fwd: boolean): void {
let found = false;
const position = this._editor.getPosition();
if (!position) {
this.nextIdx = 0;
return;
}
for (let i = 0, len = this.ranges.length; i < len && !found; i++) {
const range = this.ranges[i].range;
if (position.isBeforeOrEqual(range.getStartPosition())) {
this.nextIdx = i + (fwd ? 0 : -1);
found = true;
}
}
if (!found) {
// after the last change
this.nextIdx = fwd ? 0 : this.ranges.length - 1;
}
if (this.nextIdx < 0) {
this.nextIdx = this.ranges.length - 1;
}
}
private _move(fwd: boolean, scrollType: ScrollType): void {
assert.ok(!this.disposed, 'Illegal State - diff navigator has been disposed');
if (!this.canNavigate()) {
return;
}
if (this.nextIdx === -1) {
this._initIdx(fwd);
} else if (fwd) {
this.nextIdx += 1;
if (this.nextIdx >= this.ranges.length) {
this.nextIdx = 0;
}
} else {
this.nextIdx -= 1;
if (this.nextIdx < 0) {
this.nextIdx = this.ranges.length - 1;
}
}
const info = this.ranges[this.nextIdx];
this.ignoreSelectionChange = true;
try {
const pos = info.range.getStartPosition();
this._editor.setPosition(pos);
this._editor.revealRangeInCenter(info.range, scrollType);
this._updateAccessibilityState(pos.lineNumber, true);
} finally {
this.ignoreSelectionChange = false;
}
}
_updateAccessibilityState(lineNumber: number, jumpToChange?: boolean): void {
const modifiedEditor = this._editor.getModel()?.modified;
if (!modifiedEditor) {
return;
}
const insertedOrModified = modifiedEditor.getLineDecorations(lineNumber).find(l => l.options.className === 'line-insert');
if (insertedOrModified) {
this._audioCueService.playAudioCue(AudioCue.diffLineModified, { allowManyInParallel: true });
} else if (jumpToChange) {
// The modified editor does not include deleted lines, but when
// we are moved to the area where lines were deleted, play this cue
this._audioCueService.playAudioCue(AudioCue.diffLineDeleted, { allowManyInParallel: true });
} else {
return;
}
const codeEditor = this._codeEditorService.getActiveCodeEditor();
if (jumpToChange && codeEditor && insertedOrModified && this._accessibilityService.isScreenReaderOptimized()) {
codeEditor.setSelection({ startLineNumber: lineNumber, startColumn: 0, endLineNumber: lineNumber, endColumn: Number.MAX_VALUE });
codeEditor.writeScreenReaderContent('diff-navigation');
}
}
canNavigate(): boolean {
return this.ranges && this.ranges.length > 0;
}
next(scrollType: ScrollType = ScrollType.Smooth): void {
if (!this.canNavigateNext()) {
return;
}
this._move(true, scrollType);
}
previous(scrollType: ScrollType = ScrollType.Smooth): void {
if (!this.canNavigatePrevious()) {
return;
}
this._move(false, scrollType);
}
canNavigateNext(): boolean {
return this.canNavigateLoop() || this.nextIdx < this.ranges.length - 1;
}
canNavigatePrevious(): boolean {
return this.canNavigateLoop() || this.nextIdx !== 0;
}
canNavigateLoop(): boolean {
return Boolean(this._options.findResultLoop);
}
override dispose(): void {
super.dispose();
this.ranges = [];
this.disposed = true;
}
}

View file

@ -1,826 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from 'vs/base/browser/dom';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { createTrustedTypesPolicy } from 'vs/base/browser/trustedTypes';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { Action } from 'vs/base/common/actions';
import { Codicon } from 'vs/base/common/codicons';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { Disposable } from 'vs/base/common/lifecycle';
import { ThemeIcon } from 'vs/base/common/themables';
import { Constants } from 'vs/base/common/uint';
import 'vs/css!./media/diffReview';
import { applyFontInfo } from 'vs/editor/browser/config/domFontInfo';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { EditorFontLigatures, EditorOption, IComputedEditorOptions } from 'vs/editor/common/config/editorOptions';
import { Position } from 'vs/editor/common/core/position';
import { ILineChange } from 'vs/editor/common/diff/legacyLinesDiffComputer';
import { ScrollType } from 'vs/editor/common/editorCommon';
import { ILanguageIdCodec } from 'vs/editor/common/languages';
import { ILanguageService } from 'vs/editor/common/languages/language';
import { ITextModel, TextModelResolvedOptions } from 'vs/editor/common/model';
import { LineTokens } from 'vs/editor/common/tokens/lineTokens';
import { RenderLineInput, renderViewLine2 as renderViewLine } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { ViewLineRenderingData } from 'vs/editor/common/viewModel';
import * as nls from 'vs/nls';
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
const DIFF_LINES_PADDING = 3;
const enum DiffEntryType {
Equal = 0,
Insert = 1,
Delete = 2
}
class DiffEntry {
readonly originalLineStart: number;
readonly originalLineEnd: number;
readonly modifiedLineStart: number;
readonly modifiedLineEnd: number;
constructor(originalLineStart: number, originalLineEnd: number, modifiedLineStart: number, modifiedLineEnd: number) {
this.originalLineStart = originalLineStart;
this.originalLineEnd = originalLineEnd;
this.modifiedLineStart = modifiedLineStart;
this.modifiedLineEnd = modifiedLineEnd;
}
public getType(): DiffEntryType {
if (this.originalLineStart === 0) {
return DiffEntryType.Insert;
}
if (this.modifiedLineStart === 0) {
return DiffEntryType.Delete;
}
return DiffEntryType.Equal;
}
}
const enum DiffEditorLineClasses {
Insert = 'line-insert',
Delete = 'line-delete'
}
class Diff {
readonly entries: DiffEntry[];
constructor(entries: DiffEntry[]) {
this.entries = entries;
}
}
const diffReviewInsertIcon = registerIcon('diff-review-insert', Codicon.add, nls.localize('diffReviewInsertIcon', 'Icon for \'Insert\' in diff review.'));
const diffReviewRemoveIcon = registerIcon('diff-review-remove', Codicon.remove, nls.localize('diffReviewRemoveIcon', 'Icon for \'Remove\' in diff review.'));
const diffReviewCloseIcon = registerIcon('diff-review-close', Codicon.close, nls.localize('diffReviewCloseIcon', 'Icon for \'Close\' in diff review.'));
export class DiffReview extends Disposable {
public static _ttPolicy = createTrustedTypesPolicy('diffReview', { createHTML: value => value });
private readonly _diffEditor: DiffEditorWidget;
private _isVisible: boolean;
public readonly shadow: FastDomNode<HTMLElement>;
private readonly _actionBar: ActionBar;
public readonly actionBarContainer: FastDomNode<HTMLElement>;
public readonly domNode: FastDomNode<HTMLElement>;
private readonly _content: FastDomNode<HTMLElement>;
private readonly scrollbar: DomScrollableElement;
private _diffs: Diff[];
private _currentDiff: Diff | null;
constructor(
diffEditor: DiffEditorWidget,
@ILanguageService private readonly _languageService: ILanguageService,
@IAudioCueService private readonly _audioCueService: IAudioCueService,
@IConfigurationService private readonly _configurationService: IConfigurationService
) {
super();
this._diffEditor = diffEditor;
this._isVisible = false;
this.shadow = createFastDomNode(document.createElement('div'));
this.shadow.setClassName('diff-review-shadow');
this.actionBarContainer = createFastDomNode(document.createElement('div'));
this.actionBarContainer.setClassName('diff-review-actions');
this._actionBar = this._register(new ActionBar(
this.actionBarContainer.domNode
));
this._actionBar.push(new Action('diffreview.close', nls.localize('label.close', "Close"), 'close-diff-review ' + ThemeIcon.asClassName(diffReviewCloseIcon), true, async () => this.hide()), { label: false, icon: true });
this.domNode = createFastDomNode(document.createElement('div'));
this.domNode.setClassName('diff-review monaco-editor-background');
this._content = createFastDomNode(document.createElement('div'));
this._content.setClassName('diff-review-content');
this._content.setAttribute('role', 'code');
this.scrollbar = this._register(new DomScrollableElement(this._content.domNode, {}));
this.domNode.domNode.appendChild(this.scrollbar.getDomNode());
this._register(diffEditor.onDidUpdateDiff(() => {
if (!this._isVisible) {
return;
}
this._diffs = this._compute();
this._render();
}));
this._register(diffEditor.getModifiedEditor().onDidChangeCursorPosition(() => {
if (!this._isVisible) {
return;
}
this._render();
}));
this._register(dom.addStandardDisposableListener(this.domNode.domNode, 'click', (e) => {
e.preventDefault();
const row = dom.findParentWithClass(e.target, 'diff-review-row');
if (row) {
this._goToRow(row);
}
}));
this._register(dom.addStandardDisposableListener(this.domNode.domNode, 'keydown', (e) => {
if (
e.equals(KeyCode.DownArrow)
|| e.equals(KeyMod.CtrlCmd | KeyCode.DownArrow)
|| e.equals(KeyMod.Alt | KeyCode.DownArrow)
) {
e.preventDefault();
this._goToRow(this._getNextRow(), 'next');
}
if (
e.equals(KeyCode.UpArrow)
|| e.equals(KeyMod.CtrlCmd | KeyCode.UpArrow)
|| e.equals(KeyMod.Alt | KeyCode.UpArrow)
) {
e.preventDefault();
this._goToRow(this._getPrevRow(), 'previous');
}
if (
e.equals(KeyCode.Escape)
|| e.equals(KeyMod.CtrlCmd | KeyCode.Escape)
|| e.equals(KeyMod.Alt | KeyCode.Escape)
|| e.equals(KeyMod.Shift | KeyCode.Escape)
|| e.equals(KeyCode.Space)
|| e.equals(KeyCode.Enter)
) {
e.preventDefault();
this.accept();
}
}));
this._register(this._configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('accessibility.verbosity.diffEditor')) {
this._diffEditor.updateOptions({ accessibilityVerbose: this._configurationService.getValue('accessibility.verbosity.diffEditor') });
}
}));
this._diffs = [];
this._currentDiff = null;
}
public prev(): void {
let index = 0;
if (!this._isVisible) {
this._diffs = this._compute();
}
if (this._isVisible) {
let currentIndex = -1;
for (let i = 0, len = this._diffs.length; i < len; i++) {
if (this._diffs[i] === this._currentDiff) {
currentIndex = i;
break;
}
}
index = (this._diffs.length + currentIndex - 1);
} else {
index = this._findDiffIndex(this._diffEditor.getPosition()!);
}
if (this._diffs.length === 0) {
// Nothing to do
return;
}
index = index % this._diffs.length;
const entries = this._diffs[index].entries;
this._diffEditor.setPosition(new Position(entries[0].modifiedLineStart, 1));
this._diffEditor.setSelection({ startColumn: 1, startLineNumber: entries[0].modifiedLineStart, endColumn: Constants.MAX_SAFE_SMALL_INTEGER, endLineNumber: entries[entries.length - 1].modifiedLineEnd });
this._isVisible = true;
this._diffEditor.doLayout();
this._render();
this._goToRow(this._getPrevRow(), 'previous');
}
public next(): void {
let index = 0;
if (!this._isVisible) {
this._diffs = this._compute();
}
if (this._isVisible) {
let currentIndex = -1;
for (let i = 0, len = this._diffs.length; i < len; i++) {
if (this._diffs[i] === this._currentDiff) {
currentIndex = i;
break;
}
}
index = (currentIndex + 1);
} else {
index = this._findDiffIndex(this._diffEditor.getPosition()!);
}
if (this._diffs.length === 0) {
// Nothing to do
return;
}
index = index % this._diffs.length;
const entries = this._diffs[index].entries;
this._diffEditor.setPosition(new Position(entries[0].modifiedLineStart, 1));
this._diffEditor.setSelection({ startColumn: 1, startLineNumber: entries[0].modifiedLineStart, endColumn: Constants.MAX_SAFE_SMALL_INTEGER, endLineNumber: entries[entries.length - 1].modifiedLineEnd });
this._isVisible = true;
this._diffEditor.doLayout();
this._render();
this._goToRow(this._getNextRow(), 'next');
}
private accept(): void {
let jumpToLineNumber = -1;
const current = this._getCurrentFocusedRow();
if (current) {
const lineNumber = parseInt(current.getAttribute('data-line')!, 10);
if (!isNaN(lineNumber)) {
jumpToLineNumber = lineNumber;
}
}
this.hide();
if (jumpToLineNumber !== -1) {
this._diffEditor.setPosition(new Position(jumpToLineNumber, 1));
this._diffEditor.revealPosition(new Position(jumpToLineNumber, 1), ScrollType.Immediate);
}
}
private hide(): void {
this._isVisible = false;
this._diffEditor.updateOptions({ readOnly: false });
this._diffEditor.focus();
this._diffEditor.doLayout();
this._render();
}
private _getPrevRow(): HTMLElement {
const current = this._getCurrentFocusedRow();
if (!current) {
return this._getFirstRow();
}
if (current.previousElementSibling) {
return <HTMLElement>current.previousElementSibling;
}
return current;
}
private _getNextRow(): HTMLElement {
const current = this._getCurrentFocusedRow();
if (!current) {
return this._getFirstRow();
}
if (current.nextElementSibling) {
return <HTMLElement>current.nextElementSibling;
}
return current;
}
private _getFirstRow(): HTMLElement {
return <HTMLElement>this.domNode.domNode.querySelector('.diff-review-row');
}
private _getCurrentFocusedRow(): HTMLElement | null {
const result = <HTMLElement>document.activeElement;
if (result && /diff-review-row/.test(result.className)) {
return result;
}
return null;
}
private _goToRow(row: HTMLElement, type?: 'next' | 'previous'): void {
const current = this._getCurrentFocusedRow();
row.tabIndex = 0;
row.focus();
if (current && current !== row) {
current.tabIndex = -1;
}
const element = !type ? current : type === 'next' ? current?.nextElementSibling : current?.previousElementSibling;
if (element?.classList.contains(DiffEditorLineClasses.Insert)) {
this._audioCueService.playAudioCue(AudioCue.diffLineInserted, { allowManyInParallel: true });
} else if (element?.classList.contains(DiffEditorLineClasses.Delete)) {
this._audioCueService.playAudioCue(AudioCue.diffLineDeleted, { allowManyInParallel: true });
}
this.scrollbar.scanDomNode();
}
public isVisible(): boolean {
return this._isVisible;
}
private _width: number = 0;
public layout(top: number, width: number, height: number): void {
this._width = width;
this.shadow.setTop(top - 6);
this.shadow.setWidth(width);
this.shadow.setHeight(this._isVisible ? 6 : 0);
this.domNode.setTop(top);
this.domNode.setWidth(width);
this.domNode.setHeight(height);
this._content.setHeight(height);
this._content.setWidth(width);
if (this._isVisible) {
this.actionBarContainer.setAttribute('aria-hidden', 'false');
this.actionBarContainer.setDisplay('block');
} else {
this.actionBarContainer.setAttribute('aria-hidden', 'true');
this.actionBarContainer.setDisplay('none');
}
}
private _compute(): Diff[] {
const lineChanges = this._diffEditor.getLineChanges();
if (!lineChanges || lineChanges.length === 0) {
return [];
}
const originalModel = this._diffEditor.getOriginalEditor().getModel();
const modifiedModel = this._diffEditor.getModifiedEditor().getModel();
if (!originalModel || !modifiedModel) {
return [];
}
return DiffReview._mergeAdjacent(lineChanges, originalModel.getLineCount(), modifiedModel.getLineCount());
}
private static _mergeAdjacent(lineChanges: ILineChange[], originalLineCount: number, modifiedLineCount: number): Diff[] {
if (!lineChanges || lineChanges.length === 0) {
return [];
}
const diffs: Diff[] = [];
let diffsLength = 0;
for (let i = 0, len = lineChanges.length; i < len; i++) {
const lineChange = lineChanges[i];
const originalStart = lineChange.originalStartLineNumber;
const originalEnd = lineChange.originalEndLineNumber;
const modifiedStart = lineChange.modifiedStartLineNumber;
const modifiedEnd = lineChange.modifiedEndLineNumber;
const r: DiffEntry[] = [];
let rLength = 0;
// Emit before anchors
{
const originalEqualAbove = (originalEnd === 0 ? originalStart : originalStart - 1);
const modifiedEqualAbove = (modifiedEnd === 0 ? modifiedStart : modifiedStart - 1);
// Make sure we don't step into the previous diff
let minOriginal = 1;
let minModified = 1;
if (i > 0) {
const prevLineChange = lineChanges[i - 1];
if (prevLineChange.originalEndLineNumber === 0) {
minOriginal = prevLineChange.originalStartLineNumber + 1;
} else {
minOriginal = prevLineChange.originalEndLineNumber + 1;
}
if (prevLineChange.modifiedEndLineNumber === 0) {
minModified = prevLineChange.modifiedStartLineNumber + 1;
} else {
minModified = prevLineChange.modifiedEndLineNumber + 1;
}
}
let fromOriginal = originalEqualAbove - DIFF_LINES_PADDING + 1;
let fromModified = modifiedEqualAbove - DIFF_LINES_PADDING + 1;
if (fromOriginal < minOriginal) {
const delta = minOriginal - fromOriginal;
fromOriginal = fromOriginal + delta;
fromModified = fromModified + delta;
}
if (fromModified < minModified) {
const delta = minModified - fromModified;
fromOriginal = fromOriginal + delta;
fromModified = fromModified + delta;
}
r[rLength++] = new DiffEntry(
fromOriginal, originalEqualAbove,
fromModified, modifiedEqualAbove
);
}
// Emit deleted lines
{
if (originalEnd !== 0) {
r[rLength++] = new DiffEntry(originalStart, originalEnd, 0, 0);
}
}
// Emit inserted lines
{
if (modifiedEnd !== 0) {
r[rLength++] = new DiffEntry(0, 0, modifiedStart, modifiedEnd);
}
}
// Emit after anchors
{
const originalEqualBelow = (originalEnd === 0 ? originalStart + 1 : originalEnd + 1);
const modifiedEqualBelow = (modifiedEnd === 0 ? modifiedStart + 1 : modifiedEnd + 1);
// Make sure we don't step into the next diff
let maxOriginal = originalLineCount;
let maxModified = modifiedLineCount;
if (i + 1 < len) {
const nextLineChange = lineChanges[i + 1];
if (nextLineChange.originalEndLineNumber === 0) {
maxOriginal = nextLineChange.originalStartLineNumber;
} else {
maxOriginal = nextLineChange.originalStartLineNumber - 1;
}
if (nextLineChange.modifiedEndLineNumber === 0) {
maxModified = nextLineChange.modifiedStartLineNumber;
} else {
maxModified = nextLineChange.modifiedStartLineNumber - 1;
}
}
let toOriginal = originalEqualBelow + DIFF_LINES_PADDING - 1;
let toModified = modifiedEqualBelow + DIFF_LINES_PADDING - 1;
if (toOriginal > maxOriginal) {
const delta = maxOriginal - toOriginal;
toOriginal = toOriginal + delta;
toModified = toModified + delta;
}
if (toModified > maxModified) {
const delta = maxModified - toModified;
toOriginal = toOriginal + delta;
toModified = toModified + delta;
}
r[rLength++] = new DiffEntry(
originalEqualBelow, toOriginal,
modifiedEqualBelow, toModified,
);
}
diffs[diffsLength++] = new Diff(r);
}
// Merge adjacent diffs
let curr: DiffEntry[] = diffs[0].entries;
const r: Diff[] = [];
let rLength = 0;
for (let i = 1, len = diffs.length; i < len; i++) {
const thisDiff = diffs[i].entries;
const currLast = curr[curr.length - 1];
const thisFirst = thisDiff[0];
if (
currLast.getType() === DiffEntryType.Equal
&& thisFirst.getType() === DiffEntryType.Equal
&& thisFirst.originalLineStart <= currLast.originalLineEnd
) {
// We are dealing with equal lines that overlap
curr[curr.length - 1] = new DiffEntry(
currLast.originalLineStart, thisFirst.originalLineEnd,
currLast.modifiedLineStart, thisFirst.modifiedLineEnd
);
curr = curr.concat(thisDiff.slice(1));
continue;
}
r[rLength++] = new Diff(curr);
curr = thisDiff;
}
r[rLength++] = new Diff(curr);
return r;
}
private _findDiffIndex(pos: Position): number {
const lineNumber = pos.lineNumber;
for (let i = 0, len = this._diffs.length; i < len; i++) {
const diff = this._diffs[i].entries;
const lastModifiedLine = diff[diff.length - 1].modifiedLineEnd;
if (lineNumber <= lastModifiedLine) {
return i;
}
}
return 0;
}
private _render(): void {
const originalOptions = this._diffEditor.getOriginalEditor().getOptions();
const modifiedOptions = this._diffEditor.getModifiedEditor().getOptions();
const originalModel = this._diffEditor.getOriginalEditor().getModel();
const modifiedModel = this._diffEditor.getModifiedEditor().getModel();
const originalModelOpts = originalModel!.getOptions();
const modifiedModelOpts = modifiedModel!.getOptions();
if (!this._isVisible || !originalModel || !modifiedModel) {
dom.clearNode(this._content.domNode);
this._currentDiff = null;
this.scrollbar.scanDomNode();
return;
}
this._diffEditor.updateOptions({ readOnly: true });
const diffIndex = this._findDiffIndex(this._diffEditor.getPosition()!);
if (this._diffs[diffIndex] === this._currentDiff) {
return;
}
this._currentDiff = this._diffs[diffIndex];
const diffs = this._diffs[diffIndex].entries;
const container = document.createElement('div');
container.className = 'diff-review-table';
container.setAttribute('role', 'list');
container.setAttribute('aria-label', 'Difference review. Use "Stage | Unstage | Revert Selected Ranges" commands');
applyFontInfo(container, modifiedOptions.get(EditorOption.fontInfo));
let minOriginalLine = 0;
let maxOriginalLine = 0;
let minModifiedLine = 0;
let maxModifiedLine = 0;
for (let i = 0, len = diffs.length; i < len; i++) {
const diffEntry = diffs[i];
const originalLineStart = diffEntry.originalLineStart;
const originalLineEnd = diffEntry.originalLineEnd;
const modifiedLineStart = diffEntry.modifiedLineStart;
const modifiedLineEnd = diffEntry.modifiedLineEnd;
if (originalLineStart !== 0 && ((minOriginalLine === 0 || originalLineStart < minOriginalLine))) {
minOriginalLine = originalLineStart;
}
if (originalLineEnd !== 0 && ((maxOriginalLine === 0 || originalLineEnd > maxOriginalLine))) {
maxOriginalLine = originalLineEnd;
}
if (modifiedLineStart !== 0 && ((minModifiedLine === 0 || modifiedLineStart < minModifiedLine))) {
minModifiedLine = modifiedLineStart;
}
if (modifiedLineEnd !== 0 && ((maxModifiedLine === 0 || modifiedLineEnd > maxModifiedLine))) {
maxModifiedLine = modifiedLineEnd;
}
}
const header = document.createElement('div');
header.className = 'diff-review-row';
const cell = document.createElement('div');
cell.className = 'diff-review-cell diff-review-summary';
const originalChangedLinesCnt = maxOriginalLine - minOriginalLine + 1;
const modifiedChangedLinesCnt = maxModifiedLine - minModifiedLine + 1;
cell.appendChild(document.createTextNode(`${diffIndex + 1}/${this._diffs.length}: @@ -${minOriginalLine},${originalChangedLinesCnt} +${minModifiedLine},${modifiedChangedLinesCnt} @@`));
header.setAttribute('data-line', String(minModifiedLine));
const getAriaLines = (lines: number) => {
if (lines === 0) {
return nls.localize('no_lines_changed', "no lines changed");
} else if (lines === 1) {
return nls.localize('one_line_changed', "1 line changed");
} else {
return nls.localize('more_lines_changed', "{0} lines changed", lines);
}
};
const originalChangedLinesCntAria = getAriaLines(originalChangedLinesCnt);
const modifiedChangedLinesCntAria = getAriaLines(modifiedChangedLinesCnt);
header.setAttribute('aria-label', nls.localize({
key: 'header',
comment: [
'This is the ARIA label for a git diff header.',
'A git diff header looks like this: @@ -154,12 +159,39 @@.',
'That encodes that at original line 154 (which is now line 159), 12 lines were removed/changed with 39 lines.',
'Variables 0 and 1 refer to the diff index out of total number of diffs.',
'Variables 2 and 4 will be numbers (a line number).',
'Variables 3 and 5 will be "no lines changed", "1 line changed" or "X lines changed", localized separately.'
]
}, "Difference {0} of {1}: original line {2}, {3}, modified line {4}, {5}", (diffIndex + 1), this._diffs.length, minOriginalLine, originalChangedLinesCntAria, minModifiedLine, modifiedChangedLinesCntAria));
header.appendChild(cell);
// @@ -504,7 +517,7 @@
header.setAttribute('role', 'listitem');
container.appendChild(header);
const lineHeight = modifiedOptions.get(EditorOption.lineHeight);
let modLine = minModifiedLine;
for (let i = 0, len = diffs.length; i < len; i++) {
const diffEntry = diffs[i];
DiffReview._renderSection(container, diffEntry, modLine, lineHeight, this._width, originalOptions, originalModel, originalModelOpts, modifiedOptions, modifiedModel, modifiedModelOpts, this._languageService.languageIdCodec);
if (diffEntry.modifiedLineStart !== 0) {
modLine = diffEntry.modifiedLineEnd;
}
}
dom.clearNode(this._content.domNode);
this._content.domNode.appendChild(container);
this.scrollbar.scanDomNode();
}
private static _renderSection(
dest: HTMLElement, diffEntry: DiffEntry, modLine: number, lineHeight: number, width: number,
originalOptions: IComputedEditorOptions, originalModel: ITextModel, originalModelOpts: TextModelResolvedOptions,
modifiedOptions: IComputedEditorOptions, modifiedModel: ITextModel, modifiedModelOpts: TextModelResolvedOptions,
languageIdCodec: ILanguageIdCodec
): void {
const type = diffEntry.getType();
let rowClassName: string = 'diff-review-row';
let lineNumbersExtraClassName: string = '';
const spacerClassName: string = 'diff-review-spacer';
let spacerIcon: ThemeIcon | null = null;
switch (type) {
case DiffEntryType.Insert:
rowClassName = 'diff-review-row line-insert';
lineNumbersExtraClassName = ' char-insert';
spacerIcon = diffReviewInsertIcon;
break;
case DiffEntryType.Delete:
rowClassName = 'diff-review-row line-delete';
lineNumbersExtraClassName = ' char-delete';
spacerIcon = diffReviewRemoveIcon;
break;
}
const originalLineStart = diffEntry.originalLineStart;
const originalLineEnd = diffEntry.originalLineEnd;
const modifiedLineStart = diffEntry.modifiedLineStart;
const modifiedLineEnd = diffEntry.modifiedLineEnd;
const cnt = Math.max(
modifiedLineEnd - modifiedLineStart,
originalLineEnd - originalLineStart
);
const originalLayoutInfo = originalOptions.get(EditorOption.layoutInfo);
const originalLineNumbersWidth = originalLayoutInfo.glyphMarginWidth + originalLayoutInfo.lineNumbersWidth;
const modifiedLayoutInfo = modifiedOptions.get(EditorOption.layoutInfo);
const modifiedLineNumbersWidth = 10 + modifiedLayoutInfo.glyphMarginWidth + modifiedLayoutInfo.lineNumbersWidth;
for (let i = 0; i <= cnt; i++) {
const originalLine = (originalLineStart === 0 ? 0 : originalLineStart + i);
const modifiedLine = (modifiedLineStart === 0 ? 0 : modifiedLineStart + i);
const row = document.createElement('div');
row.style.minWidth = width + 'px';
row.className = rowClassName;
row.setAttribute('role', 'listitem');
if (modifiedLine !== 0) {
modLine = modifiedLine;
}
row.setAttribute('data-line', String(modLine));
const cell = document.createElement('div');
cell.className = 'diff-review-cell';
cell.style.height = `${lineHeight}px`;
row.appendChild(cell);
const originalLineNumber = document.createElement('span');
originalLineNumber.style.width = (originalLineNumbersWidth + 'px');
originalLineNumber.style.minWidth = (originalLineNumbersWidth + 'px');
originalLineNumber.className = 'diff-review-line-number' + lineNumbersExtraClassName;
if (originalLine !== 0) {
originalLineNumber.appendChild(document.createTextNode(String(originalLine)));
} else {
originalLineNumber.innerText = '\u00a0';
}
cell.appendChild(originalLineNumber);
const modifiedLineNumber = document.createElement('span');
modifiedLineNumber.style.width = (modifiedLineNumbersWidth + 'px');
modifiedLineNumber.style.minWidth = (modifiedLineNumbersWidth + 'px');
modifiedLineNumber.style.paddingRight = '10px';
modifiedLineNumber.className = 'diff-review-line-number' + lineNumbersExtraClassName;
if (modifiedLine !== 0) {
modifiedLineNumber.appendChild(document.createTextNode(String(modifiedLine)));
} else {
modifiedLineNumber.innerText = '\u00a0';
}
cell.appendChild(modifiedLineNumber);
const spacer = document.createElement('span');
spacer.className = spacerClassName;
if (spacerIcon) {
const spacerCodicon = document.createElement('span');
spacerCodicon.className = ThemeIcon.asClassName(spacerIcon);
spacerCodicon.innerText = '\u00a0\u00a0';
spacer.appendChild(spacerCodicon);
} else {
spacer.innerText = '\u00a0\u00a0';
}
cell.appendChild(spacer);
let lineContent: string;
if (modifiedLine !== 0) {
let html: string | TrustedHTML = this._renderLine(modifiedModel, modifiedOptions, modifiedModelOpts.tabSize, modifiedLine, languageIdCodec);
if (DiffReview._ttPolicy) {
html = DiffReview._ttPolicy.createHTML(html as string);
}
cell.insertAdjacentHTML('beforeend', html as string);
lineContent = modifiedModel.getLineContent(modifiedLine);
} else {
let html: string | TrustedHTML = this._renderLine(originalModel, originalOptions, originalModelOpts.tabSize, originalLine, languageIdCodec);
if (DiffReview._ttPolicy) {
html = DiffReview._ttPolicy.createHTML(html as string);
}
cell.insertAdjacentHTML('beforeend', html as string);
lineContent = originalModel.getLineContent(originalLine);
}
if (lineContent.length === 0) {
lineContent = nls.localize('blankLine', "blank");
}
let ariaLabel: string = '';
switch (type) {
case DiffEntryType.Equal:
if (originalLine === modifiedLine) {
ariaLabel = nls.localize({ key: 'unchangedLine', comment: ['The placeholders are contents of the line and should not be translated.'] }, "{0} unchanged line {1}", lineContent, originalLine);
} else {
ariaLabel = nls.localize('equalLine', "{0} original line {1} modified line {2}", lineContent, originalLine, modifiedLine);
}
break;
case DiffEntryType.Insert:
ariaLabel = nls.localize('insertLine', "+ {0} modified line {1}", lineContent, modifiedLine);
break;
case DiffEntryType.Delete:
ariaLabel = nls.localize('deleteLine', "- {0} original line {1}", lineContent, originalLine);
break;
}
row.setAttribute('aria-label', ariaLabel);
dest.appendChild(row);
}
}
private static _renderLine(model: ITextModel, options: IComputedEditorOptions, tabSize: number, lineNumber: number, languageIdCodec: ILanguageIdCodec): string {
const lineContent = model.getLineContent(lineNumber);
const fontInfo = options.get(EditorOption.fontInfo);
const lineTokens = LineTokens.createEmpty(lineContent, languageIdCodec);
const isBasicASCII = ViewLineRenderingData.isBasicASCII(lineContent, model.mightContainNonBasicASCII());
const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, model.mightContainRTL());
const r = renderViewLine(new RenderLineInput(
(fontInfo.isMonospace && !options.get(EditorOption.disableMonospaceOptimizations)),
fontInfo.canUseHalfwidthRightwardsArrow,
lineContent,
false,
isBasicASCII,
containsRTL,
0,
lineTokens,
[],
tabSize,
0,
fontInfo.spaceWidth,
fontInfo.middotWidth,
fontInfo.wsmiddotWidth,
options.get(EditorOption.stopRenderingLineAfter),
options.get(EditorOption.renderWhitespace),
options.get(EditorOption.renderControlCharacters),
options.get(EditorOption.fontLigatures) !== EditorFontLigatures.OFF,
null
));
return r.html;
}
}
// theming

View file

@ -7,21 +7,18 @@ import * as objects from 'vs/base/common/objects';
import { ICodeEditor, IDiffEditorConstructionOptions } from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget';
import { DiffEditorWidget, IDiffCodeEditorWidgetOptions } from 'vs/editor/browser/widget/diffEditorWidget';
import { DiffEditorWidget2, IDiffCodeEditorWidgetOptions } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';
import { ConfigurationChangedEvent, IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';
import { IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
export class EmbeddedCodeEditorWidget extends CodeEditorWidget {
@ -69,54 +66,6 @@ export class EmbeddedCodeEditorWidget extends CodeEditorWidget {
}
}
/**
* @deprecated Use EmbeddedDiffEditorWidget2 instead.
*/
export class EmbeddedDiffEditorWidget extends DiffEditorWidget {
private readonly _parentEditor: ICodeEditor;
private readonly _overwriteOptions: IDiffEditorOptions;
constructor(
domElement: HTMLElement,
options: Readonly<IDiffEditorConstructionOptions>,
codeEditorWidgetOptions: IDiffCodeEditorWidgetOptions,
parentEditor: ICodeEditor,
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService,
@ICodeEditorService codeEditorService: ICodeEditorService,
@IThemeService themeService: IThemeService,
@INotificationService notificationService: INotificationService,
@IContextMenuService contextMenuService: IContextMenuService,
@IClipboardService clipboardService: IClipboardService,
@IEditorProgressService editorProgressService: IEditorProgressService,
) {
super(domElement, parentEditor.getRawOptions(), codeEditorWidgetOptions, clipboardService, contextKeyService, instantiationService, codeEditorService, themeService, notificationService, contextMenuService, editorProgressService);
this._parentEditor = parentEditor;
this._overwriteOptions = options;
// Overwrite parent's options
super.updateOptions(this._overwriteOptions);
this._register(parentEditor.onDidChangeConfiguration(e => this._onParentConfigurationChanged(e)));
}
getParentEditor(): ICodeEditor {
return this._parentEditor;
}
private _onParentConfigurationChanged(e: ConfigurationChangedEvent): void {
super.updateOptions(this._parentEditor.getRawOptions());
super.updateOptions(this._overwriteOptions);
}
override updateOptions(newOptions: IEditorOptions): void {
objects.mixin(this._overwriteOptions, newOptions, true);
super.updateOptions(this._overwriteOptions);
}
}
/**
* TODO: Rename to EmbeddedDiffEditorWidget once EmbeddedDiffEditorWidget is removed.
*/

View file

@ -217,36 +217,30 @@ const editorConfiguration: IConfigurationNode = {
'diffEditor.hideUnchangedRegions.enabled': {
type: 'boolean',
default: diffEditorDefaultOptions.hideUnchangedRegions.enabled,
markdownDescription: nls.localize('hideUnchangedRegions.enabled', "Controls whether the diff editor shows unchanged regions. Only works when {0} is set.", '`#diffEditor.experimental.useVersion2#`'),
markdownDescription: nls.localize('hideUnchangedRegions.enabled', "Controls whether the diff editor shows unchanged regions."),
},
'diffEditor.hideUnchangedRegions.revealLineCount': {
type: 'integer',
default: diffEditorDefaultOptions.hideUnchangedRegions.revealLineCount,
markdownDescription: nls.localize('hideUnchangedRegions.revealLineCount', "Controls how many lines are used for unchanged regions. Only works when {0} is set.", '`#diffEditor.experimental.useVersion2#`'),
markdownDescription: nls.localize('hideUnchangedRegions.revealLineCount', "Controls how many lines are used for unchanged regions."),
minimum: 1,
},
'diffEditor.hideUnchangedRegions.minimumLineCount': {
type: 'integer',
default: diffEditorDefaultOptions.hideUnchangedRegions.minimumLineCount,
markdownDescription: nls.localize('hideUnchangedRegions.minimumLineCount', "Controls how many lines are used as a minimum for unchanged regions. Only works when {0} is set.", '`#diffEditor.experimental.useVersion2#`'),
markdownDescription: nls.localize('hideUnchangedRegions.minimumLineCount', "Controls how many lines are used as a minimum for unchanged regions."),
minimum: 1,
},
'diffEditor.hideUnchangedRegions.contextLineCount': {
type: 'integer',
default: diffEditorDefaultOptions.hideUnchangedRegions.contextLineCount,
markdownDescription: nls.localize('hideUnchangedRegions.contextLineCount', "Controls how many lines are used as context when comparing unchanged regions. Only works when {0} is set.", '`#diffEditor.experimental.useVersion2#`'),
markdownDescription: nls.localize('hideUnchangedRegions.contextLineCount', "Controls how many lines are used as context when comparing unchanged regions."),
minimum: 1,
},
'diffEditor.experimental.showMoves': {
type: 'boolean',
default: diffEditorDefaultOptions.experimental.showMoves,
markdownDescription: nls.localize('showMoves', "Controls whether the diff editor should show detected code moves. Only works when {0} is set.", '`#diffEditor.experimental.useVersion2#`')
},
'diffEditor.experimental.useVersion2': {
type: 'boolean',
default: true,
description: nls.localize('useVersion2', "Controls whether the diff editor uses the new or the old implementation."),
tags: ['experimental'],
markdownDescription: nls.localize('showMoves', "Controls whether the diff editor should show detected code moves.")
},
'diffEditor.experimental.showEmptyDecorations': {
type: 'boolean',

View file

@ -13,7 +13,6 @@ import { Constants } from 'vs/base/common/uint';
import { FontInfo } from 'vs/editor/common/config/fontInfo';
import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/core/textModelDefaults';
import { USUAL_WORD_SEPARATORS } from 'vs/editor/common/core/wordHelper';
import { IDocumentDiffProvider } from 'vs/editor/common/diff/documentDiffProvider';
import * as nls from 'vs/nls';
import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
import { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';
@ -817,7 +816,7 @@ export interface IDiffEditorBaseOptions {
/**
* Diff Algorithm
*/
diffAlgorithm?: 'legacy' | 'advanced' | IDocumentDiffProvider;
diffAlgorithm?: 'legacy' | 'advanced';
/**
* Whether the diff editor aria label should be verbose.

View file

@ -3,7 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { compareBy, findLastMaxBy, findMinBy } from 'vs/base/common/arrays';
import { compareBy } from 'vs/base/common/arrays';
import { findLastMaxBy, findFirstMinBy } from 'vs/base/common/arraysFind';
import { CursorState, PartialCursorState } from 'vs/editor/common/cursorCommon';
import { CursorContext } from 'vs/editor/common/cursor/cursorContext';
import { Cursor } from 'vs/editor/common/cursor/oneCursor';
@ -72,7 +73,7 @@ export class CursorCollection {
}
public getTopMostViewPosition(): Position {
return findMinBy(
return findFirstMinBy(
this.cursors,
compareBy(c => c.viewState.position, Position.compare)
)!.viewState.position;

View file

@ -11,6 +11,7 @@ import { ITextModel } from 'vs/editor/common/model';
/**
* A document diff provider computes the diff between two text models.
* @internal
*/
export interface IDocumentDiffProvider {
/**
@ -27,6 +28,7 @@ export interface IDocumentDiffProvider {
/**
* Options for the diff computation.
* @internal
*/
export interface IDocumentDiffProviderOptions {
/**
@ -47,6 +49,7 @@ export interface IDocumentDiffProviderOptions {
/**
* Represents a diff between two text models.
* @internal
*/
export interface IDocumentDiff {
/**

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { findLast } from 'vs/base/common/arrays';
import { findLast } from 'vs/base/common/arraysFind';
import * as strings from 'vs/base/common/strings';
import { CursorColumns } from 'vs/editor/common/core/cursorColumns';
import { IPosition, Position } from 'vs/editor/common/core/position';

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { findFirstInSorted } from 'vs/base/common/arrays';
import { findFirstIdxMonotonousOrArrLen } from 'vs/base/common/arraysFind';
import { RunOnceScheduler, TimeoutTimer } from 'vs/base/common/async';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { DisposableStore, dispose } from 'vs/base/common/lifecycle';
@ -211,7 +211,7 @@ export class FindModelBoundToEditorModel {
if (currentMatchesPosition === 0 && findMatches.length > 0) {
// current selection is not on top of a match
// try to find its nearest result from the top of the document
const matchAfterSelection = findFirstInSorted(findMatches.map(match => match.range), range => Range.compareRangesUsingStarts(range, editorSelection) >= 0);
const matchAfterSelection = findFirstIdxMonotonousOrArrLen(findMatches.map(match => match.range), range => Range.compareRangesUsingStarts(range, editorSelection) >= 0);
currentMatchesPosition = matchAfterSelection > 0 ? matchAfterSelection - 1 + 1 /** match position is one based */ : currentMatchesPosition;
}

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { findFirstInSorted } from 'vs/base/common/arrays';
import { findFirstIdxMonotonousOrArrLen } from 'vs/base/common/arraysFind';
import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
@ -141,7 +141,7 @@ function isInside(line: number, range: IRange) {
return line >= range.startLineNumber && line <= range.endLineNumber;
}
function findRange(ranges: IRange[], line: number): IRange | null {
const i = findFirstInSorted(ranges, r => line < r.startLineNumber) - 1;
const i = findFirstIdxMonotonousOrArrLen(ranges, r => line < r.startLineNumber) - 1;
if (i >= 0 && ranges[i].endLineNumber >= line) {
return ranges[i];
}

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { mapFind } from 'vs/base/common/arrays';
import { mapFindFirst } from 'vs/base/common/arraysFind';
import { BugIndicatingError, onUnexpectedExternalError } from 'vs/base/common/errors';
import { Disposable } from 'vs/base/common/lifecycle';
import { IObservable, IReader, ITransaction, autorun, derived, derivedHandleChanges, derivedOpts, recomputeInitiallyAndOnChange, observableSignal, observableValue, subtransaction, transaction } from 'vs/base/common/observable';
@ -244,7 +244,7 @@ export class InlineCompletionsModel extends Disposable {
? suggestWidgetInlineCompletions.inlineCompletions
: [this.selectedInlineCompletion.read(reader)].filter(isDefined);
const augmentedCompletion = mapFind(candidateInlineCompletions, completion => {
const augmentedCompletion = mapFindFirst(candidateInlineCompletions, completion => {
let r = completion.toSingleTextEdit(reader);
r = r.removeCommonPrefix(model, Range.fromPositions(r.range.getStartPosition(), suggestCompletion.range.getEndPosition()));
return r.augments(suggestCompletion) ? { edit: r, completion } : undefined;

View file

@ -16,7 +16,8 @@ import { SuggestController } from 'vs/editor/contrib/suggest/browser/suggestCont
import { IObservable, ITransaction, observableValue, transaction } from 'vs/base/common/observable';
import { SingleTextEdit } from 'vs/editor/contrib/inlineCompletions/browser/singleTextEdit';
import { ITextModel } from 'vs/editor/common/model';
import { compareBy, findMaxBy, numberComparator } from 'vs/base/common/arrays';
import { compareBy, numberComparator } from 'vs/base/common/arrays';
import { findFirstMaxBy } from 'vs/base/common/arraysFind';
export class SuggestWidgetAdaptor extends Disposable {
private isSuggestWidgetVisible: boolean = false;
@ -80,7 +81,7 @@ export class SuggestWidgetAdaptor extends Disposable {
})
.filter(item => item && item.valid && item.prefixLength > 0);
const result = findMaxBy(
const result = findFirstMaxBy(
candidates,
compareBy(s => s!.prefixLength, numberComparator)
);

View file

@ -21,7 +21,7 @@ import { localize } from 'vs/nls';
import { IQuickInputButton, IQuickPick, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { Position } from 'vs/editor/common/core/position';
import { findLast } from 'vs/base/common/arrays';
import { findLast } from 'vs/base/common/arraysFind';
export interface IGotoSymbolQuickPickItem extends IQuickPickItem {
kind: SymbolKind;

View file

@ -5,8 +5,7 @@
import 'vs/editor/browser/coreCommands';
import 'vs/editor/browser/widget/codeEditorWidget';
import 'vs/editor/browser/widget/diffEditorWidget';
import 'vs/editor/browser/widget/diffNavigator';
import 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';
import 'vs/editor/contrib/anchorSelect/browser/anchorSelect';
import 'vs/editor/contrib/bracketMatching/browser/bracketMatching';
import 'vs/editor/contrib/caretOperations/browser/caretOperations';

View file

@ -8,7 +8,6 @@ import { Disposable, IDisposable, toDisposable, DisposableStore } from 'vs/base/
import { ICodeEditor, IDiffEditor, IDiffEditorConstructionOptions } from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { InternalEditorAction } from 'vs/editor/common/editorAction';
import { IModelChangedEvent } from 'vs/editor/common/editorCommon';
@ -481,82 +480,6 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
}
}
export class StandaloneDiffEditor extends DiffEditorWidget implements IStandaloneDiffEditor {
private readonly _configurationService: IConfigurationService;
private readonly _standaloneThemeService: IStandaloneThemeService;
constructor(
domElement: HTMLElement,
_options: Readonly<IStandaloneDiffEditorConstructionOptions> | undefined,
@IInstantiationService instantiationService: IInstantiationService,
@IContextKeyService contextKeyService: IContextKeyService,
@ICodeEditorService codeEditorService: ICodeEditorService,
@IStandaloneThemeService themeService: IStandaloneThemeService,
@INotificationService notificationService: INotificationService,
@IConfigurationService configurationService: IConfigurationService,
@IContextMenuService contextMenuService: IContextMenuService,
@IEditorProgressService editorProgressService: IEditorProgressService,
@IClipboardService clipboardService: IClipboardService
) {
const options = { ..._options };
updateConfigurationService(configurationService, options, true);
const themeDomRegistration = (<StandaloneThemeService>themeService).registerEditorContainer(domElement);
if (typeof options.theme === 'string') {
themeService.setTheme(options.theme);
}
if (typeof options.autoDetectHighContrast !== 'undefined') {
themeService.setAutoDetectHighContrast(Boolean(options.autoDetectHighContrast));
}
super(domElement, options, {}, clipboardService, contextKeyService, instantiationService, codeEditorService, themeService, notificationService, contextMenuService, editorProgressService);
this._configurationService = configurationService;
this._standaloneThemeService = themeService;
this._register(themeDomRegistration);
}
public override dispose(): void {
super.dispose();
}
public override updateOptions(newOptions: Readonly<IDiffEditorOptions & IGlobalEditorOptions>): void {
updateConfigurationService(this._configurationService, newOptions, true);
if (typeof newOptions.theme === 'string') {
this._standaloneThemeService.setTheme(newOptions.theme);
}
if (typeof newOptions.autoDetectHighContrast !== 'undefined') {
this._standaloneThemeService.setAutoDetectHighContrast(Boolean(newOptions.autoDetectHighContrast));
}
super.updateOptions(newOptions);
}
protected override _createInnerEditor(instantiationService: IInstantiationService, container: HTMLElement, options: Readonly<IEditorOptions>): CodeEditorWidget {
return instantiationService.createInstance(StandaloneCodeEditor, container, options);
}
public override getOriginalEditor(): IStandaloneCodeEditor {
return <StandaloneCodeEditor>super.getOriginalEditor();
}
public override getModifiedEditor(): IStandaloneCodeEditor {
return <StandaloneCodeEditor>super.getModifiedEditor();
}
public addCommand(keybinding: number, handler: ICommandHandler, context?: string): string | null {
return this.getModifiedEditor().addCommand(keybinding, handler, context);
}
public createContextKey<T extends ContextKeyValue = ContextKeyValue>(key: string, defaultValue: T): IContextKey<T> {
return this.getModifiedEditor().createContextKey(key, defaultValue);
}
public addAction(descriptor: IActionDescriptor): IDisposable {
return this.getModifiedEditor().addAction(descriptor);
}
}
export class StandaloneDiffEditor2 extends DiffEditorWidget2 implements IStandaloneDiffEditor {
private readonly _configurationService: IConfigurationService;

View file

@ -3,45 +3,41 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./standalone-tokens';
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { splitLines } from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
import 'vs/css!./standalone-tokens';
import { FontMeasurements } from 'vs/editor/browser/config/fontMeasurements';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorCommand, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { DiffNavigator, IDiffNavigator } from 'vs/editor/browser/widget/diffNavigator';
import { IWebWorkerOptions, MonacoWebWorker, createWebWorker as actualCreateWebWorker } from 'vs/editor/browser/services/webWorker';
import { ApplyUpdateResult, ConfigurationChangedEvent, EditorOptions } from 'vs/editor/common/config/editorOptions';
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import { EditorType, IDiffEditor } from 'vs/editor/common/editorCommon';
import { FindMatch, ITextModel, TextModelResolvedOptions } from 'vs/editor/common/model';
import * as languages from 'vs/editor/common/languages';
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
import { NullState, nullTokenize } from 'vs/editor/common/languages/nullTokenize';
import { ILanguageService } from 'vs/editor/common/languages/language';
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';
import { NullState, nullTokenize } from 'vs/editor/common/languages/nullTokenize';
import { FindMatch, ITextModel, TextModelResolvedOptions } from 'vs/editor/common/model';
import { IModelService } from 'vs/editor/common/services/model';
import { createWebWorker as actualCreateWebWorker, IWebWorkerOptions, MonacoWebWorker } from 'vs/editor/browser/services/webWorker';
import * as standaloneEnums from 'vs/editor/common/standalone/standaloneEnums';
import { Colorizer, IColorizerElementOptions, IColorizerOptions } from 'vs/editor/standalone/browser/colorizer';
import { createTextModel, IActionDescriptor, IStandaloneCodeEditor, IStandaloneDiffEditor, IStandaloneDiffEditorConstructionOptions, IStandaloneEditorConstructionOptions, StandaloneDiffEditor, StandaloneDiffEditor2, StandaloneEditor } from 'vs/editor/standalone/browser/standaloneCodeEditor';
import { IActionDescriptor, IStandaloneCodeEditor, IStandaloneDiffEditor, IStandaloneDiffEditorConstructionOptions, IStandaloneEditorConstructionOptions, StandaloneDiffEditor2, StandaloneEditor, createTextModel } from 'vs/editor/standalone/browser/standaloneCodeEditor';
import { IEditorOverrideServices, StandaloneKeybindingService, StandaloneServices } from 'vs/editor/standalone/browser/standaloneServices';
import { StandaloneThemeService } from 'vs/editor/standalone/browser/standaloneThemeService';
import { IStandaloneThemeData, IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneTheme';
import { IMenuItem, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands';
import { IMarker, IMarkerData, IMarkerService } from 'vs/platform/markers/common/markers';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { EditorCommand, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { IMenuItem, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';
import { MovedText } from 'vs/editor/common/diff/linesDiffComputer';
import { DetailedLineRangeMapping, RangeMapping, LineRangeMapping } from 'vs/editor/common/diff/rangeMapping';
import { LineRange } from 'vs/editor/common/core/lineRange';
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IRange } from 'vs/editor/common/core/range';
import { IPosition } from 'vs/editor/common/core/position';
import { ITextResourceEditorInput } from 'vs/platform/editor/common/editor';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IMarker, IMarkerData, IMarkerService } from 'vs/platform/markers/common/markers';
import { IOpenerService } from 'vs/platform/opener/common/opener';
/**
* Create a new editor under `domElement`.
@ -99,21 +95,7 @@ export function getDiffEditors(): readonly IDiffEditor[] {
*/
export function createDiffEditor(domElement: HTMLElement, options?: IStandaloneDiffEditorConstructionOptions, override?: IEditorOverrideServices): IStandaloneDiffEditor {
const instantiationService = StandaloneServices.initialize(override || {});
if ((options?.experimental as any)?.useVersion2) {
return instantiationService.createInstance(StandaloneDiffEditor2, domElement, options);
}
return instantiationService.createInstance(StandaloneDiffEditor, domElement, options);
}
export interface IDiffNavigatorOptions {
readonly followsCaret?: boolean;
readonly ignoreCharChanges?: boolean;
readonly alwaysRevealFirst?: boolean;
}
export function createDiffNavigator(diffEditor: IStandaloneDiffEditor, opts?: IDiffNavigatorOptions): IDiffNavigator {
const instantiationService = StandaloneServices.initialize({});
return instantiationService.createInstance(DiffNavigator, diffEditor, opts);
return instantiationService.createInstance(StandaloneDiffEditor2, domElement, options);
}
/**
@ -519,7 +501,6 @@ export function createMonacoEditorAPI(): typeof monaco.editor {
onDidCreateEditor: <any>onDidCreateEditor,
onDidCreateDiffEditor: <any>onDidCreateDiffEditor,
createDiffEditor: <any>createDiffEditor,
createDiffNavigator: <any>createDiffNavigator,
addCommand: <any>addCommand,
addEditorAction: <any>addEditorAction,
@ -584,12 +565,7 @@ export function createMonacoEditorAPI(): typeof monaco.editor {
TextModelResolvedOptions: <any>TextModelResolvedOptions,
FindMatch: <any>FindMatch,
ApplyUpdateResult: <any>ApplyUpdateResult,
LineRange: <any>LineRange,
DetailedLineRangeMapping: <any>DetailedLineRangeMapping,
RangeMapping: <any>RangeMapping,
EditorZoom: <any>EditorZoom,
MovedText: <any>MovedText,
LineRangeMapping: <any>LineRangeMapping,
// vars
EditorType: EditorType,

195
src/vs/monaco.d.ts vendored
View file

@ -937,13 +937,6 @@ declare namespace monaco {
declare namespace monaco.editor {
export interface IDiffNavigator {
canNavigate(): boolean;
next(): void;
previous(): void;
dispose(): void;
}
/**
* Create a new editor under `domElement`.
* `domElement` should be empty (not contain other dom nodes).
@ -981,14 +974,6 @@ declare namespace monaco.editor {
*/
export function createDiffEditor(domElement: HTMLElement, options?: IStandaloneDiffEditorConstructionOptions, override?: IEditorOverrideServices): IStandaloneDiffEditor;
export interface IDiffNavigatorOptions {
readonly followsCaret?: boolean;
readonly ignoreCharChanges?: boolean;
readonly alwaysRevealFirst?: boolean;
}
export function createDiffNavigator(diffEditor: IStandaloneDiffEditor, opts?: IDiffNavigatorOptions): IDiffNavigator;
/**
* Description of a command contribution
*/
@ -2366,184 +2351,6 @@ declare namespace monaco.editor {
export interface ILineChange extends IChange {
readonly charChanges: ICharChange[] | undefined;
}
/**
* A document diff provider computes the diff between two text models.
*/
export interface IDocumentDiffProvider {
/**
* Computes the diff between the text models `original` and `modified`.
*/
computeDiff(original: ITextModel, modified: ITextModel, options: IDocumentDiffProviderOptions, cancellationToken: CancellationToken): Promise<IDocumentDiff>;
/**
* Is fired when settings of the diff algorithm change that could alter the result of the diffing computation.
* Any user of this provider should recompute the diff when this event is fired.
*/
onDidChange: IEvent<void>;
}
/**
* Options for the diff computation.
*/
export interface IDocumentDiffProviderOptions {
/**
* When set to true, the diff should ignore whitespace changes.
*/
ignoreTrimWhitespace: boolean;
/**
* A diff computation should throw if it takes longer than this value.
*/
maxComputationTimeMs: number;
/**
* If set, the diff computation should compute moves in addition to insertions and deletions.
*/
computeMoves: boolean;
}
/**
* Represents a diff between two text models.
*/
export interface IDocumentDiff {
/**
* If true, both text models are identical (byte-wise).
*/
readonly identical: boolean;
/**
* If true, the diff computation timed out and the diff might not be accurate.
*/
readonly quitEarly: boolean;
/**
* Maps all modified line ranges in the original to the corresponding line ranges in the modified text model.
*/
readonly changes: readonly DetailedLineRangeMapping[];
/**
* Sorted by original line ranges.
* The original line ranges and the modified line ranges must be disjoint (but can be touching).
*/
readonly moves: readonly MovedText[];
}
/**
* A range of lines (1-based).
*/
export class LineRange {
static fromRange(range: Range): LineRange;
static subtract(a: LineRange, b: LineRange | undefined): LineRange[];
/**
* @param lineRanges An array of sorted line ranges.
*/
static joinMany(lineRanges: readonly (readonly LineRange[])[]): readonly LineRange[];
static ofLength(startLineNumber: number, length: number): LineRange;
/**
* The start line number.
*/
readonly startLineNumber: number;
/**
* The end line number (exclusive).
*/
readonly endLineNumberExclusive: number;
constructor(startLineNumber: number, endLineNumberExclusive: number);
/**
* Indicates if this line range contains the given line number.
*/
contains(lineNumber: number): boolean;
/**
* Indicates if this line range is empty.
*/
get isEmpty(): boolean;
/**
* Moves this line range by the given offset of line numbers.
*/
delta(offset: number): LineRange;
deltaLength(offset: number): LineRange;
/**
* The number of lines this line range spans.
*/
get length(): number;
/**
* Creates a line range that combines this and the given line range.
*/
join(other: LineRange): LineRange;
toString(): string;
/**
* The resulting range is empty if the ranges do not intersect, but touch.
* If the ranges don't even touch, the result is undefined.
*/
intersect(other: LineRange): LineRange | undefined;
intersectsStrict(other: LineRange): boolean;
overlapOrTouch(other: LineRange): boolean;
equals(b: LineRange): boolean;
toInclusiveRange(): Range | null;
toExclusiveRange(): Range;
mapToLineArray<T>(f: (lineNumber: number) => T): T[];
forEach(f: (lineNumber: number) => void): void;
includes(lineNumber: number): boolean;
}
export class MovedText {
readonly lineRangeMapping: LineRangeMapping;
/**
* The diff from the original text to the moved text.
* Must be contained in the original/modified line range.
* Can be empty if the text didn't change (only moved).
*/
readonly changes: readonly DetailedLineRangeMapping[];
constructor(lineRangeMapping: LineRangeMapping, changes: readonly DetailedLineRangeMapping[]);
flip(): MovedText;
}
/**
* Maps a line range in the original text model to a line range in the modified text model.
* Also contains inner range mappings.
*/
export class DetailedLineRangeMapping extends LineRangeMapping {
/**
* If inner changes have not been computed, this is set to undefined.
* Otherwise, it represents the character-level diff in this line range.
* The original range of each range mapping should be contained in the original line range (same for modified), exceptions are new-lines.
* Must not be an empty array.
*/
readonly innerChanges: RangeMapping[] | undefined;
constructor(originalRange: LineRange, modifiedRange: LineRange, innerChanges: RangeMapping[] | undefined);
flip(): DetailedLineRangeMapping;
}
/**
* Maps a range in the original text model to a range in the modified text model.
*/
export class RangeMapping {
/**
* The original range.
*/
readonly originalRange: Range;
/**
* The modified range.
*/
readonly modifiedRange: Range;
constructor(originalRange: Range, modifiedRange: Range);
toString(): string;
flip(): RangeMapping;
}
/**
* Maps a line range in the original text model to a line range in the modified text model.
*/
export class LineRangeMapping {
static inverse(mapping: readonly DetailedLineRangeMapping[], originalLineCount: number, modifiedLineCount: number): DetailedLineRangeMapping[];
/**
* The line range in the original text model.
*/
readonly original: LineRange;
/**
* The line range in the modified text model.
*/
readonly modified: LineRange;
constructor(originalRange: LineRange, modifiedRange: LineRange);
toString(): string;
flip(): LineRangeMapping;
join(other: LineRangeMapping): LineRangeMapping;
get changedLineCount(): any;
}
export interface IDimension {
width: number;
height: number;
@ -3966,7 +3773,7 @@ declare namespace monaco.editor {
/**
* Diff Algorithm
*/
diffAlgorithm?: 'legacy' | 'advanced' | IDocumentDiffProvider;
diffAlgorithm?: 'legacy' | 'advanced';
/**
* Whether the diff editor aria label should be verbose.
*/

View file

@ -6,7 +6,6 @@
import { memoize } from 'vs/base/common/decorators';
import { join } from 'vs/base/common/path';
import { isLinux } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { createStaticIPCHandle } from 'vs/base/parts/ipc/node/ipc.net';
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
@ -69,9 +68,6 @@ export class EnvironmentMainService extends NativeEnvironmentService implements
@memoize
get useCodeCache(): boolean { return !!this.codeCachePath; }
@memoize
override get userRoamingDataHome(): URI { return this.appSettingsHome; }
unsetSnapExportedVariables() {
if (!isLinux) {
return;

View file

@ -4,13 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import { Event, Emitter } from 'vs/base/common/event';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { IFileSystemProviderWithFileReadWriteCapability, IFileChange, IWatchOptions, IStat, IFileOverwriteOptions, FileType, IFileWriteOptions, IFileDeleteOptions, FileSystemProviderCapabilities, IFileSystemProviderWithFileReadStreamCapability, IFileReadStreamOptions, IFileSystemProviderWithFileAtomicReadCapability, IFileSystemProviderWithFileFolderCopyCapability, hasFileFolderCopyCapability } from 'vs/platform/files/common/files';
import { IFileSystemProviderWithFileReadWriteCapability, IFileChange, IWatchOptions, IStat, IFileOverwriteOptions, FileType, IFileWriteOptions, IFileDeleteOptions, FileSystemProviderCapabilities, IFileSystemProviderWithFileReadStreamCapability, IFileReadStreamOptions, IFileSystemProviderWithFileAtomicReadCapability, IFileSystemProviderWithFileFolderCopyCapability, hasFileFolderCopyCapability, hasFileAtomicWriteCapability } from 'vs/platform/files/common/files';
import { URI } from 'vs/base/common/uri';
import { CancellationToken } from 'vs/base/common/cancellation';
import { newWriteableStream, ReadableStreamEvents } from 'vs/base/common/stream';
import { ILogService } from 'vs/platform/log/common/log';
import { TernarySearchTree } from 'vs/base/common/ternarySearchTree';
import { VSBuffer } from 'vs/base/common/buffer';
import { isObject } from 'vs/base/common/types';
/**
* This is a wrapper on top of the local filesystem provider which will
@ -85,6 +86,9 @@ export class FileUserDataProvider extends Disposable implements
}
writeFile(resource: URI, content: Uint8Array, opts: IFileWriteOptions): Promise<void> {
if (!isObject(opts.atomic) && hasFileAtomicWriteCapability(this.fileSystemProvider)) {
opts = { ...opts, atomic: { postfix: '.vsctmp' } };
}
return this.fileSystemProvider.writeFile(this.toFileSystemResource(resource), content, opts);
}

View file

@ -181,7 +181,7 @@ export async function main(desc: ProductDescription, args: string[]): Promise<vo
parsedArgs['_'] = [];
if (hasReadStdinArg && fileURIs.length === 0 && folderURIs.length === 0 && hasStdinWithoutTty()) {
if (hasReadStdinArg && hasStdinWithoutTty()) {
try {
let stdinFilePath = cliStdInFilePath;
if (!stdinFilePath) {

View file

@ -5,7 +5,7 @@
/* eslint-disable local/code-no-native-private */
import { mapFind } from 'vs/base/common/arrays';
import { mapFindFirst } from 'vs/base/common/arraysFind';
import { RunOnceScheduler } from 'vs/base/common/async';
import { VSBuffer } from 'vs/base/common/buffer';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
@ -229,7 +229,7 @@ export class ExtHostTesting implements ExtHostTestingShape {
* @inheritdoc
*/
$provideFileCoverage(runId: string, taskId: string, token: CancellationToken): Promise<IFileCoverage[]> {
const coverage = mapFind(this.runTracker.trackers, t => t.id === runId ? t.getCoverage(taskId) : undefined);
const coverage = mapFindFirst(this.runTracker.trackers, t => t.id === runId ? t.getCoverage(taskId) : undefined);
return coverage?.provideFileCoverage(token) ?? Promise.resolve([]);
}
@ -237,7 +237,7 @@ export class ExtHostTesting implements ExtHostTestingShape {
* @inheritdoc
*/
$resolveFileCoverage(runId: string, taskId: string, fileIndex: number, token: CancellationToken): Promise<CoverageDetails[]> {
const coverage = mapFind(this.runTracker.trackers, t => t.id === runId ? t.getCoverage(taskId) : undefined);
const coverage = mapFindFirst(this.runTracker.trackers, t => t.id === runId ? t.getCoverage(taskId) : undefined);
return coverage?.resolveFileCoverage(fileIndex, token) ?? Promise.resolve([]);
}

View file

@ -30,15 +30,19 @@ import type * as vscode from 'vscode';
* */
function es5ClassCompat(target: Function): any {
const interceptFunctions = {
apply: function () {
const args = arguments.length === 1 ? [] : arguments[1];
return Reflect.construct(target, args, arguments[0].constructor);
},
call: function () {
if (arguments.length === 0) {
apply: function (...args: any[]): any {
if (args.length === 0) {
return Reflect.construct(target, []);
} else {
const [thisArg, ...restArgs] = arguments;
const argsList = args.length === 1 ? [] : args[1];
return Reflect.construct(target, argsList, args[0].constructor);
}
},
call: function (...args: any[]): any {
if (args.length === 0) {
return Reflect.construct(target, []);
} else {
const [thisArg, ...restArgs] = args;
return Reflect.construct(target, restArgs, thisArg.constructor);
}
}

View file

@ -13,7 +13,6 @@ import { TEXT_DIFF_EDITOR_ID, IEditorFactoryRegistry, EditorExtensions, ITextDif
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { TextDiffEditorModel } from 'vs/workbench/common/editor/textDiffEditorModel';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService } from 'vs/platform/storage/common/storage';
@ -22,7 +21,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { TextFileOperationError, TextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles';
import { ScrollType, IDiffEditorViewState, IDiffEditorModel } from 'vs/editor/common/editorCommon';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { URI } from 'vs/base/common/uri';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@ -43,12 +41,9 @@ import { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/di
*/
export class TextDiffEditor extends AbstractTextEditor<IDiffEditorViewState> implements ITextDiffEditorPane {
static readonly ID = TEXT_DIFF_EDITOR_ID;
private static widgetCounter = 0; // Just for debugging
private diffEditorControl: IDiffEditor | undefined = undefined;
private readonly diffNavigatorDisposables = this._register(new DisposableStore());
private inputLifecycleStopWatch: StopWatch | undefined = undefined;
override get scopedContextKeyService(): IContextKeyService | undefined {
@ -85,18 +80,7 @@ export class TextDiffEditor extends AbstractTextEditor<IDiffEditorViewState> imp
}
protected override createEditorControl(parent: HTMLElement, configuration: ICodeEditorOptions): void {
TextDiffEditor.widgetCounter++;
let useVersion2 = this.textResourceConfigurationService.getValue(undefined, 'diffEditor.experimental.useVersion2');
if (useVersion2 === 'first') {
// This allows to have both the old and new diff editor next to each other - just for debugging
useVersion2 = TextDiffEditor.widgetCounter === 1;
}
if (useVersion2) {
this.diffEditorControl = this._register(this.instantiationService.createInstance(DiffEditorWidget2, parent, configuration, {}));
} else {
this.diffEditorControl = this._register(this.instantiationService.createInstance(DiffEditorWidget, parent, configuration, {}));
}
this.diffEditorControl = this._register(this.instantiationService.createInstance(DiffEditorWidget2, parent, configuration, {}));
}
protected updateEditorControlOptions(options: ICodeEditorOptions): void {
@ -111,7 +95,6 @@ export class TextDiffEditor extends AbstractTextEditor<IDiffEditorViewState> imp
// Cleanup previous things associated with the input
this.inputLifecycleStopWatch = undefined;
this.diffNavigatorDisposables.clear();
// Set input and resolve
await super.setInput(input, options, context, token);
@ -324,9 +307,6 @@ export class TextDiffEditor extends AbstractTextEditor<IDiffEditorViewState> imp
this.logInputLifecycleTelemetry(inputLifecycleElapsed, this.getControl()?.getModel()?.modified?.getLanguageId());
}
// Dispose previous diff navigator
this.diffNavigatorDisposables.clear();
// Clear Model
this.diffEditorControl?.setModel(null);
}

View file

@ -10,7 +10,7 @@ import { registerDiffEditorContribution } from 'vs/editor/browser/editorExtensio
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { AccessibleDiffViewerNext, AccessibleDiffViewerPrev } from 'vs/editor/browser/widget/diffEditor.contribution';
import { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';
import { EmbeddedDiffEditorWidget, EmbeddedDiffEditorWidget2 } from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
import { EmbeddedDiffEditorWidget2 } from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
import { IDiffEditorContribution } from 'vs/editor/common/editorCommon';
import { localize } from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@ -39,7 +39,7 @@ class DiffEditorHelperContribution extends Disposable implements IDiffEditorCont
this._register(createScreenReaderHelp());
const isEmbeddedDiffEditor = (this._diffEditor instanceof EmbeddedDiffEditorWidget) || (this._diffEditor instanceof EmbeddedDiffEditorWidget2);
const isEmbeddedDiffEditor = this._diffEditor instanceof EmbeddedDiffEditorWidget2;
if (!isEmbeddedDiffEditor) {
const computationResult = observableFromEvent(e => this._diffEditor.onDidUpdateDiff(e), () => this._diffEditor.getDiffComputationResult());

View file

@ -4,7 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import { Action, IAction } from 'vs/base/common/actions';
import { coalesce, findFirstInSorted } from 'vs/base/common/arrays';
import { coalesce } from 'vs/base/common/arrays';
import { findFirstIdxMonotonousOrArrLen } from 'vs/base/common/arraysFind';
import { CancelablePromise, createCancelablePromise, Delayer } from 'vs/base/common/async';
import { onUnexpectedError } from 'vs/base/common/errors';
import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
@ -588,7 +589,7 @@ export class CommentController implements IEditorContribution {
return 0;
});
const idx = findFirstInSorted(sortedWidgets, widget => {
const idx = findFirstIdxMonotonousOrArrLen(sortedWidgets, widget => {
const lineValueOne = reverse ? after.lineNumber : (widget.commentThread.range?.startLineNumber ?? 0);
const lineValueTwo = reverse ? (widget.commentThread.range?.startLineNumber ?? 0) : after.lineNumber;
const columnValueOne = reverse ? after.column : (widget.commentThread.range?.startColumn ?? 0);

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { distinct, findLastIndex } from 'vs/base/common/arrays';
import { distinct } from 'vs/base/common/arrays';
import { DeferredPromise, RunOnceScheduler } from 'vs/base/common/async';
import { decodeBase64, encodeBase64, VSBuffer } from 'vs/base/common/buffer';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
@ -27,6 +27,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ILogService } from 'vs/platform/log/common/log';
import { autorun } from 'vs/base/common/observable';
import { findLastIdx } from 'vs/base/common/arraysFind';
interface IDebugProtocolVariableWithContext extends DebugProtocol.Variable {
__vscodeVariableMenuContext?: string;
@ -1253,7 +1254,7 @@ export class DebugModel extends Disposable implements IDebugModel {
let index = -1;
if (session.parentSession) {
// Make sure that child sessions are placed after the parent session
index = findLastIndex(this.sessions, s => s.parentSession === session.parentSession || s === session.parentSession);
index = findLastIdx(this.sessions, s => s.parentSession === session.parentSession || s === session.parentSession);
}
if (index >= 0) {
this.sessions.splice(index + 1, 0, session);

View file

@ -3,7 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { compareBy, findLast, lastOrDefault, numberComparator } from 'vs/base/common/arrays';
import { compareBy, lastOrDefault, numberComparator } from 'vs/base/common/arrays';
import { findLast } from 'vs/base/common/arraysFind';
import { assertFn, checkAdjacentItems } from 'vs/base/common/assert';
import { BugIndicatingError } from 'vs/base/common/errors';
import { Position } from 'vs/editor/common/core/position';

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { findLast } from 'vs/base/common/arrays';
import { findLast } from 'vs/base/common/arraysFind';
import { Disposable } from 'vs/base/common/lifecycle';
import { derived, derivedObservableWithWritableCache, IObservable, IReader, ITransaction, observableValue, transaction } from 'vs/base/common/observable';
import { Range } from 'vs/editor/common/core/range';

View file

@ -12,7 +12,7 @@ import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contri
import { CellKind, INotebookSearchOptions, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { findFirstInSorted } from 'vs/base/common/arrays';
import { findFirstIdxMonotonousOrArrLen } from 'vs/base/common/arraysFind';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CancellationToken } from 'vs/base/common/cancellation';
import { NotebookFindFilters } from 'vs/workbench/contrib/notebook/browser/contrib/find/findFilters';
@ -341,7 +341,7 @@ export class FindModel extends Disposable {
}
const findFirstMatchAfterCellIndex = (cellIndex: number) => {
const matchAfterSelection = findFirstInSorted(findMatches.map(match => match.index), index => index >= cellIndex);
const matchAfterSelection = findFirstIdxMonotonousOrArrLen(findMatches.map(match => match.index), index => index >= cellIndex);
this._updateCurrentMatch(findMatches, this._matchesCountBeforeIndex(findMatches, matchAfterSelection));
};
@ -403,7 +403,7 @@ export class FindModel extends Disposable {
return;
}
const matchAfterSelection = findFirstInSorted(findMatches, match => match.index >= oldCurrMatchCellIndex) % findMatches.length;
const matchAfterSelection = findFirstIdxMonotonousOrArrLen(findMatches, match => match.index >= oldCurrMatchCellIndex) % findMatches.length;
if (findMatches[matchAfterSelection].index > oldCurrMatchCellIndex) {
// there is no search result in curr cell anymore, find the nearest one (from top to bottom)
this._updateCurrentMatch(findMatches, this._matchesCountBeforeIndex(findMatches, matchAfterSelection));
@ -419,7 +419,7 @@ export class FindModel extends Disposable {
if (currMatchRangeInEditor !== null) {
// we find a range for the previous current match, let's find the nearest one after it (can overlap)
const cellMatch = findMatches[matchAfterSelection];
const matchAfterOldSelection = findFirstInSorted(cellMatch.contentMatches, match => Range.compareRangesUsingStarts((match as FindMatch).range, currMatchRangeInEditor) >= 0);
const matchAfterOldSelection = findFirstIdxMonotonousOrArrLen(cellMatch.contentMatches, match => Range.compareRangesUsingStarts((match as FindMatch).range, currMatchRangeInEditor) >= 0);
this._updateCurrentMatch(findMatches, this._matchesCountBeforeIndex(findMatches, matchAfterSelection) + matchAfterOldSelection);
} else {
// no range found, let's fall back to finding the nearest match
@ -429,7 +429,7 @@ export class FindModel extends Disposable {
}
} else {
// output now has the highlight
const matchAfterSelection = findFirstInSorted(findMatches.map(match => match.index), index => index >= oldCurrMatchCellIndex) % findMatches.length;
const matchAfterSelection = findFirstIdxMonotonousOrArrLen(findMatches.map(match => match.index), index => index >= oldCurrMatchCellIndex) % findMatches.length;
this._updateCurrentMatch(findMatches, this._matchesCountBeforeIndex(findMatches, matchAfterSelection));
}
}

View file

@ -10,7 +10,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { DiffElementViewModelBase, getFormattedMetadataJSON, getFormattedOutputJSON, OutputComparison, outputEqual, OUTPUT_EDITOR_HEIGHT_MAGIC, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DiffSide, DIFF_CELL_MARGIN, INotebookTextDiffEditor, NOTEBOOK_DIFF_CELL_INPUT, NOTEBOOK_DIFF_CELL_PROPERTY, NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser';
import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { IModelService } from 'vs/editor/common/services/model';
import { ILanguageService } from 'vs/editor/common/languages/language';
import { CellEditType, CellUri, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
@ -42,6 +41,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { fixedDiffEditorOptions, fixedEditorOptions, fixedEditorPadding } from 'vs/workbench/contrib/notebook/browser/diff/diffCellEditorOptions';
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';
export function getOptimizedNestedCodeEditorWidgetOptions(): ICodeEditorWidgetOptions {
return {
@ -242,7 +242,7 @@ abstract class AbstractElementRenderer extends Disposable {
protected _metadataInfoContainer!: HTMLElement;
protected _metadataEditorContainer?: HTMLElement;
protected _metadataEditorDisposeStore!: DisposableStore;
protected _metadataEditor?: CodeEditorWidget | DiffEditorWidget;
protected _metadataEditor?: CodeEditorWidget | DiffEditorWidget2;
protected _outputHeaderContainer!: HTMLElement;
protected _outputHeader!: PropertyHeader;
@ -256,8 +256,8 @@ abstract class AbstractElementRenderer extends Disposable {
protected _outputLeftView?: OutputContainer;
protected _outputRightView?: OutputContainer;
protected _outputEditorDisposeStore!: DisposableStore;
protected _outputEditor?: CodeEditorWidget | DiffEditorWidget;
protected _outputMetadataEditor?: DiffEditorWidget;
protected _outputEditor?: CodeEditorWidget | DiffEditorWidget2;
protected _outputMetadataEditor?: DiffEditorWidget2;
protected _diffEditorContainer!: HTMLElement;
protected _diagonalFill?: HTMLElement;
@ -493,7 +493,7 @@ abstract class AbstractElementRenderer extends Disposable {
this._metadataEditorDisposeStore.clear();
if (this.cell instanceof SideBySideDiffElementViewModel) {
this._metadataEditor = this.instantiationService.createInstance(DiffEditorWidget, this._metadataEditorContainer!, {
this._metadataEditor = this.instantiationService.createInstance(DiffEditorWidget2, this._metadataEditorContainer!, {
...fixedDiffEditorOptions,
overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(),
readOnly: false,
@ -606,7 +606,7 @@ abstract class AbstractElementRenderer extends Disposable {
const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17;
const lineCount = Math.max(originalModel.getLineCount(), modifiedModel.getLineCount());
this._outputEditor = this.instantiationService.createInstance(DiffEditorWidget, this._outputEditorContainer!, {
this._outputEditor = this.instantiationService.createInstance(DiffEditorWidget2, this._outputEditorContainer!, {
...fixedDiffEditorOptions,
overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(),
readOnly: true,
@ -1214,7 +1214,7 @@ export class InsertElement extends SingleSideDiffElement {
}
export class ModifiedElement extends AbstractElementRenderer {
private _editor?: DiffEditorWidget;
private _editor?: DiffEditorWidget2;
private _editorViewStateChanged: boolean;
private _editorContainer!: HTMLElement;
private _inputToolbarContainer!: HTMLElement;
@ -1416,7 +1416,7 @@ export class ModifiedElement extends AbstractElementRenderer {
this._outputMetadataContainer.style.top = `${this.cell.layoutInfo.rawOutputHeight}px`;
// single output, metadata change, let's render a diff editor for metadata
this._outputMetadataEditor = this.instantiationService.createInstance(DiffEditorWidget, this._outputMetadataContainer!, {
this._outputMetadataEditor = this.instantiationService.createInstance(DiffEditorWidget2, this._outputMetadataContainer!, {
...fixedDiffEditorOptions,
overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(),
readOnly: true,

View file

@ -8,7 +8,7 @@ import { hash } from 'vs/base/common/hash';
import { toFormattedString } from 'vs/base/common/jsonFormatter';
import { Disposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';
import { FontInfo } from 'vs/editor/common/config/fontInfo';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { fixedEditorPadding } from 'vs/workbench/contrib/notebook/browser/diff/diffCellEditorOptions';
@ -341,10 +341,10 @@ export abstract class DiffElementViewModelBase extends Disposable {
getComputedCellContainerWidth(layoutInfo: NotebookLayoutInfo, diffEditor: boolean, fullWidth: boolean) {
if (fullWidth) {
return layoutInfo.width - 2 * DIFF_CELL_MARGIN + (diffEditor ? DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH : 0) - 2;
return layoutInfo.width - 2 * DIFF_CELL_MARGIN + (diffEditor ? DiffEditorWidget2.ENTIRE_DIFF_OVERVIEW_WIDTH : 0) - 2;
}
return (layoutInfo.width - 2 * DIFF_CELL_MARGIN + (diffEditor ? DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH : 0)) / 2 - 18 - 2;
return (layoutInfo.width - 2 * DIFF_CELL_MARGIN + (diffEditor ? DiffEditorWidget2.ENTIRE_DIFF_OVERVIEW_WIDTH : 0)) / 2 - 18 - 2;
}
getOutputEditorViewState(): editorCommon.ICodeEditorViewState | editorCommon.IDiffEditorViewState | null {

View file

@ -5,7 +5,7 @@
import * as nls from 'vs/nls';
import * as DOM from 'vs/base/browser/dom';
import { findLastIndex } from 'vs/base/common/arrays';
import { findLastIdx } from 'vs/base/common/arraysFind';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
@ -825,7 +825,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
this._list.reveal(prevChangeIndex);
} else {
// go to the last one
const index = findLastIndex(this._diffElementViewModels, vm => vm.type !== 'unchanged');
const index = findLastIdx(this._diffElementViewModels, vm => vm.type !== 'unchanged');
if (index >= 0) {
this._list.setFocus([index]);
this._list.reveal(index);

View file

@ -10,12 +10,12 @@ import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { NotebookOptions } from 'vs/workbench/contrib/notebook/browser/notebookOptions';
import { NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents';
import { WorkbenchToolBar } from 'vs/platform/actions/browser/toolbar';
import { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';
export enum DiffSide {
Original = 0,
@ -85,7 +85,7 @@ export interface CellDiffSideBySideRenderTemplate extends CellDiffCommonRenderTe
readonly body: HTMLElement;
readonly diffEditorContainer: HTMLElement;
readonly elementDisposables: DisposableStore;
readonly sourceEditor: DiffEditorWidget;
readonly sourceEditor: DiffEditorWidget2;
readonly editorContainer: HTMLElement;
readonly inputToolbarContainer: HTMLElement;
readonly toolbar: WorkbenchToolBar;

View file

@ -18,7 +18,7 @@ import { DiffElementViewModelBase, SideBySideDiffElementViewModel, SingleSideDif
import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DIFF_CELL_MARGIN, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser';
import { DeletedElement, getOptimizedNestedCodeEditorWidgetOptions, InsertElement, ModifiedElement } from 'vs/workbench/contrib/notebook/browser/diff/diffComponents';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';
import { IMenuService, MenuItemAction } from 'vs/platform/actions/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { INotificationService } from 'vs/platform/notification/common/notification';
@ -234,7 +234,7 @@ export class CellDiffSideBySideRenderer implements IListRenderer<SideBySideDiffE
private _buildSourceEditor(sourceContainer: HTMLElement) {
const editorContainer = DOM.append(sourceContainer, DOM.$('.editor-container'));
const editor = this.instantiationService.createInstance(DiffEditorWidget, editorContainer, {
const editor = this.instantiationService.createInstance(DiffEditorWidget2, editorContainer, {
...fixedDiffEditorOptions,
padding: {
top: 24,

View file

@ -29,7 +29,7 @@ import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { rot } from 'vs/base/common/numbers';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { EmbeddedDiffEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
import { EmbeddedDiffEditorWidget2 } from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
import { IDiffEditorOptions, EditorOption } from 'vs/editor/common/config/editorOptions';
import { Action, IAction, ActionRunner } from 'vs/base/common/actions';
import { IActionBarOptions } from 'vs/base/browser/ui/actionbar/actionbar';
@ -168,7 +168,7 @@ function getOuterEditorFromDiffEditor(accessor: ServicesAccessor): ICodeEditor |
const diffEditors = accessor.get(ICodeEditorService).listDiffEditors();
for (const diffEditor of diffEditors) {
if (diffEditor.hasTextFocus() && diffEditor instanceof EmbeddedDiffEditorWidget) {
if (diffEditor.hasTextFocus() && diffEditor instanceof EmbeddedDiffEditorWidget2) {
return diffEditor.getParentEditor();
}
}
@ -178,7 +178,7 @@ function getOuterEditorFromDiffEditor(accessor: ServicesAccessor): ICodeEditor |
class DirtyDiffWidget extends PeekViewWidget {
private diffEditor!: EmbeddedDiffEditorWidget;
private diffEditor!: EmbeddedDiffEditorWidget2;
private title: string;
private menu: IMenu | undefined;
private _index: number = 0;
@ -412,7 +412,7 @@ class DirtyDiffWidget extends PeekViewWidget {
stickyScroll: { enabled: false }
};
this.diffEditor = this.instantiationService.createInstance(EmbeddedDiffEditorWidget, container, options, {}, this.editor);
this.diffEditor = this.instantiationService.createInstance(EmbeddedDiffEditorWidget2, container, options, {}, this.editor);
this._disposables.add(this.diffEditor);
}

View file

@ -12,7 +12,7 @@ import { IIdentityProvider, IKeyboardNavigationLabelProvider, IListVirtualDelega
import { DefaultKeyboardNavigationDelegate, IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { ITreeContextMenuEvent, ITreeFilter, ITreeNode, ITreeRenderer, ITreeSorter, TreeFilterResult, TreeVisibility } from 'vs/base/browser/ui/tree/tree';
import { Action, ActionRunner, IAction, Separator } from 'vs/base/common/actions';
import { mapFind } from 'vs/base/common/arrays';
import { mapFindFirst } from 'vs/base/common/arraysFind';
import { RunOnceScheduler, disposableTimeout } from 'vs/base/common/async';
import { Color, RGBA } from 'vs/base/common/color';
import { Emitter, Event } from 'vs/base/common/event';
@ -509,7 +509,7 @@ class ResultSummaryView extends Disposable {
rerun.style.display = 'none';
} else {
const last = results[0];
const dominantState = mapFind(statesInOrder, s => last.counts[s] > 0 ? s : undefined);
const dominantState = mapFindFirst(statesInOrder, s => last.counts[s] > 0 ? s : undefined);
status.className = ThemeIcon.asClassName(icons.testingStatesToIcons.get(dominantState ?? TestResultState.Unset)!);
counts = collectTestStateCounts(false, [last]);
duration.textContent = last instanceof LiveTestResult ? formatDuration(last.completedAt! - last.startedAt) : '';

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { findFirstInSorted } from 'vs/base/common/arrays';
import { findFirstIdxMonotonousOrArrLen } from 'vs/base/common/arraysFind';
import { RunOnceScheduler } from 'vs/base/common/async';
import { Emitter, Event } from 'vs/base/common/event';
import { once } from 'vs/base/common/functional';
@ -168,7 +168,7 @@ export class TestResultService implements ITestResultService {
if (result.completedAt === undefined) {
this.results.unshift(result);
} else {
const index = findFirstInSorted(this.results, r => r.completedAt !== undefined && r.completedAt <= result.completedAt!);
const index = findFirstIdxMonotonousOrArrLen(this.results, r => r.completedAt !== undefined && r.completedAt <= result.completedAt!);
this.results.splice(index, 0, result);
this.persistScheduler.schedule();
}

View file

@ -7,7 +7,7 @@ import { Application, Logger } from '../../../../automation';
import { installAllHandlers } from '../../utils';
export function setup(logger: Logger) {
describe('Extensions', () => {
describe.skip('Extensions', () => {
// Shared before/after handling
installAllHandlers(logger);

View file

@ -8,7 +8,7 @@ import { installAllHandlers } from '../../utils';
export function setup(logger: Logger) {
describe('Localization', () => {
describe.skip('Localization', () => {
// Shared before/after handling
installAllHandlers(logger);