diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index c838a2d6f0e..16d190fc1be 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -1670,13 +1670,14 @@ export interface CommentInput { /** * @internal */ -export interface CommentThread { +export interface CommentThread { + isDocumentCommentThread(): this is CommentThread; commentThreadHandle: number; controllerHandle: number; extensionId?: string; threadId: string; resource: string | null; - range: IRange; + range: T; label: string | undefined; contextValue: string | undefined; comments: Comment[] | undefined; @@ -1685,7 +1686,7 @@ export interface CommentThread { canReply: boolean; input?: CommentInput; onDidChangeInput: Event; - onDidChangeRange: Event; + onDidChangeRange: Event; onDidChangeLabel: Event; onDidChangeCollasibleState: Event; onDidChangeCanReply: Event; @@ -1753,21 +1754,21 @@ export interface Comment { /** * @internal */ -export interface CommentThreadChangedEvent { +export interface CommentThreadChangedEvent { /** * Added comment threads. */ - readonly added: CommentThread[]; + readonly added: CommentThread[]; /** * Removed comment threads. */ - readonly removed: CommentThread[]; + readonly removed: CommentThread[]; /** * Changed comment threads. */ - readonly changed: CommentThread[]; + readonly changed: CommentThread[]; } export interface CodeLens { diff --git a/src/vs/workbench/api/browser/mainThreadComments.ts b/src/vs/workbench/api/browser/mainThreadComments.ts index a9aa93b820c..9857c4d2f7b 100644 --- a/src/vs/workbench/api/browser/mainThreadComments.ts +++ b/src/vs/workbench/api/browser/mainThreadComments.ts @@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle'; import { URI, UriComponents } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; -import { IRange } from 'vs/editor/common/core/range'; +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'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -24,9 +24,10 @@ import { Codicon } from 'vs/base/common/codicons'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { localize } from 'vs/nls'; import { MarshalledId } from 'vs/base/common/marshallingIds'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; -export class MainThreadCommentThread implements languages.CommentThread { +export class MainThreadCommentThread implements languages.CommentThread { private _input?: languages.CommentInput; get input(): languages.CommentInput | undefined { return this._input; @@ -78,12 +79,12 @@ export class MainThreadCommentThread implements languages.CommentThread { private readonly _onDidChangeComments = new Emitter(); get onDidChangeComments(): Event { return this._onDidChangeComments.event; } - set range(range: IRange) { + set range(range: T) { this._range = range; this._onDidChangeRange.fire(this._range); } - get range(): IRange { + get range(): T { return this._range; } @@ -98,7 +99,7 @@ export class MainThreadCommentThread implements languages.CommentThread { return this._canReply; } - private readonly _onDidChangeRange = new Emitter(); + private readonly _onDidChangeRange = new Emitter(); public onDidChangeRange = this._onDidChangeRange.event; private _collapsibleState: languages.CommentThreadCollapsibleState | undefined; @@ -120,19 +121,23 @@ export class MainThreadCommentThread implements languages.CommentThread { return this._isDisposed; } + isDocumentCommentThread(): this is languages.CommentThread { + return Range.isIRange(this._range); + } + constructor( public commentThreadHandle: number, public controllerHandle: number, public extensionId: string, public threadId: string, public resource: string, - private _range: IRange, + private _range: T, private _canReply: boolean ) { this._isDisposed = false; } - batchUpdate(changes: CommentThreadChanges) { + batchUpdate(changes: CommentThreadChanges) { const modified = (value: keyof CommentThreadChanges): boolean => Object.prototype.hasOwnProperty.call(changes, value); @@ -197,8 +202,8 @@ export class MainThreadCommentController { return this._features.options; } - private readonly _threads: Map = new Map(); - public activeCommentThread?: MainThreadCommentThread; + private readonly _threads: Map> = new Map>(); + public activeCommentThread?: MainThreadCommentThread; get features(): CommentProviderFeatures { return this._features; @@ -222,8 +227,8 @@ export class MainThreadCommentController { commentThreadHandle: number, threadId: string, resource: UriComponents, - range: IRange, - ): languages.CommentThread { + range: IRange | ICellRange, + ): languages.CommentThread { let thread = new MainThreadCommentThread( commentThreadHandle, this.handle, @@ -294,7 +299,7 @@ export class MainThreadCommentController { this._commentService.updateCommentingRanges(this._uniqueId); } - private getKnownThread(commentThreadHandle: number): MainThreadCommentThread { + private getKnownThread(commentThreadHandle: number): MainThreadCommentThread { const thread = this._threads.get(commentThreadHandle); if (!thread) { throw new Error('unknown thread'); @@ -303,7 +308,7 @@ export class MainThreadCommentController { } async getDocumentComments(resource: URI, token: CancellationToken) { - let ret: languages.CommentThread[] = []; + let ret: languages.CommentThread[] = []; for (let thread of [...this._threads.keys()]) { const commentThread = this._threads.get(thread)!; if (commentThread.resource === resource.toString()) { @@ -333,8 +338,8 @@ export class MainThreadCommentController { return this._proxy.$toggleReaction(this._handle, thread.commentThreadHandle, uri, comment, reaction); } - getAllComments(): MainThreadCommentThread[] { - let ret: MainThreadCommentThread[] = []; + getAllComments(): MainThreadCommentThread[] { + let ret: MainThreadCommentThread[] = []; for (let thread of [...this._threads.keys()]) { ret.push(this._threads.get(thread)!); } @@ -369,7 +374,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments private _handlers = new Map(); private _commentControllers = new Map(); - private _activeCommentThread?: MainThreadCommentThread; + private _activeCommentThread?: MainThreadCommentThread; private readonly _activeCommentThreadDisposables = this._register(new DisposableStore()); private _openViewListener: IDisposable | null = null; @@ -385,7 +390,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostComments); this._register(this._commentService.onDidChangeActiveCommentThread(async thread => { - let handle = (thread as MainThreadCommentThread).controllerHandle; + let handle = (thread as MainThreadCommentThread).controllerHandle; let controller = this._commentControllers.get(handle); if (!controller) { @@ -393,7 +398,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments } this._activeCommentThreadDisposables.clear(); - this._activeCommentThread = thread as MainThreadCommentThread; + this._activeCommentThread = thread as MainThreadCommentThread; controller.activeCommentThread = this._activeCommentThread; })); } @@ -441,9 +446,9 @@ export class MainThreadComments extends Disposable implements MainThreadComments commentThreadHandle: number, threadId: string, resource: UriComponents, - range: IRange, + range: IRange | ICellRange, extensionId: ExtensionIdentifier - ): languages.CommentThread | undefined { + ): languages.CommentThread | undefined { let provider = this._commentControllers.get(handle); if (!provider) { @@ -570,7 +575,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments return this._handlers.get(handle)!; } - $onDidCommentThreadsChange(handle: number, event: languages.CommentThreadChangedEvent) { + $onDidCommentThreadsChange(handle: number, event: languages.CommentThreadChangedEvent) { // notify comment service const providerId = this.getHandler(handle); this._commentService.updateComments(providerId, event); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index c4097dbba81..c4a126a3f63 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -114,8 +114,8 @@ export interface CommentChanges { readonly timestamp?: string; } -export type CommentThreadChanges = Partial<{ - range: IRange; +export type CommentThreadChanges = Partial<{ + range: T; label: string; contextValue: string | null; comments: CommentChanges[]; @@ -127,11 +127,11 @@ export interface MainThreadCommentsShape extends IDisposable { $registerCommentController(handle: number, id: string, label: string): void; $unregisterCommentController(handle: number): void; $updateCommentControllerFeatures(handle: number, features: CommentProviderFeatures): void; - $createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange, extensionId: ExtensionIdentifier): languages.CommentThread | undefined; + $createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange | ICellRange, extensionId: ExtensionIdentifier): languages.CommentThread | undefined; $updateCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, changes: CommentThreadChanges): void; $deleteCommentThread(handle: number, commentThreadHandle: number): void; $updateCommentingRanges(handle: number): void; - $onDidCommentThreadsChange(handle: number, event: languages.CommentThreadChangedEvent): void; + $onDidCommentThreadsChange(handle: number, event: languages.CommentThreadChangedEvent): void; } export interface MainThreadAuthenticationShape extends IDisposable { diff --git a/src/vs/workbench/contrib/comments/browser/commentMenus.ts b/src/vs/workbench/contrib/comments/browser/commentMenus.ts index b9512d03f6b..2f5e9a671f8 100644 --- a/src/vs/workbench/contrib/comments/browser/commentMenus.ts +++ b/src/vs/workbench/contrib/comments/browser/commentMenus.ts @@ -7,7 +7,7 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions'; import { IAction } from 'vs/base/common/actions'; -import { Comment, CommentThread } from 'vs/editor/common/languages'; +import { Comment } from 'vs/editor/common/languages'; import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; export class CommentMenus implements IDisposable { @@ -15,11 +15,11 @@ export class CommentMenus implements IDisposable { @IMenuService private readonly menuService: IMenuService ) { } - getCommentThreadTitleActions(commentThread: CommentThread, contextKeyService: IContextKeyService): IMenu { + getCommentThreadTitleActions(contextKeyService: IContextKeyService): IMenu { return this.getMenu(MenuId.CommentThreadTitle, contextKeyService); } - getCommentThreadActions(commentThread: CommentThread, contextKeyService: IContextKeyService): IMenu { + getCommentThreadActions(contextKeyService: IContextKeyService): IMenu { return this.getMenu(MenuId.CommentThreadActions, contextKeyService); } diff --git a/src/vs/workbench/contrib/comments/browser/commentNode.ts b/src/vs/workbench/contrib/comments/browser/commentNode.ts index 4bb6d999c6c..fbd43cd3aed 100644 --- a/src/vs/workbench/contrib/comments/browser/commentNode.ts +++ b/src/vs/workbench/contrib/comments/browser/commentNode.ts @@ -38,8 +38,10 @@ import { MarshalledId } from 'vs/base/common/marshallingIds'; import { TimestampWidget } from 'vs/workbench/contrib/comments/browser/timestamp'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IMarkdownString } from 'vs/base/common/htmlContent'; +import { IRange } from 'vs/editor/common/core/range'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; -export class CommentNode extends Disposable { +export class CommentNode extends Disposable { private _domNode: HTMLElement; private _body: HTMLElement; private _md: HTMLElement | undefined; @@ -64,7 +66,7 @@ export class CommentNode extends Disposable { protected toolbar: ToolBar | undefined; private _commentFormActions: CommentFormActions | null = null; - private readonly _onDidClick = new Emitter(); + private readonly _onDidClick = new Emitter>(); public get domNode(): HTMLElement { return this._domNode; @@ -73,7 +75,7 @@ export class CommentNode extends Disposable { public isEditing: boolean = false; constructor( - private commentThread: languages.CommentThread, + private commentThread: languages.CommentThread, public comment: languages.Comment, private owner: string, private resource: URI, @@ -131,7 +133,7 @@ export class CommentNode extends Disposable { } } - public get onDidClick(): Event { + public get onDidClick(): Event> { return this._onDidClick.event; } diff --git a/src/vs/workbench/contrib/comments/browser/commentReply.ts b/src/vs/workbench/contrib/comments/browser/commentReply.ts index 3b15d78b60e..6b9c90cc2ba 100644 --- a/src/vs/workbench/contrib/comments/browser/commentReply.ts +++ b/src/vs/workbench/contrib/comments/browser/commentReply.ts @@ -11,6 +11,7 @@ import { MarshalledId } from 'vs/base/common/marshallingIds'; import { URI } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { IRange } from 'vs/editor/common/core/range'; import * as languages from 'vs/editor/common/languages'; import { ILanguageService } from 'vs/editor/common/languages/language'; import { ITextModel } from 'vs/editor/common/model'; @@ -25,13 +26,14 @@ import { CommentMenus } from 'vs/workbench/contrib/comments/browser/commentMenus import { ICommentService } from 'vs/workbench/contrib/comments/browser/commentService'; import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys'; import { ICommentThreadWidget } from 'vs/workbench/contrib/comments/common/commentThreadWidget'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { SimpleCommentEditor } from './simpleCommentEditor'; const COMMENT_SCHEME = 'comment'; let INMEM_MODEL_ID = 0; export const COMMENTEDITOR_DECORATION_KEY = 'commenteditordecoration'; -export class CommentReply extends Disposable { +export class CommentReply extends Disposable { commentEditor: ICodeEditor; form: HTMLElement; commentEditorIsEmpty: IContextKey; @@ -44,7 +46,7 @@ export class CommentReply extends Disposable { constructor( readonly owner: string, container: HTMLElement, - private _commentThread: languages.CommentThread, + private _commentThread: languages.CommentThread, private _scopedInstatiationService: IInstantiationService, private _contextKeyService: IContextKeyService, private _commentMenus: CommentMenus, @@ -104,7 +106,7 @@ export class CommentReply extends Disposable { this.createCommentWidgetActions(this._formActions, model); } - public updateCommentThread(commentThread: languages.CommentThread) { + public updateCommentThread(commentThread: languages.CommentThread) { const isReplying = this.commentEditor.hasTextFocus(); if (!this._reviewThreadReplyButton) { @@ -240,9 +242,7 @@ export class CommentReply extends Disposable { * Command based actions. */ private createCommentWidgetActions(container: HTMLElement, model: ITextModel) { - const commentThread = this._commentThread; - - const menu = this._commentMenus.getCommentThreadActions(commentThread, this._contextKeyService); + const menu = this._commentMenus.getCommentThreadActions(this._contextKeyService); this._register(menu); this._register(menu.onDidChange(() => { diff --git a/src/vs/workbench/contrib/comments/browser/commentService.ts b/src/vs/workbench/contrib/comments/browser/commentService.ts index a4ce66f7391..06e1f9f294e 100644 --- a/src/vs/workbench/contrib/comments/browser/commentService.ts +++ b/src/vs/workbench/contrib/comments/browser/commentService.ts @@ -12,6 +12,7 @@ import { Range, IRange } from 'vs/editor/common/core/range'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ICommentThreadChangedEvent } from 'vs/workbench/contrib/comments/common/commentModel'; import { CommentMenus } from 'vs/workbench/contrib/comments/browser/commentMenus'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; export const ICommentService = createDecorator('commentService'); @@ -58,7 +59,7 @@ export interface ICommentService { readonly onDidSetDataProvider: Event; readonly onDidDeleteDataProvider: Event; setDocumentComments(resource: URI, commentInfos: ICommentInfo[]): void; - setWorkspaceComments(owner: string, commentsByResource: CommentThread[]): void; + setWorkspaceComments(owner: string, commentsByResource: CommentThread[]): void; removeWorkspaceComments(owner: string): void; registerCommentController(owner: string, commentControl: ICommentController): void; unregisterCommentController(owner: string): void; @@ -66,14 +67,14 @@ export interface ICommentService { createCommentThreadTemplate(owner: string, resource: URI, range: Range): void; updateCommentThreadTemplate(owner: string, threadHandle: number, range: Range): Promise; getCommentMenus(owner: string): CommentMenus; - updateComments(ownerId: string, event: CommentThreadChangedEvent): void; + updateComments(ownerId: string, event: CommentThreadChangedEvent): void; disposeCommentThread(ownerId: string, threadId: string): void; getComments(resource: URI): Promise<(ICommentInfo | null)[]>; updateCommentingRanges(ownerId: string): void; getCommentingRanges(resource: URI): Promise; hasReactionHandler(owner: string): boolean; - toggleReaction(owner: string, resource: URI, thread: CommentThread, comment: Comment, reaction: CommentReaction): Promise; - setActiveCommentThread(commentThread: CommentThread | null): void; + toggleReaction(owner: string, resource: URI, thread: CommentThread, comment: Comment, reaction: CommentReaction): Promise; + setActiveCommentThread(commentThread: CommentThread | null): void; } export class CommentService extends Disposable implements ICommentService { @@ -185,7 +186,7 @@ export class CommentService extends Disposable implements ICommentService { return menu; } - updateComments(ownerId: string, event: CommentThreadChangedEvent): void { + updateComments(ownerId: string, event: CommentThreadChangedEvent): void { const evt: ICommentThreadChangedEvent = Object.assign({}, event, { owner: ownerId }); this._onDidUpdateCommentThreads.fire(evt); } diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadBody.ts b/src/vs/workbench/contrib/comments/browser/commentThreadBody.ts index fe8953bb7f9..2bcad3a6d97 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadBody.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadBody.ts @@ -17,16 +17,18 @@ import { ICommentThreadWidget } from 'vs/workbench/contrib/comments/common/comme import { IMarkdownRendererOptions, MarkdownRenderer } from 'vs/editor/contrib/markdownRenderer/browser/markdownRenderer'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ILanguageService } from 'vs/editor/common/languages/language'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; +import { IRange } from 'vs/editor/common/core/range'; -export class CommentThreadBody extends Disposable { +export class CommentThreadBody extends Disposable { private _commentsElement!: HTMLElement; - private _commentElements: CommentNode[] = []; + private _commentElements: CommentNode[] = []; private _resizeObserver: any; private _focusedComment: number | undefined = undefined; private _onDidResize = new Emitter(); onDidResize = this._onDidResize.event; - private _commentDisposable = new Map(); + private _commentDisposable = new Map, IDisposable>(); private _markdownRenderer: MarkdownRenderer; get length() { @@ -43,7 +45,7 @@ export class CommentThreadBody extends Disposable { readonly parentResourceUri: URI, readonly container: HTMLElement, private _options: IMarkdownRendererOptions, - private _commentThread: languages.CommentThread, + private _commentThread: languages.CommentThread, private _scopedInstatiationService: IInstantiationService, private _parentCommentThreadWidget: ICommentThreadWidget, @ICommentService private commentService: ICommentService, @@ -53,6 +55,7 @@ export class CommentThreadBody extends Disposable { super(); this._register(dom.addDisposableListener(container, dom.EventType.FOCUS_IN, e => { + // TODO @rebornix, limit T to IRange | ICellRange this.commentService.setActiveCommentThread(this._commentThread); })); @@ -130,11 +133,11 @@ export class CommentThreadBody extends Disposable { return; } - updateCommentThread(commentThread: languages.CommentThread) { + updateCommentThread(commentThread: languages.CommentThread) { const oldCommentsLen = this._commentElements.length; const newCommentsLen = commentThread.comments ? commentThread.comments.length : 0; - let commentElementsToDel: CommentNode[] = []; + let commentElementsToDel: CommentNode[] = []; let commentElementsToDelIndex: number[] = []; for (let i = 0; i < oldCommentsLen; i++) { let comment = this._commentElements[i].comment; @@ -160,8 +163,8 @@ export class CommentThreadBody extends Disposable { let lastCommentElement: HTMLElement | null = null; - let newCommentNodeList: CommentNode[] = []; - let newCommentsInEditMode: CommentNode[] = []; + let newCommentNodeList: CommentNode[] = []; + let newCommentsInEditMode: CommentNode[] = []; for (let i = newCommentsLen - 1; i >= 0; i--) { let currentComment = commentThread.comments![i]; let oldCommentNode = this._commentElements.filter(commentNode => commentNode.comment.uniqueIdInThread === currentComment.uniqueIdInThread); @@ -211,14 +214,14 @@ export class CommentThreadBody extends Disposable { } } - private createNewCommentNode(comment: languages.Comment): CommentNode { + private createNewCommentNode(comment: languages.Comment): CommentNode { let newCommentNode = this._scopedInstatiationService.createInstance(CommentNode, this._commentThread, comment, this.owner, this.parentResourceUri, this._parentCommentThreadWidget, - this._markdownRenderer); + this._markdownRenderer) as unknown as CommentNode; this._register(newCommentNode); this._commentDisposable.set(newCommentNode, newCommentNode.onDidClick(clickedNode => diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadHeader.ts b/src/vs/workbench/contrib/comments/browser/commentThreadHeader.ts index e046ec8989f..1c16bb4ffdb 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadHeader.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadHeader.ts @@ -10,6 +10,7 @@ import { Codicon } from 'vs/base/common/codicons'; import { Disposable } from 'vs/base/common/lifecycle'; import * as strings from 'vs/base/common/strings'; import * as languages from 'vs/editor/common/languages'; +import { IRange } from 'vs/editor/common/core/range'; import * as nls from 'vs/nls'; import { createActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IMenu, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; @@ -23,7 +24,7 @@ const collapseIcon = registerIcon('review-comment-collapse', Codicon.chevronUp, const COLLAPSE_ACTION_CLASS = 'expand-review-action ' + ThemeIcon.asClassName(collapseIcon); -export class CommentThreadHeader extends Disposable { +export class CommentThreadHeader extends Disposable { private _headElement: HTMLElement; private _headingLabel!: HTMLElement; private _actionbarWidget!: ActionBar; @@ -33,7 +34,7 @@ export class CommentThreadHeader extends Disposable { container: HTMLElement, private _delegate: { collapse: () => void }, private _commentMenus: CommentMenus, - private _commentThread: languages.CommentThread, + private _commentThread: languages.CommentThread, private _contextKeyService: IContextKeyService, private instantiationService: IInstantiationService ) { @@ -58,7 +59,7 @@ export class CommentThreadHeader extends Disposable { this._collapseAction = new Action('review.expand', nls.localize('label.collapse', "Collapse"), COLLAPSE_ACTION_CLASS, true, () => this._delegate.collapse()); - const menu = this._commentMenus.getCommentThreadTitleActions(this._commentThread, this._contextKeyService); + const menu = this._commentMenus.getCommentThreadTitleActions(this._contextKeyService); this.setActionBarActions(menu); this._register(menu); @@ -75,7 +76,7 @@ export class CommentThreadHeader extends Disposable { this._actionbarWidget.push([...groups, this._collapseAction], { label: false, icon: true }); } - updateCommentThread(commentThread: languages.CommentThread) { + updateCommentThread(commentThread: languages.CommentThread) { this._commentThread = commentThread; this._actionbarWidget.context = this._commentThread; diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts index 08ac1c92082..2b7bb059341 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts @@ -25,11 +25,13 @@ import { FontInfo } from 'vs/editor/common/config/fontInfo'; import { contrastBorder, focusBorder, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, textBlockQuoteBackground, textBlockQuoteBorder, textLinkActiveForeground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry'; import { PANEL_BORDER } from 'vs/workbench/common/theme'; import { peekViewBorder } from 'vs/editor/contrib/peekView/browser/peekView'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; +import { IRange } from 'vs/editor/common/core/range'; -export class CommentThreadWidget extends Disposable implements ICommentThreadWidget { - private _header!: CommentThreadHeader; - private _body!: CommentThreadBody; - private _commentReply?: CommentReply; +export class CommentThreadWidget extends Disposable implements ICommentThreadWidget { + private _header!: CommentThreadHeader; + private _body!: CommentThreadBody; + private _commentReply?: CommentReply; private _commentMenus: CommentMenus; private _commentThreadDisposables: IDisposable[] = []; private _threadIsEmpty: IContextKey; @@ -43,7 +45,7 @@ export class CommentThreadWidget extends Disposable implements ICommentThreadWid private _parentResourceUri: URI, private _contextKeyService: IContextKeyService, private _scopedInstatiationService: IInstantiationService, - private _commentThread: languages.CommentThread, + private _commentThread: languages.CommentThread, private _pendingComment: string | null, private _markdownOptions: IMarkdownRendererOptions, private _commentOptions: languages.CommentOptions | undefined, @@ -60,7 +62,7 @@ export class CommentThreadWidget extends Disposable implements ICommentThreadWid this._commentMenus = this.commentService.getCommentMenus(this._owner); - this._header = new CommentThreadHeader( + this._header = new CommentThreadHeader( container, { collapse: this.collapse.bind(this) @@ -85,12 +87,12 @@ export class CommentThreadWidget extends Disposable implements ICommentThreadWid this._commentThread, this._scopedInstatiationService, this - ); + ) as unknown as CommentThreadBody; this._styleElement = dom.createStyleSheet(this.container); } - updateCommentThread(commentThread: languages.CommentThread) { + updateCommentThread(commentThread: languages.CommentThread) { if (this._commentThread !== commentThread) { this._commentThreadDisposables.forEach(disposable => disposable.dispose()); } diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts index 70fc0b73c3b..b05a8d5d5c1 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts @@ -23,6 +23,7 @@ import { ICommentThreadWidget } from 'vs/workbench/contrib/comments/common/comme import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { CommentThreadWidget } from 'vs/workbench/contrib/comments/browser/commentThreadWidget'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; export function parseMouseDownInfoFromEvent(e: IEditorMouseEvent) { const range = e.target.range; @@ -189,7 +190,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget this.editor.getModel()!.uri, this._contextKeyService, this._scopedInstatiationService, - this._commentThread, + this._commentThread as unknown as languages.CommentThread, this._pendingComment, { editor: this.editor }, this._commentOptions, @@ -207,7 +208,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget this.collapse(); } } - ); + ) as unknown as CommentThreadWidget; this._disposables.add(this._commentThreadWidget); } @@ -248,7 +249,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget } } - async update(commentThread: languages.CommentThread) { + async update(commentThread: languages.CommentThread) { if (this._commentThread !== commentThread) { this._commentThreadDisposables.forEach(disposable => disposable.dispose()); this._commentThread = commentThread; diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index 9cd423fa18a..fc069e4a5ea 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -464,28 +464,32 @@ export class CommentController implements IEditorContribution { }); changed.forEach(thread => { - let matchedZones = this._commentWidgets.filter(zoneWidget => zoneWidget.owner === e.owner && zoneWidget.commentThread.threadId === thread.threadId); - if (matchedZones.length) { - let matchedZone = matchedZones[0]; - matchedZone.update(thread); + if (thread.isDocumentCommentThread()) { + let matchedZones = this._commentWidgets.filter(zoneWidget => zoneWidget.owner === e.owner && zoneWidget.commentThread.threadId === thread.threadId); + if (matchedZones.length) { + let matchedZone = matchedZones[0]; + matchedZone.update(thread); + } } }); added.forEach(thread => { - let matchedZones = this._commentWidgets.filter(zoneWidget => zoneWidget.owner === e.owner && zoneWidget.commentThread.threadId === thread.threadId); - if (matchedZones.length) { - return; + if (thread.isDocumentCommentThread()) { + let matchedZones = this._commentWidgets.filter(zoneWidget => zoneWidget.owner === e.owner && zoneWidget.commentThread.threadId === thread.threadId); + if (matchedZones.length) { + return; + } + + let matchedNewCommentThreadZones = this._commentWidgets.filter(zoneWidget => zoneWidget.owner === e.owner && (zoneWidget.commentThread as any).commentThreadHandle === -1 && Range.equalsRange(zoneWidget.commentThread.range, thread.range)); + + if (matchedNewCommentThreadZones.length) { + matchedNewCommentThreadZones[0].update(thread); + return; + } + + const pendingCommentText = this._pendingCommentCache[e.owner] && this._pendingCommentCache[e.owner][thread.threadId!]; + this.displayCommentThread(e.owner, thread, pendingCommentText); + this._commentInfos.filter(info => info.owner === e.owner)[0].threads.push(thread); } - - let matchedNewCommentThreadZones = this._commentWidgets.filter(zoneWidget => zoneWidget.owner === e.owner && (zoneWidget.commentThread as any).commentThreadHandle === -1 && Range.equalsRange(zoneWidget.commentThread.range, thread.range)); - - if (matchedNewCommentThreadZones.length) { - matchedNewCommentThreadZones[0].update(thread); - return; - } - - const pendingCommentText = this._pendingCommentCache[e.owner] && this._pendingCommentCache[e.owner][thread.threadId!]; - this.displayCommentThread(e.owner, thread, pendingCommentText); - this._commentInfos.filter(info => info.owner === e.owner)[0].threads.push(thread); }); })); diff --git a/src/vs/workbench/contrib/comments/common/commentModel.ts b/src/vs/workbench/contrib/comments/common/commentModel.ts index 4986e959ffe..b414fd9c8a4 100644 --- a/src/vs/workbench/contrib/comments/common/commentModel.ts +++ b/src/vs/workbench/contrib/comments/common/commentModel.ts @@ -8,8 +8,9 @@ import { IRange } from 'vs/editor/common/core/range'; import { Comment, CommentThread, CommentThreadChangedEvent } from 'vs/editor/common/languages'; import { groupBy } from 'vs/base/common/arrays'; import { localize } from 'vs/nls'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; -export interface ICommentThreadChangedEvent extends CommentThreadChangedEvent { +export interface ICommentThreadChangedEvent extends CommentThreadChangedEvent { owner: string; } @@ -104,28 +105,32 @@ export class CommentsModel { }); changed.forEach(thread => { - // Find resource that has the comment thread - const matchingResourceIndex = threadsForOwner.findIndex((resourceData) => resourceData.id === thread.resource); - const matchingResourceData = threadsForOwner[matchingResourceIndex]; + if (thread.isDocumentCommentThread()) { + // Find resource that has the comment thread + const matchingResourceIndex = threadsForOwner.findIndex((resourceData) => resourceData.id === thread.resource); + const matchingResourceData = threadsForOwner[matchingResourceIndex]; - // Find comment node on resource that is that thread and replace it - const index = matchingResourceData.commentThreads.findIndex((commentThread) => commentThread.threadId === thread.threadId); - if (index >= 0) { - matchingResourceData.commentThreads[index] = ResourceWithCommentThreads.createCommentNode(owner, URI.parse(matchingResourceData.id), thread); - } else if (thread.comments && thread.comments.length) { - matchingResourceData.commentThreads.push(ResourceWithCommentThreads.createCommentNode(owner, URI.parse(matchingResourceData.id), thread)); + // Find comment node on resource that is that thread and replace it + const index = matchingResourceData.commentThreads.findIndex((commentThread) => commentThread.threadId === thread.threadId); + if (index >= 0) { + matchingResourceData.commentThreads[index] = ResourceWithCommentThreads.createCommentNode(owner, URI.parse(matchingResourceData.id), thread); + } else if (thread.comments && thread.comments.length) { + matchingResourceData.commentThreads.push(ResourceWithCommentThreads.createCommentNode(owner, URI.parse(matchingResourceData.id), thread)); + } } }); added.forEach(thread => { - const existingResource = threadsForOwner.filter(resourceWithThreads => resourceWithThreads.resource.toString() === thread.resource); - if (existingResource.length) { - const resource = existingResource[0]; - if (thread.comments && thread.comments.length) { - resource.commentThreads.push(ResourceWithCommentThreads.createCommentNode(owner, resource.resource, thread)); + if (thread.isDocumentCommentThread()) { + const existingResource = threadsForOwner.filter(resourceWithThreads => resourceWithThreads.resource.toString() === thread.resource); + if (existingResource.length) { + const resource = existingResource[0]; + if (thread.comments && thread.comments.length) { + resource.commentThreads.push(ResourceWithCommentThreads.createCommentNode(owner, resource.resource, thread)); + } + } else { + threadsForOwner.push(new ResourceWithCommentThreads(owner, URI.parse(thread.resource!), [thread])); } - } else { - threadsForOwner.push(new ResourceWithCommentThreads(owner, URI.parse(thread.resource!), [thread])); } }); diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellComments.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellComments.ts index 1f919969688..9f6e2475b4c 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellComments.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellComments.ts @@ -18,8 +18,9 @@ import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewMod import { CommentThreadWidget } from 'vs/workbench/contrib/comments/browser/commentThreadWidget'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; -export class TestCommentThread implements languages.CommentThread { +export class TestCommentThread implements languages.CommentThread { private _input?: languages.CommentInput; get input(): languages.CommentInput | undefined { return this._input; @@ -71,12 +72,12 @@ export class TestCommentThread implements languages.CommentThread { private readonly _onDidChangeComments = new Emitter(); get onDidChangeComments(): Event { return this._onDidChangeComments.event; } - set range(range: IRange) { + set range(range: ICellRange) { this._range = range; this._onDidChangeRange.fire(this._range); } - get range(): IRange { + get range(): ICellRange { return this._range; } @@ -91,7 +92,7 @@ export class TestCommentThread implements languages.CommentThread { return this._canReply; } - private readonly _onDidChangeRange = new Emitter(); + private readonly _onDidChangeRange = new Emitter(); public onDidChangeRange = this._onDidChangeRange.event; private _collapsibleState: languages.CommentThreadCollapsibleState | undefined; @@ -119,11 +120,14 @@ export class TestCommentThread implements languages.CommentThread { public extensionId: string, public threadId: string, public resource: string, - private _range: IRange, + private _range: ICellRange, private _canReply: boolean ) { this._isDisposed = false; } + isDocumentCommentThread(): this is languages.CommentThread { + return false; + } dispose() { this._isDisposed = true; @@ -137,7 +141,7 @@ export class TestCommentThread implements languages.CommentThread { export class CellComments extends CellPart { private _initialized: boolean = false; - private _commentThreadWidget: CommentThreadWidget | null = null; + private _commentThreadWidget: CommentThreadWidget | null = null; private currentElement: CodeCellViewModel | undefined; private readonly elementDisposables = this._register(new DisposableStore()); @@ -183,7 +187,7 @@ export class CellComments extends CellPart { }, collapse: () => { } } - ); + ) as unknown as CommentThreadWidget; const layoutInfo = this.notebookEditor.getLayoutInfo(); @@ -210,7 +214,7 @@ export class CellComments extends CellPart { '', 'test', element.uri.toString(), - { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }, + { start: 0, end: 1 }, true ); commentThread.label = 'Discussion'; diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index 45bfa8fd464..64cd64a518d 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -29,6 +29,7 @@ export const allApiProposals = Object.freeze({ inlineCompletionsNew: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.inlineCompletionsNew.d.ts', ipc: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.ipc.d.ts', notebookCellExecutionState: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookCellExecutionState.d.ts', + notebookComment: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookComment.d.ts', notebookConcatTextDocument: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookConcatTextDocument.d.ts', notebookContentProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookContentProvider.d.ts', notebookControllerKind: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookControllerKind.d.ts', diff --git a/src/vscode-dts/vscode.proposed.notebookComment.d.ts b/src/vscode-dts/vscode.proposed.notebookComment.d.ts new file mode 100644 index 00000000000..3936ed7427e --- /dev/null +++ b/src/vscode-dts/vscode.proposed.notebookComment.d.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * 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 CommentThread { + position: T; + } + + export interface CommentController { + createCommentThread(uri: Uri, cell: NotebookCell, comments: readonly Comment[]): CommentThread; + } +}