Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)

* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973

* disable strict null check
This commit is contained in:
Anthony Dresser
2019-07-15 22:35:46 -07:00
committed by GitHub
parent f720ec642f
commit 0b7e7ddbf9
2406 changed files with 59140 additions and 35464 deletions

View File

@@ -0,0 +1,44 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IDebugHelperService } from 'vs/workbench/contrib/debug/common/debug';
import { Client as TelemetryClient } from 'vs/base/parts/ipc/node/ipc.cp';
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
export class NodeDebugHelperService implements IDebugHelperService {
_serviceBrand: any;
constructor(
) {
}
createTelemetryService(configurationService: IConfigurationService, args: string[]): TelemetryService | undefined {
const client = new TelemetryClient(
getPathFromAmdModule(require, 'bootstrap-fork'),
{
serverName: 'Debug Telemetry',
timeout: 1000 * 60 * 5,
args: args,
env: {
ELECTRON_RUN_AS_NODE: 1,
PIPE_LOGGING: 'true',
AMD_ENTRYPOINT: 'vs/workbench/contrib/debug/node/telemetryApp'
}
}
);
const channel = client.getChannel('telemetryAppender');
const appender = new TelemetryAppenderClient(channel);
return new TelemetryService({ appender }, configurationService);
}
}
registerSingleton(IDebugHelperService, NodeDebugHelperService);

View File

