Skip to content

Commit

Permalink
Add file level commenting (microsoft#178478)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexr00 committed Mar 28, 2023
1 parent 3edcfeb commit 22c8efe
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 41 deletions.
1 change: 1 addition & 0 deletions src/vs/editor/common/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1621,6 +1621,7 @@ export interface CommentThread<T = IRange> {
export interface CommentingRanges {
readonly resource: URI;
ranges: IRange[];
fileComments: boolean;
}

/**
Expand Down
13 changes: 5 additions & 8 deletions src/vs/workbench/api/browser/mainThreadComments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,8 @@ export class MainThreadCommentController implements ICommentController {
threads: [],
commentingRanges: {
resource: resource,
ranges: []
ranges: [],
fileComments: false
}
};
}
Expand All @@ -402,7 +403,8 @@ export class MainThreadCommentController implements ICommentController {
threads: ret,
commentingRanges: {
resource: resource,
ranges: commentingRanges || []
ranges: commentingRanges?.ranges || [],
fileComments: commentingRanges?.fileComments
}
};
}
Expand Down Expand Up @@ -431,11 +433,6 @@ export class MainThreadCommentController implements ICommentController {
};
}

async getCommentingRanges(resource: URI, token: CancellationToken): Promise<IRange[]> {
const commentingRanges = await this._proxy.$provideCommentingRanges(this.handle, resource, token);
return commentingRanges || [];
}

async toggleReaction(uri: URI, thread: languages.CommentThread, comment: languages.Comment, reaction: languages.CommentReaction, token: CancellationToken): Promise<void> {
return this._proxy.$toggleReaction(this._handle, thread.commentThreadHandle, uri, comment, reaction);
}
Expand All @@ -449,7 +446,7 @@ export class MainThreadCommentController implements ICommentController {
return ret;
}

createCommentThreadTemplate(resource: UriComponents, range: IRange): void {
createCommentThreadTemplate(resource: UriComponents, range: IRange | undefined): void {
this._proxy.$createCommentThreadTemplate(this.handle, resource, range);
}

Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2071,10 +2071,10 @@ export interface ExtHostProgressShape {
}

export interface ExtHostCommentsShape {
$createCommentThreadTemplate(commentControllerHandle: number, uriComponents: UriComponents, range: IRange): void;
$createCommentThreadTemplate(commentControllerHandle: number, uriComponents: UriComponents, range: IRange | undefined): void;
$updateCommentThreadTemplate(commentControllerHandle: number, threadHandle: number, range: IRange): Promise<void>;
$deleteCommentThread(commentControllerHandle: number, commentThreadHandle: number): void;
$provideCommentingRanges(commentControllerHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<IRange[] | undefined>;
$provideCommentingRanges(commentControllerHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<{ ranges: IRange[]; fileComments: boolean } | undefined>;
$toggleReaction(commentControllerHandle: number, threadHandle: number, uri: UriComponents, comment: languages.Comment, reaction: languages.CommentReaction): Promise<void>;
}

Expand Down
37 changes: 31 additions & 6 deletions src/vs/workbench/api/common/extHostComments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type * as vscode from 'vscode';
import { ExtHostCommentsShape, IMainContext, MainContext, CommentThreadChanges, CommentChanges } from './extHost.protocol';
import { ExtHostCommands } from './extHostCommands';
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { withNullAsUndefined } from 'vs/base/common/types';

type ProviderHandle = number;

Expand Down Expand Up @@ -158,7 +159,7 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo
return commentController.value;
}

$createCommentThreadTemplate(commentControllerHandle: number, uriComponents: UriComponents, range: IRange): void {
$createCommentThreadTemplate(commentControllerHandle: number, uriComponents: UriComponents, range: IRange | undefined): void {
const commentController = this._commentControllers.get(commentControllerHandle);

if (!commentController) {
Expand All @@ -184,17 +185,41 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo
commentController?.$deleteCommentThread(commentThreadHandle);
}

$provideCommentingRanges(commentControllerHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<IRange[] | undefined> {
$provideCommentingRanges(commentControllerHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<{ ranges: IRange[]; fileComments: boolean } | undefined> {
const commentController = this._commentControllers.get(commentControllerHandle);

if (!commentController || !commentController.commentingRangeProvider) {
return Promise.resolve(undefined);
}

const document = documents.getDocument(URI.revive(uriComponents));
return asPromise(() => {
return commentController.commentingRangeProvider!.provideCommentingRanges(document, token);
}).then(ranges => ranges ? ranges.map(x => extHostTypeConverter.Range.from(x)) : undefined);
return asPromise(async () => {
const rangesResult = await (commentController.commentingRangeProvider as vscode.CommentingRangeProvider2).provideCommentingRanges(document, token);
let ranges: { ranges: vscode.Range[]; fileComments: boolean } | undefined;
if (Array.isArray(rangesResult)) {
ranges = {
ranges: rangesResult,
fileComments: false
};
} else if (rangesResult) {
ranges = {
ranges: rangesResult.ranges || [],
fileComments: rangesResult.fileComments || false
};
} else {
ranges = withNullAsUndefined(rangesResult);
}
return ranges;
}).then(ranges => {
let convertedResult: { ranges: IRange[]; fileComments: boolean } | undefined = undefined;
if (ranges) {
convertedResult = {
ranges: ranges.ranges.map(x => extHostTypeConverter.Range.from(x)),
fileComments: ranges.fileComments
};
}
return convertedResult;
});
}

$toggleReaction(commentControllerHandle: number, threadHandle: number, uri: UriComponents, comment: languages.Comment, reaction: languages.CommentReaction): Promise<void> {
Expand Down Expand Up @@ -606,7 +631,7 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo
return commentThread;
}

$createCommentThreadTemplate(uriComponents: UriComponents, range: IRange): ExtHostCommentThread {
$createCommentThreadTemplate(uriComponents: UriComponents, range: IRange | undefined): ExtHostCommentThread {
const commentThread = new ExtHostCommentThread(this.id, this.handle, undefined, URI.revive(uriComponents), extHostTypeConverter.Range.to(range), [], this._extension, true);
commentThread.collapsibleState = languages.CommentThreadCollapsibleState.Expanded;
this._threads.set(commentThread.handle, commentThread);
Expand Down
19 changes: 3 additions & 16 deletions src/vs/workbench/contrib/comments/browser/commentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,12 @@ export interface ICommentController {
};
options?: CommentOptions;
contextValue?: string;
createCommentThreadTemplate(resource: UriComponents, range: IRange): void;
createCommentThreadTemplate(resource: UriComponents, range: IRange | undefined): void;
updateCommentThreadTemplate(threadHandle: number, range: IRange): Promise<void>;
deleteCommentThreadMain(commentThreadId: string): void;
toggleReaction(uri: URI, thread: CommentThread, comment: Comment, reaction: CommentReaction, token: CancellationToken): Promise<void>;
getDocumentComments(resource: URI, token: CancellationToken): Promise<ICommentInfo>;
getNotebookComments(resource: URI, token: CancellationToken): Promise<INotebookCommentInfo>;
getCommentingRanges(resource: URI, token: CancellationToken): Promise<IRange[]>;
}

export interface ICommentService {
Expand All @@ -90,7 +89,7 @@ export interface ICommentService {
registerCommentController(owner: string, commentControl: ICommentController): void;
unregisterCommentController(owner: string): void;
getCommentController(owner: string): ICommentController | undefined;
createCommentThreadTemplate(owner: string, resource: URI, range: Range): void;
createCommentThreadTemplate(owner: string, resource: URI, range: Range | undefined): void;
updateCommentThreadTemplate(owner: string, threadHandle: number, range: Range): Promise<void>;
getCommentMenus(owner: string): CommentMenus;
updateComments(ownerId: string, event: CommentThreadChangedEvent<IRange>): void;
Expand All @@ -99,7 +98,6 @@ export interface ICommentService {
getDocumentComments(resource: URI): Promise<(ICommentInfo | null)[]>;
getNotebookComments(resource: URI): Promise<(INotebookCommentInfo | null)[]>;
updateCommentingRanges(ownerId: string): void;
getCommentingRanges(resource: URI): Promise<IRange[]>;
hasReactionHandler(owner: string): boolean;
toggleReaction(owner: string, resource: URI, thread: CommentThread<IRange | ICellRange>, comment: Comment, reaction: CommentReaction): Promise<void>;
setActiveCommentThread(commentThread: CommentThread<IRange | ICellRange> | null): void;
Expand Down Expand Up @@ -250,7 +248,7 @@ export class CommentService extends Disposable implements ICommentService {
return this._commentControls.get(owner);
}

createCommentThreadTemplate(owner: string, resource: URI, range: Range): void {
createCommentThreadTemplate(owner: string, resource: URI, range: Range | undefined): void {
const commentController = this._commentControls.get(owner);

if (!commentController) {
Expand Down Expand Up @@ -345,15 +343,4 @@ export class CommentService extends Disposable implements ICommentService {

return Promise.all(commentControlResult);
}

async getCommentingRanges(resource: URI): Promise<IRange[]> {
const commentControlResult: Promise<IRange[]>[] = [];

this._commentControls.forEach(control => {
commentControlResult.push(control.getCommentingRanges(resource, CancellationToken.None));
});

const ret = await Promise.all(commentControlResult);
return ret.reduce((prev, curr) => { prev.push(...curr); return prev; }, []);
}
}
29 changes: 22 additions & 7 deletions src/vs/workbench/contrib/comments/browser/commentsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,22 @@ class CommentingRangeDecorator {
}
}

public getMatchedCommentAction(commentRange: Range): CommentRangeAction[] {
public getMatchedCommentAction(commentRange: Range | undefined): CommentRangeAction[] {
if (commentRange === undefined) {
const foundInfos = this._infos?.filter(info => info.commentingRanges.fileComments);
if (foundInfos) {
return foundInfos.map(foundInfo => {
return {
ownerId: foundInfo.owner,
extensionId: foundInfo.extensionId,
label: foundInfo.label,
commentingRangesInfo: foundInfo.commentingRanges
};
});
}
return [];
}

// keys is ownerId
const foundHoverActions = new Map<string, { range: Range; action: CommentRangeAction }>();
for (const decoration of this.commentingRangeDecorations) {
Expand Down Expand Up @@ -293,7 +308,7 @@ export class CommentController implements IEditorContribution {
private _commentingRangeSpaceReserved = false;
private _computePromise: CancelablePromise<Array<ICommentInfo | null>> | null;
private _addInProgress!: boolean;
private _emptyThreadsToAddQueue: [Range, IEditorMouseEvent | undefined][] = [];
private _emptyThreadsToAddQueue: [Range | undefined, IEditorMouseEvent | undefined][] = [];
private _computeCommentingRangePromise!: CancelablePromise<ICommentInfo[]> | null;
private _computeCommentingRangeScheduler!: Delayer<Array<ICommentInfo | null>> | null;
private _pendingNewCommentCache: { [key: string]: { [key: string]: string } };
Expand Down Expand Up @@ -764,13 +779,13 @@ export class CommentController implements IEditorContribution {
}
}

public async addOrToggleCommentAtLine(commentRange: Range, e: IEditorMouseEvent | undefined): Promise<void> {
public async addOrToggleCommentAtLine(commentRange: Range | undefined, e: IEditorMouseEvent | undefined): Promise<void> {
// If an add is already in progress, queue the next add and process it after the current one finishes to
// prevent empty comment threads from being added to the same line.
if (!this._addInProgress) {
this._addInProgress = true;
// The widget's position is undefined until the widget has been displayed, so rely on the glyph position instead
const existingCommentsAtLine = this._commentWidgets.filter(widget => widget.getGlyphPosition() === commentRange.endLineNumber);
const existingCommentsAtLine = this._commentWidgets.filter(widget => widget.getGlyphPosition() === (commentRange ? commentRange.endLineNumber : 0));
if (existingCommentsAtLine.length) {
const allExpanded = existingCommentsAtLine.every(widget => widget.expanded);
existingCommentsAtLine.forEach(allExpanded ? widget => widget.collapse() : widget => widget.expand());
Expand All @@ -792,14 +807,14 @@ export class CommentController implements IEditorContribution {
}
}

public addCommentAtLine(range: Range, e: IEditorMouseEvent | undefined): Promise<void> {
public addCommentAtLine(range: Range | undefined, e: IEditorMouseEvent | undefined): Promise<void> {
const newCommentInfos = this._commentingRangeDecorator.getMatchedCommentAction(range);
if (!newCommentInfos.length || !this.editor?.hasModel()) {
return Promise.resolve();
}

if (newCommentInfos.length > 1) {
if (e) {
if (e && range) {
const anchor = { x: e.event.posx, y: e.event.posy };

this.contextMenuService.showContextMenu({
Expand Down Expand Up @@ -868,7 +883,7 @@ export class CommentController implements IEditorContribution {
return actions;
}

public addCommentAtLine2(range: Range, ownerId: string) {
public addCommentAtLine2(range: Range | undefined, ownerId: string) {
if (!this.editor) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ActiveCursorHasCommentingRange, CommentController, ID } from 'vs/workbench/contrib/comments/browser/commentsController';
import { IRange, Range } from 'vs/editor/common/core/range';

export class NextCommentThreadAction extends EditorAction {
constructor() {
Expand Down Expand Up @@ -88,7 +89,7 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
const ADD_COMMENT_COMMAND = 'workbench.action.addComment';
CommandsRegistry.registerCommand({
id: ADD_COMMENT_COMMAND,
handler: (accessor) => {
handler: (accessor, args: { range: IRange; fileComment: boolean }) => {
const activeEditor = getActiveEditor(accessor);
if (!activeEditor) {
return Promise.resolve();
Expand All @@ -99,7 +100,8 @@ CommandsRegistry.registerCommand({
return Promise.resolve();
}

const position = activeEditor.getSelection();
const position = args.range ? new Range(args.range.startLineNumber, args.range.startLineNumber, args.range.endLineNumber, args.range.endColumn)
: (args.fileComment ? undefined : activeEditor.getSelection());
return controller.addOrToggleCommentAtLine(position, undefined);
}
});
Expand Down
7 changes: 7 additions & 0 deletions src/vscode-dts/vscode.proposed.fileComments.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,11 @@ declare module 'vscode' {
export interface CommentController {
createCommentThread(uri: Uri, range: Range | undefined, comments: readonly Comment[]): CommentThread | CommentThread2;
}

export interface CommentingRangeProvider2 {
/**
* Provide a list of ranges which allow new comment threads creation or null for a given document
*/
provideCommentingRanges(document: TextDocument, token: CancellationToken): ProviderResult<Range[] | { fileComments: boolean; ranges?: Range[] }>;
}
}

1 comment on commit 22c8efe

@vercel
Copy link

@vercel vercel bot commented on 22c8efe Mar 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

vscode – ./

vscode-git-main-1204183885.vercel.app
vscode-1204183885.vercel.app
vscode-rose.vercel.app

Please sign in to comment.