mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-13 19:48:37 -05:00
Merge from vscode 2cd495805cf99b31b6926f08ff4348124b2cf73d
This commit is contained in:
committed by
AzureDataStudio
parent
a8a7559229
commit
1388493cc1
@@ -46,7 +46,7 @@ import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ExtHostUrls } from 'vs/workbench/api/common/extHostUrls';
|
||||
import { ExtHostWebviews } from 'vs/workbench/api/common/extHostWebview';
|
||||
import { ExtHostWindow } from 'vs/workbench/api/common/extHostWindow';
|
||||
import { IExtHostWindow } from 'vs/workbench/api/common/extHostWindow';
|
||||
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { throwProposedApiError, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
@@ -98,6 +98,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostLogService = accessor.get(ILogService);
|
||||
const extHostTunnelService = accessor.get(IExtHostTunnelService);
|
||||
const extHostApiDeprecation = accessor.get(IExtHostApiDeprecationService);
|
||||
const extHostWindow = accessor.get(IExtHostWindow);
|
||||
|
||||
// register addressable instances
|
||||
rpcProtocol.set(ExtHostContext.ExtHostLogService, <ExtHostLogServiceShape><any>extHostLogService);
|
||||
@@ -106,6 +107,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostTunnelService, extHostTunnelService);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostWindow, extHostWindow);
|
||||
|
||||
// automatically create and register addressable instances
|
||||
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, accessor.get(IExtHostDecorations));
|
||||
@@ -132,10 +134,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands));
|
||||
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
|
||||
const extHostComment = rpcProtocol.set(ExtHostContext.ExtHostComments, new ExtHostComments(rpcProtocol, extHostCommands, extHostDocuments));
|
||||
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
|
||||
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
|
||||
const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHosLabelService, new ExtHostLabelService(rpcProtocol));
|
||||
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, initData.environment, extensionStoragePaths));
|
||||
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, initData.uiKind === UIKind.Web ? new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, initData.environment) : new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, initData.environment, extensionStoragePaths));
|
||||
const extHostTheming = rpcProtocol.set(ExtHostContext.ExtHostTheming, new ExtHostTheming(rpcProtocol));
|
||||
const extHostAuthentication = rpcProtocol.set(ExtHostContext.ExtHostAuthentication, new ExtHostAuthentication(rpcProtocol));
|
||||
const extHostTimeline = rpcProtocol.set(ExtHostContext.ExtHostTimeline, new ExtHostTimeline(rpcProtocol, extHostCommands));
|
||||
@@ -208,12 +209,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
getSession(providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions) {
|
||||
return extHostAuthentication.getSession(extension, providerId, scopes, options as any);
|
||||
},
|
||||
getSessions(providerId: string, scopes: string[]): Thenable<readonly vscode.AuthenticationSession[]> {
|
||||
return extHostAuthentication.getSessions(extension, providerId, scopes);
|
||||
},
|
||||
login(providerId: string, scopes: string[]): Thenable<vscode.AuthenticationSession> {
|
||||
return extHostAuthentication.login(extension, providerId, scopes);
|
||||
},
|
||||
logout(providerId: string, sessionId: string): Thenable<void> {
|
||||
return extHostAuthentication.logout(providerId, sessionId);
|
||||
},
|
||||
@@ -589,6 +584,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTerminalService.registerLinkHandler(handler);
|
||||
},
|
||||
registerTerminalLinkProvider(handler: vscode.TerminalLinkProvider): vscode.Disposable {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTerminalService.registerLinkProvider(handler);
|
||||
},
|
||||
registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.Disposable {
|
||||
return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider, extension);
|
||||
},
|
||||
@@ -1119,7 +1118,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
CellKind: extHostTypes.CellKind,
|
||||
CellOutputKind: extHostTypes.CellOutputKind,
|
||||
NotebookCellRunState: extHostTypes.NotebookCellRunState,
|
||||
AuthenticationSession2: extHostTypes.AuthenticationSession
|
||||
AuthenticationSession: extHostTypes.AuthenticationSession
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ export interface IConfigurationInitData extends IConfigurationData {
|
||||
}
|
||||
|
||||
export interface IExtHostContext extends IRPCProtocol {
|
||||
remoteAuthority: string;
|
||||
remoteAuthority: string | null;
|
||||
}
|
||||
|
||||
export interface IMainContext extends IRPCProtocol {
|
||||
@@ -454,6 +454,8 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
|
||||
$stopSendingDataEvents(): void;
|
||||
$startHandlingLinks(): void;
|
||||
$stopHandlingLinks(): void;
|
||||
$startLinkProvider(): void;
|
||||
$stopLinkProvider(): void;
|
||||
$setEnvironmentVariableCollection(extensionIdentifier: string, persistent: boolean, collection: ISerializableEnvironmentVariableCollection | undefined): void;
|
||||
|
||||
// Process
|
||||
@@ -713,7 +715,7 @@ export interface MainThreadNotebookShape extends IDisposable {
|
||||
$updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata): Promise<void>;
|
||||
$updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata | undefined): Promise<void>;
|
||||
$spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise<void>;
|
||||
$postMessage(handle: number, value: any): Promise<boolean>;
|
||||
$postMessage(editorId: string, forRendererId: string | undefined, value: any): Promise<boolean>;
|
||||
|
||||
$onDidEdit(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void;
|
||||
$onContentChange(resource: UriComponents, viewType: string): void;
|
||||
@@ -860,6 +862,7 @@ export interface IStartDebuggingOptions {
|
||||
parentSessionID?: DebugSessionUUID;
|
||||
repl?: IDebugSessionReplMode;
|
||||
noDebug?: boolean;
|
||||
noCompact?: boolean;
|
||||
}
|
||||
|
||||
export interface MainThreadDebugServiceShape extends IDisposable {
|
||||
@@ -990,6 +993,8 @@ export interface ExtHostTreeViewsShape {
|
||||
$setExpanded(treeViewId: string, treeItemHandle: string, expanded: boolean): void;
|
||||
$setSelection(treeViewId: string, treeItemHandles: string[]): void;
|
||||
$setVisible(treeViewId: string, visible: boolean): void;
|
||||
$hasResolve(treeViewId: string): Promise<boolean>;
|
||||
$resolve(treeViewId: string, treeItemHandle: string): Promise<ITreeItem | undefined>;
|
||||
}
|
||||
|
||||
export interface ExtHostWorkspaceShape {
|
||||
@@ -1071,10 +1076,15 @@ export interface FileSystemEvents {
|
||||
deleted: UriComponents[];
|
||||
}
|
||||
|
||||
export interface SourceTargetPair {
|
||||
source?: UriComponents;
|
||||
target: UriComponents;
|
||||
}
|
||||
|
||||
export interface ExtHostFileSystemEventServiceShape {
|
||||
$onFileEvent(events: FileSystemEvents): void;
|
||||
$onWillRunFileOperation(operation: files.FileOperation, target: UriComponents, source: UriComponents | undefined, timeout: number, token: CancellationToken): Promise<any>;
|
||||
$onDidRunFileOperation(operation: files.FileOperation, target: UriComponents, source: UriComponents | undefined): void;
|
||||
$onWillRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise<any>;
|
||||
$onDidRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[]): void;
|
||||
}
|
||||
|
||||
export interface ObjectIdentifier {
|
||||
@@ -1385,6 +1395,17 @@ export interface IShellAndArgsDto {
|
||||
args: string[] | string | undefined;
|
||||
}
|
||||
|
||||
export interface ITerminalLinkDto {
|
||||
/** The ID of the link to enable activation and disposal. */
|
||||
id: number;
|
||||
/** The startIndex of the link in the line. */
|
||||
startIndex: number;
|
||||
/** The length of the link in the line. */
|
||||
length: number;
|
||||
/** The descriptive label for what the link does when activated. */
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export interface ITerminalDimensionsDto {
|
||||
columns: number;
|
||||
rows: number;
|
||||
@@ -1411,6 +1432,8 @@ export interface ExtHostTerminalServiceShape {
|
||||
$getAvailableShells(): Promise<IShellDefinitionDto[]>;
|
||||
$getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto>;
|
||||
$handleLink(id: number, link: string): Promise<boolean>;
|
||||
$provideLinks(id: number, line: string): Promise<ITerminalLinkDto[]>;
|
||||
$activateLink(id: number, linkId: number): void;
|
||||
$initEnvironmentVariableCollections(collections: [string, ISerializableEnvironmentVariableCollection][]): void;
|
||||
}
|
||||
|
||||
@@ -1419,7 +1442,7 @@ export interface ExtHostSCMShape {
|
||||
$onInputBoxValueChange(sourceControlHandle: number, value: string): void;
|
||||
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number, preserveFocus: boolean): Promise<void>;
|
||||
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string, number] | undefined>;
|
||||
$setSelectedSourceControls(selectedSourceControlHandles: number[]): Promise<void>;
|
||||
$setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ExtHostTaskShape {
|
||||
@@ -1514,7 +1537,6 @@ export interface ExtHostDebugServiceShape {
|
||||
|
||||
export interface DecorationRequest {
|
||||
readonly id: number;
|
||||
readonly handle: number;
|
||||
readonly uri: UriComponents;
|
||||
}
|
||||
|
||||
@@ -1522,7 +1544,7 @@ export type DecorationData = [number, boolean, string, string, ThemeColor];
|
||||
export type DecorationReply = { [id: number]: DecorationData; };
|
||||
|
||||
export interface ExtHostDecorationsShape {
|
||||
$provideDecorations(requests: DecorationRequest[], token: CancellationToken): Promise<DecorationReply>;
|
||||
$provideDecorations(handle: number, requests: DecorationRequest[], token: CancellationToken): Promise<DecorationReply>;
|
||||
}
|
||||
|
||||
export interface ExtHostWindowShape {
|
||||
@@ -1599,7 +1621,7 @@ export interface ExtHostNotebookShape {
|
||||
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void;
|
||||
$renderOutputs(uriComponents: UriComponents, id: string, request: IOutputRenderRequest<UriComponents>): Promise<IOutputRenderResponse<UriComponents> | undefined>;
|
||||
$renderOutputs2<T>(uriComponents: UriComponents, id: string, request: IOutputRenderRequest<T>): Promise<IOutputRenderResponse<T> | undefined>;
|
||||
$onDidReceiveMessage(editorId: string, message: any): void;
|
||||
$onDidReceiveMessage(editorId: string, rendererId: string | undefined, message: unknown): void;
|
||||
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void;
|
||||
$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void;
|
||||
$acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta): Promise<void>;
|
||||
|
||||
@@ -56,8 +56,8 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
return !!(sessions.filter(session => session.scopes.sort().join(' ') === orderedScopes).length);
|
||||
}
|
||||
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions & { createIfNone: true }): Promise<vscode.AuthenticationSession2>;
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions): Promise<vscode.AuthenticationSession2 | undefined> {
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions & { createIfNone: true }): Promise<vscode.AuthenticationSession>;
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions): Promise<vscode.AuthenticationSession | undefined> {
|
||||
const provider = this._authenticationProviders.get(providerId);
|
||||
const extensionName = requestingExtension.displayName || requestingExtension.name;
|
||||
const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier);
|
||||
@@ -100,71 +100,6 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
}
|
||||
}
|
||||
|
||||
async getSessions(requestingExtension: IExtensionDescription, providerId: string, scopes: string[]): Promise<readonly vscode.AuthenticationSession[]> {
|
||||
const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier);
|
||||
const orderedScopes = scopes.sort().join(' ');
|
||||
const sessions = await this.resolveSessions(providerId);
|
||||
return sessions
|
||||
.filter(session => session.scopes.sort().join(' ') === orderedScopes)
|
||||
.map(session => {
|
||||
return {
|
||||
id: session.id,
|
||||
account: session.account,
|
||||
scopes: session.scopes,
|
||||
getAccessToken: async () => {
|
||||
const isAllowed = await this._proxy.$getSessionsPrompt(
|
||||
providerId,
|
||||
session.account.displayName,
|
||||
'', // TODO
|
||||
// provider.displayName,
|
||||
extensionId,
|
||||
requestingExtension.displayName || requestingExtension.name);
|
||||
|
||||
if (!isAllowed) {
|
||||
throw new Error('User did not consent to token access.');
|
||||
}
|
||||
|
||||
return session.accessToken;
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async login(requestingExtension: IExtensionDescription, providerId: string, scopes: string[]): Promise<vscode.AuthenticationSession> {
|
||||
const provider = this._authenticationProviders.get(providerId);
|
||||
if (!provider) {
|
||||
throw new Error(`No authentication provider with id '${providerId}' is currently registered.`);
|
||||
}
|
||||
|
||||
const extensionName = requestingExtension.displayName || requestingExtension.name;
|
||||
const isAllowed = await this._proxy.$loginPrompt(provider.displayName, extensionName);
|
||||
if (!isAllowed) {
|
||||
throw new Error('User did not consent to login.');
|
||||
}
|
||||
|
||||
const session = await provider.login(scopes);
|
||||
await this._proxy.$setTrustedExtension(provider.id, session.account.displayName, ExtensionIdentifier.toKey(requestingExtension.identifier), extensionName);
|
||||
return {
|
||||
id: session.id,
|
||||
account: session.account,
|
||||
scopes: session.scopes,
|
||||
getAccessToken: async () => {
|
||||
const isAllowed = await this._proxy.$getSessionsPrompt(
|
||||
provider.id,
|
||||
session.account.displayName,
|
||||
provider.displayName,
|
||||
ExtensionIdentifier.toKey(requestingExtension.identifier),
|
||||
requestingExtension.displayName || requestingExtension.name);
|
||||
|
||||
if (!isAllowed) {
|
||||
throw new Error('User did not consent to token access.');
|
||||
}
|
||||
|
||||
return session.accessToken;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async logout(providerId: string, sessionId: string): Promise<void> {
|
||||
const provider = this._authenticationProviders.get(providerId);
|
||||
if (!provider) {
|
||||
|
||||
@@ -296,7 +296,8 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E
|
||||
return this._debugServiceProxy.$startDebugging(folder ? folder.uri : undefined, nameOrConfig, {
|
||||
parentSessionID: options.parentSession ? options.parentSession.id : undefined,
|
||||
repl: options.consoleMode === DebugConsoleMode.MergeWithParent ? 'mergeWithParent' : 'separate',
|
||||
noDebug: options.noDebug
|
||||
noDebug: options.noDebug,
|
||||
noCompact: options.noCompact
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -52,17 +52,20 @@ export class ExtHostDecorations implements IExtHostDecorations {
|
||||
});
|
||||
}
|
||||
|
||||
$provideDecorations(requests: DecorationRequest[], token: CancellationToken): Promise<DecorationReply> {
|
||||
async $provideDecorations(handle: number, requests: DecorationRequest[], token: CancellationToken): Promise<DecorationReply> {
|
||||
|
||||
if (!this._provider.has(handle)) {
|
||||
// might have been unregistered in the meantime
|
||||
return Object.create(null);
|
||||
}
|
||||
|
||||
const result: DecorationReply = Object.create(null);
|
||||
return Promise.all(requests.map(request => {
|
||||
const { handle, uri, id } = request;
|
||||
const entry = this._provider.get(handle);
|
||||
if (!entry) {
|
||||
// might have been unregistered in the meantime
|
||||
return undefined;
|
||||
}
|
||||
const { provider, extensionId } = entry;
|
||||
return Promise.resolve(provider.provideDecoration(URI.revive(uri), token)).then(data => {
|
||||
const { provider, extensionId } = this._provider.get(handle)!;
|
||||
|
||||
await Promise.all(requests.map(async request => {
|
||||
try {
|
||||
const { uri, id } = request;
|
||||
const data = await Promise.resolve(provider.provideDecoration(URI.revive(uri), token));
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
@@ -72,13 +75,12 @@ export class ExtHostDecorations implements IExtHostDecorations {
|
||||
} catch (e) {
|
||||
this._logService.warn(`INVALID decoration from extension '${extensionId.value}': ${e}`);
|
||||
}
|
||||
}, err => {
|
||||
} catch (err) {
|
||||
this._logService.error(err);
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
})).then(() => {
|
||||
return result;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
import { AsyncEmitter, Emitter, Event, IWaitUntil } from 'vs/base/common/event';
|
||||
import { IRelativePattern, parse } from 'vs/base/common/glob';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import type * as vscode from 'vscode';
|
||||
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, MainContext, MainThreadTextEditorsShape, IWorkspaceFileEditDto, IWorkspaceTextEditDto } from './extHost.protocol';
|
||||
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, MainContext, MainThreadTextEditorsShape, IWorkspaceFileEditDto, IWorkspaceTextEditDto, SourceTargetPair } from './extHost.protocol';
|
||||
import * as typeConverter from './extHostTypeConverters';
|
||||
import { Disposable, WorkspaceEdit } from './extHostTypes';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
@@ -142,16 +142,16 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
|
||||
|
||||
//--- file operations
|
||||
|
||||
$onDidRunFileOperation(operation: FileOperation, target: UriComponents, source: UriComponents | undefined): void {
|
||||
$onDidRunFileOperation(operation: FileOperation, files: SourceTargetPair[]): void {
|
||||
switch (operation) {
|
||||
case FileOperation.MOVE:
|
||||
this._onDidRenameFile.fire(Object.freeze({ files: [{ oldUri: URI.revive(source!), newUri: URI.revive(target) }] }));
|
||||
this._onDidRenameFile.fire(Object.freeze({ files: files.map(f => ({ oldUri: URI.revive(f.source!), newUri: URI.revive(f.target) })) }));
|
||||
break;
|
||||
case FileOperation.DELETE:
|
||||
this._onDidDeleteFile.fire(Object.freeze({ files: [URI.revive(target)] }));
|
||||
this._onDidDeleteFile.fire(Object.freeze({ files: files.map(f => URI.revive(f.target)) }));
|
||||
break;
|
||||
case FileOperation.CREATE:
|
||||
this._onDidCreateFile.fire(Object.freeze({ files: [URI.revive(target)] }));
|
||||
this._onDidCreateFile.fire(Object.freeze({ files: files.map(f => URI.revive(f.target)) }));
|
||||
break;
|
||||
default:
|
||||
//ignore, dont send
|
||||
@@ -179,16 +179,16 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
|
||||
};
|
||||
}
|
||||
|
||||
async $onWillRunFileOperation(operation: FileOperation, target: UriComponents, source: UriComponents | undefined, timeout: number, token: CancellationToken): Promise<any> {
|
||||
async $onWillRunFileOperation(operation: FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise<any> {
|
||||
switch (operation) {
|
||||
case FileOperation.MOVE:
|
||||
await this._fireWillEvent(this._onWillRenameFile, { files: [{ oldUri: URI.revive(source!), newUri: URI.revive(target) }] }, timeout, token);
|
||||
await this._fireWillEvent(this._onWillRenameFile, { files: files.map(f => ({ oldUri: URI.revive(f.source!), newUri: URI.revive(f.target) })) }, timeout, token);
|
||||
break;
|
||||
case FileOperation.DELETE:
|
||||
await this._fireWillEvent(this._onWillDeleteFile, { files: [URI.revive(target)] }, timeout, token);
|
||||
await this._fireWillEvent(this._onWillDeleteFile, { files: files.map(f => URI.revive(f.target)) }, timeout, token);
|
||||
break;
|
||||
case FileOperation.CREATE:
|
||||
await this._fireWillEvent(this._onWillCreateFile, { files: [URI.revive(target)] }, timeout, token);
|
||||
await this._fireWillEvent(this._onWillCreateFile, { files: files.map(f => URI.revive(f.target)) }, timeout, token);
|
||||
break;
|
||||
default:
|
||||
//ignore, dont send
|
||||
|
||||
@@ -73,7 +73,7 @@ class DocumentSymbolAdapter {
|
||||
const element: modes.DocumentSymbol = {
|
||||
name: info.name || '!!MISSING: name!!',
|
||||
kind: typeConvert.SymbolKind.from(info.kind),
|
||||
tags: info.tags ? info.tags.map(typeConvert.SymbolTag.from) : [],
|
||||
tags: info.tags?.map(typeConvert.SymbolTag.from) || [],
|
||||
detail: '',
|
||||
containerName: info.containerName,
|
||||
range: typeConvert.Range.from(info.location.range),
|
||||
@@ -1287,6 +1287,7 @@ class CallHierarchyAdapter {
|
||||
uri: item.uri,
|
||||
range: typeConvert.Range.from(item.range),
|
||||
selectionRange: typeConvert.Range.from(item.selectionRange),
|
||||
tags: item.tags?.map(typeConvert.SymbolTag.from)
|
||||
};
|
||||
map.set(dto._itemId, item);
|
||||
return dto;
|
||||
|
||||
@@ -553,27 +553,48 @@ export class NotebookEditorCellEditBuilder implements vscode.NotebookEditorCellE
|
||||
}
|
||||
}
|
||||
|
||||
class ExtHostWebviewComm extends Disposable {
|
||||
|
||||
onDidReceiveMessage: vscode.Event<any> = this._onDidReceiveMessage.event;
|
||||
class ExtHostWebviewCommWrapper extends Disposable {
|
||||
private readonly _onDidReceiveDocumentMessage = new Emitter<any>();
|
||||
private readonly _rendererIdToEmitters = new Map<string, Emitter<any>>();
|
||||
|
||||
constructor(
|
||||
readonly id: string,
|
||||
private _editorId: string,
|
||||
public uri: URI,
|
||||
private _proxy: MainThreadNotebookShape,
|
||||
private _onDidReceiveMessage: Emitter<any>,
|
||||
private _webviewInitData: WebviewInitData,
|
||||
public document: ExtHostNotebookDocument,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async postMessage(message: any): Promise<boolean> {
|
||||
return this._proxy.$postMessage(this.document.handle, message);
|
||||
public onDidReceiveMessage(forRendererId: string | undefined, message: any) {
|
||||
this._onDidReceiveDocumentMessage.fire(message);
|
||||
if (forRendererId !== undefined) {
|
||||
this._rendererIdToEmitters.get(forRendererId)?.fire(message);
|
||||
}
|
||||
}
|
||||
|
||||
asWebviewUri(localResource: vscode.Uri): vscode.Uri {
|
||||
return asWebviewUri(this._webviewInitData, this.id, localResource);
|
||||
public readonly contentProviderComm: vscode.NotebookCommunication = {
|
||||
editorId: this._editorId,
|
||||
onDidReceiveMessage: this._onDidReceiveDocumentMessage.event,
|
||||
postMessage: (message: any) => this._proxy.$postMessage(this._editorId, undefined, message),
|
||||
asWebviewUri: (uri: vscode.Uri) => this._asWebviewUri(uri),
|
||||
};
|
||||
|
||||
public getRendererComm(rendererId: string): vscode.NotebookCommunication {
|
||||
const emitter = new Emitter<any>();
|
||||
this._rendererIdToEmitters.set(rendererId, emitter);
|
||||
return {
|
||||
editorId: this._editorId,
|
||||
onDidReceiveMessage: emitter.event,
|
||||
postMessage: (message: any) => this._proxy.$postMessage(this._editorId, rendererId, message),
|
||||
asWebviewUri: (uri: vscode.Uri) => this._asWebviewUri(uri),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private _asWebviewUri(localResource: vscode.Uri): vscode.Uri {
|
||||
return asWebviewUri(this._webviewInitData, this._editorId, localResource);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,7 +639,7 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
readonly id: string,
|
||||
public uri: URI,
|
||||
private _proxy: MainThreadNotebookShape,
|
||||
private _webComm: ExtHostWebviewComm,
|
||||
private _webComm: vscode.NotebookCommunication,
|
||||
public document: ExtHostNotebookDocument,
|
||||
private _documentsAndEditors: ExtHostDocumentsAndEditors
|
||||
) {
|
||||
@@ -721,6 +742,7 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
|
||||
export class ExtHostNotebookOutputRenderer {
|
||||
private static _handlePool: number = 0;
|
||||
private resolvedComms = new WeakSet<ExtHostWebviewCommWrapper>();
|
||||
readonly handle = ExtHostNotebookOutputRenderer._handlePool++;
|
||||
|
||||
constructor(
|
||||
@@ -740,13 +762,19 @@ export class ExtHostNotebookOutputRenderer {
|
||||
return false;
|
||||
}
|
||||
|
||||
resolveNotebook(document: ExtHostNotebookDocument, comm: ExtHostWebviewCommWrapper) {
|
||||
if (!this.resolvedComms.has(comm) && this.renderer.resolveNotebook) {
|
||||
this.renderer.resolveNotebook(document, comm.getRendererComm(this.type));
|
||||
this.resolvedComms.add(comm);
|
||||
}
|
||||
}
|
||||
|
||||
render(document: ExtHostNotebookDocument, output: vscode.CellDisplayOutput, outputId: string, mimeType: string): string {
|
||||
let html = this.renderer.render(document, { output, outputId, mimeType });
|
||||
|
||||
return html;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ExtHostNotebookOutputRenderingHandler {
|
||||
outputDisplayOrder: INotebookDisplayOrder | undefined;
|
||||
findBestMatchedRenderer(mimeType: string): ExtHostNotebookOutputRenderer[];
|
||||
@@ -759,8 +787,9 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
private readonly _documents = new Map<string, ExtHostNotebookDocument>();
|
||||
private readonly _unInitializedDocuments = new Map<string, ExtHostNotebookDocument>();
|
||||
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor }>();
|
||||
private readonly _webviewComm = new Map<string, { comm: ExtHostWebviewComm, onDidReceiveMessage: Emitter<any> }>();
|
||||
private readonly _webviewComm = new Map<string, ExtHostWebviewCommWrapper>();
|
||||
private readonly _notebookOutputRenderers = new Map<string, ExtHostNotebookOutputRenderer>();
|
||||
private readonly _renderersUsedInNotebooks = new WeakMap<ExtHostNotebookDocument, Set<ExtHostNotebookOutputRenderer>>();
|
||||
private readonly _onDidChangeNotebookCells = new Emitter<vscode.NotebookCellsChangeEvent>();
|
||||
readonly onDidChangeNotebookCells = this._onDidChangeNotebookCells.event;
|
||||
private readonly _onDidChangeCellOutputs = new Emitter<vscode.NotebookCellOutputsChangeEvent>();
|
||||
@@ -854,6 +883,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
}
|
||||
|
||||
const renderer = this._notebookOutputRenderers.get(id)!;
|
||||
this.provideCommToNotebookRenderers(document, renderer);
|
||||
|
||||
const cellsResponse: IOutputRenderResponseCellInfo<UriComponents>[] = request.items.map(cellInfo => {
|
||||
const cell = document.getCell2(cellInfo.key)!;
|
||||
const outputResponse: IOutputRenderResponseOutputInfo[] = cellInfo.outputs.map(output => {
|
||||
@@ -890,6 +921,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
}
|
||||
|
||||
const renderer = this._notebookOutputRenderers.get(id)!;
|
||||
this.provideCommToNotebookRenderers(document, renderer);
|
||||
|
||||
const cellsResponse: IOutputRenderResponseCellInfo<T>[] = request.items.map(cellInfo => {
|
||||
const outputResponse: IOutputRenderResponseOutputInfo[] = cellInfo.outputs.map(output => {
|
||||
return {
|
||||
@@ -1035,19 +1068,36 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
return;
|
||||
}
|
||||
|
||||
let webComm = this._webviewComm.get(editorId);
|
||||
if (!webComm) {
|
||||
webComm = new ExtHostWebviewCommWrapper(editorId, revivedUri, this._proxy, this._webviewInitData, document);
|
||||
this._webviewComm.set(editorId, webComm);
|
||||
}
|
||||
|
||||
if (!provider.provider.resolveNotebook) {
|
||||
return;
|
||||
}
|
||||
|
||||
let webComm = this._webviewComm.get(editorId)?.comm;
|
||||
await provider.provider.resolveNotebook(document, webComm.contentProviderComm);
|
||||
}
|
||||
|
||||
if (webComm) {
|
||||
await provider.provider.resolveNotebook(document, webComm);
|
||||
} else {
|
||||
const onDidReceiveMessage = new Emitter<any>();
|
||||
webComm = new ExtHostWebviewComm(editorId, revivedUri, this._proxy, onDidReceiveMessage, this._webviewInitData, document);
|
||||
this._webviewComm.set(editorId, { comm: webComm, onDidReceiveMessage });
|
||||
await provider.provider.resolveNotebook(document, webComm);
|
||||
private provideCommToNotebookRenderers(document: ExtHostNotebookDocument, renderer: ExtHostNotebookOutputRenderer) {
|
||||
let alreadyRegistered = this._renderersUsedInNotebooks.get(document);
|
||||
if (!alreadyRegistered) {
|
||||
alreadyRegistered = new Set();
|
||||
this._renderersUsedInNotebooks.set(document, alreadyRegistered);
|
||||
}
|
||||
|
||||
if (alreadyRegistered.has(renderer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
alreadyRegistered.add(renderer);
|
||||
for (const editorId of this._editors.keys()) {
|
||||
const comm = this._webviewComm.get(editorId);
|
||||
if (comm) {
|
||||
renderer.resolveNotebook(document, comm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1101,12 +1151,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
}
|
||||
|
||||
if (this._notebookContentProviders.has(viewType)) {
|
||||
try {
|
||||
await this._notebookContentProviders.get(viewType)!.provider.saveNotebook(document, token);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await this._notebookContentProviders.get(viewType)!.provider.saveNotebook(document, token);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1120,12 +1165,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
}
|
||||
|
||||
if (this._notebookContentProviders.has(viewType)) {
|
||||
try {
|
||||
await this._notebookContentProviders.get(viewType)!.provider.saveNotebookAs(URI.revive(target), document, token);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await this._notebookContentProviders.get(viewType)!.provider.saveNotebookAs(URI.revive(target), document, token);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1182,12 +1222,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
return editor;
|
||||
}
|
||||
|
||||
$onDidReceiveMessage(editorId: string, message: any): void {
|
||||
let messageEmitter = this._webviewComm.get(editorId)?.onDidReceiveMessage;
|
||||
|
||||
if (messageEmitter) {
|
||||
messageEmitter.fire(message);
|
||||
}
|
||||
$onDidReceiveMessage(editorId: string, forRendererType: string | undefined, message: any): void {
|
||||
this._webviewComm.get(editorId)?.onDidReceiveMessage(forRendererType, message);
|
||||
}
|
||||
|
||||
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void {
|
||||
@@ -1226,12 +1262,11 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
|
||||
private _createExtHostEditor(document: ExtHostNotebookDocument, editorId: string, selections: number[]) {
|
||||
const revivedUri = document.uri;
|
||||
let webComm = this._webviewComm.get(editorId)?.comm;
|
||||
let webComm = this._webviewComm.get(editorId);
|
||||
|
||||
if (!webComm) {
|
||||
const onDidReceiveMessage = new Emitter<any>();
|
||||
webComm = new ExtHostWebviewComm(editorId, revivedUri, this._proxy, onDidReceiveMessage, this._webviewInitData, document);
|
||||
this._webviewComm.set(editorId, { comm: webComm!, onDidReceiveMessage });
|
||||
webComm = new ExtHostWebviewCommWrapper(editorId, revivedUri, this._proxy, this._webviewInitData, document);
|
||||
this._webviewComm.set(editorId, webComm);
|
||||
}
|
||||
|
||||
let editor = new ExtHostNotebookEditor(
|
||||
@@ -1239,7 +1274,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
editorId,
|
||||
revivedUri,
|
||||
this._proxy,
|
||||
webComm,
|
||||
webComm.contentProviderComm,
|
||||
document,
|
||||
this._documentsAndEditors
|
||||
);
|
||||
@@ -1255,6 +1290,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
|
||||
this._editors.get(editorId)?.editor.dispose();
|
||||
|
||||
for (const renderer of this._renderersUsedInNotebooks.get(document) ?? []) {
|
||||
renderer.resolveNotebook(document, webComm);
|
||||
}
|
||||
|
||||
this._editors.set(editorId, { editor });
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { score } from 'vs/editor/common/modes/languageSelector';
|
||||
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
|
||||
export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextDocument {
|
||||
|
||||
@@ -20,6 +20,7 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
private _isClosed = false;
|
||||
|
||||
private _cells!: ExtHostCell[];
|
||||
private _cellUris!: ResourceMap<number>;
|
||||
private _cellLengths!: PrefixSumComputer;
|
||||
private _cellLines!: PrefixSumComputer;
|
||||
private _versionId = 0;
|
||||
@@ -36,8 +37,8 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
this._init();
|
||||
|
||||
this._disposables.add(extHostDocuments.onDidChangeDocument(e => {
|
||||
let cellIdx = this._cells.findIndex(cell => isEqual(cell.uri, e.document.uri));
|
||||
if (cellIdx >= 0) {
|
||||
let cellIdx = this._cellUris.get(e.document.uri);
|
||||
if (cellIdx !== undefined) {
|
||||
this._cellLengths.changeValue(cellIdx, this._cells[cellIdx].document.getText().length + 1);
|
||||
this._cellLines.changeValue(cellIdx, this._cells[cellIdx].document.lineCount);
|
||||
this._versionId += 1;
|
||||
@@ -53,7 +54,6 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
};
|
||||
|
||||
this._disposables.add(extHostNotebooks.onDidChangeCellLanguage(e => documentChange(e.document)));
|
||||
this._disposables.add(extHostNotebooks.onDidChangeCellOutputs(e => documentChange(e.document)));
|
||||
this._disposables.add(extHostNotebooks.onDidChangeNotebookCells(e => documentChange(e.document)));
|
||||
}
|
||||
|
||||
@@ -68,10 +68,12 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
|
||||
private _init() {
|
||||
this._cells = [];
|
||||
this._cellUris = new ResourceMap();
|
||||
const cellLengths: number[] = [];
|
||||
const cellLineCounts: number[] = [];
|
||||
for (let cell of this._notebook.cells) {
|
||||
if (cell.cellKind === CellKind.Code && (!this._selector || score(this._selector, cell.uri, cell.language, true))) {
|
||||
this._cellUris.set(cell.uri, this._cells.length);
|
||||
this._cells.push(<ExtHostCell>cell);
|
||||
cellLengths.push(cell.document.getText().length + 1);
|
||||
cellLineCounts.push(cell.document.lineCount);
|
||||
@@ -103,8 +105,8 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
// get start and end locations and create substrings
|
||||
const start = this.locationAt(range.start);
|
||||
const end = this.locationAt(range.end);
|
||||
const startCell = this._cells.find(cell => isEqual(cell.uri, start.uri));
|
||||
const endCell = this._cells.find(cell => isEqual(cell.uri, end.uri));
|
||||
const startCell = this._cells[this._cellUris.get(start.uri) ?? -1];
|
||||
const endCell = this._cells[this._cellUris.get(end.uri) ?? -1];
|
||||
|
||||
if (!startCell || !endCell) {
|
||||
return '';
|
||||
@@ -131,8 +133,8 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
return this._cells[idx.index].document.positionAt(idx.remainder).translate(lineCount);
|
||||
}
|
||||
|
||||
const idx = this._cells.findIndex(cell => isEqual(cell.uri, locationOrOffset.uri));
|
||||
if (idx >= 0) {
|
||||
const idx = this._cellUris.get(locationOrOffset.uri);
|
||||
if (idx !== undefined) {
|
||||
let line = this._cellLines.getAccumulatedValue(idx - 1);
|
||||
return new types.Position(line + locationOrOffset.range.start.line, locationOrOffset.range.start.character);
|
||||
}
|
||||
@@ -159,4 +161,24 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
const startCell = this._cells[startIdx.index];
|
||||
return new types.Location(startCell.uri, <types.Range>startCell.document.validateRange(range));
|
||||
}
|
||||
|
||||
contains(uri: vscode.Uri): boolean {
|
||||
return this._cellUris.has(uri);
|
||||
}
|
||||
|
||||
validateRange(range: vscode.Range): vscode.Range {
|
||||
const start = this.validatePosition(range.start);
|
||||
const end = this.validatePosition(range.end);
|
||||
return range.with(start, end);
|
||||
}
|
||||
|
||||
validatePosition(position: vscode.Position): vscode.Position {
|
||||
const startIdx = this._cellLines.getIndexOf(position.line);
|
||||
|
||||
const cellPosition = new types.Position(startIdx.remainder, position.character);
|
||||
const validCellPosition = this._cells[startIdx.index].document.validatePosition(cellPosition);
|
||||
|
||||
const line = this._cellLines.getAccumulatedValue(startIdx.index - 1);
|
||||
return new types.Position(line + validCellPosition.line, validCellPosition.character);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,7 +536,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
private readonly _onDidChangeActiveProvider = new Emitter<vscode.SourceControl>();
|
||||
get onDidChangeActiveProvider(): Event<vscode.SourceControl> { return this._onDidChangeActiveProvider.event; }
|
||||
|
||||
private _selectedSourceControlHandles = new Set<number>();
|
||||
private _selectedSourceControlHandle: number | undefined;
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
@@ -681,40 +681,18 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
});
|
||||
}
|
||||
|
||||
$setSelectedSourceControls(selectedSourceControlHandles: number[]): Promise<void> {
|
||||
this.logService.trace('ExtHostSCM#$setSelectedSourceControls', selectedSourceControlHandles);
|
||||
$setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise<void> {
|
||||
this.logService.trace('ExtHostSCM#$setSelectedSourceControl', selectedSourceControlHandle);
|
||||
|
||||
const set = new Set<number>();
|
||||
|
||||
for (const handle of selectedSourceControlHandles) {
|
||||
set.add(handle);
|
||||
if (selectedSourceControlHandle !== undefined) {
|
||||
this._sourceControls.get(selectedSourceControlHandle)?.setSelectionState(true);
|
||||
}
|
||||
|
||||
set.forEach(handle => {
|
||||
if (!this._selectedSourceControlHandles.has(handle)) {
|
||||
const sourceControl = this._sourceControls.get(handle);
|
||||
if (this._selectedSourceControlHandle !== undefined) {
|
||||
this._sourceControls.get(this._selectedSourceControlHandle)?.setSelectionState(false);
|
||||
}
|
||||
|
||||
if (!sourceControl) {
|
||||
return;
|
||||
}
|
||||
|
||||
sourceControl.setSelectionState(true);
|
||||
}
|
||||
});
|
||||
|
||||
this._selectedSourceControlHandles.forEach(handle => {
|
||||
if (!set.has(handle)) {
|
||||
const sourceControl = this._sourceControls.get(handle);
|
||||
|
||||
if (!sourceControl) {
|
||||
return;
|
||||
}
|
||||
|
||||
sourceControl.setSelectionState(false);
|
||||
}
|
||||
});
|
||||
|
||||
this._selectedSourceControlHandles = set;
|
||||
this._selectedSourceControlHandle = selectedSourceControlHandle;
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import type * as vscode from 'vscode';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IShellLaunchConfigDto, IShellDefinitionDto, IShellAndArgsDto, ITerminalDimensionsDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IShellLaunchConfigDto, IShellDefinitionDto, IShellAndArgsDto, ITerminalDimensionsDto, ITerminalLinkDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
@@ -39,6 +39,7 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape {
|
||||
getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string;
|
||||
getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string;
|
||||
registerLinkHandler(handler: vscode.TerminalLinkHandler): vscode.Disposable;
|
||||
registerLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable;
|
||||
getEnvironmentVariableCollection(extension: IExtensionDescription, persistent?: boolean): vscode.EnvironmentVariableCollection;
|
||||
}
|
||||
|
||||
@@ -293,6 +294,13 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
|
||||
}
|
||||
}
|
||||
|
||||
let nextLinkId = 1;
|
||||
|
||||
interface ICachedLinkEntry {
|
||||
provider: vscode.TerminalLinkProvider;
|
||||
link: vscode.TerminalLink;
|
||||
}
|
||||
|
||||
export abstract class BaseExtHostTerminalService implements IExtHostTerminalService, ExtHostTerminalServiceShape {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
@@ -307,6 +315,8 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
||||
|
||||
private readonly _bufferer: TerminalDataBufferer;
|
||||
private readonly _linkHandlers: Set<vscode.TerminalLinkHandler> = new Set();
|
||||
private readonly _linkProviders: Set<vscode.TerminalLinkProvider> = new Set();
|
||||
private readonly _terminalLinkCache: Map<number, Map<number, ICachedLinkEntry>> = new Map();
|
||||
|
||||
public get activeTerminal(): ExtHostTerminal | undefined { return this._activeTerminal; }
|
||||
public get terminals(): ExtHostTerminal[] { return this._terminals; }
|
||||
@@ -547,17 +557,30 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
||||
|
||||
public registerLinkHandler(handler: vscode.TerminalLinkHandler): vscode.Disposable {
|
||||
this._linkHandlers.add(handler);
|
||||
if (this._linkHandlers.size === 1) {
|
||||
if (this._linkHandlers.size === 1 && this._linkProviders.size === 0) {
|
||||
this._proxy.$startHandlingLinks();
|
||||
}
|
||||
return new VSCodeDisposable(() => {
|
||||
this._linkHandlers.delete(handler);
|
||||
if (this._linkHandlers.size === 0) {
|
||||
if (this._linkHandlers.size === 0 && this._linkProviders.size === 0) {
|
||||
this._proxy.$stopHandlingLinks();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public registerLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable {
|
||||
this._linkProviders.add(provider);
|
||||
if (this._linkProviders.size === 1) {
|
||||
this._proxy.$startLinkProvider();
|
||||
}
|
||||
return new VSCodeDisposable(() => {
|
||||
this._linkProviders.delete(provider);
|
||||
if (this._linkProviders.size === 0) {
|
||||
this._proxy.$stopLinkProvider();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async $handleLink(id: number, link: string): Promise<boolean> {
|
||||
const terminal = this._getTerminalById(id);
|
||||
if (!terminal) {
|
||||
@@ -577,6 +600,60 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
||||
return false;
|
||||
}
|
||||
|
||||
public async $provideLinks(terminalId: number, line: string): Promise<ITerminalLinkDto[]> {
|
||||
const terminal = this._getTerminalById(terminalId);
|
||||
if (!terminal) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Discard any cached links the terminal has been holding, currently all links are released
|
||||
// when new links are provided.
|
||||
this._terminalLinkCache.delete(terminalId);
|
||||
|
||||
const result: ITerminalLinkDto[] = [];
|
||||
const context: vscode.TerminalLinkContext = { terminal, line };
|
||||
const promises: vscode.ProviderResult<{ provider: vscode.TerminalLinkProvider, links: vscode.TerminalLink[] }>[] = [];
|
||||
for (const provider of this._linkProviders) {
|
||||
promises.push(new Promise(async r => {
|
||||
const links = (await provider.provideTerminalLinks(context)) || [];
|
||||
r({ provider, links });
|
||||
}));
|
||||
}
|
||||
|
||||
const provideResults = await Promise.all(promises);
|
||||
const cacheLinkMap = new Map<number, ICachedLinkEntry>();
|
||||
for (const provideResult of provideResults) {
|
||||
if (provideResult && provideResult.links.length > 0) {
|
||||
result.push(...provideResult.links.map(providerLink => {
|
||||
const endIndex = Math.max(providerLink.endIndex, providerLink.startIndex + 1);
|
||||
const link = {
|
||||
id: nextLinkId++,
|
||||
startIndex: providerLink.startIndex,
|
||||
length: endIndex - providerLink.startIndex,
|
||||
label: providerLink.tooltip
|
||||
};
|
||||
cacheLinkMap.set(link.id, {
|
||||
provider: provideResult.provider,
|
||||
link: providerLink
|
||||
});
|
||||
return link;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
this._terminalLinkCache.set(terminalId, cacheLinkMap);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
$activateLink(terminalId: number, linkId: number): void {
|
||||
const cachedLink = this._terminalLinkCache.get(terminalId)?.get(linkId);
|
||||
if (!cachedLink) {
|
||||
return;
|
||||
}
|
||||
cachedLink.provider.handleTerminalLink(cachedLink.link);
|
||||
}
|
||||
|
||||
private _onProcessExit(id: number, exitCode: number | undefined): void {
|
||||
this._bufferer.stopBuffering(id);
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ import { equals, coalesce } from 'vs/base/common/arrays';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { MarkdownString } from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import * as azdata from 'azdata';
|
||||
@@ -119,6 +121,22 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
return treeView.getChildren(treeItemHandle);
|
||||
}
|
||||
|
||||
async $hasResolve(treeViewId: string): Promise<boolean> {
|
||||
const treeView = this.treeViews.get(treeViewId);
|
||||
if (!treeView) {
|
||||
throw new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId));
|
||||
}
|
||||
return treeView.hasResolve;
|
||||
}
|
||||
|
||||
$resolve(treeViewId: string, treeItemHandle: string): Promise<ITreeItem | undefined> {
|
||||
const treeView = this.treeViews.get(treeViewId);
|
||||
if (!treeView) {
|
||||
throw new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId));
|
||||
}
|
||||
return treeView.resolveTreeItem(treeItemHandle);
|
||||
}
|
||||
|
||||
$setExpanded(treeViewId: string, treeItemHandle: string, expanded: boolean): void {
|
||||
const treeView = this.treeViews.get(treeViewId);
|
||||
if (!treeView) {
|
||||
@@ -160,6 +178,7 @@ type TreeData<T> = { message: boolean, element: T | Root | false };
|
||||
|
||||
export interface TreeNode extends IDisposable { // {{SQL CARBON EDIT}} export interface
|
||||
item: ITreeItem;
|
||||
extensionItem: vscode.TreeItem2;
|
||||
parent: TreeNode | Root;
|
||||
children?: TreeNode[];
|
||||
}
|
||||
@@ -334,8 +353,28 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
protected resolveUnknownParentChain(element: T): Promise<TreeNode[]> {
|
||||
get hasResolve(): boolean {
|
||||
return !!this.dataProvider.resolveTreeItem;
|
||||
}
|
||||
|
||||
async resolveTreeItem(treeItemHandle: string): Promise<ITreeItem | undefined> {
|
||||
if (!this.dataProvider.resolveTreeItem) {
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-null-checks
|
||||
}
|
||||
const element = this.elements.get(treeItemHandle);
|
||||
if (element) {
|
||||
const node = this.nodes.get(element);
|
||||
if (node) {
|
||||
const resolve = await this.dataProvider.resolveTreeItem(element, node.extensionItem);
|
||||
// Resolvable elements. Currently only tooltip.
|
||||
node.item.tooltip = resolve.tooltip;
|
||||
return node.item;
|
||||
}
|
||||
}
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-null-checks
|
||||
}
|
||||
|
||||
protected resolveUnknownParentChain(element: T): Promise<TreeNode[]> { // {{SQL CARBON EDIT}}
|
||||
return this.resolveParent(element)
|
||||
.then((parent) => {
|
||||
if (!parent) {
|
||||
@@ -498,7 +537,18 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
return node;
|
||||
}
|
||||
|
||||
protected createTreeNode(element: T, extensionTreeItem: azdata.TreeItem2, parent: TreeNode | Root): TreeNode { // {{SQL CARBON EDIT}} change to protected, change to azdata.TreeItem
|
||||
private getTooltip(tooltip?: string | vscode.MarkdownString): string | IMarkdownString | undefined {
|
||||
if (typeof tooltip === 'string') {
|
||||
return tooltip;
|
||||
} else if (tooltip === undefined) {
|
||||
return undefined;
|
||||
} else {
|
||||
checkProposedApiEnabled(this.extension);
|
||||
return MarkdownString.from(tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
protected createTreeNode(element: T, extensionTreeItem: azdata.TreeItem2, parent: TreeNode | Root): TreeNode { // {{SQL CARBON EDIT}} change to protected, change to azdata.TreeItem
|
||||
const disposable = new DisposableStore();
|
||||
const handle = this.createHandle(element, extensionTreeItem, parent);
|
||||
const icon = this.getLightIconPath(extensionTreeItem);
|
||||
@@ -508,7 +558,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
label: toTreeItemLabel(extensionTreeItem.label, this.extension),
|
||||
description: extensionTreeItem.description,
|
||||
resourceUri: extensionTreeItem.resourceUri,
|
||||
tooltip: typeof extensionTreeItem.tooltip === 'string' ? extensionTreeItem.tooltip : undefined,
|
||||
tooltip: this.getTooltip(extensionTreeItem.tooltip),
|
||||
command: extensionTreeItem.command ? this.commands.toInternal(extensionTreeItem.command, disposable) : undefined,
|
||||
contextValue: extensionTreeItem.contextValue,
|
||||
icon,
|
||||
@@ -523,6 +573,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
|
||||
return {
|
||||
item,
|
||||
extensionItem: extensionTreeItem,
|
||||
parent,
|
||||
children: undefined,
|
||||
dispose(): void { disposable.dispose(); }
|
||||
|
||||
@@ -646,7 +646,7 @@ export namespace DocumentSymbol {
|
||||
range: Range.from(info.range),
|
||||
selectionRange: Range.from(info.selectionRange),
|
||||
kind: SymbolKind.from(info.kind),
|
||||
tags: info.tags ? info.tags.map(SymbolTag.from) : []
|
||||
tags: info.tags?.map(SymbolTag.from) ?? []
|
||||
};
|
||||
if (info.children) {
|
||||
result.children = info.children.map(from);
|
||||
@@ -911,7 +911,7 @@ export namespace CompletionItem {
|
||||
|
||||
result.insertText = suggestion.insertText;
|
||||
result.kind = CompletionItemKind.to(suggestion.kind);
|
||||
result.tags = suggestion.tags && suggestion.tags.map(CompletionItemTag.to);
|
||||
result.tags = suggestion.tags?.map(CompletionItemTag.to);
|
||||
result.detail = suggestion.detail;
|
||||
result.documentation = htmlContent.isMarkdownString(suggestion.documentation) ? MarkdownString.to(suggestion.documentation) : suggestion.documentation;
|
||||
result.sortText = suggestion.sortText;
|
||||
|
||||
@@ -1252,7 +1252,7 @@ export class MarkdownString {
|
||||
// escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
|
||||
this.value += (this.supportThemeIcons ? escapeCodicons(value) : value)
|
||||
.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&')
|
||||
.replace('\n', '\n\n');
|
||||
.replace(/\n/, '\n\n');
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -2101,7 +2101,7 @@ export class TreeItem {
|
||||
iconPath?: string | URI | { light: string | URI; dark: string | URI; };
|
||||
command?: vscode.Command;
|
||||
contextValue?: string;
|
||||
tooltip?: string;
|
||||
tooltip?: string | vscode.MarkdownString;
|
||||
|
||||
constructor(label: string | vscode.TreeItemLabel, collapsibleState?: vscode.TreeItemCollapsibleState);
|
||||
constructor(resourceUri: URI, collapsibleState?: vscode.TreeItemCollapsibleState);
|
||||
@@ -2769,7 +2769,7 @@ export enum ExtensionMode {
|
||||
|
||||
|
||||
//#region Authentication
|
||||
export class AuthenticationSession implements vscode.AuthenticationSession2 {
|
||||
export class AuthenticationSession implements vscode.AuthenticationSession {
|
||||
constructor(public id: string, public accessToken: string, public account: { displayName: string, id: string }, public scopes: string[]) { }
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostWindowShape, MainContext, MainThreadWindowShape, IMainContext, IOpenUriOptions } from './extHost.protocol';
|
||||
import { ExtHostWindowShape, MainContext, MainThreadWindowShape, IOpenUriOptions } from './extHost.protocol';
|
||||
import { WindowState } from 'vscode';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
export class ExtHostWindow implements ExtHostWindowShape {
|
||||
export class ExtHostWindow implements IExtHostWindow {
|
||||
|
||||
private static InitialState: WindowState = {
|
||||
focused: true
|
||||
@@ -24,8 +26,8 @@ export class ExtHostWindow implements ExtHostWindowShape {
|
||||
private _state = ExtHostWindow.InitialState;
|
||||
get state(): WindowState { return this._state; }
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadWindow);
|
||||
constructor(@IExtHostRpcService extHostRpc: IExtHostRpcService) {
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadWindow);
|
||||
this._proxy.$getWindowVisibility().then(isFocused => this.$onDidChangeWindowFocus(isFocused));
|
||||
}
|
||||
|
||||
@@ -67,3 +69,6 @@ export class ExtHostWindow implements ExtHostWindowShape {
|
||||
return URI.from(result);
|
||||
}
|
||||
}
|
||||
|
||||
export const IExtHostWindow = createDecorator<IExtHostWindow>('IExtHostWindow');
|
||||
export interface IExtHostWindow extends ExtHostWindow, ExtHostWindowShape { }
|
||||
|
||||
Reference in New Issue
Block a user