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 all commits
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
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