Skip to content

Commit

Permalink
feat: optimize inline diff viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
bytemain committed Jul 5, 2024
1 parent 4b9caae commit ada2e26
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 21 deletions.
4 changes: 4 additions & 0 deletions packages/ai-native/src/browser/ai-core.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
AI_NATIVE_SETTING_GROUP_TITLE,
ChatFeatureRegistryToken,
ChatRenderRegistryToken,
ChatResponse,
CommandService,
InlineChatFeatureRegistryToken,
RenameCandidatesProviderRegistryToken,
Expand All @@ -56,6 +57,7 @@ import { IEditor } from '@opensumi/ide-editor';
import { BrowserEditorContribution, IEditorFeatureRegistry } from '@opensumi/ide-editor/lib/browser';
import { IMainLayoutService } from '@opensumi/ide-main-layout';
import { Position } from '@opensumi/ide-monaco';
import * as monaco from '@opensumi/ide-monaco';
import { ISettingRegistry, SettingContribution } from '@opensumi/ide-preferences';
import { EditorContributionInstantiation } from '@opensumi/monaco-editor-core/esm/vs/editor/browser/editorExtensions';
import { HideInlineCompletion } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/commands';
Expand Down Expand Up @@ -88,7 +90,9 @@ import {
IResolveConflictRegistry,
ITerminalProviderRegistry,
} from './types';
import { InlineChatController } from './widget/inline-chat/inline-chat-controller';
import { InlineChatFeatureRegistry } from './widget/inline-chat/inline-chat.feature.registry';
import { InlineChatHandler } from './widget/inline-chat/inline-chat.handler';
import { AIInlineChatService } from './widget/inline-chat/inline-chat.service';
import { InlineInputChatService } from './widget/inline-input/inline-input.service';
import { InlineStreamDiffService } from './widget/inline-stream-diff/inline-stream-diff.service';
Expand Down
6 changes: 3 additions & 3 deletions packages/ai-native/src/browser/preferences/schema.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AINativeSettingSectionsId, PreferenceSchema } from '@opensumi/ide-core-browser';
import { localize } from '@opensumi/ide-core-common';

