Skip to content

Commit

Permalink
Adopt StorageScope.WORKSPACE in comments
Browse files Browse the repository at this point in the history
Part of #183449
  • Loading branch information
alexr00 committed Sep 14, 2023
1 parent 8ac8b0d commit 7345828
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 21 deletions.
13 changes: 13 additions & 0 deletions src/vs/editor/common/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1644,6 +1644,7 @@ export interface CommentThreadTemplate {
export interface CommentInfo {
extensionId?: string;
threads: CommentThread[];
pendingCommentThreads?: PendingCommentThread[];
commentingRanges: CommentingRanges;
}

Expand Down Expand Up @@ -1785,10 +1786,22 @@ export interface Comment {
readonly timestamp?: string;
}

export interface PendingCommentThread {
body: string;
range: IRange;
uri: URI;
owner: string;
}

/**
* @internal
*/
export interface CommentThreadChangedEvent<T> {
/**
* Pending comment threads.
*/
readonly pending: PendingCommentThread[];

/**
* Added comment threads.
*/
Expand Down
7 changes: 7 additions & 0 deletions src/vs/monaco.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7622,6 +7622,13 @@ declare namespace monaco.languages {
arguments?: any[];
}

export interface PendingCommentThread {
body: string;
range: IRange;
uri: Uri;
owner: string;
}

export interface CodeLens {
range: IRange;
id?: string;
Expand Down
23 changes: 14 additions & 9 deletions src/vs/workbench/api/browser/mainThreadComments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import { IRange, Range } from 'vs/editor/common/core/range';
import * as languages from 'vs/editor/common/languages';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
Expand Down Expand Up @@ -287,13 +286,15 @@ export class MainThreadCommentController implements ICommentController {
this._commentService.updateComments(this._uniqueId, {
added: [thread],
removed: [],
changed: []
changed: [],
pending: []
});
} else {
this._commentService.updateNotebookComments(this._uniqueId, {
added: [thread as MainThreadCommentThread<ICellRange>],
removed: [],
changed: []
changed: [],
pending: []
});
}

Expand All @@ -311,13 +312,15 @@ export class MainThreadCommentController implements ICommentController {
this._commentService.updateComments(this._uniqueId, {
added: [],
removed: [],
changed: [thread]
changed: [thread],
pending: []
});
} else {
this._commentService.updateNotebookComments(this._uniqueId, {
added: [],
removed: [],
changed: [thread as MainThreadCommentThread<ICellRange>]
changed: [thread as MainThreadCommentThread<ICellRange>],
pending: []
});
}

Expand All @@ -332,13 +335,15 @@ export class MainThreadCommentController implements ICommentController {
this._commentService.updateComments(this._uniqueId, {
added: [],
removed: [thread],
changed: []
changed: [],
pending: []
});
} else {
this._commentService.updateNotebookComments(this._uniqueId, {
added: [],
removed: [thread as MainThreadCommentThread<ICellRange>],
changed: []
changed: [],
pending: []
});
}
}
Expand Down Expand Up @@ -502,8 +507,8 @@ export class MainThreadComments extends Disposable implements MainThreadComments
}));
}

