Merge branch 'master' into joh/cell-output

This commit is contained in:
Johannes Rieken
2020-09-25 17:44:13 +02:00
59 changed files with 332 additions and 220 deletions

View File

@@ -605,7 +605,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
registerCustomEditorProvider: (viewType: string, provider: vscode.CustomTextEditorProvider | vscode.CustomReadonlyEditorProvider, options: { webviewOptions?: vscode.WebviewPanelOptions, supportsMultipleEditorsPerDocument?: boolean } = {}) => {
return extHostCustomEditors.registerCustomEditorProvider(extension, viewType, provider, options);
},
registerDecorationProvider(provider: vscode.DecorationProvider) {
registerDecorationProvider(provider: vscode.FileDecorationProvider) {
checkProposedApiEnabled(extension);
return extHostDecorations.registerDecorationProvider(provider, extension.identifier);
},
@@ -1138,7 +1138,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
CallHierarchyItem: extHostTypes.CallHierarchyItem,
DebugConsoleMode: extHostTypes.DebugConsoleMode,
DebugConfigurationProviderTriggerKind: extHostTypes.DebugConfigurationProviderTriggerKind,
Decoration: extHostTypes.Decoration,
FileDecoration: extHostTypes.FileDecoration,
UIKind: UIKind,
ColorThemeKind: extHostTypes.ColorThemeKind,
TimelineItem: extHostTypes.TimelineItem,

View File

@@ -830,7 +830,7 @@ export interface MainThreadTaskShape extends IDisposable {
export interface MainThreadExtensionServiceShape extends IDisposable {
$activateExtension(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void>;
$onWillActivateExtension(extensionId: ExtensionIdentifier): void;
$onWillActivateExtension(extensionId: ExtensionIdentifier): Promise<void>;
$onDidActivateExtension(extensionId: ExtensionIdentifier, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationReason: ExtensionActivationReason): void;
$onExtensionActivationError(extensionId: ExtensionIdentifier, error: ExtensionActivationError): Promise<void>;
$onExtensionRuntimeError(extensionId: ExtensionIdentifier, error: SerializedError): void;
@@ -1605,7 +1605,7 @@ export interface DecorationRequest {
readonly uri: UriComponents;
}
export type DecorationData = [number, boolean, string, string, ThemeColor];
export type DecorationData = [boolean, string, string, ThemeColor];
export type DecorationReply = { [id: number]: DecorationData; };
export interface ExtHostDecorationsShape {

View File

@@ -6,7 +6,7 @@
import type * as vscode from 'vscode';
import { URI } from 'vs/base/common/uri';
import { MainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, DecorationData, DecorationRequest, DecorationReply } from 'vs/workbench/api/common/extHost.protocol';
import { Disposable, Decoration } from 'vs/workbench/api/common/extHostTypes';
import { Disposable, FileDecoration } from 'vs/workbench/api/common/extHostTypes';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
@@ -15,7 +15,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { asArray } from 'vs/base/common/arrays';
interface ProviderData {
provider: vscode.DecorationProvider;
provider: vscode.FileDecorationProvider;
extensionId: ExtensionIdentifier;
}
@@ -34,12 +34,12 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
this._proxy = extHostRpc.getProxy(MainContext.MainThreadDecorations);
}
registerDecorationProvider(provider: vscode.DecorationProvider, extensionId: ExtensionIdentifier): vscode.Disposable {
registerDecorationProvider(provider: vscode.FileDecorationProvider, extensionId: ExtensionIdentifier): vscode.Disposable {
const handle = ExtHostDecorations._handlePool++;
this._provider.set(handle, { provider, extensionId });
this._proxy.$registerDecorationProvider(handle, extensionId.value);
const listener = provider.onDidChangeDecorations(e => {
const listener = provider.onDidChange(e => {
this._proxy.$onDidChange(handle, !e || (Array.isArray(e) && e.length > 250)
? null
: asArray(e));
@@ -65,13 +65,13 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
await Promise.all(requests.map(async request => {
try {
const { uri, id } = request;
const data = await Promise.resolve(provider.provideDecoration(URI.revive(uri), token));
const data = await Promise.resolve(provider.provideFileDecoration(URI.revive(uri), token));
if (!data) {
return;
}
try {
Decoration.validate(data);
result[id] = <DecorationData>[data.priority, data.bubble, data.title, data.letter, data.color];
FileDecoration.validate(data);
result[id] = <DecorationData>[data.propagate, data.tooltip, data.badge, data.color];
} catch (e) {
this._logService.warn(`INVALID decoration from extension '${extensionId.value}': ${e}`);
}

View File

@@ -303,8 +303,15 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
// --- impl
private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> {
this._mainThreadExtensionsProxy.$onWillActivateExtension(extensionDescription.identifier);
private async _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> {
if (!this._initData.remote.isRemote) {
// local extension host process
await this._mainThreadExtensionsProxy.$onWillActivateExtension(extensionDescription.identifier);
} else {
// remote extension host process
// do not wait for renderer confirmation
this._mainThreadExtensionsProxy.$onWillActivateExtension(extensionDescription.identifier);
}
return this._doActivateExtension(extensionDescription, reason).then((activatedExtension) => {
const activationTimes = activatedExtension.activationTimes;
this._mainThreadExtensionsProxy.$onDidActivateExtension(extensionDescription.identifier, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, reason);

View File

@@ -13,7 +13,7 @@ import { ITerminalChildProcess, ITerminalDimensions, EXT_HOST_CREATION_DELAY, IT
import { timeout } from 'vs/base/common/async';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { TerminalDataBufferer } from 'vs/workbench/contrib/terminal/common/terminalDataBuffering';
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
import { Disposable as VSCodeDisposable, EnvironmentVariableMutatorType } from './extHostTypes';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
@@ -22,7 +22,7 @@ import { NotSupportedError } from 'vs/base/common/errors';
import { serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
export interface IExtHostTerminalService extends ExtHostTerminalServiceShape {
export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, IDisposable {
readonly _serviceBrand: undefined;
@@ -306,14 +306,14 @@ interface ICachedLinkEntry {
link: vscode.TerminalLink;
}
export abstract class BaseExtHostTerminalService implements IExtHostTerminalService, ExtHostTerminalServiceShape {
export abstract class BaseExtHostTerminalService extends Disposable implements IExtHostTerminalService, ExtHostTerminalServiceShape {
readonly _serviceBrand: undefined;
protected _proxy: MainThreadTerminalServiceShape;
protected _activeTerminal: ExtHostTerminal | undefined;
protected _terminals: ExtHostTerminal[] = [];
protected _terminalProcesses: { [id: number]: ITerminalChildProcess } = {};
protected _terminalProcesses: Map<number, ITerminalChildProcess> = new Map();
protected _terminalProcessDisposables: { [id: number]: IDisposable } = {};
protected _extensionTerminalAwaitingStart: { [id: number]: { initialDimensions: ITerminalDimensionsDto | undefined } | undefined } = {};
protected _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal | undefined> } = {};
@@ -342,6 +342,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
supportsProcesses: boolean,
@IExtHostRpcService extHostRpc: IExtHostRpcService
) {
super();
this._proxy = extHostRpc.getProxy(MainContext.MainThreadTerminalService);
this._bufferer = new TerminalDataBufferer(this._proxy.$sendProcessData);
this._onDidWriteTerminalData = new Emitter<vscode.TerminalDataWriteEvent>({
@@ -349,6 +350,13 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
onLastListenerRemove: () => this._proxy.$stopSendingDataEvents()
});
this._proxy.$registerProcessSupport(supportsProcesses);
this._register({
dispose: () => {
for (const [_, terminalProcess] of this._terminalProcesses) {
terminalProcess.shutdown(true);
}
}
});
}
public abstract createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal;
@@ -421,11 +429,9 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
public async $acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): Promise<void> {
await this._getTerminalByIdEventually(id);
if (this._terminalProcesses[id]) {
// Extension pty terminal only - when virtual process resize fires it means that the
// terminal's maximum dimensions changed
this._terminalProcesses[id]?.resize(cols, rows);
}
// Extension pty terminal only - when virtual process resize fires it means that the
// terminal's maximum dimensions changed
this._terminalProcesses.get(id)?.resize(cols, rows);
}
public async $acceptTerminalTitleChange(id: number, name: string): Promise<void> {
@@ -497,8 +503,9 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
});
}
if (this._terminalProcesses[id]) {
(this._terminalProcesses[id] as ExtHostPseudoterminal).startSendingEvents(initialDimensions);
const terminalProcess = this._terminalProcesses.get(id);
if (terminalProcess) {
(terminalProcess as ExtHostPseudoterminal).startSendingEvents(initialDimensions);
} else {
// Defer startSendingEvents call to when _setupExtHostProcessListeners is called
this._extensionTerminalAwaitingStart[id] = { initialDimensions };
@@ -520,7 +527,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
if (p.onProcessOverrideDimensions) {
disposables.add(p.onProcessOverrideDimensions(e => this._proxy.$sendOverrideDimensions(id, e)));
}
this._terminalProcesses[id] = p;
this._terminalProcesses.set(id, p);
const awaitingStart = this._extensionTerminalAwaitingStart[id];
if (awaitingStart && p instanceof ExtHostPseudoterminal) {
@@ -532,12 +539,12 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
}
public $acceptProcessInput(id: number, data: string): void {
this._terminalProcesses[id]?.input(data);
this._terminalProcesses.get(id)?.input(data);
}
public $acceptProcessResize(id: number, cols: number, rows: number): void {
try {
this._terminalProcesses[id]?.resize(cols, rows);
this._terminalProcesses.get(id)?.resize(cols, rows);
} catch (error) {
// We tried to write to a closed pipe / channel.
if (error.code !== 'EPIPE' && error.code !== 'ERR_IPC_CHANNEL_CLOSED') {
@@ -547,15 +554,15 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
}
public $acceptProcessShutdown(id: number, immediate: boolean): void {
this._terminalProcesses[id]?.shutdown(immediate);
this._terminalProcesses.get(id)?.shutdown(immediate);
}
public $acceptProcessRequestInitialCwd(id: number): void {
this._terminalProcesses[id]?.getInitialCwd().then(initialCwd => this._proxy.$sendProcessInitialCwd(id, initialCwd));
this._terminalProcesses.get(id)?.getInitialCwd().then(initialCwd => this._proxy.$sendProcessInitialCwd(id, initialCwd));
}
public $acceptProcessRequestCwd(id: number): void {
this._terminalProcesses[id]?.getCwd().then(cwd => this._proxy.$sendProcessCwd(id, cwd));
this._terminalProcesses.get(id)?.getCwd().then(cwd => this._proxy.$sendProcessCwd(id, cwd));
}
public $acceptProcessRequestLatency(id: number): number {
@@ -648,7 +655,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
this._bufferer.stopBuffering(id);
// Remove process reference
delete this._terminalProcesses[id];
this._terminalProcesses.delete(id);
delete this._extensionTerminalAwaitingStart[id];
// Clean up process disposables

View File

@@ -2729,22 +2729,29 @@ export enum ExtensionKind {
Workspace = 2
}
export class Decoration {
export class FileDecoration {
static validate(d: Decoration): void {
if (d.letter && d.letter.length !== 1) {
static validate(d: FileDecoration): void {
if (d.badge && d.badge.length !== 1) {
throw new Error(`The 'letter'-property must be undefined or a single character`);
}
if (!d.bubble && !d.color && !d.letter && !d.priority && !d.title) {
if (!d.color && !d.badge && !d.tooltip) {
throw new Error(`The decoration is empty`);
}
}
letter?: string;
title?: string;
badge?: string;
tooltip?: string;
color?: vscode.ThemeColor;
priority?: number;
bubble?: boolean;
propagate?: boolean;
constructor(badge?: string, tooltip?: string, color?: ThemeColor) {
this.badge = badge;
this.tooltip = tooltip;
this.color = color;
}
}
//#region Theming