提交 65a12a2b 编写于 作者: I isidor

debug: bring together all ways to start debugging

fixes #22312
fixes #21835
上级 63389c46
...@@ -12,10 +12,9 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; ...@@ -12,10 +12,9 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ICommandService } from 'vs/platform/commands/common/commands'; import { ICommandService } from 'vs/platform/commands/common/commands';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IFileService } from 'vs/platform/files/common/files'; import { IFileService } from 'vs/platform/files/common/files';
import { IDebugService, IConfig, State, IProcess, IThread, IEnablement, IBreakpoint, IStackFrame, IFunctionBreakpoint, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, IExpression, REPL_ID } import { IDebugService, State, IProcess, IThread, IEnablement, IBreakpoint, IStackFrame, IFunctionBreakpoint, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, IExpression, REPL_ID }
from 'vs/workbench/parts/debug/common/debug'; from 'vs/workbench/parts/debug/common/debug';
import { Variable, Expression, Thread, Breakpoint, Process } from 'vs/workbench/parts/debug/common/debugModel'; import { Variable, Expression, Thread, Breakpoint, Process } from 'vs/workbench/parts/debug/common/debugModel';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IPartService } from 'vs/workbench/services/part/common/partService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
...@@ -105,11 +104,6 @@ export class ConfigureAction extends AbstractDebugAction { ...@@ -105,11 +104,6 @@ export class ConfigureAction extends AbstractDebugAction {
} }
} }
interface StartSessionResult {
status: 'ok' | 'initialConfiguration' | 'saveConfiguration';
content?: string;
};
export class StartAction extends AbstractDebugAction { export class StartAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.start'; static ID = 'workbench.action.debug.start';
static LABEL = nls.localize('startDebug', "Start Debugging"); static LABEL = nls.localize('startDebug', "Start Debugging");
...@@ -117,10 +111,7 @@ export class StartAction extends AbstractDebugAction { ...@@ -117,10 +111,7 @@ export class StartAction extends AbstractDebugAction {
constructor(id: string, label: string, constructor(id: string, label: string,
@IDebugService debugService: IDebugService, @IDebugService debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService, @IKeybindingService keybindingService: IKeybindingService,
@ICommandService private commandService: ICommandService, @IWorkspaceContextService private contextService: IWorkspaceContextService
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IFileService private fileService: IFileService,
@ITextFileService private textFileService: ITextFileService
) { ) {
super(id, label, 'debug-action start', debugService, keybindingService); super(id, label, 'debug-action start', debugService, keybindingService);
this.debugService.getViewModel().onDidSelectConfiguration(() => { this.debugService.getViewModel().onDidSelectConfiguration(() => {
...@@ -129,53 +120,11 @@ export class StartAction extends AbstractDebugAction { ...@@ -129,53 +120,11 @@ export class StartAction extends AbstractDebugAction {
} }
public run(): TPromise<any> { public run(): TPromise<any> {
return this.textFileService.saveAll().then(() => { return this.debugService.startDebugging(undefined, this.isNoDebug());
if (this.debugService.getModel().getProcesses().length === 0) {
this.debugService.removeReplExpressions();
}
const manager = this.debugService.getConfigurationManager();
const configName = this.debugService.getViewModel().selectedConfigurationName;
const compound = manager.getCompound(configName);
if (compound) {
return this.commandService.executeCommand('_workbench.startDebug', configName);
}
let configuration = manager.getConfiguration(configName);
return manager.getStartSessionCommand(configuration ? configuration.type : undefined).then(commandAndType => {
configuration = this.massageConfiguartion(configuration);
if (commandAndType && commandAndType.command) {
return this.commandService.executeCommand(commandAndType.command, configuration || this.getDefaultConfiguration()).then((result: StartSessionResult) => {
if (this.contextService.getWorkspace()) {
if (result && result.status === 'initialConfiguration') {
return manager.openConfigFile(false, commandAndType.type);
}
if (result && result.status === 'saveConfiguration') {
return this.fileService.updateContent(manager.configFileUri, result.content).then(() => manager.openConfigFile(false));
}
}
return undefined;
});
}
if (configName) {
return this.commandService.executeCommand('_workbench.startDebug', configuration || configName);
}
if (this.contextService.getWorkspace() && commandAndType) {
return manager.openConfigFile(false, commandAndType.type);
}
return undefined;
});
});
} }
protected getDefaultConfiguration(): any { protected isNoDebug(): boolean {
return {}; return false;
}
protected massageConfiguartion(config: IConfig): IConfig {
return config;
} }
// Disabled if the launch drop down shows the launch config that is already running. // Disabled if the launch drop down shows the launch config that is already running.
...@@ -190,27 +139,8 @@ export class RunAction extends StartAction { ...@@ -190,27 +139,8 @@ export class RunAction extends StartAction {
static ID = 'workbench.action.debug.run'; static ID = 'workbench.action.debug.run';
static LABEL = nls.localize('startWithoutDebugging', "Start Without Debugging"); static LABEL = nls.localize('startWithoutDebugging', "Start Without Debugging");
constructor(id: string, label: string, protected isNoDebug(): boolean {
@IDebugService debugService: IDebugService, return true;
@IKeybindingService keybindingService: IKeybindingService,
@ICommandService commandService: ICommandService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IFileService fileService: IFileService,
@ITextFileService textFileService: ITextFileService
) {
super(id, label, debugService, keybindingService, commandService, contextService, fileService, textFileService);
}
protected getDefaultConfiguration(): any {
return { noDebug: true };
}
protected massageConfiguartion(config: IConfig): IConfig {
if (config) {
config.noDebug = true;
}
return config;
} }
} }
......
...@@ -33,7 +33,7 @@ class DebugEntry extends Model.QuickOpenEntry { ...@@ -33,7 +33,7 @@ class DebugEntry extends Model.QuickOpenEntry {
} }
// Run selected debug configuration // Run selected debug configuration
this.debugService.getViewModel().setSelectedConfigurationName(this.configurationName); this.debugService.getViewModel().setSelectedConfigurationName(this.configurationName);
this.debugService.createProcess(this.configurationName).done(undefined, errors.onUnexpectedError); this.debugService.startDebugging().done(undefined, errors.onUnexpectedError);
return true; return true;
} }
......
...@@ -488,10 +488,17 @@ export interface IDebugService { ...@@ -488,10 +488,17 @@ export interface IDebugService {
*/ */
removeWatchExpressions(id?: string): void; removeWatchExpressions(id?: string): void;
/**
* Starts debugging. If the configName is not passed uses the selected configuration in the debug dropdown.
* Also saves all files, manages if compounds are present in the configuration
* and calls the startSessionCommand if an adapter registered it.
*/
startDebugging(configName?: string, noDebug?: boolean): TPromise<any>;
/** /**
* Creates a new debug process. Depending on the configuration will either 'launch' or 'attach'. * Creates a new debug process. Depending on the configuration will either 'launch' or 'attach'.
*/ */
createProcess(configurationOrName: IConfig | string): TPromise<any>; createProcess(config: IConfig): TPromise<any>;
/** /**
* Restarts a process or creates a new one if there is no active session. * Restarts a process or creates a new one if there is no active session.
......
...@@ -11,7 +11,7 @@ import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; ...@@ -11,7 +11,7 @@ import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IListService } from 'vs/platform/list/browser/listService'; import { IListService } from 'vs/platform/list/browser/listService';
import { IDebugService, IEnablement, CONTEXT_NOT_IN_DEBUG_MODE, CONTEXT_IN_DEBUG_MODE, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution } from 'vs/workbench/parts/debug/common/debug'; import { IDebugService, IConfig, IEnablement, CONTEXT_NOT_IN_DEBUG_MODE, CONTEXT_IN_DEBUG_MODE, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution } from 'vs/workbench/parts/debug/common/debug';
import { Expression, Variable, Breakpoint, FunctionBreakpoint } from 'vs/workbench/parts/debug/common/debugModel'; import { Expression, Variable, Breakpoint, FunctionBreakpoint } from 'vs/workbench/parts/debug/common/debugModel';
import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions'; import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
...@@ -21,13 +21,18 @@ export function registerCommands(): void { ...@@ -21,13 +21,18 @@ export function registerCommands(): void {
KeybindingsRegistry.registerCommandAndKeybindingRule({ KeybindingsRegistry.registerCommandAndKeybindingRule({
id: '_workbench.startDebug', id: '_workbench.startDebug',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
handler(accessor: ServicesAccessor, configurationOrName: any) { handler(accessor: ServicesAccessor, configurationOrName: IConfig | string) {
const debugService = accessor.get(IDebugService); const debugService = accessor.get(IDebugService);
if (!configurationOrName) { if (!configurationOrName) {
configurationOrName = debugService.getViewModel().selectedConfigurationName; configurationOrName = debugService.getViewModel().selectedConfigurationName;
} }
return debugService.createProcess(configurationOrName); if (typeof configurationOrName === 'string') {
debugService.getViewModel().setSelectedConfigurationName(configurationOrName);
return debugService.startDebugging();
} else {
return debugService.createProcess(configurationOrName);
}
}, },
when: CONTEXT_NOT_IN_DEBUG_MODE, when: CONTEXT_NOT_IN_DEBUG_MODE,
primary: undefined primary: undefined
......
...@@ -28,6 +28,7 @@ import { IWindowsService } from 'vs/platform/windows/common/windows'; ...@@ -28,6 +28,7 @@ import { IWindowsService } from 'vs/platform/windows/common/windows';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
import { TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc'; import { TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import * as debug from 'vs/workbench/parts/debug/common/debug'; import * as debug from 'vs/workbench/parts/debug/common/debug';
import { RawDebugSession } from 'vs/workbench/parts/debug/electron-browser/rawDebugSession'; import { RawDebugSession } from 'vs/workbench/parts/debug/electron-browser/rawDebugSession';
...@@ -56,6 +57,11 @@ const DEBUG_EXCEPTION_BREAKPOINTS_KEY = 'debug.exceptionbreakpoint'; ...@@ -56,6 +57,11 @@ const DEBUG_EXCEPTION_BREAKPOINTS_KEY = 'debug.exceptionbreakpoint';
const DEBUG_WATCH_EXPRESSIONS_KEY = 'debug.watchexpressions'; const DEBUG_WATCH_EXPRESSIONS_KEY = 'debug.watchexpressions';
const DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname'; const DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname';
interface StartSessionResult {
status: 'ok' | 'initialConfiguration' | 'saveConfiguration';
content?: string;
};
export class DebugService implements debug.IDebugService { export class DebugService implements debug.IDebugService {
public _serviceBrand: any; public _serviceBrand: any;
...@@ -92,6 +98,7 @@ export class DebugService implements debug.IDebugService { ...@@ -92,6 +98,7 @@ export class DebugService implements debug.IDebugService {
@ITaskService private taskService: ITaskService, @ITaskService private taskService: ITaskService,
@IFileService private fileService: IFileService, @IFileService private fileService: IFileService,
@IConfigurationService private configurationService: IConfigurationService, @IConfigurationService private configurationService: IConfigurationService,
@ICommandService private commandService: ICommandService
) { ) {
this.toDispose = []; this.toDispose = [];
this.toDisposeOnSessionEnd = new Map<string, lifecycle.IDisposable[]>(); this.toDisposeOnSessionEnd = new Map<string, lifecycle.IDisposable[]>();
...@@ -559,24 +566,63 @@ export class DebugService implements debug.IDebugService { ...@@ -559,24 +566,63 @@ export class DebugService implements debug.IDebugService {
this.model.removeWatchExpressions(id); this.model.removeWatchExpressions(id);
} }
public createProcess(configurationOrName: debug.IConfig | string): TPromise<any> { public startDebugging(configName?: string, noDebug = false): TPromise<any> {
return this.textFileService.saveAll().then(() => this.configurationService.reloadConfiguration()) // make sure configuration is up to date return this.textFileService.saveAll().then(() => {
.then(() => this.extensionService.onReady() if (this.model.getProcesses().length === 0) {
.then(() => { this.removeReplExpressions();
const compound = typeof configurationOrName === 'string' ? this.configurationManager.getCompound(configurationOrName) : null; }
if (compound) { const manager = this.getConfigurationManager();
if (!compound.configurations) { configName = configName || this.viewModel.selectedConfigurationName;
return TPromise.wrapError(new Error(nls.localize({ key: 'compoundMustHaveConfigurations', comment: ['compound indicates a "compounds" configuration item', '"configurations" is an attribute and should not be localized'] }, const config = manager.getConfiguration(configName);
"Compound must have \"configurations\" attribute set in order to start multiple configurations."))); const compound = manager.getCompound(configName);
if (compound) {
if (!compound.configurations) {
return TPromise.wrapError(new Error(nls.localize({ key: 'compoundMustHaveConfigurations', comment: ['compound indicates a "compounds" configuration item', '"configurations" is an attribute and should not be localized'] },
"Compound must have \"configurations\" attribute set in order to start multiple configurations.")));
}
return TPromise.join(compound.configurations.map(name => this.startDebugging(name)));
}
if (configName && !config) {
return TPromise.wrapError(new Error(nls.localize('configMissing', "Configuration '{0}' is missing in 'launch.json'.", configName)));
}
return manager.getStartSessionCommand(config ? config.type : undefined).then(commandAndType => {
if (noDebug && config) {
config.noDebug = true;
}
if (commandAndType && commandAndType.command) {
const defaultConfig = noDebug ? { noDebug: true } : {};
return this.commandService.executeCommand(commandAndType.command, config || defaultConfig).then((result: StartSessionResult) => {
if (this.contextService.getWorkspace()) {
if (result && result.status === 'initialConfiguration') {
return manager.openConfigFile(false, commandAndType.type);
}
if (result && result.status === 'saveConfiguration') {
return this.fileService.updateContent(manager.configFileUri, result.content).then(() => manager.openConfigFile(false));
}
} }
return undefined;
});
}
return TPromise.join(compound.configurations.map(name => this.createProcess(name))); if (config) {
} return this.createProcess(config);
const config = typeof configurationOrName === 'string' ? this.configurationManager.getConfiguration(configurationOrName) : configurationOrName; }
if (!config) { if (this.contextService.getWorkspace() && commandAndType) {
return TPromise.wrapError(new Error(nls.localize('configMissing', "Configuration '{0}' is missing in 'launch.json'.", configurationOrName))); return manager.openConfigFile(false, commandAndType.type);
} }
return undefined;
});
});
}
public createProcess(config: debug.IConfig): TPromise<any> {
return this.textFileService.saveAll().then(() => this.configurationService.reloadConfiguration()) // make sure configuration is up to date
.then(() => this.extensionService.onReady()
.then(() => {
return this.configurationManager.resloveConfiguration(config).then(resolvedConfig => { return this.configurationManager.resloveConfiguration(config).then(resolvedConfig => {
if (!resolvedConfig) { if (!resolvedConfig) {
// User canceled resolving of interactive variables, silently return // User canceled resolving of interactive variables, silently return
......
...@@ -71,7 +71,11 @@ export class MockDebugService implements debug.IDebugService { ...@@ -71,7 +71,11 @@ export class MockDebugService implements debug.IDebugService {
public removeWatchExpressions(id?: string): void { } public removeWatchExpressions(id?: string): void { }
public createProcess(configurationOrName: debug.IConfig | string): TPromise<any> { public startDebugging(configName?: string, noDebug?: boolean): TPromise<any> {
return TPromise.as(null);
}
public createProcess(config: debug.IConfig): TPromise<any> {
return TPromise.as(null); return TPromise.as(null);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册