Refresh master with initial release/0.24 snapshot (#332)

* Initial port of release/0.24 source code

* Fix additional headers

* Fix a typo in launch.json
This commit is contained in:
Karl Burtram
2017-12-15 15:38:57 -08:00
committed by GitHub
parent 271b3a0b82
commit 6ad0df0e3e
7118 changed files with 107999 additions and 56466 deletions

View File

@@ -15,7 +15,6 @@ import { SelectActionItem, IActionItem } from 'vs/base/browser/ui/actionbar/acti
import { EventEmitter } from 'vs/base/common/eventEmitter';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { IDebugService } from 'vs/workbench/parts/debug/common/debug';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler';
@@ -42,8 +41,7 @@ export class StartDebugActionItem extends EventEmitter implements IActionItem {
@IDebugService private debugService: IDebugService,
@IThemeService private themeService: IThemeService,
@IConfigurationService private configurationService: IConfigurationService,
@ICommandService private commandService: ICommandService,
@IQuickOpenService private quickOpenService: IQuickOpenService
@ICommandService private commandService: ICommandService
) {
super();
this.toDispose = [];
@@ -56,8 +54,8 @@ export class StartDebugActionItem extends EventEmitter implements IActionItem {
}
private registerListeners(): void {
this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => {
if (e.sourceConfig.launch) {
this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('launch')) {
this.updateOptions();
}
}));
@@ -160,7 +158,7 @@ export class StartDebugActionItem extends EventEmitter implements IActionItem {
if (name === manager.selectedName && launch === manager.selectedLaunch) {
this.selected = this.options.length;
}
const label = launches.length > 1 ? `${name} (${launch.name})` : name;
const label = launches.length > 1 ? `${name} (${launch.workspace.name})` : name;
this.options.push({ label, handler: () => { manager.selectConfiguration(launch, name); return true; } });
}));
@@ -171,10 +169,10 @@ export class StartDebugActionItem extends EventEmitter implements IActionItem {
const disabledIdx = this.options.length - 1;
launches.forEach(l => {
const label = launches.length > 1 ? nls.localize("addConfigTo", "Add Config ({0})...", l.name) : nls.localize('addConfiguration', "Add Configuration...");
const label = launches.length > 1 ? nls.localize("addConfigTo", "Add Config ({0})...", l.workspace.name) : nls.localize('addConfiguration', "Add Configuration...");
this.options.push({
label, handler: () => {
this.commandService.executeCommand('debug.addConfiguration', l.workspaceUri.toString()).done(undefined, errors.onUnexpectedError);
this.commandService.executeCommand('debug.addConfiguration', l.workspace.uri.toString()).done(undefined, errors.onUnexpectedError);
return false;
}
});

View File

@@ -11,7 +11,7 @@ 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 } from 'vs/platform/workspace/common/workspace';
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, IFunctionBreakpoint, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, IExpression, REPL_ID, ProcessState }
@@ -98,7 +98,7 @@ export class ConfigureAction extends AbstractDebugAction {
}
public run(event?: any): TPromise<any> {
if (!this.contextService.hasWorkspace()) {
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."));
return TPromise.as(null);
}
@@ -118,13 +118,15 @@ export class StartAction extends AbstractDebugAction {
@IWorkspaceContextService private contextService: IWorkspaceContextService
) {
super(id, label, 'debug-action start', debugService, keybindingService);
this.debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateEnablement());
this.debugService.getModel().onDidChangeCallStack(() => this.updateEnablement());
this.toDispose.push(this.debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateEnablement()));
this.toDispose.push(this.debugService.getModel().onDidChangeCallStack(() => this.updateEnablement()));
this.toDispose.push(this.contextService.onDidChangeWorkbenchState(() => this.updateEnablement()));
}
public run(): TPromise<any> {
const launch = this.debugService.getConfigurationManager().selectedLaunch;
return this.debugService.startDebugging(launch ? launch.workspaceUri : undefined, undefined, this.isNoDebug());
return this.debugService.startDebugging(launch ? launch.workspace : undefined, undefined, this.isNoDebug());
}
protected isNoDebug(): boolean {
@@ -140,10 +142,10 @@ export class StartAction extends AbstractDebugAction {
if (state === State.Initializing) {
return false;
}
if (this.contextService && !this.contextService.hasWorkspace() && processes.length > 0) {
if (this.contextService && this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && processes.length > 0) {
return false;
}
if (processes.some(p => p.getName(false) === selectedName && (!launch || p.session.root.toString() === launch.workspaceUri.toString()))) {
if (processes.some(p => p.getName(false) === selectedName && (!launch || p.session.root.uri.toString() === launch.workspace.uri.toString()))) {
return false;
}
const compound = launch && launch.getCompound(selectedName);
@@ -215,7 +217,7 @@ export class RestartAction extends AbstractDebugAction {
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && state !== State.Inactive;
return super.isEnabled(state) && (state === State.Running || state === State.Stopped);
}
}
@@ -299,7 +301,7 @@ export class StopAction extends AbstractDebugAction {
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && state !== State.Inactive;
return super.isEnabled(state) && (state === State.Running || state === State.Stopped);
}
}
@@ -317,7 +319,7 @@ export class DisconnectAction extends AbstractDebugAction {
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && state !== State.Inactive;
return super.isEnabled(state) && (state === State.Running || state === State.Stopped);
}
}
@@ -516,7 +518,7 @@ export class ReapplyBreakpointsAction extends AbstractDebugAction {
protected isEnabled(state: State): boolean {
const model = this.debugService.getModel();
return super.isEnabled(state) && state !== State.Inactive &&
return super.isEnabled(state) && (state === State.Running || state === State.Stopped) &&
(model.getFunctionBreakpoints().length + model.getBreakpoints().length + model.getExceptionBreakpoints().length > 0);
}
}

View File

@@ -21,7 +21,7 @@ import { IDebugConfiguration, IDebugService, State } from 'vs/workbench/parts/de
import { AbstractDebugAction, PauseAction, ContinueAction, StepBackAction, ReverseContinueAction, StopAction, DisconnectAction, StepOverAction, StepIntoAction, StepOutAction, RestartAction, FocusProcessAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { FocusProcessActionItem } from 'vs/workbench/parts/debug/browser/debugActionItems';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
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';
@@ -93,7 +93,7 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi
private registerListeners(): void {
this.toUnbind.push(this.debugService.onDidChangeState(state => this.update(state)));
this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(() => this.update(this.debugService.state)));
this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.onDidConfigurationChange(e)));
this.toUnbind.push(this.actionBar.actionRunner.addListener(EventType.RUN, (e: any) => {
// check for error
if (e.error && !errors.isPromiseCanceledError(e.error)) {
@@ -102,6 +102,12 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi
// log in telemetry
if (this.telemetryService) {
/* __GDPR__
"workbenchActionExecuted" : {
"id" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"from": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('workbenchActionExecuted', { id: e.action.id, from: 'debugActionsWidget' });
}
}));
@@ -141,6 +147,11 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi
private storePosition(): void {
const position = parseFloat(this.$el.getComputedStyle().left) / window.innerWidth;
this.storageService.store(DEBUG_ACTIONS_WIDGET_POSITION_KEY, position, StorageScope.WORKSPACE);
/* __GDPR__
"debug.actionswidgetposition" : {
"position" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog(DEBUG_ACTIONS_WIDGET_POSITION_KEY, { position });
}
@@ -184,8 +195,14 @@ export class DebugActionsWidget extends Themable implements IWorkbenchContributi
return DebugActionsWidget.ID;
}
private onDidConfigurationChange(event: IConfigurationChangeEvent): void {
if (event.affectsConfiguration('debug.hideActionBar')) {
this.update(this.debugService.state);
}
}
private update(state: State): void {
if (state === State.Inactive || this.configurationService.getConfiguration<IDebugConfiguration>('debug').hideActionBar) {
if (state === State.Inactive || state === State.Initializing || this.configurationService.getConfiguration<IDebugConfiguration>('debug').hideActionBar) {
return this.hide();
}

View File

@@ -13,7 +13,21 @@ import { IModeService } from 'vs/editor/common/services/modeService';
import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { DEBUG_SCHEME, IDebugService, IProcess } from 'vs/workbench/parts/debug/common/debug';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
/**
* Debug URI format
*
* a debug URI represents a Source object and the debug session where the Source comes from.
*
* debug:arbitrary_path?session=123e4567-e89b-12d3-a456-426655440000&ref=1016
* \___/ \____________/ \__________________________________________/ \______/
* | | | |
* scheme source.path session id source.referencequery
*
* the arbitrary_path and the session id are encoded with 'encodeURIComponent'
*
*/
export class DebugContentProvider implements IWorkbenchContribution, ITextModelContentProvider {
constructor(
@@ -32,15 +46,12 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC
public provideTextContent(resource: uri): TPromise<IModel> {
let process: IProcess;
let sourceRef: number;
if (resource.query) {
const keyvalues = resource.query.split('&');
for (let keyvalue of keyvalues) {
const pair = keyvalue.split('=');
if (pair.length === 2 && pair[0] === 'session') {
process = this.debugService.findProcessByUUID(decodeURIComponent(pair[1]));
break;
}
}
const data = Source.getEncodedDebugData(resource);
process = this.debugService.getModel().getProcesses().filter(p => p.getId() === data.processId).pop();
sourceRef = data.sourceReference;
}
if (!process) {
@@ -55,18 +66,26 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC
let rawSource: DebugProtocol.Source;
if (source) {
rawSource = source.raw;
if (!sourceRef) {
sourceRef = source.reference;
}
} else {
// Remove debug: scheme
rawSource = { path: resource.with({ scheme: '', query: '' }).toString(true) };
// create a Source
rawSource = {
path: resource.with({ scheme: '', query: '' }).toString(true), // Remove debug: scheme
sourceReference: sourceRef
};
}
return process.session.source({ sourceReference: source ? source.reference : undefined, source: rawSource }).then(response => {
const mime = response.body.mimeType || guessMimeTypes(resource.toString())[0];
return process.session.source({ sourceReference: sourceRef, source: rawSource }).then(response => {
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);

View File

@@ -13,15 +13,14 @@ import { IModel, TrackedRangeStickiness, IModelDeltaDecoration, IModelDecoration
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IDebugService, IBreakpoint, IRawBreakpoint, State } from 'vs/workbench/parts/debug/common/debug';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModelDecorationsChangedEvent } from 'vs/editor/common/model/textModelEvents';
import { MarkdownString } from 'vs/base/common/htmlContent';
interface IDebugEditorModelData {
model: IModel;
toDispose: lifecycle.IDisposable[];
breakpointDecorationIds: string[];
breakpointLines: number[];
breakpointDecorationsAsMap: Map<string, boolean>;
breakpointModelIds: string[];
breakpointDecorationsAsMap: Map<string, Range>;
currentStackDecorations: string[];
dirty: boolean;
topStackFrameRange: Range;
@@ -34,6 +33,7 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
private modelDataMap: Map<string, IDebugEditorModelData>;
private toDispose: lifecycle.IDisposable[];
private ignoreDecorationsChangedEvent: boolean;
constructor(
@IModelService private modelService: IModelService,
@@ -81,17 +81,18 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
const breakpoints = this.debugService.getModel().getBreakpoints().filter(bp => bp.uri.toString() === modelUrlStr);
const currentStackDecorations = model.deltaDecorations([], this.createCallStackDecorations(modelUrlStr));
const breakPointDecorations = model.deltaDecorations([], this.createBreakpointDecorations(breakpoints));
const desiredDecorations = this.createBreakpointDecorations(model, breakpoints);
const breakPointDecorations = model.deltaDecorations([], desiredDecorations);
const toDispose: lifecycle.IDisposable[] = [model.onDidChangeDecorations((e) => this.onModelDecorationsChanged(modelUrlStr, e))];
const breakpointDecorationsAsMap = new Map<string, boolean>();
breakPointDecorations.forEach(bpd => breakpointDecorationsAsMap.set(bpd, true));
const toDispose: lifecycle.IDisposable[] = [model.onDidChangeDecorations((e) => this.onModelDecorationsChanged(modelUrlStr))];
const breakpointDecorationsAsMap = new Map<string, Range>();
breakPointDecorations.forEach((decorationId, index) => breakpointDecorationsAsMap.set(decorationId, desiredDecorations[index].range));
this.modelDataMap.set(modelUrlStr, {
model: model,
toDispose: toDispose,
breakpointDecorationIds: breakPointDecorations,
breakpointLines: breakpoints.map(bp => bp.lineNumber),
breakpointModelIds: breakpoints.map(bp => bp.getId()),
breakpointDecorationsAsMap,
currentStackDecorations: currentStackDecorations,
dirty: false,
@@ -185,39 +186,46 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
}
// breakpoints management. Represent data coming from the debug service and also send data back.
private onModelDecorationsChanged(modelUrlStr: string, e: IModelDecorationsChangedEvent): void {
private onModelDecorationsChanged(modelUrlStr: string): void {
const modelData = this.modelDataMap.get(modelUrlStr);
if (modelData.breakpointDecorationsAsMap.size === 0) {
if (modelData.breakpointDecorationsAsMap.size === 0 || this.ignoreDecorationsChangedEvent) {
// I have no decorations
return;
}
if (!e.changedDecorations.some(decorationId => modelData.breakpointDecorationsAsMap.has(decorationId))) {
let somethingChanged = false;
modelData.breakpointDecorationsAsMap.forEach((breakpointRange, decorationId) => {
if (somethingChanged) {
return;
}
const newBreakpointRange = modelData.model.getDecorationRange(decorationId);
if (newBreakpointRange && !breakpointRange.equalsRange(newBreakpointRange)) {
somethingChanged = true;
}
});
if (!somethingChanged) {
// nothing to do, my decorations did not change.
return;
}
const data: IRawBreakpoint[] = [];
const lineToBreakpointDataMap = new Map<number, IBreakpoint>();
this.debugService.getModel().getBreakpoints().filter(bp => bp.uri.toString() === modelUrlStr).forEach(bp => {
lineToBreakpointDataMap.set(bp.lineNumber, bp);
});
const breakpoints = this.debugService.getModel().getBreakpoints();
const modelUri = modelData.model.uri;
for (let i = 0, len = modelData.breakpointDecorationIds.length; i < len; i++) {
const decorationRange = modelData.model.getDecorationRange(modelData.breakpointDecorationIds[i]);
const lineNumber = modelData.breakpointLines[i];
// check if the line got deleted.
if (decorationRange.endColumn - decorationRange.startColumn > 0) {
const breakpoint = lineToBreakpointDataMap.get(lineNumber);
if (decorationRange && decorationRange.endColumn - decorationRange.startColumn > 0) {
const breakpoint = breakpoints.filter(bp => bp.getId() === modelData.breakpointModelIds[i]).pop();
// since we know it is collapsed, it cannot grow to multiple lines
data.push({
lineNumber: decorationRange.startLineNumber,
enabled: breakpoint.enabled,
condition: breakpoint.condition,
hitCondition: breakpoint.hitCondition,
column: breakpoint.column ? decorationRange.startColumn : undefined
});
if (breakpoint) {
data.push({
lineNumber: decorationRange.startLineNumber,
enabled: breakpoint.enabled,
condition: breakpoint.condition,
hitCondition: breakpoint.hitCondition,
column: breakpoint.column ? decorationRange.startColumn : undefined
});
}
}
}
modelData.dirty = this.debugService.state !== State.Inactive;
@@ -254,16 +262,24 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
}
private updateBreakpoints(modelData: IDebugEditorModelData, newBreakpoints: IBreakpoint[]): void {
modelData.breakpointDecorationIds = modelData.model.deltaDecorations(modelData.breakpointDecorationIds, this.createBreakpointDecorations(newBreakpoints));
const desiredDecorations = this.createBreakpointDecorations(modelData.model, newBreakpoints);
try {
this.ignoreDecorationsChangedEvent = true;
modelData.breakpointDecorationIds = modelData.model.deltaDecorations(modelData.breakpointDecorationIds, desiredDecorations);
} finally {
this.ignoreDecorationsChangedEvent = false;
}
modelData.breakpointModelIds = newBreakpoints.map(nbp => nbp.getId());
modelData.breakpointDecorationsAsMap.clear();
modelData.breakpointDecorationIds.forEach(id => modelData.breakpointDecorationsAsMap.set(id, true));
modelData.breakpointLines = newBreakpoints.map(bp => bp.lineNumber);
modelData.breakpointDecorationIds.forEach((decorationId, index) => modelData.breakpointDecorationsAsMap.set(decorationId, desiredDecorations[index].range));
}
private createBreakpointDecorations(breakpoints: IBreakpoint[]): IModelDeltaDecoration[] {
private createBreakpointDecorations(model: IModel, breakpoints: IBreakpoint[]): { range: Range; options: IModelDecorationOptions; }[] {
return breakpoints.map((breakpoint) => {
const range = breakpoint.column ? new Range(breakpoint.lineNumber, breakpoint.column, breakpoint.lineNumber, breakpoint.column + 1)
: new Range(breakpoint.lineNumber, 1, breakpoint.lineNumber, Constants.MAX_SAFE_SMALL_INTEGER); // Decoration has to have a width #20688
const range = model.validateRange(
breakpoint.column ? new Range(breakpoint.lineNumber, breakpoint.column, breakpoint.lineNumber, breakpoint.column + 1)
: new Range(breakpoint.lineNumber, 1, breakpoint.lineNumber, Constants.MAX_SAFE_SMALL_INTEGER) // Decoration has to have a width #20688
);
return {
options: this.getBreakpointDecorationOptions(breakpoint),
range
@@ -274,7 +290,7 @@ export class DebugEditorModelManager implements IWorkbenchContribution {
private getBreakpointDecorationOptions(breakpoint: IBreakpoint): IModelDecorationOptions {
const activated = this.debugService.getModel().areBreakpointsActivated();
const state = this.debugService.state;
const debugActive = state === State.Running || state === State.Stopped || state === State.Initializing;
const debugActive = state === State.Running || state === State.Stopped;
const modelData = this.modelDataMap.get(breakpoint.uri.toString());
let result = (!breakpoint.enabled || !activated) ? DebugEditorModelManager.BREAKPOINT_DISABLED_DECORATION :

View File

@@ -11,16 +11,51 @@ import QuickOpen = require('vs/base/parts/quickopen/common/quickOpen');
import Model = require('vs/base/parts/quickopen/browser/quickOpenModel');
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { IDebugService, ILaunch } from 'vs/workbench/parts/debug/common/debug';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
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';
class DebugEntry extends Model.QuickOpenEntry {
class AddConfigEntry extends Model.QuickOpenEntry {
constructor(private debugService: IDebugService, private launch: ILaunch, private configurationName: string, highlights: Model.IHighlight[] = []) {
constructor(private label: string, private launch: ILaunch, private commandService: ICommandService, private contextService: IWorkspaceContextService, highlights: Model.IHighlight[] = []) {
super(highlights);
}
public getLabel(): string {
return this.debugService.getConfigurationManager().getLaunches().length <= 1 ? this.configurationName : `${this.configurationName} (${this.launch.name})`;
return this.label;
}
public getDescription(): string {
return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.workspace.name : '';
}
public getAriaLabel(): string {
return nls.localize('entryAriaLabel', "{0}, debug", this.getLabel());
}
public run(mode: QuickOpen.Mode, context: Model.IContext): boolean {
if (mode === QuickOpen.Mode.PREVIEW) {
return false;
}
this.commandService.executeCommand('debug.addConfiguration', this.launch.workspace.uri.toString()).done(undefined, errors.onUnexpectedError);
return true;
}
}
class StartDebugEntry extends Model.QuickOpenEntry {
constructor(private debugService: IDebugService, private contextService: IWorkspaceContextService, private launch: ILaunch, private configurationName: string, highlights: Model.IHighlight[] = []) {
super(highlights);
}
public getLabel(): string {
return this.configurationName;
}
public getDescription(): string {
return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.workspace.name : '';
}
public getAriaLabel(): string {
@@ -33,7 +68,7 @@ class DebugEntry extends Model.QuickOpenEntry {
}
// Run selected debug configuration
this.debugService.getConfigurationManager().selectConfiguration(this.launch, this.configurationName);
this.debugService.startDebugging(this.launch.workspaceUri).done(undefined, errors.onUnexpectedError);
this.debugService.startDebugging(this.launch.workspace).done(undefined, errors.onUnexpectedError);
return true;
}
@@ -41,9 +76,14 @@ class DebugEntry extends Model.QuickOpenEntry {
export class DebugQuickOpenHandler extends Quickopen.QuickOpenHandler {
public static readonly ID = 'workbench.picker.launch';
private autoFocusIndex: number;
constructor(
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IDebugService private debugService: IDebugService
@IDebugService private debugService: IDebugService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@ICommandService private commandService: ICommandService
) {
super();
}
@@ -53,20 +93,38 @@ export class DebugQuickOpenHandler extends Quickopen.QuickOpenHandler {
}
public getResults(input: string): TPromise<Model.QuickOpenModel> {
const configurations: DebugEntry[] = [];
const configurations: QuickOpenEntry[] = [];
for (let launch of this.debugService.getConfigurationManager().getLaunches()) {
const configManager = this.debugService.getConfigurationManager();
const launches = configManager.getLaunches();
for (let launch of launches) {
launch.getConfigurationNames().map(config => ({ config: config, highlights: Filters.matchesContiguousSubString(input, config) }))
.filter(({ highlights }) => !!highlights)
.forEach(({ config, highlights }) => configurations.push(new DebugEntry(this.debugService, launch, config, highlights)));
.forEach(({ config, highlights }) => {
if (launch === configManager.selectedLaunch && config === configManager.selectedName) {
this.autoFocusIndex = configurations.length;
}
configurations.push(new StartDebugEntry(this.debugService, this.contextService, 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...");
const entry = new AddConfigEntry(label, l, this.commandService, this.contextService, Filters.matchesContiguousSubString(input, label));
if (index === 0) {
configurations.push(new QuickOpenEntryGroup(entry, undefined, true));
} else {
configurations.push(entry);
}
});
return TPromise.as(new Model.QuickOpenModel(configurations));
}
public getAutoFocus(input: string): QuickOpen.IAutoFocus {
return {
autoFocusFirstEntry: !!input
autoFocusFirstEntry: !!input,
autoFocusIndex: this.autoFocusIndex
};
}

View File

@@ -0,0 +1,80 @@
/*---------------------------------------------------------------------------------------------
* 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 dom from 'vs/base/browser/dom';
import * as errors from 'vs/base/common/errors';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
import { IDebugService, State } from 'vs/workbench/parts/debug/common/debug';
import { Themable, STATUS_BAR_FOREGROUND } from 'vs/workbench/common/theme';
const $ = dom.$;
export class DebugStatus extends Themable implements IStatusbarItem {
private toDispose: IDisposable[];
private container: HTMLElement;
private label: HTMLElement;
private icon: HTMLElement;
private hidden = true;
constructor(
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IDebugService private debugService: IDebugService,
@IThemeService themeService: IThemeService
) {
super(themeService);
this.toDispose = [];
this.toDispose.push(this.debugService.getConfigurationManager().onDidSelectConfiguration(e => {
this.setLabel();
}));
this.toDispose.push(this.debugService.onDidChangeState(state => {
if (state !== State.Inactive && this.hidden) {
this.hidden = false;
this.render(this.container);
}
}));
}
protected updateStyles(): void {
super.updateStyles();
if (this.icon) {
this.icon.style.backgroundColor = this.getColor(STATUS_BAR_FOREGROUND);
}
}
public render(container: HTMLElement): IDisposable {
this.container = container;
if (!this.hidden) {
const statusBarItem = dom.append(container, $('.debug-statusbar-item'));
this.toDispose.push(dom.addDisposableListener(statusBarItem, 'click', () => {
this.quickOpenService.show('debug ').done(undefined, errors.onUnexpectedError);
}));
statusBarItem.title = nls.localize('selectAndStartDebug', "Select and start debug configuration");
const a = dom.append(statusBarItem, $('a'));
this.icon = dom.append(a, $('.icon'));
this.label = dom.append(a, $('span.label'));
this.setLabel();
this.updateStyles();
}
return this;
}
private setLabel(): void {
if (this.label && !this.hidden) {
const manager = this.debugService.getConfigurationManager();
const name = manager.selectedName || '';
this.label.textContent = manager.getLaunches().length > 1 ? `${name} (${manager.selectedLaunch.workspace.name})` : name;
}
}
public dispose(): void {
super.dispose();
this.toDispose = dispose(this.toDispose);
}
}

View File

@@ -4,13 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/debugViewlet';
import * as nls from 'vs/nls';
import { Builder } from 'vs/base/browser/builder';
import { Action, IAction } from 'vs/base/common/actions';
import * as DOM from 'vs/base/browser/dom';
import { TPromise } from 'vs/base/common/winjs.base';
import { IAction } from 'vs/base/common/actions';
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { PersistentViewsViewlet } from 'vs/workbench/parts/views/browser/views';
import { IDebugService, VIEWLET_ID, State } from 'vs/workbench/parts/debug/common/debug';
import { PersistentViewsViewlet } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IDebugService, VIEWLET_ID, State, VARIABLES_VIEW_ID, WATCH_VIEW_ID, CALLSTACK_VIEW_ID, BREAKPOINTS_VIEW_ID } from 'vs/workbench/parts/debug/common/debug';
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';
@@ -20,13 +21,13 @@ 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 { ViewLocation } from 'vs/workbench/parts/views/browser/viewsRegistry';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ViewLocation } from 'vs/workbench/browser/parts/views/viewsRegistry';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
export class DebugViewlet extends PersistentViewsViewlet {
private actions: IAction[];
private startDebugActionItem: StartDebugActionItem;
private progressRunner: IProgressRunner;
@@ -47,35 +48,30 @@ export class DebugViewlet extends PersistentViewsViewlet {
this.progressRunner = null;
this._register(this.debugService.onDidChangeState(state => this.onDebugServiceStateChange(state)));
this._register(this.contextService.onDidChangeWorkbenchState(() => this.updateTitleArea()));
}
public create(parent: Builder): TPromise<void> {
return super.create(parent).then(() => DOM.addClass(this.viewletContainer, 'debug-viewlet'));
async create(parent: Builder): TPromise<void> {
await super.create(parent);
const el = parent.getHTMLElement();
DOM.addClass(el, 'debug-viewlet');
}
public focus(): void {
super.focus();
if (!this.contextService.hasWorkspace()) {
this.views[0].focusBody();
}
if (this.startDebugActionItem) {
this.startDebugActionItem.focus();
}
}
public getActions(): IAction[] {
if (!this.actions) {
this.actions = [];
this.actions.push(this.instantiationService.createInstance(StartAction, StartAction.ID, StartAction.LABEL));
if (this.contextService.hasWorkspace()) {
this.actions.push(this.instantiationService.createInstance(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL));
}
this.actions.push(this._register(this.instantiationService.createInstance(ToggleReplAction, ToggleReplAction.ID, ToggleReplAction.LABEL)));
}
return this.actions;
const actions = [];
actions.push(this.instantiationService.createInstance(StartAction, StartAction.ID, StartAction.LABEL));
actions.push(this.instantiationService.createInstance(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL));
actions.push(this._register(this.instantiationService.createInstance(ToggleReplAction, ToggleReplAction.ID, ToggleReplAction.LABEL)));
return actions;
}
public getSecondaryActions(): IAction[] {
@@ -83,7 +79,7 @@ export class DebugViewlet extends PersistentViewsViewlet {
}
public getActionItem(action: IAction): IActionItem {
if (action.id === StartAction.ID && this.contextService.hasWorkspace()) {
if (action.id === StartAction.ID && !!this.debugService.getConfigurationManager().selectedLaunch) {
this.startDebugActionItem = this.instantiationService.createInstance(StartDebugActionItem, null, action);
return this.startDebugActionItem;
}
@@ -91,6 +87,13 @@ export class DebugViewlet extends PersistentViewsViewlet {
return null;
}
public focusView(id: string): void {
const view = this.getView(id);
if (view) {
view.focus();
}
}
private onDebugServiceStateChange(state: State): void {
if (this.progressRunner) {
this.progressRunner.done();
@@ -103,3 +106,75 @@ export class DebugViewlet extends PersistentViewsViewlet {
}
}
}
export class FocusVariablesViewAction extends Action {
static ID = 'workbench.debug.action.focusVariablesView';
static LABEL = nls.localize('debugFocusVariablesView', 'Focus Variables');
constructor(id: string, label: string,
@IViewletService private viewletService: IViewletService
) {
super(id, label);
}
public run(): TPromise<any> {
return this.viewletService.openViewlet(VIEWLET_ID).then((viewlet: DebugViewlet) => {
viewlet.focusView(VARIABLES_VIEW_ID);
});
}
}
export class FocusWatchViewAction extends Action {
static 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,
@IViewletService private viewletService: IViewletService
) {
super(id, label);
}
public run(): TPromise<any> {
return this.viewletService.openViewlet(VIEWLET_ID).then((viewlet: DebugViewlet) => {
viewlet.focusView(WATCH_VIEW_ID);
});
}
}
export class FocusCallStackViewAction extends Action {
static 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,
@IViewletService private viewletService: IViewletService
) {
super(id, label);
}
public run(): TPromise<any> {
return this.viewletService.openViewlet(VIEWLET_ID).then((viewlet: DebugViewlet) => {
viewlet.focusView(CALLSTACK_VIEW_ID);
});
}
}
export class FocusBreakpointsViewAction extends Action {
static 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,
@IViewletService private viewletService: IViewletService
) {
super(id, label);
}
public run(): TPromise<any> {
return this.viewletService.openViewlet(VIEWLET_ID).then((viewlet: DebugViewlet) => {
viewlet.focusView(BREAKPOINTS_VIEW_ID);
});
}
}

View File

@@ -21,7 +21,7 @@ const $ = dom.$;
// theming
export const debugExceptionWidgetBorder = registerColor('debugExceptionWidget.border', { dark: '#a31515', light: '#a31515', hc: '#a31515' }, nls.localize('debugExceptionWidgetBorder', 'Exception widget border color.'));
export const debugExceptionWidgetBackground = registerColor('debugExceptionWidget.background', { dark: '#a3151540', light: '#a315150d', hc: '#a3151573' }, nls.localize('debugExceptionWidgetBackground', 'Exception widget background color.'));
export const debugExceptionWidgetBackground = registerColor('debugExceptionWidget.background', { dark: '#420b0d', light: '#f1dfde', hc: '#420b0d' }, nls.localize('debugExceptionWidgetBackground', 'Exception widget background color.'));
export class ExceptionWidget extends ZoneWidget {

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import strings = require('vs/base/common/strings');
import uri from 'vs/base/common/uri';
import { isMacintosh } from 'vs/base/common/platform';
import * as errors from 'vs/base/common/errors';
@@ -46,11 +45,6 @@ export class LinkDetector {
let match = pattern.exec(text);
while (match !== null) {
let resource: uri = null;
try {
resource = (match && !strings.startsWith(match[0], 'http'))
&& (match[2] || strings.startsWith(match[1], '/') ? uri.file(match[1]) : this.contextService.toResource(match[1])); // TODO@Michel TODO@Isidor (https://github.com/Microsoft/vscode/issues/29190)
} catch (e) { }
if (!resource) {
match = pattern.exec(text);
continue;

View File

@@ -102,6 +102,21 @@
box-sizing: border-box;
}
/* Debug status */
/* A very precise css rule to overwrite the display set in statusbar.css */
.monaco-workbench > .part.statusbar > .statusbar-item > .debug-statusbar-item > a:not([disabled]):not(.disabled) {
display: flex;
padding: 0 5px 0 5px;
}
.monaco-workbench .part.statusbar .debug-statusbar-item .icon {
-webkit-mask: url('continue.svg') no-repeat 50% 50%;
-webkit-mask-size: 18px;
display: inline-block;
padding-right: 2px;
width: 16px;
}
/* Expressions */
.monaco-workbench .monaco-tree-row .expression {

View File

@@ -200,6 +200,7 @@
overflow: hidden;
text-overflow: ellipsis;
padding-right: 0.8em;
display: flex;
}
.debug-viewlet .debug-call-stack .stack-frame.label {
@@ -207,6 +208,12 @@
font-style: italic;
}
.debug-viewlet .debug-call-stack .stack-frame .label {
flex: 1;
flex-shrink: 0;
min-width: fit-content;
}
.debug-viewlet .debug-call-stack .stack-frame.subtle {
font-style: italic;
}
@@ -216,7 +223,10 @@
}
.debug-viewlet .debug-call-stack .stack-frame > .file {
float: right;
display: flex;
overflow: hidden;
flex-wrap: wrap;
justify-content: flex-end;
}
.debug-viewlet .debug-call-stack .stack-frame > .file > .line-number.unavailable {
@@ -227,6 +237,11 @@
color: rgba(108, 108, 108, 0.8);
}
.debug-viewlet .debug-call-stack .stack-frame > .file > .file-name {
overflow: hidden;
text-overflow: ellipsis;
}
.vs-dark .debug-viewlet .debug-call-stack > .monaco-tree-row:not(.selected) .stack-frame > .file {
color: rgba(204, 204, 204, 0.6);
}

View File

@@ -36,6 +36,22 @@
font-size: 12px;
}
.monaco-workbench .repl .repl-tree .monaco-tree-row .output.expression.value-and-source {
display: flex;
}
.monaco-workbench .repl .repl-tree .monaco-tree-row .output.expression.value-and-source .value {
flex: 1;
}
.monaco-workbench .repl .repl-tree .monaco-tree-row .output.expression.value-and-source .source {
margin-left: 4px;
margin-right: 8px;
cursor: pointer;
text-decoration: underline;
}
.monaco-workbench.windows .repl .repl-tree .monaco-tree-row .input.expression,
.monaco-workbench.windows .repl .repl-tree .monaco-tree-row .output.expression,
.monaco-workbench.linux .repl .repl-tree .monaco-tree-row .input.expression,