Skip to content

Commit

Permalink
feat: implement conflict actions operations (#2014)
Browse files Browse the repository at this point in the history
* feat: implement conflict actions operations

* feat: implement conflict actions operations

* refactor: decorations type

* fix: conflict-actions

* chore: improve code

* refactor: document mapping

* chore: rename type

* chore: add note
  • Loading branch information
Ricbet committed Nov 30, 2022
1 parent cca5a4d commit 23fa33b
Show file tree
Hide file tree
Showing 18 changed files with 712 additions and 169 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ 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';
Expand All @@ -19,6 +20,9 @@ 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;
Expand All @@ -34,7 +38,7 @@ export class MergeEditorService extends Disposable {
this.computerDiffModel = new ComputerDiffModel();
this.scrollSynchronizer = new ScrollSynchronizer();
this.stickinessConnectManager = new StickinessConnectManager();
this.actionsManager = new ActionsManager();
this.actionsManager = this.injector.get(ActionsManager, [this.mappingManagerService]);
}

public instantiationCodeEditor(current: HTMLDivElement, result: HTMLDivElement, incoming: HTMLDivElement): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { Range } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/range';
import { IDocumentDiff } from '@opensumi/monaco-editor-core/esm/vs/editor/common/diff/documentDiffProvider';
import {
LineRangeMapping,
RangeMapping,
} from '@opensumi/monaco-editor-core/esm/vs/editor/common/diff/linesDiffComputer';
import { RangeMapping } from '@opensumi/monaco-editor-core/esm/vs/editor/common/diff/linesDiffComputer';
import {
IEditorWorkerService,
IDiffComputationResult,
Expand All @@ -12,7 +8,9 @@ import { StandaloneServices } from '@opensumi/monaco-editor-core/esm/vs/editor/s

import { ITextModel } from '../../../monaco-api/types';

import { InnerRange } from './inner-range';
import { LineRange } from './line-range';
import { LineRangeMapping } from './line-range-mapping';

export class ComputerDiffModel {
private editorWorkerService: IEditorWorkerService;
Expand All @@ -33,7 +31,9 @@ export class ComputerDiffModel {
new LineRangeMapping(
new LineRange(c[0], c[1]),
new LineRange(c[2], c[3]),
c[4]?.map((c) => new RangeMapping(new Range(c[0], c[1], c[2], c[3]), new Range(c[4], c[5], c[6], c[7]))),
c[4]?.map(
(c) => new RangeMapping(new InnerRange(c[0], c[1], c[2], c[3]), new InnerRange(c[4], c[5], c[6], c[7])),
),
),
),
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,56 +1,103 @@
import { Injectable, Optional } from '@opensumi/di';
import { Disposable } from '@opensumi/ide-core-common';
import { IEditorDecorationsCollection } from '@opensumi/monaco-editor-core/esm/vs/editor/common/editorCommon';
import { ModelDecorationOptions } from '@opensumi/monaco-editor-core/esm/vs/editor/common/model/textModel';

import { ICodeEditor, IModelDeltaDecoration } from '../../../monaco-api/editor';
import { IActionsDescription } from '../types';
import { BaseCodeEditor } from '../view/editors/baseCodeEditor';

import { LineRange } from './line-range';
export interface IActionsDecoration {
id: string;
readonly editorDecoration: IModelDeltaDecoration;
}

@Injectable({ multiple: false })
export class ConflictActions extends Disposable {
private decorationsCollection: IEditorDecorationsCollection;
private actionsCollect: Map<number, LineRange>;
private deltaDecoration: IActionsDecoration[] = [];

private actionsCollect: Map<number, IActionsDescription> = new Map();

private get editor(): ICodeEditor {
return this.codeEditor.getEditor();
}

constructor(@Optional() private readonly codeEditor: BaseCodeEditor) {
super();

this.decorationsCollection = this.editor.createDecorationsCollection();
this.actionsCollect = new Map();
}

public override dispose(): void {
super.dispose();
this.decorationsCollection.clear();
this.actionsCollect.clear();
}

public clearDecorations(): void {
this.editor.changeDecorations((accessor) => {
for (const decoration of this.deltaDecoration) {
accessor.removeDecoration(decoration.id);
}
this.deltaDecoration = [];
});
}

public clearDecorationsById(id: string): void {
this.editor.changeDecorations((accessor) => {
if (id) {
accessor.removeDecoration(id);

this.deltaDecoration = this.deltaDecoration.filter((d) => d.id !== id);
}
});
}

public setActions(actions: IActionsDescription[]): void {
const newDecorations: IModelDeltaDecoration[] = actions.map((action) => {
const newDecorations: IActionsDecoration[] = actions.map((action) => {
const { range } = action;
this.actionsCollect.set(range.startLineNumber, range);
this.actionsCollect.set(range.startLineNumber, action);

return {
range: {
startLineNumber: range.startLineNumber,
startColumn: 0,
endLineNumber: range.startLineNumber,
endColumn: 0,
id: '',
editorDecoration: {
range: {
startLineNumber: range.startLineNumber,
startColumn: 0,
endLineNumber: range.startLineNumber,
endColumn: 0,
},
options: ModelDecorationOptions.register({
description: range.id,
...action.decorationOptions,
}),
},
options: ModelDecorationOptions.register(action.decorationOptions),
};
});

this.decorationsCollection.set(newDecorations);
this.editor.changeDecorations((accessor) => {
accessor
.deltaDecorations(
this.deltaDecoration.map((d) => d.id),
newDecorations.map((d) => d.editorDecoration),
)
.forEach((id, i) => (newDecorations[i].id = id));
this.deltaDecoration = newDecorations;
});
}

public clearActions(line: number): void {
if (this.actionsCollect.has(line)) {
const actions = this.actionsCollect.get(line);

const matchDecoration = this.deltaDecoration.find(
(d) => d.editorDecoration.options.description === actions!.range.id,
);
if (matchDecoration) {
this.clearDecorationsById(matchDecoration.id);
}

this.actionsCollect.delete(line);
}
}

public getActions(line: number): LineRange | undefined {
public getActions(line: number): IActionsDescription | undefined {
return this.actionsCollect.get(line);
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import { Injectable, Optional } from '@opensumi/di';
import { Disposable, Emitter, Event } from '@opensumi/ide-core-common';
import { IRange, Range } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/range';
import { ModelDecorationOptions } from '@opensumi/monaco-editor-core/esm/vs/editor/common/model/textModel';
import { IModelDecorationsChangedEvent } from '@opensumi/monaco-editor-core/esm/vs/editor/common/textModelEvents';

import { ICodeEditor, IModelDeltaDecoration } from '../../../monaco-api/editor';
import { EditorViewType, LineRangeType } from '../types';
import { EditorViewType } from '../types';
import { BaseCodeEditor } from '../view/editors/baseCodeEditor';
import { GuidelineWidget } from '../view/guideline-widget';

import { InnerRange } from './inner-range';
import { LineRange } from './line-range';

export interface IRenderChangesInput {
ranges: LineRange;
type: LineRangeType;
}

export interface IRenderInnerChangesInput {
ranges: Range[];
type: LineRangeType;
}

export interface IDiffDecoration {
id: string;
readonly editorDecoration: IModelDeltaDecoration;
Expand Down Expand Up @@ -58,15 +48,19 @@ export class MergeEditorDecorations extends Disposable {
this.editor.onDidChangeModelDecorations,
this.onDidChangeLineWidget,
)(() => {
this._onDidChangeDecorations.fire(this);
this.launchChange();
}),
);
}

private createLineDecoration(range: LineRange, type: LineRangeType): IDiffDecoration {
public launchChange(): void {
this._onDidChangeDecorations.fire(this);
}

public createLineDecoration(range: LineRange): IDiffDecoration {
const options = ModelDecorationOptions.register({
description: 'merge-editor-diff-line',
className: `merge-editor-diff-line-background ${type}`,
description: range.id,
className: `merge-editor-diff-line-background ${range.type}`,
isWholeLine: true,
});

Expand All @@ -76,7 +70,7 @@ export class MergeEditorDecorations extends Disposable {
range: {
startLineNumber: range.startLineNumber,
startColumn: 0,
endLineNumber: range.endLineNumberExclusive - 1,
endLineNumber: Math.max(range.startLineNumber, range.endLineNumberExclusive - 1),
endColumn: Number.MAX_SAFE_INTEGER,
},
options: {
Expand All @@ -87,21 +81,28 @@ export class MergeEditorDecorations extends Disposable {
};
}

private createInnerCharDecoration(range: IRange, type: LineRangeType): IDiffDecoration {
public createInnerCharDecoration(range: InnerRange): IDiffDecoration {
return {
id: '',
editorDecoration: {
range,
options: ModelDecorationOptions.register({
description: 'merge-editor-diff-inner-char',
className: `merge-editor-diff-inner-char-background ${type}`,
description: range.toString(),
className: `merge-editor-diff-inner-char-background ${range.type}`,
isWholeLine: false,
}),
},
};
}

private setDecorations(ranges: IRenderChangesInput[], innerChanges: IRenderInnerChangesInput[]): void {
public createGuideLineWidget(range: LineRange): GuidelineWidget {
const guidelineWidget = new GuidelineWidget(this.editor);
guidelineWidget.create();
guidelineWidget.setLineRangeType(range.type).showByLine(Math.max(0, Math.max(0, range.startLineNumber - 1)));
return guidelineWidget;
}

private setDecorations(ranges: LineRange[], innerChanges: InnerRange[][]): void {
this.editor.changeDecorations((accessor) => {
const newDecorations: IDiffDecoration[] = this.retainDecoration;
this.retainLineWidgetSet.forEach((widget) => {
Expand All @@ -110,23 +111,19 @@ export class MergeEditorDecorations extends Disposable {
});

for (const range of ranges) {
if (range.ranges.isEmpty) {
const guidelineWidget = new GuidelineWidget(this.editor);
guidelineWidget.create();
guidelineWidget.setLineRangeType(range.type).showByLine(Math.max(0, range.ranges.startLineNumber - 1));

if (range.isEmpty) {
const guidelineWidget = this.createGuideLineWidget(range);
this.lineWidgetSet.add(guidelineWidget);
this._onDidChangeLineWidget.fire();
} else {
newDecorations.push(this.createLineDecoration(range.ranges, range.type));
newDecorations.push(this.createLineDecoration(range));
}
}

for (const innerRange of innerChanges) {
const { ranges, type } = innerRange;
for (const range of ranges) {
for (const range of innerRange) {
if (!range.isEmpty()) {
newDecorations.push(this.createInnerCharDecoration(range, type));
newDecorations.push(this.createInnerCharDecoration(range));
}
}
}
Expand Down Expand Up @@ -160,7 +157,7 @@ export class MergeEditorDecorations extends Disposable {
this.cleanUpLineWidget(this.lineWidgetSet);
}

public updateDecorations(ranges: IRenderChangesInput[], innerChanges: IRenderInnerChangesInput[]): void {
public updateDecorations(ranges: LineRange[], innerChanges: InnerRange[][]): void {
this.clearDecorations();
this.render(ranges, innerChanges);
}
Expand All @@ -187,7 +184,7 @@ export class MergeEditorDecorations extends Disposable {
return this;
}

public render(ranges: IRenderChangesInput[], innerChanges: IRenderInnerChangesInput[]): void {
public render(ranges: LineRange[], innerChanges: InnerRange[][]): void {
this.setDecorations(ranges, innerChanges);
}

Expand Down
Loading

0 comments on commit 23fa33b

Please sign in to comment.