Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement conflict actions operations #2014

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
refactor: document mapping
  • Loading branch information
Ricbet committed Nov 28, 2022
commit d6c28750e4f19ce02c388953447e3319127584d6
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { Disposable, MonacoService } from '@opensumi/ide-core-browser';
import { ICodeEditor } from '../../monaco-api/editor';

import { ComputerDiffModel } from './model/computer-diff';
import { MappingManagerService } from './service/mapping-manager.service';
import { ActionsManager } from './view/actions-manager';
import { CurrentCodeEditor } from './view/editors/currentCodeEditor';
import { IncomingCodeEditor } from './view/editors/incomingCodeEditor';
import { ResultCodeEditor } from './view/editors/resultCodeEditor';
import { MappingManager } from './view/mapping-manager';
import { ScrollSynchronizer } from './view/scroll-synchronizer';
import { StickinessConnectManager } from './view/stickiness-connect-manager';

Expand All @@ -20,13 +20,15 @@ export class MergeEditorService extends Disposable {
@Autowired(MonacoService)
private readonly monacoService: MonacoService;

@Autowired(MappingManagerService)
protected readonly mappingManagerService: MappingManagerService;

private currentView: CurrentCodeEditor;
private resultView: ResultCodeEditor;
private incomingView: IncomingCodeEditor;

private computerDiffModel: ComputerDiffModel;
private actionsManager: ActionsManager;
private mappingManager: MappingManager;

public scrollSynchronizer: ScrollSynchronizer;
public stickinessConnectManager: StickinessConnectManager;
Expand All @@ -36,8 +38,7 @@ export class MergeEditorService extends Disposable {
this.computerDiffModel = new ComputerDiffModel();
this.scrollSynchronizer = new ScrollSynchronizer();
this.stickinessConnectManager = new StickinessConnectManager();
this.actionsManager = new ActionsManager();
this.mappingManager = new MappingManager();
this.actionsManager = this.injector.get(ActionsManager, [this.mappingManagerService]);
}

public instantiationCodeEditor(current: HTMLDivElement, result: HTMLDivElement, incoming: HTMLDivElement): void {
Expand All @@ -52,7 +53,6 @@ export class MergeEditorService extends Disposable {
this.scrollSynchronizer.mount(this.currentView, this.resultView, this.incomingView);
this.stickinessConnectManager.mount(this.currentView, this.resultView, this.incomingView);
this.actionsManager.mount(this.currentView, this.resultView, this.incomingView);
this.mappingManager.mount(this.currentView, this.resultView, this.incomingView);
}

public override dispose(): void {
Expand All @@ -63,7 +63,6 @@ export class MergeEditorService extends Disposable {
this.scrollSynchronizer.dispose();
this.stickinessConnectManager.dispose();
this.actionsManager.dispose();
this.mappingManager.dispose();
}

public getCurrentEditor(): ICodeEditor {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,4 @@ export class ConflictActions extends Disposable {
public getActions(line: number): IActionsDescription | undefined {
return this.actionsCollect.get(line);
}

public applyLineRangeEdits(model: ITextModel, edits: { range: IRange; text: string }[]): void {
model.pushStackElement();
model.pushEditOperations(
null,
edits.map((edit) => {
const { range, text } = edit;

return {
range,
isAutoWhitespaceEdit: false,
text,
};
}),
() => null,
);
model.pushStackElement();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,26 @@ export class DocumentMapping extends Disposable {
const sameRange = this.adjacentComputeRangeMap.get(range.id);

for (const [key, pick] of this.adjacentComputeRangeMap.entries()) {
if (sameRange && pick.isAfter(sameRange)) {
if (sameRange && (pick.isTouches(sameRange) || pick.isAfter(sameRange))) {
this.adjacentComputeRangeMap.set(key, pick.delta(offset));
}
}
}

/**
* 寻找下一个离 sameRange 最近的 sameRange 点
* @param sameRange 对位 lineRange,不一定存在于 map 中
* @returns 下一个最近的 lineRange
*/
public huntForNextSameRange(sameRange: LineRange): LineRange | undefined {
const values = this.adjacentComputeRangeMap.values();

for (const range of values) {
if (range.isAfter(sameRange)) {
return range;
}
}

return undefined;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export class LineRange extends MonacoLineRange implements IRangeContrast {
return range.startLineNumber >= this.endLineNumberExclusive;
}

public isTouches(range: LineRange): boolean {
return this.endLineNumberExclusive >= range.startLineNumber && range.endLineNumberExclusive >= this.startLineNumber;
}

public isInclude(range: LineRange | InnerRange): boolean {
if (range instanceof LineRange) {
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Injectable, Autowired, Injector, INJECTOR_TOKEN } from '@opensumi/di';
import { Disposable } from '@opensumi/ide-core-common';

import { DocumentMapping } from '../model/document-mapping';
import { LineRange } from '../model/line-range';
import { LineRangeMapping } from '../model/line-range-mapping';
import { EDiffRangeTurn, EditorViewType } from '../types';
import { BaseCodeEditor } from '../view/editors/baseCodeEditor';

@Injectable()
export class MappingManagerService extends Disposable {
@Autowired(INJECTOR_TOKEN)
private readonly injector: Injector;

public documentMappingTurnLeft: DocumentMapping;
public documentMappingTurnRight: DocumentMapping;

constructor() {
super();

this.documentMappingTurnLeft = this.injector.get(DocumentMapping, [this, EDiffRangeTurn.ORIGIN]);
this.documentMappingTurnRight = this.injector.get(DocumentMapping, [this, EDiffRangeTurn.MODIFIED]);
}

private markCompleteFactory(turn: EDiffRangeTurn): (range: LineRange) => void {
const [mapping, sameMapping] =
turn === EDiffRangeTurn.ORIGIN
? [this.documentMappingTurnLeft, this.documentMappingTurnRight]
: [this.documentMappingTurnRight, this.documentMappingTurnLeft];

return (range: LineRange) => {
const sameRange = mapping.adjacentComputeRangeMap.get(range.id);
if (!sameRange) {
return;
}

const marginLength = range.calcMargin(sameRange);

mapping.deltaAdjacentQueue(range, marginLength);
mapping.computeRangeMap.delete(range.id);
mapping.adjacentComputeRangeMap.delete(range.id);

const findNextRange = sameMapping.huntForNextSameRange(sameRange);
const reverseRange = findNextRange && sameMapping.reverse(findNextRange);
if (reverseRange) {
sameMapping.deltaAdjacentQueue(reverseRange, marginLength);
}
};
}

public inputComputeResultRangeMappingTurnLeft(changes: LineRangeMapping[]): void {
this.documentMappingTurnLeft.inputComputeResultRangeMapping(changes);
}

public inputComputeResultRangeMappingTurnRight(changes: LineRangeMapping[]): void {
this.documentMappingTurnRight.inputComputeResultRangeMapping(changes);
}

public markCompleteTurnLeft(range: LineRange): void {
this.markCompleteFactory(EDiffRangeTurn.ORIGIN)(range);
}

public markCompleteTurnRight(range: LineRange): void {
this.markCompleteFactory(EDiffRangeTurn.MODIFIED)(range);
}
}
5 changes: 5 additions & 0 deletions packages/monaco/src/browser/contrib/merge-editor/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,8 @@ export namespace CONFLICT_ACTIONS_ICON {
export const LEFT = `conflict-actions ${ACCEPT_CURRENT} ${getIcon('left')}`;
export const CLOSE = `conflict-actions ${IGNORE} ${getIcon('close')}`;
}

export interface IConflictActionsEvent {
range: LineRange;
withViewType: EditorViewType;
}
4 changes: 2 additions & 2 deletions packages/monaco/src/browser/contrib/merge-editor/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const flatInnerOriginal = (changes: LineRangeMapping[]): InnerRange[][] =
changes
.map((c) => c.innerChanges)
.filter(Boolean)
.map((m) => m!.map((m) => m.originalRange));
.map((m) => m!.map((m) => m.originalRange as InnerRange));

export const flatModified = (changes: LineRangeMapping[]): LineRange[] =>
changes.map((c) => c.modifiedRange as LineRange);
Expand All @@ -18,4 +18,4 @@ export const flatInnerModified = (changes: LineRangeMapping[]): InnerRange[][] =
changes
.map((c) => c.innerChanges)
.filter(Boolean)
.map((m) => m!.map((m) => m.modifiedRange));
.map((m) => m!.map((m) => m.modifiedRange as InnerRange));
Original file line number Diff line number Diff line change
@@ -1,20 +1,116 @@
import { Disposable } from '@opensumi/ide-core-common';
import { Disposable, Event } from '@opensumi/ide-core-common';
import { IEditorMouseEvent, MouseTargetType } from '@opensumi/monaco-editor-core/esm/vs/editor/browser/editorBrowser';
import { IRange } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/range';

import { IActionsDescription } from '../types';
import { MappingManagerService } from '../service/mapping-manager.service';
import { IActionsDescription, IConflictActionsEvent } from '../types';

import { BaseCodeEditor } from './editors/baseCodeEditor';
import { ResultCodeEditor } from './editors/resultCodeEditor';

export class ActionsManager extends Disposable {
private currentView: BaseCodeEditor | undefined;
private resultView: BaseCodeEditor | undefined;
private resultView: ResultCodeEditor | undefined;
private incomingView: BaseCodeEditor | undefined;

constructor() {
constructor(private readonly mappingManagerService: MappingManagerService) {
super();
}

public mount(currentView: BaseCodeEditor, resultView: BaseCodeEditor, incomingView: BaseCodeEditor): void {
private applyLineRangeEdits(edits: { range: IRange; text: string }[]): void {
if (!this.resultView) {
return;
}
const model = this.resultView.getModel();

if (!model) {
return;
}

model.pushStackElement();
model.pushEditOperations(
null,
edits.map((edit) => {
const { range, text } = edit;

return {
range,
isAutoWhitespaceEdit: false,
text,
};
}),
() => null,
);
model.pushStackElement();
}

private initListenEvent(): void {
if (!this.currentView || !this.resultView || !this.incomingView) {
return;
}

this.addDispose(
Event.any<IConflictActionsEvent>(
this.currentView.onDidConflictActions,
this.resultView.onDidConflictActions,
this.incomingView.onDidConflictActions,
)(({ range, withViewType }) => {
if (withViewType === 'current') {
const sameRange = this.mappingManagerService.documentMappingTurnLeft.adjacentComputeRangeMap.get(range.id);

const applyText = this.currentView!.getModel()!.getValueInRange(range.toRange());

if (sameRange) {
this.applyLineRangeEdits([
{
range: range.isEmpty ? sameRange.deltaStart(-1).toRange(Number.MAX_SAFE_INTEGER) : sameRange.toRange(),
text: applyText + (sameRange.isEmpty ? '\n' : ''),
},
]);

this.mappingManagerService.markCompleteTurnLeft(range);

this.currentView!.updateDecorations();
this.currentView!.clearActions(range);

this.resultView!.updateDecorations();

this.currentView!.launchChange();
this.incomingView!.launchChange();
return true;
}
}

if (withViewType === 'incoming') {
const sameRange = this.mappingManagerService.documentMappingTurnRight.adjacentComputeRangeMap.get(range.id);

const applyText = this.incomingView!.getModel()!.getValueInRange(range.toRange());

if (sameRange) {
this.applyLineRangeEdits([
{
range: range.isEmpty ? sameRange.deltaStart(-1).toRange(Number.MAX_SAFE_INTEGER) : sameRange.toRange(),
text: applyText + (sameRange.isEmpty ? '\n' : ''),
},
]);

this.mappingManagerService.markCompleteTurnRight(range);

this.incomingView!.updateDecorations();
this.incomingView!.clearActions(range);

this.resultView!.updateDecorations();

this.currentView!.launchChange();
this.incomingView!.launchChange();
return true;
}
}
}),
);
}

public mount(currentView: BaseCodeEditor, resultView: ResultCodeEditor, incomingView: BaseCodeEditor): void {
this.currentView = currentView;
this.resultView = resultView;
this.incomingView = incomingView;
Expand Down Expand Up @@ -57,5 +153,6 @@ export class ActionsManager extends Disposable {
this.addDispose(currentView.getEditor().onMouseDown((e: IEditorMouseEvent) => handleMouseDown(e, currentView)));
this.addDispose(incomingView.getEditor().onMouseDown((e: IEditorMouseEvent) => handleMouseDown(e, incomingView)));
this.addDispose(resultView.getEditor().onMouseDown((e: IEditorMouseEvent) => handleMouseDown(e, resultView)));
this.initListenEvent();
}
}
Loading