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 editing result view code update range mapping #2042

Merged
merged 3 commits into from
Dec 5, 2022
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
@@ -0,0 +1,100 @@
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';

@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, [EDiffRangeTurn.ORIGIN]);
this.documentMappingTurnRight = this.injector.get(DocumentMapping, [EDiffRangeTurn.MODIFIED]);
}

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

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

// 标记该 range 区域已经解决完成
range.setComplete(true);
sameRange.setComplete(true);
};
}

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);
}

/**
* 分别找出离目标 lineRange 最近的 documentMappingTurnLeft 和 documentMappingTurnRight 里的 lineRange
* 其中 target 只能是 result view 视图中的 range
*/
public findNextLineRanges(target: LineRange): {
[key in EditorViewType.CURRENT | EditorViewType.INCOMING]: LineRange | undefined;
} {
const [turnLeftRange, turnRightRange] = [this.documentMappingTurnLeft, this.documentMappingTurnRight].map(
(mapping) => mapping.findNextSameRange(target),
);
return {
[EditorViewType.CURRENT]: turnLeftRange,
[EditorViewType.INCOMING]: turnRightRange,
};
}

public findTouchesRanges(target: LineRange): {
[key in EditorViewType.CURRENT | EditorViewType.INCOMING]: LineRange | undefined;
} {
const [turnLeftRange, turnRightRange] = [this.documentMappingTurnLeft, this.documentMappingTurnRight].map(
(mapping) => mapping.findTouchesRange(target),
);
return {
[EditorViewType.CURRENT]: turnLeftRange,
[EditorViewType.INCOMING]: turnRightRange,
};
}

/**
* 检查目标 lineRange 是被包裹在哪一个 documentMapping 的其中一个 LineRange 内
* 有可能左右两者都有包含
* 其中 target 只能是 result view 视图中的 range
*/
public findIncludeRanges(target: LineRange): {
[key in EditorViewType.CURRENT | EditorViewType.INCOMING]: LineRange | undefined;
} {
const [turnLeftRange, turnRightRange] = [this.documentMappingTurnLeft, this.documentMappingTurnRight].map(
(mapping) => mapping.findIncludeRange(target),
);

return {
[EditorViewType.CURRENT]: turnLeftRange,
[EditorViewType.INCOMING]: turnRightRange,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Disposable, MonacoService } from '@opensumi/ide-core-browser';

import { ICodeEditor } from '../../monaco-api/editor';

import { MappingManagerService } from './mapping-manager.service';
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 Down Expand Up @@ -41,6 +41,16 @@ export class MergeEditorService extends Disposable {
this.actionsManager = this.injector.get(ActionsManager, [this.mappingManagerService]);
}

private initListenEvent(): void {
this.addDispose(
this.resultView.onDidChangeContent(() => {
this.resultView.updateDecorations();
this.currentView.launchChange();
this.incomingView.launchChange();
}),
);
}

public instantiationCodeEditor(current: HTMLDivElement, result: HTMLDivElement, incoming: HTMLDivElement): void {
if (this.currentView && this.resultView && this.incomingView) {
return;
Expand All @@ -53,6 +63,8 @@ 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.initListenEvent();
}

public override dispose(): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Injectable, Optional } from '@opensumi/di';
import { Disposable, Emitter, Event } from '@opensumi/ide-core-common';
import {
IModelDecorationsChangeAccessor,
TrackedRangeStickiness,
} from '@opensumi/monaco-editor-core/esm/vs/editor/common/model';
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';

Expand Down Expand Up @@ -66,6 +70,7 @@ export class MergeEditorDecorations extends Disposable {
description: range.id,
className: DECORATIONS_CLASSNAME.combine(DECORATIONS_CLASSNAME.diff_line_background, range.type),
isWholeLine: true,
stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges,
});

