Skip to content

Commit ce7b68b

Browse files
authored
Typing in a comment, switching editors and switching back will not restore the cursor position in the comment box (microsoft#230466)
Fixes microsoft#229214
1 parent 83e4461 commit ce7b68b

File tree

8 files changed

+72
-54
lines changed

8 files changed

+72
-54
lines changed

src/vs/editor/common/languages.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -2001,11 +2001,16 @@ export interface Comment {
20012001
}
20022002

20032003
export interface PendingCommentThread {
2004-
body: string;
20052004
range: IRange | undefined;
20062005
uri: URI;
20072006
uniqueOwner: string;
20082007
isReply: boolean;
2008+
comment: PendingComment;
2009+
}
2010+
2011+
export interface PendingComment {
2012+
body: string;
2013+
cursor: IPosition;
20092014
}
20102015

20112016
/**

src/vs/monaco.d.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -7999,11 +7999,16 @@ declare namespace monaco.languages {
79997999
}
80008000

80018001
export interface PendingCommentThread {
8002-
body: string;
80038002
range: IRange | undefined;
80048003
uri: Uri;
80058004
uniqueOwner: string;
80068005
isReply: boolean;
8006+
comment: PendingComment;
8007+
}
8008+
8009+
export interface PendingComment {
8010+
body: string;
8011+
cursor: IPosition;
80078012
}
80088013

80098014
export interface CodeLens {

src/vs/workbench/contrib/comments/browser/commentNode.ts

+13-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { MarkdownRenderer } from '../../../../editor/browser/widget/markdownRend
1414
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
1515
import { ICommentService } from './commentService.js';
1616
import { LayoutableEditor, MIN_EDITOR_HEIGHT, SimpleCommentEditor, calculateEditorHeight } from './simpleCommentEditor.js';
17-
import { Selection } from '../../../../editor/common/core/selection.js';
1817
import { Emitter, Event } from '../../../../base/common/event.js';
1918
import { INotificationService } from '../../../../platform/notification/common/notification.js';
2019
import { ToolBar } from '../../../../base/browser/ui/toolbar/toolbar.js';
@@ -50,6 +49,7 @@ import { IKeybindingService } from '../../../../platform/keybinding/common/keybi
5049
import { MarshalledCommentThread } from '../../../common/comments.js';
5150
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
5251
import { IResolvedTextEditorModel, ITextModelService } from '../../../../editor/common/services/resolverService.js';
52+
import { Position } from '../../../../editor/common/core/position.js';
5353

5454
class CommentsActionRunner extends ActionRunner {
5555
protected override async runAction(action: IAction, context: any[]): Promise<void> {
@@ -103,7 +103,7 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
103103
private readonly parentEditor: LayoutableEditor,
104104
private commentThread: languages.CommentThread<T>,
105105
public comment: languages.Comment,
106-
private pendingEdit: string | undefined,
106+
private pendingEdit: languages.PendingComment | undefined,
107107
private owner: string,
108108
private resource: URI,
109109
private parentThread: ICommentThreadWidget,
@@ -503,7 +503,14 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
503503
this._commentEditorModel = modelRef;
504504

505505
this._commentEditor.setModel(this._commentEditorModel.object.textEditorModel);
506-
this._commentEditor.setValue(this.pendingEdit ?? this.commentBodyValue);
506+
this._commentEditor.setValue(this.pendingEdit?.body ?? this.commentBodyValue);
507+
if (this.pendingEdit) {
508+
this._commentEditor.setPosition(this.pendingEdit.cursor);
509+
} else {
510+
const lastLine = this._commentEditorModel.object.textEditorModel.getLineCount();
511+
const lastColumn = this._commentEditorModel.object.textEditorModel.getLineLength(lastLine) + 1;
512+
this._commentEditor.setPosition(new Position(lastLine, lastColumn));
513+
}
507514
this.pendingEdit = undefined;
508515
this._commentEditor.layout({ width: container.clientWidth - 14, height: this._editorHeight });
509516
this._commentEditor.focus();
@@ -513,10 +520,6 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
513520
this._commentEditor!.focus();
514521
});
515522

516-
const lastLine = this._commentEditorModel.object.textEditorModel.getLineCount();
517-
const lastColumn = this._commentEditorModel.object.textEditorModel.getLineLength(lastLine) + 1;
518-
this._commentEditor.setSelection(new Selection(lastLine, lastColumn, lastLine, lastColumn));
519-
520523
const commentThread = this.commentThread;
521524
commentThread.input = {
522525
uri: this._commentEditor.getModel()!.uri,
@@ -571,10 +574,10 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
571574
return false;
572575
}
573576

574-
getPendingEdit(): string | undefined {
577+
getPendingEdit(): languages.PendingComment | undefined {
575578
const model = this._commentEditor?.getModel();
576-
if (model && model.getValueLength() > 0) {
577-
return model.getValue();
579+
if (this._commentEditor && model && model.getValueLength() > 0) {
580+
return { body: model.getValue(), cursor: this._commentEditor.getPosition()! };
578581
}
579582
return undefined;
580583
}

src/vs/workbench/contrib/comments/browser/commentReply.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { ICellRange } from '../../notebook/common/notebookRange.js';
3131
import { LayoutableEditor, MIN_EDITOR_HEIGHT, SimpleCommentEditor, calculateEditorHeight } from './simpleCommentEditor.js';
3232
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
3333
import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js';
34+
import { Position } from '../../../../editor/common/core/position.js';
3435

3536
let INMEM_MODEL_ID = 0;
3637
export const COMMENTEDITOR_DECORATION_KEY = 'commenteditordecoration';
@@ -57,7 +58,7 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {
5758
private _contextKeyService: IContextKeyService,
5859
private _commentMenus: CommentMenus,
5960
private _commentOptions: languages.CommentOptions | undefined,
60-
private _pendingComment: string | undefined,
61+
private _pendingComment: languages.PendingComment | undefined,
6162
private _parentThread: ICommentThreadWidget,
6263
focus: boolean,
6364
private _actionRunDelegate: (() => void) | null,
@@ -96,10 +97,13 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {
9697
}
9798

9899
const model = await this.textModelService.createModelReference(resource);
99-
model.object.textEditorModel.setValue(this._pendingComment || '');
100+
model.object.textEditorModel.setValue(this._pendingComment?.body || '');
100101

101102
this._register(model);
102103
this.commentEditor.setModel(model.object.textEditorModel);
104+
if (this._pendingComment) {
105+
this.commentEditor.setPosition(this._pendingComment.cursor);
106+
}
103107
this.calculateEditorHeight();
104108

105109
this._register(model.object.textEditorModel.onDidChangeContent(() => {
@@ -157,20 +161,21 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {
157161
}
158162
}
159163

160-
public getPendingComment(): string | undefined {
164+
public getPendingComment(): languages.PendingComment | undefined {
161165
const model = this.commentEditor.getModel();
162166

163167
if (model && model.getValueLength() > 0) { // checking length is cheap
164-
return model.getValue();
168+
return { body: model.getValue(), cursor: this.commentEditor.getPosition() ?? new Position(1, 1) };
165169
}
166170

167171
return undefined;
168172
}
169173

170-
public setPendingComment(comment: string) {
171-
this._pendingComment = comment;
174+
public setPendingComment(pending: languages.PendingComment) {
175+
this._pendingComment = pending;
172176
this.expandReplyArea();
173-
this.commentEditor.setValue(comment);
177+
this.commentEditor.setValue(pending.body);
178+
this.commentEditor.setPosition(pending.cursor);
174179
}
175180

176181
public layout(widthInPixel: number) {
@@ -254,7 +259,7 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {
254259
commentEditor.setValue(input.value);
255260

256261
if (input.value === '') {
257-
this._pendingComment = '';
262+
this._pendingComment = { body: '', cursor: new Position(1, 1) };
258263
commentForm.classList.remove('expand');
259264
commentEditor.getDomNode()!.style.outline = '';
260265
this._error.textContent = '';
@@ -339,7 +344,7 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {
339344
domNode.style.outline = '';
340345
}
341346
this.commentEditor.setValue('');
342-
this._pendingComment = '';
347+
this._pendingComment = { body: '', cursor: new Position(1, 1) };
343348
this.form.classList.remove('expand');
344349
this._error.textContent = '';
345350
this._error.classList.add('hidden');

src/vs/workbench/contrib/comments/browser/commentThreadBody.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class CommentThreadBody<T extends IRange | ICellRange = IRange> extends D
4949
readonly container: HTMLElement,
5050
private _options: IMarkdownRendererOptions,
5151
private _commentThread: languages.CommentThread<T>,
52-
private _pendingEdits: { [key: number]: string } | undefined,
52+
private _pendingEdits: { [key: number]: languages.PendingComment } | undefined,
5353
private _scopedInstatiationService: IInstantiationService,
5454
private _parentCommentThreadWidget: ICommentThreadWidget,
5555
@ICommentService private commentService: ICommentService,
@@ -142,8 +142,8 @@ export class CommentThreadBody<T extends IRange | ICellRange = IRange> extends D
142142
});
143143
}
144144

145-
getPendingEdits(): { [key: number]: string } {
146-
const pendingEdits: { [key: number]: string } = {};
145+
getPendingEdits(): { [key: number]: languages.PendingComment } {
146+
const pendingEdits: { [key: number]: languages.PendingComment } = {};
147147
this._commentElements.forEach(element => {
148148
if (element.isEditing) {
149149
const pendingEdit = element.getPendingEdit();

src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
6868
private _contextKeyService: IContextKeyService,
6969
private _scopedInstantiationService: IInstantiationService,
7070
private _commentThread: languages.CommentThread<T>,
71-
private _pendingComment: string | undefined,
72-
private _pendingEdits: { [key: number]: string } | undefined,
71+
private _pendingComment: languages.PendingComment | undefined,
72+
private _pendingEdits: { [key: number]: languages.PendingComment } | undefined,
7373
private _markdownOptions: IMarkdownRendererOptions,
7474
private _commentOptions: languages.CommentOptions | undefined,
7575
private _containerDelegate: {
@@ -333,21 +333,21 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
333333
return this._body.getCommentCoords(commentUniqueId);
334334
}
335335

336-
getPendingEdits(): { [key: number]: string } {
336+
getPendingEdits(): { [key: number]: languages.PendingComment } {
337337
return this._body.getPendingEdits();
338338
}
339339

340-
getPendingComment(): string | undefined {
340+
getPendingComment(): languages.PendingComment | undefined {
341341
if (this._commentReply) {
342342
return this._commentReply.getPendingComment();
343343
}
344344

345345
return undefined;
346346
}
347347

348-
setPendingComment(comment: string) {
349-
this._pendingComment = comment;
350-
this._commentReply?.setPendingComment(comment);
348+
setPendingComment(pending: languages.PendingComment) {
349+
this._pendingComment = pending;
350+
this._commentReply?.setPendingComment(pending);
351351
}
352352

353353
getDimensions() {
@@ -378,7 +378,7 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
378378
const activeComment = this._body.activeComment;
379379
if (activeComment) {
380380
return activeComment.submitComment();
381-
} else if ((this._commentReply?.getPendingComment()?.length ?? 0) > 0) {
381+
} else if ((this._commentReply?.getPendingComment()?.body.length ?? 0) > 0) {
382382
return this._commentReply?.submitComment();
383383
}
384384
}

src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
128128
editor: ICodeEditor,
129129
private _uniqueOwner: string,
130130
private _commentThread: languages.CommentThread,
131-
private _pendingComment: string | undefined,
132-
private _pendingEdits: { [key: number]: string } | undefined,
131+
private _pendingComment: languages.PendingComment | undefined,
132+
private _pendingEdits: { [key: number]: languages.PendingComment } | undefined,
133133
@IInstantiationService instantiationService: IInstantiationService,
134134
@IThemeService private themeService: IThemeService,
135135
@ICommentService private commentService: ICommentService,
@@ -242,17 +242,17 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
242242
}
243243
}
244244

245-
public getPendingComments(): { newComment: string | undefined; edits: { [key: number]: string } } {
245+
public getPendingComments(): { newComment: languages.PendingComment | undefined; edits: { [key: number]: languages.PendingComment } } {
246246
return {
247247
newComment: this._commentThreadWidget.getPendingComment(),
248248
edits: this._commentThreadWidget.getPendingEdits()
249249
};
250250
}
251251

252-
public setPendingComment(comment: string) {
253-
this._pendingComment = comment;
252+
public setPendingComment(pending: languages.PendingComment) {
253+
this._pendingComment = pending;
254254
this.expand();
255-
this._commentThreadWidget.setPendingComment(comment);
255+
this._commentThreadWidget.setPendingComment(pending);
256256
}
257257

258258
protected _fillContainer(container: HTMLElement): void {

src/vs/workbench/contrib/comments/browser/commentsController.ts

+16-16
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,8 @@ export class CommentController implements IEditorContribution {
464464
private _emptyThreadsToAddQueue: [Range | undefined, IEditorMouseEvent | undefined][] = [];
465465
private _computeCommentingRangePromise!: CancelablePromise<ICommentInfo[]> | null;
466466
private _computeCommentingRangeScheduler!: Delayer<Array<ICommentInfo | null>> | null;
467-
private _pendingNewCommentCache: { [key: string]: { [key: string]: string } };
468-
private _pendingEditsCache: { [key: string]: { [key: string]: { [key: number]: string } } }; // uniqueOwner -> threadId -> uniqueIdInThread -> pending comment
467+
private _pendingNewCommentCache: { [key: string]: { [key: string]: languages.PendingComment } };
468+
private _pendingEditsCache: { [key: string]: { [key: string]: { [key: number]: languages.PendingComment } } }; // uniqueOwner -> threadId -> uniqueIdInThread -> pending comment
469469
private _inProcessContinueOnComments: Map<string, languages.PendingCommentThread[]> = new Map();
470470
private _editorDisposables: IDisposable[] = [];
471471
private _activeCursorHasCommentingRange: IContextKey<boolean>;
@@ -578,12 +578,12 @@ export class CommentController implements IEditorContribution {
578578
}
579579
}
580580

581-
if (pendingNewComment !== lastCommentBody) {
581+
if (pendingNewComment.body !== lastCommentBody) {
582582
pendingComments.push({
583583
uniqueOwner: zone.uniqueOwner,
584584
uri: zone.editor.getModel()!.uri,
585585
range: zone.commentThread.range,
586-
body: pendingNewComment,
586+
comment: pendingNewComment,
587587
isReply: (zone.commentThread.comments !== undefined) && (zone.commentThread.comments.length > 0)
588588
});
589589
}
@@ -896,7 +896,7 @@ export class CommentController implements IEditorContribution {
896896
});
897897
let continueOnCommentText: string | undefined;
898898
if ((continueOnCommentIndex !== undefined) && continueOnCommentIndex >= 0) {
899-
continueOnCommentText = this._inProcessContinueOnComments.get(uniqueOwner)?.splice(continueOnCommentIndex, 1)[0].body;
899+
continueOnCommentText = this._inProcessContinueOnComments.get(uniqueOwner)?.splice(continueOnCommentIndex, 1)[0].comment.body;
900900
}
901901

902902
const pendingCommentText = (this._pendingNewCommentCache[uniqueOwner] && this._pendingNewCommentCache[uniqueOwner][thread.threadId])
@@ -999,18 +999,18 @@ export class CommentController implements IEditorContribution {
999999
const matchedZones = this._commentWidgets.filter(zoneWidget => zoneWidget.uniqueOwner === thread.uniqueOwner && Range.lift(zoneWidget.commentThread.range)?.equalsRange(thread.range));
10001000
if (thread.isReply && matchedZones.length) {
10011001
this.commentService.removeContinueOnComment({ uniqueOwner: thread.uniqueOwner, uri: editorURI, range: thread.range, isReply: true });
1002-
matchedZones[0].setPendingComment(thread.body);
1002+
matchedZones[0].setPendingComment(thread.comment);
10031003
} else if (matchedZones.length) {
10041004
this.commentService.removeContinueOnComment({ uniqueOwner: thread.uniqueOwner, uri: editorURI, range: thread.range, isReply: false });
10051005
const existingPendingComment = matchedZones[0].getPendingComments().newComment;
10061006
// We need to try to reconcile the existing pending comment with the incoming pending comment
1007-
let pendingComment: string;
1008-
if (!existingPendingComment || thread.body.includes(existingPendingComment)) {
1009-
pendingComment = thread.body;
1010-
} else if (existingPendingComment.includes(thread.body)) {
1007+
let pendingComment: languages.PendingComment;
1008+
if (!existingPendingComment || thread.comment.body.includes(existingPendingComment.body)) {
1009+
pendingComment = thread.comment;
1010+
} else if (existingPendingComment.body.includes(thread.comment.body)) {
10111011
pendingComment = existingPendingComment;
10121012
} else {
1013-
pendingComment = `${existingPendingComment}\n${thread.body}`;
1013+
pendingComment = { body: `${existingPendingComment}\n${thread.comment.body}`, cursor: thread.comment.cursor };
10141014
}
10151015
matchedZones[0].setPendingComment(pendingComment);
10161016
} else if (!thread.isReply) {
@@ -1062,7 +1062,7 @@ export class CommentController implements IEditorContribution {
10621062
return undefined;
10631063
}
10641064

1065-
private async displayCommentThread(uniqueOwner: string, thread: languages.CommentThread, shouldReveal: boolean, pendingComment: string | undefined, pendingEdits: { [key: number]: string } | undefined): Promise<void> {
1065+
private async displayCommentThread(uniqueOwner: string, thread: languages.CommentThread, shouldReveal: boolean, pendingComment: languages.PendingComment | undefined, pendingEdits: { [key: number]: languages.PendingComment } | undefined): Promise<void> {
10661066
const editor = this.editor?.getModel();
10671067
if (!editor) {
10681068
return;
@@ -1075,7 +1075,7 @@ export class CommentController implements IEditorContribution {
10751075
if (thread.range && !pendingComment) {
10761076
continueOnCommentReply = this.commentService.removeContinueOnComment({ uniqueOwner, uri: editor.uri, range: thread.range, isReply: true });
10771077
}
1078-
const zoneWidget = this.instantiationService.createInstance(ReviewZoneWidget, this.editor, uniqueOwner, thread, pendingComment ?? continueOnCommentReply?.body, pendingEdits);
1078+
const zoneWidget = this.instantiationService.createInstance(ReviewZoneWidget, this.editor, uniqueOwner, thread, pendingComment ?? continueOnCommentReply?.comment, pendingEdits);
10791079
await zoneWidget.display(thread.range, shouldReveal);
10801080
this._commentWidgets.push(zoneWidget);
10811081
this.openCommentsView(thread);
@@ -1361,12 +1361,12 @@ export class CommentController implements IEditorContribution {
13611361
const providerEditsCacheStore = this._pendingEditsCache[info.uniqueOwner];
13621362
info.threads = info.threads.filter(thread => !thread.isDisposed);
13631363
for (const thread of info.threads) {
1364-
let pendingComment: string | undefined = undefined;
1364+
let pendingComment: languages.PendingComment | undefined = undefined;
13651365
if (providerCacheStore) {
13661366
pendingComment = providerCacheStore[thread.threadId];
13671367
}
13681368

1369-
let pendingEdits: { [key: number]: string } | undefined = undefined;
1369+
let pendingEdits: { [key: number]: languages.PendingComment } | undefined = undefined;
13701370
if (providerEditsCacheStore) {
13711371
pendingEdits = providerEditsCacheStore[thread.threadId];
13721372
}
@@ -1412,7 +1412,7 @@ export class CommentController implements IEditorContribution {
14121412
lastCommentBody = lastComment.body.value;
14131413
}
14141414
}
1415-
if (pendingNewComment && (pendingNewComment !== lastCommentBody)) {
1415+
if (pendingNewComment && (pendingNewComment.body !== lastCommentBody)) {
14161416
if (!providerNewCommentCacheStore) {
14171417
this._pendingNewCommentCache[zone.uniqueOwner] = {};
14181418
}

0 commit comments

Comments
 (0)