$registerCommentController(handle: number, id: string, label: string): void {
const providerId = generateUuid();
$registerCommentController(handle: number, id: string, label: string, extensionId: string): void {
const providerId = `${label}-${extensionId}`;
this._handlers.set(handle, providerId);

const provider = new MainThreadCommentController(this._proxy, this._commentService, handle, providerId, id, label, {});
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export type CommentThreadChanges<T = IRange> = Partial<{
}>;

export interface MainThreadCommentsShape extends IDisposable {
$registerCommentController(handle: number, id: string, label: string): void;
$registerCommentController(handle: number, id: string, label: string, extensionId: string): void;
$unregisterCommentController(handle: number): void;
$updateCommentControllerFeatures(handle: number, features: CommentProviderFeatures): void;
$createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange | ICellRange | undefined, extensionId: ExtensionIdentifier, isTemplate: boolean): languages.CommentThread<IRange | ICellRange> | undefined;
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHostComments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo
private _id: string,
private _label: string
) {
proxy.$registerCommentController(this.handle, _id, _label);
proxy.$registerCommentController(this.handle, _id, _label, this._extension.identifier.value);

const that = this;
this.value = Object.freeze({
Expand Down
99 changes: 94 additions & 5 deletions src/vs/workbench/contrib/comments/browser/commentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
*--------------------------------------------------------------------------------------------*/

import * as nls from 'vs/nls';
import { CommentThreadChangedEvent, CommentInfo, Comment, CommentReaction, CommentingRanges, CommentThread, CommentOptions } from 'vs/editor/common/languages';
import { CommentThreadChangedEvent, CommentInfo, Comment, CommentReaction, CommentingRanges, CommentThread, CommentOptions, PendingCommentThread } from 'vs/editor/common/languages';
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Event, Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { Range, IRange } from 'vs/editor/common/core/range';
import { CancellationToken } from 'vs/base/common/cancellation';
Expand All @@ -18,6 +18,7 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { COMMENTS_SECTION, ICommentsConfiguration } from 'vs/workbench/contrib/comments/common/commentsConfiguration';
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';

export const ICommentService = createDecorator<ICommentService>('commentService');

Expand Down Expand Up @@ -69,6 +70,10 @@ export interface ICommentController {
getNotebookComments(resource: URI, token: CancellationToken): Promise<INotebookCommentInfo>;
}

export interface IContinueOnCommentProvider {
provideContinueOnComments(): PendingCommentThread[];
}

export interface ICommentService {
readonly _serviceBrand: undefined;
readonly onDidSetResourceCommentInfos: Event<IResourceCommentThreadEvent>;
Expand Down Expand Up @@ -103,8 +108,12 @@ export interface ICommentService {
setActiveCommentThread(commentThread: CommentThread<IRange | ICellRange> | null): void;
setCurrentCommentThread(commentThread: CommentThread<IRange | ICellRange> | undefined): void;
enableCommenting(enable: boolean): void;
registerContinueOnCommentProvider(provider: IContinueOnCommentProvider): IDisposable;
removeContinueOnComment(pendingComment: { range: IRange; uri: URI; owner: string }): PendingCommentThread | undefined;
}

const CONTINUE_ON_COMMENTS = 'comments.continueOnComments';

export class CommentService extends Disposable implements ICommentService {
declare readonly _serviceBrand: undefined;

Expand Down Expand Up @@ -152,16 +161,49 @@ export class CommentService extends Disposable implements ICommentService {
private _isCommentingEnabled: boolean = true;
private _workspaceHasCommenting: IContextKey<boolean>;

private _continueOnComments = new Map<string, PendingCommentThread[]>(); // owner -> PendingCommentThread[]
private _continueOnCommentProviders = new Set<IContinueOnCommentProvider>();

constructor(
@IInstantiationService protected readonly instantiationService: IInstantiationService,
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IContextKeyService contextKeyService: IContextKeyService
@IContextKeyService contextKeyService: IContextKeyService,
@IStorageService private readonly storageService: IStorageService
) {
super();
this._handleConfiguration();
this._handleZenMode();
this._workspaceHasCommenting = WorkspaceHasCommenting.bindTo(contextKeyService);
const storageListener = this._register(new DisposableStore());

storageListener.add(this.storageService.onDidChangeValue(StorageScope.WORKSPACE, CONTINUE_ON_COMMENTS, storageListener)((v) => {
if (!v.external) {
return;
}
const commentsToRestore: PendingCommentThread[] | undefined = this.storageService.getObject(CONTINUE_ON_COMMENTS, StorageScope.WORKSPACE);
if (!commentsToRestore) {
return;
}
const changedOwners = this._addContinueOnComments(commentsToRestore);
for (const owner of changedOwners) {
const evt: ICommentThreadChangedEvent = {
owner,
pending: this._continueOnComments.get(owner) || [],
added: [],
removed: [],
changed: []
};
this._onDidUpdateCommentThreads.fire(evt);
}
}));
this._register(storageService.onWillSaveState(() => {
for (const provider of this._continueOnCommentProviders) {
const pendingComments = provider.provideContinueOnComments();
this._addContinueOnComments(pendingComments);
}
this._saveContinueOnComments();
}));
}

private _handleConfiguration() {
Expand Down Expand Up @@ -325,12 +367,17 @@ export class CommentService extends Disposable implements ICommentService {
async getDocumentComments(resource: URI): Promise<(ICommentInfo | null)[]> {
const commentControlResult: Promise<ICommentInfo | null>[] = [];

this._commentControls.forEach(control => {
for (const control of this._commentControls.values()) {
commentControlResult.push(control.getDocumentComments(resource, CancellationToken.None)
.then(documentComments => {
const pendingComments = this._continueOnComments.get(documentComments.owner);
documentComments.pendingCommentThreads = pendingComments?.filter(pendingComment => pendingComment.uri.toString() === resource.toString());
return documentComments;
})
.catch(_ => {
return null;
}));
});
}

return Promise.all(commentControlResult);
}
Expand All @@ -347,4 +394,46 @@ export class CommentService extends Disposable implements ICommentService {

return Promise.all(commentControlResult);
}

registerContinueOnCommentProvider(provider: IContinueOnCommentProvider): IDisposable {
this._continueOnCommentProviders.add(provider);
return {
dispose: () => {
this._continueOnCommentProviders.delete(provider);
}
};
}

private _saveContinueOnComments() {
const commentsToSave: PendingCommentThread[] = [];
for (const pendingComments of this._continueOnComments.values()) {
commentsToSave.push(...pendingComments);
}
this.storageService.store(CONTINUE_ON_COMMENTS, commentsToSave, StorageScope.WORKSPACE, StorageTarget.USER);
}

removeContinueOnComment(pendingComment: { range: IRange; uri: URI; owner: string }): PendingCommentThread | undefined {
const pendingComments = this._continueOnComments.get(pendingComment.owner);
if (pendingComments) {
return pendingComments.splice(pendingComments.findIndex(comment => comment.uri.toString() === pendingComment.uri.toString() && Range.equalsRange(comment.range, pendingComment.range)), 1)[0];
}
return undefined;
}

private _addContinueOnComments(pendingComments: PendingCommentThread[]): Set<string> {
const changedOwners = new Set<string>();
for (const pendingComment of pendingComments) {
if (!this._continueOnComments.has(pendingComment.owner)) {
this._continueOnComments.set(pendingComment.owner, [pendingComment]);
changedOwners.add(pendingComment.owner);
} else {
const commentsForOwner = this._continueOnComments.get(pendingComment.owner)!;
if (commentsForOwner.every(comment => (comment.uri.toString() !== pendingComment.uri.toString()) || !Range.equalsRange(comment.range, pendingComment.range) || (comment.body !== pendingComment.body))) {
commentsForOwner.push(pendingComment);
changedOwners.add(pendingComment.owner);
}
}
}
return changedOwners;
}
}
51 changes: 46 additions & 5 deletions src/vs/workbench/contrib/comments/browser/commentsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,39 @@ export class CommentController implements IEditorContribution {

this.onModelChanged();
this.codeEditorService.registerDecorationType('comment-controller', COMMENTEDITOR_DECORATION_KEY, {});
this.beginCompute();
this.commentService.registerContinueOnCommentProvider({
provideContinueOnComments: () => {
const pendingComments: languages.PendingCommentThread[] = [];
if (this._commentWidgets) {
for (const zone of this._commentWidgets) {
const zonePendingComments = zone.getPendingComments();
const pendingNewComment = zonePendingComments.newComment;
if (!pendingNewComment || !zone.commentThread.range) {
continue;
}
let lastCommentBody;
if (zone.commentThread.comments && zone.commentThread.comments.length) {
const lastComment = zone.commentThread.comments[zone.commentThread.comments.length - 1];
if (typeof lastComment.body === 'string') {
lastCommentBody = lastComment.body;
} else {
lastCommentBody = lastComment.body.value;
}
}

if (pendingNewComment !== lastCommentBody) {
pendingComments.push({
owner: zone.owner,
uri: zone.editor.getModel()!.uri,
range: zone.commentThread.range,
body: pendingNewComment
});
}
}
}
return pendingComments;
}
});
}

private registerEditorListeners() {
Expand Down Expand Up @@ -671,9 +703,10 @@ export class CommentController implements IEditorContribution {
return;
}

const added = e.added.filter(thread => thread.resource && thread.resource.toString() === editorURI.toString());
const removed = e.removed.filter(thread => thread.resource && thread.resource.toString() === editorURI.toString());
const changed = e.changed.filter(thread => thread.resource && thread.resource.toString() === editorURI.toString());
const added = e.added.filter(thread => thread.resource && thread.resource === editorURI.toString());
const removed = e.removed.filter(thread => thread.resource && thread.resource === editorURI.toString());
const changed = e.changed.filter(thread => thread.resource && thread.resource === editorURI.toString());
const pending = e.pending.filter(pending => pending.uri.toString() === editorURI.toString());

removed.forEach(thread => {
const matchedZones = this._commentWidgets.filter(zoneWidget => zoneWidget.owner === e.owner && zoneWidget.commentThread.threadId === thread.threadId && zoneWidget.commentThread.threadId !== '');
Expand Down Expand Up @@ -713,12 +746,17 @@ export class CommentController implements IEditorContribution {
return;
}

const pendingCommentText = this._pendingNewCommentCache[e.owner] && this._pendingNewCommentCache[e.owner][thread.threadId!];
const continueOnCommentText = (thread.range ? this.commentService.removeContinueOnComment({ owner: e.owner, uri: editorURI, range: thread.range })?.body : undefined);
const pendingCommentText = (this._pendingNewCommentCache[e.owner] && this._pendingNewCommentCache[e.owner][thread.threadId!])
?? continueOnCommentText;
const pendingEdits = this._pendingEditsCache[e.owner] && this._pendingEditsCache[e.owner][thread.threadId!];
this.displayCommentThread(e.owner, thread, pendingCommentText, pendingEdits);
this._commentInfos.filter(info => info.owner === e.owner)[0].threads.push(thread);
this.tryUpdateReservedSpace();
});
pending.forEach(thread => {
this.commentService.createCommentThreadTemplate(thread.owner, thread.uri, Range.lift(thread.range));
});
this._commentThreadRangeDecorator.update(this.editor, commentInfo);
}));

Expand Down Expand Up @@ -1002,6 +1040,9 @@ export class CommentController implements IEditorContribution {

this.displayCommentThread(info.owner, thread, pendingComment, pendingEdits);
});
info.pendingCommentThreads?.forEach(thread => {
this.commentService.createCommentThreadTemplate(thread.owner, thread.uri, Range.lift(thread.range));
});
});

this._commentingRangeDecorator.update(this.editor, this._commentInfos);
Expand Down

0 comments on commit 7345828

Please sign in to comment.