@@ -1,299 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { Client as TelemetryClient } from 'vs/base/parts/ipc/node/ipc.cp';
import * as strings from 'vs/base/common/strings';
import * as objects from 'vs/base/common/objects';
import { isObject } from 'vs/base/common/types';
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { IJSONSchema, IJSONSchemaSnippet } from 'vs/base/common/jsonSchema';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IConfig, IDebuggerContribution, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager, IDebugAdapter, ITerminalSettings, IDebugger, IDebugSession } from 'vs/workbench/contrib/debug/common/debug';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import * as ConfigurationResolverUtils from 'vs/workbench/services/configurationResolver/common/configurationResolverUtils';
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { memoize } from 'vs/base/common/decorators';
import { TaskDefinitionRegistry } from 'vs/workbench/contrib/tasks/common/taskDefinitionRegistry';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { isDebuggerMainContribution } from 'vs/workbench/contrib/debug/common/debugUtils';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
export class Debugger implements IDebugger {
private debuggerContribution: IDebuggerContribution;
private mergedExtensionDescriptions: IExtensionDescription[] = [];
private mainExtensionDescription: IExtensionDescription | undefined;
constructor(private configurationManager: IConfigurationManager, dbgContribution: IDebuggerContribution, extensionDescription: IExtensionDescription,
@IConfigurationService private readonly configurationService: IConfigurationService,
@ITextResourcePropertiesService private readonly resourcePropertiesService: ITextResourcePropertiesService,
@IConfigurationResolverService private readonly configurationResolverService: IConfigurationResolverService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
) {
this.debuggerContribution = { type: dbgContribution.type };
this.merge(dbgContribution, extensionDescription);
}
public merge(otherDebuggerContribution: IDebuggerContribution, extensionDescription: IExtensionDescription): void {
/**
* Copies all properties of source into destination. The optional parameter "overwrite" allows to control
* if existing non-structured properties on the destination should be overwritten or not. Defaults to true (overwrite).
*/
function mixin(destination: any, source: any, overwrite: boolean, level = 0): any {
if (!isObject(destination)) {
return source;
}
if (isObject(source)) {
Object.keys(source).forEach(key => {
if (isObject(destination[key]) && isObject(source[key])) {
mixin(destination[key], source[key], overwrite, level + 1);
} else {
if (key in destination) {
if (overwrite) {
if (level === 0 && key === 'type') {
// don't merge the 'type' property
} else {
destination[key] = source[key];
}
}
} else {
destination[key] = source[key];
}
}
});
}
return destination;
}
// only if not already merged
if (this.mergedExtensionDescriptions.indexOf(extensionDescription) < 0) {
// remember all extensions that have been merged for this debugger
this.mergedExtensionDescriptions.push(extensionDescription);
// merge new debugger contribution into existing contributions (and don't overwrite values in built-in extensions)
mixin(this.debuggerContribution, otherDebuggerContribution, extensionDescription.isBuiltin);
// remember the extension that is considered the "main" debugger contribution
if (isDebuggerMainContribution(otherDebuggerContribution)) {
this.mainExtensionDescription = extensionDescription;
}
}
}
public createDebugAdapter(session: IDebugSession): Promise<IDebugAdapter> {
return this.configurationManager.activateDebuggers('onDebugAdapterProtocolTracker', this.type).then(_ => {
const da = this.configurationManager.createDebugAdapter(session);
if (da) {
return Promise.resolve(da);
}
throw new Error(nls.localize('cannot.find.da', "Cannot find debug adapter for type '{0}'.", this.type));
});
}
substituteVariables(folder: IWorkspaceFolder | undefined, config: IConfig): Promise<IConfig> {
return this.configurationManager.substituteVariables(this.type, folder, config).then(config => {
return this.configurationResolverService.resolveWithInteractionReplace(folder, config, 'launch', this.variables);
});
}
runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments): Promise<number | undefined> {
const config = this.configurationService.getValue<ITerminalSettings>('terminal');
return this.configurationManager.runInTerminal(this.type, args, config);
}
get label(): string {
return this.debuggerContribution.label || this.debuggerContribution.type;
}
get type(): string {
return this.debuggerContribution.type;
}
get variables(): { [key: string]: string } | undefined {
return this.debuggerContribution.variables;
}
get configurationSnippets(): IJSONSchemaSnippet[] | undefined {
return this.debuggerContribution.configurationSnippets;
}
get languages(): string[] | undefined {
return this.debuggerContribution.languages;
}
hasInitialConfiguration(): boolean {
return !!this.debuggerContribution.initialConfigurations;
}
hasConfigurationProvider(): boolean {
return this.configurationManager.hasDebugConfigurationProvider(this.type);
}
getInitialConfigurationContent(initialConfigs?: IConfig[]): Promise<string> {
// at this point we got some configs from the package.json and/or from registered DebugConfigurationProviders
let initialConfigurations = this.debuggerContribution.initialConfigurations || [];
if (initialConfigs) {
initialConfigurations = initialConfigurations.concat(initialConfigs);
}
const eol = this.resourcePropertiesService.getEOL(URI.from({ scheme: Schemas.untitled, path: '1' })) === '\r\n' ? '\r\n' : '\n';
const configs = JSON.stringify(initialConfigurations, null, '\t').split('\n').map(line => '\t' + line).join(eol).trim();
const comment1 = nls.localize('launch.config.comment1', "Use IntelliSense to learn about possible attributes.");
const comment2 = nls.localize('launch.config.comment2', "Hover to view descriptions of existing attributes.");
const comment3 = nls.localize('launch.config.comment3', "For more information, visit: {0}", 'https://go.microsoft.com/fwlink/?linkid=830387');
let content = [
'{',
`\t// ${comment1}`,
`\t// ${comment2}`,
`\t// ${comment3}`,
`\t"version": "0.2.0",`,
`\t"configurations": ${configs}`,
'}'
].join(eol);
// fix formatting
const editorConfig = this.configurationService.getValue<any>();
if (editorConfig.editor && editorConfig.editor.insertSpaces) {
content = content.replace(new RegExp('\t', 'g'), strings.repeat(' ', editorConfig.editor.tabSize));
}
return Promise.resolve(content);
}
public getMainExtensionDescriptor(): IExtensionDescription {
return this.mainExtensionDescription || this.mergedExtensionDescriptions[0];
}
@memoize
getCustomTelemetryService(): Promise<TelemetryService | undefined> {
const aiKey = this.debuggerContribution.aiKey;
if (!aiKey) {
return Promise.resolve(undefined);
}
return this.telemetryService.getTelemetryInfo().then(info => {
const telemetryInfo: { [key: string]: string } = Object.create(null);
telemetryInfo['common.vscodemachineid'] = info.machineId;
telemetryInfo['common.vscodesessionid'] = info.sessionId;
return telemetryInfo;
}).then(data => {
const client = new TelemetryClient(
getPathFromAmdModule(require, 'bootstrap-fork'),
{
serverName: 'Debug Telemetry',
timeout: 1000 * 60 * 5,
args: [`${this.getMainExtensionDescriptor().publisher}.${this.type}`, JSON.stringify(data), aiKey],
env: {
ELECTRON_RUN_AS_NODE: 1,
PIPE_LOGGING: 'true',
AMD_ENTRYPOINT: 'vs/workbench/contrib/debug/node/telemetryApp'
}
}
);
const channel = client.getChannel('telemetryAppender');
const appender = new TelemetryAppenderClient(channel);
return new TelemetryService({ appender }, this.configurationService);
});
}
getSchemaAttributes(): IJSONSchema[] | null {
if (!this.debuggerContribution.configurationAttributes) {
return null;
}
// fill in the default configuration attributes shared by all adapters.
const taskSchema = TaskDefinitionRegistry.getJsonSchema();
return Object.keys(this.debuggerContribution.configurationAttributes).map(request => {
const attributes: IJSONSchema = this.debuggerContribution.configurationAttributes[request];
const defaultRequired = ['name', 'type', 'request'];
attributes.required = attributes.required && attributes.required.length ? defaultRequired.concat(attributes.required) : defaultRequired;
attributes.additionalProperties = false;
attributes.type = 'object';
if (!attributes.properties) {
attributes.properties = {};
}
const properties = attributes.properties;
properties['type'] = {
enum: [this.type],
description: nls.localize('debugType', "Type of configuration."),
pattern: '^(?!node2)',
errorMessage: nls.localize('debugTypeNotRecognised', "The debug type is not recognized. Make sure that you have a corresponding debug extension installed and that it is enabled."),
patternErrorMessage: nls.localize('node2NotSupported', "\"node2\" is no longer supported, use \"node\" instead and set the \"protocol\" attribute to \"inspector\".")
};
properties['name'] = {
type: 'string',
description: nls.localize('debugName', "Name of configuration; appears in the launch configuration drop down menu."),
default: 'Launch'
};
properties['request'] = {
enum: [request],
description: nls.localize('debugRequest', "Request type of configuration. Can be \"launch\" or \"attach\"."),
};
properties['debugServer'] = {
type: 'number',
description: nls.localize('debugServer', "For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode"),
default: 4711
};
properties['preLaunchTask'] = {
anyOf: [taskSchema, {
type: ['string', 'null'],
}],
default: '',
description: nls.localize('debugPrelaunchTask', "Task to run before debug session starts.")
};
properties['postDebugTask'] = {
anyOf: [taskSchema, {
type: ['string', 'null'],
}],
default: '',
description: nls.localize('debugPostDebugTask', "Task to run after debug session ends.")
};
properties['internalConsoleOptions'] = INTERNAL_CONSOLE_OPTIONS_SCHEMA;
// Clear out windows, linux and osx fields to not have cycles inside the properties object
delete properties['windows'];
delete properties['osx'];
delete properties['linux'];
const osProperties = objects.deepClone(properties);
properties['windows'] = {
type: 'object',
description: nls.localize('debugWindowsConfiguration', "Windows specific launch configuration attributes."),
properties: osProperties
};
properties['osx'] = {
type: 'object',
description: nls.localize('debugOSXConfiguration', "OS X specific launch configuration attributes."),
properties: osProperties
};
properties['linux'] = {
type: 'object',
description: nls.localize('debugLinuxConfiguration', "Linux specific launch configuration attributes."),
properties: osProperties
};
Object.keys(properties).forEach(name => {
// Use schema allOf property to get independent error reporting #21113
ConfigurationResolverUtils.applyDeprecatedVariableMessage(properties[name]);
});
return attributes;
});
}
}

