提交 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';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
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';
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 { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
......@@ -105,11 +104,6 @@ export class ConfigureAction extends AbstractDebugAction {
}
}
interface StartSessionResult {
status: 'ok' | 'initialConfiguration' | 'saveConfiguration';
content?: string;
};
export class StartAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.start';
static LABEL = nls.localize('startDebug', "Start Debugging");
......@@ -117,10 +111,7 @@ export class StartAction extends AbstractDebugAction {
constructor(id: string, label: string,
@IDebugService debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
@ICommandService private commandService: ICommandService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IFileService private fileService: IFileService,
@ITextFileService private textFileService: ITextFileService
@IWorkspaceContextService private contextService: IWorkspaceContextService
) {
super(id, label, 'debug-action start', debugService, keybindingService);
this.debugService.getViewModel().onDidSelectConfiguration(() => {
......@@ -129,53 +120,11 @@ export class StartAction extends AbstractDebugAction {
}
public run(): TPromise<any> {
return this.textFileService.saveAll().then(() => {
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;
});
});
return this.debugService.startDebugging(undefined, this.isNoDebug());
}
protected getDefaultConfiguration(): any {
return {};
}
protected massageConfiguartion(config: IConfig): IConfig {
return config;
protected isNoDebug(): boolean {
return false;
}
// Disabled if the launch drop down shows the launch config that is already running.
......@@ -190,27 +139,8 @@ export class RunAction extends StartAction {
static ID = 'workbench.action.debug.run';
static LABEL = nls.localize('startWithoutDebugging', "Start Without Debugging");
constructor(id: string, label: string,
@IDebugService debugService: IDebugService,
@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;
protected isNoDebug(): boolean {
return true;
}
}
......
......@@ -33,7 +33,7 @@ class DebugEntry extends Model.QuickOpenEntry {
}
// Run selected debug configuration
this.debugService.getViewModel().setSelectedConfigurationName(this.configurationName);
this.debugService.createProcess(this.configurationName).done(undefined, errors.onUnexpectedError);
this.debugService.startDebugging().done(undefined, errors.onUnexpectedError);
return true;
}
......
......@@ -488,10 +488,17 @@ export interface IDebugService {
*/
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'.
*/
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.
......
......@@ -11,7 +11,7 @@ import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
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 { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
......@@ -21,13 +21,18 @@ export function registerCommands(): void {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: '_workbench.startDebug',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
handler(accessor: ServicesAccessor, configurationOrName: any) {
handler(accessor: ServicesAccessor, configurationOrName: IConfig | string) {
const debugService = accessor.get(IDebugService);
if (!configurationOrName) {
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,
primary: undefined
......
......@@ -28,6 +28,7 @@ import { IWindowsService } from 'vs/platform/windows/common/windows';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
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 * as debug from 'vs/workbench/parts/debug/common/debug';
import { RawDebugSession } from 'vs/workbench/parts/debug/electron-browser/rawDebugSession';
......@@ -56,6 +57,11 @@ const DEBUG_EXCEPTION_BREAKPOINTS_KEY = 'debug.exceptionbreakpoint';
const DEBUG_WATCH_EXPRESSIONS_KEY = 'debug.watchexpressions';
const DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname';
interface StartSessionResult {
status: 'ok' | 'initialConfiguration' | 'saveConfiguration';
content?: string;
};
export class DebugService implements debug.IDebugService {
public _serviceBrand: any;
......@@ -92,6 +98,7 @@ export class DebugService implements debug.IDebugService {
@ITaskService private taskService: ITaskService,
@IFileService private fileService: IFileService,
@IConfigurationService private configurationService: IConfigurationService,
@ICommandService private commandService: ICommandService
) {
this.toDispose = [];
this.toDisposeOnSessionEnd = new Map<string, lifecycle.IDisposable[]>();
......@@ -559,24 +566,63 @@ export class DebugService implements debug.IDebugService {
this.model.removeWatchExpressions(id);
}
public createProcess(configurationOrName: debug.IConfig | string): TPromise<any> {
return this.textFileService.saveAll().then(() => this.configurationService.reloadConfiguration()) // make sure configuration is up to date
.then(() => this.extensionService.onReady()
.then(() => {
const compound = typeof configurationOrName === 'string' ? this.configurationManager.getCompound(configurationOrName) : null;
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.")));
public startDebugging(configName?: string, noDebug = false): TPromise<any> {
return this.textFileService.saveAll().then(() => {
if (this.model.getProcesses().length === 0) {
this.removeReplExpressions();
}
const manager = this.getConfigurationManager();
configName = configName || this.viewModel.selectedConfigurationName;
const config = manager.getConfiguration(configName);
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)));
}
const config = typeof configurationOrName === 'string' ? this.configurationManager.getConfiguration(configurationOrName) : configurationOrName;
if (!config) {
return TPromise.wrapError(new Error(nls.localize('configMissing', "Configuration '{0}' is missing in 'launch.json'.", configurationOrName)));
}
if (config) {
return this.createProcess(config);
}
if (this.contextService.getWorkspace() && commandAndType) {
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 => {
if (!resolvedConfig) {
// User canceled resolving of interactive variables, silently return
......
......@@ -71,7 +71,11 @@ export class MockDebugService implements debug.IDebugService {
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);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册