Merge from vscode 2cd495805cf99b31b6926f08ff4348124b2cf73d

This commit is contained in:
ADS Merger
2020-06-30 04:40:21 +00:00
committed by AzureDataStudio
parent a8a7559229
commit 1388493cc1
602 changed files with 16375 additions and 12940 deletions

View File

@@ -18,7 +18,7 @@ import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { fromNow } from 'vs/base/common/date';
const VSO_ALLOWED_EXTENSIONS = ['github.vscode-pull-request-github', 'github.vscode-pull-request-github-insiders', 'vscode.git', 'ms-vsonline.vsonline'];
const VSO_ALLOWED_EXTENSIONS = ['github.vscode-pull-request-github', 'github.vscode-pull-request-github-insiders', 'vscode.git', 'ms-vsonline.vsonline', 'vscode.github-browser'];
interface IAccountUsage {
extensionId: string;
@@ -104,7 +104,7 @@ export class MainThreadAuthenticationProvider extends Disposable {
return {
label: extension.name,
description: usage
? nls.localize('accountLastUsedDate', "Last used this account {0}", fromNow(usage.lastUsed, true))
? nls.localize({ key: 'accountLastUsedDate', comment: ['The placeholder {0} is a string with time information, such as "3 days ago"'] }, "Last used this account {0}", fromNow(usage.lastUsed, true))
: nls.localize('notUsed', "Has not used this account"),
extension
};
@@ -336,7 +336,14 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
});
quickPick.items = items;
quickPick.title = nls.localize('selectAccount', "The extension '{0}' wants to access a {1} account", extensionName, providerName);
quickPick.title = nls.localize(
{
key: 'selectAccount',
comment: ['The placeholder {0} is the name of an extension. {1} is the name of the type of account, such as Microsoft or GitHub.']
},
"The extension '{0}' wants to access a {1} account",
extensionName,
providerName);
quickPick.placeholder = nls.localize('getSessionPlateholder', "Select an account for '{0}' to use or Esc to cancel", extensionName);
quickPick.onDidAccept(async _ => {

View File

@@ -6,7 +6,6 @@
import { CancellationToken } from 'vs/base/common/cancellation';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { keys } from 'vs/base/common/map';
import { URI, UriComponents } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import { IRange } from 'vs/editor/common/core/range';
@@ -284,7 +283,7 @@ export class MainThreadCommentController {
async getDocumentComments(resource: URI, token: CancellationToken) {
let ret: modes.CommentThread[] = [];
for (let thread of keys(this._threads)) {
for (let thread of [...this._threads.keys()]) {
const commentThread = this._threads.get(thread)!;
if (commentThread.resource === resource.toString()) {
ret.push(commentThread);
@@ -315,7 +314,7 @@ export class MainThreadCommentController {
getAllComments(): MainThreadCommentThread[] {
let ret: MainThreadCommentThread[] = [];
for (let thread of keys(this._threads)) {
for (let thread of [...this._threads.keys()]) {
ret.push(this._threads.get(thread)!);
}
@@ -486,7 +485,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments
if (!commentsPanelAlreadyConstructed && !this._openViewListener) {
this._openViewListener = this._viewsService.onDidChangeViewVisibility(e => {
if (e.id === COMMENTS_VIEW_ID && e.visible) {
keys(this._commentControllers).forEach(handle => {
[...this._commentControllers.keys()].forEach(handle => {
let threads = this._commentControllers.get(handle)!.getAllComments();
if (threads.length) {

View File

@@ -231,7 +231,8 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
const debugOptions: IDebugSessionOptions = {
noDebug: options.noDebug,
parentSession: this.getSession(options.parentSessionID),
repl: options.repl
repl: options.repl,
noCompact: options.noCompact
};
return this.debugService.startDebugging(launch, nameOrConfig, debugOptions).then(success => {
return success;

View File

@@ -9,33 +9,33 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ExtHostContext, MainContext, IExtHostContext, MainThreadDecorationsShape, ExtHostDecorationsShape, DecorationData, DecorationRequest } from '../common/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { IDecorationsService, IDecorationData } from 'vs/workbench/services/decorations/browser/decorations';
import { values } from 'vs/base/common/collections';
import { CancellationToken } from 'vs/base/common/cancellation';
class DecorationRequestsQueue {
private _idPool = 0;
private _requests: { [id: number]: DecorationRequest } = Object.create(null);
private _resolver: { [id: number]: (data: DecorationData) => any } = Object.create(null);
private _requests = new Map<number, DecorationRequest>();
private _resolver = new Map<number, (data: DecorationData) => any>();
private _timer: any;
constructor(
private readonly _proxy: ExtHostDecorationsShape
private readonly _proxy: ExtHostDecorationsShape,
private readonly _handle: number
) {
//
}
enqueue(handle: number, uri: URI, token: CancellationToken): Promise<DecorationData> {
enqueue(uri: URI, token: CancellationToken): Promise<DecorationData> {
const id = ++this._idPool;
const result = new Promise<DecorationData>(resolve => {
this._requests[id] = { id, handle, uri };
this._resolver[id] = resolve;
this._requests.set(id, { id, uri });
this._resolver.set(id, resolve);
this._processQueue();
});
token.onCancellationRequested(() => {
delete this._requests[id];
delete this._resolver[id];
this._requests.delete(id);
this._resolver.delete(id);
});
return result;
}
@@ -49,15 +49,15 @@ class DecorationRequestsQueue {
// make request
const requests = this._requests;
const resolver = this._resolver;
this._proxy.$provideDecorations(values(requests), CancellationToken.None).then(data => {
for (const id in resolver) {
resolver[id](data[id]);
this._proxy.$provideDecorations(this._handle, [...requests.values()], CancellationToken.None).then(data => {
for (let [id, resolve] of resolver) {
resolve(data[id]);
}
});
// reset
this._requests = [];
this._resolver = [];
this._requests = new Map();
this._resolver = new Map();
this._timer = undefined;
}, 0);
}
@@ -68,14 +68,12 @@ export class MainThreadDecorations implements MainThreadDecorationsShape {
private readonly _provider = new Map<number, [Emitter<URI[]>, IDisposable]>();
private readonly _proxy: ExtHostDecorationsShape;
private readonly _requestQueue: DecorationRequestsQueue;
constructor(
context: IExtHostContext,
@IDecorationsService private readonly _decorationsService: IDecorationsService
) {
this._proxy = context.getProxy(ExtHostContext.ExtHostDecorations);
this._requestQueue = new DecorationRequestsQueue(this._proxy);
}
dispose() {
@@ -85,23 +83,23 @@ export class MainThreadDecorations implements MainThreadDecorationsShape {
$registerDecorationProvider(handle: number, label: string): void {
const emitter = new Emitter<URI[]>();
const queue = new DecorationRequestsQueue(this._proxy, handle);
const registration = this._decorationsService.registerDecorationsProvider({
label,
onDidChange: emitter.event,
provideDecorations: (uri, token) => {
return this._requestQueue.enqueue(handle, uri, token).then(data => {
if (!data) {
return undefined;
}
const [weight, bubble, tooltip, letter, themeColor] = data;
return <IDecorationData>{
weight: weight || 0,
bubble: bubble || false,
color: themeColor && themeColor.id,
tooltip,
letter
};
});
provideDecorations: async (uri, token) => {
const data = await queue.enqueue(uri, token);
if (!data) {
return undefined;
}
const [weight, bubble, tooltip, letter, themeColor] = data;
return <IDecorationData>{
weight: weight ?? 0,
bubble: bubble ?? false,
color: themeColor?.id,
tooltip,
letter
};
}
});
this._provider.set(handle, [emitter, registration]);

View File

@@ -126,8 +126,12 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
}));
this._toDispose.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => {
if (e.source && (e.operation === FileOperation.MOVE || e.operation === FileOperation.DELETE)) {
this._modelReferenceCollection.remove(e.source);
if (e.operation === FileOperation.MOVE || e.operation === FileOperation.DELETE) {
for (const { source } of e.files) {
if (source) {
this._modelReferenceCollection.remove(source);
}
}
}
}));

View File

@@ -24,9 +24,9 @@ import { ExtHostContext, ExtHostEditorsShape, IApplyEditsOptions, IExtHostContex
import { EditorViewColumn, editorGroupToViewColumn, viewColumnToEditorGroup } from 'vs/workbench/api/common/shared/editor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { openEditorWith } from 'vs/workbench/contrib/files/common/openWith';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { openEditorWith } from 'vs/workbench/services/editor/common/editorOpenWith';
export class MainThreadTextEditors implements MainThreadTextEditorsShape {

View File

@@ -4,10 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import { DisposableStore } from 'vs/base/common/lifecycle';
import { FileChangeType, IFileService, FileOperation } from 'vs/platform/files/common/files';
import { FileChangeType, IFileService } from 'vs/platform/files/common/files';
import { extHostCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { ExtHostContext, FileSystemEvents, IExtHostContext } from '../common/extHost.protocol';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { localize } from 'vs/nls';
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -21,7 +20,6 @@ export class MainThreadFileSystemEventService {
constructor(
extHostContext: IExtHostContext,
@IFileService fileService: IFileService,
@ITextFileService textFileService: ITextFileService,
@IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService
) {
@@ -57,14 +55,13 @@ export class MainThreadFileSystemEventService {
// BEFORE file operation
workingCopyFileService.addFileOperationParticipant({
participate: (target, source, operation, progress, timeout, token) => {
return proxy.$onWillRunFileOperation(operation, target, source, timeout, token);
participate: (files, operation, progress, timeout, token) => {
return proxy.$onWillRunFileOperation(operation, files, timeout, token);
}
});
// AFTER file operation
this._listener.add(textFileService.onDidCreateTextFile(e => proxy.$onDidRunFileOperation(FileOperation.CREATE, e.resource, undefined)));
this._listener.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => proxy.$onDidRunFileOperation(e.operation, e.target, e.source)));
this._listener.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => proxy.$onDidRunFileOperation(e.operation, e.files)));
}
dispose(): void {

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import * as DOM from 'vs/base/browser/dom';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IExtHostContext, ExtHostNotebookShape, ExtHostContext, INotebookDocumentsAndEditorsDelta, INotebookModelAddedData } from '../common/extHost.protocol';
import { Disposable, IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
@@ -40,7 +41,7 @@ export class MainThreadNotebookDocument extends Disposable {
) {
super();
this._textModel = new NotebookTextModel(handle, viewType, supportBackup, uri);
this._textModel = new NotebookTextModel(handle, viewType, supportBackup, uri, undoRedoService);
this._register(this._textModel.onDidModelChangeProxy(e => {
this._proxy.$acceptModelChanged(this.uri, e);
this._proxy.$acceptEditorPropertiesChanged(uri, { selections: { selections: this._textModel.selections }, metadata: null });
@@ -51,9 +52,18 @@ export class MainThreadNotebookDocument extends Disposable {
}));
}
async applyEdit(modelVersionId: number, edits: ICellEditOperation[], emitToExtHost: boolean): Promise<boolean> {
async applyEdit(modelVersionId: number, edits: ICellEditOperation[], emitToExtHost: boolean, synchronous: boolean): Promise<boolean> {
await this.notebookService.transformEditsOutputs(this.textModel, edits);
return this._textModel.$applyEdit(modelVersionId, edits);
if (synchronous) {
return this._textModel.$applyEdit(modelVersionId, edits, emitToExtHost, synchronous);
} else {
return new Promise(resolve => {
this._register(DOM.scheduleAtNextAnimationFrame(() => {
const ret = this._textModel.$applyEdit(modelVersionId, edits, emitToExtHost, true);
resolve(ret);
}));
});
}
}
async spliceNotebookCellOutputs(cellHandle: number, splices: NotebookCellOutputsSplice[]) {
@@ -250,10 +260,10 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
private _emitDelta(delta: INotebookDocumentsAndEditorsDelta) {
if (this._isDeltaEmpty(delta)) {
return;
return undefined; // {{SQL CARBON EDIT}} strict-null-checks
}
this._proxy.$acceptDocumentAndEditorsDelta(delta);
return this._proxy.$acceptDocumentAndEditorsDelta(delta);
}
registerListeners() {
@@ -476,16 +486,11 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
return this._proxy.$executeNotebook(viewType, uri, undefined, useAttachedKernel, token);
}
async $postMessage(handle: number, value: any): Promise<boolean> {
const activeEditorPane = this.editorService.activeEditorPane as any | undefined;
if (activeEditorPane?.isNotebookEditor) {
const notebookEditor = (activeEditorPane.getControl() as INotebookEditor);
if (notebookEditor.viewModel?.handle === handle) {
notebookEditor.postMessage(value);
return true;
}
async $postMessage(editorId: string, forRendererId: string | undefined, value: any): Promise<boolean> {
const editor = this._notebookService.getNotebookEditor(editorId) as INotebookEditor | undefined;
if (editor?.isNotebookEditor) {
editor.postMessage(forRendererId, value);
return true;
}
return false;
@@ -533,7 +538,7 @@ export class MainThreadNotebookController implements IMainNotebookController {
await mainthreadNotebook.applyEdit(mainthreadNotebook.textModel.versionId, [
{ editType: CellEditType.Delete, count: mainthreadNotebook.textModel.cells.length, index: 0 },
{ editType: CellEditType.Insert, index: 0, cells: data.cells }
], true);
], true, false);
}
return mainthreadNotebook.textModel;
}
@@ -553,7 +558,7 @@ export class MainThreadNotebookController implements IMainNotebookController {
index: 0,
cells: backup.cells || []
}
], false);
], false, true);
// create document in ext host with cells data
await this._mainThreadNotebook.addNotebookDocument({
@@ -630,7 +635,7 @@ export class MainThreadNotebookController implements IMainNotebookController {
let mainthreadNotebook = this._mapping.get(URI.from(resource).toString());
if (mainthreadNotebook) {
return await mainthreadNotebook.applyEdit(modelVersionId, edits, true);
return await mainthreadNotebook.applyEdit(modelVersionId, edits, true, true);
}
return false;
@@ -645,8 +650,8 @@ export class MainThreadNotebookController implements IMainNotebookController {
return this._mainThreadNotebook.executeNotebook(viewType, uri, useAttachedKernel, token);
}
onDidReceiveMessage(editorId: string, message: any): void {
this._proxy.$onDidReceiveMessage(editorId, message);
onDidReceiveMessage(editorId: string, rendererType: string | undefined, message: unknown): void {
this._proxy.$onDidReceiveMessage(editorId, rendererType, message);
}
async removeNotebookDocument(notebook: INotebookTextModel): Promise<void> {

View File

@@ -6,7 +6,7 @@
import { URI, UriComponents } from 'vs/base/common/uri';
import { Event, Emitter } from 'vs/base/common/event';
import { assign } from 'vs/base/common/objects';
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IDisposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle';
import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation } from 'vs/workbench/contrib/scm/common/scm';
import { ExtHostContext, MainThreadSCMShape, ExtHostSCMShape, SCMProviderFeatures, SCMRawResourceSplices, SCMGroupFeatures, MainContext, IExtHostContext } from '../common/extHost.protocol';
import { Command } from 'vs/editor/common/modes';
@@ -264,7 +264,7 @@ export class MainThreadSCM implements MainThreadSCMShape {
private readonly _proxy: ExtHostSCMShape;
private _repositories = new Map<number, ISCMRepository>();
private _inputDisposables = new Map<number, IDisposable>();
private _repositoryDisposables = new Map<number, IDisposable>();
private readonly _disposables = new DisposableStore();
constructor(
@@ -272,17 +272,14 @@ export class MainThreadSCM implements MainThreadSCMShape {
@ISCMService private readonly scmService: ISCMService
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostSCM);
Event.debounce(scmService.onDidChangeSelectedRepositories, (_, e) => e, 100)
(this.onDidChangeSelectedRepositories, this, this._disposables);
}
dispose(): void {
this._repositories.forEach(r => r.dispose());
this._repositories.clear();
this._inputDisposables.forEach(d => d.dispose());
this._inputDisposables.clear();
this._repositoryDisposables.forEach(d => d.dispose());
this._repositoryDisposables.clear();
this._disposables.dispose();
}
@@ -292,8 +289,16 @@ export class MainThreadSCM implements MainThreadSCMShape {
const repository = this.scmService.registerSCMProvider(provider);
this._repositories.set(handle, repository);
const inputDisposable = repository.input.onDidChange(value => this._proxy.$onInputBoxValueChange(handle, value));
this._inputDisposables.set(handle, inputDisposable);
const disposable = combinedDisposable(
Event.filter(repository.onDidChangeSelection, selected => selected)(_ => this._proxy.$setSelectedSourceControl(handle)),
repository.input.onDidChange(value => this._proxy.$onInputBoxValueChange(handle, value))
);
if (repository.selected) {
setTimeout(() => this._proxy.$setSelectedSourceControl(handle), 0);
}
this._repositoryDisposables.set(handle, disposable);
}
$updateSourceControl(handle: number, features: SCMProviderFeatures): void {
@@ -314,8 +319,8 @@ export class MainThreadSCM implements MainThreadSCMShape {
return;
}
this._inputDisposables.get(handle)!.dispose();
this._inputDisposables.delete(handle);
this._repositoryDisposables.get(handle)!.dispose();
this._repositoryDisposables.delete(handle);
repository.dispose();
this._repositories.delete(handle);
@@ -422,12 +427,4 @@ export class MainThreadSCM implements MainThreadSCMShape {
repository.input.validateInput = async () => undefined;
}
}
private onDidChangeSelectedRepositories(repositories: ISCMRepository[]): void {
const handles = repositories
.filter(r => r.provider instanceof MainThreadSCMProvider)
.map(r => (r.provider as MainThreadSCMProvider).handle);
this._proxy.$setSelectedSourceControls(handles);
}
}

View File

@@ -15,6 +15,7 @@ import { IAccessibilityInformation } from 'vs/platform/accessibility/common/acce
export class MainThreadStatusBar implements MainThreadStatusBarShape {
private readonly entries: Map<number, { accessor: IStatusbarEntryAccessor, alignment: MainThreadStatusBarAlignment, priority: number }> = new Map();
static readonly CODICON_REGEXP = /\$\((.*?)\)/g;
constructor(
_extHostContext: IExtHostContext,
@@ -32,7 +33,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape {
if (accessibilityInformation) {
ariaLabel = accessibilityInformation.label;
} else {
ariaLabel = text && text.indexOf('$(') === -1 ? text : tooltip || text;
ariaLabel = text ? text.replace(MainThreadStatusBar.CODICON_REGEXP, (_match, codiconName) => codiconName) : '';
}
const entry: IStatusbarEntry = { text, tooltip, command, color, ariaLabel };

View File

@@ -328,10 +328,10 @@ namespace TaskDTO {
result.detail = task.configurationProperties.detail;
}
if (!ConfiguringTask.is(task) && task.command) {
if (task.command.runtime === RuntimeType.Process) {
result.execution = ProcessExecutionDTO.from(task.command);
} else if (task.command.runtime === RuntimeType.Shell) {
result.execution = ShellExecutionDTO.from(task.command);
switch (task.command.runtime) {
case RuntimeType.Process: result.execution = ProcessExecutionDTO.from(task.command); break;
case RuntimeType.Shell: result.execution = ShellExecutionDTO.from(task.command); break;
case RuntimeType.CustomExecution: result.execution = CustomExecutionDTO.from(task.command); break;
}
}
if (task.configurationProperties.problemMatchers) {

View File

@@ -9,7 +9,7 @@ import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceS
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { URI } from 'vs/base/common/uri';
import { StopWatch } from 'vs/base/common/stopwatch';
import { ITerminalInstanceService, ITerminalService, ITerminalInstance, ITerminalBeforeHandleLinkEvent } from 'vs/workbench/contrib/terminal/browser/terminal';
import { ITerminalInstanceService, ITerminalService, ITerminalInstance, ITerminalBeforeHandleLinkEvent, ITerminalExternalLinkProvider, ITerminalLink } from 'vs/workbench/contrib/terminal/browser/terminal';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { TerminalDataBufferer } from 'vs/workbench/contrib/terminal/common/terminalDataBuffering';
@@ -25,6 +25,13 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
private readonly _terminalProcessProxies = new Map<number, ITerminalProcessExtHostProxy>();
private _dataEventTracker: TerminalDataEventTracker | undefined;
private _linkHandler: IDisposable | undefined;
/**
* A single shared terminal link provider for the exthost. When an ext registers a link
* provider, this is registered with the terminal on the renderer side and all links are
* provided through this, even from multiple ext link providers. Xterm should remove lower
* priority intersecting links itself.
*/
private _linkProvider: IDisposable | undefined;
constructor(
extHostContext: IExtHostContext,
@@ -81,11 +88,13 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._proxy.$initEnvironmentVariableCollections(serializedCollections);
}
this._terminalService.extHostReady(extHostContext.remoteAuthority);
this._terminalService.extHostReady(extHostContext.remoteAuthority!); // TODO@Tyriar: remove null assertion
}
public dispose(): void {
this._toDispose.dispose();
this._linkHandler?.dispose();
this._linkProvider?.dispose();
// TODO@Daniel: Should all the previously created terminals be disposed
// when the extension host process goes down ?
@@ -162,6 +171,17 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
public $stopHandlingLinks(): void {
this._linkHandler?.dispose();
this._linkHandler = undefined;
}
public $startLinkProvider(): void {
this._linkProvider?.dispose();
this._linkProvider = this._terminalService.registerLinkProvider(new ExtensionTerminalLinkProvider(this._proxy));
}
public $stopLinkProvider(): void {
this._linkProvider?.dispose();
this._linkProvider = undefined;
}
private async _handleLink(e: ITerminalBeforeHandleLinkEvent): Promise<boolean> {
@@ -395,3 +415,22 @@ class TerminalDataEventTracker extends Disposable {
this._register(this._bufferer.startBuffering(instance.id, instance.onData));
}
}
class ExtensionTerminalLinkProvider implements ITerminalExternalLinkProvider {
constructor(
private readonly _proxy: ExtHostTerminalServiceShape
) {
}
async provideLinks(instance: ITerminalInstance, line: string): Promise<ITerminalLink[] | undefined> {
const proxy = this._proxy;
const extHostLinks = await proxy.$provideLinks(instance.id, line);
return extHostLinks.map(dto => ({
id: dto.id,
startIndex: dto.startIndex,
length: dto.length,
label: dto.label,
activate: () => proxy.$activateLink(instance.id, dto.id)
}));
}
}

View File

@@ -5,7 +5,7 @@
import { Disposable } from 'vs/base/common/lifecycle';
import { ExtHostContext, MainThreadTreeViewsShape, ExtHostTreeViewsShape, MainContext, IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { ITreeViewDataProvider, ITreeItem, IViewsService, ITreeView, IViewsRegistry, ITreeViewDescriptor, IRevealOptions, Extensions } from 'vs/workbench/common/views';
import { ITreeViewDataProvider, ITreeItem, IViewsService, ITreeView, IViewsRegistry, ITreeViewDescriptor, IRevealOptions, Extensions, ResolvableTreeItem } from 'vs/workbench/common/views';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { distinct } from 'vs/base/common/arrays';
import { INotificationService } from 'vs/platform/notification/common/notification';
@@ -165,12 +165,14 @@ export type TreeItemHandle = string;
export class TreeViewDataProvider implements ITreeViewDataProvider {
private readonly itemsMap: Map<TreeItemHandle, ITreeItem> = new Map<TreeItemHandle, ITreeItem>();
private hasResolve: Promise<boolean>;
// {{SQL CARBON EDIT}}
constructor(protected readonly treeViewId: string,
protected readonly _proxy: ExtHostTreeViewsShape,
private readonly notificationService: INotificationService
) {
this.hasResolve = this._proxy.$hasResolve(this.treeViewId);
}
getChildren(treeItem?: ITreeItem): Promise<ITreeItem[]> {
@@ -217,12 +219,16 @@ export class TreeViewDataProvider implements ITreeViewDataProvider {
return this.itemsMap.size === 0;
}
private postGetChildren(elements: ITreeItem[]): ITreeItem[] {
const result: ITreeItem[] = [];
private async postGetChildren(elements: ITreeItem[]): Promise<ResolvableTreeItem[]> {
const result: ResolvableTreeItem[] = [];
const hasResolve = await this.hasResolve;
if (elements) {
for (const element of elements) {
const resolvable = new ResolvableTreeItem(element, hasResolve ? () => {
return this._proxy.$resolve(this.treeViewId, element.handle);
} : undefined);
this.itemsMap.set(element.handle, element);
result.push(element);
result.push(resolvable);
}
}
return result;

View File

@@ -141,7 +141,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
this._register(_editorService.onDidActiveEditorChange(() => {
const activeInput = this._editorService.activeEditor;
if (activeInput instanceof DiffEditorInput && activeInput.master instanceof WebviewInput && activeInput.details instanceof WebviewInput) {
if (activeInput instanceof DiffEditorInput && activeInput.primary instanceof WebviewInput && activeInput.secondary instanceof WebviewInput) {
this.registerWebviewFromDiffEditorListeners(activeInput);
}
@@ -185,6 +185,15 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
});
}
dispose() {
super.dispose();
for (const disposable of this._editorProviders.values()) {
disposable.dispose();
}
this._editorProviders.clear();
}
public $createWebviewPanel(
extensionData: extHostProtocol.WebviewExtensionDescription,
handle: extHostProtocol.WebviewPanelHandle,
@@ -320,7 +329,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
options: modes.IWebviewPanelOptions,
capabilities: extHostProtocol.CustomTextEditorCapabilities,
supportsMultipleEditorsPerDocument: boolean,
): DisposableStore {
): void {
if (this._editorProviders.has(viewType)) {
throw new Error(`Provider for ${viewType} already registered`);
}
@@ -396,8 +405,6 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
}));
this._editorProviders.set(viewType, disposables);
return disposables;
}
public $unregisterEditorProvider(viewType: string): void {
@@ -468,22 +475,22 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
}
private registerWebviewFromDiffEditorListeners(diffEditorInput: DiffEditorInput): void {
const master = diffEditorInput.master as WebviewInput;
const details = diffEditorInput.details as WebviewInput;
const primary = diffEditorInput.primary as WebviewInput;
const secondary = diffEditorInput.secondary as WebviewInput;
if (this._webviewFromDiffEditorHandles.has(master.id) || this._webviewFromDiffEditorHandles.has(details.id)) {
if (this._webviewFromDiffEditorHandles.has(primary.id) || this._webviewFromDiffEditorHandles.has(secondary.id)) {
return;
}
this._webviewFromDiffEditorHandles.add(master.id);
this._webviewFromDiffEditorHandles.add(details.id);
this._webviewFromDiffEditorHandles.add(primary.id);
this._webviewFromDiffEditorHandles.add(secondary.id);
const disposables = new DisposableStore();
disposables.add(master.webview.onDidFocus(() => this.updateWebviewViewStates(master)));
disposables.add(details.webview.onDidFocus(() => this.updateWebviewViewStates(details)));
disposables.add(primary.webview.onDidFocus(() => this.updateWebviewViewStates(primary)));
disposables.add(secondary.webview.onDidFocus(() => this.updateWebviewViewStates(secondary)));
disposables.add(diffEditorInput.onDispose(() => {
this._webviewFromDiffEditorHandles.delete(master.id);
this._webviewFromDiffEditorHandles.delete(details.id);
this._webviewFromDiffEditorHandles.delete(primary.id);
this._webviewFromDiffEditorHandles.delete(secondary.id);
dispose(disposables);
}));
}
@@ -515,8 +522,8 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
for (const group of this._editorGroupService.groups) {
for (const input of group.editors) {
if (input instanceof DiffEditorInput) {
updateViewStatesForInput(group, input, input.master);
updateViewStatesForInput(group, input, input.details);
updateViewStatesForInput(group, input, input.primary);
updateViewStatesForInput(group, input, input.secondary);
} else {
updateViewStatesForInput(group, input, input);
}

View File

@@ -9,7 +9,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
import * as resources from 'vs/base/common/resources';
import { ExtensionMessageCollector, ExtensionsRegistry, IExtensionPoint, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { ViewContainer, IViewsRegistry, ITreeViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions, TEST_VIEW_CONTAINER_ID, IViewDescriptor, ViewContainerLocation } from 'vs/workbench/common/views';
import { TreeViewPane, CustomTreeView } from 'vs/workbench/browser/parts/views/treeView';
import { TreeViewPane } from 'vs/workbench/browser/parts/views/treeView';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { coalesce, } from 'vs/base/common/arrays';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
@@ -32,6 +32,7 @@ import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { Codicon } from 'vs/base/common/codicons';
import { CustomTreeView } from 'vs/workbench/contrib/views/browser/treeView';
export interface IUserFriendlyViewsContainerDescriptor {
id: string;