View File

@@ -4,277 +4,30 @@
*--------------------------------------------------------------------------------------------*/
import * as cp from 'child_process';
import * as nls from 'vs/nls';
import * as env from 'vs/base/common/platform';
import * as pfs from 'vs/base/node/pfs';
import { assign } from 'vs/base/common/objects';
import { ITerminalLauncher, ITerminalSettings } from 'vs/workbench/contrib/debug/common/debug';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal';
import { ITerminalSettings } from 'vs/workbench/contrib/debug/common/debug';
import { getSystemShell } from 'vs/workbench/contrib/terminal/node/terminal';
import { WindowsExternalTerminalService, MacExternalTerminalService, LinuxExternalTerminalService } from 'vs/workbench/contrib/externalTerminal/node/externalTerminalService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IExternalTerminalService } from 'vs/workbench/contrib/externalTerminal/common/externalTerminal';
const TERMINAL_TITLE = nls.localize('console.title', "VS Code Console");
let externalTerminalService: IExternalTerminalService | undefined = undefined;
let terminalLauncher: ITerminalLauncher | undefined = undefined;
export function getTerminalLauncher() {
if (!terminalLauncher) {
export function runInExternalTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): void {
if (!externalTerminalService) {
if (env.isWindows) {
terminalLauncher = new WinTerminalService();
externalTerminalService = new WindowsExternalTerminalService(<IConfigurationService><unknown>undefined);
} else if (env.isMacintosh) {
terminalLauncher = new MacTerminalService();
externalTerminalService = new MacExternalTerminalService(<IConfigurationService><unknown>undefined);
} else if (env.isLinux) {
terminalLauncher = new LinuxTerminalService();
externalTerminalService = new LinuxExternalTerminalService(<IConfigurationService><unknown>undefined);
}
}
return terminalLauncher;
}
let _DEFAULT_TERMINAL_LINUX_READY: Promise<string> | null = null;
export function getDefaultTerminalLinuxReady(): Promise<string> {
if (!_DEFAULT_TERMINAL_LINUX_READY) {
_DEFAULT_TERMINAL_LINUX_READY = new Promise<string>(resolve => {
if (env.isLinux) {
Promise.all<any>([pfs.exists('/etc/debian_version'), process.lazyEnv]).then(([isDebian]) => {
if (isDebian) {
resolve('x-terminal-emulator');
} else if (process.env.DESKTOP_SESSION === 'gnome' || process.env.DESKTOP_SESSION === 'gnome-classic') {
resolve('gnome-terminal');
} else if (process.env.DESKTOP_SESSION === 'kde-plasma') {
resolve('konsole');
} else if (process.env.COLORTERM) {
resolve(process.env.COLORTERM);
} else if (process.env.TERM) {
resolve(process.env.TERM);
} else {
resolve('xterm');
}
});
return;
}
resolve('xterm');
});
}
return _DEFAULT_TERMINAL_LINUX_READY;
}
let _DEFAULT_TERMINAL_WINDOWS: string | null = null;
export function getDefaultTerminalWindows(): string {
if (!_DEFAULT_TERMINAL_WINDOWS) {
const isWoW64 = !!process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432');
_DEFAULT_TERMINAL_WINDOWS = `${process.env.windir ? process.env.windir : 'C:\\Windows'}\\${isWoW64 ? 'Sysnative' : 'System32'}\\cmd.exe`;
}
return _DEFAULT_TERMINAL_WINDOWS;
}
abstract class TerminalLauncher implements ITerminalLauncher {
runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Promise<number | undefined> {
return this.runInTerminal0(args.title!, args.cwd, args.args, args.env || {}, config);
}
abstract runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment | {}, config: ITerminalSettings): Promise<number | undefined>;
}
class WinTerminalService extends TerminalLauncher {
private static readonly CMD = 'cmd.exe';
runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise<number | undefined> {
const exec = configuration.external.windowsExec || getDefaultTerminalWindows();
return new Promise<number | undefined>((resolve, reject) => {
const title = `"${dir} - ${TERMINAL_TITLE}"`;
const command = `""${args.join('" "')}" & pause"`; // use '|' to only pause on non-zero exit code
const cmdArgs = [
'/c', 'start', title, '/wait', exec, '/c', command
];
// merge environment variables into a copy of the process.env
const env = assign({}, process.env, envVars);
// delete environment variables that have a null value
Object.keys(env).filter(v => env[v] === null).forEach(key => delete env[key]);
const options: any = {
cwd: dir,
env: env,
windowsVerbatimArguments: true
};
const cmd = cp.spawn(WinTerminalService.CMD, cmdArgs, options);
cmd.on('error', err => {
reject(improveError(err));
});
resolve(undefined);
});
if (externalTerminalService) {
externalTerminalService.runInTerminal(args.title!, args.cwd, args.args, args.env || {}, config.external || {});
}
}
class MacTerminalService extends TerminalLauncher {
private static readonly DEFAULT_TERMINAL_OSX = 'Terminal.app';
private static readonly OSASCRIPT = '/usr/bin/osascript'; // osascript is the AppleScript interpreter on OS X
runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise<number | undefined> {
const terminalApp = configuration.external.osxExec || MacTerminalService.DEFAULT_TERMINAL_OSX;
return new Promise<number | undefined>((resolve, reject) => {
if (terminalApp === MacTerminalService.DEFAULT_TERMINAL_OSX || terminalApp === 'iTerm.app') {
// On OS X we launch an AppleScript that creates (or reuses) a Terminal window
// and then launches the program inside that window.
const script = terminalApp === MacTerminalService.DEFAULT_TERMINAL_OSX ? 'TerminalHelper' : 'iTermHelper';
const scriptpath = getPathFromAmdModule(require, `vs/workbench/contrib/externalTerminal/electron-browser/${script}.scpt`);
const osaArgs = [
scriptpath,
'-t', title || TERMINAL_TITLE,
'-w', dir,
];
for (let a of args) {
osaArgs.push('-a');
osaArgs.push(a);
}
if (envVars) {
for (let key in envVars) {
const value = envVars[key];
if (value === null) {
osaArgs.push('-u');
osaArgs.push(key);
} else {
osaArgs.push('-e');
osaArgs.push(`${key}=${value}`);
}
}
}
let stderr = '';
const osa = cp.spawn(MacTerminalService.OSASCRIPT, osaArgs);
osa.on('error', err => {
reject(improveError(err));
});
osa.stderr.on('data', (data) => {
stderr += data.toString();
});
osa.on('exit', (code: number) => {
if (code === 0) { // OK
resolve(undefined);
} else {
if (stderr) {
const lines = stderr.split('\n', 1);
reject(new Error(lines[0]));
} else {
reject(new Error(nls.localize('mac.terminal.script.failed', "Script '{0}' failed with exit code {1}", script, code)));
}
}
});
} else {
reject(new Error(nls.localize('mac.terminal.type.not.supported', "'{0}' not supported", terminalApp)));
}
});
}
}
class LinuxTerminalService extends TerminalLauncher {
private static readonly WAIT_MESSAGE = nls.localize('press.any.key', "Press any key to continue...");
runInTerminal0(title: string, dir: string, args: string[], envVars: env.IProcessEnvironment, configuration: ITerminalSettings): Promise<number | undefined> {
const terminalConfig = configuration.external;
const execThenable: Promise<string> = terminalConfig.linuxExec ? Promise.resolve(terminalConfig.linuxExec) : getDefaultTerminalLinuxReady();
return new Promise<number | undefined>((resolve, reject) => {
let termArgs: string[] = [];
//termArgs.push('--title');
//termArgs.push(`"${TERMINAL_TITLE}"`);
execThenable.then(exec => {
if (exec.indexOf('gnome-terminal') >= 0) {
termArgs.push('-x');
} else {
termArgs.push('-e');
}
termArgs.push('bash');
termArgs.push('-c');
const bashCommand = `${quote(args)}; echo; read -p "${LinuxTerminalService.WAIT_MESSAGE}" -n1;`;
termArgs.push(`''${bashCommand}''`); // wrapping argument in two sets of ' because node is so "friendly" that it removes one set...
// merge environment variables into a copy of the process.env
const env = assign({}, process.env, envVars);
// delete environment variables that have a null value
Object.keys(env).filter(v => env[v] === null).forEach(key => delete env[key]);
const options: any = {
cwd: dir,
env: env
};
let stderr = '';
const cmd = cp.spawn(exec, termArgs, options);
cmd.on('error', err => {
reject(improveError(err));
});
cmd.stderr.on('data', (data) => {
stderr += data.toString();
});
cmd.on('exit', (code: number) => {
if (code === 0) { // OK
resolve(undefined);
} else {
if (stderr) {
const lines = stderr.split('\n', 1);
reject(new Error(lines[0]));
} else {
reject(new Error(nls.localize('linux.term.failed', "'{0}' failed with exit code {1}", exec, code)));
}
}
});
});
});
}
}
/**
* tries to turn OS errors into more meaningful error messages
*/
function improveError(err: Error): Error {
if (err['errno'] === 'ENOENT' && err['path']) {
return new Error(nls.localize('ext.term.app.not.found', "can't find terminal application '{0}'", err['path']));
}
return err;
}
/**
* Quote args if necessary and combine into a space separated string.
*/
function quote(args: string[]): string {
let r = '';
for (let a of args) {
if (a.indexOf(' ') >= 0) {
r += '"' + a + '"';
} else {
r += a;
}
r += ' ';
}
return r;
}
export function hasChildProcesses(processId: number): boolean {
if (processId) {
try {
@@ -315,13 +68,13 @@ export function prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments
let shell: string;
const shell_config = config.integrated.shell;
if (env.isWindows) {
shell = shell_config.windows || getDefaultShell(env.Platform.Windows);
shell = shell_config.windows || getSystemShell(env.Platform.Windows);
shellType = ShellType.cmd;
} else if (env.isLinux) {
shell = shell_config.linux || getDefaultShell(env.Platform.Linux);
shell = shell_config.linux || getSystemShell(env.Platform.Linux);
shellType = ShellType.bash;
} else if (env.isMacintosh) {
shell = shell_config.osx || getDefaultShell(env.Platform.Mac);
shell = shell_config.osx || getSystemShell(env.Platform.Mac);
shellType = ShellType.bash;
} else {
throw new Error('Unknown platform');
@@ -348,8 +101,10 @@ export function prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments
quote = (s: string) => {
s = s.replace(/\'/g, '\'\'');
if (s.length > 0 && s.charAt(s.length - 1) === '\\') {
return `'${s}\\'`;
}
return `'${s}'`;
//return s.indexOf(' ') >= 0 || s.indexOf('\'') >= 0 || s.indexOf('"') >= 0 ? `'${s}'` : s;
};
if (args.cwd) {
@@ -378,7 +133,7 @@ export function prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments
quote = (s: string) => {
s = s.replace(/\"/g, '""');
return (s.indexOf(' ') >= 0 || s.indexOf('"') >= 0) ? `"${s}"` : s;
return (s.indexOf(' ') >= 0 || s.indexOf('"') >= 0 || s.length === 0) ? `"${s}"` : s;
};
if (args.cwd) {
@@ -407,8 +162,8 @@ export function prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments
case ShellType.bash:
quote = (s: string) => {
s = s.replace(/\"/g, '\\"');
return (s.indexOf(' ') >= 0 || s.indexOf('\\') >= 0) ? `"${s}"` : s;
s = s.replace(/([\"\\])/g, '\\$1');
return (s.indexOf(' ') >= 0 || s.length === 0) ? `"${s}"` : s;
};
const hardQuote = (s: string) => {