Skip to content

Commit eb7f068

Browse files
authored
Improves NES jump to widget (#279990)
1 parent d3100a7 commit eb7f068

File tree

11 files changed

+354
-113
lines changed

11 files changed

+354
-113
lines changed

src/vs/editor/browser/editorBrowser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,8 @@ export interface ICodeEditor extends editorCommon.IEditor {
12031203
*/
12041204
getOffsetForColumn(lineNumber: number, column: number): number;
12051205

1206+
getWidthOfLine(lineNumber: number): number;
1207+
12061208
/**
12071209
* Force an editor render now.
12081210
*/

src/vs/editor/browser/view.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,15 @@ export class View extends ViewEventHandler {
652652
return visibleRange.left;
653653
}
654654

655+
public getLineWidth(modelLineNumber: number): number {
656+
const model = this._context.viewModel.model;
657+
const viewLine = this._context.viewModel.coordinatesConverter.convertModelPositionToViewPosition(new Position(modelLineNumber, model.getLineMaxColumn(modelLineNumber))).lineNumber;
658+
this._flushAccumulatedAndRenderNow();
659+
const width = this._viewLines.getLineWidth(viewLine);
660+
661+
return width;
662+
}
663+
655664
public getTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget | null {
656665
const mouseTarget = this._pointerHandler.getTargetAtClientPoint(clientX, clientY);
657666
if (!mouseTarget) {

src/vs/editor/browser/widget/codeEditor/codeEditorWidget.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,13 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
16731673
return this._modelData.view.getOffsetForColumn(lineNumber, column);
16741674
}
16751675

1676+
public getWidthOfLine(lineNumber: number): number {
1677+
if (!this._modelData || !this._modelData.hasRealView) {
1678+
return -1;
1679+
}
1680+
return this._modelData.view.getLineWidth(lineNumber);
1681+
}
1682+
16761683
public render(forceRedraw: boolean = false): void {
16771684
if (!this._modelData || !this._modelData.hasRealView) {
16781685
return;

src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,11 @@ export class InlineCompletionsModel extends Disposable {
811811
return false;
812812
}
813813

814+
815+
if (s.inlineSuggestion.action?.kind === 'jumpTo') {
816+
return true;
817+
}
818+
814819
if (this.showCollapsed.read(reader)) {
815820
return true;
816821
}
@@ -827,6 +832,9 @@ export class InlineCompletionsModel extends Disposable {
827832
if (!s) {
828833
return false;
829834
}
835+
if (s.inlineSuggestion.action?.kind === 'jumpTo') {
836+
return false;
837+
}
830838
if (this.showCollapsed.read(reader)) {
831839
return false;
832840
}
@@ -1116,26 +1124,37 @@ export class InlineCompletionsModel extends Disposable {
11161124
const s = this.inlineEditState.get();
11171125
if (!s) { return; }
11181126

1119-
transaction(tx => {
1120-
this._jumpedToId.set(s.inlineSuggestion.semanticId, tx);
1121-
this.dontRefetchSignal.trigger(tx);
1122-
const targetRange = s.inlineSuggestion.targetRange;
1123-
const targetPosition = targetRange.getStartPosition();
1124-
this._editor.setPosition(targetPosition, 'inlineCompletions.jump');
1125-
1126-
// TODO: consider using view information to reveal it
1127-
const isSingleLineChange = targetRange.isSingleLine() && (s.inlineSuggestion.hint || (s.inlineSuggestion.action?.kind === 'edit' && !s.inlineSuggestion.action.textReplacement.text.includes('\n')));
1128-
if (isSingleLineChange) {
1129-
this._editor.revealPosition(targetPosition, ScrollType.Smooth);
1130-
} else {
1131-
const revealRange = new Range(targetRange.startLineNumber - 1, 1, targetRange.endLineNumber + 1, 1);
1132-
this._editor.revealRange(revealRange, ScrollType.Smooth);
1133-
}
1127+
const suggestion = s.inlineSuggestion;
1128+
suggestion.addRef();
1129+
try {
1130+
transaction(tx => {
1131+
if (suggestion.action?.kind === 'jumpTo') {
1132+
this.stop(undefined, tx);
1133+
suggestion.reportEndOfLife({ kind: InlineCompletionEndOfLifeReasonKind.Accepted });
1134+
}
11341135

1135-
s.inlineSuggestion.identity.setJumpTo(tx);
1136+
this._jumpedToId.set(s.inlineSuggestion.semanticId, tx);
1137+
this.dontRefetchSignal.trigger(tx);
1138+
const targetRange = s.inlineSuggestion.targetRange;
1139+
const targetPosition = targetRange.getStartPosition();
1140+
this._editor.setPosition(targetPosition, 'inlineCompletions.jump');
11361141

1137-
this._editor.focus();
1138-
});
1142+
// TODO: consider using view information to reveal it
1143+
const isSingleLineChange = targetRange.isSingleLine() && (s.inlineSuggestion.hint || (s.inlineSuggestion.action?.kind === 'edit' && !s.inlineSuggestion.action.textReplacement.text.includes('\n')));
1144+
if (isSingleLineChange || s.inlineSuggestion.action?.kind === 'jumpTo') {
1145+
this._editor.revealPosition(targetPosition, ScrollType.Smooth);
1146+
} else {
1147+
const revealRange = new Range(targetRange.startLineNumber - 1, 1, targetRange.endLineNumber + 1, 1);
1148+
this._editor.revealRange(revealRange, ScrollType.Smooth);
1149+
}
1150+
1151+
s.inlineSuggestion.identity.setJumpTo(tx);
1152+
1153+
this._editor.focus();
1154+
});
1155+
} finally {
1156+
suggestion.removeRef();
1157+
}
11391158
}
11401159

11411160
public async handleInlineSuggestionShown(inlineCompletion: InlineSuggestionItem, viewKind: InlineCompletionViewKind, viewData: InlineCompletionViewData): Promise<void> {

src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsView.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class InlineEditsView extends Disposable {
6262
private readonly _editor: ICodeEditor,
6363
private readonly _model: IObservable<ModelPerInlineEdit | undefined>,
6464
private readonly _simpleModel: IObservable<SimpleInlineSuggestModel | undefined>,
65-
private readonly _suggestInfo: IObservable<InlineSuggestionGutterMenuData | undefined>,
65+
private readonly _inlineSuggestInfo: IObservable<InlineSuggestionGutterMenuData | undefined>,
6666
private readonly _showCollapsed: IObservable<boolean>,
6767

6868
@IInstantiationService private readonly _instantiationService: IInstantiationService
@@ -133,7 +133,8 @@ export class InlineEditsView extends Disposable {
133133
edit: s.edit,
134134
diff: s.diff,
135135
model: this._simpleModel.read(reader)!,
136-
suggestInfo: this._suggestInfo.read(reader)!,
136+
inlineSuggestInfo: this._inlineSuggestInfo.read(reader)!,
137+
nextCursorPosition: s.nextCursorPosition,
137138
}) : undefined),
138139
this._previewTextModel,
139140
this._tabAction,
@@ -156,7 +157,7 @@ export class InlineEditsView extends Disposable {
156157
};
157158
});
158159
this._inlineDiffView = this._register(new OriginalEditorInlineDiffView(this._editor, this._inlineDiffViewState, this._previewTextModel));
159-
this._jumpToView = this._register(this._instantiationService.createInstance(JumpToView, this._editorObs, derived(reader => {
160+
this._jumpToView = this._register(this._instantiationService.createInstance(JumpToView, this._editorObs, { style: 'label' }, derived(reader => {
160161
const s = this._uiState.read(reader);
161162
if (s?.state?.kind === InlineCompletionViewKind.JumpTo) {
162163
return { jumpToPosition: s.state.position };
@@ -278,7 +279,7 @@ export class InlineEditsView extends Disposable {
278279
if (model.inlineEdit.inlineCompletion.identity.jumpedTo.read(reader)) {
279280
return undefined;
280281
}
281-
if (model.inlineEdit.action?.kind !== 'edit') {
282+
if (model.inlineEdit.action === undefined) {
282283
return undefined;
283284
}
284285
if (this._currentInlineEditCache?.inlineSuggestionIdentity !== model.inlineEdit.inlineCompletion.identity) {
@@ -303,6 +304,7 @@ export class InlineEditsView extends Disposable {
303304
newTextLineCount: number;
304305
isInDiffEditor: boolean;
305306
longDistanceHint: ILongDistanceHint | undefined;
307+
nextCursorPosition: Position | null;
306308
} | undefined>(this, reader => {
307309
const model = this._model.read(reader);
308310
const textModel = this._editorObs.model.read(reader);
@@ -369,6 +371,8 @@ export class InlineEditsView extends Disposable {
369371

370372
model.handleInlineEditShown(state.kind, state.viewData); // call this in the next animation frame
371373

374+
const nextCursorPosition = inlineEdit.action?.kind === 'jumpTo' ? inlineEdit.action.position : null;
375+
372376
return {
373377
state,
374378
diff,
@@ -377,6 +381,7 @@ export class InlineEditsView extends Disposable {
377381
newTextLineCount: inlineEdit.modifiedLineRange.length,
378382
isInDiffEditor: model.isInDiffEditor,
379383
longDistanceHint,
384+
nextCursorPosition: nextCursorPosition,
380385
};
381386
});
382387

0 commit comments

Comments
 (0)