export enum EInlineDifPreviewMode {
export enum EInlineDiffPreviewMode {
inlineLive = 'inlineLive',
sideBySide = 'sideBySide',
}
Expand All @@ -10,12 +10,12 @@ export const aiNativePreferenceSchema: PreferenceSchema = {
properties: {
[AINativeSettingSectionsId.InlineDiffPreviewMode]: {
type: 'string',
enum: [EInlineDifPreviewMode.inlineLive, EInlineDifPreviewMode.sideBySide],
enum: [EInlineDiffPreviewMode.inlineLive, EInlineDiffPreviewMode.sideBySide],
enumDescriptions: [
localize('preference.ai.native.inlineDiff.preview.mode.inlineLive'),
localize('preference.ai.native.inlineDiff.preview.mode.sideBySide'),
],
default: EInlineDifPreviewMode.inlineLive,
default: EInlineDiffPreviewMode.inlineLive,
},
[AINativeSettingSectionsId.InlineChatAutoVisible]: {
type: 'boolean',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { monacoApi } from '@opensumi/ide-monaco/lib/browser/monaco-api';
import { ContentWidgetPositionPreference } from '@opensumi/ide-monaco/lib/browser/monaco-exports/editor';

import { CodeActionService } from '../../contrib/code-action/code-action.service';
import { EInlineDifPreviewMode } from '../../preferences/schema';
import { EInlineDiffPreviewMode } from '../../preferences/schema';
import { ERunStrategy } from '../../types';
import {
BaseInlineDiffPreviewer,
Expand Down Expand Up @@ -310,7 +310,7 @@ export class InlineChatHandler extends Disposable {
});
}

private visibleDiffWidget(
visibleDiffWidget(
monacoEditor: monaco.ICodeEditor,
options: {
crossSelection: monaco.Selection;
Expand All @@ -325,12 +325,12 @@ export class InlineChatHandler extends Disposable {
const { crossSelection, chatResponse } = options;
const { relationId, startTime, isRetry } = reportInfo;

const inlineDiffMode = this.preferenceService.getValid<EInlineDifPreviewMode>(
const inlineDiffMode = this.preferenceService.getValid<EInlineDiffPreviewMode>(
AINativeSettingSectionsId.InlineDiffPreviewMode,
EInlineDifPreviewMode.inlineLive,
EInlineDiffPreviewMode.inlineLive,
);

if (inlineDiffMode === EInlineDifPreviewMode.sideBySide) {
if (inlineDiffMode === EInlineDiffPreviewMode.sideBySide) {
this.diffPreviewer = this.injector.get(SideBySideInlineDiffWidget, [monacoEditor, crossSelection]);
} else {
this.diffPreviewer = this.injector.get(LiveInlineDiffPreviewer, [monacoEditor, crossSelection]);
Expand All @@ -342,7 +342,7 @@ export class InlineChatHandler extends Disposable {
);

const doLayoutContentWidget = () => {
if (inlineDiffMode === EInlineDifPreviewMode.sideBySide) {
if (inlineDiffMode === EInlineDiffPreviewMode.sideBySide) {
this.aiInlineContentWidget.setPositionPreference([ContentWidgetPositionPreference.BELOW]);
} else {
this.aiInlineContentWidget.setPositionPreference([ContentWidgetPositionPreference.EXACT]);
Expand Down Expand Up @@ -455,6 +455,18 @@ export class InlineChatHandler extends Disposable {
);
}

get onPartialEditEvent() {
return (this.diffPreviewer as LiveInlineDiffPreviewer).onPartialEditEvent;
}

accpetAllPartialEdits() {
this.diffPreviewer.handleAction(EResultKind.ACCEPT);
}

discardAllPartialEdits() {
this.diffPreviewer.handleAction(EResultKind.DISCARD);
}

private async handleDiffPreviewStrategy(
monacoEditor: monaco.ICodeEditor,
strategy: (...arg: any[]) => MaybePromise<ChatResponse | InlineChatController>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Autowired, INJECTOR_TOKEN, Injectable, Injector } from '@opensumi/di';
import { Disposable, ErrorResponse, ReplyResponse } from '@opensumi/ide-core-common';
import { Disposable, ErrorResponse, IDisposable, ReplyResponse } from '@opensumi/ide-core-common';
import { EOL, ICodeEditor, IPosition, ITextModel, Position, Selection } from '@opensumi/ide-monaco';
import { LineRange } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/lineRange';
import { DefaultEndOfLine } from '@opensumi/monaco-editor-core/esm/vs/editor/common/model';
Expand Down Expand Up @@ -158,6 +158,7 @@ export class LiveInlineDiffPreviewer extends BaseInlineDiffPreviewer<InlineStrea
const zone = this.node.getZone();
return Position.lift({ lineNumber: Math.max(0, zone.startLineNumber - 1), column: 1 });
}

handleAction(action: EResultKind): void {
switch (action) {
case EResultKind.ACCEPT:
Expand All @@ -182,14 +183,10 @@ export class LiveInlineDiffPreviewer extends BaseInlineDiffPreviewer<InlineStrea
this.node.addLinesToDiff(message);
}
onEnd(): void {
const { changes } = this.node.recompute(EComputerMode.legacy);
const zone = this.node.getZone();
const allAddRanges = changes.map((c) => {
const lineNumber = zone.startLineNumber + c.addedRange.startLineNumber - 1;
return new LineRange(lineNumber, lineNumber + 1);
});
this.node.renderPartialEditWidgets(allAddRanges);
this.node.pushStackElement();
this.node.end();
this.monacoEditor.focus();
}
get onPartialEditEvent() {
return this.node.onPartialEditEvent;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class InlineStreamDiffHandler extends Disposable {

private undoRedoGroup: UndoRedoGroup;

protected readonly _onDidEditChange = new Emitter<void>();
protected readonly _onDidEditChange = this.registerDispose(new Emitter<void>());
public readonly onDidEditChange: Event<void> = this._onDidEditChange.event;

constructor(private readonly monacoEditor: ICodeEditor, private readonly selection: Selection) {
Expand Down Expand Up @@ -350,4 +350,22 @@ export class InlineStreamDiffHandler extends Disposable {

return diffModel;
}

end() {
this.recompute(EComputerMode.legacy);

const { changes } = this.currentDiffModel;
const zone = this.getZone();

const allAddRanges = changes.map((c) => {
const lineNumber = zone.startLineNumber + c.addedRange.startLineNumber - 1;
return new LineRange(lineNumber, lineNumber + 1);
});
this.renderPartialEditWidgets(allAddRanges);
this.pushStackElement();
}

get onPartialEditEvent() {
return this.livePreviewDiffDecorationModel.onPartialEditEvent;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,40 @@ enum EPartialEdit {
discard = 'discard',
}

export interface IPartialEditEvent {
/**
* 总 diff 数
*/
totalPartialEditCount: number;
/**
* 已采纳数
*/
acceptedPartialEditCount: number;

/**
* 已添加行数
*/
totalAddedLinesCount: number;
/**
* 已删除行数
*/
totalRemovedLinesCount: number;
/**
* 当前冲突信息
*/
currentPartialEdit: {
type: EPartialEdit;
deletedLinesCount: number;
addedLinesCount: number;
original: {
range: IRange;
};
modified: {
range: IRange;
};
};
}

@Injectable({ multiple: true })
class AcceptPartialEditWidget extends ReactInlineContentWidget {
static ID = 'AcceptPartialEditWidgetID';
Expand All @@ -64,10 +98,10 @@ class AcceptPartialEditWidget extends ReactInlineContentWidget {
private _id: string;
private _decorationId: string;

private readonly _onAccept = new Emitter<void>();
private readonly _onAccept = this.registerDispose(new Emitter<void>());
public readonly onAccept: Event<void> = this._onAccept.event;

private readonly _onDiscard = new Emitter<void>();
private readonly _onDiscard = this.registerDispose(new Emitter<void>());
public readonly onDiscard: Event<void> = this._onDiscard.event;

positionPreference = [ContentWidgetPositionPreference.EXACT];
Expand Down Expand Up @@ -191,6 +225,9 @@ export class LivePreviewDiffDecorationModel extends Disposable {
@Autowired(InlineStreamDiffService)
private readonly inlineStreamDiffService: InlineStreamDiffService;

private readonly _onPartialEditEvent = this.registerDispose(new Emitter<IPartialEditEvent>());
public readonly onPartialEditEvent: Event<IPartialEditEvent> = this._onPartialEditEvent.event;

private zoneDec: IEditorDecorationsCollection;

private activeLineDec: IEditorDecorationsCollection;
Expand Down Expand Up @@ -426,6 +463,34 @@ export class LivePreviewDiffDecorationModel extends Disposable {
findRemovedWidget?.resume();
};

const event: IPartialEditEvent = {
totalPartialEditCount: this.partialEditWidgetList.length,
acceptedPartialEditCount: this.partialEditWidgetList.filter((w) => w.isHidden).length,
totalAddedLinesCount: 0,
totalRemovedLinesCount: 0,
currentPartialEdit: {
addedLinesCount: 0,
deletedLinesCount: 0,
modified: {
range: {
endColumn: 0,
endLineNumber: 0,
startColumn: 0,
startLineNumber: 0,
},
},
original: {
range: {
endColumn: 0,
endLineNumber: 0,
startColumn: 0,
startLineNumber: 0,
},
},
type,
},
};

/**
* 将 partial widget 的所有操作和代码变更放在单独的 undo/redo 堆栈组里面
*/
Expand Down Expand Up @@ -460,6 +525,8 @@ export class LivePreviewDiffDecorationModel extends Disposable {
}

this.monacoEditor.focus();

this._onPartialEditEvent.fire(event);
}

/**
Expand Down

0 comments on commit ada2e26

Please sign in to comment.