mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-26 17:23:15 -05:00
Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)
* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 * disable strict null check
This commit is contained in:
@@ -10,10 +10,10 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto, IShellDefinitionDto, IShellAndArgsDto, ITerminalDimensionsDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { EXT_HOST_CREATION_DELAY, IShellLaunchConfig, ITerminalEnvironment } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { EXT_HOST_CREATION_DELAY, IShellLaunchConfig, ITerminalEnvironment, ITerminalChildProcess, ITerminalDimensions } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
@@ -21,7 +21,9 @@ import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
// {{SQL CARBON EDIT}}
|
||||
// import { ExtHostVariableResolverService } from 'vs/workbench/api/node/extHostDebugService';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal';
|
||||
import { getSystemShell, detectAvailableShells } from 'vs/workbench/contrib/terminal/node/terminal';
|
||||
import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/terminalEnvironment';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
const RENDERER_NO_PROCESS_ID = -1;
|
||||
|
||||
@@ -115,9 +117,17 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
|
||||
cwd?: string | URI,
|
||||
env?: { [key: string]: string | null },
|
||||
waitOnExit?: boolean,
|
||||
strictEnv?: boolean
|
||||
strictEnv?: boolean,
|
||||
hideFromUser?: boolean
|
||||
): void {
|
||||
this._proxy.$createTerminal(this._name, shellPath, shellArgs, cwd, env, waitOnExit, strictEnv).then(terminal => {
|
||||
this._proxy.$createTerminal({ name: this._name, shellPath, shellArgs, cwd, env, waitOnExit, strictEnv, hideFromUser }).then(terminal => {
|
||||
this._name = terminal.name;
|
||||
this._runQueuedRequests(terminal.id);
|
||||
});
|
||||
}
|
||||
|
||||
public createVirtualProcess(): Promise<void> {
|
||||
return this._proxy.$createTerminal({ name: this._name, isVirtualProcess: true }).then(terminal => {
|
||||
this._name = terminal.name;
|
||||
this._runQueuedRequests(terminal.id);
|
||||
});
|
||||
@@ -176,7 +186,7 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
|
||||
this._pidPromiseComplete(processId);
|
||||
this._pidPromiseComplete = null;
|
||||
} else {
|
||||
// Recreate the promise if this is the nth processId set (eg. reused task terminals)
|
||||
// Recreate the promise if this is the nth processId set (e.g. reused task terminals)
|
||||
this._pidPromise.then(pid => {
|
||||
if (pid !== processId) {
|
||||
this._pidPromise = Promise.resolve(processId);
|
||||
@@ -274,10 +284,13 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
private _proxy: MainThreadTerminalServiceShape;
|
||||
private _activeTerminal: ExtHostTerminal | undefined;
|
||||
private _terminals: ExtHostTerminal[] = [];
|
||||
private _terminalProcesses: { [id: number]: TerminalProcess } = {};
|
||||
private _terminalProcesses: { [id: number]: ITerminalChildProcess } = {};
|
||||
private _terminalRenderers: ExtHostTerminalRenderer[] = [];
|
||||
private _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal> } = {};
|
||||
|
||||
// TODO: Pull this from main side
|
||||
private _isWorkspaceShellAllowed: boolean = false;
|
||||
|
||||
public get activeTerminal(): ExtHostTerminal | undefined { return this._activeTerminal; }
|
||||
public get terminals(): ExtHostTerminal[] { return this._terminals; }
|
||||
|
||||
@@ -309,11 +322,28 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
|
||||
public createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal {
|
||||
const terminal = new ExtHostTerminal(this._proxy, options.name);
|
||||
terminal.create(options.shellPath, options.shellArgs, options.cwd, options.env, /*options.waitOnExit*/ undefined, options.strictEnv);
|
||||
terminal.create(options.shellPath, options.shellArgs, options.cwd, options.env, /*options.waitOnExit*/ undefined, options.strictEnv, options.hideFromUser);
|
||||
this._terminals.push(terminal);
|
||||
return terminal;
|
||||
}
|
||||
|
||||
public createVirtualProcessTerminal(options: vscode.TerminalVirtualProcessOptions): vscode.Terminal {
|
||||
const terminal = new ExtHostTerminal(this._proxy, options.name);
|
||||
const p = new ExtHostVirtualProcess(options.virtualProcess);
|
||||
terminal.createVirtualProcess().then(() => this._setupExtHostProcessListeners(terminal._id, p));
|
||||
this._terminals.push(terminal);
|
||||
return terminal;
|
||||
}
|
||||
|
||||
public attachVirtualProcessToTerminal(id: number, virtualProcess: vscode.TerminalVirtualProcess) {
|
||||
const terminal = this._getTerminalById(id);
|
||||
if (!terminal) {
|
||||
throw new Error(`Cannot resolve terminal with id ${id} for virtual process`);
|
||||
}
|
||||
const p = new ExtHostVirtualProcess(virtualProcess);
|
||||
this._setupExtHostProcessListeners(id, p);
|
||||
}
|
||||
|
||||
public createTerminalRenderer(name: string): vscode.TerminalRenderer {
|
||||
const terminal = new ExtHostTerminal(this._proxy, name);
|
||||
terminal._setProcessId(undefined);
|
||||
@@ -325,6 +355,32 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
return renderer;
|
||||
}
|
||||
|
||||
public getDefaultShell(configProvider: ExtHostConfigProvider): string {
|
||||
const fetchSetting = (key: string) => {
|
||||
const setting = configProvider
|
||||
.getConfiguration(key.substr(0, key.lastIndexOf('.')))
|
||||
.inspect<string | string[]>(key.substr(key.lastIndexOf('.') + 1));
|
||||
return this._apiInspectConfigToPlain<string | string[]>(setting);
|
||||
};
|
||||
return terminalEnvironment.getDefaultShell(
|
||||
fetchSetting,
|
||||
this._isWorkspaceShellAllowed,
|
||||
getSystemShell(platform.platform),
|
||||
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
|
||||
process.env.windir
|
||||
);
|
||||
}
|
||||
|
||||
private _getDefaultShellArgs(configProvider: ExtHostConfigProvider): string[] | string | undefined {
|
||||
const fetchSetting = (key: string) => {
|
||||
const setting = configProvider
|
||||
.getConfiguration(key.substr(0, key.lastIndexOf('.')))
|
||||
.inspect<string | string[]>(key.substr(key.lastIndexOf('.') + 1));
|
||||
return this._apiInspectConfigToPlain<string | string[]>(setting);
|
||||
};
|
||||
return terminalEnvironment.getDefaultShellArgs(fetchSetting, this._isWorkspaceShellAllowed);
|
||||
}
|
||||
|
||||
public async resolveTerminalRenderer(id: number): Promise<vscode.TerminalRenderer> {
|
||||
// Check to see if the extension host already knows about this terminal.
|
||||
for (const terminalRenderer of this._terminalRenderers) {
|
||||
@@ -352,7 +408,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
}
|
||||
return;
|
||||
}
|
||||
this._performTerminalIdAction(id, terminal => {
|
||||
this.performTerminalIdAction(id, terminal => {
|
||||
if (terminal) {
|
||||
this._activeTerminal = terminal;
|
||||
if (original !== this._activeTerminal) {
|
||||
@@ -380,14 +436,26 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
});
|
||||
}
|
||||
}
|
||||
// When a terminal's dimensions change, a renderer's _maximum_ dimensions change
|
||||
const renderer = this._getTerminalRendererById(id);
|
||||
if (renderer) {
|
||||
renderer._setMaximumDimensions(cols, rows);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public $acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): void {
|
||||
if (this._terminalProcesses[id]) {
|
||||
// Virtual processes only - when virtual process resize fires it means that the
|
||||
// terminal's maximum dimensions changed
|
||||
this._terminalProcesses[id].resize(cols, rows);
|
||||
} else {
|
||||
// Terminal renderer
|
||||
this._getTerminalByIdEventually(id).then(() => {
|
||||
// When a terminal's dimensions change, a renderer's _maximum_ dimensions change
|
||||
const renderer = this._getTerminalRendererById(id);
|
||||
if (renderer) {
|
||||
renderer._setMaximumDimensions(cols, rows);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public $acceptTerminalRendererInput(id: number, data: string): void {
|
||||
const renderer = this._getTerminalRendererById(id);
|
||||
if (renderer) {
|
||||
@@ -425,10 +493,10 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
}
|
||||
|
||||
public $acceptTerminalProcessId(id: number, processId: number): void {
|
||||
this._performTerminalIdAction(id, terminal => terminal._setProcessId(processId));
|
||||
this.performTerminalIdAction(id, terminal => terminal._setProcessId(processId));
|
||||
}
|
||||
|
||||
private _performTerminalIdAction(id: number, callback: (terminal: ExtHostTerminal) => void): void {
|
||||
public performTerminalIdAction(id: number, callback: (terminal: ExtHostTerminal) => void): void {
|
||||
let terminal = this._getTerminalById(id);
|
||||
if (terminal) {
|
||||
callback(terminal);
|
||||
@@ -439,7 +507,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
if (terminal) {
|
||||
callback(terminal);
|
||||
}
|
||||
}, EXT_HOST_CREATION_DELAY);
|
||||
}, EXT_HOST_CREATION_DELAY * 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,6 +521,12 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
};
|
||||
}
|
||||
|
||||
private async _getNonInheritedEnv(): Promise<platform.IProcessEnvironment> {
|
||||
const env = await getMainProcessParentEnv();
|
||||
env.VSCODE_IPC_HOOK_CLI = process.env['VSCODE_IPC_HOOK_CLI']!;
|
||||
return env;
|
||||
}
|
||||
|
||||
public async $createProcess(id: number, shellLaunchConfigDto: ShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void> {
|
||||
const shellLaunchConfig: IShellLaunchConfig = {
|
||||
name: shellLaunchConfigDto.name,
|
||||
@@ -466,13 +540,8 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux');
|
||||
const configProvider = await this._extHostConfiguration.getConfigProvider();
|
||||
if (!shellLaunchConfig.executable) {
|
||||
const fetchSetting = (key: string) => {
|
||||
const setting = configProvider
|
||||
.getConfiguration(key.substr(0, key.lastIndexOf('.')))
|
||||
.inspect<string | string[]>(key.substr(key.lastIndexOf('.') + 1));
|
||||
return this._apiInspectConfigToPlain<string | string[]>(setting);
|
||||
};
|
||||
terminalEnvironment.mergeDefaultShellPathAndArgs(shellLaunchConfig, fetchSetting, isWorkspaceShellAllowed || false, getDefaultShell(platform.platform));
|
||||
shellLaunchConfig.executable = this.getDefaultShell(configProvider);
|
||||
shellLaunchConfig.args = this._getDefaultShellArgs(configProvider);
|
||||
}
|
||||
|
||||
// Get the initial cwd
|
||||
@@ -495,6 +564,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
// {{SQL CARBON EDIT}}
|
||||
// const variableResolver = workspaceFolders ? new ExtHostVariableResolverService(workspaceFolders, this._extHostDocumentsAndEditors, configProvider) : undefined;
|
||||
const variableResolver = undefined;
|
||||
const baseEnv = terminalConfig.get<boolean>('inheritEnv', true) ? process.env as platform.IProcessEnvironment : await this._getNonInheritedEnv();
|
||||
const env = terminalEnvironment.createTerminalEnvironment(
|
||||
shellLaunchConfig,
|
||||
lastActiveWorkspace,
|
||||
@@ -502,16 +572,30 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
variableResolver,
|
||||
isWorkspaceShellAllowed,
|
||||
pkg.version,
|
||||
terminalConfig.get<boolean>('setLocaleVariables', false)
|
||||
terminalConfig.get<boolean>('setLocaleVariables', false),
|
||||
baseEnv
|
||||
);
|
||||
|
||||
// Fork the process and listen for messages
|
||||
this._logService.debug(`Terminal process launching on ext host`, shellLaunchConfig, initialCwd, cols, rows, env);
|
||||
const p = new TerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, terminalConfig.get('windowsEnableConpty') as boolean, this._logService);
|
||||
p.onProcessIdReady(pid => this._proxy.$sendProcessPid(id, pid));
|
||||
// TODO: Support conpty on remote, it doesn't seem to work for some reason?
|
||||
// TODO: When conpty is enabled, only enable it when accessibilityMode is off
|
||||
const enableConpty = false; //terminalConfig.get('windowsEnableConpty') as boolean;
|
||||
this._setupExtHostProcessListeners(id, new TerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, enableConpty, this._logService));
|
||||
}
|
||||
|
||||
public $startVirtualProcess(id: number, initialDimensions: ITerminalDimensionsDto | undefined): void {
|
||||
(this._terminalProcesses[id] as ExtHostVirtualProcess).startSendingEvents(initialDimensions);
|
||||
}
|
||||
|
||||
private _setupExtHostProcessListeners(id: number, p: ITerminalChildProcess): void {
|
||||
p.onProcessReady((e: { pid: number, cwd: string }) => this._proxy.$sendProcessReady(id, e.pid, e.cwd));
|
||||
p.onProcessTitleChanged(title => this._proxy.$sendProcessTitle(id, title));
|
||||
p.onProcessData(data => this._proxy.$sendProcessData(id, data));
|
||||
p.onProcessExit(exitCode => this._onProcessExit(id, exitCode));
|
||||
if (p.onProcessOverrideDimensions) {
|
||||
p.onProcessOverrideDimensions(e => this._proxy.$sendOverrideDimensions(id, e));
|
||||
}
|
||||
this._terminalProcesses[id] = p;
|
||||
}
|
||||
|
||||
@@ -546,10 +630,19 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
return id;
|
||||
}
|
||||
|
||||
private _onProcessExit(id: number, exitCode: number): void {
|
||||
// Remove listeners
|
||||
this._terminalProcesses[id].dispose();
|
||||
public $requestAvailableShells(): Promise<IShellDefinitionDto[]> {
|
||||
return detectAvailableShells();
|
||||
}
|
||||
|
||||
public async $requestDefaultShellAndArgs(): Promise<IShellAndArgsDto> {
|
||||
const configProvider = await this._extHostConfiguration.getConfigProvider();
|
||||
return Promise.resolve({
|
||||
shell: this.getDefaultShell(configProvider),
|
||||
args: this._getDefaultShellArgs(configProvider)
|
||||
});
|
||||
}
|
||||
|
||||
private _onProcessExit(id: number, exitCode: number): void {
|
||||
// Remove process reference
|
||||
delete this._terminalProcesses[id];
|
||||
|
||||
@@ -611,6 +704,10 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
});
|
||||
return index;
|
||||
}
|
||||
|
||||
public $acceptWorkspacePermissionsChanged(isAllowed: boolean): void {
|
||||
this._isWorkspaceShellAllowed = isAllowed;
|
||||
}
|
||||
}
|
||||
|
||||
class ApiRequest {
|
||||
@@ -626,3 +723,90 @@ class ApiRequest {
|
||||
this._callback.apply(proxy, [id].concat(this._args));
|
||||
}
|
||||
}
|
||||
|
||||
class ExtHostVirtualProcess implements ITerminalChildProcess {
|
||||
private _queuedEvents: (IQueuedEvent<string> | IQueuedEvent<number> | IQueuedEvent<{ pid: number, cwd: string }> | IQueuedEvent<ITerminalDimensions | undefined>)[] = [];
|
||||
private _queueDisposables: IDisposable[] | undefined;
|
||||
|
||||
private readonly _onProcessData = new Emitter<string>();
|
||||
public readonly onProcessData: Event<string> = this._onProcessData.event;
|
||||
private readonly _onProcessExit = new Emitter<number>();
|
||||
public readonly onProcessExit: Event<number> = this._onProcessExit.event;
|
||||
private readonly _onProcessReady = new Emitter<{ pid: number, cwd: string }>();
|
||||
public get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; }
|
||||
private readonly _onProcessTitleChanged = new Emitter<string>();
|
||||
public readonly onProcessTitleChanged: Event<string> = this._onProcessTitleChanged.event;
|
||||
private readonly _onProcessOverrideDimensions = new Emitter<ITerminalDimensions | undefined>();
|
||||
public get onProcessOverrideDimensions(): Event<ITerminalDimensions | undefined> { return this._onProcessOverrideDimensions.event; }
|
||||
|
||||
constructor(
|
||||
private readonly _virtualProcess: vscode.TerminalVirtualProcess
|
||||
) {
|
||||
this._queueDisposables = [];
|
||||
this._queueDisposables.push(this._virtualProcess.onDidWrite(e => this._queuedEvents.push({ emitter: this._onProcessData, data: e })));
|
||||
if (this._virtualProcess.onDidExit) {
|
||||
this._queueDisposables.push(this._virtualProcess.onDidExit(e => this._queuedEvents.push({ emitter: this._onProcessExit, data: e })));
|
||||
}
|
||||
if (this._virtualProcess.onDidOverrideDimensions) {
|
||||
this._queueDisposables.push(this._virtualProcess.onDidOverrideDimensions(e => this._queuedEvents.push({ emitter: this._onProcessOverrideDimensions, data: e ? { cols: e.columns, rows: e.rows } : undefined })));
|
||||
}
|
||||
}
|
||||
|
||||
shutdown(): void {
|
||||
if (this._virtualProcess.shutdown) {
|
||||
this._virtualProcess.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
input(data: string): void {
|
||||
if (this._virtualProcess.handleInput) {
|
||||
this._virtualProcess.handleInput(data);
|
||||
}
|
||||
}
|
||||
|
||||
resize(cols: number, rows: number): void {
|
||||
if (this._virtualProcess.setDimensions) {
|
||||
this._virtualProcess.setDimensions({ columns: cols, rows });
|
||||
}
|
||||
}
|
||||
|
||||
getInitialCwd(): Promise<string> {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
|
||||
getCwd(): Promise<string> {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
|
||||
getLatency(): Promise<number> {
|
||||
return Promise.resolve(0);
|
||||
}
|
||||
|
||||
startSendingEvents(initialDimensions: ITerminalDimensionsDto | undefined): void {
|
||||
// Flush all buffered events
|
||||
this._queuedEvents.forEach(e => (<any>e.emitter.fire)(e.data));
|
||||
this._queuedEvents = [];
|
||||
this._queueDisposables = undefined;
|
||||
|
||||
// Attach the real listeners
|
||||
this._virtualProcess.onDidWrite(e => this._onProcessData.fire(e));
|
||||
if (this._virtualProcess.onDidExit) {
|
||||
this._virtualProcess.onDidExit(e => {
|
||||
// Ensure only positive exit codes are returned
|
||||
this._onProcessExit.fire(e >= 0 ? e : 1);
|
||||
});
|
||||
}
|
||||
if (this._virtualProcess.onDidOverrideDimensions) {
|
||||
this._virtualProcess.onDidOverrideDimensions(e => this._onProcessOverrideDimensions.fire(e ? { cols: e.columns, rows: e.rows } : undefined)); // {{SQL CARBON EDIT}} strict-null-check
|
||||
}
|
||||
|
||||
if (this._virtualProcess.start) {
|
||||
this._virtualProcess.start(initialDimensions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface IQueuedEvent<T> {
|
||||
emitter: Emitter<T>;
|
||||
data: T;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user