Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adopt StorageScope.WORKSPACE in comments #193098

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading