mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-06 17:23:53 -05:00
VS Code merge to df8fe74bd55313de0dd2303bc47a4aab0ca56b0e (#17979)
* Merge from vscode 504f934659740e9d41501cad9f162b54d7745ad9 * delete unused folders * distro * Bump build node version * update chokidar * FIx hygiene errors * distro * Fix extension lint issues * Remove strict-vscode * Add copyright header exemptions * Bump vscode-extension-telemetry to fix webpacking issue with zone.js * distro * Fix failing tests (revert marked.js back to current one until we decide to update) * Skip searchmodel test * Fix mac build * temp debug script loading * Try disabling coverage * log error too * Revert "log error too" This reverts commit af0183e5d4ab458fdf44b88fbfab9908d090526f. * Revert "temp debug script loading" This reverts commit 3d687d541c76db2c5b55626c78ae448d3c25089c. * Add comments explaining coverage disabling * Fix ansi_up loading issue * Merge latest from ads * Use newer option * Fix compile * add debug logging warn * Always log stack * log more * undo debug * Update to use correct base path (+cleanup) * distro * fix compile errors * Remove strict-vscode * Fix sql editors not showing * Show db dropdown input & fix styling * Fix more info in gallery * Fix gallery asset requests * Delete unused workflow * Fix tapable resolutions for smoke test compile error * Fix smoke compile * Disable crash reporting * Disable interactive Co-authored-by: ADS Merger <karlb@microsoft.com>
This commit is contained in:
@@ -1,20 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
|
||||
if (isWeb) {
|
||||
CommandsRegistry.registerCommand('_workbench.fetchJSON', async function (accessor: ServicesAccessor, url: string, method: string) {
|
||||
const result = await fetch(url, { method, headers: { Accept: 'application/json' } });
|
||||
|
||||
if (result.ok) {
|
||||
return result.json();
|
||||
} else {
|
||||
throw new Error(result.statusText);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -66,6 +66,7 @@ import './mainThreadNotebook';
|
||||
import './mainThreadNotebookKernels';
|
||||
import './mainThreadNotebookDocumentsAndEditors';
|
||||
import './mainThreadNotebookRenderers';
|
||||
import './mainThreadInteractive';
|
||||
import './mainThreadTask';
|
||||
import './mainThreadLabelService';
|
||||
import './mainThreadTunnelService';
|
||||
@@ -73,8 +74,6 @@ import './mainThreadAuthentication';
|
||||
import './mainThreadTimeline';
|
||||
import './mainThreadTesting';
|
||||
import './mainThreadSecretState';
|
||||
import 'vs/workbench/api/common/apiCommands';
|
||||
import 'vs/workbench/api/browser/apiCommands';
|
||||
|
||||
export class ExtensionPoints implements IWorkbenchContribution {
|
||||
|
||||
|
||||
@@ -16,6 +16,13 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { fromNow } from 'vs/base/common/date';
|
||||
import { ActivationKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
interface TrustedExtensionsQuickPickItem {
|
||||
label: string;
|
||||
description: string;
|
||||
extension: AllowedExtension;
|
||||
}
|
||||
|
||||
export class MainThreadAuthenticationProvider extends Disposable {
|
||||
constructor(
|
||||
@@ -38,7 +45,7 @@ export class MainThreadAuthenticationProvider extends Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
const quickPick = this.quickInputService.createQuickPick<{ label: string, description: string, extension: AllowedExtension }>();
|
||||
const quickPick = this.quickInputService.createQuickPick<TrustedExtensionsQuickPickItem>();
|
||||
quickPick.canSelectMany = true;
|
||||
quickPick.customButton = true;
|
||||
quickPick.customLabel = nls.localize('manageTrustedExtensions.cancel', 'Cancel');
|
||||
@@ -60,12 +67,23 @@ export class MainThreadAuthenticationProvider extends Disposable {
|
||||
quickPick.placeholder = nls.localize('manageExensions', "Choose which extensions can access this account");
|
||||
|
||||
quickPick.onDidAccept(() => {
|
||||
const updatedAllowedList = quickPick.selectedItems.map(item => item.extension);
|
||||
const updatedAllowedList = quickPick.items
|
||||
.map(i => (i as TrustedExtensionsQuickPickItem).extension);
|
||||
this.storageService.store(`${this.id}-${accountName}`, JSON.stringify(updatedAllowedList), StorageScope.GLOBAL, StorageTarget.USER);
|
||||
|
||||
quickPick.dispose();
|
||||
});
|
||||
|
||||
quickPick.onDidChangeSelection((changed) => {
|
||||
quickPick.items.forEach(item => {
|
||||
if ((item as TrustedExtensionsQuickPickItem).extension) {
|
||||
(item as TrustedExtensionsQuickPickItem).extension.allowed = false;
|
||||
}
|
||||
});
|
||||
|
||||
changed.forEach((item) => item.extension.allowed = true);
|
||||
});
|
||||
|
||||
quickPick.onDidHide(() => {
|
||||
quickPick.dispose();
|
||||
});
|
||||
@@ -126,7 +144,8 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService
|
||||
) {
|
||||
super();
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostAuthentication);
|
||||
@@ -135,14 +154,6 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
|
||||
this._proxy.$onDidChangeAuthenticationSessions(e.providerId, e.label);
|
||||
}));
|
||||
|
||||
this._register(this.authenticationService.onDidRegisterAuthenticationProvider(info => {
|
||||
this._proxy.$onDidChangeAuthenticationProviders([info], []);
|
||||
}));
|
||||
|
||||
this._register(this.authenticationService.onDidUnregisterAuthenticationProvider(info => {
|
||||
this._proxy.$onDidChangeAuthenticationProviders([], [info]);
|
||||
}));
|
||||
|
||||
this._proxy.$setProviders(this.authenticationService.declaredProviders);
|
||||
|
||||
this._register(this.authenticationService.onDidChangeDeclaredProviders(e => {
|
||||
@@ -170,13 +181,17 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
|
||||
$removeSession(providerId: string, sessionId: string): Promise<void> {
|
||||
return this.authenticationService.removeSession(providerId, sessionId);
|
||||
}
|
||||
private async loginPrompt(providerName: string, extensionName: string): Promise<boolean> {
|
||||
private async loginPrompt(providerName: string, extensionName: string, recreatingSession: boolean, detail?: string): Promise<boolean> {
|
||||
const message = recreatingSession
|
||||
? nls.localize('confirmRelogin', "The extension '{0}' wants you to sign in again using {1}.", extensionName, providerName)
|
||||
: nls.localize('confirmLogin', "The extension '{0}' wants to sign in using {1}.", extensionName, providerName);
|
||||
const { choice } = await this.dialogService.show(
|
||||
Severity.Info,
|
||||
nls.localize('confirmLogin', "The extension '{0}' wants to sign in using {1}.", extensionName, providerName),
|
||||
message,
|
||||
[nls.localize('allow', "Allow"), nls.localize('cancel', "Cancel")],
|
||||
{
|
||||
cancelId: 1
|
||||
cancelId: 1,
|
||||
detail
|
||||
}
|
||||
);
|
||||
|
||||
@@ -227,12 +242,17 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
|
||||
return this.authenticationService.selectSession(providerId, extensionId, extensionName, scopes, potentialSessions);
|
||||
}
|
||||
|
||||
async $getSession(providerId: string, scopes: string[], extensionId: string, extensionName: string, options: { createIfNone: boolean, clearSessionPreference: boolean }): Promise<modes.AuthenticationSession | undefined> {
|
||||
async $getSession(providerId: string, scopes: string[], extensionId: string, extensionName: string, options: { createIfNone: boolean, forceNewSession: boolean | { detail: string }, clearSessionPreference: boolean }): Promise<modes.AuthenticationSession | undefined> {
|
||||
const sessions = await this.authenticationService.getSessions(providerId, scopes, true);
|
||||
let silent = !options.createIfNone;
|
||||
|
||||
if (options.forceNewSession && !sessions.length) {
|
||||
throw new Error('No existing sessions found.');
|
||||
}
|
||||
|
||||
const silent = !options.createIfNone;
|
||||
let session: modes.AuthenticationSession | undefined;
|
||||
if (sessions.length) {
|
||||
// Ignore existing sessions if we are forceRecreating
|
||||
if (!options.forceNewSession && sessions.length) {
|
||||
if (!this.authenticationService.supportsMultipleAccounts(providerId)) {
|
||||
session = sessions[0];
|
||||
const allowed = this.authenticationService.isAccessAllowed(providerId, session.account.label, extensionId);
|
||||
@@ -253,9 +273,11 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
|
||||
return this.selectSession(providerId, extensionId, extensionName, scopes, sessions, !!options.clearSessionPreference, silent);
|
||||
}
|
||||
} else {
|
||||
if (!silent) {
|
||||
const providerName = await this.authenticationService.getLabel(providerId);
|
||||
const isAllowed = await this.loginPrompt(providerName, extensionName);
|
||||
// If we are forceRecreating, we need to show the prompt.
|
||||
if (options.forceNewSession || !silent) {
|
||||
const providerName = this.authenticationService.getLabel(providerId);
|
||||
const detail = (typeof options.forceNewSession === 'object') ? options.forceNewSession!.detail : undefined;
|
||||
const isAllowed = await this.loginPrompt(providerName, extensionName, !!options.forceNewSession, detail);
|
||||
if (!isAllowed) {
|
||||
throw new Error('User did not consent to login.');
|
||||
}
|
||||
@@ -268,6 +290,12 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
|
||||
}
|
||||
|
||||
if (session) {
|
||||
type AuthProviderUsageClassification = {
|
||||
extensionId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
providerId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
};
|
||||
this.telemetryService.publicLog2<{ extensionId: string, providerId: string }, AuthProviderUsageClassification>('authentication.providerUsage', { providerId, extensionId });
|
||||
|
||||
addAccountUsage(this.storageService, providerId, session.account.label, extensionId, extensionName);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
import { CLIOutput, IExtensionGalleryService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionManagementCLIService } from 'vs/platform/extensionManagement/common/extensionManagementCLIService';
|
||||
import { getExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
@@ -21,7 +22,6 @@ import { IOpenWindowOptions, IWindowOpenable } from 'vs/platform/windows/common/
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService';
|
||||
import { IExtensionManifest } from 'vs/workbench/workbench.web.api';
|
||||
|
||||
|
||||
// this class contains the commands that the CLI server is reying on
|
||||
|
||||
@@ -23,6 +23,7 @@ import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneCont
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
|
||||
import { localize } from 'vs/nls';
|
||||
import { MarshalledId } from 'vs/base/common/marshalling';
|
||||
|
||||
|
||||
export class MainThreadCommentThread implements modes.CommentThread {
|
||||
@@ -154,7 +155,7 @@ export class MainThreadCommentThread implements modes.CommentThread {
|
||||
|
||||
toJSON(): any {
|
||||
return {
|
||||
$mid: 7,
|
||||
$mid: MarshalledId.CommentThread,
|
||||
commentControlHandle: this.controllerHandle,
|
||||
commentThreadHandle: this.commentThreadHandle,
|
||||
};
|
||||
@@ -347,7 +348,7 @@ export class MainThreadCommentController {
|
||||
|
||||
toJSON(): any {
|
||||
return {
|
||||
$mid: 6,
|
||||
$mid: MarshalledId.CommentController,
|
||||
handle: this.handle
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ import { IUndoRedoService, UndoRedoElementType } from 'vs/platform/undoRedo/comm
|
||||
import { MainThreadWebviewPanels } from 'vs/workbench/api/browser/mainThreadWebviewPanels';
|
||||
import { MainThreadWebviews, reviveWebviewExtension } from 'vs/workbench/api/browser/mainThreadWebviews';
|
||||
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { editorGroupToViewColumn, IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor';
|
||||
import { IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor';
|
||||
import { editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';
|
||||
import { CustomDocumentBackupData } from 'vs/workbench/contrib/customEditor/browser/customEditorInputFactory';
|
||||
import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
|
||||
@@ -195,7 +196,7 @@ export class MainThreadCustomEditors extends Disposable implements extHostProtoc
|
||||
title: webviewInput.getTitle(),
|
||||
webviewOptions: webviewInput.webview.contentOptions,
|
||||
panelOptions: webviewInput.webview.options,
|
||||
}, editorGroupToViewColumn(this._editorGroupService, webviewInput.group || 0), cancellation);
|
||||
}, editorGroupToColumn(this._editorGroupService, webviewInput.group || 0), cancellation);
|
||||
} catch (error) {
|
||||
onUnexpectedError(error);
|
||||
webviewInput.webview.html = this.mainThreadWebview.getWebviewResolvedFailedContent(viewType);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { URI as uri, UriComponents } from 'vs/base/common/uri';
|
||||
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory, IDataBreakpoint, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory, IDataBreakpoint, IDebugSessionOptions, IInstructionBreakpoint } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import {
|
||||
ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext,
|
||||
IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto, IDataBreakpointDto, IStartDebuggingOptions, IDebugConfiguration
|
||||
@@ -226,8 +226,10 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
const debugOptions: IDebugSessionOptions = {
|
||||
noDebug: options.noDebug,
|
||||
parentSession,
|
||||
lifecycleManagedByParent: options.lifecycleManagedByParent,
|
||||
repl: options.repl,
|
||||
compact: options.compact,
|
||||
debugUI: options.debugUI,
|
||||
compoundRoot: parentSession?.compoundRoot
|
||||
};
|
||||
return this.debugService.startDebugging(launch, nameOrConfig, debugOptions).then(success => {
|
||||
@@ -337,7 +339,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private convertToDto(bps: (ReadonlyArray<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint>)): Array<ISourceBreakpointDto | IFunctionBreakpointDto | IDataBreakpointDto> {
|
||||
private convertToDto(bps: (ReadonlyArray<IBreakpoint | IFunctionBreakpoint | IDataBreakpoint | IInstructionBreakpoint>)): Array<ISourceBreakpointDto | IFunctionBreakpointDto | IDataBreakpointDto> {
|
||||
return bps.map(bp => {
|
||||
if ('name' in bp) {
|
||||
const fbp = <IFunctionBreakpoint>bp;
|
||||
|
||||
@@ -20,7 +20,8 @@ import { MainThreadTextEditor } from 'vs/workbench/api/browser/mainThreadEditor'
|
||||
import { MainThreadTextEditors } from 'vs/workbench/api/browser/mainThreadEditors';
|
||||
import { ExtHostContext, ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta, IExtHostContext, IModelAddedData, ITextEditorAddData, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor';
|
||||
import { editorGroupToViewColumn, EditorGroupColumn, IEditorPane } from 'vs/workbench/common/editor';
|
||||
import { IEditorPane } from 'vs/workbench/common/editor';
|
||||
import { EditorGroupColumn, editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
@@ -414,7 +415,7 @@ export class MainThreadDocumentsAndEditors {
|
||||
private _findEditorPosition(editor: MainThreadTextEditor): EditorGroupColumn | undefined {
|
||||
for (const editorPane of this._editorService.visibleEditorPanes) {
|
||||
if (editor.matches(editorPane)) {
|
||||
return editorGroupToViewColumn(this._editorGroupService, editorPane.group);
|
||||
return editorGroupToColumn(this._editorGroupService, editorPane.group);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
|
||||
@@ -14,12 +14,12 @@ import { ISelection } from 'vs/editor/common/core/selection';
|
||||
import { IDecorationOptions, IDecorationRenderOptions, ILineChange } from 'vs/editor/common/editorCommon';
|
||||
import { ISingleEditOperation } from 'vs/editor/common/model';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { ITextEditorOptions, IResourceEditorInput, EditorActivation, EditorOverride } from 'vs/platform/editor/common/editor';
|
||||
import { ITextEditorOptions, IResourceEditorInput, EditorActivation, EditorResolution } from 'vs/platform/editor/common/editor';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { MainThreadDocumentsAndEditors } from 'vs/workbench/api/browser/mainThreadDocumentsAndEditors';
|
||||
import { MainThreadTextEditor } from 'vs/workbench/api/browser/mainThreadEditor';
|
||||
import { ExtHostContext, ExtHostEditorsShape, IApplyEditsOptions, IExtHostContext, ITextDocumentShowOptions, ITextEditorConfigurationUpdate, ITextEditorPositionData, IUndoStopOptions, MainThreadTextEditorsShape, TextEditorRevealType, IWorkspaceEditDto, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { editorGroupToViewColumn, EditorGroupColumn, viewColumnToEditorGroup } from 'vs/workbench/common/editor';
|
||||
import { editorGroupToColumn, columnToEditorGroup, EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
@@ -27,6 +27,7 @@ import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/wo
|
||||
import { revive } from 'vs/base/common/marshalling';
|
||||
import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { NotebookDto } from 'vs/workbench/api/browser/mainThreadNotebookDto';
|
||||
import { INotebookService } from 'sql/workbench/services/notebook/browser/notebookService'; // {{SQL CARBON EDIT}}
|
||||
|
||||
export function reviveWorkspaceEditDto2(data: IWorkspaceEditDto | undefined): ResourceEdit[] {
|
||||
@@ -41,7 +42,7 @@ export function reviveWorkspaceEditDto2(data: IWorkspaceEditDto | undefined): Re
|
||||
} else if (edit._type === WorkspaceEditType.Text) {
|
||||
result.push(new ResourceTextEdit(edit.resource, edit.edit, edit.modelVersionId, edit.metadata));
|
||||
} else if (edit._type === WorkspaceEditType.Cell) {
|
||||
result.push(new ResourceNotebookCellEdit(edit.resource, edit.edit, edit.notebookVersionId, edit.metadata));
|
||||
result.push(new ResourceNotebookCellEdit(edit.resource, NotebookDto.fromCellEditOperationDto(edit.edit), edit.notebookVersionId, edit.metadata));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -127,7 +128,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
|
||||
for (let editorPane of this._editorService.visibleEditorPanes) {
|
||||
const id = this._documentsAndEditors.findTextEditorIdFor(editorPane);
|
||||
if (id) {
|
||||
result[id] = editorGroupToViewColumn(this._editorGroupService, editorPane.group);
|
||||
result[id] = editorGroupToColumn(this._editorGroupService, editorPane.group);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -147,7 +148,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
|
||||
// preserve pre 1.38 behaviour to not make group active when preserveFocus: true
|
||||
// but make sure to restore the editor to fix https://github.com/microsoft/vscode/issues/79633
|
||||
activation: options.preserveFocus ? EditorActivation.RESTORE : undefined,
|
||||
override: notebookFileTypes?.some(ext => uri?.fsPath?.toLowerCase().endsWith(ext)) || uri?.fsPath?.toLowerCase().endsWith('.sql') ? undefined : EditorOverride.DISABLED // {{SQL CARBON EDIT}}
|
||||
override: notebookFileTypes?.some(ext => uri?.fsPath?.toLowerCase().endsWith(ext)) || uri?.fsPath?.toLowerCase().endsWith('.sql') ? undefined : EditorResolution.DISABLED // {{SQL CARBON EDIT}}
|
||||
};
|
||||
|
||||
const input: IResourceEditorInput = {
|
||||
@@ -155,7 +156,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
|
||||
options: editorOptions
|
||||
};
|
||||
|
||||
const editor = await this._editorService.openEditor(input, viewColumnToEditorGroup(this._editorGroupService, options.position));
|
||||
const editor = await this._editorService.openEditor(input, columnToEditorGroup(this._editorGroupService, options.position));
|
||||
if (!editor) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -169,7 +170,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
|
||||
await this._editorService.openEditor({
|
||||
resource: model.uri,
|
||||
options: { preserveFocus: false }
|
||||
}, viewColumnToEditorGroup(this._editorGroupService, position));
|
||||
}, columnToEditorGroup(this._editorGroupService, position));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ export class MainThreadFileSystemEventService {
|
||||
changed: [],
|
||||
deleted: []
|
||||
};
|
||||
this._listener.add(fileService.onDidFilesChange(event => {
|
||||
this._listener.add(fileService.onDidChangeFilesRaw(event => {
|
||||
for (let change of event.changes) {
|
||||
switch (change.type) {
|
||||
case FileChangeType.ADDED:
|
||||
|
||||
36
src/vs/workbench/api/browser/mainThreadInteractive.ts
Normal file
36
src/vs/workbench/api/browser/mainThreadInteractive.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostContext, ExtHostInteractiveShape, IExtHostContext, MainThreadInteractiveShape } from 'vs/workbench/api/common/extHost.protocol'; // {{SQL CARBON EDIT}} Disable unused
|
||||
// import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; {{SQL CARBON EDIT}} Disable unused
|
||||
import { IInteractiveDocumentService } from 'vs/workbench/contrib/interactive/browser/interactiveDocumentService';
|
||||
|
||||
// @extHostNamedCustomer(MainContext.MainThreadInteractive)
|
||||
export class MainThreadInteractive implements MainThreadInteractiveShape {
|
||||
private readonly _proxy: ExtHostInteractiveShape;
|
||||
|
||||
private readonly _disposables = new DisposableStore();
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@IInteractiveDocumentService interactiveDocumentService: IInteractiveDocumentService
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostInteractive);
|
||||
|
||||
this._disposables.add(interactiveDocumentService.onWillAddInteractiveDocument((e) => {
|
||||
this._proxy.$willAddInteractiveDocument(e.inputUri, '\n', 'plaintext', e.notebookUri);
|
||||
}));
|
||||
|
||||
this._disposables.add(interactiveDocumentService.onWillRemoveInteractiveDocument((e) => {
|
||||
this._proxy.$willRemoveInteractiveDocument(e.inputUri, e.notebookUri);
|
||||
}));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._disposables.dispose();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import * as search from 'vs/workbench/contrib/search/common/search';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Position as EditorPosition } from 'vs/editor/common/core/position';
|
||||
import { Range as EditorRange, IRange } from 'vs/editor/common/core/range';
|
||||
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField, ISuggestResultDtoField, ICodeActionProviderMetadataDto, ILanguageWordDefinitionDto, IdentifiableInlineCompletions, IdentifiableInlineCompletion } from '../common/extHost.protocol';
|
||||
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField, ISuggestResultDtoField, ICodeActionProviderMetadataDto, ILanguageWordDefinitionDto, IdentifiableInlineCompletions, IdentifiableInlineCompletion, ITypeHierarchyItemDto } from '../common/extHost.protocol';
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
@@ -20,6 +20,7 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import * as typeh from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { decodeSemanticTokensDto } from 'vs/editor/common/services/semanticTokensDto';
|
||||
|
||||
@@ -148,6 +149,13 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
return data as callh.CallHierarchyItem;
|
||||
}
|
||||
|
||||
private static _reviveTypeHierarchyItemDto(data: ITypeHierarchyItemDto | undefined): typeh.TypeHierarchyItem {
|
||||
if (data) {
|
||||
data.uri = URI.revive(data.uri);
|
||||
}
|
||||
return data as typeh.TypeHierarchyItem;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
// --- outline
|
||||
@@ -444,8 +452,10 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
private static _inflateSuggestDto(defaultRange: IRange | { insert: IRange, replace: IRange }, data: ISuggestDataDto): modes.CompletionItem {
|
||||
|
||||
const label = data[ISuggestDataDtoField.label];
|
||||
|
||||
return {
|
||||
label: data[ISuggestDataDtoField.label2] ?? data[ISuggestDataDtoField.label],
|
||||
label,
|
||||
kind: data[ISuggestDataDtoField.kind] ?? modes.CompletionItemKind.Property,
|
||||
tags: data[ISuggestDataDtoField.kindModifier],
|
||||
detail: data[ISuggestDataDtoField.detail],
|
||||
@@ -453,7 +463,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
sortText: data[ISuggestDataDtoField.sortText],
|
||||
filterText: data[ISuggestDataDtoField.filterText],
|
||||
preselect: data[ISuggestDataDtoField.preselect],
|
||||
insertText: typeof data.h === 'undefined' ? data[ISuggestDataDtoField.label] : data.h,
|
||||
insertText: data[ISuggestDataDtoField.insertText] ?? (typeof label === 'string' ? label : label.label),
|
||||
range: data[ISuggestDataDtoField.range] ?? defaultRange,
|
||||
insertTextRules: data[ISuggestDataDtoField.insertTextRules],
|
||||
commitCharacters: data[ISuggestDataDtoField.commitCharacters],
|
||||
@@ -772,6 +782,43 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
}
|
||||
}
|
||||
|
||||
// --- type hierarchy
|
||||
|
||||
$registerTypeHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, typeh.TypeHierarchyProviderRegistry.register(selector, {
|
||||
|
||||
prepareTypeHierarchy: async (document, position, token) => {
|
||||
const items = await this._proxy.$prepareTypeHierarchy(handle, document.uri, position, token);
|
||||
if (!items) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
dispose: () => {
|
||||
for (const item of items) {
|
||||
this._proxy.$releaseTypeHierarchy(handle, item._sessionId);
|
||||
}
|
||||
},
|
||||
roots: items.map(MainThreadLanguageFeatures._reviveTypeHierarchyItemDto)
|
||||
};
|
||||
},
|
||||
|
||||
provideSupertypes: async (item, token) => {
|
||||
const supertypes = await this._proxy.$provideTypeHierarchySupertypes(handle, item._sessionId, item._itemId, token);
|
||||
if (!supertypes) {
|
||||
return supertypes;
|
||||
}
|
||||
return supertypes.map(item => MainThreadLanguageFeatures._reviveTypeHierarchyItemDto(item)) as any; // {{SQL CARBON EDIT}} Cast to any to get around weird compile error - trusting them to do the right thing here
|
||||
},
|
||||
provideSubtypes: async (item, token) => {
|
||||
const subtypes = await this._proxy.$provideTypeHierarchySubtypes(handle, item._sessionId, item._itemId, token);
|
||||
if (!subtypes) {
|
||||
return subtypes;
|
||||
}
|
||||
return subtypes.map(MainThreadLanguageFeatures._reviveTypeHierarchyItemDto) as any; // {{SQL CARBON EDIT}} Cast to any to get around weird compile error - trusting them to do the right thing here
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class MainThreadDocumentSemanticTokensProvider implements modes.DocumentSemanticTokensProvider {
|
||||
|
||||
@@ -12,6 +12,8 @@ import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
import { StandardTokenType } from 'vs/editor/common/modes';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { ILanguageStatus, ILanguageStatusService } from 'vs/workbench/services/languageStatus/common/languageStatusService';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadLanguages)
|
||||
export class MainThreadLanguages implements MainThreadLanguagesShape {
|
||||
@@ -21,8 +23,8 @@ export class MainThreadLanguages implements MainThreadLanguagesShape {
|
||||
@IModeService private readonly _modeService: IModeService,
|
||||
@IModelService private readonly _modelService: IModelService,
|
||||
@ITextModelService private _resolverService: ITextModelService,
|
||||
) {
|
||||
}
|
||||
@ILanguageStatusService private readonly _languageStatusService: ILanguageStatusService,
|
||||
) { }
|
||||
|
||||
dispose(): void {
|
||||
// nothing
|
||||
@@ -62,4 +64,17 @@ export class MainThreadLanguages implements MainThreadLanguagesShape {
|
||||
range: new Range(position.lineNumber, 1 + tokens.getStartOffset(idx), position.lineNumber, 1 + tokens.getEndOffset(idx))
|
||||
};
|
||||
}
|
||||
|
||||
// --- language status
|
||||
|
||||
private readonly _status = new Map<number, IDisposable>();
|
||||
|
||||
$setLanguageStatus(handle: number, status: ILanguageStatus): void {
|
||||
this._status.get(handle)?.dispose();
|
||||
this._status.set(handle, this._languageStatusService.addStatus(status));
|
||||
}
|
||||
|
||||
$removeLanguageStatus(handle: number): void {
|
||||
this._status.get(handle)?.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IExtHostContext, ExtHostContext, MainThreadLogShape, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { UriComponents, URI } from 'vs/base/common/uri';
|
||||
import { FileLogger } from 'vs/platform/log/common/fileLog';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { basename } from 'vs/base/common/path';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadLog)
|
||||
export class MainThreadLogService implements MainThreadLogShape {
|
||||
@@ -40,9 +42,26 @@ export class MainThreadLogService implements MainThreadLogShape {
|
||||
const uri = URI.revive(file);
|
||||
let logger = this._loggers.get(uri.toString());
|
||||
if (!logger) {
|
||||
logger = this._instaService.createInstance(FileLogger, basename(file.path), URI.revive(file), this._logService.getLevel());
|
||||
logger = this._instaService.createInstance(FileLogger, basename(file.path), URI.revive(file), this._logService.getLevel(), false);
|
||||
this._loggers.set(uri.toString(), logger);
|
||||
}
|
||||
logger.log(level, message);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Internal commands to improve extension test runs
|
||||
|
||||
CommandsRegistry.registerCommand('_extensionTests.setLogLevel', function (accessor: ServicesAccessor, level: number) {
|
||||
const logService = accessor.get(ILogService);
|
||||
const environmentService = accessor.get(IEnvironmentService);
|
||||
|
||||
if (environmentService.isExtensionDevelopment && !!environmentService.extensionTestsLocationURI) {
|
||||
logService.setLevel(level);
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand('_extensionTests.getLogLevel', function (accessor: ServicesAccessor) {
|
||||
const logService = accessor.get(ILogService);
|
||||
|
||||
return logService.getLevel();
|
||||
});
|
||||
|
||||
@@ -33,7 +33,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape {
|
||||
|
||||
$showMessage(severity: Severity, message: string, options: MainThreadMessageOptions, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Promise<number | undefined> {
|
||||
if (options.modal) {
|
||||
return this._showModalMessage(severity, message, commands, options.useCustom);
|
||||
return this._showModalMessage(severity, message, options.detail, commands, options.useCustom);
|
||||
} else {
|
||||
return this._showMessage(severity, message, commands, options.extension);
|
||||
}
|
||||
@@ -100,7 +100,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape {
|
||||
});
|
||||
}
|
||||
|
||||
private async _showModalMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number; }[], useCustom?: boolean): Promise<number | undefined> {
|
||||
private async _showModalMessage(severity: Severity, message: string, detail: string | undefined, commands: { title: string; isCloseAffordance: boolean; handle: number; }[], useCustom?: boolean): Promise<number | undefined> {
|
||||
let cancelId: number | undefined = undefined;
|
||||
|
||||
const buttons = commands.map((command, index) => {
|
||||
@@ -121,7 +121,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape {
|
||||
cancelId = buttons.length - 1;
|
||||
}
|
||||
|
||||
const { choice } = await this._dialogService.show(severity, message, buttons, { cancelId, custom: useCustom });
|
||||
const { choice } = await this._dialogService.show(severity, message, buttons, { cancelId, custom: useCustom, detail });
|
||||
return choice === commands.length ? undefined : commands[choice].handle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,13 @@ import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { NotebookDto } from 'vs/workbench/api/browser/mainThreadNotebookDto';
|
||||
// import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; {{SQL CARBON EDIT}} Disable VS Code notebooks
|
||||
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
|
||||
import { INotebookCellStatusBarItemProvider, INotebookContributionData, NotebookDataDto, TransientCellMetadata, TransientDocumentMetadata, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookCellStatusBarItemProvider, INotebookContributionData, NotebookData as NotebookData, TransientCellMetadata, TransientDocumentMetadata, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookContentProvider, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, MainThreadNotebookShape, NotebookExtensionDescription } from '../common/extHost.protocol'; // {{SQL CARBON EDIT}} Remove MainContext
|
||||
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, MainThreadNotebookShape, NotebookExtensionDescription } from '../common/extHost.protocol'; // {{SQL CARBON EDIT}} Disable VS Code notebooks
|
||||
|
||||
// @extHostNamedCustomer(MainContext.MainThreadNotebook) {{SQL CARBON EDIT}} Disable VS Code notebooks
|
||||
export class MainThreadNotebooks implements MainThreadNotebookShape {
|
||||
@@ -56,7 +58,7 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
|
||||
open: async (uri: URI, backupId: string | undefined, untitledDocumentData: VSBuffer | undefined, token: CancellationToken) => {
|
||||
const data = await this._proxy.$openNotebook(viewType, uri, backupId, untitledDocumentData, token);
|
||||
return {
|
||||
data,
|
||||
data: NotebookDto.fromNotebookDataDto(data.value),
|
||||
transientOptions: contentOptions
|
||||
};
|
||||
},
|
||||
@@ -100,14 +102,16 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$registerNotebookSerializer(handle: number, extension: NotebookExtensionDescription, viewType: string, options: TransientOptions, data: INotebookContributionData | undefined): void {
|
||||
const registration = this._notebookService.registerNotebookSerializer(viewType, extension, {
|
||||
options,
|
||||
dataToNotebook: (data: VSBuffer): Promise<NotebookDataDto> => {
|
||||
return this._proxy.$dataToNotebook(handle, data, CancellationToken.None);
|
||||
dataToNotebook: async (data: VSBuffer): Promise<NotebookData> => {
|
||||
const dto = await this._proxy.$dataToNotebook(handle, data, CancellationToken.None);
|
||||
return NotebookDto.fromNotebookDataDto(dto.value);
|
||||
},
|
||||
notebookToData: (data: NotebookDataDto): Promise<VSBuffer> => {
|
||||
return this._proxy.$notebookToData(handle, data, CancellationToken.None);
|
||||
notebookToData: (data: NotebookData): Promise<VSBuffer> => {
|
||||
return this._proxy.$notebookToData(handle, new SerializableObjectWithBuffers(NotebookDto.toNotebookDataDto(data)), CancellationToken.None);
|
||||
}
|
||||
});
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
@@ -9,15 +9,13 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { BoundModelReferenceCollection } from 'vs/workbench/api/browser/mainThreadDocuments';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { IImmediateCellEditOperation, IMainCellDto, NotebookCellsChangeType, NotebookDataDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService';
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
|
||||
import { ExtHostContext, ExtHostNotebookDocumentsShape, IExtHostContext, MainThreadNotebookDocumentsShape } from '../common/extHost.protocol';
|
||||
import { ExtHostContext, ExtHostNotebookDocumentsShape, IExtHostContext, MainThreadNotebookDocumentsShape, NotebookCellDto, NotebookCellsChangedEventDto, NotebookDataDto } from '../common/extHost.protocol';
|
||||
import { MainThreadNotebooksAndEditors } from 'vs/workbench/api/browser/mainThreadNotebookDocumentsAndEditors';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
|
||||
import { NotebookDto } from 'vs/workbench/api/browser/mainThreadNotebookDto';
|
||||
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
|
||||
export class MainThreadNotebookDocuments implements MainThreadNotebookDocumentsShape {
|
||||
|
||||
@@ -30,7 +28,6 @@ export class MainThreadNotebookDocuments implements MainThreadNotebookDocumentsS
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
notebooksAndEditors: MainThreadNotebooksAndEditors,
|
||||
@INotebookService private readonly _notebookService: INotebookService,
|
||||
@INotebookEditorModelResolverService private readonly _notebookEditorModelResolverService: INotebookEditorModelResolverService,
|
||||
@IUriIdentityService private readonly _uriIdentityService: IUriIdentityService
|
||||
) {
|
||||
@@ -56,36 +53,59 @@ export class MainThreadNotebookDocuments implements MainThreadNotebookDocumentsS
|
||||
for (const textModel of notebooks) {
|
||||
const disposableStore = new DisposableStore();
|
||||
disposableStore.add(textModel.onDidChangeContent(event => {
|
||||
const dto = event.rawEvents.map(e => {
|
||||
const data =
|
||||
e.kind === NotebookCellsChangeType.ModelChange || e.kind === NotebookCellsChangeType.Initialize
|
||||
? {
|
||||
kind: e.kind,
|
||||
versionId: event.versionId,
|
||||
changes: e.changes.map(diff => [diff[0], diff[1], diff[2].map(cell => MainThreadNotebookDocuments._cellToDto(cell as NotebookCellTextModel))] as [number, number, IMainCellDto[]])
|
||||
}
|
||||
: (
|
||||
e.kind === NotebookCellsChangeType.Move
|
||||
? {
|
||||
kind: e.kind,
|
||||
index: e.index,
|
||||
length: e.length,
|
||||
newIdx: e.newIdx,
|
||||
versionId: event.versionId,
|
||||
cells: e.cells.map(cell => MainThreadNotebookDocuments._cellToDto(cell as NotebookCellTextModel))
|
||||
}
|
||||
: e
|
||||
);
|
||||
|
||||
return data;
|
||||
});
|
||||
const eventDto: NotebookCellsChangedEventDto = {
|
||||
versionId: event.versionId,
|
||||
rawEvents: []
|
||||
};
|
||||
|
||||
for (const e of event.rawEvents) {
|
||||
|
||||
switch (e.kind) {
|
||||
case NotebookCellsChangeType.ModelChange:
|
||||
eventDto.rawEvents.push({
|
||||
kind: e.kind,
|
||||
changes: e.changes.map(diff => [diff[0], diff[1], diff[2].map(cell => NotebookDto.toNotebookCellDto(cell as NotebookCellTextModel))] as [number, number, NotebookCellDto[]])
|
||||
});
|
||||
break;
|
||||
case NotebookCellsChangeType.Move:
|
||||
eventDto.rawEvents.push({
|
||||
kind: e.kind,
|
||||
index: e.index,
|
||||
length: e.length,
|
||||
newIdx: e.newIdx,
|
||||
});
|
||||
break;
|
||||
case NotebookCellsChangeType.Output:
|
||||
eventDto.rawEvents.push({
|
||||
kind: e.kind,
|
||||
index: e.index,
|
||||
outputs: e.outputs.map(NotebookDto.toNotebookOutputDto)
|
||||
});
|
||||
break;
|
||||
case NotebookCellsChangeType.OutputItem:
|
||||
eventDto.rawEvents.push({
|
||||
kind: e.kind,
|
||||
index: e.index,
|
||||
outputId: e.outputId,
|
||||
outputItems: e.outputItems.map(NotebookDto.toNotebookOutputItemDto),
|
||||
append: e.append
|
||||
});
|
||||
break;
|
||||
case NotebookCellsChangeType.ChangeLanguage:
|
||||
case NotebookCellsChangeType.ChangeCellMetadata:
|
||||
case NotebookCellsChangeType.ChangeCellInternalMetadata:
|
||||
eventDto.rawEvents.push(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// using the model resolver service to know if the model is dirty or not.
|
||||
// assuming this is the first listener it can mean that at first the model
|
||||
// is marked as dirty and that another event is fired
|
||||
this._proxy.$acceptModelChanged(
|
||||
textModel.uri,
|
||||
{ rawEvents: dto, versionId: event.versionId },
|
||||
new SerializableObjectWithBuffers(eventDto),
|
||||
this._notebookEditorModelResolverService.isDirty(textModel.uri)
|
||||
);
|
||||
|
||||
@@ -106,39 +126,9 @@ export class MainThreadNotebookDocuments implements MainThreadNotebookDocumentsS
|
||||
}
|
||||
}
|
||||
|
||||
private static _cellToDto(cell: NotebookCellTextModel): IMainCellDto {
|
||||
return {
|
||||
handle: cell.handle,
|
||||
uri: cell.uri,
|
||||
source: cell.textBuffer.getLinesContent(),
|
||||
eol: cell.textBuffer.getEOL(),
|
||||
language: cell.language,
|
||||
cellKind: cell.cellKind,
|
||||
outputs: cell.outputs,
|
||||
metadata: cell.metadata,
|
||||
internalMetadata: cell.internalMetadata,
|
||||
};
|
||||
}
|
||||
|
||||
async $tryCreateNotebook(options: { viewType: string, content?: NotebookDataDto }): Promise<UriComponents> {
|
||||
|
||||
const info = this._notebookService.getContributedNotebookType(options.viewType);
|
||||
if (!info) {
|
||||
throw new Error('UNKNOWN view type: ' + options.viewType);
|
||||
}
|
||||
|
||||
// find a free URI for the untitled case
|
||||
const suffix = NotebookProviderInfo.possibleFileEnding(info.selectors) ?? '';
|
||||
let uri: URI;
|
||||
for (let counter = 1; ; counter++) {
|
||||
let candidate = URI.from({ scheme: Schemas.untitled, path: `Untitled-${counter}${suffix}`, query: options.viewType });
|
||||
if (!this._notebookService.getNotebookTextModel(candidate)) {
|
||||
uri = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const ref = await this._notebookEditorModelResolverService.resolve(uri, options.viewType);
|
||||
const ref = await this._notebookEditorModelResolverService.resolve({ untitledResource: undefined }, options.viewType);
|
||||
|
||||
// untitled notebooks are disposed when they get saved. we should not hold a reference
|
||||
// to such a disposed notebook and therefore dispose the reference as well
|
||||
@@ -147,17 +137,14 @@ export class MainThreadNotebookDocuments implements MainThreadNotebookDocumentsS
|
||||
});
|
||||
|
||||
// untitled notebooks are dirty by default
|
||||
this._proxy.$acceptDirtyStateChanged(uri, true);
|
||||
this._proxy.$acceptDirtyStateChanged(ref.object.resource, true);
|
||||
|
||||
// apply content changes... slightly HACKY -> this triggers a change event
|
||||
if (options.content) {
|
||||
ref.object.notebook.reset(
|
||||
options.content.cells,
|
||||
options.content.metadata,
|
||||
ref.object.notebook.transientOptions
|
||||
);
|
||||
const data = NotebookDto.fromNotebookDataDto(options.content);
|
||||
ref.object.notebook.reset(data.cells, data.metadata, ref.object.notebook.transientOptions);
|
||||
}
|
||||
return uri;
|
||||
return ref.object.resource;
|
||||
}
|
||||
|
||||
async $tryOpenNotebook(uriComponents: UriComponents): Promise<URI> {
|
||||
@@ -175,19 +162,4 @@ export class MainThreadNotebookDocuments implements MainThreadNotebookDocumentsS
|
||||
ref.dispose();
|
||||
return saveResult;
|
||||
}
|
||||
|
||||
async $applyEdits(resource: UriComponents, cellEdits: IImmediateCellEditOperation[], computeUndoRedo = true): Promise<void> {
|
||||
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
|
||||
if (!textModel) {
|
||||
throw new Error(`Can't apply edits to unknown notebook model: ${URI.revive(resource).toString()}`);
|
||||
}
|
||||
|
||||
try {
|
||||
textModel.applyEdits(cellEdits, true, undefined, () => undefined, undefined, computeUndoRedo);
|
||||
} catch (e) {
|
||||
// Clearing outputs at the same time as the EH calling append/replaceOutputItems is an expected race, and it should be a no-op.
|
||||
// And any other failure should not throw back to the extension.
|
||||
onUnexpectedError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,10 @@ import { combinedDisposable, DisposableStore, IDisposable } from 'vs/base/common
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { MainThreadNotebookDocuments } from 'vs/workbench/api/browser/mainThreadNotebookDocuments';
|
||||
import { NotebookDto } from 'vs/workbench/api/browser/mainThreadNotebookDto';
|
||||
import { MainThreadNotebookEditors } from 'vs/workbench/api/browser/mainThreadNotebookEditors';
|
||||
// import { extHostCustomer } from 'vs/workbench/api/common/extHostCustomers'; {{SQL CARBON EDIT}} Disable VS Code notebooks
|
||||
import { editorGroupToViewColumn } from 'vs/workbench/common/editor';
|
||||
import { editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import { getNotebookEditorFromEditorPane, IActiveNotebookEditor, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
@@ -19,6 +20,7 @@ import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookS
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, INotebookDocumentsAndEditorsDelta, INotebookEditorAddData, INotebookModelAddedData, MainContext } from '../common/extHost.protocol';
|
||||
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
|
||||
interface INotebookAndEditorDelta {
|
||||
removedDocuments: URI[];
|
||||
@@ -189,7 +191,7 @@ export class MainThreadNotebooksAndEditors {
|
||||
};
|
||||
|
||||
// send to extension FIRST
|
||||
this._proxy.$acceptDocumentAndEditorsDelta(dto);
|
||||
this._proxy.$acceptDocumentAndEditorsDelta(new SerializableObjectWithBuffers(dto));
|
||||
|
||||
// handle internally
|
||||
this._onDidRemoveEditors.fire(delta.removedEditors);
|
||||
@@ -226,17 +228,7 @@ export class MainThreadNotebooksAndEditors {
|
||||
uri: e.uri,
|
||||
metadata: e.metadata,
|
||||
versionId: e.versionId,
|
||||
cells: e.cells.map(cell => ({
|
||||
handle: cell.handle,
|
||||
uri: cell.uri,
|
||||
source: cell.textBuffer.getLinesContent(),
|
||||
eol: cell.textBuffer.getEOL(),
|
||||
language: cell.language,
|
||||
cellKind: cell.cellKind,
|
||||
outputs: cell.outputs,
|
||||
metadata: cell.metadata,
|
||||
internalMetadata: cell.internalMetadata,
|
||||
}))
|
||||
cells: e.cells.map(NotebookDto.toNotebookCellDto)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -246,10 +238,10 @@ export class MainThreadNotebooksAndEditors {
|
||||
|
||||
return {
|
||||
id: add.getId(),
|
||||
documentUri: add.viewModel.uri,
|
||||
documentUri: add.textModel.uri,
|
||||
selections: add.getSelections(),
|
||||
visibleRanges: add.visibleRanges,
|
||||
viewColumn: pane && editorGroupToViewColumn(this._editorGroupService, pane.group)
|
||||
viewColumn: pane && editorGroupToColumn(this._editorGroupService, pane.group)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
127
src/vs/workbench/api/browser/mainThreadNotebookDto.ts
Normal file
127
src/vs/workbench/api/browser/mainThreadNotebookDto.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import * as notebookCommon from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellExecutionUpdateType, ICellExecuteUpdate } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
|
||||
|
||||
export namespace NotebookDto {
|
||||
|
||||
export function toNotebookOutputItemDto(item: notebookCommon.IOutputItemDto): extHostProtocol.NotebookOutputItemDto {
|
||||
return {
|
||||
mime: item.mime,
|
||||
valueBytes: item.data
|
||||
};
|
||||
}
|
||||
|
||||
export function toNotebookOutputDto(output: notebookCommon.IOutputDto): extHostProtocol.NotebookOutputDto {
|
||||
return {
|
||||
outputId: output.outputId,
|
||||
metadata: output.metadata,
|
||||
items: output.outputs.map(toNotebookOutputItemDto)
|
||||
};
|
||||
}
|
||||
|
||||
export function toNotebookCellDataDto(cell: notebookCommon.ICellDto2): extHostProtocol.NotebookCellDataDto {
|
||||
return {
|
||||
cellKind: cell.cellKind,
|
||||
language: cell.language,
|
||||
mime: cell.mime,
|
||||
source: cell.source,
|
||||
internalMetadata: cell.internalMetadata,
|
||||
metadata: cell.metadata,
|
||||
outputs: cell.outputs.map(toNotebookOutputDto)
|
||||
};
|
||||
}
|
||||
|
||||
export function toNotebookDataDto(data: notebookCommon.NotebookData): extHostProtocol.NotebookDataDto {
|
||||
return {
|
||||
metadata: data.metadata,
|
||||
cells: data.cells.map(toNotebookCellDataDto)
|
||||
};
|
||||
}
|
||||
|
||||
export function fromNotebookOutputItemDto(item: extHostProtocol.NotebookOutputItemDto): notebookCommon.IOutputItemDto {
|
||||
return {
|
||||
mime: item.mime,
|
||||
data: item.valueBytes
|
||||
};
|
||||
}
|
||||
|
||||
export function fromNotebookOutputDto(output: extHostProtocol.NotebookOutputDto): notebookCommon.IOutputDto {
|
||||
return {
|
||||
outputId: output.outputId,
|
||||
metadata: output.metadata,
|
||||
outputs: output.items.map(fromNotebookOutputItemDto)
|
||||
};
|
||||
}
|
||||
|
||||
export function fromNotebookCellDataDto(cell: extHostProtocol.NotebookCellDataDto): notebookCommon.ICellDto2 {
|
||||
return {
|
||||
cellKind: cell.cellKind,
|
||||
language: cell.language,
|
||||
mime: cell.mime,
|
||||
source: cell.source,
|
||||
outputs: cell.outputs.map(fromNotebookOutputDto),
|
||||
metadata: cell.metadata,
|
||||
internalMetadata: cell.internalMetadata
|
||||
};
|
||||
}
|
||||
|
||||
export function fromNotebookDataDto(data: extHostProtocol.NotebookDataDto): notebookCommon.NotebookData {
|
||||
return {
|
||||
metadata: data.metadata,
|
||||
cells: data.cells.map(fromNotebookCellDataDto)
|
||||
};
|
||||
}
|
||||
|
||||
export function toNotebookCellDto(cell: NotebookCellTextModel): extHostProtocol.NotebookCellDto {
|
||||
return {
|
||||
handle: cell.handle,
|
||||
uri: cell.uri,
|
||||
source: cell.textBuffer.getLinesContent(),
|
||||
eol: cell.textBuffer.getEOL(),
|
||||
language: cell.language,
|
||||
cellKind: cell.cellKind,
|
||||
outputs: cell.outputs.map(toNotebookOutputDto),
|
||||
metadata: cell.metadata,
|
||||
internalMetadata: cell.internalMetadata,
|
||||
};
|
||||
}
|
||||
|
||||
export function fromCellExecuteUpdateDto(data: extHostProtocol.ICellExecuteUpdateDto): ICellExecuteUpdate {
|
||||
if (data.editType === CellExecutionUpdateType.Output) {
|
||||
return {
|
||||
editType: data.editType,
|
||||
cellHandle: data.cellHandle,
|
||||
append: data.append,
|
||||
outputs: data.outputs.map(fromNotebookOutputDto)
|
||||
};
|
||||
} else if (data.editType === CellExecutionUpdateType.OutputItems) {
|
||||
return {
|
||||
editType: data.editType,
|
||||
append: data.append,
|
||||
outputId: data.outputId,
|
||||
items: data.items.map(fromNotebookOutputItemDto)
|
||||
};
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
export function fromCellEditOperationDto(edit: extHostProtocol.ICellEditOperationDto): notebookCommon.ICellEditOperation {
|
||||
if (edit.editType === notebookCommon.CellEditType.Replace) {
|
||||
return {
|
||||
editType: edit.editType,
|
||||
index: edit.index,
|
||||
count: edit.count,
|
||||
cells: edit.cells.map(fromNotebookCellDataDto)
|
||||
};
|
||||
} else {
|
||||
return edit;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,19 +6,20 @@
|
||||
import { DisposableStore, dispose } from 'vs/base/common/lifecycle';
|
||||
import { getNotebookEditorFromEditorPane, INotebookEditor, INotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService';
|
||||
import { ExtHostContext, ExtHostNotebookEditorsShape, IExtHostContext, INotebookDocumentShowOptions, INotebookEditorViewColumnInfo, MainThreadNotebookEditorsShape, NotebookEditorRevealType } from '../common/extHost.protocol';
|
||||
import { ExtHostContext, ExtHostNotebookEditorsShape, ICellEditOperationDto, IExtHostContext, INotebookDocumentShowOptions, INotebookEditorViewColumnInfo, MainThreadNotebookEditorsShape, NotebookEditorRevealType } from '../common/extHost.protocol';
|
||||
import { MainThreadNotebooksAndEditors } from 'vs/workbench/api/browser/mainThreadNotebookDocumentsAndEditors';
|
||||
import { ICellEditOperation, INotebookDecorationRenderOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookDecorationRenderOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { EditorActivation, EditorOverride } from 'vs/platform/editor/common/editor';
|
||||
import { EditorActivation, EditorResolution } from 'vs/platform/editor/common/editor';
|
||||
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { editorGroupToViewColumn } from 'vs/workbench/common/editor';
|
||||
import { editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import { equals } from 'vs/base/common/objects';
|
||||
import { NotebookDto } from 'vs/workbench/api/browser/mainThreadNotebookDto';
|
||||
|
||||
class MainThreadNotebook {
|
||||
|
||||
@@ -95,7 +96,7 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape
|
||||
for (let editorPane of this._editorService.visibleEditorPanes) {
|
||||
const candidate = getNotebookEditorFromEditorPane(editorPane);
|
||||
if (candidate && this._mainThreadEditors.has(candidate.getId())) {
|
||||
result[candidate.getId()] = editorGroupToViewColumn(this._editorGroupService, editorPane.group);
|
||||
result[candidate.getId()] = editorGroupToColumn(this._editorGroupService, editorPane.group);
|
||||
}
|
||||
}
|
||||
if (!equals(result, this._currentViewColumnInfo)) {
|
||||
@@ -104,7 +105,7 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape
|
||||
}
|
||||
}
|
||||
|
||||
async $tryApplyEdits(editorId: string, modelVersionId: number, cellEdits: ICellEditOperation[]): Promise<boolean> {
|
||||
async $tryApplyEdits(editorId: string, modelVersionId: number, cellEdits: ICellEditOperationDto[]): Promise<boolean> {
|
||||
const wrapper = this._mainThreadEditors.get(editorId);
|
||||
if (!wrapper) {
|
||||
return false;
|
||||
@@ -118,7 +119,7 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape
|
||||
return false;
|
||||
}
|
||||
//todo@jrieken use proper selection logic!
|
||||
return editor.textModel.applyEdits(cellEdits, true, undefined, () => undefined, undefined);
|
||||
return editor.textModel.applyEdits(cellEdits.map(NotebookDto.fromCellEditOperationDto), true, undefined, () => undefined, undefined);
|
||||
}
|
||||
|
||||
async $tryShowNotebookDocument(resource: UriComponents, viewType: string, options: INotebookDocumentShowOptions): Promise<string> {
|
||||
@@ -130,7 +131,7 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape
|
||||
// preserve pre 1.38 behaviour to not make group active when preserveFocus: true
|
||||
// but make sure to restore the editor to fix https://github.com/microsoft/vscode/issues/79633
|
||||
activation: options.preserveFocus ? EditorActivation.RESTORE : undefined,
|
||||
override: EditorOverride.DISABLED
|
||||
override: EditorResolution.DISABLED
|
||||
};
|
||||
|
||||
const input = NotebookEditorInput.create(this._instantiationService, URI.revive(resource), viewType);
|
||||
@@ -189,9 +190,14 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape
|
||||
|
||||
$trySetSelections(id: string, ranges: ICellRange[]): void {
|
||||
const editor = this._notebookEditorService.getNotebookEditor(id);
|
||||
if (editor) {
|
||||
// @rebornix how to set an editor selection?
|
||||
// editor.setSelections(ranges)
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.setSelections(ranges);
|
||||
|
||||
if (ranges.length) {
|
||||
editor.setFocus({ start: ranges[0].start, end: ranges[0].start + 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,23 +3,26 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { flatten, isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { flatten, groupBy, isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { combinedDisposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { NotebookDto } from 'vs/workbench/api/browser/mainThreadNotebookDto';
|
||||
// import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; {{SQL CARBON EDIT}} Disable VS Code notebooks
|
||||
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService';
|
||||
import { INotebookKernel, INotebookKernelChangeEvent } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
|
||||
import { ExtHostContext, ExtHostNotebookKernelsShape, IExtHostContext, INotebookKernelDto2, MainThreadNotebookKernelsShape } from '../common/extHost.protocol';// {{SQL CARBON EDIT}} Remove MainContext
|
||||
import { INotebookCellExecution, INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
|
||||
import { INotebookKernel, INotebookKernelChangeEvent, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
|
||||
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import { ExtHostContext, ExtHostNotebookKernelsShape, ICellExecuteUpdateDto, IExtHostContext, INotebookKernelDto2, MainThreadNotebookKernelsShape } from '../common/extHost.protocol'; // {{SQL CARBON EDIT}} Disable VS Code notebooks
|
||||
|
||||
abstract class MainThreadKernel implements INotebookKernel {
|
||||
|
||||
private readonly _onDidChange = new Emitter<INotebookKernelChangeEvent>();
|
||||
private readonly preloads: { uri: URI, provides: string[] }[];
|
||||
private readonly preloads: { uri: URI, provides: string[]; }[];
|
||||
readonly onDidChange: Event<INotebookKernelChangeEvent> = this._onDidChange.event;
|
||||
|
||||
readonly id: string;
|
||||
@@ -97,10 +100,14 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
|
||||
private readonly _kernels = new Map<number, [kernel: MainThreadKernel, registraion: IDisposable]>();
|
||||
private readonly _proxy: ExtHostNotebookKernelsShape;
|
||||
|
||||
private readonly _executions = new Map<number, INotebookCellExecution>();
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@IModeService private readonly _modeService: IModeService,
|
||||
@INotebookKernelService private readonly _notebookKernelService: INotebookKernelService,
|
||||
@INotebookExecutionService private readonly _notebookExecutionService: INotebookExecutionService,
|
||||
// @INotebookService private readonly _notebookService: INotebookService,
|
||||
@INotebookEditorService notebookEditorService: INotebookEditorService
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebookKernels);
|
||||
@@ -125,7 +132,7 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
|
||||
if (!editor.hasModel()) {
|
||||
return;
|
||||
}
|
||||
const { selected } = this._notebookKernelService.getMatchingKernel(editor.viewModel.notebookDocument);
|
||||
const { selected } = this._notebookKernelService.getMatchingKernel(editor.textModel);
|
||||
if (!selected) {
|
||||
return;
|
||||
}
|
||||
@@ -155,7 +162,7 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
|
||||
if (!editor.hasModel()) {
|
||||
continue;
|
||||
}
|
||||
if (this._notebookKernelService.getMatchingKernel(editor.viewModel.notebookDocument).selected !== kernel) {
|
||||
if (this._notebookKernelService.getMatchingKernel(editor.textModel).selected !== kernel) {
|
||||
// different kernel
|
||||
continue;
|
||||
}
|
||||
@@ -186,7 +193,7 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
|
||||
}
|
||||
}(data, this._modeService);
|
||||
|
||||
const listener = this._notebookKernelService.onDidChangeNotebookKernelBinding(e => {
|
||||
const listener = this._notebookKernelService.onDidChangeSelectedNotebooks(e => {
|
||||
if (e.oldKernel === kernel.id) {
|
||||
this._proxy.$acceptNotebookAssociation(handle, e.notebook, false);
|
||||
} else if (e.newKernel === kernel.id) {
|
||||
@@ -219,4 +226,33 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
|
||||
this._notebookKernelService.updateKernelNotebookAffinity(tuple[0], URI.revive(notebook), value);
|
||||
}
|
||||
}
|
||||
|
||||
// --- execution
|
||||
|
||||
$addExecution(handle: number, uri: UriComponents, cellHandle: number): void {
|
||||
const execution = this._notebookExecutionService.createNotebookCellExecution(URI.revive(uri), cellHandle);
|
||||
this._executions.set(handle, execution);
|
||||
}
|
||||
|
||||
$updateExecutions(data: SerializableObjectWithBuffers<ICellExecuteUpdateDto[]>): void {
|
||||
const updates = data.value;
|
||||
const groupedUpdates = groupBy(updates, (a, b) => a.executionHandle - b.executionHandle);
|
||||
groupedUpdates.forEach(datas => {
|
||||
const first = datas[0];
|
||||
const execution = this._executions.get(first.executionHandle);
|
||||
if (!execution) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
execution.update(datas.map(NotebookDto.fromCellExecuteUpdateDto));
|
||||
} catch (e) {
|
||||
onUnexpectedError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$removeExecution(handle: number): void {
|
||||
this._executions.delete(handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export class MainThreadNotebookRenderers extends Disposable implements MainThrea
|
||||
}));
|
||||
}
|
||||
|
||||
$postMessage(editorId: string, rendererId: string, message: unknown): void {
|
||||
this.messaging.fireDidReceiveMessage(editorId, rendererId, message);
|
||||
$postMessage(editorId: string | undefined, rendererId: string, message: unknown): Promise<boolean> {
|
||||
return this.messaging.receiveMessage(editorId, rendererId, message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { IViewsService } from 'vs/workbench/common/views';
|
||||
export class MainThreadOutputService extends Disposable implements MainThreadOutputServiceShape {
|
||||
|
||||
private static _idPool = 1;
|
||||
private static _extensionIdPool = new Map<string, number>();
|
||||
|
||||
private readonly _proxy: ExtHostOutputServiceShape;
|
||||
private readonly _outputService: IOutputService;
|
||||
@@ -41,8 +42,16 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
|
||||
setVisibleChannel();
|
||||
}
|
||||
|
||||
public $register(label: string, log: boolean, file?: UriComponents): Promise<string> {
|
||||
const id = 'extension-output-#' + (MainThreadOutputService._idPool++);
|
||||
public $register(label: string, log: boolean, file?: UriComponents, extensionId?: string): Promise<string> {
|
||||
let id: string;
|
||||
if (extensionId) {
|
||||
const idCounter = (MainThreadOutputService._extensionIdPool.get(extensionId) || 0) + 1;
|
||||
MainThreadOutputService._extensionIdPool.set(extensionId, idCounter);
|
||||
id = `extension-output-${extensionId}-#${idCounter}`;
|
||||
} else {
|
||||
id = `extension-output-#${(MainThreadOutputService._idPool++)}`;
|
||||
}
|
||||
|
||||
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id, label, file: file ? URI.revive(file) : undefined, log });
|
||||
this._register(toDisposable(() => this.$dispose(id)));
|
||||
return Promise.resolve(id);
|
||||
|
||||
@@ -3,18 +3,24 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IPickOptions, IInputOptions, IQuickInputService, IQuickInput } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IPickOptions, IInputOptions, IQuickInputService, IQuickInput, IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { ExtHostContext, MainThreadQuickOpenShape, ExtHostQuickOpenShape, TransferQuickPickItems, MainContext, IExtHostContext, TransferQuickInput, TransferQuickInputButton, IInputBoxOptions } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
interface QuickInputSession {
|
||||
input: IQuickInput;
|
||||
handlesToItems: Map<number, TransferQuickPickItems>;
|
||||
}
|
||||
|
||||
function reviveIconPathUris(iconPath: { dark: URI; light?: URI | undefined; }) {
|
||||
iconPath.dark = URI.revive(iconPath.dark);
|
||||
if (iconPath.light) {
|
||||
iconPath.light = URI.revive(iconPath.light);
|
||||
}
|
||||
}
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadQuickOpen)
|
||||
export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
|
||||
|
||||
@@ -126,49 +132,39 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
|
||||
const sessionId = params.id;
|
||||
let session = this.sessions.get(sessionId);
|
||||
if (!session) {
|
||||
|
||||
const input = params.type === 'quickPick' ? this._quickInputService.createQuickPick() : this._quickInputService.createInputBox();
|
||||
input.onDidAccept(() => {
|
||||
this._proxy.$onDidAccept(sessionId);
|
||||
});
|
||||
input.onDidTriggerButton(button => {
|
||||
this._proxy.$onDidTriggerButton(sessionId, (button as TransferQuickInputButton).handle);
|
||||
});
|
||||
input.onDidChangeValue(value => {
|
||||
this._proxy.$onDidChangeValue(sessionId, value);
|
||||
});
|
||||
input.onDidHide(() => {
|
||||
this._proxy.$onDidHide(sessionId);
|
||||
});
|
||||
|
||||
if (params.type === 'quickPick') {
|
||||
const input = this._quickInputService.createQuickPick();
|
||||
input.onDidAccept(() => {
|
||||
this._proxy.$onDidAccept(sessionId);
|
||||
});
|
||||
input.onDidChangeActive(items => {
|
||||
// Add extra events specific for quickpick
|
||||
const quickpick = input as IQuickPick<IQuickPickItem>;
|
||||
quickpick.onDidChangeActive(items => {
|
||||
this._proxy.$onDidChangeActive(sessionId, items.map(item => (item as TransferQuickPickItems).handle));
|
||||
});
|
||||
input.onDidChangeSelection(items => {
|
||||
quickpick.onDidChangeSelection(items => {
|
||||
this._proxy.$onDidChangeSelection(sessionId, items.map(item => (item as TransferQuickPickItems).handle));
|
||||
});
|
||||
input.onDidTriggerButton(button => {
|
||||
this._proxy.$onDidTriggerButton(sessionId, (button as TransferQuickInputButton).handle);
|
||||
quickpick.onDidTriggerItemButton((e) => {
|
||||
this._proxy.$onDidTriggerItemButton(sessionId, (e.item as TransferQuickPickItems).handle, (e.button as TransferQuickInputButton).handle);
|
||||
});
|
||||
input.onDidChangeValue(value => {
|
||||
this._proxy.$onDidChangeValue(sessionId, value);
|
||||
});
|
||||
input.onDidHide(() => {
|
||||
this._proxy.$onDidHide(sessionId);
|
||||
});
|
||||
session = {
|
||||
input,
|
||||
handlesToItems: new Map()
|
||||
};
|
||||
} else {
|
||||
const input = this._quickInputService.createInputBox();
|
||||
input.onDidAccept(() => {
|
||||
this._proxy.$onDidAccept(sessionId);
|
||||
});
|
||||
input.onDidTriggerButton(button => {
|
||||
this._proxy.$onDidTriggerButton(sessionId, (button as TransferQuickInputButton).handle);
|
||||
});
|
||||
input.onDidChangeValue(value => {
|
||||
this._proxy.$onDidChangeValue(sessionId, value);
|
||||
});
|
||||
input.onDidHide(() => {
|
||||
this._proxy.$onDidHide(sessionId);
|
||||
});
|
||||
session = {
|
||||
input,
|
||||
handlesToItems: new Map()
|
||||
};
|
||||
}
|
||||
|
||||
session = {
|
||||
input,
|
||||
handlesToItems: new Map()
|
||||
};
|
||||
this.sessions.set(sessionId, session);
|
||||
}
|
||||
const { input, handlesToItems } = session;
|
||||
@@ -185,6 +181,15 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
|
||||
} else if (param === 'items') {
|
||||
handlesToItems.clear();
|
||||
params[param].forEach((item: TransferQuickPickItems) => {
|
||||
if (item.buttons) {
|
||||
item.buttons = item.buttons.map((button: TransferQuickInputButton) => {
|
||||
if (button.iconPath) {
|
||||
reviveIconPathUris(button.iconPath);
|
||||
}
|
||||
|
||||
return button;
|
||||
});
|
||||
}
|
||||
handlesToItems.set(item.handle, item);
|
||||
});
|
||||
(input as any)[param] = params[param];
|
||||
@@ -197,23 +202,12 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
|
||||
if (button.handle === -1) {
|
||||
return this._quickInputService.backButton;
|
||||
}
|
||||
const { iconPath, tooltip, handle } = button;
|
||||
if ('id' in iconPath) {
|
||||
return {
|
||||
iconClass: ThemeIcon.asClassName(iconPath),
|
||||
tooltip,
|
||||
handle
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
iconPath: {
|
||||
dark: URI.revive(iconPath.dark),
|
||||
light: iconPath.light && URI.revive(iconPath.light)
|
||||
},
|
||||
tooltip,
|
||||
handle
|
||||
};
|
||||
|
||||
if (button.iconPath) {
|
||||
reviveIconPathUris(button.iconPath);
|
||||
}
|
||||
|
||||
return button;
|
||||
});
|
||||
} else {
|
||||
(input as any)[param] = params[param];
|
||||
|
||||
@@ -12,6 +12,9 @@ import { Command } from 'vs/editor/common/modes';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ISplice, Sequence } from 'vs/base/common/sequence';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { MarshalledId } from 'vs/base/common/marshalling';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
|
||||
class MainThreadSCMResourceGroup implements ISCMResourceGroup {
|
||||
|
||||
@@ -36,7 +39,7 @@ class MainThreadSCMResourceGroup implements ISCMResourceGroup {
|
||||
|
||||
toJSON(): any {
|
||||
return {
|
||||
$mid: 4,
|
||||
$mid: MarshalledId.ScmResourceGroup,
|
||||
sourceControlHandle: this.sourceControlHandle,
|
||||
groupHandle: this.handle
|
||||
};
|
||||
@@ -78,7 +81,7 @@ class MainThreadSCMResource implements ISCMResource {
|
||||
|
||||
toJSON(): any {
|
||||
return {
|
||||
$mid: 3,
|
||||
$mid: MarshalledId.ScmResource,
|
||||
sourceControlHandle: this.sourceControlHandle,
|
||||
groupHandle: this.groupHandle,
|
||||
handle: this.handle
|
||||
@@ -203,11 +206,14 @@ class MainThreadSCMProvider implements ISCMProvider {
|
||||
for (const [start, deleteCount, rawResources] of groupSlices) {
|
||||
const resources = rawResources.map(rawResource => {
|
||||
const [handle, sourceUri, icons, tooltip, strikeThrough, faded, contextValue, command] = rawResource;
|
||||
const icon = icons[0];
|
||||
const iconDark = icons[1] || icon;
|
||||
|
||||
const [light, dark] = icons;
|
||||
const icon = ThemeIcon.isThemeIcon(light) ? light : URI.revive(light);
|
||||
const iconDark = (ThemeIcon.isThemeIcon(dark) ? dark : URI.revive(dark)) || icon;
|
||||
|
||||
const decorations = {
|
||||
icon: icon ? URI.revive(icon) : undefined,
|
||||
iconDark: iconDark ? URI.revive(iconDark) : undefined,
|
||||
icon: icon,
|
||||
iconDark: iconDark,
|
||||
tooltip,
|
||||
strikeThrough,
|
||||
faded
|
||||
@@ -256,7 +262,7 @@ class MainThreadSCMProvider implements ISCMProvider {
|
||||
|
||||
toJSON(): any {
|
||||
return {
|
||||
$mid: 5,
|
||||
$mid: MarshalledId.ScmProvider,
|
||||
handle: this.handle
|
||||
};
|
||||
}
|
||||
@@ -433,7 +439,7 @@ export class MainThreadSCM implements MainThreadSCMShape {
|
||||
repository.input.setFocus();
|
||||
}
|
||||
|
||||
$showValidationMessage(sourceControlHandle: number, message: string, type: InputValidationType) {
|
||||
$showValidationMessage(sourceControlHandle: number, message: string | IMarkdownString, type: InputValidationType) {
|
||||
const repository = this._repositories.get(sourceControlHandle);
|
||||
if (!repository) {
|
||||
return;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { dispose, IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { IFileMatch, IFileQuery, IRawFileMatch2, ISearchComplete, ISearchCompleteStats, ISearchProgressItem, ISearchResultProvider, ISearchService, ITextQuery, QueryType, SearchProviderType } from 'vs/workbench/services/search/common/search';
|
||||
@@ -20,9 +21,15 @@ export class MainThreadSearch implements MainThreadSearchShape {
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@ISearchService private readonly _searchService: ISearchService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@IConfigurationService _configurationService: IConfigurationService,
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostSearch);
|
||||
|
||||
const forceEHSearch = _configurationService.getValue('search.experimental.forceExtensionHostSearch');
|
||||
if (forceEHSearch) {
|
||||
this._proxy.$enableExtensionHostSearch();
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { dispose } from 'vs/base/common/lifecycle';
|
||||
import { Command } from 'vs/editor/common/modes';
|
||||
import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { getCodiconAriaLabel } from 'vs/base/common/codicons';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadStatusBar)
|
||||
export class MainThreadStatusBar implements MainThreadStatusBarShape {
|
||||
@@ -27,7 +28,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape {
|
||||
this.entries.clear();
|
||||
}
|
||||
|
||||
$setEntry(entryId: number, id: string, name: string, text: string, tooltip: string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignment: MainThreadStatusBarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation): void {
|
||||
$setEntry(entryId: number, id: string, name: string, text: string, tooltip: IMarkdownString | string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignment: MainThreadStatusBarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation): void {
|
||||
// if there are icons in the text use the tooltip for the aria label
|
||||
let ariaLabel: string;
|
||||
let role: string | undefined = undefined;
|
||||
@@ -36,6 +37,10 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape {
|
||||
role = accessibilityInformation.role;
|
||||
} else {
|
||||
ariaLabel = getCodiconAriaLabel(text);
|
||||
if (tooltip) {
|
||||
const tooltipString = typeof tooltip === 'string' ? tooltip : tooltip.value;
|
||||
ariaLabel += `, ${tooltipString}`;
|
||||
}
|
||||
}
|
||||
const entry: IStatusbarEntry = { name, text, tooltip, command, color, backgroundColor, ariaLabel, role };
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder } from 'vs/platf
|
||||
import {
|
||||
ContributedTask, ConfiguringTask, KeyedTaskIdentifier, TaskExecution, Task, TaskEvent, TaskEventKind,
|
||||
PresentationOptions, CommandOptions, CommandConfiguration, RuntimeType, CustomTask, TaskScope, TaskSource,
|
||||
TaskSourceKind, ExtensionTaskSource, RunOptions, TaskSet, TaskDefinition
|
||||
TaskSourceKind, ExtensionTaskSource, RunOptions, TaskSet, TaskDefinition, TaskGroup
|
||||
} from 'vs/workbench/contrib/tasks/common/tasks';
|
||||
|
||||
|
||||
@@ -320,9 +320,8 @@ namespace TaskDTO {
|
||||
hasDefinedMatchers: ContributedTask.is(task) ? task.hasDefinedMatchers : false,
|
||||
runOptions: RunOptionsDTO.from(task.runOptions),
|
||||
};
|
||||
if (task.configurationProperties.group) {
|
||||
result.group = task.configurationProperties.group;
|
||||
}
|
||||
result.group = TaskGroup.from(task.configurationProperties.group);
|
||||
|
||||
if (task.configurationProperties.detail) {
|
||||
result.detail = task.configurationProperties.detail;
|
||||
}
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DisposableStore, Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, TerminalLaunchConfig, ITerminalDimensionsDto, TerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, TerminalLaunchConfig, ITerminalDimensionsDto, ExtHostTerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensions, TitleEventSource } from 'vs/platform/terminal/common/terminal';
|
||||
import { IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensions, TerminalLocation, TitleEventSource } from 'vs/platform/terminal/common/terminal';
|
||||
import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering';
|
||||
import { ITerminalExternalLinkProvider, ITerminalInstance, ITerminalInstanceService, ITerminalLink, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ITerminalEditorService, ITerminalExternalLinkProvider, ITerminalGroupService, ITerminalInstance, ITerminalInstanceService, ITerminalLink, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { TerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy';
|
||||
import { IEnvironmentVariableService, ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { deserializeEnvironmentVariableCollection, serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared';
|
||||
@@ -20,6 +20,7 @@ import { IStartExtensionTerminalRequest, ITerminalProcessExtHostProxy, ITerminal
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { OperatingSystem, OS } from 'vs/base/common/platform';
|
||||
import { TerminalEditorLocationOptions } from 'vscode';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTerminalService)
|
||||
export class MainThreadTerminalService implements MainThreadTerminalServiceShape {
|
||||
@@ -30,7 +31,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
* to a numeric terminal id (an id generated on the renderer side)
|
||||
* This comes in play only when dealing with terminals created on the extension host side
|
||||
*/
|
||||
private _extHostTerminalIds = new Map<string, number>();
|
||||
private _extHostTerminals = new Map<string, Promise<ITerminalInstance>>();
|
||||
private readonly _toDispose = new DisposableStore();
|
||||
private readonly _terminalProcessProxies = new Map<number, ITerminalProcessExtHostProxy>();
|
||||
private readonly _profileProviders = new Map<string, IDisposable>();
|
||||
@@ -53,30 +54,33 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
@IEnvironmentVariableService private readonly _environmentVariableService: IEnvironmentVariableService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@ITerminalProfileResolverService private readonly _terminalProfileResolverService: ITerminalProfileResolverService,
|
||||
@IRemoteAgentService remoteAgentService: IRemoteAgentService
|
||||
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
|
||||
@ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService,
|
||||
@ITerminalEditorService private readonly _terminalEditorService: ITerminalEditorService
|
||||
) {
|
||||
this._proxy = _extHostContext.getProxy(ExtHostContext.ExtHostTerminalService);
|
||||
|
||||
// ITerminalService listeners
|
||||
this._toDispose.add(_terminalService.onInstanceCreated((instance) => {
|
||||
this._toDispose.add(_terminalService.onDidCreateInstance((instance) => {
|
||||
this._onTerminalOpened(instance);
|
||||
this._onInstanceDimensionsChanged(instance);
|
||||
}));
|
||||
|
||||
this._toDispose.add(_terminalService.onInstanceDisposed(instance => this._onTerminalDisposed(instance)));
|
||||
this._toDispose.add(_terminalService.onInstanceProcessIdReady(instance => this._onTerminalProcessIdReady(instance)));
|
||||
this._toDispose.add(_terminalService.onInstanceDimensionsChanged(instance => this._onInstanceDimensionsChanged(instance)));
|
||||
this._toDispose.add(_terminalService.onInstanceMaximumDimensionsChanged(instance => this._onInstanceMaximumDimensionsChanged(instance)));
|
||||
this._toDispose.add(_terminalService.onInstanceRequestStartExtensionTerminal(e => this._onRequestStartExtensionTerminal(e)));
|
||||
this._toDispose.add(_terminalService.onActiveInstanceChanged(instance => this._onActiveTerminalChanged(instance ? instance.instanceId : null)));
|
||||
this._toDispose.add(_terminalService.onInstanceTitleChanged(instance => instance && this._onTitleChanged(instance.instanceId, instance.title)));
|
||||
this._toDispose.add(_terminalService.onDidDisposeInstance(instance => this._onTerminalDisposed(instance)));
|
||||
this._toDispose.add(_terminalService.onDidReceiveProcessId(instance => this._onTerminalProcessIdReady(instance)));
|
||||
this._toDispose.add(_terminalService.onDidChangeInstanceDimensions(instance => this._onInstanceDimensionsChanged(instance)));
|
||||
this._toDispose.add(_terminalService.onDidMaximumDimensionsChange(instance => this._onInstanceMaximumDimensionsChanged(instance)));
|
||||
this._toDispose.add(_terminalService.onDidRequestStartExtensionTerminal(e => this._onRequestStartExtensionTerminal(e)));
|
||||
this._toDispose.add(_terminalService.onDidChangeActiveInstance(instance => this._onActiveTerminalChanged(instance ? instance.instanceId : null)));
|
||||
this._toDispose.add(_terminalService.onDidChangeInstanceTitle(instance => instance && this._onTitleChanged(instance.instanceId, instance.title)));
|
||||
this._toDispose.add(_terminalService.onDidInputInstanceData(instance => this._proxy.$acceptTerminalInteraction(instance.instanceId)));
|
||||
|
||||
// Set initial ext host state
|
||||
this._terminalService.terminalInstances.forEach(t => {
|
||||
this._terminalService.instances.forEach(t => {
|
||||
this._onTerminalOpened(t);
|
||||
t.processReady.then(() => this._onTerminalProcessIdReady(t));
|
||||
});
|
||||
const activeInstance = this._terminalService.getActiveInstance();
|
||||
const activeInstance = this._terminalService.activeInstance;
|
||||
if (activeInstance) {
|
||||
this._proxy.$acceptActiveTerminalChanged(activeInstance.instanceId);
|
||||
}
|
||||
@@ -107,19 +111,11 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
this._proxy.$acceptDefaultProfile(...await Promise.all([defaultProfile, defaultAutomationProfile]));
|
||||
}
|
||||
|
||||
private _getTerminalId(id: TerminalIdentifier): number | undefined {
|
||||
if (typeof id === 'number') {
|
||||
return id;
|
||||
private async _getTerminalInstance(id: ExtHostTerminalIdentifier): Promise<ITerminalInstance | undefined> {
|
||||
if (typeof id === 'string') {
|
||||
return this._extHostTerminals.get(id);
|
||||
}
|
||||
return this._extHostTerminalIds.get(id);
|
||||
}
|
||||
|
||||
private _getTerminalInstance(id: TerminalIdentifier): ITerminalInstance | undefined {
|
||||
const rendererId = this._getTerminalId(id);
|
||||
if (typeof rendererId === 'number') {
|
||||
return this._terminalService.getInstanceFromId(rendererId);
|
||||
}
|
||||
return undefined;
|
||||
return this._terminalService.getInstanceFromId(id);
|
||||
}
|
||||
|
||||
public async $createTerminal(extHostTerminalId: string, launchConfig: TerminalLaunchConfig): Promise<void> {
|
||||
@@ -129,6 +125,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
args: launchConfig.shellArgs,
|
||||
cwd: typeof launchConfig.cwd === 'string' ? launchConfig.cwd : URI.revive(launchConfig.cwd),
|
||||
icon: launchConfig.icon,
|
||||
color: launchConfig.color,
|
||||
initialText: launchConfig.initialText,
|
||||
waitOnExit: launchConfig.waitOnExit,
|
||||
ignoreConfigurationCwd: true,
|
||||
@@ -138,46 +135,55 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
customPtyImplementation: launchConfig.isExtensionCustomPtyTerminal
|
||||
? (id, cols, rows) => new TerminalProcessExtHostProxy(id, cols, rows, this._terminalService)
|
||||
: undefined,
|
||||
extHostTerminalId: extHostTerminalId,
|
||||
extHostTerminalId,
|
||||
isFeatureTerminal: launchConfig.isFeatureTerminal,
|
||||
isExtensionOwnedTerminal: launchConfig.isExtensionOwnedTerminal,
|
||||
useShellEnvironment: launchConfig.useShellEnvironment
|
||||
useShellEnvironment: launchConfig.useShellEnvironment,
|
||||
};
|
||||
let terminal: ITerminalInstance | undefined;
|
||||
if (launchConfig.isSplitTerminal) {
|
||||
const activeInstance = this._terminalService.getActiveInstance();
|
||||
if (activeInstance) {
|
||||
terminal = withNullAsUndefined(this._terminalService.splitInstance(activeInstance, shellLaunchConfig));
|
||||
}
|
||||
}
|
||||
if (!terminal) {
|
||||
terminal = this._terminalService.createTerminal(shellLaunchConfig);
|
||||
}
|
||||
this._extHostTerminalIds.set(extHostTerminalId, terminal.instanceId);
|
||||
this._extHostTerminals.set(extHostTerminalId, new Promise(async r => {
|
||||
const terminal = await this._terminalService.createTerminal({
|
||||
config: shellLaunchConfig,
|
||||
location: await this._deserializeParentTerminal(launchConfig.location)
|
||||
});
|
||||
r(terminal);
|
||||
}));
|
||||
}
|
||||
|
||||
public $show(id: TerminalIdentifier, preserveFocus: boolean): void {
|
||||
const terminalInstance = this._getTerminalInstance(id);
|
||||
private async _deserializeParentTerminal(location?: TerminalLocation | TerminalEditorLocationOptions | { parentTerminal: ExtHostTerminalIdentifier } | { splitActiveTerminal: boolean }): Promise<TerminalLocation | TerminalEditorLocationOptions | { parentTerminal: ITerminalInstance } | { splitActiveTerminal: boolean } | undefined> {
|
||||
if (typeof location === 'object' && 'parentTerminal' in location) {
|
||||
const parentTerminal = await this._extHostTerminals.get(location.parentTerminal.toString());
|
||||
return parentTerminal ? { parentTerminal } : undefined;
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
public async $show(id: ExtHostTerminalIdentifier, preserveFocus: boolean): Promise<void> {
|
||||
const terminalInstance = await this._getTerminalInstance(id);
|
||||
if (terminalInstance) {
|
||||
this._terminalService.setActiveInstance(terminalInstance);
|
||||
this._terminalService.showPanel(!preserveFocus);
|
||||
if (terminalInstance.target === TerminalLocation.Editor) {
|
||||
this._terminalEditorService.revealActiveEditor(preserveFocus);
|
||||
} else {
|
||||
this._terminalGroupService.showPanel(!preserveFocus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public $hide(id: TerminalIdentifier): void {
|
||||
const rendererId = this._getTerminalId(id);
|
||||
const instance = this._terminalService.getActiveInstance();
|
||||
if (instance && instance.instanceId === rendererId) {
|
||||
this._terminalService.hidePanel();
|
||||
public async $hide(id: ExtHostTerminalIdentifier): Promise<void> {
|
||||
const instanceToHide = await this._getTerminalInstance(id);
|
||||
const activeInstance = this._terminalService.activeInstance;
|
||||
if (activeInstance && activeInstance.instanceId === instanceToHide?.instanceId && activeInstance.target !== TerminalLocation.Editor) {
|
||||
this._terminalGroupService.hidePanel();
|
||||
}
|
||||
}
|
||||
|
||||
public $dispose(id: TerminalIdentifier): void {
|
||||
this._getTerminalInstance(id)?.dispose();
|
||||
public async $dispose(id: ExtHostTerminalIdentifier): Promise<void> {
|
||||
(await this._getTerminalInstance(id))?.dispose();
|
||||
}
|
||||
|
||||
public $sendText(id: TerminalIdentifier, text: string, addNewLine: boolean): void {
|
||||
this._getTerminalInstance(id)?.sendText(text, addNewLine);
|
||||
public async $sendText(id: ExtHostTerminalIdentifier, text: string, addNewLine: boolean): Promise<void> {
|
||||
const instance = await this._getTerminalInstance(id);
|
||||
await instance?.sendText(text, addNewLine);
|
||||
}
|
||||
|
||||
public $startSendingDataEvents(): void {
|
||||
@@ -186,7 +192,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
this._onTerminalData(id, data);
|
||||
});
|
||||
// Send initial events if they exist
|
||||
this._terminalService.terminalInstances.forEach(t => {
|
||||
this._terminalService.instances.forEach(t => {
|
||||
t.initialDataEvents?.forEach(d => this._onTerminalData(t.instanceId, d));
|
||||
});
|
||||
}
|
||||
@@ -211,10 +217,12 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
this._terminalService.registerProcessSupport(isSupported);
|
||||
}
|
||||
|
||||
public $registerProfileProvider(id: string): void {
|
||||
public $registerProfileProvider(id: string, extensionIdentifier: string): void {
|
||||
// Proxy profile provider requests through the extension host
|
||||
this._profileProviders.set(id, this._terminalService.registerTerminalProfileProvider(id, {
|
||||
createContributedTerminalProfile: async (isSplitTerminal) => this._proxy.$createContributedProfileTerminal(id, isSplitTerminal)
|
||||
this._profileProviders.set(id, this._terminalService.registerTerminalProfileProvider(extensionIdentifier, id, {
|
||||
createContributedTerminalProfile: async (options) => {
|
||||
return this._proxy.$createContributedProfileTerminal(id, options);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -267,7 +275,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
this._proxy.$acceptTerminalMaximumDimensions(instance.instanceId, instance.maxCols, instance.maxRows);
|
||||
}
|
||||
|
||||
|
||||
private _onRequestStartExtensionTerminal(request: IStartExtensionTerminalRequest): void {
|
||||
const proxy = request.proxy;
|
||||
this._terminalProcessProxies.set(proxy.instanceId, proxy);
|
||||
@@ -380,9 +387,9 @@ class TerminalDataEventTracker extends Disposable {
|
||||
|
||||
this._register(this._bufferer = new TerminalDataBufferer(this._callback));
|
||||
|
||||
this._terminalService.terminalInstances.forEach(instance => this._registerInstance(instance));
|
||||
this._register(this._terminalService.onInstanceCreated(instance => this._registerInstance(instance)));
|
||||
this._register(this._terminalService.onInstanceDisposed(instance => this._bufferer.stopBuffering(instance.instanceId)));
|
||||
this._terminalService.instances.forEach(instance => this._registerInstance(instance));
|
||||
this._register(this._terminalService.onDidCreateInstance(instance => this._registerInstance(instance)));
|
||||
this._register(this._terminalService.onDidDisposeInstance(instance => this._bufferer.stopBuffering(instance.instanceId)));
|
||||
}
|
||||
|
||||
private _registerInstance(instance: ITerminalInstance): void {
|
||||
|
||||
@@ -5,17 +5,19 @@
|
||||
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore, IDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isDefined } from 'vs/base/common/types';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { TestResultState } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ExtensionRunTestsRequest, getTestSubscriptionKey, ITestItem, ITestMessage, ITestRunTask, RunTestsRequest, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { MutableObservableValue } from 'vs/workbench/contrib/testing/common/observableValue';
|
||||
import { ExtensionRunTestsRequest, ITestItem, ITestMessage, ITestRunProfile, ITestRunTask, ResolvedTestRunRequest, TestDiffOpType, TestResultState, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { TestCoverage } from 'vs/workbench/contrib/testing/common/testCoverage';
|
||||
import { LiveTestResult } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
import { ITestRootProvider, ITestService } from 'vs/workbench/contrib/testing/common/testService';
|
||||
import { ExtHostContext, ExtHostTestingResource, ExtHostTestingShape, IExtHostContext, MainContext, MainThreadTestingShape } from '../common/extHost.protocol';
|
||||
import { IMainThreadTestController, ITestRootProvider, ITestService } from 'vs/workbench/contrib/testing/common/testService';
|
||||
import { ExtHostContext, ExtHostTestingShape, IExtHostContext, ILocationDto, MainContext, MainThreadTestingShape } from '../common/extHost.protocol';
|
||||
|
||||
const reviveDiff = (diff: TestsDiff) => {
|
||||
for (const entry of diff) {
|
||||
@@ -34,24 +36,31 @@ const reviveDiff = (diff: TestsDiff) => {
|
||||
@extHostNamedCustomer(MainContext.MainThreadTesting)
|
||||
export class MainThreadTesting extends Disposable implements MainThreadTestingShape, ITestRootProvider {
|
||||
private readonly proxy: ExtHostTestingShape;
|
||||
private readonly testSubscriptions = new Map<string, IDisposable>();
|
||||
private readonly testProviderRegistrations = new Map<string, IDisposable>();
|
||||
private readonly diffListener = this._register(new MutableDisposable());
|
||||
private readonly testProviderRegistrations = new Map<string, {
|
||||
instance: IMainThreadTestController;
|
||||
label: MutableObservableValue<string>;
|
||||
disposable: IDisposable
|
||||
}>();
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@ITestService private readonly testService: ITestService,
|
||||
@ITestProfileService private readonly testProfiles: ITestProfileService,
|
||||
@ITestResultService private readonly resultService: ITestResultService,
|
||||
) {
|
||||
super();
|
||||
this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostTesting);
|
||||
this._register(this.testService.onShouldSubscribe(args => this.proxy.$subscribeToTests(args.resource, args.uri)));
|
||||
this._register(this.testService.onShouldUnsubscribe(args => this.proxy.$unsubscribeFromTests(args.resource, args.uri)));
|
||||
|
||||
const prevResults = resultService.results.map(r => r.toJSON()).filter(isDefined);
|
||||
if (prevResults.length) {
|
||||
this.proxy.$publishTestResults(prevResults);
|
||||
}
|
||||
|
||||
this._register(this.testService.onDidCancelTestRun(({ runId }) => {
|
||||
this.proxy.$cancelExtensionTestRun(runId);
|
||||
}));
|
||||
|
||||
this._register(resultService.onResultsChanged(evt => {
|
||||
const results = 'completed' in evt ? evt.completed : ('inserted' in evt ? evt.inserted : undefined);
|
||||
const serialized = results?.toJSON();
|
||||
@@ -59,18 +68,36 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh
|
||||
this.proxy.$publishTestResults([serialized]);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
this._register(testService.registerRootProvider(this));
|
||||
|
||||
for (const { resource, uri } of this.testService.subscriptions) {
|
||||
this.proxy.$subscribeToTests(resource, uri);
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
$publishTestRunProfile(profile: ITestRunProfile): void {
|
||||
const controller = this.testProviderRegistrations.get(profile.controllerId);
|
||||
if (controller) {
|
||||
this.testProfiles.addProfile(controller.instance, profile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
$addTestsToRun(runId: string, tests: ITestItem[]): void {
|
||||
$updateTestRunConfig(controllerId: string, profileId: number, update: Partial<ITestRunProfile>): void {
|
||||
this.testProfiles.updateProfile(controllerId, profileId, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
$removeTestProfile(controllerId: string, profileId: number): void {
|
||||
this.testProfiles.removeProfile(controllerId, profileId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
$addTestsToRun(controllerId: string, runId: string, tests: ITestItem[]): void {
|
||||
for (const test of tests) {
|
||||
test.uri = URI.revive(test.uri);
|
||||
if (test.range) {
|
||||
@@ -78,7 +105,24 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh
|
||||
}
|
||||
}
|
||||
|
||||
this.withLiveRun(runId, r => r.addTestChainToRun(tests));
|
||||
this.withLiveRun(runId, r => r.addTestChainToRun(controllerId, tests));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
$signalCoverageAvailable(runId: string, taskId: string): void {
|
||||
this.withLiveRun(runId, run => {
|
||||
const task = run.tasks.find(t => t.id === taskId);
|
||||
if (!task) {
|
||||
return;
|
||||
}
|
||||
|
||||
(task.coverage as MutableObservableValue<TestCoverage>).value = new TestCoverage({
|
||||
provideFileCoverage: token => this.proxy.$provideFileCoverage(runId, taskId, token),
|
||||
resolveFileCoverage: (i, token) => this.proxy.$resolveFileCoverage(runId, taskId, i, token),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,85 +163,110 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $appendOutputToRun(runId: string, _taskId: string, output: VSBuffer): void {
|
||||
this.withLiveRun(runId, r => r.output.append(output));
|
||||
public $appendOutputToRun(runId: string, taskId: string, output: VSBuffer, locationDto?: ILocationDto, testId?: string): void {
|
||||
const location = locationDto && {
|
||||
uri: URI.revive(locationDto.uri),
|
||||
range: Range.lift(locationDto.range)
|
||||
};
|
||||
|
||||
this.withLiveRun(runId, r => r.appendOutput(output, taskId, location, testId));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $appendTestMessageInRun(runId: string, taskId: string, testId: string, message: ITestMessage): void {
|
||||
public $appendTestMessagesInRun(runId: string, taskId: string, testId: string, messages: ITestMessage[]): void {
|
||||
const r = this.resultService.getResult(runId);
|
||||
if (r && r instanceof LiveTestResult) {
|
||||
if (message.location) {
|
||||
message.location.uri = URI.revive(message.location.uri);
|
||||
message.location.range = Range.lift(message.location.range);
|
||||
}
|
||||
for (const message of messages) {
|
||||
if (message.location) {
|
||||
message.location.uri = URI.revive(message.location.uri);
|
||||
message.location.range = Range.lift(message.location.range);
|
||||
}
|
||||
|
||||
r.appendMessage(testId, taskId, message);
|
||||
r.appendMessage(testId, taskId, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $registerTestController(id: string) {
|
||||
const disposable = this.testService.registerTestController(id, {
|
||||
runTests: (req, token) => this.proxy.$runTestsForProvider(req, token),
|
||||
lookupTest: test => this.proxy.$lookupTest(test),
|
||||
expandTest: (src, levels) => this.proxy.$expandTest(src, isFinite(levels) ? levels : -1),
|
||||
public $registerTestController(controllerId: string, labelStr: string) {
|
||||
const disposable = new DisposableStore();
|
||||
const label = new MutableObservableValue(labelStr);
|
||||
const controller: IMainThreadTestController = {
|
||||
id: controllerId,
|
||||
label,
|
||||
configureRunProfile: id => this.proxy.$configureRunProfile(controllerId, id),
|
||||
runTests: (req, token) => this.proxy.$runControllerTests(req, token),
|
||||
expandTest: (testId, levels) => this.proxy.$expandTest(testId, isFinite(levels) ? levels : -1),
|
||||
};
|
||||
|
||||
|
||||
disposable.add(toDisposable(() => this.testProfiles.removeProfile(controllerId)));
|
||||
disposable.add(this.testService.registerTestController(controllerId, controller));
|
||||
|
||||
this.testProviderRegistrations.set(controllerId, {
|
||||
instance: controller,
|
||||
label,
|
||||
disposable
|
||||
});
|
||||
|
||||
this.testProviderRegistrations.set(id, disposable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $unregisterTestController(id: string) {
|
||||
this.testProviderRegistrations.get(id)?.dispose();
|
||||
this.testProviderRegistrations.delete(id);
|
||||
public $updateControllerLabel(controllerId: string, label: string) {
|
||||
const controller = this.testProviderRegistrations.get(controllerId);
|
||||
if (controller) {
|
||||
controller.label.value = label;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $subscribeToDiffs(resource: ExtHostTestingResource, uriComponents: UriComponents): void {
|
||||
const uri = URI.revive(uriComponents);
|
||||
const disposable = this.testService.subscribeToDiffs(resource, uri,
|
||||
diff => this.proxy.$acceptDiff(resource, uriComponents, diff));
|
||||
this.testSubscriptions.set(getTestSubscriptionKey(resource, uri), disposable);
|
||||
public $unregisterTestController(controllerId: string) {
|
||||
this.testProviderRegistrations.get(controllerId)?.disposable.dispose();
|
||||
this.testProviderRegistrations.delete(controllerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $unsubscribeFromDiffs(resource: ExtHostTestingResource, uriComponents: UriComponents): void {
|
||||
const key = getTestSubscriptionKey(resource, URI.revive(uriComponents));
|
||||
this.testSubscriptions.get(key)?.dispose();
|
||||
this.testSubscriptions.delete(key);
|
||||
public $subscribeToDiffs(): void {
|
||||
this.proxy.$acceptDiff(this.testService.collection.getReviverDiff());
|
||||
this.diffListener.value = this.testService.onDidProcessDiff(this.proxy.$acceptDiff, this.proxy);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $publishDiff(resource: ExtHostTestingResource, uri: UriComponents, diff: TestsDiff): void {
|
||||
public $unsubscribeFromDiffs(): void {
|
||||
this.diffListener.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $publishDiff(controllerId: string, diff: TestsDiff): void {
|
||||
reviveDiff(diff);
|
||||
this.testService.publishDiff(resource, URI.revive(uri), diff);
|
||||
this.testService.publishDiff(controllerId, diff);
|
||||
}
|
||||
|
||||
public async $runTests(req: RunTestsRequest, token: CancellationToken): Promise<string> {
|
||||
const result = await this.testService.runTests(req, token);
|
||||
public async $runTests(req: ResolvedTestRunRequest, token: CancellationToken): Promise<string> {
|
||||
const result = await this.testService.runResolvedTests(req, token);
|
||||
return result.id;
|
||||
}
|
||||
|
||||
public override dispose() {
|
||||
super.dispose();
|
||||
for (const subscription of this.testSubscriptions.values()) {
|
||||
subscription.dispose();
|
||||
for (const subscription of this.testProviderRegistrations.values()) {
|
||||
subscription.disposable.dispose();
|
||||
}
|
||||
this.testSubscriptions.clear();
|
||||
this.testProviderRegistrations.clear();
|
||||
}
|
||||
|
||||
private withLiveRun<T>(runId: string, fn: (run: LiveTestResult) => T): T | undefined {
|
||||
|
||||
@@ -13,7 +13,7 @@ import { isUndefinedOrNull, isNumber } from 'vs/base/common/types';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IConnectionTreeService } from 'sql/workbench/services/connection/common/connectionTreeService';
|
||||
import { IConnectionTreeService } from 'sql/workbench/services/connection/common/connectionTreeService'; // {{SQL CARBON EDIT}} Add our tree service
|
||||
import { TreeDataTransferConverter } from 'vs/workbench/api/common/shared/treeDataTransfer';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTreeViews)
|
||||
@@ -198,14 +198,14 @@ export class TreeViewDataProvider implements ITreeViewDataProvider {
|
||||
this.hasResolve = this._proxy.$hasResolve(this.treeViewId);
|
||||
}
|
||||
|
||||
getChildren(treeItem?: ITreeItem): Promise<ITreeItem[]> {
|
||||
return Promise.resolve(this._proxy.$getChildren(this.treeViewId, treeItem ? treeItem.handle : undefined)
|
||||
getChildren(treeItem?: ITreeItem): Promise<ITreeItem[] | undefined> {
|
||||
return this._proxy.$getChildren(this.treeViewId, treeItem ? treeItem.handle : undefined)
|
||||
.then(
|
||||
children => this.postGetChildren(children),
|
||||
err => {
|
||||
this.notificationService.error(err);
|
||||
return [];
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
getItemsToRefresh(itemsToRefreshByHandle: { [treeItemHandle: string]: ITreeItem }): ITreeItem[] {
|
||||
@@ -242,8 +242,11 @@ export class TreeViewDataProvider implements ITreeViewDataProvider {
|
||||
return this.itemsMap.size === 0;
|
||||
}
|
||||
|
||||
protected async postGetChildren(elements: ITreeItem[]): Promise<ITreeItem[]> { // {{SQL CARBON EDIT}} For use by Component Tree View
|
||||
const result: ITreeItem[] = []; // {{SQL CARBON EDIT}}
|
||||
protected async postGetChildren(elements: ITreeItem[] | undefined): Promise<ITreeItem[] | undefined> { // {{SQL CARBON EDIT}} For use by Component Tree View
|
||||
if (elements === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const result: ITreeItem[] = []; // {{SQL CARBON EDIT}} We don't always return ResolvableTreeItems
|
||||
const hasResolve = await this.hasResolve;
|
||||
if (elements) {
|
||||
for (const element of elements) {
|
||||
|
||||
@@ -7,8 +7,8 @@ import * as nls from 'vs/nls';
|
||||
import { MainThreadTunnelServiceShape, IExtHostContext, MainContext, ExtHostContext, ExtHostTunnelServiceShape, CandidatePortSource, PortAttributesProviderSelector } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { CandidatePort, IRemoteExplorerService, makeAddress, PORT_AUTO_FORWARD_SETTING, PORT_AUTO_SOURCE_SETTING, PORT_AUTO_SOURCE_SETTING_OUTPUT, PORT_AUTO_SOURCE_SETTING_PROCESS } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import { ITunnelProvider, ITunnelService, TunnelCreationOptions, TunnelProviderFeatures, TunnelOptions, RemoteTunnel, isPortPrivileged, ProvidedPortAttributes, PortAttributesProvider } from 'vs/platform/remote/common/tunnel';
|
||||
import { CandidatePort, IRemoteExplorerService, makeAddress, PORT_AUTO_FORWARD_SETTING, PORT_AUTO_SOURCE_SETTING, PORT_AUTO_SOURCE_SETTING_OUTPUT, PORT_AUTO_SOURCE_SETTING_PROCESS, TunnelSource } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import { ITunnelProvider, ITunnelService, TunnelCreationOptions, TunnelProviderFeatures, TunnelOptions, RemoteTunnel, isPortPrivileged, ProvidedPortAttributes, PortAttributesProvider, TunnelProtocol } from 'vs/platform/remote/common/tunnel';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import type { TunnelDescription } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
@@ -57,6 +57,9 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun
|
||||
return this._proxy.$registerCandidateFinder(this.processFindingEnabled());
|
||||
}
|
||||
}));
|
||||
this._register(this.tunnelService.onAddedTunnelProvider(() => {
|
||||
return this._proxy.$registerCandidateFinder(this.processFindingEnabled());
|
||||
}));
|
||||
}
|
||||
|
||||
private _alreadyRegistered: boolean = false;
|
||||
@@ -94,7 +97,16 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun
|
||||
}
|
||||
|
||||
async $openTunnel(tunnelOptions: TunnelOptions, source: string): Promise<TunnelDto | undefined> {
|
||||
const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remoteAddress, tunnelOptions.localAddressPort, tunnelOptions.label, source, false);
|
||||
const tunnel = await this.remoteExplorerService.forward({
|
||||
remote: tunnelOptions.remoteAddress,
|
||||
local: tunnelOptions.localAddressPort,
|
||||
name: tunnelOptions.label,
|
||||
source: {
|
||||
source: TunnelSource.Extension,
|
||||
description: source
|
||||
},
|
||||
elevateIfNeeded: false
|
||||
});
|
||||
if (tunnel) {
|
||||
if (!this.elevateionRetry
|
||||
&& (tunnelOptions.localAddressPort !== undefined)
|
||||
@@ -118,7 +130,16 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun
|
||||
run: async () => {
|
||||
this.elevateionRetry = true;
|
||||
await this.remoteExplorerService.close({ host: tunnel.tunnelRemoteHost, port: tunnel.tunnelRemotePort });
|
||||
await this.remoteExplorerService.forward(tunnelOptions.remoteAddress, tunnelOptions.localAddressPort, tunnelOptions.label, source, true);
|
||||
await this.remoteExplorerService.forward({
|
||||
remote: tunnelOptions.remoteAddress,
|
||||
local: tunnelOptions.localAddressPort,
|
||||
name: tunnelOptions.label,
|
||||
source: {
|
||||
source: TunnelSource.Extension,
|
||||
description: source
|
||||
},
|
||||
elevateIfNeeded: true
|
||||
});
|
||||
this.elevateionRetry = false;
|
||||
}
|
||||
}]);
|
||||
@@ -156,6 +177,7 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun
|
||||
localAddress: typeof tunnel.localAddress === 'string' ? tunnel.localAddress : makeAddress(tunnel.localAddress.host, tunnel.localAddress.port),
|
||||
tunnelLocalPort: typeof tunnel.localAddress !== 'string' ? tunnel.localAddress.port : undefined,
|
||||
public: tunnel.public,
|
||||
protocol: tunnel.protocol ?? TunnelProtocol.Http,
|
||||
dispose: async (silent?: boolean) => {
|
||||
this.logService.trace(`ForwardedPorts: (MainThreadTunnelService) Closing tunnel from tunnel provider: ${tunnel?.remoteAddress.host}:${tunnel?.remoteAddress.port}`);
|
||||
return this._proxy.$closeTunnel({ host: tunnel.remoteAddress.host, port: tunnel.remoteAddress.port }, silent);
|
||||
|
||||
@@ -9,7 +9,8 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { MainThreadWebviews, reviveWebviewContentOptions, reviveWebviewExtension } from 'vs/workbench/api/browser/mainThreadWebviews';
|
||||
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { EditorGroupColumn, editorGroupToViewColumn, IEditorInput, viewColumnToEditorGroup } from 'vs/workbench/common/editor';
|
||||
import { IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { EditorGroupColumn, columnToEditorGroup, editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import { WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
|
||||
@@ -161,7 +162,7 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
|
||||
const mainThreadShowOptions: ICreateWebViewShowOptions = Object.create(null);
|
||||
if (showOptions) {
|
||||
mainThreadShowOptions.preserveFocus = !!showOptions.preserveFocus;
|
||||
mainThreadShowOptions.group = viewColumnToEditorGroup(this._editorGroupService, showOptions.viewColumn);
|
||||
mainThreadShowOptions.group = columnToEditorGroup(this._editorGroupService, showOptions.viewColumn);
|
||||
}
|
||||
|
||||
const extension = reviveWebviewExtension(extensionData);
|
||||
@@ -171,10 +172,14 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
|
||||
|
||||
/* __GDPR__
|
||||
"webviews:createWebviewPanel" : {
|
||||
"extensionId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
"extensionId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"viewType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this._telemetryService.publicLog('webviews:createWebviewPanel', { extensionId: extension.id.value });
|
||||
this._telemetryService.publicLog('webviews:createWebviewPanel', {
|
||||
extensionId: extension.id.value,
|
||||
viewType
|
||||
});
|
||||
}
|
||||
|
||||
public $disposeWebview(handle: extHostProtocol.WebviewHandle): void {
|
||||
@@ -198,7 +203,7 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
|
||||
return;
|
||||
}
|
||||
|
||||
const targetGroup = this._editorGroupService.getGroup(viewColumnToEditorGroup(this._editorGroupService, showOptions.viewColumn)) || this._editorGroupService.getGroup(webview.group || 0);
|
||||
const targetGroup = this._editorGroupService.getGroup(columnToEditorGroup(this._editorGroupService, showOptions.viewColumn)) || this._editorGroupService.getGroup(webview.group || 0);
|
||||
if (targetGroup) {
|
||||
this._webviewWorkbenchService.revealWebview(webview, targetGroup, !!showOptions.preserveFocus);
|
||||
}
|
||||
@@ -239,7 +244,7 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
|
||||
state,
|
||||
panelOptions: webviewInput.webview.options,
|
||||
webviewOptions: webviewInput.webview.contentOptions,
|
||||
}, editorGroupToViewColumn(this._editorGroupService, webviewInput.group || 0));
|
||||
}, editorGroupToColumn(this._editorGroupService, webviewInput.group || 0));
|
||||
} catch (error) {
|
||||
onUnexpectedError(error);
|
||||
webviewInput.webview.html = this._mainThreadWebviews.getWebviewResolvedFailedContent(viewType);
|
||||
@@ -277,7 +282,7 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
|
||||
viewStates[handle] = {
|
||||
visible: topLevelInput === group.activeEditor,
|
||||
active: editorInput === activeEditorInput,
|
||||
position: editorGroupToViewColumn(this._editorGroupService, group.id),
|
||||
position: editorGroupToColumn(this._editorGroupService, group.id),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -214,7 +214,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
|
||||
}
|
||||
|
||||
private isWorkspaceTrusted(): boolean {
|
||||
return this._workspaceTrustManagementService.isWorkpaceTrusted();
|
||||
return this._workspaceTrustManagementService.isWorkspaceTrusted();
|
||||
}
|
||||
|
||||
private _onDidGrantWorkspaceTrust(): void {
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { CommandsRegistry, ICommandService, ICommandHandler } from 'vs/platform/commands/common/commands';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IViewDescriptorService, IViewsService, ViewVisibilityState } from 'vs/workbench/common/views';
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// The following commands are registered on both sides separately.
|
||||
//
|
||||
// We are trying to maintain backwards compatibility for cases where
|
||||
// API commands are encoded as markdown links, for example.
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
export interface ICommandsExecutor {
|
||||
executeCommand<T>(id: string, ...args: any[]): Promise<T | undefined>;
|
||||
}
|
||||
|
||||
function adjustHandler(handler: (executor: ICommandsExecutor, ...args: any[]) => any): ICommandHandler {
|
||||
return (accessor, ...args: any[]) => {
|
||||
return handler(accessor.get(ICommandService), ...args);
|
||||
};
|
||||
}
|
||||
|
||||
CommandsRegistry.registerCommand('_extensionTests.setLogLevel', function (accessor: ServicesAccessor, level: number) {
|
||||
const logService = accessor.get(ILogService);
|
||||
const environmentService = accessor.get(IEnvironmentService);
|
||||
|
||||
if (environmentService.isExtensionDevelopment && !!environmentService.extensionTestsLocationURI) {
|
||||
logService.setLevel(level);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
CommandsRegistry.registerCommand('_extensionTests.getLogLevel', function (accessor: ServicesAccessor) {
|
||||
const logService = accessor.get(ILogService);
|
||||
|
||||
return logService.getLevel();
|
||||
});
|
||||
|
||||
|
||||
CommandsRegistry.registerCommand('_workbench.action.moveViews', async function (accessor: ServicesAccessor, options: { viewIds: string[], destinationId: string }) {
|
||||
const viewDescriptorService = accessor.get(IViewDescriptorService);
|
||||
|
||||
const destination = viewDescriptorService.getViewContainerById(options.destinationId);
|
||||
if (!destination) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FYI, don't use `moveViewsToContainer` in 1 shot, because it expects all views to have the same current location
|
||||
for (const viewId of options.viewIds) {
|
||||
const viewDescriptor = viewDescriptorService.getViewDescriptorById(viewId);
|
||||
if (viewDescriptor?.canMoveView) {
|
||||
viewDescriptorService.moveViewsToContainer([viewDescriptor], destination, ViewVisibilityState.Default);
|
||||
}
|
||||
}
|
||||
|
||||
await accessor.get(IViewsService).openViewContainer(destination.id, true);
|
||||
});
|
||||
|
||||
export class MoveViewsAPICommand {
|
||||
public static readonly ID = 'vscode.moveViews';
|
||||
public static execute(executor: ICommandsExecutor, options: { viewIds: string[], destinationId: string }): Promise<any> {
|
||||
if (!Array.isArray(options?.viewIds) || typeof options?.destinationId !== 'string') {
|
||||
return Promise.reject('Invalid arguments');
|
||||
}
|
||||
|
||||
return executor.executeCommand('_workbench.action.moveViews', options);
|
||||
}
|
||||
}
|
||||
CommandsRegistry.registerCommand({
|
||||
id: MoveViewsAPICommand.ID,
|
||||
handler: adjustHandler(MoveViewsAPICommand.execute),
|
||||
description: {
|
||||
description: 'Move Views',
|
||||
args: []
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// The following commands are registered on the renderer but as API
|
||||
// command. DO NOT USE this unless you have understood what this
|
||||
// means
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
|
||||
class OpenAPICommand {
|
||||
public static readonly ID = 'vscode.open';
|
||||
public static execute(executor: ICommandsExecutor, resource: URI): Promise<any> {
|
||||
|
||||
return executor.executeCommand('_workbench.open', resource);
|
||||
}
|
||||
}
|
||||
CommandsRegistry.registerCommand(OpenAPICommand.ID, adjustHandler(OpenAPICommand.execute));
|
||||
|
||||
class DiffAPICommand {
|
||||
public static readonly ID = 'vscode.diff';
|
||||
public static execute(executor: ICommandsExecutor, left: URI, right: URI, label: string, options?: typeConverters.TextEditorOpenOptions): Promise<any> {
|
||||
return executor.executeCommand('_workbench.diff', [
|
||||
left, right,
|
||||
label,
|
||||
]);
|
||||
}
|
||||
}
|
||||
CommandsRegistry.registerCommand(DiffAPICommand.ID, adjustHandler(DiffAPICommand.execute));
|
||||
@@ -34,7 +34,10 @@ const configurationEntrySchema: IJSONSchema = {
|
||||
},
|
||||
additionalProperties: {
|
||||
anyOf: [
|
||||
{ $ref: 'http://json-schema.org/draft-07/schema#' },
|
||||
{
|
||||
title: nls.localize('vscode.extension.contributes.configuration.properties.schema', 'Schema of the configuration property.'),
|
||||
$ref: 'http://json-schema.org/draft-07/schema#'
|
||||
},
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -81,6 +84,16 @@ const configurationEntrySchema: IJSONSchema = {
|
||||
markdownDeprecationMessage: {
|
||||
type: 'string',
|
||||
description: nls.localize('scope.markdownDeprecationMessage', 'If set, the property is marked as deprecated and the given message is shown as an explanation in the markdown format.')
|
||||
},
|
||||
editPresentation: {
|
||||
type: 'string',
|
||||
enum: ['singlelineText', 'multilineText'],
|
||||
enumDescriptions: [
|
||||
nls.localize('scope.singlelineText.description', 'The value will be shown in an inputbox.'),
|
||||
nls.localize('scope.multilineText.description', 'The value will be shown in a textarea.')
|
||||
],
|
||||
default: 'singlelineText',
|
||||
description: nls.localize('scope.editPresentation', 'When specified, controls the presentation format of the string setting.')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,6 +172,8 @@ configurationExtPoint.setHandler((extensions, { added, removed }) => {
|
||||
configurationRegistry.deregisterConfigurations(removedConfigurations);
|
||||
}
|
||||
|
||||
const seenProperties = new Set<string>();
|
||||
|
||||
function handleConfiguration(node: IConfigurationNode, extension: IExtensionPointUser<any>): IConfigurationNode[] {
|
||||
const configurations: IConfigurationNode[] = [];
|
||||
let configuration = objects.deepClone(node);
|
||||
@@ -176,6 +191,60 @@ configurationExtPoint.setHandler((extensions, { added, removed }) => {
|
||||
return configurations;
|
||||
}
|
||||
|
||||
function validateProperties(configuration: IConfigurationNode, extension: IExtensionPointUser<any>): void {
|
||||
let properties = configuration.properties;
|
||||
if (properties) {
|
||||
if (typeof properties !== 'object') {
|
||||
extension.collector.error(nls.localize('invalid.properties', "'configuration.properties' must be an object"));
|
||||
configuration.properties = {};
|
||||
}
|
||||
for (let key in properties) {
|
||||
const message = validateProperty(key);
|
||||
if (message) {
|
||||
delete properties[key];
|
||||
extension.collector.warn(message);
|
||||
continue;
|
||||
}
|
||||
if (seenProperties.has(key)) {
|
||||
delete properties[key];
|
||||
extension.collector.warn(nls.localize('config.property.duplicate', "Cannot register '{0}'. This property is already registered.", key));
|
||||
continue;
|
||||
}
|
||||
const propertyConfiguration = properties[key];
|
||||
if (!isObject(propertyConfiguration)) {
|
||||
delete properties[key];
|
||||
extension.collector.error(nls.localize('invalid.property', "configuration.properties property '{0}' must be an object", key));
|
||||
continue;
|
||||
}
|
||||
seenProperties.add(key);
|
||||
if (propertyConfiguration.scope) {
|
||||
if (propertyConfiguration.scope.toString() === 'application') {
|
||||
propertyConfiguration.scope = ConfigurationScope.APPLICATION;
|
||||
} else if (propertyConfiguration.scope.toString() === 'machine') {
|
||||
propertyConfiguration.scope = ConfigurationScope.MACHINE;
|
||||
} else if (propertyConfiguration.scope.toString() === 'resource') {
|
||||
propertyConfiguration.scope = ConfigurationScope.RESOURCE;
|
||||
} else if (propertyConfiguration.scope.toString() === 'machine-overridable') {
|
||||
propertyConfiguration.scope = ConfigurationScope.MACHINE_OVERRIDABLE;
|
||||
} else if (propertyConfiguration.scope.toString() === 'language-overridable') {
|
||||
propertyConfiguration.scope = ConfigurationScope.LANGUAGE_OVERRIDABLE;
|
||||
} else {
|
||||
propertyConfiguration.scope = ConfigurationScope.WINDOW;
|
||||
}
|
||||
} else {
|
||||
propertyConfiguration.scope = ConfigurationScope.WINDOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
let subNodes = configuration.allOf;
|
||||
if (subNodes) {
|
||||
extension.collector.error(nls.localize('invalid.allOf', "'configuration.allOf' is deprecated and should no longer be used. Instead, pass multiple configuration sections as an array to the 'configuration' contribution point."));
|
||||
for (let node of subNodes) {
|
||||
validateProperties(node, extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (added.length) {
|
||||
const addedConfigurations: IConfigurationNode[] = [];
|
||||
for (let extension of added) {
|
||||
@@ -196,54 +265,6 @@ configurationExtPoint.setHandler((extensions, { added, removed }) => {
|
||||
});
|
||||
// END VSCode extension point `configuration`
|
||||
|
||||
function validateProperties(configuration: IConfigurationNode, extension: IExtensionPointUser<any>): void {
|
||||
let properties = configuration.properties;
|
||||
if (properties) {
|
||||
if (typeof properties !== 'object') {
|
||||
extension.collector.error(nls.localize('invalid.properties', "'configuration.properties' must be an object"));
|
||||
configuration.properties = {};
|
||||
}
|
||||
for (let key in properties) {
|
||||
const message = validateProperty(key);
|
||||
if (message) {
|
||||
delete properties[key];
|
||||
extension.collector.warn(message);
|
||||
continue;
|
||||
}
|
||||
const propertyConfiguration = properties[key];
|
||||
if (!isObject(propertyConfiguration)) {
|
||||
delete properties[key];
|
||||
extension.collector.error(nls.localize('invalid.property', "configuration.properties property '{0}' must be an object", key));
|
||||
continue;
|
||||
}
|
||||
if (propertyConfiguration.scope) {
|
||||
if (propertyConfiguration.scope.toString() === 'application') {
|
||||
propertyConfiguration.scope = ConfigurationScope.APPLICATION;
|
||||
} else if (propertyConfiguration.scope.toString() === 'machine') {
|
||||
propertyConfiguration.scope = ConfigurationScope.MACHINE;
|
||||
} else if (propertyConfiguration.scope.toString() === 'resource') {
|
||||
propertyConfiguration.scope = ConfigurationScope.RESOURCE;
|
||||
} else if (propertyConfiguration.scope.toString() === 'machine-overridable') {
|
||||
propertyConfiguration.scope = ConfigurationScope.MACHINE_OVERRIDABLE;
|
||||
} else if (propertyConfiguration.scope.toString() === 'language-overridable') {
|
||||
propertyConfiguration.scope = ConfigurationScope.LANGUAGE_OVERRIDABLE;
|
||||
} else {
|
||||
propertyConfiguration.scope = ConfigurationScope.WINDOW;
|
||||
}
|
||||
} else {
|
||||
propertyConfiguration.scope = ConfigurationScope.WINDOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
let subNodes = configuration.allOf;
|
||||
if (subNodes) {
|
||||
extension.collector.error(nls.localize('invalid.allOf', "'configuration.allOf' is deprecated and should no longer be used. Instead, pass multiple configuration sections as an array to the 'configuration' contribution point."));
|
||||
for (let node of subNodes) {
|
||||
validateProperties(node, extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
|
||||
jsonRegistry.registerSchema('vscode://schemas/workspaceConfig', {
|
||||
allowComments: true,
|
||||
@@ -321,6 +342,11 @@ jsonRegistry.registerSchema('vscode://schemas/workspaceConfig', {
|
||||
type: 'string',
|
||||
doNotSuggest: true,
|
||||
description: nls.localize('workspaceConfig.remoteAuthority', "The remote server where the workspace is located."),
|
||||
},
|
||||
'transient': {
|
||||
type: 'boolean',
|
||||
doNotSuggest: true,
|
||||
description: nls.localize('workspaceConfig.transient', "A transient workspace will disappear when restarting or reloading."),
|
||||
}
|
||||
},
|
||||
errorMessage: nls.localize('unknownWorkspaceProperty', "Unknown workspace configuration property")
|
||||
|
||||
@@ -17,7 +17,7 @@ import { ExtHostContext, MainContext, ExtHostLogServiceShape, UIKind, CandidateP
|
||||
import { ExtHostApiCommands } from 'vs/workbench/api/common/extHostApiCommands';
|
||||
import { ExtHostClipboard } from 'vs/workbench/api/common/extHostClipboard';
|
||||
import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtHostComments } from 'vs/workbench/api/common/extHostComments';
|
||||
import { createExtHostComments } from 'vs/workbench/api/common/extHostComments';
|
||||
import { ExtHostConfigProvider, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ExtHostDiagnostics } from 'vs/workbench/api/common/extHostDiagnostics';
|
||||
import { ExtHostDialogs } from 'vs/workbench/api/common/extHostDialogs';
|
||||
@@ -90,6 +90,7 @@ import { Schemas } from 'vs/base/common/network';
|
||||
import { matchesScheme } from 'vs/platform/opener/common/opener';
|
||||
// import { ExtHostNotebookEditors } from 'vs/workbench/api/common/extHostNotebookEditors'; {{SQL CARBON EDIT}} Disable VS Code notebooks
|
||||
// import { ExtHostNotebookDocuments } from 'vs/workbench/api/common/extHostNotebookDocuments'; {{SQL CARBON EDIT}} Disable VS Code notebooks
|
||||
// import { ExtHostInteractive } from 'vs/workbench/api/common/extHostInteractive'; {{SQL CARBON EDIT}} Remove until we need it
|
||||
import { ExtHostNotebook } from 'sql/workbench/api/common/extHostNotebook';
|
||||
import { functionalityNotSupportedError } from 'sql/base/common/locConstants';
|
||||
|
||||
@@ -165,7 +166,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService(rpcProtocol, extHostLogService, extHostDocumentsAndEditors));
|
||||
const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, createExtHostQuickOpen(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 extHostComment = rpcProtocol.set(ExtHostContext.ExtHostComments, createExtHostComments(rpcProtocol, extHostCommands, extHostDocuments));
|
||||
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
|
||||
const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHosLabelService, new ExtHostLabelService(rpcProtocol));
|
||||
const extHostTheming = rpcProtocol.set(ExtHostContext.ExtHostTheming, new ExtHostTheming(rpcProtocol));
|
||||
@@ -175,8 +176,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
const extHostWebviewPanels = rpcProtocol.set(ExtHostContext.ExtHostWebviewPanels, new ExtHostWebviewPanels(rpcProtocol, extHostWebviews, extHostWorkspace));
|
||||
const extHostCustomEditors = rpcProtocol.set(ExtHostContext.ExtHostCustomEditors, new ExtHostCustomEditors(rpcProtocol, extHostDocuments, extensionStoragePaths, extHostWebviews, extHostWebviewPanels));
|
||||
const extHostWebviewViews = rpcProtocol.set(ExtHostContext.ExtHostWebviewViews, new ExtHostWebviewViews(rpcProtocol, extHostWebviews));
|
||||
const extHostTesting = rpcProtocol.set(ExtHostContext.ExtHostTesting, new ExtHostTesting(rpcProtocol, extHostDocumentsAndEditors, extHostWorkspace));
|
||||
const extHostTesting = rpcProtocol.set(ExtHostContext.ExtHostTesting, new ExtHostTesting(rpcProtocol, extHostCommands));
|
||||
const extHostUriOpeners = rpcProtocol.set(ExtHostContext.ExtHostUriOpeners, new ExtHostUriOpeners(rpcProtocol));
|
||||
// rpcProtocol.set(ExtHostContext.ExtHostInteractive, new ExtHostInteractive(rpcProtocol, extHostNotebook, extHostDocumentsAndEditors, extHostCommands)); {{SQL CARBON EDIT}} Disable interactive stuff until we need it
|
||||
|
||||
// Check that no named customers are missing
|
||||
// {{SQL CARBON EDIT}} filter out the services we don't expose
|
||||
@@ -186,7 +188,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
ExtHostContext.ExtHostNotebookDocuments,
|
||||
ExtHostContext.ExtHostNotebookEditors,
|
||||
ExtHostContext.ExtHostNotebookKernels,
|
||||
ExtHostContext.ExtHostNotebookRenderers
|
||||
ExtHostContext.ExtHostNotebookRenderers,
|
||||
ExtHostContext.ExtHostInteractive
|
||||
]);
|
||||
const expected: ProxyIdentifier<any>[] = values(ExtHostContext).filter(v => !filteredProxies.has(v));
|
||||
|
||||
@@ -238,6 +241,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
|
||||
const authentication: typeof vscode.authentication = {
|
||||
getSession(providerId: string, scopes: readonly string[], options?: vscode.AuthenticationGetSessionOptions) {
|
||||
if (options?.forceNewSession) {
|
||||
checkProposedApiEnabled(extension);
|
||||
}
|
||||
return extHostAuthentication.getSession(extension, providerId, scopes, options as any);
|
||||
},
|
||||
get onDidChangeSessions(): Event<vscode.AuthenticationSessionsChangeEvent> {
|
||||
@@ -245,18 +251,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
},
|
||||
registerAuthenticationProvider(id: string, label: string, provider: vscode.AuthenticationProvider, options?: vscode.AuthenticationProviderOptions): vscode.Disposable {
|
||||
return extHostAuthentication.registerAuthenticationProvider(id, label, provider, options);
|
||||
},
|
||||
get onDidChangeAuthenticationProviders(): Event<vscode.AuthenticationProvidersChangeEvent> {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostAuthentication.onDidChangeAuthenticationProviders;
|
||||
},
|
||||
get providers(): ReadonlyArray<vscode.AuthenticationProviderInformation> {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostAuthentication.providers;
|
||||
},
|
||||
logout(providerId: string, sessionId: string): Thenable<void> {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostAuthentication.removeSession(providerId, sessionId);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -313,6 +307,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
get language() { return initData.environment.appLanguage; },
|
||||
get appName() { return initData.environment.appName; },
|
||||
get appRoot() { return initData.environment.appRoot?.fsPath ?? ''; },
|
||||
get embedderIdentifier() { return initData.environment.embedderIdentifier; },
|
||||
get uriScheme() { return initData.environment.appUriScheme; },
|
||||
get clipboard(): vscode.Clipboard { return extHostClipboard.value; },
|
||||
get shell() {
|
||||
@@ -339,16 +334,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
return extHostUrls.createAppUri(uri);
|
||||
}
|
||||
|
||||
const isHttp = matchesScheme(uri, Schemas.http) || matchesScheme(uri, Schemas.https);
|
||||
|
||||
if (!isHttp) {
|
||||
checkProposedApiEnabled(extension); // https://github.com/microsoft/vscode/issues/124263
|
||||
}
|
||||
|
||||
try {
|
||||
return await extHostWindow.asExternalUri(uri, { allowTunneling: !!initData.remote.authority });
|
||||
} catch (err) {
|
||||
if (isHttp) {
|
||||
if (matchesScheme(uri, Schemas.http) || matchesScheme(uri, Schemas.https)) {
|
||||
return uri;
|
||||
}
|
||||
|
||||
@@ -371,30 +360,18 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
? extHostTypes.ExtensionKind.Workspace
|
||||
: extHostTypes.ExtensionKind.UI;
|
||||
|
||||
const test: typeof vscode.test = {
|
||||
registerTestController(provider) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTesting.registerTestController(extension.identifier.value, provider);
|
||||
const tests: typeof vscode.tests = {
|
||||
createTestController(provider, label) {
|
||||
return extHostTesting.createTestController(provider, label);
|
||||
},
|
||||
createDocumentTestObserver(document) {
|
||||
createTestObserver() {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTesting.createTextDocumentTestObserver(document);
|
||||
},
|
||||
createWorkspaceTestObserver(workspaceFolder) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTesting.createWorkspaceTestObserver(workspaceFolder);
|
||||
return extHostTesting.createTestObserver();
|
||||
},
|
||||
runTests(provider) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTesting.runTests(provider);
|
||||
},
|
||||
createTestItem<T>(options: vscode.TestItemOptions, data?: T) {
|
||||
return new extHostTypes.TestItemImpl(options.id, options.label, options.uri, data);
|
||||
},
|
||||
createTestRun(request, name, persist) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTesting.createTestRun(extension.identifier.value, request, name, persist);
|
||||
},
|
||||
get onDidChangeTestResults() {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTesting.onResultsChanged;
|
||||
@@ -405,9 +382,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
},
|
||||
};
|
||||
|
||||
// todo@connor4312: backwards compatibility for a short period
|
||||
(test as any).createTestRunTask = test.createTestRun;
|
||||
|
||||
// namespace: extensions
|
||||
const extensions: typeof vscode.extensions = {
|
||||
getExtension(extensionId: string): vscode.Extension<any> | undefined {
|
||||
@@ -543,6 +517,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
registerInlayHintsProvider(selector: vscode.DocumentSelector, provider: vscode.InlayHintsProvider): vscode.Disposable {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostLanguageFeatures.registerInlayHintsProvider(extension, selector, provider);
|
||||
},
|
||||
registerTypeHierarchyProvider(selector: vscode.DocumentSelector, provider: vscode.TypeHierarchyProvider): vscode.Disposable {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostLanguageFeatures.registerTypeHierarchyProvider(extension, selector, provider);
|
||||
},
|
||||
createLanguageStatusItem(selector: vscode.DocumentSelector): vscode.LanguageStatusItem {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostLanguages.createLanguageStatusItem(selector);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -601,6 +583,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTerminalService.onDidChangeTerminalDimensions(listener, thisArg, disposables);
|
||||
},
|
||||
onDidChangeTerminalState(listener, thisArg?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTerminalService.onDidChangeTerminalState(listener, thisArg, disposables);
|
||||
},
|
||||
onDidWriteTerminalData(listener, thisArg?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTerminalService.onDidWriteTerminalData(listener, thisArg, disposables);
|
||||
@@ -645,7 +631,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
alignment = priorityOrAlignment;
|
||||
priority = priorityArg;
|
||||
} else {
|
||||
alignment = alignmentOrId as number; // {{SQL CARBON EDIT}} strict-null-check
|
||||
alignment = alignmentOrId;
|
||||
priority = priorityOrAlignment;
|
||||
}
|
||||
|
||||
@@ -664,7 +650,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
return extHostProgress.withProgress(extension, options, task);
|
||||
},
|
||||
createOutputChannel(name: string): vscode.OutputChannel {
|
||||
return extHostOutputService.createOutputChannel(name);
|
||||
return extHostOutputService.createOutputChannel(name, extension);
|
||||
},
|
||||
createWebviewPanel(viewType: string, title: string, showOptions: vscode.ViewColumn | { viewColumn: vscode.ViewColumn, preserveFocus?: boolean }, options?: vscode.WebviewPanelOptions & vscode.WebviewOptions): vscode.WebviewPanel {
|
||||
return extHostWebviewPanels.createWebviewPanel(extension, viewType, title, showOptions, options);
|
||||
@@ -675,12 +661,12 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
},
|
||||
createTerminal(nameOrOptions?: vscode.TerminalOptions | vscode.ExtensionTerminalOptions | string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal {
|
||||
if (typeof nameOrOptions === 'object') {
|
||||
if ('location' in nameOrOptions) {
|
||||
checkProposedApiEnabled(extension);
|
||||
}
|
||||
if ('pty' in nameOrOptions) {
|
||||
return extHostTerminalService.createExtensionTerminal(nameOrOptions);
|
||||
}
|
||||
if (nameOrOptions.iconPath) {
|
||||
checkProposedApiEnabled(extension);
|
||||
}
|
||||
return extHostTerminalService.createTerminalFromOptions(nameOrOptions);
|
||||
}
|
||||
return extHostTerminalService.createTerminal(nameOrOptions, shellPath, shellArgs);
|
||||
@@ -689,7 +675,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
return extHostTerminalService.registerLinkProvider(provider);
|
||||
},
|
||||
registerTerminalProfileProvider(id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable {
|
||||
return extHostTerminalService.registerProfileProvider(id, provider);
|
||||
return extHostTerminalService.registerProfileProvider(extension, id, provider);
|
||||
},
|
||||
registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.Disposable {
|
||||
return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider, extension);
|
||||
@@ -1052,66 +1038,87 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
get activeDebugSession() {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.activeDebugSession; {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
get activeDebugConsole() {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.activeDebugConsole; {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
get breakpoints() {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return [];
|
||||
return undefined!;
|
||||
// return extHostDebugService.breakpoints; {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
onDidStartDebugSession(listener, thisArg?, disposables?) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.onDidStartDebugSession(listener, thisArg, disposables); {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
onDidTerminateDebugSession(listener, thisArg?, disposables?) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.onDidTerminateDebugSession(listener, thisArg, disposables); {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
onDidChangeActiveDebugSession(listener, thisArg?, disposables?) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.onDidChangeActiveDebugSession(listener, thisArg, disposables); {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
onDidReceiveDebugSessionCustomEvent(listener, thisArg?, disposables?) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.onDidReceiveDebugSessionCustomEvent(listener, thisArg, disposables); {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
onDidChangeBreakpoints(listener, thisArgs?, disposables?) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.onDidChangeBreakpoints(listener, thisArgs, disposables); {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
registerDebugConfigurationProvider(debugType: string, provider: vscode.DebugConfigurationProvider, triggerKind?: vscode.DebugConfigurationProviderTriggerKind) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.registerDebugConfigurationProvider(debugType, provider, triggerKind || extHostTypes.DebugConfigurationProviderTriggerKind.Initial); {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
registerDebugAdapterDescriptorFactory(debugType: string, factory: vscode.DebugAdapterDescriptorFactory) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.registerDebugAdapterDescriptorFactory(extension, debugType, factory); {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
registerDebugAdapterTrackerFactory(debugType: string, factory: vscode.DebugAdapterTrackerFactory) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.registerDebugAdapterTrackerFactory(debugType, factory); {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, parentSessionOrOptions?: vscode.DebugSession | vscode.DebugSessionOptions) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
/* {{SQL CARBON EDIT}} Removed
|
||||
if (!parentSessionOrOptions || (typeof parentSessionOrOptions === 'object' && 'configuration' in parentSessionOrOptions)) {
|
||||
return extHostDebugService.startDebugging(folder, nameOrConfig, { parentSession: parentSessionOrOptions });
|
||||
}
|
||||
return extHostDebugService.startDebugging(folder, nameOrConfig, parentSessionOrOptions || {});
|
||||
*/
|
||||
},
|
||||
stopDebugging(session?: vscode.DebugSession) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.stopDebugging(session); {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
addBreakpoints(breakpoints: readonly vscode.Breakpoint[]) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio'); // {{SQL CARBON EDIT}}
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.addBreakpoints(breakpoints); {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
removeBreakpoints(breakpoints: readonly vscode.Breakpoint[]) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio'); // {{SQL CARBON EDIT}}
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.removeBreakpoints(breakpoints); {{SQL CARBON EDIT}} Removed
|
||||
},
|
||||
asDebugSourceUri(source: vscode.DebugProtocolSource, session?: vscode.DebugSession): vscode.Uri {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
// return extHostDebugService.asDebugSourceUri(source, session); {{SQL CARBON EDIT}} Removed
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1168,7 +1175,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
// {{SQL CARBON EDIT}} Disable VS Code notebooks
|
||||
throw new Error(functionalityNotSupportedError);
|
||||
// checkProposedApiEnabled(extension);
|
||||
// return extHostNotebookRenderers.createRendererMessaging(rendererId);
|
||||
// return extHostNotebookRenderers.createRendererMessaging(extension, rendererId);
|
||||
},
|
||||
onDidChangeNotebookDocumentMetadata(listener, thisArgs?, disposables?) {
|
||||
// {{SQL CARBON EDIT}} Disable VS Code notebooks
|
||||
@@ -1222,7 +1229,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
notebooks,
|
||||
scm,
|
||||
tasks,
|
||||
test,
|
||||
tests,
|
||||
window,
|
||||
workspace,
|
||||
// types
|
||||
@@ -1324,6 +1331,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
TaskPanelKind: extHostTypes.TaskPanelKind,
|
||||
TaskRevealKind: extHostTypes.TaskRevealKind,
|
||||
TaskScope: extHostTypes.TaskScope,
|
||||
TerminalLink: extHostTypes.TerminalLink,
|
||||
TerminalLocation: extHostTypes.TerminalLocation,
|
||||
TerminalProfile: extHostTypes.TerminalProfile,
|
||||
TextDocumentSaveReason: extHostTypes.TextDocumentSaveReason,
|
||||
TextEdit: extHostTypes.TextEdit,
|
||||
TextEditorCursorStyle: TextEditorCursorStyle,
|
||||
@@ -1334,6 +1344,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
ThemeIcon: extHostTypes.ThemeIcon,
|
||||
TreeItem: extHostTypes.TreeItem,
|
||||
TreeItemCollapsibleState: extHostTypes.TreeItemCollapsibleState,
|
||||
TypeHierarchyItem: extHostTypes.TypeHierarchyItem,
|
||||
UIKind: UIKind,
|
||||
Uri: URI,
|
||||
ViewColumn: extHostTypes.ViewColumn,
|
||||
@@ -1360,12 +1371,19 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor, ex
|
||||
NotebookControllerAffinity: extHostTypes.NotebookControllerAffinity,
|
||||
PortAttributes: extHostTypes.PortAttributes,
|
||||
LinkedEditingRanges: extHostTypes.LinkedEditingRanges,
|
||||
TestItemStatus: extHostTypes.TestItemStatus,
|
||||
TestResultState: extHostTypes.TestResultState,
|
||||
TestRunRequest: extHostTypes.TestRunRequest,
|
||||
TestMessage: extHostTypes.TestMessage,
|
||||
TestTag: extHostTypes.TestTag,
|
||||
TestRunProfileKind: extHostTypes.TestRunProfileKind,
|
||||
TextSearchCompleteMessageType: TextSearchCompleteMessageType,
|
||||
TestMessageSeverity: extHostTypes.TestMessageSeverity,
|
||||
WorkspaceTrustState: extHostTypes.WorkspaceTrustState
|
||||
CoveredCount: extHostTypes.CoveredCount,
|
||||
FileCoverage: extHostTypes.FileCoverage,
|
||||
StatementCoverage: extHostTypes.StatementCoverage,
|
||||
BranchCoverage: extHostTypes.BranchCoverage,
|
||||
FunctionCoverage: extHostTypes.FunctionCoverage,
|
||||
WorkspaceTrustState: extHostTypes.WorkspaceTrustState,
|
||||
LanguageStatusSeverity: extHostTypes.LanguageStatusSeverity,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import { IExtHostTerminalService, WorkerExtHostTerminalService } from 'vs/workbe
|
||||
import { IExtHostTask, WorkerExtHostTask } from 'vs/workbench/api/common/extHostTask';
|
||||
// import { IExtHostDebugService, WorkerExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService'; {{SQL CARBON EDIT}}
|
||||
import { IExtHostSearch, ExtHostSearch } from 'vs/workbench/api/common/extHostSearch';
|
||||
import { IExtensionStoragePaths, ExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { IExtHostStorage, ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
import { IExtHostTunnelService, ExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { IExtHostApiDeprecationService, ExtHostApiDeprecationService, } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
||||
@@ -25,7 +24,6 @@ import { IExtHostSecretState, ExtHostSecretState } from 'vs/workbench/api/common
|
||||
import { ExtHostTelemetry, IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry';
|
||||
import { ExtHostEditorTabs, IExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
|
||||
|
||||
registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths);
|
||||
registerSingleton(IExtHostApiDeprecationService, ExtHostApiDeprecationService);
|
||||
registerSingleton(IExtHostCommands, ExtHostCommands);
|
||||
registerSingleton(IExtHostConfiguration, ExtHostConfiguration);
|
||||
|
||||
@@ -24,6 +24,7 @@ import { EndOfLineSequence, ISingleEditOperation } from 'vs/editor/common/model'
|
||||
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { CharacterPair, CommentRule, EnterAction } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { ILanguageStatus } from 'vs/workbench/services/languageStatus/common/languageStatusService';
|
||||
import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { ConfigurationTarget, IConfigurationChange, IConfigurationData, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -39,28 +40,32 @@ import { IRemoteConnectionData, RemoteAuthorityResolverErrorCode, ResolverResult
|
||||
import { ProvidedPortAttributes, TunnelCreationOptions, TunnelOptions, TunnelProviderFeatures } from 'vs/platform/remote/common/tunnel';
|
||||
import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { TreeDataTransferDTO } from 'vs/workbench/api/common/shared/treeDataTransfer';
|
||||
import { IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensions, ITerminalEnvironment, ITerminalLaunchError, ITerminalProfile } from 'vs/platform/terminal/common/terminal';
|
||||
import { ICreateContributedTerminalProfileOptions, IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensions, ITerminalEnvironment, ITerminalLaunchError, ITerminalProfile, TerminalLocation } from 'vs/platform/terminal/common/terminal';
|
||||
import { ThemeColor, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { IExtensionIdWithVersion } from 'vs/platform/userDataSync/common/extensionsStorageSync';
|
||||
import { WorkspaceTrustRequestOptions } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { ExtHostInteractive } from 'vs/workbench/api/common/extHostInteractive';
|
||||
import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { DebugConfigurationProviderTriggerKind, TestResultState } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as tasks from 'vs/workbench/api/common/shared/tasks';
|
||||
import { EditorGroupColumn, SaveReason } from 'vs/workbench/common/editor';
|
||||
import { TreeDataTransferDTO } from 'vs/workbench/api/common/shared/treeDataTransfer';
|
||||
import { SaveReason } from 'vs/workbench/common/editor';
|
||||
import { IRevealOptions, ITreeItem } from 'vs/workbench/common/views';
|
||||
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import { IAdapterDescriptor, IConfig, IDebugSessionReplMode } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { CellKind, ICellEditOperation, IImmediateCellEditOperation, IMainCellDto, INotebookCellStatusBarItem, INotebookContributionData, INotebookDecorationRenderOptions, IOutputDto, NotebookCellMetadata, NotebookCellsChangedEventDto, NotebookDataDto, NotebookDocumentMetadata, TransientCellMetadata, TransientDocumentMetadata, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import * as notebookCommon from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellExecutionUpdateType, ICellExecutionComplete, ICellExecutionStateUpdate } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { InputValidationType } from 'vs/workbench/contrib/scm/common/scm';
|
||||
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
|
||||
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { ExtensionRunTestsRequest, InternalTestItem, ISerializedTestResults, ITestItem, ITestMessage, ITestRunTask, RunTestForProviderRequest, RunTestsRequest, TestIdWithSrc, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { CoverageDetails, ExtensionRunTestsRequest, IFileCoverage, ISerializedTestResults, ITestItem, ITestMessage, ITestRunProfile, ITestRunTask, ResolvedTestRunRequest, RunTestForControllerRequest, TestResultState, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { InternalTimelineOptions, Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor } from 'vs/workbench/contrib/timeline/common/timeline';
|
||||
import { TypeHierarchyItem } from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
|
||||
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import { ActivationKind, ExtensionHostKind, MissingExtensionDependency } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol, SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import { CandidatePort } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import * as search from 'vs/workbench/services/search/common/search';
|
||||
import * as statusbar from 'vs/workbench/services/statusbar/common/statusbar';
|
||||
@@ -71,6 +76,7 @@ import { ITreeItem as sqlITreeItem } from 'sql/workbench/common/views';
|
||||
export interface IEnvironment {
|
||||
isExtensionDevelopmentDebug: boolean;
|
||||
appName: string;
|
||||
embedderIdentifier: string;
|
||||
appRoot?: URI;
|
||||
appLanguage: string;
|
||||
appUriScheme: string;
|
||||
@@ -79,6 +85,7 @@ export interface IEnvironment {
|
||||
globalStorageHome: URI;
|
||||
workspaceStorageHome: URI;
|
||||
useHostProxy?: boolean;
|
||||
skipWorkspaceStorageLock?: boolean;
|
||||
}
|
||||
|
||||
export interface IStaticWorkspaceData {
|
||||
@@ -172,7 +179,7 @@ export interface MainThreadAuthenticationShape extends IDisposable {
|
||||
$unregisterAuthenticationProvider(id: string): void;
|
||||
$ensureProvider(id: string): Promise<void>;
|
||||
$sendDidChangeSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): void;
|
||||
$getSession(providerId: string, scopes: readonly string[], extensionId: string, extensionName: string, options: { createIfNone?: boolean, clearSessionPreference?: boolean }): Promise<modes.AuthenticationSession | undefined>;
|
||||
$getSession(providerId: string, scopes: readonly string[], extensionId: string, extensionName: string, options: { createIfNone?: boolean, forceNewSession?: boolean | { detail: string }, clearSessionPreference?: boolean }): Promise<modes.AuthenticationSession | undefined>;
|
||||
$removeSession(providerId: string, sessionId: string): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -416,6 +423,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
||||
$emitFoldingRangeEvent(eventHandle: number, event?: any): void;
|
||||
$registerSelectionRangeProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerCallHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerTypeHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$setLanguageConfiguration(handle: number, languageId: string, configuration: ILanguageConfigurationDto): void;
|
||||
}
|
||||
|
||||
@@ -423,11 +431,14 @@ export interface MainThreadLanguagesShape extends IDisposable {
|
||||
$getLanguages(): Promise<string[]>;
|
||||
$changeLanguage(resource: UriComponents, languageId: string): Promise<void>;
|
||||
$tokensAtPosition(resource: UriComponents, position: IPosition): Promise<undefined | { type: modes.StandardTokenType, range: IRange }>;
|
||||
$setLanguageStatus(handle: number, status: ILanguageStatus): void;
|
||||
$removeLanguageStatus(handle: number): void;
|
||||
}
|
||||
|
||||
export interface MainThreadMessageOptions {
|
||||
extension?: IExtensionDescription;
|
||||
modal?: boolean;
|
||||
detail?: string;
|
||||
useCustom?: boolean;
|
||||
}
|
||||
|
||||
@@ -436,7 +447,7 @@ export interface MainThreadMessageServiceShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface MainThreadOutputServiceShape extends IDisposable {
|
||||
$register(label: string, log: boolean, file?: UriComponents): Promise<string>;
|
||||
$register(label: string, log: boolean, file?: UriComponents, extensionId?: string): Promise<string>;
|
||||
$append(channelId: string, value: string): Promise<void> | undefined;
|
||||
$update(channelId: string): Promise<void> | undefined;
|
||||
$clear(channelId: string, till: number): Promise<void> | undefined;
|
||||
@@ -460,7 +471,7 @@ export interface MainThreadProgressShape extends IDisposable {
|
||||
* All other terminals (that are not created on the extension host side) always
|
||||
* use the numeric id.
|
||||
*/
|
||||
export type TerminalIdentifier = number | string;
|
||||
export type ExtHostTerminalIdentifier = number | string;
|
||||
|
||||
export interface TerminalLaunchConfig {
|
||||
name?: string;
|
||||
@@ -469,6 +480,7 @@ export interface TerminalLaunchConfig {
|
||||
cwd?: string | UriComponents;
|
||||
env?: ITerminalEnvironment;
|
||||
icon?: URI | { light: URI; dark: URI } | ThemeIcon;
|
||||
color?: string;
|
||||
initialText?: string;
|
||||
waitOnExit?: boolean;
|
||||
strictEnv?: boolean;
|
||||
@@ -477,21 +489,21 @@ export interface TerminalLaunchConfig {
|
||||
isFeatureTerminal?: boolean;
|
||||
isExtensionOwnedTerminal?: boolean;
|
||||
useShellEnvironment?: boolean;
|
||||
isSplitTerminal?: boolean;
|
||||
location?: TerminalLocation | { viewColumn: number, preserveFocus?: boolean } | { parentTerminal: ExtHostTerminalIdentifier } | { splitActiveTerminal: boolean };
|
||||
}
|
||||
|
||||
export interface MainThreadTerminalServiceShape extends IDisposable {
|
||||
$createTerminal(extHostTerminalId: string, config: TerminalLaunchConfig): Promise<void>;
|
||||
$dispose(id: TerminalIdentifier): void;
|
||||
$hide(id: TerminalIdentifier): void;
|
||||
$sendText(id: TerminalIdentifier, text: string, addNewLine: boolean): void;
|
||||
$show(id: TerminalIdentifier, preserveFocus: boolean): void;
|
||||
$dispose(id: ExtHostTerminalIdentifier): void;
|
||||
$hide(id: ExtHostTerminalIdentifier): void;
|
||||
$sendText(id: ExtHostTerminalIdentifier, text: string, addNewLine: boolean): void;
|
||||
$show(id: ExtHostTerminalIdentifier, preserveFocus: boolean): void;
|
||||
$startSendingDataEvents(): void;
|
||||
$stopSendingDataEvents(): void;
|
||||
$startLinkProvider(): void;
|
||||
$stopLinkProvider(): void;
|
||||
$registerProcessSupport(isSupported: boolean): void;
|
||||
$registerProfileProvider(id: string): void;
|
||||
$registerProfileProvider(id: string, extensionIdentifier: string): void;
|
||||
$unregisterProfileProvider(id: string): void;
|
||||
$setEnvironmentVariableCollection(extensionIdentifier: string, persistent: boolean, collection: ISerializableEnvironmentVariableCollection | undefined): void;
|
||||
|
||||
@@ -508,12 +520,11 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
|
||||
|
||||
export interface TransferQuickPickItems extends quickInput.IQuickPickItem {
|
||||
handle: number;
|
||||
buttons?: TransferQuickInputButton[];
|
||||
}
|
||||
|
||||
export interface TransferQuickInputButton {
|
||||
export interface TransferQuickInputButton extends quickInput.IQuickInputButton {
|
||||
handle: number;
|
||||
iconPath: { dark: URI; light?: URI; } | { id: string; };
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
export type TransferQuickInput = TransferQuickPick | TransferInputBox;
|
||||
@@ -599,7 +610,7 @@ export interface MainThreadQuickOpenShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface MainThreadStatusBarShape extends IDisposable {
|
||||
$setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: ICommandDto | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignment: statusbar.StatusbarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): void;
|
||||
$setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: IMarkdownString | string | undefined, command: ICommandDto | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignment: statusbar.StatusbarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): void;
|
||||
$dispose(id: number): void;
|
||||
}
|
||||
|
||||
@@ -661,7 +672,7 @@ export interface WebviewExtensionDescription {
|
||||
|
||||
export interface NotebookExtensionDescription {
|
||||
readonly id: ExtensionIdentifier;
|
||||
readonly location: UriComponents;
|
||||
readonly location: UriComponents | undefined;
|
||||
}
|
||||
|
||||
export enum WebviewEditorCapabilities {
|
||||
@@ -838,28 +849,6 @@ export enum CellOutputKind {
|
||||
Rich = 3
|
||||
}
|
||||
|
||||
export interface ICellDto {
|
||||
handle: number;
|
||||
uri: UriComponents,
|
||||
source: string[];
|
||||
language: string;
|
||||
cellKind: CellKind;
|
||||
outputs: IOutputDto[];
|
||||
metadata?: NotebookCellMetadata;
|
||||
}
|
||||
|
||||
export type NotebookCellsSplice = [
|
||||
number /* start */,
|
||||
number /* delete count */,
|
||||
ICellDto[]
|
||||
];
|
||||
|
||||
export type NotebookCellOutputsSplice = [
|
||||
number /* start */,
|
||||
number /* delete count */,
|
||||
IOutputDto[]
|
||||
];
|
||||
|
||||
export enum NotebookEditorRevealType {
|
||||
Default = 0,
|
||||
InCenter = 1,
|
||||
@@ -874,7 +863,7 @@ export interface INotebookDocumentShowOptions {
|
||||
selections?: ICellRange[];
|
||||
}
|
||||
|
||||
export type INotebookCellStatusBarEntryDto = Dto<INotebookCellStatusBarItem>;
|
||||
export type INotebookCellStatusBarEntryDto = Dto<notebookCommon.INotebookCellStatusBarItem>;
|
||||
|
||||
export interface INotebookCellStatusBarListDto {
|
||||
items: INotebookCellStatusBarEntryDto[];
|
||||
@@ -882,11 +871,11 @@ export interface INotebookCellStatusBarListDto {
|
||||
}
|
||||
|
||||
export interface MainThreadNotebookShape extends IDisposable {
|
||||
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, options: TransientOptions, registration: INotebookContributionData | undefined): Promise<void>;
|
||||
$updateNotebookProviderOptions(viewType: string, options?: { transientOutputs: boolean; transientCellMetadata: TransientCellMetadata; transientDocumentMetadata: TransientDocumentMetadata; }): Promise<void>;
|
||||
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, options: notebookCommon.TransientOptions, registration: notebookCommon.INotebookContributionData | undefined): Promise<void>;
|
||||
$updateNotebookProviderOptions(viewType: string, options?: { transientOutputs: boolean; transientCellMetadata: notebookCommon.TransientCellMetadata; transientDocumentMetadata: notebookCommon.TransientDocumentMetadata; }): Promise<void>;
|
||||
$unregisterNotebookProvider(viewType: string): Promise<void>;
|
||||
|
||||
$registerNotebookSerializer(handle: number, extension: NotebookExtensionDescription, viewType: string, options: TransientOptions, registration: INotebookContributionData | undefined): void;
|
||||
$registerNotebookSerializer(handle: number, extension: NotebookExtensionDescription, viewType: string, options: notebookCommon.TransientOptions, registration: notebookCommon.INotebookContributionData | undefined): void;
|
||||
$unregisterNotebookSerializer(handle: number): void;
|
||||
|
||||
$registerNotebookCellStatusBarItemProvider(handle: number, eventHandle: number | undefined, viewType: string): Promise<void>;
|
||||
@@ -897,18 +886,17 @@ export interface MainThreadNotebookShape extends IDisposable {
|
||||
export interface MainThreadNotebookEditorsShape extends IDisposable {
|
||||
$tryShowNotebookDocument(uriComponents: UriComponents, viewType: string, options: INotebookDocumentShowOptions): Promise<string>;
|
||||
$tryRevealRange(id: string, range: ICellRange, revealType: NotebookEditorRevealType): Promise<void>;
|
||||
$registerNotebookEditorDecorationType(key: string, options: INotebookDecorationRenderOptions): void;
|
||||
$registerNotebookEditorDecorationType(key: string, options: notebookCommon.INotebookDecorationRenderOptions): void;
|
||||
$removeNotebookEditorDecorationType(key: string): void;
|
||||
$trySetSelections(id: string, range: ICellRange[]): void;
|
||||
$trySetDecorations(id: string, range: ICellRange, decorationKey: string): void;
|
||||
$tryApplyEdits(editorId: string, modelVersionId: number, cellEdits: ICellEditOperation[]): Promise<boolean>
|
||||
$tryApplyEdits(editorId: string, modelVersionId: number, cellEdits: ICellEditOperationDto[]): Promise<boolean>
|
||||
}
|
||||
|
||||
export interface MainThreadNotebookDocumentsShape extends IDisposable {
|
||||
$tryCreateNotebook(options: { viewType: string, content?: NotebookDataDto }): Promise<UriComponents>;
|
||||
$tryOpenNotebook(uriComponents: UriComponents): Promise<UriComponents>;
|
||||
$trySaveNotebook(uri: UriComponents): Promise<boolean>;
|
||||
$applyEdits(resource: UriComponents, edits: IImmediateCellEditOperation[], computeUndoRedo?: boolean): Promise<void>;
|
||||
}
|
||||
|
||||
export interface INotebookKernelDto2 {
|
||||
@@ -925,16 +913,49 @@ export interface INotebookKernelDto2 {
|
||||
preloads?: { uri: UriComponents; provides: string[] }[];
|
||||
}
|
||||
|
||||
export interface ICellExecuteOutputEditDto {
|
||||
editType: CellExecutionUpdateType.Output;
|
||||
executionHandle: number;
|
||||
cellHandle: number;
|
||||
append?: boolean;
|
||||
outputs: NotebookOutputDto[]
|
||||
}
|
||||
|
||||
export interface ICellExecuteOutputItemEditDto {
|
||||
editType: CellExecutionUpdateType.OutputItems;
|
||||
executionHandle: number;
|
||||
append?: boolean;
|
||||
outputId: string;
|
||||
items: NotebookOutputItemDto[]
|
||||
}
|
||||
|
||||
export interface ICellExecutionStateUpdateDto extends ICellExecutionStateUpdate {
|
||||
executionHandle: number;
|
||||
}
|
||||
|
||||
export interface ICellExecutionCompleteDto extends ICellExecutionComplete {
|
||||
executionHandle: number;
|
||||
}
|
||||
|
||||
export type ICellExecuteUpdateDto = ICellExecuteOutputEditDto | ICellExecuteOutputItemEditDto | ICellExecutionStateUpdateDto | ICellExecutionCompleteDto;
|
||||
|
||||
export interface MainThreadNotebookKernelsShape extends IDisposable {
|
||||
$postMessage(handle: number, editorId: string | undefined, message: any): Promise<boolean>;
|
||||
$addKernel(handle: number, data: INotebookKernelDto2): Promise<void>;
|
||||
$updateKernel(handle: number, data: Partial<INotebookKernelDto2>): void;
|
||||
$removeKernel(handle: number): void;
|
||||
$updateNotebookPriority(handle: number, uri: UriComponents, value: number | undefined): void;
|
||||
|
||||
$addExecution(handle: number, uri: UriComponents, cellHandle: number): void;
|
||||
$updateExecutions(data: SerializableObjectWithBuffers<ICellExecuteUpdateDto[]>): void;
|
||||
$removeExecution(handle: number): void;
|
||||
}
|
||||
|
||||
export interface MainThreadNotebookRenderersShape extends IDisposable {
|
||||
$postMessage(editorId: string, rendererId: string, message: unknown): void;
|
||||
$postMessage(editorId: string | undefined, rendererId: string, message: unknown): Promise<boolean>;
|
||||
}
|
||||
|
||||
export interface MainThreadInteractiveShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface MainThreadUrlsShape extends IDisposable {
|
||||
@@ -1042,7 +1063,7 @@ export interface SCMGroupFeatures {
|
||||
export type SCMRawResource = [
|
||||
number /*handle*/,
|
||||
UriComponents /*resourceUri*/,
|
||||
UriComponents[] /*icons: light, dark*/,
|
||||
[UriComponents | ThemeIcon | undefined, UriComponents | ThemeIcon | undefined] /*icons: light, dark*/,
|
||||
string /*tooltip*/,
|
||||
boolean /*strike through*/,
|
||||
boolean /*faded*/,
|
||||
@@ -1077,7 +1098,7 @@ export interface MainThreadSCMShape extends IDisposable {
|
||||
$setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void;
|
||||
$setInputBoxVisibility(sourceControlHandle: number, visible: boolean): void;
|
||||
$setInputBoxFocus(sourceControlHandle: number): void;
|
||||
$showValidationMessage(sourceControlHandle: number, message: string, type: InputValidationType): void;
|
||||
$showValidationMessage(sourceControlHandle: number, message: string | IMarkdownString, type: InputValidationType): void;
|
||||
$setValidationProviderIsEnabled(sourceControlHandle: number, enabled: boolean): void;
|
||||
}
|
||||
|
||||
@@ -1092,9 +1113,13 @@ export interface IDebugConfiguration {
|
||||
|
||||
export interface IStartDebuggingOptions {
|
||||
parentSessionID?: DebugSessionUUID;
|
||||
lifecycleManagedByParent?: boolean;
|
||||
repl?: IDebugSessionReplMode;
|
||||
noDebug?: boolean;
|
||||
compact?: boolean;
|
||||
debugUI?: {
|
||||
simple?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MainThreadDebugServiceShape extends IDisposable {
|
||||
@@ -1238,8 +1263,7 @@ export interface ExtHostDocumentsAndEditorsShape {
|
||||
}
|
||||
|
||||
export interface ExtHostTreeViewsShape {
|
||||
// {{SQL CARBON EDIT}}
|
||||
$getChildren(treeViewId: string, treeItemHandle?: string): Promise<sqlITreeItem[]>;
|
||||
$getChildren(treeViewId: string, treeItemHandle?: string): Promise<sqlITreeItem[] | undefined>; // {{SQL CARBON EDIT}}
|
||||
$onDrop(treeViewId: string, treeDataTransfer: TreeDataTransferDTO, newParentTreeItemHandle: string): Promise<void>;
|
||||
$setExpanded(treeViewId: string, treeItemHandle: string, expanded: boolean): void;
|
||||
$setSelection(treeViewId: string, treeItemHandles: string[]): void;
|
||||
@@ -1285,7 +1309,6 @@ export interface ExtHostAuthenticationShape {
|
||||
$createSession(id: string, scopes: string[]): Promise<modes.AuthenticationSession>;
|
||||
$removeSession(id: string, sessionId: string): Promise<void>;
|
||||
$onDidChangeAuthenticationSessions(id: string, label: string): Promise<void>;
|
||||
$onDidChangeAuthenticationProviders(added: modes.AuthenticationProviderInformation[], removed: modes.AuthenticationProviderInformation[]): Promise<void>;
|
||||
$setProviders(providers: modes.AuthenticationProviderInformation[]): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -1294,6 +1317,7 @@ export interface ExtHostSecretStateShape {
|
||||
}
|
||||
|
||||
export interface ExtHostSearchShape {
|
||||
$enableExtensionHostSearch(): void;
|
||||
$provideFileSearchResults(handle: number, session: number, query: search.IRawQuery, token: CancellationToken): Promise<search.ISearchCompleteStats>;
|
||||
$provideTextSearchResults(handle: number, session: number, query: search.IRawTextQuery, token: CancellationToken): Promise<search.ISearchCompleteStats>;
|
||||
$clearCache(cacheKey: string): Promise<void>;
|
||||
@@ -1402,14 +1426,10 @@ export const enum ISuggestDataDtoField {
|
||||
additionalTextEdits = 'l',
|
||||
command = 'm',
|
||||
kindModifier = 'n',
|
||||
|
||||
// to merge into label
|
||||
label2 = 'o',
|
||||
}
|
||||
|
||||
export interface ISuggestDataDto {
|
||||
[ISuggestDataDtoField.label]: string;
|
||||
[ISuggestDataDtoField.label2]?: string | modes.CompletionItemLabel;
|
||||
[ISuggestDataDtoField.label]: string | modes.CompletionItemLabel;
|
||||
[ISuggestDataDtoField.kind]?: modes.CompletionItemKind;
|
||||
[ISuggestDataDtoField.detail]?: string;
|
||||
[ISuggestDataDtoField.documentation]?: string | IMarkdownString;
|
||||
@@ -1520,12 +1540,22 @@ export interface IWorkspaceTextEditDto {
|
||||
metadata?: IWorkspaceEditEntryMetadataDto;
|
||||
}
|
||||
|
||||
export type ICellEditOperationDto =
|
||||
notebookCommon.ICellPartialMetadataEdit
|
||||
| notebookCommon.IDocumentMetadataEdit
|
||||
| {
|
||||
editType: notebookCommon.CellEditType.Replace,
|
||||
index: number,
|
||||
count: number,
|
||||
cells: NotebookCellDataDto[]
|
||||
};
|
||||
|
||||
export interface IWorkspaceCellEditDto {
|
||||
_type: WorkspaceEditType.Cell;
|
||||
resource: UriComponents;
|
||||
edit: ICellEditOperation;
|
||||
notebookVersionId?: number;
|
||||
metadata?: IWorkspaceEditEntryMetadataDto;
|
||||
edit: ICellEditOperationDto;
|
||||
}
|
||||
|
||||
export interface IWorkspaceEditDto {
|
||||
@@ -1626,6 +1656,8 @@ export interface IInlineValueContextDto {
|
||||
stoppedLocation: IRange;
|
||||
}
|
||||
|
||||
export type ITypeHierarchyItemDto = Dto<TypeHierarchyItem>;
|
||||
|
||||
export interface ExtHostLanguageFeaturesShape {
|
||||
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.DocumentSymbol[] | undefined>;
|
||||
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<ICodeLensListDto | undefined>;
|
||||
@@ -1676,6 +1708,10 @@ export interface ExtHostLanguageFeaturesShape {
|
||||
$provideCallHierarchyOutgoingCalls(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<IOutgoingCallDto[] | undefined>;
|
||||
$releaseCallHierarchy(handle: number, sessionId: string): void;
|
||||
$setWordDefinitions(wordDefinitions: ILanguageWordDefinitionDto[]): void;
|
||||
$prepareTypeHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<ITypeHierarchyItemDto[] | undefined>;
|
||||
$provideTypeHierarchySupertypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<ITypeHierarchyItemDto[] | undefined>;
|
||||
$provideTypeHierarchySubtypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<ITypeHierarchyItemDto[] | undefined>;
|
||||
$releaseTypeHierarchy(handle: number, sessionId: string): void;
|
||||
}
|
||||
|
||||
export interface ExtHostQuickOpenShape {
|
||||
@@ -1686,6 +1722,7 @@ export interface ExtHostQuickOpenShape {
|
||||
$onDidAccept(sessionId: number): void;
|
||||
$onDidChangeValue(sessionId: number, value: string): void;
|
||||
$onDidTriggerButton(sessionId: number, handle: number): void;
|
||||
$onDidTriggerItemButton(sessionId: number, itemHandle: number, buttonHandle: number): void;
|
||||
$onDidHide(sessionId: number): void;
|
||||
}
|
||||
|
||||
@@ -1719,6 +1756,7 @@ export interface ExtHostTerminalServiceShape {
|
||||
$acceptTerminalTitleChange(id: number, name: string): void;
|
||||
$acceptTerminalDimensions(id: number, cols: number, rows: number): void;
|
||||
$acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): void;
|
||||
$acceptTerminalInteraction(id: number): void;
|
||||
$startExtensionTerminal(id: number, initialDimensions: ITerminalDimensionsDto | undefined): Promise<ITerminalLaunchError | undefined>;
|
||||
$acceptProcessAckDataEvent(id: number, charCount: number): void;
|
||||
$acceptProcessInput(id: number, data: string): void;
|
||||
@@ -1731,14 +1769,14 @@ export interface ExtHostTerminalServiceShape {
|
||||
$activateLink(id: number, linkId: number): void;
|
||||
$initEnvironmentVariableCollections(collections: [string, ISerializableEnvironmentVariableCollection][]): void;
|
||||
$acceptDefaultProfile(profile: ITerminalProfile, automationProfile: ITerminalProfile): void;
|
||||
$createContributedProfileTerminal(id: string, isSplitTerminal: boolean): Promise<void>;
|
||||
$createContributedProfileTerminal(id: string, options: ICreateContributedTerminalProfileOptions): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ExtHostSCMShape {
|
||||
$provideOriginalResource(sourceControlHandle: number, uri: UriComponents, token: CancellationToken): Promise<UriComponents | null>;
|
||||
$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>;
|
||||
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string | IMarkdownString, number] | undefined>;
|
||||
$setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -1888,15 +1926,15 @@ export interface INotebookEditorPropertiesChangeData {
|
||||
}
|
||||
|
||||
export interface INotebookDocumentPropertiesChangeData {
|
||||
metadata?: NotebookDocumentMetadata;
|
||||
metadata?: notebookCommon.NotebookDocumentMetadata;
|
||||
}
|
||||
|
||||
export interface INotebookModelAddedData {
|
||||
uri: UriComponents;
|
||||
versionId: number;
|
||||
cells: IMainCellDto[],
|
||||
cells: NotebookCellDto[],
|
||||
viewType: string;
|
||||
metadata?: NotebookDocumentMetadata;
|
||||
metadata?: notebookCommon.NotebookDocumentMetadata;
|
||||
}
|
||||
|
||||
export interface INotebookEditorAddData {
|
||||
@@ -1916,17 +1954,56 @@ export interface INotebookDocumentsAndEditorsDelta {
|
||||
visibleEditors?: string[];
|
||||
}
|
||||
|
||||
export interface NotebookOutputItemDto {
|
||||
readonly mime: string;
|
||||
readonly valueBytes: VSBuffer;
|
||||
}
|
||||
|
||||
export interface NotebookOutputDto {
|
||||
items: NotebookOutputItemDto[];
|
||||
outputId: string;
|
||||
metadata?: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface NotebookCellDataDto {
|
||||
source: string;
|
||||
language: string;
|
||||
mime: string | undefined;
|
||||
cellKind: notebookCommon.CellKind;
|
||||
outputs: NotebookOutputDto[];
|
||||
metadata?: notebookCommon.NotebookCellMetadata;
|
||||
internalMetadata?: notebookCommon.NotebookCellInternalMetadata;
|
||||
}
|
||||
|
||||
export interface NotebookDataDto {
|
||||
readonly cells: NotebookCellDataDto[];
|
||||
readonly metadata: notebookCommon.NotebookDocumentMetadata;
|
||||
}
|
||||
|
||||
export interface NotebookCellDto {
|
||||
handle: number;
|
||||
uri: UriComponents;
|
||||
eol: string;
|
||||
source: string[];
|
||||
language: string;
|
||||
mime?: string;
|
||||
cellKind: notebookCommon.CellKind;
|
||||
outputs: NotebookOutputDto[];
|
||||
metadata?: notebookCommon.NotebookCellMetadata;
|
||||
internalMetadata?: notebookCommon.NotebookCellInternalMetadata;
|
||||
}
|
||||
|
||||
export interface ExtHostNotebookShape extends ExtHostNotebookDocumentsAndEditorsShape {
|
||||
$provideNotebookCellStatusBarItems(handle: number, uri: UriComponents, index: number, token: CancellationToken): Promise<INotebookCellStatusBarListDto | undefined>;
|
||||
$releaseNotebookCellStatusBarItems(id: number): void;
|
||||
|
||||
$openNotebook(viewType: string, uri: UriComponents, backupId: string | undefined, untitledDocumentData: VSBuffer | undefined, token: CancellationToken): Promise<NotebookDataDto>;
|
||||
$openNotebook(viewType: string, uri: UriComponents, backupId: string | undefined, untitledDocumentData: VSBuffer | undefined, token: CancellationToken): Promise<SerializableObjectWithBuffers<NotebookDataDto>>;
|
||||
$saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean>;
|
||||
$saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean>;
|
||||
$backupNotebook(viewType: string, uri: UriComponents, cancellation: CancellationToken): Promise<string>;
|
||||
|
||||
$dataToNotebook(handle: number, data: VSBuffer, token: CancellationToken): Promise<NotebookDataDto>;
|
||||
$notebookToData(handle: number, data: NotebookDataDto, token: CancellationToken): Promise<VSBuffer>;
|
||||
$dataToNotebook(handle: number, data: VSBuffer, token: CancellationToken): Promise<SerializableObjectWithBuffers<NotebookDataDto>>;
|
||||
$notebookToData(handle: number, data: SerializableObjectWithBuffers<NotebookDataDto>, token: CancellationToken): Promise<VSBuffer>;
|
||||
}
|
||||
|
||||
export interface ExtHostNotebookRenderersShape {
|
||||
@@ -1934,11 +2011,50 @@ export interface ExtHostNotebookRenderersShape {
|
||||
}
|
||||
|
||||
export interface ExtHostNotebookDocumentsAndEditorsShape {
|
||||
$acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta): void;
|
||||
$acceptDocumentAndEditorsDelta(delta: SerializableObjectWithBuffers<INotebookDocumentsAndEditorsDelta>): void;
|
||||
}
|
||||
|
||||
export type NotebookRawContentEventDto =
|
||||
// notebookCommon.NotebookCellsInitializeEvent<NotebookCellDto>
|
||||
| {
|
||||
|
||||
readonly kind: notebookCommon.NotebookCellsChangeType.ModelChange;
|
||||
readonly changes: notebookCommon.NotebookCellTextModelSplice<NotebookCellDto>[];
|
||||
}
|
||||
| {
|
||||
readonly kind: notebookCommon.NotebookCellsChangeType.Move;
|
||||
readonly index: number;
|
||||
readonly length: number;
|
||||
readonly newIdx: number;
|
||||
}
|
||||
| {
|
||||
readonly kind: notebookCommon.NotebookCellsChangeType.Output;
|
||||
readonly index: number;
|
||||
readonly outputs: NotebookOutputDto[];
|
||||
}
|
||||
| {
|
||||
readonly kind: notebookCommon.NotebookCellsChangeType.OutputItem;
|
||||
readonly index: number;
|
||||
readonly outputId: string;
|
||||
readonly outputItems: NotebookOutputItemDto[];
|
||||
readonly append: boolean;
|
||||
}
|
||||
| notebookCommon.NotebookCellsChangeLanguageEvent
|
||||
| notebookCommon.NotebookCellsChangeMimeEvent
|
||||
| notebookCommon.NotebookCellsChangeMetadataEvent
|
||||
| notebookCommon.NotebookCellsChangeInternalMetadataEvent
|
||||
// | notebookCommon.NotebookDocumentChangeMetadataEvent
|
||||
// | notebookCommon.NotebookCellContentChangeEvent
|
||||
// | notebookCommon.NotebookDocumentUnknownChangeEvent
|
||||
;
|
||||
|
||||
export type NotebookCellsChangedEventDto = {
|
||||
readonly rawEvents: NotebookRawContentEventDto[];
|
||||
readonly versionId: number;
|
||||
};
|
||||
|
||||
export interface ExtHostNotebookDocumentsShape {
|
||||
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEventDto, isDirty: boolean): void;
|
||||
$acceptModelChanged(uriComponents: UriComponents, event: SerializableObjectWithBuffers<NotebookCellsChangedEventDto>, isDirty: boolean): void;
|
||||
$acceptDirtyStateChanged(uriComponents: UriComponents, isDirty: boolean): void;
|
||||
$acceptModelSaved(uriComponents: UriComponents): void;
|
||||
$acceptDocumentPropertiesChanged(uriComponents: UriComponents, data: INotebookDocumentPropertiesChangeData): void;
|
||||
@@ -1958,6 +2074,11 @@ export interface ExtHostNotebookKernelsShape {
|
||||
$acceptKernelMessageFromRenderer(handle: number, editorId: string, message: any): void;
|
||||
}
|
||||
|
||||
export interface ExtHostInteractiveShape {
|
||||
$willAddInteractiveDocument(uri: UriComponents, eol: string, modeId: string, notebookUri: UriComponents): void;
|
||||
$willRemoveInteractiveDocument(uri: UriComponents, notebookUri: UriComponents): void;
|
||||
}
|
||||
|
||||
export interface ExtHostStorageShape {
|
||||
$acceptValue(shared: boolean, key: string, value: object | undefined): void;
|
||||
}
|
||||
@@ -1988,41 +2109,68 @@ export const enum ExtHostTestingResource {
|
||||
}
|
||||
|
||||
export interface ExtHostTestingShape {
|
||||
$runTestsForProvider(req: RunTestForProviderRequest, token: CancellationToken): Promise<void>;
|
||||
$subscribeToTests(resource: ExtHostTestingResource, uri: UriComponents): void;
|
||||
$unsubscribeFromTests(resource: ExtHostTestingResource, uri: UriComponents): void;
|
||||
$lookupTest(test: TestIdWithSrc): Promise<InternalTestItem | undefined>;
|
||||
$acceptDiff(resource: ExtHostTestingResource, uri: UriComponents, diff: TestsDiff): void;
|
||||
$runControllerTests(req: RunTestForControllerRequest, token: CancellationToken): Promise<void>;
|
||||
$cancelExtensionTestRun(runId: string | undefined): void;
|
||||
/** Handles a diff of tests, as a result of a subscribeToDiffs() call */
|
||||
$acceptDiff(diff: TestsDiff): void;
|
||||
/** Publishes that a test run finished. */
|
||||
$publishTestResults(results: ISerializedTestResults[]): void;
|
||||
$expandTest(src: TestIdWithSrc, levels: number): Promise<void>;
|
||||
/** Expands a test item's children, by the given number of levels. */
|
||||
$expandTest(testId: string, levels: number): Promise<void>;
|
||||
/** Requests file coverage for a test run. Errors if not available. */
|
||||
$provideFileCoverage(runId: string, taskId: string, token: CancellationToken): Promise<IFileCoverage[]>;
|
||||
/**
|
||||
* Requests coverage details for the file index in coverage data for the run.
|
||||
* Requires file coverage to have been previously requested via $provideFileCoverage.
|
||||
*/
|
||||
$resolveFileCoverage(runId: string, taskId: string, fileIndex: number, token: CancellationToken): Promise<CoverageDetails[]>;
|
||||
/** Configures a test run config. */
|
||||
$configureRunProfile(controllerId: string, configId: number): void;
|
||||
}
|
||||
|
||||
export interface MainThreadTestingShape {
|
||||
/** Registeres that there's a test controller with the given ID */
|
||||
$registerTestController(id: string): void;
|
||||
// --- test lifecycle:
|
||||
|
||||
/** Registers that there's a test controller with the given ID */
|
||||
$registerTestController(controllerId: string, label: string): void;
|
||||
/** Updates the label of an existing test controller. */
|
||||
$updateControllerLabel(controllerId: string, label: string): void;
|
||||
/** Diposes of the test controller with the given ID */
|
||||
$unregisterTestController(id: string): void;
|
||||
/** Requests tests from the given resource/uri, from the observer API. */
|
||||
$subscribeToDiffs(resource: ExtHostTestingResource, uri: UriComponents): void;
|
||||
/** Stops requesting tests from the given resource/uri, from the observer API. */
|
||||
$unsubscribeFromDiffs(resource: ExtHostTestingResource, uri: UriComponents): void;
|
||||
$unregisterTestController(controllerId: string): void;
|
||||
/** Requests tests published to VS Code. */
|
||||
$subscribeToDiffs(): void;
|
||||
/** Stops requesting tests published to VS Code. */
|
||||
$unsubscribeFromDiffs(): void;
|
||||
/** Publishes that new tests were available on the given source. */
|
||||
$publishDiff(resource: ExtHostTestingResource, uri: UriComponents, diff: TestsDiff): void;
|
||||
/** Request by an extension to run tests. */
|
||||
$runTests(req: RunTestsRequest, token: CancellationToken): Promise<string>;
|
||||
$publishDiff(controllerId: string, diff: TestsDiff): void;
|
||||
|
||||
// --- test run configurations:
|
||||
|
||||
/** Called when a new test run configuration is available */
|
||||
$publishTestRunProfile(config: ITestRunProfile): void;
|
||||
/** Updates an existing test run configuration */
|
||||
$updateTestRunConfig(controllerId: string, configId: number, update: Partial<ITestRunProfile>): void;
|
||||
/** Removes a previously-published test run config */
|
||||
$removeTestProfile(controllerId: string, configId: number): void;
|
||||
|
||||
|
||||
// --- test run handling:
|
||||
|
||||
/** Request by an extension to run tests. */
|
||||
$runTests(req: ResolvedTestRunRequest, token: CancellationToken): Promise<string>;
|
||||
/**
|
||||
* Adds tests to the run. The tests are given in descending depth. The first
|
||||
* item will be a previously-known test, or a test root.
|
||||
*/
|
||||
$addTestsToRun(runId: string, tests: ITestItem[]): void;
|
||||
$addTestsToRun(controllerId: string, runId: string, tests: ITestItem[]): void;
|
||||
/** Updates the state of a test run in the given run. */
|
||||
$updateTestStateInRun(runId: string, taskId: string, testId: string, state: TestResultState, duration?: number): void;
|
||||
/** Appends a message to a test in the run. */
|
||||
$appendTestMessageInRun(runId: string, taskId: string, testId: string, message: ITestMessage): void;
|
||||
$appendTestMessagesInRun(runId: string, taskId: string, testId: string, messages: ITestMessage[]): void;
|
||||
/** Appends raw output to the test run.. */
|
||||
$appendOutputToRun(runId: string, taskId: string, output: VSBuffer): void;
|
||||
$appendOutputToRun(runId: string, taskId: string, output: VSBuffer, location?: ILocationDto, testId?: string): void;
|
||||
/** Triggered when coverage is added to test results. */
|
||||
$signalCoverageAvailable(runId: string, taskId: string): void;
|
||||
/** Signals a task in a test run started. */
|
||||
$startedTestRunTask(runId: string, task: ITestRunTask): void;
|
||||
/** Signals a task in a test run ended. */
|
||||
@@ -2087,6 +2235,7 @@ export const MainContext = {
|
||||
MainThreadNotebookEditors: createMainId<MainThreadNotebookEditorsShape>('MainThreadNotebookEditorsShape'),
|
||||
MainThreadNotebookKernels: createMainId<MainThreadNotebookKernelsShape>('MainThreadNotebookKernels'),
|
||||
MainThreadNotebookRenderers: createMainId<MainThreadNotebookRenderersShape>('MainThreadNotebookRenderers'),
|
||||
MainThreadInteractive: createMainId<MainThreadInteractiveShape>('MainThreadInteractive'),
|
||||
MainThreadTheming: createMainId<MainThreadThemingShape>('MainThreadTheming'),
|
||||
MainThreadTunnelService: createMainId<MainThreadTunnelServiceShape>('MainThreadTunnelService'),
|
||||
MainThreadTimeline: createMainId<MainThreadTimelineShape>('MainThreadTimeline'),
|
||||
@@ -2137,6 +2286,7 @@ export const ExtHostContext = {
|
||||
ExtHostNotebookEditors: createMainId<ExtHostNotebookEditorsShape>('ExtHostNotebookEditors'),
|
||||
ExtHostNotebookKernels: createMainId<ExtHostNotebookKernelsShape>('ExtHostNotebookKernels'),
|
||||
ExtHostNotebookRenderers: createMainId<ExtHostNotebookRenderersShape>('ExtHostNotebookRenderers'),
|
||||
ExtHostInteractive: createMainId<ExtHostInteractive>('ExtHostInteractive'),
|
||||
ExtHostTheming: createMainId<ExtHostThemingShape>('ExtHostTheming'),
|
||||
ExtHostTunnelService: createMainId<ExtHostTunnelServiceShape>('ExtHostTunnelService'),
|
||||
ExtHostAuthentication: createMainId<ExtHostAuthenticationShape>('ExtHostAuthentication'),
|
||||
|
||||
@@ -7,7 +7,7 @@ import { URI } from 'vs/base/common/uri';
|
||||
import type * as vscode from 'vscode';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import { IRawColorInfo, IWorkspaceEditDto, ICallHierarchyItemDto, IIncomingCallDto, IOutgoingCallDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { IRawColorInfo, IWorkspaceEditDto, ICallHierarchyItemDto, IIncomingCallDto, IOutgoingCallDto, ITypeHierarchyItemDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import * as search from 'vs/workbench/contrib/search/common/search';
|
||||
import { ApiCommand, ApiCommandArgument, ApiCommandResult, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
@@ -406,6 +406,22 @@ const newCommands: ApiCommand[] = [
|
||||
],
|
||||
ApiCommandResult.Void
|
||||
),
|
||||
// --- type hierarchy
|
||||
new ApiCommand(
|
||||
'vscode.prepareTypeHierarchy', '_executePrepareTypeHierarchy', 'Prepare type hierarchy at a position inside a document',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<ITypeHierarchyItemDto[], types.TypeHierarchyItem[]>('A TypeHierarchyItem or undefined', v => v.map(typeConverters.TypeHierarchyItem.to))
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.provideSupertypes', '_executeProvideSupertypes', 'Compute supertypes for an item',
|
||||
[ApiCommandArgument.TypeHierarchyItem],
|
||||
new ApiCommandResult<ITypeHierarchyItemDto[], types.TypeHierarchyItem[]>('A TypeHierarchyItem or undefined', v => v.map(typeConverters.TypeHierarchyItem.to))
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.provideSubtypes', '_executeProvideSubtypes', 'Compute subtypes for an item',
|
||||
[ApiCommandArgument.TypeHierarchyItem],
|
||||
new ApiCommandResult<ITypeHierarchyItemDto[], types.TypeHierarchyItem[]>('A TypeHierarchyItem or undefined', v => v.map(typeConverters.TypeHierarchyItem.to))
|
||||
),
|
||||
];
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -27,9 +27,6 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
|
||||
private _providers: vscode.AuthenticationProviderInformation[] = [];
|
||||
|
||||
private _onDidChangeAuthenticationProviders = new Emitter<vscode.AuthenticationProvidersChangeEvent>();
|
||||
readonly onDidChangeAuthenticationProviders: Event<vscode.AuthenticationProvidersChangeEvent> = this._onDidChangeAuthenticationProviders.event;
|
||||
|
||||
private _onDidChangeSessions = new Emitter<vscode.AuthenticationSessionsChangeEvent>();
|
||||
readonly onDidChangeSessions: Event<vscode.AuthenticationSessionsChangeEvent> = this._onDidChangeSessions.event;
|
||||
|
||||
@@ -44,11 +41,9 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
get providers(): ReadonlyArray<vscode.AuthenticationProviderInformation> {
|
||||
return Object.freeze(this._providers.slice());
|
||||
}
|
||||
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions & { createIfNone: true }): Promise<vscode.AuthenticationSession>;
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions & ({ createIfNone: true } | { forceNewSession: true } | { forceNewSession: { detail: string } })): Promise<vscode.AuthenticationSession>;
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions & { forceNewSession: true }): Promise<vscode.AuthenticationSession>;
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions & { forceNewSession: { detail: string } }): Promise<vscode.AuthenticationSession>;
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions = {}): Promise<vscode.AuthenticationSession | undefined> {
|
||||
const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier);
|
||||
const inFlightRequests = this._inFlightRequests.get(extensionId) || [];
|
||||
@@ -164,22 +159,4 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
this._onDidChangeSessions.fire({ provider: { id, label } });
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
$onDidChangeAuthenticationProviders(added: modes.AuthenticationProviderInformation[], removed: modes.AuthenticationProviderInformation[]) {
|
||||
added.forEach(provider => {
|
||||
if (!this._providers.some(p => p.id === provider.id)) {
|
||||
this._providers.push(provider);
|
||||
}
|
||||
});
|
||||
|
||||
removed.forEach(p => {
|
||||
const index = this._providers.findIndex(provider => provider.id === p.id);
|
||||
if (index > -1) {
|
||||
this._providers.splice(index);
|
||||
}
|
||||
});
|
||||
|
||||
this._onDidChangeAuthenticationProviders.fire({ added, removed });
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,7 +378,8 @@ export class ApiCommandArgument<V, O = V> {
|
||||
static readonly Number = new ApiCommandArgument<number>('number', '', v => typeof v === 'number', v => v);
|
||||
static readonly String = new ApiCommandArgument<string>('string', '', v => typeof v === 'string', v => v);
|
||||
|
||||
static readonly CallHierarchyItem = new ApiCommandArgument('item', 'A call hierarchy item', v => v instanceof extHostTypes.CallHierarchyItem, extHostTypeConverter.CallHierarchyItem.to);
|
||||
static readonly CallHierarchyItem = new ApiCommandArgument('item', 'A call hierarchy item', v => v instanceof extHostTypes.CallHierarchyItem, extHostTypeConverter.CallHierarchyItem.from);
|
||||
static readonly TypeHierarchyItem = new ApiCommandArgument('item', 'A type hierarchy item', v => v instanceof extHostTypes.TypeHierarchyItem, extHostTypeConverter.TypeHierarchyItem.from);
|
||||
|
||||
constructor(
|
||||
readonly name: string,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,7 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { ExtHostWebviews, shouldSerializeBuffersForPostMessage, toExtensionData } from 'vs/workbench/api/common/extHostWebview';
|
||||
import { ExtHostWebviewPanels } from 'vs/workbench/api/common/extHostWebviewPanels';
|
||||
import { EditorGroupColumn } from 'vs/workbench/common/editor';
|
||||
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import type * as vscode from 'vscode';
|
||||
import { Cache } from './cache';
|
||||
import * as extHostProtocol from './extHost.protocol';
|
||||
|
||||
@@ -289,9 +289,11 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E
|
||||
public startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, options: vscode.DebugSessionOptions): Promise<boolean> {
|
||||
return this._debugServiceProxy.$startDebugging(folder ? folder.uri : undefined, nameOrConfig, {
|
||||
parentSessionID: options.parentSession ? options.parentSession.id : undefined,
|
||||
lifecycleManagedByParent: options.lifecycleManagedByParent,
|
||||
repl: options.consoleMode === DebugConsoleMode.MergeWithParent ? 'mergeWithParent' : 'separate',
|
||||
noDebug: options.noDebug,
|
||||
compact: options.compact
|
||||
compact: options.compact,
|
||||
debugUI: options.debugUI
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import type * as vscode from 'vscode';
|
||||
import { MainContext, MainThreadDiagnosticsShape, ExtHostDiagnosticsShape, IMainContext } from './extHost.protocol';
|
||||
import { DiagnosticSeverity } from './extHostTypes';
|
||||
import * as converter from './extHostTypeConverters';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter, DebounceEmitter } from 'vs/base/common/event';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
@@ -215,15 +215,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
|
||||
|
||||
private readonly _proxy: MainThreadDiagnosticsShape;
|
||||
private readonly _collections = new Map<string, DiagnosticCollection>();
|
||||
private readonly _onDidChangeDiagnostics = new Emitter<vscode.Uri[]>();
|
||||
|
||||
static _debouncer(last: vscode.Uri[] | undefined, current: vscode.Uri[]): vscode.Uri[] {
|
||||
if (!last) {
|
||||
return current;
|
||||
} else {
|
||||
return last.concat(current);
|
||||
}
|
||||
}
|
||||
private readonly _onDidChangeDiagnostics = new DebounceEmitter<vscode.Uri[]>({ merge: all => all.flat(), delay: 50 });
|
||||
|
||||
static _mapper(last: vscode.Uri[]): { uris: readonly vscode.Uri[] } {
|
||||
const map = new ResourceMap<vscode.Uri>();
|
||||
@@ -233,7 +225,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
|
||||
return { uris: Object.freeze(Array.from(map.values())) };
|
||||
}
|
||||
|
||||
readonly onDidChangeDiagnostics: Event<vscode.DiagnosticChangeEvent> = Event.map(Event.debounce(this._onDidChangeDiagnostics.event, ExtHostDiagnostics._debouncer, 50), ExtHostDiagnostics._mapper);
|
||||
readonly onDidChangeDiagnostics: Event<vscode.DiagnosticChangeEvent> = Event.map(this._onDidChangeDiagnostics.event, ExtHostDiagnostics._mapper);
|
||||
|
||||
constructor(mainContext: IMainContext, @ILogService private readonly _logService: ILogService) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDiagnostics);
|
||||
|
||||
@@ -143,7 +143,7 @@ export class ExtHostDocumentData extends MirrorTextModel {
|
||||
private _offsetAt(position: vscode.Position): number {
|
||||
position = this._validatePosition(position);
|
||||
this._ensureLineStarts();
|
||||
return this._lineStarts!.getAccumulatedValue(position.line - 1) + position.character;
|
||||
return this._lineStarts!.getPrefixSum(position.line - 1) + position.character;
|
||||
}
|
||||
|
||||
private _positionAt(offset: number): vscode.Position {
|
||||
|
||||
@@ -92,7 +92,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
// double check -> only notebook cell documents should be
|
||||
// referenced/opened more than once...
|
||||
if (ref) {
|
||||
if (resource.scheme !== Schemas.vscodeNotebookCell) {
|
||||
if (resource.scheme !== Schemas.vscodeNotebookCell && resource.scheme !== Schemas.vscodeInteractiveInput) {
|
||||
throw new Error(`document '${resource} already exists!'`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +204,8 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
}
|
||||
|
||||
public async deactivateAll(): Promise<void> {
|
||||
this._storagePath.onWillDeactivateAll();
|
||||
|
||||
let allPromises: Promise<void>[] = [];
|
||||
try {
|
||||
const allExtensions = this._registry.getAllExtensionDescriptions();
|
||||
@@ -551,7 +553,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
public async $extensionTestsExecute(): Promise<number> {
|
||||
await this._eagerExtensionsActivated.wait();
|
||||
try {
|
||||
return this._doHandleExtensionTests();
|
||||
return await this._doHandleExtensionTests();
|
||||
} catch (error) {
|
||||
console.error(error); // ensure any error message makes it onto the console
|
||||
throw error;
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { AsyncEmitter, IWaitUntil } from 'vs/base/common/async';
|
||||
import { Emitter, Event, AsyncEmitter, IWaitUntil } from 'vs/base/common/event';
|
||||
import { IRelativePattern, parse } from 'vs/base/common/glob';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
|
||||
60
src/vs/workbench/api/common/extHostInteractive.ts
Normal file
60
src/vs/workbench/api/common/extHostInteractive.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ExtHostInteractiveShape, IMainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ApiCommand, ApiCommandArgument, ApiCommandResult, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { NotebookEditor } from 'vscode';
|
||||
|
||||
export class ExtHostInteractive implements ExtHostInteractiveShape {
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
private _extHostNotebooks: ExtHostNotebookController,
|
||||
private _textDocumentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
private _commands: ExtHostCommands
|
||||
) {
|
||||
const apiCommand = new ApiCommand(
|
||||
'interactive.open',
|
||||
'_interactive.open',
|
||||
'Open interactive window and return notebook editor and input URI',
|
||||
[
|
||||
new ApiCommandArgument('showOptions', 'Show Options', v => true, v => v),
|
||||
new ApiCommandArgument('resource', 'Interactive resource Uri', v => true, v => v),
|
||||
new ApiCommandArgument('controllerId', 'Notebook controller Id', v => true, v => v),
|
||||
new ApiCommandArgument('title', 'Interactive editor title', v => true, v => v)
|
||||
],
|
||||
new ApiCommandResult<{ notebookUri: UriComponents, inputUri: UriComponents, notebookEditorId?: string }, { notebookUri: URI, inputUri: URI, notebookEditor?: NotebookEditor }>('Notebook and input URI', (v: { notebookUri: UriComponents, inputUri: UriComponents, notebookEditorId?: string }) => {
|
||||
if (v.notebookEditorId !== undefined) {
|
||||
const editor = this._extHostNotebooks.getEditorById(v.notebookEditorId);
|
||||
return { notebookUri: URI.revive(v.notebookUri), inputUri: URI.revive(v.inputUri), notebookEditor: editor.apiEditor };
|
||||
}
|
||||
return { notebookUri: URI.revive(v.notebookUri), inputUri: URI.revive(v.inputUri) };
|
||||
})
|
||||
);
|
||||
this._commands.registerApiCommand(apiCommand);
|
||||
}
|
||||
|
||||
$willAddInteractiveDocument(uri: UriComponents, eol: string, modeId: string, notebookUri: UriComponents) {
|
||||
this._textDocumentsAndEditors.acceptDocumentsAndEditorsDelta({
|
||||
addedDocuments: [{
|
||||
EOL: eol,
|
||||
lines: [''],
|
||||
modeId: modeId,
|
||||
uri: uri,
|
||||
isDirty: false,
|
||||
versionId: 1,
|
||||
notebook: this._extHostNotebooks.getNotebookDocument(URI.revive(notebookUri))?.apiNotebook
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
$willRemoveInteractiveDocument(uri: UriComponents, notebookUri: UriComponents) {
|
||||
this._textDocumentsAndEditors.acceptDocumentsAndEditorsDelta({
|
||||
removedDocuments: [uri]
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -987,8 +987,7 @@ class SuggestAdapter {
|
||||
//
|
||||
x: id,
|
||||
//
|
||||
[extHostProtocol.ISuggestDataDtoField.label]: item.label ?? '',
|
||||
[extHostProtocol.ISuggestDataDtoField.label2]: item.label2,
|
||||
[extHostProtocol.ISuggestDataDtoField.label]: item.label,
|
||||
[extHostProtocol.ISuggestDataDtoField.kind]: item.kind !== undefined ? typeConvert.CompletionItemKind.from(item.kind) : undefined,
|
||||
[extHostProtocol.ISuggestDataDtoField.kindModifier]: item.tags && item.tags.map(typeConvert.CompletionItemTag.from),
|
||||
[extHostProtocol.ISuggestDataDtoField.detail]: item.detail,
|
||||
@@ -1433,17 +1432,7 @@ class CallHierarchyAdapter {
|
||||
|
||||
private _cacheAndConvertItem(sessionId: string, item: vscode.CallHierarchyItem): extHostProtocol.ICallHierarchyItemDto {
|
||||
const map = this._cache.get(sessionId)!;
|
||||
const dto: extHostProtocol.ICallHierarchyItemDto = {
|
||||
_sessionId: sessionId,
|
||||
_itemId: map.size.toString(36),
|
||||
name: item.name,
|
||||
detail: item.detail,
|
||||
kind: typeConvert.SymbolKind.from(item.kind),
|
||||
uri: item.uri,
|
||||
range: typeConvert.Range.from(item.range),
|
||||
selectionRange: typeConvert.Range.from(item.selectionRange),
|
||||
tags: item.tags?.map(typeConvert.SymbolTag.from)
|
||||
};
|
||||
const dto = typeConvert.CallHierarchyItem.from(item, sessionId, map.size.toString(36));
|
||||
map.set(dto._itemId, item);
|
||||
return dto;
|
||||
}
|
||||
@@ -1454,12 +1443,86 @@ class CallHierarchyAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
class TypeHierarchyAdapter {
|
||||
|
||||
private readonly _idPool = new IdGenerator('');
|
||||
private readonly _cache = new Map<string, Map<string, vscode.TypeHierarchyItem>>();
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _provider: vscode.TypeHierarchyProvider
|
||||
) { }
|
||||
|
||||
async prepareSession(uri: URI, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {
|
||||
const doc = this._documents.getDocument(uri);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
|
||||
const items = await this._provider.prepareTypeHierarchy(doc, pos, token);
|
||||
if (!items) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const sessionId = this._idPool.nextId();
|
||||
this._cache.set(sessionId, new Map());
|
||||
|
||||
if (Array.isArray(items)) {
|
||||
return items.map(item => this._cacheAndConvertItem(sessionId, item));
|
||||
} else {
|
||||
return [this._cacheAndConvertItem(sessionId, items)];
|
||||
}
|
||||
}
|
||||
|
||||
async provideSupertypes(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {
|
||||
const item = this._itemFromCache(sessionId, itemId);
|
||||
if (!item) {
|
||||
throw new Error('missing type hierarchy item');
|
||||
}
|
||||
const supertypes = await this._provider.provideTypeHierarchySupertypes(item, token);
|
||||
if (!supertypes) {
|
||||
return undefined;
|
||||
}
|
||||
return supertypes.map(supertype => {
|
||||
return this._cacheAndConvertItem(sessionId, supertype);
|
||||
});
|
||||
}
|
||||
|
||||
async provideSubtypes(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {
|
||||
const item = this._itemFromCache(sessionId, itemId);
|
||||
if (!item) {
|
||||
throw new Error('missing type hierarchy item');
|
||||
}
|
||||
const subtypes = await this._provider.provideTypeHierarchySubtypes(item, token);
|
||||
if (!subtypes) {
|
||||
return undefined;
|
||||
}
|
||||
return subtypes.map(subtype => {
|
||||
return this._cacheAndConvertItem(sessionId, subtype);
|
||||
});
|
||||
}
|
||||
|
||||
releaseSession(sessionId: string): void {
|
||||
this._cache.delete(sessionId);
|
||||
}
|
||||
|
||||
private _cacheAndConvertItem(sessionId: string, item: vscode.TypeHierarchyItem): extHostProtocol.ITypeHierarchyItemDto {
|
||||
const map = this._cache.get(sessionId)!;
|
||||
const dto = typeConvert.TypeHierarchyItem.from(item, sessionId, map.size.toString(36));
|
||||
map.set(dto._itemId, item);
|
||||
return dto;
|
||||
}
|
||||
|
||||
private _itemFromCache(sessionId: string, itemId: string): vscode.TypeHierarchyItem | undefined {
|
||||
const map = this._cache.get(sessionId);
|
||||
return map?.get(itemId);
|
||||
}
|
||||
}
|
||||
type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
|
||||
| DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentFormattingAdapter
|
||||
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
|
||||
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter
|
||||
| TypeDefinitionAdapter | ColorProviderAdapter | FoldingProviderAdapter | DeclarationAdapter
|
||||
| SelectionRangeAdapter | CallHierarchyAdapter | DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter
|
||||
| SelectionRangeAdapter | CallHierarchyAdapter | TypeHierarchyAdapter
|
||||
| DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter
|
||||
| EvaluatableExpressionAdapter | InlineValuesAdapter
|
||||
| LinkedEditingRangeAdapter | InlayHintsAdapter | InlineCompletionAdapter;
|
||||
|
||||
@@ -2068,6 +2131,29 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
this._withAdapter(handle, CallHierarchyAdapter, adapter => Promise.resolve(adapter.releaseSession(sessionId)), undefined);
|
||||
}
|
||||
|
||||
// --- type hierarchy
|
||||
registerTypeHierarchyProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.TypeHierarchyProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new TypeHierarchyAdapter(this._documents, provider), extension);
|
||||
this._proxy.$registerTypeHierarchyProvider(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$prepareTypeHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {
|
||||
return this._withAdapter(handle, TypeHierarchyAdapter, adapter => Promise.resolve(adapter.prepareSession(URI.revive(resource), position, token)), undefined);
|
||||
}
|
||||
|
||||
$provideTypeHierarchySupertypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {
|
||||
return this._withAdapter(handle, TypeHierarchyAdapter, adapter => adapter.provideSupertypes(sessionId, itemId, token), undefined);
|
||||
}
|
||||
|
||||
$provideTypeHierarchySubtypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {
|
||||
return this._withAdapter(handle, TypeHierarchyAdapter, adapter => adapter.provideSubtypes(sessionId, itemId, token), undefined);
|
||||
}
|
||||
|
||||
$releaseTypeHierarchy(handle: number, sessionId: string): void {
|
||||
this._withAdapter(handle, TypeHierarchyAdapter, adapter => Promise.resolve(adapter.releaseSession(sessionId)), undefined);
|
||||
}
|
||||
|
||||
// --- configuration
|
||||
|
||||
private static _serializeRegExp(regExp: RegExp): extHostProtocol.IRegExpDto {
|
||||
|
||||
@@ -7,7 +7,10 @@ import { MainContext, MainThreadLanguagesShape, IMainContext } from './extHost.p
|
||||
import type * as vscode from 'vscode';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { StandardTokenType, Range, Position } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { StandardTokenType, Range, Position, LanguageStatusSeverity } from 'vs/workbench/api/common/extHostTypes';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { disposableTimeout } from 'vs/base/common/async';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export class ExtHostLanguages {
|
||||
|
||||
@@ -61,4 +64,69 @@ export class ExtHostLanguages {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private _handlePool: number = 0;
|
||||
|
||||
createLanguageStatusItem(selector: vscode.DocumentSelector): vscode.LanguageStatusItem {
|
||||
|
||||
const handle = this._handlePool++;
|
||||
const proxy = this._proxy;
|
||||
|
||||
const data: { selector: any, text: string, detail: string | vscode.MarkdownString, severity: vscode.LanguageStatusSeverity } = {
|
||||
selector,
|
||||
text: '',
|
||||
detail: '',
|
||||
severity: LanguageStatusSeverity.Information,
|
||||
};
|
||||
|
||||
let soonHandle: IDisposable | undefined;
|
||||
const updateAsync = () => {
|
||||
soonHandle?.dispose();
|
||||
soonHandle = disposableTimeout(() => {
|
||||
this._proxy.$setLanguageStatus(handle, {
|
||||
selector: data.selector,
|
||||
text: data.text,
|
||||
message: typeof data.detail === 'string' ? data.detail : typeConvert.MarkdownString.from(data.detail),
|
||||
severity: data.severity === LanguageStatusSeverity.Error ? Severity.Error : data.severity === LanguageStatusSeverity.Warning ? Severity.Warning : Severity.Info
|
||||
});
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const result: vscode.LanguageStatusItem = {
|
||||
get selector() {
|
||||
return data.selector;
|
||||
},
|
||||
set selector(value) {
|
||||
data.selector = value;
|
||||
updateAsync();
|
||||
},
|
||||
get text() {
|
||||
return data.text;
|
||||
},
|
||||
set text(value) {
|
||||
data.text = value;
|
||||
updateAsync();
|
||||
},
|
||||
get detail() {
|
||||
return data.detail;
|
||||
},
|
||||
set detail(value) {
|
||||
data.detail = value;
|
||||
updateAsync();
|
||||
},
|
||||
get severity() {
|
||||
return data.severity;
|
||||
},
|
||||
set severity(value) {
|
||||
data.severity = value;
|
||||
updateAsync();
|
||||
},
|
||||
dispose() {
|
||||
soonHandle?.dispose();
|
||||
proxy.$removeLanguageStatus(handle);
|
||||
}
|
||||
};
|
||||
updateAsync();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export class ExtensionMemento implements vscode.Memento {
|
||||
}, 0);
|
||||
}
|
||||
|
||||
get keys(): readonly string[] {
|
||||
keys(): readonly string[] {
|
||||
// Filter out `undefined` values, as they can stick around in the `_value` until the `onDidChangeStorage` event runs
|
||||
return Object.entries(this._value ?? {}).filter(([, value]) => value !== undefined).map(([key]) => key);
|
||||
}
|
||||
|
||||
@@ -37,8 +37,9 @@ export class ExtHostMessageService {
|
||||
if (typeof optionsOrFirstItem === 'string' || isMessageItem(optionsOrFirstItem)) {
|
||||
items = [optionsOrFirstItem, ...rest];
|
||||
} else {
|
||||
options.modal = optionsOrFirstItem && optionsOrFirstItem.modal;
|
||||
options.useCustom = optionsOrFirstItem && optionsOrFirstItem.useCustom;
|
||||
options.modal = optionsOrFirstItem?.modal;
|
||||
options.useCustom = optionsOrFirstItem?.useCustom;
|
||||
options.detail = optionsOrFirstItem?.detail;
|
||||
items = rest;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,19 +10,21 @@ import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { MarshalledId } from 'vs/base/common/marshalling';
|
||||
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { Cache } from 'vs/workbench/api/common/cache';
|
||||
import { ExtHostNotebookShape, IMainContext, IModelAddedData, INotebookCellStatusBarListDto, INotebookDocumentsAndEditorsDelta, INotebookDocumentShowOptions, INotebookEditorAddData, MainContext, MainThreadNotebookDocumentsShape, MainThreadNotebookEditorsShape, MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostNotebookShape, IMainContext, IModelAddedData, INotebookCellStatusBarListDto, INotebookDocumentsAndEditorsDelta, INotebookDocumentShowOptions, INotebookEditorAddData, MainContext, MainThreadNotebookDocumentsShape, MainThreadNotebookEditorsShape, MainThreadNotebookShape, NotebookDataDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { CommandsConverter, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import { INotebookExclusiveDocumentFilter, INotebookContributionData, NotebookCellsChangeType, NotebookDataDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookExclusiveDocumentFilter, INotebookContributionData } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import type * as vscode from 'vscode';
|
||||
import { ExtHostCell, ExtHostNotebookDocument } from './extHostNotebookDocument';
|
||||
import { ExtHostNotebookEditor } from './extHostNotebookEditor';
|
||||
@@ -91,7 +93,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
commands.registerArgumentProcessor({
|
||||
// Serialized INotebookCellActionContext
|
||||
processArgument: (arg) => {
|
||||
if (arg && arg.$mid === 12) {
|
||||
if (arg && arg.$mid === MarshalledId.NotebookCellActionContext) {
|
||||
const notebookUri = arg.notebookEditor?.notebookUri;
|
||||
const cellHandle = arg.cell.handle;
|
||||
|
||||
@@ -185,7 +187,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
|
||||
private static _convertNotebookRegistrationData(extension: IExtensionDescription, registration: vscode.NotebookRegistrationData | undefined): INotebookContributionData | undefined {
|
||||
if (!registration) {
|
||||
return undefined; // {{SQL CARBON EDIT}} Strict nulls
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-nulls
|
||||
}
|
||||
const viewOptionsFilenamePattern = registration.filenamePattern
|
||||
.map(pattern => typeConverters.NotebookExclusiveDocumentPattern.from(pattern))
|
||||
@@ -333,33 +335,33 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
});
|
||||
}
|
||||
|
||||
async $dataToNotebook(handle: number, bytes: VSBuffer, token: CancellationToken): Promise<NotebookDataDto> {
|
||||
async $dataToNotebook(handle: number, bytes: VSBuffer, token: CancellationToken): Promise<SerializableObjectWithBuffers<NotebookDataDto>> {
|
||||
const serializer = this._notebookSerializer.get(handle);
|
||||
if (!serializer) {
|
||||
throw new Error('NO serializer found');
|
||||
}
|
||||
const data = await serializer.deserializeNotebook(bytes.buffer, token);
|
||||
return typeConverters.NotebookData.from(data);
|
||||
return new SerializableObjectWithBuffers(typeConverters.NotebookData.from(data));
|
||||
}
|
||||
|
||||
async $notebookToData(handle: number, data: NotebookDataDto, token: CancellationToken): Promise<VSBuffer> {
|
||||
async $notebookToData(handle: number, data: SerializableObjectWithBuffers<NotebookDataDto>, token: CancellationToken): Promise<VSBuffer> {
|
||||
const serializer = this._notebookSerializer.get(handle);
|
||||
if (!serializer) {
|
||||
throw new Error('NO serializer found');
|
||||
}
|
||||
const bytes = await serializer.serializeNotebook(typeConverters.NotebookData.to(data), token);
|
||||
const bytes = await serializer.serializeNotebook(typeConverters.NotebookData.to(data.value), token);
|
||||
return VSBuffer.wrap(bytes);
|
||||
}
|
||||
|
||||
// --- open, save, saveAs, backup
|
||||
|
||||
async $openNotebook(viewType: string, uri: UriComponents, backupId: string | undefined, untitledDocumentData: VSBuffer | undefined, token: CancellationToken): Promise<NotebookDataDto> {
|
||||
async $openNotebook(viewType: string, uri: UriComponents, backupId: string | undefined, untitledDocumentData: VSBuffer | undefined, token: CancellationToken): Promise<SerializableObjectWithBuffers<NotebookDataDto>> {
|
||||
const { provider } = this._getProviderData(viewType);
|
||||
const data = await provider.openNotebook(URI.revive(uri), { backupId, untitledDocumentData: untitledDocumentData?.buffer }, token);
|
||||
return {
|
||||
return new SerializableObjectWithBuffers({
|
||||
metadata: data.metadata ?? Object.create(null),
|
||||
cells: data.cells.map(typeConverters.NotebookCellData.from),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async $saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean> {
|
||||
@@ -410,10 +412,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
this._editors.set(editorId, editor);
|
||||
}
|
||||
|
||||
$acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta): void {
|
||||
$acceptDocumentAndEditorsDelta(delta: SerializableObjectWithBuffers<INotebookDocumentsAndEditorsDelta>): void {
|
||||
|
||||
if (delta.removedDocuments) {
|
||||
for (const uri of delta.removedDocuments) {
|
||||
if (delta.value.removedDocuments) {
|
||||
for (const uri of delta.value.removedDocuments) {
|
||||
const revivedUri = URI.revive(uri);
|
||||
const document = this._documents.get(revivedUri);
|
||||
|
||||
@@ -432,13 +434,12 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
}
|
||||
}
|
||||
|
||||
if (delta.addedDocuments) {
|
||||
if (delta.value.addedDocuments) {
|
||||
|
||||
const addedCellDocuments: IModelAddedData[] = [];
|
||||
|
||||
for (const modelData of delta.addedDocuments) {
|
||||
for (const modelData of delta.value.addedDocuments) {
|
||||
const uri = URI.revive(modelData.uri);
|
||||
const viewType = modelData.viewType;
|
||||
|
||||
if (this._documents.has(uri)) {
|
||||
throw new Error(`adding EXISTING notebook ${uri} `);
|
||||
@@ -463,19 +464,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
that._onDidChangeCellExecutionState.fire(event);
|
||||
}
|
||||
},
|
||||
viewType,
|
||||
modelData.metadata ?? Object.create({}),
|
||||
uri,
|
||||
modelData
|
||||
);
|
||||
|
||||
document.acceptModelChanged({
|
||||
versionId: modelData.versionId,
|
||||
rawEvents: [{
|
||||
kind: NotebookCellsChangeType.Initialize,
|
||||
changes: [[0, 0, modelData.cells]]
|
||||
}]
|
||||
}, false);
|
||||
|
||||
// add cell document as vscode.TextDocument
|
||||
addedCellDocuments.push(...modelData.cells.map(cell => ExtHostCell.asModelAddData(document.apiNotebook, cell)));
|
||||
|
||||
@@ -487,8 +479,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
}
|
||||
}
|
||||
|
||||
if (delta.addedEditors) {
|
||||
for (const editorModelData of delta.addedEditors) {
|
||||
if (delta.value.addedEditors) {
|
||||
for (const editorModelData of delta.value.addedEditors) {
|
||||
if (this._editors.has(editorModelData.id)) {
|
||||
return;
|
||||
}
|
||||
@@ -504,8 +496,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
|
||||
const removedEditors: ExtHostNotebookEditor[] = [];
|
||||
|
||||
if (delta.removedEditors) {
|
||||
for (const editorid of delta.removedEditors) {
|
||||
if (delta.value.removedEditors) {
|
||||
for (const editorid of delta.value.removedEditors) {
|
||||
const editor = this._editors.get(editorid);
|
||||
|
||||
if (editor) {
|
||||
@@ -520,8 +512,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
}
|
||||
}
|
||||
|
||||
if (delta.visibleEditors) {
|
||||
this._visibleNotebookEditors = delta.visibleEditors.map(id => this._editors.get(id)!).filter(editor => !!editor) as ExtHostNotebookEditor[];
|
||||
if (delta.value.visibleEditors) {
|
||||
this._visibleNotebookEditors = delta.value.visibleEditors.map(id => this._editors.get(id)!).filter(editor => !!editor) as ExtHostNotebookEditor[];
|
||||
const visibleEditorsSet = new Set<string>();
|
||||
this._visibleNotebookEditors.forEach(editor => visibleEditorsSet.add(editor.id));
|
||||
|
||||
@@ -534,13 +526,13 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
this._onDidChangeVisibleNotebookEditors.fire(this.visibleNotebookEditors);
|
||||
}
|
||||
|
||||
if (delta.newActiveEditor === null) {
|
||||
if (delta.value.newActiveEditor === null) {
|
||||
// clear active notebook as current active editor is non-notebook editor
|
||||
this._activeNotebookEditor = undefined;
|
||||
} else if (delta.newActiveEditor) {
|
||||
this._activeNotebookEditor = this._editors.get(delta.newActiveEditor);
|
||||
} else if (delta.value.newActiveEditor) {
|
||||
this._activeNotebookEditor = this._editors.get(delta.value.newActiveEditor);
|
||||
}
|
||||
if (delta.newActiveEditor !== undefined) {
|
||||
if (delta.value.newActiveEditor !== undefined) {
|
||||
this._onDidChangeActiveNotebookEditor.fire(this._activeNotebookEditor?.apiEditor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,23 +107,29 @@ 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[this._cellUris.get(start.uri) ?? -1];
|
||||
const endCell = this._cells[this._cellUris.get(end.uri) ?? -1];
|
||||
|
||||
if (!startCell || !endCell) {
|
||||
const startIdx = this._cellUris.get(start.uri);
|
||||
const endIdx = this._cellUris.get(end.uri);
|
||||
|
||||
if (startIdx === undefined || endIdx === undefined) {
|
||||
return '';
|
||||
} else if (startCell === endCell) {
|
||||
return startCell.document.getText(new types.Range(start.range.start, end.range.end));
|
||||
} else {
|
||||
const a = startCell.document.getText(new types.Range(start.range.start, new types.Position(startCell.document.lineCount, 0)));
|
||||
const b = endCell.document.getText(new types.Range(new types.Position(0, 0), end.range.end));
|
||||
return a + '\n' + b;
|
||||
}
|
||||
|
||||
if (startIdx === endIdx) {
|
||||
return this._cells[startIdx].document.getText(new types.Range(start.range.start, end.range.end));
|
||||
}
|
||||
|
||||
const parts = [this._cells[startIdx].document.getText(new types.Range(start.range.start, new types.Position(this._cells[startIdx].document.lineCount, 0)))];
|
||||
for (let i = startIdx + 1; i < endIdx; i++) {
|
||||
parts.push(this._cells[i].document.getText());
|
||||
}
|
||||
parts.push(this._cells[endIdx].document.getText(new types.Range(new types.Position(0, 0), end.range.end)));
|
||||
return parts.join('\n');
|
||||
}
|
||||
|
||||
offsetAt(position: vscode.Position): number {
|
||||
const idx = this._cellLines.getIndexOf(position.line);
|
||||
const offset1 = this._cellLengths.getAccumulatedValue(idx.index - 1);
|
||||
const offset1 = this._cellLengths.getPrefixSum(idx.index - 1);
|
||||
const offset2 = this._cells[idx.index].document.offsetAt(position.with(idx.remainder));
|
||||
return offset1 + offset2;
|
||||
}
|
||||
@@ -131,13 +137,13 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
positionAt(locationOrOffset: vscode.Location | number): vscode.Position {
|
||||
if (typeof locationOrOffset === 'number') {
|
||||
const idx = this._cellLengths.getIndexOf(locationOrOffset);
|
||||
const lineCount = this._cellLines.getAccumulatedValue(idx.index - 1);
|
||||
const lineCount = this._cellLines.getPrefixSum(idx.index - 1);
|
||||
return this._cells[idx.index].document.positionAt(idx.remainder).translate(lineCount);
|
||||
}
|
||||
|
||||
const idx = this._cellUris.get(locationOrOffset.uri);
|
||||
if (idx !== undefined) {
|
||||
const line = this._cellLines.getAccumulatedValue(idx - 1);
|
||||
const line = this._cellLines.getPrefixSum(idx - 1);
|
||||
return new types.Position(line + locationOrOffset.range.start.line, locationOrOffset.range.start.character);
|
||||
}
|
||||
// do better?
|
||||
@@ -180,7 +186,7 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
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);
|
||||
const line = this._cellLines.getPrefixSum(startIdx.index - 1);
|
||||
return new types.Position(line + validCellPosition.line, validCellPosition.character);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { deepFreeze, equals } from 'vs/base/common/objects';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { INotebookDocumentPropertiesChangeData, MainThreadNotebookDocumentsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { ExtHostDocumentsAndEditors, IExtHostModelAddedData } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import { CellKind, IMainCellDto, IOutputDto, IOutputItemDto, NotebookCellInternalMetadata, NotebookCellMetadata, NotebookCellsChangedEventDto, NotebookCellsChangeType, NotebookCellsSplice2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import * as notebookCommon from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
class RawContentChangeEvent {
|
||||
@@ -32,7 +32,7 @@ class RawContentChangeEvent {
|
||||
|
||||
export class ExtHostCell {
|
||||
|
||||
static asModelAddData(notebook: vscode.NotebookDocument, cell: IMainCellDto): IExtHostModelAddedData {
|
||||
static asModelAddData(notebook: vscode.NotebookDocument, cell: extHostProtocol.NotebookCellDto): IExtHostModelAddedData {
|
||||
return {
|
||||
EOL: cell.eol,
|
||||
lines: cell.source,
|
||||
@@ -45,31 +45,32 @@ export class ExtHostCell {
|
||||
}
|
||||
|
||||
private _outputs: vscode.NotebookCellOutput[];
|
||||
private _metadata: NotebookCellMetadata;
|
||||
private _previousResult: vscode.NotebookCellExecutionSummary | undefined;
|
||||
private _metadata: Readonly<notebookCommon.NotebookCellMetadata>;
|
||||
private _previousResult: Readonly<vscode.NotebookCellExecutionSummary | undefined>;
|
||||
|
||||
private _internalMetadata: NotebookCellInternalMetadata;
|
||||
private _internalMetadata: notebookCommon.NotebookCellInternalMetadata;
|
||||
readonly handle: number;
|
||||
readonly uri: URI;
|
||||
readonly cellKind: CellKind;
|
||||
readonly cellKind: notebookCommon.CellKind;
|
||||
|
||||
private _apiCell: vscode.NotebookCell | undefined;
|
||||
private _mime: string | undefined;
|
||||
|
||||
constructor(
|
||||
readonly notebook: ExtHostNotebookDocument,
|
||||
private readonly _extHostDocument: ExtHostDocumentsAndEditors,
|
||||
private readonly _cellData: IMainCellDto,
|
||||
private readonly _cellData: extHostProtocol.NotebookCellDto,
|
||||
) {
|
||||
this.handle = _cellData.handle;
|
||||
this.uri = URI.revive(_cellData.uri);
|
||||
this.cellKind = _cellData.cellKind;
|
||||
this._outputs = _cellData.outputs.map(extHostTypeConverters.NotebookCellOutput.to);
|
||||
this._internalMetadata = _cellData.internalMetadata ?? {};
|
||||
this._metadata = _cellData.metadata ?? {};
|
||||
this._previousResult = extHostTypeConverters.NotebookCellExecutionSummary.to(_cellData.internalMetadata ?? {});
|
||||
this._metadata = Object.freeze(_cellData.metadata ?? {});
|
||||
this._previousResult = Object.freeze(extHostTypeConverters.NotebookCellExecutionSummary.to(_cellData.internalMetadata ?? {}));
|
||||
}
|
||||
|
||||
get internalMetadata(): NotebookCellInternalMetadata {
|
||||
get internalMetadata(): notebookCommon.NotebookCellInternalMetadata {
|
||||
return this._internalMetadata;
|
||||
}
|
||||
|
||||
@@ -85,6 +86,8 @@ export class ExtHostCell {
|
||||
notebook: that.notebook.apiNotebook,
|
||||
kind: extHostTypeConverters.NotebookCellKind.to(this._cellData.cellKind),
|
||||
document: data.document,
|
||||
get mime() { return that._mime; },
|
||||
set mime(value: string | undefined) { that._mime = value; },
|
||||
get outputs() { return that._outputs.slice(0); },
|
||||
get metadata() { return that._metadata; },
|
||||
get executionSummary() { return that._previousResult; }
|
||||
@@ -93,11 +96,11 @@ export class ExtHostCell {
|
||||
return this._apiCell;
|
||||
}
|
||||
|
||||
setOutputs(newOutputs: IOutputDto[]): void {
|
||||
setOutputs(newOutputs: extHostProtocol.NotebookOutputDto[]): void {
|
||||
this._outputs = newOutputs.map(extHostTypeConverters.NotebookCellOutput.to);
|
||||
}
|
||||
|
||||
setOutputItems(outputId: string, append: boolean, newOutputItems: IOutputItemDto[]) {
|
||||
setOutputItems(outputId: string, append: boolean, newOutputItems: extHostProtocol.NotebookOutputItemDto[]) {
|
||||
const newItems = newOutputItems.map(extHostTypeConverters.NotebookCellOutputItem.to);
|
||||
const output = this._outputs.find(op => op.id === outputId);
|
||||
if (output) {
|
||||
@@ -108,13 +111,17 @@ export class ExtHostCell {
|
||||
}
|
||||
}
|
||||
|
||||
setMetadata(newMetadata: NotebookCellMetadata): void {
|
||||
this._metadata = newMetadata;
|
||||
setMetadata(newMetadata: notebookCommon.NotebookCellMetadata): void {
|
||||
this._metadata = Object.freeze(newMetadata);
|
||||
}
|
||||
|
||||
setInternalMetadata(newInternalMetadata: NotebookCellInternalMetadata): void {
|
||||
setInternalMetadata(newInternalMetadata: notebookCommon.NotebookCellInternalMetadata): void {
|
||||
this._internalMetadata = newInternalMetadata;
|
||||
this._previousResult = extHostTypeConverters.NotebookCellExecutionSummary.to(newInternalMetadata);
|
||||
this._previousResult = Object.freeze(extHostTypeConverters.NotebookCellExecutionSummary.to(newInternalMetadata));
|
||||
}
|
||||
|
||||
setMime(newMime: string | undefined) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,23 +138,30 @@ export class ExtHostNotebookDocument {
|
||||
private static _handlePool: number = 0;
|
||||
readonly handle = ExtHostNotebookDocument._handlePool++;
|
||||
|
||||
private _cells: ExtHostCell[] = [];
|
||||
private readonly _cells: ExtHostCell[] = [];
|
||||
|
||||
private readonly _notebookType: string;
|
||||
|
||||
private _notebook: vscode.NotebookDocument | undefined;
|
||||
private _metadata: Record<string, any>;
|
||||
private _versionId: number = 0;
|
||||
private _isDirty: boolean = false;
|
||||
private _backup?: vscode.NotebookDocumentBackup;
|
||||
private _disposed: boolean = false;
|
||||
|
||||
constructor(
|
||||
private readonly _proxy: MainThreadNotebookDocumentsShape,
|
||||
private readonly _proxy: extHostProtocol.MainThreadNotebookDocumentsShape,
|
||||
private readonly _textDocumentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
private readonly _textDocuments: ExtHostDocuments,
|
||||
private readonly _emitter: INotebookEventEmitter,
|
||||
private readonly _notebookType: string,
|
||||
private _metadata: Record<string, any>,
|
||||
readonly uri: URI,
|
||||
) { }
|
||||
data: extHostProtocol.INotebookModelAddedData
|
||||
) {
|
||||
this._notebookType = data.viewType;
|
||||
this._metadata = Object.freeze(data.metadata ?? Object.create(null));
|
||||
this._spliceNotebookCells([[0, 0, data.cells]], true /* init -> no event*/);
|
||||
this._versionId = data.versionId;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._disposed = true;
|
||||
@@ -191,32 +205,36 @@ export class ExtHostNotebookDocument {
|
||||
this._backup = undefined;
|
||||
}
|
||||
|
||||
acceptDocumentPropertiesChanged(data: INotebookDocumentPropertiesChangeData) {
|
||||
acceptDocumentPropertiesChanged(data: extHostProtocol.INotebookDocumentPropertiesChangeData) {
|
||||
if (data.metadata) {
|
||||
this._metadata = { ...this._metadata, ...data.metadata };
|
||||
this._metadata = Object.freeze({ ...this._metadata, ...data.metadata });
|
||||
}
|
||||
}
|
||||
|
||||
acceptModelChanged(event: NotebookCellsChangedEventDto, isDirty: boolean): void {
|
||||
acceptDirty(isDirty: boolean): void {
|
||||
this._isDirty = isDirty;
|
||||
}
|
||||
|
||||
acceptModelChanged(event: extHostProtocol.NotebookCellsChangedEventDto, isDirty: boolean): void {
|
||||
this._versionId = event.versionId;
|
||||
this._isDirty = isDirty;
|
||||
|
||||
for (const rawEvent of event.rawEvents) {
|
||||
if (rawEvent.kind === NotebookCellsChangeType.Initialize) {
|
||||
this._spliceNotebookCells(rawEvent.changes, true);
|
||||
} if (rawEvent.kind === NotebookCellsChangeType.ModelChange) {
|
||||
if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ModelChange) {
|
||||
this._spliceNotebookCells(rawEvent.changes, false);
|
||||
} else if (rawEvent.kind === NotebookCellsChangeType.Move) {
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.Move) {
|
||||
this._moveCell(rawEvent.index, rawEvent.newIdx);
|
||||
} else if (rawEvent.kind === NotebookCellsChangeType.Output) {
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.Output) {
|
||||
this._setCellOutputs(rawEvent.index, rawEvent.outputs);
|
||||
} else if (rawEvent.kind === NotebookCellsChangeType.OutputItem) {
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.OutputItem) {
|
||||
this._setCellOutputItems(rawEvent.index, rawEvent.outputId, rawEvent.append, rawEvent.outputItems);
|
||||
} else if (rawEvent.kind === NotebookCellsChangeType.ChangeLanguage) {
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeLanguage) {
|
||||
this._changeCellLanguage(rawEvent.index, rawEvent.language);
|
||||
} else if (rawEvent.kind === NotebookCellsChangeType.ChangeCellMetadata) {
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMime) {
|
||||
this._changeCellMime(rawEvent.index, rawEvent.mime);
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMetadata) {
|
||||
this._changeCellMetadata(rawEvent.index, rawEvent.metadata);
|
||||
} else if (rawEvent.kind === NotebookCellsChangeType.ChangeCellInternalMetadata) {
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellInternalMetadata) {
|
||||
this._changeCellInternalMetadata(rawEvent.index, rawEvent.internalMetadata);
|
||||
}
|
||||
}
|
||||
@@ -261,7 +279,7 @@ export class ExtHostNotebookDocument {
|
||||
return this._proxy.$trySaveNotebook(this.uri);
|
||||
}
|
||||
|
||||
private _spliceNotebookCells(splices: NotebookCellsSplice2[], initialization: boolean): void {
|
||||
private _spliceNotebookCells(splices: notebookCommon.NotebookCellTextModelSplice<extHostProtocol.NotebookCellDto>[], initialization: boolean): void {
|
||||
if (this._disposed) {
|
||||
return;
|
||||
}
|
||||
@@ -317,13 +335,13 @@ export class ExtHostNotebookDocument {
|
||||
}));
|
||||
}
|
||||
|
||||
private _setCellOutputs(index: number, outputs: IOutputDto[]): void {
|
||||
private _setCellOutputs(index: number, outputs: extHostProtocol.NotebookOutputDto[]): void {
|
||||
const cell = this._cells[index];
|
||||
cell.setOutputs(outputs);
|
||||
this._emitter.emitCellOutputsChange(deepFreeze({ document: this.apiNotebook, cells: [cell.apiCell] }));
|
||||
}
|
||||
|
||||
private _setCellOutputItems(index: number, outputId: string, append: boolean, outputItems: IOutputItemDto[]): void {
|
||||
private _setCellOutputItems(index: number, outputId: string, append: boolean, outputItems: extHostProtocol.NotebookOutputItemDto[]): void {
|
||||
const cell = this._cells[index];
|
||||
cell.setOutputItems(outputId, append, outputItems);
|
||||
this._emitter.emitCellOutputsChange(deepFreeze({ document: this.apiNotebook, cells: [cell.apiCell] }));
|
||||
@@ -336,7 +354,12 @@ export class ExtHostNotebookDocument {
|
||||
}
|
||||
}
|
||||
|
||||
private _changeCellMetadata(index: number, newMetadata: NotebookCellMetadata): void {
|
||||
private _changeCellMime(index: number, newMime: string | undefined): void {
|
||||
const cell = this._cells[index];
|
||||
cell.apiCell.mime = newMime;
|
||||
}
|
||||
|
||||
private _changeCellMetadata(index: number, newMetadata: notebookCommon.NotebookCellMetadata): void {
|
||||
const cell = this._cells[index];
|
||||
|
||||
const originalExtMetadata = cell.apiCell.metadata;
|
||||
@@ -348,7 +371,7 @@ export class ExtHostNotebookDocument {
|
||||
}
|
||||
}
|
||||
|
||||
private _changeCellInternalMetadata(index: number, newInternalMetadata: NotebookCellInternalMetadata): void {
|
||||
private _changeCellInternalMetadata(index: number, newInternalMetadata: notebookCommon.NotebookCellInternalMetadata): void {
|
||||
const cell = this._cells[index];
|
||||
|
||||
const originalInternalMetadata = cell.internalMetadata;
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ExtHostNotebookDocumentsShape, INotebookDocumentPropertiesChangeData } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { NotebookCellsChangedEventDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
export class ExtHostNotebookDocuments implements ExtHostNotebookDocumentsShape {
|
||||
export class ExtHostNotebookDocuments implements extHostProtocol.ExtHostNotebookDocumentsShape {
|
||||
|
||||
private readonly _onDidChangeNotebookDocumentMetadata = new Emitter<vscode.NotebookDocumentMetadataChangeEvent>();
|
||||
readonly onDidChangeNotebookDocumentMetadata = this._onDidChangeNotebookDocumentMetadata.event;
|
||||
@@ -24,14 +24,14 @@ export class ExtHostNotebookDocuments implements ExtHostNotebookDocumentsShape {
|
||||
private readonly _notebooksAndEditors: ExtHostNotebookController,
|
||||
) { }
|
||||
|
||||
$acceptModelChanged(uri: UriComponents, event: NotebookCellsChangedEventDto, isDirty: boolean): void {
|
||||
$acceptModelChanged(uri: UriComponents, event: SerializableObjectWithBuffers<extHostProtocol.NotebookCellsChangedEventDto>, isDirty: boolean): void {
|
||||
const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri));
|
||||
document.acceptModelChanged(event, isDirty);
|
||||
document.acceptModelChanged(event.value, isDirty);
|
||||
}
|
||||
|
||||
$acceptDirtyStateChanged(uri: UriComponents, isDirty: boolean): void {
|
||||
const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri));
|
||||
document.acceptModelChanged({ rawEvents: [], versionId: document.apiNotebook.version }, isDirty);
|
||||
document.acceptDirty(isDirty);
|
||||
}
|
||||
|
||||
$acceptModelSaved(uri: UriComponents): void {
|
||||
@@ -39,7 +39,7 @@ export class ExtHostNotebookDocuments implements ExtHostNotebookDocumentsShape {
|
||||
this._onDidSaveNotebookDocument.fire(document.apiNotebook);
|
||||
}
|
||||
|
||||
$acceptDocumentPropertiesChanged(uri: UriComponents, data: INotebookDocumentPropertiesChangeData): void {
|
||||
$acceptDocumentPropertiesChanged(uri: UriComponents, data: extHostProtocol.INotebookDocumentPropertiesChangeData): void {
|
||||
this._logService.debug('ExtHostNotebook#$acceptDocumentPropertiesChanged', uri.path, data);
|
||||
const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri));
|
||||
document.acceptDocumentPropertiesChanged(data);
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MainThreadNotebookEditorsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ICellEditOperationDto, MainThreadNotebookEditorsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as extHostConverter from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { CellEditType, ICellEditOperation, ICellReplaceEdit } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellEditType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostNotebookDocument } from './extHostNotebookDocument';
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
|
||||
interface INotebookEditData {
|
||||
documentVersionId: number;
|
||||
cellEdits: ICellEditOperation[];
|
||||
cellEdits: ICellEditOperationDto[];
|
||||
}
|
||||
|
||||
class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit {
|
||||
@@ -21,7 +21,7 @@ class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit {
|
||||
private readonly _documentVersionId: number;
|
||||
|
||||
private _finalized: boolean = false;
|
||||
private _collectedEdits: ICellEditOperation[] = [];
|
||||
private _collectedEdits: ICellEditOperationDto[] = [];
|
||||
|
||||
constructor(documentVersionId: number) {
|
||||
this._documentVersionId = documentVersionId;
|
||||
@@ -52,7 +52,7 @@ class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit {
|
||||
replaceCellMetadata(index: number, metadata: Record<string, any>): void {
|
||||
this._throwIfFinalized();
|
||||
this._collectedEdits.push({
|
||||
editType: CellEditType.Metadata,
|
||||
editType: CellEditType.PartialMetadata,
|
||||
index,
|
||||
metadata
|
||||
});
|
||||
@@ -174,7 +174,7 @@ export class ExtHostNotebookEditor {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
const compressedEdits: ICellEditOperation[] = [];
|
||||
const compressedEdits: ICellEditOperationDto[] = [];
|
||||
let compressedEditsIndex = -1;
|
||||
|
||||
for (let i = 0; i < editData.cellEdits.length; i++) {
|
||||
@@ -190,8 +190,8 @@ export class ExtHostNotebookEditor {
|
||||
const edit = editData.cellEdits[i];
|
||||
if (prev.editType === CellEditType.Replace && edit.editType === CellEditType.Replace) {
|
||||
if (prev.index === edit.index) {
|
||||
prev.cells.push(...(editData.cellEdits[i] as ICellReplaceEdit).cells);
|
||||
prev.count += (editData.cellEdits[i] as ICellReplaceEdit).count;
|
||||
prev.cells.push(...(editData.cellEdits[i] as any).cells);
|
||||
prev.count += (editData.cellEdits[i] as any).count;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,25 +3,26 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { asArray } from 'vs/base/common/arrays';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostNotebookKernelsShape, IMainContext, INotebookKernelDto2, MainContext, MainThreadNotebookDocumentsShape, MainThreadNotebookKernelsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { asWebviewUri } from 'vs/workbench/api/common/shared/webview';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { ExtHostCell, ExtHostNotebookDocument } from 'vs/workbench/api/common/extHostNotebookDocument';
|
||||
import { CellEditType, IImmediateCellEditOperation, IOutputDto, NotebookCellExecutionState, NullablePartialNotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { asArray } from 'vs/base/common/arrays';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ExtHostNotebookKernelsShape, ICellExecuteUpdateDto, IMainContext, INotebookKernelDto2, MainContext, MainThreadNotebookKernelsShape, NotebookOutputDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtHostCell, ExtHostNotebookDocument } from 'vs/workbench/api/common/extHostNotebookDocument';
|
||||
import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { NotebookCellOutput } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { asWebviewUri } from 'vs/workbench/api/common/shared/webview';
|
||||
import { CellExecutionUpdateType } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
|
||||
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
interface IKernelData {
|
||||
extensionId: ExtensionIdentifier,
|
||||
@@ -40,12 +41,12 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
private _handlePool: number = 0;
|
||||
|
||||
constructor(
|
||||
private readonly _mainContext: IMainContext,
|
||||
mainContext: IMainContext,
|
||||
private readonly _initData: IExtHostInitDataService,
|
||||
private readonly _extHostNotebook: ExtHostNotebookController,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
) {
|
||||
this._proxy = _mainContext.getProxy(MainContext.MainThreadNotebookKernels);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadNotebookKernels);
|
||||
}
|
||||
|
||||
createNotebookController(extension: IExtensionDescription, id: string, viewType: string, label: string, handler?: (cells: vscode.NotebookCell[], notebook: vscode.NotebookDocument, controller: vscode.NotebookController) => void | Thenable<void>, preloads?: vscode.NotebookRendererScript[]): vscode.NotebookController {
|
||||
@@ -303,7 +304,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
if (this._activeExecutions.has(cellObj.uri)) {
|
||||
throw new Error(`duplicate execution for ${cellObj.uri}`);
|
||||
}
|
||||
const execution = new NotebookCellExecutionTask(cellObj.notebook, cellObj, this._mainContext.getProxy(MainContext.MainThreadNotebookDocuments));
|
||||
const execution = new NotebookCellExecutionTask(cellObj.notebook, cellObj, this._proxy);
|
||||
this._activeExecutions.set(cellObj.uri, execution);
|
||||
const listener = execution.onDidChangeState(() => {
|
||||
if (execution.state === NotebookCellExecutionTaskState.Resolved) {
|
||||
@@ -324,6 +325,9 @@ export enum NotebookCellExecutionTaskState { // {{SQL CARBON EDIT}} Use for our
|
||||
}
|
||||
|
||||
class NotebookCellExecutionTask extends Disposable {
|
||||
private static HANDLE = 0;
|
||||
private _handle = NotebookCellExecutionTask.HANDLE++;
|
||||
|
||||
private _onDidChangeState = new Emitter<void>();
|
||||
readonly onDidChangeState = this._onDidChangeState.event;
|
||||
|
||||
@@ -332,36 +336,34 @@ class NotebookCellExecutionTask extends Disposable {
|
||||
|
||||
private readonly _tokenSource = this._register(new CancellationTokenSource());
|
||||
|
||||
private readonly _collector: TimeoutBasedCollector<IImmediateCellEditOperation>;
|
||||
private readonly _collector: TimeoutBasedCollector<ICellExecuteUpdateDto>;
|
||||
|
||||
private _executionOrder: number | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly _document: ExtHostNotebookDocument,
|
||||
private readonly _cell: ExtHostCell,
|
||||
private readonly _proxy: MainThreadNotebookDocumentsShape
|
||||
private readonly _proxy: MainThreadNotebookKernelsShape
|
||||
) {
|
||||
super();
|
||||
|
||||
this._collector = new TimeoutBasedCollector(10, edits => this.applyEdits(edits));
|
||||
this._collector = new TimeoutBasedCollector(10, updates => this.update(updates));
|
||||
|
||||
this._executionOrder = _cell.internalMetadata.executionOrder;
|
||||
this.mixinMetadata({
|
||||
runState: NotebookCellExecutionState.Pending,
|
||||
executionOrder: null
|
||||
});
|
||||
this._proxy.$addExecution(this._handle, this._cell.notebook.uri, this._cell.handle);
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
this._tokenSource.cancel();
|
||||
}
|
||||
|
||||
private async applyEditSoon(edit: IImmediateCellEditOperation): Promise<void> {
|
||||
await this._collector.addItem(edit);
|
||||
private async updateSoon(update: ICellExecuteUpdateDto): Promise<void> {
|
||||
await this._collector.addItem(update);
|
||||
}
|
||||
|
||||
private async applyEdits(edits: IImmediateCellEditOperation[]): Promise<void> {
|
||||
return this._proxy.$applyEdits(this._document.uri, edits, false);
|
||||
private async update(update: ICellExecuteUpdateDto | ICellExecuteUpdateDto[]): Promise<void> {
|
||||
const updates = Array.isArray(update) ? update : [update];
|
||||
return this._proxy.$updateExecutions(new SerializableObjectWithBuffers(updates));
|
||||
}
|
||||
|
||||
private verifyStateForOutput() {
|
||||
@@ -374,17 +376,9 @@ class NotebookCellExecutionTask extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private mixinMetadata(mixinMetadata: NullablePartialNotebookCellInternalMetadata) {
|
||||
const edit: IImmediateCellEditOperation = { editType: CellEditType.PartialInternalMetadata, handle: this._cell.handle, internalMetadata: mixinMetadata };
|
||||
this.applyEdits([edit]);
|
||||
}
|
||||
|
||||
private cellIndexToHandle(cellOrCellIndex: vscode.NotebookCell | number | undefined): number {
|
||||
private cellIndexToHandle(cellOrCellIndex: vscode.NotebookCell | undefined): number {
|
||||
let cell: ExtHostCell | undefined = this._cell;
|
||||
if (typeof cellOrCellIndex === 'number') {
|
||||
// todo@jrieken remove support for number shortly
|
||||
cell = this._document.getCellFromIndex(cellOrCellIndex);
|
||||
} else if (cellOrCellIndex) {
|
||||
if (cellOrCellIndex) {
|
||||
cell = this._document.getCellFromApiCell(cellOrCellIndex);
|
||||
}
|
||||
if (!cell) {
|
||||
@@ -393,7 +387,7 @@ class NotebookCellExecutionTask extends Disposable {
|
||||
return cell.handle;
|
||||
}
|
||||
|
||||
private validateAndConvertOutputs(items: vscode.NotebookCellOutput[]): IOutputDto[] {
|
||||
private validateAndConvertOutputs(items: vscode.NotebookCellOutput[]): NotebookOutputDto[] {
|
||||
return items.map(output => {
|
||||
const newOutput = NotebookCellOutput.ensureUniqueMimeTypes(output.items, true);
|
||||
if (newOutput === output.items) {
|
||||
@@ -407,18 +401,28 @@ class NotebookCellExecutionTask extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
private async updateOutputs(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell: vscode.NotebookCell | number | undefined, append: boolean): Promise<void> {
|
||||
private async updateOutputs(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell: vscode.NotebookCell | undefined, append: boolean): Promise<void> {
|
||||
const handle = this.cellIndexToHandle(cell);
|
||||
const outputDtos = this.validateAndConvertOutputs(asArray(outputs));
|
||||
return this.applyEditSoon({ editType: CellEditType.Output, handle, append, outputs: outputDtos });
|
||||
return this.updateSoon(
|
||||
{
|
||||
editType: CellExecutionUpdateType.Output,
|
||||
executionHandle: this._handle,
|
||||
cellHandle: handle,
|
||||
append,
|
||||
outputs: outputDtos
|
||||
});
|
||||
}
|
||||
|
||||
private async updateOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], outputOrOutputId: vscode.NotebookCellOutput | string, append: boolean): Promise<void> {
|
||||
if (NotebookCellOutput.isNotebookCellOutput(outputOrOutputId)) {
|
||||
outputOrOutputId = outputOrOutputId.id;
|
||||
}
|
||||
private async updateOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput, append: boolean): Promise<void> {
|
||||
items = NotebookCellOutput.ensureUniqueMimeTypes(asArray(items), true);
|
||||
return this.applyEditSoon({ editType: CellEditType.OutputItems, items: items.map(extHostTypeConverters.NotebookCellOutputItem.from), outputId: outputOrOutputId, append });
|
||||
return this.updateSoon({
|
||||
editType: CellExecutionUpdateType.OutputItems,
|
||||
executionHandle: this._handle,
|
||||
items: items.map(extHostTypeConverters.NotebookCellOutputItem.from),
|
||||
outputId: output.id,
|
||||
append
|
||||
});
|
||||
}
|
||||
|
||||
asApiObject(): vscode.NotebookCellExecution {
|
||||
@@ -429,9 +433,11 @@ class NotebookCellExecutionTask extends Disposable {
|
||||
get executionOrder() { return that._executionOrder; },
|
||||
set executionOrder(v: number | undefined) {
|
||||
that._executionOrder = v;
|
||||
that.mixinMetadata({
|
||||
executionOrder: v
|
||||
});
|
||||
that.update([{
|
||||
editType: CellExecutionUpdateType.ExecutionState,
|
||||
executionHandle: that._handle,
|
||||
executionOrder: that._executionOrder
|
||||
}]);
|
||||
},
|
||||
|
||||
start(startTime?: number): void {
|
||||
@@ -442,9 +448,10 @@ class NotebookCellExecutionTask extends Disposable {
|
||||
that._state = NotebookCellExecutionTaskState.Started;
|
||||
that._onDidChangeState.fire();
|
||||
|
||||
that.mixinMetadata({
|
||||
runState: NotebookCellExecutionState.Executing,
|
||||
runStartTime: startTime ?? null
|
||||
that.update({
|
||||
editType: CellExecutionUpdateType.ExecutionState,
|
||||
executionHandle: that._handle,
|
||||
runStartTime: startTime
|
||||
});
|
||||
},
|
||||
|
||||
@@ -456,34 +463,41 @@ class NotebookCellExecutionTask extends Disposable {
|
||||
that._state = NotebookCellExecutionTaskState.Resolved;
|
||||
that._onDidChangeState.fire();
|
||||
|
||||
that.mixinMetadata({
|
||||
runState: null,
|
||||
lastRunSuccess: success ?? null,
|
||||
runEndTime: endTime ?? null,
|
||||
that.updateSoon({
|
||||
editType: CellExecutionUpdateType.Complete,
|
||||
executionHandle: that._handle,
|
||||
runEndTime: endTime,
|
||||
lastRunSuccess: success
|
||||
});
|
||||
|
||||
// The last update needs to be ordered correctly and applied immediately,
|
||||
// so we use updateSoon and immediately flush.
|
||||
that._collector.flush();
|
||||
|
||||
that._proxy.$removeExecution(that._handle);
|
||||
},
|
||||
|
||||
clearOutput(cell?: vscode.NotebookCell | number): Thenable<void> {
|
||||
clearOutput(cell?: vscode.NotebookCell): Thenable<void> {
|
||||
that.verifyStateForOutput();
|
||||
return that.updateOutputs([], cell, false);
|
||||
},
|
||||
|
||||
appendOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell | number): Promise<void> {
|
||||
appendOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
return that.updateOutputs(outputs, cell, true);
|
||||
},
|
||||
|
||||
replaceOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell | number): Promise<void> {
|
||||
replaceOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
return that.updateOutputs(outputs, cell, false);
|
||||
},
|
||||
|
||||
appendOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput | string): Promise<void> {
|
||||
appendOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
return that.updateOutputItems(items, output, true);
|
||||
},
|
||||
|
||||
replaceOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput | string): Promise<void> {
|
||||
replaceOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
return that.updateOutputItems(items, output, false);
|
||||
}
|
||||
@@ -495,22 +509,38 @@ class NotebookCellExecutionTask extends Disposable {
|
||||
class TimeoutBasedCollector<T> {
|
||||
private batch: T[] = [];
|
||||
private waitPromise: Promise<void> | undefined;
|
||||
private lastFlush = Date.now();
|
||||
|
||||
constructor(
|
||||
private readonly delay: number,
|
||||
private readonly callback: (items: T[]) => Promise<void>) { }
|
||||
private readonly callback: (items: T[]) => Promise<void> | void) { }
|
||||
|
||||
addItem(item: T): Promise<void> {
|
||||
this.batch.push(item);
|
||||
if (!this.waitPromise) {
|
||||
this.waitPromise = timeout(this.delay).then(() => {
|
||||
this.waitPromise = undefined;
|
||||
const batch = this.batch;
|
||||
this.batch = [];
|
||||
return this.callback(batch);
|
||||
return this.flush();
|
||||
});
|
||||
}
|
||||
|
||||
// This can be called by the extension repeatedly for a long time before the timeout is able to run.
|
||||
// Force a flush after the delay.
|
||||
if (Date.now() - this.lastFlush > this.delay) {
|
||||
this.flush();
|
||||
}
|
||||
|
||||
return this.waitPromise;
|
||||
}
|
||||
|
||||
flush(): void | Promise<void> {
|
||||
if (this.batch.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastFlush = Date.now();
|
||||
this.waitPromise = undefined;
|
||||
const batch = this.batch;
|
||||
this.batch = [];
|
||||
return this.callback(batch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtHostNotebookRenderersShape, IMainContext, MainContext, MainThreadNotebookRenderersShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtHostNotebookEditor } from 'vs/workbench/api/common/extHostNotebookEditor';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
|
||||
export class ExtHostNotebookRenderers implements ExtHostNotebookRenderersShape {
|
||||
private readonly _rendererMessageEmitters = new Map<string /* rendererId */, Emitter<vscode.NotebookRendererMessage<any>>>();
|
||||
private readonly _rendererMessageEmitters = new Map<string /* rendererId */, Emitter<{ editor: vscode.NotebookEditor, message: any }>>();
|
||||
private readonly proxy: MainThreadNotebookRenderersShape;
|
||||
|
||||
constructor(mainContext: IMainContext, private readonly _extHostNotebook: ExtHostNotebookController) {
|
||||
@@ -22,17 +24,35 @@ export class ExtHostNotebookRenderers implements ExtHostNotebookRenderersShape {
|
||||
this._rendererMessageEmitters.get(rendererId)?.fire({ editor: editor.apiEditor, message });
|
||||
}
|
||||
|
||||
public createRendererMessaging<TSend, TRecv>(rendererId: string): vscode.NotebookRendererMessaging<TSend, TRecv> {
|
||||
const messaging: vscode.NotebookRendererMessaging<TSend, TRecv> = {
|
||||
onDidReceiveMessage: (...args) =>
|
||||
this.getOrCreateEmitterFor(rendererId).event(...args),
|
||||
postMessage: (editor, message) => {
|
||||
const extHostEditor = ExtHostNotebookEditor.apiEditorsToExtHost.get(editor);
|
||||
if (!extHostEditor) {
|
||||
throw new Error(`The first argument to postMessage() must be a NotebookEditor`);
|
||||
public createRendererMessaging(manifest: IExtensionManifest, rendererId: string): vscode.NotebookRendererMessaging {
|
||||
if (!manifest.contributes?.notebookRenderer?.some(r => r.id === rendererId)) {
|
||||
throw new Error(`Extensions may only call createRendererMessaging() for renderers they contribute (got ${rendererId})`);
|
||||
}
|
||||
|
||||
// In the stable API, the editor is given as an empty object, and this map
|
||||
// is used to maintain references. This can be removed after editor finalization.
|
||||
const notebookEditorVisible = !!manifest.enableProposedApi;
|
||||
const notebookEditorAliases = new WeakMap<{}, vscode.NotebookEditor>();
|
||||
|
||||
const messaging: vscode.NotebookRendererMessaging = {
|
||||
onDidReceiveMessage: (listener, thisArg, disposables) => {
|
||||
const wrappedListener = notebookEditorVisible ? listener : (evt: { editor: vscode.NotebookEditor, message: any }) => {
|
||||
const obj = {};
|
||||
notebookEditorAliases.set(obj, evt.editor);
|
||||
listener({ editor: obj as vscode.NotebookEditor, message: evt.message });
|
||||
};
|
||||
|
||||
return this.getOrCreateEmitterFor(rendererId).event(wrappedListener, thisArg, disposables);
|
||||
},
|
||||
postMessage: (message, editorOrAlias) => {
|
||||
if (ExtHostNotebookEditor.apiEditorsToExtHost.has(message)) { // back compat for swapped args
|
||||
[message, editorOrAlias] = [editorOrAlias, message];
|
||||
}
|
||||
|
||||
this.proxy.$postMessage(extHostEditor.id, rendererId, message);
|
||||
|
||||
const editor = notebookEditorVisible ? editorOrAlias : notebookEditorAliases.get(editorOrAlias!);
|
||||
const extHostEditor = editor && ExtHostNotebookEditor.apiEditorsToExtHost.get(editor);
|
||||
return this.proxy.$postMessage(extHostEditor?.id, rendererId, message);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
export abstract class AbstractExtHostOutputChannel extends Disposable implements vscode.OutputChannel {
|
||||
|
||||
@@ -23,12 +24,12 @@ export abstract class AbstractExtHostOutputChannel extends Disposable implements
|
||||
protected readonly _onDidAppend: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidAppend: Event<void> = this._onDidAppend.event;
|
||||
|
||||
constructor(name: string, log: boolean, file: URI | undefined, proxy: MainThreadOutputServiceShape) {
|
||||
constructor(name: string, log: boolean, file: URI | undefined, extensionId: string | undefined, proxy: MainThreadOutputServiceShape) {
|
||||
super();
|
||||
|
||||
this._name = name;
|
||||
this._proxy = proxy;
|
||||
this._id = proxy.$register(this.name, log, file);
|
||||
this._id = proxy.$register(this.name, log, file, extensionId);
|
||||
this._disposed = false;
|
||||
this._offset = 0;
|
||||
}
|
||||
@@ -86,8 +87,8 @@ export abstract class AbstractExtHostOutputChannel extends Disposable implements
|
||||
|
||||
export class ExtHostPushOutputChannel extends AbstractExtHostOutputChannel {
|
||||
|
||||
constructor(name: string, proxy: MainThreadOutputServiceShape) {
|
||||
super(name, false, undefined, proxy);
|
||||
constructor(name: string, extensionId: string, proxy: MainThreadOutputServiceShape) {
|
||||
super(name, false, undefined, extensionId, proxy);
|
||||
}
|
||||
|
||||
override append(value: string): void {
|
||||
@@ -100,7 +101,7 @@ export class ExtHostPushOutputChannel extends AbstractExtHostOutputChannel {
|
||||
class ExtHostLogFileOutputChannel extends AbstractExtHostOutputChannel {
|
||||
|
||||
constructor(name: string, file: URI, proxy: MainThreadOutputServiceShape) {
|
||||
super(name, true, file, proxy);
|
||||
super(name, true, file, undefined, proxy);
|
||||
}
|
||||
|
||||
override append(value: string): void {
|
||||
@@ -148,12 +149,12 @@ export class ExtHostOutputService implements ExtHostOutputServiceShape {
|
||||
$setVisibleChannel(channelId: string): void {
|
||||
}
|
||||
|
||||
createOutputChannel(name: string): vscode.OutputChannel {
|
||||
createOutputChannel(name: string, extension: IExtensionDescription): vscode.OutputChannel {
|
||||
name = name.trim();
|
||||
if (!name) {
|
||||
throw new Error('illegal argument `name`. must not be falsy');
|
||||
}
|
||||
return new ExtHostPushOutputChannel(name, this._proxy);
|
||||
return new ExtHostPushOutputChannel(name, extension.identifier.value, this._proxy);
|
||||
}
|
||||
|
||||
createOutputChannelFromLogFile(name: string, file: URI): vscode.OutputChannel {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Emitter } from 'vs/base/common/event';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { IExtHostWorkspaceProvider } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { InputBox, InputBoxOptions, QuickInput, QuickInputButton, QuickPick, QuickPickItem, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
|
||||
import { InputBox, InputBoxOptions, QuickInput, QuickInputButton, QuickPick, QuickPickItem, QuickPickItemButtonEvent, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
|
||||
import { ExtHostQuickOpenShape, IMainContext, MainContext, TransferQuickPickItems, TransferQuickInput, TransferQuickInputButton } from './extHost.protocol';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ThemeIcon, QuickInputButtons } from 'vs/workbench/api/common/extHostTypes';
|
||||
@@ -17,6 +17,7 @@ import { isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { ThemeIcon as ThemeIconUtils } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
export type Item = string | QuickPickItem;
|
||||
|
||||
@@ -238,6 +239,13 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
|
||||
}
|
||||
}
|
||||
|
||||
$onDidTriggerItemButton(sessionId: number, itemHandle: number, buttonHandle: number): void {
|
||||
const session = this._sessions.get(sessionId);
|
||||
if (session instanceof ExtHostQuickPick) {
|
||||
session._fireDidTriggerItemButton(itemHandle, buttonHandle);
|
||||
}
|
||||
}
|
||||
|
||||
$onDidHide(sessionId: number): void {
|
||||
const session = this._sessions.get(sessionId);
|
||||
if (session) {
|
||||
@@ -369,11 +377,13 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
|
||||
this._handlesToButtons.set(handle, button);
|
||||
});
|
||||
this.update({
|
||||
buttons: buttons.map<TransferQuickInputButton>((button, i) => ({
|
||||
iconPath: getIconUris(button.iconPath),
|
||||
tooltip: button.tooltip,
|
||||
handle: button === QuickInputButtons.Back ? -1 : i,
|
||||
}))
|
||||
buttons: buttons.map<TransferQuickInputButton>((button, i) => {
|
||||
return {
|
||||
...getIconPathOrClass(button),
|
||||
tooltip: button.tooltip,
|
||||
handle: button === QuickInputButtons.Back ? -1 : i,
|
||||
};
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@@ -481,6 +491,22 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
|
||||
return typeof iconPath === 'object' && 'dark' in iconPath ? iconPath.dark : iconPath;
|
||||
}
|
||||
|
||||
function getIconPathOrClass(button: QuickInputButton) {
|
||||
const iconPathOrIconClass = getIconUris(button.iconPath);
|
||||
let iconPath: { dark: URI; light?: URI | undefined; } | undefined;
|
||||
let iconClass: string | undefined;
|
||||
if ('id' in iconPathOrIconClass) {
|
||||
iconClass = ThemeIconUtils.asClassName(iconPathOrIconClass);
|
||||
} else {
|
||||
iconPath = iconPathOrIconClass;
|
||||
}
|
||||
|
||||
return {
|
||||
iconPath,
|
||||
iconClass
|
||||
};
|
||||
}
|
||||
|
||||
class ExtHostQuickPick<T extends QuickPickItem> extends ExtHostQuickInput implements QuickPick<T> {
|
||||
|
||||
private _items: T[] = [];
|
||||
@@ -494,12 +520,14 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
|
||||
private readonly _onDidChangeActiveEmitter = new Emitter<T[]>();
|
||||
private _selectedItems: T[] = [];
|
||||
private readonly _onDidChangeSelectionEmitter = new Emitter<T[]>();
|
||||
private readonly _onDidTriggerItemButtonEmitter = new Emitter<QuickPickItemButtonEvent<T>>();
|
||||
|
||||
constructor(extensionId: ExtensionIdentifier, enableProposedApi: boolean, onDispose: () => void) {
|
||||
constructor(extensionId: ExtensionIdentifier, private readonly enableProposedApi: boolean, onDispose: () => void) {
|
||||
super(extensionId, onDispose);
|
||||
this._disposables.push(
|
||||
this._onDidChangeActiveEmitter,
|
||||
this._onDidChangeSelectionEmitter,
|
||||
this._onDidTriggerItemButtonEmitter
|
||||
);
|
||||
this.update({ type: 'quickPick' });
|
||||
}
|
||||
@@ -523,7 +551,17 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
|
||||
handle: i,
|
||||
detail: item.detail,
|
||||
picked: item.picked,
|
||||
alwaysShow: item.alwaysShow
|
||||
alwaysShow: item.alwaysShow,
|
||||
// Proposed API only at the moment
|
||||
buttons: item.buttons && this.enableProposedApi
|
||||
? item.buttons.map<TransferQuickInputButton>((button, i) => {
|
||||
return {
|
||||
...getIconPathOrClass(button),
|
||||
tooltip: button.tooltip,
|
||||
handle: i
|
||||
};
|
||||
})
|
||||
: undefined,
|
||||
}))
|
||||
});
|
||||
}
|
||||
@@ -597,6 +635,22 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
|
||||
this._selectedItems = items;
|
||||
this._onDidChangeSelectionEmitter.fire(items);
|
||||
}
|
||||
|
||||
onDidTriggerItemButton = this._onDidTriggerItemButtonEmitter.event;
|
||||
|
||||
_fireDidTriggerItemButton(itemHandle: number, buttonHandle: number) {
|
||||
const item = this._handlesToItems.get(itemHandle)!;
|
||||
if (!item || !item.buttons || !item.buttons.length) {
|
||||
return;
|
||||
}
|
||||
const button = item.buttons[buttonHandle];
|
||||
if (button) {
|
||||
this._onDidTriggerItemButtonEmitter.fire({
|
||||
button,
|
||||
item
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExtHostInputBox extends ExtHostQuickInput implements InputBox {
|
||||
|
||||
@@ -18,18 +18,26 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { MarshalledId } from 'vs/base/common/marshalling';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { MarkdownString } from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
|
||||
type ProviderHandle = number;
|
||||
type GroupHandle = number;
|
||||
type ResourceStateHandle = number;
|
||||
|
||||
function getIconResource(decorations?: vscode.SourceControlResourceThemableDecorations): vscode.Uri | undefined {
|
||||
function getIconResource(decorations?: vscode.SourceControlResourceThemableDecorations): UriComponents | ThemeIcon | undefined {
|
||||
if (!decorations) {
|
||||
return undefined;
|
||||
} else if (typeof decorations.iconPath === 'string') {
|
||||
return URI.file(decorations.iconPath);
|
||||
} else {
|
||||
} else if (URI.isUri(decorations.iconPath)) {
|
||||
return decorations.iconPath;
|
||||
} else if (ThemeIcon.isThemeIcon(decorations.iconPath)) {
|
||||
return decorations.iconPath;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,8 +50,8 @@ function compareResourceThemableDecorations(a: vscode.SourceControlResourceThema
|
||||
return 1;
|
||||
}
|
||||
|
||||
const aPath = typeof a.iconPath === 'string' ? a.iconPath : a.iconPath.fsPath;
|
||||
const bPath = typeof b.iconPath === 'string' ? b.iconPath : b.iconPath.fsPath;
|
||||
const aPath = typeof a.iconPath === 'string' ? a.iconPath : URI.isUri(a.iconPath) ? a.iconPath.fsPath : (a.iconPath as vscode.ThemeIcon).id;
|
||||
const bPath = typeof b.iconPath === 'string' ? b.iconPath : URI.isUri(b.iconPath) ? b.iconPath.fsPath : (b.iconPath as vscode.ThemeIcon).id;
|
||||
return comparePaths(aPath, bPath);
|
||||
}
|
||||
|
||||
@@ -269,7 +277,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
|
||||
this._proxy.$setInputBoxFocus(this._sourceControlHandle);
|
||||
}
|
||||
|
||||
showValidationMessage(message: string, type: vscode.SourceControlInputBoxValidationType) {
|
||||
showValidationMessage(message: string | vscode.MarkdownString, type: vscode.SourceControlInputBoxValidationType) {
|
||||
checkProposedApiEnabled(this._extension);
|
||||
|
||||
this._proxy.$showValidationMessage(this._sourceControlHandle, message, type as any);
|
||||
@@ -367,12 +375,8 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
|
||||
this._resourceStatesMap.set(handle, r);
|
||||
|
||||
const sourceUri = r.resourceUri;
|
||||
const iconUri = getIconResource(r.decorations);
|
||||
const lightIconUri = r.decorations && getIconResource(r.decorations.light) || iconUri;
|
||||
const darkIconUri = r.decorations && getIconResource(r.decorations.dark) || iconUri;
|
||||
const icons: UriComponents[] = [];
|
||||
let command: ICommandDto | undefined;
|
||||
|
||||
let command: ICommandDto | undefined;
|
||||
if (r.command) {
|
||||
if (r.command.command === 'vscode.open' || r.command.command === 'vscode.diff') {
|
||||
const disposables = new DisposableStore();
|
||||
@@ -383,13 +387,10 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
|
||||
}
|
||||
}
|
||||
|
||||
if (lightIconUri) {
|
||||
icons.push(lightIconUri);
|
||||
}
|
||||
|
||||
if (darkIconUri && (darkIconUri.toString() !== lightIconUri?.toString())) {
|
||||
icons.push(darkIconUri);
|
||||
}
|
||||
const icon = getIconResource(r.decorations);
|
||||
const lightIcon = r.decorations && getIconResource(r.decorations.light) || icon;
|
||||
const darkIcon = r.decorations && getIconResource(r.decorations.dark) || icon;
|
||||
const icons: SCMRawResource[2] = [lightIcon, darkIcon];
|
||||
|
||||
const tooltip = (r.decorations && r.decorations.tooltip) || '';
|
||||
const strikeThrough = r.decorations && !!r.decorations.strikeThrough;
|
||||
@@ -660,7 +661,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
|
||||
_commands.registerArgumentProcessor({
|
||||
processArgument: arg => {
|
||||
if (arg && arg.$mid === 3) {
|
||||
if (arg && arg.$mid === MarshalledId.ScmResource) {
|
||||
const sourceControl = this._sourceControls.get(arg.sourceControlHandle);
|
||||
|
||||
if (!sourceControl) {
|
||||
@@ -674,7 +675,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
}
|
||||
|
||||
return group.getResourceState(arg.handle);
|
||||
} else if (arg && arg.$mid === 4) {
|
||||
} else if (arg && arg.$mid === MarshalledId.ScmResourceGroup) {
|
||||
const sourceControl = this._sourceControls.get(arg.sourceControlHandle);
|
||||
|
||||
if (!sourceControl) {
|
||||
@@ -682,7 +683,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
}
|
||||
|
||||
return sourceControl.getResourceGroup(arg.groupHandle);
|
||||
} else if (arg && arg.$mid === 5) {
|
||||
} else if (arg && arg.$mid === MarshalledId.ScmProvider) {
|
||||
const sourceControl = this._sourceControls.get(arg.handle);
|
||||
|
||||
if (!sourceControl) {
|
||||
@@ -771,7 +772,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
return group.$executeResourceCommand(handle, preserveFocus);
|
||||
}
|
||||
|
||||
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string, number] | undefined> {
|
||||
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string | IMarkdownString, number] | undefined> {
|
||||
this.logService.trace('ExtHostSCM#$validateInput', sourceControlHandle);
|
||||
|
||||
const sourceControl = this._sourceControls.get(sourceControlHandle);
|
||||
@@ -789,7 +790,12 @@ export class ExtHostSCM implements ExtHostSCMShape {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return Promise.resolve<[string, number]>([result.message, result.type]);
|
||||
const message = MarkdownString.fromStrict(result.message);
|
||||
if (!message) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return Promise.resolve<[string | IMarkdownString, number]>([message, result.type]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -105,11 +105,13 @@ export class ExtHostSearch implements ExtHostSearchShape {
|
||||
return engine.search(progress => this._proxy.$handleTextMatch(handle, session, progress), token);
|
||||
}
|
||||
|
||||
$enableExtensionHostSearch(): void { }
|
||||
|
||||
protected createTextSearchManager(query: ITextQuery, provider: vscode.TextSearchProvider): TextSearchManager {
|
||||
return new TextSearchManager(query, provider, {
|
||||
readdir: resource => Promise.resolve([]), // TODO@rob implement
|
||||
toCanonicalName: encoding => encoding
|
||||
});
|
||||
}, 'textSearchProvider');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,13 +11,17 @@ import { localize } from 'vs/nls';
|
||||
import { CommandsConverter } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { MarkdownString } from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
|
||||
export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
|
||||
private static ID_GEN = 0;
|
||||
|
||||
private static ALLOWED_BACKGROUND_COLORS = new Map<string, ThemeColor>(
|
||||
[['statusBarItem.errorBackground', new ThemeColor('statusBarItem.errorForeground')]]
|
||||
[
|
||||
['statusBarItem.errorBackground', new ThemeColor('statusBarItem.errorForeground')],
|
||||
['statusBarItem.warningBackground', new ThemeColor('statusBarItem.warningForeground')]
|
||||
]
|
||||
);
|
||||
|
||||
#proxy: MainThreadStatusBarShape;
|
||||
@@ -35,7 +39,7 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
private _visible: boolean = false;
|
||||
|
||||
private _text: string = '';
|
||||
private _tooltip?: string;
|
||||
private _tooltip?: string | vscode.MarkdownString;
|
||||
private _name?: string;
|
||||
private _color?: string | ThemeColor;
|
||||
private _backgroundColor?: ThemeColor;
|
||||
@@ -83,10 +87,6 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
public get tooltip(): string | undefined {
|
||||
return this._tooltip;
|
||||
}
|
||||
|
||||
public get color(): string | ThemeColor | undefined {
|
||||
return this._color;
|
||||
}
|
||||
@@ -209,8 +209,10 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
color = ExtHostStatusBarEntry.ALLOWED_BACKGROUND_COLORS.get(this._backgroundColor.id);
|
||||
}
|
||||
|
||||
const tooltip = this._tooltip ? MarkdownString.fromStrict(this._tooltip) : undefined;
|
||||
|
||||
// Set to status bar
|
||||
this.#proxy.$setEntry(this._entryId, id, name, this._text, this._tooltip, this._command?.internal, color,
|
||||
this.#proxy.$setEntry(this._entryId, id, name, this._text, tooltip, this._command?.internal, color,
|
||||
this._backgroundColor, this._alignment === ExtHostStatusBarAlignment.Left ? MainThreadStatusBarAlignment.LEFT : MainThreadStatusBarAlignment.RIGHT,
|
||||
this._priority, this._accessibilityInformation);
|
||||
}, 0);
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface IExtensionStoragePaths {
|
||||
whenReady: Promise<any>;
|
||||
workspaceValue(extension: IExtensionDescription): URI | undefined;
|
||||
globalValue(extension: IExtensionDescription): URI;
|
||||
onWillDeactivateAll(): void;
|
||||
}
|
||||
|
||||
export class ExtensionStoragePaths implements IExtensionStoragePaths {
|
||||
@@ -25,14 +26,14 @@ export class ExtensionStoragePaths implements IExtensionStoragePaths {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly _workspace?: IStaticWorkspaceData;
|
||||
private readonly _environment: IEnvironment;
|
||||
protected readonly _environment: IEnvironment;
|
||||
|
||||
readonly whenReady: Promise<URI | undefined>;
|
||||
private _value?: URI;
|
||||
|
||||
constructor(
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@ILogService protected readonly _logService: ILogService,
|
||||
@IExtHostConsumerFileSystem private readonly _extHostFileSystem: IExtHostConsumerFileSystem
|
||||
) {
|
||||
this._workspace = initData.workspace ?? undefined;
|
||||
@@ -40,12 +41,16 @@ export class ExtensionStoragePaths implements IExtensionStoragePaths {
|
||||
this.whenReady = this._getOrCreateWorkspaceStoragePath().then(value => this._value = value);
|
||||
}
|
||||
|
||||
protected async _getWorkspaceStorageURI(storageName: string): Promise<URI> {
|
||||
return URI.joinPath(this._environment.workspaceStorageHome, storageName);
|
||||
}
|
||||
|
||||
private async _getOrCreateWorkspaceStoragePath(): Promise<URI | undefined> {
|
||||
if (!this._workspace) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
const storageName = this._workspace.id;
|
||||
const storageUri = URI.joinPath(this._environment.workspaceStorageHome, storageName);
|
||||
const storageUri = await this._getWorkspaceStorageURI(storageName);
|
||||
|
||||
try {
|
||||
await this._extHostFileSystem.value.stat(storageUri);
|
||||
@@ -84,4 +89,7 @@ export class ExtensionStoragePaths implements IExtensionStoragePaths {
|
||||
globalValue(extension: IExtensionDescription): URI {
|
||||
return URI.joinPath(this._environment.globalStorageHome, extension.identifier.value.toLowerCase());
|
||||
}
|
||||
|
||||
onWillDeactivateAll(): void {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { asPromise } from 'vs/base/common/async';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
|
||||
import { MainContext, MainThreadTaskShape, ExtHostTaskShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
|
||||
import * as Objects from 'vs/base/common/objects';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import { IExtHostWorkspaceProvider, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import type * as vscode from 'vscode';
|
||||
@@ -213,6 +213,14 @@ export namespace TaskHandleDTO {
|
||||
};
|
||||
}
|
||||
}
|
||||
export namespace TaskGroupDTO {
|
||||
export function from(value: vscode.TaskGroup): tasks.TaskGroupDTO | undefined {
|
||||
if (value === undefined || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return { _id: value.id, isDefault: value.isDefault };
|
||||
}
|
||||
}
|
||||
|
||||
export namespace TaskDTO {
|
||||
export function fromMany(tasks: vscode.Task[], extension: IExtensionDescription): tasks.TaskDTO[] {
|
||||
@@ -257,7 +265,6 @@ export namespace TaskDTO {
|
||||
if (!definition || !scope) {
|
||||
return undefined;
|
||||
}
|
||||
const group = (value.group as types.TaskGroup) ? (value.group as types.TaskGroup).id : undefined;
|
||||
const result: tasks.TaskDTO = {
|
||||
_id: (value as types.Task)._id!,
|
||||
definition,
|
||||
@@ -269,7 +276,7 @@ export namespace TaskDTO {
|
||||
},
|
||||
execution: execution!,
|
||||
isBackground: value.isBackground,
|
||||
group: group,
|
||||
group: TaskGroupDTO.from(value.group as vscode.TaskGroup),
|
||||
presentationOptions: TaskPresentationOptionsDTO.from(value.presentationOptions),
|
||||
problemMatchers: value.problemMatchers,
|
||||
hasDefinedMatchers: (value as types.Task).hasDefinedMatchers,
|
||||
@@ -311,7 +318,13 @@ export namespace TaskDTO {
|
||||
result.isBackground = value.isBackground;
|
||||
}
|
||||
if (value.group !== undefined) {
|
||||
result.group = types.TaskGroup.from(value.group);
|
||||
result.group = types.TaskGroup.from(value.group._id);
|
||||
if (result.group) {
|
||||
result.group = Objects.deepClone(result.group);
|
||||
if (value.group.isDefault) {
|
||||
result.group.isDefault = value.group.isDefault;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value.presentationOptions) {
|
||||
result.presentationOptions = TaskPresentationOptionsDTO.to(value.presentationOptions)!;
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
import type * as vscode from 'vscode';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, ITerminalDimensionsDto, ITerminalLinkDto, TerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, ITerminalDimensionsDto, ITerminalLinkDto, ExtHostTerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable as VSCodeDisposable, EnvironmentVariableMutatorType, ThemeColor } from './extHostTypes';
|
||||
import { Disposable as VSCodeDisposable, EnvironmentVariableMutatorType } from './extHostTypes';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { localize } from 'vs/nls';
|
||||
import { NotSupportedError } from 'vs/base/common/errors';
|
||||
@@ -18,9 +18,9 @@ import { serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/ter
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { IProcessReadyEvent, IShellLaunchConfigDto, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProfile, TerminalIcon, TerminalShellType } from 'vs/platform/terminal/common/terminal';
|
||||
import { ICreateContributedTerminalProfileOptions, IProcessReadyEvent, IShellLaunchConfigDto, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProfile, TerminalIcon, TerminalLocation, TerminalShellType } from 'vs/platform/terminal/common/terminal';
|
||||
import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
|
||||
export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, IDisposable {
|
||||
@@ -34,6 +34,7 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, ID
|
||||
onDidOpenTerminal: Event<vscode.Terminal>;
|
||||
onDidChangeActiveTerminal: Event<vscode.Terminal | undefined>;
|
||||
onDidChangeTerminalDimensions: Event<vscode.TerminalDimensionsChangeEvent>;
|
||||
onDidChangeTerminalState: Event<vscode.Terminal>;
|
||||
onDidWriteTerminalData: Event<vscode.TerminalDataWriteEvent>;
|
||||
|
||||
createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal;
|
||||
@@ -43,14 +44,15 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, ID
|
||||
getDefaultShell(useAutomationShell: boolean): string;
|
||||
getDefaultShellArgs(useAutomationShell: boolean): string[] | string;
|
||||
registerLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable;
|
||||
registerProfileProvider(id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable;
|
||||
registerProfileProvider(extension: IExtensionDescription, id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable;
|
||||
getEnvironmentVariableCollection(extension: IExtensionDescription, persistent?: boolean): vscode.EnvironmentVariableCollection;
|
||||
}
|
||||
|
||||
export interface ITerminalInternalOptions {
|
||||
isFeatureTerminal?: boolean;
|
||||
useShellEnvironment?: boolean;
|
||||
isSplitTerminal?: boolean;
|
||||
resolvedExtHostIdentifier?: ExtHostTerminalIdentifier;
|
||||
splitActiveTerminal?: boolean;
|
||||
}
|
||||
|
||||
export const IExtHostTerminalService = createDecorator<IExtHostTerminalService>('IExtHostTerminalService');
|
||||
@@ -62,6 +64,7 @@ export class ExtHostTerminal {
|
||||
private _pidPromiseComplete: ((value: number | undefined) => any) | undefined;
|
||||
private _rows: number | undefined;
|
||||
private _exitStatus: vscode.TerminalExitStatus | undefined;
|
||||
private _state: vscode.TerminalState = { interactedWith: false };
|
||||
|
||||
public isOpen: boolean = false;
|
||||
|
||||
@@ -69,7 +72,7 @@ export class ExtHostTerminal {
|
||||
|
||||
constructor(
|
||||
private _proxy: MainThreadTerminalServiceShape,
|
||||
public _id: TerminalIdentifier,
|
||||
public _id: ExtHostTerminalIdentifier,
|
||||
private readonly _creationOptions: vscode.TerminalOptions | vscode.ExtensionTerminalOptions,
|
||||
private _name?: string,
|
||||
) {
|
||||
@@ -90,6 +93,9 @@ export class ExtHostTerminal {
|
||||
get exitStatus(): vscode.TerminalExitStatus | undefined {
|
||||
return that._exitStatus;
|
||||
},
|
||||
get state(): vscode.TerminalState {
|
||||
return that._state;
|
||||
},
|
||||
sendText(text: string, addNewLine: boolean = true): void {
|
||||
that._checkDisposed();
|
||||
that._proxy.$sendText(that._id, text, addNewLine);
|
||||
@@ -134,17 +140,19 @@ export class ExtHostTerminal {
|
||||
cwd: withNullAsUndefined(options.cwd),
|
||||
env: withNullAsUndefined(options.env),
|
||||
icon: withNullAsUndefined(asTerminalIcon(options.iconPath)),
|
||||
color: ThemeColor.isThemeColor(options.color) ? options.color.id : undefined,
|
||||
initialText: withNullAsUndefined(options.message),
|
||||
strictEnv: withNullAsUndefined(options.strictEnv),
|
||||
hideFromUser: withNullAsUndefined(options.hideFromUser),
|
||||
isFeatureTerminal: withNullAsUndefined(internalOptions?.isFeatureTerminal),
|
||||
isExtensionOwnedTerminal: true,
|
||||
useShellEnvironment: withNullAsUndefined(internalOptions?.useShellEnvironment),
|
||||
isSplitTerminal: withNullAsUndefined(internalOptions?.isSplitTerminal)
|
||||
location: this._serializeParentTerminal(options.location, internalOptions?.resolvedExtHostIdentifier, internalOptions?.splitActiveTerminal)
|
||||
});
|
||||
}
|
||||
|
||||
public async createExtensionTerminal(isSplitTerminal?: boolean, iconPath?: URI | { light: URI; dark: URI } | ThemeIcon): Promise<number> {
|
||||
|
||||
public async createExtensionTerminal(location?: TerminalLocation | vscode.TerminalEditorLocationOptions | vscode.TerminalSplitLocationOptions, parentTerminal?: ExtHostTerminalIdentifier, iconPath?: TerminalIcon, color?: ThemeColor): Promise<number> {
|
||||
if (typeof this._id !== 'string') {
|
||||
throw new Error('Terminal has already been created');
|
||||
}
|
||||
@@ -152,7 +160,8 @@ export class ExtHostTerminal {
|
||||
name: this._name,
|
||||
isExtensionCustomPtyTerminal: true,
|
||||
icon: iconPath,
|
||||
isSplitTerminal
|
||||
color: ThemeColor.isThemeColor(color) ? color.id : undefined,
|
||||
location: this._serializeParentTerminal(location, parentTerminal)
|
||||
});
|
||||
// At this point, the id has been set via `$acceptTerminalOpened`
|
||||
if (typeof this._id === 'string') {
|
||||
@@ -161,6 +170,15 @@ export class ExtHostTerminal {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
private _serializeParentTerminal(location?: TerminalLocation | vscode.TerminalEditorLocationOptions | vscode.TerminalSplitLocationOptions, parentTerminal?: ExtHostTerminalIdentifier, splitActiveTerminal?: boolean): TerminalLocation | vscode.TerminalEditorLocationOptions | { parentTerminal: ExtHostTerminalIdentifier } | { splitActiveTerminal: boolean } | undefined {
|
||||
if (typeof location === 'object' && 'parentTerminal' in location) {
|
||||
return parentTerminal ? { parentTerminal } : undefined;
|
||||
} else if (splitActiveTerminal) {
|
||||
return { splitActiveTerminal: true };
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
private _checkDisposed() {
|
||||
if (this._disposed) {
|
||||
throw new Error('Terminal has already been disposed');
|
||||
@@ -188,6 +206,14 @@ export class ExtHostTerminal {
|
||||
return true;
|
||||
}
|
||||
|
||||
public setInteractedWith(): boolean {
|
||||
if (!this._state.interactedWith) {
|
||||
this._state = { interactedWith: true };
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public _setProcessId(processId: number | undefined): void {
|
||||
// The event may fire 2 times when the panel is restored
|
||||
if (this._pidPromiseComplete) {
|
||||
@@ -245,7 +271,7 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
|
||||
}
|
||||
|
||||
async processBinary(data: string): Promise<void> {
|
||||
// No-op, processBinary is not supported in extextion owned terminals.
|
||||
// No-op, processBinary is not supported in extension owned terminals.
|
||||
}
|
||||
|
||||
acknowledgeDataEvent(charCount: number): void {
|
||||
@@ -253,6 +279,10 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
|
||||
// implemented it will need new pause and resume VS Code APIs.
|
||||
}
|
||||
|
||||
async setUnicodeVersion(version: '6' | '11'): Promise<void> {
|
||||
// No-op, xterm-headless isn't used for extension owned terminals.
|
||||
}
|
||||
|
||||
getInitialCwd(): Promise<string> {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
@@ -321,16 +351,18 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
public get activeTerminal(): vscode.Terminal | undefined { return this._activeTerminal?.value; }
|
||||
public get terminals(): vscode.Terminal[] { return this._terminals.map(term => term.value); }
|
||||
|
||||
protected readonly _onDidCloseTerminal: Emitter<vscode.Terminal> = new Emitter<vscode.Terminal>();
|
||||
public get onDidCloseTerminal(): Event<vscode.Terminal> { return this._onDidCloseTerminal && this._onDidCloseTerminal.event; }
|
||||
protected readonly _onDidOpenTerminal: Emitter<vscode.Terminal> = new Emitter<vscode.Terminal>();
|
||||
public get onDidOpenTerminal(): Event<vscode.Terminal> { return this._onDidOpenTerminal && this._onDidOpenTerminal.event; }
|
||||
protected readonly _onDidChangeActiveTerminal: Emitter<vscode.Terminal | undefined> = new Emitter<vscode.Terminal | undefined>();
|
||||
public get onDidChangeActiveTerminal(): Event<vscode.Terminal | undefined> { return this._onDidChangeActiveTerminal && this._onDidChangeActiveTerminal.event; }
|
||||
protected readonly _onDidChangeTerminalDimensions: Emitter<vscode.TerminalDimensionsChangeEvent> = new Emitter<vscode.TerminalDimensionsChangeEvent>();
|
||||
public get onDidChangeTerminalDimensions(): Event<vscode.TerminalDimensionsChangeEvent> { return this._onDidChangeTerminalDimensions && this._onDidChangeTerminalDimensions.event; }
|
||||
protected readonly _onDidCloseTerminal = new Emitter<vscode.Terminal>();
|
||||
readonly onDidCloseTerminal = this._onDidCloseTerminal.event;
|
||||
protected readonly _onDidOpenTerminal = new Emitter<vscode.Terminal>();
|
||||
readonly onDidOpenTerminal = this._onDidOpenTerminal.event;
|
||||
protected readonly _onDidChangeActiveTerminal = new Emitter<vscode.Terminal | undefined>();
|
||||
readonly onDidChangeActiveTerminal = this._onDidChangeActiveTerminal.event;
|
||||
protected readonly _onDidChangeTerminalDimensions = new Emitter<vscode.TerminalDimensionsChangeEvent>();
|
||||
readonly onDidChangeTerminalDimensions = this._onDidChangeTerminalDimensions.event;
|
||||
protected readonly _onDidChangeTerminalState = new Emitter<vscode.Terminal>();
|
||||
readonly onDidChangeTerminalState = this._onDidChangeTerminalState.event;
|
||||
protected readonly _onDidWriteTerminalData: Emitter<vscode.TerminalDataWriteEvent>;
|
||||
public get onDidWriteTerminalData(): Event<vscode.TerminalDataWriteEvent> { return this._onDidWriteTerminalData && this._onDidWriteTerminalData.event; }
|
||||
get onDidWriteTerminalData(): Event<vscode.TerminalDataWriteEvent> { return this._onDidWriteTerminalData.event; }
|
||||
|
||||
constructor(
|
||||
supportsProcesses: boolean,
|
||||
@@ -369,7 +401,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
public createExtensionTerminal(options: vscode.ExtensionTerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal {
|
||||
const terminal = new ExtHostTerminal(this._proxy, generateUuid(), options, options.name);
|
||||
const p = new ExtHostPseudoterminal(options.pty);
|
||||
terminal.createExtensionTerminal(internalOptions?.isSplitTerminal, asTerminalIcon(options.iconPath)).then(id => {
|
||||
terminal.createExtensionTerminal(this._resolveLocation(options.location), internalOptions?.resolvedExtHostIdentifier, asTerminalIcon(options.iconPath), asTerminalColor(options.color)).then(id => {
|
||||
const disposable = this._setupExtHostProcessListeners(id, p);
|
||||
this._terminalProcessDisposables[id] = disposable;
|
||||
});
|
||||
@@ -377,6 +409,13 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
return terminal.value;
|
||||
}
|
||||
|
||||
private _resolveLocation(location?: TerminalLocation | vscode.TerminalEditorLocationOptions | vscode.TerminalSplitLocationOptions): undefined | TerminalLocation | vscode.TerminalEditorLocationOptions {
|
||||
if (typeof location === 'object' && 'parentTerminal' in location) {
|
||||
return undefined;
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
public attachPtyToTerminal(id: number, pty: vscode.Pseudoterminal): void {
|
||||
const terminal = this._getTerminalById(id);
|
||||
if (!terminal) {
|
||||
@@ -392,7 +431,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
if (id === null) {
|
||||
this._activeTerminal = undefined;
|
||||
if (original !== this._activeTerminal) {
|
||||
this._onDidChangeActiveTerminal.fire(this._activeTerminal?.value); // {{SQL CARBON EDIT}}
|
||||
this._onDidChangeActiveTerminal.fire(this._activeTerminal.value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -544,6 +583,13 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
this._terminalProcesses.get(id)?.input(data);
|
||||
}
|
||||
|
||||
public $acceptTerminalInteraction(id: number): void {
|
||||
const terminal = this._getTerminalById(id);
|
||||
if (terminal?.setInteractedWith()) {
|
||||
this._onDidChangeTerminalState.fire(terminal.value);
|
||||
}
|
||||
}
|
||||
|
||||
public $acceptProcessResize(id: number, cols: number, rows: number): void {
|
||||
try {
|
||||
this._terminalProcesses.get(id)?.resize(cols, rows);
|
||||
@@ -584,32 +630,33 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
});
|
||||
}
|
||||
|
||||
public registerProfileProvider(id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable {
|
||||
public registerProfileProvider(extension: IExtensionDescription, id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable {
|
||||
if (this._profileProviders.has(id)) {
|
||||
throw new Error(`Terminal profile provider "${id}" already registered`);
|
||||
}
|
||||
this._profileProviders.set(id, provider);
|
||||
this._proxy.$registerProfileProvider(id);
|
||||
this._proxy.$registerProfileProvider(id, extension.identifier.value);
|
||||
return new VSCodeDisposable(() => {
|
||||
this._profileProviders.delete(id);
|
||||
this._proxy.$unregisterProfileProvider(id);
|
||||
});
|
||||
}
|
||||
|
||||
public async $createContributedProfileTerminal(id: string, isSplitTerminal: boolean): Promise<void> {
|
||||
public async $createContributedProfileTerminal(id: string, options: ICreateContributedTerminalProfileOptions): Promise<void> {
|
||||
const token = new CancellationTokenSource().token;
|
||||
const options = await this._profileProviders.get(id)?.provideProfileOptions(token);
|
||||
const profile = await this._profileProviders.get(id)?.provideTerminalProfile(token);
|
||||
if (token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
if (!options) {
|
||||
if (!profile || !('options' in profile)) {
|
||||
throw new Error(`No terminal profile options provided for id "${id}"`);
|
||||
}
|
||||
if ('pty' in options) {
|
||||
this.createExtensionTerminal(options, { isSplitTerminal });
|
||||
|
||||
if ('pty' in profile.options) {
|
||||
this.createExtensionTerminal(profile.options, options);
|
||||
return;
|
||||
}
|
||||
this.createTerminalFromOptions(options, { isSplitTerminal });
|
||||
this.createTerminalFromOptions(profile.options, options);
|
||||
}
|
||||
|
||||
public async $provideLinks(terminalId: number, line: string): Promise<ITerminalLinkDto[]> {
|
||||
@@ -708,7 +755,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
return index !== null ? array[index] : null;
|
||||
}
|
||||
|
||||
private _getTerminalObjectIndexById<T extends ExtHostTerminal>(array: T[], id: TerminalIdentifier): number | null {
|
||||
private _getTerminalObjectIndexById<T extends ExtHostTerminal>(array: T[], id: ExtHostTerminalIdentifier): number | null {
|
||||
let index: number | null = null;
|
||||
array.some((item, i) => {
|
||||
const thisId = item._id;
|
||||
@@ -839,14 +886,20 @@ export class WorkerExtHostTerminalService extends BaseExtHostTerminalService {
|
||||
}
|
||||
|
||||
function asTerminalIcon(iconPath?: vscode.Uri | { light: vscode.Uri; dark: vscode.Uri } | vscode.ThemeIcon): TerminalIcon | undefined {
|
||||
if (!iconPath) {
|
||||
if (!iconPath || typeof iconPath === 'string') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!('id' in iconPath)) {
|
||||
return iconPath;
|
||||
}
|
||||
|
||||
return {
|
||||
id: iconPath.id,
|
||||
color: iconPath.color as ThemeColor
|
||||
};
|
||||
}
|
||||
|
||||
function asTerminalColor(color?: vscode.ThemeColor): ThemeColor | undefined {
|
||||
return ThemeColor.isThemeColor(color) ? color as ThemeColor : undefined;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,42 +3,320 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { TestItemImpl } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { TestIdPathParts } from 'vs/workbench/contrib/testing/common/testId';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export const enum ExtHostTestItemEventType {
|
||||
NewChild,
|
||||
Disposed,
|
||||
export const enum ExtHostTestItemEventOp {
|
||||
Upsert,
|
||||
RemoveChild,
|
||||
Invalidated,
|
||||
SetProp,
|
||||
Bulk,
|
||||
}
|
||||
|
||||
export interface ITestItemUpsertChild {
|
||||
op: ExtHostTestItemEventOp.Upsert;
|
||||
item: TestItemImpl;
|
||||
}
|
||||
|
||||
export interface ITestItemRemoveChild {
|
||||
op: ExtHostTestItemEventOp.RemoveChild;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface ITestItemInvalidated {
|
||||
op: ExtHostTestItemEventOp.Invalidated;
|
||||
}
|
||||
|
||||
export interface ITestItemSetProp {
|
||||
op: ExtHostTestItemEventOp.SetProp;
|
||||
key: keyof vscode.TestItem;
|
||||
value: any;
|
||||
previous: any;
|
||||
}
|
||||
export interface ITestItemBulkReplace {
|
||||
op: ExtHostTestItemEventOp.Bulk;
|
||||
ops: (ITestItemUpsertChild | ITestItemRemoveChild)[];
|
||||
}
|
||||
|
||||
export type ExtHostTestItemEvent =
|
||||
| [evt: ExtHostTestItemEventType.NewChild, item: TestItemImpl]
|
||||
| [evt: ExtHostTestItemEventType.Disposed]
|
||||
| [evt: ExtHostTestItemEventType.Invalidated]
|
||||
| [evt: ExtHostTestItemEventType.SetProp, key: keyof vscode.TestItem<never>, value: any];
|
||||
| ITestItemUpsertChild
|
||||
| ITestItemRemoveChild
|
||||
| ITestItemInvalidated
|
||||
| ITestItemSetProp
|
||||
| ITestItemBulkReplace;
|
||||
|
||||
export interface IExtHostTestItemApi {
|
||||
children: Map<string, TestItemImpl>;
|
||||
controllerId: string;
|
||||
parent?: TestItemImpl;
|
||||
bus: Emitter<ExtHostTestItemEvent>;
|
||||
listener?: (evt: ExtHostTestItemEvent) => void;
|
||||
}
|
||||
|
||||
const eventPrivateApis = new WeakMap<TestItemImpl, IExtHostTestItemApi>();
|
||||
|
||||
export const createPrivateApiFor = (impl: TestItemImpl, controllerId: string) => {
|
||||
const api: IExtHostTestItemApi = { controllerId };
|
||||
eventPrivateApis.set(impl, api);
|
||||
return api;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the private API for a test item implementation. This implementation
|
||||
* is a managed object, but we keep a weakmap to avoid exposing any of the
|
||||
* internals to extensions.
|
||||
*/
|
||||
export const getPrivateApiFor = (impl: TestItemImpl) => {
|
||||
let api = eventPrivateApis.get(impl);
|
||||
if (!api) {
|
||||
api = { children: new Map(), bus: new Emitter() };
|
||||
eventPrivateApis.set(impl, api);
|
||||
export const getPrivateApiFor = (impl: TestItemImpl) => eventPrivateApis.get(impl)!;
|
||||
|
||||
const testItemPropAccessor = <K extends keyof vscode.TestItem>(
|
||||
api: IExtHostTestItemApi,
|
||||
key: K,
|
||||
defaultValue: vscode.TestItem[K],
|
||||
equals: (a: vscode.TestItem[K], b: vscode.TestItem[K]) => boolean
|
||||
) => {
|
||||
let value = defaultValue;
|
||||
return {
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
get() {
|
||||
return value;
|
||||
},
|
||||
set(newValue: vscode.TestItem[K]) {
|
||||
if (!equals(value, newValue)) {
|
||||
const oldValue = value;
|
||||
value = newValue;
|
||||
api.listener?.({
|
||||
op: ExtHostTestItemEventOp.SetProp,
|
||||
key,
|
||||
value: newValue,
|
||||
previous: oldValue,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
type WritableProps = Pick<vscode.TestItem, 'range' | 'label' | 'description' | 'canResolveChildren' | 'busy' | 'error' | 'tags'>;
|
||||
|
||||
const strictEqualComparator = <T>(a: T, b: T) => a === b;
|
||||
|
||||
const propComparators: { [K in keyof Required<WritableProps>]: (a: vscode.TestItem[K], b: vscode.TestItem[K]) => boolean } = {
|
||||
range: (a, b) => {
|
||||
if (a === b) { return true; }
|
||||
if (!a || !b) { return false; }
|
||||
return a.isEqual(b);
|
||||
},
|
||||
label: strictEqualComparator,
|
||||
description: strictEqualComparator,
|
||||
busy: strictEqualComparator,
|
||||
error: strictEqualComparator,
|
||||
canResolveChildren: strictEqualComparator,
|
||||
tags: (a, b) => {
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.some(t1 => !b.find(t2 => t1.id === t2.id))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
const writablePropKeys = Object.keys(propComparators) as (keyof Required<WritableProps>)[];
|
||||
|
||||
const makePropDescriptors = (api: IExtHostTestItemApi, label: string): { [K in keyof Required<WritableProps>]: PropertyDescriptor } => ({
|
||||
range: testItemPropAccessor(api, 'range', undefined, propComparators.range),
|
||||
label: testItemPropAccessor(api, 'label', label, propComparators.label),
|
||||
description: testItemPropAccessor(api, 'description', undefined, propComparators.description),
|
||||
canResolveChildren: testItemPropAccessor(api, 'canResolveChildren', false, propComparators.canResolveChildren),
|
||||
busy: testItemPropAccessor(api, 'busy', false, propComparators.busy),
|
||||
error: testItemPropAccessor(api, 'error', undefined, propComparators.error),
|
||||
tags: testItemPropAccessor(api, 'tags', [], propComparators.tags),
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns a partial test item containing the writable properties in B that
|
||||
* are different from A.
|
||||
*/
|
||||
export const diffTestItems = (a: vscode.TestItem, b: vscode.TestItem) => {
|
||||
const output = new Map<keyof WritableProps, unknown>();
|
||||
for (const key of writablePropKeys) {
|
||||
const cmp = propComparators[key] as (a: unknown, b: unknown) => boolean;
|
||||
if (!cmp(a[key], b[key])) {
|
||||
output.set(key, b[key]);
|
||||
}
|
||||
}
|
||||
|
||||
return api;
|
||||
return output;
|
||||
};
|
||||
|
||||
export class DuplicateTestItemError extends Error {
|
||||
constructor(id: string) {
|
||||
super(`Attempted to insert a duplicate test item ID ${id}`);
|
||||
}
|
||||
}
|
||||
|
||||
export class InvalidTestItemError extends Error {
|
||||
constructor(id: string) {
|
||||
super(`TestItem with ID "${id}" is invalid. Make sure to create it from the createTestItem method.`);
|
||||
}
|
||||
}
|
||||
|
||||
export class MixedTestItemController extends Error {
|
||||
constructor(id: string, ctrlA: string, ctrlB: string) {
|
||||
super(`TestItem with ID "${id}" is from controller "${ctrlA}" and cannot be added as a child of an item from controller "${ctrlB}".`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export type TestItemCollectionImpl = vscode.TestItemCollection & { toJSON(): readonly TestItemImpl[] } & Iterable<TestItemImpl>;
|
||||
|
||||
const createTestItemCollection = (owningItem: TestItemImpl): TestItemCollectionImpl => {
|
||||
const api = getPrivateApiFor(owningItem);
|
||||
let mapped = new Map<string, TestItemImpl>();
|
||||
|
||||
return {
|
||||
/** @inheritdoc */
|
||||
get size() {
|
||||
return mapped.size;
|
||||
},
|
||||
|
||||
/** @inheritdoc */
|
||||
forEach(callback: (item: vscode.TestItem, collection: vscode.TestItemCollection) => unknown, thisArg?: unknown) {
|
||||
for (const item of mapped.values()) {
|
||||
callback.call(thisArg, item, this);
|
||||
}
|
||||
},
|
||||
|
||||
/** @inheritdoc */
|
||||
replace(items: Iterable<vscode.TestItem>) {
|
||||
const newMapped = new Map<string, TestItemImpl>();
|
||||
const toDelete = new Set(mapped.keys());
|
||||
const bulk: ITestItemBulkReplace = { op: ExtHostTestItemEventOp.Bulk, ops: [] };
|
||||
|
||||
for (const item of items) {
|
||||
if (!(item instanceof TestItemImpl)) {
|
||||
throw new InvalidTestItemError(item.id);
|
||||
}
|
||||
|
||||
const itemController = getPrivateApiFor(item).controllerId;
|
||||
if (itemController !== api.controllerId) {
|
||||
throw new MixedTestItemController(item.id, itemController, api.controllerId);
|
||||
}
|
||||
|
||||
if (newMapped.has(item.id)) {
|
||||
throw new DuplicateTestItemError(item.id);
|
||||
}
|
||||
|
||||
newMapped.set(item.id, item);
|
||||
toDelete.delete(item.id);
|
||||
bulk.ops.push({ op: ExtHostTestItemEventOp.Upsert, item });
|
||||
}
|
||||
|
||||
for (const id of toDelete.keys()) {
|
||||
bulk.ops.push({ op: ExtHostTestItemEventOp.RemoveChild, id });
|
||||
}
|
||||
|
||||
api.listener?.(bulk);
|
||||
|
||||
// important mutations come after firing, so if an error happens no
|
||||
// changes will be "saved":
|
||||
mapped = newMapped;
|
||||
},
|
||||
|
||||
|
||||
/** @inheritdoc */
|
||||
add(item: vscode.TestItem) {
|
||||
if (!(item instanceof TestItemImpl)) {
|
||||
throw new InvalidTestItemError(item.id);
|
||||
}
|
||||
|
||||
mapped.set(item.id, item);
|
||||
api.listener?.({ op: ExtHostTestItemEventOp.Upsert, item });
|
||||
},
|
||||
|
||||
/** @inheritdoc */
|
||||
delete(id: string) {
|
||||
if (mapped.delete(id)) {
|
||||
api.listener?.({ op: ExtHostTestItemEventOp.RemoveChild, id });
|
||||
}
|
||||
},
|
||||
|
||||
/** @inheritdoc */
|
||||
get(itemId: string) {
|
||||
return mapped.get(itemId);
|
||||
},
|
||||
|
||||
/** JSON serialization function. */
|
||||
toJSON() {
|
||||
return Array.from(mapped.values());
|
||||
},
|
||||
|
||||
/** @inheritdoc */
|
||||
[Symbol.iterator]() {
|
||||
return mapped.values();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export class TestItemImpl implements vscode.TestItem {
|
||||
public readonly id!: string;
|
||||
public readonly uri!: vscode.Uri | undefined;
|
||||
public readonly children!: TestItemCollectionImpl;
|
||||
public readonly parent!: TestItemImpl | undefined;
|
||||
|
||||
public range!: vscode.Range | undefined;
|
||||
public description!: string | undefined;
|
||||
public label!: string;
|
||||
public error!: string | vscode.MarkdownString;
|
||||
public busy!: boolean;
|
||||
public canResolveChildren!: boolean;
|
||||
public tags!: readonly vscode.TestTag[];
|
||||
|
||||
/**
|
||||
* Note that data is deprecated and here for back-compat only
|
||||
*/
|
||||
constructor(controllerId: string, id: string, label: string, uri: vscode.Uri | undefined) {
|
||||
if (id.includes(TestIdPathParts.Delimiter)) {
|
||||
throw new Error(`Test IDs may not include the ${JSON.stringify(id)} symbol`);
|
||||
}
|
||||
|
||||
const api = createPrivateApiFor(this, controllerId);
|
||||
Object.defineProperties(this, {
|
||||
id: {
|
||||
value: id,
|
||||
enumerable: true,
|
||||
writable: false,
|
||||
},
|
||||
uri: {
|
||||
value: uri,
|
||||
enumerable: true,
|
||||
writable: false,
|
||||
},
|
||||
parent: {
|
||||
enumerable: false,
|
||||
get() {
|
||||
return api.parent instanceof TestItemRootImpl ? undefined : api.parent;
|
||||
},
|
||||
},
|
||||
children: {
|
||||
value: createTestItemCollection(this),
|
||||
enumerable: true,
|
||||
writable: false,
|
||||
},
|
||||
...makePropDescriptors(api, label),
|
||||
});
|
||||
}
|
||||
|
||||
/** @deprecated back compat */
|
||||
public invalidateResults() {
|
||||
getPrivateApiFor(this).listener?.({ op: ExtHostTestItemEventOp.Invalidated });
|
||||
}
|
||||
}
|
||||
|
||||
export class TestItemRootImpl extends TestItemImpl {
|
||||
constructor(controllerId: string, label: string) {
|
||||
super(controllerId, controllerId, label, undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { CommandsConverter, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ThemeIcon } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { MarshalledId } from 'vs/base/common/marshalling';
|
||||
|
||||
export interface IExtHostTimeline extends ExtHostTimelineShape {
|
||||
readonly _serviceBrand: undefined;
|
||||
@@ -38,7 +39,7 @@ export class ExtHostTimeline implements IExtHostTimeline {
|
||||
|
||||
commands.registerArgumentProcessor({
|
||||
processArgument: arg => {
|
||||
if (arg && arg.$mid === 11) {
|
||||
if (arg && arg.$mid === MarshalledId.TimelineActionContext) {
|
||||
const uri = arg.uri === undefined ? undefined : URI.revive(arg.uri);
|
||||
return this._itemsBySourceAndUriMap.get(arg.source)?.get(getUriKey(uri))?.get(arg.handle);
|
||||
}
|
||||
@@ -131,7 +132,7 @@ export class ExtHostTimeline implements IExtHostTimeline {
|
||||
let themeIcon;
|
||||
if (item.iconPath) {
|
||||
if (iconPath instanceof ThemeIcon) {
|
||||
themeIcon = { id: iconPath.id };
|
||||
themeIcon = { id: iconPath.id, color: iconPath.color };
|
||||
}
|
||||
else if (URI.isUri(iconPath)) {
|
||||
icon = iconPath;
|
||||
|
||||
@@ -123,7 +123,7 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
};
|
||||
}
|
||||
|
||||
$getChildren(treeViewId: string, treeItemHandle?: string): Promise<ITreeItem[]> {
|
||||
$getChildren(treeViewId: string, treeItemHandle?: string): Promise<ITreeItem[] | undefined> {
|
||||
const treeView = this.treeViews.get(treeViewId);
|
||||
if (!treeView) {
|
||||
return Promise.reject(new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId)));
|
||||
@@ -224,7 +224,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
private readonly dataProvider: vscode.TreeDataProvider<T>;
|
||||
private readonly dndController: vscode.DragAndDropController<T> | undefined;
|
||||
|
||||
private roots: TreeNode[] | null = null;
|
||||
private roots: TreeNode[] | undefined = undefined;
|
||||
private elements: Map<TreeItemHandle, T> = new Map<TreeItemHandle, T>();
|
||||
// {{SQL CARBON EDIT}}
|
||||
protected nodes: Map<T, TreeNode> = new Map<T, TreeNode>();
|
||||
@@ -276,7 +276,10 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
if (this.proxy) {
|
||||
this.proxy.$registerTreeViewDataProvider(viewId, { showCollapseAll: !!options.showCollapseAll, canSelectMany: !!options.canSelectMany, canDragAndDrop: options.dragAndDropController !== undefined });
|
||||
}
|
||||
if (this.dataProvider.onDidChangeTreeData) {
|
||||
this.dndController = options.dragAndDropController;
|
||||
if (this.dataProvider.onDidChangeTreeData2) {
|
||||
this._register(this.dataProvider.onDidChangeTreeData2(elementOrElements => this._onDidChangeData.fire({ message: false, element: elementOrElements })));
|
||||
} else if (this.dataProvider.onDidChangeTreeData) {
|
||||
this._register(this.dataProvider.onDidChangeTreeData(element => this._onDidChangeData.fire({ message: false, element })));
|
||||
}
|
||||
|
||||
@@ -316,16 +319,20 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
}));
|
||||
}
|
||||
|
||||
getChildren(parentHandle: TreeItemHandle | Root): Promise<ITreeItem[]> {
|
||||
async getChildren(parentHandle: TreeItemHandle | Root): Promise<ITreeItem[] | undefined> {
|
||||
const parentElement = parentHandle ? this.getExtensionElement(parentHandle) : undefined;
|
||||
if (parentHandle && !parentElement) {
|
||||
this.logService.error(`No tree item with id \'${parentHandle}\' found.`);
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
const childrenNodes = this.getChildrenNodes(parentHandle); // Get it from cache
|
||||
return (childrenNodes ? Promise.resolve(childrenNodes) : this.fetchChildrenNodes(parentElement))
|
||||
.then(nodes => nodes.map(n => n.item));
|
||||
let childrenNodes: TreeNode[] | undefined = this.getChildrenNodes(parentHandle); // Get it from cache
|
||||
|
||||
if (!childrenNodes) {
|
||||
childrenNodes = await this.fetchChildrenNodes(parentElement);
|
||||
}
|
||||
|
||||
return childrenNodes ? childrenNodes.map(n => n.item) : undefined;
|
||||
}
|
||||
|
||||
getExtensionElement(treeItemHandle: TreeItemHandle): T | undefined {
|
||||
@@ -481,7 +488,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
}));
|
||||
}
|
||||
|
||||
private getChildrenNodes(parentNodeOrHandle: TreeNode | TreeItemHandle | Root): TreeNode[] | null {
|
||||
private getChildrenNodes(parentNodeOrHandle: TreeNode | TreeItemHandle | Root): TreeNode[] | undefined {
|
||||
if (parentNodeOrHandle) {
|
||||
let parentNode: TreeNode | undefined;
|
||||
if (typeof parentNodeOrHandle === 'string') {
|
||||
@@ -490,12 +497,12 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
} else {
|
||||
parentNode = parentNodeOrHandle;
|
||||
}
|
||||
return parentNode ? parentNode.children || null : null;
|
||||
return parentNode ? parentNode.children || undefined : undefined;
|
||||
}
|
||||
return this.roots;
|
||||
}
|
||||
|
||||
private async fetchChildrenNodes(parentElement?: T): Promise<TreeNode[]> {
|
||||
private async fetchChildrenNodes(parentElement?: T): Promise<TreeNode[] | undefined> {
|
||||
// clear children cache
|
||||
this.clearChildren(parentElement);
|
||||
|
||||
@@ -505,7 +512,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
const parentNode = parentElement ? this.nodes.get(parentElement) : undefined;
|
||||
const elements = await this.dataProvider.getChildren(parentElement);
|
||||
if (cts.token.isCancellationRequested) {
|
||||
return [];
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const items = await Promise.all(coalesce(elements || []).map(async element => {
|
||||
@@ -513,7 +520,7 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
return item && !cts.token.isCancellationRequested ? this.createAndRegisterTreeNode(element, item, parentNode) : null;
|
||||
}));
|
||||
if (cts.token.isCancellationRequested) {
|
||||
return [];
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return coalesce(items);
|
||||
@@ -797,9 +804,8 @@ export class ExtHostTreeView<T> extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
protected clearAll(): void {
|
||||
this.roots = null;
|
||||
protected clearAll(): void { // {{SQL CARBON EDIT}}
|
||||
this.roots = undefined;
|
||||
this.elements.clear();
|
||||
this.nodes.forEach(node => node.dispose());
|
||||
this.nodes.clear();
|
||||
|
||||
@@ -17,11 +17,12 @@ export interface TunnelDto {
|
||||
remoteAddress: { port: number, host: string };
|
||||
localAddress: { port: number, host: string } | string;
|
||||
public: boolean;
|
||||
protocol: string | undefined;
|
||||
}
|
||||
|
||||
export namespace TunnelDto {
|
||||
export function fromApiTunnel(tunnel: vscode.Tunnel): TunnelDto {
|
||||
return { remoteAddress: tunnel.remoteAddress, localAddress: tunnel.localAddress, public: !!tunnel.public };
|
||||
return { remoteAddress: tunnel.remoteAddress, localAddress: tunnel.localAddress, public: !!tunnel.public, protocol: tunnel.protocol };
|
||||
}
|
||||
export function fromServiceTunnel(tunnel: RemoteTunnel): TunnelDto {
|
||||
return {
|
||||
@@ -30,7 +31,8 @@ export namespace TunnelDto {
|
||||
port: tunnel.tunnelRemotePort
|
||||
},
|
||||
localAddress: tunnel.localAddress,
|
||||
public: tunnel.public
|
||||
public: tunnel.public,
|
||||
protocol: tunnel.protocol
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { coalesce, isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import * as htmlContent from 'vs/base/common/htmlContent';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import * as marked from 'vs/base/common/marked/marked';
|
||||
@@ -19,18 +20,21 @@ import { IContentDecorationRenderOptions, IDecorationOptions, IDecorationRenderO
|
||||
import { EndOfLineSequence, TrackedRangeStickiness } from 'vs/editor/common/model';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import * as languageSelector from 'vs/editor/common/modes/languageSelector';
|
||||
import { EditorOverride, ITextEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { EditorResolution, ITextEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { IMarkerData, IRelatedInformation, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers';
|
||||
import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { CommandsConverter } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { EditorGroupColumn, SaveReason } from 'vs/workbench/common/editor';
|
||||
import { getPrivateApiFor, TestItemImpl } from 'vs/workbench/api/common/extHostTestingPrivateApi';
|
||||
import { SaveReason } from 'vs/workbench/common/editor';
|
||||
import * as notebooks from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import * as search from 'vs/workbench/contrib/search/common/search';
|
||||
import { ISerializedTestResults, ITestItem, ITestMessage, SerializedTestResultItem } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { CoverageDetails, DetailType, ICoveredCount, IFileCoverage, ISerializedTestResults, ITestErrorMessage, ITestItem, ITestItemContext, ITestTag, SerializedTestResultItem, TestMessageType } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
|
||||
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import { ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import type * as vscode from 'vscode';
|
||||
import * as types from './extHostTypes';
|
||||
@@ -548,33 +552,6 @@ export namespace WorkspaceEdit {
|
||||
notebookVersionId: extHostNotebooks?.getNotebookDocument(entry.uri, true)?.apiNotebook.version
|
||||
});
|
||||
|
||||
} else if (entry._type === types.FileEditType.CellOutput) {
|
||||
if (entry.newOutputs) {
|
||||
result.edits.push({
|
||||
_type: extHostProtocol.WorkspaceEditType.Cell,
|
||||
metadata: entry.metadata,
|
||||
resource: entry.uri,
|
||||
edit: {
|
||||
editType: notebooks.CellEditType.Output,
|
||||
index: entry.index,
|
||||
append: entry.append,
|
||||
outputs: entry.newOutputs.map(NotebookCellOutput.from)
|
||||
}
|
||||
});
|
||||
}
|
||||
// todo@joh merge metadata and output edit?
|
||||
if (entry.newMetadata) {
|
||||
result.edits.push({
|
||||
_type: extHostProtocol.WorkspaceEditType.Cell,
|
||||
metadata: entry.metadata,
|
||||
resource: entry.uri,
|
||||
edit: {
|
||||
editType: notebooks.CellEditType.PartialMetadata,
|
||||
index: entry.index,
|
||||
metadata: entry.newMetadata
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (entry._type === types.FileEditType.CellReplace) {
|
||||
result.edits.push({
|
||||
_type: extHostProtocol.WorkspaceEditType.Cell,
|
||||
@@ -588,18 +565,6 @@ export namespace WorkspaceEdit {
|
||||
cells: entry.cells.map(NotebookCellData.from)
|
||||
}
|
||||
});
|
||||
} else if (entry._type === types.FileEditType.CellOutputItem) {
|
||||
result.edits.push({
|
||||
_type: extHostProtocol.WorkspaceEditType.Cell,
|
||||
metadata: entry.metadata,
|
||||
resource: entry.uri,
|
||||
edit: {
|
||||
editType: notebooks.CellEditType.OutputItems,
|
||||
outputId: entry.outputId,
|
||||
items: entry.newOutputItems?.map(NotebookCellOutputItem.from) || [],
|
||||
append: entry.append
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -759,6 +724,28 @@ export namespace CallHierarchyItem {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function from(item: vscode.CallHierarchyItem, sessionId?: string, itemId?: string): extHostProtocol.ICallHierarchyItemDto {
|
||||
|
||||
sessionId = sessionId ?? (<types.CallHierarchyItem>item)._sessionId;
|
||||
itemId = itemId ?? (<types.CallHierarchyItem>item)._itemId;
|
||||
|
||||
if (sessionId === undefined || itemId === undefined) {
|
||||
throw new Error('invalid item');
|
||||
}
|
||||
|
||||
return {
|
||||
_sessionId: sessionId,
|
||||
_itemId: itemId,
|
||||
name: item.name,
|
||||
detail: item.detail,
|
||||
kind: SymbolKind.from(item.kind),
|
||||
uri: item.uri,
|
||||
range: Range.from(item.range),
|
||||
selectionRange: Range.from(item.selectionRange),
|
||||
tags: item.tags?.map(SymbolTag.from)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export namespace CallHierarchyIncomingCall {
|
||||
@@ -1036,11 +1023,7 @@ export namespace CompletionItem {
|
||||
|
||||
export function to(suggestion: modes.CompletionItem, converter?: CommandsConverter): types.CompletionItem {
|
||||
|
||||
const result = new types.CompletionItem(typeof suggestion.label === 'string' ? suggestion.label : suggestion.label.name);
|
||||
if (typeof suggestion.label !== 'string') {
|
||||
result.label2 = suggestion.label;
|
||||
}
|
||||
|
||||
const result = new types.CompletionItem(suggestion.label);
|
||||
result.insertText = suggestion.insertText;
|
||||
result.kind = CompletionItemKind.to(suggestion.kind);
|
||||
result.tags = suggestion.tags?.map(CompletionItemTag.to);
|
||||
@@ -1343,7 +1326,7 @@ export namespace TextEditorOpenOptions {
|
||||
inactive: options.background,
|
||||
preserveFocus: options.preserveFocus,
|
||||
selection: typeof options.selection === 'object' ? Range.from(options.selection) : undefined,
|
||||
override: typeof options.override === 'boolean' ? EditorOverride.DISABLED : undefined
|
||||
override: typeof options.override === 'boolean' ? EditorResolution.DISABLED : undefined
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1458,8 +1441,8 @@ export namespace NotebookCellKind {
|
||||
|
||||
export namespace NotebookData {
|
||||
|
||||
export function from(data: vscode.NotebookData): notebooks.NotebookDataDto {
|
||||
const res: notebooks.NotebookDataDto = {
|
||||
export function from(data: vscode.NotebookData): extHostProtocol.NotebookDataDto {
|
||||
const res: extHostProtocol.NotebookDataDto = {
|
||||
metadata: data.metadata ?? Object.create(null),
|
||||
cells: [],
|
||||
};
|
||||
@@ -1470,7 +1453,7 @@ export namespace NotebookData {
|
||||
return res;
|
||||
}
|
||||
|
||||
export function to(data: notebooks.NotebookDataDto): vscode.NotebookData {
|
||||
export function to(data: extHostProtocol.NotebookDataDto): vscode.NotebookData {
|
||||
const res = new types.NotebookData(
|
||||
data.cells.map(NotebookCellData.to),
|
||||
);
|
||||
@@ -1483,10 +1466,11 @@ export namespace NotebookData {
|
||||
|
||||
export namespace NotebookCellData {
|
||||
|
||||
export function from(data: vscode.NotebookCellData): notebooks.ICellDto2 {
|
||||
export function from(data: vscode.NotebookCellData): extHostProtocol.NotebookCellDataDto {
|
||||
return {
|
||||
cellKind: NotebookCellKind.from(data.kind),
|
||||
language: data.languageId,
|
||||
mime: data.mime,
|
||||
source: data.value,
|
||||
metadata: data.metadata,
|
||||
internalMetadata: NotebookCellExecutionSummary.from(data.executionSummary ?? {}),
|
||||
@@ -1494,11 +1478,12 @@ export namespace NotebookCellData {
|
||||
};
|
||||
}
|
||||
|
||||
export function to(data: notebooks.ICellDto2): vscode.NotebookCellData {
|
||||
export function to(data: extHostProtocol.NotebookCellDataDto): vscode.NotebookCellData {
|
||||
return new types.NotebookCellData(
|
||||
NotebookCellKind.to(data.cellKind),
|
||||
data.source,
|
||||
data.language,
|
||||
data.mime,
|
||||
data.outputs ? data.outputs.map(NotebookCellOutput.to) : undefined,
|
||||
data.metadata,
|
||||
data.internalMetadata ? NotebookCellExecutionSummary.to(data.internalMetadata) : undefined
|
||||
@@ -1507,29 +1492,29 @@ export namespace NotebookCellData {
|
||||
}
|
||||
|
||||
export namespace NotebookCellOutputItem {
|
||||
export function from(item: types.NotebookCellOutputItem): notebooks.IOutputItemDto {
|
||||
export function from(item: types.NotebookCellOutputItem): extHostProtocol.NotebookOutputItemDto {
|
||||
return {
|
||||
mime: item.mime,
|
||||
valueBytes: Array.from(item.data), //todo@jrieken this HACKY and SLOW... hoist VSBuffer instead
|
||||
valueBytes: VSBuffer.wrap(item.data),
|
||||
};
|
||||
}
|
||||
|
||||
export function to(item: notebooks.IOutputItemDto): types.NotebookCellOutputItem {
|
||||
return new types.NotebookCellOutputItem(new Uint8Array(item.valueBytes), item.mime);
|
||||
export function to(item: extHostProtocol.NotebookOutputItemDto): types.NotebookCellOutputItem {
|
||||
return new types.NotebookCellOutputItem(item.valueBytes.buffer, item.mime);
|
||||
}
|
||||
}
|
||||
|
||||
export namespace NotebookCellOutput {
|
||||
export function from(output: vscode.NotebookCellOutput): notebooks.IOutputDto {
|
||||
export function from(output: vscode.NotebookCellOutput): extHostProtocol.NotebookOutputDto {
|
||||
return {
|
||||
outputId: output.id,
|
||||
outputs: output.items.map(NotebookCellOutputItem.from),
|
||||
items: output.items.map(NotebookCellOutputItem.from),
|
||||
metadata: output.metadata
|
||||
};
|
||||
}
|
||||
|
||||
export function to(output: notebooks.IOutputDto): vscode.NotebookCellOutput {
|
||||
const items = output.outputs.map(NotebookCellOutputItem.to);
|
||||
export function to(output: extHostProtocol.NotebookOutputDto): vscode.NotebookCellOutput {
|
||||
const items = output.items.map(NotebookCellOutputItem.to);
|
||||
return new types.NotebookCellOutput(items, output.outputId, output.metadata);
|
||||
}
|
||||
}
|
||||
@@ -1655,100 +1640,132 @@ export namespace NotebookRendererScript {
|
||||
}
|
||||
|
||||
export namespace TestMessage {
|
||||
export function from(message: vscode.TestMessage): ITestMessage {
|
||||
export function from(message: vscode.TestMessage): ITestErrorMessage {
|
||||
return {
|
||||
message: MarkdownString.fromStrict(message.message) || '',
|
||||
severity: message.severity,
|
||||
expectedOutput: message.expectedOutput,
|
||||
actualOutput: message.actualOutput,
|
||||
type: TestMessageType.Error,
|
||||
expected: message.expectedOutput,
|
||||
actual: message.actualOutput,
|
||||
location: message.location ? location.from(message.location) as any : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function to(item: ITestMessage): vscode.TestMessage {
|
||||
export function to(item: ITestErrorMessage): vscode.TestMessage {
|
||||
const message = new types.TestMessage(typeof item.message === 'string' ? item.message : MarkdownString.to(item.message));
|
||||
message.severity = item.severity;
|
||||
message.actualOutput = item.actualOutput;
|
||||
message.expectedOutput = item.expectedOutput;
|
||||
message.actualOutput = item.actual;
|
||||
message.expectedOutput = item.expected;
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace TestItem {
|
||||
export type Raw<T = unknown> = vscode.TestItem<T>;
|
||||
export namespace TestTag {
|
||||
const enum Constants {
|
||||
Delimiter = '\0',
|
||||
}
|
||||
|
||||
export function from(item: vscode.TestItem<unknown>): ITestItem {
|
||||
export const namespace = (ctrlId: string, tagId: string) =>
|
||||
ctrlId + Constants.Delimiter + tagId;
|
||||
|
||||
export const denamespace = (namespaced: string) => {
|
||||
const index = namespaced.indexOf(Constants.Delimiter);
|
||||
return { ctrlId: namespaced.slice(0, index), tagId: namespaced.slice(index + 1) };
|
||||
};
|
||||
}
|
||||
|
||||
export namespace TestItem {
|
||||
export type Raw = vscode.TestItem;
|
||||
|
||||
export function from(item: TestItemImpl): ITestItem {
|
||||
const ctrlId = getPrivateApiFor(item).controllerId;
|
||||
return {
|
||||
extId: item.id,
|
||||
extId: TestId.fromExtHostTestItem(item, ctrlId).toString(),
|
||||
label: item.label,
|
||||
uri: item.uri,
|
||||
tags: item.tags.map(t => TestTag.namespace(ctrlId, t.id)),
|
||||
range: Range.from(item.range) || null,
|
||||
debuggable: item.debuggable ?? false,
|
||||
description: item.description || null,
|
||||
runnable: item.runnable ?? true,
|
||||
error: item.error ? (MarkdownString.fromStrict(item.error) || null) : null,
|
||||
};
|
||||
}
|
||||
|
||||
export function fromResultSnapshot(item: vscode.TestResultSnapshot): ITestItem {
|
||||
export function toPlain(item: ITestItem): Omit<vscode.TestItem, 'children' | 'invalidate' | 'discoverChildren'> {
|
||||
return {
|
||||
extId: item.id,
|
||||
label: item.label,
|
||||
uri: item.uri,
|
||||
range: Range.from(item.range) || null,
|
||||
debuggable: false,
|
||||
description: item.description || null,
|
||||
error: null,
|
||||
runnable: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function toPlain(item: ITestItem): Omit<vscode.TestItem<never>, 'children' | 'invalidate' | 'discoverChildren'> {
|
||||
return {
|
||||
id: item.extId,
|
||||
id: TestId.fromString(item.extId).localId,
|
||||
label: item.label,
|
||||
uri: URI.revive(item.uri),
|
||||
tags: (item.tags || []).map(t => {
|
||||
const { tagId } = TestTag.denamespace(t);
|
||||
return new types.TestTag(tagId, tagId);
|
||||
}),
|
||||
range: Range.to(item.range || undefined),
|
||||
addChild: () => undefined,
|
||||
dispose: () => undefined,
|
||||
status: types.TestItemStatus.Pending,
|
||||
data: undefined as never,
|
||||
debuggable: item.debuggable,
|
||||
invalidateResults: () => undefined,
|
||||
canResolveChildren: false,
|
||||
busy: false,
|
||||
description: item.description || undefined,
|
||||
runnable: item.runnable,
|
||||
};
|
||||
}
|
||||
|
||||
export function to(item: ITestItem): types.TestItemImpl {
|
||||
const testItem = new types.TestItemImpl(item.extId, item.label, URI.revive(item.uri), undefined);
|
||||
function to(item: ITestItem): TestItemImpl {
|
||||
const testId = TestId.fromString(item.extId);
|
||||
const testItem = new TestItemImpl(testId.controllerId, testId.localId, item.label, URI.revive(item.uri));
|
||||
testItem.range = Range.to(item.range || undefined);
|
||||
testItem.debuggable = item.debuggable;
|
||||
testItem.description = item.description || undefined;
|
||||
testItem.runnable = item.runnable;
|
||||
return testItem;
|
||||
}
|
||||
|
||||
export function toItemFromContext(context: ITestItemContext): TestItemImpl {
|
||||
let node: TestItemImpl | undefined;
|
||||
for (const test of context.tests) {
|
||||
const next = to(test.item);
|
||||
getPrivateApiFor(next).parent = node;
|
||||
node = next;
|
||||
}
|
||||
|
||||
return node!;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace TestTag {
|
||||
export function from(tag: vscode.TestTag): ITestTag {
|
||||
return { id: tag.id, label: tag.label };
|
||||
}
|
||||
|
||||
export function to(tag: ITestTag): vscode.TestTag {
|
||||
return new types.TestTag(tag.id, tag.label);
|
||||
}
|
||||
}
|
||||
|
||||
export namespace TestResults {
|
||||
const convertTestResultItem = (item: SerializedTestResultItem, byInternalId: Map<string, SerializedTestResultItem>): vscode.TestResultSnapshot => ({
|
||||
...TestItem.toPlain(item.item),
|
||||
taskStates: item.tasks.map(t => ({
|
||||
state: t.state,
|
||||
duration: t.duration,
|
||||
messages: t.messages.map(TestMessage.to),
|
||||
})),
|
||||
children: item.children
|
||||
.map(c => byInternalId.get(c))
|
||||
.filter(isDefined)
|
||||
.map(c => convertTestResultItem(c, byInternalId)),
|
||||
});
|
||||
const convertTestResultItem = (item: SerializedTestResultItem, byInternalId: Map<string, SerializedTestResultItem>): vscode.TestResultSnapshot => {
|
||||
const snapshot: vscode.TestResultSnapshot = ({
|
||||
...TestItem.toPlain(item.item),
|
||||
parent: undefined,
|
||||
taskStates: item.tasks.map(t => ({
|
||||
state: t.state as number as types.TestResultState,
|
||||
duration: t.duration,
|
||||
messages: t.messages
|
||||
.filter((m): m is ITestErrorMessage => m.type === TestMessageType.Error)
|
||||
.map(TestMessage.to),
|
||||
})),
|
||||
children: item.children
|
||||
.map(c => byInternalId.get(c))
|
||||
.filter(isDefined)
|
||||
.map(c => convertTestResultItem(c, byInternalId))
|
||||
});
|
||||
|
||||
for (const child of snapshot.children) {
|
||||
(child as any).parent = snapshot;
|
||||
}
|
||||
|
||||
return snapshot;
|
||||
};
|
||||
|
||||
export function to(serialized: ISerializedTestResults): vscode.TestRunResult {
|
||||
const roots: SerializedTestResultItem[] = [];
|
||||
const byInternalId = new Map<string, SerializedTestResultItem>();
|
||||
for (const item of serialized.items) {
|
||||
byInternalId.set(item.item.extId, item);
|
||||
if (item.direct) {
|
||||
if (serialized.request.targets.some(t => t.controllerId === item.controllerId && t.testIds.includes(item.item.extId))) {
|
||||
roots.push(item);
|
||||
}
|
||||
}
|
||||
@@ -1760,6 +1777,45 @@ export namespace TestResults {
|
||||
}
|
||||
}
|
||||
|
||||
export namespace TestCoverage {
|
||||
function fromCoveredCount(count: vscode.CoveredCount): ICoveredCount {
|
||||
return { covered: count.covered, total: count.covered };
|
||||
}
|
||||
|
||||
function fromLocation(location: vscode.Range | vscode.Position) {
|
||||
return 'line' in location ? Position.from(location) : Range.from(location);
|
||||
}
|
||||
|
||||
export function fromDetailed(coverage: vscode.DetailedCoverage): CoverageDetails {
|
||||
if ('branches' in coverage) {
|
||||
return {
|
||||
count: coverage.executionCount,
|
||||
location: fromLocation(coverage.location),
|
||||
type: DetailType.Statement,
|
||||
branches: coverage.branches.length
|
||||
? coverage.branches.map(b => ({ count: b.executionCount, location: b.location && fromLocation(b.location) }))
|
||||
: undefined,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: DetailType.Function,
|
||||
count: coverage.executionCount,
|
||||
location: fromLocation(coverage.location),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function fromFile(coverage: vscode.FileCoverage): IFileCoverage {
|
||||
return {
|
||||
uri: coverage.uri,
|
||||
statement: fromCoveredCount(coverage.statementCoverage),
|
||||
branch: coverage.branchCoverage && fromCoveredCount(coverage.branchCoverage),
|
||||
function: coverage.functionCoverage && fromCoveredCount(coverage.functionCoverage),
|
||||
details: coverage.detailedCoverage?.map(fromDetailed),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export namespace CodeActionTriggerKind {
|
||||
|
||||
export function to(value: modes.CodeActionTriggerType): types.CodeActionTriggerKind {
|
||||
@@ -1772,3 +1828,44 @@ export namespace CodeActionTriggerKind {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export namespace TypeHierarchyItem {
|
||||
|
||||
export function to(item: extHostProtocol.ITypeHierarchyItemDto): types.TypeHierarchyItem {
|
||||
const result = new types.TypeHierarchyItem(
|
||||
SymbolKind.to(item.kind),
|
||||
item.name,
|
||||
item.detail || '',
|
||||
URI.revive(item.uri),
|
||||
Range.to(item.range),
|
||||
Range.to(item.selectionRange)
|
||||
);
|
||||
|
||||
result._sessionId = item._sessionId;
|
||||
result._itemId = item._itemId;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function from(item: vscode.TypeHierarchyItem, sessionId?: string, itemId?: string): extHostProtocol.ITypeHierarchyItemDto {
|
||||
|
||||
sessionId = sessionId ?? (<types.TypeHierarchyItem>item)._sessionId;
|
||||
itemId = itemId ?? (<types.TypeHierarchyItem>item)._itemId;
|
||||
|
||||
if (sessionId === undefined || itemId === undefined) {
|
||||
throw new Error('invalid item');
|
||||
}
|
||||
|
||||
return {
|
||||
_sessionId: sessionId,
|
||||
_itemId: itemId,
|
||||
kind: SymbolKind.from(item.kind),
|
||||
name: item.name,
|
||||
detail: item.detail ?? '',
|
||||
uri: item.uri,
|
||||
range: Range.from(item.range),
|
||||
selectionRange: Range.from(item.selectionRange),
|
||||
tags: item.tags?.map(SymbolTag.from)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,20 +6,19 @@
|
||||
import { asArray, coalesceInPlace, equals } from 'vs/base/common/arrays';
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { isMarkdownString, MarkdownString as BaseMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { ReadonlyMapView, ResourceMap } from 'vs/base/common/map';
|
||||
import { normalizeMimeType } from 'vs/base/common/mime';
|
||||
import { MarkdownString as BaseMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { Mimes, normalizeMimeType } from 'vs/base/common/mime';
|
||||
import { isArray, isStringArray } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { FileSystemProviderErrorCode, markAsFileSystemProviderError } from 'vs/platform/files/common/files';
|
||||
import { RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { getPrivateApiFor, ExtHostTestItemEventType, IExtHostTestItemApi } from 'vs/workbench/api/common/extHostTestingPrivateApi';
|
||||
import { CellEditType, ICellEditOperation } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellEditType, ICellPartialMetadataEdit, IDocumentMetadataEdit } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
function es5ClassCompat(target: Function): any {
|
||||
// @ts-ignore - {{SQL CARBON EDIT}}
|
||||
///@ts-expect-error
|
||||
function _() { return Reflect.construct(target, arguments, this.constructor); }
|
||||
Object.defineProperty(_, 'name', Object.getOwnPropertyDescriptor(target, 'name')!);
|
||||
Object.setPrototypeOf(_, target);
|
||||
@@ -588,9 +587,7 @@ export const enum FileEditType {
|
||||
File = 1,
|
||||
Text = 2,
|
||||
Cell = 3,
|
||||
CellOutput = 4,
|
||||
CellReplace = 5,
|
||||
CellOutputItem = 6
|
||||
}
|
||||
|
||||
export interface IFileOperation {
|
||||
@@ -611,7 +608,7 @@ export interface IFileTextEdit {
|
||||
export interface IFileCellEdit {
|
||||
_type: FileEditType.Cell;
|
||||
uri: URI;
|
||||
edit?: ICellEditOperation;
|
||||
edit?: ICellPartialMetadataEdit | IDocumentMetadataEdit;
|
||||
notebookMetadata?: Record<string, any>;
|
||||
metadata?: vscode.WorkspaceEditEntryMetadata;
|
||||
}
|
||||
@@ -625,28 +622,8 @@ export interface ICellEdit {
|
||||
cells: vscode.NotebookCellData[];
|
||||
}
|
||||
|
||||
export interface ICellOutputEdit {
|
||||
_type: FileEditType.CellOutput;
|
||||
uri: URI;
|
||||
index: number;
|
||||
append: boolean;
|
||||
newOutputs?: NotebookCellOutput[];
|
||||
newMetadata?: Record<string, any>;
|
||||
metadata?: vscode.WorkspaceEditEntryMetadata;
|
||||
}
|
||||
|
||||
export interface ICellOutputItemsEdit {
|
||||
_type: FileEditType.CellOutputItem;
|
||||
uri: URI;
|
||||
index: number;
|
||||
outputId: string;
|
||||
append: boolean;
|
||||
newOutputItems?: NotebookCellOutputItem[];
|
||||
metadata?: vscode.WorkspaceEditEntryMetadata;
|
||||
}
|
||||
|
||||
|
||||
type WorkspaceEditEntry = IFileOperation | IFileTextEdit | IFileCellEdit | ICellEdit | ICellOutputEdit | ICellOutputItemsEdit;
|
||||
type WorkspaceEditEntry = IFileOperation | IFileTextEdit | IFileCellEdit | ICellEdit;
|
||||
|
||||
@es5ClassCompat
|
||||
export class WorkspaceEdit implements vscode.WorkspaceEdit {
|
||||
@@ -1019,20 +996,18 @@ export class Diagnostic {
|
||||
@es5ClassCompat
|
||||
export class Hover {
|
||||
|
||||
public contents: vscode.MarkdownString[] | vscode.MarkedString[];
|
||||
public contents: (vscode.MarkdownString | vscode.MarkedString)[];
|
||||
public range: Range | undefined;
|
||||
|
||||
constructor(
|
||||
contents: vscode.MarkdownString | vscode.MarkedString | vscode.MarkdownString[] | vscode.MarkedString[],
|
||||
contents: vscode.MarkdownString | vscode.MarkedString | (vscode.MarkdownString | vscode.MarkedString)[],
|
||||
range?: Range
|
||||
) {
|
||||
if (!contents) {
|
||||
throw new Error('Illegal argument, contents must be defined');
|
||||
}
|
||||
if (Array.isArray(contents)) {
|
||||
this.contents = <vscode.MarkdownString[] | vscode.MarkedString[]>contents;
|
||||
} else if (isMarkdownString(contents)) {
|
||||
this.contents = [contents];
|
||||
this.contents = contents;
|
||||
} else {
|
||||
this.contents = [contents];
|
||||
}
|
||||
@@ -1267,6 +1242,7 @@ export class CallHierarchyItem {
|
||||
_itemId?: string;
|
||||
|
||||
kind: SymbolKind;
|
||||
tags?: SymbolTag[];
|
||||
name: string;
|
||||
detail?: string;
|
||||
uri: URI;
|
||||
@@ -1304,6 +1280,13 @@ export class CallHierarchyOutgoingCall {
|
||||
}
|
||||
}
|
||||
|
||||
export enum LanguageStatusSeverity {
|
||||
Information = 0,
|
||||
Warning = 1,
|
||||
Error = 2
|
||||
}
|
||||
|
||||
|
||||
@es5ClassCompat
|
||||
export class CodeLens {
|
||||
|
||||
@@ -1356,6 +1339,10 @@ export class MarkdownString implements vscode.MarkdownString {
|
||||
return this.#delegate.supportThemeIcons;
|
||||
}
|
||||
|
||||
set supportThemeIcons(value: boolean | undefined) {
|
||||
this.#delegate.supportThemeIcons = value;
|
||||
}
|
||||
|
||||
appendText(value: string): vscode.MarkdownString {
|
||||
this.#delegate.appendText(value);
|
||||
return this;
|
||||
@@ -1487,18 +1474,15 @@ export enum CompletionItemTag {
|
||||
}
|
||||
|
||||
export interface CompletionItemLabel {
|
||||
name: string;
|
||||
parameters?: string;
|
||||
qualifier?: string;
|
||||
type?: string;
|
||||
label: string;
|
||||
detail?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
|
||||
@es5ClassCompat
|
||||
export class CompletionItem implements vscode.CompletionItem {
|
||||
|
||||
label: string;
|
||||
label2?: CompletionItemLabel;
|
||||
label: string | CompletionItemLabel;
|
||||
kind?: CompletionItemKind;
|
||||
tags?: CompletionItemTag[];
|
||||
detail?: string;
|
||||
@@ -1514,7 +1498,7 @@ export class CompletionItem implements vscode.CompletionItem {
|
||||
additionalTextEdits?: TextEdit[];
|
||||
command?: vscode.Command;
|
||||
|
||||
constructor(label: string, kind?: CompletionItemKind) {
|
||||
constructor(label: string | CompletionItemLabel, kind?: CompletionItemKind) {
|
||||
this.label = label;
|
||||
this.kind = kind;
|
||||
}
|
||||
@@ -1522,7 +1506,6 @@ export class CompletionItem implements vscode.CompletionItem {
|
||||
toJSON(): any {
|
||||
return {
|
||||
label: this.label,
|
||||
label2: this.label2,
|
||||
kind: this.kind && CompletionItemKind[this.kind],
|
||||
detail: this.detail,
|
||||
documentation: this.documentation,
|
||||
@@ -1729,6 +1712,39 @@ export enum SourceControlInputBoxValidationType {
|
||||
Information = 2
|
||||
}
|
||||
|
||||
export class TerminalLink implements vscode.TerminalLink {
|
||||
constructor(
|
||||
public startIndex: number,
|
||||
public length: number,
|
||||
public tooltip?: string
|
||||
) {
|
||||
if (typeof startIndex !== 'number' || startIndex < 0) {
|
||||
throw illegalArgument('startIndex');
|
||||
}
|
||||
if (typeof length !== 'number' || length < 1) {
|
||||
throw illegalArgument('length');
|
||||
}
|
||||
if (tooltip !== undefined && typeof tooltip !== 'string') {
|
||||
throw illegalArgument('tooltip');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export enum TerminalLocation {
|
||||
Panel = 0,
|
||||
Editor = 1,
|
||||
}
|
||||
|
||||
export class TerminalProfile implements vscode.TerminalProfile {
|
||||
constructor(
|
||||
public options: vscode.TerminalOptions | vscode.ExtensionTerminalOptions
|
||||
) {
|
||||
if (typeof options !== 'object') {
|
||||
illegalArgument('options');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export enum TaskRevealKind {
|
||||
Always = 1,
|
||||
|
||||
@@ -1748,6 +1764,7 @@ export enum TaskPanelKind {
|
||||
@es5ClassCompat
|
||||
export class TaskGroup implements vscode.TaskGroup {
|
||||
|
||||
isDefault?: boolean;
|
||||
private _id: string;
|
||||
|
||||
public static Clean: TaskGroup = new TaskGroup('clean', 'Clean');
|
||||
@@ -2894,10 +2911,8 @@ export class FileDecoration {
|
||||
badge?: string;
|
||||
tooltip?: string;
|
||||
color?: vscode.ThemeColor;
|
||||
priority?: number;
|
||||
propagate?: boolean;
|
||||
|
||||
|
||||
constructor(badge?: string, tooltip?: string, color?: ThemeColor) {
|
||||
this.badge = badge;
|
||||
this.tooltip = tooltip;
|
||||
@@ -3009,14 +3024,16 @@ export class NotebookCellData {
|
||||
kind: NotebookCellKind;
|
||||
value: string;
|
||||
languageId: string;
|
||||
mime?: string;
|
||||
outputs?: vscode.NotebookCellOutput[];
|
||||
metadata?: Record<string, any>;
|
||||
executionSummary?: vscode.NotebookCellExecutionSummary;
|
||||
|
||||
constructor(kind: NotebookCellKind, value: string, languageId: string, outputs?: vscode.NotebookCellOutput[], metadata?: Record<string, any>, executionSummary?: vscode.NotebookCellExecutionSummary) {
|
||||
constructor(kind: NotebookCellKind, value: string, languageId: string, mime?: string, outputs?: vscode.NotebookCellOutput[], metadata?: Record<string, any>, executionSummary?: vscode.NotebookCellExecutionSummary) {
|
||||
this.kind = kind;
|
||||
this.value = value;
|
||||
this.languageId = languageId;
|
||||
this.mime = mime;
|
||||
this.outputs = outputs ?? [];
|
||||
this.metadata = metadata;
|
||||
this.executionSummary = executionSummary;
|
||||
@@ -3072,7 +3089,7 @@ export class NotebookCellOutputItem {
|
||||
|
||||
static #encoder = new TextEncoder();
|
||||
|
||||
static text(value: string, mime: string = 'text/plain'): NotebookCellOutputItem {
|
||||
static text(value: string, mime: string = Mimes.text): NotebookCellOutputItem {
|
||||
const bytes = NotebookCellOutputItem.#encoder.encode(String(value));
|
||||
return new NotebookCellOutputItem(bytes, mime);
|
||||
}
|
||||
@@ -3088,7 +3105,7 @@ export class NotebookCellOutputItem {
|
||||
) {
|
||||
const mimeNormalized = normalizeMimeType(mime, true);
|
||||
if (!mimeNormalized) {
|
||||
throw new Error('INVALID mime type, must not be empty or falsy: ' + mime);
|
||||
throw new Error(`INVALID mime type: ${mime}. Must be in the format "type/subtype[;optionalparameter]"`);
|
||||
}
|
||||
this.mime = mimeNormalized;
|
||||
}
|
||||
@@ -3275,7 +3292,6 @@ export class PortAttributes {
|
||||
|
||||
//#region Testing
|
||||
export enum TestResultState {
|
||||
Unset = 0,
|
||||
Queued = 1,
|
||||
Running = 2,
|
||||
Passed = 3,
|
||||
@@ -3284,126 +3300,23 @@ export enum TestResultState {
|
||||
Errored = 6
|
||||
}
|
||||
|
||||
export enum TestMessageSeverity {
|
||||
Error = 0,
|
||||
Warning = 1,
|
||||
Information = 2,
|
||||
Hint = 3
|
||||
export enum TestRunProfileKind {
|
||||
Run = 1,
|
||||
Debug = 2,
|
||||
Coverage = 3,
|
||||
}
|
||||
|
||||
export enum TestItemStatus {
|
||||
Pending = 0,
|
||||
Resolved = 1,
|
||||
@es5ClassCompat
|
||||
export class TestRunRequest implements vscode.TestRunRequest {
|
||||
constructor(
|
||||
public readonly include?: vscode.TestItem[],
|
||||
public readonly exclude?: vscode.TestItem[] | undefined,
|
||||
public readonly profile?: vscode.TestRunProfile,
|
||||
) { }
|
||||
}
|
||||
|
||||
const testItemPropAccessor = <K extends keyof vscode.TestItem<never>>(
|
||||
api: IExtHostTestItemApi,
|
||||
key: K,
|
||||
defaultValue: vscode.TestItem<never>[K],
|
||||
equals: (a: vscode.TestItem<never>[K], b: vscode.TestItem<never>[K]) => boolean
|
||||
) => {
|
||||
let value = defaultValue;
|
||||
return {
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
get() {
|
||||
return value;
|
||||
},
|
||||
set(newValue: vscode.TestItem<never>[K]) {
|
||||
if (!equals(value, newValue)) {
|
||||
value = newValue;
|
||||
api.bus.fire([ExtHostTestItemEventType.SetProp, key, newValue]);
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const strictEqualComparator = <T>(a: T, b: T) => a === b;
|
||||
const rangeComparator = (a: vscode.Range | undefined, b: vscode.Range | undefined) => {
|
||||
if (a === b) { return true; }
|
||||
if (!a || !b) { return false; }
|
||||
return a.isEqual(b);
|
||||
};
|
||||
|
||||
export class TestItemImpl implements vscode.TestItem<unknown> {
|
||||
public readonly id!: string;
|
||||
public readonly uri!: vscode.Uri | undefined;
|
||||
public readonly children!: ReadonlyMap<string, TestItemImpl>;
|
||||
public readonly parent!: TestItemImpl | undefined;
|
||||
|
||||
public range!: vscode.Range | undefined;
|
||||
public description!: string | undefined;
|
||||
public runnable!: boolean;
|
||||
public debuggable!: boolean;
|
||||
public error!: string | vscode.MarkdownString;
|
||||
public status!: vscode.TestItemStatus;
|
||||
|
||||
/** Extension-owned resolve handler */
|
||||
public resolveHandler?: (token: vscode.CancellationToken) => void;
|
||||
|
||||
constructor(id: string, public label: string, uri: vscode.Uri | undefined, public data: unknown) {
|
||||
const api = getPrivateApiFor(this);
|
||||
|
||||
Object.defineProperties(this, {
|
||||
id: {
|
||||
value: id,
|
||||
enumerable: true,
|
||||
writable: false,
|
||||
},
|
||||
uri: {
|
||||
value: uri,
|
||||
enumerable: true,
|
||||
writable: false,
|
||||
},
|
||||
parent: {
|
||||
enumerable: false,
|
||||
get: () => api.parent,
|
||||
},
|
||||
children: {
|
||||
value: new ReadonlyMapView(api.children),
|
||||
enumerable: true,
|
||||
writable: false,
|
||||
},
|
||||
range: testItemPropAccessor(api, 'range', undefined, rangeComparator),
|
||||
description: testItemPropAccessor(api, 'description', undefined, strictEqualComparator),
|
||||
runnable: testItemPropAccessor(api, 'runnable', true, strictEqualComparator),
|
||||
debuggable: testItemPropAccessor(api, 'debuggable', false, strictEqualComparator),
|
||||
status: testItemPropAccessor(api, 'status', TestItemStatus.Resolved, strictEqualComparator),
|
||||
error: testItemPropAccessor(api, 'error', undefined, strictEqualComparator),
|
||||
});
|
||||
}
|
||||
|
||||
public invalidate() {
|
||||
getPrivateApiFor(this).bus.fire([ExtHostTestItemEventType.Invalidated]);
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
const api = getPrivateApiFor(this);
|
||||
if (api.parent) {
|
||||
getPrivateApiFor(api.parent).children.delete(this.id);
|
||||
}
|
||||
|
||||
api.bus.fire([ExtHostTestItemEventType.Disposed]);
|
||||
}
|
||||
|
||||
public addChild(child: vscode.TestItem<unknown>) {
|
||||
if (!(child instanceof TestItemImpl)) {
|
||||
throw new Error('Test child must be created through vscode.test.createTestItem()');
|
||||
}
|
||||
|
||||
const api = getPrivateApiFor(this);
|
||||
if (api.children.has(child.id)) {
|
||||
throw new Error(`Attempted to insert a duplicate test item ID ${child.id}`);
|
||||
}
|
||||
|
||||
api.children.set(child.id, child);
|
||||
api.bus.fire([ExtHostTestItemEventType.NewChild, child]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@es5ClassCompat
|
||||
export class TestMessage implements vscode.TestMessage {
|
||||
public severity = TestMessageSeverity.Error;
|
||||
public expectedOutput?: string;
|
||||
public actualOutput?: string;
|
||||
|
||||
@@ -3417,6 +3330,94 @@ export class TestMessage implements vscode.TestMessage {
|
||||
constructor(public message: string | vscode.MarkdownString) { }
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class TestTag implements vscode.TestTag {
|
||||
constructor(
|
||||
public readonly id: string,
|
||||
public readonly label?: string,
|
||||
) {
|
||||
if (/\s/.test(id)) {
|
||||
throw new Error(`Test tag ID "${id}" may not include whitespace`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Test Coverage
|
||||
@es5ClassCompat
|
||||
export class CoveredCount implements vscode.CoveredCount {
|
||||
constructor(public covered: number, public total: number) { }
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class FileCoverage implements vscode.FileCoverage {
|
||||
public static fromDetails(uri: vscode.Uri, details: vscode.DetailedCoverage[]): vscode.FileCoverage {
|
||||
const statements = new CoveredCount(0, 0);
|
||||
const branches = new CoveredCount(0, 0);
|
||||
const fn = new CoveredCount(0, 0);
|
||||
|
||||
for (const detail of details) {
|
||||
if ('branches' in detail) {
|
||||
statements.total += 1;
|
||||
statements.covered += detail.executionCount > 0 ? 1 : 0;
|
||||
|
||||
for (const branch of detail.branches) {
|
||||
branches.total += 1;
|
||||
branches.covered += branch.executionCount > 0 ? 1 : 0;
|
||||
}
|
||||
} else {
|
||||
fn.total += 1;
|
||||
fn.covered += detail.executionCount > 0 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
const coverage = new FileCoverage(
|
||||
uri,
|
||||
statements,
|
||||
branches.total > 0 ? branches : undefined,
|
||||
fn.total > 0 ? fn : undefined,
|
||||
);
|
||||
|
||||
coverage.detailedCoverage = details;
|
||||
|
||||
return coverage;
|
||||
}
|
||||
|
||||
detailedCoverage?: vscode.DetailedCoverage[];
|
||||
|
||||
constructor(
|
||||
public readonly uri: vscode.Uri,
|
||||
public statementCoverage: vscode.CoveredCount,
|
||||
public branchCoverage?: vscode.CoveredCount,
|
||||
public functionCoverage?: vscode.CoveredCount,
|
||||
) { }
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class StatementCoverage implements vscode.StatementCoverage {
|
||||
constructor(
|
||||
public executionCount: number,
|
||||
public location: Position | Range,
|
||||
public branches: vscode.BranchCoverage[] = [],
|
||||
) { }
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class BranchCoverage implements vscode.BranchCoverage {
|
||||
constructor(
|
||||
public executionCount: number,
|
||||
public location: Position | Range,
|
||||
) { }
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class FunctionCoverage implements vscode.FunctionCoverage {
|
||||
constructor(
|
||||
public executionCount: number,
|
||||
public location: Position | Range,
|
||||
) { }
|
||||
}
|
||||
//#endregion
|
||||
|
||||
export enum ExternalUriOpenerPriority {
|
||||
@@ -3437,5 +3438,28 @@ export enum PortAutoForwardAction {
|
||||
OpenBrowser = 2,
|
||||
OpenPreview = 3,
|
||||
Silent = 4,
|
||||
Ignore = 5
|
||||
Ignore = 5,
|
||||
OpenBrowserOnce = 6
|
||||
}
|
||||
|
||||
export class TypeHierarchyItem {
|
||||
_sessionId?: string;
|
||||
_itemId?: string;
|
||||
|
||||
kind: SymbolKind;
|
||||
tags?: SymbolTag[];
|
||||
name: string;
|
||||
detail?: string;
|
||||
uri: URI;
|
||||
range: Range;
|
||||
selectionRange: Range;
|
||||
|
||||
constructor(kind: SymbolKind, name: string, detail: string, uri: URI, range: Range, selectionRange: Range) {
|
||||
this.kind = kind;
|
||||
this.name = name;
|
||||
this.detail = detail;
|
||||
this.uri = uri;
|
||||
this.range = range;
|
||||
this.selectionRange = selectionRange;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { serializeWebviewOptions, ExtHostWebview, ExtHostWebviews, toExtensionData, shouldSerializeBuffersForPostMessage } from 'vs/workbench/api/common/extHostWebview';
|
||||
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { EditorGroupColumn } from 'vs/workbench/common/editor';
|
||||
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import type * as vscode from 'vscode';
|
||||
import * as extHostProtocol from './extHost.protocol';
|
||||
import * as extHostTypes from './extHostTypes';
|
||||
|
||||
@@ -15,7 +15,7 @@ interface IJSONValidationExtensionPoint {
|
||||
|
||||
const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint<IJSONValidationExtensionPoint[]>({
|
||||
extensionPoint: 'jsonValidation',
|
||||
defaultExtensionKind: 'workspace',
|
||||
defaultExtensionKind: ['workspace', 'web'],
|
||||
jsonSchema: {
|
||||
description: nls.localize('contributes.jsonValidation', 'Contributes json schema configuration.'),
|
||||
type: 'array',
|
||||
|
||||
@@ -183,27 +183,40 @@ const apiMenus: IAPIMenu[] = [
|
||||
{
|
||||
key: 'notebook/toolbar',
|
||||
id: MenuId.NotebookToolbar,
|
||||
description: localize('notebook.toolbar', "The contributed notebook toolbar menu"),
|
||||
proposed: true
|
||||
description: localize('notebook.toolbar', "The contributed notebook toolbar menu")
|
||||
},
|
||||
*/
|
||||
{
|
||||
key: 'notebook/toolbar/right',
|
||||
id: MenuId.NotebookRightToolbar,
|
||||
description: localize('notebook.toolbar.right', "The contributed notebook right toolbar menu"),
|
||||
key: 'notebook/cell/title',
|
||||
id: MenuId.NotebookCellTitle,
|
||||
description: localize('notebook.cell.title', "The contributed notebook cell title menu")
|
||||
},
|
||||
{
|
||||
key: 'notebook/cell/execute',
|
||||
id: MenuId.NotebookCellExecute,
|
||||
description: localize('notebook.cell.execute', "The contributed notebook cell execution menu")
|
||||
},
|
||||
{
|
||||
key: 'interactive/toolbar',
|
||||
id: MenuId.InteractiveToolbar,
|
||||
description: localize('interactive.toolbar', "The contributed interactive toolbar menu"),
|
||||
proposed: true
|
||||
},
|
||||
{
|
||||
key: 'notebook/cell/title',
|
||||
id: MenuId.NotebookCellTitle,
|
||||
description: localize('notebook.cell.title', "The contributed notebook cell title menu"),
|
||||
key: 'interactive/cell/title',
|
||||
id: MenuId.InteractiveCellTitle,
|
||||
description: localize('interactive.cell.title', "The contributed interactive cell title menu"),
|
||||
proposed: true
|
||||
},
|
||||
{
|
||||
key: 'testing/item/context',
|
||||
id: MenuId.TestItem,
|
||||
description: localize('testing.item.title', "The contributed test item menu"),
|
||||
proposed: true
|
||||
description: localize('testing.item.context', "The contributed test item menu"),
|
||||
},
|
||||
{
|
||||
key: 'testing/item/gutter',
|
||||
id: MenuId.TestItemGutter,
|
||||
description: localize('testing.item.gutter.title', "The menu for a gutter decoration for a test item"),
|
||||
},
|
||||
{
|
||||
key: 'extension/context',
|
||||
@@ -282,6 +295,12 @@ const apiMenus: IAPIMenu[] = [
|
||||
description: locConstants.menusExtensionPointDataGridContext
|
||||
},
|
||||
// {{SQL CARBON EDIT}} end menu entries
|
||||
{
|
||||
key: 'file/newFile',
|
||||
id: MenuId.NewFile,
|
||||
description: localize('file.newFile', "The 'New File...' quick pick, shown on welcome page and File menu."),
|
||||
supportsSubmenus: false,
|
||||
},
|
||||
{
|
||||
key: 'editor/inlineCompletions/actions',
|
||||
id: MenuId.InlineCompletionsActions,
|
||||
@@ -575,11 +594,11 @@ namespace schema {
|
||||
type: 'string'
|
||||
},
|
||||
shortTitle: {
|
||||
description: localize('vscode.extension.contributes.commandType.shortTitle', 'Short title by which the command is represented in the UI'),
|
||||
markdownDescription: localize('vscode.extension.contributes.commandType.shortTitle', '(Optional) Short title by which the command is represented in the UI. Menus pick either `title` or `shortTitle` depending on the context in which they show commands.'),
|
||||
type: 'string'
|
||||
},
|
||||
category: {
|
||||
description: localize('vscode.extension.contributes.commandType.category', '(Optional) Category string by the command is grouped in the UI'),
|
||||
description: localize('vscode.extension.contributes.commandType.category', '(Optional) Category string by which the command is grouped in the UI'),
|
||||
type: 'string'
|
||||
},
|
||||
enablement: {
|
||||
@@ -656,7 +675,9 @@ commandsExtensionPoint.setHandler(extensions => {
|
||||
bucket.push({
|
||||
id: command,
|
||||
title,
|
||||
source: extension.description.displayName ?? extension.description.name,
|
||||
shortTitle: extension.description.enableProposedApi ? shortTitle : undefined,
|
||||
tooltip: extension.description.enableProposedApi ? title : undefined,
|
||||
category,
|
||||
precondition: ContextKeyExpr.deserialize(enablement),
|
||||
icon: absoluteIcon
|
||||
|
||||
@@ -82,6 +82,11 @@ export interface TaskHandleDTO {
|
||||
workspaceFolder: UriComponents | string;
|
||||
}
|
||||
|
||||
export interface TaskGroupDTO {
|
||||
isDefault?: boolean;
|
||||
_id: string;
|
||||
}
|
||||
|
||||
export interface TaskDTO {
|
||||
_id: string;
|
||||
name?: string;
|
||||
@@ -89,7 +94,7 @@ export interface TaskDTO {
|
||||
definition: TaskDefinitionDTO;
|
||||
isBackground?: boolean;
|
||||
source: TaskSourceDTO;
|
||||
group?: string;
|
||||
group?: TaskGroupDTO;
|
||||
detail?: string;
|
||||
presentationOptions?: TaskPresentationOptionsDTO;
|
||||
problemMatchers: string[];
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import type * as vscode from 'vscode';
|
||||
@@ -57,9 +58,27 @@ export function asWebviewUri(
|
||||
|
||||
return URI.from({
|
||||
scheme: Schemas.https,
|
||||
authority: `${resource.scheme}+${resource.authority}.${webviewRootResourceAuthority}`,
|
||||
authority: `${resource.scheme}+${encodeAuthority(resource.authority)}.${webviewRootResourceAuthority}`,
|
||||
path: resource.path,
|
||||
fragment: resource.fragment,
|
||||
query: resource.query,
|
||||
});
|
||||
}
|
||||
|
||||
function encodeAuthority(authority: string): string {
|
||||
return authority.replace(/./g, char => {
|
||||
const code = char.charCodeAt(0);
|
||||
if (
|
||||
(code >= CharCode.a && code <= CharCode.z)
|
||||
|| (code >= CharCode.A && code <= CharCode.Z)
|
||||
|| (code >= CharCode.Digit0 && code <= CharCode.Digit9)
|
||||
) {
|
||||
return char;
|
||||
}
|
||||
return '-' + code.toString(16).padStart(4, '0');
|
||||
});
|
||||
}
|
||||
|
||||
export function decodeAuthority(authority: string) {
|
||||
return authority.replace(/-([0-9a-f]{4})/g, (_, code) => String.fromCharCode(parseInt(code, 16)));
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import { IExtHostTask } from 'vs/workbench/api/common/extHostTask';
|
||||
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { ExtensionStoragePaths } from 'vs/workbench/api/node/extHostStoragePaths';
|
||||
|
||||
// #########################################################################
|
||||
// ### ###
|
||||
@@ -29,6 +31,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
registerSingleton(IExtHostExtensionService, ExtHostExtensionService);
|
||||
registerSingleton(ILogService, ExtHostLogService);
|
||||
registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths);
|
||||
|
||||
// registerSingleton(IExtHostDebugService, ExtHostDebugService); {{SQL CARBON EDIT}}
|
||||
registerSingleton(IExtHostOutputService, ExtHostOutputService2);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import type * as vscode from 'vscode';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { DebugAdapterExecutable } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { DebugAdapterExecutable, ThemeIcon } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ExecutableDebugAdapter, SocketDebugAdapter, NamedPipeDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter';
|
||||
import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter';
|
||||
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
@@ -98,6 +98,7 @@ export class ExtHostDebugService extends ExtHostDebugServiceBase {
|
||||
shellArgs: shellArgs,
|
||||
cwd: args.cwd,
|
||||
name: terminalName,
|
||||
iconPath: new ThemeIcon('debug'),
|
||||
};
|
||||
giveShellTimeToInitialize = true;
|
||||
terminal = this._terminalService.createTerminalFromOptions(options, {
|
||||
|
||||
@@ -17,6 +17,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { createRotatingLogger } from 'vs/platform/log/node/spdlogLog';
|
||||
import { Logger } from 'spdlog';
|
||||
import { ByteSize } from 'vs/platform/files/common/files';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
class OutputAppender {
|
||||
|
||||
@@ -43,8 +44,8 @@ class ExtHostOutputChannelBackedByFile extends AbstractExtHostOutputChannel {
|
||||
|
||||
private _appender: OutputAppender;
|
||||
|
||||
constructor(name: string, appender: OutputAppender, proxy: MainThreadOutputServiceShape) {
|
||||
super(name, false, URI.file(appender.file), proxy);
|
||||
constructor(name: string, appender: OutputAppender, extensionId: string, proxy: MainThreadOutputServiceShape) {
|
||||
super(name, false, URI.file(appender.file), extensionId, proxy);
|
||||
this._appender = appender;
|
||||
}
|
||||
|
||||
@@ -95,17 +96,17 @@ export class ExtHostOutputService2 extends ExtHostOutputService {
|
||||
}
|
||||
}
|
||||
|
||||
override createOutputChannel(name: string): vscode.OutputChannel {
|
||||
override createOutputChannel(name: string, extension: IExtensionDescription): vscode.OutputChannel {
|
||||
name = name.trim();
|
||||
if (!name) {
|
||||
throw new Error('illegal argument `name`. must not be falsy');
|
||||
}
|
||||
const extHostOutputChannel = this._doCreateOutChannel(name);
|
||||
const extHostOutputChannel = this._doCreateOutChannel(name, extension);
|
||||
extHostOutputChannel.then(channel => channel._id.then(id => this._channels.set(id, channel)));
|
||||
return new LazyOutputChannel(name, extHostOutputChannel);
|
||||
}
|
||||
|
||||
private async _doCreateOutChannel(name: string): Promise<AbstractExtHostOutputChannel> {
|
||||
private async _doCreateOutChannel(name: string, extension: IExtensionDescription): Promise<AbstractExtHostOutputChannel> {
|
||||
try {
|
||||
const outputDirPath = join(this._logsLocation.fsPath, `output_logging_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`);
|
||||
const exists = await SymlinkSupport.existsDirectory(outputDirPath);
|
||||
@@ -115,11 +116,11 @@ export class ExtHostOutputService2 extends ExtHostOutputService {
|
||||
const fileName = `${this._namePool++}-${name.replace(/[\\/:\*\?"<>\|]/g, '')}`;
|
||||
const file = URI.file(join(outputDirPath, `${fileName}.log`));
|
||||
const appender = await OutputAppender.create(fileName, file.fsPath);
|
||||
return new ExtHostOutputChannelBackedByFile(name, appender, this._proxy);
|
||||
return new ExtHostOutputChannelBackedByFile(name, appender, extension.identifier.value, this._proxy);
|
||||
} catch (error) {
|
||||
// Do not crash if logger cannot be created
|
||||
this.logService.error(error);
|
||||
return new ExtHostPushOutputChannel(name, this._proxy);
|
||||
return new ExtHostPushOutputChannel(name, extension.identifier.value, this._proxy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,21 +4,21 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IFileQuery, IRawFileQuery, ISearchCompleteStats, isSerializedFileMatch, ISerializedSearchProgressItem, ITextQuery } from 'vs/workbench/services/search/common/search';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { ExtHostSearch, reviveQuery } from 'vs/workbench/api/common/extHostSearch';
|
||||
import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
|
||||
import { IFileQuery, IRawFileQuery, ISearchCompleteStats, ISerializedSearchProgressItem, isSerializedFileMatch, ITextQuery } from 'vs/workbench/services/search/common/search';
|
||||
import { TextSearchManager } from 'vs/workbench/services/search/common/textSearchManager';
|
||||
import { SearchService } from 'vs/workbench/services/search/node/rawSearchService';
|
||||
import { RipgrepSearchProvider } from 'vs/workbench/services/search/node/ripgrepSearchProvider';
|
||||
import { OutputChannel } from 'vs/workbench/services/search/node/ripgrepSearchUtils';
|
||||
import type * as vscode from 'vscode';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { ExtHostSearch, reviveQuery } from 'vs/workbench/api/common/extHostSearch';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { NativeTextSearchManager } from 'vs/workbench/services/search/node/textSearchManager';
|
||||
import { TextSearchManager } from 'vs/workbench/services/search/common/textSearchManager';
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
export class NativeExtHostSearch extends ExtHostSearch {
|
||||
|
||||
@@ -42,10 +42,14 @@ export class NativeExtHostSearch extends ExtHostSearch {
|
||||
}
|
||||
}
|
||||
|
||||
override $enableExtensionHostSearch(): void {
|
||||
this._registerEHSearchProviders();
|
||||
}
|
||||
|
||||
private _registerEHSearchProviders(): void {
|
||||
const outputChannel = new OutputChannel('RipgrepSearchEH', this._logService);
|
||||
this.registerTextSearchProvider(Schemas.file, new RipgrepSearchProvider(outputChannel));
|
||||
this.registerInternalFileSearchProvider(Schemas.file, new SearchService());
|
||||
this.registerInternalFileSearchProvider(Schemas.file, new SearchService('fileSearchProvider'));
|
||||
}
|
||||
|
||||
private registerInternalFileSearchProvider(scheme: string, provider: SearchService): IDisposable {
|
||||
@@ -100,6 +104,6 @@ export class NativeExtHostSearch extends ExtHostSearch {
|
||||
}
|
||||
|
||||
protected override createTextSearchManager(query: ITextQuery, provider: vscode.TextSearchProvider): TextSearchManager {
|
||||
return new NativeTextSearchManager(query, provider);
|
||||
return new NativeTextSearchManager(query, provider, undefined, 'textSearchProvider');
|
||||
}
|
||||
}
|
||||
|
||||
289
src/vs/workbench/api/node/extHostStoragePaths.ts
Normal file
289
src/vs/workbench/api/node/extHostStoragePaths.ts
Normal file
@@ -0,0 +1,289 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtensionStoragePaths as CommonExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IntervalTimer, timeout } from 'vs/base/common/async';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class ExtensionStoragePaths extends CommonExtensionStoragePaths {
|
||||
|
||||
private _workspaceStorageLock: Lock | null = null;
|
||||
|
||||
protected override async _getWorkspaceStorageURI(storageName: string): Promise<URI> {
|
||||
const workspaceStorageURI = await super._getWorkspaceStorageURI(storageName);
|
||||
if (workspaceStorageURI.scheme !== Schemas.file) {
|
||||
return workspaceStorageURI;
|
||||
}
|
||||
|
||||
if (this._environment.skipWorkspaceStorageLock) {
|
||||
this._logService.info(`Skipping acquiring lock for ${workspaceStorageURI.fsPath}.`);
|
||||
return workspaceStorageURI;
|
||||
}
|
||||
|
||||
const workspaceStorageBase = workspaceStorageURI.fsPath;
|
||||
let attempt = 0;
|
||||
do {
|
||||
let workspaceStoragePath: string;
|
||||
if (attempt === 0) {
|
||||
workspaceStoragePath = workspaceStorageBase;
|
||||
} else {
|
||||
workspaceStoragePath = (
|
||||
/[/\\]$/.test(workspaceStorageBase)
|
||||
? `${workspaceStorageBase.substr(0, workspaceStorageBase.length - 1)}-${attempt}`
|
||||
: `${workspaceStorageBase}-${attempt}`
|
||||
);
|
||||
}
|
||||
|
||||
await mkdir(workspaceStoragePath);
|
||||
|
||||
const lockfile = path.join(workspaceStoragePath, 'vscode.lock');
|
||||
const lock = await tryAcquireLock(this._logService, lockfile, false);
|
||||
if (lock) {
|
||||
this._workspaceStorageLock = lock;
|
||||
process.on('exit', () => {
|
||||
lock.dispose();
|
||||
});
|
||||
return URI.file(workspaceStoragePath);
|
||||
}
|
||||
|
||||
attempt++;
|
||||
} while (attempt < 10);
|
||||
|
||||
// just give up
|
||||
return workspaceStorageURI;
|
||||
}
|
||||
|
||||
override onWillDeactivateAll(): void {
|
||||
// the lock will be released soon
|
||||
if (this._workspaceStorageLock) {
|
||||
this._workspaceStorageLock.setWillRelease(6000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function mkdir(dir: string): Promise<void> {
|
||||
try {
|
||||
await fs.promises.stat(dir);
|
||||
return;
|
||||
} catch {
|
||||
// doesn't exist, that's OK
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.mkdir(dir, { recursive: true });
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
|
||||
const MTIME_UPDATE_TIME = 1000; // 1s
|
||||
const STALE_LOCK_TIME = 10 * 60 * 1000; // 10 minutes
|
||||
|
||||
class Lock extends Disposable {
|
||||
|
||||
private readonly _timer: IntervalTimer;
|
||||
|
||||
constructor(
|
||||
private readonly logService: ILogService,
|
||||
private readonly filename: string
|
||||
) {
|
||||
super();
|
||||
|
||||
this._timer = this._register(new IntervalTimer());
|
||||
this._timer.cancelAndSet(async () => {
|
||||
const contents = await readLockfileContents(logService, filename);
|
||||
if (!contents || contents.pid !== process.pid) {
|
||||
// we don't hold the lock anymore ...
|
||||
logService.info(`Lock '${filename}': The lock was lost unexpectedly.`);
|
||||
this._timer.cancel();
|
||||
}
|
||||
try {
|
||||
await fs.promises.utimes(filename, new Date(), new Date());
|
||||
} catch (err) {
|
||||
logService.error(err);
|
||||
logService.info(`Lock '${filename}': Could not update mtime.`);
|
||||
}
|
||||
}, MTIME_UPDATE_TIME);
|
||||
}
|
||||
|
||||
public override dispose(): void {
|
||||
super.dispose();
|
||||
try { fs.unlinkSync(this.filename); } catch (err) { }
|
||||
}
|
||||
|
||||
public async setWillRelease(timeUntilReleaseMs: number): Promise<void> {
|
||||
this.logService.info(`Lock '${this.filename}': Marking the lockfile as scheduled to be released in ${timeUntilReleaseMs} ms.`);
|
||||
try {
|
||||
const contents: ILockfileContents = {
|
||||
pid: process.pid,
|
||||
willReleaseAt: Date.now() + timeUntilReleaseMs
|
||||
};
|
||||
await fs.promises.writeFile(this.filename, JSON.stringify(contents), { flag: 'w' });
|
||||
} catch (err) {
|
||||
this.logService.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to acquire a lock on a directory.
|
||||
* This does not use the real `flock`, but uses a file.
|
||||
* @returns a disposable if the lock could be acquired or null if it could not.
|
||||
*/
|
||||
async function tryAcquireLock(logService: ILogService, filename: string, isSecondAttempt: boolean): Promise<Lock | null> {
|
||||
try {
|
||||
const contents: ILockfileContents = {
|
||||
pid: process.pid,
|
||||
willReleaseAt: 0
|
||||
};
|
||||
await fs.promises.writeFile(filename, JSON.stringify(contents), { flag: 'wx' });
|
||||
} catch (err) {
|
||||
logService.error(err);
|
||||
}
|
||||
|
||||
// let's see if we got the lock
|
||||
const contents = await readLockfileContents(logService, filename);
|
||||
if (!contents || contents.pid !== process.pid) {
|
||||
// we didn't get the lock
|
||||
if (isSecondAttempt) {
|
||||
logService.info(`Lock '${filename}': Could not acquire lock, giving up.`);
|
||||
return null;
|
||||
}
|
||||
logService.info(`Lock '${filename}': Could not acquire lock, checking if the file is stale.`);
|
||||
return checkStaleAndTryAcquireLock(logService, filename);
|
||||
}
|
||||
|
||||
// we got the lock
|
||||
logService.info(`Lock '${filename}': Lock acquired.`);
|
||||
return new Lock(logService, filename);
|
||||
}
|
||||
|
||||
interface ILockfileContents {
|
||||
pid: number;
|
||||
willReleaseAt: number | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns 0 if the pid cannot be read
|
||||
*/
|
||||
async function readLockfileContents(logService: ILogService, filename: string): Promise<ILockfileContents | null> {
|
||||
let contents: Buffer;
|
||||
try {
|
||||
contents = await fs.promises.readFile(filename);
|
||||
} catch (err) {
|
||||
// cannot read the file
|
||||
logService.error(err);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(String(contents));
|
||||
} catch (err) {
|
||||
// cannot parse the file
|
||||
logService.error(err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns 0 if the mtime cannot be read
|
||||
*/
|
||||
async function readmtime(logService: ILogService, filename: string): Promise<number> {
|
||||
let stats: fs.Stats;
|
||||
try {
|
||||
stats = await fs.promises.stat(filename);
|
||||
} catch (err) {
|
||||
// cannot read the file stats to check if it is stale or not
|
||||
logService.error(err);
|
||||
return 0;
|
||||
}
|
||||
return stats.mtime.getTime();
|
||||
}
|
||||
|
||||
function processExists(pid: number): boolean {
|
||||
try {
|
||||
process.kill(pid, 0); // throws an exception if the process doesn't exist anymore.
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function checkStaleAndTryAcquireLock(logService: ILogService, filename: string): Promise<Lock | null> {
|
||||
const contents = await readLockfileContents(logService, filename);
|
||||
if (!contents) {
|
||||
logService.info(`Lock '${filename}': Could not read pid of lock holder.`);
|
||||
return tryDeleteAndAcquireLock(logService, filename);
|
||||
}
|
||||
|
||||
if (contents.willReleaseAt) {
|
||||
let timeUntilRelease = contents.willReleaseAt - Date.now();
|
||||
if (timeUntilRelease < 5000) {
|
||||
if (timeUntilRelease > 0) {
|
||||
logService.info(`Lock '${filename}': The lockfile is scheduled to be released in ${timeUntilRelease} ms.`);
|
||||
} else {
|
||||
logService.info(`Lock '${filename}': The lockfile is scheduled to have been released.`);
|
||||
}
|
||||
|
||||
while (timeUntilRelease > 0) {
|
||||
await timeout(Math.min(100, timeUntilRelease));
|
||||
const mtime = await readmtime(logService, filename);
|
||||
if (mtime === 0) {
|
||||
// looks like the lock was released
|
||||
return tryDeleteAndAcquireLock(logService, filename);
|
||||
}
|
||||
timeUntilRelease = contents.willReleaseAt - Date.now();
|
||||
}
|
||||
|
||||
return tryDeleteAndAcquireLock(logService, filename);
|
||||
}
|
||||
}
|
||||
|
||||
if (!processExists(contents.pid)) {
|
||||
logService.info(`Lock '${filename}': The pid ${contents.pid} appears to be gone.`);
|
||||
return tryDeleteAndAcquireLock(logService, filename);
|
||||
}
|
||||
|
||||
const mtime1 = await readmtime(logService, filename);
|
||||
const elapsed1 = Date.now() - mtime1;
|
||||
if (elapsed1 <= STALE_LOCK_TIME) {
|
||||
// the lock does not look stale
|
||||
logService.info(`Lock '${filename}': The lock does not look stale, elapsed: ${elapsed1} ms, giving up.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// the lock holder updates the mtime every 1s.
|
||||
// let's give it a chance to update the mtime
|
||||
// in case of a wake from sleep or something similar
|
||||
logService.info(`Lock '${filename}': The lock looks stale, waiting for 2s.`);
|
||||
await timeout(2000);
|
||||
|
||||
const mtime2 = await readmtime(logService, filename);
|
||||
const elapsed2 = Date.now() - mtime2;
|
||||
if (elapsed2 <= STALE_LOCK_TIME) {
|
||||
// the lock does not look stale
|
||||
logService.info(`Lock '${filename}': The lock does not look stale, elapsed: ${elapsed2} ms, giving up.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// the lock looks stale
|
||||
logService.info(`Lock '${filename}': The lock looks stale even after waiting for 2s.`);
|
||||
return tryDeleteAndAcquireLock(logService, filename);
|
||||
}
|
||||
|
||||
async function tryDeleteAndAcquireLock(logService: ILogService, filename: string): Promise<Lock | null> {
|
||||
logService.info(`Lock '${filename}': Deleting a stale lock.`);
|
||||
try {
|
||||
await fs.promises.unlink(filename);
|
||||
} catch (err) {
|
||||
// cannot delete the file
|
||||
// maybe the file is already deleted
|
||||
}
|
||||
return tryAcquireLock(logService, filename, true);
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import * as tasks from '../common/shared/tasks';
|
||||
import { ExtHostVariableResolverService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceFolder, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
@@ -24,6 +24,8 @@ import { Schemas } from 'vs/base/common/network';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
||||
import { IExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import { homedir } from 'os';
|
||||
|
||||
export class ExtHostTask extends ExtHostTaskBase {
|
||||
private _variableResolver: ExtHostVariableResolverService | undefined;
|
||||
@@ -37,7 +39,7 @@ export class ExtHostTask extends ExtHostTaskBase {
|
||||
@IExtHostTerminalService extHostTerminalService: IExtHostTerminalService,
|
||||
@ILogService logService: ILogService,
|
||||
@IExtHostApiDeprecationService deprecationService: IExtHostApiDeprecationService,
|
||||
@IExtHostEditorTabs private readonly editorTabs: IExtHostEditorTabs
|
||||
@IExtHostEditorTabs private readonly editorTabs: IExtHostEditorTabs,
|
||||
) {
|
||||
super(extHostRpc, initData, workspaceService, editorService, configurationService, extHostTerminalService, logService, deprecationService);
|
||||
if (initData.remote.isRemote && initData.remote.authority) {
|
||||
@@ -134,6 +136,22 @@ export class ExtHostTask extends ExtHostTaskBase {
|
||||
return this._variableResolver;
|
||||
}
|
||||
|
||||
private async getAFolder(workspaceFolders: vscode.WorkspaceFolder[] | undefined): Promise<IWorkspaceFolder> {
|
||||
let folder = (workspaceFolders && workspaceFolders.length > 0) ? workspaceFolders[0] : undefined;
|
||||
if (!folder) {
|
||||
const userhome = URI.file(homedir());
|
||||
folder = new WorkspaceFolder({ uri: userhome, name: resources.basename(userhome), index: 0 });
|
||||
}
|
||||
return {
|
||||
uri: folder.uri,
|
||||
name: folder.name,
|
||||
index: folder.index,
|
||||
toResource: () => {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public async $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Promise<{ process?: string, variables: { [key: string]: string; } }> {
|
||||
const uri: URI = URI.revive(uriComponents);
|
||||
const result = {
|
||||
@@ -141,19 +159,18 @@ export class ExtHostTask extends ExtHostTaskBase {
|
||||
variables: Object.create(null)
|
||||
};
|
||||
const workspaceFolder = await this._workspaceProvider.resolveWorkspaceFolder(uri);
|
||||
const workspaceFolders = await this._workspaceProvider.getWorkspaceFolders2();
|
||||
if (!workspaceFolders || !workspaceFolder) {
|
||||
throw new Error('Unexpected: Tasks can only be run in a workspace folder');
|
||||
}
|
||||
const workspaceFolders = (await this._workspaceProvider.getWorkspaceFolders2()) ?? [];
|
||||
|
||||
const resolver = await this.getVariableResolver(workspaceFolders);
|
||||
const ws: IWorkspaceFolder = {
|
||||
const ws: IWorkspaceFolder = workspaceFolder ? {
|
||||
uri: workspaceFolder.uri,
|
||||
name: workspaceFolder.name,
|
||||
index: workspaceFolder.index,
|
||||
toResource: () => {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
};
|
||||
} : await this.getAFolder(workspaceFolders);
|
||||
|
||||
for (let variable of toResolve.variables) {
|
||||
result.variables[variable] = await resolver.resolveAsync(ws, variable);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,21 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
|
||||
public createTerminalFromOptions(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal {
|
||||
const terminal = new ExtHostTerminal(this._proxy, generateUuid(), options, options.name);
|
||||
this._terminals.push(terminal);
|
||||
terminal.create(options, internalOptions);
|
||||
terminal.create(options, this._serializeParentTerminal(options, internalOptions));
|
||||
return terminal.value;
|
||||
}
|
||||
|
||||
private _serializeParentTerminal(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): ITerminalInternalOptions {
|
||||
internalOptions = internalOptions ? internalOptions : {};
|
||||
if (options.location && typeof options.location === 'object' && 'parentTerminal' in options.location) {
|
||||
const parentTerminal = options.location.parentTerminal;
|
||||
if (parentTerminal) {
|
||||
const parentExtHostTerminal = this._terminals.find(t => t.value === parentTerminal);
|
||||
if (parentExtHostTerminal) {
|
||||
internalOptions.resolvedExtHostIdentifier = parentExtHostTerminal._id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return internalOptions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { IExtHostTunnelService, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { TunnelOptions, TunnelCreationOptions, ProvidedPortAttributes, ProvidedOnAutoForward } from 'vs/platform/remote/common/tunnel';
|
||||
import { TunnelOptions, TunnelCreationOptions, ProvidedPortAttributes, ProvidedOnAutoForward, isLocalhost, isAllInterfaces } from 'vs/platform/remote/common/tunnel';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { MovingAverage } from 'vs/base/common/numbers';
|
||||
import { CandidatePort } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
@@ -270,7 +270,7 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
|
||||
let oldPorts: { host: string, port: number, detail?: string }[] | undefined = undefined;
|
||||
while (this._candidateFindingEnabled) {
|
||||
const startTime = new Date().getTime();
|
||||
const newPorts = await this.findCandidatePorts();
|
||||
const newPorts = (await this.findCandidatePorts()).filter(candidate => (isLocalhost(candidate.host) || isAllInterfaces(candidate.host)));
|
||||
this.logService.trace(`ForwardedPorts: (ExtHostTunnelService) found candidate ports ${newPorts.map(port => port.port).join(', ')}`);
|
||||
const timeTaken = new Date().getTime() - startTime;
|
||||
movingAverage.update(timeTaken);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
|
||||
import { ExtensionStoragePaths, IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { ExtHostExtensionService } from 'vs/workbench/api/worker/extHostExtensionService';
|
||||
import { ExtHostLogService } from 'vs/workbench/api/worker/extHostLogService';
|
||||
|
||||
@@ -17,3 +18,4 @@ import { ExtHostLogService } from 'vs/workbench/api/worker/extHostLogService';
|
||||
|
||||
registerSingleton(IExtHostExtensionService, ExtHostExtensionService);
|
||||
registerSingleton(ILogService, ExtHostLogService);
|
||||
registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths);
|
||||
|
||||
@@ -12,6 +12,7 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio
|
||||
import { ExtensionRuntime } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { MainContext, MainThreadConsoleShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { FileAccess } from 'vs/base/common/network';
|
||||
|
||||
namespace TrustedFunction {
|
||||
|
||||
@@ -91,7 +92,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
|
||||
if (extensionId) {
|
||||
performance.mark(`code/extHost/willFetchExtensionCode/${extensionId.value}`);
|
||||
}
|
||||
const response = await fetch(module.toString(true));
|
||||
const response = await fetch(FileAccess.asBrowserUri(module).toString(true));
|
||||
if (extensionId) {
|
||||
performance.mark(`code/extHost/didFetchExtensionCode/${extensionId.value}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user