Skip to content

Commit 739bf4e

Browse files
authored
Implement Add "Ignore" buttons microsoft#164425 (microsoft#165387)
1 parent b75ba63 commit 739bf4e

File tree

6 files changed

+94
-54
lines changed

6 files changed

+94
-54
lines changed

src/vs/workbench/contrib/mergeEditor/browser/model/mergeEditorModel.ts

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { DetailedLineRangeMapping, DocumentLineRangeMap, DocumentRangeMap, LineR
1717
import { TextModelDiffChangeReason, TextModelDiffs, TextModelDiffState } from 'vs/workbench/contrib/mergeEditor/browser/model/textModelDiffs';
1818
import { MergeEditorTelemetry } from 'vs/workbench/contrib/mergeEditor/browser/telemetry';
1919
import { leftJoin } from 'vs/workbench/contrib/mergeEditor/browser/utils';
20-
import { ModifiedBaseRange, ModifiedBaseRangeState, ModifiedBaseRangeStateKind } from './modifiedBaseRange';
20+
import { InputNumber, ModifiedBaseRange, ModifiedBaseRangeState, ModifiedBaseRangeStateKind } from './modifiedBaseRange';
2121

2222
export interface InputData {
2323
readonly textModel: ITextModel;
@@ -40,13 +40,7 @@ export class MergeEditorModel extends EditorModel {
4040
derived('modifiedBaseRangeResultStates', reader => {
4141
const map = new Map<ModifiedBaseRange, ModifiedBaseRangeData>(
4242
this.modifiedBaseRanges.read(reader).map<[ModifiedBaseRange, ModifiedBaseRangeData]>((s) => [
43-
s,
44-
{
45-
accepted: observableValue(`BaseRangeState${s.baseRange}`, ModifiedBaseRangeState.base),
46-
handled: observableValue(`BaseRangeHandledState${s.baseRange}`, false),
47-
computedFromDiffing: false,
48-
previousNonDiffingState: undefined,
49-
}
43+
s, new ModifiedBaseRangeData(s)
5044
])
5145
);
5246
return map;
@@ -109,7 +103,9 @@ export class MergeEditorModel extends EditorModel {
109103
shouldRecomputeHandledFromAccepted = false;
110104
for (const [_range, observableState] of states) {
111105
const state = observableState.accepted.get();
112-
observableState.handled.set(!(state.kind === ModifiedBaseRangeStateKind.base || state.kind === ModifiedBaseRangeStateKind.unrecognized), tx);
106+
const handled = !(state.kind === ModifiedBaseRangeStateKind.base || state.kind === ModifiedBaseRangeStateKind.unrecognized);
107+
observableState.handledInput1.set(handled, tx);
108+
observableState.handledInput2.set(handled, tx);
113109
}
114110
}
115111
});
@@ -149,7 +145,8 @@ export class MergeEditorModel extends EditorModel {
149145
state.accepted.set(newState, tx);
150146
state.computedFromDiffing = false;
151147
state.previousNonDiffingState = undefined;
152-
state.handled.set(handled, tx);
148+
state.handledInput1.set(handled, tx);
149+
state.handledInput2.set(handled, tx);
153150
}
154151

155152
this.resultTextModel.pushEditOperations(null, [{
@@ -201,6 +198,7 @@ export class MergeEditorModel extends EditorModel {
201198

202199
public readonly baseInput2Diffs = this.input2TextModelDiffs.diffs;
203200
public readonly baseResultDiffs = this.resultTextModelDiffs.diffs;
201+
public get isApplyingEditInResult(): boolean { return this.resultTextModelDiffs.isApplyingChange; }
204202
public readonly input1ResultMapping = derived('input1ResultMapping', reader => {
205203
return this.getInputResultMapping(
206204
this.baseInput1Diffs.read(reader),
@@ -408,7 +406,7 @@ export class MergeEditorModel extends EditorModel {
408406
public setState(
409407
baseRange: ModifiedBaseRange,
410408
state: ModifiedBaseRangeState,
411-
markHandled: boolean,
409+
markInputAsHandled: boolean | InputNumber,
412410
transaction: ITransaction,
413411
pushStackElement: boolean = false
414412
): void {
@@ -444,8 +442,13 @@ export class MergeEditorModel extends EditorModel {
444442
}
445443
}
446444

447-
if (markHandled) {
448-
existingState.handled.set(true, transaction);
445+
if (markInputAsHandled !== false) {
446+
if (markInputAsHandled === true || markInputAsHandled === 1) {
447+
existingState.handledInput1.set(true, transaction);
448+
}
449+
if (markInputAsHandled === true || markInputAsHandled === 2) {
450+
existingState.handledInput2.set(true, transaction);
451+
}
449452
}
450453
}
451454

@@ -466,13 +469,32 @@ export class MergeEditorModel extends EditorModel {
466469
return this.modifiedBaseRangeResultStates.get().get(baseRange)!.handled;
467470
}
468471

472+
public isInputHandled(baseRange: ModifiedBaseRange, inputNumber: InputNumber): IObservable<boolean> {
473+
const state = this.modifiedBaseRangeResultStates.get().get(baseRange)!;
474+
return inputNumber === 1 ? state.handledInput1 : state.handledInput2;
475+
}
476+
477+
public setInputHandled(baseRange: ModifiedBaseRange, inputNumber: InputNumber, handled: boolean, tx: ITransaction): void {
478+
const state = this.modifiedBaseRangeResultStates.get().get(baseRange)!;
479+
if (state.handled.get() === handled) {
480+
return;
481+
}
482+
483+
if (inputNumber === 1) {
484+
state.handledInput1.set(handled, tx);
485+
} else {
486+
state.handledInput2.set(handled, tx);
487+
}
488+
}
489+
469490
public setHandled(baseRange: ModifiedBaseRange, handled: boolean, tx: ITransaction): void {
470491
const state = this.modifiedBaseRangeResultStates.get().get(baseRange)!;
471492
if (state.handled.get() === handled) {
472493
return;
473494
}
474495

475-
state.handled.set(handled, tx);
496+
state.handledInput1.set(handled, tx);
497+
state.handledInput2.set(handled, tx);
476498
}
477499

478500
public readonly unhandledConflictsCount = derived('unhandledConflictsCount', reader => {
@@ -689,13 +711,17 @@ function arrayCount<T>(array: Iterable<T>, predicate: (value: T) => boolean): nu
689711
return count;
690712
}
691713

692-
interface ModifiedBaseRangeData {
693-
accepted: ISettableObservable<ModifiedBaseRangeState>;
714+
class ModifiedBaseRangeData {
715+
constructor(private readonly baseRange: ModifiedBaseRange) { }
716+
717+
public accepted: ISettableObservable<ModifiedBaseRangeState> = observableValue(`BaseRangeState${this.baseRange.baseRange}`, ModifiedBaseRangeState.base);
718+
public handledInput1: ISettableObservable<boolean> = observableValue(`BaseRangeHandledState${this.baseRange.baseRange}.Input1`, false);
719+
public handledInput2: ISettableObservable<boolean> = observableValue(`BaseRangeHandledState${this.baseRange.baseRange}.Input2`, false);
694720

695-
handled: ISettableObservable<boolean>;
721+
public computedFromDiffing = false;
722+
public previousNonDiffingState: ModifiedBaseRangeState | undefined = undefined;
696723

697-
computedFromDiffing: boolean;
698-
previousNonDiffingState: ModifiedBaseRangeState | undefined;
724+
public readonly handled = derived('handled', reader => this.handledInput1.read(reader) && this.handledInput2.read(reader));
699725
}
700726

701727
export const enum MergeEditorModelState {

src/vs/workbench/contrib/mergeEditor/browser/model/textModelDiffs.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ export class TextModelDiffs extends Disposable {
2222
private readonly barrier = new ReentrancyBarrier();
2323
private isDisposed = false;
2424

25+
public get isApplyingChange() {
26+
return this.barrier.isActive;
27+
}
28+
2529
constructor(
2630
private readonly baseTextModel: ITextModel,
2731
private readonly textModel: ITextModel,

src/vs/workbench/contrib/mergeEditor/browser/utils.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,47 @@ import { IModelDeltaDecoration } from 'vs/editor/common/model';
1212
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
1313

1414
export class ReentrancyBarrier {
15-
private isActive = false;
15+
private _isActive = false;
16+
17+
public get isActive() {
18+
return this._isActive;
19+
}
1620

1721
public makeExclusive<TFunction extends Function>(fn: TFunction): TFunction {
1822
return ((...args: any[]) => {
19-
if (this.isActive) {
23+
if (this._isActive) {
2024
return;
2125
}
22-
this.isActive = true;
26+
this._isActive = true;
2327
try {
2428
return fn(...args);
2529
} finally {
26-
this.isActive = false;
30+
this._isActive = false;
2731
}
2832
}) as any;
2933
}
3034

3135
public runExclusively(fn: () => void): void {
32-
if (this.isActive) {
36+
if (this._isActive) {
3337
return;
3438
}
35-
this.isActive = true;
39+
this._isActive = true;
3640
try {
3741
fn();
3842
} finally {
39-
this.isActive = false;
43+
this._isActive = false;
4044
}
4145
}
4246

4347
public runExclusivelyOrThrow(fn: () => void): void {
44-
if (this.isActive) {
48+
if (this._isActive) {
4549
throw new BugIndicatingError();
4650
}
47-
this.isActive = true;
51+
this._isActive = true;
4852
try {
4953
fn();
5054
} finally {
51-
this.isActive = false;
55+
this._isActive = false;
5256
}
5357
}
5458
}

src/vs/workbench/contrib/mergeEditor/browser/view/conflictActions.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export class ActionsSource {
127127
model.setState(
128128
modifiedBaseRange,
129129
state.withInputValue(inputNumber, true, false),
130-
true,
130+
inputNumber,
131131
tx
132132
);
133133
model.telemetry.reportAcceptInvoked(inputNumber, state.includesInput(otherInputNumber));
@@ -159,7 +159,7 @@ export class ActionsSource {
159159
model.setState(
160160
modifiedBaseRange,
161161
state.withInputValue(inputNumber, true, false),
162-
true,
162+
inputNumber,
163163
tx
164164
);
165165
model.telemetry.reportAcceptInvoked(inputNumber, state.includesInput(otherInputNumber));
@@ -174,7 +174,7 @@ export class ActionsSource {
174174
model.setState(
175175
modifiedBaseRange,
176176
state.withInputValue(inputNumber, true, true),
177-
true,
177+
inputNumber,
178178
tx
179179
);
180180
model.telemetry.reportSmartCombinationInvoked(state.includesInput(otherInputNumber));
@@ -184,6 +184,19 @@ export class ActionsSource {
184184
}
185185
}
186186

187+
if (!model.isInputHandled(modifiedBaseRange, inputNumber).read(reader)) {
188+
result.push(
189+
command(
190+
localize('ignore', 'Ignore'),
191+
async () => {
192+
transaction((tx) => {
193+
model.setInputHandled(modifiedBaseRange, inputNumber, true, tx);
194+
});
195+
},
196+
localize('markAsHandledTooltip', "Don't take this side of the conflict.")
197+
)
198+
);
199+
}
187200

188201
}
189202
return result;
@@ -299,20 +312,6 @@ export class ActionsSource {
299312
);
300313
}
301314

302-
if (state.kind === ModifiedBaseRangeStateKind.base && !model.isHandled(modifiedBaseRange).read(reader)) {
303-
result.push(
304-
command(
305-
localize('markAsHandled', 'Mark As Handled'),
306-
async () => {
307-
transaction((tx) => {
308-
model.setHandled(modifiedBaseRange, true, tx);
309-
});
310-
},
311-
localize('markAsHandledTooltip', 'Marks this conflict as handled.')
312-
)
313-
);
314-
}
315-
316315
return result;
317316
});
318317

src/vs/workbench/contrib/mergeEditor/browser/view/editors/inputCodeEditorView.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export class InputCodeEditorView extends CodeEditorView {
140140
}
141141

142142
const blockClassNames = ['merge-editor-block'];
143-
const isHandled = model.isHandled(modifiedBaseRange).read(reader);
143+
const isHandled = model.isInputHandled(modifiedBaseRange, this.inputNumber).read(reader);
144144
if (isHandled) {
145145
blockClassNames.push('handled');
146146
}
@@ -261,7 +261,8 @@ export class ModifiedBaseRangeGutterItemModel implements IGutterItemInfo {
261261
.getState(this.baseRange)
262262
.get()
263263
.withInputValue(this.inputNumber, value),
264-
tx
264+
tx,
265+
this.inputNumber
265266
);
266267
}
267268
public toggleBothSides(): void {
@@ -288,7 +289,7 @@ export class ModifiedBaseRangeGutterItemModel implements IGutterItemInfo {
288289
const update = (newState: ModifiedBaseRangeState) => {
289290
transaction(tx => {
290291
/** @description Context Menu: Update Base Range State */
291-
return this.viewModel.setState(this.baseRange, newState, tx);
292+
return this.viewModel.setState(this.baseRange, newState, tx, this.inputNumber);
292293
});
293294
};
294295

src/vs/workbench/contrib/mergeEditor/browser/view/viewModel.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
1313
import { INotificationService } from 'vs/platform/notification/common/notification';
1414
import { LineRange } from 'vs/workbench/contrib/mergeEditor/browser/model/lineRange';
1515
import { MergeEditorModel } from 'vs/workbench/contrib/mergeEditor/browser/model/mergeEditorModel';
16-
import { ModifiedBaseRange, ModifiedBaseRangeState } from 'vs/workbench/contrib/mergeEditor/browser/model/modifiedBaseRange';
16+
import { InputNumber, ModifiedBaseRange, ModifiedBaseRangeState } from 'vs/workbench/contrib/mergeEditor/browser/model/modifiedBaseRange';
1717
import { BaseCodeEditorView } from 'vs/workbench/contrib/mergeEditor/browser/view/editors/baseCodeEditorView';
1818
import { CodeEditorView } from 'vs/workbench/contrib/mergeEditor/browser/view/editors/codeEditorView';
1919
import { InputCodeEditorView } from 'vs/workbench/contrib/mergeEditor/browser/view/editors/inputCodeEditorView';
@@ -37,6 +37,9 @@ export class MergeEditorViewModel extends Disposable {
3737
super();
3838

3939
this._register(resultCodeEditorView.editor.onDidChangeModelContent(e => {
40+
if (this.model.isApplyingEditInResult) {
41+
return;
42+
}
4043
transaction(tx => {
4144
/** @description Mark conflicts touched by manual edits as handled */
4245
for (const change of e.changes) {
@@ -151,10 +154,11 @@ export class MergeEditorViewModel extends Disposable {
151154
public setState(
152155
baseRange: ModifiedBaseRange,
153156
state: ModifiedBaseRangeState,
154-
tx: ITransaction
157+
tx: ITransaction,
158+
inputNumber: InputNumber,
155159
): void {
156160
this.manuallySetActiveModifiedBaseRange.set({ range: baseRange, counter: this.counter++ }, tx);
157-
this.model.setState(baseRange, state, true, tx);
161+
this.model.setState(baseRange, state, inputNumber, tx);
158162
}
159163

160164
private goToConflict(getModifiedBaseRange: (editor: CodeEditorView, curLineNumber: number) => ModifiedBaseRange | undefined): void {
@@ -231,7 +235,8 @@ export class MergeEditorViewModel extends Disposable {
231235
this.setState(
232236
activeModifiedBaseRange,
233237
this.model.getState(activeModifiedBaseRange).get().toggle(inputNumber),
234-
tx
238+
tx,
239+
inputNumber,
235240
);
236241
});
237242
}
@@ -243,7 +248,8 @@ export class MergeEditorViewModel extends Disposable {
243248
this.setState(
244249
range,
245250
this.model.getState(range).get().withInputValue(inputNumber, true),
246-
tx
251+
tx,
252+
inputNumber
247253
);
248254
}
249255
});

0 commit comments

Comments
 (0)