mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Merge from vscode 071a5cf16fc999727acc31c790d78f750fa4b166 (#5261)
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const ts = require("typescript");
|
const ts = require("typescript");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/*----------------------------------------------------------
|
/*----------------------------------------------------------
|
||||||
|
|||||||
@@ -1211,6 +1211,16 @@ export interface Command {
|
|||||||
arguments?: any[];
|
arguments?: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export interface CommentThreadTemplate {
|
||||||
|
label: string;
|
||||||
|
acceptInputCommand?: Command;
|
||||||
|
additionalCommands?: Command[];
|
||||||
|
deleteCommand?: Command;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
@@ -1220,6 +1230,7 @@ export interface CommentInfo {
|
|||||||
commentingRanges?: (IRange[] | CommentingRanges);
|
commentingRanges?: (IRange[] | CommentingRanges);
|
||||||
reply?: Command;
|
reply?: Command;
|
||||||
draftMode?: DraftMode;
|
draftMode?: DraftMode;
|
||||||
|
template?: CommentThreadTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1298,8 +1309,7 @@ export interface CommentThread2 {
|
|||||||
export interface CommentingRanges {
|
export interface CommentingRanges {
|
||||||
readonly resource: URI;
|
readonly resource: URI;
|
||||||
ranges: IRange[];
|
ranges: IRange[];
|
||||||
newCommentThreadCommand?: Command;
|
newCommentThreadCallback?: (uri: UriComponents, range: IRange) => Promise<CommentThread | undefined>;
|
||||||
newCommentThreadCallback?: (uri: UriComponents, range: IRange) => Promise<void>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import { ContextKeyExpr, IContextKey, IContextKeyService, RawContextKey } from '
|
|||||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||||
import { ILogService } from 'vs/platform/log/common/log';
|
import { ILogService } from 'vs/platform/log/common/log';
|
||||||
import { SnippetSession } from './snippetSession';
|
import { SnippetSession } from './snippetSession';
|
||||||
import { EditorState, CodeEditorStateFlag } from 'vs/editor/browser/core/editorState';
|
|
||||||
|
|
||||||
export class SnippetController2 implements IEditorContribution {
|
export class SnippetController2 implements IEditorContribution {
|
||||||
|
|
||||||
@@ -114,26 +113,10 @@ export class SnippetController2 implements IEditorContribution {
|
|||||||
|
|
||||||
this._updateState();
|
this._updateState();
|
||||||
|
|
||||||
// we listen on model and selection changes. usually
|
|
||||||
// both events come in together and this is to prevent
|
|
||||||
// that we don't call _updateState twice.
|
|
||||||
let state: EditorState;
|
|
||||||
let dedupedUpdateState = () => {
|
|
||||||
if (!state || !state.validate(this._editor)) {
|
|
||||||
this._updateState();
|
|
||||||
state = new EditorState(this._editor, CodeEditorStateFlag.Selection | CodeEditorStateFlag.Value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this._snippetListener = [
|
this._snippetListener = [
|
||||||
this._editor.onDidChangeModelContent(e => {
|
this._editor.onDidChangeModelContent(e => e.isFlush && this.cancel()),
|
||||||
if (e.isFlush) {
|
|
||||||
this.cancel();
|
|
||||||
} else {
|
|
||||||
setTimeout(dedupedUpdateState, 0);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
this._editor.onDidChangeCursorSelection(dedupedUpdateState),
|
|
||||||
this._editor.onDidChangeModel(() => this.cancel()),
|
this._editor.onDidChangeModel(() => this.cancel()),
|
||||||
|
this._editor.onDidChangeCursorSelection(() => this._updateState())
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -198,6 +198,10 @@ export class OneSnippet {
|
|||||||
let ranges: Range[] | undefined;
|
let ranges: Range[] | undefined;
|
||||||
|
|
||||||
for (const placeholder of placeholdersWithEqualIndex) {
|
for (const placeholder of placeholdersWithEqualIndex) {
|
||||||
|
if (placeholder.isFinalTabstop) {
|
||||||
|
// ignore those
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ranges) {
|
if (!ranges) {
|
||||||
ranges = [];
|
ranges = [];
|
||||||
@@ -571,12 +575,6 @@ export class SnippetSession {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allPossibleSelections.has(0)) {
|
|
||||||
// selection overlaps with a final tab stop which means
|
|
||||||
// we done
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add selections from 'this' snippet so that we know all
|
// add selections from 'this' snippet so that we know all
|
||||||
// selections for this placeholder
|
// selections for this placeholder
|
||||||
allPossibleSelections.forEach((array, index) => {
|
allPossibleSelections.forEach((array, index) => {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKe
|
|||||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||||
import { NullLogService } from 'vs/platform/log/common/log';
|
import { NullLogService } from 'vs/platform/log/common/log';
|
||||||
import { Handler } from 'vs/editor/common/editorCommon';
|
import { Handler } from 'vs/editor/common/editorCommon';
|
||||||
import { timeout } from 'vs/base/common/async';
|
|
||||||
|
|
||||||
suite('SnippetController2', function () {
|
suite('SnippetController2', function () {
|
||||||
|
|
||||||
@@ -134,11 +133,11 @@ suite('SnippetController2', function () {
|
|||||||
assertSelections(editor, new Selection(1, 1, 1, 7), new Selection(2, 5, 2, 11));
|
assertSelections(editor, new Selection(1, 1, 1, 7), new Selection(2, 5, 2, 11));
|
||||||
|
|
||||||
editor.trigger('test', 'cut', {});
|
editor.trigger('test', 'cut', {});
|
||||||
assertContextKeys(contextKeys, false, false, false);
|
assertContextKeys(contextKeys, true, false, true);
|
||||||
assertSelections(editor, new Selection(1, 1, 1, 1), new Selection(2, 5, 2, 5));
|
assertSelections(editor, new Selection(1, 1, 1, 1), new Selection(2, 5, 2, 5));
|
||||||
|
|
||||||
editor.trigger('test', 'type', { text: 'abc' });
|
editor.trigger('test', 'type', { text: 'abc' });
|
||||||
assertContextKeys(contextKeys, false, false, false);
|
assertContextKeys(contextKeys, true, false, true);
|
||||||
|
|
||||||
ctrl.next();
|
ctrl.next();
|
||||||
assertContextKeys(contextKeys, false, false, false);
|
assertContextKeys(contextKeys, false, false, false);
|
||||||
@@ -160,9 +159,9 @@ suite('SnippetController2', function () {
|
|||||||
assertSelections(editor, new Selection(1, 4, 1, 4), new Selection(2, 8, 2, 8));
|
assertSelections(editor, new Selection(1, 4, 1, 4), new Selection(2, 8, 2, 8));
|
||||||
assertContextKeys(contextKeys, true, false, true);
|
assertContextKeys(contextKeys, true, false, true);
|
||||||
|
|
||||||
// ctrl.next();
|
ctrl.next();
|
||||||
// assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11));
|
assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11));
|
||||||
// assertContextKeys(contextKeys, true, true, true);
|
assertContextKeys(contextKeys, true, true, true);
|
||||||
|
|
||||||
ctrl.next();
|
ctrl.next();
|
||||||
assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11));
|
assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11));
|
||||||
@@ -177,10 +176,10 @@ suite('SnippetController2', function () {
|
|||||||
|
|
||||||
ctrl.insert('farboo');
|
ctrl.insert('farboo');
|
||||||
assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11));
|
assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11));
|
||||||
// assertContextKeys(contextKeys, true, false, true);
|
assertContextKeys(contextKeys, true, false, true);
|
||||||
|
|
||||||
// ctrl.next();
|
ctrl.next();
|
||||||
// assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11));
|
assertSelections(editor, new Selection(1, 7, 1, 7), new Selection(2, 11, 2, 11));
|
||||||
assertContextKeys(contextKeys, false, false, false);
|
assertContextKeys(contextKeys, false, false, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -403,22 +402,12 @@ suite('SnippetController2', function () {
|
|||||||
assertSelections(editor, new Selection(1, 22, 1, 22));
|
assertSelections(editor, new Selection(1, 22, 1, 22));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('A little confusing visual effect of highlighting for snippet tabstop #43270', async function () {
|
test('User defined snippet tab stops ignored #72862', function () {
|
||||||
const ctrl = new SnippetController2(editor, logService, contextKeys);
|
const ctrl = new SnippetController2(editor, logService, contextKeys);
|
||||||
model.setValue('');
|
model.setValue('');
|
||||||
editor.setSelection(new Selection(1, 1, 1, 1));
|
editor.setSelection(new Selection(1, 1, 1, 1));
|
||||||
|
|
||||||
ctrl.insert('background-color: ${1:fff};$0');
|
ctrl.insert('export default $1');
|
||||||
assertSelections(editor, new Selection(1, 19, 1, 22));
|
|
||||||
|
|
||||||
editor.setSelection(new Selection(1, 22, 1, 22));
|
|
||||||
assertContextKeys(contextKeys, true, false, true);
|
assertContextKeys(contextKeys, true, false, true);
|
||||||
editor.trigger('', 'deleteRight', null);
|
|
||||||
|
|
||||||
assert.equal(model.getValue(), 'background-color: fff');
|
|
||||||
|
|
||||||
await timeout(0); // this depends on re-scheduling of events...
|
|
||||||
|
|
||||||
assertContextKeys(contextKeys, false, false, false);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ suite('SnippetSession', function () {
|
|||||||
|
|
||||||
// reset selection to placeholder
|
// reset selection to placeholder
|
||||||
session.next();
|
session.next();
|
||||||
assert.equal(session.isSelectionWithinPlaceholders(), false);
|
assert.equal(session.isSelectionWithinPlaceholders(), true);
|
||||||
assert.equal(session.isAtLastPlaceholder, true);
|
assert.equal(session.isAtLastPlaceholder, true);
|
||||||
assertSelections(editor, new Selection(1, 13, 1, 13), new Selection(2, 17, 2, 17));
|
assertSelections(editor, new Selection(1, 13, 1, 13), new Selection(2, 17, 2, 17));
|
||||||
});
|
});
|
||||||
|
|||||||
107
src/vs/vscode.proposed.d.ts
vendored
107
src/vs/vscode.proposed.d.ts
vendored
@@ -814,28 +814,35 @@ declare module 'vscode' {
|
|||||||
/**
|
/**
|
||||||
* A comment is displayed within the editor or the Comments Panel, depending on how it is provided.
|
* A comment is displayed within the editor or the Comments Panel, depending on how it is provided.
|
||||||
*/
|
*/
|
||||||
export interface Comment {
|
export class Comment {
|
||||||
/**
|
/**
|
||||||
* The id of the comment
|
* The id of the comment
|
||||||
*/
|
*/
|
||||||
|
readonly id: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id of the comment
|
||||||
|
*
|
||||||
|
* @deprecated Use Id instead
|
||||||
|
*/
|
||||||
readonly commentId: string;
|
readonly commentId: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The text of the comment
|
* The human-readable comment body
|
||||||
*/
|
*/
|
||||||
readonly body: MarkdownString;
|
readonly body: MarkdownString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The display name of the user who created the comment
|
||||||
|
*/
|
||||||
|
readonly userName: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional label describing the [Comment](#Comment)
|
* Optional label describing the [Comment](#Comment)
|
||||||
* Label will be rendered next to userName if exists.
|
* Label will be rendered next to userName if exists.
|
||||||
*/
|
*/
|
||||||
readonly label?: string;
|
readonly label?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The display name of the user who created the comment
|
|
||||||
*/
|
|
||||||
readonly userName: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The icon path for the user who created the comment
|
* The icon path for the user who created the comment
|
||||||
*/
|
*/
|
||||||
@@ -896,6 +903,13 @@ declare module 'vscode' {
|
|||||||
* Proposed Comment Reaction
|
* Proposed Comment Reaction
|
||||||
*/
|
*/
|
||||||
commentReactions?: CommentReaction[];
|
commentReactions?: CommentReaction[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id The id of the comment
|
||||||
|
* @param body The human-readable comment body
|
||||||
|
* @param userName The display name of the user who created the comment
|
||||||
|
*/
|
||||||
|
constructor(id: string, body: MarkdownString, userName: string);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -925,6 +939,7 @@ declare module 'vscode' {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Comment Reactions
|
* Comment Reactions
|
||||||
|
* Stay in proposed.
|
||||||
*/
|
*/
|
||||||
interface CommentReaction {
|
interface CommentReaction {
|
||||||
readonly label?: string;
|
readonly label?: string;
|
||||||
@@ -1006,6 +1021,9 @@ declare module 'vscode' {
|
|||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stay in proposed
|
||||||
|
*/
|
||||||
export interface CommentReactionProvider {
|
export interface CommentReactionProvider {
|
||||||
availableReactions: CommentReaction[];
|
availableReactions: CommentReaction[];
|
||||||
toggleReaction?(document: TextDocument, comment: Comment, reaction: CommentReaction): Promise<void>;
|
toggleReaction?(document: TextDocument, comment: Comment, reaction: CommentReaction): Promise<void>;
|
||||||
@@ -1016,12 +1034,50 @@ declare module 'vscode' {
|
|||||||
* Provide a list of ranges which allow new comment threads creation or null for a given document
|
* Provide a list of ranges which allow new comment threads creation or null for a given document
|
||||||
*/
|
*/
|
||||||
provideCommentingRanges(document: TextDocument, token: CancellationToken): ProviderResult<Range[]>;
|
provideCommentingRanges(document: TextDocument, token: CancellationToken): ProviderResult<Range[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CommentThreadTemplate {
|
||||||
|
/**
|
||||||
|
* The human-readable label describing the [Comment Thread](#CommentThread)
|
||||||
|
*/
|
||||||
|
label: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method `createEmptyCommentThread` is called when users attempt to create new comment thread from the gutter or command palette.
|
* Optional accept input command
|
||||||
* Extensions still need to call `createCommentThread` inside this call when appropriate.
|
*
|
||||||
|
* `acceptInputCommand` is the default action rendered on Comment Widget, which is always placed rightmost.
|
||||||
|
* This command will be invoked when users the user accepts the value in the comment editor.
|
||||||
|
* This command will disabled when the comment editor is empty.
|
||||||
*/
|
*/
|
||||||
createEmptyCommentThread(document: TextDocument, range: Range): ProviderResult<void>;
|
acceptInputCommand?: Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional additonal commands.
|
||||||
|
*
|
||||||
|
* `additionalCommands` are the secondary actions rendered on Comment Widget.
|
||||||
|
*/
|
||||||
|
additionalCommands?: Command[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command to be executed when users try to delete the comment thread. Currently, this is only called
|
||||||
|
* when the user collapses a comment thread that has no comments in it.
|
||||||
|
*/
|
||||||
|
deleteCommand?: Command;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EmptyCommentThreadFactory {
|
||||||
|
template: CommentThreadTemplate;
|
||||||
|
/**
|
||||||
|
* When users attempt to create new comment thread from the gutter or command palette, `template` will be used first to create the Comment Thread Widget in the editor for users to start comment drafting.
|
||||||
|
* Then `createEmptyCommentThread` is called after that. Extensions should still call [`createCommentThread`](CommentController.createCommentThread) to create a real [`CommentThread`](#CommentThread)
|
||||||
|
* Extensions still need to call `createCommentThread` inside this call when appropriate.
|
||||||
|
*
|
||||||
|
* @param document The document in which users attempt to create a new comment thread
|
||||||
|
* @param range The range the comment threadill located within the document.
|
||||||
|
*
|
||||||
|
* @returns commentThread The [`CommentThread`](#CommentThread) created by extensions
|
||||||
|
*/
|
||||||
|
createEmptyCommentThread(document: TextDocument, range: Range): ProviderResult<CommentThread>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CommentController {
|
export interface CommentController {
|
||||||
@@ -1036,23 +1092,44 @@ declare module 'vscode' {
|
|||||||
readonly label: string;
|
readonly label: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The active (focused) [comment input box](#CommentInputBox).
|
* The active [comment input box](#CommentInputBox) or `undefined`. The active `inputBox` is the input box of
|
||||||
|
* the comment thread widget that currently has focus. It's `undefined` when the focus is not in any CommentInputBox.
|
||||||
*/
|
*/
|
||||||
readonly inputBox?: CommentInputBox;
|
readonly inputBox: CommentInputBox | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a [CommentThread](#CommentThread)
|
* The active [comment thread](#CommentThread) or `undefined`. The `activeCommentThread` is the comment thread of
|
||||||
|
* the comment thread widget that currently has focus. It's `undefined` when the focus is not in any comment thread widget.
|
||||||
|
*/
|
||||||
|
readonly activeCommentThread: CommentThread | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a [CommentThread](#CommentThread). The comment thread will be displayed in visible text editors (if the resource matches)
|
||||||
|
* and Comments Panel.
|
||||||
|
* @param id An `id` for the comment thread.
|
||||||
|
* @param resource The uri of the document the thread has been created on.
|
||||||
|
* @param range The range the comment thread is located within the document.
|
||||||
|
* @param comments The ordered comments of the thread.
|
||||||
*/
|
*/
|
||||||
createCommentThread(id: string, resource: Uri, range: Range, comments: Comment[]): CommentThread;
|
createCommentThread(id: string, resource: Uri, range: Range, comments: Comment[]): CommentThread;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional commenting range provider.
|
* Optional commenting range provider. Provide a list [ranges](#Range) which support commenting to any given resource uri.
|
||||||
* Provide a list [ranges](#Range) which support commenting to any given resource uri.
|
*
|
||||||
|
* If not provided and `emptyCommentThreadFactory` exits, users can leave comments in any document opened in the editor.
|
||||||
*/
|
*/
|
||||||
commentingRangeProvider?: CommentingRangeProvider;
|
commentingRangeProvider?: CommentingRangeProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional empty comment thread factory. It's necessary for supporting users to trigger Comment Thread creation from the editor or command palette.
|
||||||
|
*
|
||||||
|
* If not provided, users won't be able to trigger new comment thread creation from the editor gutter area or command palette.
|
||||||
|
*/
|
||||||
|
emptyCommentThreadFactory?: EmptyCommentThreadFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional reaction provider
|
* Optional reaction provider
|
||||||
|
* Stay in proposed.
|
||||||
*/
|
*/
|
||||||
reactionProvider?: CommentReactionProvider;
|
reactionProvider?: CommentReactionProvider;
|
||||||
|
|
||||||
|
|||||||
@@ -298,12 +298,18 @@ export class MainThreadCommentController {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this._threads.set(commentThreadHandle, thread);
|
this._threads.set(commentThreadHandle, thread);
|
||||||
this._commentService.updateComments(this._uniqueId, {
|
|
||||||
added: [thread],
|
// As we create comment thread from template and then restore from the newly created maint thread comment thread,
|
||||||
removed: [],
|
// we postpone the update event to avoid duplication.
|
||||||
changed: [],
|
// This can be actually removed once we are on the new API.
|
||||||
draftMode: modes.DraftMode.NotSupported
|
setTimeout(() => {
|
||||||
});
|
this._commentService.updateComments(this._uniqueId, {
|
||||||
|
added: [thread],
|
||||||
|
removed: [],
|
||||||
|
changed: [],
|
||||||
|
draftMode: modes.DraftMode.NotSupported
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
@@ -379,10 +385,17 @@ export class MainThreadCommentController {
|
|||||||
commentingRanges: commentingRanges ?
|
commentingRanges: commentingRanges ?
|
||||||
{
|
{
|
||||||
resource: resource, ranges: commentingRanges, newCommentThreadCallback: async (uri: UriComponents, range: IRange) => {
|
resource: resource, ranges: commentingRanges, newCommentThreadCallback: async (uri: UriComponents, range: IRange) => {
|
||||||
await this._proxy.$createNewCommentWidgetCallback(this.handle, uri, range, token);
|
let threadHandle = await this._proxy.$createNewCommentWidgetCallback(this.handle, uri, range, token);
|
||||||
|
|
||||||
|
if (threadHandle !== undefined) {
|
||||||
|
return this.getKnownThread(threadHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined; // {{SQL CARBON EDIT}} @anthonydresser revert back after strict-null-check
|
||||||
}
|
}
|
||||||
} : [],
|
} : [],
|
||||||
draftMode: modes.DraftMode.NotSupported
|
draftMode: modes.DraftMode.NotSupported,
|
||||||
|
template: this._features.commentThreadTemplate
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,6 +471,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments
|
|||||||
this._proxy.$onCommentWidgetInputChange(controller.handle, this._input ? this._input.value : undefined);
|
this._proxy.$onCommentWidgetInputChange(controller.handle, this._input ? this._input.value : undefined);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
await this._proxy.$onActiveCommentThreadChange(controller.handle, controller.activeCommentThread.commentThreadHandle);
|
||||||
await this._proxy.$onCommentWidgetInputChange(controller.handle, this._input ? this._input.value : undefined);
|
await this._proxy.$onCommentWidgetInputChange(controller.handle, this._input ? this._input.value : undefined);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -510,8 +524,6 @@ export class MainThreadComments extends Disposable implements MainThreadComments
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('createCommentThread', commentThreadHandle);
|
|
||||||
|
|
||||||
return provider.createCommentThread(commentThreadHandle, threadId, resource, range);
|
return provider.createCommentThread(commentThreadHandle, threadId, resource, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,11 +121,19 @@ export interface MainThreadCommandsShape extends IDisposable {
|
|||||||
$getCommands(): Promise<string[]>;
|
$getCommands(): Promise<string[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CommentThreadTemplate {
|
||||||
|
label: string;
|
||||||
|
acceptInputCommand?: modes.Command;
|
||||||
|
additionalCommands?: modes.Command[];
|
||||||
|
deleteCommand?: modes.Command;
|
||||||
|
}
|
||||||
|
|
||||||
export interface CommentProviderFeatures {
|
export interface CommentProviderFeatures {
|
||||||
startDraftLabel?: string;
|
startDraftLabel?: string;
|
||||||
deleteDraftLabel?: string;
|
deleteDraftLabel?: string;
|
||||||
finishDraftLabel?: string;
|
finishDraftLabel?: string;
|
||||||
reactionGroup?: modes.CommentReaction[];
|
reactionGroup?: modes.CommentReaction[];
|
||||||
|
commentThreadTemplate?: CommentThreadTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MainThreadCommentsShape extends IDisposable {
|
export interface MainThreadCommentsShape extends IDisposable {
|
||||||
@@ -1206,10 +1214,11 @@ export interface ExtHostCommentsShape {
|
|||||||
$provideDocumentComments(handle: number, document: UriComponents): Promise<modes.CommentInfo | null>;
|
$provideDocumentComments(handle: number, document: UriComponents): Promise<modes.CommentInfo | null>;
|
||||||
$createNewCommentThread(handle: number, document: UriComponents, range: IRange, text: string): Promise<modes.CommentThread | null>;
|
$createNewCommentThread(handle: number, document: UriComponents, range: IRange, text: string): Promise<modes.CommentThread | null>;
|
||||||
$onCommentWidgetInputChange(commentControllerHandle: number, input: string | undefined): Promise<number | undefined>;
|
$onCommentWidgetInputChange(commentControllerHandle: number, input: string | undefined): Promise<number | undefined>;
|
||||||
|
$onActiveCommentThreadChange(commentControllerHandle: number, threadHandle: number | undefined): Promise<number | undefined>;
|
||||||
$provideCommentingRanges(commentControllerHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<IRange[] | undefined>;
|
$provideCommentingRanges(commentControllerHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<IRange[] | undefined>;
|
||||||
$provideReactionGroup(commentControllerHandle: number): Promise<modes.CommentReaction[] | undefined>;
|
$provideReactionGroup(commentControllerHandle: number): Promise<modes.CommentReaction[] | undefined>;
|
||||||
$toggleReaction(commentControllerHandle: number, threadHandle: number, uri: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void>;
|
$toggleReaction(commentControllerHandle: number, threadHandle: number, uri: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void>;
|
||||||
$createNewCommentWidgetCallback(commentControllerHandle: number, uriComponents: UriComponents, range: IRange, token: CancellationToken): Promise<void>;
|
$createNewCommentWidgetCallback(commentControllerHandle: number, uriComponents: UriComponents, range: IRange, token: CancellationToken): Promise<number | undefined>;
|
||||||
$replyToCommentThread(handle: number, document: UriComponents, range: IRange, commentThread: modes.CommentThread, text: string): Promise<modes.CommentThread | null>;
|
$replyToCommentThread(handle: number, document: UriComponents, range: IRange, commentThread: modes.CommentThread, text: string): Promise<modes.CommentThread | null>;
|
||||||
$editComment(handle: number, document: UriComponents, comment: modes.Comment, text: string): Promise<void>;
|
$editComment(handle: number, document: UriComponents, comment: modes.Comment, text: string): Promise<void>;
|
||||||
$deleteComment(handle: number, document: UriComponents, comment: modes.Comment): Promise<void>;
|
$deleteComment(handle: number, document: UriComponents, comment: modes.Comment): Promise<void>;
|
||||||
|
|||||||
@@ -99,6 +99,17 @@ export class ExtHostComments implements ExtHostCommentsShape {
|
|||||||
return Promise.resolve(commentControllerHandle);
|
return Promise.resolve(commentControllerHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$onActiveCommentThreadChange(commentControllerHandle: number, threadHandle: number): Promise<number | undefined> {
|
||||||
|
const commentController = this._commentControllers.get(commentControllerHandle);
|
||||||
|
|
||||||
|
if (!commentController) {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
commentController.$onActiveCommentThreadChange(threadHandle);
|
||||||
|
return Promise.resolve(threadHandle);
|
||||||
|
}
|
||||||
|
|
||||||
$provideCommentingRanges(commentControllerHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<IRange[] | undefined> {
|
$provideCommentingRanges(commentControllerHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<IRange[] | undefined> {
|
||||||
const commentController = this._commentControllers.get(commentControllerHandle);
|
const commentController = this._commentControllers.get(commentControllerHandle);
|
||||||
|
|
||||||
@@ -146,28 +157,34 @@ export class ExtHostComments implements ExtHostCommentsShape {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$createNewCommentWidgetCallback(commentControllerHandle: number, uriComponents: UriComponents, range: IRange, token: CancellationToken): Promise<void> {
|
$createNewCommentWidgetCallback(commentControllerHandle: number, uriComponents: UriComponents, range: IRange, token: CancellationToken): Promise<number | undefined> {
|
||||||
const commentController = this._commentControllers.get(commentControllerHandle);
|
const commentController = this._commentControllers.get(commentControllerHandle);
|
||||||
|
|
||||||
if (!commentController) {
|
if (!commentController) {
|
||||||
return Promise.resolve();
|
return Promise.resolve(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(commentController as any).emptyCommentThreadFactory && !(commentController.commentingRangeProvider && commentController.commentingRangeProvider.createEmptyCommentThread)) {
|
if (!(commentController as any).emptyCommentThreadFactory && !(commentController.commentingRangeProvider && commentController.commentingRangeProvider.createEmptyCommentThread) && !(commentController.emptyCommentThreadFactory && commentController.emptyCommentThreadFactory.createEmptyCommentThread)) {
|
||||||
return Promise.resolve();
|
return Promise.resolve(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
const document = this._documents.getDocument(URI.revive(uriComponents));
|
const document = this._documents.getDocument(URI.revive(uriComponents));
|
||||||
return asPromise(() => {
|
return asPromise(() => {
|
||||||
// TODO, remove this once GH PR stable deprecates `emptyCommentThreadFactory`.
|
if (commentController.emptyCommentThreadFactory) {
|
||||||
if ((commentController as any).emptyCommentThreadFactory) {
|
return commentController.emptyCommentThreadFactory!.createEmptyCommentThread(document, extHostTypeConverter.Range.to(range));
|
||||||
return (commentController as any).emptyCommentThreadFactory!.createEmptyCommentThread(document, extHostTypeConverter.Range.to(range));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commentController.commentingRangeProvider && commentController.commentingRangeProvider.createEmptyCommentThread) {
|
if (commentController.commentingRangeProvider && commentController.commentingRangeProvider.createEmptyCommentThread) {
|
||||||
return commentController.commentingRangeProvider.createEmptyCommentThread(document, extHostTypeConverter.Range.to(range));
|
return commentController.commentingRangeProvider.createEmptyCommentThread(document, extHostTypeConverter.Range.to(range));
|
||||||
}
|
}
|
||||||
}).then(() => Promise.resolve());
|
|
||||||
|
return undefined; // {{SQL CARBON EDIT}} @anthonydresser revert back after strict-null-check
|
||||||
|
}).then((commentThread: ExtHostCommentThread | undefined) => {
|
||||||
|
if (commentThread) {
|
||||||
|
return Promise.resolve(commentThread.handle);
|
||||||
|
}
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
registerWorkspaceCommentProvider(
|
registerWorkspaceCommentProvider(
|
||||||
@@ -451,6 +468,12 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
|||||||
|
|
||||||
private _localDisposables: types.Disposable[];
|
private _localDisposables: types.Disposable[];
|
||||||
|
|
||||||
|
private _isDiposed: boolean;
|
||||||
|
|
||||||
|
public get isDisposed(): boolean {
|
||||||
|
return this._isDiposed;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _proxy: MainThreadCommentsShape,
|
private _proxy: MainThreadCommentsShape,
|
||||||
private readonly _commandsConverter: CommandsConverter,
|
private readonly _commandsConverter: CommandsConverter,
|
||||||
@@ -469,6 +492,7 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this._localDisposables = [];
|
this._localDisposables = [];
|
||||||
|
this._isDiposed = false;
|
||||||
|
|
||||||
this._localDisposables.push(this.onDidUpdateCommentThread(() => {
|
this._localDisposables.push(this.onDidUpdateCommentThread(() => {
|
||||||
this.eventuallyUpdateCommentThread();
|
this.eventuallyUpdateCommentThread();
|
||||||
@@ -519,6 +543,7 @@ export class ExtHostCommentThread implements vscode.CommentThread {
|
|||||||
this._commentController.handle,
|
this._commentController.handle,
|
||||||
this.handle
|
this.handle
|
||||||
);
|
);
|
||||||
|
this._isDiposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -562,7 +587,17 @@ class ExtHostCommentController implements vscode.CommentController {
|
|||||||
return this._label;
|
return this._label;
|
||||||
}
|
}
|
||||||
|
|
||||||
public inputBox?: ExtHostCommentInputBox;
|
public inputBox: ExtHostCommentInputBox | undefined;
|
||||||
|
private _activeCommentThread: ExtHostCommentThread | undefined;
|
||||||
|
|
||||||
|
public get activeCommentThread(): ExtHostCommentThread | undefined {
|
||||||
|
if (this._activeCommentThread && this._activeCommentThread.isDisposed) {
|
||||||
|
this._activeCommentThread = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._activeCommentThread;
|
||||||
|
}
|
||||||
|
|
||||||
public activeCommentingRange?: vscode.Range;
|
public activeCommentingRange?: vscode.Range;
|
||||||
|
|
||||||
public get handle(): number {
|
public get handle(): number {
|
||||||
@@ -570,7 +605,31 @@ class ExtHostCommentController implements vscode.CommentController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _threads: Map<number, ExtHostCommentThread> = new Map<number, ExtHostCommentThread>();
|
private _threads: Map<number, ExtHostCommentThread> = new Map<number, ExtHostCommentThread>();
|
||||||
commentingRangeProvider?: vscode.CommentingRangeProvider;
|
commentingRangeProvider?: vscode.CommentingRangeProvider & { createEmptyCommentThread: (document: vscode.TextDocument, range: types.Range) => Promise<vscode.CommentThread>; };
|
||||||
|
|
||||||
|
private _emptyCommentThreadFactory: vscode.EmptyCommentThreadFactory | undefined;
|
||||||
|
get emptyCommentThreadFactory(): vscode.EmptyCommentThreadFactory | undefined {
|
||||||
|
return this._emptyCommentThreadFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
set emptyCommentThreadFactory(newEmptyCommentThreadFactory: vscode.EmptyCommentThreadFactory | undefined) {
|
||||||
|
this._emptyCommentThreadFactory = newEmptyCommentThreadFactory;
|
||||||
|
|
||||||
|
if (this._emptyCommentThreadFactory && this._emptyCommentThreadFactory.template) {
|
||||||
|
let template = this._emptyCommentThreadFactory.template;
|
||||||
|
const acceptInputCommand = template.acceptInputCommand ? this._commandsConverter.toInternal(template.acceptInputCommand) : undefined;
|
||||||
|
const additionalCommands = template.additionalCommands ? template.additionalCommands.map(x => this._commandsConverter.toInternal(x)) : [];
|
||||||
|
const deleteCommand = template.deleteCommand ? this._commandsConverter.toInternal(template.deleteCommand) : undefined;
|
||||||
|
this._proxy.$updateCommentControllerFeatures(this.handle, {
|
||||||
|
commentThreadTemplate: {
|
||||||
|
label: template.label,
|
||||||
|
acceptInputCommand,
|
||||||
|
additionalCommands,
|
||||||
|
deleteCommand
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _commentReactionProvider?: vscode.CommentReactionProvider;
|
private _commentReactionProvider?: vscode.CommentReactionProvider;
|
||||||
|
|
||||||
@@ -610,6 +669,10 @@ class ExtHostCommentController implements vscode.CommentController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$onActiveCommentThreadChange(threadHandle: number) {
|
||||||
|
this._activeCommentThread = this.getCommentThread(threadHandle);
|
||||||
|
}
|
||||||
|
|
||||||
getCommentThread(handle: number) {
|
getCommentThread(handle: number) {
|
||||||
return this._threads.get(handle);
|
return this._threads.get(handle);
|
||||||
}
|
}
|
||||||
@@ -664,6 +727,7 @@ function convertFromComment(comment: modes.Comment): vscode.Comment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
id: comment.commentId,
|
||||||
commentId: comment.commentId,
|
commentId: comment.commentId,
|
||||||
body: extHostTypeConverter.MarkdownString.to(comment.body),
|
body: extHostTypeConverter.MarkdownString.to(comment.body),
|
||||||
userName: comment.userName,
|
userName: comment.userName,
|
||||||
@@ -685,7 +749,7 @@ function convertToModeComment(commentController: ExtHostCommentController, vscod
|
|||||||
const iconPath = vscodeComment.userIconPath ? vscodeComment.userIconPath.toString() : vscodeComment.gravatar;
|
const iconPath = vscodeComment.userIconPath ? vscodeComment.userIconPath.toString() : vscodeComment.gravatar;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
commentId: vscodeComment.commentId,
|
commentId: vscodeComment.id || vscodeComment.commentId,
|
||||||
body: extHostTypeConverter.MarkdownString.from(vscodeComment.body),
|
body: extHostTypeConverter.MarkdownString.from(vscodeComment.body),
|
||||||
userName: vscodeComment.userName,
|
userName: vscodeComment.userName,
|
||||||
userIconPath: iconPath,
|
userIconPath: iconPath,
|
||||||
|
|||||||
@@ -2287,6 +2287,61 @@ export enum FoldingRangeKind {
|
|||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
//#region Comment
|
||||||
|
@es5ClassCompat
|
||||||
|
export class Comment {
|
||||||
|
id: string;
|
||||||
|
body: MarkdownString;
|
||||||
|
userName: string;
|
||||||
|
label?: string;
|
||||||
|
userIconPath?: URI;
|
||||||
|
selectCommand?: vscode.Command;
|
||||||
|
editCommand?: vscode.Command;
|
||||||
|
deleteCommand?: vscode.Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id of the comment
|
||||||
|
*
|
||||||
|
* @deprecated Use Id instead
|
||||||
|
*/
|
||||||
|
commentId: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use userIconPath instead. The avatar src of the user who created the comment
|
||||||
|
*/
|
||||||
|
gravatar?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated, use editCommand
|
||||||
|
*/
|
||||||
|
canEdit?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated, use deleteCommand
|
||||||
|
*/
|
||||||
|
canDelete?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
command?: vscode.Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
isDraft?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proposed Comment Reaction
|
||||||
|
*/
|
||||||
|
commentReactions?: vscode.CommentReaction[];
|
||||||
|
|
||||||
|
constructor(id: string, body: MarkdownString, userName: string) {
|
||||||
|
this.id = id;
|
||||||
|
this.body = body;
|
||||||
|
this.userName = userName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export enum CommentThreadCollapsibleState {
|
export enum CommentThreadCollapsibleState {
|
||||||
/**
|
/**
|
||||||
@@ -2298,6 +2353,7 @@ export enum CommentThreadCollapsibleState {
|
|||||||
*/
|
*/
|
||||||
Expanded = 1
|
Expanded = 1
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
@es5ClassCompat
|
@es5ClassCompat
|
||||||
export class QuickInputButtons {
|
export class QuickInputButtons {
|
||||||
|
|||||||
@@ -780,6 +780,7 @@ export function createApiFactory(
|
|||||||
Color: extHostTypes.Color,
|
Color: extHostTypes.Color,
|
||||||
ColorInformation: extHostTypes.ColorInformation,
|
ColorInformation: extHostTypes.ColorInformation,
|
||||||
ColorPresentation: extHostTypes.ColorPresentation,
|
ColorPresentation: extHostTypes.ColorPresentation,
|
||||||
|
Comment: extHostTypes.Comment,
|
||||||
CommentThreadCollapsibleState: extHostTypes.CommentThreadCollapsibleState,
|
CommentThreadCollapsibleState: extHostTypes.CommentThreadCollapsibleState,
|
||||||
CompletionItem: extHostTypes.CompletionItem,
|
CompletionItem: extHostTypes.CompletionItem,
|
||||||
CompletionItemKind: extHostTypes.CompletionItemKind,
|
CompletionItemKind: extHostTypes.CompletionItemKind,
|
||||||
|
|||||||
@@ -309,17 +309,17 @@ export const STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND = registerColor('statusB
|
|||||||
hc: Color.black.transparent(0.3),
|
hc: Color.black.transparent(0.3),
|
||||||
}, nls.localize('statusBarProminentItemHoverBackground', "Status bar prominent items background color when hovering. Prominent items stand out from other status bar entries to indicate importance. Change mode `Toggle Tab Key Moves Focus` from command palette to see an example. The status bar is shown in the bottom of the window."));
|
}, nls.localize('statusBarProminentItemHoverBackground', "Status bar prominent items background color when hovering. Prominent items stand out from other status bar entries to indicate importance. Change mode `Toggle Tab Key Moves Focus` from command palette to see an example. The status bar is shown in the bottom of the window."));
|
||||||
|
|
||||||
export const STATUS_BAR_HOST_NAME_BACKGROUND = registerColor('statusBarItem.hostBackground', {
|
export const STATUS_BAR_HOST_NAME_BACKGROUND = registerColor('statusBarItem.remoteBackground', {
|
||||||
dark: '#C40057',
|
dark: '#16825D',
|
||||||
light: '#C40057',
|
light: '#16825D',
|
||||||
hc: '#C40057'
|
hc: '#FFFFFF00'
|
||||||
}, nls.localize('statusBarItemHostBackground', "Background color for the host indicator on the status bar."));
|
}, nls.localize('statusBarItemHostBackground', "Background color for the remote indicator on the status bar."));
|
||||||
|
|
||||||
export const STATUS_BAR_HOST_NAME_FOREGROUND = registerColor('statusBarItem.hostForeground', {
|
export const STATUS_BAR_HOST_NAME_FOREGROUND = registerColor('statusBarItem.remoteForeground', {
|
||||||
dark: '#FFFFFF',
|
dark: '#FFFFFF',
|
||||||
light: '#FFFFFF',
|
light: '#FFFFFF',
|
||||||
hc: '#FFFFFF'
|
hc: '#FFFFFF'
|
||||||
}, nls.localize('statusBarItemHostForeground', "Foreground color for the host indicator on the status bar."));
|
}, nls.localize('statusBarItemHostForeground', "Foreground color for the remote indicator on the status bar."));
|
||||||
|
|
||||||
|
|
||||||
// < --- Activity Bar --- >
|
// < --- Activity Bar --- >
|
||||||
@@ -366,6 +366,18 @@ export const ACTIVITY_BAR_BADGE_FOREGROUND = registerColor('activityBarBadge.for
|
|||||||
hc: Color.white
|
hc: Color.white
|
||||||
}, nls.localize('activityBarBadgeForeground', "Activity notification badge foreground color. The activity bar is showing on the far left or right and allows to switch between views of the side bar."));
|
}, nls.localize('activityBarBadgeForeground', "Activity notification badge foreground color. The activity bar is showing on the far left or right and allows to switch between views of the side bar."));
|
||||||
|
|
||||||
|
export const EXTENSION_BADGE_REMOTE_BACKGROUND = registerColor('extensionBadge.remoteBackground', {
|
||||||
|
dark: ACTIVITY_BAR_BADGE_BACKGROUND,
|
||||||
|
light: ACTIVITY_BAR_BADGE_BACKGROUND,
|
||||||
|
hc: ACTIVITY_BAR_BADGE_BACKGROUND
|
||||||
|
}, nls.localize('extensionBadge.remoteBackground', "Background color for the remote badge in the extensions view"));
|
||||||
|
|
||||||
|
export const EXTENSION_BADGE_REMOTE_FOREGROUND = registerColor('extensionBadge.remoteForeground', {
|
||||||
|
dark: ACTIVITY_BAR_BADGE_FOREGROUND,
|
||||||
|
light: ACTIVITY_BAR_BADGE_FOREGROUND,
|
||||||
|
hc: ACTIVITY_BAR_BADGE_FOREGROUND
|
||||||
|
}, nls.localize('extensionBadge.remoteForeground', "Foreground color for the remote badge in the extensions view"));
|
||||||
|
|
||||||
|
|
||||||
// < --- Side Bar --- >
|
// < --- Side Bar --- >
|
||||||
|
|
||||||
|
|||||||
@@ -322,15 +322,17 @@ export class CommentService extends Disposable implements ICommentService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let commentControlResult: Promise<ICommentInfo>[] = [];
|
let commentControlResult: Promise<ICommentInfo | null>[] = [];
|
||||||
|
|
||||||
this._commentControls.forEach(control => {
|
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 Promise.all([...result, ...commentControlResult]);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCommentingRanges(resource: URI): Promise<IRange[]> {
|
async getCommentingRanges(resource: URI): Promise<IRange[]> {
|
||||||
|
|||||||
@@ -212,6 +212,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
|||||||
} else {
|
} else {
|
||||||
const deleteCommand = (this._commentThread as modes.CommentThread2).deleteCommand;
|
const deleteCommand = (this._commentThread as modes.CommentThread2).deleteCommand;
|
||||||
if (deleteCommand) {
|
if (deleteCommand) {
|
||||||
|
this.commentService.setActiveCommentThread(this._commentThread);
|
||||||
return this.commandService.executeCommand(deleteCommand.id, ...(deleteCommand.arguments || []));
|
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 oldCommentsLen = this._commentElements.length;
|
||||||
const newCommentsLen = commentThread.comments ? commentThread.comments.length : 0;
|
const newCommentsLen = commentThread.comments ? commentThread.comments.length : 0;
|
||||||
|
|
||||||
@@ -288,12 +289,20 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
|||||||
|
|
||||||
this._commentThread = commentThread;
|
this._commentThread = commentThread;
|
||||||
this._commentElements = newCommentNodeList;
|
this._commentElements = newCommentNodeList;
|
||||||
this.createThreadLabel();
|
this.createThreadLabel(replaceTemplate);
|
||||||
|
|
||||||
|
if (replaceTemplate) {
|
||||||
|
this.createTextModelListener();
|
||||||
|
}
|
||||||
|
|
||||||
if (this._formActions && this._commentEditor.hasModel()) {
|
if (this._formActions && this._commentEditor.hasModel()) {
|
||||||
dom.clearNode(this._formActions);
|
dom.clearNode(this._formActions);
|
||||||
const model = this._commentEditor.getModel();
|
const model = this._commentEditor.getModel();
|
||||||
this.createCommentWidgetActions2(this._formActions, model);
|
this.createCommentWidgetActions2(this._formActions, model);
|
||||||
|
|
||||||
|
if (replaceTemplate) {
|
||||||
|
this.createCommentWidgetActionsListener(this._formActions, model);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move comment glyph widget and show position if the line has changed.
|
// 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*/ });
|
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._commentGlyph = new CommentGlyphWidget(this.editor, lineNumber);
|
||||||
|
|
||||||
this._disposables.push(this.editor.onMouseDown(e => this.onEditorMouseDown(e)));
|
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._commentEditor.setModel(model);
|
||||||
this._disposables.push(this._commentEditor);
|
this._disposables.push(this._commentEditor);
|
||||||
this._disposables.push(this._commentEditor.getModel()!.onDidChangeContent(() => this.setCommentEditorDecorations()));
|
this._disposables.push(this._commentEditor.getModel()!.onDidChangeContent(() => this.setCommentEditorDecorations()));
|
||||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined && !fromTemplate) {
|
||||||
this._disposables.push(this._commentEditor.onDidFocusEditorWidget(() => {
|
this.createTextModelListener();
|
||||||
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();
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setCommentEditorDecorations();
|
this.setCommentEditorDecorations();
|
||||||
@@ -456,50 +415,9 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
|||||||
this._formActions = dom.append(this._commentForm, dom.$('.form-actions'));
|
this._formActions = dom.append(this._commentForm, dom.$('.form-actions'));
|
||||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
||||||
this.createCommentWidgetActions2(this._formActions, model);
|
this.createCommentWidgetActions2(this._formActions, model);
|
||||||
|
if (!fromTemplate) {
|
||||||
this._disposables.push((this._commentThread as modes.CommentThread2).onDidChangeAcceptInputCommand(_ => {
|
this.createCommentWidgetActionsListener(this._formActions, model);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
this.createCommentWidgetActions(this._formActions, model);
|
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) {
|
private handleError(e: Error) {
|
||||||
this._error.textContent = e.message;
|
this._error.textContent = e.message;
|
||||||
this._commentEditor.getDomNode()!.style.outline = `1px solid ${this.themeService.getTheme().getColor(inputValidationErrorBorder)}`;
|
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;
|
let label: string | undefined;
|
||||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
||||||
label = (this._commentThread as modes.CommentThread2).label;
|
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) {
|
if (this._commentThread.comments && this._commentThread.comments.length) {
|
||||||
const participantsList = this._commentThread.comments.filter(arrays.uniqueFilter(comment => comment.userName)).map(comment => `@${comment.userName}`).join(', ');
|
const participantsList = this._commentThread.comments.filter(arrays.uniqueFilter(comment => comment.userName)).map(comment => `@${comment.userName}`).join(', ');
|
||||||
label = nls.localize('commentThreadParticipants', "Participants: {0}", participantsList);
|
label = nls.localize('commentThreadParticipants', "Participants: {0}", participantsList);
|
||||||
@@ -813,8 +832,11 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._headingLabel.innerHTML = strings.escape(label);
|
if (label) {
|
||||||
this._headingLabel.setAttribute('aria-label', label);
|
this._headingLabel.innerHTML = strings.escape(label);
|
||||||
|
this._headingLabel.setAttribute('aria-label', label);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private expandReplyArea() {
|
private expandReplyArea() {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import { CancelablePromise, createCancelablePromise, Delayer } from 'vs/base/com
|
|||||||
import { overviewRulerCommentingRangeForeground } from 'vs/workbench/contrib/comments/browser/commentGlyphWidget';
|
import { overviewRulerCommentingRangeForeground } from 'vs/workbench/contrib/comments/browser/commentGlyphWidget';
|
||||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
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 { 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 { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { ctxCommentEditorFocused, SimpleCommentEditor } from 'vs/workbench/contrib/comments/browser/simpleCommentEditor';
|
import { ctxCommentEditorFocused, SimpleCommentEditor } from 'vs/workbench/contrib/comments/browser/simpleCommentEditor';
|
||||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||||
@@ -64,7 +64,7 @@ class CommentingRangeDecoration {
|
|||||||
return this._decorationId;
|
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 startLineNumber = _range.startLineNumber;
|
||||||
const endLineNumber = _range.endLineNumber;
|
const endLineNumber = _range.endLineNumber;
|
||||||
let commentingRangeDecorations = [{
|
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 {
|
return {
|
||||||
extensionId: this._extensionId,
|
extensionId: this._extensionId,
|
||||||
label: this._label,
|
label: this._label,
|
||||||
replyCommand: this._reply,
|
replyCommand: this._reply,
|
||||||
ownerId: this._ownerId,
|
ownerId: this._ownerId,
|
||||||
commentingRangesInfo: this.commentingRangesInfo
|
commentingRangesInfo: this.commentingRangesInfo,
|
||||||
|
template: this._template
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,11 +125,11 @@ class CommentingRangeDecorator {
|
|||||||
for (const info of commentInfos) {
|
for (const info of commentInfos) {
|
||||||
if (Array.isArray(info.commentingRanges)) {
|
if (Array.isArray(info.commentingRanges)) {
|
||||||
info.commentingRanges.forEach(range => {
|
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 {
|
} else {
|
||||||
(info.commentingRanges ? info.commentingRanges.ranges : []).forEach(range => {
|
(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(
|
constructor(
|
||||||
editor: ICodeEditor,
|
editor: ICodeEditor,
|
||||||
@ICommentService private readonly commentService: ICommentService,
|
@ICommentService private readonly commentService: ICommentService,
|
||||||
@ICommandService private readonly _commandService: ICommandService,
|
|
||||||
@INotificationService private readonly notificationService: INotificationService,
|
@INotificationService private readonly notificationService: INotificationService,
|
||||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||||
@ICodeEditorService private readonly codeEditorService: ICodeEditorService,
|
@ICodeEditorService private readonly codeEditorService: ICodeEditorService,
|
||||||
@@ -441,6 +441,11 @@ export class ReviewController implements IEditorContribution {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
added.forEach(thread => {
|
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];
|
const pendingCommentText = this._pendingCommentCache[e.owner] && this._pendingCommentCache[e.owner][thread.threadId];
|
||||||
this.displayCommentThread(e.owner, thread, pendingCommentText, draftMode);
|
this.displayCommentThread(e.owner, thread, pendingCommentText, draftMode);
|
||||||
this._commentInfos.filter(info => info.owner === e.owner)[0].threads.push(thread);
|
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);
|
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) {
|
private addComment(lineNumber: number, replyCommand: modes.Command | undefined, ownerId: string, extensionId: string | undefined, draftMode: modes.DraftMode | undefined, pendingComment: string | null) {
|
||||||
if (this._newCommentWidget) {
|
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.`);
|
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);
|
const commentInfos = newCommentInfos.filter(info => info.ownerId === pick.id);
|
||||||
|
|
||||||
if (commentInfos.length) {
|
if (commentInfos.length) {
|
||||||
const { replyCommand, ownerId, extensionId, commentingRangesInfo } = commentInfos[0];
|
const { replyCommand, ownerId, extensionId, commentingRangesInfo, template } = commentInfos[0];
|
||||||
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo);
|
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo, template);
|
||||||
}
|
}
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this._addInProgress = false;
|
this._addInProgress = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const { replyCommand, ownerId, extensionId, commentingRangesInfo } = newCommentInfos[0]!;
|
const { replyCommand, ownerId, extensionId, commentingRangesInfo, template } = newCommentInfos[0]!;
|
||||||
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo);
|
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo, template);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
@@ -640,11 +669,11 @@ export class ReviewController implements IEditorContribution {
|
|||||||
return picks;
|
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)[] = [];
|
const actions: (IAction | ContextSubMenu)[] = [];
|
||||||
|
|
||||||
commentInfos.forEach(commentInfo => {
|
commentInfos.forEach(commentInfo => {
|
||||||
const { replyCommand, ownerId, extensionId, label, commentingRangesInfo } = commentInfo;
|
const { replyCommand, ownerId, extensionId, label, commentingRangesInfo, template } = commentInfo;
|
||||||
|
|
||||||
actions.push(new Action(
|
actions.push(new Action(
|
||||||
'addCommentThread',
|
'addCommentThread',
|
||||||
@@ -652,7 +681,7 @@ export class ReviewController implements IEditorContribution {
|
|||||||
undefined,
|
undefined,
|
||||||
true,
|
true,
|
||||||
() => {
|
() => {
|
||||||
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo);
|
this.addCommentAtLine2(lineNumber, replyCommand, ownerId, extensionId, commentingRangesInfo, template);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
@@ -660,17 +689,25 @@ export class ReviewController implements IEditorContribution {
|
|||||||
return actions;
|
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) {
|
if (commentingRangesInfo) {
|
||||||
let range = new Range(lineNumber, 1, lineNumber, 1);
|
let range = new Range(lineNumber, 1, lineNumber, 1);
|
||||||
if (commentingRangesInfo.newCommentThreadCommand) {
|
if (commentingRangesInfo.newCommentThreadCallback && template) {
|
||||||
if (replyCommand) {
|
// create comment widget through template
|
||||||
const commandId = replyCommand.id;
|
let commentThreadWidget = this.addCommentThreadFromTemplate(lineNumber, ownerId, extensionId, template);
|
||||||
const args = replyCommand.arguments || [];
|
commentThreadWidget.display(lineNumber, true);
|
||||||
|
|
||||||
this._commandService.executeCommand(commandId, ...args);
|
return commentingRangesInfo.newCommentThreadCallback(this.editor.getModel()!.uri, range)
|
||||||
this._addInProgress = false;
|
.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) {
|
} else if (commentingRangesInfo.newCommentThreadCallback) {
|
||||||
return commentingRangesInfo.newCommentThreadCallback(this.editor.getModel()!.uri, range)
|
return commentingRangesInfo.newCommentThreadCallback(this.editor.getModel()!.uri, range)
|
||||||
.then(_ => {
|
.then(_ => {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { IExtensionManagementServerService, IExtensionTipsService } from 'vs/pla
|
|||||||
import { ILabelService } from 'vs/platform/label/common/label';
|
import { ILabelService } from 'vs/platform/label/common/label';
|
||||||
import { extensionButtonProminentBackground, extensionButtonProminentForeground, DisabledLabelAction, ReloadAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
|
import { extensionButtonProminentBackground, extensionButtonProminentForeground, DisabledLabelAction, ReloadAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
|
||||||
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
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 { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
||||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||||
import { Emitter, Event } from 'vs/base/common/event';
|
import { Emitter, Event } from 'vs/base/common/event';
|
||||||
@@ -323,8 +323,8 @@ class RemoteBadge extends Disposable {
|
|||||||
if (!this.element) {
|
if (!this.element) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const bgColor = this.themeService.getTheme().getColor(STATUS_BAR_HOST_NAME_BACKGROUND);
|
const bgColor = this.themeService.getTheme().getColor(EXTENSION_BADGE_REMOTE_BACKGROUND);
|
||||||
const fgColor = this.themeService.getTheme().getColor(STATUS_BAR_HOST_NAME_FOREGROUND);
|
const fgColor = this.themeService.getTheme().getColor(EXTENSION_BADGE_REMOTE_FOREGROUND);
|
||||||
this.element.style.backgroundColor = bgColor ? bgColor.toString() : '';
|
this.element.style.backgroundColor = bgColor ? bgColor.toString() : '';
|
||||||
this.element.style.color = fgColor ? fgColor.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 { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||||
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
|
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
|
||||||
import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
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 { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
|
||||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
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';
|
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(
|
return this.editorService.openEditor(
|
||||||
{
|
{
|
||||||
leftResource: resource.with({ scheme: CONFLICT_RESOLUTION_SCHEME }),
|
leftResource: resourceToFileOnDisk(CONFLICT_RESOLUTION_SCHEME, resource),
|
||||||
rightResource: resource,
|
rightResource: resource,
|
||||||
label: editorLabel,
|
label: editorLabel,
|
||||||
options: { pinned: true }
|
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 { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||||
import { ExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel';
|
import { ExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel';
|
||||||
import { once } from 'vs/base/common/functional';
|
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.
|
* Explorer viewlet id.
|
||||||
@@ -133,6 +131,14 @@ export const SortOrderConfiguration = {
|
|||||||
|
|
||||||
export type SortOrder = 'default' | 'mixed' | 'filesFirst' | 'type' | 'modified';
|
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 {
|
export class FileOnDiskContentProvider implements ITextModelContentProvider {
|
||||||
private fileWatcherDisposable: IDisposable | undefined;
|
private fileWatcherDisposable: IDisposable | undefined;
|
||||||
|
|
||||||
@@ -140,13 +146,12 @@ export class FileOnDiskContentProvider implements ITextModelContentProvider {
|
|||||||
@ITextFileService private readonly textFileService: ITextFileService,
|
@ITextFileService private readonly textFileService: ITextFileService,
|
||||||
@IFileService private readonly fileService: IFileService,
|
@IFileService private readonly fileService: IFileService,
|
||||||
@IModeService private readonly modeService: IModeService,
|
@IModeService private readonly modeService: IModeService,
|
||||||
@IModelService private readonly modelService: IModelService,
|
@IModelService private readonly modelService: IModelService
|
||||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService
|
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
provideTextContent(resource: URI): Promise<ITextModel> {
|
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
|
// Make sure our file from disk is resolved up to date
|
||||||
return this.resolveEditorModel(resource).then(codeEditorModel => {
|
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?: true): Promise<ITextModel>;
|
||||||
private resolveEditorModel(resource: URI, createAsNeeded?: boolean): Promise<ITextModel | null>;
|
private resolveEditorModel(resource: URI, createAsNeeded?: boolean): Promise<ITextModel | null>;
|
||||||
private resolveEditorModel(resource: URI, createAsNeeded: boolean = true): 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 => {
|
return this.textFileService.readStream(savedFileResource).then(content => {
|
||||||
let codeEditorModel = this.modelService.getModel(resource);
|
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());
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -469,7 +469,7 @@ export class RemoteFileDialog {
|
|||||||
this.autoCompletePathSegment = '';
|
this.autoCompletePathSegment = '';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const itemBasename = quickPickItem.label;
|
const itemBasename = this.trimTrailingSlash(quickPickItem.label);
|
||||||
// Either force the autocomplete, or the old value should be one smaller than the new value and match the new value.
|
// Either force the autocomplete, or the old value should be one smaller than the new value and match the new value.
|
||||||
if (itemBasename === '..') {
|
if (itemBasename === '..') {
|
||||||
// Don't match on the up directory item ever.
|
// Don't match on the up directory item ever.
|
||||||
|
|||||||
@@ -899,6 +899,7 @@ export class TestFileService implements IFileService {
|
|||||||
readonly onError: Event<Error> = Event.None;
|
readonly onError: Event<Error> = Event.None;
|
||||||
|
|
||||||
private content = 'Hello Html';
|
private content = 'Hello Html';
|
||||||
|
private lastReadFileUri: URI;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._onFileChanges = new Emitter<FileChangesEvent>();
|
this._onFileChanges = new Emitter<FileChangesEvent>();
|
||||||
@@ -913,6 +914,10 @@ export class TestFileService implements IFileService {
|
|||||||
return this.content;
|
return this.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getLastReadFileUri(): URI {
|
||||||
|
return this.lastReadFileUri;
|
||||||
|
}
|
||||||
|
|
||||||
public get onFileChanges(): Event<FileChangesEvent> {
|
public get onFileChanges(): Event<FileChangesEvent> {
|
||||||
return this._onFileChanges.event;
|
return this._onFileChanges.event;
|
||||||
}
|
}
|
||||||
@@ -952,6 +957,8 @@ export class TestFileService implements IFileService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readFile(resource: URI, options?: IReadFileOptions | undefined): Promise<IFileContent> {
|
readFile(resource: URI, options?: IReadFileOptions | undefined): Promise<IFileContent> {
|
||||||
|
this.lastReadFileUri = resource;
|
||||||
|
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
resource: resource,
|
resource: resource,
|
||||||
value: VSBuffer.fromString(this.content),
|
value: VSBuffer.fromString(this.content),
|
||||||
@@ -964,6 +971,8 @@ export class TestFileService implements IFileService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readFileStream(resource: URI, options?: IReadFileOptions | undefined): Promise<IFileStreamContent> {
|
readFileStream(resource: URI, options?: IReadFileOptions | undefined): Promise<IFileStreamContent> {
|
||||||
|
this.lastReadFileUri = resource;
|
||||||
|
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
resource: resource,
|
resource: resource,
|
||||||
value: {
|
value: {
|
||||||
|
|||||||
Reference in New Issue
Block a user