Merge VS Code 1.21 source code (#1067)

* Initial VS Code 1.21 file copy with patches

* A few more merges

* Post npm install

* Fix batch of build breaks

* Fix more build breaks

* Fix more build errors

* Fix more build breaks

* Runtime fixes 1

* Get connection dialog working with some todos

* Fix a few packaging issues

* Copy several node_modules to package build to fix loader issues

* Fix breaks from master

* A few more fixes

* Make tests pass

* First pass of license header updates

* Second pass of license header updates

* Fix restore dialog issues

* Remove add additional themes menu items

* fix select box issues where the list doesn't show up

* formatting

* Fix editor dispose issue

* Copy over node modules to correct location on all platforms
This commit is contained in:
Karl Burtram
2018-04-04 15:27:51 -07:00
committed by GitHub
parent 5fba3e31b4
commit dafb780987
9412 changed files with 141255 additions and 98813 deletions

View File

@@ -0,0 +1,247 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from 'vs/base/browser/dom';
import { IExpression, IDebugService, IEnablement } from 'vs/workbench/parts/debug/common/debug';
import { Expression, Variable } from 'vs/workbench/parts/debug/common/debugModel';
import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ITree, ContextMenuEvent, IActionProvider } from 'vs/base/parts/tree/browser/tree';
import { InputBox, IInputValidationOptions } from 'vs/base/browser/ui/inputbox/inputBox';
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { once } from 'vs/base/common/functional';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions';
import { IControllerOptions } from 'vs/base/parts/tree/browser/treeDefaults';
import { fillInActions } from 'vs/platform/actions/browser/menuItemActionItem';
import { KeyCode } from 'vs/base/common/keyCodes';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { onUnexpectedError } from 'vs/base/common/errors';
import { WorkbenchTreeController } from 'vs/platform/list/browser/listService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
export const MAX_VALUE_RENDER_LENGTH_IN_VIEWLET = 1024;
export const twistiePixels = 20;
const booleanRegex = /^true|false$/i;
const stringRegex = /^(['"]).*\1$/;
const $ = dom.$;
export interface IRenderValueOptions {
preserveWhitespace?: boolean;
showChanged?: boolean;
maxValueLength?: number;
showHover?: boolean;
colorize?: boolean;
}
export interface IVariableTemplateData {
expression: HTMLElement;
name: HTMLElement;
value: HTMLElement;
}
export function renderViewTree(container: HTMLElement): HTMLElement {
const treeContainer = document.createElement('div');
dom.addClass(treeContainer, 'debug-view-content');
container.appendChild(treeContainer);
return treeContainer;
}
function replaceWhitespace(value: string): string {
const map: { [x: string]: string } = { '\n': '\\n', '\r': '\\r', '\t': '\\t' };
return value.replace(/[\n\r\t]/g, char => map[char]);
}
export function renderExpressionValue(expressionOrValue: IExpression | string, container: HTMLElement, options: IRenderValueOptions): void {
let value = typeof expressionOrValue === 'string' ? expressionOrValue : expressionOrValue.value;
// remove stale classes
container.className = 'value';
// when resolving expressions we represent errors from the server as a variable with name === null.
if (value === null || ((expressionOrValue instanceof Expression || expressionOrValue instanceof Variable) && !expressionOrValue.available)) {
dom.addClass(container, 'unavailable');
if (value !== Expression.DEFAULT_VALUE) {
dom.addClass(container, 'error');
}
}
if (options.colorize && typeof expressionOrValue !== 'string') {
if (expressionOrValue.type === 'number' || expressionOrValue.type === 'boolean' || expressionOrValue.type === 'string') {
dom.addClass(container, expressionOrValue.type);
} else if (!isNaN(+value)) {
dom.addClass(container, 'number');
} else if (booleanRegex.test(value)) {
dom.addClass(container, 'boolean');
} else if (stringRegex.test(value)) {
dom.addClass(container, 'string');
}
}
if (options.showChanged && (<any>expressionOrValue).valueChanged && value !== Expression.DEFAULT_VALUE) {
// value changed color has priority over other colors.
container.className = 'value changed';
}
if (options.maxValueLength && value.length > options.maxValueLength) {
value = value.substr(0, options.maxValueLength) + '...';
}
if (value && !options.preserveWhitespace) {
container.textContent = replaceWhitespace(value);
} else {
container.textContent = value;
}
if (options.showHover) {
container.title = value;
}
}
export function renderVariable(tree: ITree, variable: Variable, data: IVariableTemplateData, showChanged: boolean): void {
if (variable.available) {
data.name.textContent = replaceWhitespace(variable.name);
data.name.title = variable.type ? variable.type : variable.name;
dom.toggleClass(data.name, 'virtual', !!variable.presentationHint && variable.presentationHint.kind === 'virtual');
}
if (variable.value) {
data.name.textContent += variable.name ? ':' : '';
renderExpressionValue(variable, data.value, {
showChanged,
maxValueLength: MAX_VALUE_RENDER_LENGTH_IN_VIEWLET,
preserveWhitespace: false,
showHover: true,
colorize: true
});
} else {
data.value.textContent = '';
data.value.title = '';
}
}
export interface IRenameBoxOptions {
initialValue: string;
ariaLabel: string;
placeholder?: string;
validationOptions?: IInputValidationOptions;
}
export function renderRenameBox(debugService: IDebugService, contextViewService: IContextViewService, themeService: IThemeService, tree: ITree, element: any, container: HTMLElement, options: IRenameBoxOptions): void {
let inputBoxContainer = dom.append(container, $('.inputBoxContainer'));
let inputBox = new InputBox(inputBoxContainer, contextViewService, {
validationOptions: options.validationOptions,
placeholder: options.placeholder,
ariaLabel: options.ariaLabel
});
const styler = attachInputBoxStyler(inputBox, themeService);
inputBox.value = options.initialValue ? options.initialValue : '';
inputBox.focus();
inputBox.select();
let disposed = false;
const toDispose: IDisposable[] = [inputBox, styler];
const wrapUp = once((renamed: boolean) => {
if (!disposed) {
disposed = true;
if (element instanceof Expression && renamed && inputBox.value) {
debugService.renameWatchExpression(element.getId(), inputBox.value);
debugService.getViewModel().setSelectedExpression(undefined);
} else if (element instanceof Expression && !element.name) {
debugService.removeWatchExpressions(element.getId());
debugService.getViewModel().setSelectedExpression(undefined);
} else if (element instanceof Variable) {
element.errorMessage = null;
if (renamed && element.value !== inputBox.value) {
element.setVariable(inputBox.value)
// if everything went fine we need to refresh ui elements since the variable update can change watch and variables view
.done(() => {
tree.refresh(element, false);
// Need to force watch expressions to update since a variable change can have an effect on watches
debugService.focusStackFrame(debugService.getViewModel().focusedStackFrame);
}, onUnexpectedError);
}
}
tree.DOMFocus();
tree.setFocus(element);
// need to remove the input box since this template will be reused.
container.removeChild(inputBoxContainer);
dispose(toDispose);
}
});
toDispose.push(dom.addStandardDisposableListener(inputBox.inputElement, 'keydown', (e: IKeyboardEvent) => {
const isEscape = e.equals(KeyCode.Escape);
const isEnter = e.equals(KeyCode.Enter);
if (isEscape || isEnter) {
e.preventDefault();
e.stopPropagation();
wrapUp(isEnter);
}
}));
toDispose.push(dom.addDisposableListener(inputBox.inputElement, 'blur', () => {
wrapUp(true);
}));
}
export class BaseDebugController extends WorkbenchTreeController {
private contributedContextMenu: IMenu;
constructor(
private actionProvider: IActionProvider,
menuId: MenuId,
options: IControllerOptions,
@IDebugService protected debugService: IDebugService,
@IContextMenuService private contextMenuService: IContextMenuService,
@IContextKeyService contextKeyService: IContextKeyService,
@IMenuService menuService: IMenuService,
@IConfigurationService configurationService: IConfigurationService
) {
super(options, configurationService);
this.contributedContextMenu = menuService.createMenu(menuId, contextKeyService);
}
public onContextMenu(tree: ITree, element: IEnablement, event: ContextMenuEvent, focusElement = true): boolean {
if (event.target && event.target.tagName && event.target.tagName.toLowerCase() === 'input') {
return false;
}
event.preventDefault();
event.stopPropagation();
if (focusElement) {
tree.setFocus(element);
}
if (this.actionProvider.hasSecondaryActions(tree, element)) {
const anchor = { x: event.posx, y: event.posy };
this.contextMenuService.showContextMenu({
getAnchor: () => anchor,
getActions: () => this.actionProvider.getSecondaryActions(tree, element).then(actions => {
fillInActions(this.contributedContextMenu, { arg: this.getContext(element) }, actions, this.contextMenuService);
return actions;
}),
onHide: (wasCancelled?: boolean) => {
if (wasCancelled) {
tree.DOMFocus();
}
},
getActionsContext: () => element
});
return true;
}
return false;
}
protected getContext(element: any): any {
return undefined;
}
}

View File

@@ -15,7 +15,7 @@ import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/zoneWidget';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IDebugService, IBreakpoint, IRawBreakpoint } from 'vs/workbench/parts/debug/common/debug';
import { IDebugService, IBreakpoint } from 'vs/workbench/parts/debug/common/debug';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { once } from 'vs/base/common/functional';
import { attachInputBoxStyler, attachSelectBoxStyler } from 'vs/platform/theme/common/styler';
@@ -71,7 +71,7 @@ export class BreakpointWidget extends ZoneWidget {
this.hitCountContext = breakpoint && breakpoint.hitCondition && !breakpoint.condition;
const selected = this.hitCountContext ? 1 : 0;
const selectBox = new SelectBox([nls.localize('expression', "Expression"), nls.localize('hitCount', "Hit Count")], selected);
const selectBox = new SelectBox([nls.localize('expression', "Expression"), nls.localize('hitCount', "Hit Count")], selected, this.contextViewService);
this.toDispose.push(attachSelectBoxStyler(selectBox, this.themeService));
selectBox.render(dom.append(container, $('.breakpoint-select-container')));
selectBox.onDidSelect(e => {
@@ -109,31 +109,38 @@ export class BreakpointWidget extends ZoneWidget {
const oldBreakpoint = this.debugService.getModel().getBreakpoints()
.filter(bp => bp.lineNumber === this.lineNumber && bp.column === this.column && bp.uri.toString() === uri.toString()).pop();
const raw: IRawBreakpoint = {
lineNumber: this.lineNumber,
column: oldBreakpoint ? oldBreakpoint.column : undefined,
enabled: true,
condition: oldBreakpoint && oldBreakpoint.condition,
hitCondition: oldBreakpoint && oldBreakpoint.hitCondition
};
let condition = oldBreakpoint && oldBreakpoint.condition;
let hitCondition = oldBreakpoint && oldBreakpoint.hitCondition;
if (this.hitCountContext) {
raw.hitCondition = this.inputBox.value;
hitCondition = this.inputBox.value;
if (this.conditionInput) {
raw.condition = this.conditionInput;
condition = this.conditionInput;
}
} else {
raw.condition = this.inputBox.value;
condition = this.inputBox.value;
if (this.hitCountInput) {
raw.hitCondition = this.hitCountInput;
hitCondition = this.hitCountInput;
}
}
if (oldBreakpoint) {
this.debugService.removeBreakpoints(oldBreakpoint.getId()).done(null, errors.onUnexpectedError);
this.debugService.updateBreakpoints(oldBreakpoint.uri, {
[oldBreakpoint.getId()]: {
condition,
hitCondition,
verified: oldBreakpoint.verified
}
}, false);
} else {
this.debugService.addBreakpoints(uri, [{
lineNumber: this.lineNumber,
column: oldBreakpoint ? oldBreakpoint.column : undefined,
enabled: true,
condition,
hitCondition
}]).done(null, errors.onUnexpectedError);
}
this.debugService.addBreakpoints(uri, [raw]).done(null, errors.onUnexpectedError);
}
this.dispose();

View File

@@ -0,0 +1,617 @@
/*---------------------------------------------------------------------------------------------
* 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 * as resources from 'vs/base/common/resources';
import * as dom from 'vs/base/browser/dom';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IAction, Action } from 'vs/base/common/actions';
import { IDebugService, IBreakpoint, CONTEXT_BREAKPOINTS_FOCUSED, EDITOR_CONTRIBUTION_ID, State, DEBUG_SCHEME, IFunctionBreakpoint, IExceptionBreakpoint, IEnablement, IDebugEditorContribution } from 'vs/workbench/parts/debug/common/debug';
import { ExceptionBreakpoint, FunctionBreakpoint, Breakpoint } from 'vs/workbench/parts/debug/common/debugModel';
import { AddFunctionBreakpointAction, ToggleBreakpointsActivatedAction, RemoveAllBreakpointsAction, RemoveBreakpointAction, EnableAllBreakpointsAction, DisableAllBreakpointsAction, ReapplyBreakpointsAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { Constants } from 'vs/editor/common/core/uint';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { getPathLabel } from 'vs/base/common/labels';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { basename } from 'vs/base/common/paths';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { TPromise } from 'vs/base/common/winjs.base';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { IDelegate, IListContextMenuEvent, IRenderer } from 'vs/base/browser/ui/list/list';
import { IEditorService, IEditor } from 'vs/platform/editor/common/editor';
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { WorkbenchList } from 'vs/platform/list/browser/listService';
import { ViewsViewletPanel, IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
const $ = dom.$;
export class BreakpointsView extends ViewsViewletPanel {
private static readonly MAX_VISIBLE_FILES = 9;
private static readonly MEMENTO = 'breakopintsview.memento';
private settings: any;
private list: WorkbenchList<IEnablement>;
private needsRefresh: boolean;
constructor(
options: IViewletViewOptions,
@IContextMenuService contextMenuService: IContextMenuService,
@IDebugService private debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
@IInstantiationService private instantiationService: IInstantiationService,
@IThemeService private themeService: IThemeService,
@IEditorService private editorService: IEditorService,
@IContextViewService private contextViewService: IContextViewService,
@IConfigurationService configurationService: IConfigurationService
) {
super(options, keybindingService, contextMenuService, configurationService);
this.minimumBodySize = this.maximumBodySize = this.getExpandedBodySize();
this.settings = options.viewletSettings;
this.disposables.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.onBreakpointsChange()));
}
public renderBody(container: HTMLElement): void {
dom.addClass(container, 'debug-breakpoints');
const delegate = new BreakpointsDelegate(this.debugService);
this.list = this.instantiationService.createInstance(WorkbenchList, container, delegate, [
this.instantiationService.createInstance(BreakpointsRenderer),
new ExceptionBreakpointsRenderer(this.debugService),
this.instantiationService.createInstance(FunctionBreakpointsRenderer),
new FunctionBreakpointInputRenderer(this.debugService, this.contextViewService, this.themeService)
], {
identityProvider: element => element.getId(),
multipleSelectionSupport: false
}) as WorkbenchList<IEnablement>;
CONTEXT_BREAKPOINTS_FOCUSED.bindTo(this.list.contextKeyService);
this.list.onContextMenu(this.onListContextMenu, this, this.disposables);
this.disposables.push(this.list.onOpen(e => {
let isSingleClick = false;
let isDoubleClick = false;
let openToSide = false;
const browserEvent = e.browserEvent;
if (browserEvent instanceof MouseEvent) {
isSingleClick = browserEvent.detail === 1;
isDoubleClick = browserEvent.detail === 2;
openToSide = (browserEvent.ctrlKey || browserEvent.metaKey || browserEvent.altKey);
}
const focused = this.list.getFocusedElements();
const element = focused.length ? focused[0] : undefined;
if (element instanceof Breakpoint) {
openBreakpointSource(element, openToSide, isSingleClick, this.debugService, this.editorService).done(undefined, onUnexpectedError);
}
if (isDoubleClick && element instanceof FunctionBreakpoint && element !== this.debugService.getViewModel().getSelectedFunctionBreakpoint()) {
this.debugService.getViewModel().setSelectedFunctionBreakpoint(element);
this.onBreakpointsChange();
}
}));
this.list.splice(0, this.list.length, this.elements);
}
protected layoutBody(size: number): void {
if (this.list) {
this.list.layout(size);
}
}
private onListContextMenu(e: IListContextMenuEvent<IEnablement>): void {
const actions: IAction[] = [];
const element = e.element;
if (element instanceof Breakpoint || element instanceof FunctionBreakpoint) {
actions.push(new Action('workbench.action.debug.openEditorAndEditBreakpoint', nls.localize('editConditionalBreakpoint', "Edit Breakpoint..."), undefined, true, () => {
if (element instanceof Breakpoint) {
return openBreakpointSource(element, false, false, this.debugService, this.editorService).then(editor => {
const codeEditor = editor.getControl();
if (isCodeEditor(codeEditor)) {
codeEditor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(element.lineNumber, element.column);
}
});
}
this.debugService.getViewModel().setSelectedFunctionBreakpoint(element);
this.onBreakpointsChange();
return undefined;
}));
actions.push(new Separator());
}
actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, RemoveBreakpointAction.LABEL, this.debugService, this.keybindingService));
if (this.debugService.getModel().getBreakpoints().length + this.debugService.getModel().getFunctionBreakpoints().length > 1) {
actions.push(new RemoveAllBreakpointsAction(RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL, this.debugService, this.keybindingService));
actions.push(new Separator());
actions.push(new EnableAllBreakpointsAction(EnableAllBreakpointsAction.ID, EnableAllBreakpointsAction.LABEL, this.debugService, this.keybindingService));
actions.push(new DisableAllBreakpointsAction(DisableAllBreakpointsAction.ID, DisableAllBreakpointsAction.LABEL, this.debugService, this.keybindingService));
}
actions.push(new Separator());
actions.push(new ReapplyBreakpointsAction(ReapplyBreakpointsAction.ID, ReapplyBreakpointsAction.LABEL, this.debugService, this.keybindingService));
this.contextMenuService.showContextMenu({
getAnchor: () => e.anchor,
getActions: () => TPromise.as(actions),
getActionsContext: () => element
});
}
public getActions(): IAction[] {
return [
new AddFunctionBreakpointAction(AddFunctionBreakpointAction.ID, AddFunctionBreakpointAction.LABEL, this.debugService, this.keybindingService),
new ToggleBreakpointsActivatedAction(ToggleBreakpointsActivatedAction.ID, ToggleBreakpointsActivatedAction.ACTIVATE_LABEL, this.debugService, this.keybindingService),
new RemoveAllBreakpointsAction(RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL, this.debugService, this.keybindingService)
];
}
public setExpanded(expanded: boolean): void {
super.setExpanded(expanded);
if (expanded && this.needsRefresh) {
this.onBreakpointsChange();
}
}
public setVisible(visible: boolean): TPromise<void> {
return super.setVisible(visible).then(() => {
if (visible && this.needsRefresh) {
this.onBreakpointsChange();
}
});
}
private onBreakpointsChange(): void {
if (this.isExpanded() && this.isVisible()) {
this.minimumBodySize = this.getExpandedBodySize();
if (this.maximumBodySize < Number.POSITIVE_INFINITY) {
this.maximumBodySize = this.minimumBodySize;
}
if (this.list) {
this.list.splice(0, this.list.length, this.elements);
this.needsRefresh = false;
}
} else {
this.needsRefresh = true;
}
}
private get elements(): IEnablement[] {
const model = this.debugService.getModel();
const elements = (<IEnablement[]>model.getExceptionBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getBreakpoints());
return elements;
}
private getExpandedBodySize(): number {
const model = this.debugService.getModel();
const length = model.getBreakpoints().length + model.getExceptionBreakpoints().length + model.getFunctionBreakpoints().length;
return Math.min(BreakpointsView.MAX_VISIBLE_FILES, length) * 22;
}
public shutdown(): void {
this.settings[BreakpointsView.MEMENTO] = !this.isExpanded();
}
}
class BreakpointsDelegate implements IDelegate<IEnablement> {
constructor(private debugService: IDebugService) {
// noop
}
getHeight(element: IEnablement): number {
return 22;
}
getTemplateId(element: IEnablement): string {
if (element instanceof Breakpoint) {
return BreakpointsRenderer.ID;
}
if (element instanceof FunctionBreakpoint) {
const selected = this.debugService.getViewModel().getSelectedFunctionBreakpoint();
if (!element.name || (selected && selected.getId() === element.getId())) {
return FunctionBreakpointInputRenderer.ID;
}
return FunctionBreakpointsRenderer.ID;
}
if (element instanceof ExceptionBreakpoint) {
return ExceptionBreakpointsRenderer.ID;
}
return undefined;
}
}
interface IBaseBreakpointTemplateData {
breakpoint: HTMLElement;
name: HTMLElement;
checkbox: HTMLInputElement;
context: IEnablement;
toDispose: IDisposable[];
}
interface IBaseBreakpointWithIconTemplateData extends IBaseBreakpointTemplateData {
icon: HTMLElement;
}
interface IBreakpointTemplateData extends IBaseBreakpointWithIconTemplateData {
lineNumber: HTMLElement;
filePath: HTMLElement;
}
interface IInputTemplateData {
inputBox: InputBox;
breakpoint: IFunctionBreakpoint;
reactedOnEvent: boolean;
toDispose: IDisposable[];
}
class BreakpointsRenderer implements IRenderer<IBreakpoint, IBreakpointTemplateData> {
constructor(
@IDebugService private debugService: IDebugService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IEnvironmentService private environmentService: IEnvironmentService,
@ITextFileService private textFileService: ITextFileService
) {
// noop
}
static readonly ID = 'breakpoints';
get templateId() {
return BreakpointsRenderer.ID;
}
renderTemplate(container: HTMLElement): IBreakpointTemplateData {
const data: IBreakpointTemplateData = Object.create(null);
data.breakpoint = dom.append(container, $('.breakpoint'));
data.icon = $('.icon');
data.checkbox = <HTMLInputElement>$('input');
data.checkbox.type = 'checkbox';
data.toDispose = [];
data.toDispose.push(dom.addStandardDisposableListener(data.checkbox, 'change', (e) => {
this.debugService.enableOrDisableBreakpoints(!data.context.enabled, data.context);
}));
dom.append(data.breakpoint, data.icon);
dom.append(data.breakpoint, data.checkbox);
data.name = dom.append(data.breakpoint, $('span.name'));
data.filePath = dom.append(data.breakpoint, $('span.file-path'));
const lineNumberContainer = dom.append(data.breakpoint, $('.line-number-container'));
data.lineNumber = dom.append(lineNumberContainer, $('span.line-number'));
return data;
}
renderElement(breakpoint: IBreakpoint, index: number, data: IBreakpointTemplateData): void {
data.context = breakpoint;
dom.toggleClass(data.breakpoint, 'disabled', !this.debugService.getModel().areBreakpointsActivated());
data.name.textContent = basename(getPathLabel(breakpoint.uri, this.contextService));
data.lineNumber.textContent = breakpoint.lineNumber.toString();
if (breakpoint.column) {
data.lineNumber.textContent += `:${breakpoint.column}`;
}
data.filePath.textContent = getPathLabel(resources.dirname(breakpoint.uri), this.contextService, this.environmentService);
data.checkbox.checked = breakpoint.enabled;
const { message, className } = getBreakpointMessageAndClassName(this.debugService, this.textFileService, breakpoint);
data.icon.className = className + ' icon';
data.icon.title = message ? message : '';
const debugActive = this.debugService.state === State.Running || this.debugService.state === State.Stopped;
if (debugActive && !breakpoint.verified) {
dom.addClass(data.breakpoint, 'disabled');
if (breakpoint.message) {
data.breakpoint.title = breakpoint.message;
}
} else if (breakpoint.condition || breakpoint.hitCondition) {
data.breakpoint.title = breakpoint.condition ? breakpoint.condition : breakpoint.hitCondition;
}
}
disposeTemplate(templateData: IBreakpointTemplateData): void {
dispose(templateData.toDispose);
}
}
class ExceptionBreakpointsRenderer implements IRenderer<IExceptionBreakpoint, IBaseBreakpointTemplateData> {
constructor(
private debugService: IDebugService
) {
// noop
}
static readonly ID = 'exceptionbreakpoints';
get templateId() {
return ExceptionBreakpointsRenderer.ID;
}
renderTemplate(container: HTMLElement): IBaseBreakpointTemplateData {
const data: IBreakpointTemplateData = Object.create(null);
data.breakpoint = dom.append(container, $('.breakpoint'));
data.checkbox = <HTMLInputElement>$('input');
data.checkbox.type = 'checkbox';
data.toDispose = [];
data.toDispose.push(dom.addStandardDisposableListener(data.checkbox, 'change', (e) => {
this.debugService.enableOrDisableBreakpoints(!data.context.enabled, data.context);
}));
dom.append(data.breakpoint, data.checkbox);
data.name = dom.append(data.breakpoint, $('span.name'));
dom.addClass(data.breakpoint, 'exception');
return data;
}
renderElement(exceptionBreakpoint: IExceptionBreakpoint, index: number, data: IBaseBreakpointTemplateData): void {
data.context = exceptionBreakpoint;
data.name.textContent = exceptionBreakpoint.label || `${exceptionBreakpoint.filter} exceptions`;
data.breakpoint.title = data.name.textContent;
data.checkbox.checked = exceptionBreakpoint.enabled;
}
disposeTemplate(templateData: IBaseBreakpointTemplateData): void {
dispose(templateData.toDispose);
}
}
class FunctionBreakpointsRenderer implements IRenderer<FunctionBreakpoint, IBaseBreakpointWithIconTemplateData> {
constructor(
@IDebugService private debugService: IDebugService,
@ITextFileService private textFileService: ITextFileService
) {
// noop
}
static readonly ID = 'functionbreakpoints';
get templateId() {
return FunctionBreakpointsRenderer.ID;
}
renderTemplate(container: HTMLElement): IBaseBreakpointWithIconTemplateData {
const data: IBreakpointTemplateData = Object.create(null);
data.breakpoint = dom.append(container, $('.breakpoint'));
data.icon = $('.icon');
data.checkbox = <HTMLInputElement>$('input');
data.checkbox.type = 'checkbox';
data.toDispose = [];
data.toDispose.push(dom.addStandardDisposableListener(data.checkbox, 'change', (e) => {
this.debugService.enableOrDisableBreakpoints(!data.context.enabled, data.context);
}));
dom.append(data.breakpoint, data.icon);
dom.append(data.breakpoint, data.checkbox);
data.name = dom.append(data.breakpoint, $('span.name'));
return data;
}
renderElement(functionBreakpoint: FunctionBreakpoint, index: number, data: IBaseBreakpointWithIconTemplateData): void {
data.context = functionBreakpoint;
data.name.textContent = functionBreakpoint.name;
const { className, message } = getBreakpointMessageAndClassName(this.debugService, this.textFileService, functionBreakpoint);
data.icon.className = className + ' icon';
data.icon.title = message ? message : '';
data.checkbox.checked = functionBreakpoint.enabled;
data.breakpoint.title = functionBreakpoint.name;
// Mark function breakpoints as disabled if deactivated or if debug type does not support them #9099
const process = this.debugService.getViewModel().focusedProcess;
dom.toggleClass(data.breakpoint, 'disalbed', (process && !process.session.capabilities.supportsFunctionBreakpoints) || !this.debugService.getModel().areBreakpointsActivated());
if (process && !process.session.capabilities.supportsFunctionBreakpoints) {
data.breakpoint.title = nls.localize('functionBreakpointsNotSupported', "Function breakpoints are not supported by this debug type");
}
}
disposeTemplate(templateData: IBaseBreakpointWithIconTemplateData): void {
dispose(templateData.toDispose);
}
}
class FunctionBreakpointInputRenderer implements IRenderer<IFunctionBreakpoint, IInputTemplateData> {
constructor(
private debugService: IDebugService,
private contextViewService: IContextViewService,
private themeService: IThemeService
) {
// noop
}
static readonly ID = 'functionbreakpointinput';
get templateId() {
return FunctionBreakpointInputRenderer.ID;
}
renderTemplate(container: HTMLElement): IInputTemplateData {
const template: IInputTemplateData = Object.create(null);
const inputBoxContainer = dom.append(container, $('.inputBoxContainer'));
const inputBox = new InputBox(inputBoxContainer, this.contextViewService, {
placeholder: nls.localize('functionBreakpointPlaceholder', "Function to break on"),
ariaLabel: nls.localize('functionBreakPointInputAriaLabel', "Type function breakpoint")
});
const styler = attachInputBoxStyler(inputBox, this.themeService);
const toDispose: IDisposable[] = [inputBox, styler];
const wrapUp = (renamed: boolean) => {
if (!template.reactedOnEvent) {
template.reactedOnEvent = true;
this.debugService.getViewModel().setSelectedFunctionBreakpoint(undefined);
if (inputBox.value && (renamed || template.breakpoint.name)) {
this.debugService.renameFunctionBreakpoint(template.breakpoint.getId(), renamed ? inputBox.value : template.breakpoint.name).done(null, onUnexpectedError);
} else {
this.debugService.removeFunctionBreakpoints(template.breakpoint.getId()).done(null, onUnexpectedError);
}
}
};
toDispose.push(dom.addStandardDisposableListener(inputBox.inputElement, 'keydown', (e: IKeyboardEvent) => {
const isEscape = e.equals(KeyCode.Escape);
const isEnter = e.equals(KeyCode.Enter);
if (isEscape || isEnter) {
e.preventDefault();
e.stopPropagation();
wrapUp(isEnter);
}
}));
toDispose.push(dom.addDisposableListener(inputBox.inputElement, 'blur', () => {
if (!template.breakpoint.name) {
wrapUp(true);
}
}));
template.inputBox = inputBox;
template.toDispose = toDispose;
return template;
}
renderElement(functionBreakpoint: IFunctionBreakpoint, index: number, data: IInputTemplateData): void {
data.breakpoint = functionBreakpoint;
data.reactedOnEvent = false;
data.inputBox.value = functionBreakpoint.name || '';
data.inputBox.focus();
data.inputBox.select();
}
disposeTemplate(templateData: IInputTemplateData): void {
dispose(templateData.toDispose);
}
}
export function openBreakpointSource(breakpoint: Breakpoint, sideBySide: boolean, preserveFocus: boolean, debugService: IDebugService, editorService: IEditorService): TPromise<IEditor> {
if (breakpoint.uri.scheme === DEBUG_SCHEME && debugService.state === State.Inactive) {
return TPromise.as(null);
}
const selection = breakpoint.endLineNumber ? {
startLineNumber: breakpoint.lineNumber,
endLineNumber: breakpoint.endLineNumber,
startColumn: breakpoint.column,
endColumn: breakpoint.endColumn
} : {
startLineNumber: breakpoint.lineNumber,
startColumn: breakpoint.column || 1,
endLineNumber: breakpoint.lineNumber,
endColumn: breakpoint.column || Constants.MAX_SAFE_SMALL_INTEGER
};
return editorService.openEditor({
resource: breakpoint.uri,
options: {
preserveFocus,
selection,
revealIfVisible: true,
revealInCenterIfOutsideViewport: true,
pinned: !preserveFocus
}
}, sideBySide);
}
export function getBreakpointMessageAndClassName(debugService: IDebugService, textFileService: ITextFileService, breakpoint: IBreakpoint | FunctionBreakpoint): { message?: string, className: string } {
const state = debugService.state;
const debugActive = state === State.Running || state === State.Stopped;
if (!breakpoint.enabled || !debugService.getModel().areBreakpointsActivated()) {
return {
className: breakpoint instanceof FunctionBreakpoint ? 'debug-function-breakpoint-disabled' : 'debug-breakpoint-disabled',
message: nls.localize('breakpointDisabledHover', "Disabled breakpoint"),
};
}
const appendMessage = (text: string): string => {
return !(breakpoint instanceof FunctionBreakpoint) && breakpoint.message ? text.concat(', ' + breakpoint.message) : text;
};
if (debugActive && !breakpoint.verified) {
return {
className: breakpoint instanceof FunctionBreakpoint ? 'debug-function-breakpoint-unverified' : 'debug-breakpoint-unverified',
message: appendMessage(nls.localize('breakpointUnverifieddHover', "Unverified breakpoint")),
};
}
const process = debugService.getViewModel().focusedProcess;
if (breakpoint instanceof FunctionBreakpoint) {
if (process && !process.session.capabilities.supportsFunctionBreakpoints) {
return {
className: 'debug-function-breakpoint-unverified',
message: nls.localize('functionBreakpointUnsupported', "Function breakpoints not supported by this debug type"),
};
}
return {
className: 'debug-function-breakpoint',
};
}
if (debugActive && textFileService.isDirty(breakpoint.uri)) {
return {
className: 'debug-breakpoint-unverified',
message: appendMessage(nls.localize('breakpointDirtydHover', "Unverified breakpoint. File is modified, please restart debug session.")),
};
}
if (breakpoint.condition || breakpoint.hitCondition) {
if (process && breakpoint.condition && !process.session.capabilities.supportsConditionalBreakpoints) {
return {
className: 'debug-breakpoint-unsupported',
message: nls.localize('conditionalBreakpointUnsupported', "Conditional breakpoints not supported by this debug type"),
};
}
if (process && breakpoint.hitCondition && !process.session.capabilities.supportsHitConditionalBreakpoints) {
return {
className: 'debug-breakpoint-unsupported',
message: nls.localize('hitBreakpointUnsupported', "Hit conditional breakpoints not supported by this debug type"),
};
}
if (breakpoint.condition && breakpoint.hitCondition) {
return {
className: 'debug-breakpoint-conditional',
message: appendMessage(`Expression: ${breakpoint.condition}\nHitCount: ${breakpoint.hitCondition}`)
};
}
return {
className: 'debug-breakpoint-conditional',
message: appendMessage(breakpoint.condition ? breakpoint.condition : breakpoint.hitCondition)
};
}
return {
className: 'debug-breakpoint',
message: breakpoint.message
};
}

View File

@@ -19,6 +19,8 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { selectBorder } from 'vs/platform/theme/common/colorRegistry';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
const $ = dom.$;
@@ -40,10 +42,12 @@ export class StartDebugActionItem implements IActionItem {
@IDebugService private debugService: IDebugService,
@IThemeService private themeService: IThemeService,
@IConfigurationService private configurationService: IConfigurationService,
@ICommandService private commandService: ICommandService
@ICommandService private commandService: ICommandService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IContextViewService contextViewService: IContextViewService,
) {
this.toDispose = [];
this.selectBox = new SelectBox([], -1);
this.selectBox = new SelectBox([], -1, contextViewService);
this.toDispose.push(attachSelectBoxStyler(this.selectBox, themeService, {
selectBackground: SIDE_BAR_BACKGROUND
}));
@@ -151,12 +155,13 @@ export class StartDebugActionItem implements IActionItem {
this.options = [];
const manager = this.debugService.getConfigurationManager();
const launches = manager.getLaunches();
manager.getLaunches().forEach(launch =>
const inWorkspace = this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE;
launches.forEach(launch =>
launch.getConfigurationNames().forEach(name => {
if (name === manager.selectedName && launch === manager.selectedLaunch) {
if (name === manager.selectedConfiguration.name && launch === manager.selectedConfiguration.launch) {
this.selected = this.options.length;
}
const label = launches.length > 1 ? `${name} (${launch.workspace.name})` : name;
const label = inWorkspace ? `${name} (${launch.name})` : name;
this.options.push({ label, handler: () => { manager.selectConfiguration(launch, name); return true; } });
}));
@@ -166,11 +171,11 @@ export class StartDebugActionItem implements IActionItem {
this.options.push({ label: StartDebugActionItem.SEPARATOR, handler: undefined });
const disabledIdx = this.options.length - 1;
launches.forEach(l => {
const label = launches.length > 1 ? nls.localize("addConfigTo", "Add Config ({0})...", l.workspace.name) : nls.localize('addConfiguration', "Add Configuration...");
launches.filter(l => !l.hidden).forEach(l => {
const label = inWorkspace ? nls.localize("addConfigTo", "Add Config ({0})...", l.name) : nls.localize('addConfiguration', "Add Configuration...");
this.options.push({
label, handler: () => {
this.commandService.executeCommand('debug.addConfiguration', l.workspace.uri.toString()).done(undefined, errors.onUnexpectedError);
this.commandService.executeCommand('debug.addConfiguration', l.uri.toString()).done(undefined, errors.onUnexpectedError);
return false;
}
});
@@ -184,9 +189,10 @@ export class FocusProcessActionItem extends SelectActionItem {
constructor(
action: IAction,
@IDebugService private debugService: IDebugService,
@IThemeService themeService: IThemeService
@IThemeService themeService: IThemeService,
@IContextViewService contextViewService: IContextViewService
) {
super(null, action, [], -1);
super(null, action, [], -1, contextViewService);
this.toDispose.push(attachSelectBoxStyler(this.selectBox, themeService));

View File

@@ -6,14 +6,12 @@
import * as nls from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import * as lifecycle from 'vs/base/common/lifecycle';
import severity from 'vs/base/common/severity';
import { TPromise } from 'vs/base/common/winjs.base';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IFileService } from 'vs/platform/files/common/files';
import { IMessageService } from 'vs/platform/message/common/message';
import { IDebugService, State, IProcess, IThread, IEnablement, IBreakpoint, IStackFrame, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, IExpression, REPL_ID, ProcessState }
from 'vs/workbench/parts/debug/common/debug';
import { Variable, Expression, Thread, Breakpoint, Process } from 'vs/workbench/parts/debug/common/debugModel';
@@ -22,6 +20,9 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { TogglePanelAction } from 'vs/workbench/browser/panel';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { CollapseAction } from 'vs/workbench/browser/viewlet';
import { ITree } from 'vs/base/parts/tree/browser/tree';
export abstract class AbstractDebugAction extends Action {
@@ -71,13 +72,14 @@ export abstract class AbstractDebugAction extends Action {
}
export class ConfigureAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.configure';
static readonly ID = 'workbench.action.debug.configure';
static LABEL = nls.localize('openLaunchJson', "Open {0}", 'launch.json');
constructor(id: string, label: string,
@IDebugService debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
@IMessageService private messageService: IMessageService
@INotificationService private notificationService: INotificationService,
@IWorkspaceContextService private contextService: IWorkspaceContextService
) {
super(id, label, 'debug-action configure', debugService, keybindingService);
this.toDispose.push(debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateClass()));
@@ -85,7 +87,7 @@ export class ConfigureAction extends AbstractDebugAction {
}
public get tooltip(): string {
if (this.debugService.getConfigurationManager().selectedName) {
if (this.debugService.getConfigurationManager().selectedConfiguration.name) {
return ConfigureAction.LABEL;
}
@@ -93,17 +95,17 @@ export class ConfigureAction extends AbstractDebugAction {
}
private updateClass(): void {
this.class = this.debugService.getConfigurationManager().selectedName ? 'debug-action configure' : 'debug-action configure notification';
this.class = this.debugService.getConfigurationManager().selectedConfiguration.name ? 'debug-action configure' : 'debug-action configure notification';
}
public run(event?: any): TPromise<any> {
if (!this.debugService.getConfigurationManager().selectedLaunch) {
this.messageService.show(severity.Info, nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration."));
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
this.notificationService.info(nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration."));
return TPromise.as(null);
}
const sideBySide = !!(event && (event.ctrlKey || event.metaKey));
return this.debugService.getConfigurationManager().selectedLaunch.openConfigFile(sideBySide);
return this.debugService.getConfigurationManager().selectedConfiguration.launch.openConfigFile(sideBySide);
}
}
@@ -124,8 +126,8 @@ export class StartAction extends AbstractDebugAction {
}
public run(): TPromise<any> {
const launch = this.debugService.getConfigurationManager().selectedLaunch;
return this.debugService.startDebugging(launch ? launch.workspace : undefined, undefined, this.isNoDebug());
const launch = this.debugService.getConfigurationManager().selectedConfiguration.launch;
return this.debugService.startDebugging(launch, undefined, this.isNoDebug());
}
protected isNoDebug(): boolean {
@@ -134,7 +136,7 @@ export class StartAction extends AbstractDebugAction {
public static isEnabled(debugService: IDebugService, contextService: IWorkspaceContextService, configName: string) {
const processes = debugService.getModel().getProcesses();
const launch = debugService.getConfigurationManager().selectedLaunch;
const launch = debugService.getConfigurationManager().selectedConfiguration.launch;
if (debugService.state === State.Initializing) {
return false;
@@ -142,7 +144,7 @@ export class StartAction extends AbstractDebugAction {
if (contextService && contextService.getWorkbenchState() === WorkbenchState.EMPTY && processes.length > 0) {
return false;
}
if (processes.some(p => p.getName(false) === configName && (!launch || p.session.root.uri.toString() === launch.workspace.uri.toString()))) {
if (processes.some(p => p.getName(false) === configName && (!launch || !launch.workspace || !p.session.root || p.session.root.uri.toString() === launch.workspace.uri.toString()))) {
return false;
}
const compound = launch && launch.getCompound(configName);
@@ -155,12 +157,12 @@ export class StartAction extends AbstractDebugAction {
// Disabled if the launch drop down shows the launch config that is already running.
protected isEnabled(state: State): boolean {
return StartAction.isEnabled(this.debugService, this.contextService, this.debugService.getConfigurationManager().selectedName);
return StartAction.isEnabled(this.debugService, this.contextService, this.debugService.getConfigurationManager().selectedConfiguration.name);
}
}
export class RunAction extends StartAction {
static ID = 'workbench.action.debug.run';
static readonly ID = 'workbench.action.debug.run';
static LABEL = nls.localize('startWithoutDebugging', "Start Without Debugging");
protected isNoDebug(): boolean {
@@ -169,7 +171,7 @@ export class RunAction extends StartAction {
}
export class SelectAndStartAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.selectandstart';
static readonly ID = 'workbench.action.debug.selectandstart';
static LABEL = nls.localize('selectAndStartDebugging', "Select and Start Debugging");
constructor(id: string, label: string,
@@ -190,7 +192,7 @@ export class SelectAndStartAction extends AbstractDebugAction {
}
export class RestartAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.restart';
static readonly ID = 'workbench.action.debug.restart';
static LABEL = nls.localize('restartDebug', "Restart");
static RECONNECT_LABEL = nls.localize('reconnectDebug', "Reconnect");
@@ -224,7 +226,7 @@ export class RestartAction extends AbstractDebugAction {
}
export class StepOverAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.stepOver';
static readonly ID = 'workbench.action.debug.stepOver';
static LABEL = nls.localize('stepOverDebug', "Step Over");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -245,7 +247,7 @@ export class StepOverAction extends AbstractDebugAction {
}
export class StepIntoAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.stepInto';
static readonly ID = 'workbench.action.debug.stepInto';
static LABEL = nls.localize('stepIntoDebug', "Step Into");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -266,7 +268,7 @@ export class StepIntoAction extends AbstractDebugAction {
}
export class StepOutAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.stepOut';
static readonly ID = 'workbench.action.debug.stepOut';
static LABEL = nls.localize('stepOutDebug', "Step Out");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -287,7 +289,7 @@ export class StepOutAction extends AbstractDebugAction {
}
export class StopAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.stop';
static readonly ID = 'workbench.action.debug.stop';
static LABEL = nls.localize('stopDebug', "Stop");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -308,7 +310,7 @@ export class StopAction extends AbstractDebugAction {
}
export class DisconnectAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.disconnect';
static readonly ID = 'workbench.action.debug.disconnect';
static LABEL = nls.localize('disconnectDebug', "Disconnect");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -326,7 +328,7 @@ export class DisconnectAction extends AbstractDebugAction {
}
export class ContinueAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.continue';
static readonly ID = 'workbench.action.debug.continue';
static LABEL = nls.localize('continueDebug', "Continue");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -347,7 +349,7 @@ export class ContinueAction extends AbstractDebugAction {
}
export class PauseAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.pause';
static readonly ID = 'workbench.action.debug.pause';
static LABEL = nls.localize('pauseDebug', "Pause");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -368,7 +370,7 @@ export class PauseAction extends AbstractDebugAction {
}
export class RestartFrameAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.restartFrame';
static readonly ID = 'workbench.action.debug.restartFrame';
static LABEL = nls.localize('restartFrame', "Restart Frame");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -385,7 +387,7 @@ export class RestartFrameAction extends AbstractDebugAction {
}
export class RemoveBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.removeBreakpoint';
static readonly ID = 'workbench.debug.viewlet.action.removeBreakpoint';
static LABEL = nls.localize('removeBreakpoint', "Remove Breakpoint");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -399,7 +401,7 @@ export class RemoveBreakpointAction extends AbstractDebugAction {
}
export class RemoveAllBreakpointsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.removeAllBreakpoints';
static readonly ID = 'workbench.debug.viewlet.action.removeAllBreakpoints';
static LABEL = nls.localize('removeAllBreakpoints', "Remove All Breakpoints");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -418,7 +420,7 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction {
}
export class EnableBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.enableBreakpoint';
static readonly ID = 'workbench.debug.viewlet.action.enableBreakpoint';
static LABEL = nls.localize('enableBreakpoint', "Enable Breakpoint");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -431,7 +433,7 @@ export class EnableBreakpointAction extends AbstractDebugAction {
}
export class DisableBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.disableBreakpoint';
static readonly ID = 'workbench.debug.viewlet.action.disableBreakpoint';
static LABEL = nls.localize('disableBreakpoint', "Disable Breakpoint");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -444,7 +446,7 @@ export class DisableBreakpointAction extends AbstractDebugAction {
}
export class EnableAllBreakpointsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.enableAllBreakpoints';
static readonly ID = 'workbench.debug.viewlet.action.enableAllBreakpoints';
static LABEL = nls.localize('enableAllBreakpoints', "Enable All Breakpoints");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -463,7 +465,7 @@ export class EnableAllBreakpointsAction extends AbstractDebugAction {
}
export class DisableAllBreakpointsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.disableAllBreakpoints';
static readonly ID = 'workbench.debug.viewlet.action.disableAllBreakpoints';
static LABEL = nls.localize('disableAllBreakpoints', "Disable All Breakpoints");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -482,7 +484,7 @@ export class DisableAllBreakpointsAction extends AbstractDebugAction {
}
export class ToggleBreakpointsActivatedAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.toggleBreakpointsActivatedAction';
static readonly ID = 'workbench.debug.viewlet.action.toggleBreakpointsActivatedAction';
static ACTIVATE_LABEL = nls.localize('activateBreakpoints', "Activate Breakpoints");
static DEACTIVATE_LABEL = nls.localize('deactivateBreakpoints', "Deactivate Breakpoints");
@@ -506,7 +508,7 @@ export class ToggleBreakpointsActivatedAction extends AbstractDebugAction {
}
export class ReapplyBreakpointsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.reapplyBreakpointsAction';
static readonly ID = 'workbench.debug.viewlet.action.reapplyBreakpointsAction';
static LABEL = nls.localize('reapplyAllBreakpoints', "Reapply All Breakpoints");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -526,7 +528,7 @@ export class ReapplyBreakpointsAction extends AbstractDebugAction {
}
export class AddFunctionBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.addFunctionBreakpointAction';
static readonly ID = 'workbench.debug.viewlet.action.addFunctionBreakpointAction';
static LABEL = nls.localize('addFunctionBreakpoint', "Add Function Breakpoint");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -546,7 +548,7 @@ export class AddFunctionBreakpointAction extends AbstractDebugAction {
}
export class AddConditionalBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.addConditionalBreakpointAction';
static readonly ID = 'workbench.debug.viewlet.action.addConditionalBreakpointAction';
static LABEL = nls.localize('addConditionalBreakpoint', "Add Conditional Breakpoint...");
constructor(id: string, label: string,
@@ -565,7 +567,7 @@ export class AddConditionalBreakpointAction extends AbstractDebugAction {
}
export class EditConditionalBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.editConditionalBreakpointAction';
static readonly ID = 'workbench.debug.viewlet.action.editConditionalBreakpointAction';
static LABEL = nls.localize('editConditionalBreakpoint', "Edit Breakpoint...");
constructor(id: string, label: string,
@@ -584,7 +586,7 @@ export class EditConditionalBreakpointAction extends AbstractDebugAction {
export class SetValueAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.setValue';
static readonly ID = 'workbench.debug.viewlet.action.setValue';
static LABEL = nls.localize('setValue', "Set Value");
constructor(id: string, label: string, private variable: Variable, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -607,7 +609,7 @@ export class SetValueAction extends AbstractDebugAction {
export class AddWatchExpressionAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.addWatchExpression';
static readonly ID = 'workbench.debug.viewlet.action.addWatchExpression';
static LABEL = nls.localize('addWatchExpression', "Add Expression");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -616,7 +618,8 @@ export class AddWatchExpressionAction extends AbstractDebugAction {
}
public run(): TPromise<any> {
return this.debugService.addWatchExpression();
this.debugService.addWatchExpression();
return TPromise.as(undefined);
}
protected isEnabled(state: State): boolean {
@@ -625,7 +628,7 @@ export class AddWatchExpressionAction extends AbstractDebugAction {
}
export class EditWatchExpressionAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.editWatchExpression';
static readonly ID = 'workbench.debug.viewlet.action.editWatchExpression';
static LABEL = nls.localize('editWatchExpression', "Edit Expression");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -639,7 +642,7 @@ export class EditWatchExpressionAction extends AbstractDebugAction {
}
export class AddToWatchExpressionsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.addToWatchExpressions';
static readonly ID = 'workbench.debug.viewlet.action.addToWatchExpressions';
static LABEL = nls.localize('addToWatchExpressions', "Add to Watch");
constructor(id: string, label: string, private expression: IExpression, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -648,12 +651,14 @@ export class AddToWatchExpressionsAction extends AbstractDebugAction {
public run(): TPromise<any> {
const name = this.expression instanceof Variable ? this.expression.evaluateName : this.expression.name;
return this.debugService.addWatchExpression(name);
this.debugService.addWatchExpression(name);
return TPromise.as(undefined);
}
}
export class RemoveWatchExpressionAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.removeWatchExpression';
static readonly ID = 'workbench.debug.viewlet.action.removeWatchExpression';
static LABEL = nls.localize('removeWatchExpression', "Remove Expression");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -667,7 +672,7 @@ export class RemoveWatchExpressionAction extends AbstractDebugAction {
}
export class RemoveAllWatchExpressionsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.removeAllWatchExpressions';
static readonly ID = 'workbench.debug.viewlet.action.removeAllWatchExpressions';
static LABEL = nls.localize('removeAllWatchExpressions', "Remove All Expressions");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -686,7 +691,7 @@ export class RemoveAllWatchExpressionsAction extends AbstractDebugAction {
}
export class ClearReplAction extends AbstractDebugAction {
static ID = 'workbench.debug.panel.action.clearReplAction';
static readonly ID = 'workbench.debug.panel.action.clearReplAction';
static LABEL = nls.localize('clearRepl', "Clear Console");
constructor(id: string, label: string,
@@ -706,7 +711,7 @@ export class ClearReplAction extends AbstractDebugAction {
}
export class ToggleReplAction extends TogglePanelAction {
static ID = 'workbench.debug.action.toggleRepl';
static readonly ID = 'workbench.debug.action.toggleRepl';
static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugConsoleAction' }, 'Debug Console');
private toDispose: lifecycle.IDisposable[];
@@ -748,7 +753,7 @@ export class ToggleReplAction extends TogglePanelAction {
export class FocusReplAction extends Action {
static ID = 'workbench.debug.action.focusRepl';
static readonly ID = 'workbench.debug.action.focusRepl';
static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugFocusConsole' }, 'Focus Debug Console');
@@ -764,7 +769,7 @@ export class FocusReplAction extends Action {
}
export class FocusProcessAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.focusProcess';
static readonly ID = 'workbench.action.debug.focusProcess';
static LABEL = nls.localize('focusProcess', "Focus Process");
constructor(id: string, label: string,
@@ -778,19 +783,19 @@ export class FocusProcessAction extends AbstractDebugAction {
public run(processName: string): TPromise<any> {
const isMultiRoot = this.debugService.getConfigurationManager().getLaunches().length > 1;
const process = this.debugService.getModel().getProcesses().filter(p => p.getName(isMultiRoot) === processName).pop();
return this.debugService.focusStackFrameAndEvaluate(null, process, true).then(() => {
const stackFrame = this.debugService.getViewModel().focusedStackFrame;
if (stackFrame) {
return stackFrame.openInEditor(this.editorService, true);
}
return undefined;
});
this.debugService.focusStackFrame(undefined, undefined, process, true);
const stackFrame = this.debugService.getViewModel().focusedStackFrame;
if (stackFrame) {
return stackFrame.openInEditor(this.editorService, true);
}
return TPromise.as(undefined);
}
}
// Actions used by the chakra debugger
export class StepBackAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.stepBack';
static readonly ID = 'workbench.action.debug.stepBack';
static LABEL = nls.localize('stepBackDebug', "Step Back");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -813,7 +818,7 @@ export class StepBackAction extends AbstractDebugAction {
}
export class ReverseContinueAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.reverseContinue';
static readonly ID = 'workbench.action.debug.reverseContinue';
static LABEL = nls.localize('reverseContinue', "Reverse");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
@@ -834,3 +839,15 @@ export class ReverseContinueAction extends AbstractDebugAction {
process && process.session.capabilities.supportsStepBack;
}
}
export class ReplCollapseAllAction extends CollapseAction {
constructor(viewer: ITree, private toFocus: { focus(): void; }) {
super(viewer, true, undefined);
}
public run(event?: any): TPromise<any> {
return super.run(event).then(() => {
this.toFocus.focus();
});
}
}

View File

@@ -3,11 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!vs/workbench/parts/debug/browser/media/debugActionsWidget';
import 'vs/css!./media/debugActionsWidget';
import * as errors from 'vs/base/common/errors';
import * as strings from 'vs/base/common/strings';
import * as browser from 'vs/base/browser/browser';
import severity from 'vs/base/common/severity';
import * as builder from 'vs/base/browser/builder';
import * as dom from 'vs/base/browser/dom';
import * as arrays from 'vs/base/common/arrays';
@@ -21,7 +20,6 @@ import { AbstractDebugAction, PauseAction, ContinueAction, StepBackAction, Rever
import { FocusProcessActionItem } from 'vs/workbench/parts/debug/browser/debugActionItems';
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IMessageService } from 'vs/platform/message/common/message';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Themable } from 'vs/workbench/common/theme';
import { IThemeService } from 'vs/platform/theme/common/themeService';
@@ -29,6 +27,8 @@ import { registerColor, contrastBorder, widgetShadow } from 'vs/platform/theme/c
import { localize } from 'vs/nls';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { INotificationService } from 'vs/platform/notification/common/notification';
const $ = builder.$;
const DEBUG_ACTIONS_WIDGET_POSITION_KEY = 'debug.actionswidgetposition';
@@ -38,6 +38,11 @@ export const debugToolBarBackground = registerColor('debugToolBar.background', {
light: '#F3F3F3',
hc: '#000000'
}, localize('debugToolBarBackground', "Debug toolbar background color."));
export const debugToolBarBorder = registerColor('debugToolBar.border', {
dark: null,
light: null,
hc: null
}, localize('debugToolBarBorder', "Debug toolbar border color."));
export class DebugActionsWidget extends Themable implements IWorkbenchContribution {
@@ -51,7 +56,7 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi
private isBuilt: boolean;
constructor(
@IMessageService private messageService: IMessageService,
@INotificationService private notificationService: INotificationService,
@ITelemetryService private telemetryService: ITelemetryService,
@IDebugService private debugService: IDebugService,
@IPartService private partService: IPartService,
@@ -59,7 +64,8 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi
@IConfigurationService private configurationService: IConfigurationService,
@IThemeService themeService: IThemeService,
@IKeybindingService private keybindingService: IKeybindingService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IContextViewService contextViewService: IContextViewService
) {
super(themeService);
@@ -75,7 +81,7 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi
orientation: ActionsOrientation.HORIZONTAL,
actionItemProvider: (action: IAction) => {
if (action.id === FocusProcessAction.ID) {
return new FocusProcessActionItem(action, this.debugService, this.themeService);
return new FocusProcessActionItem(action, this.debugService, this.themeService, contextViewService);
}
return null;
@@ -97,7 +103,7 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi
this.toUnbind.push(this.actionBar.actionRunner.onDidRun((e: IRunEvent) => {
// check for error
if (e.error && !errors.isPromiseCanceledError(e.error)) {
this.messageService.show(severity.Error, e.error);
this.notificationService.error(e.error);
}
// log in telemetry
@@ -159,9 +165,16 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi
this.$el.style('box-shadow', widgetShadowColor ? `0 5px 8px ${widgetShadowColor}` : null);
const contrastBorderColor = this.getColor(contrastBorder);
this.$el.style('border-style', contrastBorderColor ? 'solid' : null);
this.$el.style('border-width', contrastBorderColor ? '1px' : null);
this.$el.style('border-color', contrastBorderColor);
const borderColor = this.getColor(debugToolBarBorder);
if (contrastBorderColor) {
this.$el.style('border', `1px solid ${contrastBorderColor}`);
} else {
this.$el.style({
'border': borderColor ? `solid ${borderColor}` : 'none',
'border-width': '1px 0'
});
}
}
}
@@ -282,4 +295,4 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi
delete this.$el;
}
}
}
}

View File

@@ -0,0 +1,241 @@
/*---------------------------------------------------------------------------------------------
* 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 { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { TPromise } from 'vs/base/common/winjs.base';
import { List } from 'vs/base/browser/ui/list/listWidget';
import * as errors from 'vs/base/common/errors';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IListService } from 'vs/platform/list/browser/listService';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IDebugService, IEnablement, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution, CONTEXT_IN_DEBUG_MODE, CONTEXT_NOT_IN_DEBUG_REPL, CONTEXT_EXPRESSION_SELECTED, CONTEXT_BREAKPOINT_SELECTED } 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';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { openBreakpointSource } from 'vs/workbench/parts/debug/browser/breakpointsView';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { InputFocusedContext } from 'vs/platform/workbench/common/contextkeys';
export function registerCommands(): void {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.toggleBreakpoint',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(5),
when: ContextKeyExpr.and(CONTEXT_BREAKPOINTS_FOCUSED, InputFocusedContext.toNegated()),
primary: KeyCode.Space,
handler: (accessor) => {
const listService = accessor.get(IListService);
const debugService = accessor.get(IDebugService);
const focused = listService.lastFocusedList;
// Tree only
if (!(focused instanceof List)) {
const tree = focused;
const element = <IEnablement>tree.getFocus();
debugService.enableOrDisableBreakpoints(!element.enabled, element).done(null, errors.onUnexpectedError);
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.renameWatchExpression',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(5),
when: CONTEXT_WATCH_EXPRESSIONS_FOCUSED,
primary: KeyCode.F2,
mac: { primary: KeyCode.Enter },
handler: (accessor) => {
const listService = accessor.get(IListService);
const debugService = accessor.get(IDebugService);
const focused = listService.lastFocusedList;
// Tree only
if (!(focused instanceof List)) {
const element = focused.getFocus();
if (element instanceof Expression) {
debugService.getViewModel().setSelectedExpression(element);
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.setVariable',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(5),
when: CONTEXT_VARIABLES_FOCUSED,
primary: KeyCode.F2,
mac: { primary: KeyCode.Enter },
handler: (accessor) => {
const listService = accessor.get(IListService);
const debugService = accessor.get(IDebugService);
const focused = listService.lastFocusedList;
// Tree only
if (!(focused instanceof List)) {
const element = focused.getFocus();
if (element instanceof Variable) {
debugService.getViewModel().setSelectedExpression(element);
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.removeWatchExpression',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: ContextKeyExpr.and(CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_EXPRESSION_SELECTED.toNegated()),
primary: KeyCode.Delete,
mac: { primary: KeyMod.CtrlCmd | KeyCode.Backspace },
handler: (accessor) => {
const listService = accessor.get(IListService);
const debugService = accessor.get(IDebugService);
const focused = listService.lastFocusedList;
// Tree only
if (!(focused instanceof List)) {
const element = focused.getFocus();
if (element instanceof Expression) {
debugService.removeWatchExpressions(element.getId());
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.removeBreakpoint',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: ContextKeyExpr.and(CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_BREAKPOINT_SELECTED.toNegated()),
primary: KeyCode.Delete,
mac: { primary: KeyMod.CtrlCmd | KeyCode.Backspace },
handler: (accessor) => {
const listService = accessor.get(IListService);
const debugService = accessor.get(IDebugService);
const focused = listService.lastFocusedList;
// Tree only
if (!(focused instanceof List)) {
const element = focused.getFocus();
if (element instanceof Breakpoint) {
debugService.removeBreakpoints(element.getId()).done(null, errors.onUnexpectedError);
} else if (element instanceof FunctionBreakpoint) {
debugService.removeFunctionBreakpoints(element.getId()).done(null, errors.onUnexpectedError);
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.installAdditionalDebuggers',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: undefined,
primary: undefined,
handler: (accessor) => {
const viewletService = accessor.get(IViewletService);
return viewletService.openViewlet(EXTENSIONS_VIEWLET_ID, true)
.then(viewlet => viewlet as IExtensionsViewlet)
.then(viewlet => {
viewlet.search('tag:debuggers @sort:installs');
viewlet.focus();
});
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.addConfiguration',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: undefined,
primary: undefined,
handler: (accessor, launchUri: string) => {
const manager = accessor.get(IDebugService).getConfigurationManager();
if (accessor.get(IWorkspaceContextService).getWorkbenchState() === WorkbenchState.EMPTY) {
accessor.get(INotificationService).info(nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration."));
return TPromise.as(null);
}
const launch = manager.getLaunches().filter(l => l.uri.toString() === launchUri).pop() || manager.selectedConfiguration.launch;
return launch.openConfigFile(false).done(editor => {
if (editor) {
const codeEditor = <ICodeEditor>editor.getControl();
if (codeEditor) {
return codeEditor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).addLaunchConfiguration();
}
}
return undefined;
});
}
});
const COLUMN_BREAKPOINT_COMMAND_ID = 'editor.debug.action.toggleColumnBreakpoint';
KeybindingsRegistry.registerCommandAndKeybindingRule({
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
primary: KeyMod.Shift | KeyCode.F9,
when: EditorContextKeys.textFocus,
id: COLUMN_BREAKPOINT_COMMAND_ID,
handler: (accessor) => {
const debugService = accessor.get(IDebugService);
const editorService = accessor.get(IWorkbenchEditorService);
const editor = editorService.getActiveEditor();
const control = editor && <ICodeEditor>editor.getControl();
if (control) {
const position = control.getPosition();
const modelUri = control.getModel().uri;
const bp = debugService.getModel().getBreakpoints()
.filter(bp => bp.lineNumber === position.lineNumber && bp.column === position.column && bp.uri.toString() === modelUri.toString()).pop();
if (bp) {
return TPromise.as(null);
}
if (debugService.getConfigurationManager().canSetBreakpointsIn(control.getModel())) {
return debugService.addBreakpoints(modelUri, [{ lineNumber: position.lineNumber, column: position.column }]);
}
}
return TPromise.as(null);
}
});
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: COLUMN_BREAKPOINT_COMMAND_ID,
title: nls.localize('columnBreakpoint', "Column Breakpoint"),
category: nls.localize('debug', "Debug")
}
});
MenuRegistry.appendMenuItem(MenuId.EditorContext, {
command: {
id: COLUMN_BREAKPOINT_COMMAND_ID,
title: nls.localize('addColumnBreakpoint', "Add Column Breakpoint")
},
when: ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, CONTEXT_NOT_IN_DEBUG_REPL, EditorContextKeys.writable),
group: 'debug',
order: 1
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.openBreakpointToSide',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: CONTEXT_BREAKPOINTS_FOCUSED,
primary: KeyMod.CtrlCmd | KeyCode.Enter,
secondary: [KeyMod.Alt | KeyCode.Enter],
handler: (accessor) => {
const listService = accessor.get(IListService);
const list = listService.lastFocusedList;
if (list instanceof List) {
const focus = list.getFocusedElements();
if (focus.length && focus[0] instanceof Breakpoint) {
return openBreakpointSource(focus[0], true, false, accessor.get(IDebugService), accessor.get(IWorkbenchEditorService));
}
}
return TPromise.as(undefined);
}
});
}

View File

@@ -7,7 +7,7 @@ import uri from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import { guessMimeTypes, MIME_TEXT } from 'vs/base/common/mime';
import { IModel } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService';
@@ -39,7 +39,7 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC
textModelResolverService.registerTextModelContentProvider(DEBUG_SCHEME, this);
}
public provideTextContent(resource: uri): TPromise<IModel> {
public provideTextContent(resource: uri): TPromise<ITextModel> {
let process: IProcess;
let sourceRef: number;
@@ -56,7 +56,7 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC
}
if (!process) {
return TPromise.wrapError<IModel>(new Error(localize('unable', "Unable to resolve the resource without a debug session")));
return TPromise.wrapError<ITextModel>(new Error(localize('unable', "Unable to resolve the resource without a debug session")));
}
const source = process.sources.get(resource.toString());
let rawSource: DebugProtocol.Source;
@@ -73,20 +73,24 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC
};
}
const createErrModel = (message: string) => {
this.debugService.sourceIsNotAvailable(resource);
const modePromise = this.modeService.getOrCreateMode(MIME_TEXT);
const model = this.modelService.createModel(message, modePromise, resource);
return model;
};
return process.session.source({ sourceReference: sourceRef, source: rawSource }).then(response => {
if (!response) {
return createErrModel(localize('canNotResolveSource', "Could not resolve resource {0}, no response from debug extension.", resource.toString()));
}
const mime = response.body.mimeType || guessMimeTypes(resource.path)[0];
const modePromise = this.modeService.getOrCreateMode(mime);
const model = this.modelService.createModel(response.body.content, modePromise, resource);
return model;
}, (err: DebugProtocol.ErrorResponse) => {
this.debugService.sourceIsNotAvailable(resource);
const modePromise = this.modeService.getOrCreateMode(MIME_TEXT);
const model = this.modelService.createModel(err.message, modePromise, resource);
return model;
});
}, (err: DebugProtocol.ErrorResponse) => createErrModel(err.message));
}
}

View File

@@ -49,63 +49,6 @@ class ToggleBreakpointAction extends EditorAction {
}
}
function addColumnBreakpoint(accessor: ServicesAccessor, editor: ICodeEditor, remove: boolean): TPromise<any> {
const debugService = accessor.get(IDebugService);
const position = editor.getPosition();
const modelUri = editor.getModel().uri;
const bp = debugService.getModel().getBreakpoints()
.filter(bp => bp.lineNumber === position.lineNumber && bp.column === position.column && bp.uri.toString() === modelUri.toString()).pop();
if (bp) {
return remove ? debugService.removeBreakpoints(bp.getId()) : TPromise.as(null);
}
if (debugService.getConfigurationManager().canSetBreakpointsIn(editor.getModel())) {
return debugService.addBreakpoints(modelUri, [{ lineNumber: position.lineNumber, column: position.column }]);
}
return TPromise.as(null);
}
class ToggleColumnBreakpointAction extends EditorAction {
constructor() {
super({
id: 'editor.debug.action.toggleColumnBreakpoint',
label: nls.localize('columnBreakpointAction', "Debug: Column Breakpoint"),
alias: 'Debug: Column Breakpoint',
precondition: null,
kbOpts: {
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.Shift | KeyCode.F9
}
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): TPromise<any> {
return addColumnBreakpoint(accessor, editor, true);
}
}
// TODO@Isidor merge two column breakpoints actions together
class ToggleColumnBreakpointContextMenuAction extends EditorAction {
constructor() {
super({
id: 'editor.debug.action.toggleColumnBreakpointContextMenu',
label: nls.localize('columnBreakpoint', "Add Column Breakpoint"),
alias: 'Toggle Column Breakpoint',
precondition: ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, CONTEXT_NOT_IN_DEBUG_REPL, EditorContextKeys.writable),
menuOpts: {
group: 'debug',
order: 1
}
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): TPromise<any> {
return addColumnBreakpoint(accessor, editor, false);
}
}
class ConditionalBreakpointAction extends EditorAction {
constructor() {
@@ -268,12 +211,9 @@ class CloseBreakpointWidgetCommand extends EditorCommand {
}
registerEditorAction(ToggleBreakpointAction);
registerEditorAction(ToggleColumnBreakpointAction);
registerEditorAction(ToggleColumnBreakpointContextMenuAction);
registerEditorAction(ConditionalBreakpointAction);
registerEditorAction(RunToCursorAction);
registerEditorAction(SelectionToReplAction);
registerEditorAction(SelectionToWatchExpressionsAction);
registerEditorAction(ShowDebugHoverAction);
registerEditorCommand(new CloseBreakpointWidgetCommand());

View File

@@ -3,16 +3,16 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import * as objects from 'vs/base/common/objects';
import * as lifecycle from 'vs/base/common/lifecycle';
import { Constants } from 'vs/editor/common/core/uint';
import { Range } from 'vs/editor/common/core/range';
import { IModel, TrackedRangeStickiness, IModelDeltaDecoration, IModelDecorationOptions } from 'vs/editor/common/editorCommon';
import { ITextModel, TrackedRangeStickiness, IModelDeltaDecoration, IModelDecorationOptions } from 'vs/editor/common/model';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IDebugService, IBreakpoint, State } from 'vs/workbench/parts/debug/common/debug';
import { IModelService } from 'vs/editor/common/services/modelService';
import { MarkdownString } from 'vs/base/common/htmlContent';
import { getBreakpointMessageAndClassName } from 'vs/workbench/parts/debug/browser/breakpointsView';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
interface IBreakpointDecoration {
decorationId: string;
@@ -21,26 +21,24 @@ interface IBreakpointDecoration {
}
interface IDebugEditorModelData {
model: IModel;
model: ITextModel;
toDispose: lifecycle.IDisposable[];
breakpointDecorations: IBreakpointDecoration[];
currentStackDecorations: string[];
dirty: boolean;
topStackFrameRange: Range;
}
const stickiness = TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges;
export class DebugEditorModelManager implements IWorkbenchContribution {
static ID = 'breakpointManager';
static readonly ID = 'breakpointManager';
static readonly STICKINESS = TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges;
private modelDataMap: Map<string, IDebugEditorModelData>;
private toDispose: lifecycle.IDisposable[];
private ignoreDecorationsChangedEvent: boolean;
constructor(
@IModelService private modelService: IModelService,
@IDebugService private debugService: IDebugService
@IDebugService private debugService: IDebugService,
@ITextFileService private textFileService: ITextFileService
) {
this.modelDataMap = new Map<string, IDebugEditorModelData>();
this.toDispose = [];
@@ -68,14 +66,13 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
this.toDispose.push(this.debugService.onDidChangeState(state => {
if (state === State.Inactive) {
this.modelDataMap.forEach(modelData => {
modelData.dirty = false;
modelData.topStackFrameRange = undefined;
});
}
}));
}
private onModelAdded(model: IModel): void {
private onModelAdded(model: ITextModel): void {
const modelUrlStr = model.uri.toString();
const breakpoints = this.debugService.getModel().getBreakpoints().filter(bp => bp.uri.toString() === modelUrlStr);
@@ -89,12 +86,11 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
toDispose: toDispose,
breakpointDecorations: breakpointDecorationIds.map((decorationId, index) => ({ decorationId, modelId: breakpoints[index].getId(), range: desiredDecorations[index].range })),
currentStackDecorations: currentStackDecorations,
dirty: false,
topStackFrameRange: undefined
});
}
private onModelRemoved(model: IModel): void {
private onModelRemoved(model: ITextModel): void {
const modelUriStr = model.uri.toString();
if (this.modelDataMap.has(modelUriStr)) {
lifecycle.dispose(this.modelDataMap.get(modelUriStr).toDispose);
@@ -220,9 +216,8 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
}
}
}
modelData.dirty = this.debugService.state !== State.Inactive;
this.debugService.updateBreakpoints(modelUri, data);
this.debugService.updateBreakpoints(modelUri, data, true);
}
private onBreakpointsChange(): void {
@@ -262,121 +257,73 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
({ decorationId, modelId: newBreakpoints[index].getId(), range: desiredDecorations[index].range }));
}
private createBreakpointDecorations(model: IModel, breakpoints: IBreakpoint[]): { range: Range; options: IModelDecorationOptions; }[] {
return breakpoints.map((breakpoint) => {
const column = model.getLineFirstNonWhitespaceColumn(breakpoint.lineNumber);
const range = model.validateRange(
breakpoint.column ? new Range(breakpoint.lineNumber, breakpoint.column, breakpoint.lineNumber, breakpoint.column + 1)
: new Range(breakpoint.lineNumber, column, breakpoint.lineNumber, column + 1) // Decoration has to have a width #20688
);
return {
options: this.getBreakpointDecorationOptions(breakpoint),
range
};
private createBreakpointDecorations(model: ITextModel, breakpoints: IBreakpoint[]): { range: Range; options: IModelDecorationOptions; }[] {
const result: { range: Range; options: IModelDecorationOptions; }[] = [];
breakpoints.forEach((breakpoint) => {
if (breakpoint.lineNumber <= model.getLineCount()) {
const column = model.getLineFirstNonWhitespaceColumn(breakpoint.lineNumber);
const range = model.validateRange(
breakpoint.column ? new Range(breakpoint.lineNumber, breakpoint.column, breakpoint.lineNumber, breakpoint.column + 1)
: new Range(breakpoint.lineNumber, column, breakpoint.lineNumber, column + 1) // Decoration has to have a width #20688
);
result.push({
options: this.getBreakpointDecorationOptions(breakpoint),
range
});
}
});
return result;
}
private getBreakpointDecorationOptions(breakpoint: IBreakpoint): IModelDecorationOptions {
const activated = this.debugService.getModel().areBreakpointsActivated();
const state = this.debugService.state;
const debugActive = state === State.Running || state === State.Stopped;
const modelData = this.modelDataMap.get(breakpoint.uri.toString());
const { className, message } = getBreakpointMessageAndClassName(this.debugService, this.textFileService, breakpoint);
let glyphMarginHoverMessage: MarkdownString;
let result = (!breakpoint.enabled || !activated) ? DebugEditorModelManager.BREAKPOINT_DISABLED_DECORATION :
debugActive && modelData && modelData.dirty && !breakpoint.verified ? DebugEditorModelManager.BREAKPOINT_DIRTY_DECORATION :
debugActive && !breakpoint.verified ? DebugEditorModelManager.BREAKPOINT_UNVERIFIED_DECORATION :
!breakpoint.condition && !breakpoint.hitCondition ? DebugEditorModelManager.BREAKPOINT_DECORATION : null;
if (result) {
result = objects.deepClone(result);
if (breakpoint.message) {
result.glyphMarginHoverMessage = new MarkdownString().appendText(breakpoint.message);
if (message) {
if (breakpoint.condition || breakpoint.hitCondition) {
const modelData = this.modelDataMap.get(breakpoint.uri.toString());
const modeId = modelData ? modelData.model.getLanguageIdentifier().language : '';
glyphMarginHoverMessage = new MarkdownString().appendCodeblock(modeId, message);
} else {
glyphMarginHoverMessage = new MarkdownString().appendText(message);
}
if (breakpoint.column) {
result.beforeContentClassName = `debug-breakpoint-column ${result.glyphMarginClassName}-column`;
}
return result;
}
const process = this.debugService.getViewModel().focusedProcess;
if (process && !process.session.capabilities.supportsConditionalBreakpoints) {
return DebugEditorModelManager.BREAKPOINT_UNSUPPORTED_DECORATION;
}
const modeId = modelData ? modelData.model.getLanguageIdentifier().language : '';
let condition: string;
if (breakpoint.condition && breakpoint.hitCondition) {
condition = `Expression: ${breakpoint.condition}\nHitCount: ${breakpoint.hitCondition}`;
} else {
condition = breakpoint.condition ? breakpoint.condition : breakpoint.hitCondition;
}
const glyphMarginHoverMessage = new MarkdownString().appendCodeblock(modeId, condition);
const glyphMarginClassName = 'debug-breakpoint-conditional-glyph';
const beforeContentClassName = breakpoint.column ? `debug-breakpoint-column ${glyphMarginClassName}-column` : undefined;
return {
glyphMarginClassName,
glyphMarginClassName: className,
glyphMarginHoverMessage,
stickiness,
beforeContentClassName
stickiness: DebugEditorModelManager.STICKINESS,
beforeContentClassName: breakpoint.column ? `debug-breakpoint-column ${className}-column` : undefined
};
}
// editor decorations
private static BREAKPOINT_DECORATION: IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-glyph',
stickiness
};
private static BREAKPOINT_DISABLED_DECORATION: IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-disabled-glyph',
glyphMarginHoverMessage: new MarkdownString().appendText(nls.localize('breakpointDisabledHover', "Disabled Breakpoint")),
stickiness
};
private static BREAKPOINT_UNVERIFIED_DECORATION: IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-unverified-glyph',
glyphMarginHoverMessage: new MarkdownString().appendText(nls.localize('breakpointUnverifieddHover', "Unverified Breakpoint")),
stickiness
};
private static BREAKPOINT_DIRTY_DECORATION: IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-unverified-glyph',
glyphMarginHoverMessage: new MarkdownString().appendText(nls.localize('breakpointDirtydHover', "Unverified breakpoint. File is modified, please restart debug session.")),
stickiness
};
private static BREAKPOINT_UNSUPPORTED_DECORATION: IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-unsupported-glyph',
glyphMarginHoverMessage: new MarkdownString().appendText(nls.localize('breakpointUnsupported', "Conditional breakpoints not supported by this debug type")),
stickiness
};
// we need a separate decoration for glyph margin, since we do not want it on each line of a multi line statement.
private static TOP_STACK_FRAME_MARGIN: IModelDecorationOptions = {
glyphMarginClassName: 'debug-top-stack-frame-glyph',
stickiness
glyphMarginClassName: 'debug-top-stack-frame',
stickiness: DebugEditorModelManager.STICKINESS
};
private static FOCUSED_STACK_FRAME_MARGIN: IModelDecorationOptions = {
glyphMarginClassName: 'debug-focused-stack-frame-glyph',
stickiness
glyphMarginClassName: 'debug-focused-stack-frame',
stickiness: DebugEditorModelManager.STICKINESS
};
private static TOP_STACK_FRAME_DECORATION: IModelDecorationOptions = {
isWholeLine: true,
inlineClassName: 'debug-remove-token-colors',
className: 'debug-top-stack-frame-line',
stickiness
stickiness: DebugEditorModelManager.STICKINESS
};
private static TOP_STACK_FRAME_EXCEPTION_DECORATION: IModelDecorationOptions = {
isWholeLine: true,
inlineClassName: 'debug-remove-token-colors',
className: 'debug-top-stack-frame-exception-line',
stickiness
stickiness: DebugEditorModelManager.STICKINESS
};
private static TOP_STACK_FRAME_INLINE_DECORATION: IModelDecorationOptions = {
@@ -387,6 +334,6 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
isWholeLine: true,
inlineClassName: 'debug-remove-token-colors',
className: 'debug-focused-stack-frame-line',
stickiness
stickiness: DebugEditorModelManager.STICKINESS
};
}

View File

@@ -15,8 +15,7 @@ import * as errors from 'vs/base/common/errors';
import { QuickOpenEntry, QuickOpenEntryGroup } from 'vs/base/parts/quickopen/browser/quickOpenModel';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { StartAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { IMessageService } from 'vs/platform/message/common/message';
import { Severity } from 'vs/workbench/services/message/browser/messageList';
import { INotificationService } from 'vs/platform/notification/common/notification';
class AddConfigEntry extends Model.QuickOpenEntry {
@@ -29,7 +28,7 @@ class AddConfigEntry extends Model.QuickOpenEntry {
}
public getDescription(): string {
return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.workspace.name : '';
return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.name : '';
}
public getAriaLabel(): string {
@@ -40,7 +39,7 @@ class AddConfigEntry extends Model.QuickOpenEntry {
if (mode === QuickOpen.Mode.PREVIEW) {
return false;
}
this.commandService.executeCommand('debug.addConfiguration', this.launch.workspace.uri.toString()).done(undefined, errors.onUnexpectedError);
this.commandService.executeCommand('debug.addConfiguration', this.launch.uri.toString()).done(undefined, errors.onUnexpectedError);
return true;
}
@@ -48,7 +47,7 @@ class AddConfigEntry extends Model.QuickOpenEntry {
class StartDebugEntry extends Model.QuickOpenEntry {
constructor(private debugService: IDebugService, private contextService: IWorkspaceContextService, private messageService: IMessageService, private launch: ILaunch, private configurationName: string, highlights: Model.IHighlight[] = []) {
constructor(private debugService: IDebugService, private contextService: IWorkspaceContextService, private notificationService: INotificationService, private launch: ILaunch, private configurationName: string, highlights: Model.IHighlight[] = []) {
super(highlights);
}
@@ -57,7 +56,7 @@ class StartDebugEntry extends Model.QuickOpenEntry {
}
public getDescription(): string {
return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.workspace.name : '';
return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.name : '';
}
public getAriaLabel(): string {
@@ -70,7 +69,7 @@ class StartDebugEntry extends Model.QuickOpenEntry {
}
// Run selected debug configuration
this.debugService.getConfigurationManager().selectConfiguration(this.launch, this.configurationName);
this.debugService.startDebugging(this.launch.workspace).done(undefined, e => this.messageService.show(Severity.Error, e));
this.debugService.startDebugging(this.launch).done(undefined, e => this.notificationService.error(e));
return true;
}
@@ -85,7 +84,7 @@ export class DebugQuickOpenHandler extends Quickopen.QuickOpenHandler {
@IDebugService private debugService: IDebugService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@ICommandService private commandService: ICommandService,
@IMessageService private messageService: IMessageService
@INotificationService private notificationService: INotificationService
) {
super();
}
@@ -103,14 +102,15 @@ export class DebugQuickOpenHandler extends Quickopen.QuickOpenHandler {
launch.getConfigurationNames().map(config => ({ config: config, highlights: Filters.matchesContiguousSubString(input, config) }))
.filter(({ highlights }) => !!highlights)
.forEach(({ config, highlights }) => {
if (launch === configManager.selectedLaunch && config === configManager.selectedName) {
if (launch === configManager.selectedConfiguration.launch && config === configManager.selectedConfiguration.name) {
this.autoFocusIndex = configurations.length;
}
configurations.push(new StartDebugEntry(this.debugService, this.contextService, this.messageService, launch, config, highlights));
configurations.push(new StartDebugEntry(this.debugService, this.contextService, this.notificationService, launch, config, highlights));
});
}
launches.forEach((l, index) => {
const label = launches.length > 1 ? nls.localize("addConfigTo", "Add Config ({0})...", l.workspace.name) : nls.localize('addConfiguration', "Add Configuration...");
launches.filter(l => !l.hidden).forEach((l, index) => {
const label = this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? nls.localize("addConfigTo", "Add Config ({0})...", l.name) : nls.localize('addConfiguration', "Add Configuration...");
const entry = new AddConfigEntry(label, l, this.commandService, this.contextService, Filters.matchesContiguousSubString(input, label));
if (index === 0) {
configurations.push(new QuickOpenEntryGroup(entry, undefined, true));

View File

@@ -92,8 +92,13 @@ export class DebugStatus extends Themable implements IStatusbarItem {
private setLabel(): void {
if (this.label && this.statusBarItem) {
const manager = this.debugService.getConfigurationManager();
const name = manager.selectedName || '';
this.label.textContent = manager.getLaunches().length > 1 ? `${name} (${manager.selectedLaunch.workspace.name})` : name;
const name = manager.selectedConfiguration.name;
if (name) {
this.statusBarItem.style.display = 'block';
this.label.textContent = manager.getLaunches().length > 1 ? `${name} (${manager.selectedConfiguration.launch.name})` : name;
} else {
this.statusBarItem.style.display = 'none';
}
}
}

View File

@@ -15,17 +15,18 @@ import { IDebugService, VIEWLET_ID, State, VARIABLES_VIEW_ID, WATCH_VIEW_ID, CAL
import { StartAction, ToggleReplAction, ConfigureAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { StartDebugActionItem } from 'vs/workbench/parts/debug/browser/debugActionItems';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IProgressService, IProgressRunner } from 'vs/platform/progress/common/progress';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ViewLocation } from 'vs/workbench/browser/parts/views/viewsRegistry';
import { ViewLocation } from 'vs/workbench/common/views';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IPartService } from 'vs/workbench/services/part/common/partService';
export class DebugViewlet extends PersistentViewsViewlet {
@@ -35,6 +36,7 @@ export class DebugViewlet extends PersistentViewsViewlet {
private panelListeners = new Map<string, IDisposable>();
constructor(
@IPartService partService: IPartService,
@ITelemetryService telemetryService: ITelemetryService,
@IProgressService private progressService: IProgressService,
@IDebugService private debugService: IDebugService,
@@ -46,7 +48,7 @@ export class DebugViewlet extends PersistentViewsViewlet {
@IContextMenuService contextMenuService: IContextMenuService,
@IExtensionService extensionService: IExtensionService
) {
super(VIEWLET_ID, ViewLocation.Debug, `${VIEWLET_ID}.state`, false, telemetryService, storageService, instantiationService, themeService, contextService, contextKeyService, contextMenuService, extensionService);
super(VIEWLET_ID, ViewLocation.Debug, `${VIEWLET_ID}.state`, false, partService, telemetryService, storageService, instantiationService, themeService, contextService, contextKeyService, contextMenuService, extensionService);
this.progressRunner = null;
@@ -82,7 +84,7 @@ export class DebugViewlet extends PersistentViewsViewlet {
}
public getActionItem(action: IAction): IActionItem {
if (action.id === StartAction.ID && !!this.debugService.getConfigurationManager().selectedLaunch) {
if (action.id === StartAction.ID) {
this.startDebugActionItem = this.instantiationService.createInstance(StartDebugActionItem, null, action);
return this.startDebugActionItem;
}
@@ -138,7 +140,7 @@ export class DebugViewlet extends PersistentViewsViewlet {
export class FocusVariablesViewAction extends Action {
static ID = 'workbench.debug.action.focusVariablesView';
static readonly ID = 'workbench.debug.action.focusVariablesView';
static LABEL = nls.localize('debugFocusVariablesView', 'Focus Variables');
constructor(id: string, label: string,
@@ -156,7 +158,7 @@ export class FocusVariablesViewAction extends Action {
export class FocusWatchViewAction extends Action {
static ID = 'workbench.debug.action.focusWatchView';
static readonly ID = 'workbench.debug.action.focusWatchView';
static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugFocusWatchView' }, 'Focus Watch');
constructor(id: string, label: string,
@@ -174,7 +176,7 @@ export class FocusWatchViewAction extends Action {
export class FocusCallStackViewAction extends Action {
static ID = 'workbench.debug.action.focusCallStackView';
static readonly ID = 'workbench.debug.action.focusCallStackView';
static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugFocusCallStackView' }, 'Focus CallStack');
constructor(id: string, label: string,
@@ -192,7 +194,7 @@ export class FocusCallStackViewAction extends Action {
export class FocusBreakpointsViewAction extends Action {
static ID = 'workbench.debug.action.focusBreakpointsView';
static readonly ID = 'workbench.debug.action.focusBreakpointsView';
static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugFocusBreakpointsView' }, 'Focus Breakpoints');
constructor(id: string, label: string,

View File

@@ -11,6 +11,7 @@ import * as nls from 'vs/nls';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
export class LinkDetector {
private static readonly MAX_LENGTH = 500;
private static FILE_LOCATION_PATTERNS: RegExp[] = [
// group 0: full path with line and column
// group 1: full path without line and column, matched by `*.*` in the end to work only on paths with extensions in the end (s.t. node:10352 would not match)
@@ -34,8 +35,11 @@ export class LinkDetector {
* If no links were detected, returns the original string.
*/
public handleLinks(text: string): HTMLElement | string {
let linkContainer: HTMLElement;
if (text.length > LinkDetector.MAX_LENGTH) {
return text;
}
let linkContainer: HTMLElement;
for (let pattern of LinkDetector.FILE_LOCATION_PATTERNS) {
pattern.lastIndex = 0; // the holy grail of software development
let lastMatchIndex = 0;

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#252526;}.icon-canvas-transparent{opacity:0;}.icon-vs-red{fill:#c10;}</style></defs><title>BreakpointFunction_16xMD</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14.7,14H1.3L8,1.941Z"/></g><g id="iconBg"><path class="icon-vs-red" d="M13,13H3L8,4Z"/></g></svg>

After

Width:  |  Height:  |  Size: 482 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#252526;}.icon-canvas-transparent{opacity:0;}.icon-disabled-grey{fill:#848484;}</style></defs><title>BreakpointFunction_disabled_16xMD</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14.7,14H1.3L8,1.941Z"/></g><g id="iconBg"><path class="icon-disabled-grey" d="M13,13H3L8,4Z"/></g></svg>

After

Width:  |  Height:  |  Size: 508 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-disabled-grey{fill:#848484;}</style></defs><title>BreakpointFunction_disabled_16xMD</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14.7,14H1.3L8,1.941Z"/></g><g id="iconBg"><path class="icon-disabled-grey" d="M13,13H3L8,4Z"/></g></svg>

After

Width:  |  Height:  |  Size: 508 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#252526;}.icon-canvas-transparent{opacity:0;}.icon-vs-red{fill:#848484;}</style></defs><title>BreakpointFunctionUnverified_16xMD</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14.7,14H1.3L8,1.941Z"/></g><g id="iconBg"><path class="icon-vs-red" d="M8,4,3,13H13ZM8,6.059,11.3,12H4.7Z"/></g></svg>

After

Width:  |  Height:  |  Size: 516 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-vs-red{fill:#848484;}</style></defs><title>BreakpointFunctionUnverified_16xMD</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14.7,14H1.3L8,1.941Z"/></g><g id="iconBg"><path class="icon-vs-red" d="M8,4,3,13H13ZM8,6.059,11.3,12H4.7Z"/></g></svg>

After

Width:  |  Height:  |  Size: 516 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-vs-red{fill:#e51400;}</style></defs><title>BreakpointFunction_16xMD</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14.7,14H1.3L8,1.941Z"/></g><g id="iconBg"><path class="icon-vs-red" d="M13,13H3L8,4Z"/></g></svg>

After

Width:  |  Height:  |  Size: 484 B

View File

@@ -14,7 +14,7 @@
}
.monaco-editor .debug-top-stack-frame-range {
background: #ffeca0;
background: rgba(255, 255, 102, 0.6);
}
.monaco-editor .debug-top-stack-frame-column::before {
@@ -29,30 +29,30 @@
background: rgba(206, 231, 206, 1);
}
.monaco-editor .debug-breakpoint-hint-glyph {
.debug-breakpoint-hint {
background: url('breakpoint-hint.svg') center center no-repeat;
}
.monaco-editor .debug-breakpoint-disabled-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-disabled-glyph-column::before {
.debug-breakpoint-disabled,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-disabled-column::before {
background: url('breakpoint-disabled.svg') center center no-repeat;
}
.monaco-editor .debug-breakpoint-unverified-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-unverified-glyph-column::before {
.debug-breakpoint-unverified,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-unverified-column::before {
background: url('breakpoint-unverified.svg') center center no-repeat;
}
.monaco-editor .debug-top-stack-frame-glyph {
.monaco-editor .debug-top-stack-frame {
background: url('current-arrow.svg') center center no-repeat;
}
.monaco-editor .debug-focused-stack-frame-glyph {
.monaco-editor .debug-focused-stack-frame {
background: url('stackframe-arrow.svg') center center no-repeat;
}
.monaco-editor .debug-breakpoint-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-glyph-column::before {
.debug-breakpoint,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-column::before {
background: url('breakpoint.svg') center center no-repeat;
}
@@ -68,27 +68,40 @@
background-position: initial !important;
}
.monaco-editor .debug-breakpoint-conditional-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-conditional-glyph-column::before {
.debug-function-breakpoint {
background: url('breakpoint-function.svg') center center no-repeat;
}
.debug-function-breakpoint-unverified {
background: url('breakpoint-function-unverified.svg') center center no-repeat;
}
.debug-function-breakpoint-disabled {
background: url('breakpoint-function-disabled.svg') center center no-repeat;
}
.debug-breakpoint-conditional,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-conditional-column::before {
background: url('breakpoint-conditional.svg') center center no-repeat;
}
.monaco-editor .debug-breakpoint-unsupported-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-unsupported-glyph-column::before {
.debug-breakpoint-unsupported,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-unsupported-column::before {
background: url('breakpoint-unsupported.svg') center center no-repeat;
}
.monaco-editor .debug-top-stack-frame-glyph.debug-breakpoint-glyph,
.monaco-editor .debug-top-stack-frame-glyph.debug-breakpoint-conditional-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-glyph-column.debug-top-stack-frame-column::before,
.monaco-editor.vs-dark .debug-top-stack-frame-glyph.debug-breakpoint-glyph,
.monaco-editor.vs-dark .debug-top-stack-frame-glyph.debug-breakpoint-conditional-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-glyph-column.debug-top-stack-frame-column::before {
.monaco-editor .debug-top-stack-frame.debug-breakpoint,
.monaco-editor .debug-top-stack-frame.debug-breakpoint-conditional,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-column.debug-top-stack-frame-column::before,
.monaco-editor.vs-dark .debug-top-stack-frame.debug-breakpoint,
.monaco-editor.vs-dark .debug-top-stack-frame.debug-breakpoint-conditional,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-column.debug-top-stack-frame-column::before {
background: url('current-and-breakpoint.svg') center center no-repeat;
}
.monaco-editor .debug-focused-stack-frame-glyph.debug-breakpoint-glyph,
.monaco-editor .debug-focused-stack-frame-glyph.debug-breakpoint-conditional-glyph {
.monaco-editor .debug-focused-stack-frame.debug-breakpoint,
.monaco-editor .debug-focused-stack-frame.debug-breakpoint-conditional {
background: url('stackframe-and-breakpoint.svg') center center no-repeat;
}
@@ -233,40 +246,61 @@
background-color: rgba(255, 255, 0, 0.3)
}
.monaco-editor.vs-dark .debug-breakpoint-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-glyph-column::before {
.vs-dark .debug-breakpoint,
.hc-black .debug-breakpoint,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-column::before {
background: url('breakpoint-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-breakpoint-conditional-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-conditional-glyph-column::before {
.vs-dark .debug-breakpoint-conditional,
.hc-black .debug-breakpoint-conditional,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-conditional-column::before {
background: url('breakpoint-conditional-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-breakpoint-unsupported-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-unsupported-glyph-column::before {
.vs-dark .debug-breakpoint-unsupported,
.hc-black .debug-breakpoint-unsupported,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-unsupported-column::before {
background: url('breakpoint-unsupported-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-breakpoint-disabled-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-disabled-glyph-column::before {
.vs-dark .debug-breakpoint-disabled,
.hc-black .debug-breakpoint-disabled,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-disabled-column::before {
background: url('breakpoint-disabled-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-breakpoint-unverified-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-unverified-glyph-column::before {
.vs-dark .debug-breakpoint-unverified,
.hc-black .debug-breakpoint-unverified,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-unverified-column::before {
background: url('breakpoint-unverified-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-focused-stack-frame-glyph {
.monaco-editor.vs-dark .debug-focused-stack-frame {
background: url('stackframe-arrow-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-focused-stack-frame-glyph.debug-breakpoint-glyph,
.monaco-editor.vs-dark .debug-focused-stack-frame-glyph.debug-breakpoint-conditional-glyph {
.monaco-editor.vs-dark .debug-focused-stack-frame.debug-breakpoint,
.monaco-editor.vs-dark .debug-focused-stack-frame.debug-breakpoint-conditional {
background: url('stackframe-and-breakpoint-dark.svg') center center no-repeat;
}
.vs-dark .debug-function-breakpoint,
.hc-black .debug-function-breakpoint {
background: url('breakpoint-function-dark.svg') center center no-repeat;
}
.vs-dark .debug-function-breakpoint-unverified,
.hc-black .debug-function-breakpoint-unverified {
background: url('breakpoint-function-unverified.svg') center center no-repeat;
}
.vs-dark .debug-function-breakpoint-disabled,
.hc-black .debug-function-breakpoint-disabled {
background: url('breakpoint-function-disabled.svg') center center no-repeat;
}
/* High Contrast Theming */
.monaco-editor.hc-black .debug-focused-stack-frame-line {

View File

@@ -348,7 +348,11 @@
/* Breakpoints */
.debug-viewlet .debug-breakpoints .monaco-list-row {
.debug-viewlet .debug-breakpoints .monaco-list-row .breakpoint {
padding-left: 2px;
}
.debug-viewlet .debug-breakpoints .breakpoint.exception {
padding-left: 20px;
}
@@ -363,6 +367,11 @@
flex-shrink: 0;
}
.debug-viewlet .debug-breakpoints .breakpoint > .icon {
width: 18px;
height: 18px;
}
.debug-viewlet .debug-breakpoints .breakpoint > .file-path {
opacity: 0.7;
font-size: 0.9em;

View File

@@ -0,0 +1,123 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { localize } from 'vs/nls';
import { registerColor, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
import { IDebugService, State } from 'vs/workbench/parts/debug/common/debug';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_BACKGROUND, Themable, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER, STATUS_BAR_BORDER } from 'vs/workbench/common/theme';
import { addClass, removeClass, createStyleSheet } from 'vs/base/browser/dom';
// colors for theming
export const STATUS_BAR_DEBUGGING_BACKGROUND = registerColor('statusBar.debuggingBackground', {
dark: '#CC6633',
light: '#CC6633',
hc: '#CC6633'
}, localize('statusBarDebuggingBackground', "Status bar background color when a program is being debugged. The status bar is shown in the bottom of the window"));
export const STATUS_BAR_DEBUGGING_FOREGROUND = registerColor('statusBar.debuggingForeground', {
dark: STATUS_BAR_FOREGROUND,
light: STATUS_BAR_FOREGROUND,
hc: STATUS_BAR_FOREGROUND
}, localize('statusBarDebuggingForeground', "Status bar foreground color when a program is being debugged. The status bar is shown in the bottom of the window"));
export const STATUS_BAR_DEBUGGING_BORDER = registerColor('statusBar.debuggingBorder', {
dark: STATUS_BAR_BORDER,
light: STATUS_BAR_BORDER,
hc: STATUS_BAR_BORDER
}, localize('statusBarDebuggingBorder', "Status bar border color separating to the sidebar and editor when a program is being debugged. The status bar is shown in the bottom of the window"));
export class StatusBarColorProvider extends Themable implements IWorkbenchContribution {
private styleElement: HTMLStyleElement;
constructor(
@IThemeService themeService: IThemeService,
@IDebugService private debugService: IDebugService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IPartService private partService: IPartService
) {
super(themeService);
this.registerListeners();
}
private registerListeners(): void {
this.toUnbind.push(this.debugService.onDidChangeState(state => this.updateStyles()));
this.toUnbind.push(this.contextService.onDidChangeWorkbenchState(state => this.updateStyles()));
}
protected updateStyles(): void {
super.updateStyles();
const container = this.partService.getContainer(Parts.STATUSBAR_PART);
if (this.isDebugging()) {
addClass(container, 'debugging');
} else {
removeClass(container, 'debugging');
}
// Container Colors
const backgroundColor = this.getColor(this.getColorKey(STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_DEBUGGING_BACKGROUND, STATUS_BAR_BACKGROUND));
container.style.backgroundColor = backgroundColor;
container.style.color = this.getColor(this.getColorKey(STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_DEBUGGING_FOREGROUND, STATUS_BAR_FOREGROUND));
// Border Color
const borderColor = this.getColor(this.getColorKey(STATUS_BAR_NO_FOLDER_BORDER, STATUS_BAR_DEBUGGING_BORDER, STATUS_BAR_BORDER)) || this.getColor(contrastBorder);
container.style.borderTopWidth = borderColor ? '1px' : null;
container.style.borderTopStyle = borderColor ? 'solid' : null;
container.style.borderTopColor = borderColor;
// Notification Beak
if (!this.styleElement) {
this.styleElement = createStyleSheet(container);
}
this.styleElement.innerHTML = `.monaco-workbench > .part.statusbar > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor} !important; }`;
}
private getColorKey(noFolderColor: string, debuggingColor: string, normalColor: string): string {
// Not debugging
if (!this.isDebugging()) {
if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) {
return normalColor;
}
return noFolderColor;
}
// Debugging
return debuggingColor;
}
private isDebugging(): boolean {
if (this.debugService.state === State.Inactive || this.debugService.state === State.Initializing) {
return false;
}
if (this.isRunningWithoutDebug()) {
return false;
}
return true;
}
private isRunningWithoutDebug(): boolean {
const process = this.debugService.getViewModel().focusedProcess;
return process && process.configuration && process.configuration.noDebug;
}
}
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const statusBarItemDebuggingForeground = theme.getColor(STATUS_BAR_DEBUGGING_FOREGROUND);
if (statusBarItemDebuggingForeground) {
collector.addRule(`.monaco-workbench > .part.statusbar.debugging > .statusbar-item .mask-icon { background-color: ${statusBarItemDebuggingForeground} !important; }`);
}
});