提交 c5ed5b07 编写于 作者: D Daniel Imms

Merge remote-tracking branch 'origin/master' into tyriar/r136_windows_remote_links

{
"name": "code-oss-dev",
"version": "1.36.0",
"distro": "5fc996cf23a90ee6ea8d55df47948fcccfd7b613",
"distro": "0293a04fc4ec308a7770025ead5660e2fb9667a9",
"author": {
"name": "Microsoft Corporation"
},
......
......@@ -206,6 +206,11 @@ export interface IFileDialogService {
*/
pickWorkspaceAndOpen(options: IPickAndOpenOptions): Promise<void>;
/**
* Shows a save file file dialog and save the file at the chosen file URI.
*/
pickFileToSave(options: ISaveDialogOptions): Promise<URI | undefined>;
/**
* Shows a save file dialog and returns the chosen file URI.
*/
......
......@@ -54,6 +54,24 @@ export class OpenLocalFileAction extends Action {
}
}
export class SaveLocalFileAction extends Action {
static readonly ID = 'workbench.action.files.saveLocalFile';
static LABEL = nls.localize('saveLocalFile', "Save Local File...");
constructor(
id: string,
label: string,
@IFileDialogService private readonly dialogService: IFileDialogService
) {
super(id, label);
}
run(event?: any, data?: ITelemetryData): Promise<any> {
return this.dialogService.pickFileToSave({ availableFileSystems: [Schemas.file] });
}
}
export class OpenFolderAction extends Action {
static readonly ID = 'workbench.action.files.openFolder';
......
......@@ -700,8 +700,7 @@ body[data-exploration="icon-exploration"] .extensions-viewlet > .extensions .ext
Panels
****************/
body[data-exploration="icon-exploration"] .monaco-workbench .hide-panel-action,
.hc-black .monaco-workbench .hide-panel-action {
body[data-exploration="icon-exploration"] .monaco-workbench .hide-panel-action {
-webkit-mask-image: url("images/panel/close-alt1.svg");
}
......@@ -947,7 +946,7 @@ body[data-exploration="icon-exploration"] .monaco-workbench .symbol-icon.operato
background-color: var(--blue);
}
ody[data-exploration="icon-exploration"] .monaco-workbench .symbol-icon.type-parameter::before {
body[data-exploration="icon-exploration"] .monaco-workbench .symbol-icon.type-parameter::before {
-webkit-mask-image: url("images/intellisense/parameter-alt1.svg");
}
......
......@@ -27,7 +27,7 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { DebugEditorModelManager } from 'vs/workbench/contrib/debug/browser/debugEditorModelManager';
import { StartAction, AddFunctionBreakpointAction, ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { DebugToolBar } from 'vs/workbench/contrib/debug/browser/debugToolBar';
import * as service from 'vs/workbench/contrib/debug/electron-browser/debugService';
import * as service from 'vs/workbench/contrib/debug/browser/debugService';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, REVERSE_CONTINUE_ID, STEP_BACK_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID } from 'vs/workbench/contrib/debug/browser/debugCommands';
import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
......@@ -249,6 +249,11 @@ configurationRegistry.registerConfiguration({
description: nls.localize('debug.console.lineHeight', "Controls the line height in pixels in the debug console. Use 0 to compute the line height from the font size."),
default: 0
},
'debug.console.wordWrap': {
type: 'boolean',
description: nls.localize('debug.console.wordWrap', "Controls if the lines should wrap in the debug console."),
default: true
},
'launch': {
type: 'object',
description: nls.localize({ comment: ['This is the description for a setting'], key: 'launch' }, "Global debug launch configuration. Should be used as an alternative to 'launch.json' that is shared across workspaces."),
......
......@@ -21,13 +21,12 @@ import { IFileService } from 'vs/platform/files/common/files';
import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterDescriptorFactory, IDebugAdapter, ITerminalSettings, ITerminalLauncher, IDebugSession, IAdapterDescriptor, CONTEXT_DEBUG_CONFIGURATION_TYPE, IDebugAdapterFactory, IDebugService } from 'vs/workbench/contrib/debug/common/debug';
import { Debugger } from 'vs/workbench/contrib/debug/node/debugger';
import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterDescriptorFactory, IDebugAdapter, ITerminalSettings, ITerminalLauncher, IDebugSession, IAdapterDescriptor, CONTEXT_DEBUG_CONFIGURATION_TYPE, IDebugAdapterFactory, IDebugService, IDebugHelperService } from 'vs/workbench/contrib/debug/common/debug';
import { Debugger } from 'vs/workbench/contrib/debug/common/debugger';
import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { TerminalLauncher } from 'vs/workbench/contrib/debug/electron-browser/terminalSupport';
import { Registry } from 'vs/platform/registry/common/platform';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { launchSchema, debuggersExtPoint, breakpointsExtPoint } from 'vs/workbench/contrib/debug/common/debugSchemas';
......@@ -67,7 +66,8 @@ export class ConfigurationManager implements IConfigurationManager {
@IStorageService private readonly storageService: IStorageService,
@ILifecycleService lifecycleService: ILifecycleService,
@IExtensionService private readonly extensionService: IExtensionService,
@IContextKeyService contextKeyService: IContextKeyService
@IContextKeyService contextKeyService: IContextKeyService,
@IDebugHelperService private readonly debugHelperService: IDebugHelperService
) {
this.configProviders = [];
this.adapterDescriptorFactories = [];
......@@ -114,7 +114,7 @@ export class ConfigurationManager implements IConfigurationManager {
let tl: ITerminalLauncher | undefined = this.debugAdapterFactories.get(debugType);
if (!tl) {
if (!this.terminalLauncher) {
this.terminalLauncher = this.instantiationService.createInstance(TerminalLauncher);
this.terminalLauncher = this.debugHelperService.createTerminalLauncher(this.instantiationService);
}
tl = this.terminalLauncher;
}
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ServiceIdentifier, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITerminalLauncher, IDebugHelperService, ILaunchVSCodeArguments } from 'vs/workbench/contrib/debug/common/debug';
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 BrowserDebugHelperService implements IDebugHelperService {
_serviceBrand: ServiceIdentifier<IDebugHelperService>;
createTerminalLauncher(instantiationService: IInstantiationService): ITerminalLauncher {
throw new Error('Method createTerminalLauncher not implemented.');
}
launchVsCode(vscodeArgs: ILaunchVSCodeArguments): Promise<number> {
throw new Error('Method launchVsCode not implemented.');
}
createTelemetryService(configurationService: IConfigurationService, args: string[]): TelemetryService | undefined {
return undefined;
}
}
registerSingleton(IDebugHelperService, BrowserDebugHelperService);
\ No newline at end of file
......@@ -21,7 +21,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { DebugModel, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, Expression } from 'vs/workbench/contrib/debug/common/debugModel';
import { ViewModel } from 'vs/workbench/contrib/debug/common/debugViewModel';
import * as debugactions from 'vs/workbench/contrib/debug/browser/debugActions';
import { ConfigurationManager } from 'vs/workbench/contrib/debug/electron-browser/debugConfigurationManager';
import { ConfigurationManager } from 'vs/workbench/contrib/debug/browser/debugConfigurationManager';
import Constants from 'vs/workbench/contrib/markers/browser/constants';
import { ITaskService, ITaskSummary } from 'vs/workbench/contrib/tasks/common/taskService';
import { TaskError } from 'vs/workbench/contrib/tasks/common/taskSystem';
......@@ -39,7 +39,7 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IAction, Action } from 'vs/base/common/actions';
import { deepClone, equals } from 'vs/base/common/objects';
import { DebugSession } from 'vs/workbench/contrib/debug/electron-browser/debugSession';
import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IEnablement, IBreakpoint, IBreakpointData, ICompound, IGlobalConfig, IStackFrame, AdapterEndEvent, getStateLabel } from 'vs/workbench/contrib/debug/common/debug';
import { isExtensionHostDebugging } from 'vs/workbench/contrib/debug/common/debugUtils';
......
......@@ -12,12 +12,12 @@ import { Event, Emitter } from 'vs/base/common/event';
import { CompletionItem, completionKindFromString } from 'vs/editor/common/modes';
import { Position } from 'vs/editor/common/core/position';
import * as aria from 'vs/base/browser/ui/aria/aria';
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration, IReplElement, IStackFrame, IExpression, IReplElementSource } from 'vs/workbench/contrib/debug/common/debug';
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration, IReplElement, IStackFrame, IExpression, IReplElementSource, IDebugHelperService } from 'vs/workbench/contrib/debug/common/debug';
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
import { mixin } from 'vs/base/common/objects';
import { Thread, ExpressionContainer, DebugModel } from 'vs/workbench/contrib/debug/common/debugModel';
import { RawDebugSession } from 'vs/workbench/contrib/debug/electron-browser/rawDebugSession';
import product from 'vs/platform/product/node/product';
import { RawDebugSession } from 'vs/workbench/contrib/debug/browser/rawDebugSession';
import { IProductService } from 'vs/platform/product/common/product';
import { IWorkspaceFolder, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { RunOnceScheduler } from 'vs/base/common/async';
......@@ -30,7 +30,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ReplModel } from 'vs/workbench/contrib/debug/common/replModel';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ISignService } from 'vs/platform/sign/common/sign';
......@@ -66,9 +65,10 @@ export class DebugSession implements IDebugSession {
@IConfigurationService private readonly configurationService: IConfigurationService,
@IViewletService private readonly viewletService: IViewletService,
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@INotificationService private readonly notificationService: INotificationService,
@ISignService private readonly signService: ISignService
@ISignService private readonly signService: ISignService,
@IProductService private readonly productService: IProductService,
@IDebugHelperService private readonly debugUIService: IDebugHelperService
) {
this.id = generateUuid();
this.repl = new ReplModel(this);
......@@ -169,7 +169,7 @@ export class DebugSession implements IDebugSession {
return dbgr.createDebugAdapter(this).then(debugAdapter => {
this.raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService, this.environmentService, this.signService);
this.raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService, this.signService, this.debugUIService);
return this.raw!.start().then(() => {
......@@ -177,7 +177,7 @@ export class DebugSession implements IDebugSession {
return this.raw!.initialize({
clientID: 'vscode',
clientName: product.nameLong,
clientName: this.productService.nameLong,
adapterID: this.configuration.type,
pathFormat: 'path',
linesStartAt1: true,
......
......@@ -9,28 +9,11 @@ import * as objects from 'vs/base/common/objects';
import { Action } from 'vs/base/common/actions';
import * as errors from 'vs/base/common/errors';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { formatPII, isUri } from 'vs/workbench/contrib/debug/common/debugUtils';
import { IDebugAdapter, IConfig, AdapterEndEvent, IDebugger } from 'vs/workbench/contrib/debug/common/debug';
import { formatPII } from 'vs/workbench/contrib/debug/common/debugUtils';
import { IDebugAdapter, IConfig, AdapterEndEvent, IDebugger, IDebugHelperService, ILaunchVSCodeArguments } from 'vs/workbench/contrib/debug/common/debug';
import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
import * as cp from 'child_process';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ISignService } from 'vs/platform/sign/common/sign';
/**
* This interface represents a single command line argument split into a "prefix" and a "path" half.
* The optional "prefix" contains arbitrary text and the optional "path" contains a file system path.
* Concatenating both results in the original command line argument.
*/
export interface ILaunchVSCodeArgument {
prefix?: string;
path?: string;
}
export interface ILaunchVSCodeArguments {
args: ILaunchVSCodeArgument[];
env?: { [key: string]: string | null; };
}
/**
* Encapsulates the DebugAdapter lifecycle and some idiosyncrasies of the Debug Adapter Protocol.
*/
......@@ -72,8 +55,8 @@ export class RawDebugSession {
dbgr: IDebugger,
private readonly telemetryService: ITelemetryService,
public readonly customTelemetryService: ITelemetryService | undefined,
private readonly environmentService: IEnvironmentService,
private readonly signService: ISignService
private readonly signService: ISignService,
private readonly debugUIService: IDebugHelperService
) {
this.debugAdapter = debugAdapter;
this._capabilities = Object.create(null);
......@@ -520,7 +503,7 @@ export class RawDebugSession {
switch (request.command) {
case 'launchVSCode':
this.launchVsCode(<ILaunchVSCodeArguments>request.arguments).then(pid => {
this.debugUIService.launchVsCode(<ILaunchVSCodeArguments>request.arguments).then(pid => {
response.body = {
processId: pid
};
......@@ -566,82 +549,6 @@ export class RawDebugSession {
}
}
private launchVsCode(vscodeArgs: ILaunchVSCodeArguments): Promise<number> {
const spawnOpts: cp.SpawnOptions = {
detached: false // https://github.com/Microsoft/vscode/issues/57018
};
if (vscodeArgs.env) {
// merge environment variables into a copy of the process.env
const envArgs = objects.mixin(objects.mixin({}, process.env), vscodeArgs.env);
// and delete some if necessary
Object.keys(envArgs).filter(k => envArgs[k] === null).forEach(key => delete envArgs[key]);
spawnOpts.env = envArgs;
}
let spawnArgs = vscodeArgs.args.map(a => {
if ((a.prefix === '--file-uri=' || a.prefix === '--folder-uri=') && !isUri(a.path)) {
return (a.path || '');
}
return (a.prefix || '') + (a.path || '');
});
let runtimeExecutable = this.environmentService['execPath'];
if (!runtimeExecutable) {
return Promise.reject(new Error(`VS Code executable unknown`));
}
// if VS Code runs out of sources, add the VS Code workspace path as the first argument so that Electron turns into VS Code
const electronIdx = runtimeExecutable.indexOf(process.platform === 'win32' ? '\\.build\\electron\\' : '/.build/electron/');
if (electronIdx > 0) {
// guess the VS Code workspace path from the executable
const vscodeWorkspacePath = runtimeExecutable.substr(0, electronIdx);
// only add VS Code workspace path if user hasn't already added that path as a (folder) argument
const x = spawnArgs.filter(a => a.indexOf(vscodeWorkspacePath) === 0);
if (x.length === 0) {
spawnArgs.unshift(vscodeWorkspacePath);
}
}
// Workaround for bug Microsoft/vscode#45832
if (process.platform === 'win32' && runtimeExecutable.indexOf(' ') > 0) {
let foundArgWithSpace = false;
// check whether there is one arg with a space
const args: string[] = [];
for (const a of spawnArgs) {
if (a.indexOf(' ') > 0) {
args.push(`"${a}"`);
foundArgWithSpace = true;
} else {
args.push(a);
}
}
if (foundArgWithSpace) {
spawnArgs = args;
runtimeExecutable = `"${runtimeExecutable}"`;
spawnOpts.shell = true;
}
}
return new Promise((resolve, reject) => {
const process = cp.spawn(runtimeExecutable, spawnArgs, spawnOpts);
process.on('error', error => {
reject(error);
});
process.on('exit', code => {
if (code === 0) {
resolve(process.pid);
} else {
reject(new Error(`VS Code exited with ${code}`));
}
});
});
}
private send<R extends DebugProtocol.Response>(command: string, args: any, timeout?: number): Promise<R> {
return new Promise<R>((completeDispatch, errorDispatch) => {
if (!this.debugAdapter) {
......
......@@ -375,6 +375,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
this.createReplInput(this.container);
this.replDelegate = new ReplDelegate(this.configurationService);
const wordWrap = this.configurationService.getValue<IDebugConfiguration>('debug').console.wordWrap;
this.tree = this.instantiationService.createInstance(WorkbenchAsyncDataTree, treeContainer, this.replDelegate, [
this.instantiationService.createInstance(VariablesRenderer),
this.instantiationService.createInstance(ReplSimpleElementsRenderer),
......@@ -386,11 +387,10 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
identityProvider: { getId: (element: IReplElement) => element.getId() },
mouseSupport: false,
keyboardNavigationLabelProvider: { getKeyboardNavigationLabel: (e: IReplElement) => e },
horizontalScrolling: false,
horizontalScrolling: !wordWrap,
setRowLineHeight: false,
supportDynamicHeights: true
supportDynamicHeights: wordWrap
}) as WorkbenchAsyncDataTree<IDebugSession, IReplElement, FuzzyScore>;
this._register(this.tree.onContextMenu(e => this.onContextMenu(e)));
let lastSelectedString: string;
this._register(this.tree.onMouseClick(() => {
......@@ -742,8 +742,13 @@ class ReplDelegate implements IListVirtualDelegate<IReplElement> {
const countNumberOfLines = (str: string) => Math.max(1, (str.match(/\r\n|\n/g) || []).length);
// Give approximate heights. Repl has dynamic height so the tree will measure the actual height on its own.
const fontSize = this.configurationService.getValue<IDebugConfiguration>('debug').console.fontSize;
const config = this.configurationService.getValue<IDebugConfiguration>('debug');
const fontSize = config.console.fontSize;
const rowHeight = Math.ceil(1.4 * fontSize);
const wordWrap = config.console.wordWrap;
if (!wordWrap) {
return element instanceof Expression ? 2 * rowHeight : rowHeight;
}
// In order to keep scroll position we need to give a good approximation to the tree
// For every 150 characters increase the number of lines needed
......
......@@ -8,7 +8,7 @@ import { URI as uri } from 'vs/base/common/uri';
import severity from 'vs/base/common/severity';
import { Event } from 'vs/base/common/event';
import { IJSONSchemaSnippet } from 'vs/base/common/jsonSchema';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { ITextModel as EditorIModel } from 'vs/editor/common/model';
import { IEditor, ITextEditor } from 'vs/workbench/common/editor';
......@@ -25,6 +25,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { TaskIdentifier } from 'vs/workbench/contrib/tasks/common/tasks';
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
import { ITerminalConfiguration } from 'vs/workbench/contrib/terminal/common/terminal';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
export const VIEWLET_ID = 'workbench.view.debug';
export const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer(VIEWLET_ID);
......@@ -437,6 +438,7 @@ export interface IDebugConfiguration {
fontSize: number;
fontFamily: string;
lineHeight: number;
wordWrap: boolean;
};
}
......@@ -834,3 +836,33 @@ export interface IDebugEditorContribution extends IEditorContribution {
closeBreakpointWidget(): void;
addLaunchConfiguration(): Promise<any>;
}
// temporary debug helper service
export const DEBUG_HELPER_SERVICE_ID = 'debugHelperService';
export const IDebugHelperService = createDecorator<IDebugHelperService>(DEBUG_HELPER_SERVICE_ID);
/**
* This interface represents a single command line argument split into a "prefix" and a "path" half.
* The optional "prefix" contains arbitrary text and the optional "path" contains a file system path.
* Concatenating both results in the original command line argument.
*/
export interface ILaunchVSCodeArgument {
prefix?: string;
path?: string;
}
export interface ILaunchVSCodeArguments {
args: ILaunchVSCodeArgument[];
env?: { [key: string]: string | null; };
}
export interface IDebugHelperService {
_serviceBrand: any;
createTerminalLauncher(instantiationService: IInstantiationService): ITerminalLauncher;
launchVsCode(vscodeArgs: ILaunchVSCodeArguments): Promise<number>;
createTelemetryService(configurationService: IConfigurationService, args: string[]): TelemetryService | undefined;
}
......@@ -4,14 +4,12 @@
*--------------------------------------------------------------------------------------------*/
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 { IConfig, IDebuggerContribution, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager, IDebugAdapter, ITerminalSettings, IDebugger, IDebugSession, IDebugHelperService } 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';
......@@ -19,7 +17,6 @@ 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';
......@@ -37,6 +34,7 @@ export class Debugger implements IDebugger {
@ITextResourcePropertiesService private readonly resourcePropertiesService: ITextResourcePropertiesService,
@IConfigurationResolverService private readonly configurationResolverService: IConfigurationResolverService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IDebugHelperService private readonly debugHelperService: IDebugHelperService
) {
this.debuggerContribution = { type: dbgContribution.type };
this.merge(dbgContribution, extensionDescription);
......@@ -193,24 +191,8 @@ export class Debugger implements IDebugger {
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);
const args = [`${this.getMainExtensionDescriptor().publisher}.${this.type}`, JSON.stringify(data), aiKey];
return this.debugHelperService.createTelemetryService(this.configurationService, args);
});
}
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as objects from 'vs/base/common/objects';
import { isUri } from 'vs/workbench/contrib/debug/common/debugUtils';
import * as cp from 'child_process';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { TerminalLauncher } from 'vs/workbench/contrib/debug/node/terminalSupport';
import { ITerminalLauncher, IDebugHelperService, ILaunchVSCodeArguments } 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(
@IEnvironmentService private readonly environmentService: IEnvironmentService
) {
}
createTerminalLauncher(instantiationService: IInstantiationService): ITerminalLauncher {
return instantiationService.createInstance(TerminalLauncher);
}
launchVsCode(vscodeArgs: ILaunchVSCodeArguments): Promise<number> {
const spawnOpts: cp.SpawnOptions = {
detached: false // https://github.com/Microsoft/vscode/issues/57018
};
if (vscodeArgs.env) {
// merge environment variables into a copy of the process.env
const envArgs = objects.mixin(objects.mixin({}, process.env), vscodeArgs.env);
// and delete some if necessary
Object.keys(envArgs).filter(k => envArgs[k] === null).forEach(key => delete envArgs[key]);
spawnOpts.env = envArgs;
}
let spawnArgs = vscodeArgs.args.map(a => {
if ((a.prefix === '--file-uri=' || a.prefix === '--folder-uri=') && !isUri(a.path)) {
return (a.path || '');
}
return (a.prefix || '') + (a.path || '');
});
let runtimeExecutable = this.environmentService['execPath'];
if (!runtimeExecutable) {
return Promise.reject(new Error(`VS Code executable unknown`));
}
// if VS Code runs out of sources, add the VS Code workspace path as the first argument so that Electron turns into VS Code
const electronIdx = runtimeExecutable.indexOf(process.platform === 'win32' ? '\\.build\\electron\\' : '/.build/electron/');
if (electronIdx > 0) {
// guess the VS Code workspace path from the executable
const vscodeWorkspacePath = runtimeExecutable.substr(0, electronIdx);
// only add VS Code workspace path if user hasn't already added that path as a (folder) argument
const x = spawnArgs.filter(a => a.indexOf(vscodeWorkspacePath) === 0);
if (x.length === 0) {
spawnArgs.unshift(vscodeWorkspacePath);
}
}
// Workaround for bug Microsoft/vscode#45832
if (process.platform === 'win32' && runtimeExecutable.indexOf(' ') > 0) {
let foundArgWithSpace = false;
// check whether there is one arg with a space
const args: string[] = [];
for (const a of spawnArgs) {
if (a.indexOf(' ') > 0) {
args.push(`"${a}"`);
foundArgWithSpace = true;
} else {
args.push(a);
}
}
if (foundArgWithSpace) {
spawnArgs = args;
runtimeExecutable = `"${runtimeExecutable}"`;
spawnOpts.shell = true;
}
}
return new Promise((resolve, reject) => {
const process = cp.spawn(runtimeExecutable, spawnArgs, spawnOpts);
process.on('error', error => {
reject(error);
});
process.on('exit', code => {
if (code === 0) {
resolve(process.pid);
} else {
reject(new Error(`VS Code exited with ${code}`));
}
});
});
}
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);
\ No newline at end of file
......@@ -10,12 +10,12 @@ import { SimpleReplElement, DebugModel, Expression, RawObjectReplElement, StackF
import * as sinon from 'sinon';
import { MockRawSession } from 'vs/workbench/contrib/debug/test/common/mockDebug';
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
import { DebugSession } from 'vs/workbench/contrib/debug/electron-browser/debugSession';
import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession';
import { ReplModel } from 'vs/workbench/contrib/debug/common/replModel';
import { IBreakpointUpdateData } from 'vs/workbench/contrib/debug/common/debug';
function createMockSession(model: DebugModel, name = 'mockSession', parentSession?: DebugSession | undefined): DebugSession {
return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, parentSession, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, parentSession, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
}
suite('Debug - Model', () => {
......@@ -437,7 +437,7 @@ suite('Debug - Model', () => {
// Repl output
test('repl output', () => {
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
const repl = new ReplModel(session);
repl.appendToRepl('first line\n', severity.Error);
repl.appendToRepl('second line ', severity.Error);
......
......@@ -7,7 +7,7 @@ import * as assert from 'assert';
import { join, normalize } from 'vs/base/common/path';
import * as platform from 'vs/base/common/platform';
import { IDebugAdapterExecutable, IConfigurationManager, IConfig, IDebugSession } from 'vs/workbench/contrib/debug/common/debug';
import { Debugger } from 'vs/workbench/contrib/debug/node/debugger';
import { Debugger } from 'vs/workbench/contrib/debug/common/debugger';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { URI } from 'vs/base/common/uri';
import { ExecutableDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter';
......@@ -130,7 +130,7 @@ suite('Debug - Debugger', () => {
const testResourcePropertiesService = new TestTextResourcePropertiesService(configurationService);
setup(() => {
_debugger = new Debugger(configurationManager, debuggerContribution, extensionDescriptor0, configurationService, testResourcePropertiesService, undefined!, undefined!);
_debugger = new Debugger(configurationManager, debuggerContribution, extensionDescriptor0, configurationService, testResourcePropertiesService, undefined!, undefined!, undefined!);
});
teardown(() => {
......
......@@ -25,6 +25,7 @@ interface IConfiguration extends IWindowsConfiguration {
telemetry: { enableCrashReporter: boolean };
keyboard: { touchbar: { enabled: boolean } };
workbench: { list: { horizontalScrolling: boolean }, useExperimentalGridLayout: boolean };
debug: { console: { wordWrap: boolean } };
}
export class SettingsChangeRelauncher extends Disposable implements IWorkbenchContribution {
......@@ -38,6 +39,7 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo
private touchbarEnabled: boolean;
private treeHorizontalScrolling: boolean;
private useGridLayout: boolean;
private debugConsoleWordWrap: boolean;
constructor(
@IWindowsService private readonly windowsService: IWindowsService,
......@@ -109,6 +111,12 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo
changed = true;
}
// Debug console word wrap
if (config.debug && typeof config.debug.console.wordWrap === 'boolean' && config.debug.console.wordWrap !== this.debugConsoleWordWrap) {
this.debugConsoleWordWrap = config.debug.console.wordWrap;
changed = true;
}
// Notify only when changed and we are the focused window (avoids notification spam across windows)
if (notify && changed) {
this.doConfirm(
......
......@@ -14,7 +14,7 @@ import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenTwitterUrlAction, OpenRequestFeatureUrlAction, OpenPrivacyStatementUrlAction, OpenLicenseUrlAction, OpenNewsletterSignupUrlAction } from 'vs/workbench/electron-browser/actions/helpActions';
import { ToggleSharedProcessAction, InspectContextKeysAction, ToggleScreencastModeAction, ToggleDevToolsAction } from 'vs/workbench/electron-browser/actions/developerActions';
import { ShowAboutDialogAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, OpenRecentAction, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ReloadWindowAction, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-browser/actions/windowActions';
import { AddRootFolderAction, GlobalRemoveRootFolderAction, OpenWorkspaceAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, DuplicateWorkspaceInNewWindowAction, OpenFileFolderAction, OpenFileAction, OpenFolderAction, CloseWorkspaceAction, OpenLocalFileAction, OpenLocalFolderAction, OpenLocalFileFolderAction } from 'vs/workbench/browser/actions/workspaceActions';
import { AddRootFolderAction, GlobalRemoveRootFolderAction, OpenWorkspaceAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, DuplicateWorkspaceInNewWindowAction, OpenFileFolderAction, OpenFileAction, OpenFolderAction, CloseWorkspaceAction, OpenLocalFileAction, OpenLocalFolderAction, OpenLocalFileFolderAction, SaveLocalFileAction } from 'vs/workbench/browser/actions/workspaceActions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { inQuickOpenContext, getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
......@@ -45,6 +45,7 @@ import product from 'vs/platform/product/node/product';
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenLocalFolderAction, OpenLocalFolderAction.ID, OpenLocalFolderAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_O) }, RemoteFileDialogContext), 'File: Open Local Folder...', fileCategory);
}
registry.registerWorkbenchAction(new SyncActionDescriptor(SaveLocalFileAction, SaveLocalFileAction.ID, SaveLocalFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_S }, RemoteFileDialogContext), 'File: Save Local File...', fileCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenRecentAction, QuickOpenRecentAction.ID, QuickOpenRecentAction.LABEL), 'File: Quick Open Recent...', fileCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenRecentAction, OpenRecentAction.ID, OpenRecentAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_R, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R } }), 'File: Open Recent...', fileCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'File: Close Workspace', fileCategory);
......
......@@ -187,6 +187,25 @@ export class FileDialogService implements IFileDialogService {
return this.windowService.pickWorkspaceAndOpen(this.toNativeOpenDialogOptions(options));
}
async pickFileToSave(options: ISaveDialogOptions): Promise<URI | undefined> {
const schema = this.getFileSystemSchema(options);
if (this.shouldUseSimplified(schema)) {
if (!options.availableFileSystems) {
options.availableFileSystems = this.ensureFileSchema(schema); // always allow file as well
}
options.title = nls.localize('saveFileAs.title', 'Save As');
return this.saveRemoteResource(options);
}
const result = await this.windowService.showSaveDialog(this.toNativeSaveDialogOptions(options));
if (result) {
return URI.file(result);
}
return;
}
private toNativeSaveDialogOptions(options: ISaveDialogOptions): Electron.SaveDialogOptions {
return {
defaultPath: options.defaultUri && options.defaultUri.fsPath || options.defaultFileName,
......
......@@ -23,7 +23,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { equalsIgnoreCase, format, startsWithIgnoreCase } from 'vs/base/common/strings';
import { OpenLocalFileAction, OpenLocalFileFolderAction, OpenLocalFolderAction } from 'vs/workbench/browser/actions/workspaceActions';
import { OpenLocalFileAction, OpenLocalFileFolderAction, OpenLocalFolderAction, SaveLocalFileAction } from 'vs/workbench/browser/actions/workspaceActions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment';
import { isValidBasename } from 'vs/base/common/extpath';
......@@ -211,7 +211,12 @@ export class RemoteFileDialog {
if (this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1)) {
this.filePickBox.customButton = true;
this.filePickBox.customLabel = nls.localize('remoteFileDialog.local', 'Show Local');
const action = this.allowFileSelection ? (this.allowFolderSelection ? OpenLocalFileFolderAction : OpenLocalFileAction) : OpenLocalFolderAction;
let action;
if (isSave) {
action = SaveLocalFileAction;
} else {
action = this.allowFileSelection ? (this.allowFolderSelection ? OpenLocalFileFolderAction : OpenLocalFileAction) : OpenLocalFolderAction;
}
const keybinding = this.keybindingService.lookupKeybinding(action.ID);
if (keybinding) {
const label = keybinding.getLabel();
......@@ -251,7 +256,10 @@ export class RemoteFileDialog {
}
this.options.defaultUri = undefined;
this.filePickBox.hide();
if (this.requiresTrailing) {
if (isSave) {
// Remove defaultUri and filters to get a consistant experience with the keybinding.
this.options.defaultUri = undefined;
this.options.filters = undefined;
return this.fileDialogService.showSaveDialog(this.options).then(result => {
doResolve(this, result);
});
......
......@@ -653,7 +653,7 @@ export abstract class TextFileService extends Disposable implements ITextFileSer
// Help user to find a name for the file by opening it first
await this.editorService.openEditor({ resource, options: { revealIfOpened: true, preserveFocus: true, } });
return this.fileDialogService.showSaveDialog(this.getSaveDialogOptions(defaultUri));
return this.fileDialogService.pickFileToSave(this.getSaveDialogOptions(defaultUri));
}
private getSaveDialogOptions(defaultUri: URI): ISaveDialogOptions {
......
......@@ -439,6 +439,9 @@ export class TestFileDialogService implements IFileDialogService {
public pickWorkspaceAndOpen(_options: IPickAndOpenOptions): Promise<any> {
return Promise.resolve(0);
}
public pickFileToSave(_options: ISaveDialogOptions): Promise<URI | undefined> {
return Promise.resolve(undefined);
}
public showSaveDialog(_options: ISaveDialogOptions): Promise<URI | undefined> {
return Promise.resolve(undefined);
}
......
......@@ -230,11 +230,12 @@ import 'vs/workbench/contrib/scm/browser/scm.contribution';
import 'vs/workbench/contrib/scm/browser/scmViewlet';
// Debug
import 'vs/workbench/contrib/debug/electron-browser/debug.contribution';
import 'vs/workbench/contrib/debug/browser/debug.contribution';
import 'vs/workbench/contrib/debug/browser/debugQuickOpen';
import 'vs/workbench/contrib/debug/browser/debugEditorContribution';
import 'vs/workbench/contrib/debug/browser/repl';
import 'vs/workbench/contrib/debug/browser/debugViewlet';
import 'vs/workbench/contrib/debug/node/debugHelperService';
// Markers
import 'vs/workbench/contrib/markers/browser/markers.contribution';
......
......@@ -234,11 +234,13 @@ import 'vs/workbench/contrib/scm/browser/scm.contribution';
import 'vs/workbench/contrib/scm/browser/scmViewlet';
// Debug
// import 'vs/workbench/contrib/debug/electron-browser/debug.contribution';
// import 'vs/workbench/contrib/debug/browser/debugQuickOpen';
// import 'vs/workbench/contrib/debug/browser/debugEditorContribution';
// import 'vs/workbench/contrib/debug/browser/repl';
// import 'vs/workbench/contrib/debug/browser/debugViewlet';
import 'vs/workbench/contrib/debug/browser/debug.contribution';
import 'vs/workbench/contrib/debug/browser/debugQuickOpen';
import 'vs/workbench/contrib/debug/browser/debugEditorContribution';
import 'vs/workbench/contrib/debug/browser/repl';
import 'vs/workbench/contrib/debug/browser/debugViewlet';
import 'vs/workbench/contrib/debug/browser/debugHelperService';
// Markers
import 'vs/workbench/contrib/markers/browser/markers.contribution';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册