Skip to content

Commit c003e4f

Browse files
committed
feat: line-change of code edits adds change parameter
1 parent 5530a45 commit c003e4f

2 files changed

Lines changed: 79 additions & 26 deletions

File tree

packages/ai-native/src/browser/contrib/intelligent-completions/source/base.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ export abstract class BaseCodeEditsSource extends Disposable {
6969
private cancellationTokenSource = new CancellationTokenSource();
7070
private readonly relationID = observableValue<string | undefined>(this, undefined);
7171

72-
protected abstract doTrigger(...args: any[]): MaybePromise<void>;
73-
7472
public readonly codeEditsContextBean = disposableObservableValue<CodeEditsContextBean | undefined>(this, undefined);
7573
public abstract priority: number;
7674
public abstract mount(): IDisposable;
Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,102 @@
11
import { Injectable } from '@opensumi/di';
22
import { AINativeSettingSectionsId, ECodeEditsSourceTyping, IDisposable } from '@opensumi/ide-core-common';
3-
import { ICursorPositionChangedEvent, Position } from '@opensumi/ide-monaco';
3+
import { ICursorPositionChangedEvent, IModelContentChangedEvent } from '@opensumi/ide-monaco';
4+
import {
5+
autorunDelta,
6+
derivedHandleChanges,
7+
observableFromEvent,
8+
recomputeInitiallyAndOnChange,
9+
} from '@opensumi/ide-monaco/lib/common/observable';
410

511
import { BaseCodeEditsSource } from './base';
612

713
export interface ILineChangeData {
814
currentLineNumber: number;
915
preLineNumber?: number;
16+
change?: IModelContentChangedEvent;
1017
}
1118

1219
@Injectable({ multiple: true })
1320
export class LineChangeCodeEditsSource extends BaseCodeEditsSource {
1421
public priority = 2;
1522

16-
private prePosition = this.monacoEditor.getPosition();
17-
1823
public mount(): IDisposable {
24+
const modelContentChangeObs = observableFromEvent<IModelContentChangedEvent>(
25+
this,
26+
this.monacoEditor.onDidChangeModelContent,
27+
(event: IModelContentChangedEvent) => event,
28+
);
29+
const positionChangeObs = observableFromEvent<ICursorPositionChangedEvent>(
30+
this,
31+
this.monacoEditor.onDidChangeCursorPosition,
32+
(event: ICursorPositionChangedEvent) => event,
33+
);
34+
35+
const latestModelContentChangeObs = derivedHandleChanges(
36+
{
37+
owner: this,
38+
createEmptyChangeSummary: () => ({ change: undefined }),
39+
handleChange: (ctx, changeSummary: { change: IModelContentChangedEvent | undefined }) => {
40+
// 如果只是改了光标则设置 change 为空,避免获取到缓存的 change
41+
if (ctx.didChange(positionChangeObs)) {
42+
changeSummary.change = undefined;
43+
} else {
44+
changeSummary.change = modelContentChangeObs.get();
45+
}
46+
return true;
47+
},
48+
},
49+
(reader, changeSummary) => {
50+
positionChangeObs.read(reader);
51+
modelContentChangeObs.read(reader);
52+
return changeSummary.change;
53+
},
54+
);
55+
56+
this.addDispose(recomputeInitiallyAndOnChange(latestModelContentChangeObs));
57+
58+
let lastModelContent: IModelContentChangedEvent | undefined;
1959
this.addDispose(
20-
this.monacoEditor.onDidChangeCursorPosition((event: ICursorPositionChangedEvent) => {
21-
const currentPosition = event.position;
22-
if (this.prePosition && this.prePosition.lineNumber !== currentPosition.lineNumber) {
23-
this.doTrigger(currentPosition);
24-
this.prePosition = currentPosition;
25-
}
60+
/**
61+
* 由于 monaco 的 changeModelContent 事件比 changeCursorPosition 事件先触发,所以这里需要拿上一次的值进行消费
62+
* 否则永远返回 undefined
63+
*/
64+
autorunDelta(latestModelContentChangeObs, ({ lastValue }) => {
65+
lastModelContent = lastValue;
2666
}),
2767
);
28-
return this;
29-
}
3068

31-
protected doTrigger(position: Position) {
32-
const isLineChangeEnabled = this.preferenceService.getValid(AINativeSettingSectionsId.CodeEditsLineChange, false);
69+
this.addDispose(
70+
autorunDelta(positionChangeObs, ({ lastValue, newValue }) => {
71+
const contentChange = lastModelContent;
3372

34-
if (!isLineChangeEnabled || !position) {
35-
return;
36-
}
73+
const isLineChangeEnabled = this.preferenceService.getValid(
74+
AINativeSettingSectionsId.CodeEditsLineChange,
75+
false,
76+
);
77+
if (!isLineChangeEnabled) {
78+
return false;
79+
}
3780

38-
this.setBean({
39-
typing: ECodeEditsSourceTyping.LineChange,
40-
position,
41-
data: {
42-
preLineNumber: this.prePosition?.lineNumber,
43-
currentLineNumber: position.lineNumber,
44-
},
45-
});
81+
const prePosition = lastValue?.position;
82+
const currentPosition = newValue?.position;
83+
if (prePosition && prePosition.lineNumber !== currentPosition?.lineNumber) {
84+
this.setBean({
85+
typing: ECodeEditsSourceTyping.LineChange,
86+
position: currentPosition,
87+
data: {
88+
preLineNumber: prePosition.lineNumber,
89+
currentLineNumber: currentPosition.lineNumber,
90+
change: contentChange,
91+
},
92+
});
93+
}
94+
95+
// 消费完之后设置为 undefined,避免下次获取到缓存的值
96+
lastModelContent = undefined;
97+
}),
98+
);
99+
100+
return this;
46101
}
47102
}

0 commit comments

Comments
 (0)