Merge from vscode 2cfc8172e533e50c90e6a3152f6bfb1f82f963f3 (#6516)

* Merge from vscode 2cfc8172e533e50c90e6a3152f6bfb1f82f963f3

* fix tests
This commit is contained in:
Anthony Dresser
2019-07-28 15:15:24 -07:00
committed by GitHub
parent aacf1e7f1c
commit 1d56a17f32
292 changed files with 19784 additions and 1873 deletions

View File

@@ -15,6 +15,7 @@ export class MainThreadCommands implements MainThreadCommandsShape {
private readonly _commandRegistrations = new Map<string, IDisposable>();
private readonly _generateCommandsDocumentationRegistration: IDisposable;
private readonly _proxy: ExtHostCommandsShape;
private _onDidExecuteCommandListener?: IDisposable;
constructor(
extHostContext: IExtHostContext,
@@ -77,6 +78,19 @@ export class MainThreadCommands implements MainThreadCommandsShape {
return this._commandService.executeCommand<T>(id, ...args);
}
$registerCommandListener() {
if (!this._onDidExecuteCommandListener) {
this._onDidExecuteCommandListener = this._commandService.onDidExecuteCommand(command => this._proxy.$handleDidExecuteCommand(command));
}
}
$unregisterCommandListener() {
if (this._onDidExecuteCommandListener) {
this._onDidExecuteCommandListener.dispose();
this._onDidExecuteCommandListener = undefined;
}
}
$getCommands(): Promise<string[]> {
return Promise.resolve([...CommandsRegistry.getCommands().keys()]);
}

View File

@@ -5,7 +5,7 @@
import { DisposableStore } from 'vs/base/common/lifecycle';
import { URI as uri } from 'vs/base/common/uri';
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, ITerminalSettings, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory } from 'vs/workbench/contrib/debug/common/debug';
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory } from 'vs/workbench/contrib/debug/common/debug';
import {
ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext,
IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto
@@ -71,8 +71,8 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
return Promise.resolve(this._proxy.$substituteVariables(folder ? folder.uri : undefined, config));
}
runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Promise<number | undefined> {
return Promise.resolve(this._proxy.$runInTerminal(args, config));
runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments): Promise<number | undefined> {
return Promise.resolve(this._proxy.$runInTerminal(args));
}
// RPC methods (MainThreadDebugServiceShape)

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalProcessExtHostProxy, ITerminalProcessExtHostRequest, ITerminalDimensions, EXT_HOST_CREATION_DELAY, IAvailableShellsRequest, IDefaultShellAndArgsRequest, ITerminalVirtualProcessRequest } from 'vs/workbench/contrib/terminal/common/terminal';
import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalProcessExtHostProxy, ISpawnExtHostProcessRequest, ITerminalDimensions, EXT_HOST_CREATION_DELAY, IAvailableShellsRequest, IDefaultShellAndArgsRequest, IStartExtensionTerminalRequest } from 'vs/workbench/contrib/terminal/common/terminal';
import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, ShellLaunchConfigDto, TerminalLaunchConfig, ITerminalDimensionsDto } from 'vs/workbench/api/common/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { URI } from 'vs/base/common/uri';
@@ -35,8 +35,8 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
// ITerminalService listeners
this._toDispose.add(_terminalService.onInstanceCreated((instance) => {
// Delay this message so the TerminalInstance constructor has a chance to finish and
// return the ID normally to the extension host. The ID that is passed here will be used
// to register non-extension API terminals in the extension host.
// return the ID normally to the extension host. The ID that is passed here will be
// used to register non-extension API terminals in the extension host.
setTimeout(() => {
this._onTerminalOpened(instance);
this._onInstanceDimensionsChanged(instance);
@@ -47,8 +47,8 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._toDispose.add(_terminalService.onInstanceProcessIdReady(instance => this._onTerminalProcessIdReady(instance)));
this._toDispose.add(_terminalService.onInstanceDimensionsChanged(instance => this._onInstanceDimensionsChanged(instance)));
this._toDispose.add(_terminalService.onInstanceMaximumDimensionsChanged(instance => this._onInstanceMaximumDimensionsChanged(instance)));
this._toDispose.add(_terminalService.onInstanceRequestExtHostProcess(request => this._onTerminalRequestExtHostProcess(request)));
this._toDispose.add(_terminalService.onInstanceRequestVirtualProcess(e => this._onTerminalRequestVirtualProcess(e)));
this._toDispose.add(_terminalService.onInstanceRequestSpawnExtHostProcess(request => this._onRequestSpawnExtHostProcess(request)));
this._toDispose.add(_terminalService.onInstanceRequestStartExtensionTerminal(e => this._onRequestStartExtensionTerminal(e)));
this._toDispose.add(_terminalService.onActiveInstanceChanged(instance => this._onActiveTerminalChanged(instance ? instance.id : null)));
this._toDispose.add(_terminalService.onInstanceTitleChanged(instance => this._onTitleChanged(instance.id, instance.title)));
this._toDispose.add(_terminalService.configHelper.onWorkspacePermissionsChanged(isAllowed => this._onWorkspacePermissionsChanged(isAllowed)));
@@ -90,7 +90,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
env: launchConfig.env,
strictEnv: launchConfig.strictEnv,
hideFromUser: launchConfig.hideFromUser,
isVirtualProcess: launchConfig.isVirtualProcess
isExtensionTerminal: launchConfig.isExtensionTerminal
};
const terminal = this._terminalService.createTerminal(shellLaunchConfig);
this._terminalProcesses.set(terminal.id, new Promise<ITerminalProcessExtHostProxy>(r => this._terminalProcessesReady.set(terminal.id, r)));
@@ -240,7 +240,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._proxy.$acceptTerminalMaximumDimensions(instance.id, instance.maxCols, instance.maxRows);
}
private _onTerminalRequestExtHostProcess(request: ITerminalProcessExtHostRequest): void {
private _onRequestSpawnExtHostProcess(request: ISpawnExtHostProcessRequest): void {
// Only allow processes on remote ext hosts
if (!this._remoteAuthority) {
return;
@@ -261,7 +261,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
cwd: request.shellLaunchConfig.cwd,
env: request.shellLaunchConfig.env
};
this._proxy.$createProcess(proxy.terminalId, shellLaunchConfigDto, request.activeWorkspaceRootUri, request.cols, request.rows, request.isWorkspaceShellAllowed);
this._proxy.$spawnExtHostProcess(proxy.terminalId, shellLaunchConfigDto, request.activeWorkspaceRootUri, request.cols, request.rows, request.isWorkspaceShellAllowed);
proxy.onInput(data => this._proxy.$acceptProcessInput(proxy.terminalId, data));
proxy.onResize(dimensions => this._proxy.$acceptProcessResize(proxy.terminalId, dimensions.cols, dimensions.rows));
proxy.onShutdown(immediate => this._proxy.$acceptProcessShutdown(proxy.terminalId, immediate));
@@ -270,7 +270,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
proxy.onRequestLatency(() => this._onRequestLatency(proxy.terminalId));
}
private _onTerminalRequestVirtualProcess(request: ITerminalVirtualProcessRequest): void {
private _onRequestStartExtensionTerminal(request: IStartExtensionTerminalRequest): void {
const proxy = request.proxy;
const ready = this._terminalProcessesReady.get(proxy.terminalId);
if (!ready) {
@@ -286,7 +286,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
columns: request.cols,
rows: request.rows
} : undefined;
this._proxy.$startVirtualProcess(proxy.terminalId, initialDimensions);
this._proxy.$startExtensionTerminal(proxy.terminalId, initialDimensions);
proxy.onInput(data => this._proxy.$acceptProcessInput(proxy.terminalId, data));
proxy.onShutdown(immediate => this._proxy.$acceptProcessShutdown(proxy.terminalId, immediate));
proxy.onRequestCwd(() => this._proxy.$acceptProcessRequestCwd(proxy.terminalId));
@@ -323,6 +323,13 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._getTerminalProcess(terminalId).then(e => e.emitCwd(cwd));
}
public $sendResolvedLaunchConfig(terminalId: number, shellLaunchConfig: IShellLaunchConfig): void {
const instance = this._terminalService.getInstanceFromId(terminalId);
if (instance) {
this._getTerminalProcess(terminalId).then(e => e.emitResolvedShellLaunchConfig(shellLaunchConfig));
}
}
private async _onRequestLatency(terminalId: number): Promise<void> {
const COUNT = 2;
let sum = 0;

View File

@@ -24,6 +24,7 @@ import { ExtHostContext, ExtHostWorkspaceShape, IExtHostContext, MainContext, Ma
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { isEqualOrParent } from 'vs/base/common/resources';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { withNullAsUndefined } from 'vs/base/common/types';
@extHostNamedCustomer(MainContext.MainThreadWorkspace)
export class MainThreadWorkspace implements MainThreadWorkspaceShape {
@@ -122,21 +123,21 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
// --- search ---
$startFileSearch(includePattern: string, _includeFolder: UriComponents | undefined, excludePatternOrDisregardExcludes: string | false | undefined, maxResults: number, token: CancellationToken): Promise<URI[] | undefined> {
$startFileSearch(includePattern: string | null, _includeFolder: UriComponents | null, excludePatternOrDisregardExcludes: string | false | null, maxResults: number | null, token: CancellationToken): Promise<UriComponents[] | null> {
const includeFolder = URI.revive(_includeFolder);
const workspace = this._contextService.getWorkspace();
if (!workspace.folders.length) {
return Promise.resolve(undefined);
return Promise.resolve(null);
}
const query = this._queryBuilder.file(
includeFolder ? [includeFolder] : workspace.folders.map(f => f.uri),
{
maxResults,
maxResults: withNullAsUndefined(maxResults),
disregardExcludeSettings: (excludePatternOrDisregardExcludes === false) || undefined,
disregardSearchExcludeSettings: true,
disregardIgnoreFiles: true,
includePattern,
includePattern: withNullAsUndefined(includePattern),
excludePattern: typeof excludePatternOrDisregardExcludes === 'string' ? excludePatternOrDisregardExcludes : undefined,
_reason: 'startFileSearch'
});

View File

@@ -21,7 +21,7 @@ import { EndOfLineSequence, ISingleEditOperation } from 'vs/editor/common/model'
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
import * as modes from 'vs/editor/common/modes';
import { CharacterPair, CommentRule, EnterAction } from 'vs/editor/common/modes/languageConfiguration';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { ICommandHandlerDescription, ICommandEvent } from 'vs/platform/commands/common/commands';
import { ConfigurationTarget, IConfigurationData, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
@@ -40,9 +40,9 @@ import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
import * as tasks from 'vs/workbench/api/common/shared/tasks';
import { IRevealOptions, ITreeItem } from 'vs/workbench/common/views';
import * as callHierarchy from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { IAdapterDescriptor, IConfig, ITerminalSettings } from 'vs/workbench/contrib/debug/common/debug';
import { IAdapterDescriptor, IConfig } from 'vs/workbench/contrib/debug/common/debug';
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
import { ITerminalDimensions } from 'vs/workbench/contrib/terminal/common/terminal';
import { ITerminalDimensions, IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal';
import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier';
import * as search from 'vs/workbench/services/search/common/search';
@@ -118,6 +118,8 @@ export interface MainThreadClipboardShape extends IDisposable {
export interface MainThreadCommandsShape extends IDisposable {
$registerCommand(id: string): void;
$registerCommandListener(): void;
$unregisterCommandListener(): void;
$unregisterCommand(id: string): void;
$executeCommand<T>(id: string, args: any[]): Promise<T | undefined>;
$getCommands(): Promise<string[]>;
@@ -391,7 +393,7 @@ export interface TerminalLaunchConfig {
waitOnExit?: boolean;
strictEnv?: boolean;
hideFromUser?: boolean;
isVirtualProcess?: boolean;
isExtensionTerminal?: boolean;
}
export interface MainThreadTerminalServiceShape extends IDisposable {
@@ -408,9 +410,10 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
$sendProcessData(terminalId: number, data: string): void;
$sendProcessReady(terminalId: number, pid: number, cwd: string): void;
$sendProcessExit(terminalId: number, exitCode: number): void;
$sendOverrideDimensions(terminalId: number, dimensions: ITerminalDimensions | undefined): void;
$sendProcessInitialCwd(terminalId: number, cwd: string): void;
$sendProcessCwd(terminalId: number, initialCwd: string): void;
$sendOverrideDimensions(terminalId: number, dimensions: ITerminalDimensions | undefined): void;
$sendResolvedLaunchConfig(terminalId: number, shellLaunchConfig: IShellLaunchConfig): void;
// Renderer
$terminalRendererSetName(terminalId: number, name: string): void;
@@ -582,7 +585,7 @@ export interface ITextSearchComplete {
}
export interface MainThreadWorkspaceShape extends IDisposable {
$startFileSearch(includePattern: string | undefined, includeFolder: UriComponents | undefined, excludePatternOrDisregardExcludes: string | false | undefined, maxResults: number | undefined, token: CancellationToken): Promise<UriComponents[] | undefined>;
$startFileSearch(includePattern: string | null, includeFolder: UriComponents | null, excludePatternOrDisregardExcludes: string | false | null, maxResults: number | null, token: CancellationToken): Promise<UriComponents[] | null>;
$startTextSearch(query: search.IPatternInfo, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete>;
$checkExists(folders: UriComponents[], includes: string[], token: CancellationToken): Promise<boolean>;
$saveAll(includeUntitled?: boolean): Promise<boolean>;
@@ -739,6 +742,7 @@ export interface MainThreadWindowShape extends IDisposable {
export interface ExtHostCommandsShape {
$executeContributedCommand<T>(id: string, ...args: any[]): Promise<T>;
$getContributedCommandHandlerDescriptions(): Promise<{ [id: string]: string | ICommandHandlerDescription }>;
$handleDidExecuteCommand(command: ICommandEvent): void;
}
export interface ExtHostConfigurationShape {
@@ -1161,8 +1165,8 @@ export interface ExtHostTerminalServiceShape {
$acceptTerminalTitleChange(id: number, name: string): void;
$acceptTerminalDimensions(id: number, cols: number, rows: number): void;
$acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): void;
$createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void;
$startVirtualProcess(id: number, initialDimensions: ITerminalDimensionsDto | undefined): void;
$spawnExtHostProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void;
$startExtensionTerminal(id: number, initialDimensions: ITerminalDimensionsDto | undefined): void;
$acceptProcessInput(id: number, data: string): void;
$acceptProcessResize(id: number, cols: number, rows: number): void;
$acceptProcessShutdown(id: number, immediate: boolean): void;
@@ -1245,7 +1249,7 @@ export type IDebugSessionDto = IDebugSessionFullDto | DebugSessionUUID;
export interface ExtHostDebugServiceShape {
$substituteVariables(folder: UriComponents | undefined, config: IConfig): Promise<IConfig>;
$runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Promise<number | undefined>;
$runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments): Promise<number | undefined>;
$startDASession(handle: number, session: IDebugSessionDto): Promise<void>;
$stopDASession(handle: number): Promise<void>;
$sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): void;

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { validateConstraint } from 'vs/base/common/types';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { ICommandHandlerDescription, ICommandEvent } from 'vs/platform/commands/common/commands';
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
import * as extHostTypeConverter from 'vs/workbench/api/common/extHostTypeConverters';
import { cloneAndChange } from 'vs/base/common/objects';
@@ -17,6 +17,7 @@ import { revive } from 'vs/base/common/marshalling';
import { Range } from 'vs/editor/common/core/range';
import { Position } from 'vs/editor/common/core/position';
import { URI } from 'vs/base/common/uri';
import { Event, Emitter } from 'vs/base/common/event';
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
interface CommandHandler {
@@ -31,6 +32,9 @@ export interface ArgumentProcessor {
export class ExtHostCommands implements ExtHostCommandsShape {
private readonly _onDidExecuteCommand: Emitter<vscode.CommandExecutionEvent>;
readonly onDidExecuteCommand: Event<vscode.CommandExecutionEvent>;
private readonly _commands = new Map<string, CommandHandler>();
private readonly _proxy: MainThreadCommandsShape;
private readonly _converter: CommandsConverter;
@@ -42,6 +46,11 @@ export class ExtHostCommands implements ExtHostCommandsShape {
logService: ILogService
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadCommands);
this._onDidExecuteCommand = new Emitter<vscode.CommandExecutionEvent>({
onFirstListenerDidAdd: () => this._proxy.$registerCommandListener(),
onLastListenerRemove: () => this._proxy.$unregisterCommandListener(),
});
this.onDidExecuteCommand = Event.filter(this._onDidExecuteCommand.event, e => e.command[0] !== '_'); // filter 'private' commands
this._logService = logService;
this._converter = new CommandsConverter(this);
this._argumentProcessors = [
@@ -106,6 +115,13 @@ export class ExtHostCommands implements ExtHostCommandsShape {
});
}
$handleDidExecuteCommand(command: ICommandEvent): void {
this._onDidExecuteCommand.fire({
command: command.commandId,
arguments: command.args.map(arg => this._argumentProcessors.reduce((r, p) => p.processArgument(r), arg))
});
}
executeCommand<T>(id: string, ...args: any[]): Promise<T> {
this._logService.trace('ExtHostCommands#executeCommand', id);
@@ -154,6 +170,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
try {
const result = callback.apply(thisArg, args);
this._onDidExecuteCommand.fire({ command: id, arguments: args });
return Promise.resolve(result);
} catch (err) {
this._logService.error(err, id);
@@ -205,7 +222,7 @@ export class CommandsConverter {
// --- conversion between internal and api commands
constructor(commands: ExtHostCommands) {
this._delegatingCommandId = `_internal_command_delegation_${Date.now()}`;
this._delegatingCommandId = `_vscode_delegate_cmd_${Date.now().toString(36)}`;
this._commands = commands;
this._commands.registerCommand(true, this._delegatingCommandId, this._executeConvertedCommand, this);
}

View File

@@ -108,6 +108,8 @@ export namespace DiagnosticTag {
switch (value) {
case types.DiagnosticTag.Unnecessary:
return MarkerTag.Unnecessary;
case types.DiagnosticTag.Deprecated:
return MarkerTag.Deprecated;
}
return undefined;
}
@@ -988,8 +990,9 @@ export namespace GlobPattern {
export function from(pattern: vscode.GlobPattern): string | types.RelativePattern;
export function from(pattern: undefined): undefined;
export function from(pattern: vscode.GlobPattern | undefined): string | types.RelativePattern | undefined;
export function from(pattern: vscode.GlobPattern | undefined): string | types.RelativePattern | undefined {
export function from(pattern: null): null;
export function from(pattern: vscode.GlobPattern | undefined | null): string | types.RelativePattern | undefined | null;
export function from(pattern: vscode.GlobPattern | undefined | null): string | types.RelativePattern | undefined | null {
if (pattern instanceof types.RelativePattern) {
return pattern;
}

View File

@@ -773,6 +773,7 @@ export class SnippetString {
export enum DiagnosticTag {
Unnecessary = 1,
Deprecated = 2
}
export enum DiagnosticSeverity {
@@ -1773,19 +1774,19 @@ export class CustomExecution implements vscode.CustomExecution {
}
export class CustomExecution2 implements vscode.CustomExecution2 {
private _callback: () => Thenable<vscode.TerminalVirtualProcess>;
constructor(callback: () => Thenable<vscode.TerminalVirtualProcess>) {
private _callback: () => Thenable<vscode.Pseudoterminal>;
constructor(callback: () => Thenable<vscode.Pseudoterminal>) {
this._callback = callback;
}
public computeId(): string {
return 'customExecution' + generateUuid();
}
public set callback(value: () => Thenable<vscode.TerminalVirtualProcess>) {
public set callback(value: () => Thenable<vscode.Pseudoterminal>) {
this._callback = value;
}
public get callback(): (() => Thenable<vscode.TerminalVirtualProcess>) {
public get callback(): (() => Thenable<vscode.Pseudoterminal>) {
return this._callback;
}
}

View File

@@ -24,6 +24,7 @@ import { ExtHostWorkspaceShape, IWorkspaceData, MainThreadMessageServiceShape, M
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { Barrier } from 'vs/base/common/async';
import { Schemas } from 'vs/base/common/network';
import { withUndefinedAsNull } from 'vs/base/common/types';
export interface IExtHostWorkspaceProvider {
getWorkspaceFolder2(uri: vscode.Uri, resolveParent?: boolean): Promise<vscode.WorkspaceFolder | undefined>;
@@ -407,7 +408,10 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
// --- search ---
findFiles(include: string | RelativePattern | undefined, exclude: vscode.GlobPattern | undefined, maxResults: number | undefined, extensionId: ExtensionIdentifier, token: vscode.CancellationToken = CancellationToken.None): Promise<vscode.Uri[]> {
/**
* Note, null/undefined have different and important meanings for "exclude"
*/
findFiles(include: string | RelativePattern | undefined, exclude: vscode.GlobPattern | null | undefined, maxResults: number | undefined, extensionId: ExtensionIdentifier, token: vscode.CancellationToken = CancellationToken.None): Promise<vscode.Uri[]> {
this._logService.trace(`extHostWorkspace#findFiles: fileSearch, extension: ${extensionId.value}, entryPoint: findFiles`);
let includePattern: string | undefined;
@@ -438,7 +442,13 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
return Promise.resolve([]);
}
return this._proxy.$startFileSearch(includePattern, includeFolder, excludePatternOrDisregardExcludes, maxResults, token)
return this._proxy.$startFileSearch(
withUndefinedAsNull(includePattern),
withUndefinedAsNull(includeFolder),
withUndefinedAsNull(excludePatternOrDisregardExcludes),
withUndefinedAsNull(maxResults),
token
)
.then(data => Array.isArray(data) ? data.map(d => URI.revive(d)) : []);
}

View File

@@ -66,7 +66,6 @@ import * as vscode from 'vscode';
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { originalFSPath } from 'vs/base/common/resources';
import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer';
import { withNullAsUndefined } from 'vs/base/common/types';
import { values } from 'vs/base/common/collections';
import { Schemas } from 'vs/base/common/network';
import { IURITransformer } from 'vs/base/common/uriIpc';
@@ -75,6 +74,7 @@ import { ExtHostLabelService } from 'vs/workbench/api/common/extHostLabelService
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions';
import { getRemoteName } from 'vs/platform/remote/common/remoteHosts';
export interface IExtensionApiFactory {
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
@@ -249,7 +249,11 @@ export function createApiFactory(
},
getCommands(filterInternal: boolean = false): Thenable<string[]> {
return extHostCommands.getCommands(filterInternal);
}
},
onDidExecuteCommand: proposedApiFunction(extension, (listener, thisArgs?, disposables?) => {
checkProposedApiEnabled(extension);
return extHostCommands.onDidExecuteCommand(listener, thisArgs, disposables);
}),
};
// namespace: env
@@ -278,15 +282,7 @@ export function createApiFactory(
return extHostWindow.openUri(uri, { allowTunneling: !!initData.remote.isRemote });
},
get remoteName() {
if (!initData.remote.authority) {
return undefined;
}
const pos = initData.remote.authority.indexOf('+');
if (pos < 0) {
// funky? bad authority?
return initData.remote.authority;
}
return initData.remote.authority.substr(0, pos);
return getRemoteName(initData.remote.authority);
}
};
if (!initData.environment.extensionTestsLocationURI) {
@@ -540,10 +536,10 @@ export function createApiFactory(
checkProposedApiEnabled(extension);
return extHostEditorInsets.createWebviewEditorInset(editor, line, height, options, extension);
},
createTerminal(nameOrOptions?: vscode.TerminalOptions | vscode.TerminalVirtualProcessOptions | string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal {
createTerminal(nameOrOptions?: vscode.TerminalOptions | vscode.ExtensionTerminalOptions | string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal {
if (typeof nameOrOptions === 'object') {
if ('virtualProcess' in nameOrOptions) {
return extHostTerminalService.createVirtualProcessTerminal(nameOrOptions);
if ('pty' in nameOrOptions) {
return extHostTerminalService.createExtensionTerminal(nameOrOptions);
} else {
nameOrOptions.hideFromUser = nameOrOptions.hideFromUser || (nameOrOptions.runInBackground && extension.enableProposedApi);
return extHostTerminalService.createTerminalFromOptions(nameOrOptions);
@@ -613,7 +609,8 @@ export function createApiFactory(
return extHostWorkspace.getRelativePath(pathOrUri, includeWorkspace);
},
findFiles: (include, exclude, maxResults?, token?) => {
return extHostWorkspace.findFiles(typeConverters.GlobPattern.from(include), typeConverters.GlobPattern.from(withNullAsUndefined(exclude)), maxResults, extension.identifier, token);
// Note, undefined/null have different meanings on "exclude"
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) => {
let options: vscode.FindTextInFilesOptions;

View File

@@ -20,7 +20,7 @@ import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstract
import { IExtHostWorkspaceProvider } from 'vs/workbench/api/common/extHostWorkspace';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { ITerminalSettings, IDebuggerContribution, IConfig, IDebugAdapter, IDebugAdapterServer, IDebugAdapterExecutable, IAdapterDescriptor } from 'vs/workbench/contrib/debug/common/debug';
import { IDebuggerContribution, IConfig, IDebugAdapter, IDebugAdapterServer, IDebugAdapterExecutable, IAdapterDescriptor } from 'vs/workbench/contrib/debug/common/debug';
import { hasChildProcesses, prepareCommand, runInExternalTerminal } from 'vs/workbench/contrib/debug/node/terminals';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/common/variableResolver';
@@ -34,6 +34,8 @@ import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
import { IProcessEnvironment } from 'vs/base/common/platform';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { SignService } from 'vs/platform/sign/node/signService';
import { ISignService } from 'vs/platform/sign/common/sign';
export class ExtHostDebugService implements ExtHostDebugServiceShape {
@@ -81,6 +83,8 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
private _integratedTerminalInstance?: vscode.Terminal;
private _terminalDisposedListener: IDisposable;
private _signService: ISignService;
constructor(mainContext: IMainContext,
private _workspaceService: IExtHostWorkspaceProvider,
@@ -314,7 +318,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
// RPC methods (ExtHostDebugServiceShape)
public $runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Promise<number | undefined> {
public async $runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments): Promise<number | undefined> {
if (args.kind === 'integrated') {
@@ -337,10 +341,22 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
} else {
resolve(true);
}
}).then(needNewTerminal => {
}).then(async needNewTerminal => {
const configProvider = await this._configurationService.getConfigProvider();
const shell = this._terminalService.getDefaultShell(configProvider);
if (needNewTerminal || !this._integratedTerminalInstance) {
this._integratedTerminalInstance = this._terminalService.createTerminal(args.title || nls.localize('debug.terminal.title', "debuggee"));
const options: vscode.TerminalOptions = {
shellPath: shell,
// shellArgs: this._terminalService._getDefaultShellArgs(configProvider),
cwd: args.cwd,
name: args.title || nls.localize('debug.terminal.title', "debuggee"),
env: args.env
};
delete args.cwd;
delete args.env;
this._integratedTerminalInstance = this._terminalService.createTerminalFromOptions(options);
}
const terminal: vscode.Terminal = this._integratedTerminalInstance;
@@ -348,7 +364,8 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return this._integratedTerminalInstance.processId.then(shellProcessId => {
const command = prepareCommand(args, config);
const command = prepareCommand(args, shell, configProvider);
terminal.sendText(command, true);
return shellProcessId;
@@ -357,7 +374,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
} else if (args.kind === 'external') {
runInExternalTerminal(args, config);
runInExternalTerminal(args, await this._configurationService.getConfigProvider());
}
return Promise.resolve(undefined);
}
@@ -421,16 +438,45 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
this._debugAdaptersTrackers.set(debugAdapterHandle, tracker);
}
debugAdapter.onMessage(message => {
debugAdapter.onMessage(async message => {
if (tracker && tracker.onDidSendMessage) {
tracker.onDidSendMessage(message);
if (message.type === 'request' && (<DebugProtocol.Request>message).command === 'handshake') {
const request = <DebugProtocol.Request>message;
const response: DebugProtocol.Response = {
type: 'response',
seq: 0,
command: request.command,
request_seq: request.seq,
success: true
};
if (!this._signService) {
this._signService = new SignService();
}
try {
const signature = await this._signService.sign(request.arguments.value);
response.body = {
signature: signature
};
debugAdapter.sendResponse(response);
} catch (e) {
response.success = false;
response.message = e.message;
debugAdapter.sendResponse(response);
}
} else {
if (tracker && tracker.onDidSendMessage) {
tracker.onDidSendMessage(message);
}
// DA -> VS Code
message = convertToVSCPaths(message, true);
mythis._debugServiceProxy.$acceptDAMessage(debugAdapterHandle, message);
}
// DA -> VS Code
message = convertToVSCPaths(message, true);
mythis._debugServiceProxy.$acceptDAMessage(debugAdapterHandle, message);
});
debugAdapter.onError(err => {
if (tracker && tracker.onError) {

View File

@@ -322,15 +322,6 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
private _logExtensionActivationTimes(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason, outcome: string, activationTimes?: ExtensionActivationTimes) {
const event = getTelemetryActivationEvent(extensionDescription, reason);
/* __GDPR__
"extensionActivationTimes" : {
"${include}": [
"${TelemetryActivationEvent}",
"${ExtensionActivationTimes}"
],
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
type ExtensionActivationTimesClassification = {
outcome: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
} & TelemetryActivationEventFragment & ExtensionActivationTimesFragment;

View File

@@ -589,9 +589,7 @@ export class ExtHostTask implements ExtHostTaskShape {
// Clone the custom execution to keep the original untouched. This is important for multiple runs of the same task.
this._activeCustomExecutions2.set(execution.id, execution2);
this._terminalService.performTerminalIdAction(terminalId, async terminal => {
this._terminalService.attachVirtualProcessToTerminal(terminalId, await execution2.callback());
});
await this._terminalService.attachPtyToTerminal(terminalId, await execution2.callback());
}
// Once a terminal is spun up for the custom execution task this event will be fired.

View File

@@ -91,7 +91,7 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
this._idPromise.then(c => {
this._proxy.$registerOnDataListener(this._id);
});
return this._onData && this._onData.event;
return this._onData.event;
}
constructor(
@@ -110,7 +110,7 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
});
}
public create(
public async create(
shellPath?: string,
shellArgs?: string[] | string,
cwd?: string | URI,
@@ -118,18 +118,16 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
waitOnExit?: boolean,
strictEnv?: boolean,
hideFromUser?: boolean
): void {
this._proxy.$createTerminal({ name: this._name, shellPath, shellArgs, cwd, env, waitOnExit, strictEnv, hideFromUser }).then(terminal => {
this._name = terminal.name;
this._runQueuedRequests(terminal.id);
});
): Promise<void> {
const terminal = await this._proxy.$createTerminal({ name: this._name, shellPath, shellArgs, cwd, env, waitOnExit, strictEnv, hideFromUser });
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);
});
public async createExtensionTerminal(): Promise<void> {
const terminal = await this._proxy.$createTerminal({ name: this._name, isExtensionTerminal: true });
this._name = terminal.name;
this._runQueuedRequests(terminal.id);
}
public get name(): string {
@@ -312,9 +310,9 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
private _logService: ILogService
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadTerminalService);
this.updateLastActiveWorkspace();
this.updateVariableResolver();
this.registerListeners();
this._updateLastActiveWorkspace();
this._updateVariableResolver();
this._registerListeners();
}
public createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal {
@@ -331,20 +329,20 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
return terminal;
}
public createVirtualProcessTerminal(options: vscode.TerminalVirtualProcessOptions): vscode.Terminal {
public createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal {
const terminal = new ExtHostTerminal(this._proxy, options.name);
const p = new ExtHostVirtualProcess(options.virtualProcess);
terminal.createVirtualProcess().then(() => this._setupExtHostProcessListeners(terminal._id, p));
const p = new ExtHostPseudoterminal(options.pty);
terminal.createExtensionTerminal().then(() => this._setupExtHostProcessListeners(terminal._id, p));
this._terminals.push(terminal);
return terminal;
}
public attachVirtualProcessToTerminal(id: number, virtualProcess: vscode.TerminalVirtualProcess) {
const terminal = this._getTerminalById(id);
public async attachPtyToTerminal(id: number, pty: vscode.Pseudoterminal): Promise<void> {
const terminal = this._getTerminalByIdEventually(id);
if (!terminal) {
throw new Error(`Cannot resolve terminal with id ${id} for virtual process`);
}
const p = new ExtHostVirtualProcess(virtualProcess);
const p = new ExtHostPseudoterminal(pty);
this._setupExtHostProcessListeners(id, p);
}
@@ -534,25 +532,25 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
return env;
}
private registerListeners(): void {
this._extHostDocumentsAndEditors.onDidChangeActiveTextEditor(() => this.updateLastActiveWorkspace());
this._extHostWorkspace.onDidChangeWorkspace(() => this.updateVariableResolver());
private _registerListeners(): void {
this._extHostDocumentsAndEditors.onDidChangeActiveTextEditor(() => this._updateLastActiveWorkspace());
this._extHostWorkspace.onDidChangeWorkspace(() => this._updateVariableResolver());
}
private updateLastActiveWorkspace(): void {
private _updateLastActiveWorkspace(): void {
const activeEditor = this._extHostDocumentsAndEditors.activeEditor();
if (activeEditor) {
this._lastActiveWorkspace = this._extHostWorkspace.getWorkspaceFolder(activeEditor.document.uri) as IWorkspaceFolder;
}
}
private async updateVariableResolver(): Promise<void> {
private async _updateVariableResolver(): Promise<void> {
const configProvider = await this._extHostConfiguration.getConfigProvider();
const workspaceFolders = await this._extHostWorkspace.getWorkspaceFolders2();
this._variableResolver = new ExtHostVariableResolverService(workspaceFolders || [], this._extHostDocumentsAndEditors, configProvider);
}
public async $createProcess(id: number, shellLaunchConfigDto: ShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void> {
public async $spawnExtHostProcess(id: number, shellLaunchConfigDto: ShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void> {
const shellLaunchConfig: IShellLaunchConfig = {
name: shellLaunchConfigDto.name,
executable: shellLaunchConfigDto.executable,
@@ -612,6 +610,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
baseEnv
);
this._proxy.$sendResolvedLaunchConfig(id, shellLaunchConfig);
// Fork the process and listen for messages
this._logService.debug(`Terminal process launching on ext host`, shellLaunchConfig, initialCwd, cols, rows, env);
// TODO: Support conpty on remote, it doesn't seem to work for some reason?
@@ -620,8 +619,22 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
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);
public async $startExtensionTerminal(id: number, initialDimensions: ITerminalDimensionsDto | undefined): Promise<void> {
// Make sure the ExtHostTerminal exists so onDidOpenTerminal has fired before we call
// Pseudoterminal.start
await this._getTerminalByIdEventually(id);
// Processes should be initialized here for normal virtual process terminals, however for
// tasks they are responsible for attaching the virtual process to a terminal so this
// function may be called before tasks is able to attach to the terminal.
let retries = 5;
while (retries-- > 0) {
if (this._terminalProcesses[id]) {
(this._terminalProcesses[id] as ExtHostPseudoterminal).startSendingEvents(initialDimensions);
return;
}
await timeout(50);
}
}
private _setupExtHostProcessListeners(id: number, p: ITerminalChildProcess): void {
@@ -760,7 +773,7 @@ class ApiRequest {
}
}
class ExtHostVirtualProcess implements ITerminalChildProcess {
class ExtHostPseudoterminal implements ITerminalChildProcess {
private _queuedEvents: (IQueuedEvent<string> | IQueuedEvent<number> | IQueuedEvent<{ pid: number, cwd: string }> | IQueuedEvent<ITerminalDimensions | undefined>)[] = [];
private _queueDisposables: IDisposable[] | undefined;
@@ -776,33 +789,33 @@ class ExtHostVirtualProcess implements ITerminalChildProcess {
public get onProcessOverrideDimensions(): Event<ITerminalDimensions | undefined> { return this._onProcessOverrideDimensions.event; }
constructor(
private readonly _virtualProcess: vscode.TerminalVirtualProcess
private readonly _pty: vscode.Pseudoterminal
) {
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 })));
this._queueDisposables.push(this._pty.onDidWrite(e => this._queuedEvents.push({ emitter: this._onProcessData, data: e })));
if (this._pty.onDidClose) {
this._queueDisposables.push(this._pty.onDidClose(e => this._queuedEvents.push({ emitter: this._onProcessExit, data: 0 })));
}
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 })));
if (this._pty.onDidOverrideDimensions) {
this._queueDisposables.push(this._pty.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();
if (this._pty.close) {
this._pty.close();
}
}
input(data: string): void {
if (this._virtualProcess.handleInput) {
this._virtualProcess.handleInput(data);
if (this._pty.handleInput) {
this._pty.handleInput(data);
}
}
resize(cols: number, rows: number): void {
if (this._virtualProcess.setDimensions) {
this._virtualProcess.setDimensions({ columns: cols, rows });
if (this._pty.setDimensions) {
this._pty.setDimensions({ columns: cols, rows });
}
}
@@ -825,19 +838,16 @@ class ExtHostVirtualProcess implements ITerminalChildProcess {
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);
});
this._pty.onDidWrite(e => this._onProcessData.fire(e));
if (this._pty.onDidClose) {
this._pty.onDidClose(e => this._onProcessExit.fire(0));
}
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._pty.onDidOverrideDimensions) {
this._pty.onDidOverrideDimensions(e => this._onProcessOverrideDimensions.fire(e ? { cols: e.columns, rows: e.rows } : undefined)); // {{SQL CARBON EDIT}} strict-null-checks
}
if (this._virtualProcess.start) {
this._virtualProcess.start(initialDimensions);
if (this._pty.open) {
this._pty.open(initialDimensions);
}
}
}