diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 16550bdef8d..01eb0df109e 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -1888,6 +1888,14 @@ export interface CommentThreadChangedEvent { readonly changed: CommentThread[]; } +/** + * @internal + */ +export interface CommentingRangeResources { + schemes: string[]; + uris: URI[]; +} + export interface CodeLens { range: IRange; id?: string; diff --git a/src/vs/workbench/api/browser/mainThreadComments.ts b/src/vs/workbench/api/browser/mainThreadComments.ts index 538c754e1b3..f885f89333a 100644 --- a/src/vs/workbench/api/browser/mainThreadComments.ts +++ b/src/vs/workbench/api/browser/mainThreadComments.ts @@ -550,6 +550,14 @@ export class MainThreadComments extends Disposable implements MainThreadComments provider.updateFeatures(features); } + async $onDidChangeResourcesWithCommentingRanges(handle: number, schemes: string[], uris: UriComponents[]): Promise { + const provider = this._commentControllers.get(handle); + if (!provider) { + return; + } + this._commentService.setResourcesWithCommentingRanges(provider.id, { schemes, uris: uris.map(uri => URI.revive(uri)) }); + } + $createCommentThread(handle: number, commentThreadHandle: number, threadId: string, diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 29b99b8cc41..b512d5da601 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -146,6 +146,7 @@ export interface MainThreadCommentsShape extends IDisposable { $updateCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, changes: CommentThreadChanges): void; $deleteCommentThread(handle: number, commentThreadHandle: number): void; $updateCommentingRanges(handle: number): void; + $onDidChangeResourcesWithCommentingRanges(handle: number, schemes: string[], uris: UriComponents[]): Promise; } export interface AuthenticationForceNewSessionOptions { diff --git a/src/vs/workbench/api/common/extHostComments.ts b/src/vs/workbench/api/common/extHostComments.ts index 0f04b3f2455..18764746b77 100644 --- a/src/vs/workbench/api/common/extHostComments.ts +++ b/src/vs/workbench/api/common/extHostComments.ts @@ -563,8 +563,17 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo return this._commentingRangeProvider; } + private _commentingRangeProviderResourcesChanged: vscode.Disposable | undefined; set commentingRangeProvider(provider: vscode.CommentingRangeProvider | undefined) { this._commentingRangeProvider = provider; + this._commentingRangeProviderResourcesChanged?.dispose(); + this._commentingRangeProviderResourcesChanged = undefined; + if (this._commentingRangeProvider?.onDidChangeResourcesWithCommentingRanges) { + checkProposedApiEnabled(this._extension, 'commentingRangeResourcesChanged'); + this._commentingRangeProviderResourcesChanged = this._commentingRangeProvider.onDidChangeResourcesWithCommentingRanges(e => { + proxy.$onDidChangeResourcesWithCommentingRanges(this.handle, e.schemes, e.resources); + }); + } proxy.$updateCommentingRanges(this.handle); } @@ -695,7 +704,7 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo this._threads.forEach(value => { value.dispose(); }); - + this._commentingRangeProviderResourcesChanged?.dispose(); this._localDisposables.forEach(disposable => disposable.dispose()); } } diff --git a/src/vs/workbench/contrib/comments/browser/commentService.ts b/src/vs/workbench/contrib/comments/browser/commentService.ts index 1072a60aedf..2d9dcdde5e6 100644 --- a/src/vs/workbench/contrib/comments/browser/commentService.ts +++ b/src/vs/workbench/contrib/comments/browser/commentService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CommentThreadChangedEvent, CommentInfo, Comment, CommentReaction, CommentingRanges, CommentThread, CommentOptions, PendingCommentThread } from 'vs/editor/common/languages'; +import { CommentThreadChangedEvent, CommentInfo, Comment, CommentReaction, CommentingRanges, CommentThread, CommentOptions, PendingCommentThread, CommentingRangeResources } from 'vs/editor/common/languages'; import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; @@ -112,6 +112,8 @@ export interface ICommentService { enableCommenting(enable: boolean): void; registerContinueOnCommentProvider(provider: IContinueOnCommentProvider): IDisposable; removeContinueOnComment(pendingComment: { range: IRange | undefined; uri: URI; owner: string; isReply?: boolean }): PendingCommentThread | undefined; + setResourcesWithCommentingRanges(owner: string, resources: CommentingRangeResources): void; + resourceHasCommentingRanges(resource: URI): boolean; } const CONTINUE_ON_COMMENTS = 'comments.continueOnComments'; @@ -169,6 +171,8 @@ export class CommentService extends Disposable implements ICommentService { private readonly _commentsModel: CommentsModel = this._register(new CommentsModel()); public readonly commentsModel: ICommentsModel = this._commentsModel; + private _commentingRangeResources = new Map(); // owner -> CommentingRangeResources + constructor( @IInstantiationService protected readonly instantiationService: IInstantiationService, @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, @@ -494,4 +498,19 @@ export class CommentService extends Disposable implements ICommentService { } return changedOwners; } + + setResourcesWithCommentingRanges(owner: string, resources: CommentingRangeResources): void { + this._commentingRangeResources.set(owner, resources); + } + + resourceHasCommentingRanges(resource: URI): boolean { + for (const resources of this._commentingRangeResources.values()) { + if (resources.schemes.includes(resource.scheme)) { + return true; + } else if (resources.uris.some(uri => uri.toString() === resource.toString())) { + return true; + } + } + return false; + } } diff --git a/src/vs/workbench/contrib/comments/browser/commentsController.ts b/src/vs/workbench/contrib/comments/browser/commentsController.ts index 4faf49116c0..1f795367c89 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsController.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsController.ts @@ -780,6 +780,7 @@ export class CommentController implements IEditorContribution { public onModelChanged(): void { this.localToDispose.clear(); + this.tryUpdateReservedSpace(); this.removeCommentWidgetsAndStoreCache(); if (!this.editor) { @@ -1194,10 +1195,14 @@ export class CommentController implements IEditorContribution { return; } - const hasCommentsOrRanges = this._commentInfos.some(info => { + const hasCommentsOrRangesInInfo = this._commentInfos.some(info => { const hasRanges = Boolean(info.commentingRanges && (Array.isArray(info.commentingRanges) ? info.commentingRanges : info.commentingRanges.ranges).length); return hasRanges || (info.threads.length > 0); }); + const uri = this.editor.getModel()?.uri; + const resourceHasCommentingRanges = uri ? this.commentService.resourceHasCommentingRanges(uri) : false; + + const hasCommentsOrRanges = hasCommentsOrRangesInInfo || resourceHasCommentingRanges; if (hasCommentsOrRanges && !this._commentingRangeSpaceReserved && this.commentService.isCommentingEnabled) { this._commentingRangeSpaceReserved = true; diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index 76ffed1feeb..48e060c3e8f 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -20,6 +20,7 @@ export const allApiProposals = Object.freeze({ codeActionRanges: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.codeActionRanges.d.ts', codiconDecoration: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.codiconDecoration.d.ts', commentReactor: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.commentReactor.d.ts', + commentingRangeResourcesChanged: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.commentingRangeResourcesChanged.d.ts', commentsDraftState: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.commentsDraftState.d.ts', contribCommentEditorActionsMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribCommentEditorActionsMenu.d.ts', contribCommentPeekContext: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribCommentPeekContext.d.ts', diff --git a/src/vscode-dts/vscode.proposed.commentingRangeResourcesChanged.d.ts b/src/vscode-dts/vscode.proposed.commentingRangeResourcesChanged.d.ts new file mode 100644 index 00000000000..7a4f22aecf7 --- /dev/null +++ b/src/vscode-dts/vscode.proposed.commentingRangeResourcesChanged.d.ts @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + export interface CommentingRangeProvider { + readonly onDidChangeResourcesWithCommentingRanges?: Event<{ schemes: string[]; resources: Uri[] }>; + } +}