mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-30 16:50:30 -04:00
Merge from vscode 071a5cf16fc999727acc31c790d78f750fa4b166 (#5261)
This commit is contained in:
@@ -322,15 +322,17 @@ export class CommentService extends Disposable implements ICommentService {
|
||||
}
|
||||
}
|
||||
|
||||
let commentControlResult: Promise<ICommentInfo>[] = [];
|
||||
let commentControlResult: Promise<ICommentInfo | null>[] = [];
|
||||
|
||||
this._commentControls.forEach(control => {
|
||||
commentControlResult.push(control.getDocumentComments(resource, CancellationToken.None));
|
||||
commentControlResult.push(control.getDocumentComments(resource, CancellationToken.None)
|
||||
.catch(e => {
|
||||
console.log(e);
|
||||
return null;
|
||||
}));
|
||||
});
|
||||
|
||||
let ret = [...await Promise.all(result), ...await Promise.all(commentControlResult)];
|
||||
|
||||
return ret;
|
||||
return Promise.all([...result, ...commentControlResult]);
|
||||
}
|
||||
|
||||
async getCommentingRanges(resource: URI): Promise<IRange[]> {
|
||||
|
||||
@@ -212,6 +212,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
} else {
|
||||
const deleteCommand = (this._commentThread as modes.CommentThread2).deleteCommand;
|
||||
if (deleteCommand) {
|
||||
this.commentService.setActiveCommentThread(this._commentThread);
|
||||
return this.commandService.executeCommand(deleteCommand.id, ...(deleteCommand.arguments || []));
|
||||
}
|
||||
}
|
||||
@@ -239,7 +240,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
}
|
||||
}
|
||||
|
||||
async update(commentThread: modes.CommentThread | modes.CommentThread2) {
|
||||
async update(commentThread: modes.CommentThread | modes.CommentThread2, replaceTemplate: boolean = false) {
|
||||
const oldCommentsLen = this._commentElements.length;
|
||||
const newCommentsLen = commentThread.comments ? commentThread.comments.length : 0;
|
||||
|
||||
@@ -288,12 +289,20 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
|
||||
this._commentThread = commentThread;
|
||||
this._commentElements = newCommentNodeList;
|
||||
this.createThreadLabel();
|
||||
this.createThreadLabel(replaceTemplate);
|
||||
|
||||
if (replaceTemplate) {
|
||||
this.createTextModelListener();
|
||||
}
|
||||
|
||||
if (this._formActions && this._commentEditor.hasModel()) {
|
||||
dom.clearNode(this._formActions);
|
||||
const model = this._commentEditor.getModel();
|
||||
this.createCommentWidgetActions2(this._formActions, model);
|
||||
|
||||
if (replaceTemplate) {
|
||||
this.createCommentWidgetActionsListener(this._formActions, model);
|
||||
}
|
||||
}
|
||||
|
||||
// Move comment glyph widget and show position if the line has changed.
|
||||
@@ -348,7 +357,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
this._commentEditor.layout({ height: 5 * 18, width: widthInPixel - 54 /* margin 20px * 10 + scrollbar 14px*/ });
|
||||
}
|
||||
|
||||
display(lineNumber: number) {
|
||||
display(lineNumber: number, fromTemplate: boolean = false) {
|
||||
this._commentGlyph = new CommentGlyphWidget(this.editor, lineNumber);
|
||||
|
||||
this._disposables.push(this.editor.onMouseDown(e => this.onEditorMouseDown(e)));
|
||||
@@ -386,58 +395,8 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
this._commentEditor.setModel(model);
|
||||
this._disposables.push(this._commentEditor);
|
||||
this._disposables.push(this._commentEditor.getModel()!.onDidChangeContent(() => this.setCommentEditorDecorations()));
|
||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
||||
this._disposables.push(this._commentEditor.onDidFocusEditorWidget(() => {
|
||||
let commentThread = this._commentThread as modes.CommentThread2;
|
||||
commentThread.input = {
|
||||
uri: this._commentEditor.getModel()!.uri,
|
||||
value: this._commentEditor.getValue()
|
||||
};
|
||||
this.commentService.setActiveCommentThread(this._commentThread);
|
||||
}));
|
||||
|
||||
this._disposables.push(this._commentEditor.getModel()!.onDidChangeContent(() => {
|
||||
let modelContent = this._commentEditor.getValue();
|
||||
let thread = (this._commentThread as modes.CommentThread2);
|
||||
if (thread.input && thread.input.uri === this._commentEditor.getModel()!.uri && thread.input.value !== modelContent) {
|
||||
let newInput: modes.CommentInput = thread.input;
|
||||
newInput.value = modelContent;
|
||||
thread.input = newInput;
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeInput(input => {
|
||||
let thread = (this._commentThread as modes.CommentThread2);
|
||||
|
||||
if (thread.input && thread.input.uri !== this._commentEditor.getModel()!.uri) {
|
||||
return;
|
||||
}
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._commentEditor.getValue() !== input.value) {
|
||||
this._commentEditor.setValue(input.value);
|
||||
|
||||
if (input.value === '') {
|
||||
this._pendingComment = '';
|
||||
if (dom.hasClass(this._commentForm, 'expand')) {
|
||||
dom.removeClass(this._commentForm, 'expand');
|
||||
}
|
||||
this._commentEditor.getDomNode()!.style.outline = '';
|
||||
this._error.textContent = '';
|
||||
dom.addClass(this._error, 'hidden');
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeComments(async _ => {
|
||||
await this.update(this._commentThread);
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeLabel(_ => {
|
||||
this.createThreadLabel();
|
||||
}));
|
||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined && !fromTemplate) {
|
||||
this.createTextModelListener();
|
||||
}
|
||||
|
||||
this.setCommentEditorDecorations();
|
||||
@@ -456,50 +415,9 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
this._formActions = dom.append(this._commentForm, dom.$('.form-actions'));
|
||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
||||
this.createCommentWidgetActions2(this._formActions, model);
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeAcceptInputCommand(_ => {
|
||||
if (this._formActions) {
|
||||
dom.clearNode(this._formActions);
|
||||
this.createCommentWidgetActions2(this._formActions, model);
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeAdditionalCommands(_ => {
|
||||
if (this._formActions) {
|
||||
dom.clearNode(this._formActions);
|
||||
this.createCommentWidgetActions2(this._formActions, model);
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeRange(range => {
|
||||
// Move comment glyph widget and show position if the line has changed.
|
||||
const lineNumber = this._commentThread.range.startLineNumber;
|
||||
let shouldMoveWidget = false;
|
||||
if (this._commentGlyph) {
|
||||
if (this._commentGlyph.getPosition().position!.lineNumber !== lineNumber) {
|
||||
shouldMoveWidget = true;
|
||||
this._commentGlyph.setLineNumber(lineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldMoveWidget && this._isExpanded) {
|
||||
this.show({ lineNumber, column: 1 }, 2);
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeCollasibleState(state => {
|
||||
if (state === modes.CommentThreadCollapsibleState.Expanded && !this._isExpanded) {
|
||||
const lineNumber = this._commentThread.range.startLineNumber;
|
||||
|
||||
this.show({ lineNumber, column: 1 }, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state === modes.CommentThreadCollapsibleState.Collapsed && this._isExpanded) {
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
}));
|
||||
if (!fromTemplate) {
|
||||
this.createCommentWidgetActionsListener(this._formActions, model);
|
||||
}
|
||||
} else {
|
||||
this.createCommentWidgetActions(this._formActions, model);
|
||||
}
|
||||
@@ -526,6 +444,106 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
}
|
||||
}
|
||||
|
||||
private createTextModelListener() {
|
||||
this._disposables.push(this._commentEditor.onDidFocusEditorWidget(() => {
|
||||
let commentThread = this._commentThread as modes.CommentThread2;
|
||||
commentThread.input = {
|
||||
uri: this._commentEditor.getModel()!.uri,
|
||||
value: this._commentEditor.getValue()
|
||||
};
|
||||
this.commentService.setActiveCommentThread(this._commentThread);
|
||||
}));
|
||||
|
||||
this._disposables.push(this._commentEditor.getModel()!.onDidChangeContent(() => {
|
||||
let modelContent = this._commentEditor.getValue();
|
||||
let thread = (this._commentThread as modes.CommentThread2);
|
||||
if (thread.input && thread.input.uri === this._commentEditor.getModel()!.uri && thread.input.value !== modelContent) {
|
||||
let newInput: modes.CommentInput = thread.input;
|
||||
newInput.value = modelContent;
|
||||
thread.input = newInput;
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeInput(input => {
|
||||
let thread = (this._commentThread as modes.CommentThread2);
|
||||
|
||||
if (thread.input && thread.input.uri !== this._commentEditor.getModel()!.uri) {
|
||||
return;
|
||||
}
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._commentEditor.getValue() !== input.value) {
|
||||
this._commentEditor.setValue(input.value);
|
||||
|
||||
if (input.value === '') {
|
||||
this._pendingComment = '';
|
||||
if (dom.hasClass(this._commentForm, 'expand')) {
|
||||
dom.removeClass(this._commentForm, 'expand');
|
||||
}
|
||||
this._commentEditor.getDomNode()!.style.outline = '';
|
||||
this._error.textContent = '';
|
||||
dom.addClass(this._error, 'hidden');
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeComments(async _ => {
|
||||
await this.update(this._commentThread);
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeLabel(_ => {
|
||||
this.createThreadLabel();
|
||||
}));
|
||||
}
|
||||
|
||||
private createCommentWidgetActionsListener(container: HTMLElement, model: ITextModel) {
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeAcceptInputCommand(_ => {
|
||||
if (container) {
|
||||
dom.clearNode(container);
|
||||
this.createCommentWidgetActions2(container, model);
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeAdditionalCommands(_ => {
|
||||
if (container) {
|
||||
dom.clearNode(container);
|
||||
this.createCommentWidgetActions2(container, model);
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeRange(range => {
|
||||
// Move comment glyph widget and show position if the line has changed.
|
||||
const lineNumber = this._commentThread.range.startLineNumber;
|
||||
let shouldMoveWidget = false;
|
||||
if (this._commentGlyph) {
|
||||
if (this._commentGlyph.getPosition().position!.lineNumber !== lineNumber) {
|
||||
shouldMoveWidget = true;
|
||||
this._commentGlyph.setLineNumber(lineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldMoveWidget && this._isExpanded) {
|
||||
this.show({ lineNumber, column: 1 }, 2);
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeCollasibleState(state => {
|
||||
if (state === modes.CommentThreadCollapsibleState.Expanded && !this._isExpanded) {
|
||||
const lineNumber = this._commentThread.range.startLineNumber;
|
||||
|
||||
this.show({ lineNumber, column: 1 }, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state === modes.CommentThreadCollapsibleState.Collapsed && this._isExpanded) {
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private handleError(e: Error) {
|
||||
this._error.textContent = e.message;
|
||||
this._commentEditor.getDomNode()!.style.outline = `1px solid ${this.themeService.getTheme().getColor(inputValidationErrorBorder)}`;
|
||||
@@ -798,13 +816,14 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
}
|
||||
}
|
||||
|
||||
private createThreadLabel() {
|
||||
private createThreadLabel(replaceTemplate: boolean = false) {
|
||||
let label: string | undefined;
|
||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
||||
label = (this._commentThread as modes.CommentThread2).label;
|
||||
}
|
||||
|
||||
if (label === undefined) {
|
||||
if (label === undefined && !replaceTemplate) {
|
||||
// if it's for replacing the comment thread template, the comment thread widget title can be undefined as extensions may set it later
|
||||
if (this._commentThread.comments && this._commentThread.comments.length) {
|
||||
const participantsList = this._commentThread.comments.filter(arrays.uniqueFilter(comment => comment.userName)).map(comment => `@${comment.userName}`).join(', ');
|
||||
label = nls.localize('commentThreadParticipants', "Participants: {0}", participantsList);
|
||||
@@ -813,8 +832,11 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
}
|
||||
}
|
||||
|
||||
this._headingLabel.innerHTML = strings.escape(label);
|
||||
this._headingLabel.setAttribute('aria-label', label);
|
||||
if (label) {
|
||||
this._headingLabel.innerHTML = strings.escape(label);
|
||||
this._headingLabel.setAttribute('aria-label', label);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private expandReplyArea() {
|
||||
|
||||
@@ -30,7 +30,7 @@ import { CancelablePromise, createCancelablePromise, Delayer } from 'vs/base/com
|
||||
import { overviewRulerCommentingRangeForeground } from 'vs/workbench/contrib/comments/browser/commentGlyphWidget';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { STATUS_BAR_ITEM_HOVER_BACKGROUND, STATUS_BAR_ITEM_ACTIVE_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ctxCommentEditorFocused, SimpleCommentEditor } from 'vs/workbench/contrib/comments/browser/simpleCommentEditor';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
@@ -64,7 +64,7 @@ class CommentingRangeDecoration {
|
||||
return this._decorationId;
|
||||
}
|
||||
|
||||
constructor(private _editor: ICodeEditor, private _ownerId: string, private _extensionId: string | undefined, private _label: string | undefined, private _range: IRange, private _reply: modes.Command | undefined, commentingOptions: ModelDecorationOptions, private commentingRangesInfo?: modes.CommentingRanges) {
|
||||
constructor(private _editor: ICodeEditor, private _ownerId: string, private _extensionId: string | undefined, private _label: string | undefined, private _range: IRange, private _reply: modes.Command | undefined, commentingOptions: ModelDecorationOptions, private _template: modes.CommentThreadTemplate | undefined, private commentingRangesInfo?: modes.CommentingRanges) {
|
||||
const startLineNumber = _range.startLineNumber;
|
||||
const endLineNumber = _range.endLineNumber;
|
||||
let commentingRangeDecorations = [{
|
||||
@@ -81,13 +81,14 @@ class CommentingRangeDecoration {
|
||||
}
|
||||
}
|
||||
|
||||
public getCommentAction(): { replyCommand: modes.Command | undefined, ownerId: string, extensionId: string | undefined, label: string | undefined, commentingRangesInfo: modes.CommentingRanges | undefined } {
|
||||
public getCommentAction(): { replyCommand: modes.Command | undefined, ownerId: string, extensionId: string | undefined, label: string | undefined, commentingRangesInfo: modes.CommentingRanges | undefined, template: modes.CommentThreadTemplate | undefined } {
|
||||
return {
|
||||
extensionId: this._extensionId,
|
||||
label: this._label,
|
||||
replyCommand: this._reply,
|
||||
ownerId: this._ownerId,
|
||||
commentingRangesInfo: this.commentingRangesInfo
|
||||
commentingRangesInfo: this.commentingRangesInfo,
|
||||
template: this._template
|
||||
};
|
||||
}
|
||||
|
||||
@@ -124,11 +125,11 @@ class CommentingRangeDecorator {
|
||||
for (const info of commentInfos) {
|
||||
if (Array.isArray(info.commentingRanges)) {
|
||||
info.commentingRanges.forEach(range => {
|
||||
commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, range, info.reply, this.decorationOptions));
|
||||
commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, range, info.reply, this.decorationOptions, info.template));
|
||||
});
|
||||
} else {
|
||||
(info.commentingRanges ? info.commentingRanges.ranges : []).forEach(range => {
|
||||
commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, range, (info.commentingRanges as modes.CommentingRanges).newCommentThreadCommand, this.decorationOptions, info.commentingRanges as modes.CommentingRanges));
|
||||
commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, range, undefined, this.decorationOptions, info.template, info.commentingRanges as modes.CommentingRanges));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -178,7 +179,6 @@ export class ReviewController implements IEditorContribution {
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@ICommentService private readonly commentService: ICommentService,
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@ICodeEditorService private readonly codeEditorService: ICodeEditorService,
|
||||
@@ -441,6 +441,11 @@ export class ReviewController implements IEditorContribution {
|
||||
}
|
||||
});
|
||||
added.forEach(thread => {
|
||||
let matchedZones = this._commentWidgets.filter(zoneWidget => zoneWidget.owner === e.owner && zoneWidget.commentThread.threadId === thread.threadId);
|
||||
if (matchedZones.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pendingCommentText = this._pendingCommentCache[e.owner] && this._pendingCommentCache[e.owner][thread.threadId];
|
||||
this.displayCommentThread(e.owner, thread, pendingCommentText, draftMode);
|
||||
this._commentInfos.filter(info => info.owner === e.owner)[0].threads.push(thread);
|
||||
@@ -457,6 +462,30 @@ export class ReviewController implements IEditorContribution {
|
||||
this._commentWidgets.push(zoneWidget);
|
||||
}
|
||||
|
||||
private addCommentThreadFromTemplate(lineNumber: number, ownerId: string, extensionId: string | undefined, template: modes.CommentThreadTemplate): ReviewZoneWidget {
|
||||
let templateReviewZoneWidget = this.instantiationService.createInstance(ReviewZoneWidget, this.editor, ownerId, {
|
||||
commentThreadHandle: -1,
|
||||
label: template!.label,
|
||||
acceptInputCommand: template.acceptInputCommand,
|
||||
additionalCommands: template.additionalCommands,
|
||||
deleteCommand: template.deleteCommand,
|
||||
extensionId: extensionId,
|
||||
threadId: null,
|
||||
resource: null,
|
||||
comments: [],
|
||||
range: {
|
||||
startLineNumber: lineNumber,
|
||||
startColumn: 0,
|
||||
endLineNumber: lineNumber,
|
||||
endColumn: 0
|
||||
},
|
||||
collapsibleState: modes.CommentThreadCollapsibleState.Expanded,
|
||||
},
|
||||
'', modes.DraftMode.NotSupported);
|
||||
|
||||
return templateReviewZoneWidget;
|
||||
}
|
||||
|
||||
private addComment(lineNumber: number, replyCommand: modes.Command | undefined, ownerId: string, extensionId: string | undefined, draftMode: modes.DraftMode | undefined, pendingComment: string | null) {
|
||||
if (this._newCommentWidget) {
|
||||
this.notificationService.warn(`Please submit the comment at line ${this._newCommentWidget.position ? this._newCommentWidget.position.lineNumber : -1} before creating a new one.`);
|
||||
@@ -612,16 +641,16 @@ export class ReviewController implements IEditorContribution {
|
||||
const commentInfos = newCommentInfos.filter(info => info.ownerId === pick.id);
|
||||
|
||||
if (commentInfos.length) {
|
||||
const { replyCommand, ownerId, extensionId, commentingRangesInfo } = commentInfos[0];
|
||||
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo);
|
||||
const { replyCommand, ownerId, extensionId, commentingRangesInfo, template } = commentInfos[0];
|
||||
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo, template);
|
||||
}
|
||||
}).then(() => {
|
||||
this._addInProgress = false;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const { replyCommand, ownerId, extensionId, commentingRangesInfo } = newCommentInfos[0]!;
|
||||
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo);
|
||||
const { replyCommand, ownerId, extensionId, commentingRangesInfo, template } = newCommentInfos[0]!;
|
||||
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo, template);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
@@ -640,11 +669,11 @@ export class ReviewController implements IEditorContribution {
|
||||
return picks;
|
||||
}
|
||||
|
||||
private getContextMenuActions(commentInfos: { replyCommand: modes.Command | undefined, ownerId: string, extensionId: string | undefined, label: string | undefined, commentingRangesInfo: modes.CommentingRanges | undefined }[], lineNumber: number): (IAction | ContextSubMenu)[] {
|
||||
private getContextMenuActions(commentInfos: { replyCommand: modes.Command | undefined, ownerId: string, extensionId: string | undefined, label: string | undefined, commentingRangesInfo: modes.CommentingRanges | undefined, template: modes.CommentThreadTemplate | undefined }[], lineNumber: number): (IAction | ContextSubMenu)[] {
|
||||
const actions: (IAction | ContextSubMenu)[] = [];
|
||||
|
||||
commentInfos.forEach(commentInfo => {
|
||||
const { replyCommand, ownerId, extensionId, label, commentingRangesInfo } = commentInfo;
|
||||
const { replyCommand, ownerId, extensionId, label, commentingRangesInfo, template } = commentInfo;
|
||||
|
||||
actions.push(new Action(
|
||||
'addCommentThread',
|
||||
@@ -652,7 +681,7 @@ export class ReviewController implements IEditorContribution {
|
||||
undefined,
|
||||
true,
|
||||
() => {
|
||||
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo);
|
||||
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo, template);
|
||||
return Promise.resolve();
|
||||
}
|
||||
));
|
||||
@@ -660,17 +689,25 @@ export class ReviewController implements IEditorContribution {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public addCommentAtLine2(lineNumber: number, replyCommand: modes.Command | undefined, ownerId: string, extensionId: string | undefined, commentingRangesInfo: modes.CommentingRanges | undefined) {
|
||||
public addCommentAtLine2(lineNumber: number, replyCommand: modes.Command | undefined, ownerId: string, extensionId: string | undefined, commentingRangesInfo: modes.CommentingRanges | undefined, template: modes.CommentThreadTemplate | undefined) {
|
||||
if (commentingRangesInfo) {
|
||||
let range = new Range(lineNumber, 1, lineNumber, 1);
|
||||
if (commentingRangesInfo.newCommentThreadCommand) {
|
||||
if (replyCommand) {
|
||||
const commandId = replyCommand.id;
|
||||
const args = replyCommand.arguments || [];
|
||||
if (commentingRangesInfo.newCommentThreadCallback && template) {
|
||||
// create comment widget through template
|
||||
let commentThreadWidget = this.addCommentThreadFromTemplate(lineNumber, ownerId, extensionId, template);
|
||||
commentThreadWidget.display(lineNumber, true);
|
||||
|
||||
this._commandService.executeCommand(commandId, ...args);
|
||||
this._addInProgress = false;
|
||||
}
|
||||
return commentingRangesInfo.newCommentThreadCallback(this.editor.getModel()!.uri, range)
|
||||
.then(commentThread => {
|
||||
commentThreadWidget.update(commentThread!, true);
|
||||
this._commentWidgets.push(commentThreadWidget);
|
||||
this.processNextThreadToAdd();
|
||||
})
|
||||
.catch(e => {
|
||||
this.notificationService.error(nls.localize('commentThreadAddFailure', "Adding a new comment thread failed: {0}.", e.message));
|
||||
commentThreadWidget.dispose();
|
||||
this.processNextThreadToAdd();
|
||||
});
|
||||
} else if (commentingRangesInfo.newCommentThreadCallback) {
|
||||
return commentingRangesInfo.newCommentThreadCallback(this.editor.getModel()!.uri, range)
|
||||
.then(_ => {
|
||||
|
||||
@@ -13,7 +13,7 @@ import { IExtensionManagementServerService, IExtensionTipsService } from 'vs/pla
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { extensionButtonProminentBackground, extensionButtonProminentForeground, DisabledLabelAction, ReloadAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
|
||||
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
||||
import { STATUS_BAR_HOST_NAME_BACKGROUND, STATUS_BAR_HOST_NAME_FOREGROUND } from 'vs/workbench/common/theme';
|
||||
import { EXTENSION_BADGE_REMOTE_BACKGROUND, EXTENSION_BADGE_REMOTE_FOREGROUND } from 'vs/workbench/common/theme';
|
||||
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
@@ -323,8 +323,8 @@ class RemoteBadge extends Disposable {
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
const bgColor = this.themeService.getTheme().getColor(STATUS_BAR_HOST_NAME_BACKGROUND);
|
||||
const fgColor = this.themeService.getTheme().getColor(STATUS_BAR_HOST_NAME_FOREGROUND);
|
||||
const bgColor = this.themeService.getTheme().getColor(EXTENSION_BADGE_REMOTE_BACKGROUND);
|
||||
const fgColor = this.themeService.getTheme().getColor(EXTENSION_BADGE_REMOTE_FOREGROUND);
|
||||
this.element.style.backgroundColor = bgColor ? bgColor.toString() : '';
|
||||
this.element.style.color = fgColor ? fgColor.toString() : '';
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ import { ResourceMap } from 'vs/base/common/map';
|
||||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
|
||||
import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { FileOnDiskContentProvider } from 'vs/workbench/contrib/files/common/files';
|
||||
import { FileOnDiskContentProvider, resourceToFileOnDisk } from 'vs/workbench/contrib/files/common/files';
|
||||
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { SAVE_FILE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL } from 'vs/workbench/contrib/files/browser/fileCommands';
|
||||
@@ -248,7 +248,7 @@ class ResolveSaveConflictAction extends Action {
|
||||
|
||||
return this.editorService.openEditor(
|
||||
{
|
||||
leftResource: resource.with({ scheme: CONFLICT_RESOLUTION_SCHEME }),
|
||||
leftResource: resourceToFileOnDisk(CONFLICT_RESOLUTION_SCHEME, resource),
|
||||
rightResource: resource,
|
||||
label: editorLabel,
|
||||
options: { pinned: true }
|
||||
|
||||
@@ -23,8 +23,6 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
|
||||
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel';
|
||||
import { once } from 'vs/base/common/functional';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { toLocalResource } from 'vs/base/common/resources';
|
||||
|
||||
/**
|
||||
* Explorer viewlet id.
|
||||
@@ -133,6 +131,14 @@ export const SortOrderConfiguration = {
|
||||
|
||||
export type SortOrder = 'default' | 'mixed' | 'filesFirst' | 'type' | 'modified';
|
||||
|
||||
export function resourceToFileOnDisk(scheme: string, resource: URI): URI {
|
||||
return resource.with({ scheme, query: JSON.stringify({ scheme: resource.scheme }) });
|
||||
}
|
||||
|
||||
export function fileOnDiskToResource(resource: URI): URI {
|
||||
return resource.with({ scheme: JSON.parse(resource.query)['scheme'], query: null });
|
||||
}
|
||||
|
||||
export class FileOnDiskContentProvider implements ITextModelContentProvider {
|
||||
private fileWatcherDisposable: IDisposable | undefined;
|
||||
|
||||
@@ -140,13 +146,12 @@ export class FileOnDiskContentProvider implements ITextModelContentProvider {
|
||||
@ITextFileService private readonly textFileService: ITextFileService,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService
|
||||
@IModelService private readonly modelService: IModelService
|
||||
) {
|
||||
}
|
||||
|
||||
provideTextContent(resource: URI): Promise<ITextModel> {
|
||||
const savedFileResource = toLocalResource(resource, this.environmentService.configuration.remoteAuthority);
|
||||
const savedFileResource = fileOnDiskToResource(resource);
|
||||
|
||||
// Make sure our file from disk is resolved up to date
|
||||
return this.resolveEditorModel(resource).then(codeEditorModel => {
|
||||
@@ -174,7 +179,7 @@ export class FileOnDiskContentProvider implements ITextModelContentProvider {
|
||||
private resolveEditorModel(resource: URI, createAsNeeded?: true): Promise<ITextModel>;
|
||||
private resolveEditorModel(resource: URI, createAsNeeded?: boolean): Promise<ITextModel | null>;
|
||||
private resolveEditorModel(resource: URI, createAsNeeded: boolean = true): Promise<ITextModel | null> {
|
||||
const savedFileResource = toLocalResource(resource, this.environmentService.configuration.remoteAuthority);
|
||||
const savedFileResource = fileOnDiskToResource(resource);
|
||||
|
||||
return this.textFileService.readStream(savedFileResource).then(content => {
|
||||
let codeEditorModel = this.modelService.getModel(resource);
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { workbenchInstantiationService, TestFileService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { FileOnDiskContentProvider, resourceToFileOnDisk } from 'vs/workbench/contrib/files/common/files';
|
||||
import { snapshotToString } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
|
||||
class ServiceAccessor {
|
||||
constructor(
|
||||
@IFileService public fileService: TestFileService
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
suite('Files - FileOnDiskContentProvider', () => {
|
||||
|
||||
let instantiationService: IInstantiationService;
|
||||
let accessor: ServiceAccessor;
|
||||
|
||||
setup(() => {
|
||||
instantiationService = workbenchInstantiationService();
|
||||
accessor = instantiationService.createInstance(ServiceAccessor);
|
||||
});
|
||||
|
||||
test('provideTextContent', async () => {
|
||||
const provider = instantiationService.createInstance(FileOnDiskContentProvider);
|
||||
const uri = URI.parse('testFileOnDiskContentProvider://foo');
|
||||
|
||||
const content = await provider.provideTextContent(resourceToFileOnDisk('conflictResolution', uri));
|
||||
|
||||
assert.equal(snapshotToString(content.createSnapshot()), 'Hello Html');
|
||||
assert.equal(accessor.fileService.getLastReadFileUri().toString(), uri.toString());
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user