Merge branch 'main' into joh/shortcut_fs

This commit is contained in:
Johannes Rieken
2021-11-16 10:20:45 +01:00
639 changed files with 13615 additions and 9181 deletions

View File

@@ -10,7 +10,7 @@ import { IActiveCodeEditor, IViewZone } from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { reviveWebviewContentOptions } from 'vs/workbench/api/browser/mainThreadWebviews';
import { ExtHostContext, ExtHostEditorInsetsShape, IExtHostContext, IWebviewOptions, MainContext, MainThreadEditorInsetsShape } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostContext, ExtHostEditorInsetsShape, IExtHostContext, IWebviewContentOptions, MainContext, MainThreadEditorInsetsShape } from 'vs/workbench/api/common/extHost.protocol';
import { IWebviewService, IWebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
import { extHostNamedCustomer } from '../common/extHostCustomers';
@@ -70,7 +70,7 @@ export class MainThreadEditorInsets implements MainThreadEditorInsetsShape {
this._disposables.dispose();
}
async $createEditorInset(handle: number, id: string, uri: UriComponents, line: number, height: number, options: IWebviewOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): Promise<void> {
async $createEditorInset(handle: number, id: string, uri: UriComponents, line: number, height: number, options: IWebviewContentOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): Promise<void> {
let editor: IActiveCodeEditor | undefined;
id = id.substr(0, id.indexOf(',')); //todo@jrieken HACK
@@ -121,7 +121,7 @@ export class MainThreadEditorInsets implements MainThreadEditorInsetsShape {
inset.webview.html = value;
}
$setOptions(handle: number, options: IWebviewOptions): void {
$setOptions(handle: number, options: IWebviewContentOptions): void {
const inset = this.getInset(handle);
inset.webview.contentOptions = reviveWebviewContentOptions(options);
}

View File

@@ -37,9 +37,14 @@ export class MainThreadDiagnostics implements MainThreadDiagnosticsShape {
private _forwardMarkers(resources: readonly URI[]): void {
const data: [UriComponents, IMarkerData[]][] = [];
for (const resource of resources) {
const markerData = this._markerService.read({ resource }).filter(marker => !this._activeOwners.has(marker.owner));
if (markerData.length > 0) {
data.push([resource, markerData]);
const allMarkerData = this._markerService.read({ resource });
if (allMarkerData.length === 0) {
data.push([resource, []]);
} else {
const forgeinMarkerData = allMarkerData.filter(marker => !this._activeOwners.has(marker.owner));
if (forgeinMarkerData.length > 0) {
data.push([resource, forgeinMarkerData]);
}
}
}
if (data.length > 0) {

View File

@@ -280,7 +280,7 @@ export class MainThreadEditorTabs {
if (!editor) {
return;
}
return group.closeEditor(editor);
await group.closeEditor(editor);
}
//#endregion
}

View File

@@ -177,7 +177,8 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
const editorPanes = this._editorService.visibleEditorPanes;
for (let editorPane of editorPanes) {
if (mainThreadEditor.matches(editorPane)) {
return editorPane.group.closeEditor(editorPane.input);
await editorPane.group.closeEditor(editorPane.input);
return;
}
}
}

View File

@@ -4,48 +4,44 @@
*--------------------------------------------------------------------------------------------*/
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
import { ILoggerOptions, ILoggerService, ILogService, log, LogLevel } from 'vs/platform/log/common/log';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IExtHostContext, ExtHostContext, MainThreadLogShape, MainContext } from 'vs/workbench/api/common/extHost.protocol';
import { IExtHostContext, ExtHostContext, MainThreadLoggerShape, 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, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { basename } from 'vs/base/common/path';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@extHostNamedCustomer(MainContext.MainThreadLog)
export class MainThreadLogService implements MainThreadLogShape {
@extHostNamedCustomer(MainContext.MainThreadLogger)
export class MainThreadLoggerService implements MainThreadLoggerShape {
private readonly _loggers = new Map<string, FileLogger>();
private readonly _logListener: IDisposable;
constructor(
extHostContext: IExtHostContext,
@ILogService private readonly _logService: ILogService,
@IInstantiationService private readonly _instaService: IInstantiationService,
@ILogService logService: ILogService,
@ILoggerService private readonly _loggerService: ILoggerService,
) {
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostLogService);
this._logListener = _logService.onDidChangeLogLevel(level => {
proxy.$setLevel(level);
this._loggers.forEach(value => value.setLevel(level));
});
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostLogLevelServiceShape);
this._logListener = logService.onDidChangeLogLevel(level => proxy.$setLevel(level));
}
$log(file: UriComponents, messages: [LogLevel, string][]): void {
const logger = this._loggerService.getLogger(URI.revive(file));
if (!logger) {
throw new Error('Create the logger before logging');
}
for (const [level, message] of messages) {
log(logger, level, message);
}
}
async $createLogger(file: UriComponents, options?: ILoggerOptions): Promise<void> {
this._loggerService.createLogger(URI.revive(file), options);
}
dispose(): void {
this._logListener.dispose();
this._loggers.forEach(value => value.dispose());
this._loggers.clear();
}
$log(file: UriComponents, level: LogLevel, message: any[]): void {
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(), false);
this._loggers.set(uri.toString(), logger);
}
logger.log(level, message);
}
}

View File

@@ -131,7 +131,7 @@ export class MainThreadNotebooksAndEditors {
private _handleEditorAdd(editor: INotebookEditor): void {
this._editorListeners.set(editor.getId(), combinedDisposable(
editor.onDidChangeModel(() => this._updateState()),
editor.onDidFocusEditorWidget(() => this._updateState(editor)),
editor.onDidFocusWidget(() => this._updateState(editor)),
));
this._updateState();
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Registry } from 'vs/platform/registry/common/platform';
import { IOutputService, IOutputChannel, OUTPUT_VIEW_ID } from 'vs/workbench/contrib/output/common/output';
import { IOutputService, IOutputChannel, OUTPUT_VIEW_ID, OutputChannelUpdateMode } from 'vs/workbench/contrib/output/common/output';
import { Extensions, IOutputChannelRegistry } from 'vs/workbench/services/output/common/output';
import { MainThreadOutputServiceShape, MainContext, IExtHostContext, ExtHostOutputServiceShape, ExtHostContext } from '../common/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
@@ -12,11 +12,11 @@ import { UriComponents, URI } from 'vs/base/common/uri';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { Event } from 'vs/base/common/event';
import { IViewsService } from 'vs/workbench/common/views';
import { isNumber } from 'vs/base/common/types';
@extHostNamedCustomer(MainContext.MainThreadOutputService)
export class MainThreadOutputService extends Disposable implements MainThreadOutputServiceShape {
private static _idPool = 1;
private static _extensionIdPool = new Map<string, number>();
private readonly _proxy: ExtHostOutputServiceShape;
@@ -42,78 +42,48 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
setVisibleChannel();
}
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++)}`;
}
public async $register(label: string, log: boolean, file: UriComponents, extensionId: string): Promise<string> {
const idCounter = (MainThreadOutputService._extensionIdPool.get(extensionId) || 0) + 1;
MainThreadOutputService._extensionIdPool.set(extensionId, idCounter);
const id = `extension-output-${extensionId}-#${idCounter}`;
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id, label, file: file ? URI.revive(file) : undefined, log });
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id, label, file: URI.revive(file), log });
this._register(toDisposable(() => this.$dispose(id)));
return Promise.resolve(id);
return id;
}
public $append(channelId: string, value: string): Promise<void> | undefined {
public async $update(channelId: string, mode: OutputChannelUpdateMode, till?: number): Promise<void> {
const channel = this._getChannel(channelId);
if (channel) {
channel.append(value);
if (mode === OutputChannelUpdateMode.Append) {
channel.update(mode);
} else if (isNumber(till)) {
channel.update(mode, till);
}
}
return undefined;
}
public $update(channelId: string): Promise<void> | undefined {
const channel = this._getChannel(channelId);
if (channel) {
channel.update();
}
return undefined;
}
public $clear(channelId: string, till: number): Promise<void> | undefined {
const channel = this._getChannel(channelId);
if (channel) {
channel.clear(till);
}
return undefined;
}
public $replaceAll(channelId: string, till: number, value: string): Promise<void> | undefined {
const channel = this._getChannel(channelId);
if (channel) {
channel.replaceAll(till, value);
}
return undefined;
}
public $reveal(channelId: string, preserveFocus: boolean): Promise<void> | undefined {
public async $reveal(channelId: string, preserveFocus: boolean): Promise<void> {
const channel = this._getChannel(channelId);
if (channel) {
this._outputService.showChannel(channel.id, preserveFocus);
}
return undefined;
}
public $close(channelId: string): Promise<void> | undefined {
public async $close(channelId: string): Promise<void> {
if (this._viewsService.isViewVisible(OUTPUT_VIEW_ID)) {
const activeChannel = this._outputService.getActiveChannel();
if (activeChannel && channelId === activeChannel.id) {
this._viewsService.closeView(OUTPUT_VIEW_ID);
}
}
return undefined;
}
public $dispose(channelId: string): Promise<void> | undefined {
public async $dispose(channelId: string): Promise<void> {
const channel = this._getChannel(channelId);
if (channel) {
channel.dispose();
}
return undefined;
}
private _getChannel(channelId: string): IOutputChannel | undefined {

View File

@@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/
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 { ExtHostContext, MainThreadQuickOpenShape, ExtHostQuickOpenShape, TransferQuickPickItem, MainContext, IExtHostContext, TransferQuickInput, TransferQuickInputButton, IInputBoxOptions, TransferQuickPickItemOrSeparator } 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';
interface QuickInputSession {
input: IQuickInput;
handlesToItems: Map<number, TransferQuickPickItems>;
handlesToItems: Map<number, TransferQuickPickItem>;
}
function reviveIconPathUris(iconPath: { dark: URI; light?: URI | undefined; }) {
@@ -27,7 +27,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
private readonly _proxy: ExtHostQuickOpenShape;
private readonly _quickInputService: IQuickInputService;
private readonly _items: Record<number, {
resolve(items: TransferQuickPickItems[]): void;
resolve(items: TransferQuickPickItemOrSeparator[]): void;
reject(error: Error): void;
}> = {};
@@ -42,8 +42,8 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
public dispose(): void {
}
$show(instance: number, options: IPickOptions<TransferQuickPickItems>, token: CancellationToken): Promise<number | number[] | undefined> {
const contents = new Promise<TransferQuickPickItems[]>((resolve, reject) => {
$show(instance: number, options: IPickOptions<TransferQuickPickItem>, token: CancellationToken): Promise<number | number[] | undefined> {
const contents = new Promise<TransferQuickPickItemOrSeparator[]>((resolve, reject) => {
this._items[instance] = { resolve, reject };
});
@@ -51,7 +51,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
...options,
onDidFocus: el => {
if (el) {
this._proxy.$onItemSelected((<TransferQuickPickItems>el).handle);
this._proxy.$onItemSelected((<TransferQuickPickItem>el).handle);
}
}
};
@@ -73,7 +73,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
}
}
$setItems(instance: number, items: TransferQuickPickItems[]): Promise<void> {
$setItems(instance: number, items: TransferQuickPickItemOrSeparator[]): Promise<void> {
if (this._items[instance]) {
this._items[instance].resolve(items);
delete this._items[instance];
@@ -140,13 +140,13 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
// 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));
this._proxy.$onDidChangeActive(sessionId, items.map(item => (item as TransferQuickPickItem).handle));
});
quickpick.onDidChangeSelection(items => {
this._proxy.$onDidChangeSelection(sessionId, items.map(item => (item as TransferQuickPickItems).handle));
this._proxy.$onDidChangeSelection(sessionId, items.map(item => (item as TransferQuickPickItem).handle));
});
quickpick.onDidTriggerItemButton((e) => {
this._proxy.$onDidTriggerItemButton(sessionId, (e.item as TransferQuickPickItems).handle, (e.button as TransferQuickInputButton).handle);
this._proxy.$onDidTriggerItemButton(sessionId, (e.item as TransferQuickPickItem).handle, (e.button as TransferQuickInputButton).handle);
});
}
@@ -169,7 +169,11 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
}
} else if (param === 'items') {
handlesToItems.clear();
params[param].forEach((item: TransferQuickPickItems) => {
params[param].forEach((item: TransferQuickPickItemOrSeparator) => {
if (item.type === 'separator') {
return;
}
if (item.buttons) {
item.buttons = item.buttons.map((button: TransferQuickInputButton) => {
if (button.iconPath) {

View File

@@ -431,15 +431,6 @@ export class MainThreadSCM implements MainThreadSCMShape {
repository.input.visible = visible;
}
$setInputBoxFocus(sourceControlHandle: number): void {
const repository = this._repositories.get(sourceControlHandle);
if (!repository) {
return;
}
repository.input.setFocus();
}
$showValidationMessage(sourceControlHandle: number, message: string | IMarkdownString, type: InputValidationType) {
const repository = this._repositories.get(sourceControlHandle);
if (!repository) {

View File

@@ -659,7 +659,7 @@ export class MainThreadTask implements MainThreadTaskShape {
this._taskService.registerTaskSystem(key, {
platform: platform,
uriProvider: (path: string): URI => {
return URI.parse(`${info.scheme}://${info.authority}${path}`);
return URI.from({ scheme: info.scheme, authority: info.authority, path });
},
context: this._extHostContext,
resolveVariables: (workspaceFolder: IWorkspaceFolder, toResolve: ResolveSet, target: ConfigurationTarget): Promise<ResolvedVariables | undefined> => {

View File

@@ -153,7 +153,9 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun
return (await this.tunnelService.tunnels).map(tunnel => {
return {
remoteAddress: { port: tunnel.tunnelRemotePort, host: tunnel.tunnelRemoteHost },
localAddress: tunnel.localAddress
localAddress: tunnel.localAddress,
privacy: tunnel.privacy,
protocol: tunnel.protocol
};
});
}

View File

@@ -5,19 +5,19 @@
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { URI } 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 { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { EditorGroupColumn, columnToEditorGroup, editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
import { WebviewIcons } from 'vs/workbench/contrib/webviewPanel/browser/webviewIconManager';
import { ICreateWebViewShowOptions, IWebviewWorkbenchService } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
import { columnToEditorGroup, editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ACTIVE_GROUP, IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
/**
@@ -151,19 +151,13 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
extensionData: extHostProtocol.WebviewExtensionDescription,
handle: extHostProtocol.WebviewHandle,
viewType: string,
initData: {
title: string;
webviewOptions: extHostProtocol.IWebviewOptions;
panelOptions: extHostProtocol.IWebviewPanelOptions;
serializeBuffersForPostMessage: boolean;
},
showOptions: { viewColumn?: EditorGroupColumn, preserveFocus?: boolean; },
initData: extHostProtocol.IWebviewInitData,
showOptions: extHostProtocol.WebviewPanelShowOptions,
): void {
const mainThreadShowOptions: ICreateWebViewShowOptions = Object.create(null);
if (showOptions) {
mainThreadShowOptions.preserveFocus = !!showOptions.preserveFocus;
mainThreadShowOptions.group = columnToEditorGroup(this._editorGroupService, showOptions.viewColumn);
}
const mainThreadShowOptions: ICreateWebViewShowOptions = showOptions ? {
preserveFocus: !!showOptions.preserveFocus,
group: columnToEditorGroup(this._editorGroupService, showOptions.viewColumn)
} : {};
const extension = reviveWebviewExtension(extensionData);
@@ -192,7 +186,7 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
webview.setName(value);
}
public $setIconPath(handle: extHostProtocol.WebviewHandle, value: { light: UriComponents, dark: UriComponents; } | undefined): void {
public $setIconPath(handle: extHostProtocol.WebviewHandle, value: extHostProtocol.IWebviewIconPath | undefined): void {
const webview = this.getWebviewInput(handle);
webview.iconPath = reviveWebviewIcon(value);
}
@@ -203,10 +197,7 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
return;
}
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);
}
this._webviewWorkbenchService.revealWebview(webview, showOptions.viewColumn ?? ACTIVE_GROUP, !!showOptions.preserveFocus);
}
public $registerSerializer(viewType: string, options: { serializeBuffersForPostMessage: boolean }): void {
@@ -316,12 +307,14 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
}
}
function reviveWebviewIcon(
value: { light: UriComponents, dark: UriComponents; } | undefined
): WebviewIcons | undefined {
return value
? { light: URI.revive(value.light), dark: URI.revive(value.dark) }
: undefined;
function reviveWebviewIcon(value: extHostProtocol.IWebviewIconPath | undefined): WebviewIcons | undefined {
if (!value) {
return undefined;
}
return {
light: URI.revive(value.light),
dark: URI.revive(value.dark),
};
}
function reviveWebviewOptions(panelOptions: extHostProtocol.IWebviewPanelOptions): WebviewOptions {

View File

@@ -55,7 +55,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
webview.html = value;
}
public $setOptions(handle: extHostProtocol.WebviewHandle, options: extHostProtocol.IWebviewOptions): void {
public $setOptions(handle: extHostProtocol.WebviewHandle, options: extHostProtocol.IWebviewContentOptions): void {
const webview = this.getWebview(handle);
webview.contentOptions = reviveWebviewContentOptions(options);
}
@@ -123,10 +123,13 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
}
export function reviveWebviewExtension(extensionData: extHostProtocol.WebviewExtensionDescription): WebviewExtensionDescription {
return { id: extensionData.id, location: URI.revive(extensionData.location) };
return {
id: extensionData.id,
location: URI.revive(extensionData.location),
};
}
export function reviveWebviewContentOptions(webviewOptions: extHostProtocol.IWebviewOptions): WebviewContentOptions {
export function reviveWebviewContentOptions(webviewOptions: extHostProtocol.IWebviewContentOptions): WebviewContentOptions {
return {
allowScripts: webviewOptions.enableScripts,
allowForms: webviewOptions.enableForms,

View File

@@ -25,6 +25,7 @@ import { VIEWLET_ID as EXPLORER } from 'vs/workbench/contrib/files/common/files'
import { VIEWLET_ID as REMOTE } from 'vs/workbench/contrib/remote/browser/remoteExplorer';
import { VIEWLET_ID as SCM } from 'vs/workbench/contrib/scm/common/scm';
import { WebviewViewPane } from 'vs/workbench/contrib/webviewView/browser/webviewViewPane';
import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionMessageCollector, ExtensionsRegistry, IExtensionPoint, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
@@ -404,8 +405,8 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
return;
}
if (entry.key === 'remote' && !extension.description.enableProposedApi) {
collector.warn(localize('ViewContainerRequiresProposedAPI', "View container '{0}' requires 'enableProposedApi' turned on to be added to 'Remote'.", entry.key));
if (entry.key === 'remote' && !isProposedApiEnabled(extension.description, 'contribViewsRemote')) {
collector.warn(localize('ViewContainerRequiresProposedAPI', "View container '{0}' requires 'enabledApiProposals: [\"contribViewsRemote\"]' to be added to 'Remote'.", entry.key));
return;
}

View File

@@ -13,7 +13,7 @@ import { OverviewRulerLane } from 'vs/editor/common/model';
import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration';
import { score } from 'vs/editor/common/modes/languageSelector';
import * as files from 'vs/platform/files/common/files';
import { ExtHostContext, MainContext, ExtHostLogServiceShape, UIKind, CandidatePortSource } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostContext, MainContext, UIKind, CandidatePortSource, ExtHostLogLevelServiceShape } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostApiCommands } from 'vs/workbench/api/common/extHostApiCommands';
import { ExtHostClipboard } from 'vs/workbench/api/common/extHostClipboard';
import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
@@ -46,7 +46,6 @@ import { ExtHostUrls } from 'vs/workbench/api/common/extHostUrls';
import { ExtHostWebviews } from 'vs/workbench/api/common/extHostWebview';
import { IExtHostWindow } from 'vs/workbench/api/common/extHostWindow';
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { throwProposedApiError, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
import type * as vscode from 'vscode';
@@ -60,7 +59,7 @@ import { IExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations'
import { IExtHostTask } from 'vs/workbench/api/common/extHostTask';
import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService';
import { IExtHostSearch } from 'vs/workbench/api/common/extHostSearch';
import { ILogService } from 'vs/platform/log/common/log';
import { ILoggerService, ILogService } from 'vs/platform/log/common/log';
import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
@@ -92,6 +91,7 @@ import { ExtHostNotebookEditors } from 'vs/workbench/api/common/extHostNotebookE
import { ExtHostNotebookDocuments } from 'vs/workbench/api/common/extHostNotebookDocuments';
import { ExtHostInteractive } from 'vs/workbench/api/common/extHostInteractive';
import { combinedDisposable } from 'vs/base/common/lifecycle';
import { checkProposedApiEnabled, isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
export interface IExtensionApiFactory {
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
@@ -114,6 +114,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const rpcProtocol = accessor.get(IExtHostRpcService);
const extHostStorage = accessor.get(IExtHostStorage);
const extensionStoragePaths = accessor.get(IExtensionStoragePaths);
const extHostLoggerService = accessor.get(ILoggerService);
const extHostLogService = accessor.get(ILogService);
const extHostTunnelService = accessor.get(IExtHostTunnelService);
const extHostApiDeprecation = accessor.get(IExtHostApiDeprecationService);
@@ -123,7 +124,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
// register addressable instances
rpcProtocol.set(ExtHostContext.ExtHostFileSystemInfo, extHostFileSystemInfo);
rpcProtocol.set(ExtHostContext.ExtHostLogService, <ExtHostLogServiceShape><any>extHostLogService);
rpcProtocol.set(ExtHostContext.ExtHostLogLevelServiceShape, <ExtHostLogLevelServiceShape><any>extHostLoggerService);
rpcProtocol.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace);
rpcProtocol.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration);
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
@@ -200,8 +201,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
// We only inform once, it is not a warning because we just want to raise awareness and because
// we cannot say if the extension is doing it right or wrong...
const checkSelector = (function () {
let done = (!extension.isUnderDevelopment);
function informOnce(selector: vscode.DocumentSelector) {
let done = !extension.isUnderDevelopment;
function informOnce() {
if (!done) {
extHostLogService.info(`Extension '${extension.identifier.value}' uses a document selector without scheme. Learn more about this: https://go.microsoft.com/fwlink/?linkid=872305`);
done = true;
@@ -211,14 +212,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
if (Array.isArray(selector)) {
selector.forEach(perform);
} else if (typeof selector === 'string') {
informOnce(selector);
informOnce();
} else {
const filter = selector as vscode.DocumentFilter; // TODO: microsoft/TypeScript#42768
if (typeof filter.scheme === 'undefined') {
informOnce(selector);
informOnce();
}
if (!extension.enableProposedApi && typeof filter.exclusive === 'boolean') {
throwProposedApiError(extension);
if (typeof filter.exclusive === 'boolean') {
checkProposedApiEnabled(extension, 'documentFiltersExclusive');
}
}
return selector;
@@ -227,14 +228,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const authentication: typeof vscode.authentication = {
getSession(providerId: string, scopes: readonly string[], options?: vscode.AuthenticationGetSessionOptions) {
if (options?.forceNewSession || options?.silent) {
checkProposedApiEnabled(extension);
if (options?.forceNewSession) {
checkProposedApiEnabled(extension, 'authSession');
}
return extHostAuthentication.getSession(extension, providerId, scopes, options as any);
},
// TODO: remove this after GHPR and Codespaces move off of it
async hasSession(providerId: string, scopes: readonly string[]) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'authSession');
return !!(await extHostAuthentication.getSession(extension, providerId, scopes, { silent: true } as any));
},
get onDidChangeSessions(): Event<vscode.AuthenticationSessionsChangeEvent> {
@@ -271,7 +272,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
}, undefined, undefined, extension);
},
registerDiffInformationCommand: (id: string, callback: (diff: vscode.LineChange[], ...args: any[]) => any, thisArg?: any): vscode.Disposable => {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'diffCommand');
return extHostCommands.registerCommand(true, id, async (...args: any[]): Promise<any> => {
const activeTextEditor = extHostDocumentsAndEditors.activeEditor(true);
if (!activeTextEditor) {
@@ -339,7 +340,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return getRemoteName(initData.remote.authority);
},
get remoteAuthority() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'resolvers');
return initData.remote.authority;
},
get uiKind() {
@@ -360,19 +361,19 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostTesting.createTestController(provider, label);
},
createTestObserver() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'testObserver');
return extHostTesting.createTestObserver();
},
runTests(provider) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'testObserver');
return extHostTesting.runTests(provider);
},
get onDidChangeTestResults() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'testObserver');
return extHostTesting.onResultsChanged;
},
get testResults() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'testObserver');
return extHostTesting.results;
},
};
@@ -484,7 +485,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostLanguageFeatures.registerCompletionItemProvider(extension, checkSelector(selector), provider, triggerCharacters);
},
registerInlineCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.InlineCompletionItemProvider): vscode.Disposable {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'inlineCompletions');
return extHostLanguageFeatures.registerInlineCompletionsProvider(extension, checkSelector(selector), provider);
},
registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
@@ -509,15 +510,15 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostLanguageFeatures.setLanguageConfiguration(extension, language, configuration);
},
getTokenInformationAtPosition(doc: vscode.TextDocument, pos: vscode.Position) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'tokenInformation');
return extHostLanguages.tokenAtPosition(doc, pos);
},
registerInlayHintsProvider(selector: vscode.DocumentSelector, provider: vscode.InlayHintsProvider): vscode.Disposable {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'inlayHints');
return extHostLanguageFeatures.registerInlayHintsProvider(extension, selector, provider);
},
createLanguageStatusItem(id: string, selector: vscode.DocumentSelector): vscode.LanguageStatusItem {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'languageStatus');
return extHostLanguages.createLanguageStatusItem(extension, id, selector);
}
};
@@ -574,14 +575,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostTerminalService.onDidChangeActiveTerminal(listener, thisArg, disposables);
},
onDidChangeTerminalDimensions(listener, thisArg?, disposables?) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'terminalDimensions');
return extHostTerminalService.onDidChangeTerminalDimensions(listener, thisArg, disposables);
},
onDidChangeTerminalState(listener, thisArg?, disposables?) {
return extHostTerminalService.onDidChangeTerminalState(listener, thisArg, disposables);
},
onDidWriteTerminalData(listener, thisArg?, disposables?) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'terminalDataWriteEvent');
return extHostTerminalService.onDidWriteTerminalData(listener, thisArg, disposables);
},
get state() {
@@ -600,7 +601,11 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return <Thenable<any>>extHostMessageService.showMessage(extension, Severity.Error, message, rest[0], <Array<string | vscode.MessageItem>>rest.slice(1));
},
showQuickPick(items: any, options?: vscode.QuickPickOptions, token?: vscode.CancellationToken): any {
return extHostQuickOpen.showQuickPick(items, !!extension.enableProposedApi, options, token);
// TODO: remove this once quickPickSeparators has been finalized.
if (Array.isArray(items) && items.some((item) => item.kind !== undefined)) {
checkProposedApiEnabled(extension, 'quickPickSeparators');
}
return extHostQuickOpen.showQuickPick(items, options, token);
},
showWorkspaceFolderPick(options?: vscode.WorkspaceFolderPickOptions) {
return extHostQuickOpen.showWorkspaceFolderPick(options);
@@ -649,13 +654,13 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostWebviewPanels.createWebviewPanel(extension, viewType, title, showOptions, options);
},
createWebviewTextEditorInset(editor: vscode.TextEditor, line: number, height: number, options?: vscode.WebviewOptions): vscode.WebviewEditorInset {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'editorInsets');
return extHostEditorInsets.createWebviewEditorInset(editor, line, height, options, extension);
},
createTerminal(nameOrOptions?: vscode.TerminalOptions | vscode.ExtensionTerminalOptions | string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal {
if (typeof nameOrOptions === 'object') {
if ('location' in nameOrOptions) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'terminalLocation');
}
if ('pty' in nameOrOptions) {
return extHostTerminalService.createExtensionTerminal(nameOrOptions);
@@ -689,7 +694,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostUrls.registerUriHandler(extension.identifier, handler);
},
createQuickPick<T extends vscode.QuickPickItem>(): vscode.QuickPick<T> {
return extHostQuickOpen.createQuickPick(extension.identifier, !!extension.enableProposedApi);
return extHostQuickOpen.createQuickPick(extension);
},
createInputBox(): vscode.InputBox {
return extHostQuickOpen.createInputBox(extension.identifier);
@@ -708,55 +713,55 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostWebviewViews.registerWebviewViewProvider(extension, viewId, provider, options?.webviewOptions);
},
get activeNotebookEditor(): vscode.NotebookEditor | undefined {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebook.activeNotebookEditor;
},
onDidChangeActiveNotebookEditor(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebook.onDidChangeActiveNotebookEditor(listener, thisArgs, disposables);
},
get visibleNotebookEditors() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebook.visibleNotebookEditors;
},
get onDidChangeVisibleNotebookEditors() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebook.onDidChangeVisibleNotebookEditors;
},
onDidChangeNotebookEditorSelection(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebookEditors.onDidChangeNotebookEditorSelection(listener, thisArgs, disposables);
},
onDidChangeNotebookEditorVisibleRanges(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebookEditors.onDidChangeNotebookEditorVisibleRanges(listener, thisArgs, disposables);
},
showNotebookDocument(uriOrDocument, options?) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebook.showNotebookDocument(uriOrDocument, options);
},
registerExternalUriOpener(id: string, opener: vscode.ExternalUriOpener, metadata: vscode.ExternalUriOpenerMetadata) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'externalUriOpener');
return extHostUriOpeners.registerExternalUriOpener(extension.identifier, id, opener, metadata);
},
get tabs() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'tabs');
return extHostEditorTabs.tabs;
},
get activeTab() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'tabs');
return extHostEditorTabs.activeTab;
},
get onDidChangeTabs() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'tabs');
return extHostEditorTabs.onDidChangeTabs;
},
get onDidChangeActiveTab() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'tabs');
return extHostEditorTabs.onDidChangeActiveTab;
},
getInlineCompletionItemController<T extends vscode.InlineCompletionItem>(provider: vscode.InlineCompletionItemProvider<T>): vscode.InlineCompletionController<T> {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'inlineCompletions');
return InlineCompletionController.get(provider);
}
};
@@ -805,6 +810,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostWorkspace.findFiles(typeConverters.GlobPattern.from(include), typeConverters.GlobPattern.from(exclude), maxResults, extension.identifier, token);
},
findTextInFiles: (query: vscode.TextSearchQuery, optionsOrCallback: vscode.FindTextInFilesOptions | ((result: vscode.TextSearchResult) => void), callbackOrToken?: vscode.CancellationToken | ((result: vscode.TextSearchResult) => void), token?: vscode.CancellationToken) => {
checkProposedApiEnabled(extension, 'findTextInFiles');
let options: vscode.FindTextInFilesOptions;
let callback: (result: vscode.TextSearchResult) => void;
@@ -891,11 +897,11 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostNotebook.onDidCloseNotebookDocument;
},
registerNotebookSerializer(viewType: string, serializer: vscode.NotebookSerializer, options?: vscode.NotebookDocumentContentOptions, registration?: vscode.NotebookRegistrationData) {
return extHostNotebook.registerNotebookSerializer(extension, viewType, serializer, options, extension.enableProposedApi ? registration : undefined);
return extHostNotebook.registerNotebookSerializer(extension, viewType, serializer, options, isProposedApiEnabled(extension, 'notebookLiveShare') ? registration : undefined);
},
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider, options?: vscode.NotebookDocumentContentOptions, registration?: vscode.NotebookRegistrationData) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider, options, extension.enableProposedApi ? registration : undefined);
checkProposedApiEnabled(extension, 'notebookContentProvider');
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider, options, isProposedApiEnabled(extension, 'notebookLiveShare') ? registration : undefined);
},
onDidChangeConfiguration: (listener: (_: any) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
return configProvider.onDidChangeConfiguration(listener, thisArgs, disposables);
@@ -923,19 +929,19 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostConsumerFileSystem.value;
},
registerFileSearchProvider: (scheme: string, provider: vscode.FileSearchProvider) => {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'fileSearchProvider');
return extHostSearch.registerFileSearchProvider(scheme, provider);
},
registerTextSearchProvider: (scheme: string, provider: vscode.TextSearchProvider) => {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'textSearchProvider');
return extHostSearch.registerTextSearchProvider(scheme, provider);
},
registerRemoteAuthorityResolver: (authorityPrefix: string, resolver: vscode.RemoteAuthorityResolver) => {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'resolvers');
return extensionService.registerRemoteAuthorityResolver(authorityPrefix, resolver);
},
registerResourceLabelFormatter: (formatter: vscode.ResourceLabelFormatter) => {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'resolvers');
return extHostLabelService.$registerResourceLabelFormatter(formatter);
},
onDidCreateFiles: (listener, thisArg, disposables) => {
@@ -957,7 +963,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostFileSystemEvent.getOnWillRenameFileEvent(extension)(listener, thisArg, disposables);
},
openTunnel: (forward: vscode.TunnelOptions) => {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'resolvers');
return extHostTunnelService.openTunnel(extension, forward).then(value => {
if (!value) {
throw new Error('cannot open tunnel');
@@ -966,26 +972,26 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
});
},
get tunnels() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'resolvers');
return extHostTunnelService.getTunnels();
},
onDidChangeTunnels: (listener, thisArg?, disposables?) => {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'resolvers');
return extHostTunnelService.onDidChangeTunnels(listener, thisArg, disposables);
},
registerPortAttributesProvider: (portSelector: { pid?: number, portRange?: [number, number], commandMatcher?: RegExp }, provider: vscode.PortAttributesProvider) => {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'portsAttributes');
return extHostTunnelService.registerPortsAttributesProvider(portSelector, provider);
},
registerTimelineProvider: (scheme: string | string[], provider: vscode.TimelineProvider) => {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'timeline');
return extHostTimeline.registerTimelineProvider(scheme, provider, extension.identifier, extHostCommands.converter);
},
get isTrusted() {
return extHostWorkspace.trusted;
},
requestWorkspaceTrust: (options?: vscode.WorkspaceTrustRequestOptions) => {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'workspaceTrust');
return extHostWorkspace.requestWorkspaceTrust(options);
},
onDidGrantWorkspaceTrust: (listener, thisArgs?, disposables?) => {
@@ -1098,44 +1104,44 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
// namespace: notebook
const notebooks: typeof vscode.notebooks = {
createNotebookController(id: string, notebookType: string, label: string, handler?, rendererScripts?: vscode.NotebookRendererScript[]) {
return extHostNotebookKernels.createNotebookController(extension, id, notebookType, label, handler, extension.enableProposedApi ? rendererScripts : undefined);
return extHostNotebookKernels.createNotebookController(extension, id, notebookType, label, handler, isProposedApiEnabled(extension, 'notebookMessaging') ? rendererScripts : undefined);
},
registerNotebookCellStatusBarItemProvider: (notebookType: string, provider: vscode.NotebookCellStatusBarItemProvider) => {
return extHostNotebook.registerNotebookCellStatusBarItemProvider(extension, notebookType, provider);
},
get onDidSaveNotebookDocument(): Event<vscode.NotebookDocument> {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebookDocuments.onDidSaveNotebookDocument;
},
createNotebookEditorDecorationType(options: vscode.NotebookDecorationRenderOptions): vscode.NotebookEditorDecorationType {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditorDecorationType');
return extHostNotebookEditors.createNotebookEditorDecorationType(options);
},
createRendererMessaging(rendererId) {
return extHostNotebookRenderers.createRendererMessaging(extension, rendererId);
},
onDidChangeNotebookDocumentMetadata(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebookDocuments.onDidChangeNotebookDocumentMetadata(listener, thisArgs, disposables);
},
onDidChangeNotebookCells(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebook.onDidChangeNotebookCells(listener, thisArgs, disposables);
},
onDidChangeNotebookCellExecutionState(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookCellExecutionState');
return extHostNotebook.onDidChangeNotebookCellExecutionState(listener, thisArgs, disposables);
},
onDidChangeCellOutputs(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebook.onDidChangeCellOutputs(listener, thisArgs, disposables);
},
onDidChangeCellMetadata(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookEditor');
return extHostNotebook.onDidChangeCellMetadata(listener, thisArgs, disposables);
},
createConcatTextDocument(notebook, selector) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookConcatTextDocument');
return new ExtHostNotebookConcatDocument(extHostNotebook, extHostDocuments, notebook, selector);
},
};
@@ -1309,6 +1315,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
FunctionCoverage: extHostTypes.FunctionCoverage,
WorkspaceTrustState: extHostTypes.WorkspaceTrustState,
LanguageStatusSeverity: extHostTypes.LanguageStatusSeverity,
QuickPickItemKind: extHostTypes.QuickPickItemKind,
};
};
}

View File

@@ -23,7 +23,12 @@ import { IExtHostFileSystemInfo, ExtHostFileSystemInfo } from 'vs/workbench/api/
import { IExtHostSecretState, ExtHostSecretState } from 'vs/workbench/api/common/exHostSecretState';
import { ExtHostTelemetry, IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry';
import { ExtHostEditorTabs, IExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
import { ExtHostLoggerService } from 'vs/workbench/api/common/extHostLoggerService';
import { ILoggerService, ILogService } from 'vs/platform/log/common/log';
import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService';
registerSingleton(ILoggerService, ExtHostLoggerService);
registerSingleton(ILogService, ExtHostLogService);
registerSingleton(IExtHostApiDeprecationService, ExtHostApiDeprecationService);
registerSingleton(IExtHostCommands, ExtHostCommands);
registerSingleton(IExtHostConfiguration, ExtHostConfiguration);

View File

@@ -31,7 +31,7 @@ import { ConfigurationScope } from 'vs/platform/configuration/common/configurati
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import * as files from 'vs/platform/files/common/files';
import { ResourceLabelFormatter } from 'vs/platform/label/common/label';
import { LogLevel } from 'vs/platform/log/common/log';
import { ILoggerOptions, LogLevel } from 'vs/platform/log/common/log';
import { IMarkerData } from 'vs/platform/markers/common/markers';
import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress';
import * as quickInput from 'vs/platform/quickinput/common/quickInput';
@@ -56,6 +56,7 @@ import { IAdapterDescriptor, IConfig, IDebugSessionReplMode } from 'vs/workbench
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 { OutputChannelUpdateMode } from 'vs/workbench/contrib/output/common/output';
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';
@@ -443,14 +444,12 @@ export interface MainThreadMessageServiceShape extends IDisposable {
}
export interface MainThreadOutputServiceShape extends IDisposable {
$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;
$replaceAll(channelId: string, till: number, value?: string): Promise<void> | undefined;
$reveal(channelId: string, preserveFocus: boolean): Promise<void> | undefined;
$close(channelId: string): Promise<void> | undefined;
$dispose(channelId: string): Promise<void> | undefined;
$register(label: string, log: boolean, file: UriComponents, extensionId: string): Promise<string>;
$update(channelId: string, mode: OutputChannelUpdateMode.Append): Promise<void>;
$update(channelId: string, mode: OutputChannelUpdateMode, till: number): Promise<void>;
$reveal(channelId: string, preserveFocus: boolean): Promise<void>;
$close(channelId: string): Promise<void>;
$dispose(channelId: string): Promise<void>;
}
export interface MainThreadProgressShape extends IDisposable {
@@ -511,7 +510,8 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
$sendProcessExit(terminalId: number, exitCode: number | undefined): void;
}
export interface TransferQuickPickItems extends quickInput.IQuickPickItem {
export type TransferQuickPickItemOrSeparator = TransferQuickPickItem | quickInput.IQuickPickSeparator;
export interface TransferQuickPickItem extends quickInput.IQuickPickItem {
handle: number;
buttons?: TransferQuickInputButton[];
}
@@ -549,7 +549,7 @@ export interface TransferQuickPick extends BaseTransferQuickInput {
buttons?: TransferQuickInputButton[];
items?: TransferQuickPickItems[];
items?: TransferQuickPickItemOrSeparator[];
activeItems?: number[];
@@ -594,8 +594,8 @@ export interface IInputBoxOptions {
}
export interface MainThreadQuickOpenShape extends IDisposable {
$show(instance: number, options: quickInput.IPickOptions<TransferQuickPickItems>, token: CancellationToken): Promise<number | number[] | undefined>;
$setItems(instance: number, items: TransferQuickPickItems[]): Promise<void>;
$show(instance: number, options: quickInput.IPickOptions<TransferQuickPickItem>, token: CancellationToken): Promise<number | number[] | undefined>;
$setItems(instance: number, items: TransferQuickPickItemOrSeparator[]): Promise<void>;
$setError(instance: number, error: Error): Promise<void>;
$input(options: IInputBoxOptions | undefined, validateInput: boolean, token: CancellationToken): Promise<string | undefined>;
$createOrUpdate(params: TransferQuickInput): Promise<void>;
@@ -619,11 +619,11 @@ export interface MainThreadTelemetryShape extends IDisposable {
}
export interface MainThreadEditorInsetsShape extends IDisposable {
$createEditorInset(handle: number, id: string, uri: UriComponents, line: number, height: number, options: IWebviewOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): Promise<void>;
$createEditorInset(handle: number, id: string, uri: UriComponents, line: number, height: number, options: IWebviewContentOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): Promise<void>;
$disposeEditorInset(handle: number): void;
$setHtml(handle: number, value: string): void;
$setOptions(handle: number, options: IWebviewOptions): void;
$setOptions(handle: number, options: IWebviewContentOptions): void;
$postMessage(handle: number, value: any): Promise<boolean>;
}
@@ -682,12 +682,12 @@ export interface IWebviewPortMapping {
readonly extensionHostPort: number;
}
export interface IWebviewOptions {
export interface IWebviewContentOptions {
readonly enableScripts?: boolean;
readonly enableForms?: boolean;
readonly enableCommandUris?: boolean;
readonly localResourceRoots?: ReadonlyArray<UriComponents>;
readonly portMapping?: ReadonlyArray<IWebviewPortMapping>;
readonly localResourceRoots?: readonly UriComponents[];
readonly portMapping?: readonly IWebviewPortMapping[];
}
export interface IWebviewPanelOptions {
@@ -730,27 +730,34 @@ export interface WebviewMessageArrayBufferReference {
export interface MainThreadWebviewsShape extends IDisposable {
$setHtml(handle: WebviewHandle, value: string): void;
$setOptions(handle: WebviewHandle, options: IWebviewOptions): void;
$setOptions(handle: WebviewHandle, options: IWebviewContentOptions): void;
$postMessage(handle: WebviewHandle, value: string, ...buffers: VSBuffer[]): Promise<boolean>
}
export interface IWebviewIconPath {
readonly light: UriComponents;
readonly dark: UriComponents;
}
export interface IWebviewInitData {
readonly title: string;
readonly webviewOptions: IWebviewContentOptions;
readonly panelOptions: IWebviewPanelOptions;
readonly serializeBuffersForPostMessage: boolean;
}
export interface MainThreadWebviewPanelsShape extends IDisposable {
$createWebviewPanel(
extension: WebviewExtensionDescription,
handle: WebviewHandle,
viewType: string,
initData: {
title: string;
webviewOptions: IWebviewOptions;
panelOptions: IWebviewPanelOptions;
serializeBuffersForPostMessage: boolean;
},
initData: IWebviewInitData,
showOptions: WebviewPanelShowOptions,
): void;
$disposeWebview(handle: WebviewHandle): void;
$reveal(handle: WebviewHandle, showOptions: WebviewPanelShowOptions): void;
$setTitle(handle: WebviewHandle, value: string): void;
$setIconPath(handle: WebviewHandle, value: { light: UriComponents, dark: UriComponents; } | undefined): void;
$setIconPath(handle: WebviewHandle, value: IWebviewIconPath | undefined): void;
$registerSerializer(viewType: string, options: { serializeBuffersForPostMessage: boolean }): void;
$unregisterSerializer(viewType: string): void;
@@ -797,7 +804,7 @@ export interface ExtHostWebviewPanelsShape {
initData: {
title: string;
state: any;
webviewOptions: IWebviewOptions;
webviewOptions: IWebviewContentOptions;
panelOptions: IWebviewPanelOptions;
},
position: EditorGroupColumn,
@@ -811,7 +818,7 @@ export interface ExtHostCustomEditorsShape {
viewType: string,
initData: {
title: string;
webviewOptions: IWebviewOptions;
webviewOptions: IWebviewContentOptions;
panelOptions: IWebviewPanelOptions;
},
position: EditorGroupColumn,
@@ -1099,7 +1106,6 @@ export interface MainThreadSCMShape extends IDisposable {
$setInputBoxValue(sourceControlHandle: number, value: string): void;
$setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void;
$setInputBoxVisibility(sourceControlHandle: number, visible: boolean): void;
$setInputBoxFocus(sourceControlHandle: number): void;
$showValidationMessage(sourceControlHandle: number, message: string | IMarkdownString, type: InputValidationType): void;
$setValidationProviderIsEnabled(sourceControlHandle: number, enabled: boolean): void;
}
@@ -1895,12 +1901,13 @@ export interface ExtHostWindowShape {
$onDidChangeWindowFocus(value: boolean): void;
}
export interface ExtHostLogServiceShape {
export interface ExtHostLogLevelServiceShape {
$setLevel(level: LogLevel): void;
}
export interface MainThreadLogShape {
$log(file: UriComponents, level: LogLevel, args: any[]): void;
export interface MainThreadLoggerShape {
$log(file: UriComponents, messages: [LogLevel, string][]): void;
$createLogger(file: UriComponents, options?: ILoggerOptions): Promise<void>;
}
export interface ExtHostOutputServiceShape {
@@ -2213,7 +2220,7 @@ export const MainContext = {
MainThreadKeytar: createMainId<MainThreadKeytarShape>('MainThreadKeytar'),
MainThreadLanguageFeatures: createMainId<MainThreadLanguageFeaturesShape>('MainThreadLanguageFeatures'),
MainThreadLanguages: createMainId<MainThreadLanguagesShape>('MainThreadLanguages'),
MainThreadLog: createMainId<MainThreadLogShape>('MainThread'),
MainThreadLogger: createMainId<MainThreadLoggerShape>('MainThreadLogger'),
MainThreadMessageService: createMainId<MainThreadMessageServiceShape>('MainThreadMessageService'),
MainThreadOutputService: createMainId<MainThreadOutputServiceShape>('MainThreadOutputService'),
MainThreadProgress: createMainId<MainThreadProgressShape>('MainThreadProgress'),
@@ -2268,7 +2275,7 @@ export const ExtHostContext = {
ExtHostLanguageFeatures: createExtId<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures'),
ExtHostQuickOpen: createExtId<ExtHostQuickOpenShape>('ExtHostQuickOpen'),
ExtHostExtensionService: createExtId<ExtHostExtensionServiceShape>('ExtHostExtensionService'),
ExtHostLogService: createExtId<ExtHostLogServiceShape>('ExtHostLogService'),
ExtHostLogLevelServiceShape: createExtId<ExtHostLogLevelServiceShape>('ExtHostLogLevelServiceShape'),
ExtHostTerminalService: createExtId<ExtHostTerminalServiceShape>('ExtHostTerminalService'),
ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM'),
ExtHostSearch: createExtId<ExtHostSearchShape>('ExtHostSearch'),

View File

@@ -253,7 +253,7 @@ export class ExtHostCustomEditors implements extHostProtocol.ExtHostCustomEditor
viewType: string,
initData: {
title: string;
webviewOptions: extHostProtocol.IWebviewOptions;
webviewOptions: extHostProtocol.IWebviewContentOptions;
panelOptions: extHostProtocol.IWebviewPanelOptions;
},
position: EditorGroupColumn,

View File

@@ -17,7 +17,7 @@ import { ExtHostConfiguration, IExtHostConfiguration } from 'vs/workbench/api/co
import { ActivatedExtension, EmptyExtension, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionModule, HostExtension, ExtensionActivationTimesFragment } from 'vs/workbench/api/common/extHostExtensionActivator';
import { ExtHostStorage, IExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { MissingExtensionDependency, checkProposedApiEnabled, ActivationKind } from 'vs/workbench/services/extensions/common/extensions';
import { MissingExtensionDependency, ActivationKind, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
import * as errors from 'vs/base/common/errors';
import type * as vscode from 'vscode';
@@ -447,7 +447,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
return extension;
},
get extensionRuntime() {
checkProposedApiEnabled(extensionDescription);
checkProposedApiEnabled(extensionDescription, 'extensionRuntime');
return that.extensionRuntime;
},
get environmentVariableCollection() { return that._extHostTerminalService.getEnvironmentVariableCollection(extensionDescription); }
@@ -698,7 +698,8 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
};
const options: ResolvedOptions = {
extensionHostEnv: result.extensionHostEnv,
isTrusted: result.isTrusted
isTrusted: result.isTrusted,
authenticationSession: result.authenticationSession ? { id: result.authenticationSession.id, providerId: result.authenticationSession.providerId } : undefined
};
return {

View File

@@ -15,7 +15,8 @@ import { State, StateMachine, LinkComputer, Edge } from 'vs/editor/common/modes/
import { commonPrefixLength } from 'vs/base/common/strings';
import { CharCode } from 'vs/base/common/charCode';
import { VSBuffer } from 'vs/base/common/buffer';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
class FsLinkProvider {
@@ -133,7 +134,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
}
}
registerFileSystemProvider(extension: ExtensionIdentifier, scheme: string, provider: vscode.FileSystemProvider, options: { isCaseSensitive?: boolean, isReadonly?: boolean } = {}) {
registerFileSystemProvider(extension: IExtensionDescription, scheme: string, provider: vscode.FileSystemProvider, options: { isCaseSensitive?: boolean, isReadonly?: boolean } = {}) {
if (this._registeredSchemes.has(scheme)) {
throw new Error(`a provider for the scheme '${scheme}' is already registered`);
@@ -160,11 +161,12 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
if (typeof provider.open === 'function' && typeof provider.close === 'function'
&& typeof provider.read === 'function' && typeof provider.write === 'function'
) {
checkProposedApiEnabled(extension, 'fsChunks');
capabilities += files.FileSystemProviderCapabilities.FileOpenReadWriteClose;
}
this._proxy.$registerFileSystemProvider(handle, scheme, capabilities).catch(err => {
console.error(`FAILED to register filesystem provider of ${extension.value}-extension for the scheme ${scheme}`);
console.error(`FAILED to register filesystem provider of ${extension.identifier.value}-extension for the scheme ${scheme}`);
console.error(err);
});

View File

@@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILoggerService, LogService } from 'vs/platform/log/common/log';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { ExtensionHostLogFileName } from 'vs/workbench/services/extensions/common/extensions';
export class ExtHostLogService extends LogService {
declare readonly _serviceBrand: undefined;
constructor(
@ILoggerService loggerService: ILoggerService,
@IExtHostInitDataService initData: IExtHostInitDataService,
) {
super(loggerService.createLogger(initData.logFile, { name: ExtensionHostLogFileName }));
}
}

View File

@@ -0,0 +1,70 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILogger, ILoggerOptions, AbstractMessageLogger, LogLevel, AbstractLoggerService } from 'vs/platform/log/common/log';
import { MainThreadLoggerShape, MainContext, ExtHostLogLevelServiceShape as ExtHostLogLevelServiceShape } from 'vs/workbench/api/common/extHost.protocol';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { URI } from 'vs/base/common/uri';
import { Emitter } from 'vs/base/common/event';
export class ExtHostLoggerService extends AbstractLoggerService implements ExtHostLogLevelServiceShape {
declare readonly _serviceBrand: undefined;
private readonly _onDidChangeLogLevel: Emitter<LogLevel>;
private readonly _proxy: MainThreadLoggerShape;
constructor(
@IExtHostRpcService rpc: IExtHostRpcService,
@IExtHostInitDataService initData: IExtHostInitDataService,
) {
const emitter = new Emitter<LogLevel>();
super(initData.logLevel, emitter.event);
this._proxy = rpc.getProxy(MainContext.MainThreadLogger);
this._onDidChangeLogLevel = this._register(emitter);
}
$setLevel(level: LogLevel): void {
this._onDidChangeLogLevel.fire(level);
}
protected doCreateLogger(resource: URI, logLevel: LogLevel, options?: ILoggerOptions): ILogger {
return new Logger(this._proxy, resource, logLevel, options);
}
}
class Logger extends AbstractMessageLogger {
private isLoggerCreated: boolean = false;
private buffer: [LogLevel, string][] = [];
constructor(
private readonly proxy: MainThreadLoggerShape,
private readonly file: URI,
logLevel: LogLevel,
loggerOptions?: ILoggerOptions,
) {
super(loggerOptions?.always);
this.setLevel(logLevel);
this.proxy.$createLogger(file, loggerOptions)
.then(() => {
this.doLog(this.buffer);
this.isLoggerCreated = true;
});
}
protected log(level: LogLevel, message: string) {
const messages: [LogLevel, string][] = [[level, message]];
if (this.isLoggerCreated) {
this.doLog(messages);
} else {
this.buffer.push(...messages);
}
}
private doLog(messages: [LogLevel, string][]) {
this.proxy.$log(this.file, messages);
}
}

View File

@@ -44,7 +44,7 @@ export class ExtHostMessageService {
}
if (options.useCustom) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'resolvers');
}
const commands: { title: string; isCloseAffordance: boolean; handle: number; }[] = [];

View File

@@ -167,11 +167,11 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
_update();
},
get kind() {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookControllerKind');
return data.kind ?? '';
},
set kind(value) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookControllerKind');
data.kind = value;
_update();
},
@@ -234,11 +234,11 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
// --- ipc
onDidReceiveMessage: onDidReceiveMessage.event,
postMessage(message, editor) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookMessaging');
return that._proxy.$postMessage(handle, editor && that._extHostNotebook.getIdByEditor(editor), message);
},
asWebviewUri(uri: URI) {
checkProposedApiEnabled(extension);
checkProposedApiEnabled(extension, 'notebookMessaging');
return asWebviewUri(uri, that._initData.remote);
},
};

View File

@@ -4,10 +4,11 @@
*--------------------------------------------------------------------------------------------*/
import { Emitter } from 'vs/base/common/event';
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
import { IExtensionDescription } 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 { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import * as vscode from 'vscode';
@@ -24,14 +25,14 @@ export class ExtHostNotebookRenderers implements ExtHostNotebookRenderersShape {
this._rendererMessageEmitters.get(rendererId)?.fire({ editor: editor.apiEditor, message });
}
public createRendererMessaging(manifest: IExtensionManifest, rendererId: string): vscode.NotebookRendererMessaging {
public createRendererMessaging(manifest: IExtensionDescription, 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 notebookEditorVisible = isProposedApiEnabled(manifest, 'notebookEditor');
const notebookEditorAliases = new WeakMap<{}, vscode.NotebookEditor>();
const messaging: vscode.NotebookRendererMessaging = {

View File

@@ -7,150 +7,114 @@ import { MainContext, MainThreadOutputServiceShape, ExtHostOutputServiceShape }
import type * as vscode from 'vscode';
import { URI } from 'vs/base/common/uri';
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';
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { ILogger, ILoggerService } from 'vs/platform/log/common/log';
import { OutputChannelUpdateMode } from 'vs/workbench/contrib/output/common/output';
import { IExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileSystemConsumer';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
import { toLocalISOString } from 'vs/base/common/date';
import { VSBuffer } from 'vs/base/common/buffer';
export abstract class AbstractExtHostOutputChannel extends Disposable implements vscode.OutputChannel {
readonly _id: Promise<string>;
private readonly _name: string;
protected readonly _proxy: MainThreadOutputServiceShape;
private _disposed: boolean;
private _offset: number;
private readonly _extension: IExtensionDescription;
export class ExtHostOutputChannel extends Disposable implements vscode.OutputChannel {
private offset: number = 0;
public visible: boolean = false;
constructor(name: string, log: boolean, file: URI | undefined, extension: IExtensionDescription, proxy: MainThreadOutputServiceShape) {
private _disposed: boolean = false;
get disposed(): boolean { return this._disposed; }
constructor(
readonly id: string, readonly name: string,
private readonly logger: ILogger,
private readonly proxy: MainThreadOutputServiceShape
) {
super();
this._name = name;
this._proxy = proxy;
this._id = proxy.$register(this.name, log, file, extension.identifier.value);
this._disposed = false;
this._offset = 0;
this._extension = extension;
}
get name(): string {
return this._name;
}
append(value: string): void {
this.validate();
this.incrementOffset(value);
}
appendLine(value: string): void {
this.validate();
this.append(value + '\n');
}
clear(): void {
this.validate();
const till = this._offset;
this._id.then(id => this._proxy.$clear(id, till));
append(value: string): void {
this.write(value);
if (this.visible) {
this.logger.flush();
this.proxy.$update(this.id, OutputChannelUpdateMode.Append);
}
}
replaceAll(value: string, donotSendValue?: boolean): void {
this.validate(true);
const till = this._offset;
this.incrementOffset(value);
this._id.then(id => this._proxy.$replaceAll(id, till, donotSendValue ? undefined : value));
clear(): void {
const till = this.offset;
this.logger.flush();
this.proxy.$update(this.id, OutputChannelUpdateMode.Clear, till);
}
replace(value: string): void {
const till = this.offset;
this.write(value);
this.proxy.$update(this.id, OutputChannelUpdateMode.Replace, till);
if (this.visible) {
this.logger.flush();
}
}
show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void {
this.validate();
this._id.then(id => this._proxy.$reveal(id, !!(typeof columnOrPreserveFocus === 'boolean' ? columnOrPreserveFocus : preserveFocus)));
this.logger.flush();
this.proxy.$reveal(this.id, !!(typeof columnOrPreserveFocus === 'boolean' ? columnOrPreserveFocus : preserveFocus));
}
hide(): void {
this.validate();
this._id.then(id => this._proxy.$close(id));
this.proxy.$close(this.id);
}
protected validate(checkProposedApi?: boolean): void {
if (checkProposedApi) {
checkProposedApiEnabled(this._extension);
}
if (this._disposed) {
throw new Error('Channel has been closed');
}
}
private incrementOffset(value: string) {
this._offset += value ? VSBuffer.fromString(value).byteLength : 0;
private write(value: string): void {
this.offset += VSBuffer.fromString(value).byteLength;
this.logger.info(value);
}
override dispose(): void {
super.dispose();
if (!this._disposed) {
this._id
.then(id => this._proxy.$dispose(id))
.then(() => this._disposed = true);
this.proxy.$dispose(this.id);
this._disposed = true;
}
}
}
export class ExtHostPushOutputChannel extends AbstractExtHostOutputChannel {
constructor(name: string, extension: IExtensionDescription, proxy: MainThreadOutputServiceShape) {
super(name, false, undefined, extension, proxy);
}
override append(value: string): void {
super.append(value);
this._id.then(id => this._proxy.$append(id, value));
}
}
export class LazyOutputChannel implements vscode.OutputChannel {
constructor(
readonly name: string,
private readonly _channel: Promise<AbstractExtHostOutputChannel>
) { }
append(value: string): void {
this._channel.then(channel => channel.append(value));
}
appendLine(value: string): void {
this._channel.then(channel => channel.appendLine(value));
}
clear(): void {
this._channel.then(channel => channel.clear());
}
replaceAll(value: string): void {
this._channel.then(channel => channel.replaceAll(value));
}
show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void {
this._channel.then(channel => channel.show(columnOrPreserveFocus, preserveFocus));
}
hide(): void {
this._channel.then(channel => channel.hide());
}
dispose(): void {
this._channel.then(channel => channel.dispose());
}
}
export class ExtHostOutputService implements ExtHostOutputServiceShape {
readonly _serviceBrand: undefined;
protected readonly _proxy: MainThreadOutputServiceShape;
private readonly proxy: MainThreadOutputServiceShape;
constructor(@IExtHostRpcService extHostRpc: IExtHostRpcService) {
this._proxy = extHostRpc.getProxy(MainContext.MainThreadOutputService);
private readonly outputsLocation: URI;
private outputDirectoryPromise: Thenable<URI> | undefined;
private namePool: number = 1;
private readonly channels: Map<string, ExtHostOutputChannel> = new Map<string, ExtHostOutputChannel>();
private visibleChannelId: string | null = null;
constructor(
@IExtHostRpcService extHostRpc: IExtHostRpcService,
@IExtHostInitDataService initData: IExtHostInitDataService,
@IExtHostConsumerFileSystem private readonly extHostFileSystem: IExtHostConsumerFileSystem,
@IExtHostFileSystemInfo private readonly extHostFileSystemInfo: IExtHostFileSystemInfo,
@ILoggerService private readonly loggerService: ILoggerService,
) {
this.proxy = extHostRpc.getProxy(MainContext.MainThreadOutputService);
this.outputsLocation = this.extHostFileSystemInfo.extUri.joinPath(initData.logsLocation, `output_logging_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`);
}
$setVisibleChannel(channelId: string): void {
$setVisibleChannel(visibleChannelId: string | null): void {
this.visibleChannelId = visibleChannelId;
for (const [id, channel] of this.channels) {
channel.visible = id === this.visibleChannelId;
}
}
createOutputChannel(name: string, extension: IExtensionDescription): vscode.OutputChannel {
@@ -158,9 +122,68 @@ export class ExtHostOutputService implements ExtHostOutputServiceShape {
if (!name) {
throw new Error('illegal argument `name`. must not be falsy');
}
return new ExtHostPushOutputChannel(name, extension, this._proxy);
const extHostOutputChannel = this.doCreateOutputChannel(name, extension);
extHostOutputChannel.then(channel => {
this.channels.set(channel.id, channel);
channel.visible = channel.id === this.visibleChannelId;
});
return this.createExtHostOutputChannel(name, extHostOutputChannel);
}
private async doCreateOutputChannel(name: string, extension: IExtensionDescription): Promise<ExtHostOutputChannel> {
const outputDir = await this.createOutputDirectory();
const file = this.extHostFileSystemInfo.extUri.joinPath(outputDir, `${this.namePool++}-${name.replace(/[\\/:\*\?"<>\|]/g, '')}.log`);
const logger = this.loggerService.createLogger(file, { always: true, donotRotate: true, donotUseFormatters: true });
const id = await this.proxy.$register(name, false, file, extension.identifier.value);
return new ExtHostOutputChannel(id, name, logger, this.proxy);
}
private createOutputDirectory(): Thenable<URI> {
if (!this.outputDirectoryPromise) {
this.outputDirectoryPromise = this.extHostFileSystem.value.createDirectory(this.outputsLocation).then(() => this.outputsLocation);
}
return this.outputDirectoryPromise;
}
private createExtHostOutputChannel(name: string, channelPromise: Promise<ExtHostOutputChannel>): vscode.OutputChannel {
let disposed = false;
const validate = () => {
if (disposed) {
throw new Error('Channel has been closed');
}
};
return {
get name(): string { return name; },
append(value: string): void {
validate();
channelPromise.then(channel => channel.append(value));
},
appendLine(value: string): void {
validate();
channelPromise.then(channel => channel.appendLine(value));
},
clear(): void {
validate();
channelPromise.then(channel => channel.clear());
},
replace(value: string): void {
validate();
channelPromise.then(channel => channel.replace(value));
},
show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void {
validate();
channelPromise.then(channel => channel.show(columnOrPreserveFocus, preserveFocus));
},
hide(): void {
validate();
channelPromise.then(channel => channel.hide());
},
dispose(): void {
disposed = true;
channelPromise.then(channel => channel.dispose());
}
};
}
}
export interface IExtHostOutputService extends ExtHostOutputService { }

View File

@@ -9,29 +9,30 @@ 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, QuickPickItemButtonEvent, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
import { ExtHostQuickOpenShape, IMainContext, MainContext, TransferQuickPickItems, TransferQuickInput, TransferQuickInputButton } from './extHost.protocol';
import type { InputBox, InputBoxOptions, QuickInput, QuickInputButton, QuickPick, QuickPickItem, QuickPickItemButtonEvent, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
import { ExtHostQuickOpenShape, IMainContext, MainContext, TransferQuickInput, TransferQuickInputButton, TransferQuickPickItemOrSeparator } from './extHost.protocol';
import { URI } from 'vs/base/common/uri';
import { ThemeIcon, QuickInputButtons } from 'vs/workbench/api/common/extHostTypes';
import { ThemeIcon, QuickInputButtons, QuickPickItemKind } from 'vs/workbench/api/common/extHostTypes';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { ExtensionIdentifier, IExtensionDescription } 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';
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
export type Item = string | QuickPickItem;
export interface ExtHostQuickOpen {
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, enableProposedApi: boolean, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Promise<QuickPickItem[] | undefined>;
showQuickPick(itemsOrItemsPromise: string[] | Promise<string[]>, enableProposedApi: boolean, options?: QuickPickOptions, token?: CancellationToken): Promise<string | undefined>;
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, enableProposedApi: boolean, options?: QuickPickOptions, token?: CancellationToken): Promise<QuickPickItem | undefined>;
showQuickPick(itemsOrItemsPromise: Item[] | Promise<Item[]>, enableProposedApi: boolean, options?: QuickPickOptions, token?: CancellationToken): Promise<Item | Item[] | undefined>;
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Promise<QuickPickItem[] | undefined>;
showQuickPick(itemsOrItemsPromise: string[] | Promise<string[]>, options?: QuickPickOptions, token?: CancellationToken): Promise<string | undefined>;
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, options?: QuickPickOptions, token?: CancellationToken): Promise<QuickPickItem | undefined>;
showQuickPick(itemsOrItemsPromise: Item[] | Promise<Item[]>, options?: QuickPickOptions, token?: CancellationToken): Promise<Item | Item[] | undefined>;
showInput(options?: InputBoxOptions, token?: CancellationToken): Promise<string | undefined>;
showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions, token?: CancellationToken): Promise<WorkspaceFolder | undefined>
createQuickPick<T extends QuickPickItem>(extensionId: ExtensionIdentifier, enableProposedApi: boolean): QuickPick<T>;
createQuickPick<T extends QuickPickItem>(extensionId: IExtensionDescription): QuickPick<T>;
createInputBox(extensionId: ExtensionIdentifier): InputBox;
}
@@ -56,10 +57,10 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
this._commands = commands;
}
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, enableProposedApi: boolean, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Promise<QuickPickItem[] | undefined>;
showQuickPick(itemsOrItemsPromise: string[] | Promise<string[]>, enableProposedApi: boolean, options?: QuickPickOptions, token?: CancellationToken): Promise<string | undefined>;
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, enableProposedApi: boolean, options?: QuickPickOptions, token?: CancellationToken): Promise<QuickPickItem | undefined>;
showQuickPick(itemsOrItemsPromise: Item[] | Promise<Item[]>, enableProposedApi: boolean, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Promise<Item | Item[] | undefined> {
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Promise<QuickPickItem[] | undefined>;
showQuickPick(itemsOrItemsPromise: string[] | Promise<string[]>, options?: QuickPickOptions, token?: CancellationToken): Promise<string | undefined>;
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, options?: QuickPickOptions, token?: CancellationToken): Promise<QuickPickItem | undefined>;
showQuickPick(itemsOrItemsPromise: Item[] | Promise<Item[]>, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Promise<Item | Item[] | undefined> {
// clear state from last invocation
this._onDidSelectItem = undefined;
@@ -87,33 +88,23 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
return itemsPromise.then(items => {
const pickItems: TransferQuickPickItems[] = [];
const pickItems: TransferQuickPickItemOrSeparator[] = [];
for (let handle = 0; handle < items.length; handle++) {
const item = items[handle];
let label: string;
let description: string | undefined;
let detail: string | undefined;
let picked: boolean | undefined;
let alwaysShow: boolean | undefined;
if (typeof item === 'string') {
label = item;
pickItems.push({ label: item, handle });
} else if (item.kind === QuickPickItemKind.Separator) {
pickItems.push({ type: 'separator', label: item.label });
} else {
label = item.label;
description = item.description;
detail = item.detail;
picked = item.picked;
alwaysShow = item.alwaysShow;
pickItems.push({
label: item.label,
description: item.description,
detail: item.detail,
picked: item.picked,
alwaysShow: item.alwaysShow,
handle
});
}
pickItems.push({
label,
description,
handle,
detail,
picked,
alwaysShow
});
}
// handle selection changes
@@ -192,8 +183,8 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
// ---- QuickInput
createQuickPick<T extends QuickPickItem>(extensionId: ExtensionIdentifier, enableProposedApi: boolean): QuickPick<T> {
const session: ExtHostQuickPick<T> = new ExtHostQuickPick(extensionId, enableProposedApi, () => this._sessions.delete(session._id));
createQuickPick<T extends QuickPickItem>(extension: IExtensionDescription): QuickPick<T> {
const session: ExtHostQuickPick<T> = new ExtHostQuickPick(extension, () => this._sessions.delete(session._id));
this._sessions.set(session._id, session);
return session;
}
@@ -531,8 +522,9 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
private readonly _onDidChangeSelectionEmitter = new Emitter<T[]>();
private readonly _onDidTriggerItemButtonEmitter = new Emitter<QuickPickItemButtonEvent<T>>();
constructor(extensionId: ExtensionIdentifier, private readonly enableProposedApi: boolean, onDispose: () => void) {
super(extensionId, onDispose);
// TODO: revert this change once quickPickSeparators has been finalized.
constructor(private readonly extension: IExtensionDescription, onDispose: () => void) {
super(extension.identifier, onDispose);
this._disposables.push(
this._onDidChangeActiveEmitter,
this._onDidChangeSelectionEmitter,
@@ -546,6 +538,10 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
}
set items(items: T[]) {
if (items.some((item) => item.kind !== undefined)) {
checkProposedApiEnabled(this.extension, 'quickPickSeparators');
}
this._items = items.slice();
this._handlesToItems.clear();
this._itemsToHandles.clear();
@@ -553,25 +549,33 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
this._handlesToItems.set(i, item);
this._itemsToHandles.set(item, i);
});
this.update({
items: items.map((item, i) => ({
label: item.label,
description: item.description,
handle: i,
detail: item.detail,
picked: item.picked,
alwaysShow: item.alwaysShow,
// Proposed API only at the moment
buttons: item.buttons && this.enableProposedApi
? item.buttons.map<TransferQuickInputButton>((button, i) => {
const pickItems: TransferQuickPickItemOrSeparator[] = [];
for (let handle = 0; handle < items.length; handle++) {
const item = items[handle];
if (item.kind === QuickPickItemKind.Separator) {
pickItems.push({ type: 'separator', label: item.label });
} else {
pickItems.push({
handle,
label: item.label,
description: item.description,
detail: item.detail,
picked: item.picked,
alwaysShow: item.alwaysShow,
buttons: item.buttons?.map<TransferQuickInputButton>((button, i) => {
return {
...getIconPathOrClass(button),
tooltip: button.tooltip,
handle: i
};
})
: undefined,
}))
}),
});
}
}
this.update({
items: pickItems,
});
}

View File

@@ -17,11 +17,11 @@ import { ISplice } from 'vs/base/common/sequence';
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';
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
type ProviderHandle = number;
type GroupHandle = number;
@@ -230,13 +230,13 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
private _validateInput: IValidateInput | undefined;
get validateInput(): IValidateInput | undefined {
checkProposedApiEnabled(this._extension);
checkProposedApiEnabled(this._extension, 'scmValidation');
return this._validateInput;
}
set validateInput(fn: IValidateInput | undefined) {
checkProposedApiEnabled(this._extension);
checkProposedApiEnabled(this._extension, 'scmValidation');
if (fn && typeof fn !== 'function') {
throw new Error(`[${this._extension.identifier.value}]: Invalid SCM input box validation function`);
@@ -267,18 +267,8 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
// noop
}
focus(): void {
checkProposedApiEnabled(this._extension);
if (!this._visible) {
this.visible = true;
}
this._proxy.$setInputBoxFocus(this._sourceControlHandle);
}
showValidationMessage(message: string | vscode.MarkdownString, type: vscode.SourceControlInputBoxValidationType) {
checkProposedApiEnabled(this._extension);
checkProposedApiEnabled(this._extension, 'scmValidation');
this._proxy.$showValidationMessage(this._sourceControlHandle, message, type as any);
}
@@ -512,11 +502,11 @@ class ExtHostSourceControl implements vscode.SourceControl {
private _actionButtonDisposables = new MutableDisposable<DisposableStore>();
private _actionButton: vscode.Command | undefined;
get actionButton(): vscode.Command | undefined {
checkProposedApiEnabled(this._extension);
checkProposedApiEnabled(this._extension, 'scmActionButton');
return this._actionButton;
}
set actionButton(actionButton: vscode.Command | undefined) {
checkProposedApiEnabled(this._extension);
checkProposedApiEnabled(this._extension, 'scmActionButton');
this._actionButtonDisposables.value = new DisposableStore();
this._actionButton = actionButton;

View File

@@ -275,15 +275,11 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
}
input(data: string): void {
if (this._pty.handleInput) {
this._pty.handleInput(data);
}
this._pty.handleInput?.(data);
}
resize(cols: number, rows: number): void {
if (this._pty.setDimensions) {
this._pty.setDimensions({ columns: cols, rows });
}
this._pty.setDimensions?.({ columns: cols, rows });
}
async processBinary(data: string): Promise<void> {
@@ -314,28 +310,22 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
startSendingEvents(initialDimensions: ITerminalDimensionsDto | undefined): void {
// Attach the listeners
this._pty.onDidWrite(e => this._onProcessData.fire(e));
if (this._pty.onDidClose) {
this._pty.onDidClose((e: number | void = undefined) => {
this._onProcessExit.fire(e === void 0 ? undefined : e);
});
}
if (this._pty.onDidOverrideDimensions) {
this._pty.onDidOverrideDimensions(e => {
if (e) {
this._onDidChangeProperty.fire({ type: ProcessPropertyType.OverrideDimensions, value: { cols: e.columns, rows: e.rows } });
}
});
}
if (this._pty.onDidChangeName) {
this._pty.onDidChangeName(title => {
this._onDidChangeProperty.fire({ type: ProcessPropertyType.Title, value: title });
});
}
this._pty.onDidClose?.((e: number | void = undefined) => {
this._onProcessExit.fire(e === void 0 ? undefined : e);
});
this._pty.onDidOverrideDimensions?.(e => {
if (e) {
this._onDidChangeProperty.fire({ type: ProcessPropertyType.OverrideDimensions, value: { cols: e.columns, rows: e.rows } });
}
});
this._pty.onDidChangeName?.(title => {
this._onDidChangeProperty.fire({ type: ProcessPropertyType.Title, value: title });
});
this._pty.open(initialDimensions ? initialDimensions : undefined);
if (this._pty.setDimensions && initialDimensions) {
this._pty.setDimensions(initialDimensions);
if (initialDimensions) {
this._pty.setDimensions?.(initialDimensions);
}
this._onProcessReady.fire({ pid: -1, cwd: '', capabilities: this._capabilities });
@@ -586,7 +576,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
protected _setupExtHostProcessListeners(id: number, p: ITerminalChildProcess): IDisposable {
const disposables = new DisposableStore();
disposables.add(p.onProcessReady((e: { pid: number, cwd: string }) => this._proxy.$sendProcessReady(id, e.pid, e.cwd)));
disposables.add(p.onProcessReady(e => this._proxy.$sendProcessReady(id, e.pid, e.cwd)));
disposables.add(p.onDidChangeProperty(property => this._proxy.$sendProcessProperty(id, property)));
// Buffer data events to reduce the amount of messages going to the renderer

View File

@@ -1776,7 +1776,7 @@ export enum TaskPanelKind {
@es5ClassCompat
export class TaskGroup implements vscode.TaskGroup {
isDefault?: boolean;
isDefault: boolean | undefined;
private _id: string;
public static Clean: TaskGroup = new TaskGroup('clean', 'Clean');
@@ -2904,6 +2904,11 @@ export class QuickInputButtons {
private constructor() { }
}
export enum QuickPickItemKind {
Default = 1,
Separator = 2,
}
export enum ExtensionKind {
UI = 1,
Workspace = 2

View File

@@ -176,7 +176,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
this._logService.warn(`${extensionId} created a webview without a content security policy: https://aka.ms/vscode-webview-missing-csp`);
}
public createNewWebview(handle: string, options: extHostProtocol.IWebviewOptions, extension: IExtensionDescription): ExtHostWebview {
public createNewWebview(handle: string, options: extHostProtocol.IWebviewContentOptions, extension: IExtensionDescription): ExtHostWebview {
const webview = new ExtHostWebview(handle, this._webviewProxy, reviveOptions(options), this.initData, this.workspace, extension, this._deprecationService);
this._webviews.set(handle, webview);
@@ -202,7 +202,7 @@ export function serializeWebviewOptions(
extension: IExtensionDescription,
workspace: IExtHostWorkspace | undefined,
options: vscode.WebviewOptions,
): extHostProtocol.IWebviewOptions {
): extHostProtocol.IWebviewContentOptions {
return {
enableCommandUris: options.enableCommandUris,
enableScripts: options.enableScripts,
@@ -212,7 +212,7 @@ export function serializeWebviewOptions(
};
}
export function reviveOptions(options: extHostProtocol.IWebviewOptions): vscode.WebviewOptions {
export function reviveOptions(options: extHostProtocol.IWebviewContentOptions): vscode.WebviewOptions {
return {
enableCommandUris: options.enableCommandUris,
enableScripts: options.enableScripts,

View File

@@ -281,7 +281,7 @@ export class ExtHostWebviewPanels implements extHostProtocol.ExtHostWebviewPanel
initData: {
title: string;
state: any;
webviewOptions: extHostProtocol.IWebviewOptions;
webviewOptions: extHostProtocol.IWebviewContentOptions;
panelOptions: extHostProtocol.IWebviewPanelOptions;
},
position: EditorGroupColumn

View File

@@ -16,14 +16,15 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { Iterable } from 'vs/base/common/iterator';
import { index } from 'vs/base/common/arrays';
import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { ApiProposalName } from 'vs/workbench/services/extensions/common/extensionsApiProposals';
interface IAPIMenu {
readonly key: string;
readonly id: MenuId;
readonly description: string;
readonly proposed?: boolean; // defaults to false
readonly proposed?: ApiProposalName;
readonly supportsSubmenus?: boolean; // defaults to true
readonly deprecationMessage?: string;
}
const apiMenus: IAPIMenu[] = [
@@ -84,17 +85,11 @@ const apiMenus: IAPIMenu[] = [
id: MenuId.DebugToolBar,
description: localize('menus.debugToolBar', "The debug toolbar menu")
},
{
key: 'menuBar/file',
id: MenuId.MenubarFileMenu,
description: localize('menus.file', "The top level file menu"),
proposed: true
},
{
key: 'menuBar/home',
id: MenuId.MenubarHomeMenu,
description: localize('menus.home', "The home indicator context menu (web only)"),
proposed: true,
proposed: 'contribMenuBarHome',
supportsSubmenus: false
},
{
@@ -132,14 +127,6 @@ const apiMenus: IAPIMenu[] = [
id: MenuId.SCMChangeContext,
description: localize('menus.changeTitle', "The Source Control inline change menu")
},
{
key: 'statusBar/windowIndicator',
id: MenuId.StatusBarWindowIndicatorMenu,
description: localize('menus.statusBarWindowIndicator', "The window indicator menu in the status bar"),
proposed: true,
supportsSubmenus: false,
deprecationMessage: localize('menus.statusBarWindowIndicator.deprecated', "Use menu 'statusBar/remoteIndicator' instead."),
},
{
key: 'statusBar/remoteIndicator',
id: MenuId.StatusBarRemoteIndicatorMenu,
@@ -197,19 +184,19 @@ const apiMenus: IAPIMenu[] = [
key: 'notebook/cell/executePrimary',
id: MenuId.NotebookCellExecutePrimary,
description: localize('notebook.cell.executePrimary', "The contributed primary notebook cell execution button"),
proposed: true
proposed: 'notebookEditor'
},
{
key: 'interactive/toolbar',
id: MenuId.InteractiveToolbar,
description: localize('interactive.toolbar', "The contributed interactive toolbar menu"),
proposed: true
proposed: 'notebookEditor'
},
{
key: 'interactive/cell/title',
id: MenuId.InteractiveCellTitle,
description: localize('interactive.cell.title', "The contributed interactive cell title menu"),
proposed: true
proposed: 'notebookEditor'
},
{
key: 'testing/item/context',
@@ -262,7 +249,7 @@ const apiMenus: IAPIMenu[] = [
id: MenuId.InlineCompletionsActions,
description: localize('inlineCompletions.actions', "The actions shown when hovering on an inline completion"),
supportsSubmenus: false,
proposed: true
proposed: 'inlineCompletions'
},
];
@@ -450,8 +437,7 @@ namespace schema {
description: localize('vscode.extension.contributes.menus', "Contributes menu items to the editor"),
type: 'object',
properties: index(apiMenus, menu => menu.key, menu => ({
description: menu.proposed ? `(${localize('proposed', "Proposed API")}) ${menu.description}` : menu.description,
deprecationMessage: menu.deprecationMessage,
markdownDescription: menu.proposed ? localize('proposed', "Proposed API, requires `enabledApiProposal: [\"{0}\"]` - {1}", menu.proposed, menu.description) : menu.description,
type: 'array',
items: menu.supportsSubmenus === false ? menuItem : { oneOf: [menuItem, submenuItem] }
})),
@@ -633,7 +619,7 @@ commandsExtensionPoint.setHandler(extensions => {
title,
source: extension.description.displayName ?? extension.description.name,
shortTitle,
tooltip: extension.description.enableProposedApi ? title : undefined,
tooltip: title,
category,
precondition: ContextKeyExpr.deserialize(enablement),
icon: absoluteIcon
@@ -763,8 +749,8 @@ menusExtensionPoint.setHandler(extensions => {
return;
}
if (menu.proposed && !extension.description.enableProposedApi) {
collector.error(localize('proposedAPI.invalid', "{0} is a proposed menu identifier and is only available when running out of dev or with the following command line switch: --enable-proposed-api {1}", entry.key, extension.description.identifier.value));
if (menu.proposed && !isProposedApiEnabled(extension.description, menu.proposed)) {
collector.error(localize('proposedAPI.invalid', "{0} is a proposed menu identifier. It requires 'package.json#enabledApiProposals: [\"{1}\"]' and is only available when running out of dev or with the following command line switch: --enable-proposed-api {2}", entry.key, menu.proposed, extension.description.identifier.value));
return;
}

View File

@@ -4,24 +4,22 @@
*--------------------------------------------------------------------------------------------*/
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ExtHostOutputService2 } from 'vs/workbench/api/node/extHostOutputService';
import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService';
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService';
import { NativeExtHostSearch } from 'vs/workbench/api/node/extHostSearch';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
import { ExtHostTunnelService } from 'vs/workbench/api/node/extHostTunnelService';
import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService';
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
import { IExtHostOutputService } from 'vs/workbench/api/common/extHostOutput';
import { IExtHostSearch } from 'vs/workbench/api/common/extHostSearch';
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';
import { ExtHostLoggerService } from 'vs/workbench/api/node/extHostLoggerService';
import { ILoggerService } from 'vs/platform/log/common/log';
// #########################################################################
// ### ###
@@ -30,11 +28,10 @@ import { ExtensionStoragePaths } from 'vs/workbench/api/node/extHostStoragePaths
// #########################################################################
registerSingleton(IExtHostExtensionService, ExtHostExtensionService);
registerSingleton(ILogService, ExtHostLogService);
registerSingleton(ILoggerService, ExtHostLoggerService);
registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths);
registerSingleton(IExtHostDebugService, ExtHostDebugService);
registerSingleton(IExtHostOutputService, ExtHostOutputService2);
registerSingleton(IExtHostSearch, NativeExtHostSearch);
registerSingleton(IExtHostTask, ExtHostTask);
registerSingleton(IExtHostTerminalService, ExtHostTerminalService);

View File

@@ -1,25 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILogService, LogService, LogLevel } from 'vs/platform/log/common/log';
import { ExtHostLogServiceShape } from 'vs/workbench/api/common/extHost.protocol';
import { ExtensionHostLogFileName } from 'vs/workbench/services/extensions/common/extensions';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { Schemas } from 'vs/base/common/network';
import { SpdLogLogger } from 'vs/platform/log/node/spdlogLog';
export class ExtHostLogService extends LogService implements ILogService, ExtHostLogServiceShape {
constructor(
@IExtHostInitDataService initData: IExtHostInitDataService,
) {
if (initData.logFile.scheme !== Schemas.file) { throw new Error('Only file-logging supported'); }
super(new SpdLogLogger(ExtensionHostLogFileName, initData.logFile.fsPath, true, initData.logLevel));
}
$setLevel(level: LogLevel): void {
this.setLevel(level);
}
}

View File

@@ -0,0 +1,22 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILogger, ILoggerOptions, LogLevel } from 'vs/platform/log/common/log';
import { URI } from 'vs/base/common/uri';
import { ExtHostLoggerService as BaseExtHostLoggerService } from 'vs/workbench/api/common/extHostLoggerService';
import { Schemas } from 'vs/base/common/network';
import { SpdLogLogger } from 'vs/platform/log/node/spdlogLog';
import { generateUuid } from 'vs/base/common/uuid';
export class ExtHostLoggerService extends BaseExtHostLoggerService {
protected override doCreateLogger(resource: URI, logLevel: LogLevel, options?: ILoggerOptions): ILogger {
if (resource.scheme === Schemas.file) {
return new SpdLogLogger(options?.name || generateUuid(), resource.fsPath, !options?.donotRotate, !!options?.donotUseFormatters, logLevel);
}
return super.doCreateLogger(resource, logLevel, options);
}
}

View File

@@ -1,137 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { MainThreadOutputServiceShape } from '../common/extHost.protocol';
import type * as vscode from 'vscode';
import { URI } from 'vs/base/common/uri';
import { join } from 'vs/base/common/path';
import { toLocalISOString } from 'vs/base/common/date';
import { Promises, SymlinkSupport } from 'vs/base/node/pfs';
import { AbstractExtHostOutputChannel, ExtHostPushOutputChannel, ExtHostOutputService, LazyOutputChannel } from 'vs/workbench/api/common/extHostOutput';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
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 {
static async create(name: string, file: string): Promise<OutputAppender> {
const appender = await createRotatingLogger(name, file, 30 * ByteSize.MB, 1);
appender.clearFormatters();
return new OutputAppender(name, file, appender);
}
private constructor(readonly name: string, readonly file: string, private readonly appender: Logger) { }
append(content: string): void {
this.appender.critical(content);
}
flush(): void {
this.appender.flush();
}
}
class ExtHostOutputChannelBackedByFile extends AbstractExtHostOutputChannel {
private _appender: OutputAppender;
constructor(name: string, appender: OutputAppender, extension: IExtensionDescription, proxy: MainThreadOutputServiceShape) {
super(name, false, URI.file(appender.file), extension, proxy);
this._appender = appender;
}
override append(value: string): void {
super.append(value);
this._appender.append(value);
if (this.visible) {
this.update();
}
}
override replaceAll(value: string): void {
super.replaceAll(value, true);
this._appender.append(value);
if (this.visible) {
this._appender.flush();
}
}
override show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void {
this._appender.flush();
super.show(columnOrPreserveFocus, preserveFocus);
}
override clear(): void {
this._appender.flush();
super.clear();
}
private update(): void {
this._appender.flush();
this._id.then(id => this._proxy.$update(id));
}
}
export class ExtHostOutputService2 extends ExtHostOutputService {
private _logsLocation: URI;
private _namePool: number = 1;
private readonly _channels: Map<string, AbstractExtHostOutputChannel> = new Map<string, AbstractExtHostOutputChannel>();
private visibleChannelId: string | null = null;
constructor(
@IExtHostRpcService extHostRpc: IExtHostRpcService,
@ILogService private readonly logService: ILogService,
@IExtHostInitDataService initData: IExtHostInitDataService,
) {
super(extHostRpc);
this._logsLocation = initData.logsLocation;
}
override $setVisibleChannel(visibleChannelId: string | null): void {
this.visibleChannelId = visibleChannelId;
for (const [id, channel] of this._channels) {
channel.visible = id === this.visibleChannelId;
}
}
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, extension);
extHostOutputChannel.then(channel => channel._id.then(id => {
this._channels.set(id, channel);
channel.visible = id === this.visibleChannelId;
}));
return new LazyOutputChannel(name, extHostOutputChannel);
}
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);
if (!exists) {
await Promises.mkdir(outputDirPath, { recursive: true });
}
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, extension, this._proxy);
} catch (error) {
// Do not crash if logger cannot be created
this.logService.error(error);
return new ExtHostPushOutputChannel(name, extension, this._proxy);
}
}
}

View File

@@ -4,11 +4,9 @@
*--------------------------------------------------------------------------------------------*/
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,5 +15,4 @@ import { ExtHostLogService } from 'vs/workbench/api/worker/extHostLogService';
// #########################################################################
registerSingleton(IExtHostExtensionService, ExtHostExtensionService);
registerSingleton(ILogService, ExtHostLogService);
registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths);

View File

@@ -1,70 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILogService, LogLevel, AbstractLogger } from 'vs/platform/log/common/log';
import { ExtHostLogServiceShape, MainThreadLogShape, MainContext } from 'vs/workbench/api/common/extHost.protocol';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { UriComponents } from 'vs/base/common/uri';
export class ExtHostLogService extends AbstractLogger implements ILogService, ExtHostLogServiceShape {
declare readonly _serviceBrand: undefined;
private readonly _proxy: MainThreadLogShape;
private readonly _logFile: UriComponents;
constructor(
@IExtHostRpcService rpc: IExtHostRpcService,
@IExtHostInitDataService initData: IExtHostInitDataService,
) {
super();
this._proxy = rpc.getProxy(MainContext.MainThreadLog);
this._logFile = initData.logFile.toJSON();
this.setLevel(initData.logLevel);
}
$setLevel(level: LogLevel): void {
this.setLevel(level);
}
trace(_message: string, ..._args: any[]): void {
if (this.getLevel() <= LogLevel.Trace) {
this._proxy.$log(this._logFile, LogLevel.Trace, Array.from(arguments));
}
}
debug(_message: string, ..._args: any[]): void {
if (this.getLevel() <= LogLevel.Debug) {
this._proxy.$log(this._logFile, LogLevel.Debug, Array.from(arguments));
}
}
info(_message: string, ..._args: any[]): void {
if (this.getLevel() <= LogLevel.Info) {
this._proxy.$log(this._logFile, LogLevel.Info, Array.from(arguments));
}
}
warn(_message: string, ..._args: any[]): void {
if (this.getLevel() <= LogLevel.Warning) {
this._proxy.$log(this._logFile, LogLevel.Warning, Array.from(arguments));
}
}
error(_message: string | Error, ..._args: any[]): void {
if (this.getLevel() <= LogLevel.Error) {
this._proxy.$log(this._logFile, LogLevel.Error, Array.from(arguments));
}
}
critical(_message: string | Error, ..._args: any[]): void {
if (this.getLevel() <= LogLevel.Critical) {
this._proxy.$log(this._logFile, LogLevel.Critical, Array.from(arguments));
}
}
flush(): void { }
}