return Array.from({ length }).map((_, idx) => {
Expand Down Expand Up @@ -133,7 +138,7 @@ export class MergeEditorDecorations extends Disposable {
}

private setDecorations(ranges: LineRange[], innerChanges: InnerRange[][]): void {
this.editor.changeDecorations((accessor) => {
this.editor.changeDecorations((accessor: IModelDecorationsChangeAccessor) => {
const newDecorations: IDiffDecoration[] = this.retainDecoration;
this.retainLineWidgetSet.forEach((widget) => {
widget.showByLine(widget.getRecordLine());
Expand All @@ -158,12 +163,9 @@ export class MergeEditorDecorations extends Disposable {
}
}

accessor
.deltaDecorations(
this.deltaDecoration.map((d) => d.id),
newDecorations.map((d) => d.editorDecoration),
)
.forEach((id, i) => (newDecorations[i].id = id));
newDecorations.forEach((d) => {
d.id = accessor.addDecoration(d.editorDecoration.range, d.editorDecoration.options);
});
this.deltaDecoration = newDecorations;
});
}
Expand All @@ -175,7 +177,7 @@ export class MergeEditorDecorations extends Disposable {
widgets.clear();
}

public clearDecorations(): void {
public clearDecorations(): this {
this.editor.changeDecorations((accessor) => {
for (const decoration of this.deltaDecoration) {
accessor.removeDecoration(decoration.id);
Expand All @@ -185,11 +187,13 @@ export class MergeEditorDecorations extends Disposable {
});

this.cleanUpLineWidget(this.lineWidgetSet);
return this;
}

public updateDecorations(ranges: LineRange[], innerChanges: InnerRange[][]): void {
public updateDecorations(ranges: LineRange[], innerChanges: InnerRange[][]): this {
this.clearDecorations();
this.render(ranges, innerChanges);
return this;
}

public getDecorations(): IDiffDecoration[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,34 @@ export class DocumentMapping extends Disposable {
}
}

public deltaAdjacentQueue(range: LineRange, offset: number): void {
/**
* 将 range 之后的所有 range 都增量 offset
* @param range 目标 range
* @param offset 有增有减
* @param isContainSelf 是否包含自己,也增量 offset
* @returns
*/
public deltaAdjacentQueueAfter(range: LineRange, offset: number, isContainSelf = false): void {
const sameRange = this.adjacentComputeRangeMap.get(range.id);
if (!sameRange) {
return;
}

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

public deltaEndAdjacentQueue(sameRange: LineRange, offset: number): void {
for (const [key, pick] of this.adjacentComputeRangeMap.entries()) {
if (pick.id === sameRange.id) {
this.adjacentComputeRangeMap.set(key, sameRange.deltaEnd(offset));
// 将在 sameRange 之后的 range offset 都增加
} else if (pick.isAfter(sameRange)) {
this.adjacentComputeRangeMap.set(key, pick.delta(offset));
}
}
Expand All @@ -84,11 +107,41 @@ export class DocumentMapping extends Disposable {
* @param sameRange 对位 lineRange,不一定存在于 map 中
* @returns 下一个最近的 lineRange
*/
public huntForNextSameRange(sameRange: LineRange): LineRange | undefined {
public findNextSameRange(sameRange: LineRange): LineRange | undefined {
const values = this.adjacentComputeRangeMap.values();

for (const range of values) {
if (range.id !== sameRange.id && range.isAfter(sameRange)) {
return range;
}
}

return undefined;
}

/**
* 找出 sameRange 是否被包裹在哪一个 lineRange 里,如果有并返回该 lineRange
*/
public findIncludeRange(sameRange: LineRange): LineRange | undefined {
const values = this.adjacentComputeRangeMap.values();

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

return undefined;
}

/**
* 找出 sameRange 是否与哪一个 lineRange 接触
*/
public findTouchesRange(sameRange: LineRange): LineRange | undefined {
const values = this.adjacentComputeRangeMap.values();

for (const range of values) {
if (range.isAfter(sameRange)) {
if (range.isTouches(sameRange)) {
return range;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ import { EditorViewType, IRangeContrast, LineRangeType } from '../types';
import { InnerRange } from './inner-range';

export class LineRange extends MonacoLineRange implements IRangeContrast {
static fromPositions(startLineNumber: number, endLineNumber: number = startLineNumber): LineRange {
return new LineRange(startLineNumber, endLineNumber);
}

private _id: string;
public get id(): string {
return this._id;
}

private _type: LineRangeType;
public get type(): LineRangeType {
return this._type;
Expand All @@ -24,6 +33,13 @@ export class LineRange extends MonacoLineRange implements IRangeContrast {
constructor(startLineNumber: number, endLineNumberExclusive: number) {
super(startLineNumber, endLineNumberExclusive);
this._type = 'insert';
this._isComplete = false;
this._id = `${this.startLineNumber}_${this.endLineNumberExclusive}_${this.length}`;
}

private setId(id: string): this {
this._id = id;
return this;
}

public setTurnDirection(t: EditorViewType.CURRENT | EditorViewType.INCOMING) {
Expand All @@ -41,10 +57,6 @@ export class LineRange extends MonacoLineRange implements IRangeContrast {
return this;
}

public get id(): string {
return `${this.startLineNumber}_${this.endLineNumberExclusive}_${this.length}`;
}

public calcMargin(range: LineRange): number {
return this.length - range.length;
}
Expand Down Expand Up @@ -98,15 +110,23 @@ export class LineRange extends MonacoLineRange implements IRangeContrast {
).setType(this._type);
}

private retainState(range: LineRange): LineRange {
return range
.setId(this._id)
.setType(this._type)
.setTurnDirection(this._turnDirection)
.setComplete(this._isComplete);
}

public override delta(offset: number): LineRange {
return new LineRange(this.startLineNumber + offset, this.endLineNumberExclusive + offset).setType(this._type);
return this.retainState(new LineRange(this.startLineNumber + offset, this.endLineNumberExclusive + offset));
}

public deltaStart(offset: number): LineRange {
return new LineRange(this.startLineNumber + offset, this.endLineNumberExclusive).setType(this._type);
return this.retainState(new LineRange(this.startLineNumber + offset, this.endLineNumberExclusive));
}

public deltaEnd(offset: number): LineRange {
return new LineRange(this.startLineNumber, this.endLineNumberExclusive + offset).setType(this._type);
return this.retainState(new LineRange(this.startLineNumber, this.endLineNumberExclusive + offset));
}
}
Loading